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