Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TGClient.cxx
Go to the documentation of this file.
1 // @(#)root/gui:$Id$
2 // Author: Fons Rademakers 27/12/97
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, 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  This source is based on Xclass95, a Win95-looking GUI toolkit.
14  Copyright (C) 1996, 1997 David Barth, Ricky Ralston, Hector Peraza.
15 
16  Xclass95 is free software; you can redistribute it and/or
17  modify it under the terms of the GNU Library General Public
18  License as published by the Free Software Foundation; either
19  version 2 of the License, or (at your option) any later version.
20 
21 **************************************************************************/
22 
23 //////////////////////////////////////////////////////////////////////////
24 // //
25 // TGClient //
26 // //
27 // Window client. In client server windowing systems, like X11 this //
28 // class is used to make the initial connection to the window server. //
29 // //
30 //////////////////////////////////////////////////////////////////////////
31 
32 #include "RConfigure.h"
33 
34 #include "TGClient.h"
35 #include "TROOT.h"
36 #include "TApplication.h"
37 #include "TSystem.h"
38 #include "TEnv.h"
39 #include "THashList.h"
40 #include "TSysEvtHandler.h"
41 #include "TVirtualX.h"
42 #include "TGWindow.h"
43 #include "TGResourcePool.h"
44 #include "TGGC.h"
45 #include "TGFont.h"
46 #include "TGMimeTypes.h"
47 #include "TGFrame.h"
48 #include "TGIdleHandler.h"
49 #include "TError.h"
50 #include "TGlobal.h"
51 
52 // Global pointer to the TGClient object
53 static TGClient *gClientGlobal = nullptr;
54 
55 namespace {
56 static struct AddPseudoGlobals {
57 AddPseudoGlobals() {
58  // User "gCling" as synonym for "libCore static initialization has happened".
59  // This code here must not trigger it
60  TGlobalMappedFunction::MakeFunctor("gClient", "TGClient*", TGClient::Instance, [] {
61  TGClient::Instance(); // first ensure object is created;
62  return (void *) &gClientGlobal;
63  });
64 }
65 } gAddPseudoGlobals;
66 }
67 
68 // Initialize gClient in case libGui is loaded in batch mode
69 void TriggerDictionaryInitialization_libGui();
70 class TGClientInit {
71 public:
72  TGClientInit() {
73  TROOT *rootlocal = ROOT::Internal::gROOTLocal;
74  if (rootlocal && rootlocal->IsBatch()) {
75  // For now check if the heaeder files (or the module containing them)
76  // has been loaded in Cling.
77  // This is required because the dictionaries must be initialized
78  // __before__ the TGClient creation which will induce the creation
79  // of a TClass object which will need the dictionary for TGClient!
80  TriggerDictionaryInitialization_libGui();
81  new TGClient();
82  }
83  TApplication::NeedGraphicsLibs();
84  }
85 };
86 static TGClientInit gClientInit;
87 
88 ////////////////////////////////////////////////////////////////////////////////
89 /// Returns global gClient (initialize graphics first, if not already done)
90 
91 TGClient *TGClient::Instance()
92 {
93  if (!gClientGlobal && gApplication)
94  gApplication->InitializeGraphics();
95  return gClientGlobal;
96 }
97 
98 //----- Graphics Input handler -------------------------------------------------
99 ////////////////////////////////////////////////////////////////////////////////
100 
101 class TGInputHandler : public TFileHandler {
102 private:
103  TGClient *fClient; // connection to display server
104 public:
105  TGInputHandler(TGClient *c, Int_t fd) : TFileHandler(fd, 1) { fClient = c; }
106  Bool_t Notify();
107  // Important: don't override ReadNotify()
108 };
109 
110 ////////////////////////////////////////////////////////////////////////////////
111 /// Notify input from the display server.
112 
113 Bool_t TGInputHandler::Notify()
114 {
115  return fClient->HandleInput();
116 }
117 
118 
119 ClassImp(TGClient);
120 
121 ////////////////////////////////////////////////////////////////////////////////
122 /// Create a connection with the display sever on host dpyName and setup
123 /// the complete GUI system, i.e., graphics contexts, fonts, etc. for all
124 /// widgets.
125 
126 TGClient::TGClient(const char *dpyName)
127 {
128  fRoot = 0;
129  fPicturePool = 0;
130  fMimeTypeList = 0;
131  fWlist = 0;
132  fPlist = 0;
133  fUWHandlers = 0;
134  fIdleHandlers = 0;
135 
136  if (gClientGlobal) {
137  Error("TGClient", "only one instance of TGClient allowed");
138  MakeZombie();
139  return;
140  }
141 
142  // Set DISPLAY based on utmp (only if DISPLAY is not yet set).
143  gSystem->SetDisplay();
144 
145  // Open the connection to the display
146  if ((fXfd = gVirtualX->OpenDisplay(dpyName)) < 0) {
147  Error("TGClient", "can't open display \"%s\", switching to batch mode...\n In case you run from a remote ssh session, reconnect with ssh -Y",
148  gVirtualX->DisplayName(dpyName));
149  MakeZombie();
150  return;
151  }
152 
153  if (fXfd >= 0 && !ROOT::Internal::gROOTLocal->IsBatch()) {
154  TGInputHandler *xi = new TGInputHandler(this, fXfd);
155  if (fXfd) gSystem->AddFileHandler(xi);
156  // X11 events are handled via gXDisplay->Notify() in
157  // TUnixSystem::DispatchOneEvent(). When no events available we wait for
158  // events on all TFileHandlers including this one via a select() call.
159  // However, X11 events are always handled via gXDisplay->Notify() and not
160  // via the ReadNotify() (therefore TGInputHandler should not override
161  // TFileHandler::ReadNotify()).
162  gXDisplay = xi;
163  }
164 
165  // Initialize internal window list. Use a THashList for fast
166  // finding of windows based on window id (see GetWindowById()).
167 
168  fWlist = new THashList(200);
169  fPlist = new TList;
170 
171  // Create root window
172 
173  fDefaultRoot = fRoot = new TGFrame(this, gVirtualX->GetDefaultRootWindow());
174 
175  // Setup some atoms (defined in TVirtualX)...
176 
177  gWM_DELETE_WINDOW = gVirtualX->InternAtom("WM_DELETE_WINDOW", kFALSE);
178  gMOTIF_WM_HINTS = gVirtualX->InternAtom("_MOTIF_WM_HINTS", kFALSE);
179  gROOT_MESSAGE = gVirtualX->InternAtom("_ROOT_MESSAGE", kFALSE);
180 
181  // Create the graphics event handler, an object for the root window,
182  // a picture pool, mimetype list, etc...
183 
184  fGlobalNeedRedraw = kFALSE;
185  fForceRedraw = kFALSE;
186  fWaitForWindow = kNone;
187  fWaitForEvent = kOtherEvent;
188 
189  fResourcePool = new TGResourcePool(this);
190 
191  fPicturePool = fResourcePool->GetPicturePool();
192  fGCPool = fResourcePool->GetGCPool();
193  fFontPool = fResourcePool->GetFontPool();
194 
195  fMimeTypeList = fResourcePool->GetMimeTypes();
196  fDefaultColormap = fResourcePool->GetDefaultColormap();
197 
198  // Set some color defaults...
199 
200  fWhite = fResourcePool->GetWhiteColor();
201  fBlack = fResourcePool->GetBlackColor();
202  fBackColor = fResourcePool->GetFrameBgndColor();
203  fForeColor = fResourcePool->GetFrameFgndColor();
204  fHilite = GetHilite(fBackColor);
205  fShadow = GetShadow(fBackColor);
206  fSelForeColor = fResourcePool->GetSelectedFgndColor();
207  fSelBackColor = fResourcePool->GetSelectedBgndColor();
208 
209  fStyle = 0;
210  TString style = gEnv->GetValue("Gui.Style", "modern");
211  if (style.Contains("flat", TString::kIgnoreCase))
212  fStyle = 2;
213  else if (style.Contains("modern", TString::kIgnoreCase))
214  fStyle = 1;
215 
216  gClientGlobal = this;
217 }
218 
219 ////////////////////////////////////////////////////////////////////////////////
220 /// Returns current root (i.e. base) window. By changing the root
221 /// window one can change the window hierarchy, e.g. a top level
222 /// frame (TGMainFrame) can be embedded in another window.
223 
224 const TGWindow *TGClient::GetRoot() const
225 {
226  return fRoot;
227 }
228 
229 ////////////////////////////////////////////////////////////////////////////////
230 /// Returns the root (i.e. desktop) window. Should only be used as parent
231 /// for frames that will never be embedded, like popups, message boxes,
232 /// etc. (like TGToolTips, TGMessageBox, etc.).
233 
234 const TGWindow *TGClient::GetDefaultRoot() const
235 {
236  return fDefaultRoot;
237 }
238 
239 ////////////////////////////////////////////////////////////////////////////////
240 /// Sets the current root (i.e. base) window. By changing the root
241 /// window one can change the window hierarchy, e.g. a top level
242 /// frame (TGMainFrame) can be embedded in another window.
243 
244 void TGClient::SetRoot(TGWindow *root)
245 {
246  fRoot = root ? root : fDefaultRoot;
247 }
248 
249 ////////////////////////////////////////////////////////////////////////////////
250 /// Set the button style (modern or classic).
251 
252 void TGClient::SetStyle(const char *style)
253 {
254  fStyle = 0;
255  if (style && strstr(style, "modern"))
256  fStyle = 1;
257 }
258 
259 ////////////////////////////////////////////////////////////////////////////////
260 /// Get display width.
261 
262 UInt_t TGClient::GetDisplayWidth() const
263 {
264  Int_t x, y;
265  UInt_t w, h;
266 
267  gVirtualX->GetGeometry(-1, x, y, w, h);
268 
269  return w;
270 }
271 
272 ////////////////////////////////////////////////////////////////////////////////
273 /// Get display height.
274 
275 UInt_t TGClient::GetDisplayHeight() const
276 {
277  Int_t x, y;
278  UInt_t w, h;
279 
280  gVirtualX->GetGeometry(-1, x, y, w, h);
281 
282  return h;
283 }
284 
285 ////////////////////////////////////////////////////////////////////////////////
286 /// Get picture from the picture pool. Picture must be freed using
287 /// TGClient::FreePicture(). If picture is not found 0 is returned.
288 
289 const TGPicture *TGClient::GetPicture(const char *name)
290 {
291  return fPicturePool->GetPicture(name);
292 }
293 
294 ////////////////////////////////////////////////////////////////////////////////
295 /// Get picture with specified size from pool (picture will be scaled if
296 /// necessary). Picture must be freed using TGClient::FreePicture(). If
297 /// picture is not found 0 is returned.
298 
299 const TGPicture *TGClient::GetPicture(const char *name,
300  UInt_t new_width, UInt_t new_height)
301 {
302  return fPicturePool->GetPicture(name, new_width, new_height);
303 }
304 
305 ////////////////////////////////////////////////////////////////////////////////
306 /// Free picture resource.
307 
308 void TGClient::FreePicture(const TGPicture *pic)
309 {
310  if (pic) fPicturePool->FreePicture(pic);
311 }
312 
313 ////////////////////////////////////////////////////////////////////////////////
314 /// Get graphics context from the gc pool. Context must be freed via
315 /// TGClient::FreeGC(). If rw is true a new read/write-able GC
316 /// is returned, otherwise a shared read-only context is returned.
317 /// For historical reasons it is also possible to create directly a
318 /// TGGC object, but it is advised to use this new interface only.
319 
320 TGGC *TGClient::GetGC(GCValues_t *values, Bool_t rw)
321 {
322  return fGCPool->GetGC(values, rw);
323 }
324 
325 ////////////////////////////////////////////////////////////////////////////////
326 /// Free a graphics context.
327 
328 void TGClient::FreeGC(const TGGC *gc)
329 {
330  fGCPool->FreeGC(gc);
331 }
332 
333 ////////////////////////////////////////////////////////////////////////////////
334 /// Free a graphics context.
335 
336 void TGClient::FreeGC(GContext_t gc)
337 {
338  fGCPool->FreeGC(gc);
339 }
340 
341 ////////////////////////////////////////////////////////////////////////////////
342 /// Get a font from the font pool. Fonts must be freed via
343 /// TGClient::FreeFont(). Returns 0 in case of error or if font
344 /// does not exist. If fixedDefault is false the "fixed" font
345 /// will not be substituted as fallback when the asked for font
346 /// does not exist.
347 
348 TGFont *TGClient::GetFont(const char *font, Bool_t fixedDefault)
349 {
350  return fFontPool->GetFont(font, fixedDefault);
351 }
352 
353 ////////////////////////////////////////////////////////////////////////////////
354 /// Get again specified font. Will increase its usage count.
355 
356 TGFont *TGClient::GetFont(const TGFont *font)
357 {
358  return fFontPool->GetFont(font);
359 }
360 
361 ////////////////////////////////////////////////////////////////////////////////
362 /// Free a font.
363 
364 void TGClient::FreeFont(const TGFont *font)
365 {
366  fFontPool->FreeFont(font);
367 }
368 
369 ////////////////////////////////////////////////////////////////////////////////
370 /// Set redraw flags.
371 
372 void TGClient::NeedRedraw(TGWindow *w, Bool_t force)
373 {
374  if (gVirtualX->NeedRedraw((ULong_t)w,force)) return;
375  if (force) {
376  w->DoRedraw();
377  return;
378  }
379  w->fNeedRedraw = kTRUE;
380  fGlobalNeedRedraw = kTRUE;
381 }
382 
383 ////////////////////////////////////////////////////////////////////////////////
384 
385 void TGClient::CancelRedraw(TGWindow *w)
386 {
387  w->fNeedRedraw = kFALSE;
388 }
389 
390 ////////////////////////////////////////////////////////////////////////////////
391 /// Get a color by name. If color is found return kTRUE and pixel is
392 /// set to the color's pixel value, kFALSE otherwise.
393 
394 Bool_t TGClient::GetColorByName(const char *name, Pixel_t &pixel) const
395 {
396  ColorStruct_t color;
397  WindowAttributes_t attributes = WindowAttributes_t();
398  Bool_t status = kTRUE;
399 
400  gVirtualX->GetWindowAttributes(fRoot->GetId(), attributes);
401  color.fPixel = 0;
402  if (!gVirtualX->ParseColor(attributes.fColormap, name, color)) {
403  Error("GetColorByName", "couldn't parse color %s", name);
404  status = kFALSE;
405  } else if (!gVirtualX->AllocColor(attributes.fColormap, color)) {
406  Warning("GetColorByName", "couldn't retrieve color %s.\n"
407  "Please close any other application, like netscape, "
408  "that might exhaust\nthe colormap and start ROOT again", name);
409  status = kFALSE;
410  }
411 
412  pixel = color.fPixel;
413 
414  return status;
415 }
416 
417 ////////////////////////////////////////////////////////////////////////////////
418 /// Get a font by name. If font is not found, fixed font is returned,
419 /// if fixed font also does not exist return 0 and print error.
420 /// The loaded font needs to be freed using TVirtualX::DeleteFont().
421 /// If fixedDefault is false the "fixed" font will not be substituted
422 /// as fallback when the asked for font does not exist.
423 
424 FontStruct_t TGClient::GetFontByName(const char *name, Bool_t fixedDefault) const
425 {
426  if (gROOT->IsBatch())
427  return (FontStruct_t) -1;
428 
429  FontStruct_t font = gVirtualX->LoadQueryFont(name);
430 
431  if (!font && fixedDefault) {
432  font = gVirtualX->LoadQueryFont("fixed");
433  if (font)
434  Warning("GetFontByName", "couldn't retrieve font %s, using \"fixed\"", name);
435  }
436  if (!font) {
437  if (fixedDefault)
438  Error("GetFontByName", "couldn't retrieve font %s nor backup font \"fixed\"", name);
439  else
440  Warning("GetFontByName", "couldn't retrieve font %s", name);
441  }
442 
443  return font;
444 }
445 
446 ////////////////////////////////////////////////////////////////////////////////
447 /// Return pixel value of hilite color based on base_color.
448 
449 Pixel_t TGClient::GetHilite(Pixel_t base_color) const
450 {
451  ColorStruct_t color, white_p;
452  WindowAttributes_t attributes = WindowAttributes_t();
453 
454  gVirtualX->GetWindowAttributes(fRoot->GetId(), attributes);
455 
456  color.fPixel = base_color;
457  gVirtualX->QueryColor(attributes.fColormap, color);
458 
459  GetColorByName("white", white_p.fPixel);
460  gVirtualX->QueryColor(attributes.fColormap, white_p);
461 
462  color.fRed = TMath::Max((UShort_t)(white_p.fRed/5), color.fRed);
463  color.fGreen = TMath::Max((UShort_t)(white_p.fGreen/5), color.fGreen);
464  color.fBlue = TMath::Max((UShort_t)(white_p.fBlue/5), color.fBlue);
465 
466  color.fRed = (UShort_t)TMath::Min((Int_t)white_p.fRed, (Int_t)(color.fRed*140)/100);
467  color.fGreen = (UShort_t)TMath::Min((Int_t)white_p.fGreen, (Int_t)(color.fGreen*140)/100);
468  color.fBlue = (UShort_t)TMath::Min((Int_t)white_p.fBlue, (Int_t)(color.fBlue*140)/100);
469 
470  if (!gVirtualX->AllocColor(attributes.fColormap, color))
471  Error("GetHilite", "couldn't allocate hilight color");
472 
473  return color.fPixel;
474 }
475 
476 ////////////////////////////////////////////////////////////////////////////////
477 /// Return pixel value of shadow color based on base_color.
478 /// Shadow is 60% of base_color intensity.
479 
480 Pixel_t TGClient::GetShadow(Pixel_t base_color) const
481 {
482  ColorStruct_t color;
483  WindowAttributes_t attributes = WindowAttributes_t();
484 
485  gVirtualX->GetWindowAttributes(fRoot->GetId(), attributes);
486 
487  color.fPixel = base_color;
488  gVirtualX->QueryColor(attributes.fColormap, color);
489 
490  color.fRed = (UShort_t)((color.fRed*60)/100);
491  color.fGreen = (UShort_t)((color.fGreen*60)/100);
492  color.fBlue = (UShort_t)((color.fBlue*60)/100);
493 
494  if (!gVirtualX->AllocColor(attributes.fColormap, color))
495  Error("GetShadow", "couldn't allocate shadow color");
496 
497  return color.fPixel;
498 }
499 
500 ////////////////////////////////////////////////////////////////////////////////
501 /// Free color.
502 
503 void TGClient::FreeColor(Pixel_t color) const
504 {
505  gVirtualX->FreeColor(fDefaultColormap, color);
506 }
507 
508 ////////////////////////////////////////////////////////////////////////////////
509 /// Add a TGWindow to the clients list of windows.
510 
511 void TGClient::RegisterWindow(TGWindow *w)
512 {
513  fWlist->Add(w);
514 
515  // Emits signal
516  RegisteredWindow(w->GetId());
517 }
518 
519 ////////////////////////////////////////////////////////////////////////////////
520 /// Remove a TGWindow from the list of windows.
521 
522 void TGClient::UnregisterWindow(TGWindow *w)
523 {
524  fWlist->Remove(w);
525 }
526 
527 ////////////////////////////////////////////////////////////////////////////////
528 /// Add a popup menu to the list of popups. This list is used to pass
529 /// events to popup menus that are popped up over a transient window which
530 /// is waited for (see WaitFor()).
531 
532 void TGClient::RegisterPopup(TGWindow *w)
533 {
534  fPlist->Add(w);
535 
536  // Emits signal
537  RegisteredWindow(w->GetId());
538 }
539 
540 ////////////////////////////////////////////////////////////////////////////////
541 /// Remove a popup menu from the list of popups.
542 
543 void TGClient::UnregisterPopup(TGWindow *w)
544 {
545  fPlist->Remove(w);
546 }
547 
548 ////////////////////////////////////////////////////////////////////////////////
549 /// Add handler for unknown (i.e. unregistered) windows.
550 
551 void TGClient::AddUnknownWindowHandler(TGUnknownWindowHandler *h)
552 {
553  if (!fUWHandlers) {
554  fUWHandlers = new TList;
555  fUWHandlers->SetOwner();
556  }
557 
558  fUWHandlers->Add(h);
559 }
560 
561 ////////////////////////////////////////////////////////////////////////////////
562 /// Remove handler for unknown (i.e. unregistered) windows.
563 
564 void TGClient::RemoveUnknownWindowHandler(TGUnknownWindowHandler *h)
565 {
566  fUWHandlers->Remove(h);
567 }
568 
569 ////////////////////////////////////////////////////////////////////////////////
570 /// Add handler for idle events.
571 
572 void TGClient::AddIdleHandler(TGIdleHandler *h)
573 {
574  if (!fIdleHandlers) {
575  fIdleHandlers = new TList;
576  fIdleHandlers->SetOwner();
577  }
578 
579  fIdleHandlers->Add(h);
580 }
581 
582 ////////////////////////////////////////////////////////////////////////////////
583 /// Remove handler for idle events.
584 
585 void TGClient::RemoveIdleHandler(TGIdleHandler *h)
586 {
587  fIdleHandlers->Remove(h);
588 }
589 
590 ////////////////////////////////////////////////////////////////////////////////
591 /// Find a TGWindow via its handle. If window is not found return 0.
592 
593 TGWindow *TGClient::GetWindowById(Window_t wid) const
594 {
595  TGWindow wt(wid);
596 
597  return (TGWindow *) fWlist->FindObject(&wt);
598 }
599 
600 ////////////////////////////////////////////////////////////////////////////////
601 /// Find a TGWindow via its name (unique name used in TGWindow::SavePrimitive).
602 /// If window is not found return 0.
603 
604 TGWindow *TGClient::GetWindowByName(const char *name) const
605 {
606  TIter next(fWlist);
607 
608  TObject *obj;
609  while ((obj = next())) {
610  TString n = obj->GetName();
611  if (n == name) {
612  return (TGWindow*)obj;
613  }
614  }
615  return 0;
616 }
617 
618 ////////////////////////////////////////////////////////////////////////////////
619 /// Closing down client: cleanup and close X connection.
620 
621 TGClient::~TGClient()
622 {
623  if (IsZombie())
624  return;
625 
626  if (fWlist)
627  fWlist->Delete("slow");
628  delete fWlist;
629  delete fPlist;
630  delete fUWHandlers;
631  delete fIdleHandlers;
632  delete fResourcePool;
633 
634  gVirtualX->CloseDisplay(); // this should do a cleanup of the remaining
635  // X allocated objects...
636 }
637 
638 ////////////////////////////////////////////////////////////////////////////////
639 /// Process one event. This method should only be called when there is
640 /// a GUI event ready to be processed. If event has been processed
641 /// kTRUE is returned. If processing of a specific event type for a specific
642 /// window was requested kFALSE is returned when specific event has been
643 /// processed, kTRUE otherwise. If no more pending events return kFALSE.
644 
645 Bool_t TGClient::ProcessOneEvent()
646 {
647  Event_t event;
648 
649  if (!fRoot) return kFALSE;
650  if (gVirtualX->EventsPending()) {
651  gVirtualX->NextEvent(event);
652  if (fWaitForWindow == kNone) {
653  HandleEvent(&event);
654  if (fForceRedraw)
655  DoRedraw();
656  return kTRUE;
657  } else {
658  HandleMaskEvent(&event, fWaitForWindow);
659  if ((event.fType == fWaitForEvent) && (event.fWindow == fWaitForWindow))
660  fWaitForWindow = kNone;
661  if (fForceRedraw)
662  DoRedraw();
663  return kTRUE;
664  }
665  }
666 
667  // if nothing else to do redraw windows that need redrawing
668  if (DoRedraw()) return kTRUE;
669 
670  // process one idle event if there is nothing else to do
671  if (ProcessIdleEvent()) return kTRUE;
672 
673  return kFALSE;
674 }
675 
676 ////////////////////////////////////////////////////////////////////////////////
677 /// Process one idle event.
678 
679 Bool_t TGClient::ProcessIdleEvent()
680 {
681  if (fIdleHandlers) {
682  TGIdleHandler *ih = (TGIdleHandler *) fIdleHandlers->First();
683  if (ih) {
684  RemoveIdleHandler(ih);
685  ih->HandleEvent();
686  return kTRUE;
687  }
688  }
689  return kFALSE;
690 }
691 
692 ////////////////////////////////////////////////////////////////////////////////
693 /// Handles input from the display server. Returns kTRUE if one or more
694 /// events have been processed, kFALSE otherwise.
695 
696 Bool_t TGClient::HandleInput()
697 {
698  Bool_t handledevent = kFALSE;
699 
700  while (ProcessOneEvent())
701  handledevent = kTRUE;
702  return handledevent;
703 }
704 
705 ////////////////////////////////////////////////////////////////////////////////
706 /// Wait for window to be destroyed.
707 
708 void TGClient::WaitFor(TGWindow *w)
709 {
710  Window_t wsave = fWaitForWindow;
711  EGEventType esave = fWaitForEvent;
712 
713  fWaitForWindow = w->GetId();
714  fWaitForEvent = kDestroyNotify;
715 
716  //Let VirtualX know, that we are
717  //in a nested loop for a window w.
718  //Noop on X11/win32gdk.
719  if (gVirtualX)
720  gVirtualX->BeginModalSessionFor(w->GetId());
721 
722  while (fWaitForWindow != kNone) {
723  if (esave == kUnmapNotify)
724  wsave = kNone;
725  gSystem->ProcessEvents();//gSystem->InnerLoop();
726  gSystem->Sleep(5);
727  }
728 
729  fWaitForWindow = wsave;
730  fWaitForEvent = esave;
731 }
732 
733 ////////////////////////////////////////////////////////////////////////////////
734 /// Wait for window to be unmapped.
735 
736 void TGClient::WaitForUnmap(TGWindow *w)
737 {
738  Window_t wsave = fWaitForWindow;
739  EGEventType esave = fWaitForEvent;
740 
741  fWaitForWindow = w->GetId();
742  fWaitForEvent = kUnmapNotify;
743 
744  //Let VirtualX know, that we are
745  //in a nested loop for a window w.
746  //Noop on X11/win32gdk.
747  if (gVirtualX)
748  gVirtualX->BeginModalSessionFor(w->GetId());
749 
750  while (fWaitForWindow != kNone) {
751  gSystem->ProcessEvents();//gSystem->InnerLoop();
752  gSystem->Sleep(5);
753  }
754 
755  fWaitForWindow = wsave;
756  fWaitForEvent = esave;
757 }
758 
759 ////////////////////////////////////////////////////////////////////////////////
760 /// reset waiting
761 
762 void TGClient::ResetWaitFor(TGWindow *w)
763 {
764  if (fWaitForWindow == w->GetId()) fWaitForWindow = kNone;
765 }
766 
767 ////////////////////////////////////////////////////////////////////////////////
768 /// Like gSystem->ProcessEvents() but then only allow events for w to
769 /// be processed. For example to interrupt the processing and destroy
770 /// the window, call gROOT->SetInterrupt() before destroying the window.
771 
772 Bool_t TGClient::ProcessEventsFor(TGWindow *w)
773 {
774  Window_t wsave = fWaitForWindow;
775  EGEventType esave = fWaitForEvent;
776 
777  fWaitForWindow = w->GetId();
778  fWaitForEvent = kDestroyNotify;
779 
780  Bool_t intr = gSystem->ProcessEvents();
781 
782  fWaitForWindow = wsave;
783  fWaitForEvent = esave;
784 
785  return intr;
786 }
787 
788 ////////////////////////////////////////////////////////////////////////////////
789 /// Redraw all windows that need redrawing. Returns kFALSE if no redraw
790 /// was needed, kTRUE otherwise.
791 /// Only redraw the application's windows when the event queue
792 /// does not contain expose event anymore.
793 
794 Bool_t TGClient::DoRedraw()
795 {
796  if (!fGlobalNeedRedraw) return kFALSE;
797 
798  TGWindow *w;
799  TObjLink *lnk = fWlist->FirstLink();
800  while (lnk) {
801  w = (TGWindow *) lnk->GetObject();
802  if (w->fNeedRedraw) {
803  w->DoRedraw();
804  w->fNeedRedraw = kFALSE;
805  }
806  lnk = lnk->Next();
807  }
808 
809  fGlobalNeedRedraw = kFALSE;
810  fForceRedraw = kFALSE;
811 
812  return kTRUE;
813 }
814 
815 ////////////////////////////////////////////////////////////////////////////////
816 /// Handle a GUI event.
817 
818 Bool_t TGClient::HandleEvent(Event_t *event)
819 {
820  TGWindow *w;
821 
822  // Emit signal for event recorder(s)
823  if (event->fType != kConfigureNotify) {
824  ProcessedEvent(event, 0);
825  }
826 
827  // Find window where event happened
828  if ((w = GetWindowById(event->fWindow)) == 0) {
829  if (fUWHandlers && fUWHandlers->GetSize() > 0) {
830  TGUnknownWindowHandler *unkwh;
831  TListIter it(fUWHandlers);
832  while ((unkwh = (TGUnknownWindowHandler*)it.Next())) {
833  if (unkwh->HandleEvent(event))
834  return kTRUE;
835  }
836  }
837  //Warning("HandleEvent", "unknown window %ld not handled\n",
838  // event->fWindow);
839  return kFALSE;
840  }
841 
842  // and let it handle the event
843  w->HandleEvent(event);
844 
845  return kTRUE;
846 }
847 
848 ////////////////////////////////////////////////////////////////////////////////
849 /// Handle masked events only if window wid is the window for which the
850 /// event was reported or if wid is a parent of the event window. The not
851 /// masked event are handled directly. The masked events are:
852 /// kButtonPress, kButtonRelease, kKeyPress, kKeyRelease, kEnterNotify,
853 /// kLeaveNotify, kMotionNotify.
854 
855 Bool_t TGClient::HandleMaskEvent(Event_t *event, Window_t wid)
856 {
857  TGWindow *w, *ptr, *pop;
858 
859  if ((w = GetWindowById(event->fWindow)) == 0) return kFALSE;
860 
861  // Emit signal for event recorder(s)
862  if (event->fType != kConfigureNotify) {
863  ProcessedEvent(event, wid);
864  }
865 
866  // This breaks class member protection, but TGClient is a friend of
867  // TGWindow and _should_ know what to do and what *not* to do...
868 
869  for (ptr = w; ptr->fParent != 0; ptr = (TGWindow *) ptr->fParent) {
870  if ((ptr->fId == wid) ||
871  ((event->fType != kButtonPress) &&
872  (event->fType != kButtonRelease) &&
873  (event->fType != kGKeyPress) &&
874  (event->fType != kKeyRelease) &&
875  (event->fType != kEnterNotify) &&
876  (event->fType != kLeaveNotify) &&
877  (event->fType != kMotionNotify))) {
878  w->HandleEvent(event);
879  return kTRUE;
880  }
881  }
882 
883  // check if this is a popup menu
884  TIter next(fPlist);
885  while ((pop = (TGWindow *) next())) {
886  for (ptr = w; ptr->fParent != 0; ptr = (TGWindow *) ptr->fParent) {
887  if ((ptr->fId == pop->fId) &&
888  ((event->fType == kButtonPress) ||
889  (event->fType == kButtonRelease) ||
890  (event->fType == kGKeyPress) ||
891  (event->fType == kKeyRelease) ||
892  (event->fType == kEnterNotify) ||
893  (event->fType == kLeaveNotify) ||
894  (event->fType == kMotionNotify))) {
895  w->HandleEvent(event);
896  return kTRUE;
897  }
898  }
899  }
900 
901  if (event->fType == kButtonPress || event->fType == kGKeyPress)
902  gVirtualX->Bell(0);
903 
904  return kFALSE;
905 }
906 
907 ////////////////////////////////////////////////////////////////////////////////
908 /// Execute string "cmd" via the interpreter. Before executing replace
909 /// in the command string the token $MSG, $PARM1 and $PARM2 by msg,
910 /// parm1 and parm2, respectively. The function in cmd string must accept
911 /// these as longs.
912 
913 void TGClient::ProcessLine(TString cmd, Long_t msg, Long_t parm1, Long_t parm2)
914 {
915  if (cmd.IsNull()) return;
916 
917  char s[32];
918 
919  snprintf(s, sizeof(s), "%ld", msg);
920  cmd.ReplaceAll("$MSG", s);
921 
922  snprintf(s, sizeof(s), "%ld", parm1);
923  cmd.ReplaceAll("$PARM1", s);
924 
925  snprintf(s, sizeof(s), "%ld", parm2);
926  cmd.ReplaceAll("$PARM2", s);
927 
928  gROOT->ProcessLine(cmd.Data());
929 }
930 
931 ////////////////////////////////////////////////////////////////////////////////
932 /// Returns kTRUE if edit/guibuilding is forbidden.
933 
934 Bool_t TGClient::IsEditDisabled() const
935 {
936  return (fDefaultRoot->GetEditDisabled() == 1);
937 }
938 
939 ////////////////////////////////////////////////////////////////////////////////
940 /// If on is kTRUE editting/guibuilding is forbidden.
941 
942 void TGClient::SetEditDisabled(Bool_t on)
943 {
944  fDefaultRoot->SetEditDisabled(on);
945 }
946 
947 ////////////////////////////////////////////////////////////////////////////////
948 /// Emits a signal when an event has been processed.
949 /// Used in TRecorder.
950 
951 void TGClient::ProcessedEvent(Event_t *event, Window_t wid)
952 {
953  Long_t args[2];
954  args[0] = (Long_t) event;
955  args[1] = (Long_t) wid;
956 
957  Emit("ProcessedEvent(Event_t*, Window_t)", args);
958 }
959 
960 ////////////////////////////////////////////////////////////////////////////////
961 /// Emits a signal when a Window has been registered in TGClient.
962 /// Used in TRecorder.
963 
964 void TGClient::RegisteredWindow(Window_t w)
965 {
966  Emit("RegisteredWindow(Window_t)", w);
967 }