00001 #include "bcwindowbase.h" 00002 #include "bcwindowevents.h" 00003 #include "bctimer.h" 00004 00005 BC_WindowEvents::BC_WindowEvents(BC_WindowBase *window) 00006 : Thread(1, 0, 0) 00007 { 00008 this->window = window; 00009 done = 0; 00010 } 00011 00012 BC_WindowEvents::~BC_WindowEvents() 00013 { 00014 // First set done, then send dummy event through XSendEvent to unlock the loop in ::run() 00015 done = 1; 00016 XEvent event; 00017 XClientMessageEvent *ptr = (XClientMessageEvent*)&event; 00018 event.type = ClientMessage; 00019 ptr->message_type = XInternAtom(window->display, "DUMMY_XATOM", False); 00020 ptr->format = 32; 00021 XSendEvent(window->display, 00022 window->win, 00023 0, 00024 0, 00025 &event); 00026 window->flush(); 00027 Thread::join(); 00028 } 00029 00030 void BC_WindowEvents::start() 00031 { 00032 done = 0; 00033 Thread::start(); 00034 } 00035 00036 00037 void BC_WindowEvents::run() 00038 { 00039 // Can't cancel in XNextEvent because X server never figures out it's not 00040 // listening anymore and XCloseDisplay locks up. 00041 XEvent *event; 00042 while(!done) 00043 { 00044 // XNextEvent should also be protected by XLockDisplay ... 00045 // Currently implemented is a hackish solution, FIXME 00046 // Impact of this solution on the performance has not been analyzed 00047 00048 // The proper solution is HARD because of : 00049 // 1. idiotic xlib does not have XTryLockDisplay - we will need to _completely_ implement XLockDisplay by ourselves (including cascaded locking - it is not the same as mutex!) 00050 // 2. the locking shemantic inside new lock_window and here will be really tricky, we should: 00051 // in lock_window check wheather BC_WindowEvents is in XNextEvent and it is send custom xevent to break out of the loop and make sure lock is not taken again if lock_window() is waiting on it 00052 // 3. Send custom events from previous point through _separate_ xwindows display connection since XSendEvent would need to be protected by XLockDisplay which obviously can't be 00053 00054 window->lock_window(); 00055 while (XPending(window->display)) 00056 { 00057 event = new XEvent; 00058 XNextEvent(window->display, event); 00059 window->put_event(event); 00060 } 00061 00062 window->unlock_window(); 00063 Timer::delay(20); // sleep 20ms 00064 } 00065 } 00066 00067 00068
1.5.5