00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "RConfigure.h"
00033
00034 #include "TGClient.h"
00035 #include "TROOT.h"
00036 #include "TApplication.h"
00037 #include "TSystem.h"
00038 #include "TEnv.h"
00039 #include "THashList.h"
00040 #include "TSysEvtHandler.h"
00041 #include "TVirtualX.h"
00042 #include "TGWindow.h"
00043 #include "TGResourcePool.h"
00044 #include "TGGC.h"
00045 #include "TGFont.h"
00046 #include "TGMimeTypes.h"
00047 #include "TGFrame.h"
00048 #include "TGIdleHandler.h"
00049
00050
00051
00052 TGClient *gClient = 0;
00053
00054
00055 extern "C" void G__cpp_setup_tagtableG__Gui1();
00056 class TGClientInit {
00057 public:
00058 TGClientInit() {
00059 if (gROOT && gROOT->IsBatch()) {
00060
00061
00062 G__cpp_setup_tagtableG__Gui1();
00063 new TGClient();
00064 }
00065 TApplication::NeedGraphicsLibs();
00066 }
00067 };
00068 static TGClientInit gClientInit;
00069
00070
00071
00072
00073 class TGInputHandler : public TFileHandler {
00074 private:
00075 TGClient *fClient;
00076 public:
00077 TGInputHandler(TGClient *c, Int_t fd) : TFileHandler(fd, 1) { fClient = c; }
00078 Bool_t Notify();
00079
00080 };
00081
00082
00083 Bool_t TGInputHandler::Notify()
00084 {
00085
00086
00087 return fClient->HandleInput();
00088 }
00089
00090
00091 ClassImp(TGClient)
00092
00093
00094 TGClient::TGClient(const char *dpyName)
00095 {
00096
00097
00098
00099
00100 fRoot = 0;
00101 fPicturePool = 0;
00102 fMimeTypeList = 0;
00103 fWlist = 0;
00104 fPlist = 0;
00105 fUWHandlers = 0;
00106 fIdleHandlers = 0;
00107
00108 if (gClient) {
00109 Error("TGClient", "only one instance of TGClient allowed");
00110 MakeZombie();
00111 return;
00112 }
00113
00114
00115 gSystem->SetDisplay();
00116
00117
00118 if ((fXfd = gVirtualX->OpenDisplay(dpyName)) < 0) {
00119 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",
00120 gVirtualX->DisplayName(dpyName));
00121 MakeZombie();
00122 return;
00123 }
00124
00125 if (fXfd >= 0 && !gROOT->IsBatch()) {
00126 TGInputHandler *xi = new TGInputHandler(this, fXfd);
00127 if (fXfd) gSystem->AddFileHandler(xi);
00128
00129
00130
00131
00132
00133
00134 gXDisplay = xi;
00135 }
00136
00137
00138
00139
00140 fWlist = new THashList(200);
00141 fPlist = new TList;
00142
00143
00144
00145 fDefaultRoot = fRoot = new TGFrame(this, gVirtualX->GetDefaultRootWindow());
00146
00147
00148
00149 gWM_DELETE_WINDOW = gVirtualX->InternAtom("WM_DELETE_WINDOW", kFALSE);
00150 gMOTIF_WM_HINTS = gVirtualX->InternAtom("_MOTIF_WM_HINTS", kFALSE);
00151 gROOT_MESSAGE = gVirtualX->InternAtom("_ROOT_MESSAGE", kFALSE);
00152
00153
00154
00155
00156 fGlobalNeedRedraw = kFALSE;
00157 fForceRedraw = kFALSE;
00158 fWaitForWindow = kNone;
00159 fWaitForEvent = kOtherEvent;
00160
00161 fResourcePool = new TGResourcePool(this);
00162
00163 fPicturePool = fResourcePool->GetPicturePool();
00164 fGCPool = fResourcePool->GetGCPool();
00165 fFontPool = fResourcePool->GetFontPool();
00166
00167 fMimeTypeList = fResourcePool->GetMimeTypes();
00168 fDefaultColormap = fResourcePool->GetDefaultColormap();
00169
00170
00171
00172 fWhite = fResourcePool->GetWhiteColor();
00173 fBlack = fResourcePool->GetBlackColor();
00174 fBackColor = fResourcePool->GetFrameBgndColor();
00175 fForeColor = fResourcePool->GetFrameFgndColor();
00176 fHilite = GetHilite(fBackColor);
00177 fShadow = GetShadow(fBackColor);
00178 fSelForeColor = fResourcePool->GetSelectedFgndColor();
00179 fSelBackColor = fResourcePool->GetSelectedBgndColor();
00180
00181 gClient = this;
00182 }
00183
00184
00185 const TGWindow *TGClient::GetRoot() const
00186 {
00187
00188
00189
00190
00191 return fRoot;
00192 }
00193
00194
00195 const TGWindow *TGClient::GetDefaultRoot() const
00196 {
00197
00198
00199
00200
00201 return fDefaultRoot;
00202 }
00203
00204
00205 void TGClient::SetRoot(TGWindow *root)
00206 {
00207
00208
00209
00210
00211 fRoot = root ? root : fDefaultRoot;
00212 }
00213
00214
00215 UInt_t TGClient::GetDisplayWidth() const
00216 {
00217
00218
00219 Int_t x, y;
00220 UInt_t w, h;
00221
00222 gVirtualX->GetGeometry(-1, x, y, w, h);
00223
00224 return w;
00225 }
00226
00227
00228 UInt_t TGClient::GetDisplayHeight() const
00229 {
00230
00231
00232 Int_t x, y;
00233 UInt_t w, h;
00234
00235 gVirtualX->GetGeometry(-1, x, y, w, h);
00236
00237 return h;
00238 }
00239
00240
00241 const TGPicture *TGClient::GetPicture(const char *name)
00242 {
00243
00244
00245
00246 return fPicturePool->GetPicture(name);
00247 }
00248
00249
00250 const TGPicture *TGClient::GetPicture(const char *name,
00251 UInt_t new_width, UInt_t new_height)
00252 {
00253
00254
00255
00256
00257 return fPicturePool->GetPicture(name, new_width, new_height);
00258 }
00259
00260
00261 void TGClient::FreePicture(const TGPicture *pic)
00262 {
00263
00264
00265 if (pic) fPicturePool->FreePicture(pic);
00266 }
00267
00268
00269 TGGC *TGClient::GetGC(GCValues_t *values, Bool_t rw)
00270 {
00271
00272
00273
00274
00275
00276
00277 return fGCPool->GetGC(values, rw);
00278 }
00279
00280
00281 void TGClient::FreeGC(const TGGC *gc)
00282 {
00283
00284
00285 fGCPool->FreeGC(gc);
00286 }
00287
00288
00289 void TGClient::FreeGC(GContext_t gc)
00290 {
00291
00292
00293 fGCPool->FreeGC(gc);
00294 }
00295
00296
00297 TGFont *TGClient::GetFont(const char *font, Bool_t fixedDefault)
00298 {
00299
00300
00301
00302
00303
00304
00305 return fFontPool->GetFont(font, fixedDefault);
00306 }
00307
00308
00309 TGFont *TGClient::GetFont(const TGFont *font)
00310 {
00311
00312
00313 return fFontPool->GetFont(font);
00314 }
00315
00316
00317 void TGClient::FreeFont(const TGFont *font)
00318 {
00319
00320
00321 fFontPool->FreeFont(font);
00322 }
00323
00324
00325 void TGClient::NeedRedraw(TGWindow *w, Bool_t force)
00326 {
00327
00328 if (gVirtualX->NeedRedraw((ULong_t)w,force)) return;
00329 if (force) {
00330 w->DoRedraw();
00331 return;
00332 }
00333 w->fNeedRedraw = kTRUE;
00334 fGlobalNeedRedraw = kTRUE;
00335 }
00336
00337
00338 Bool_t TGClient::GetColorByName(const char *name, Pixel_t &pixel) const
00339 {
00340
00341
00342
00343 ColorStruct_t color;
00344 WindowAttributes_t attributes = WindowAttributes_t();
00345 Bool_t status = kTRUE;
00346
00347 gVirtualX->GetWindowAttributes(fRoot->GetId(), attributes);
00348 color.fPixel = 0;
00349 if (!gVirtualX->ParseColor(attributes.fColormap, name, color)) {
00350 Error("GetColorByName", "couldn't parse color %s", name);
00351 status = kFALSE;
00352 } else if (!gVirtualX->AllocColor(attributes.fColormap, color)) {
00353 Warning("GetColorByName", "couldn't retrieve color %s.\n"
00354 "Please close any other application, like netscape, "
00355 "that might exhaust\nthe colormap and start ROOT again", name);
00356 status = kFALSE;
00357 }
00358
00359 pixel = color.fPixel;
00360
00361 return status;
00362 }
00363
00364
00365 FontStruct_t TGClient::GetFontByName(const char *name, Bool_t fixedDefault) const
00366 {
00367
00368
00369
00370
00371
00372
00373 if (gROOT->IsBatch())
00374 return (FontStruct_t) -1;
00375
00376 FontStruct_t font = gVirtualX->LoadQueryFont(name);
00377
00378 if (!font && fixedDefault) {
00379 font = gVirtualX->LoadQueryFont("fixed");
00380 if (font)
00381 Warning("GetFontByName", "couldn't retrieve font %s, using \"fixed\"", name);
00382 }
00383 if (!font) {
00384 if (fixedDefault)
00385 Error("GetFontByName", "couldn't retrieve font %s nor backup font \"fixed\"", name);
00386 else
00387 Warning("GetFontByName", "couldn't retrieve font %s", name);
00388 }
00389
00390 return font;
00391 }
00392
00393
00394 Pixel_t TGClient::GetHilite(Pixel_t base_color) const
00395 {
00396
00397
00398 ColorStruct_t color, white_p;
00399 WindowAttributes_t attributes = WindowAttributes_t();
00400
00401 gVirtualX->GetWindowAttributes(fRoot->GetId(), attributes);
00402
00403 color.fPixel = base_color;
00404 gVirtualX->QueryColor(attributes.fColormap, color);
00405
00406 GetColorByName("white", white_p.fPixel);
00407 gVirtualX->QueryColor(attributes.fColormap, white_p);
00408
00409 color.fRed = TMath::Max((UShort_t)(white_p.fRed/5), color.fRed);
00410 color.fGreen = TMath::Max((UShort_t)(white_p.fGreen/5), color.fGreen);
00411 color.fBlue = TMath::Max((UShort_t)(white_p.fBlue/5), color.fBlue);
00412
00413 color.fRed = (UShort_t)TMath::Min((Int_t)white_p.fRed, (Int_t)(color.fRed*140)/100);
00414 color.fGreen = (UShort_t)TMath::Min((Int_t)white_p.fGreen, (Int_t)(color.fGreen*140)/100);
00415 color.fBlue = (UShort_t)TMath::Min((Int_t)white_p.fBlue, (Int_t)(color.fBlue*140)/100);
00416
00417 if (!gVirtualX->AllocColor(attributes.fColormap, color))
00418 Error("GetHilite", "couldn't allocate hilight color");
00419
00420 return color.fPixel;
00421 }
00422
00423
00424 Pixel_t TGClient::GetShadow(Pixel_t base_color) const
00425 {
00426
00427
00428
00429 ColorStruct_t color;
00430 WindowAttributes_t attributes = WindowAttributes_t();
00431
00432 gVirtualX->GetWindowAttributes(fRoot->GetId(), attributes);
00433
00434 color.fPixel = base_color;
00435 gVirtualX->QueryColor(attributes.fColormap, color);
00436
00437 color.fRed = (UShort_t)((color.fRed*60)/100);
00438 color.fGreen = (UShort_t)((color.fGreen*60)/100);
00439 color.fBlue = (UShort_t)((color.fBlue*60)/100);
00440
00441 if (!gVirtualX->AllocColor(attributes.fColormap, color))
00442 Error("GetShadow", "couldn't allocate shadow color");
00443
00444 return color.fPixel;
00445 }
00446
00447
00448 void TGClient::FreeColor(Pixel_t color) const
00449 {
00450
00451
00452 gVirtualX->FreeColor(fDefaultColormap, color);
00453 }
00454
00455
00456 void TGClient::RegisterWindow(TGWindow *w)
00457 {
00458
00459
00460 fWlist->Add(w);
00461
00462
00463 RegisteredWindow(w->GetId());
00464 }
00465
00466
00467 void TGClient::UnregisterWindow(TGWindow *w)
00468 {
00469
00470
00471 fWlist->Remove(w);
00472 }
00473
00474
00475 void TGClient::RegisterPopup(TGWindow *w)
00476 {
00477
00478
00479
00480
00481 fPlist->Add(w);
00482
00483
00484 RegisteredWindow(w->GetId());
00485 }
00486
00487
00488 void TGClient::UnregisterPopup(TGWindow *w)
00489 {
00490
00491
00492 fPlist->Remove(w);
00493 }
00494
00495
00496 void TGClient::AddUnknownWindowHandler(TGUnknownWindowHandler *h)
00497 {
00498
00499
00500 if (!fUWHandlers) {
00501 fUWHandlers = new TList;
00502 fUWHandlers->SetOwner();
00503 }
00504
00505 fUWHandlers->Add(h);
00506 }
00507
00508
00509 void TGClient::RemoveUnknownWindowHandler(TGUnknownWindowHandler *h)
00510 {
00511
00512
00513 fUWHandlers->Remove(h);
00514 }
00515
00516
00517 void TGClient::AddIdleHandler(TGIdleHandler *h)
00518 {
00519
00520
00521 if (!fIdleHandlers) {
00522 fIdleHandlers = new TList;
00523 fIdleHandlers->SetOwner();
00524 }
00525
00526 fIdleHandlers->Add(h);
00527 }
00528
00529
00530 void TGClient::RemoveIdleHandler(TGIdleHandler *h)
00531 {
00532
00533
00534 fIdleHandlers->Remove(h);
00535 }
00536
00537
00538 TGWindow *TGClient::GetWindowById(Window_t wid) const
00539 {
00540
00541
00542 TGWindow wt(wid);
00543
00544 return (TGWindow *) fWlist->FindObject(&wt);
00545 }
00546
00547
00548 TGWindow *TGClient::GetWindowByName(const char *name) const
00549 {
00550
00551
00552
00553 TIter next(fWlist);
00554
00555 TObject *obj;
00556 while ((obj = next())) {
00557 TString n = obj->GetName();
00558 if (n == name) {
00559 return (TGWindow*)obj;
00560 }
00561 }
00562 return 0;
00563 }
00564
00565
00566 TGClient::~TGClient()
00567 {
00568
00569
00570 if (IsZombie())
00571 return;
00572
00573 if (fWlist)
00574 fWlist->Delete("slow");
00575 delete fWlist;
00576 delete fPlist;
00577 delete fUWHandlers;
00578 delete fIdleHandlers;
00579 delete fResourcePool;
00580
00581 gVirtualX->CloseDisplay();
00582
00583 }
00584
00585
00586 Bool_t TGClient::ProcessOneEvent()
00587 {
00588
00589
00590
00591
00592
00593
00594 Event_t event;
00595
00596 if (!fRoot) return kFALSE;
00597 if (gVirtualX->EventsPending()) {
00598 gVirtualX->NextEvent(event);
00599 if (fWaitForWindow == kNone) {
00600 HandleEvent(&event);
00601 if (fForceRedraw)
00602 DoRedraw();
00603 return kTRUE;
00604 } else {
00605 HandleMaskEvent(&event, fWaitForWindow);
00606 if ((event.fType == fWaitForEvent) && (event.fWindow == fWaitForWindow))
00607 fWaitForWindow = kNone;
00608 if (fForceRedraw)
00609 DoRedraw();
00610 return kTRUE;
00611 }
00612 }
00613
00614
00615 if (DoRedraw()) return kTRUE;
00616
00617
00618 if (ProcessIdleEvent()) return kTRUE;
00619
00620 return kFALSE;
00621 }
00622
00623
00624 Bool_t TGClient::ProcessIdleEvent()
00625 {
00626
00627
00628 if (fIdleHandlers) {
00629 TGIdleHandler *ih = (TGIdleHandler *) fIdleHandlers->First();
00630 if (ih) {
00631 RemoveIdleHandler(ih);
00632 ih->HandleEvent();
00633 return kTRUE;
00634 }
00635 }
00636 return kFALSE;
00637 }
00638
00639
00640 Bool_t TGClient::HandleInput()
00641 {
00642
00643
00644
00645 Bool_t handledevent = kFALSE;
00646
00647 while (ProcessOneEvent())
00648 handledevent = kTRUE;
00649 return handledevent;
00650 }
00651
00652
00653 void TGClient::WaitFor(TGWindow *w)
00654 {
00655
00656
00657 Window_t wsave = fWaitForWindow;
00658 EGEventType esave = fWaitForEvent;
00659
00660 fWaitForWindow = w->GetId();
00661 fWaitForEvent = kDestroyNotify;
00662
00663 while (fWaitForWindow != kNone) {
00664 if (esave == kUnmapNotify)
00665 wsave = kNone;
00666 gSystem->ProcessEvents();
00667 gSystem->Sleep(5);
00668 }
00669
00670 fWaitForWindow = wsave;
00671 fWaitForEvent = esave;
00672 }
00673
00674
00675 void TGClient::WaitForUnmap(TGWindow *w)
00676 {
00677
00678
00679 Window_t wsave = fWaitForWindow;
00680 EGEventType esave = fWaitForEvent;
00681
00682 fWaitForWindow = w->GetId();
00683 fWaitForEvent = kUnmapNotify;
00684
00685 while (fWaitForWindow != kNone) {
00686 gSystem->ProcessEvents();
00687 gSystem->Sleep(5);
00688 }
00689
00690 fWaitForWindow = wsave;
00691 fWaitForEvent = esave;
00692 }
00693
00694
00695 void TGClient::ResetWaitFor(TGWindow *w)
00696 {
00697
00698
00699 if (fWaitForWindow == w->GetId()) fWaitForWindow = kNone;
00700 }
00701
00702
00703 Bool_t TGClient::ProcessEventsFor(TGWindow *w)
00704 {
00705
00706
00707
00708
00709 Window_t wsave = fWaitForWindow;
00710 EGEventType esave = fWaitForEvent;
00711
00712 fWaitForWindow = w->GetId();
00713 fWaitForEvent = kDestroyNotify;
00714
00715 Bool_t intr = gSystem->ProcessEvents();
00716
00717 fWaitForWindow = wsave;
00718 fWaitForEvent = esave;
00719
00720 return intr;
00721 }
00722
00723
00724 Bool_t TGClient::DoRedraw()
00725 {
00726
00727
00728
00729
00730
00731 if (!fGlobalNeedRedraw) return kFALSE;
00732
00733 TGWindow *w;
00734 TObjLink *lnk = fWlist->FirstLink();
00735 while (lnk) {
00736 w = (TGWindow *) lnk->GetObject();
00737 if (w->fNeedRedraw) {
00738 w->DoRedraw();
00739 w->fNeedRedraw = kFALSE;
00740 }
00741 lnk = lnk->Next();
00742 }
00743
00744 fGlobalNeedRedraw = kFALSE;
00745 fForceRedraw = kFALSE;
00746
00747 return kTRUE;
00748 }
00749
00750
00751 Bool_t TGClient::HandleEvent(Event_t *event)
00752 {
00753
00754
00755 TGWindow *w;
00756
00757
00758 if (event->fType != kConfigureNotify) {
00759 ProcessedEvent(event, 0);
00760 }
00761
00762
00763 if ((w = GetWindowById(event->fWindow)) == 0) {
00764 if (fUWHandlers && fUWHandlers->GetSize() > 0) {
00765 TGUnknownWindowHandler *unkwh;
00766 TListIter it(fUWHandlers);
00767 while ((unkwh = (TGUnknownWindowHandler*)it.Next())) {
00768 if (unkwh->HandleEvent(event))
00769 return kTRUE;
00770 }
00771 }
00772
00773
00774 return kFALSE;
00775 }
00776
00777
00778 w->HandleEvent(event);
00779
00780 return kTRUE;
00781 }
00782
00783
00784 Bool_t TGClient::HandleMaskEvent(Event_t *event, Window_t wid)
00785 {
00786
00787
00788
00789
00790
00791
00792 TGWindow *w, *ptr, *pop;
00793
00794 if ((w = GetWindowById(event->fWindow)) == 0) return kFALSE;
00795
00796
00797 if (event->fType != kConfigureNotify) {
00798 ProcessedEvent(event, wid);
00799 }
00800
00801
00802
00803
00804 for (ptr = w; ptr->fParent != 0; ptr = (TGWindow *) ptr->fParent) {
00805 if ((ptr->fId == wid) ||
00806 ((event->fType != kButtonPress) &&
00807 (event->fType != kButtonRelease) &&
00808 (event->fType != kGKeyPress) &&
00809 (event->fType != kKeyRelease) &&
00810 (event->fType != kEnterNotify) &&
00811 (event->fType != kLeaveNotify) &&
00812 (event->fType != kMotionNotify))) {
00813 w->HandleEvent(event);
00814 return kTRUE;
00815 }
00816 }
00817
00818
00819 TIter next(fPlist);
00820 while ((pop = (TGWindow *) next())) {
00821 for (ptr = w; ptr->fParent != 0; ptr = (TGWindow *) ptr->fParent) {
00822 if ((ptr->fId == pop->fId) &&
00823 ((event->fType == kButtonPress) ||
00824 (event->fType == kButtonRelease) ||
00825 (event->fType == kGKeyPress) ||
00826 (event->fType == kKeyRelease) ||
00827 (event->fType == kEnterNotify) ||
00828 (event->fType == kLeaveNotify) ||
00829 (event->fType == kMotionNotify))) {
00830 w->HandleEvent(event);
00831 return kTRUE;
00832 }
00833 }
00834 }
00835
00836 if (event->fType == kButtonPress || event->fType == kGKeyPress)
00837 gVirtualX->Bell(0);
00838
00839 return kFALSE;
00840 }
00841
00842
00843 void TGClient::ProcessLine(TString cmd, Long_t msg, Long_t parm1, Long_t parm2)
00844 {
00845
00846
00847
00848
00849
00850 if (cmd.IsNull()) return;
00851
00852 char s[32];
00853
00854 snprintf(s, sizeof(s), "%ld", msg);
00855 cmd.ReplaceAll("$MSG", s);
00856
00857 snprintf(s, sizeof(s), "%ld", parm1);
00858 cmd.ReplaceAll("$PARM1", s);
00859
00860 snprintf(s, sizeof(s), "%ld", parm2);
00861 cmd.ReplaceAll("$PARM2", s);
00862
00863 gROOT->ProcessLine(cmd.Data());
00864 }
00865
00866
00867 Bool_t TGClient::IsEditDisabled() const
00868 {
00869
00870
00871 return (fDefaultRoot->GetEditDisabled() == 1);
00872 }
00873
00874
00875 void TGClient::SetEditDisabled(Bool_t on)
00876 {
00877
00878
00879 fDefaultRoot->SetEditDisabled(on);
00880 }
00881
00882
00883 void TGClient::ProcessedEvent(Event_t *event, Window_t wid)
00884 {
00885
00886
00887
00888 Long_t args[2];
00889 args[0] = (Long_t) event;
00890 args[1] = (Long_t) wid;
00891
00892 Emit("ProcessedEvent(Event_t*, Window_t)", args);
00893 }
00894
00895
00896 void TGClient::RegisteredWindow(Window_t w)
00897 {
00898
00899
00900
00901 Emit("RegisteredWindow(Window_t)", w);
00902 }