Back to home page

EIC code displayed by LXR

 
 

    


Warning, /include/Geant4/toolx/X11/base_session is written in an unsupported language. File is not indexed.

0001 // Copyright (C) 2010, Guy Barrand. All rights reserved.
0002 // See the file tools.license for terms.
0003 
0004 #ifndef toolx_X11_base_session
0005 #define toolx_X11_base_session
0006 
0007 // pure X11 code, no GL.
0008 
0009 #include <ostream>
0010 #include <vector>
0011 
0012 #include "dispatcher"
0013 #include <tools/forit>
0014 
0015 #include <X11/Xatom.h>     //XA_INTEGER
0016 
0017 #include <X11/Xutil.h>     //XVisualInfo
0018 
0019 namespace toolx {
0020 namespace X11 {
0021 
0022 class base_session {
0023 public:
0024   //virtual bool make_current(Window) const {
0025   //  if(!m_display) return false;
0026   //  return true;
0027   //}
0028   //virtual bool swap_buffers(Window) const {
0029   //  if(!m_display) return false;
0030   //  return true;
0031   //}
0032 public:
0033   base_session(std::ostream& a_out,unsigned int a_monitor = 0)
0034   :m_out(a_out)
0035   ,m_monitor(a_monitor)
0036   ,m_display(0)
0037   ,m_WM_DELETE_WINDOW_atom(None)
0038   ,m_SESSION_EXIT_STEER_atom(None)
0039   {
0040     //NOTE : macOS : XOpenDisplay leaks 128 bytes.
0041     m_display = ::XOpenDisplay(NULL);
0042     if(!m_display) {
0043       m_out << "toolx::X11::base_session::base_session : can't open display." << std::endl;
0044       return;
0045     }
0046 
0047     int monitors = ::XScreenCount(m_display);
0048     if(int(m_monitor)>=monitors) {
0049       m_out << "toolx::X11::base_session::base_session : bad monitor index "
0050             << m_monitor << ". (#monitors " << monitors << ")." << std::endl;
0051       ::XCloseDisplay(m_display);
0052       m_display = 0;
0053       return;
0054     }
0055 
0056     m_WM_DELETE_WINDOW_atom = ::XInternAtom(m_display,"WM_DELETE_WINDOW",False);
0057     if(m_WM_DELETE_WINDOW_atom==None) {
0058       m_out << "toolx::X11::base_session::base_session : can't create WM_DELETE_WINDOW Atom." << std::endl;
0059       ::XCloseDisplay(m_display);
0060       m_display = 0;
0061       return;
0062     }
0063 
0064     m_SESSION_EXIT_STEER_atom = ::XInternAtom(m_display,"TOOLX_X11_SESSION_EXIT_STEER",False);
0065     if(m_SESSION_EXIT_STEER_atom==None) {
0066       m_out << "toolx::X11::base_session::base_session :"
0067             << " can't create TOOLX_X11_SESSION_EXIT_STEER Atom." << std::endl;
0068       ::XCloseDisplay(m_display);
0069       m_display = 0;
0070       return;
0071     }
0072   }
0073   virtual ~base_session() {
0074     clear_dispatchers();
0075     if(m_display) ::XCloseDisplay(m_display);
0076     m_display = 0;
0077     //std::cout << "debug : ~base_session" << std::endl;
0078   }
0079 protected:
0080   base_session(const base_session& a_from)
0081   :m_out(a_from.m_out)
0082   ,m_monitor(a_from.m_monitor)
0083   ,m_display(0)
0084   ,m_WM_DELETE_WINDOW_atom(None)
0085   ,m_SESSION_EXIT_STEER_atom(None)
0086   {}
0087   base_session& operator=(const base_session& a_from){
0088     if(&a_from==this) return *this;
0089     return *this;
0090   }
0091 public:
0092   std::ostream& out() const {return m_out;}
0093 
0094   Atom WM_DELETE_WINDOW_atom() const {return m_WM_DELETE_WINDOW_atom;}
0095   Atom SESSION_EXIT_STEER_atom() const {return m_SESSION_EXIT_STEER_atom;}
0096 
0097   bool is_valid() const {return m_display?true:false;}
0098 
0099   unsigned int monitor() const {return m_monitor;}
0100   Display* display() const {return m_display;}
0101 
0102   bool steer() {
0103     if(!m_display) return false;
0104 
0105     while(true) {
0106       XEvent xevent;
0107       ::XNextEvent(m_display,&xevent);
0108       if(xevent.type==ClientMessage) {
0109         if(xevent.xclient.data.l[0]==(long)m_SESSION_EXIT_STEER_atom) break;
0110       }
0111       dispatch(xevent);
0112     }
0113 
0114     return true;
0115   }
0116 
0117   bool sync() {
0118     if(!m_display) return false;
0119   //::glXWaitX();
0120     ::XSync(m_display,False);
0121     while(true) {
0122       XEvent xevent;
0123       if(::XPending(m_display)) {
0124         ::XNextEvent(m_display,&xevent);
0125         if(xevent.type==ClientMessage) {
0126           if(xevent.xclient.data.l[0]==(long)m_SESSION_EXIT_STEER_atom) return false;
0127         }
0128         dispatch(xevent);
0129       } else {
0130         break;
0131       }
0132     }
0133     return true;
0134   }
0135 
0136   bool event_pending(bool& a_is) {
0137     if(!m_display) {a_is = false;return false;}
0138     a_is = ::XPending(m_display)?true:false;
0139     return true;
0140   }
0141 
0142   bool next_event(bool& a_to_exit) {
0143     if(!m_display) {a_to_exit = false;return false;}
0144     XEvent xevent;
0145     ::XNextEvent(m_display,&xevent);
0146     if(xevent.type==ClientMessage) {
0147       if(xevent.xclient.data.l[0]==(long)m_SESSION_EXIT_STEER_atom) {
0148         a_to_exit = true;
0149         return true;
0150       }
0151     }
0152     dispatch(xevent);
0153     a_to_exit = false;
0154     return true;
0155   }
0156 
0157   bool flush() {
0158     if(!m_display) return false;
0159     ::XFlush(m_display);
0160     return true;
0161   }
0162 
0163 
0164   //////////////////////////////////////////////////
0165   //////////////////////////////////////////////////
0166   //////////////////////////////////////////////////
0167   Window create_window(const char* a_title,int a_x,int a_y,unsigned int a_width,unsigned int a_height) {
0168     if(!m_display) return 0L;
0169 
0170     XSetWindowAttributes swa;
0171     swa.event_mask = StructureNotifyMask | ExposureMask
0172        | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask
0173        | PointerMotionMask
0174        | KeyPressMask;
0175 
0176     swa.background_pixel = ::XWhitePixel(m_display,m_monitor);
0177 
0178     Window window = ::XCreateWindow(m_display,
0179                                     ::XRootWindow(m_display,m_monitor),
0180                                     a_x,a_y,a_width,a_height,
0181                                     0,
0182                                     (int)CopyFromParent,
0183                                     InputOutput,
0184                                     (Visual*)CopyFromParent,
0185                                     CWEventMask|CWBackPixel,&swa);
0186     if(window==0L) {
0187       m_out << "toolx::X11::base_session::create_window : can't create a X11 window." << std::endl;
0188       return 0L;
0189     }
0190 
0191     XTextProperty tp;
0192     ::XStringListToTextProperty((char**)&a_title,1,&tp);
0193     XSizeHints sh;
0194     sh.flags = USPosition | USSize;
0195     ::XSetWMProperties(m_display,window,&tp,&tp,0,0,&sh,0,0);
0196     ::XFree(tp.value);
0197 
0198     ::XSetWMProtocols(m_display,window,&m_WM_DELETE_WINDOW_atom,1);
0199     return window;
0200   }
0201 
0202   void map_raise_window(Window a_window) const {
0203     if(!m_display) return;
0204     ::XMapWindow(m_display,a_window);
0205     ::XRaiseWindow(m_display,a_window);
0206   }
0207 
0208   void show_window(Window a_window) const {
0209     if(!m_display) return;
0210 
0211     XWindowAttributes watbs;
0212     ::XGetWindowAttributes(m_display,a_window,&watbs);
0213     if(watbs.map_state!=IsUnmapped) return;
0214 
0215     ::XMapWindow(m_display,a_window);
0216     ::XRaiseWindow(m_display,a_window);
0217 
0218    {XEvent event;
0219     ::XIfEvent(m_display,&event,wait_map_notify,(char*)a_window);}
0220   }
0221 
0222   void hide_window(Window a_window) const {
0223     if(!m_display) return;
0224 
0225     XWindowAttributes watbs;
0226     ::XGetWindowAttributes(m_display,a_window,&watbs);
0227     if(watbs.map_state==IsUnmapped) return;
0228 
0229     ::XUnmapWindow(m_display,a_window);
0230 
0231    {XEvent event;
0232     ::XIfEvent(m_display,&event,wait_unmap_notify,(char*)a_window);}
0233   }
0234 
0235   void resize_window(Window a_window,unsigned int a_width,unsigned int a_height) const {
0236     if(!m_display) return;
0237     unsigned int mask = CWWidth | CWHeight | CWBorderWidth;
0238     XWindowChanges changes;
0239     changes.border_width = 0;
0240     changes.width = a_width;
0241     changes.height = a_height;
0242     ::XConfigureWindow(m_display,a_window,mask,&changes);
0243   }
0244 
0245   bool window_size(Window a_window,int& a_width,int& a_height) const {
0246     if(!m_display) {a_width = 0;a_height = 0;return false;}
0247     XWindowAttributes watbs;
0248     if(!XGetWindowAttributes(m_display,a_window,&watbs)) {a_width = 0;a_height = 0;return false;}
0249     a_width  = watbs.width;
0250     a_height = watbs.height;
0251     return true;
0252   }
0253 
0254   void delete_window(Window a_window) const {
0255     if(!m_display) return;
0256     ::XDestroyWindow(m_display,a_window);
0257   }
0258 
0259   void set_override_redirect(Window a_window) const {
0260     //must be executed before window is mapped.
0261     if(!m_display) return;
0262     XSetWindowAttributes swa;
0263     swa.override_redirect = True;
0264     ::XChangeWindowAttributes(m_display,a_window,CWOverrideRedirect,&swa);
0265   }
0266 
0267   void set_wm_no_decorations(Window a_window) const {
0268     //must be executed before window is mapped.
0269     if(!m_display) return;
0270 
0271     // struct, mwm_hints_decorations taken from OpenMotif MwmUtils.h.
0272     struct{
0273       unsigned long flags;
0274       unsigned long functions;
0275       unsigned long decorations;
0276       long          inputMode;
0277       unsigned long status;
0278     } prop;
0279 
0280     //unsigned long mwm_hints_functions = 1L << 0;
0281     unsigned long mwm_hints_decorations  = 1L << 1;
0282 
0283     Atom atom = ::XInternAtom(m_display,"_MOTIF_WM_HINTS",False);
0284     if(atom==None) {
0285       m_out << "toolx::X11::base_session::set_wm_no_decorations : can't create/get _MOTIF_WM_HINTS Atom." << std::endl;
0286       return;
0287     }
0288     prop.flags = mwm_hints_decorations;
0289     prop.functions = 0;
0290     prop.decorations = 0;
0291 
0292     ::XChangeProperty(m_display,a_window,atom,atom,32,PropModeReplace,(unsigned char*)&prop,5);
0293   }
0294 
0295   bool post(Window a_win,
0296             long a_0 = 0,long a_1 = 0,
0297             long a_2 = 0,long a_3 = 0,
0298             long a_4 = 0) const {
0299     if(!m_display) return false;
0300     XEvent event;
0301     event.type = ClientMessage;
0302     event.xclient.display = m_display;
0303     event.xclient.window = a_win;
0304     event.xclient.message_type = XA_INTEGER;
0305     event.xclient.format = 8;    /* put 8 because bug with 32 on VMCMS */
0306     event.xclient.data.l[0] = a_0;
0307     event.xclient.data.l[1] = a_1;
0308     event.xclient.data.l[2] = a_2;
0309     event.xclient.data.l[3] = a_3;
0310     event.xclient.data.l[4] = a_4;
0311     //lock();
0312     Status stat = ::XSendEvent(m_display,a_win,False,0L,&event);
0313     ::XFlush(m_display);
0314     //unlock();
0315     return (stat==0?false:true);
0316   }
0317 
0318   bool post_EXIT_STEER(Window a_win) {
0319     return post(a_win,SESSION_EXIT_STEER_atom());
0320   }
0321 
0322   //////////////////////////////////////////////////
0323   //////////////////////////////////////////////////
0324   //////////////////////////////////////////////////
0325   void add_dispatcher(dispatcher* a_dispatcher) {
0326     m_dispatchers.push_back(a_dispatcher); //take ownership.
0327   }
0328 
0329   void invalidate_dispatchers_with_window(Window a_win){
0330     tools_vforit(dispatcher*,m_dispatchers,it) {
0331       if((*it)->window()==a_win) (*it)->invalidate();
0332     }
0333   }
0334 
0335   void remove_dispatchers_with_window(Window a_win){
0336     tools_vforit_npp(dispatcher*,m_dispatchers,it) {
0337       if((*it)->window()==a_win) {
0338         dispatcher* obj = *it;
0339         it = m_dispatchers.erase(it);
0340         delete obj;
0341       } else {
0342         it++;
0343       }
0344     }
0345   }
0346 
0347   bool dispatch(XEvent& a_event) {
0348    {tools_vforit_npp(dispatcher*,m_dispatchers,it) {
0349       if(!(*it)->is_valid()) {
0350         dispatcher* obj = *it;
0351         it = m_dispatchers.erase(it);
0352         delete obj;
0353       } else {
0354         it++;
0355       }
0356     }}
0357     tools_vforit(dispatcher*,m_dispatchers,it) {
0358       if((*it)->is_valid()) {
0359         if((*it)->dispatch(a_event)) return true;
0360       }
0361     }
0362     return false;
0363   }
0364 protected:
0365   static Bool wait_map_notify(Display*,XEvent* a_event,char* a_arg){
0366     return (a_event->type == MapNotify) && (a_event->xmap.window == (Window)a_arg);
0367   }
0368   static Bool wait_unmap_notify(Display*,XEvent* a_event,char* a_arg){
0369     return (a_event->type == UnmapNotify) && (a_event->xmap.window == (Window)a_arg);
0370   }
0371 
0372 /*
0373   void wait_xxx(Window a_window) {
0374     if(!m_display) return;
0375    {wait_what arg;
0376     arg.m_event_type = ConfigureNotify;
0377     arg.m_window = a_window;
0378     XEvent event;
0379     ::XIfEvent(m_display,&event,wait_for,(char*)&arg);
0380     dispatch(event);}
0381   }
0382 
0383   struct wait_what {
0384     int m_event_type;
0385     Window m_window;
0386   };
0387   static Bool wait_for(Display*,XEvent* a_event,char* a_arg){
0388     wait_what* arg = (wait_what*)a_arg;
0389     return (a_event->type == arg->m_event_type) &&
0390            (a_event->xmap.window == arg->m_window);
0391   }
0392 */
0393 
0394   void clear_dispatchers() {
0395     tools_vforit_npp(dispatcher*,m_dispatchers,it) {
0396       dispatcher* obj = *it;
0397       it = m_dispatchers.erase(it);
0398       delete obj;
0399     }
0400     m_dispatchers.clear();
0401   }
0402 
0403 protected:
0404   std::ostream& m_out;
0405   unsigned int  m_monitor;
0406   Display*      m_display;
0407   Atom          m_WM_DELETE_WINDOW_atom;
0408   Atom          m_SESSION_EXIT_STEER_atom;
0409   std::vector<dispatcher*> m_dispatchers;
0410 };
0411 
0412 }}
0413 
0414 
0415 #endif
0416