#include "RConfigure.h"
#include "TGClient.h"
#include "TROOT.h"
#include "TApplication.h"
#include "TSystem.h"
#include "TEnv.h"
#include "THashList.h"
#include "TSysEvtHandler.h"
#include "TVirtualX.h"
#include "TGWindow.h"
#include "TGResourcePool.h"
#include "TGGC.h"
#include "TGFont.h"
#include "TGMimeTypes.h"
#include "TGFrame.h"
#include "TGIdleHandler.h"
TGClient *gClient = 0;
extern "C" void G__cpp_setup_tagtableG__Gui1();
class TGClientInit {
public:
TGClientInit() {
if (gROOT && gROOT->IsBatch()) {
G__cpp_setup_tagtableG__Gui1();
new TGClient();
}
TApplication::NeedGraphicsLibs();
}
};
static TGClientInit gClientInit;
class TGInputHandler : public TFileHandler {
private:
TGClient *fClient;
public:
TGInputHandler(TGClient *c, Int_t fd) : TFileHandler(fd, 1) { fClient = c; }
Bool_t Notify();
};
Bool_t TGInputHandler::Notify()
{
return fClient->HandleInput();
}
ClassImp(TGClient)
TGClient::TGClient(const char *dpyName)
{
fRoot = 0;
fPicturePool = 0;
fMimeTypeList = 0;
fWlist = 0;
fPlist = 0;
fUWHandlers = 0;
fIdleHandlers = 0;
if (gClient) {
Error("TGClient", "only one instance of TGClient allowed");
MakeZombie();
return;
}
gSystem->SetDisplay();
if ((fXfd = gVirtualX->OpenDisplay(dpyName)) < 0) {
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",
gVirtualX->DisplayName(dpyName));
MakeZombie();
return;
}
if (fXfd >= 0 && !gROOT->IsBatch()) {
TGInputHandler *xi = new TGInputHandler(this, fXfd);
if (fXfd) gSystem->AddFileHandler(xi);
gXDisplay = xi;
}
fWlist = new THashList(200);
fPlist = new TList;
fDefaultRoot = fRoot = new TGFrame(this, gVirtualX->GetDefaultRootWindow());
gWM_DELETE_WINDOW = gVirtualX->InternAtom("WM_DELETE_WINDOW", kFALSE);
gMOTIF_WM_HINTS = gVirtualX->InternAtom("_MOTIF_WM_HINTS", kFALSE);
gROOT_MESSAGE = gVirtualX->InternAtom("_ROOT_MESSAGE", kFALSE);
fGlobalNeedRedraw = kFALSE;
fForceRedraw = kFALSE;
fWaitForWindow = kNone;
fWaitForEvent = kOtherEvent;
fResourcePool = new TGResourcePool(this);
fPicturePool = fResourcePool->GetPicturePool();
fGCPool = fResourcePool->GetGCPool();
fFontPool = fResourcePool->GetFontPool();
fMimeTypeList = fResourcePool->GetMimeTypes();
fDefaultColormap = fResourcePool->GetDefaultColormap();
fWhite = fResourcePool->GetWhiteColor();
fBlack = fResourcePool->GetBlackColor();
fBackColor = fResourcePool->GetFrameBgndColor();
fForeColor = fResourcePool->GetFrameFgndColor();
fHilite = GetHilite(fBackColor);
fShadow = GetShadow(fBackColor);
fSelForeColor = fResourcePool->GetSelectedFgndColor();
fSelBackColor = fResourcePool->GetSelectedBgndColor();
fStyle = 0;
TString style = gEnv->GetValue("Gui.Style", "modern");
if (style.Contains("flat", TString::kIgnoreCase))
fStyle = 2;
else if (style.Contains("modern", TString::kIgnoreCase))
fStyle = 1;
gClient = this;
}
const TGWindow *TGClient::GetRoot() const
{
return fRoot;
}
const TGWindow *TGClient::GetDefaultRoot() const
{
return fDefaultRoot;
}
void TGClient::SetRoot(TGWindow *root)
{
fRoot = root ? root : fDefaultRoot;
}
void TGClient::SetStyle(const char *style)
{
fStyle = 0;
if (style && strstr(style, "modern"))
fStyle = 1;
}
UInt_t TGClient::GetDisplayWidth() const
{
Int_t x, y;
UInt_t w, h;
gVirtualX->GetGeometry(-1, x, y, w, h);
return w;
}
UInt_t TGClient::GetDisplayHeight() const
{
Int_t x, y;
UInt_t w, h;
gVirtualX->GetGeometry(-1, x, y, w, h);
return h;
}
const TGPicture *TGClient::GetPicture(const char *name)
{
return fPicturePool->GetPicture(name);
}
const TGPicture *TGClient::GetPicture(const char *name,
UInt_t new_width, UInt_t new_height)
{
return fPicturePool->GetPicture(name, new_width, new_height);
}
void TGClient::FreePicture(const TGPicture *pic)
{
if (pic) fPicturePool->FreePicture(pic);
}
TGGC *TGClient::GetGC(GCValues_t *values, Bool_t rw)
{
return fGCPool->GetGC(values, rw);
}
void TGClient::FreeGC(const TGGC *gc)
{
fGCPool->FreeGC(gc);
}
void TGClient::FreeGC(GContext_t gc)
{
fGCPool->FreeGC(gc);
}
TGFont *TGClient::GetFont(const char *font, Bool_t fixedDefault)
{
return fFontPool->GetFont(font, fixedDefault);
}
TGFont *TGClient::GetFont(const TGFont *font)
{
return fFontPool->GetFont(font);
}
void TGClient::FreeFont(const TGFont *font)
{
fFontPool->FreeFont(font);
}
void TGClient::NeedRedraw(TGWindow *w, Bool_t force)
{
if (gVirtualX->NeedRedraw((ULong_t)w,force)) return;
if (force) {
w->DoRedraw();
return;
}
w->fNeedRedraw = kTRUE;
fGlobalNeedRedraw = kTRUE;
}
void TGClient::CancelRedraw(TGWindow *w)
{
w->fNeedRedraw = kFALSE;
}
Bool_t TGClient::GetColorByName(const char *name, Pixel_t &pixel) const
{
ColorStruct_t color;
WindowAttributes_t attributes = WindowAttributes_t();
Bool_t status = kTRUE;
gVirtualX->GetWindowAttributes(fRoot->GetId(), attributes);
color.fPixel = 0;
if (!gVirtualX->ParseColor(attributes.fColormap, name, color)) {
Error("GetColorByName", "couldn't parse color %s", name);
status = kFALSE;
} else if (!gVirtualX->AllocColor(attributes.fColormap, color)) {
Warning("GetColorByName", "couldn't retrieve color %s.\n"
"Please close any other application, like netscape, "
"that might exhaust\nthe colormap and start ROOT again", name);
status = kFALSE;
}
pixel = color.fPixel;
return status;
}
FontStruct_t TGClient::GetFontByName(const char *name, Bool_t fixedDefault) const
{
if (gROOT->IsBatch())
return (FontStruct_t) -1;
FontStruct_t font = gVirtualX->LoadQueryFont(name);
if (!font && fixedDefault) {
font = gVirtualX->LoadQueryFont("fixed");
if (font)
Warning("GetFontByName", "couldn't retrieve font %s, using \"fixed\"", name);
}
if (!font) {
if (fixedDefault)
Error("GetFontByName", "couldn't retrieve font %s nor backup font \"fixed\"", name);
else
Warning("GetFontByName", "couldn't retrieve font %s", name);
}
return font;
}
Pixel_t TGClient::GetHilite(Pixel_t base_color) const
{
ColorStruct_t color, white_p;
WindowAttributes_t attributes = WindowAttributes_t();
gVirtualX->GetWindowAttributes(fRoot->GetId(), attributes);
color.fPixel = base_color;
gVirtualX->QueryColor(attributes.fColormap, color);
GetColorByName("white", white_p.fPixel);
gVirtualX->QueryColor(attributes.fColormap, white_p);
color.fRed = TMath::Max((UShort_t)(white_p.fRed/5), color.fRed);
color.fGreen = TMath::Max((UShort_t)(white_p.fGreen/5), color.fGreen);
color.fBlue = TMath::Max((UShort_t)(white_p.fBlue/5), color.fBlue);
color.fRed = (UShort_t)TMath::Min((Int_t)white_p.fRed, (Int_t)(color.fRed*140)/100);
color.fGreen = (UShort_t)TMath::Min((Int_t)white_p.fGreen, (Int_t)(color.fGreen*140)/100);
color.fBlue = (UShort_t)TMath::Min((Int_t)white_p.fBlue, (Int_t)(color.fBlue*140)/100);
if (!gVirtualX->AllocColor(attributes.fColormap, color))
Error("GetHilite", "couldn't allocate hilight color");
return color.fPixel;
}
Pixel_t TGClient::GetShadow(Pixel_t base_color) const
{
ColorStruct_t color;
WindowAttributes_t attributes = WindowAttributes_t();
gVirtualX->GetWindowAttributes(fRoot->GetId(), attributes);
color.fPixel = base_color;
gVirtualX->QueryColor(attributes.fColormap, color);
color.fRed = (UShort_t)((color.fRed*60)/100);
color.fGreen = (UShort_t)((color.fGreen*60)/100);
color.fBlue = (UShort_t)((color.fBlue*60)/100);
if (!gVirtualX->AllocColor(attributes.fColormap, color))
Error("GetShadow", "couldn't allocate shadow color");
return color.fPixel;
}
void TGClient::FreeColor(Pixel_t color) const
{
gVirtualX->FreeColor(fDefaultColormap, color);
}
void TGClient::RegisterWindow(TGWindow *w)
{
fWlist->Add(w);
RegisteredWindow(w->GetId());
}
void TGClient::UnregisterWindow(TGWindow *w)
{
fWlist->Remove(w);
}
void TGClient::RegisterPopup(TGWindow *w)
{
fPlist->Add(w);
RegisteredWindow(w->GetId());
}
void TGClient::UnregisterPopup(TGWindow *w)
{
fPlist->Remove(w);
}
void TGClient::AddUnknownWindowHandler(TGUnknownWindowHandler *h)
{
if (!fUWHandlers) {
fUWHandlers = new TList;
fUWHandlers->SetOwner();
}
fUWHandlers->Add(h);
}
void TGClient::RemoveUnknownWindowHandler(TGUnknownWindowHandler *h)
{
fUWHandlers->Remove(h);
}
void TGClient::AddIdleHandler(TGIdleHandler *h)
{
if (!fIdleHandlers) {
fIdleHandlers = new TList;
fIdleHandlers->SetOwner();
}
fIdleHandlers->Add(h);
}
void TGClient::RemoveIdleHandler(TGIdleHandler *h)
{
fIdleHandlers->Remove(h);
}
TGWindow *TGClient::GetWindowById(Window_t wid) const
{
TGWindow wt(wid);
return (TGWindow *) fWlist->FindObject(&wt);
}
TGWindow *TGClient::GetWindowByName(const char *name) const
{
TIter next(fWlist);
TObject *obj;
while ((obj = next())) {
TString n = obj->GetName();
if (n == name) {
return (TGWindow*)obj;
}
}
return 0;
}
TGClient::~TGClient()
{
if (IsZombie())
return;
if (fWlist)
fWlist->Delete("slow");
delete fWlist;
delete fPlist;
delete fUWHandlers;
delete fIdleHandlers;
delete fResourcePool;
gVirtualX->CloseDisplay();
}
Bool_t TGClient::ProcessOneEvent()
{
Event_t event;
if (!fRoot) return kFALSE;
if (gVirtualX->EventsPending()) {
gVirtualX->NextEvent(event);
if (fWaitForWindow == kNone) {
HandleEvent(&event);
if (fForceRedraw)
DoRedraw();
return kTRUE;
} else {
HandleMaskEvent(&event, fWaitForWindow);
if ((event.fType == fWaitForEvent) && (event.fWindow == fWaitForWindow))
fWaitForWindow = kNone;
if (fForceRedraw)
DoRedraw();
return kTRUE;
}
}
if (DoRedraw()) return kTRUE;
if (ProcessIdleEvent()) return kTRUE;
return kFALSE;
}
Bool_t TGClient::ProcessIdleEvent()
{
if (fIdleHandlers) {
TGIdleHandler *ih = (TGIdleHandler *) fIdleHandlers->First();
if (ih) {
RemoveIdleHandler(ih);
ih->HandleEvent();
return kTRUE;
}
}
return kFALSE;
}
Bool_t TGClient::HandleInput()
{
Bool_t handledevent = kFALSE;
while (ProcessOneEvent())
handledevent = kTRUE;
return handledevent;
}
void TGClient::WaitFor(TGWindow *w)
{
Window_t wsave = fWaitForWindow;
EGEventType esave = fWaitForEvent;
fWaitForWindow = w->GetId();
fWaitForEvent = kDestroyNotify;
if (gVirtualX)
gVirtualX->BeginModalSessionFor(w->GetId());
while (fWaitForWindow != kNone) {
if (esave == kUnmapNotify)
wsave = kNone;
gSystem->ProcessEvents();
gSystem->Sleep(5);
}
fWaitForWindow = wsave;
fWaitForEvent = esave;
}
void TGClient::WaitForUnmap(TGWindow *w)
{
Window_t wsave = fWaitForWindow;
EGEventType esave = fWaitForEvent;
fWaitForWindow = w->GetId();
fWaitForEvent = kUnmapNotify;
if (gVirtualX)
gVirtualX->BeginModalSessionFor(w->GetId());
while (fWaitForWindow != kNone) {
gSystem->ProcessEvents();
gSystem->Sleep(5);
}
fWaitForWindow = wsave;
fWaitForEvent = esave;
}
void TGClient::ResetWaitFor(TGWindow *w)
{
if (fWaitForWindow == w->GetId()) fWaitForWindow = kNone;
}
Bool_t TGClient::ProcessEventsFor(TGWindow *w)
{
Window_t wsave = fWaitForWindow;
EGEventType esave = fWaitForEvent;
fWaitForWindow = w->GetId();
fWaitForEvent = kDestroyNotify;
Bool_t intr = gSystem->ProcessEvents();
fWaitForWindow = wsave;
fWaitForEvent = esave;
return intr;
}
Bool_t TGClient::DoRedraw()
{
if (!fGlobalNeedRedraw) return kFALSE;
TGWindow *w;
TObjLink *lnk = fWlist->FirstLink();
while (lnk) {
w = (TGWindow *) lnk->GetObject();
if (w->fNeedRedraw) {
w->DoRedraw();
w->fNeedRedraw = kFALSE;
}
lnk = lnk->Next();
}
fGlobalNeedRedraw = kFALSE;
fForceRedraw = kFALSE;
return kTRUE;
}
Bool_t TGClient::HandleEvent(Event_t *event)
{
TGWindow *w;
if (event->fType != kConfigureNotify) {
ProcessedEvent(event, 0);
}
if ((w = GetWindowById(event->fWindow)) == 0) {
if (fUWHandlers && fUWHandlers->GetSize() > 0) {
TGUnknownWindowHandler *unkwh;
TListIter it(fUWHandlers);
while ((unkwh = (TGUnknownWindowHandler*)it.Next())) {
if (unkwh->HandleEvent(event))
return kTRUE;
}
}
return kFALSE;
}
w->HandleEvent(event);
return kTRUE;
}
Bool_t TGClient::HandleMaskEvent(Event_t *event, Window_t wid)
{
TGWindow *w, *ptr, *pop;
if ((w = GetWindowById(event->fWindow)) == 0) return kFALSE;
if (event->fType != kConfigureNotify) {
ProcessedEvent(event, wid);
}
for (ptr = w; ptr->fParent != 0; ptr = (TGWindow *) ptr->fParent) {
if ((ptr->fId == wid) ||
((event->fType != kButtonPress) &&
(event->fType != kButtonRelease) &&
(event->fType != kGKeyPress) &&
(event->fType != kKeyRelease) &&
(event->fType != kEnterNotify) &&
(event->fType != kLeaveNotify) &&
(event->fType != kMotionNotify))) {
w->HandleEvent(event);
return kTRUE;
}
}
TIter next(fPlist);
while ((pop = (TGWindow *) next())) {
for (ptr = w; ptr->fParent != 0; ptr = (TGWindow *) ptr->fParent) {
if ((ptr->fId == pop->fId) &&
((event->fType == kButtonPress) ||
(event->fType == kButtonRelease) ||
(event->fType == kGKeyPress) ||
(event->fType == kKeyRelease) ||
(event->fType == kEnterNotify) ||
(event->fType == kLeaveNotify) ||
(event->fType == kMotionNotify))) {
w->HandleEvent(event);
return kTRUE;
}
}
}
if (event->fType == kButtonPress || event->fType == kGKeyPress)
gVirtualX->Bell(0);
return kFALSE;
}
void TGClient::ProcessLine(TString cmd, Long_t msg, Long_t parm1, Long_t parm2)
{
if (cmd.IsNull()) return;
char s[32];
snprintf(s, sizeof(s), "%ld", msg);
cmd.ReplaceAll("$MSG", s);
snprintf(s, sizeof(s), "%ld", parm1);
cmd.ReplaceAll("$PARM1", s);
snprintf(s, sizeof(s), "%ld", parm2);
cmd.ReplaceAll("$PARM2", s);
gROOT->ProcessLine(cmd.Data());
}
Bool_t TGClient::IsEditDisabled() const
{
return (fDefaultRoot->GetEditDisabled() == 1);
}
void TGClient::SetEditDisabled(Bool_t on)
{
fDefaultRoot->SetEditDisabled(on);
}
void TGClient::ProcessedEvent(Event_t *event, Window_t wid)
{
Long_t args[2];
args[0] = (Long_t) event;
args[1] = (Long_t) wid;
Emit("ProcessedEvent(Event_t*, Window_t)", args);
}
void TGClient::RegisteredWindow(Window_t w)
{
Emit("RegisteredWindow(Window_t)", w);
}