Geant4 Cross Reference |
1 // Copyright (C) 2010, Guy Barrand. All rights 2 // See the file tools.license for terms. 3 4 #ifndef toolx_X11_base_session 5 #define toolx_X11_base_session 6 7 // pure X11 code, no GL. 8 9 #include <ostream> 10 #include <vector> 11 12 #include "dispatcher" 13 #include <tools/forit> 14 15 #include <X11/Xatom.h> //XA_INTEGER 16 17 #include <X11/Xutil.h> //XVisualInfo 18 19 namespace toolx { 20 namespace X11 { 21 22 class base_session { 23 public: 24 //virtual bool make_current(Window) const { 25 // if(!m_display) return false; 26 // return true; 27 //} 28 //virtual bool swap_buffers(Window) const { 29 // if(!m_display) return false; 30 // return true; 31 //} 32 public: 33 base_session(std::ostream& a_out,unsigned in 34 :m_out(a_out) 35 ,m_monitor(a_monitor) 36 ,m_display(0) 37 ,m_WM_DELETE_WINDOW_atom(None) 38 ,m_SESSION_EXIT_STEER_atom(None) 39 { 40 //NOTE : macOS : XOpenDisplay leaks 128 by 41 m_display = ::XOpenDisplay(NULL); 42 if(!m_display) { 43 m_out << "toolx::X11::base_session::base 44 return; 45 } 46 47 int monitors = ::XScreenCount(m_display); 48 if(int(m_monitor)>=monitors) { 49 m_out << "toolx::X11::base_session::base 50 << m_monitor << ". (#monitors " << 51 ::XCloseDisplay(m_display); 52 m_display = 0; 53 return; 54 } 55 56 m_WM_DELETE_WINDOW_atom = ::XInternAtom(m_ 57 if(m_WM_DELETE_WINDOW_atom==None) { 58 m_out << "toolx::X11::base_session::base 59 ::XCloseDisplay(m_display); 60 m_display = 0; 61 return; 62 } 63 64 m_SESSION_EXIT_STEER_atom = ::XInternAtom( 65 if(m_SESSION_EXIT_STEER_atom==None) { 66 m_out << "toolx::X11::base_session::base 67 << " can't create TOOLX_X11_SESSIO 68 ::XCloseDisplay(m_display); 69 m_display = 0; 70 return; 71 } 72 } 73 virtual ~base_session() { 74 clear_dispatchers(); 75 if(m_display) ::XCloseDisplay(m_display); 76 m_display = 0; 77 //std::cout << "debug : ~base_session" << 78 } 79 protected: 80 base_session(const base_session& a_from) 81 :m_out(a_from.m_out) 82 ,m_monitor(a_from.m_monitor) 83 ,m_display(0) 84 ,m_WM_DELETE_WINDOW_atom(None) 85 ,m_SESSION_EXIT_STEER_atom(None) 86 {} 87 base_session& operator=(const base_session& 88 if(&a_from==this) return *this; 89 return *this; 90 } 91 public: 92 std::ostream& out() const {return m_out;} 93 94 Atom WM_DELETE_WINDOW_atom() const {return m 95 Atom SESSION_EXIT_STEER_atom() const {return 96 97 bool is_valid() const {return m_display?true 98 99 unsigned int monitor() const {return m_monit 100 Display* display() const {return m_display;} 101 102 bool steer() { 103 if(!m_display) return false; 104 105 while(true) { 106 XEvent xevent; 107 ::XNextEvent(m_display,&xevent); 108 if(xevent.type==ClientMessage) { 109 if(xevent.xclient.data.l[0]==(long)m_S 110 } 111 dispatch(xevent); 112 } 113 114 return true; 115 } 116 117 bool sync() { 118 if(!m_display) return false; 119 //::glXWaitX(); 120 ::XSync(m_display,False); 121 while(true) { 122 XEvent xevent; 123 if(::XPending(m_display)) { 124 ::XNextEvent(m_display,&xevent); 125 if(xevent.type==ClientMessage) { 126 if(xevent.xclient.data.l[0]==(long)m 127 } 128 dispatch(xevent); 129 } else { 130 break; 131 } 132 } 133 return true; 134 } 135 136 bool event_pending(bool& a_is) { 137 if(!m_display) {a_is = false;return false; 138 a_is = ::XPending(m_display)?true:false; 139 return true; 140 } 141 142 bool next_event(bool& a_to_exit) { 143 if(!m_display) {a_to_exit = false;return f 144 XEvent xevent; 145 ::XNextEvent(m_display,&xevent); 146 if(xevent.type==ClientMessage) { 147 if(xevent.xclient.data.l[0]==(long)m_SES 148 a_to_exit = true; 149 return true; 150 } 151 } 152 dispatch(xevent); 153 a_to_exit = false; 154 return true; 155 } 156 157 bool flush() { 158 if(!m_display) return false; 159 ::XFlush(m_display); 160 return true; 161 } 162 163 164 //////////////////////////////////////////// 165 //////////////////////////////////////////// 166 //////////////////////////////////////////// 167 Window create_window(const char* a_title,int 168 if(!m_display) return 0L; 169 170 XSetWindowAttributes swa; 171 swa.event_mask = StructureNotifyMask | Exp 172 | ButtonPressMask | ButtonReleaseMask | 173 | PointerMotionMask 174 | KeyPressMask; 175 176 swa.background_pixel = ::XWhitePixel(m_dis 177 178 Window window = ::XCreateWindow(m_display, 179 ::XRootWin 180 a_x,a_y,a_ 181 0, 182 (int)CopyF 183 InputOutpu 184 (Visual*)C 185 CWEventMask|CWBackPixel,&swa); 186 if(window==0L) { 187 m_out << "toolx::X11::base_session::crea 188 return 0L; 189 } 190 191 XTextProperty tp; 192 ::XStringListToTextProperty((char**)&a_tit 193 XSizeHints sh; 194 sh.flags = USPosition | USSize; 195 ::XSetWMProperties(m_display,window,&tp,&t 196 ::XFree(tp.value); 197 198 ::XSetWMProtocols(m_display,window,&m_WM_D 199 return window; 200 } 201 202 void map_raise_window(Window a_window) const 203 if(!m_display) return; 204 ::XMapWindow(m_display,a_window); 205 ::XRaiseWindow(m_display,a_window); 206 } 207 208 void show_window(Window a_window) const { 209 if(!m_display) return; 210 211 XWindowAttributes watbs; 212 ::XGetWindowAttributes(m_display,a_window, 213 if(watbs.map_state!=IsUnmapped) return; 214 215 ::XMapWindow(m_display,a_window); 216 ::XRaiseWindow(m_display,a_window); 217 218 {XEvent event; 219 ::XIfEvent(m_display,&event,wait_map_notif 220 } 221 222 void hide_window(Window a_window) const { 223 if(!m_display) return; 224 225 XWindowAttributes watbs; 226 ::XGetWindowAttributes(m_display,a_window, 227 if(watbs.map_state==IsUnmapped) return; 228 229 ::XUnmapWindow(m_display,a_window); 230 231 {XEvent event; 232 ::XIfEvent(m_display,&event,wait_unmap_not 233 } 234 235 void resize_window(Window a_window,unsigned 236 if(!m_display) return; 237 unsigned int mask = CWWidth | CWHeight | C 238 XWindowChanges changes; 239 changes.border_width = 0; 240 changes.width = a_width; 241 changes.height = a_height; 242 ::XConfigureWindow(m_display,a_window,mask 243 } 244 245 bool window_size(Window a_window,int& a_widt 246 if(!m_display) {a_width = 0;a_height = 0;r 247 XWindowAttributes watbs; 248 if(!XGetWindowAttributes(m_display,a_windo 249 a_width = watbs.width; 250 a_height = watbs.height; 251 return true; 252 } 253 254 void delete_window(Window a_window) const { 255 if(!m_display) return; 256 ::XDestroyWindow(m_display,a_window); 257 } 258 259 void set_override_redirect(Window a_window) 260 //must be executed before window is mapped 261 if(!m_display) return; 262 XSetWindowAttributes swa; 263 swa.override_redirect = True; 264 ::XChangeWindowAttributes(m_display,a_wind 265 } 266 267 void set_wm_no_decorations(Window a_window) 268 //must be executed before window is mapped 269 if(!m_display) return; 270 271 // struct, mwm_hints_decorations taken fro 272 struct{ 273 unsigned long flags; 274 unsigned long functions; 275 unsigned long decorations; 276 long inputMode; 277 unsigned long status; 278 } prop; 279 280 //unsigned long mwm_hints_functions = 1L < 281 unsigned long mwm_hints_decorations = 1L 282 283 Atom atom = ::XInternAtom(m_display,"_MOTI 284 if(atom==None) { 285 m_out << "toolx::X11::base_session::set_ 286 return; 287 } 288 prop.flags = mwm_hints_decorations; 289 prop.functions = 0; 290 prop.decorations = 0; 291 292 ::XChangeProperty(m_display,a_window,atom, 293 } 294 295 bool post(Window a_win, 296 long a_0 = 0,long a_1 = 0, 297 long a_2 = 0,long a_3 = 0, 298 long a_4 = 0) const { 299 if(!m_display) return false; 300 XEvent event; 301 event.type = ClientMessage; 302 event.xclient.display = m_display; 303 event.xclient.window = a_win; 304 event.xclient.message_type = XA_INTEGER; 305 event.xclient.format = 8; /* put 8 beca 306 event.xclient.data.l[0] = a_0; 307 event.xclient.data.l[1] = a_1; 308 event.xclient.data.l[2] = a_2; 309 event.xclient.data.l[3] = a_3; 310 event.xclient.data.l[4] = a_4; 311 //lock(); 312 Status stat = ::XSendEvent(m_display,a_win 313 ::XFlush(m_display); 314 //unlock(); 315 return (stat==0?false:true); 316 } 317 318 bool post_EXIT_STEER(Window a_win) { 319 return post(a_win,SESSION_EXIT_STEER_atom( 320 } 321 322 //////////////////////////////////////////// 323 //////////////////////////////////////////// 324 //////////////////////////////////////////// 325 void add_dispatcher(dispatcher* a_dispatcher 326 m_dispatchers.push_back(a_dispatcher); //t 327 } 328 329 void invalidate_dispatchers_with_window(Wind 330 tools_vforit(dispatcher*,m_dispatchers,it) 331 if((*it)->window()==a_win) (*it)->invali 332 } 333 } 334 335 void remove_dispatchers_with_window(Window a 336 tools_vforit_npp(dispatcher*,m_dispatchers 337 if((*it)->window()==a_win) { 338 dispatcher* obj = *it; 339 it = m_dispatchers.erase(it); 340 delete obj; 341 } else { 342 it++; 343 } 344 } 345 } 346 347 bool dispatch(XEvent& a_event) { 348 {tools_vforit_npp(dispatcher*,m_dispatchers 349 if(!(*it)->is_valid()) { 350 dispatcher* obj = *it; 351 it = m_dispatchers.erase(it); 352 delete obj; 353 } else { 354 it++; 355 } 356 }} 357 tools_vforit(dispatcher*,m_dispatchers,it) 358 if((*it)->is_valid()) { 359 if((*it)->dispatch(a_event)) return tr 360 } 361 } 362 return false; 363 } 364 protected: 365 static Bool wait_map_notify(Display*,XEvent* 366 return (a_event->type == MapNotify) && (a_ 367 } 368 static Bool wait_unmap_notify(Display*,XEven 369 return (a_event->type == UnmapNotify) && ( 370 } 371 372 /* 373 void wait_xxx(Window a_window) { 374 if(!m_display) return; 375 {wait_what arg; 376 arg.m_event_type = ConfigureNotify; 377 arg.m_window = a_window; 378 XEvent event; 379 ::XIfEvent(m_display,&event,wait_for,(char 380 dispatch(event);} 381 } 382 383 struct wait_what { 384 int m_event_type; 385 Window m_window; 386 }; 387 static Bool wait_for(Display*,XEvent* a_even 388 wait_what* arg = (wait_what*)a_arg; 389 return (a_event->type == arg->m_event_type 390 (a_event->xmap.window == arg->m_win 391 } 392 */ 393 394 void clear_dispatchers() { 395 tools_vforit_npp(dispatcher*,m_dispatchers 396 dispatcher* obj = *it; 397 it = m_dispatchers.erase(it); 398 delete obj; 399 } 400 m_dispatchers.clear(); 401 } 402 403 protected: 404 std::ostream& m_out; 405 unsigned int m_monitor; 406 Display* m_display; 407 Atom m_WM_DELETE_WINDOW_atom; 408 Atom m_SESSION_EXIT_STEER_atom; 409 std::vector<dispatcher*> m_dispatchers; 410 }; 411 412 }} 413 414 415 #endif 416