00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include "GUI/XWinManaged.H"
00039
00040 #include "Image/Image.H"
00041 #include "Image/Pixels.H"
00042 #include "Util/log.H"
00043 #include "Util/sformat.H"
00044 #include "rutz/mutex.h"
00045
00046 #include <stdlib.h>
00047 #include <unistd.h>
00048 #include <X11/Xutil.h>
00049
00050 namespace
00051 {
00052 const int SLEEPTIME = 10000;
00053
00054 const long g_event_mask = (ExposureMask |
00055 ButtonPressMask | KeyPressMask);
00056
00057 const unsigned int g_max_queue_len = 32;
00058 }
00059
00060
00061 void XWinManaged::init()
00062 {
00063 this->selectInput(g_event_mask);
00064
00065 deleteAtom = this->setWMProtocol("WM_DELETE_WINDOW");
00066
00067 windowPresent.atomic_set(1);
00068 itsTraceEvents.atomic_set(0);
00069
00070 if (0 != pthread_mutex_init(&itsEventsMutex, NULL))
00071 LFATAL("pthread_mutex_init() failed");
00072
00073 if (0 != pthread_create(&eventLoopThread, NULL, &cEventLoop, this))
00074 LFATAL("Cannot create thread");
00075 }
00076
00077
00078 XWinManaged::XWinManaged(const Dims& dims,
00079 const int x, const int y, const char* title)
00080 :
00081 XWindow(dims, x, y, title),
00082 toBeClosed(false)
00083 {
00084 init();
00085 }
00086
00087
00088
00089 XWinManaged::XWinManaged(const Image< PixRGB<byte> >& img,
00090 const char* title)
00091 :
00092 XWindow(img.getDims(), -1, -1, title),
00093 toBeClosed(false)
00094 {
00095 init();
00096 XWindow::drawImage(img);
00097 }
00098
00099
00100
00101 XWinManaged::XWinManaged(const Image<byte>& img, const char* title)
00102 :
00103 XWindow(img.getDims(), -1, -1, title),
00104 toBeClosed(false)
00105 {
00106 init();
00107 XWindow::drawImage(img);
00108 }
00109
00110
00111 XWinManaged::XWinManaged(const Image<float>& img, const char* title,
00112 bool normalize)
00113 :
00114 XWindow(img.getDims(), -1, -1, title),
00115 toBeClosed(false)
00116 {
00117 init();
00118 drawImage(img,0,0,normalize);
00119 }
00120
00121
00122
00123 XWinManaged::~XWinManaged()
00124 {
00125 windowPresent.atomic_set(0);
00126
00127 if (0 != pthread_join(eventLoopThread, NULL))
00128 LERROR("Thread is not returning");
00129
00130 if (0 != pthread_mutex_destroy(&itsEventsMutex))
00131 LERROR("pthread_mutex_destroy() failed");
00132 }
00133
00134
00135 void* XWinManaged::cEventLoop(void* xself)
00136 {
00137 XWinManaged* self = static_cast<XWinManaged*>(xself);
00138
00139 while (1)
00140 {
00141 if (!self->windowPresent.atomic_get())
00142 break;
00143
00144
00145 XEvent event;
00146 const Bool status1 = self->checkMaskEvent(g_event_mask, &event);
00147
00148 if (True == status1)
00149 self->eventHandler(&event);
00150
00151
00152
00153
00154
00155
00156 const Bool status2 = self->checkTypedEvent(ClientMessage, &event);
00157
00158 if (True == status2)
00159 self->eventHandler(&event);
00160
00161 if (False == status1 && False == status2)
00162
00163
00164 usleep (SLEEPTIME);
00165 }
00166 pthread_exit(NULL);
00167 return 0;
00168 }
00169
00170
00171 void XWinManaged::eventHandler(XEvent* event)
00172 {
00173 if (itsTraceEvents.atomic_get() > 0 || MYLOGVERB >= LOG_DEBUG)
00174 LINFO("%s in window '%s'...",
00175 describeEvent(event).c_str(), this->getTitle());
00176
00177 switch(event->type)
00178 {
00179
00180 case ClientMessage:
00181 {
00182 if (event->xclient.data.l[0] == (int)deleteAtom)
00183 {
00184
00185 toBeClosed = true;
00186 }
00187 }
00188 break;
00189
00190 case Expose:
00191 {
00192 while (this->checkMaskEvent(ExposureMask, event))
00193 { }
00194
00195 this->redrawImage();
00196 }
00197 break;
00198
00199 case KeyPress:
00200 {
00201 GVX_MUTEX_LOCK(&itsEventsMutex);
00202 itsKeyEvents.push_back(event->xkey);
00203 if (itsKeyEvents.size() > g_max_queue_len)
00204 itsKeyEvents.pop_front();
00205 }
00206 break;
00207
00208 case ButtonPress:
00209 {
00210 GVX_MUTEX_LOCK(&itsEventsMutex);
00211 itsButtonEvents.push_back(event->xbutton);
00212 if (itsButtonEvents.size() > g_max_queue_len)
00213 itsButtonEvents.pop_front();
00214 }
00215 break;
00216 }
00217 }
00218
00219
00220 void XWinManaged::setTraceEvents(bool on)
00221 {
00222 itsTraceEvents.atomic_set(on ? 1 : 0);
00223 }
00224
00225
00226 int XWinManaged::getLastKeyPress()
00227 {
00228 XKeyEvent ev;
00229 if (!this->getLastKeyEvent(&ev))
00230 return -1;
00231
00232 return ev.keycode;
00233 }
00234
00235
00236 std::string XWinManaged::getLastKeyString()
00237 {
00238 XKeyEvent ev;
00239 if (!this->getLastKeyEvent(&ev))
00240 return std::string();
00241
00242 char buf[30];
00243 const int len =
00244 XLookupString(&ev, &buf[0], sizeof(buf), 0, 0);
00245 (void) len;
00246 buf[sizeof(buf)-1] = '\0';
00247
00248 return std::string(&buf[0]);
00249 }
00250
00251
00252 KeySym XWinManaged::getLastKeySym(std::string* s)
00253 {
00254 XKeyEvent ev;
00255 if (!this->getLastKeyEvent(&ev))
00256 return NoSymbol;
00257
00258 char buf[30];
00259 KeySym keysym;
00260 const int len =
00261 XLookupString(&ev, &buf[0], sizeof(buf), &keysym, 0);
00262 (void) len;
00263 buf[sizeof(buf)-1] = '\0';
00264
00265 if (s != 0)
00266 *s = buf;
00267
00268 return keysym;
00269 }
00270
00271
00272 bool XWinManaged::getLastKeyEvent(XKeyEvent* ev)
00273 {
00274 GVX_MUTEX_LOCK(&itsEventsMutex);
00275 if (itsKeyEvents.empty())
00276 return false;
00277
00278 *ev = itsKeyEvents.front();
00279 itsKeyEvents.pop_front();
00280 return true;
00281 }
00282
00283
00284 Point2D<int> XWinManaged::getLastMouseClick()
00285 {
00286 XButtonEvent ev;
00287 if (!this->getLastButtonEvent(&ev))
00288 return Point2D<int>(-1, -1);
00289
00290 return Point2D<int>(ev.x, ev.y);
00291 }
00292
00293
00294 bool XWinManaged::getLastButtonEvent(XButtonEvent* ev)
00295 {
00296 GVX_MUTEX_LOCK(&itsEventsMutex);
00297 if (itsButtonEvents.empty())
00298 return false;
00299
00300 *ev = itsButtonEvents.front();
00301 itsButtonEvents.pop_front();
00302 return true;
00303 }
00304
00305
00306 std::string XWinManaged::describeKeyEvent(const XKeyEvent* ev) const
00307 {
00308 char buf[30];
00309 KeySym keysym;
00310 XKeyEvent evcopy = *ev;
00311 const int len =
00312 XLookupString(&evcopy, &buf[0], sizeof(buf),
00313 &keysym, 0);
00314
00315 const char* symname = XKeysymToString(keysym);
00316 if (symname == 0)
00317 symname = "VoidSymbol";
00318
00319 if (len > 1)
00320 return sformat("KeyPress code=%d sym=XK_%s (\"%s\")",
00321 ev->keycode, symname, &buf[0]);
00322
00323
00324 return sformat("KeyPress code=%d sym=XK_%s",
00325 ev->keycode, symname);
00326 }
00327
00328
00329 std::string XWinManaged::describeButtonEvent(const XButtonEvent* ev) const
00330 {
00331 return sformat("ButtonPress button #%u at (%d,%d)",
00332 ev->button, ev->x, ev->y);
00333 }
00334
00335
00336 std::string XWinManaged::describeEvent(const XEvent* ev) const
00337 {
00338 switch (ev->type)
00339 {
00340 case ClientMessage:
00341 if (ev->xclient.data.l[0] == (int)deleteAtom)
00342 return "Close button";
00343 else
00344 return "ClientMessage";
00345 break;
00346
00347 case Expose:
00348 return "Expose";
00349 break;
00350
00351 case KeyPress:
00352 return describeKeyEvent(&ev->xkey);
00353 break;
00354
00355 case ButtonPress:
00356 return describeButtonEvent(&ev->xbutton);
00357 break;
00358 }
00359
00360
00361 return "other XEvent";
00362 }
00363
00364
00365
00366
00367
00368