ROOT  6.06/09
Reference Guide
TRecorder.cxx
Go to the documentation of this file.
1 // @(#)root/gui:$Id$
2 // Author: Katerina Opocenska 11/09/2008
3 
4 /*************************************************************************
5 * Copyright (C) 1995-2008, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11 
12 //////////////////////////////////////////////////////////////////////////
13 // //
14 // ROOT EVENT RECORDING SYSTEM //
15 // ================================================================== //
16 // //
17 // TRecorder class provides interface for recording and replaying //
18 // events in ROOT. //
19 // Recorded events are: //
20 // - Commands typed by user in commandline ('new TCanvas') //
21 // - GUI events (mouse movement, button clicks, ...) //
22 // //
23 // All the recorded events from one session are stored in one TFile //
24 // and can be replayed again anytime. //
25 // //
26 // Recording //
27 // ================================================================== //
28 // //
29 // 1] To start recording //
30 // //
31 // TRecorder r(const char *filename, "NEW") //
32 // TRecorder r(const char *filename, "RECREATE") //
33 // //
34 // or: //
35 // //
36 // TRecorder *recorder = new TRecorder; //
37 // recorder->Start(const char *filename, ...) //
38 // //
39 // -filename Name of ROOT file in which to save //
40 // recorded events. //
41 // //
42 // 2] To stop recording //
43 // //
44 // recorder->Stop() //
45 // //
46 // //
47 // IMPORTANT: //
48 // State capturing is part of recording. It means that if you want to //
49 // record events for some object (window), creation of this object //
50 // must be also recorded. //
51 // //
52 // Example: //
53 // -------- //
54 // t = new TRecorder(); // Create a new recorder //
55 // t->Start("logfile.root"); // ! Start recording first //
56 // //
57 // c = new TCanvas(); // ! Then, create an object //
58 // c->Dump(); // Work with that object //
59 // //
60 // t->Stop(); // Stop recording //
61 // //
62 // It is strongly recommended to start recording with empty ROOT //
63 // environment, at least with no previously created ROOT GUI. //
64 // This ensures that only events for well known windows are stored. //
65 // Events for windows, which were not created during recording, //
66 // cannot be replayed. //
67 // //
68 // Replaying //
69 // =================================================================== //
70 // //
71 // 1] To start replaying //
72 // //
73 // TRecorder r(const char *filename) //
74 // TRecorder r(const char *filename, "READ") //
75 // //
76 // or: //
77 // //
78 // TRecorder *recorder = new TRecorder; //
79 // recorder->Replay(const char *filename, //
80 // Bool_t showMouseCursor = kTRUE); //
81 // //
82 // -filename A name of file with recorded events //
83 // previously created with TRecorder::Start //
84 // //
85 // -showMouseCursor If kTRUE, mouse cursor is replayed as well. //
86 // In that case it is not recommended to use mouse //
87 // during replaying. //
88 // //
89 // In general, it is not recommended to use mouse to change positions //
90 // and states of ROOT windows during replaying. //
91 // //
92 // IMPORTANT: //
93 // The state of ROOT environment before replaying of some events //
94 // must be exactly the same as before recording them. //
95 // Therefore it is strongly recommended to start both recording //
96 // and replaying with empty ROOT environment. //
97 // //
98 // 2] To pause replaying //
99 // //
100 // recorder->Pause() //
101 // //
102 // Replaying is stopped until recorder->Resume() is called. //
103 // //
104 // //
105 // 3] To resume paused replaying //
106 // //
107 // recorder->Resume() //
108 // //
109 // Resumes previously stopped replaying. //
110 // //
111 // //
112 // 4] To stop replaying before its end //
113 // //
114 // recorder->Stop() //
115 // //
116 //////////////////////////////////////////////////////////////////////////
117 
118 #include "TRecorder.h"
119 
120 #include "TROOT.h"
121 #include "TFile.h"
122 #include "TTimer.h"
123 #include "TTree.h"
124 #include "TMutex.h"
125 #include "TGButton.h"
126 #include "TGFileDialog.h"
127 #include "TGLabel.h"
128 #include "TGWindow.h"
129 #include "Buttons.h"
130 #include "TKey.h"
131 #include "TPaveLabel.h"
132 #include "TLatex.h"
133 #include "TVirtualDragManager.h"
134 #include "TGPicture.h"
135 #include "KeySymbols.h"
136 
137 // Names of ROOT GUI events. Used for listing event logs.
138 const char *kRecEventNames[] = {
139  "KeyPress",
140  "KeyRelease",
141  "ButtonPress",
142  "ButtonRelease",
143  "MotionNotify",
144  "EnterNotify",
145  "LeaveNotify",
146  "FocusIn",
147  "FocusOut",
148  "Expose",
149  "ConfigureNotify",
150  "MapNotify",
151  "UnmapNotify",
152  "DestroyNotify",
153  "ClientMessage",
154  "SelectionClear",
155  "SelectionRequest",
156  "SelectionNotify",
157  "ColormapNotify",
158  "ButtonDoubleClick",
159  "OtherEvent"
160 };
161 
162 // Names of TTrees in the TFile with recorded events
163 const char *kCmdEventTree = "CmdEvents"; // Name of TTree with commandline events
164 const char *kGuiEventTree = "GuiEvents"; // Name of TTree with GUI events
165 const char *kWindowsTree = "WindowsTree"; // Name of TTree with window IDs
166 const char *kExtraEventTree = "ExtraEvents"; // Name of TTree with extra events (PaveLabels and Texts)
167 const char *kBranchName = "MainBranch"; // Name of the main branch in all TTress
168 
170 
171 
172 //_____________________________________________________________________________
173 //
174 // TGCursorWindow
175 //
176 // Window used as fake mouse cursor wile replaying events.
177 //_____________________________________________________________________________
178 
179 class TGCursorWindow : public TGFrame {
180 
181 protected:
182  Pixmap_t fPic, fMask; // Pixmaps used as Window shape
183 
184 public:
185  TGCursorWindow();
186  virtual ~TGCursorWindow();
187 };
188 
190 static Int_t gDecorWidth = 0;
191 static Int_t gDecorHeight = 0;
192 
193 ////////////////////////////////////////////////////////////////////////////////
194 /// TGCursorWindow constructor.
195 
197  TGFrame(gClient->GetDefaultRoot(), 32, 32, kTempFrame)
198 {
199  SetWindowAttributes_t wattr;
200  const TGPicture *pbg = fClient->GetPicture("recursor.png");
201  fPic = pbg->GetPicture();
202  fMask = pbg->GetMask();
203 
204  gVirtualX->ShapeCombineMask(fId, 0, 0, fMask);
205  SetBackgroundPixmap(fPic);
206 
208  wattr.fSaveUnder = kTRUE;
209  wattr.fOverrideRedirect = kTRUE;
210 
211  gVirtualX->ChangeWindowAttributes(fId, &wattr);
212 }
213 
214 ////////////////////////////////////////////////////////////////////////////////
215 /// Destructor.
216 
218 {
219 }
220 
221 ////////////////////////////////////////////////////////////////////////////////
222 /// Creates initial INACTIVE state for the recorder
223 
225 {
226  fFilename = "";
228 }
229 
230 ////////////////////////////////////////////////////////////////////////////////
231 /// Creates a recorder with filename to replay or to record,
232 /// depending on option (NEW or RECREATE will start recording,
233 /// READ will start replaying)
234 
236 {
237  TString opt(option);
238  fFilename = "";
240  if ((opt == "NEW") || (opt == "RECREATE"))
241  Start(filename, option);
242  else
243  Replay(filename);
244 }
245 
246 ////////////////////////////////////////////////////////////////////////////////
247 /// Destructor.
248 
250 {
251  delete fRecorderState;
252 }
253 
254 ////////////////////////////////////////////////////////////////////////////////
255 /// Browse the recorder from a ROOT file. This allows to replay a
256 /// session from the browser.
257 
259 {
260  Replay(fFilename);
261 }
262 
263 ////////////////////////////////////////////////////////////////////////////////
264 /// Starts recording events
265 
266 void TRecorder::Start(const char *filename, Option_t *option, Window_t *w,
267  Int_t winCount)
268 {
269  fRecorderState->Start(this, filename, option, w, winCount);
270 }
271 
272 ////////////////////////////////////////////////////////////////////////////////
273 /// Stopps recording events
274 
275 void TRecorder::Stop(Bool_t guiCommand)
276 {
277  fRecorderState->Stop(this, guiCommand);
278 }
279 
280 ////////////////////////////////////////////////////////////////////////////////
281 /// Replays events from 'filename'
282 
283 Bool_t TRecorder::Replay(const char *filename, Bool_t showMouseCursor,
285 {
286  return fRecorderState->Replay(this, filename, showMouseCursor, mode);
287 }
288 
289 ////////////////////////////////////////////////////////////////////////////////
290 /// Pauses replaying
291 
293 {
294  fRecorderState->Pause(this);
295 }
296 
297 ////////////////////////////////////////////////////////////////////////////////
298 /// Resumes replaying
299 
301 {
302  fRecorderState->Resume(this);
303 }
304 
305 ////////////////////////////////////////////////////////////////////////////////
306 /// Cancells replaying
307 
309 {
310  fRecorderState->ReplayStop(this);
311 }
312 
313 ////////////////////////////////////////////////////////////////////////////////
314 /// Prints out recorded commandline events
315 
316 void TRecorder::ListCmd(const char *filename)
317 {
318  fRecorderState->ListCmd(filename);
319 }
320 
321 ////////////////////////////////////////////////////////////////////////////////
322 /// Prints out recorded GUI events
323 
324 void TRecorder::ListGui(const char *filename)
325 {
326  fRecorderState->ListGui(filename);
327 }
328 
329 ////////////////////////////////////////////////////////////////////////////////
330 /// Changes state from the current to the passed one (newstate)
331 /// Deletes the old state if delPreviousState = KTRUE
332 
333 void TRecorder::ChangeState(TRecorderState *newstate, Bool_t delPreviousState)
334 {
335  if (delPreviousState)
336  delete fRecorderState;
337 
338  fRecorderState = newstate;
339 }
340 
341 ////////////////////////////////////////////////////////////////////////////////
342 /// Get current state of recorder.
343 
345 {
346  return fRecorderState->GetState();
347 }
348 
349 
350 ////////////////////////////////////////////////////////////////////////////////
351 /// Save previous canvases in a .root file
352 
353 void TRecorder::PrevCanvases(const char *filename, Option_t *option)
354 {
355  fRecorderState->PrevCanvases(filename,option);
356 }
357 
358 //______________________________________________________________________________
359 // Represents state of TRecorder when replaying
360 
362 
363 ////////////////////////////////////////////////////////////////////////////////
364 /// Allocates all necessary data structures used for replaying
365 /// What is allocated here is deleted in destructor
366 
368 {
369  fCanv = 0;
370  fCmdTree = 0;
371  fCmdTreeCounter = 0;
372  fEventReplayed = kTRUE;
373  fExtraTree = 0;
374  fExtraTreeCounter = 0;
375  fFilterStatusBar = kFALSE;
376  fGuiTree = 0;
377  fGuiTreeCounter = 0;
378  fNextEvent = 0;
379  fRecorder = 0;
380  fRegWinCounter = 0;
381  fShowMouseCursor = kTRUE;
382  fWaitingForWindow = kFALSE;
383  fWin = 0;
384  fWinTree = 0;
385  fWinTreeEntries = 0;
386  fFile = TFile::Open(filename);
387  fCmdEvent = new TRecCmdEvent();
388  fGuiEvent = new TRecGuiEvent();
389  fExtraEvent = new TRecExtraEvent();
390  fWindowList = new TList();
391  fTimer = new TTimer();
392  fMutex = new TMutex(kFALSE);
393  if (!gCursorWin)
394  gCursorWin = new TGCursorWindow();
395 }
396 
397 ////////////////////////////////////////////////////////////////////////////////
398 /// Closes all signal-slot connections
399 /// Frees all memory allocated in contructor.
400 
402 {
403  fTimer->Disconnect(fTimer, "Timeout()", this, "ReplayRealtime()");
404  fTimer->TurnOff();
405  // delete fTimer;
406 
407  gClient->Disconnect(gClient, "RegisteredWindow(Window_t)", this,
408  "RegisterWindow(Window_t)");
409 
410  if (fFile) {
411  fFile->Close();
412  delete fFile;
413  }
414 
415  delete fWindowList;
416  delete fCmdEvent;
417  delete fGuiEvent;
418  delete fExtraEvent;
419  delete fMutex;
420  if (gCursorWin)
421  gCursorWin->DeleteWindow();
422  gCursorWin = 0;
423 }
424 
425 ////////////////////////////////////////////////////////////////////////////////
426 /// Initialization of data structures for replaying.
427 /// Start of replaying.
428 ///
429 /// Return value:
430 /// - kTRUE = everything is OK and replaying has begun
431 /// - kFALSE = non existing or invalid log file, replaying has not started
432 
435 {
436  fWin = 0;
437  fGuiTreeCounter = 0;
438  fCmdTreeCounter = 0;
439  fExtraTreeCounter = 0;
440  fRegWinCounter = 0;
441  fRecorder = 0;
442 
444 
446 
447  fEventReplayed = 1;
448 
449  fRecorder = r;
450  fShowMouseCursor = showMouseCursor;
451 
452  if (!fFile || fFile->IsZombie() || !fFile->IsOpen())
453  return kFALSE;
454 
455  fCmdTree = (TTree*) fFile->Get(kCmdEventTree);
456  fWinTree = (TTree*) fFile->Get(kWindowsTree);
457  fGuiTree = (TTree*) fFile->Get(kGuiEventTree);
458  fExtraTree = (TTree*) fFile->Get(kExtraEventTree);
459 
460  if (!fCmdTree || !fWinTree || ! fGuiTree || ! fExtraTree) {
461  Error("TRecorderReplaying::Initialize",
462  "The ROOT file is not valid event logfile.");
463  return kFALSE;
464  }
465 
466  try {
467  fCmdTree->SetBranchAddress(kBranchName, &fCmdEvent);
468  fWinTree->SetBranchAddress(kBranchName, &fWin);
469  fGuiTree->SetBranchAddress(kBranchName, &fGuiEvent);
470  fExtraTree->SetBranchAddress(kBranchName, &fExtraEvent);
471  }
472  catch(...) {
473  Error("TRecorderReplaying::Initialize",
474  "The ROOT file is not valid event logfile");
475  return kFALSE;
476  }
477 
478  // No event to replay in given ROOT file
479  if (!PrepareNextEvent()) {
480  Info("TRecorderReplaying::Initialize",
481  "Log file empty. No event to replay.");
482  return kFALSE;
483  }
484 
485  // Number of registered windows during recording
487 
488  // When a window is registered during replaying,
489  // TRecorderReplaying::RegisterWindow(Window_t) is called
490  gClient->Connect("RegisteredWindow(Window_t)", "TRecorderReplaying",
491  this, "RegisterWindow(Window_t)");
492 
493  Info("TRecorderReplaying::Initialize", "Replaying of file %s started",
494  fFile->GetName());
495 
497  if (f && !f->IsZombie()) {
498  TIter nextkey(f->GetListOfKeys());
499  TKey *key;
500  TObject *obj;
501  while ((key = (TKey*)nextkey())) {
503  obj = key->ReadObj();
504  if (!obj->InheritsFrom("TCanvas"))
505  continue;
506  fCanv = (TCanvas*) obj;
507  fCanv->Draw();
508  }
509  TCanvas *canvas;
510  TIter nextc(gROOT->GetListOfCanvases());
511  while ((canvas = (TCanvas*)nextc())) {
512  canvas->SetWindowSize(canvas->GetWindowWidth(),
513  canvas->GetWindowHeight());
514  }
516  f->Close();
517  }
518 
519  gPad = 0;
520  // Starts replaying
521  fTimer->Connect("Timeout()","TRecorderReplaying",this,"ReplayRealtime()");
522  fTimer->Start(0);
523 
524  return kTRUE;
525 }
526 
527 ////////////////////////////////////////////////////////////////////////////////
528 /// Creates mapping for the newly registered window w and adds this
529 /// mapping to fWindowList
530 ///
531 /// Called by signal whenever a new window is registered during replaying.
532 ///
533 /// The new window ID is mapped to the old one with the same number in the
534 /// list of registered windows.
535 /// It means that 1st new window is mapped to the 1st original,
536 /// 2nd to the 2nd, Nth new to the Nth original.
537 
539 {
540  if (fFilterStatusBar) {
541  TGWindow *win = gClient->GetWindowById(w);
542  if (win) {
543  if (win->GetParent()->InheritsFrom("TGStatusBar")) {
545  return;
546  }
547  }
548  }
549 
550  // Get original window ID that was registered as 'fRegWinCounter'th
553  }
554  else {
555  // More windows registered when replaying then when recording.
556  // Cannot continue
557  Error("TRecorderReplaying::RegisterWindow",
558  "More windows registered than expected");
559  //ReplayStop(fRecorder);
560  return;
561  }
562 
563  if ((gDebug > 0) && (fWaitingForWindow)) {
564  std::ios::fmtflags f = std::cout.flags(); // store flags
565  std::cout << " Window registered: new ID: " << std::hex << w <<
566  " previous ID: " << fWin << std::dec << std::endl;
567  std::cout.flags( f ); // restore flags (reset std::hex)
568  }
569 
570  // Lock mutex for guarding access to fWindowList
571  fMutex->Lock();
572 
573  // Increases counter of registered windows
574  fRegWinCounter++;
575 
576  // Creates new mapping of original window (fWin) and a new one (w)
577  TRecWinPair *ids = new TRecWinPair(fWin, w);
578  // Saves the newly created mapping
579  fWindowList->Add(ids);
580 
581  // If we are waiting for this window to be registered
582  // (Replaying was stopped because of that)
584 
585  if (gDebug > 0) {
586  std::ios::fmtflags f = std::cout.flags(); // store flags
587  std::cout << " Window " << std::hex << fGuiEvent->fWindow <<
588  " registered." << std::dec << std::endl;
589  std::cout.flags( f ); // restore flags (reset std::hex)
590  }
591 
593  // Sets that we do not wait for this window anymore
595 
596  // Start replaying of events again
597  fTimer->Start(25);
598  }
599  fMutex->UnLock();
600 }
601 
602 ////////////////////////////////////////////////////////////////////////////////
603 /// All references to the old windows (IDs) in fNextEvent are replaced by
604 /// new ones according to the mappings in fWindowList
605 
607 {
608  // Lock mutex for guarding access to fWindowList
609  fMutex->Lock();
610 
611  TRecWinPair *ids;
613 
614  Bool_t found = kFALSE;
615 
616  // Iterates through the whole list of mappings
617  while ((ids = (TRecWinPair*)it.Next())) {
618  // Window that the event belongs to
619  if (!found && fGuiEvent->fWindow == 0) {
620  fGuiEvent->fWindow = gVirtualX->GetDefaultRootWindow();
621  found = kTRUE;
622  }
623  else if (!found && ids->fKey == fGuiEvent->fWindow) {
624  fGuiEvent->fWindow = ids->fValue;
625  found = kTRUE;
626  }
627  for (Int_t i = 0; i < 5; ++i) {
628  if ((Long_t) ids->fKey == fGuiEvent->fUser[i])
629  fGuiEvent->fUser[i] = ids->fValue;
630  }
631  if (fGuiEvent->fMasked && ids->fKey == fGuiEvent->fMasked) {
632  fGuiEvent->fMasked = ids->fValue;
633  }
634  }
635 
636  if (!found && fGuiEvent->fWindow == 0) {
637  fGuiEvent->fWindow = gVirtualX->GetDefaultRootWindow();
638  found = kTRUE;
639  }
640  // Mapping for the event found
641  if (found) {
642  fMutex->UnLock();
643  return kTRUE;
644  }
645 
646  if (gDebug > 0) {
647  // save actual formatting flags
648  std::ios_base::fmtflags org_flags = std::cout.flags();
649  std::cout << "fGuiTreeCounter = " << std::dec << fGuiTreeCounter <<
650  " No mapping found for ID " << std::hex << fGuiEvent->fWindow << std::endl;
652  // restore original formatting flags
653  std::cout.flags(org_flags);
654  }
655 
656  // Stopps timer and waits for the appropriate window to be registered
657  fTimer->Stop();
659 
660  fMutex->UnLock();
661  return kFALSE;
662 }
663 
664 ////////////////////////////////////////////////////////////////////////////////
665 
667 {
668  // Not all the recorded events are replayed.
669  // Some of them are generated automatically in ROOT
670  // as a consequence of other events.
671  //
672  // RETURN VALUE:
673  // - kTRUE = passed TRecGuiEvent *e should be filtered
674  // (should not be replayed)
675  // - kFALSE = passed TRecGuiEvent *e should not be filtered
676  // (should be replayed)
677 
678  // We do not replay any client messages except closing of windows
679  if (e->fType == kClientMessage) {
680  if ((e->fFormat == 32) && (e->fHandle != TRecGuiEvent::kROOT_MESSAGE)
682  return kFALSE;
683  else
684  return kTRUE;
685  }
686 
687  // See TRecorderRecording::SetTypeOfConfigureNotify to get know
688  // which kConfigureNotify events are filtered
689  if (e->fType == kConfigureNotify && e->fUser[4] == TRecGuiEvent::kCNFilter) {
690  return kTRUE;
691  }
692 
693  if (e->fType == kOtherEvent) {
694  if (e->fFormat >= kGKeyPress && e->fFormat < kOtherEvent)
695  return kFALSE;
696  return kTRUE;
697  }
698 
699  return kFALSE;
700 }
701 
702 ////////////////////////////////////////////////////////////////////////////////
703 /// Finds the next event in log file to replay and sets it to fNextEvent
704 ///
705 /// Reads both from CmdTree and GuiTree and chooses that event that becomes
706 /// earlier
707 /// - fCmdTreeCounter determines actual position in fCmdTree
708 /// - fGuiTreeCounter determines actual position in fCmdTree
709 ///
710 /// If GUI event should be replayed, we must first make sure that there is
711 /// appropriate mapping for this event
712 ///
713 /// RETURN VALUE:
714 /// kFALSE = there is no event to be replayed
715 /// kTRUE = there is still at least one event to be replayed. Cases:
716 /// - fNextEvent = 0 => We are waiting for the appropriate
717 /// window to be registered
718 /// - fNextEvent != 0 => fNextEvent can be replayed (windows are
719 /// ready)
720 
722 {
723  fCmdEvent = 0;
724  fGuiEvent = 0;
725  fExtraEvent = 0;
726  fNextEvent = 0;
727 
728  // Reads the next unreplayed commandline event to fCmdEvent
731 
732  // Reads the next unreplayed extra event to fExtraEvent
735 
736  // Reads the next unreplayed GUI event to fGuiEvent
737  // Skips GUI events that should not be replayed (FilterEvent call)
738  while (fGuiTree->GetEntries() > fGuiTreeCounter) {
740  if (!fGuiEvent || !FilterEvent(fGuiEvent))
741  break;
742  fGuiTreeCounter++;
743  }
744 
745  // Chooses which one will be fNextEvent (the next event to be replayed)
746  if (fCmdEvent && fGuiEvent && fExtraEvent) {
747  // If there are all uf them, compares their times and chooses the
748  // earlier one
749  if ((fCmdEvent->GetTime() <= fGuiEvent->GetTime()) &&
752  else {
753  if (fGuiEvent->GetTime() <= fExtraEvent->GetTime())
755  else
757  }
758  }
759  else if (fCmdEvent && fGuiEvent) {
760  // If there are both of them, compares their times and chooses the
761  // earlier one
762  if (fCmdEvent->GetTime() <= fGuiEvent->GetTime())
764  else
766  }
767  else if (fCmdEvent && fExtraEvent ) {
768  // If there are both of them, compares their times and chooses the
769  // earlier one
770  if (fCmdEvent->GetTime() <= fExtraEvent->GetTime())
772  else
774  }
775  else if (fGuiEvent && fExtraEvent) {
776  // If there are both of them, compares their times and chooses the
777  // earlier one
778  if (fExtraEvent->GetTime() <= fGuiEvent->GetTime())
780  else
782  }
783 
784  // Nor commandline neither event to replay
785  else if (!fCmdEvent && !fGuiEvent && !fExtraEvent)
786  fNextEvent = 0;
787  // Only GUI event to replay
788  else if (fGuiEvent)
790  // Only commandline event to replay
791  else if (fCmdEvent)
793  else
795 
796  // Nothing to replay
797  if (fNextEvent == 0)
798  return kFALSE;
799 
800  // Commandline event to replay
801  if (fNextEvent == fCmdEvent)
802  fCmdTreeCounter++;
803 
804  // Extra event to replay
805  if (fNextEvent == fExtraEvent)
807 
808  // GUI event to replay
809  if (fNextEvent == fGuiEvent) {
810  // We have the new window to send this event to
811  if (RemapWindowReferences())
812  fGuiTreeCounter++;
813  // We do not have it yet (waiting for registraion)
814  else
815  fNextEvent = 0;
816  }
817  return kTRUE;
818 }
819 
820 ////////////////////////////////////////////////////////////////////////////////
821 /// ButtonPress and ButtonRelease must be sometimes replayed more times
822 /// Example: pressing of a button opens small window and user chooses
823 /// something from that window (color)
824 /// Window must be opened while user is choosing
825 
827 {
828  if (!fGuiEvent) {
829  Error("TRecorderReplaying::CanOverlap()", "fGuiEvent = 0");
830  return kFALSE;
831  }
832 
833  // only GUI events overlapping is allowed
835  return kFALSE;
836 
837 
838  if (gDebug > 0) {
839  std::cout << "Event overlapping " <<
840  kRecEventNames[((TRecGuiEvent*)fNextEvent)->fType] << std::endl;
842  }
843 
844  // GUI event
846 
847  // Overlapping allowed for ButtonPress, ButtonRelease and MotionNotify
848  if (e->fType == kButtonPress || e->fType == kButtonRelease ||
849  e->fType == kMotionNotify)
850  return kTRUE;
851 
852  return kFALSE;
853 }
854 
855 ////////////////////////////////////////////////////////////////////////////////
856 /// Replays the next event.
857 ///
858 /// It is called when fTimer times out.
859 /// Every time fTimer is set again to time equal to time difference between
860 /// current two events being replayed.
861 ///
862 /// It can happen that execution of an event lasts different time during the
863 /// recording and during the replaying.
864 /// If fTimer times out too early and the previous event has not been yet
865 /// replayed, it is usually postponed in order
866 /// to keep events execution in the right order.
867 /// The excpetions are determined by TRecorderReplaying::CanOverlap()
868 ///
869 
871 {
872  UInt_t keysym;
873  char str[2];
874 
875  if ((gROOT->GetEditorMode() == kText) ||
876  (gROOT->GetEditorMode() == kPaveLabel)){
877  gROOT->SetEditorMode();
878  }
879 
880  // If there are automatically generated ROOT events in the queue, they
881  // are let to be handled first
882  if (gVirtualX->EventsPending()) {
884  return;
885  }
886 
887  // Previous event has not been replayed yet and it is not allowed for
888  // this event to be replayed more times
889  if (!fEventReplayed && !CanOverlap())
890  return;
891 
892  // Event to replay prepared
893  if (fNextEvent) {
894  // Sets that fNextEvent has not been replayed yet
895  fEventReplayed = 0;
896 
897  // Remembers its execution time to compute time difference with
898  // the next event
900 
901  // Special execution of events causing potential deadlocks
904  if (ev->fType == kGKeyPress && ev->fState & kKeyControlMask) {
905  Event_t *e = ev->CreateEvent(ev);
906  gVirtualX->LookupString(e, str, sizeof(str), keysym);
907  // catch the ctrl-s event
908  if ((keysym & ~0x20) == kKey_S) {
909  fEventReplayed = 1;
912  return;
913  }
914  }
915  }
916 
917  // REPLAYS CURRENT EVENT
919 
920  // Sets that fNextEvent has been replayed
921  fEventReplayed = 1;
922  }
923 
924  // Prepares new event for replaying
925  if (!PrepareNextEvent()) {
926  // No more events to be replayed (replaying has finished).
927 
928  // Switches recorder back to INACTIVE state
929  Info("TRecorderReplaying::ReplayRealtime", "Replaying finished");
931  return;
932  }
933  else {
934  // We have event to replay here.
935 
936  // It will be replayed with the same time difference to the previous
937  // one as when recording.
938  // After given time, timer will call this method again
939  if (fNextEvent)
941  }
942 }
943 
944 ////////////////////////////////////////////////////////////////////////////////
945 /// Pauses replaying
946 
948 {
949  fTimer->Stop();
950  r->ChangeState(new TRecorderPaused(this), kFALSE);
951  Info("TRecorderReplaying::Pause", "Replaying paused.");
952 }
953 
954 ////////////////////////////////////////////////////////////////////////////////
955 /// Cancels replaying
956 
958 {
959  Info("TRecorderReplaying::ReplayStop", "Replaying cancelled");
960  r->ChangeState(new TRecorderInactive());
961 }
962 
963 ////////////////////////////////////////////////////////////////////////////////
964 /// Continues previously paused replaying
965 
967 {
968  if (fNextEvent)
970 }
971 
972 //______________________________________________________________________________
973 // Represents state of TRecorder after its creation
974 
976 
977 ////////////////////////////////////////////////////////////////////////////////
978 /// Switches from INACTIVE state to RECORDING and starts recording
979 
980 void TRecorderInactive::Start(TRecorder *r, const char *filename,
981  Option_t *option, Window_t *w, Int_t winCount)
982 {
983  // const char *filename = name of ROOT file where to store recorded events
984  // Option_t *option = option for creation of ROOT file
985  // Window_t *w = list of IDs of recorder windows (if GUI for
986  // recorder is used) [0 by default]
987  // Int_t winCount = number of IDs it this list [0 by default]
988 
989  TRecorderRecording *rec = new TRecorderRecording(r, filename, option, w, winCount);
990  if (rec->StartRecording()) {
991  r->ChangeState(rec);
992  r->fFilename = gSystem->BaseName(filename);
993  }
994  else
995  delete rec;
996 }
997 
998 ////////////////////////////////////////////////////////////////////////////////
999 /// Switches from INACTIVE state of recorder to REPLAYING
1000 /// Return kTRUE if replaying has started or kFALSE if it is not possible
1001 /// (bad file etc.)
1002 
1004  Bool_t showMouseCursor,
1006 {
1007  // const char *filename = name of ROOT file from where to replay recorded
1008  // events
1009  // TRecorder::EReplayModes mode = mode of replaying
1010 
1011  TRecorderReplaying *replay = new TRecorderReplaying(filename);
1012 
1013  if (replay->Initialize(r, showMouseCursor, mode)) {
1014  r->ChangeState(replay);
1015  r->fFilename = gSystem->BaseName(filename);
1016  return kTRUE;
1017  }
1018  else {
1019  delete replay;
1020  return kFALSE;
1021  }
1022 }
1023 
1024 ////////////////////////////////////////////////////////////////////////////////
1025 /// Prints out commandline events recorded in given file
1026 
1028 {
1029  /*
1030  if (!TClassTable::GetDict(" TRecCmdEvent")) {
1031  Error("TRecorderInactive::List", " TRecCmdEvent not in dictionary.");
1032  return;
1033  }*/
1034 
1035  TFile *file = TFile::Open(filename);
1036  if (!file) return;
1037  if (file->IsZombie() || !file->IsOpen()) {
1038  delete file;
1039  return;
1040  }
1041  TTree *t1 = (TTree*)file->Get(kCmdEventTree);
1042 
1043  if (!t1) {
1044  Error("TRecorderInactive::List",
1045  "The ROOT file is not valid event logfile.");
1046  delete file;
1047  return;
1048  }
1049 
1050  TRecCmdEvent *fCmdEvent = new TRecCmdEvent();
1051  t1->SetBranchAddress(kBranchName, &fCmdEvent);
1052 
1053  Int_t entries = t1->GetEntries();
1054  for (Int_t i = 0; i < entries; ++i) {
1055  t1->GetEntry(i);
1056  std::cout << "[" << i << "] " << "fTime=" <<
1057  (ULong64_t) fCmdEvent->GetTime() << " fText=" <<
1058  fCmdEvent->GetText() << std::endl;
1059  }
1060  std::cout << std::endl;
1061 
1062  delete fCmdEvent;
1063  delete file;
1064 }
1065 
1066 ////////////////////////////////////////////////////////////////////////////////
1067 /// Prints out GUI events recorded in given file
1068 
1070 {
1071  /*
1072  if (!TClassTable::GetDict("TRecGuiEvent")) {
1073  Error("TRecorderInactive::ListGui",
1074  "TRecGuiEvent not in the dictionary.");
1075  return;
1076  }*/
1077 
1078  TFile *file = TFile::Open(filename);
1079  if (!file) return;
1080  if (file->IsZombie() || !file->IsOpen()) {
1081  delete file;
1082  return;
1083  }
1084  TTree *t1 = (TTree*)file->Get(kGuiEventTree);
1085 
1086  if (!t1) {
1087  Error("TRecorderInactive::ListGui",
1088  "The ROOT file is not valid event logfile.");
1089  delete file;
1090  return;
1091  }
1092 
1093  TRecGuiEvent *guiEvent = new TRecGuiEvent();
1094  t1->SetBranchAddress(kBranchName, &guiEvent);
1095 
1096  Int_t entries = t1->GetEntries();
1097 
1098  for (Int_t i = 0; i < entries ; ++i) {
1099  t1->GetEntry(i);
1100  DumpRootEvent(guiEvent, i);
1101  }
1102 
1103  delete file;
1104  delete guiEvent;
1105 }
1106 
1107 ////////////////////////////////////////////////////////////////////////////////
1108 /// Prints out attributes of one GUI event TRecGuiEvent *e
1109 /// Int_n n is number of event if called in cycle
1110 
1112 {
1113  std::ios::fmtflags f = std::cout.flags(); // store flags
1114  std::cout << "[" << n << "] " << std::dec << std::setw(10)
1115  << e->GetTime().AsString() << std::setw(15) << kRecEventNames[e->fType]
1116  << " fW:" << std::hex << e->fWindow
1117  << " t:" << std::dec << e->fTime
1118  << " x:" << DisplayValid(e->fX)
1119  << " y:" << DisplayValid(e->fY)
1120  << " fXR:" << DisplayValid(e->fXRoot)
1121  << " fYR:" << DisplayValid(e->fYRoot)
1122  << " c:" << DisplayValid(e->fCode)
1123  << " s:" << DisplayValid(e->fState)
1124  << " w:" << DisplayValid(e->fWidth)
1125  << " h:" << DisplayValid(e->fHeight)
1126  << " cnt:" << DisplayValid(e->fCount)
1127  << " se:" << e->fSendEvent
1128  << " h:" << e->fHandle
1129  << " fF:" << DisplayValid(e->fFormat)
1130  << " | ";
1131 
1132  for (Int_t i=0; i<5; ++i)
1133  if (DisplayValid(e->fUser[i]) != -1)
1134  std::cout << "[" << i << "]=" << DisplayValid(e->fUser[i]);
1135 
1136  if (e->fMasked)
1137  std::cout << " | fM:" << std::hex << e->fMasked;
1138 
1139  std::cout << std::endl;
1140  std::cout.flags( f ); // restore flags (reset std::hex)
1141 }
1142 
1143 ////////////////////////////////////////////////////////////////////////////////
1144 /// Save previous canvases in a .root file
1145 
1147 {
1148  fCollect = gROOT->GetListOfCanvases();
1149  TFile *f = TFile::Open(filename, option);
1150  if (f && !f->IsZombie()) {
1151  fCollect->Write();
1152  f->Close();
1153  delete f;
1154  }
1155 }
1156 
1157 //______________________________________________________________________________
1158 // Represents state of TRecorder when paused
1159 
1161 
1162 ////////////////////////////////////////////////////////////////////////////////
1163 /// Rememeber the recorder state that is paused
1164 
1166 {
1167  fReplayingState = state;
1168 }
1169 
1170 ////////////////////////////////////////////////////////////////////////////////
1171 /// Continues replaying
1172 
1174 {
1176  Info("TRecorderPaused::Resume", "Replaying resumed");
1177 
1178  // Switches back to the previous replaying state
1180 }
1181 
1182 ////////////////////////////////////////////////////////////////////////////////
1183 /// Replaying is cancelled
1184 
1186 {
1187  delete fReplayingState;
1188 
1189  Info("TRecorderReplaying::ReplayStop", "Reaplying cancelled");
1190  r->ChangeState(new TRecorderInactive());
1191 }
1192 
1193 
1194 //______________________________________________________________________________
1195 // Represents state of TRecorder when recording events
1196 
1198 
1199 ////////////////////////////////////////////////////////////////////////////////
1200 /// Initializes TRecorderRecording for recording
1201 /// What is allocated here is deleted in destructor
1202 
1204  Option_t *option, Window_t *w,
1205  Int_t winCount)
1206 {
1207  fRecorder = r;
1208  fBeginPave = 0;
1209 
1210  // Remember window IDs of GUI recorder (appropriate events are
1211  // filtered = not recorded)
1212  fFilteredIdsCount = winCount;
1213  fFilteredIds = new Window_t[fFilteredIdsCount];
1214  for(Int_t i=0; i < fFilteredIdsCount; ++i)
1215  fFilteredIds[i] = w[i];
1216 
1217  // No unhandled commandline event in the beginning
1218  fCmdEventPending = kFALSE;
1219 
1220  // Filer pave events (mouse button move)
1221  fFilterEventPave = kFALSE;
1222 
1223  // No registered windows in the beginning
1224  fRegWinCounter = 0;
1225 
1226  // New timer for recording
1227  fTimer = new TTimer(25, kTRUE);
1228 
1229  fMouseTimer = new TTimer(50, kTRUE);
1230  fMouseTimer->Connect("Timeout()", "TRecorderRecording", this,
1231  "RecordMousePosition()");
1232 
1233  // File where store recorded events
1234  fFile = TFile::Open(filename, option);
1235 
1236  // TTrees with windows, commandline events and GUi events
1237  fWinTree = new TTree(kWindowsTree, "Windows");
1238  fCmdTree = new TTree(kCmdEventTree, "Commandline events");
1239  fGuiTree = new TTree(kGuiEventTree, "GUI events");
1240  fExtraTree = new TTree(kExtraEventTree, "Extra events");
1241 
1242  fWin = 0;
1243  fCmdEvent = new TRecCmdEvent();
1244  fGuiEvent = new TRecGuiEvent();
1245  fExtraEvent = new TRecExtraEvent();
1246 }
1247 
1248 ////////////////////////////////////////////////////////////////////////////////
1249 /// Freeing of allocated memory
1250 
1252 {
1253  delete[] fFilteredIds;
1254 
1255  if (fFile)
1256  delete fFile;
1257  delete fMouseTimer;
1258  delete fTimer;
1259  delete fCmdEvent;
1260  delete fGuiEvent;
1261  delete fExtraEvent;
1262 }
1263 
1264 ////////////////////////////////////////////////////////////////////////////////
1265 /// Connects appropriate signals and slots in order to gain all registered
1266 /// windows and processed events in ROOT and then starts recording
1267 
1269 {
1270  if (!fFile || fFile->IsZombie() || !fFile->IsOpen())
1271  return kFALSE;
1272 
1273  // When user types something in the commandline,
1274  // TRecorderRecording::RecordCmdEvent(const char *line) is called
1275  gApplication->Connect("LineProcessed(const char*)", "TRecorderRecording",
1276  this, "RecordCmdEvent(const char*)");
1277 
1278  // When a new window in ROOT is registered,
1279  // TRecorderRecording::RegisterWindow(Window_t) is called
1280  gClient->Connect("RegisteredWindow(Window_t)", "TRecorderRecording", this,
1281  "RegisterWindow(Window_t)");
1282 
1283  // When a GUI event (different from kConfigureNotify) is processed in
1284  // TGClient::HandleEvent or in TGClient::HandleMaskEvent,
1285  // TRecorderRecording::RecordGuiEvent(Event_t*, Window_t) is called
1286  gClient->Connect("ProcessedEvent(Event_t*, Window_t)", "TRecorderRecording",
1287  this, "RecordGuiEvent(Event_t*, Window_t)");
1288 
1289  // When a kConfigureNotify event is processed in TGFrame::HandleEvent,
1290  // TRecorderRecording::RecordGuiCNEvent(Event_t*) is called
1291  TQObject::Connect("TGFrame", "ProcessedConfigure(Event_t*)",
1292  "TRecorderRecording", this, "RecordGuiCNEvent(Event_t*)");
1293 
1294  // When a PaveLabel is created, TRecorderRecording::RecordPave(TObject*)
1295  // is called
1296  TQObject::Connect("TPad", "RecordPave(const TObject*)", "TRecorderRecording",
1297  this, "RecordPave(const TObject*)");
1298 
1299  // When a Text is created, TRecorderRecording::RecordText() is called
1300  TQObject::Connect("TPad", "RecordLatex(const TObject*)",
1301  "TRecorderRecording", this, "RecordText(const TObject*)");
1302 
1303  // When a PaveLabel is created, TRecorderRecording::FilterEventPave()
1304  // is called to filter mouse clicks events.
1305  TQObject::Connect("TPad", "EventPave()", "TRecorderRecording", this,
1306  "FilterEventPave()");
1307 
1308  // When starting editing a TLatex or a TPaveLabel, StartEditing()
1309  // is called to memorize edition starting time.
1310  TQObject::Connect("TPad", "StartEditing()", "TRecorderRecording", this,
1311  "StartEditing()");
1312 
1313  // Gui Builder specific events.
1314  TQObject::Connect("TGuiBldDragManager", "TimerEvent(Event_t*)",
1315  "TRecorderRecording", this, "RecordGuiBldEvent(Event_t*)");
1316 
1317  // Creates in TTrees appropriate branches to store registered windows,
1318  // commandline events and GUI events
1319  fWinTree->Branch(kBranchName, &fWin, "fWin/l");
1320  fCmdTree->Branch(kBranchName, " TRecCmdEvent", &fCmdEvent);
1321  fGuiTree->Branch(kBranchName, "TRecGuiEvent", &fGuiEvent);
1322  fExtraTree->Branch(kBranchName, "TRecExtraEvent", &fExtraEvent);
1323 
1324  Int_t numCanvases = gROOT->GetListOfCanvases()->LastIndex();
1325 
1326  if (numCanvases >= 0){
1327 
1328  TIter nextwindow (gClient->GetListOfWindows());
1329  TGWindow *twin;
1330  Window_t twin2;
1331  Int_t cnt = 0;
1332  while ((twin = (TGWindow*) nextwindow())) {
1333  twin2 = (Window_t) twin->GetId();
1334  if (IsFiltered(twin2)) {
1335  if (gDebug > 0) {
1336  std::cout << "WindowID "<< twin2 << " filtered" << std::endl;
1337  }
1338  }
1339  else if (twin != gClient->GetRoot()) {
1340  RegisterWindow(twin2);
1341  }
1342  cnt++;
1343  }
1344  //Info("TRecorderRecording::StartRecording", "Previous Canvases");
1345  }
1346 
1347  // Starts the timer for recording
1348  fTimer->TurnOn();
1349 
1350  // start mouse events recording timer
1351  fMouseTimer->Start(50);
1352 
1353  Info("TRecorderRecording::StartRecording", "Recording started. Log file: %s",
1354  fFile->GetName());
1355 
1356  return kTRUE;
1357 }
1358 
1359 ////////////////////////////////////////////////////////////////////////////////
1360 /// Disconnects all slots and stopps recording.
1361 
1363 {
1364  TQObject::Disconnect("TGuiBldDragManager", "TimerEvent(Event_t*)", this,
1365  "RecordGuiBldEvent(Event_t*)");
1366  TQObject::Disconnect("TGFrame", "ProcessedConfigure(Event_t*)", this,
1367  "RecordGuiCNEvent(Event_t*)");
1368  TQObject::Disconnect("TPad", "RecordPave(const TObject*)", this,
1369  "RecordPave(const TObject*)");
1370  TQObject::Disconnect("TPad", "RecordLatex(const TObject*)", this,
1371  "RecordText(const TObject*)");
1372  TQObject::Disconnect("TPad", "EventPave()", this, "FilterEventPave()");
1373  TQObject::Disconnect("TPad", "StartEditing()", this, "StartEditing()");
1374  gClient->Disconnect(gClient, "ProcessedEvent(Event_t*, Window_t)", this,
1375  "RecordGuiEvent(Event_t*, Window_t)");
1376  gClient->Disconnect(gClient, "RegisteredWindow(Window_t)", this,
1377  "RegisterWindow(Window_t)");
1378  gApplication->Disconnect(gApplication, "LineProcessed(const char*)", this,
1379  "RecordCmdEvent(const char*)");
1380 
1381  // Decides if to store the last event. It is stored if GUI recorder is used,
1382  // otherwise it is 'TEventRecorded::Stop' and should not be stored
1383  if (fCmdEventPending && guiCommand)
1384  fCmdTree->Fill();
1385 
1386  fRecorder->Write("recorder");
1387  fFile->Write();
1388  fFile->Close();
1389  fTimer->TurnOff();
1390 
1391  fMouseTimer->TurnOff();
1392 
1393  Info("TRecorderRecording::Stop", "Recording finished.");
1394 
1396 }
1397 
1398 ////////////////////////////////////////////////////////////////////////////////
1399 /// This method is called when RegisteredWindow(Window_t) is emitted from
1400 /// TGClient.
1401 
1403 {
1404  // Stores ID of the registered window in appropriate TTree
1405  fWin = (ULong64_t) w;
1406  fWinTree->Fill();
1407 }
1408 
1409 ////////////////////////////////////////////////////////////////////////////////
1410 /// Records commandline event (text and time) ans saves the previous
1411 /// commandline event
1412 /// This 1 event delay in saving ensures that the last commandline events
1413 /// 'TRecorder::Stop' will be not stored
1414 
1416 {
1417  // If there is some previously recorded event, saves it in TTree now
1418  if (fCmdEventPending)
1419  fCmdTree->Fill();
1420 
1421  // Fill information about this new commandline event: command text and
1422  // time of event execution
1424  fCmdEvent->SetText((char*)line);
1425 
1426  // This event will be stored next time (if it is not the last one
1427  // 'TRecorder::Stop')
1429  return;
1430 }
1431 
1432 ////////////////////////////////////////////////////////////////////////////////
1433 /// Records GUI Event_t *e different from kConfigureNotify (they are
1434 /// recorded in TRecorderRecording::RecordGuiCNEvent)
1435 ///
1436 /// It is called via signal-slot when an event is processed in
1437 /// TGClient::HandleEvent(Event_t *event)
1438 /// or in TGClient::HandleMaskEvent(Event_t *event, Window_t wid)
1439 ///
1440 /// If signal is emitted from TGClient::HandleEvent(Event_t *event),
1441 /// then wid = 0
1442 
1444 {
1445  // If this event is caused by a recorder itself (GUI recorder),
1446  // it is not recorded
1448  return;
1449 
1450  // Doesn't record the mouse clicks when a pavelabel is recorded
1451  if (fFilterEventPave && (e->fCode == 1)) {
1453  return;
1454  }
1456 
1457  // don't record any copy/paste event, as event->fUser[x] parameters
1458  // will be invalid when replaying on a different OS
1459  if (e->fType == kSelectionClear || e->fType == kSelectionRequest ||
1460  e->fType == kSelectionNotify)
1461  return;
1462 
1463  // Copies all items of e to fGuiEvent
1464  CopyEvent(e, wid);
1465 
1466  // Saves time of recording
1468 
1469  // Saves recorded event itself in TTree
1470  fGuiTree->Fill();
1471 }
1472 
1473 ////////////////////////////////////////////////////////////////////////////////
1474 /// Special case for the gui builder, having a timer handling some of the
1475 /// events.
1476 
1478 {
1479  e->fFormat = e->fType;
1480  e->fType = kOtherEvent;
1481 
1482  // Copies all items of e to fGuiEvent
1483  CopyEvent(e, 0);
1484 
1485  // Saves time of recording
1487 
1488  // Saves recorded event itself in TTree
1489  fGuiTree->Fill();
1490 }
1491 
1492 ////////////////////////////////////////////////////////////////////////////////
1493 /// Try to record all mouse moves...
1494 
1496 {
1497  Window_t dum;
1498  Event_t ev;
1499  ev.fCode = 0;
1500  ev.fType = kMotionNotify;
1501  ev.fState = 0;
1502  ev.fWindow = 0;
1503  ev.fUser[0] = ev.fUser[1] = ev.fUser[2] = ev.fUser[3] = ev.fUser[4] = 0;
1504  ev.fCount = 0;
1505  ev.fFormat = 0;
1506  ev.fHandle = 0;
1507  ev.fHeight = 0;
1508  ev.fSendEvent = 0;
1509  ev.fTime = 0;
1510  ev.fWidth = 0;
1511 
1512  gVirtualX->QueryPointer(gVirtualX->GetDefaultRootWindow(), dum, dum,
1513  ev.fXRoot, ev.fYRoot, ev.fX, ev.fY, ev.fState);
1514  ev.fXRoot -= gDecorWidth;
1515  ev.fYRoot -= gDecorHeight;
1516 
1517  RecordGuiEvent(&ev, 0);
1518  fMouseTimer->Reset();
1519 }
1520 
1521 ////////////////////////////////////////////////////////////////////////////////
1522 /// Records GUI Event_t *e of type kConfigureNotify.
1523 /// It is called via signal-slot when an kConfigureNotify event is processed
1524 /// in TGFrame::HandleEvent
1525 
1527 {
1528  // If this event is caused by a recorder itself, it is not recorded
1530  return;
1531 
1532  // Sets fUser[4] value to one of EConfigureNotifyType
1533  // According to this value, event is or is not replayed in the future
1535 
1536  // Copies all items of e to fGuiEvent
1537  CopyEvent(e, 0);
1538 
1539  // Saves time of recording
1541 
1542  // Saves recorded event itself in TTree
1543  fGuiTree->Fill();
1544 }
1545 
1546 ////////////////////////////////////////////////////////////////////////////////
1547 /// Records TPaveLabel object created in TCreatePrimitives::Pave()
1548 
1550 {
1551  Long64_t extratime = fBeginPave;
1552  Long64_t interval = (Long64_t)fTimer->GetAbsTime() - fBeginPave;
1553  TPaveLabel *pavel = (TPaveLabel *) obj;
1554  const char *label;
1555  label = pavel->GetLabel();
1556  TString aux = "";
1557  TString cad = "";
1558  cad = "TPaveLabel *p = new TPaveLabel(";
1559  cad += pavel->GetX1();
1560  cad += ",";
1561  cad += pavel->GetY1();
1562  cad += ",";
1563  cad += pavel->GetX2();
1564  cad += ",";
1565  cad += pavel->GetY2();
1566  cad += ",\"\"); p->Draw(); gPad->Modified(); gPad->Update();";
1567  Int_t i, len = (Int_t)strlen(label);
1568  interval /= (len + 2);
1569  RecordExtraEvent(cad, extratime);
1570  for (i=0; i < len; ++i) {
1571  cad = "p->SetLabel(\"";
1572  cad += (aux += label[i]);
1573  cad += "\"); ";
1574 #ifndef R__WIN32
1575  cad += " p->SetTextFont(83); p->SetTextSizePixels(14); ";
1576 #endif
1577  cad += " gPad->Modified(); gPad->Update();";
1578  extratime += interval;
1579  RecordExtraEvent(cad, extratime);
1580  }
1581  cad = "p->SetTextFont(";
1582  cad += pavel->GetTextFont();
1583  cad += "); p->SetTextSize(";
1584  cad += pavel->GetTextSize();
1585  cad += "); gPad->Modified(); gPad->Update();";
1586  extratime += interval;
1587  RecordExtraEvent(cad, extratime);
1588 }
1589 
1590 ////////////////////////////////////////////////////////////////////////////////
1591 /// Records TLatex object created in TCreatePrimitives::Text()
1592 
1594 {
1595  Long64_t extratime = fBeginPave;
1596  Long64_t interval = (Long64_t)fTimer->GetAbsTime() - fBeginPave;
1597  TLatex *texto = (TLatex *) obj;
1598  const char *label;
1599  label = texto->GetTitle();
1600  TString aux = "";
1601  TString cad = "";
1602  cad = "TLatex *l = new TLatex(";
1603  cad += texto->GetX();
1604  cad += ",";
1605  cad += texto->GetY();
1606  cad += ",\"\"); l->Draw(); gPad->Modified(); gPad->Update();";
1607  Int_t i, len = (Int_t)strlen(label);
1608  interval /= (len + 2);
1609  RecordExtraEvent(cad, extratime);
1610  for (i=0; i < len; ++i) {
1611  cad = "l->SetTitle(\"";
1612  cad += (aux += label[i]);
1613  cad += "\"); ";
1614 #ifndef R__WIN32
1615  cad += " l->SetTextFont(83); l->SetTextSizePixels(14); ";
1616 #endif
1617  cad += " gPad->Modified(); gPad->Update();";
1618  extratime += interval;
1619  RecordExtraEvent(cad, extratime);
1620  }
1621  cad = "l->SetTextFont(";
1622  cad += texto->GetTextFont();
1623  cad += "); l->SetTextSize(";
1624  cad += texto->GetTextSize();
1625  cad += "); gPad->Modified(); gPad->Update();";
1626  cad += " TVirtualPad *spad = gPad->GetCanvas()->GetSelectedPad();";
1627  cad += " gPad->GetCanvas()->Selected(spad, l, kButton1Down);";
1628  extratime += interval;
1629  RecordExtraEvent(cad, extratime);
1630 }
1631 
1632 ////////////////////////////////////////////////////////////////////////////////
1633 /// Change the state of the flag to kTRUE when you are recording a pavelabel.
1634 
1636 {
1638 }
1639 
1640 ////////////////////////////////////////////////////////////////////////////////
1641 /// Memorize the starting time of editinga TLatex or a TPaveLabel
1642 
1644 {
1646 }
1647 
1648 ////////////////////////////////////////////////////////////////////////////////
1649 /// Records TLatex or TPaveLabel object created in TCreatePrimitives,
1650 /// ExtTime is needed for the correct replay of these events.
1651 
1653 {
1654  fExtraEvent->SetTime(extTime);
1655  fExtraEvent->SetText(line);
1656  fExtraTree->Fill();
1657 }
1658 
1659 ////////////////////////////////////////////////////////////////////////////////
1660 /// Copies all items of given event to fGuiEvent
1661 
1663 {
1664  fGuiEvent->fType = e->fType;
1665  fGuiEvent->fWindow = e->fWindow;
1666  fGuiEvent->fTime = e->fTime;
1667 
1668  fGuiEvent->fX = e->fX;
1669  fGuiEvent->fY = e->fY;
1670  fGuiEvent->fXRoot = e->fXRoot;
1671  fGuiEvent->fYRoot = e->fYRoot;
1672 
1673  fGuiEvent->fCode = e->fCode;
1674  fGuiEvent->fState = e->fState;
1675 
1676  fGuiEvent->fWidth = e->fWidth;
1677  fGuiEvent->fHeight = e->fHeight;
1678 
1679  fGuiEvent->fCount = e->fCount;
1681  fGuiEvent->fHandle = e->fHandle;
1682  fGuiEvent->fFormat = e->fFormat;
1683 
1686 
1687  for(Int_t i=0; i<5; ++i)
1688  fGuiEvent->fUser[i] = e->fUser[i];
1689 
1692 
1693  if (e->fType == kGKeyPress || e->fType == kKeyRelease) {
1694  char tmp[10] = {0};
1695  UInt_t keysym = 0;
1696  gVirtualX->LookupString(e, tmp, sizeof(tmp), keysym);
1697  fGuiEvent->fCode = keysym;
1698  }
1699 
1700  fGuiEvent->fMasked = wid;
1701 }
1702 
1703 ////////////////////////////////////////////////////////////////////////////////
1704 /// Returns kTRUE if passed id belongs to window IDs of recorder GUI itself
1705 
1707 {
1708  for(Int_t i=0; i < fFilteredIdsCount; ++i)
1709  if (id == fFilteredIds[i])
1710  return kTRUE;
1711 
1712  return kFALSE;
1713 }
1714 
1715 ////////////////////////////////////////////////////////////////////////////////
1716 /// Sets type of kConfigureNotify event to one of EConfigureNotify
1717 ///
1718 /// On Linux paremeters of GUI event kConfigureNotify are different
1719 /// than parameters of the same event executed on Windows.
1720 /// Therefore we need to distinguish [on Linux], if the event is movement
1721 /// or resize event.
1722 /// On Windows, we do not need to distinguish them.
1723 
1725 {
1726  // On both platforms, we mark the events matching the criteria
1727  // (automatically generated in ROOT) as events that should be filtered
1728  // when replaying (TRecGuiEvent::kCNFilter)
1729  if ((e->fX == 0 && e->fY == 0)) { // || e->fFormat == 32 ) {
1731  return;
1732  }
1733 
1734 #ifdef WIN32
1735 
1736  // No need to distinguish between move and resize on Windows
1738 
1739 #else
1740 
1741  TGWindow *w = gClient->GetWindowById(e->fWindow);
1742  if (w) {
1743  TGFrame *t = (TGFrame *)w;
1744 
1745  // If this event does not cause any change in position or size ->
1746  // automatically generated event
1747  if (t->GetWidth() == e->fWidth && t->GetHeight() == e->fHeight &&
1748  e->fX == t->GetX() && e->fY == t->GetY()) {
1750  }
1751  else {
1752  // Size of the window did not change -> move
1753  if (t->GetWidth() == e->fWidth && t->GetHeight() == e->fHeight) {
1754  e->fUser[4] = TRecGuiEvent::kCNMove;
1755  }
1756  // Size of the window changed -> resize
1757  else {
1759  }
1760  }
1761  }
1762 
1763 #endif
1764 }
1765 
1766 
1767 
1768 //______________________________________________________________________________
1769 // The GUI for the recorder
1770 
1772 
1773 ////////////////////////////////////////////////////////////////////////////////
1774 /// The GUI for the recorder
1775 
1776 TGRecorder::TGRecorder(const TGWindow *p, UInt_t w, UInt_t h) :
1777  TGMainFrame(p ? p : gClient->GetRoot(), w, h)
1778 {
1779  TGHorizontalFrame *hframe;
1780  TGVerticalFrame *vframe;
1781  SetCleanup(kDeepCleanup);
1782  fRecorder = new TRecorder();
1783  fFilteredIds[0] = GetId();
1784 
1785  // Create a horizontal frame widget with buttons
1786  hframe = new TGHorizontalFrame(this, 200, 75, kChildFrame | kFixedHeight,
1787  (Pixel_t)0x000000);
1788  fFilteredIds[1] = hframe->GetId();
1789 
1790  // LABEL WITH TIME
1791 
1792  vframe = new TGVerticalFrame(hframe, 200, 75, kChildFrame | kFixedHeight,
1793  (Pixel_t)0x000000);
1794  fFilteredIds[2] = vframe->GetId();
1795 
1796  TGLabel *fStatusLabel = new TGLabel(vframe, "Status:");
1797  fStatusLabel->SetTextColor(0x7cffff);
1798  fStatusLabel->SetBackgroundColor((Pixel_t)0x000000);
1799  vframe->AddFrame(fStatusLabel, new TGLayoutHints(kLHintsLeft | kLHintsTop,
1800  2, 2, 2, 2));
1801  fFilteredIds[3] = fStatusLabel->GetId();
1802 
1803  TGLabel *fTimeLabel = new TGLabel(vframe, "Time: ");
1804  fTimeLabel->SetTextColor(0x7cffff);
1805  fTimeLabel->SetBackgroundColor((Pixel_t)0x000000);
1806  vframe->AddFrame(fTimeLabel, new TGLayoutHints(kLHintsLeft | kLHintsTop,
1807  2, 2, 13, 2));
1808  fFilteredIds[4] = fTimeLabel->GetId();
1809 
1810  hframe->AddFrame(vframe, new TGLayoutHints(kLHintsLeft | kLHintsExpandY));
1811 
1812  vframe = new TGVerticalFrame(hframe, 200, 75, kChildFrame | kFixedHeight,
1813  (Pixel_t)0x000000);
1814  fFilteredIds[5] = vframe->GetId();
1815 
1816  fStatus = new TGLabel(vframe, "Inactive");
1817  fStatus->SetTextColor(0x7cffff);
1818  fStatus->SetBackgroundColor((Pixel_t)0x000000);
1819  vframe->AddFrame(fStatus, new TGLayoutHints(kLHintsLeft | kLHintsTop,
1820  2, 2, 2, 2));
1821  fFilteredIds[6] = fStatus->GetId();
1822 
1823  fTimeDisplay = new TGLabel(vframe, "00:00:00");
1824  fTimeDisplay->SetTextColor(0x7cffff);
1825  fTimeDisplay->SetTextFont("Helvetica -34", kFALSE);
1826  fTimeDisplay->SetBackgroundColor((Pixel_t)0x000000);
1827  vframe->AddFrame(fTimeDisplay, new TGLayoutHints(kLHintsLeft | kLHintsTop,
1828  2, 2, 2, 2));
1829  fFilteredIds[7] = fTimeDisplay->GetId();
1830 
1831  hframe->AddFrame(vframe, new TGLayoutHints(kLHintsLeft | kLHintsExpandY,
1832  10, 0, 0, 0));
1833  AddFrame(hframe, new TGLayoutHints(kLHintsExpandX, 2, 2, 2, 2));
1834 
1835  // Create a horizontal frame widget with buttons
1836  hframe = new TGHorizontalFrame(this, 200, 200);
1837  fFilteredIds[8] = hframe->GetId();
1838 
1839  // START-STOP button
1840  fStartStop = new TGPictureButton(hframe,gClient->GetPicture("record.png"));
1841  fStartStop->SetStyle(gClient->GetStyle());
1842  fStartStop->Connect("Clicked()","TGRecorder",this,"StartStop()");
1843  hframe->AddFrame(fStartStop, new TGLayoutHints(kLHintsLeft | kLHintsTop,
1844  2, 2, 2, 2));
1845  fStartStop->Resize(40,40);
1846  fFilteredIds[9] = fStartStop->GetId();
1847 
1848  // REPLAY button
1849  fReplay = new TGPictureButton(hframe,gClient->GetPicture("replay.png"));
1850  fReplay->SetStyle(gClient->GetStyle());
1851  fReplay->Connect("Clicked()","TGRecorder",this,"Replay()");
1852  hframe->AddFrame(fReplay, new TGLayoutHints(kLHintsLeft | kLHintsTop,
1853  2, 2, 2, 2));
1854  fReplay->Resize(40,40);
1855  fFilteredIds[10] = fReplay->GetId();
1856 
1857  // MOUSE CURSOR CHECKBOX
1858  fCursorCheckBox = new TGCheckButton(this,"Show mouse cursor");
1859  AddFrame(fCursorCheckBox, new TGLayoutHints(kLHintsCenterX, 2, 2, 2, 2));
1860  fFilteredIds[11] = fCursorCheckBox->GetId();
1861 
1862  // Timer
1863  fTimer = new TTimer(25);
1864  fTimer->Connect("Timeout()", "TGRecorder", this, "Update()");
1865 
1866  AddFrame(hframe, new TGLayoutHints(kLHintsCenterX, 2, 2, 2, 2));
1867 
1868  SetEditDisabled(kEditDisable | kEditDisableGrab);
1869  SetWindowName("ROOT Event Recorder");
1870  MapSubwindows();
1871  Layout();
1872  MapWindow();
1873 
1874  SetDefault();
1875 }
1876 
1877 ////////////////////////////////////////////////////////////////////////////////
1878 /// Sets GUI to the default inactive state
1879 
1881 {
1882  fTimeDisplay->SetText("00:00:00");
1883 
1884  fReplay->SetPicture(gClient->GetPicture("replay.png"));
1886 
1889 
1890  fStartStop->SetPicture(gClient->GetPicture("record.png"));
1892 }
1893 
1894 ////////////////////////////////////////////////////////////////////////////////
1895 /// Called when fTimer timeouts (every 0.025 second)
1896 /// Updates GUI of recorder
1897 
1899 {
1900  struct tm *running;
1901  static int cnt = 0;
1902  TString stime;
1903  time( &fElapsed );
1904  time_t elapsed_time = (time_t)difftime( fElapsed, fStart );
1905  running = gmtime( &elapsed_time );
1906 
1907  switch(fRecorder->GetState()) {
1908 
1909  // When recording or replaying, updates timer
1910  // and displays new value of seconds counter
1911  case TRecorder::kRecording:
1912  case TRecorder::kReplaying:
1913 
1914  // Every whole second: updates timer and displays new value
1915  if (cnt >= 10) {
1917  fStatus->SetText("Replaying");
1918  else
1919  fStatus->SetText("Recording");
1920  stime.Form("%02d:%02d:%02d", running->tm_hour,
1921  running->tm_min, running->tm_sec);
1922  fTimeDisplay->SetText(stime.Data());
1923 
1924  cnt = 0;
1925  if (gVirtualX->EventsPending()) {
1926  fStatus->SetText("Waiting...");
1927  fStatus->SetTextColor((Pixel_t)0xff0000);
1928  }
1929  else {
1930  fStatus->SetTextColor((Pixel_t)0x7cffff);
1931  }
1932  fStatus->Resize();
1933  fTimeDisplay->Resize();
1934  }
1935  else
1936  ++cnt;
1937 
1938  // Changes background color according to the queue of pending events
1939  fTimer->Reset();
1940  break;
1941 
1942  // End of replaying or recording. Sets recorder GUI to default state
1943  case TRecorder::kInactive:
1944  fStatus->SetText("Inactive");
1945  fStatus->SetTextColor((Pixel_t)0x7cffff);
1946  fStatus->Resize();
1947  fTimer->TurnOff();
1948  SetDefault();
1949  break;
1950 
1951  default:
1952  break;
1953  }
1954 }
1955 
1956 ////////////////////////////////////////////////////////////////////////////////
1957 /// Handles push of the fStartStop button
1958 /// according to the current recorder state
1959 
1961 {
1962  static const char *gFiletypes[] = {
1963  "All files", "*", "Text files", "*.txt", "ROOT files", "*.root", 0, 0
1964  };
1965  TGFileInfo fi;
1966 
1967  switch(fRecorder->GetState()) {
1968 
1969  // Starts recording
1970  case TRecorder::kInactive:
1971 
1972  fi.fFileTypes = gFiletypes;
1973  fi.fOverwrite = kFALSE;
1974 
1975  new TGFileDialog(gClient->GetDefaultRoot(),
1976  gClient->GetDefaultRoot(),
1977  kFDSave,&fi);
1978 
1979  if (fi.fFilename && strlen(fi.fFilename)) {
1980 
1981  if (!gROOT->GetListOfCanvases()->IsEmpty()) {
1982  fRecorder->PrevCanvases(fi.fFilename, "RECREATE");
1983  fRecorder->Start(fi.fFilename, "UPDATE", fFilteredIds,
1984  fgWidgetsCount);
1985  }
1986  else {
1987  fRecorder->Start(fi.fFilename, "RECREATE", fFilteredIds,
1988  fgWidgetsCount);
1989  }
1991  fStartStop->SetPicture(gClient->GetPicture("stop.png"));
1993  fTimer->TurnOn();
1994  time( &fStart );
1995  }
1996  break;
1997 
1998  // Stops recording
1999  case TRecorder::kRecording:
2000  fRecorder->Stop(kTRUE);
2001  break;
2002 
2003  // Pauses replaying
2004  case TRecorder::kReplaying:
2005  fRecorder->Pause();
2006  fStartStop->SetPicture(gClient->GetPicture("replay.png"));
2007  break;
2008 
2009  // Resumes replaying
2010  case TRecorder::kPaused:
2011  fRecorder->Resume();
2012  fStartStop->SetPicture(gClient->GetPicture("pause.png"));
2013  break;
2014 
2015  default:
2016  break;
2017  } // switch
2018 }
2019 
2020 ////////////////////////////////////////////////////////////////////////////////
2021 /// Handles push of fReplay button
2022 /// according to the current recorder state
2023 
2025 {
2026  TGFileInfo fi;
2027 
2028  switch(fRecorder->GetState()) {
2029 
2030  // Starts replaying
2031  case TRecorder::kInactive:
2032 
2033  new TGFileDialog(gClient->GetDefaultRoot(),
2034  gClient->GetDefaultRoot(),
2035  kFDOpen, &fi);
2036 
2037  if (fi.fFilename && strlen(fi.fFilename)) {
2039 
2040  fTimer->TurnOn();
2041  time( &fStart );
2042 
2043  fReplay->SetPicture(gClient->GetPicture("stop.png"));
2044  fStartStop->SetPicture(gClient->GetPicture("pause.png"));
2045 
2046  if (fCursorCheckBox->IsOn())
2048 
2050  }
2051  }
2052  break;
2053 
2054  // Stops replaying
2055  case TRecorder::kReplaying:
2056  case TRecorder::kPaused:
2057  fRecorder->ReplayStop();
2058  break;
2059 
2060  default:
2061  break;
2062 
2063  } // switch
2064 }
2065 
2066 ////////////////////////////////////////////////////////////////////////////////
2067 /// Destructor. Cleanup the GUI.
2068 
2070 {
2071  fTimer->TurnOff();
2072  delete fTimer;
2073  Cleanup();
2074 }
2075 
2076 //______________________________________________________________________________
2077 // Helper class
2078 
2081 
2082 ////////////////////////////////////////////////////////////////////////////////
2083 /// Replays stored GUI event
2084 
2085 void TRecGuiEvent::ReplayEvent(Bool_t showMouseCursor)
2086 {
2087  Int_t px, py, dx, dy;
2088  Window_t wtarget;
2089  Event_t *e = CreateEvent(this);
2090 
2091  // don't try to replay any copy/paste event, as event->fUser[x]
2092  // parameters are invalid on different OSes
2093  if (e->fType == kSelectionClear || e->fType == kSelectionRequest ||
2094  e->fType == kSelectionNotify) {
2095  delete e;
2096  return;
2097  }
2098 
2099  // Replays movement/resize event
2100  if (e->fType == kConfigureNotify) {
2101  TGWindow *w = gClient->GetWindowById(e->fWindow);
2102 
2103  // Theoretically, w should always exist (we found the right mapping,
2104  // otherwise we would not get here).
2105  // Anyway, it can happen that it was destroyed by some earlier ROOT event
2106  // We give higher priority to automatically generated
2107  // ROOT events in TRecorderReplaying::ReplayRealtime.
2108 
2109  if (w) {
2111  if (e->fUser[4] == TRecGuiEvent::kCNMove) {
2112  // Linux: movement of the window
2113  // first get window attribute to compensate the border size
2114  gVirtualX->GetWindowAttributes(e->fWindow, attr);
2115  if ((e->fX - attr.fX > 0) && (e->fY - attr.fY > 0))
2116  w->Move(e->fX - attr.fX, e->fY - attr.fY);
2117  }
2118  else {
2119  if (e->fUser[4] == TRecGuiEvent::kCNResize) {
2120  // Linux: resize of the window
2121  w->Resize(e->fWidth, e->fHeight);
2122  }
2123  else {
2124  if (e->fUser[4] == TRecGuiEvent::kCNMoveResize) {
2125  // Windows: movement or resize of the window
2126  w->MoveResize(e->fX, e->fY, e->fWidth, e->fHeight);
2127  }
2128  else {
2129  if (gDebug > 0)
2130  Error("TRecGuiEvent::ReplayEvent",
2131  "kConfigureNotify: Unknown value: fUser[4] = %ld ",
2132  e->fUser[4]);
2133  }
2134  }
2135  }
2136  }
2137  else {
2138  // w = 0
2139  if (gDebug > 0)
2140  Error("TRecGuiEvent::ReplayEvent",
2141  "kConfigureNotify: Window does not exist anymore ");
2142  }
2143  delete e;
2144  return;
2145 
2146  } // kConfigureNotify
2147 
2148  if (showMouseCursor && e->fType == kButtonPress) {
2149  gVirtualX->TranslateCoordinates(e->fWindow, gVirtualX->GetDefaultRootWindow(),
2150  e->fX, e->fY, px, py, wtarget);
2151  dx = px - gCursorWin->GetX();
2152  dy = py - gCursorWin->GetY();
2153  if (TMath::Abs(dx) > 5) gDecorWidth += dx;
2154  if (TMath::Abs(dy) > 5) gDecorHeight += dy;
2155  }
2156  // Displays fake mouse cursor for MotionNotify event
2157  if (showMouseCursor && e->fType == kMotionNotify) {
2158  if (gCursorWin && e->fWindow == gVirtualX->GetDefaultRootWindow()) {
2159  if (!gCursorWin->IsMapped()) {
2160  gCursorWin->MapRaised();
2161  }
2162  if (gVirtualX->GetDrawMode() == TVirtualX::kCopy) {
2163 //#ifdef R__MACOSX
2164  // this may have side effects (e.g. stealing focus)
2165  gCursorWin->RaiseWindow();
2166 //#endif
2167  gCursorWin->Move(e->fXRoot + gDecorWidth, e->fYRoot + gDecorHeight);
2168  }
2169  }
2170  }
2171 
2172  // Lets all the other events to be handled the same way as when recording
2173  // first, special case for the gui builder, having a timer handling
2174  // some of the events
2175  if (e->fType == kOtherEvent && e->fFormat >= kGKeyPress &&
2176  e->fFormat < kOtherEvent) {
2177  e->fType = (EGEventType)e->fFormat;
2178  if (gDragManager)
2180  delete e;
2181  return;
2182  }
2183  else { // then the normal cases
2184  if (!fMasked)
2185  gClient->HandleEvent(e);
2186  else
2187  gClient->HandleMaskEvent(e, fMasked);
2188  }
2189  delete e;
2190 }
2191 
2192 ////////////////////////////////////////////////////////////////////////////////
2193 /// Converts TRecGuiEvent type to Event_t type
2194 
2196 {
2197  Event_t *e = new Event_t();
2198 
2199  // Copies all data items
2200 
2201  e->fType = ge->fType;
2202  e->fWindow = ge->fWindow;
2203  e->fTime = ge->fTime;
2204 
2205  e->fX = ge->fX;
2206  e->fY = ge->fY;
2207  e->fXRoot = ge->fXRoot;
2208  e->fYRoot = ge->fYRoot;
2209 
2210  e->fCode = ge->fCode;
2211  e->fState = ge->fState;
2212 
2213  e->fWidth = ge->fWidth;
2214  e->fHeight = ge->fHeight;
2215 
2216  e->fCount = ge->fCount;
2217  e->fSendEvent = ge->fSendEvent;
2218 
2219  e->fHandle = ge->fHandle;
2220  e->fFormat = ge->fFormat;
2221 
2223  e->fHandle = gROOT_MESSAGE;
2224 
2225  for(Int_t i=0; i<5; ++i)
2226  e->fUser[i] = ge->fUser[i];
2227 
2229  e->fUser[0] = gWM_DELETE_WINDOW;
2230 
2231  if (ge->fType == kGKeyPress || ge->fType == kKeyRelease) {
2232  e->fCode = gVirtualX->KeysymToKeycode(ge->fCode);
2233 #ifdef R__WIN32
2234  e->fUser[1] = 1;
2235  e->fUser[2] = e->fCode;
2236 #endif
2237  }
2238 
2239  return e;
2240 }
2241 
void RegisterWindow(Window_t w)
This method is called when RegisteredWindow(Window_t) is emitted from TGClient.
Definition: TRecorder.cxx:1402
virtual const char * BaseName(const char *pathname)
Base name of a file name. Base name of /user/root is root.
Definition: TSystem.cxx:928
virtual Int_t Write(const char *name=0, Int_t option=0, Int_t bufsize=0)
Write this object to the current directory.
Definition: TObject.cxx:823
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:52
void RecordCmdEvent(const char *line)
Records commandline event (text and time) ans saves the previous commandline event This 1 event delay...
Definition: TRecorder.cxx:1415
Bool_t fSendEvent
Definition: GuiTypes.h:185
Time_t fTime
Definition: TRecorder.h:305
TGPictureButton * fReplay
Definition: TRecorder.h:807
virtual void Resize(UInt_t w=0, UInt_t h=0)
Resize the frame.
Definition: TGFrame.cxx:587
Bool_t fSendEvent
Definition: TRecorder.h:315
TRecExtraEvent * fExtraEvent
Definition: TRecorder.h:597
Definition: TMutex.h:37
const char * kRecEventNames[]
Definition: TRecorder.cxx:138
Long_t fUser[5]
Definition: TRecorder.h:318
Bool_t Replay(const char *filename, Bool_t showMouseCursor=kTRUE, TRecorder::EReplayModes mode=kRealtime)
Replays events from 'filename'.
Definition: TRecorder.cxx:283
friend class TRecorderInactive
Definition: TRecorder.h:632
virtual Bool_t ProcessEvents()
Process pending events (GUI, timers, sockets).
Definition: TSystem.cxx:420
Window_t fValue
Definition: TRecorder.h:369
void CopyEvent(Event_t *e, Window_t wid)
Copies all items of given event to fGuiEvent.
Definition: TRecorder.cxx:1662
void RecordText(const TObject *obj)
Records TLatex object created in TCreatePrimitives::Text()
Definition: TRecorder.cxx:1593
TCanvas * fCanv
Definition: TRecorder.h:584
void FilterEventPave()
Change the state of the flag to kTRUE when you are recording a pavelabel.
Definition: TRecorder.cxx:1635
void ListGui(const char *filename)
Prints out recorded GUI events.
Definition: TRecorder.cxx:324
long long Long64_t
Definition: RtypesCore.h:69
ULong64_t fWin
Definition: TRecorder.h:681
Bool_t fWaitingForWindow
Definition: TRecorder.h:615
unsigned int hex
Definition: math.cpp:442
virtual Font_t GetTextFont() const
Definition: TAttText.h:49
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:487
static long DisplayValid(Long_t n)
Definition: TRecorder.h:754
const TGWindow * GetParent() const
Definition: TGWindow.h:87
void Reset()
Reset the timer.
Definition: TTimer.cxx:155
TLine * line
Bool_t fOverwrite
Definition: TGFileDialog.h:67
const char Option_t
Definition: RtypesCore.h:62
virtual void SetTextColor(Pixel_t color, Bool_t global=kFALSE)
Changes text color.
Definition: TGLabel.cxx:359
Int_t fCount
Definition: GuiTypes.h:184
TTree * fExtraTree
Definition: TRecorder.h:592
virtual Int_t Fill()
Fill all branches.
Definition: TTree.cxx:4328
Double_t GetX2() const
Definition: TBox.h:73
TH1 * h
Definition: legend2.C:5
virtual void SetPicture(const TGPicture *new_pic)
Change a picture in a picture button.
Definition: TGButton.cxx:990
UInt_t GetWidth() const
Definition: TGFrame.h:287
void RecordExtraEvent(TString line, TTime extTime)
Records TLatex or TPaveLabel object created in TCreatePrimitives, ExtTime is needed for the correct r...
Definition: TRecorder.cxx:1652
virtual void ListCmd(const char *)
Definition: TRecorder.h:547
const char * kCmdEventTree
Definition: TRecorder.cxx:163
EGEventType
Definition: GuiTypes.h:60
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format...
Definition: TFile.h:45
TGCheckButton * fCursorCheckBox
Definition: TRecorder.h:811
virtual Float_t GetTextSize() const
Definition: TAttText.h:50
Int_t fCount
Definition: TRecorder.h:314
virtual TObject * Get(const char *namecycle)
Return pointer to object identified by namecycle.
static const char * filename()
virtual void Pause(TRecorder *)
Definition: TRecorder.h:543
#define gROOT
Definition: TROOT.h:340
Double_t GetY() const
Definition: TText.h:76
Int_t fExtraTreeCounter
Definition: TRecorder.h:602
Int_t fY
Definition: GuiTypes.h:179
void SetText(TString text)
Definition: TRecorder.h:262
virtual Int_t GetEntry(Long64_t entry=0, Int_t getall=0)
Read all branches of entry and return total number of bytes read.
Definition: TTree.cxx:5163
R__EXTERN Atom_t gWM_DELETE_WINDOW
Definition: TVirtualX.h:51
Bool_t IsZombie() const
Definition: TObject.h:141
Basic string class.
Definition: TString.h:137
virtual TTime GetTime() const
Definition: TRecorder.h:187
#define gClient
Definition: TGClient.h:174
int Int_t
Definition: RtypesCore.h:41
TSeqCollection * fCollect
Definition: TRecorder.h:739
bool Bool_t
Definition: RtypesCore.h:59
const Bool_t kFALSE
Definition: Rtypes.h:92
virtual Bool_t Replay(TRecorder *, const char *, Bool_t, TRecorder::EReplayModes)
Definition: TRecorder.h:542
virtual void SetTime(TTime t)
Definition: TRecorder.h:192
Int_t GetY() const
Definition: TGFrame.h:295
R__EXTERN TApplication * gApplication
Definition: TApplication.h:171
Bool_t FilterEvent(TRecGuiEvent *e)
Definition: TRecorder.cxx:666
Basic time type with millisecond precision.
Definition: TTime.h:29
UInt_t GetHeight() const
Definition: TGFrame.h:288
TTime fPreviousEventTime
Definition: TRecorder.h:612
TObject * Next()
Return next object in the list. Returns 0 when no more objects in list.
Definition: TList.cxx:932
UInt_t GetWindowHeight() const
Definition: TCanvas.h:185
void Start(const char *filename, Option_t *option="RECREATE", Window_t *w=0, Int_t winCount=0)
Starts recording events.
Definition: TRecorder.cxx:266
Window_t fWindow
Definition: GuiTypes.h:177
TLatex * t1
Definition: textangle.C:20
void RecordPave(const TObject *obj)
Records TPaveLabel object created in TCreatePrimitives::Pave()
Definition: TRecorder.cxx:1549
Short_t Abs(Short_t d)
Definition: TMathBase.h:110
virtual void ReplayStop(TRecorder *)
Definition: TRecorder.h:545
R__EXTERN TVirtualDragManager * gDragManager
Int_t fYRoot
Definition: TRecorder.h:309
Iterator of linked list.
Definition: TList.h:187
Int_t UnLock()
Unlock the mutex.
Definition: TMutex.cxx:68
TGCursorWindow()
TGCursorWindow constructor.
Definition: TRecorder.cxx:196
Definition: Buttons.h:30
friend class TRecorderPaused
Definition: TRecorder.h:633
static TFile * Open(const char *name, Option_t *option="", const char *ftitle="", Int_t compress=1, Int_t netopt=0)
Create / open a file.
Definition: TFile.cxx:3851
virtual void ReplayStop(TRecorder *r)
Replaying is cancelled.
Definition: TRecorder.cxx:1185
TRecorderReplaying * fReplayingState
Definition: TRecorder.h:778
const char * Data() const
Definition: TString.h:349
UInt_t fHeight
Definition: TRecorder.h:313
virtual void Start(TRecorder *, const char *, Option_t *, Window_t *, Int_t)
Definition: TRecorder.h:540
TList * fWindowList
Definition: TRecorder.h:608
Window_t fMasked
Definition: TRecorder.h:322
void Update()
Called when fTimer timeouts (every 0.025 second) Updates GUI of recorder.
Definition: TRecorder.cxx:1898
virtual Bool_t IsOpen() const
Returns kTRUE in case file is open and kFALSE if file is not open.
Definition: TFile.cxx:1373
ULong_t Pixel_t
Definition: GuiTypes.h:41
TTime GetAbsTime() const
Definition: TTimer.h:84
virtual Int_t SetBranchAddress(const char *bname, void *add, TBranch **ptr=0)
Change branch address, dealing with clone trees properly.
Definition: TTree.cxx:7529
friend class TRecorderInactive
Definition: TRecorder.h:699
virtual void SetText(TGString *newText)
Set new text in label.
Definition: TGLabel.cxx:177
Bool_t fCmdEventPending
Definition: TRecorder.h:686
const char ** fFileTypes
Definition: TGFileDialog.h:65
TRecorder()
Creates initial INACTIVE state for the recorder.
Definition: TRecorder.cxx:224
Handle_t fHandle
Definition: GuiTypes.h:186
virtual void Start(Long_t milliSec=-1, Bool_t singleShot=kFALSE)
Starts the timer with a milliSec timeout.
Definition: TTimer.cxx:209
To draw Mathematical Formula.
Definition: TLatex.h:33
Handle_t Atom_t
Definition: GuiTypes.h:38
virtual void Stop(TRecorder *, Bool_t)
Definition: TRecorder.h:541
TRecCmdEvent * fCmdEvent
Definition: TRecorder.h:596
TGLabel * fTimeDisplay
Definition: TRecorder.h:810
void RecordGuiCNEvent(Event_t *e)
Records GUI Event_t *e of type kConfigureNotify.
Definition: TRecorder.cxx:1526
Int_t fXRoot
Definition: GuiTypes.h:180
if(pyself &&pyself!=Py_None)
TRecGuiEvent * fGuiEvent
Definition: TRecorder.h:682
void Info(const char *location, const char *msgfmt,...)
TRecGuiEvent * fGuiEvent
Definition: TRecorder.h:595
void RecordMousePosition()
Try to record all mouse moves...
Definition: TRecorder.cxx:1495
Handle_t fHandle
Definition: TRecorder.h:316
TRecCmdEvent * fCmdEvent
Definition: TRecorder.h:683
virtual void SetBackgroundColor(Pixel_t back)
Set background color (override from TGWindow base class).
Definition: TGFrame.cxx:294
virtual void ListGui(const char *filename)
Prints out GUI events recorded in given file.
Definition: TRecorder.cxx:1069
TTimer * fTimer
Definition: TRecorder.h:813
void Replay()
Handles push of fReplay button according to the current recorder state.
Definition: TRecorder.cxx:2024
Book space in a file, create I/O buffers, to fill them, (un)compress them.
Definition: TKey.h:30
Bool_t Initialize(TRecorder *r, Bool_t showMouseCursor, TRecorder::EReplayModes mode)
Initialization of data structures for replaying.
Definition: TRecorder.cxx:433
const char * AsString() const
void ListCmd(const char *filename)
Prints out recorded commandline events.
Definition: TRecorder.cxx:316
virtual void SetDisabledAndSelected(Bool_t)
Set the state of a check button to disabled and either on or off.
Definition: TGButton.cxx:1260
TRecorder * fRecorder
Definition: TRecorder.h:578
void Error(const char *location, const char *msgfmt,...)
Int_t fXRoot
Definition: TRecorder.h:308
time_t fStart
Definition: TRecorder.h:814
TString fFilename
Definition: TRecorder.h:453
TRecExtraEvent * fExtraEvent
Definition: TRecorder.h:684
A doubly linked list.
Definition: TList.h:47
virtual ~TGRecorder()
Destructor. Cleanup the GUI.
Definition: TRecorder.cxx:2069
A Pave (see TPave) with a text centered in the Pave.
Definition: TPaveLabel.h:32
virtual void SetStyle(UInt_t newstyle)
Set the button style (modern or classic).
Definition: TGButton.cxx:221
Bool_t fOverrideRedirect
Definition: GuiTypes.h:108
void SetText(const char *text)
Definition: TRecorder.h:220
Using a TBrowser one can browse all ROOT objects.
Definition: TBrowser.h:41
Bool_t Connect(const char *signal, const char *receiver_class, void *receiver, const char *slot)
Non-static method is used to connect from the signal of this object to the receiver slot...
Definition: TQObject.cxx:1135
const char * kBranchName
Definition: TRecorder.cxx:167
virtual void Resize(UInt_t w, UInt_t h)
Resize the window.
Definition: TGWindow.cxx:164
virtual Bool_t Replay(TRecorder *r, const char *filename, Bool_t showMouseCursor, TRecorder::EReplayModes mode)
Switches from INACTIVE state of recorder to REPLAYING Return kTRUE if replaying has started or kFALSE...
Definition: TRecorder.cxx:1003
TGLabel * fStatus
Definition: TRecorder.h:809
const char * GetText() const
Definition: TRecorder.h:225
ROOT::R::TRInterface & r
Definition: Object.C:4
virtual void Stop(TRecorder *r, Bool_t guiCommand)
Disconnects all slots and stopps recording.
Definition: TRecorder.cxx:1362
R__EXTERN TSystem * gSystem
Definition: TSystem.h:549
const Mask_t kWASaveUnder
Definition: GuiTypes.h:151
void Resume()
Resumes replaying.
Definition: TRecorder.cxx:300
Time_t fTime
Definition: GuiTypes.h:178
EGEventType fType
Definition: GuiTypes.h:176
void ChangeState(TRecorderState *newstate, Bool_t deletePreviousState=kTRUE)
Changes state from the current to the passed one (newstate) Deletes the old state if delPreviousState...
Definition: TRecorder.cxx:333
UInt_t fHeight
Definition: GuiTypes.h:183
virtual Int_t Write(const char *name=0, Int_t opt=0, Int_t bufsiz=0)
Write memory objects to this file.
Definition: TFile.cxx:2248
static const char * gFiletypes[]
Definition: TGTextEdit.cxx:48
time_t fElapsed
Definition: TRecorder.h:814
void RegisterWindow(Window_t w)
Creates mapping for the newly registered window w and adds this mapping to fWindowList.
Definition: TRecorder.cxx:538
Window_t fKey
Definition: TRecorder.h:368
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2321
void SetTypeOfConfigureNotify(Event_t *e)
Sets type of kConfigureNotify event to one of EConfigureNotify.
Definition: TRecorder.cxx:1724
unsigned int UInt_t
Definition: RtypesCore.h:42
UInt_t fState
Definition: TRecorder.h:311
virtual void Continue()
Continues previously paused replaying.
Definition: TRecorder.cxx:966
virtual void TurnOff()
Remove timer from system timer list.
Definition: TTimer.cxx:227
static void DumpRootEvent(TRecGuiEvent *e, Int_t n)
Prints out attributes of one GUI event TRecGuiEvent *e Int_n n is number of event if called in cycle...
Definition: TRecorder.cxx:1111
void ReplayRealtime()
Replays the next event.
Definition: TRecorder.cxx:870
virtual Bool_t IsOn() const
Definition: TGButton.h:315
static Int_t gDecorWidth
Definition: TRecorder.cxx:190
Int_t fYRoot
Definition: GuiTypes.h:180
UInt_t fWidth
Definition: TRecorder.h:312
Handles synchronous and a-synchronous timer events.
Definition: TTimer.h:57
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:51
ClassImp(TRecorderReplaying) TRecorderReplaying
Allocates all necessary data structures used for replaying What is allocated here is deleted in destr...
Definition: TRecorder.cxx:361
Long64_t fBeginPave
Definition: TRecorder.h:674
static Int_t gDecorHeight
Definition: TRecorder.cxx:191
TTimer * fMouseTimer
Definition: TRecorder.h:673
const char * kGuiEventTree
Definition: TRecorder.cxx:164
#define gVirtualX
Definition: TVirtualX.h:362
UInt_t GetWindowWidth() const
Definition: TCanvas.h:184
virtual ERecEventType GetType() const =0
Bool_t PrepareNextEvent()
Finds the next event in log file to replay and sets it to fNextEvent.
Definition: TRecorder.cxx:721
static const Int_t fgWidgetsCount
Definition: TRecorder.h:816
virtual void Move(Int_t x, Int_t y)
Move the window.
Definition: TGWindow.cxx:156
const char * kExtraEventTree
Definition: TRecorder.cxx:166
long Long_t
Definition: RtypesCore.h:50
The Canvas class.
Definition: TCanvas.h:48
void PrevCanvases(const char *filename, Option_t *option)
Save previous canvases in a .root file.
Definition: TRecorder.cxx:1146
void RecordGuiEvent(Event_t *e, Window_t wid)
Records GUI Event_t *e different from kConfigureNotify (they are recorded in TRecorderRecording::Reco...
Definition: TRecorder.cxx:1443
void Replay()
Definition: TRecorder.h:491
virtual void ReplayEvent(Bool_t showMouseCursor=kTRUE)=0
TRecorderState * fRecorderState
Definition: TRecorder.h:441
double f(double x)
Pixmap_t GetPicture() const
Definition: TGPicture.h:75
virtual void ListCmd(const char *filename)
Prints out commandline events recorded in given file.
Definition: TRecorder.cxx:1027
virtual void SetEnabled(Bool_t e=kTRUE)
Set enabled or disabled state of button.
Definition: TGButton.cxx:409
UInt_t fCode
Definition: GuiTypes.h:181
void StartStop()
Handles push of the fStartStop button according to the current recorder state.
Definition: TRecorder.cxx:1960
unsigned long long ULong64_t
Definition: RtypesCore.h:70
Pixmap_t GetMask() const
Definition: TGPicture.h:76
const Mask_t kWAOverrideRedirect
Definition: GuiTypes.h:150
UInt_t fCode
Definition: TRecorder.h:310
Int_t fFormat
Definition: TRecorder.h:317
char * fFilename
Definition: TGFileDialog.h:63
Int_t Lock()
Lock the mutex.
Definition: TMutex.cxx:46
void RecordGuiBldEvent(Event_t *e)
Special case for the gui builder, having a timer handling some of the events.
Definition: TRecorder.cxx:1477
Bool_t Disconnect(const char *signal=0, void *receiver=0, const char *slot=0)
Disconnects signal of this object from slot of receiver.
Definition: TQObject.cxx:1293
void ReplayStop()
Cancells replaying.
Definition: TRecorder.cxx:308
void SetWindowSize(UInt_t ww, UInt_t wh)
Definition: TCanvas.h:221
virtual void AddFrame(TGFrame *f, TGLayoutHints *l=0)
Add frame to the composite frame using the specified layout hints.
Definition: TGFrame.cxx:1099
Int_t GetX() const
Definition: TGFrame.h:294
virtual void SetOn(Bool_t on=kTRUE, Bool_t emit=kFALSE)
Definition: TGButton.h:124
void SetDefault()
Sets GUI to the default inactive state.
Definition: TRecorder.cxx:1880
Bool_t fFilterStatusBar
Definition: TRecorder.h:629
Bool_t fFilterEventPave
Definition: TRecorder.h:696
const char * GetLabel() const
Definition: TPaveLabel.h:47
void StartEditing()
Memorize the starting time of editinga TLatex or a TPaveLabel.
Definition: TRecorder.cxx:1643
Long_t fUser[5]
Definition: GuiTypes.h:188
Bool_t fShowMouseCursor
Definition: TRecorder.h:627
Mother of all ROOT objects.
Definition: TObject.h:58
TRecorder * fRecorder
Definition: TRecorder.h:668
Window_t fFilteredIds[fgWidgetsCount]
Definition: TRecorder.h:817
Window_t * fFilteredIds
Definition: TRecorder.h:694
virtual Int_t Branch(TCollection *list, Int_t bufsize=32000, Int_t splitlevel=99, const char *name="")
Create one branch for each element in the collection.
Definition: TTree.cxx:1624
virtual void MoveResize(Int_t x, Int_t y, UInt_t w, UInt_t h)
Move and resize the window.
Definition: TGWindow.cxx:172
virtual void Draw(Option_t *option="")
Draw a canvas.
Definition: TCanvas.cxx:795
UInt_t fWidth
Definition: GuiTypes.h:183
Bool_t StartRecording()
Connects appropriate signals and slots in order to gain all registered windows and processed events i...
Definition: TRecorder.cxx:1268
typedef void((*Func_t)())
virtual ~TGCursorWindow()
Destructor.
Definition: TRecorder.cxx:217
Handle_t Window_t
Definition: GuiTypes.h:30
virtual void PrevCanvases(const char *, Option_t *)
Definition: TRecorder.h:550
Int_t fFormat
Definition: GuiTypes.h:187
void Stop(Bool_t guiCommand=kFALSE)
Stopps recording events.
Definition: TRecorder.cxx:275
RooCmdArg Layout(Double_t xmin, Double_t xmax=0.99, Double_t ymin=0.95)
virtual void ReplayStop(TRecorder *r)
Cancels replaying.
Definition: TRecorder.cxx:957
virtual void Resume(TRecorder *)
Definition: TRecorder.h:544
virtual void Add(TObject *obj)
Definition: TList.h:81
Bool_t IsFiltered(Window_t id)
Returns kTRUE if passed id belongs to window IDs of recorder GUI itself.
Definition: TRecorder.cxx:1706
virtual void Resume(TRecorder *r)
Continues replaying.
Definition: TRecorder.cxx:1173
Double_t GetY1() const
Definition: TBox.h:74
static TGCursorWindow * gCursorWin
Definition: TRecorder.cxx:189
EGEventType fType
Definition: TRecorder.h:303
virtual Bool_t HandleTimerEvent(Event_t *, TTimer *)
static Event_t * CreateEvent(TRecGuiEvent *ge)
Converts TRecGuiEvent type to Event_t type.
Definition: TRecorder.cxx:2195
Handle_t Pixmap_t
Definition: GuiTypes.h:31
virtual ~TRecorderReplaying()
Closes all signal-slot connections Frees all memory allocated in contructor.
Definition: TRecorder.cxx:401
#define gPad
Definition: TVirtualPad.h:288
Double_t GetX1() const
Definition: TBox.h:72
UInt_t fState
Definition: GuiTypes.h:182
void Pause()
Pauses replaying.
Definition: TRecorder.cxx:292
R__EXTERN Int_t gDebug
Definition: Rtypes.h:128
virtual ~TRecorder()
Destructor.
Definition: TRecorder.cxx:249
virtual Long64_t GetEntries() const
Definition: TTree.h:382
virtual void Stop()
Definition: TTimer.h:99
A TTree object has a header with a name and a title.
Definition: TTree.h:94
TRecEvent * fNextEvent
Definition: TRecorder.h:610
virtual void ListGui(const char *)
Definition: TRecorder.h:548
virtual TRecorder::ERecorderState GetState() const =0
Bool_t fEventReplayed
Definition: TRecorder.h:621
virtual void Pause(TRecorder *r)
Pauses replaying.
Definition: TRecorder.cxx:947
const Mask_t kKeyControlMask
Definition: GuiTypes.h:198
Double_t GetY2() const
Definition: TBox.h:75
virtual void ReplayEvent(Bool_t showMouseCursor=kTRUE)
virtual ~TRecorderRecording()
Freeing of allocated memory.
Definition: TRecorder.cxx:1251
Int_t fFilteredIdsCount
Definition: TRecorder.h:693
virtual TRecorder::ERecorderState GetState() const
Get current state of recorder.
Definition: TRecorder.cxx:344
virtual void Cleanup()
Cleanup and delete all objects contained in this composite frame.
Definition: TGFrame.cxx:949
const Bool_t kTRUE
Definition: Rtypes.h:91
TObject * obj
virtual void TurnOn()
Add the timer to the system timer list.
Definition: TTimer.cxx:239
Handle_t GetId() const
Definition: TGObject.h:52
const Int_t n
Definition: legend1.C:16
TGPictureButton * fStartStop
Definition: TRecorder.h:806
void PrevCanvases(const char *filename, Option_t *option)
Save previous canvases in a .root file.
Definition: TRecorder.cxx:353
Int_t fX
Definition: GuiTypes.h:179
TRecorder * fRecorder
Definition: TRecorder.h:804
virtual Int_t Write(const char *name=0, Int_t option=0, Int_t bufsize=0)
Write all objects in this collection.
TTree * fExtraTree
Definition: TRecorder.h:679
void Browse(TBrowser *)
Browse the recorder from a ROOT file.
Definition: TRecorder.cxx:258
Window_t fWindow
Definition: TRecorder.h:304
Double_t GetX() const
Definition: TText.h:68
const char * cnt
Definition: TXMLSetup.cxx:75
friend class TRecorderInactive
Definition: TRecorder.h:448
const char * kWindowsTree
Definition: TRecorder.cxx:165
R__EXTERN Atom_t gROOT_MESSAGE
Definition: TVirtualX.h:53
Bool_t RemapWindowReferences()
All references to the old windows (IDs) in fNextEvent are replaced by new ones according to the mappi...
Definition: TRecorder.cxx:606
virtual void Close(Option_t *option="")
Close a file.
Definition: TFile.cxx:898
ULong64_t fWin
Definition: TRecorder.h:594
Bool_t CanOverlap()
ButtonPress and ButtonRelease must be sometimes replayed more times Example: pressing of a button ope...
Definition: TRecorder.cxx:826