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