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