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