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