Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
GX11Gui.cxx
Go to the documentation of this file.
1 // @(#)root/x11:$Id$
2 // Author: Fons Rademakers 28/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 /** \class TGX11
13 */
14 
15 // This file contains the implementation of the GUI methods of the
16 // TGX11 class. Most of the methods are used by the machine independent
17 // GUI classes (libGUI.so).
18 
19 #include <stdio.h>
20 #include <string.h>
21 #include <stdlib.h>
22 #include <ctype.h>
23 #include <limits.h>
24 #include <unistd.h>
25 
26 #include <X11/Xlib.h>
27 #include <X11/Xutil.h>
28 #include <X11/Xatom.h>
29 #include <X11/cursorfont.h>
30 #include <X11/keysym.h>
31 #include <X11/xpm.h>
32 
33 #include "TGX11.h"
34 #include "TROOT.h"
35 #include "TError.h"
36 #include "TSystem.h"
37 #include "TException.h"
38 #include "TClassTable.h"
39 #include "KeySymbols.h"
40 #include "TEnv.h"
41 
42 #include <X11/extensions/shape.h>
43 
44 //---- MWM Hints stuff
45 
46 struct MWMHintsProperty_t {
47  Handle_t fFlags;
48  Handle_t fFunctions;
49  Handle_t fDecorations;
50  Int_t fInputMode;
51 };
52 
53 //---- hints
54 
55 const ULong_t kMWMHintsFunctions = BIT(0);
56 const ULong_t kMWMHintsDecorations = BIT(1);
57 const ULong_t kMWMHintsInputMode = BIT(2);
58 
59 const Int_t kPropMotifWMHintsElements = 4;
60 const Int_t kPropMWMHintElements = kPropMotifWMHintsElements;
61 
62 
63 //---- Key symbol mapping
64 
65 struct KeySymbolMap_t {
66  KeySym fXKeySym;
67  EKeySym fKeySym;
68 };
69 
70 //---- Mapping table of all non-trivial mappings (the ASCII keys map
71 //---- one to one so are not included)
72 
73 static KeySymbolMap_t gKeyMap[] = {
74  { XK_Escape, kKey_Escape },
75  { XK_Tab, kKey_Tab },
76 #ifndef XK_ISO_Left_Tab
77  { 0xFE20, kKey_Backtab },
78 #else
79  { XK_ISO_Left_Tab, kKey_Backtab },
80 #endif
81  { XK_BackSpace, kKey_Backspace },
82  { XK_Return, kKey_Return },
83  { XK_Insert, kKey_Insert },
84  { XK_Delete, kKey_Delete },
85  { XK_Clear, kKey_Delete },
86  { XK_Pause, kKey_Pause },
87  { XK_Print, kKey_Print },
88  { 0x1005FF60, kKey_SysReq }, // hardcoded Sun SysReq
89  { 0x1007ff00, kKey_SysReq }, // hardcoded X386 SysReq
90  { XK_Home, kKey_Home }, // cursor movement
91  { XK_End, kKey_End },
92  { XK_Left, kKey_Left },
93  { XK_Up, kKey_Up },
94  { XK_Right, kKey_Right },
95  { XK_Down, kKey_Down },
96  { XK_Prior, kKey_Prior },
97  { XK_Next, kKey_Next },
98  { XK_Shift_L, kKey_Shift }, // modifiers
99  { XK_Shift_R, kKey_Shift },
100  { XK_Shift_Lock, kKey_Shift },
101  { XK_Control_L, kKey_Control },
102  { XK_Control_R, kKey_Control },
103  { XK_Meta_L, kKey_Meta },
104  { XK_Meta_R, kKey_Meta },
105  { XK_Alt_L, kKey_Alt },
106  { XK_Alt_R, kKey_Alt },
107  { XK_Caps_Lock, kKey_CapsLock },
108  { XK_Num_Lock, kKey_NumLock },
109  { XK_Scroll_Lock, kKey_ScrollLock },
110  { XK_KP_Space, kKey_Space }, // numeric keypad
111  { XK_KP_Tab, kKey_Tab },
112  { XK_KP_Enter, kKey_Enter },
113  { XK_KP_F1, kKey_F1 },
114  { XK_KP_F2, kKey_F2 },
115  { XK_KP_F3, kKey_F3 },
116  { XK_KP_F4, kKey_F4 },
117  { XK_KP_Home, kKey_Home },
118  { XK_KP_Left, kKey_Left },
119  { XK_KP_Up, kKey_Up },
120  { XK_KP_Right, kKey_Right },
121  { XK_KP_Down, kKey_Down },
122  { XK_KP_Prior, kKey_Prior },
123  { XK_KP_Page_Up, kKey_PageUp },
124  { XK_KP_Next, kKey_Next },
125  { XK_KP_Page_Down, kKey_PageDown },
126  { XK_KP_End, kKey_End },
127  { XK_KP_Begin, kKey_Home },
128  { XK_KP_Insert, kKey_Insert },
129  { XK_KP_Delete, kKey_Delete },
130  { XK_KP_Equal, kKey_Equal },
131  { XK_KP_Multiply, kKey_Asterisk },
132  { XK_KP_Add, kKey_Plus },
133  { XK_KP_Separator, kKey_Comma },
134  { XK_KP_Subtract, kKey_Minus },
135  { XK_KP_Decimal, kKey_Period },
136  { XK_KP_Divide, kKey_Slash },
137  { 0, (EKeySym) 0 }
138 };
139 
140 struct RXGCValues:XGCValues{};
141 struct RXColor:XColor{};
142 struct RXpmAttributes:XpmAttributes{};
143 struct RXSetWindowAttributes:XSetWindowAttributes{};
144 struct RVisual:Visual{};
145 
146 ////////////////////////////////////////////////////////////////////////////////
147 
148 inline void SplitLong(Long_t ll, Long_t &i1, Long_t &i2)
149 {
150  union { Long_t l; Int_t i[2]; } conv;
151 
152  conv.l = ll;
153  i1 = conv.i[0];
154  i2 = conv.i[1];
155 }
156 
157 ////////////////////////////////////////////////////////////////////////////////
158 
159 inline void AsmLong(Long_t i1, Long_t i2, Long_t &ll)
160 {
161  union { Long_t l; Int_t i[2]; } conv;
162 
163  conv.i[0] = (Int_t) i1;
164  conv.i[1] = (Int_t) i2;
165  ll = conv.l;
166 }
167 
168 ////////////////////////////////////////////////////////////////////////////////
169 /// Handle X11 error.
170 
171 static Int_t RootX11ErrorHandler(Display *disp, XErrorEvent *err)
172 {
173  char msg[80];
174  XGetErrorText(disp, err->error_code, msg, 80);
175 
176  // force segV. to allow backtracing the error with gdb
177  if (gDebug == (Long_t)gVirtualX) {
178  gSystem->ProcessEvents();
179  ::Error("RootX11ErrorHandler", "%s (XID: %u, XREQ: %u)", msg,
180  (UInt_t)err->resourceid, err->request_code);
181  int *kil = (int*)1;
182  delete kil;
183  return 0;
184  }
185 
186  if (!err->resourceid) return 0;
187 
188  TObject *w = (TObject *)gROOT->ProcessLineFast(Form("gClient ? gClient->GetWindowById(%lu) : 0",
189  (ULong_t)err->resourceid));
190 
191  if (!w) {
192  ::Error("RootX11ErrorHandler", "%s (XID: %u, XREQ: %u)", msg,
193  (UInt_t)err->resourceid, err->request_code);
194  } else {
195  ::Error("RootX11ErrorHandler", "%s (%s XID: %u, XREQ: %u)", msg, w->ClassName(),
196  (UInt_t)err->resourceid, err->request_code);
197  w->Print("tree");
198  }
199  if (TROOT::Initialized()) {
200  //Getlinem(kInit, "Root > ");
201  Throw(2);
202  }
203  return 0;
204 }
205 
206 ////////////////////////////////////////////////////////////////////////////////
207 /// Handle X11 I/O error (happens when connection to display server
208 /// is broken).
209 
210 static Int_t RootX11IOErrorHandler(Display *)
211 {
212  ::Error("RootX11IOErrorHandler", "fatal X11 error (connection to server lost?!)");
213  fprintf(stderr,"\n**** Save data and exit application ****\n\n");
214  // delete X connection handler (to avoid looping in TSystem::DispatchOneEvent())
215  if (gXDisplay && gSystem) {
216  gSystem->RemoveFileHandler(gXDisplay);
217  SafeDelete(gXDisplay);
218  }
219  if (TROOT::Initialized()) {
220  //Getlinem(kInit, "Root > ");
221  Throw(2);
222  }
223  return 0;
224 }
225 
226 
227 ////////////////////////////////////////////////////////////////////////////////
228 /// Map window on screen.
229 
230 void TGX11::MapWindow(Window_t id)
231 {
232  if (!id) return;
233 
234  XMapWindow((Display*)fDisplay, (Window) id);
235 }
236 
237 ////////////////////////////////////////////////////////////////////////////////
238 /// Map sub windows.
239 
240 void TGX11::MapSubwindows(Window_t id)
241 {
242  if (!id) return;
243 
244  XMapSubwindows((Display*)fDisplay, (Window) id);
245 }
246 
247 ////////////////////////////////////////////////////////////////////////////////
248 /// Map window on screen and put on top of all windows.
249 
250 void TGX11::MapRaised(Window_t id)
251 {
252  if (!id) return;
253 
254  XMapRaised((Display*)fDisplay, (Window) id);
255 }
256 
257 ////////////////////////////////////////////////////////////////////////////////
258 /// Unmap window from screen.
259 
260 void TGX11::UnmapWindow(Window_t id)
261 {
262  if (!id) return;
263 
264  XUnmapWindow((Display*)fDisplay, (Window) id);
265 }
266 
267 ////////////////////////////////////////////////////////////////////////////////
268 /// Destroy window.
269 
270 void TGX11::DestroyWindow(Window_t id)
271 {
272  if (!id) return;
273 
274  XDestroyWindow((Display*)fDisplay, (Window) id);
275 }
276 
277 ////////////////////////////////////////////////////////////////////////////////
278 /// Destroy subwindows of this window.
279 
280 void TGX11::DestroySubwindows(Window_t id)
281 {
282  if (!id) return;
283 
284  XDestroySubwindows((Display*)fDisplay, (Window) id);
285 }
286 
287 ////////////////////////////////////////////////////////////////////////////////
288 /// Put window on top of window stack.
289 
290 void TGX11::RaiseWindow(Window_t id)
291 {
292  if (!id) return;
293 
294  XRaiseWindow((Display*)fDisplay, (Window) id);
295 }
296 
297 ////////////////////////////////////////////////////////////////////////////////
298 /// Lower window so it lays below all its siblings.
299 
300 void TGX11::LowerWindow(Window_t id)
301 {
302  if (!id) return;
303 
304  XLowerWindow((Display*)fDisplay, (Window) id);
305 }
306 
307 ////////////////////////////////////////////////////////////////////////////////
308 /// Move a window.
309 
310 void TGX11::MoveWindow(Window_t id, Int_t x, Int_t y)
311 {
312  if (!id) return;
313 
314  XMoveWindow((Display*)fDisplay, (Window) id, x, y);
315 }
316 
317 ////////////////////////////////////////////////////////////////////////////////
318 /// Move and resize a window.
319 
320 void TGX11::MoveResizeWindow(Window_t id, Int_t x, Int_t y, UInt_t w, UInt_t h)
321 {
322  if (!id) return;
323 
324  XMoveResizeWindow((Display*)fDisplay, (Window) id, x, y, w, h);
325 }
326 
327 ////////////////////////////////////////////////////////////////////////////////
328 /// Resize the window.
329 
330 void TGX11::ResizeWindow(Window_t id, UInt_t w, UInt_t h)
331 {
332  if (!id) return;
333 
334  // protect against potential negative values
335  if (w >= (UInt_t)INT_MAX || h >= (UInt_t)INT_MAX)
336  return;
337  XResizeWindow((Display*)fDisplay, (Window) id, w, h);
338 }
339 
340 ////////////////////////////////////////////////////////////////////////////////
341 /// Iconify the window.
342 
343 void TGX11::IconifyWindow(Window_t id)
344 {
345  if (!id) return;
346 
347  XIconifyWindow((Display*)fDisplay, (Window) id, fScreenNumber);
348 }
349 
350 ////////////////////////////////////////////////////////////////////////////////
351 /// Reparent window to new parent window at position (x,y).
352 
353 void TGX11::ReparentWindow(Window_t id, Window_t pid, Int_t x, Int_t y)
354 {
355  if (!id) return;
356 
357  XReparentWindow((Display*)fDisplay, (Window) id, (Window) pid, x, y);
358 }
359 
360 ////////////////////////////////////////////////////////////////////////////////
361 /// Set the window background color.
362 
363 void TGX11::SetWindowBackground(Window_t id, ULong_t color)
364 {
365  if (!id) return;
366 
367  XSetWindowBackground((Display*)fDisplay, (Window) id, color);
368 }
369 
370 ////////////////////////////////////////////////////////////////////////////////
371 /// Set pixmap as window background.
372 
373 void TGX11::SetWindowBackgroundPixmap(Window_t id, Pixmap_t pxm)
374 {
375  if (!id) return;
376 
377  XSetWindowBackgroundPixmap((Display*)fDisplay, (Window) id, (Pixmap) pxm);
378 }
379 
380 ////////////////////////////////////////////////////////////////////////////////
381 /// Return handle to newly created X window.
382 
383 Window_t TGX11::CreateWindow(Window_t parent, Int_t x, Int_t y,
384  UInt_t w, UInt_t h, UInt_t border,
385  Int_t depth, UInt_t clss,
386  void *visual, SetWindowAttributes_t *attr, UInt_t)
387 {
388  RXSetWindowAttributes xattr;
389  ULong_t xmask = 0;
390 
391  if (attr)
392  MapSetWindowAttributes(attr, xmask, xattr);
393 
394  if (depth == 0)
395  depth = fDepth;
396  if (visual == 0)
397  visual = fVisual;
398  if (fColormap && !(xmask & CWColormap)) {
399  xmask |= CWColormap;
400  xattr.colormap = fColormap;
401  }
402  if ((Window)parent == fRootWin && fRootWin != fVisRootWin) {
403  xmask |= CWBorderPixel;
404  xattr.border_pixel = fBlackPixel;
405  }
406 
407  return (Window_t) XCreateWindow((Display*)fDisplay, (Window) parent, x, y,
408  w, h, border, depth, clss, (Visual*)visual,
409  xmask, &xattr);
410 }
411 
412 ////////////////////////////////////////////////////////////////////////////////
413 /// Map event mask to or from X.
414 
415 void TGX11::MapEventMask(UInt_t &emask, UInt_t &xemask, Bool_t tox)
416 {
417  if (tox) {
418  Long_t lxemask = NoEventMask;
419  if ((emask & kKeyPressMask))
420  lxemask |= KeyPressMask;
421  if ((emask & kKeyReleaseMask))
422  lxemask |= KeyReleaseMask;
423  if ((emask & kButtonPressMask))
424  lxemask |= ButtonPressMask;
425  if ((emask & kButtonReleaseMask))
426  lxemask |= ButtonReleaseMask;
427  if ((emask & kPointerMotionMask))
428  lxemask |= PointerMotionMask;
429  if ((emask & kButtonMotionMask))
430  lxemask |= ButtonMotionMask;
431  if ((emask & kExposureMask))
432  lxemask |= ExposureMask;
433  if ((emask & kStructureNotifyMask))
434  lxemask |= StructureNotifyMask;
435  if ((emask & kEnterWindowMask))
436  lxemask |= EnterWindowMask;
437  if ((emask & kLeaveWindowMask))
438  lxemask |= LeaveWindowMask;
439  if ((emask & kFocusChangeMask))
440  lxemask |= FocusChangeMask;
441  if ((emask & kOwnerGrabButtonMask))
442  lxemask |= OwnerGrabButtonMask;
443  if ((emask & kColormapChangeMask))
444  lxemask |= ColormapChangeMask;
445  xemask = (UInt_t)lxemask;
446  } else {
447  emask = 0;
448  if ((xemask & KeyPressMask))
449  emask |= kKeyPressMask;
450  if ((xemask & KeyReleaseMask))
451  emask |= kKeyReleaseMask;
452  if ((xemask & ButtonPressMask))
453  emask |= kButtonPressMask;
454  if ((xemask & ButtonReleaseMask))
455  emask |= kButtonReleaseMask;
456  if ((xemask & PointerMotionMask))
457  emask |= kPointerMotionMask;
458  if ((xemask & ButtonMotionMask))
459  emask |= kButtonMotionMask;
460  if ((xemask & ExposureMask))
461  emask |= kExposureMask;
462  if ((xemask & StructureNotifyMask))
463  emask |= kStructureNotifyMask;
464  if ((xemask & EnterWindowMask))
465  emask |= kEnterWindowMask;
466  if ((xemask & LeaveWindowMask))
467  emask |= kLeaveWindowMask;
468  if ((xemask & FocusChangeMask))
469  emask |= kFocusChangeMask;
470  if ((xemask & OwnerGrabButtonMask))
471  emask |= kOwnerGrabButtonMask;
472  if ((xemask & ColormapChangeMask))
473  emask |= kColormapChangeMask;
474  }
475 }
476 
477 ////////////////////////////////////////////////////////////////////////////////
478 /// Map a SetWindowAttributes_t to a XSetWindowAttributes structure.
479 
480 void TGX11::MapSetWindowAttributes(SetWindowAttributes_t *attr,
481  ULong_t &xmask, RXSetWindowAttributes &xattr)
482 {
483  Mask_t mask = attr->fMask;
484  xmask = 0;
485 
486  if ((mask & kWABackPixmap)) {
487  xmask |= CWBackPixmap;
488  if (attr->fBackgroundPixmap == kNone)
489  xattr.background_pixmap = None;
490  else if (attr->fBackgroundPixmap == kParentRelative)
491  xattr.background_pixmap = ParentRelative;
492  else
493  xattr.background_pixmap = (Pixmap)attr->fBackgroundPixmap;
494  }
495  if ((mask & kWABackPixel)) {
496  xmask |= CWBackPixel;
497  xattr.background_pixel = attr->fBackgroundPixel;
498  }
499  if ((mask & kWABorderPixmap)) {
500  xmask |= CWBorderPixmap;
501  xattr.border_pixmap = (Pixmap)attr->fBorderPixmap;
502  }
503  if ((mask & kWABorderPixel)) {
504  xmask |= CWBorderPixel;
505  xattr.border_pixel = attr->fBorderPixel;
506  }
507  if ((mask & kWABitGravity)) {
508  xmask |= CWBitGravity;
509  xattr.bit_gravity = attr->fBitGravity; //assume ident mapping (rdm)
510  }
511  if ((mask & kWAWinGravity)) {
512  xmask |= CWWinGravity;
513  xattr.win_gravity = attr->fWinGravity; // assume ident mapping (rdm)
514  }
515  if ((mask & kWABackingStore)) {
516  xmask |= CWBackingStore;
517  if (attr->fBackingStore == kNotUseful)
518  xattr.backing_store = NotUseful;
519  else if (attr->fBackingStore == kWhenMapped)
520  xattr.backing_store = WhenMapped;
521  else if (attr->fBackingStore == kAlways)
522  xattr.backing_store = Always;
523  else
524  xattr.backing_store = attr->fBackingStore;
525  }
526  if ((mask & kWABackingPlanes)) {
527  xmask |= CWBackingPlanes;
528  xattr.backing_planes = attr->fBackingPlanes;
529  }
530  if ((mask & kWABackingPixel)) {
531  xmask |= CWBackingPixel;
532  xattr.backing_pixel = attr->fBackingPixel;
533  }
534  if ((mask & kWAOverrideRedirect)) {
535  xmask |= CWOverrideRedirect;
536  xattr.override_redirect = attr->fOverrideRedirect;
537  }
538  if ((mask & kWASaveUnder)) {
539  xmask |= CWSaveUnder;
540  xattr.save_under = (Bool)attr->fSaveUnder;
541  }
542  if ((mask & kWAEventMask)) {
543  xmask |= CWEventMask;
544  UInt_t xmsk, msk = (UInt_t) attr->fEventMask;
545  MapEventMask(msk, xmsk, kTRUE);
546  xattr.event_mask = xmsk;
547  }
548  if ((mask & kWADontPropagate)) {
549  xmask |= CWDontPropagate;
550  xattr.do_not_propagate_mask = attr->fDoNotPropagateMask;
551  }
552  if ((mask & kWAColormap)) {
553  xmask |= CWColormap;
554  xattr.colormap = (Colormap)attr->fColormap;
555  }
556  if ((mask & kWACursor)) {
557  xmask |= CWCursor;
558  if (attr->fCursor == kNone)
559  xattr.cursor = None;
560  else
561  xattr.cursor = (Cursor)attr->fCursor;
562  }
563 }
564 
565 ////////////////////////////////////////////////////////////////////////////////
566 /// Map a GCValues_t to a XCGValues structure if tox is true. Map
567 /// the other way in case tox is false.
568 
569 void TGX11::MapGCValues(GCValues_t &gval,
570  ULong_t &xmask, RXGCValues &xgval, Bool_t tox)
571 {
572  if (tox) {
573  // map GCValues_t to XGCValues
574  Mask_t mask = gval.fMask;
575  xmask = 0;
576 
577  if ((mask & kGCFunction)) {
578  xmask |= GCFunction;
579  xgval.function = gval.fFunction; // ident mapping
580  }
581  if ((mask & kGCPlaneMask)) {
582  xmask |= GCPlaneMask;
583  xgval.plane_mask = gval.fPlaneMask;
584  }
585  if ((mask & kGCForeground)) {
586  xmask |= GCForeground;
587  xgval.foreground = gval.fForeground;
588  }
589  if ((mask & kGCBackground)) {
590  xmask |= GCBackground;
591  xgval.background = gval.fBackground;
592  }
593  if ((mask & kGCLineWidth)) {
594  xmask |= GCLineWidth;
595  xgval.line_width = gval.fLineWidth;
596  }
597  if ((mask & kGCLineStyle)) {
598  xmask |= GCLineStyle;
599  xgval.line_style = gval.fLineStyle; // ident mapping
600  }
601  if ((mask & kGCCapStyle)) {
602  xmask |= GCCapStyle;
603  xgval.cap_style = gval.fCapStyle; // ident mapping
604  }
605  if ((mask & kGCJoinStyle)) {
606  xmask |= GCJoinStyle;
607  xgval.join_style = gval.fJoinStyle; // ident mapping
608  }
609  if ((mask & kGCFillStyle)) {
610  xmask |= GCFillStyle;
611  xgval.fill_style = gval.fFillStyle; // ident mapping
612  }
613  if ((mask & kGCFillRule)) {
614  xmask |= GCFillRule;
615  xgval.fill_rule = gval.fFillRule; // ident mapping
616  }
617  if ((mask & kGCTile)) {
618  xmask |= GCTile;
619  xgval.tile = (Pixmap) gval.fTile;
620  }
621  if ((mask & kGCStipple)) {
622  xmask |= GCStipple;
623  xgval.stipple = (Pixmap) gval.fStipple;
624  }
625  if ((mask & kGCTileStipXOrigin)) {
626  xmask |= GCTileStipXOrigin;
627  xgval.ts_x_origin = gval.fTsXOrigin;
628  }
629  if ((mask & kGCTileStipYOrigin)) {
630  xmask |= GCTileStipYOrigin;
631  xgval.ts_y_origin = gval.fTsYOrigin;
632  }
633  if ((mask & kGCFont)) {
634  if (!fHasXft) {
635  xmask |= GCFont;
636  xgval.font = (Font) gval.fFont;
637  }
638  }
639  if ((mask & kGCSubwindowMode)) {
640  xmask |= GCSubwindowMode;
641  xgval.subwindow_mode = gval.fSubwindowMode; // ident mapping
642  }
643  if ((mask & kGCGraphicsExposures)) {
644  xmask |= GCGraphicsExposures;
645  xgval.graphics_exposures = (Bool) gval.fGraphicsExposures;
646  }
647  if ((mask & kGCClipXOrigin)) {
648  xmask |= GCClipXOrigin;
649  xgval.clip_x_origin = gval.fClipXOrigin;
650  }
651  if ((mask & kGCClipYOrigin)) {
652  xmask |= GCClipYOrigin;
653  xgval.clip_y_origin = gval.fClipYOrigin;
654  }
655  if ((mask & kGCClipMask)) {
656  xmask |= GCClipMask;
657  xgval.clip_mask = (Pixmap) gval.fClipMask;
658  }
659  if ((mask & kGCDashOffset)) {
660  xmask |= GCDashOffset;
661  xgval.dash_offset = gval.fDashOffset;
662  }
663  if ((mask & kGCDashList)) {
664  xmask |= GCDashList;
665  xgval.dashes = gval.fDashes[0];
666  }
667  if ((mask & kGCArcMode)) {
668  xmask |= GCArcMode;
669  xgval.arc_mode = gval.fArcMode; // ident mapping
670  }
671 
672  } else {
673  // map XValues to GCValues_t
674  Mask_t mask = 0;
675 
676  if ((xmask & GCFunction)) {
677  mask |= kGCFunction;
678  gval.fFunction = (EGraphicsFunction) xgval.function; // ident mapping
679  }
680  if ((xmask & GCPlaneMask)) {
681  mask |= kGCPlaneMask;
682  gval.fPlaneMask = xgval.plane_mask;
683  }
684  if ((xmask & GCForeground)) {
685  mask |= kGCForeground;
686  gval.fForeground = xgval.foreground;
687  }
688  if ((xmask & GCBackground)) {
689  mask |= kGCBackground;
690  gval.fBackground = xgval.background;
691  }
692  if ((xmask & GCLineWidth)) {
693  mask |= kGCLineWidth;
694  gval.fLineWidth = xgval.line_width;
695  }
696  if ((xmask & GCLineStyle)) {
697  mask |= kGCLineStyle;
698  gval.fLineStyle = xgval.line_style; // ident mapping
699  }
700  if ((xmask & GCCapStyle)) {
701  mask |= kGCCapStyle;
702  gval.fCapStyle = xgval.cap_style; // ident mapping
703  }
704  if ((xmask & GCJoinStyle)) {
705  mask |= kGCJoinStyle;
706  gval.fJoinStyle = xgval.join_style; // ident mapping
707  }
708  if ((xmask & GCFillStyle)) {
709  mask |= kGCFillStyle;
710  gval.fFillStyle = xgval.fill_style; // ident mapping
711  }
712  if ((xmask & GCFillRule)) {
713  mask |= kGCFillRule;
714  gval.fFillRule = xgval.fill_rule; // ident mapping
715  }
716  if ((xmask & GCTile)) {
717  mask |= kGCTile;
718  gval.fTile = (Pixmap_t) xgval.tile;
719  }
720  if ((xmask & GCStipple)) {
721  mask |= kGCStipple;
722  gval.fStipple = (Pixmap_t) xgval.stipple;
723  }
724  if ((xmask & GCTileStipXOrigin)) {
725  mask |= kGCTileStipXOrigin;
726  gval.fTsXOrigin = xgval.ts_x_origin;
727  }
728  if ((xmask & GCTileStipYOrigin)) {
729  mask |= kGCTileStipYOrigin;
730  gval.fTsYOrigin = xgval.ts_y_origin;
731  }
732  if ((xmask & GCFont)) {
733  mask |= kGCFont;
734  gval.fFont = (FontH_t) xgval.font;
735  }
736  if ((xmask & GCSubwindowMode)) {
737  mask |= kGCSubwindowMode;
738  gval.fSubwindowMode = xgval.subwindow_mode; // ident mapping
739  }
740  if ((xmask & GCGraphicsExposures)) {
741  mask |= kGCGraphicsExposures;
742  gval.fGraphicsExposures = (Bool_t) xgval.graphics_exposures;
743  }
744  if ((xmask & GCClipXOrigin)) {
745  mask |= kGCClipXOrigin;
746  gval.fClipXOrigin = xgval.clip_x_origin;
747  }
748  if ((xmask & GCClipYOrigin)) {
749  mask |= kGCClipYOrigin;
750  gval.fClipYOrigin = xgval.clip_y_origin;
751  }
752  if ((xmask & GCClipMask)) {
753  mask |= kGCClipMask;
754  gval.fClipMask = (Pixmap_t) xgval.clip_mask;
755  }
756  if ((xmask & GCDashOffset)) {
757  mask |= kGCDashOffset;
758  gval.fDashOffset = xgval.dash_offset;
759  }
760  if ((xmask & GCDashList)) {
761  mask |= kGCDashList;
762  gval.fDashes[0] = xgval.dashes;
763  gval.fDashLen = 1;
764  }
765  if ((xmask & GCArcMode)) {
766  mask |= kGCArcMode;
767  gval.fArcMode = xgval.arc_mode; // ident mapping
768  }
769  gval.fMask = mask;
770  }
771 }
772 
773 ////////////////////////////////////////////////////////////////////////////////
774 /// Get window attributes and return filled in attributes structure.
775 
776 void TGX11::GetWindowAttributes(Window_t id, WindowAttributes_t &attr)
777 {
778  if (!id) return;
779 
780  XWindowAttributes xattr;
781 
782  XGetWindowAttributes((Display*)fDisplay, id, &xattr);
783 
784  attr.fX = xattr.x;
785  attr.fY = xattr.y;
786  attr.fWidth = xattr.width;
787  attr.fHeight = xattr.height;
788  attr.fBorderWidth = xattr.border_width;
789  attr.fDepth = xattr.depth;
790  attr.fVisual = xattr.visual;
791  attr.fRoot = (Window_t) xattr.root;
792  if (xattr.c_class == InputOutput) attr.fClass = kInputOutput;
793  if (xattr.c_class == InputOnly) attr.fClass = kInputOnly;
794  attr.fBitGravity = xattr.bit_gravity; // assume ident mapping (rdm)
795  attr.fWinGravity = xattr.win_gravity; // assume ident mapping (rdm)
796  if (xattr.backing_store == NotUseful) attr.fBackingStore = kNotUseful;
797  if (xattr.backing_store == WhenMapped) attr.fBackingStore = kWhenMapped;
798  if (xattr.backing_store == Always) attr.fBackingStore = kAlways;
799  attr.fBackingPlanes = xattr.backing_planes;
800  attr.fBackingPixel = xattr.backing_pixel;
801  attr.fSaveUnder = (Bool_t) xattr.save_under;
802  if ((Window) id == fRootWin)
803  attr.fColormap = (Colormap_t) fColormap;
804  else
805  attr.fColormap = (Colormap_t) xattr.colormap;
806  attr.fMapInstalled = (Bool_t) xattr.map_installed;
807  attr.fMapState = xattr.map_state; // ident mapping
808  attr.fAllEventMasks = xattr.all_event_masks; // not ident, but not used by GUI classes
809  attr.fYourEventMask = xattr.your_event_mask; // not ident, but not used by GUI classes
810  attr.fDoNotPropagateMask = xattr.do_not_propagate_mask;
811  attr.fOverrideRedirect = (Bool_t) xattr.override_redirect;
812  attr.fScreen = xattr.screen;
813 }
814 
815 ////////////////////////////////////////////////////////////////////////////////
816 /// Open connection to display server (if such a thing exist on the
817 /// current platform). On X11 this method returns on success the X
818 /// display socket descriptor (> 0), 0 in case of batch mode and < 0
819 /// in case of failure (cannot connect to display dpyName). It also
820 /// initializes the TGX11 class via Init(). Called from TGClient ctor.
821 
822 Int_t TGX11::OpenDisplay(const char *dpyName)
823 {
824 #ifdef _REENTRANT
825  // In some cases there can be problems due to XInitThreads, like when
826  // using Qt, so we allow for it to be turned off
827  if (gEnv->GetValue("X11.XInitThread", 1)) {
828  // Must be very first call before any X11 call !!
829  if (!XInitThreads())
830  Warning("OpenDisplay", "system has no X11 thread support");
831  }
832 #endif
833 
834  Display *dpy;
835  if (!(dpy = XOpenDisplay(dpyName)))
836  return -1;
837 
838  // Set custom X11 error handlers
839  XSetErrorHandler(RootX11ErrorHandler);
840  XSetIOErrorHandler(RootX11IOErrorHandler);
841 
842  if (gEnv->GetValue("X11.Sync", 0))
843  XSynchronize(dpy, 1);
844 
845  // Init the GX11 class, sets a.o. fDisplay.
846  if (!Init(dpy))
847  return -1;
848 
849  return ConnectionNumber(dpy);
850 }
851 
852 ////////////////////////////////////////////////////////////////////////////////
853 /// Close connection to display server.
854 
855 void TGX11::CloseDisplay()
856 {
857  XCloseDisplay((Display*)fDisplay);
858  fDisplay = 0;
859 }
860 
861 ////////////////////////////////////////////////////////////////////////////////
862 /// Returns handle to display (might be useful in some cases where
863 /// direct X11 manipulation outside of TVirtualX is needed, e.g. GL
864 /// interface).
865 
866 Display_t TGX11::GetDisplay() const
867 {
868  return (Display_t) fDisplay;
869 }
870 
871 ////////////////////////////////////////////////////////////////////////////////
872 /// Returns handle to visual (might be useful in some cases where
873 /// direct X11 manipulation outside of TVirtualX is needed, e.g. GL
874 /// interface).
875 
876 Visual_t TGX11::GetVisual() const
877 {
878  return (Visual_t) fVisual;
879 }
880 
881 ////////////////////////////////////////////////////////////////////////////////
882 /// Returns handle to colormap (might be useful in some cases where
883 /// direct X11 manipulation outside of TVirtualX is needed, e.g. GL
884 /// interface).
885 
886 Colormap_t TGX11::GetColormap() const
887 {
888  return (Colormap_t) fColormap;
889 }
890 
891 ////////////////////////////////////////////////////////////////////////////////
892 /// Returns screen number (might be useful in some cases where
893 /// direct X11 manipulation outside of TVirtualX is needed, e.g. GL
894 /// interface).
895 
896 Int_t TGX11::GetScreen() const
897 {
898  return fScreenNumber;
899 }
900 
901 ////////////////////////////////////////////////////////////////////////////////
902 /// Returns depth of screen (number of bit planes). Equivalent to
903 /// GetPlanes().
904 
905 Int_t TGX11::GetDepth() const
906 {
907  return fDepth;
908 }
909 
910 ////////////////////////////////////////////////////////////////////////////////
911 /// Return atom handle for atom_name. If it does not exist
912 /// create it if only_if_exist is false. Atoms are used to communicate
913 /// between different programs (i.e. window manager) via the X server.
914 
915 Atom_t TGX11::InternAtom(const char *atom_name, Bool_t only_if_exist)
916 {
917  Atom a = XInternAtom((Display*)fDisplay, (char *)atom_name, (Bool)only_if_exist);
918 
919  if (a == None) return kNone;
920  return (Atom_t) a;
921 }
922 
923 ////////////////////////////////////////////////////////////////////////////////
924 /// Return handle to the default root window created when calling
925 /// XOpenDisplay().
926 
927 Window_t TGX11::GetDefaultRootWindow() const
928 {
929  return (Window_t) fRootWin;
930 }
931 
932 ////////////////////////////////////////////////////////////////////////////////
933 /// Return the parent of the window.
934 
935 Window_t TGX11::GetParent(Window_t id) const
936 {
937  if (!id) return (Window_t)0;
938 
939  Window root, parent;
940  Window *children = 0;
941  UInt_t nchildren;
942 
943  XQueryTree((Display*)fDisplay, (Window) id, &root, &parent, &children, &nchildren);
944 
945  if (children) XFree(children);
946 
947  return (Window_t) parent;
948 }
949 
950 
951 ////////////////////////////////////////////////////////////////////////////////
952 /// Load font and query font. If font is not found 0 is returned,
953 /// otherwise an opaque pointer to the FontStruct_t.
954 /// Free the loaded font using DeleteFont().
955 
956 FontStruct_t TGX11::LoadQueryFont(const char *font_name)
957 {
958  XFontStruct *fs = XLoadQueryFont((Display*)fDisplay, (char *)font_name);
959  return (FontStruct_t) fs;
960 }
961 
962 ////////////////////////////////////////////////////////////////////////////////
963 /// Return handle to font described by font structure.
964 
965 FontH_t TGX11::GetFontHandle(FontStruct_t fs)
966 {
967  if (fs) {
968  XFontStruct *fss = (XFontStruct *)fs;
969  return fss->fid;
970  }
971  return 0;
972 }
973 
974 ////////////////////////////////////////////////////////////////////////////////
975 /// Explicitly delete font structure obtained with LoadQueryFont().
976 
977 void TGX11::DeleteFont(FontStruct_t fs)
978 {
979  if (fDisplay) XFreeFont((Display*)fDisplay, (XFontStruct *) fs);
980 }
981 
982 ////////////////////////////////////////////////////////////////////////////////
983 /// Create a graphics context using the values set in gval (but only for
984 /// those entries that are in the mask).
985 
986 GContext_t TGX11::CreateGC(Drawable_t id, GCValues_t *gval)
987 {
988  RXGCValues xgval;
989  ULong_t xmask = 0;
990 
991  if (gval)
992  MapGCValues(*gval, xmask, xgval);
993 
994  if (!id || ((Drawable) id == fRootWin))
995  id = (Drawable_t) fVisRootWin;
996 
997  GC gc = XCreateGC((Display*)fDisplay, (Drawable) id, xmask, &xgval);
998 
999  if (gval && (gval->fMask & kGCFont))
1000  MapGCFont((GContext_t)gc, gval->fFont);
1001 
1002  return (GContext_t) gc;
1003 }
1004 
1005 ////////////////////////////////////////////////////////////////////////////////
1006 /// Change entries in an existing graphics context, gc, by values from gval.
1007 
1008 void TGX11::ChangeGC(GContext_t gc, GCValues_t *gval)
1009 {
1010  RXGCValues xgval;
1011  ULong_t xmask = 0;
1012 
1013  if (gval)
1014  MapGCValues(*gval, xmask, xgval);
1015 
1016  XChangeGC((Display*)fDisplay, (GC) gc, xmask, &xgval);
1017 
1018  if (gval && (gval->fMask & kGCFont))
1019  MapGCFont((GContext_t)gc, gval->fFont);
1020 }
1021 
1022 ////////////////////////////////////////////////////////////////////////////////
1023 /// Copies graphics context from org to dest. Only the values specified
1024 /// in mask are copied. If mask = 0 then copy all fields. Both org and
1025 /// dest must exist.
1026 
1027 void TGX11::CopyGC(GContext_t org, GContext_t dest, Mask_t mask)
1028 {
1029  GCValues_t gval;
1030  RXGCValues xgval;
1031  ULong_t xmask;
1032 
1033  if (!mask) {
1034  // in this case copy all fields
1035  mask = kMaxUInt;
1036  }
1037 
1038  gval.fMask = mask; // only set fMask used to convert to xmask
1039  MapGCValues(gval, xmask, xgval);
1040 
1041  XCopyGC((Display*)fDisplay, (GC) org, xmask, (GC) dest);
1042 }
1043 
1044 ////////////////////////////////////////////////////////////////////////////////
1045 /// Explicitly delete a graphics context.
1046 
1047 void TGX11::DeleteGC(GContext_t gc)
1048 {
1049  // Protection against deletion of global TGGC objects, which are
1050  // destructed after fDisplay has been closed.
1051  if (fDisplay)
1052  XFreeGC((Display*)fDisplay, (GC) gc);
1053 }
1054 
1055 ////////////////////////////////////////////////////////////////////////////////
1056 /// Create cursor handle (just return cursor from cursor pool fCursors).
1057 
1058 Cursor_t TGX11::CreateCursor(ECursor cursor)
1059 {
1060  return (Cursor_t) fCursors[cursor];
1061 }
1062 
1063 ////////////////////////////////////////////////////////////////////////////////
1064 /// Set the specified cursor.
1065 
1066 void TGX11::SetCursor(Window_t id, Cursor_t curid)
1067 {
1068  if (!id) return;
1069 
1070  XDefineCursor((Display*)fDisplay, (Window) id, (Cursor) curid);
1071 }
1072 
1073 ////////////////////////////////////////////////////////////////////////////////
1074 /// Creates a pixmap of the width and height you specified
1075 /// and returns a pixmap ID that identifies it.
1076 
1077 Pixmap_t TGX11::CreatePixmap(Drawable_t id, UInt_t w, UInt_t h)
1078 {
1079  return (Pixmap_t) XCreatePixmap((Display*)fDisplay, (Drawable) (id ? id : fRootWin), w, h, fDepth);
1080 }
1081 
1082 ////////////////////////////////////////////////////////////////////////////////
1083 /// Create a pixmap from bitmap data. Ones will get foreground color and
1084 /// zeroes background color.
1085 
1086 Pixmap_t TGX11::CreatePixmap(Drawable_t id, const char *bitmap,
1087  UInt_t width, UInt_t height, ULong_t forecolor, ULong_t backcolor,
1088  Int_t depth)
1089 {
1090  return (Pixmap_t) XCreatePixmapFromBitmapData((Display*)fDisplay, (id ? id : fRootWin), (char *)bitmap,
1091  width, height, forecolor, backcolor, depth);
1092 }
1093 
1094 ////////////////////////////////////////////////////////////////////////////////
1095 /// Create a bitmap (i.e. pixmap with depth 1) from the bitmap data.
1096 
1097 Pixmap_t TGX11::CreateBitmap(Drawable_t id, const char *bitmap,
1098  UInt_t width, UInt_t height)
1099 {
1100  return (Pixmap_t) XCreateBitmapFromData((Display*)fDisplay, (id ? id : fRootWin), (char *)bitmap,
1101  width, height);
1102 }
1103 
1104 ////////////////////////////////////////////////////////////////////////////////
1105 /// Explicitly delete pixmap resource.
1106 
1107 void TGX11::DeletePixmap(Pixmap_t pmap)
1108 {
1109  if (fDisplay) XFreePixmap((Display*)fDisplay, (Pixmap) pmap);
1110 }
1111 
1112 ////////////////////////////////////////////////////////////////////////////////
1113 /// Map a PictureAttributes_t to a XpmAttributes structure. If toxpm is
1114 /// kTRUE map from attr to xpmattr, else map the other way.
1115 
1116 void TGX11::MapPictureAttributes(PictureAttributes_t &attr, RXpmAttributes &xpmattr,
1117  Bool_t toxpm)
1118 {
1119 #ifdef XpmVersion
1120  if (toxpm) {
1121  Mask_t mask = attr.fMask;
1122  ULong_t xmask = 0;
1123 
1124  if ((mask & kPAColormap)) {
1125  xmask |= XpmColormap;
1126  xpmattr.colormap = (Colormap)attr.fColormap;
1127  }
1128  if ((mask & kPADepth)) {
1129  xmask |= XpmDepth;
1130  xpmattr.depth = attr.fDepth;
1131  }
1132  if ((mask & kPASize)) {
1133  xmask |= XpmSize;
1134  xpmattr.width = attr.fWidth;
1135  xpmattr.height = attr.fHeight;
1136  }
1137  if ((mask & kPAHotspot)) {
1138  xmask |= XpmHotspot;
1139  xpmattr.x_hotspot = attr.fXHotspot;
1140  xpmattr.y_hotspot = attr.fYHotspot;
1141  }
1142  if ((mask & kPAReturnPixels)) {
1143  xmask |= XpmReturnPixels;
1144  xpmattr.pixels = 0; // output parameters
1145  xpmattr.npixels = 0;
1146  }
1147  if ((mask & kPACloseness)) {
1148  xmask |= XpmCloseness;
1149  xpmattr.closeness = attr.fCloseness;
1150  }
1151  xpmattr.valuemask = xmask;
1152  } else {
1153  ULong_t xmask = xpmattr.valuemask;
1154  Mask_t mask = 0;
1155 
1156  attr.fPixels = 0;
1157  attr.fNpixels = 0;
1158 
1159  if ((xmask & XpmColormap)) {
1160  mask |= kPAColormap;
1161  attr.fColormap = (Colormap_t)xpmattr.colormap;
1162  mask |= kPADepth;
1163  attr.fDepth = xpmattr.depth;
1164  }
1165  if ((xmask & XpmSize)) {
1166  mask |= kPASize;
1167  attr.fWidth = xpmattr.width;
1168  attr.fHeight = xpmattr.height;
1169  }
1170  if ((xmask & XpmHotspot)) {
1171  mask |= kPAHotspot;
1172  attr.fXHotspot = xpmattr.x_hotspot;
1173  attr.fYHotspot = xpmattr.y_hotspot;
1174  }
1175  if ((xmask & XpmReturnPixels)) {
1176  mask |= kPAReturnPixels;
1177  if (xpmattr.npixels) {
1178  attr.fPixels = new ULong_t[xpmattr.npixels];
1179  for (UInt_t i = 0; i < xpmattr.npixels; i++)
1180  attr.fPixels[i] = xpmattr.pixels[i];
1181  attr.fNpixels = xpmattr.npixels;
1182  }
1183  }
1184  if ((xmask & XpmCloseness)) {
1185  mask |= kPACloseness;
1186  attr.fCloseness = xpmattr.closeness;
1187  }
1188  attr.fMask = mask;
1189  }
1190 #endif
1191 }
1192 
1193 ////////////////////////////////////////////////////////////////////////////////
1194 /// Create a picture pixmap from data on file. The picture attributes
1195 /// are used for input and output. Returns kTRUE in case of success,
1196 /// kFALSE otherwise. If mask does not exist it is set to kNone.
1197 
1198 Bool_t TGX11::CreatePictureFromFile(Drawable_t id, const char *filename,
1199  Pixmap_t &pict, Pixmap_t &pict_mask,
1200  PictureAttributes_t &attr)
1201 {
1202  if (strstr(filename, ".gif") || strstr(filename, ".GIF")) {
1203  pict = ReadGIF(0, 0, filename, id);
1204  pict_mask = kNone;
1205  attr.fDepth = fDepth;
1206  Int_t dummy;
1207  GetWindowSize(pict, dummy, dummy, attr.fWidth, attr.fHeight);
1208  return kTRUE;
1209  }
1210 
1211 #ifdef XpmVersion
1212  RXpmAttributes xpmattr;
1213 
1214  MapPictureAttributes(attr, xpmattr);
1215 
1216  // make sure pixel depth of pixmap is the same as in the visual
1217  if ((Drawable) id == fRootWin && fRootWin != fVisRootWin) {
1218  xpmattr.valuemask |= XpmDepth;
1219  xpmattr.depth = fDepth;
1220  }
1221 
1222  Int_t res = XpmReadFileToPixmap((Display*)fDisplay, (id ? id : fRootWin), (char*)filename,
1223  (Pixmap*)&pict, (Pixmap*)&pict_mask, &xpmattr);
1224 
1225  MapPictureAttributes(attr, xpmattr, kFALSE);
1226  XpmFreeAttributes(&xpmattr);
1227 
1228  if (res == XpmSuccess || res == XpmColorError)
1229  return kTRUE;
1230 
1231  if (pict) {
1232  XFreePixmap((Display*)fDisplay, (Pixmap)pict);
1233  pict = kNone;
1234  }
1235  if (pict_mask) {
1236  XFreePixmap((Display*)fDisplay, (Pixmap)pict_mask);
1237  pict_mask = kNone;
1238  }
1239 #else
1240  Error("CreatePictureFromFile", "cannot get picture, not compiled with Xpm");
1241 #endif
1242 
1243  return kFALSE;
1244 }
1245 
1246 ////////////////////////////////////////////////////////////////////////////////
1247 /// Create a picture pixmap from data. The picture attributes
1248 /// are used for input and output. Returns kTRUE in case of success,
1249 /// kFALSE otherwise. If mask does not exist it is set to kNone.
1250 
1251 Bool_t TGX11::CreatePictureFromData(Drawable_t id, char **data, Pixmap_t &pict,
1252  Pixmap_t &pict_mask, PictureAttributes_t &attr)
1253 {
1254 #ifdef XpmVersion
1255  RXpmAttributes xpmattr;
1256 
1257  MapPictureAttributes(attr, xpmattr);
1258 
1259  // make sure pixel depth of pixmap is the same as in the visual
1260  if ((Drawable) id == fRootWin && fRootWin != fVisRootWin) {
1261  xpmattr.valuemask |= XpmDepth;
1262  xpmattr.depth = fDepth;
1263  }
1264 
1265  Int_t res = XpmCreatePixmapFromData((Display*)fDisplay, (id ? id : fRootWin), data, (Pixmap*)&pict,
1266  (Pixmap*)&pict_mask, &xpmattr);
1267 
1268  MapPictureAttributes(attr, xpmattr, kFALSE);
1269  XpmFreeAttributes(&xpmattr);
1270 
1271  if (res == XpmSuccess || res == XpmColorError)
1272  return kTRUE;
1273 
1274  if (pict) {
1275  XFreePixmap((Display*)fDisplay, (Pixmap)pict);
1276  pict = kNone;
1277  }
1278  if (pict_mask) {
1279  XFreePixmap((Display*)fDisplay, (Pixmap)pict_mask);
1280  pict_mask = kNone;
1281  }
1282 #else
1283  Error("CreatePictureFromData", "cannot get picture, not compiled with Xpm");
1284 #endif
1285 
1286  return kFALSE;
1287 }
1288 
1289 ////////////////////////////////////////////////////////////////////////////////
1290 /// Read picture data from file and store in ret_data. Returns kTRUE in
1291 /// case of success, kFALSE otherwise.
1292 
1293 Bool_t TGX11::ReadPictureDataFromFile(const char *filename, char ***ret_data)
1294 {
1295 #ifdef XpmVersion
1296  if (XpmReadFileToData((char*)filename, ret_data) == XpmSuccess)
1297  return kTRUE;
1298 #else
1299  Error("ReadPictureFromDataFile", "cannot get picture, not compiled with Xpm");
1300 #endif
1301  return kFALSE;
1302 }
1303 
1304 ////////////////////////////////////////////////////////////////////////////////
1305 /// Delete picture data created by the function ReadPictureDataFromFile.
1306 
1307 void TGX11::DeletePictureData(void *data)
1308 {
1309 #ifdef XpmVersion
1310  // some older libXpm's don't have this function and it is typically
1311  // implemented with a simple free()
1312  // XpmFree(data);
1313  free(data);
1314 #endif
1315 }
1316 
1317 ////////////////////////////////////////////////////////////////////////////////
1318 /// Specify a dash pattern. Offset defines the phase of the pattern.
1319 /// Each element in the dash_list array specifies the length (in pixels)
1320 /// of a segment of the pattern. N defines the length of the list.
1321 
1322 void TGX11::SetDashes(GContext_t gc, Int_t offset, const char *dash_list, Int_t n)
1323 {
1324  XSetDashes((Display*)fDisplay, (GC) gc, offset, (char *)dash_list, n);
1325 }
1326 
1327 ////////////////////////////////////////////////////////////////////////////////
1328 /// Map a ColorStruct_t to a XColor structure.
1329 
1330 void TGX11::MapColorStruct(ColorStruct_t *color, RXColor &xcolor)
1331 {
1332  xcolor.pixel = color->fPixel;
1333  xcolor.red = color->fRed;
1334  xcolor.green = color->fGreen;
1335  xcolor.blue = color->fBlue;
1336  xcolor.flags = color->fMask; //ident mapping
1337 }
1338 
1339 ////////////////////////////////////////////////////////////////////////////////
1340 /// Parse string cname containing color name, like "green" or "#00FF00".
1341 /// It returns a filled in ColorStruct_t. Returns kFALSE in case parsing
1342 /// failed, kTRUE in case of success. On success, the ColorStruct_t
1343 /// fRed, fGreen and fBlue fields are all filled in and the mask is set
1344 /// for all three colors, but fPixel is not set.
1345 
1346 Bool_t TGX11::ParseColor(Colormap_t cmap, const char *cname, ColorStruct_t &color)
1347 {
1348  XColor xc;
1349 
1350  if (XParseColor((Display*)fDisplay, (Colormap)cmap, (char *)cname, &xc)) {
1351  color.fPixel = 0;
1352  color.fRed = xc.red;
1353  color.fGreen = xc.green;
1354  color.fBlue = xc.blue;
1355  color.fMask = kDoRed | kDoGreen | kDoBlue;
1356  return kTRUE;
1357  }
1358  return kFALSE;
1359 }
1360 
1361 ////////////////////////////////////////////////////////////////////////////////
1362 /// Find and allocate a color cell according to the color values specified
1363 /// in the ColorStruct_t. If no cell could be allocated it returns kFALSE,
1364 /// otherwise kTRUE.
1365 
1366 Bool_t TGX11::AllocColor(Colormap_t cmap, ColorStruct_t &color)
1367 {
1368  RXColor xc;
1369 
1370  MapColorStruct(&color, xc);
1371 
1372  color.fPixel = 0;
1373  if (AllocColor((Colormap)cmap, &xc)) {
1374  color.fPixel = xc.pixel;
1375  return kTRUE;
1376  }
1377 
1378  return kFALSE;
1379 }
1380 
1381 ////////////////////////////////////////////////////////////////////////////////
1382 /// Fill in the primary color components for a specific pixel value.
1383 /// On input fPixel should be set on return the fRed, fGreen and
1384 /// fBlue components will be set.
1385 
1386 void TGX11::QueryColor(Colormap_t cmap, ColorStruct_t &color)
1387 {
1388  XColor xc;
1389 
1390  xc.pixel = color.fPixel;
1391 
1392  // still very slight dark shift ??
1393  //QueryColors((Colormap)cmap, &xc, 1);
1394  //printf("1 xc.red = %u, xc.green = %u, xc.blue = %u\n", xc.red, xc.green, xc.blue);
1395  XQueryColor((Display*)fDisplay, (Colormap)cmap, &xc);
1396  //printf("2 xc.red = %u, xc.green = %u, xc.blue = %u\n", xc.red, xc.green, xc.blue);
1397 
1398  color.fRed = xc.red;
1399  color.fGreen = xc.green;
1400  color.fBlue = xc.blue;
1401 }
1402 
1403 ////////////////////////////////////////////////////////////////////////////////
1404 /// Free color cell with specified pixel value.
1405 
1406 void TGX11::FreeColor(Colormap_t cmap, ULong_t pixel)
1407 {
1408  if (fRedDiv == -1)
1409  XFreeColors((Display*)fDisplay, (Colormap)cmap, &pixel, 1, 0);
1410 }
1411 
1412 ////////////////////////////////////////////////////////////////////////////////
1413 /// Returns number of pending events.
1414 
1415 Int_t TGX11::EventsPending()
1416 {
1417  if (!fDisplay) return 0;
1418  return XPending((Display*)fDisplay);
1419 }
1420 
1421 ////////////////////////////////////////////////////////////////////////////////
1422 /// Copies first pending event from event queue to Event_t structure
1423 /// and removes event from queue. Not all of the event fields are valid
1424 /// for each event type, except fType and fWindow.
1425 
1426 void TGX11::NextEvent(Event_t &event)
1427 {
1428  XNextEvent((Display*)fDisplay, (XEvent*)fXEvent);
1429 
1430  // fill in Event_t
1431  MapEvent(event, fXEvent, kFALSE);
1432 }
1433 
1434 ////////////////////////////////////////////////////////////////////////////////
1435 /// Map modifier key state to or from X.
1436 
1437 void TGX11::MapModifierState(UInt_t &state, UInt_t &xstate, Bool_t tox)
1438 {
1439  if (tox) {
1440  xstate = 0;
1441  if ((state & kKeyShiftMask))
1442  xstate |= ShiftMask;
1443  if ((state & kKeyLockMask))
1444  xstate |= LockMask;
1445  if ((state & kKeyControlMask))
1446  xstate |= ControlMask;
1447  if ((state & kKeyMod1Mask))
1448  xstate |= Mod1Mask;
1449  if ((state & kKeyMod2Mask))
1450  xstate |= Mod2Mask;
1451  if ((state & kKeyMod3Mask))
1452  xstate |= Mod3Mask;
1453  if ((state & kKeyMod4Mask))
1454  xstate |= Mod4Mask;
1455  if ((state & kKeyMod5Mask))
1456  xstate |= Mod5Mask;
1457  if ((state & kButton1Mask))
1458  xstate |= Button1Mask;
1459  if ((state & kButton2Mask))
1460  xstate |= Button2Mask;
1461  if ((state & kButton3Mask))
1462  xstate |= Button3Mask;
1463  if ((state & kAnyModifier))
1464  xstate |= AnyModifier; // or should it be = instead of |= ?
1465  } else {
1466  state = 0;
1467  if ((xstate & ShiftMask))
1468  state |= kKeyShiftMask;
1469  if ((xstate & LockMask))
1470  state |= kKeyLockMask;
1471  if ((xstate & ControlMask))
1472  state |= kKeyControlMask;
1473  if ((xstate & Mod1Mask))
1474  state |= kKeyMod1Mask;
1475  if ((xstate & Mod2Mask))
1476  state |= kKeyMod2Mask;
1477  if ((xstate & Mod3Mask))
1478  state |= kKeyMod3Mask;
1479  if ((xstate & Mod4Mask))
1480  state |= kKeyMod4Mask;
1481  if ((xstate & Mod5Mask))
1482  state |= kKeyMod5Mask;
1483  if ((xstate & Button1Mask))
1484  state |= kButton1Mask;
1485  if ((xstate & Button2Mask))
1486  state |= kButton2Mask;
1487  if ((xstate & Button3Mask))
1488  state |= kButton3Mask;
1489  if ((xstate & AnyModifier))
1490  state |= kAnyModifier; // idem
1491  }
1492 }
1493 
1494 ////////////////////////////////////////////////////////////////////////////////
1495 /// Map Event_t structure to XEvent structure. If tox is false
1496 /// map the other way.
1497 
1498 void TGX11::MapEvent(Event_t &ev, void *xevi, Bool_t tox)
1499 {
1500  XEvent &xev = *(XEvent *)xevi;
1501 
1502  if (tox) {
1503  // map from Event_t to XEvent
1504  xev.type = 0;
1505  if (ev.fType == kGKeyPress) xev.type = KeyPress;
1506  if (ev.fType == kKeyRelease) xev.type = KeyRelease;
1507  if (ev.fType == kButtonPress) xev.type = ButtonPress;
1508  if (ev.fType == kButtonRelease) xev.type = ButtonRelease;
1509  if (ev.fType == kMotionNotify) xev.type = MotionNotify;
1510  if (ev.fType == kEnterNotify) xev.type = EnterNotify;
1511  if (ev.fType == kLeaveNotify) xev.type = LeaveNotify;
1512  if (ev.fType == kFocusIn) xev.type = FocusIn;
1513  if (ev.fType == kFocusOut) xev.type = FocusOut;
1514  if (ev.fType == kExpose) xev.type = Expose;
1515  if (ev.fType == kConfigureNotify) xev.type = ConfigureNotify;
1516  if (ev.fType == kMapNotify) xev.type = MapNotify;
1517  if (ev.fType == kUnmapNotify) xev.type = UnmapNotify;
1518  if (ev.fType == kDestroyNotify) xev.type = DestroyNotify;
1519  if (ev.fType == kClientMessage) xev.type = ClientMessage;
1520  if (ev.fType == kSelectionClear) xev.type = SelectionClear;
1521  if (ev.fType == kSelectionRequest) xev.type = SelectionRequest;
1522  if (ev.fType == kSelectionNotify) xev.type = SelectionNotify;
1523  if (ev.fType == kColormapNotify) xev.type = ColormapNotify;
1524 
1525  xev.xany.window = (Window) ev.fWindow;
1526  xev.xany.send_event = (Bool) ev.fSendEvent;
1527  xev.xany.display = (Display*)fDisplay;
1528 
1529  if (ev.fType == kGKeyPress || ev.fType == kKeyRelease) {
1530  xev.xkey.time = (Time) ev.fTime;
1531  xev.xkey.x = ev.fX;
1532  xev.xkey.y = ev.fY;
1533  xev.xkey.x_root = ev.fXRoot;
1534  xev.xkey.y_root = ev.fYRoot;
1535  MapModifierState(ev.fState, xev.xkey.state, kTRUE); // key mask
1536  xev.xkey.keycode = ev.fCode; // key code
1537  }
1538  if (ev.fType == kSelectionNotify) {
1539  xev.xselection.time = (Time) ev.fTime;
1540  xev.xselection.requestor = (Window) ev.fUser[0];
1541  xev.xselection.selection = (Atom) ev.fUser[1];
1542  xev.xselection.target = (Atom) ev.fUser[2];
1543  xev.xselection.property = (Atom) ev.fUser[3];
1544  }
1545  if (ev.fType == kClientMessage) {
1546  xev.xclient.message_type = ev.fHandle;
1547  xev.xclient.format = ev.fFormat;
1548  xev.xclient.data.l[0] = ev.fUser[0];
1549  if (sizeof(ev.fUser[0]) > 4) {
1550  SplitLong(ev.fUser[1], xev.xclient.data.l[1], xev.xclient.data.l[3]);
1551  SplitLong(ev.fUser[2], xev.xclient.data.l[2], xev.xclient.data.l[4]);
1552  } else {
1553  xev.xclient.data.l[1] = ev.fUser[1];
1554  xev.xclient.data.l[2] = ev.fUser[2];
1555  xev.xclient.data.l[3] = ev.fUser[3];
1556  xev.xclient.data.l[4] = ev.fUser[4];
1557  }
1558  }
1559  } else {
1560  // map from XEvent to Event_t
1561  ev.fType = kOtherEvent;
1562  if (xev.type == KeyPress) ev.fType = kGKeyPress;
1563  if (xev.type == KeyRelease) ev.fType = kKeyRelease;
1564  if (xev.type == ButtonPress) ev.fType = kButtonPress;
1565  if (xev.type == ButtonRelease) ev.fType = kButtonRelease;
1566  if (xev.type == MotionNotify) ev.fType = kMotionNotify;
1567  if (xev.type == EnterNotify) ev.fType = kEnterNotify;
1568  if (xev.type == LeaveNotify) ev.fType = kLeaveNotify;
1569  if (xev.type == FocusIn) ev.fType = kFocusIn;
1570  if (xev.type == FocusOut) ev.fType = kFocusOut;
1571  if (xev.type == Expose) ev.fType = kExpose;
1572  if (xev.type == GraphicsExpose) ev.fType = kExpose;
1573  if (xev.type == ConfigureNotify) ev.fType = kConfigureNotify;
1574  if (xev.type == MapNotify) ev.fType = kMapNotify;
1575  if (xev.type == UnmapNotify) ev.fType = kUnmapNotify;
1576  if (xev.type == DestroyNotify) ev.fType = kDestroyNotify;
1577  if (xev.type == ClientMessage) ev.fType = kClientMessage;
1578  if (xev.type == SelectionClear) ev.fType = kSelectionClear;
1579  if (xev.type == SelectionRequest) ev.fType = kSelectionRequest;
1580  if (xev.type == SelectionNotify) ev.fType = kSelectionNotify;
1581  if (xev.type == ColormapNotify) ev.fType = kColormapNotify;
1582 
1583  ev.fWindow = (Window_t) xev.xany.window;
1584  ev.fSendEvent = xev.xany.send_event ? kTRUE : kFALSE;
1585 
1586  if (ev.fType == kGKeyPress || ev.fType == kKeyRelease) {
1587  ev.fTime = (Time_t) xev.xkey.time;
1588  ev.fX = xev.xkey.x;
1589  ev.fY = xev.xkey.y;
1590  ev.fXRoot = xev.xkey.x_root;
1591  ev.fYRoot = xev.xkey.y_root;
1592  MapModifierState(ev.fState, xev.xkey.state, kFALSE); // key mask
1593  ev.fCode = xev.xkey.keycode; // key code
1594  ev.fUser[0] = xev.xkey.subwindow; // child window
1595  }
1596  if (ev.fType == kButtonPress || ev.fType == kButtonRelease) {
1597  ev.fTime = (Time_t) xev.xbutton.time;
1598  ev.fX = xev.xbutton.x;
1599  ev.fY = xev.xbutton.y;
1600  ev.fXRoot = xev.xbutton.x_root;
1601  ev.fYRoot = xev.xbutton.y_root;
1602  MapModifierState(ev.fState, xev.xbutton.state, kFALSE); // button mask
1603  ev.fCode = xev.xbutton.button; // button code
1604  ev.fUser[0] = xev.xbutton.subwindow; // child window
1605  }
1606  if (ev.fType == kMotionNotify) {
1607  ev.fTime = (Time_t) xev.xmotion.time;
1608  ev.fX = xev.xmotion.x;
1609  ev.fY = xev.xmotion.y;
1610  ev.fXRoot = xev.xmotion.x_root;
1611  ev.fYRoot = xev.xmotion.y_root;
1612  MapModifierState(ev.fState, xev.xmotion.state, kFALSE); // key or button mask
1613  ev.fUser[0] = xev.xmotion.subwindow; // child window
1614  }
1615  if (ev.fType == kEnterNotify || ev.fType == kLeaveNotify) {
1616  ev.fTime = (Time_t) xev.xcrossing.time;
1617  ev.fX = xev.xcrossing.x;
1618  ev.fY = xev.xcrossing.y;
1619  ev.fXRoot = xev.xcrossing.x_root;
1620  ev.fYRoot = xev.xcrossing.y_root;
1621  ev.fCode = xev.xcrossing.mode; // NotifyNormal, NotifyGrab, NotifyUngrab
1622  MapModifierState(ev.fState, xev.xcrossing.state, kFALSE); // key or button mask
1623  }
1624  if (ev.fType == kFocusIn || ev.fType == kFocusOut) {
1625  // check this when porting to Win32 (see also TGTextEntry::HandleFocusChange)
1626  ev.fCode = xev.xfocus.mode; // NotifyNormal, NotifyGrab, NotifyUngrab
1627  ev.fState = xev.xfocus.detail; // NotifyPointer et al.
1628  }
1629  if (ev.fType == kExpose) {
1630  ev.fX = xev.xexpose.x;
1631  ev.fY = xev.xexpose.y;
1632  ev.fWidth = xev.xexpose.width; // width and
1633  ev.fHeight = xev.xexpose.height; // height of exposed area
1634  ev.fCount = xev.xexpose.count; // number of expose events still to come
1635  }
1636  if (ev.fType == kConfigureNotify) {
1637  ev.fX = xev.xconfigure.x;
1638  ev.fY = xev.xconfigure.y;
1639  ev.fWidth = xev.xconfigure.width;
1640  ev.fHeight = xev.xconfigure.height;
1641  }
1642  if (ev.fType == kMapNotify || ev.fType == kUnmapNotify) {
1643  ev.fHandle = xev.xmap.window; // window to be (un)mapped
1644  }
1645  if (ev.fType == kDestroyNotify) {
1646  ev.fHandle = xev.xdestroywindow.window; // window to be destroyed
1647  }
1648  if (ev.fType == kClientMessage) {
1649  ev.fHandle = xev.xclient.message_type;
1650  ev.fFormat = xev.xclient.format;
1651  ev.fUser[0] = xev.xclient.data.l[0];
1652  if (sizeof(ev.fUser[0]) > 4) {
1653  AsmLong(xev.xclient.data.l[1], xev.xclient.data.l[3], ev.fUser[1]);
1654  AsmLong(xev.xclient.data.l[2], xev.xclient.data.l[4], ev.fUser[2]);
1655  } else {
1656  ev.fUser[1] = xev.xclient.data.l[1];
1657  ev.fUser[2] = xev.xclient.data.l[2];
1658  ev.fUser[3] = xev.xclient.data.l[3];
1659  ev.fUser[4] = xev.xclient.data.l[4];
1660  }
1661  }
1662  if (ev.fType == kSelectionClear) {
1663  ev.fUser[0] = xev.xselectionclear.selection;
1664  }
1665  if (ev.fType == kSelectionRequest) {
1666  ev.fTime = (Time_t) xev.xselectionrequest.time;
1667  ev.fUser[0] = xev.xselectionrequest.requestor;
1668  ev.fUser[1] = xev.xselectionrequest.selection;
1669  ev.fUser[2] = xev.xselectionrequest.target;
1670  ev.fUser[3] = xev.xselectionrequest.property;
1671  }
1672  if (ev.fType == kSelectionNotify) {
1673  ev.fTime = (Time_t) xev.xselection.time;
1674  ev.fUser[0] = xev.xselection.requestor;
1675  ev.fUser[1] = xev.xselection.selection;
1676  ev.fUser[2] = xev.xselection.target;
1677  ev.fUser[3] = xev.xselection.property;
1678  }
1679  if (ev.fType == kColormapNotify) {
1680  ev.fHandle = xev.xcolormap.colormap;
1681  ev.fCode = xev.xcolormap.state; // ColormapUninstalled, ColormapInstalled
1682  ev.fState = xev.xcolormap.c_new; // true if new colormap
1683  }
1684  }
1685 }
1686 
1687 ////////////////////////////////////////////////////////////////////////////////
1688 /// Sound bell. Percent is loudness from -100% .. 100%.
1689 
1690 void TGX11::Bell(Int_t percent)
1691 {
1692  XBell((Display*)fDisplay, percent);
1693 }
1694 
1695 ////////////////////////////////////////////////////////////////////////////////
1696 /// Copy a drawable (i.e. pixmap) to another drawable (pixmap, window).
1697 /// The graphics context gc will be used and the source will be copied
1698 /// from src_x,src_y,src_x+width,src_y+height to dest_x,dest_y.
1699 
1700 void TGX11::CopyArea(Drawable_t src, Drawable_t dest, GContext_t gc,
1701  Int_t src_x, Int_t src_y, UInt_t width, UInt_t height,
1702  Int_t dest_x, Int_t dest_y)
1703 {
1704  if (!src || !dest) return;
1705 
1706  XCopyArea((Display*)fDisplay, src, dest, (GC) gc, src_x, src_y, width, height,
1707  dest_x, dest_y);
1708 }
1709 
1710 ////////////////////////////////////////////////////////////////////////////////
1711 /// Change window attributes.
1712 
1713 void TGX11::ChangeWindowAttributes(Window_t id, SetWindowAttributes_t *attr)
1714 {
1715  if (!id) return;
1716 
1717  RXSetWindowAttributes xattr;
1718  ULong_t xmask = 0;
1719 
1720  if (attr)
1721  MapSetWindowAttributes(attr, xmask, xattr);
1722 
1723  XChangeWindowAttributes((Display*)fDisplay, (Window) id, xmask, &xattr);
1724 
1725  if (attr && (attr->fMask & kWABorderWidth))
1726  XSetWindowBorderWidth((Display*)fDisplay, (Window) id, attr->fBorderWidth);
1727 }
1728 
1729 ////////////////////////////////////////////////////////////////////////////////
1730 /// This function alters the property for the specified window and
1731 /// causes the X server to generate a PropertyNotify event on that
1732 /// window.
1733 
1734 void TGX11::ChangeProperty(Window_t id, Atom_t property, Atom_t type,
1735  UChar_t *data, Int_t len)
1736 {
1737  if (!id) return;
1738 
1739  XChangeProperty((Display*)fDisplay, (Window) id, (Atom) property, (Atom) type,
1740  8, PropModeReplace, data, len);
1741 }
1742 
1743 ////////////////////////////////////////////////////////////////////////////////
1744 /// Draw a line.
1745 
1746 void TGX11::DrawLine(Drawable_t id, GContext_t gc, Int_t x1, Int_t y1, Int_t x2, Int_t y2)
1747 {
1748  if (!id) return;
1749 
1750  XDrawLine((Display*)fDisplay, (Drawable) id, (GC) gc, x1, y1, x2, y2);
1751 }
1752 
1753 ////////////////////////////////////////////////////////////////////////////////
1754 /// Clear a window area to the background color.
1755 
1756 void TGX11::ClearArea(Window_t id, Int_t x, Int_t y, UInt_t w, UInt_t h)
1757 {
1758  if (!id) return;
1759 
1760  XClearArea((Display*)fDisplay, (Window) id, x, y, w, h, False);
1761 }
1762 
1763 ////////////////////////////////////////////////////////////////////////////////
1764 /// Check if there is for window "id" an event of type "type". If there
1765 /// is fill in the event structure and return true. If no such event
1766 /// return false.
1767 
1768 Bool_t TGX11::CheckEvent(Window_t id, EGEventType type, Event_t &ev)
1769 {
1770  if (!id) return kFALSE;
1771 
1772  Event_t tev;
1773  XEvent xev;
1774 
1775  tev.fCode = 0;
1776  tev.fState = 0;
1777  tev.fWindow = 0;
1778  tev.fUser[0] = tev.fUser[1] = tev.fUser[2] = tev.fUser[3] = tev.fUser[4] = 0;
1779  tev.fCount = 0;
1780  tev.fFormat = 0;
1781  tev.fHandle = 0;
1782  tev.fSendEvent = 0;
1783  tev.fTime = 0;
1784  tev.fX = tev.fY = 0;
1785  tev.fXRoot = tev.fYRoot = 0;
1786  tev.fType = type;
1787  MapEvent(tev, &xev);
1788 
1789  Bool r = XCheckTypedWindowEvent((Display*)fDisplay, (Window) id, xev.type, &xev);
1790 
1791  if (r) MapEvent(ev, &xev, kFALSE);
1792 
1793  return r ? kTRUE : kFALSE;
1794 }
1795 
1796 ////////////////////////////////////////////////////////////////////////////////
1797 /// Send event ev to window id.
1798 
1799 void TGX11::SendEvent(Window_t id, Event_t *ev)
1800 {
1801  if (!ev || !id) return;
1802 
1803  XEvent xev;
1804 
1805  MapEvent(*ev, &xev);
1806 
1807  XSendEvent((Display*)fDisplay, (Window) id, False, None, &xev);
1808 }
1809 
1810 ////////////////////////////////////////////////////////////////////////////////
1811 /// Tell WM to send message when window is closed via WM.
1812 
1813 void TGX11::WMDeleteNotify(Window_t id)
1814 {
1815  if (!id) return;
1816 
1817  XSetWMProtocols((Display*)fDisplay, (Window) id, &gWM_DELETE_WINDOW, 1);
1818 }
1819 
1820 ////////////////////////////////////////////////////////////////////////////////
1821 /// Turn key auto repeat on or off.
1822 
1823 void TGX11::SetKeyAutoRepeat(Bool_t on)
1824 {
1825  if (on)
1826  XAutoRepeatOn((Display*)fDisplay);
1827  else
1828  XAutoRepeatOff((Display*)fDisplay);
1829 }
1830 
1831 ////////////////////////////////////////////////////////////////////////////////
1832 /// Establish passive grab on a certain key. That is, when a certain key
1833 /// keycode is hit while certain modifier's (Shift, Control, Meta, Alt)
1834 /// are active then the keyboard will be grabbed for window id.
1835 /// When grab is false, ungrab the keyboard for this key and modifier.
1836 
1837 void TGX11::GrabKey(Window_t id, Int_t keycode, UInt_t modifier, Bool_t grab)
1838 {
1839 // if (!id) return;
1840 
1841  UInt_t xmod;
1842 
1843  MapModifierState(modifier, xmod);
1844 
1845  if (grab)
1846  XGrabKey((Display*)fDisplay, keycode, xmod, (Window) id, True,
1847  GrabModeAsync, GrabModeAsync);
1848  else
1849  XUngrabKey((Display*)fDisplay, keycode, xmod, (Window) id);
1850 }
1851 
1852 ////////////////////////////////////////////////////////////////////////////////
1853 /// Establish passive grab on a certain mouse button. That is, when a
1854 /// certain mouse button is hit while certain modifier's (Shift, Control,
1855 /// Meta, Alt) are active then the mouse will be grabbed for window id.
1856 /// When grab is false, ungrab the mouse button for this button and modifier.
1857 
1858 void TGX11::GrabButton(Window_t id, EMouseButton button, UInt_t modifier,
1859  UInt_t evmask, Window_t confine, Cursor_t cursor,
1860  Bool_t grab)
1861 {
1862  if (!id) return;
1863 
1864  UInt_t xmod;
1865 
1866  MapModifierState(modifier, xmod);
1867 
1868  if (grab) {
1869  UInt_t xevmask;
1870  MapEventMask(evmask, xevmask);
1871 
1872  XGrabButton((Display*)fDisplay, button, xmod, (Window) id, True, xevmask,
1873  GrabModeAsync, GrabModeAsync, (Window) confine,
1874  (Cursor) cursor);
1875  } else
1876  XUngrabButton((Display*)fDisplay, button, xmod, (Window) id);
1877 }
1878 
1879 ////////////////////////////////////////////////////////////////////////////////
1880 /// Establish an active pointer grab. While an active pointer grab is in
1881 /// effect, further pointer events are only reported to the grabbing
1882 /// client window.
1883 
1884 void TGX11::GrabPointer(Window_t id, UInt_t evmask, Window_t confine,
1885  Cursor_t cursor, Bool_t grab, Bool_t owner_events)
1886 {
1887 // if (!id) return;
1888 
1889  if (grab) {
1890  UInt_t xevmask;
1891  MapEventMask(evmask, xevmask);
1892 
1893  XGrabPointer((Display*)fDisplay, (Window) id, (Bool) owner_events,
1894  xevmask, GrabModeAsync, GrabModeAsync, (Window) confine,
1895  (Cursor) cursor, CurrentTime);
1896  } else
1897  XUngrabPointer((Display*)fDisplay, CurrentTime);
1898 }
1899 
1900 ////////////////////////////////////////////////////////////////////////////////
1901 /// Set window name.
1902 
1903 void TGX11::SetWindowName(Window_t id, char *name)
1904 {
1905  if (!id) return;
1906 
1907  XTextProperty wname;
1908 
1909  if (XStringListToTextProperty(&name, 1, &wname) == 0) {
1910  Error("SetWindowName", "cannot allocate window name \"%s\"", name);
1911  return;
1912  }
1913  XSetWMName((Display*)fDisplay, (Window) id, &wname);
1914  XFree(wname.value);
1915 }
1916 
1917 ////////////////////////////////////////////////////////////////////////////////
1918 /// Set window icon name.
1919 
1920 void TGX11::SetIconName(Window_t id, char *name)
1921 {
1922  if (!id) return;
1923 
1924  XTextProperty wname;
1925 
1926  if (XStringListToTextProperty(&name, 1, &wname) == 0) {
1927  Error("SetIconName", "cannot allocate icon name \"%s\"", name);
1928  return;
1929  }
1930  XSetWMIconName((Display*)fDisplay, (Window) id, &wname);
1931  XFree(wname.value);
1932 }
1933 
1934 ////////////////////////////////////////////////////////////////////////////////
1935 /// Set pixmap the WM can use when the window is iconized.
1936 
1937 void TGX11::SetIconPixmap(Window_t id, Pixmap_t pic)
1938 {
1939  if (!id) return;
1940 
1941  XWMHints hints;
1942 
1943  hints.flags = IconPixmapHint;
1944  hints.icon_pixmap = (Pixmap) pic;
1945 
1946  XSetWMHints((Display*)fDisplay, (Window) id, &hints);
1947 }
1948 
1949 ////////////////////////////////////////////////////////////////////////////////
1950 /// Set the windows class and resource name.
1951 
1952 void TGX11::SetClassHints(Window_t id, char *className, char *resourceName)
1953 {
1954  if (!id) return;
1955 
1956  XClassHint class_hints;
1957 
1958  class_hints.res_class = className;
1959  class_hints.res_name = resourceName;
1960  XSetClassHint((Display*)fDisplay, (Window) id, &class_hints);
1961 }
1962 
1963 ////////////////////////////////////////////////////////////////////////////////
1964 /// Set decoration style for MWM-compatible wm (mwm, ncdwm, fvwm?).
1965 
1966 void TGX11::SetMWMHints(Window_t id, UInt_t value, UInt_t funcs, UInt_t input)
1967 {
1968  if (!id) return;
1969 
1970  MWMHintsProperty_t prop;
1971 
1972  prop.fDecorations = value;
1973  prop.fFunctions = funcs;
1974  prop.fInputMode = input;
1975  prop.fFlags = kMWMHintsDecorations | kMWMHintsFunctions | kMWMHintsInputMode;
1976 
1977  XChangeProperty((Display*)fDisplay, (Window) id, gMOTIF_WM_HINTS, gMOTIF_WM_HINTS, 32,
1978  PropModeReplace, (UChar_t *)&prop, kPropMWMHintElements);
1979 }
1980 
1981 ////////////////////////////////////////////////////////////////////////////////
1982 /// Tell the window manager the desired window position.
1983 
1984 void TGX11::SetWMPosition(Window_t id, Int_t x, Int_t y)
1985 {
1986  if (!id) return;
1987 
1988  XSizeHints hints;
1989 
1990  hints.flags = USPosition | PPosition;
1991  hints.x = x;
1992  hints.y = y;
1993 
1994  XSetWMNormalHints((Display*)fDisplay, (Window) id, &hints);
1995 }
1996 
1997 ////////////////////////////////////////////////////////////////////////////////
1998 /// Tell the window manager the desired window size.
1999 
2000 void TGX11::SetWMSize(Window_t id, UInt_t w, UInt_t h)
2001 {
2002  if (!id) return;
2003 
2004  XSizeHints hints;
2005 
2006  hints.flags = USSize | PSize | PBaseSize;
2007  hints.width = hints.base_width = w;
2008  hints.height = hints.base_height = h;
2009 
2010  XSetWMNormalHints((Display*)fDisplay, (Window) id, &hints);
2011 }
2012 
2013 ////////////////////////////////////////////////////////////////////////////////
2014 /// Give the window manager minimum and maximum size hints. Also
2015 /// specify via winc and hinc the resize increments.
2016 
2017 void TGX11::SetWMSizeHints(Window_t id, UInt_t wmin, UInt_t hmin,
2018  UInt_t wmax, UInt_t hmax,
2019  UInt_t winc, UInt_t hinc)
2020 {
2021  if (!id) return;
2022 
2023  XSizeHints hints;
2024 
2025  hints.flags = PMinSize | PMaxSize | PResizeInc;
2026  hints.min_width = (Int_t)wmin;
2027  hints.max_width = (Int_t)wmax;
2028  hints.min_height = (Int_t)hmin;
2029  hints.max_height = (Int_t)hmax;
2030  hints.width_inc = (Int_t)winc;
2031  hints.height_inc = (Int_t)hinc;
2032 
2033  XSetWMNormalHints((Display*)fDisplay, (Window) id, &hints);
2034 }
2035 
2036 ////////////////////////////////////////////////////////////////////////////////
2037 /// Set the initial state of the window. Either kNormalState or kIconicState.
2038 
2039 void TGX11::SetWMState(Window_t id, EInitialState state)
2040 {
2041  if (!id) return;
2042 
2043  XWMHints hints;
2044  Int_t xstate = NormalState;
2045 
2046  if (state == kNormalState)
2047  xstate = NormalState;
2048  if (state == kIconicState)
2049  xstate = IconicState;
2050 
2051  hints.flags = StateHint;
2052  hints.initial_state = xstate;
2053 
2054  XSetWMHints((Display*)fDisplay, (Window) id, &hints);
2055 }
2056 
2057 ////////////////////////////////////////////////////////////////////////////////
2058 /// Tell window manager that window is a transient window of main.
2059 
2060 void TGX11::SetWMTransientHint(Window_t id, Window_t main_id)
2061 {
2062  if (!id) return;
2063 
2064  XSetTransientForHint((Display*)fDisplay, (Window) id, (Window) main_id);
2065 }
2066 
2067 ////////////////////////////////////////////////////////////////////////////////
2068 /// Draw a string using a specific graphics context in position (x,y).
2069 
2070 void TGX11::DrawString(Drawable_t id, GContext_t gc, Int_t x, Int_t y,
2071  const char *s, Int_t len)
2072 {
2073  if (!id) return;
2074 
2075  XDrawString((Display*)fDisplay, (Drawable) id, (GC) gc, x, y, (char *) s, len);
2076 }
2077 
2078 ////////////////////////////////////////////////////////////////////////////////
2079 /// Return length of string in pixels. Size depends on font.
2080 
2081 Int_t TGX11::TextWidth(FontStruct_t font, const char *s, Int_t len)
2082 {
2083  return XTextWidth((XFontStruct*) font, (char*) s, len);
2084 }
2085 
2086 ////////////////////////////////////////////////////////////////////////////////
2087 /// Return some font properties.
2088 
2089 void TGX11::GetFontProperties(FontStruct_t font, Int_t &max_ascent, Int_t &max_descent)
2090 {
2091  XFontStruct *f = (XFontStruct *) font;
2092 
2093  max_ascent = f->max_bounds.ascent;
2094  max_descent = f->max_bounds.descent;
2095 }
2096 
2097 ////////////////////////////////////////////////////////////////////////////////
2098 /// Get current values from graphics context gc. Which values of the
2099 /// context to get is encoded in the GCValues::fMask member. If fMask = 0
2100 /// then copy all fields.
2101 
2102 void TGX11::GetGCValues(GContext_t gc, GCValues_t &gval)
2103 {
2104  RXGCValues xgval;
2105  ULong_t xmask;
2106 
2107  if (!gval.fMask) {
2108  // in this case copy all fields
2109  gval.fMask = kMaxUInt;
2110  }
2111 
2112  MapGCValues(gval, xmask, xgval);
2113 
2114  XGetGCValues((Display*)fDisplay, (GC) gc, xmask, &xgval);
2115 
2116  MapGCValues(gval, xmask, xgval, kFALSE);
2117 }
2118 
2119 ////////////////////////////////////////////////////////////////////////////////
2120 /// Retrieve associated font structure once we have the font handle.
2121 /// Free returned FontStruct_t using FreeFontStruct().
2122 
2123 FontStruct_t TGX11::GetFontStruct(FontH_t fh)
2124 {
2125  XFontStruct *fs;
2126 
2127  fs = XQueryFont((Display*)fDisplay, (Font) fh);
2128 
2129  return (FontStruct_t) fs;
2130 }
2131 
2132 ////////////////////////////////////////////////////////////////////////////////
2133 /// Free font structure returned by GetFontStruct().
2134 
2135 void TGX11::FreeFontStruct(FontStruct_t fs)
2136 {
2137  // in XFree86 4.0 XFreeFontInfo() is broken, ok again in 4.0.1
2138  static int xfree86_400 = -1;
2139  if (xfree86_400 == -1) {
2140  if (strstr(XServerVendor((Display*)fDisplay), "XFree86") &&
2141  XVendorRelease((Display*)fDisplay) == 4000)
2142  xfree86_400 = 1;
2143  else
2144  xfree86_400 = 0;
2145  }
2146 
2147  if (xfree86_400 == 0)
2148  XFreeFontInfo(0, (XFontStruct *) fs, 1);
2149 }
2150 
2151 ////////////////////////////////////////////////////////////////////////////////
2152 /// Clear window.
2153 
2154 void TGX11::ClearWindow(Window_t id)
2155 {
2156  if (!id) return;
2157 
2158  XClearWindow((Display*)fDisplay, (Window) id);
2159 }
2160 
2161 ////////////////////////////////////////////////////////////////////////////////
2162 /// Convert a keysym to the appropriate keycode. For example keysym is
2163 /// a letter and keycode is the matching keyboard key (which is dependent
2164 /// on the current keyboard mapping).
2165 
2166 Int_t TGX11::KeysymToKeycode(UInt_t keysym)
2167 {
2168  UInt_t xkeysym;
2169  MapKeySym(keysym, xkeysym);
2170 
2171  return XKeysymToKeycode((Display*)fDisplay, xkeysym);
2172 }
2173 
2174 ////////////////////////////////////////////////////////////////////////////////
2175 /// Draw a filled rectangle. Filling is done according to the gc.
2176 
2177 void TGX11::FillRectangle(Drawable_t id, GContext_t gc, Int_t x, Int_t y, UInt_t w, UInt_t h)
2178 {
2179  if (!id) return;
2180 
2181  XFillRectangle((Display*)fDisplay, (Drawable) id, (GC) gc, x, y, w, h);
2182 }
2183 
2184 ////////////////////////////////////////////////////////////////////////////////
2185 /// Draw a rectangle outline.
2186 
2187 void TGX11::DrawRectangle(Drawable_t id, GContext_t gc, Int_t x, Int_t y, UInt_t w, UInt_t h)
2188 {
2189  if (!id) return;
2190 
2191  XDrawRectangle((Display*)fDisplay, (Drawable) id, (GC) gc, x, y, w, h);
2192 }
2193 
2194 ////////////////////////////////////////////////////////////////////////////////
2195 /// Draws multiple line segments. Each line is specified by a pair of points.
2196 
2197 void TGX11::DrawSegments(Drawable_t id, GContext_t gc, Segment_t *seg, Int_t nseg)
2198 {
2199  if (!id) return;
2200 
2201  XDrawSegments((Display*)fDisplay, (Drawable) id, (GC) gc, (XSegment *) seg, nseg);
2202 }
2203 
2204 ////////////////////////////////////////////////////////////////////////////////
2205 /// Defines which input events the window is interested in. By default
2206 /// events are propagated up the window stack. This mask can also be
2207 /// set at window creation time via the SetWindowAttributes_t::fEventMask
2208 /// attribute.
2209 
2210 void TGX11::SelectInput(Window_t id, UInt_t evmask)
2211 {
2212  if (!id) return;
2213 
2214  UInt_t xevmask;
2215 
2216  MapEventMask(evmask, xevmask);
2217 
2218  XSelectInput((Display*)fDisplay, (Window) id, xevmask);
2219 }
2220 
2221 ////////////////////////////////////////////////////////////////////////////////
2222 /// Returns the window id of the window having the input focus.
2223 
2224 Window_t TGX11::GetInputFocus()
2225 {
2226  Window focus;
2227  int return_to;
2228 
2229  XGetInputFocus((Display*)fDisplay, &focus, &return_to);
2230  return (Window_t) focus;
2231 }
2232 
2233 ////////////////////////////////////////////////////////////////////////////////
2234 /// Set keyboard input focus to window id.
2235 
2236 void TGX11::SetInputFocus(Window_t id)
2237 {
2238  if (!id) return;
2239 
2240  XWindowAttributes xattr;
2241 
2242  XGetWindowAttributes((Display*)fDisplay, (Window) id, &xattr);
2243 
2244  if (xattr.map_state == IsViewable)
2245  XSetInputFocus((Display*)fDisplay, (Window) id, RevertToParent, CurrentTime);
2246 }
2247 
2248 ////////////////////////////////////////////////////////////////////////////////
2249 /// Returns the window id of the current owner of the primary selection.
2250 /// That is the window in which, for example some text is selected.
2251 
2252 Window_t TGX11::GetPrimarySelectionOwner()
2253 {
2254  return (Window_t) XGetSelectionOwner((Display*)fDisplay, XA_PRIMARY);
2255 }
2256 
2257 ////////////////////////////////////////////////////////////////////////////////
2258 /// Makes the window id the current owner of the primary selection.
2259 /// That is the window in which, for example some text is selected.
2260 
2261 void TGX11::SetPrimarySelectionOwner(Window_t id)
2262 {
2263  if (!id) return;
2264 
2265  XSetSelectionOwner((Display*)fDisplay, XA_PRIMARY, id, CurrentTime);
2266 }
2267 
2268 ////////////////////////////////////////////////////////////////////////////////
2269 /// XConvertSelection() causes a SelectionRequest event to be sent to the
2270 /// current primary selection owner. This event specifies the selection
2271 /// property (primary selection), the format into which to convert that
2272 /// data before storing it (target = XA_STRING), the property in which
2273 /// the owner will place the information (sel_property), the window that
2274 /// wants the information (id), and the time of the conversion request
2275 /// (when).
2276 /// The selection owner responds by sending a SelectionNotify event, which
2277 /// confirms the selected atom and type.
2278 
2279 void TGX11::ConvertPrimarySelection(Window_t id, Atom_t clipboard, Time_t when)
2280 {
2281  if (!id) return;
2282 
2283  XConvertSelection((Display*)fDisplay, XA_PRIMARY, XA_STRING, (Atom) clipboard,
2284  (Window) id, (Time) when);
2285 }
2286 
2287 ////////////////////////////////////////////////////////////////////////////////
2288 /// Convert the keycode from the event structure to a key symbol (according
2289 /// to the modifiers specified in the event structure and the current
2290 /// keyboard mapping). In buf a null terminated ASCII string is returned
2291 /// representing the string that is currently mapped to the key code.
2292 
2293 void TGX11::LookupString(Event_t *event, char *buf, Int_t buflen, UInt_t &keysym)
2294 {
2295  XEvent xev;
2296  KeySym xkeysym;
2297 
2298  MapEvent(*event, &xev);
2299 
2300  int n = XLookupString(&xev.xkey, buf, buflen-1, &xkeysym, 0);
2301  if (n >= buflen)
2302  Error("LookupString", "buf too small, must be at least %d", n+1);
2303  else
2304  buf[n] = 0;
2305 
2306  UInt_t ks, xks = (UInt_t) xkeysym;
2307  MapKeySym(ks, xks, kFALSE);
2308  keysym = (Int_t) ks;
2309 }
2310 
2311 ////////////////////////////////////////////////////////////////////////////////
2312 /// Map to and from X key symbols. Keysym are the values returned by
2313 /// XLookUpString.
2314 
2315 void TGX11::MapKeySym(UInt_t &keysym, UInt_t &xkeysym, Bool_t tox)
2316 {
2317  if (tox) {
2318  xkeysym = XK_VoidSymbol;
2319  if (keysym < 127) {
2320  xkeysym = keysym;
2321  } else if (keysym >= kKey_F1 && keysym <= kKey_F35) {
2322  xkeysym = XK_F1 + (keysym - (UInt_t)kKey_F1); // function keys
2323  } else {
2324  for (int i = 0; gKeyMap[i].fKeySym; i++) { // any other keys
2325  if (keysym == (UInt_t) gKeyMap[i].fKeySym) {
2326  xkeysym = (UInt_t) gKeyMap[i].fXKeySym;
2327  break;
2328  }
2329  }
2330  }
2331  } else {
2332  keysym = kKey_Unknown;
2333  // commentary in X11/keysymdef says that X codes match ASCII
2334  if (xkeysym < 127) {
2335  keysym = xkeysym;
2336  } else if (xkeysym >= XK_F1 && xkeysym <= XK_F35) {
2337  keysym = kKey_F1 + (xkeysym - XK_F1); // function keys
2338  } else if (xkeysym >= XK_KP_0 && xkeysym <= XK_KP_9) {
2339  keysym = kKey_0 + (xkeysym - XK_KP_0); // numeric keypad keys
2340  } else {
2341  for (int i = 0; gKeyMap[i].fXKeySym; i++) { // any other keys
2342  if (xkeysym == gKeyMap[i].fXKeySym) {
2343  keysym = (UInt_t) gKeyMap[i].fKeySym;
2344  break;
2345  }
2346  }
2347  }
2348  }
2349 }
2350 
2351 ////////////////////////////////////////////////////////////////////////////////
2352 /// Get contents of paste buffer atom into string. If del is true delete
2353 /// the paste buffer afterwards.
2354 
2355 void TGX11::GetPasteBuffer(Window_t id, Atom_t atom, TString &text, Int_t &nchar,
2356  Bool_t del)
2357 {
2358  if (!id) return;
2359 
2360  Atom actual_type, property = (Atom) atom;
2361  int actual_format;
2362  ULong_t nitems, bytes_after, nread;
2363  unsigned char *data;
2364 
2365  nchar = 0;
2366  text = "";
2367 
2368  if (property == None) return;
2369 
2370  // get past buffer
2371  nread = 0;
2372  do {
2373  if (XGetWindowProperty((Display*)fDisplay, (Window) id, property,
2374  nread/4, 1024, (Bool)del,
2375  AnyPropertyType,
2376  &actual_type, &actual_format,
2377  &nitems, &bytes_after,
2378  (unsigned char **) &data)
2379  != Success)
2380  break;
2381 
2382  if (actual_type != XA_STRING) break;
2383 
2384  text.Insert((Int_t) nread, (const char *) data, (Int_t) nitems);
2385  nread += nitems;
2386  XFree(data);
2387 
2388  } while (bytes_after > 0);
2389 
2390  nchar = (Int_t) nread;
2391 }
2392 
2393 ////////////////////////////////////////////////////////////////////////////////
2394 /// TranslateCoordinates translates coordinates from the frame of
2395 /// reference of one window to another. If the point is contained
2396 /// in a mapped child of the destination, the id of that child is
2397 /// returned as well.
2398 
2399 void TGX11::TranslateCoordinates(Window_t src, Window_t dest, Int_t src_x,
2400  Int_t src_y, Int_t &dest_x, Int_t &dest_y, Window_t &child)
2401 {
2402  if (!src || !dest) return;
2403 
2404  Window xchild;
2405 
2406  XTranslateCoordinates((Display*)fDisplay, (Window) src, (Window) dest, src_x,
2407  src_y, &dest_x, &dest_y, &xchild);
2408  child = (Window_t) xchild;
2409 }
2410 
2411 ////////////////////////////////////////////////////////////////////////////////
2412 /// Return geometry of window (should be called GetGeometry but signature
2413 /// already used).
2414 
2415 void TGX11::GetWindowSize(Drawable_t id, Int_t &x, Int_t &y, UInt_t &w, UInt_t &h)
2416 {
2417  if (!id) return;
2418 
2419  Window wdummy;
2420  UInt_t bdum, ddum;
2421 
2422  XGetGeometry((Display*)fDisplay, (Drawable) id, &wdummy, &x, &y, &w, &h, &bdum, &ddum);
2423 }
2424 
2425 ////////////////////////////////////////////////////////////////////////////////
2426 /// FillPolygon fills the region closed by the specified path.
2427 /// The path is closed automatically if the last point in the list does
2428 /// not coincide with the first point. All point coordinates are
2429 /// treated as relative to the origin. For every pair of points
2430 /// inside the polygon, the line segment connecting them does not
2431 /// intersect the path.
2432 
2433 void TGX11::FillPolygon(Window_t id, GContext_t gc, Point_t *points, Int_t npnt)
2434 {
2435  if (!id) return;
2436 
2437  XFillPolygon((Display*)fDisplay, (Window) id, (GC) gc, (XPoint *) points, npnt,
2438  Convex, CoordModeOrigin);
2439 }
2440 
2441 ////////////////////////////////////////////////////////////////////////////////
2442 /// Returns the root window the pointer is logically on and the pointer
2443 /// coordinates relative to the root window's origin.
2444 /// The pointer coordinates returned to win_x and win_y are relative to
2445 /// the origin of the specified window. In this case, QueryPointer returns
2446 /// the child that contains the pointer, if any, or else kNone to
2447 /// childw. QueryPointer returns the current logical state of the
2448 /// keyboard buttons and the modifier keys in mask.
2449 
2450 void TGX11::QueryPointer(Window_t id, Window_t &rootw, Window_t &childw,
2451  Int_t &root_x, Int_t &root_y, Int_t &win_x,
2452  Int_t &win_y, UInt_t &mask)
2453 {
2454  if (!id) return;
2455 
2456  Window xrootw, xchildw;
2457  UInt_t xmask;
2458 
2459  XQueryPointer((Display*)fDisplay, (Window) id, &xrootw, &xchildw,
2460  &root_x, &root_y, &win_x, &win_y, &xmask);
2461 
2462  rootw = (Window_t) xrootw;
2463  childw = (Window_t) xchildw;
2464 
2465  MapModifierState(mask, xmask, kFALSE);
2466 }
2467 
2468 ////////////////////////////////////////////////////////////////////////////////
2469 /// Set foreground color in graphics context (shortcut for ChangeGC with
2470 /// only foreground mask set).
2471 
2472 void TGX11::SetForeground(GContext_t gc, ULong_t foreground)
2473 {
2474  XSetForeground((Display*)fDisplay, (GC) gc, foreground);
2475 }
2476 
2477 ////////////////////////////////////////////////////////////////////////////////
2478 /// Set clipping rectangles in graphics context. X, Y specify the origin
2479 /// of the rectangles. Recs specifies an array of rectangles that define
2480 /// the clipping mask and n is the number of rectangles.
2481 
2482 void TGX11::SetClipRectangles(GContext_t gc, Int_t x, Int_t y, Rectangle_t *recs, Int_t n)
2483 {
2484  XSetClipRectangles((Display*)fDisplay, (GC) gc, x, y, (XRectangle *) recs, n, Unsorted);
2485 }
2486 
2487 ////////////////////////////////////////////////////////////////////////////////
2488 /// Flush (mode = 0, default) or synchronize (mode = 1) X output buffer.
2489 /// Flush flushes output buffer. Sync flushes buffer and waits till all
2490 /// requests have been processed by X server.
2491 
2492 void TGX11::Update(Int_t mode)
2493 {
2494  if (mode == 0)
2495  XFlush((Display*)fDisplay);
2496  if (mode == 1)
2497  XSync((Display*)fDisplay, False);
2498 }
2499 
2500 ////////////////////////////////////////////////////////////////////////////////
2501 /// Create a new empty region.
2502 
2503 Region_t TGX11::CreateRegion()
2504 {
2505  return (Region_t) XCreateRegion();
2506 }
2507 
2508 ////////////////////////////////////////////////////////////////////////////////
2509 /// Destroy region.
2510 
2511 void TGX11::DestroyRegion(Region_t reg)
2512 {
2513  XDestroyRegion((Region)reg);
2514 }
2515 
2516 ////////////////////////////////////////////////////////////////////////////////
2517 /// Union of rectangle with a region.
2518 
2519 void TGX11::UnionRectWithRegion(Rectangle_t *rect, Region_t src, Region_t dest)
2520 {
2521  XRectangle *r = (XRectangle *) rect; // 1 on 1 mapping
2522  XUnionRectWithRegion(r, (Region) src, (Region) dest);
2523 }
2524 
2525 ////////////////////////////////////////////////////////////////////////////////
2526 /// Create region for the polygon defined by the points array.
2527 /// If winding is true use WindingRule else EvenOddRule as fill rule.
2528 
2529 Region_t TGX11::PolygonRegion(Point_t *points, Int_t np, Bool_t winding)
2530 {
2531  XPoint *p = (XPoint *) points;
2532  return (Region_t) XPolygonRegion(p, np, winding ? WindingRule : EvenOddRule);
2533 }
2534 
2535 ////////////////////////////////////////////////////////////////////////////////
2536 /// Compute the union of rega and regb and return result region.
2537 /// The output region may be the same result region.
2538 
2539 void TGX11::UnionRegion(Region_t rega, Region_t regb, Region_t result)
2540 {
2541  XUnionRegion((Region) rega, (Region) regb, (Region) result);
2542 }
2543 
2544 ////////////////////////////////////////////////////////////////////////////////
2545 /// Compute the intersection of rega and regb and return result region.
2546 /// The output region may be the same as the result region.
2547 
2548 void TGX11::IntersectRegion(Region_t rega, Region_t regb, Region_t result)
2549 {
2550  XIntersectRegion((Region) rega, (Region) regb, (Region) result);
2551 }
2552 
2553 ////////////////////////////////////////////////////////////////////////////////
2554 /// Subtract rega from regb.
2555 
2556 void TGX11::SubtractRegion(Region_t rega, Region_t regb, Region_t result)
2557 {
2558  XSubtractRegion((Region) rega, (Region) regb, (Region) result);
2559 }
2560 
2561 ////////////////////////////////////////////////////////////////////////////////
2562 /// Calculate the difference between the union and intersection of
2563 /// two regions.
2564 
2565 void TGX11::XorRegion(Region_t rega, Region_t regb, Region_t result)
2566 {
2567  XXorRegion((Region) rega, (Region) regb, (Region) result);
2568 }
2569 
2570 ////////////////////////////////////////////////////////////////////////////////
2571 /// Return true if the region is empty.
2572 
2573 Bool_t TGX11::EmptyRegion(Region_t reg)
2574 {
2575  return (Bool_t) XEmptyRegion((Region) reg);
2576 }
2577 
2578 ////////////////////////////////////////////////////////////////////////////////
2579 /// Returns true if the point x,y is in the region.
2580 
2581 Bool_t TGX11::PointInRegion(Int_t x, Int_t y, Region_t reg)
2582 {
2583  return (Bool_t) XPointInRegion((Region) reg, x, y);
2584 }
2585 
2586 ////////////////////////////////////////////////////////////////////////////////
2587 /// Returns true if two regions are equal.
2588 
2589 Bool_t TGX11::EqualRegion(Region_t rega, Region_t regb)
2590 {
2591  return (Bool_t) XEqualRegion((Region) rega, (Region) regb);
2592 }
2593 
2594 ////////////////////////////////////////////////////////////////////////////////
2595 /// Return smallest enclosing rectangle.
2596 
2597 void TGX11::GetRegionBox(Region_t reg, Rectangle_t *rect)
2598 {
2599  XClipBox((Region) reg, (XRectangle*) rect);
2600 }
2601 
2602 ////////////////////////////////////////////////////////////////////////////////
2603 /// Return list of font names matching fontname regexp, like "-*-times-*".
2604 
2605 char **TGX11::ListFonts(const char *fontname, Int_t max, Int_t &count)
2606 {
2607  char **fontlist;
2608  Int_t fontcount = 0;
2609  fontlist = XListFonts((Display*)fDisplay, (char *)fontname, max, &fontcount);
2610  count = fontcount;
2611  return fontlist;
2612 }
2613 
2614 ////////////////////////////////////////////////////////////////////////////////
2615 /// Free list of font names.
2616 
2617 void TGX11::FreeFontNames(char **fontlist)
2618 {
2619  XFreeFontNames(fontlist);
2620 }
2621 
2622 ////////////////////////////////////////////////////////////////////////////////
2623 /// Create a client-side XImage. Returns handle to XImage.
2624 
2625 Drawable_t TGX11::CreateImage(UInt_t width, UInt_t height)
2626 {
2627  Int_t bitmap_pad;
2628 
2629  if (fDepth <= 8)
2630  bitmap_pad = 8;
2631  else if (fDepth <= 16)
2632  bitmap_pad = 16;
2633  else
2634  bitmap_pad = 32;
2635 
2636  XImage *xim = XCreateImage((Display*)fDisplay, fVisual, fDepth, ZPixmap,
2637  0, 0, width, height, bitmap_pad, 0);
2638 
2639  // use calloc since Xlib will use free() in XDestroyImage
2640  if (xim) xim->data = (char *) calloc(xim->bytes_per_line * xim->height, 1);
2641 
2642  return (Drawable_t) xim;
2643 }
2644 
2645 ////////////////////////////////////////////////////////////////////////////////
2646 /// Get size of XImage img.
2647 
2648 void TGX11::GetImageSize(Drawable_t img, UInt_t &width, UInt_t &height)
2649 {
2650  width = ((XImage*)img)->width;
2651  height = ((XImage*)img)->height;
2652 }
2653 
2654 ////////////////////////////////////////////////////////////////////////////////
2655 /// Set pixel at specified location in XImage img.
2656 
2657 void TGX11::PutPixel(Drawable_t img, Int_t x, Int_t y, ULong_t pixel)
2658 {
2659  XPutPixel((XImage*) img, x, y, pixel);
2660 }
2661 
2662 ////////////////////////////////////////////////////////////////////////////////
2663 /// Put (x,y,w,h) part of image img in window win at position dx,dy.
2664 
2665 void TGX11::PutImage(Drawable_t win, GContext_t gc, Drawable_t img, Int_t dx,
2666  Int_t dy, Int_t x, Int_t y, UInt_t w, UInt_t h)
2667 {
2668  if (!win) return;
2669 
2670  XPutImage((Display*)fDisplay, (Drawable) win, (GC) gc, (XImage*) img,
2671  x, y, dx, dy, w, h);
2672 }
2673 
2674 ////////////////////////////////////////////////////////////////////////////////
2675 /// Destroy XImage img.
2676 
2677 void TGX11::DeleteImage(Drawable_t img)
2678 {
2679  XDestroyImage((XImage*) img);
2680 }
2681 
2682 ////////////////////////////////////////////////////////////////////////////////
2683 /// The Nonrectangular Window Shape Extension adds nonrectangular
2684 /// windows to the System.
2685 /// This allows for making shaped (partially transparent) windows
2686 
2687 void TGX11::ShapeCombineMask(Window_t id, Int_t x, Int_t y, Pixmap_t mask)
2688 {
2689  XShapeCombineMask((Display*)fDisplay, (Window) id, ShapeBounding, x, y,
2690  (Pixmap) mask, ShapeSet);
2691 }
2692 
2693 ////////////////////////////////////////////////////////////////////////////////
2694 /// Returns the width of the screen in millimeters.
2695 
2696 UInt_t TGX11::ScreenWidthMM() const
2697 {
2698  return (UInt_t)WidthMMOfScreen(DefaultScreenOfDisplay((Display*)fDisplay));
2699 }
2700 
2701 ////////////////////////////////////////////////////////////////////////////////
2702 /// Deletes the specified property only if the property was defined on the
2703 /// specified window and causes the X server to generate a PropertyNotify
2704 /// event on the window unless the property does not exist.
2705 
2706 void TGX11::DeleteProperty(Window_t win, Atom_t& prop)
2707 {
2708  XDeleteProperty((Display*)fDisplay, win, prop);
2709 }
2710 
2711 ////////////////////////////////////////////////////////////////////////////////
2712 /// Returns the actual type of the property; the actual format of the property;
2713 /// the number of 8-bit, 16-bit, or 32-bit items transferred; the number of
2714 /// bytes remaining to be read in the property; and a pointer to the data
2715 /// actually returned.
2716 
2717 Int_t TGX11::GetProperty(Window_t win, Atom_t prop, Long_t offset, Long_t length,
2718  Bool_t del, Atom_t req_type, Atom_t *act_type,
2719  Int_t *act_format, ULong_t *nitems, ULong_t *bytes,
2720  unsigned char **prop_list)
2721 {
2722  return XGetWindowProperty((Display*)fDisplay, win, prop, offset, length, del, req_type,
2723  act_type, act_format, nitems, bytes, prop_list);
2724 }
2725 
2726 ////////////////////////////////////////////////////////////////////////////////
2727 /// Changes the specified dynamic parameters if the pointer is actively
2728 /// grabbed by the client.
2729 
2730 void TGX11::ChangeActivePointerGrab(Window_t /*win*/, UInt_t mask, Cursor_t cur)
2731 {
2732  UInt_t xevmask;
2733  MapEventMask(mask, xevmask);
2734  if (cur == kNone)
2735  XChangeActivePointerGrab((Display*)fDisplay, xevmask, fCursors[kHand], CurrentTime);
2736  else
2737  XChangeActivePointerGrab((Display*)fDisplay, xevmask, cur, CurrentTime);
2738 }
2739 
2740 ////////////////////////////////////////////////////////////////////////////////
2741 /// Requests that the specified selection be converted to the specified
2742 /// target type.
2743 
2744 void TGX11::ConvertSelection(Window_t win, Atom_t &sel, Atom_t &target,
2745  Atom_t &prop, Time_t &stamp)
2746 {
2747  XConvertSelection((Display*)fDisplay, sel, target, prop, win, stamp);
2748 }
2749 
2750 ////////////////////////////////////////////////////////////////////////////////
2751 /// Changes the owner and last-change time for the specified selection
2752 
2753 Bool_t TGX11::SetSelectionOwner(Window_t owner, Atom_t &sel)
2754 {
2755  return XSetSelectionOwner((Display*)fDisplay, sel, owner, CurrentTime);
2756 }
2757 
2758 ////////////////////////////////////////////////////////////////////////////////
2759 /// This function alters the property for the specified window and
2760 /// causes the X server to generate a PropertyNotify event on that
2761 /// window.
2762 
2763 void TGX11::ChangeProperties(Window_t id, Atom_t property, Atom_t type,
2764  Int_t format, UChar_t *data, Int_t len)
2765 {
2766  if (!id) return;
2767 
2768  XChangeProperty((Display*)fDisplay, (Window) id, (Atom) property, (Atom) type,
2769  format, PropModeReplace, data, len);
2770 }
2771 
2772 ////////////////////////////////////////////////////////////////////////////////
2773 /// Add XdndAware property and the list of drag and drop types to the
2774 /// Window win.
2775 
2776 void TGX11::SetDNDAware(Window_t win, Atom_t *typelist)
2777 {
2778  unsigned char version = 4;
2779  Atom_t dndaware = InternAtom("XdndAware", kFALSE);
2780  XChangeProperty((Display*)fDisplay, (Window) win, (Atom) dndaware, (Atom) XA_ATOM,
2781  32, PropModeReplace, (unsigned char *) &version, 1);
2782 
2783  if (typelist) {
2784  int n;
2785 
2786  for (n = 0; typelist[n]; n++) { }
2787  if (n > 0) {
2788  XChangeProperty((Display*)fDisplay, win, dndaware, XA_ATOM, 32, PropModeAppend,
2789  (unsigned char *) typelist, n);
2790  }
2791  }
2792 }
2793 
2794 ////////////////////////////////////////////////////////////////////////////////
2795 /// Add the list of drag and drop types to the Window win.
2796 
2797 void TGX11::SetTypeList(Window_t win, Atom_t prop, Atom_t *typelist)
2798 {
2799  if (typelist) {
2800  int n;
2801  for (n = 0; typelist[n]; n++) { }
2802  if (n > 0) {
2803  XChangeProperty((Display*)fDisplay, win, prop, XA_ATOM, 32, PropModeAppend,
2804  (unsigned char *) typelist, n);
2805  }
2806  }
2807 }
2808 
2809 ////////////////////////////////////////////////////////////////////////////////
2810 /// Recursively search in the children of Window for a Window which is at
2811 /// location x, y and is DND aware, with a maximum depth of maxd.
2812 /// Possibility to exclude dragwin and input.
2813 
2814 Window_t TGX11::FindRWindow(Window_t win, Window_t dragwin, Window_t input,
2815  int x, int y, int maxd)
2816 {
2817  WindowAttributes_t wattr;
2818  static Atom_t *dndTypeList = 0;
2819 
2820  if (dndTypeList == 0) {
2821  dndTypeList = new Atom_t[3];
2822  dndTypeList[0] = InternAtom("application/root", kFALSE);
2823  dndTypeList[1] = InternAtom("text/uri-list", kFALSE);
2824  dndTypeList[2] = 0;
2825  }
2826 
2827  if (maxd <= 0) return kNone;
2828 
2829  if (win == dragwin || win == input) return kNone;
2830 
2831  GetWindowAttributes(win, wattr);
2832  if (wattr.fMapState != kIsUnmapped &&
2833  x >= wattr.fX && x < wattr.fX + wattr.fWidth &&
2834  y >= wattr.fY && y < wattr.fY + wattr.fHeight) {
2835 
2836  if (IsDNDAware(win, dndTypeList)) return win;
2837 
2838  Window r, p, *children;
2839  UInt_t numch;
2840  int i;
2841 
2842  if (XQueryTree((Display*)fDisplay, win, &r, &p, &children, &numch)) {
2843  if (children && numch > 0) {
2844  r = kNone;
2845  // upon return from XQueryTree, children are listed in the current
2846  // stacking order, from bottom-most (first) to top-most (last)
2847  for (i = numch-1; i >= 0; --i) {
2848  r = FindRWindow((Window_t)children[i], dragwin, input,
2849  x - wattr.fX, y - wattr.fY, maxd-1);
2850  if (r != kNone) break;
2851  }
2852  XFree(children);
2853  if (r != kNone) return r;
2854  }
2855  return kNone; //win; // ?!?
2856  }
2857  }
2858  return kNone;
2859 }
2860 
2861 ////////////////////////////////////////////////////////////////////////////////
2862 /// Checks if Window win is DND aware, and knows any of the DND formats
2863 /// passed in argument.
2864 
2865 Bool_t TGX11::IsDNDAware(Window_t win, Atom_t *typelist)
2866 {
2867  Atom_t actual;
2868  Int_t format;
2869  ULong_t count, remaining;
2870  unsigned char *data = 0;
2871  Atom_t *types, *t;
2872  Int_t result = kTRUE;
2873  static Atom_t dndaware = kNone;
2874 
2875  if (win == kNone) return kFALSE;
2876 
2877  if (dndaware == kNone)
2878  dndaware = InternAtom("XdndAware", kFALSE);
2879 
2880  XGetWindowProperty((Display*)fDisplay, win, dndaware, 0, 0x8000000L, kFALSE,
2881  XA_ATOM, &actual, &format, &count, &remaining, &data);
2882 
2883  if ((actual != XA_ATOM) || (format != 32) || (count == 0) || !data) {
2884  if (data) XFree(data);
2885  return kFALSE;
2886  }
2887 
2888  types = (Atom_t *) data;
2889 
2890  if ((count > 1) && typelist) {
2891  result = kFALSE;
2892  for (t = typelist; *t; t++) {
2893  for (ULong_t j = 1; j < count; j++) {
2894  if (types[j] == *t) {
2895  result = kTRUE;
2896  break;
2897  }
2898  }
2899  if (result) break;
2900  }
2901  }
2902  XFree(data);
2903  return result;
2904 }