Otclient  14/8/2020
x11window.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010-2016 OTClient <https://github.com/edubart/otclient>
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to deal
6  * in the Software without restriction, including without limitation the rights
7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20  * THE SOFTWARE.
21  */
22 
23 #ifndef WIN32
24 
25 #include "x11window.h"
28 #include <unistd.h>
29 
30 #define LSB_BIT_SET(p, n) (p[(n)/8] |= (1 <<((n)%8)))
31 
33 {
34  m_display = nullptr;
35  m_visual = nullptr;
36  m_window = 0;
37  m_rootWindow = 0;
38  m_colormap = 0;
39  m_cursor = 0;
40  m_hiddenCursor = 0;
41  m_xim = nullptr;
42  m_xic = nullptr;
43  m_screen = 0;
44  m_wmDelete = 0;
45  m_minimumSize = Size(600,480);
46  m_size = Size(600,480);
47 
48 #ifdef OPENGL_ES
49  m_eglConfig = 0;
50  m_eglContext = 0;
51  m_eglDisplay = 0;
52  m_eglSurface = 0;
53 #else
54  m_fbConfig = nullptr;
55  m_glxContext = nullptr;
56 #endif
57 
58  m_keyMap[XK_Escape] = Fw::KeyEscape;
59  m_keyMap[XK_Tab] = Fw::KeyTab;
60  m_keyMap[XK_Return] = Fw::KeyEnter;
61  m_keyMap[XK_BackSpace] = Fw::KeyBackspace;
62 
63  m_keyMap[XK_Page_Up] = Fw::KeyPageUp;
64  m_keyMap[XK_Page_Down] = Fw::KeyPageDown;
65  m_keyMap[XK_Home] = Fw::KeyHome;
66  m_keyMap[XK_End] = Fw::KeyEnd;
67  m_keyMap[XK_Insert] = Fw::KeyInsert;
68  m_keyMap[XK_Delete] = Fw::KeyDelete;
69 
70  m_keyMap[XK_Up] = Fw::KeyUp;
71  m_keyMap[XK_Down] = Fw::KeyDown;
72  m_keyMap[XK_Left] = Fw::KeyLeft;
73  m_keyMap[XK_Right] = Fw::KeyRight;
74 
75  m_keyMap[XK_Num_Lock] = Fw::KeyNumLock;
76  m_keyMap[XK_Scroll_Lock] = Fw::KeyScrollLock;
77  m_keyMap[XK_Caps_Lock] = Fw::KeyCapsLock;
78  m_keyMap[XK_Print] = Fw::KeyPrintScreen;
79  m_keyMap[XK_Pause] = Fw::KeyPause;
80 
81  m_keyMap[XK_Control_L] = Fw::KeyCtrl;
82  m_keyMap[XK_Control_R] = Fw::KeyCtrl;
83  m_keyMap[XK_Shift_R] = Fw::KeyShift;
84  m_keyMap[XK_Shift_L] = Fw::KeyShift;
85  m_keyMap[XK_Alt_R] = Fw::KeyAlt;
86  m_keyMap[XK_Alt_L] = Fw::KeyAlt;
87  m_keyMap[XK_Meta_L] = Fw::KeyMeta;
88  m_keyMap[XK_Meta_R] = Fw::KeyMeta;
89  m_keyMap[XK_Menu] = Fw::KeyMenu;
90 
91  // ascii characters
92  m_keyMap[XK_space] = Fw::KeySpace;
93  m_keyMap[XK_exclam] = Fw::KeyExclamation;
94  m_keyMap[XK_quotedbl] = Fw::KeyQuote;
95  m_keyMap[XK_numbersign] = Fw::KeyNumberSign;
96  m_keyMap[XK_dollar] = Fw::KeyDollar;
97  m_keyMap[XK_percent] = Fw::KeyPercent;
98  m_keyMap[XK_ampersand] = Fw::KeyAmpersand;
99  m_keyMap[XK_apostrophe] = Fw::KeyApostrophe;
100  m_keyMap[XK_parenleft] = Fw::KeyLeftParen;
101  m_keyMap[XK_parenright] = Fw::KeyRightParen;
102  m_keyMap[XK_asterisk] = Fw::KeyAsterisk;
103  m_keyMap[XK_plus] = Fw::KeyPlus;
104  m_keyMap[XK_comma] = Fw::KeyComma;
105  m_keyMap[XK_minus] = Fw::KeyMinus;
106  m_keyMap[XK_period] = Fw::KeyPeriod;
107  m_keyMap[XK_slash] = Fw::KeySlash;
108  m_keyMap[XK_1] = Fw::Key1;
109  m_keyMap[XK_2] = Fw::Key2;
110  m_keyMap[XK_3] = Fw::Key3;
111  m_keyMap[XK_4] = Fw::Key4;
112  m_keyMap[XK_5] = Fw::Key5;
113  m_keyMap[XK_6] = Fw::Key6;
114  m_keyMap[XK_7] = Fw::Key7;
115  m_keyMap[XK_8] = Fw::Key8;
116  m_keyMap[XK_9] = Fw::Key9;
117  m_keyMap[XK_0] = Fw::Key0;
118  m_keyMap[XK_colon] = Fw::KeyColon;
119  m_keyMap[XK_semicolon] = Fw::KeySemicolon;
120  m_keyMap[XK_less] = Fw::KeyLess;
121  m_keyMap[XK_equal] = Fw::KeyEqual;
122  m_keyMap[XK_greater] = Fw::KeyGreater;
123  m_keyMap[XK_question] = Fw::KeyQuestion;
124  m_keyMap[XK_at] = Fw::KeyAtSign;
125  m_keyMap[XK_a] = Fw::KeyA;
126  m_keyMap[XK_b] = Fw::KeyB;
127  m_keyMap[XK_c] = Fw::KeyC;
128  m_keyMap[XK_d] = Fw::KeyD;
129  m_keyMap[XK_e] = Fw::KeyE;
130  m_keyMap[XK_f] = Fw::KeyF;
131  m_keyMap[XK_g] = Fw::KeyG;
132  m_keyMap[XK_h] = Fw::KeyH;
133  m_keyMap[XK_i] = Fw::KeyI;
134  m_keyMap[XK_j] = Fw::KeyJ;
135  m_keyMap[XK_k] = Fw::KeyK;
136  m_keyMap[XK_l] = Fw::KeyL;
137  m_keyMap[XK_m] = Fw::KeyM;
138  m_keyMap[XK_n] = Fw::KeyN;
139  m_keyMap[XK_o] = Fw::KeyO;
140  m_keyMap[XK_p] = Fw::KeyP;
141  m_keyMap[XK_q] = Fw::KeyQ;
142  m_keyMap[XK_r] = Fw::KeyR;
143  m_keyMap[XK_s] = Fw::KeyS;
144  m_keyMap[XK_t] = Fw::KeyT;
145  m_keyMap[XK_u] = Fw::KeyU;
146  m_keyMap[XK_v] = Fw::KeyV;
147  m_keyMap[XK_w] = Fw::KeyW;
148  m_keyMap[XK_x] = Fw::KeyX;
149  m_keyMap[XK_y] = Fw::KeyY;
150  m_keyMap[XK_z] = Fw::KeyZ;
151  m_keyMap[XK_bracketleft] = Fw::KeyLeftBracket;
152  m_keyMap[XK_backslash] = Fw::KeyBackslash;
153  m_keyMap[XK_bracketright] = Fw::KeyRightBracket;
154  m_keyMap[XK_asciicircum] = Fw::KeyCaret;
155  m_keyMap[XK_underscore] = Fw::KeyUnderscore;
156  m_keyMap[XK_grave] = Fw::KeyGrave;
157  m_keyMap[XK_braceleft] = Fw::KeyLeftCurly;
158  m_keyMap[XK_bar] = Fw::KeyBar;
159  m_keyMap[XK_braceright] = Fw::KeyRightCurly;
160  m_keyMap[XK_asciitilde] = Fw::KeyTilde;
161 
162  // keypad
163  /*
164  m_keyMap[XK_KP_Add] = Fw::KeyPlus;
165  m_keyMap[XK_KP_Subtract] = Fw::KeyMinus;
166  m_keyMap[XK_KP_Decimal] = Fw::KeyPeriod;
167  m_keyMap[XK_KP_Divide] = Fw::KeySlash;
168  m_keyMap[XK_KP_Multiply] = Fw::KeyAsterisk;
169  */
170  m_keyMap[XK_KP_Enter] = Fw::KeyEnter;
171 
172  // keypad with numlock off
173  m_keyMap[XK_KP_Insert] = Fw::KeyNumpad0;
174  m_keyMap[XK_KP_End] = Fw::KeyNumpad1;
175  m_keyMap[XK_KP_Down] = Fw::KeyNumpad2;
176  m_keyMap[XK_KP_Page_Down] = Fw::KeyNumpad3;
177  m_keyMap[XK_KP_Left] = Fw::KeyNumpad4;
178  m_keyMap[XK_KP_Begin] = Fw::KeyNumpad5;
179  m_keyMap[XK_KP_Right] = Fw::KeyNumpad6;
180  m_keyMap[XK_KP_Home] = Fw::KeyNumpad7;
181  m_keyMap[XK_KP_Up] = Fw::KeyNumpad8;
182  m_keyMap[XK_KP_Page_Up] = Fw::KeyNumpad9;
183  m_keyMap[XK_KP_Delete] = Fw::KeyDelete;
184 
185  // keypad with numlock on
186  m_keyMap[XK_KP_0] = Fw::Key0;
187  m_keyMap[XK_KP_1] = Fw::Key1;
188  m_keyMap[XK_KP_2] = Fw::Key2;
189  m_keyMap[XK_KP_3] = Fw::Key3;
190  m_keyMap[XK_KP_4] = Fw::Key4;
191  m_keyMap[XK_KP_5] = Fw::Key5;
192  m_keyMap[XK_KP_6] = Fw::Key6;
193  m_keyMap[XK_KP_7] = Fw::Key7;
194  m_keyMap[XK_KP_8] = Fw::Key8;
195  m_keyMap[XK_KP_9] = Fw::Key9;
196 
197  m_keyMap[XK_F1] = Fw::KeyF1;
198  m_keyMap[XK_F2] = Fw::KeyF2;
199  m_keyMap[XK_F3] = Fw::KeyF3;
200  m_keyMap[XK_F4] = Fw::KeyF4;
201  m_keyMap[XK_F5] = Fw::KeyF5;
202  m_keyMap[XK_F6] = Fw::KeyF6;
203  m_keyMap[XK_F7] = Fw::KeyF7;
204  m_keyMap[XK_F8] = Fw::KeyF8;
205  m_keyMap[XK_F9] = Fw::KeyF9;
206  m_keyMap[XK_F10] = Fw::KeyF10;
207  m_keyMap[XK_F11] = Fw::KeyF11;
208  m_keyMap[XK_F12] = Fw::KeyF12;
209 }
210 
212 {
213  internalOpenDisplay();
214  internalCheckGL();
215  internalChooseGLVisual();
216  internalCreateGLContext();
217  internalCreateWindow();
218 }
219 
221 {
222  if(m_cursor != None) {
223  XUndefineCursor(m_display, m_window);
224  m_cursor = None;
225  }
226 
227  if(m_hiddenCursor) {
228  XFreeCursor(m_display, m_hiddenCursor);
229  m_hiddenCursor = 0;
230  }
231 
232  for(Cursor cursor : m_cursors)
233  XFreeCursor(m_display, cursor);
234  m_cursors.clear();
235 
236  if(m_window) {
237  XDestroyWindow(m_display, m_window);
238  m_window = 0;
239  }
240 
241  if(m_colormap) {
242  XFreeColormap(m_display, m_colormap);
243  m_colormap = 0;
244  }
245 
246  internalDestroyGLContext();
247 
248  if(m_visual) {
249  XFree(m_visual);
250  m_visual = nullptr;
251  }
252 
253  if(m_xic) {
254  XDestroyIC(m_xic);
255  m_xic = nullptr;
256  }
257 
258  if(m_xim) {
259  XCloseIM(m_xim);
260  m_xim = nullptr;
261  }
262 
263  if(m_display) {
264  XCloseDisplay(m_display);
265  m_display = nullptr;
266  }
267 
268  m_visible = false;
269 }
270 
271 void X11Window::internalOpenDisplay()
272 {
273  m_display = XOpenDisplay(nullptr);
274  if(!m_display)
275  g_logger.fatal("Unable to open X11 display");
276  m_screen = DefaultScreen(m_display);
277 }
278 
279 void X11Window::internalCreateWindow()
280 {
281  Visual *vis;
282  int depth;
283  unsigned int attrsMask;
284  XSetWindowAttributes attrs;
285  memset(&attrs, 0, sizeof(attrs));
286 
287  attrs.event_mask = KeyPressMask | KeyReleaseMask |
288  ButtonPressMask | ButtonReleaseMask | PointerMotionMask |
289  ExposureMask | VisibilityChangeMask |
290  StructureNotifyMask | FocusChangeMask;
291 
292  m_colormap = XCreateColormap(m_display, m_rootWindow, m_visual->visual, AllocNone);
293  attrs.colormap = m_colormap;
294  attrs.border_pixel = 0;
295  attrs.override_redirect = False;
296  vis = m_visual->visual;
297  depth = m_visual->depth;
298  attrsMask = CWEventMask | CWBorderPixel | CWColormap;
299 
300 #ifdef OPENGL_ES
301  attrs.override_redirect = False;
302  attrsMask |= CWOverrideRedirect;
303 #endif
304 
306  m_window = XCreateWindow(m_display, m_rootWindow,
308  0,
309  depth,
310  InputOutput,
311  vis,
312  attrsMask, &attrs);
313  m_visible = true;
314 
315  if(!m_window)
316  g_logger.fatal("Unable to create X11 window!");
317 
318  // ensure window input focus
319  XWMHints hints;
320  hints.input = True;
321  hints.flags = InputHint;
322  XSetWMHints(m_display, m_window, &hints);
323 
324  // ensure window position
325  XMoveWindow(m_display, m_window, m_position.x, m_position.y);
326 
327  // handle wm_delete events
328  m_wmDelete = XInternAtom(m_display, "WM_DELETE_WINDOW", True);
329  XSetWMProtocols(m_display, m_window, &m_wmDelete , 1);
330 
331  if(!internalSetupWindowInput())
332  g_logger.warning("Input of special keys may be messed up, because window input initialization failed");
333 
334  internalConnectGLContext();
335 }
336 
337 bool X11Window::internalSetupWindowInput()
338 {
339  // create input context (to have better key input handling)
340  if(!XSupportsLocale()) {
341  g_logger.error("X11 doesn't support the current locale");
342  return false;
343  }
344 
345  XSetLocaleModifiers("");
346  m_xim = XOpenIM(m_display, nullptr, nullptr, nullptr);
347  if(!m_xim) {
348  g_logger.error("XOpenIM failed");
349  return false;
350  }
351 
352  m_xic = XCreateIC(m_xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, XNClientWindow, m_window, NULL);
353  if(!m_xic) {
354  g_logger.error("Unable to create the input context");
355  return false;
356  }
357 
358  return true;
359 }
360 
361 void X11Window::internalCheckGL()
362 {
363 #ifdef OPENGL_ES
364  m_eglDisplay = eglGetDisplay((EGLNativeDisplayType)m_display);
365  if(m_eglDisplay == EGL_NO_DISPLAY)
366  g_logger.fatal("EGL not supported");
367 
368  if(!eglInitialize(m_eglDisplay, NULL, NULL))
369  g_logger.fatal("Unable to initialize EGL");
370 #else
371  if(!glXQueryExtension(m_display, nullptr, nullptr))
372  g_logger.fatal("GLX not supported");
373 #endif
374 }
375 
376 void X11Window::internalChooseGLVisual()
377 {
378 #ifdef OPENGL_ES
379  static int attrList[] = {
380 #if OPENGL_ES==2
381  EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
382 #else
383  EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
384 #endif
385  EGL_RED_SIZE, 4,
386  EGL_GREEN_SIZE, 4,
387  EGL_BLUE_SIZE, 4,
388  EGL_ALPHA_SIZE, 4,
389  EGL_NONE
390  };
391 
392  EGLint numConfig;
393  XVisualInfo visTemplate;
394  int numVisuals;
395 
396  if(!eglChooseConfig(m_eglDisplay, attrList, &m_eglConfig, 1, &numConfig))
397  g_logger.fatal("Failed to choose EGL config");
398 
399  if(numConfig != 1)
400  g_logger.warning("Didn't got the exact EGL config");
401 
402  EGLint vid;
403  if(!eglGetConfigAttrib(m_eglDisplay, m_eglConfig, EGL_NATIVE_VISUAL_ID, &vid))
404  g_logger.fatal("Unable to get visual EGL visual id");
405 
406  memset(&visTemplate, 0, sizeof(visTemplate));
407  visTemplate.visualid = vid;
408  m_visual = XGetVisualInfo(m_display, VisualIDMask, &visTemplate, &numVisuals);
409  if(!m_visual)
410  g_logger.fatal("Couldn't choose RGBA, double buffered visual");
411 
412  m_rootWindow = DefaultRootWindow(m_display);
413 #else
414  static int attrList[] = {
415  GLX_RENDER_TYPE, GLX_RGBA_BIT,
416  GLX_DOUBLEBUFFER, True,
417  GLX_RED_SIZE, 8,
418  GLX_GREEN_SIZE, 8,
419  GLX_BLUE_SIZE, 8,
420  GLX_ALPHA_SIZE, 8,
421  None
422  };
423 
424  int nelements;
425  m_fbConfig = glXChooseFBConfig(m_display, m_screen, attrList, &nelements);
426  if(!m_fbConfig)
427  g_logger.fatal("Couldn't choose RGBA, double buffered fbconfig");
428 
429  m_visual = glXGetVisualFromFBConfig(m_display, *m_fbConfig);
430  if(!m_visual)
431  g_logger.fatal("Couldn't choose RGBA, double buffered visual");
432 
433  m_rootWindow = RootWindow(m_display, m_visual->screen);
434 #endif
435 }
436 
437 void X11Window::internalCreateGLContext()
438 {
439 #ifdef OPENGL_ES
440  EGLint attrList[] = {
441 #if OPENGL_ES==2
442  EGL_CONTEXT_CLIENT_VERSION, 2,
443 #else
444  EGL_CONTEXT_CLIENT_VERSION, 1,
445 #endif
446  EGL_NONE
447  };
448 
449  m_eglContext = eglCreateContext(m_eglDisplay, m_eglConfig, EGL_NO_CONTEXT, attrList);
450  if(m_eglContext == EGL_NO_CONTEXT )
451  g_logger.fatal(stdext::format("Unable to create EGL context: %s", eglGetError()));
452 #else
453  m_glxContext = glXCreateContext(m_display, m_visual, nullptr, True);
454 
455  if(!m_glxContext)
456  g_logger.fatal("Unable to create GLX context");
457 
458  if(!glXIsDirect(m_display, m_glxContext))
459  g_logger.warning("GL direct rendering is not possible");
460 #endif
461 }
462 
463 void X11Window::internalDestroyGLContext()
464 {
465 #ifdef OPENGL_ES
466  if(m_eglDisplay) {
467  if(m_eglContext) {
468  eglDestroyContext(m_eglDisplay, m_eglContext);
469  m_eglContext = 0;
470  }
471  if(m_eglSurface) {
472  eglDestroySurface(m_eglDisplay, m_eglSurface);
473  m_eglSurface = 0;
474  }
475  eglTerminate(m_eglDisplay);
476  m_eglDisplay = 0;
477  }
478 #else
479  if(m_glxContext) {
480  glXMakeCurrent(m_display, None, nullptr);
481  glXDestroyContext(m_display, m_glxContext);
482  m_glxContext = nullptr;
483  }
484 #endif
485 }
486 
487 void X11Window::internalConnectGLContext()
488 {
489 #ifdef OPENGL_ES
490  m_eglSurface = eglCreateWindowSurface(m_eglDisplay, m_eglConfig, m_window, NULL);
491  if(m_eglSurface == EGL_NO_SURFACE)
492  g_logger.fatal(stdext::format("Unable to create EGL surface: %s", eglGetError()));
493  if(!eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext))
494  g_logger.fatal("Unable to connect EGL context into X11 window");
495 #else
496  if(!glXMakeCurrent(m_display, m_window, m_glxContext))
497  g_logger.fatal("Unable to set GLX context on X11 window");
498 #endif
499 }
500 
501 void *X11Window::getExtensionProcAddress(const char *ext)
502 {
503 #ifdef OPENGL_ES
504  //TODO
505  return NULL;
506 #else
507  return (void *)glXGetProcAddressARB((const GLubyte*)ext);
508 #endif
509 }
510 
511 bool X11Window::isExtensionSupported(const char *ext)
512 {
513 #ifdef OPENGL_ES
514  //TODO
515  return false;
516 #else
517  const char *exts = glXQueryExtensionsString(m_display, m_screen);
518  if(strstr(exts, ext))
519  return true;
520 #endif
521  return false;
522 }
523 
524 void X11Window::move(const Point& pos)
525 {
526  m_position = pos;
527  if(m_visible) {
528  XMoveWindow(m_display, m_window, m_position.x, m_position.y);
529  XFlush(m_display);
530  }
531 }
532 
533 void X11Window::resize(const Size& size)
534 {
535  if(size.width() < m_minimumSize.width() || size.height() < m_minimumSize.height())
536  return;
537  XResizeWindow(m_display, m_window, size.width(), size.height());
538  XFlush(m_display);
539 }
540 
542 {
543  m_visible = true;
544  XMapWindow(m_display, m_window);
545  XMoveWindow(m_display, m_window, m_position.x, m_position.y);
546  XFlush(m_display);
547  if(m_maximized)
548  maximize();
549  if(m_fullscreen)
550  setFullscreen(true);
551 }
552 
554 {
555  m_visible = false;
556  XUnmapWindow(m_display, m_window);
557  XFlush(m_display);
558 }
559 
561 {
562  if(m_visible) {
563  Atom wmState = XInternAtom(m_display, "_NET_WM_STATE", False);
564  Atom wmStateMaximizedVert = XInternAtom(m_display, "_NET_WM_STATE_MAXIMIZED_VERT", False);
565  Atom wmStateMaximizedHorz = XInternAtom(m_display, "_NET_WM_STATE_MAXIMIZED_HORZ", False);
566 
567  XEvent e = {0};
568  e.xany.type = ClientMessage;
569  e.xclient.send_event = True;
570  e.xclient.message_type = wmState;
571  e.xclient.format = 32;
572  e.xclient.window = m_window;
573  e.xclient.data.l[0] = 1;
574  e.xclient.data.l[1] = wmStateMaximizedVert;
575  e.xclient.data.l[2] = wmStateMaximizedHorz;
576  e.xclient.data.l[3] = 0;
577 
578  XSendEvent(m_display, m_rootWindow, 0, SubstructureNotifyMask | SubstructureRedirectMask, &e);
579  XFlush(m_display);
580  }
581  m_maximized = true;
582 }
583 
585 {
586  bool needsResizeUpdate = false;
587 
588  XEvent event, peekEvent;
589  while(XPending(m_display) > 0) {
590  XNextEvent(m_display, &event);
591 
592  // check for repeated key releases
593  bool repatedKeyRelease = false;
594  if(event.type == KeyRelease && XPending(m_display)) {
595  XPeekEvent(m_display, &peekEvent);
596  if((peekEvent.type == KeyPress) && (peekEvent.xkey.keycode == event.xkey.keycode) && ((peekEvent.xkey.time-event.xkey.time) < 2))
597  repatedKeyRelease = true;
598  }
599 
600  // process keydown and keyrelease events first
601  if(event.type == KeyPress || (event.type == KeyRelease && !repatedKeyRelease)) {
602  // remove caps lock and shift maks
603  XKeyEvent xkey = event.xkey;
604  xkey.state &= ~(ShiftMask | LockMask);
605 
606  // lookup keysym and translate it
607  KeySym keysym;
608  char buf[32];
609  XLookupString(&xkey, buf, sizeof(buf), &keysym, nullptr);
610  Fw::Key keyCode = Fw::KeyUnknown;
611 
612  if(m_keyMap.find(keysym) != m_keyMap.end())
613  keyCode = m_keyMap[keysym];
614 
615  if(event.type == KeyPress)
616  processKeyDown(keyCode);
617  else if(event.type == KeyRelease)
618  processKeyUp(keyCode);
619  }
620 
621  // call filter because xim will discard KeyPress events when keys still composing
622  if(XFilterEvent(&event, m_window))
623  continue;
624 
625  // discard repated key releases
626  if(repatedKeyRelease)
627  continue;
628 
629  switch(event.type) {
630  case ClientMessage: {
631  // close event
632  if((Atom)event.xclient.data.l[0] == m_wmDelete && m_onClose)
633  m_onClose();
634  break;
635  }
636  case ConfigureNotify: {
637  Size newSize(event.xconfigure.width, event.xconfigure.height);
638  Point newPos(event.xconfigure.x, event.xconfigure.y);
639 
640  // updates window size
641  if(m_size != newSize) {
642  m_size = newSize;
643  needsResizeUpdate = true;
644  }
645 
646  // checks if the window is maximized
647  if(m_visible) {
648  m_maximized = false;
649  Atom wmState = XInternAtom(m_display, "_NET_WM_STATE", False);
650  Atom wmStateMaximizedVert = XInternAtom(m_display, "_NET_WM_STATE_MAXIMIZED_VERT", False);
651  Atom wmStateMaximizedHorz = XInternAtom(m_display, "_NET_WM_STATE_MAXIMIZED_HORZ", False);
652  Atom actualType;
653  ulong i, numItems, bytesAfter;
654  uchar *propertyValue = nullptr;
655  int actualFormat;
656 
657  if(XGetWindowProperty(m_display, m_window, wmState,
658  0, 1024, False, XA_ATOM, &actualType,
659  &actualFormat, &numItems, &bytesAfter,
660  &propertyValue) == Success) {
661  Atom *atoms = (Atom*)propertyValue;
662  int maximizedMask = 0;
663 
664  for(i=0; i<numItems; ++i) {
665  if(atoms[i] == wmStateMaximizedVert)
666  maximizedMask |= 1;
667  else if(atoms[i] == wmStateMaximizedHorz)
668  maximizedMask |= 2;
669  }
670 
671  if(maximizedMask == 3)
672  m_maximized = true;
673 
674  XFree(propertyValue);
675  }
676  }
677 
678  // updates window pos
679  if(m_visible)
680  m_position = newPos;
682  break;
683  }
684  case SelectionRequest: {
685  XEvent respond;
686  XSelectionRequestEvent *req = &(event.xselectionrequest);
687 
688  Atom targets = XInternAtom(m_display, "TARGETS", False);
689  if(req->target == targets) {
690  Atom typeList[] = { XInternAtom(m_display, "UTF8_STRING", False),
691  XInternAtom(m_display, "TEXT", False),
692  XInternAtom(m_display, "STRING", False),
693  XInternAtom(m_display, "text/plain;charset=UTF-8", False),
694  XInternAtom(m_display, "text/plain", False),
695  XInternAtom(m_display, "COMPOUND_TEXT", False),
696  XA_STRING };
697 
698  XChangeProperty(m_display, req->requestor,
699  req->property, req->target,
700  8, PropModeReplace,
701  (uchar *)&typeList,
702  sizeof(typeList));
703  respond.xselection.property = req->property;
704  } else {
705  std::string clipboardText = stdext::latin1_to_utf8(m_clipboardText);
706  XChangeProperty(m_display,
707  req->requestor,
708  req->property, req->target,
709  8,
710  PropModeReplace,
711  (uchar *)clipboardText.c_str(),
712  clipboardText.length());
713  respond.xselection.property = req->property;
714  }
715 
716  respond.xselection.type = SelectionNotify;
717  respond.xselection.display = req->display;
718  respond.xselection.requestor = req->requestor;
719  respond.xselection.selection = req->selection;
720  respond.xselection.target = req->target;
721  respond.xselection.time = req->time;
722  XSendEvent(m_display, req->requestor, 0, 0, &respond);
723  XFlush(m_display);
724  break;
725  }
726  // process text events
727  case KeyPress: {
728  // text cant be insert while holding ctrl or alt
729  if(event.xkey.state & ControlMask || event.xkey.state & Mod1Mask)
730  break;
731 
732  // process key text events
733  KeySym keysym;
734  char buf[32];
735  memset(buf, 0, 32);
736  int len;
737 
738  // lookup for keyText
739  if(m_xic) { // with xim we can get latin1 input correctly
740  Status status;
741  len = XmbLookupString(m_xic, &event.xkey, buf, sizeof(buf), &keysym, &status);
742  } else { // otherwise use XLookupString, but often it doesn't work right with dead keys
743  static XComposeStatus compose = {nullptr, 0};
744  len = XLookupString(&event.xkey, buf, sizeof(buf), &keysym, &compose);
745  }
746 
747  // filter unwanted characters
748  if(len == 0 || (uchar)(buf[0]) < 32 || keysym == XK_BackSpace || keysym == XK_Return || keysym == XK_Delete || keysym == XK_Escape)
749  break;
750  std::string text = buf;
751 
752  //g_logger.debug("char: ", buf[0], " code: ", (int)((uchar)buf[0]));
753 
754  if(m_onInputEvent && text.length() > 0) {
756  m_inputEvent.keyText = text;
758  }
759  break;
760  }
761  case ButtonPress:
762  case ButtonRelease: {
764  m_inputEvent.type = (event.type == ButtonPress) ? Fw::MousePressInputEvent : Fw::MouseReleaseInputEvent;
765  switch(event.xbutton.button) {
766  case Button1:
768  m_mouseButtonStates[Fw::MouseLeftButton] = (event.type == ButtonPress);
769  break;
770  case Button3:
772  m_mouseButtonStates[Fw::MouseRightButton] = (event.type == ButtonPress);
773  break;
774  case Button2:
776  m_mouseButtonStates[Fw::MouseMidButton] = (event.type == ButtonPress);
777  break;
778  case Button4:
779  if(event.type == ButtonPress) {
783  } else
785  break;
786  case Button5:
787  if(event.type == ButtonPress) {
791  } else
793  break;
794  default:
796  break;
797  }
800  break;
801  }
802 
803  case MotionNotify: {
806  Point newMousePos(event.xbutton.x, event.xbutton.y);
808  m_inputEvent.mousePos = newMousePos;
809  if(m_onInputEvent)
811  break;
812  }
813  case MapNotify:
814  m_visible = true;
815  needsResizeUpdate = true;
816  break;
817  case UnmapNotify:
818  m_visible = false;
819  releaseAllKeys();
820  break;
821  case FocusIn:
822  m_focused = true;
823  releaseAllKeys();
824  break;
825  case FocusOut:
826  m_focused = false;
827  releaseAllKeys();
828  break;
829  case Expose:
830  // window needs redraw
831  break;
832  }
833  }
834 
835  if(needsResizeUpdate && m_onResize)
837 
838  fireKeysPress();
839 }
840 
842 {
843 #ifdef OPENGL_ES
844  eglSwapBuffers(m_eglDisplay, m_eglSurface);
845 #else
846  glXSwapBuffers(m_display, m_window);
847 #endif
848 }
849 
851 {
853 }
854 
856 {
857  if(m_cursor != None)
859 
860  if(m_hiddenCursor == None) {
861  char bm[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
862  Pixmap pix = XCreateBitmapFromData(m_display, m_window, bm, 8, 8);
863  XColor black;
864  memset(&black, 0, sizeof(black));
865  black.flags = DoRed | DoGreen | DoBlue;
866  m_hiddenCursor = XCreatePixmapCursor(m_display, pix, pix, &black, &black, 0, 0);
867  XFreePixmap(m_display, pix);
868  }
869 
870  m_cursor = m_hiddenCursor;
871  XDefineCursor(m_display, m_window, m_cursor);
872 }
873 
874 void X11Window::setMouseCursor(int cursorId)
875 {
876  if(cursorId >= (int)m_cursors.size() || cursorId < 0)
877  return;
878 
879  if(m_cursor != None)
881 
882  m_cursor = m_cursors[cursorId];
883  XDefineCursor(m_display, m_window, m_cursor);
884 }
885 
887 {
888  XUndefineCursor(m_display, m_window);
889  m_cursor = None;
890 }
891 
892 int X11Window::internalLoadMouseCursor(const ImagePtr& image, const Point& hotSpot)
893 {
894  int width = image->getWidth();
895  int height = image->getHeight();
896  int numbits = width * height;
897  int numbytes = (width * height)/8;
898 
899  XColor bg, fg;
900  bg.red = 255 << 8;
901  bg.green = 255 << 8;
902  bg.blue = 255 << 8;
903  fg.red = 0;
904  fg.green = 0;
905  fg.blue = 0;
906 
907  std::vector<uchar> mapBits(numbytes, 0);
908  std::vector<uchar> maskBits(numbytes, 0);
909 
910  for(int i=0;i<numbits;++i) {
911  uint32 rgba = stdext::readULE32(image->getPixelData() + i*4);
912  if(rgba == 0xffffffff) { //white, background
913  LSB_BIT_SET(maskBits, i);
914  } else if(rgba == 0xff000000) { //black, foreground
915  LSB_BIT_SET(mapBits, i);
916  LSB_BIT_SET(maskBits, i);
917  } //otherwise 0x00000000 => alpha
918  }
919 
920  Pixmap cp = XCreateBitmapFromData(m_display, m_window, (char*)&mapBits[0], width, height);
921  Pixmap mp = XCreateBitmapFromData(m_display, m_window, (char*)&maskBits[0], width, height);
922  Cursor cursor = XCreatePixmapCursor(m_display, cp, mp, &fg, &bg, hotSpot.x, hotSpot.y);
923  XFreePixmap(m_display, cp);
924  XFreePixmap(m_display, mp);
925 
926  m_cursors.push_back(cursor);
927  return m_cursors.size()-1;
928 }
929 
930 void X11Window::setTitle(const std::string& title)
931 {
932  XStoreName(m_display, m_window, title.c_str());
933  XSetIconName(m_display, m_window, title.c_str());
934 }
935 
936 void X11Window::setMinimumSize(const Size& minimumSize)
937 {
938  XSizeHints sizeHints;
939  memset(&sizeHints, 0, sizeof(sizeHints));
940  sizeHints.flags = PMinSize;
941  sizeHints.min_width = minimumSize.width();
942  sizeHints.min_height= minimumSize.height();
943  XSetWMSizeHints(m_display, m_window, &sizeHints, XA_WM_NORMAL_HINTS);
944 }
945 
946 void X11Window::setFullscreen(bool fullscreen)
947 {
948  if(m_visible) {
949  Atom wmState = XInternAtom(m_display, "_NET_WM_STATE", False);
950  Atom wmStateFullscreen = XInternAtom(m_display, "_NET_WM_STATE_FULLSCREEN", False);
951 
952  XEvent xev;
953  xev.xclient.type = ClientMessage;
954  xev.xclient.serial = 0;
955  xev.xclient.send_event = True;
956  xev.xclient.window = m_window;
957  xev.xclient.message_type = wmState;
958  xev.xclient.format = 32;
959  xev.xclient.data.l[0] = fullscreen ? 1 : 0;
960  xev.xclient.data.l[1] = wmStateFullscreen;
961  xev.xclient.data.l[2] = 0;
962 
963  XSendEvent(m_display, m_rootWindow, False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
964  XFlush(m_display);
965  }
966  m_fullscreen = fullscreen;
967 }
968 
969 void X11Window::setVerticalSync(bool enable)
970 {
971 #ifdef OPENGL_ES
972  //TODO
973 #else
974  typedef GLint (*glSwapIntervalProc)(GLint);
975  glSwapIntervalProc glSwapInterval = nullptr;
976 
977  if(isExtensionSupported("GLX_MESA_swap_control"))
978  glSwapInterval = (glSwapIntervalProc)getExtensionProcAddress("glXSwapIntervalMESA");
979  else if(isExtensionSupported("GLX_SGI_swap_control"))
980  glSwapInterval = (glSwapIntervalProc)getExtensionProcAddress("glXSwapIntervalSGI");
981 
982  if(glSwapInterval)
983  glSwapInterval(enable ? 1 : 0);
984 #endif
985 }
986 
987 void X11Window::setIcon(const std::string& file)
988 {
989  ImagePtr image = Image::load(file);
990 
991  if(!image) {
992  g_logger.traceError(stdext::format("unable to load icon file %s", file));
993  return;
994  }
995 
996  if(image->getBpp() != 4) {
997  g_logger.error("the app icon must have 4 channels");
998  return;
999  }
1000 
1001  int n = image->getWidth() * image->getHeight();
1002  std::vector<unsigned long int> iconData(n + 2);
1003  iconData[0] = image->getWidth();
1004  iconData[1] = image->getHeight();
1005  for(int i=0; i < n;++i) {
1006  uint8 *pixel = (uint8*)&iconData[2 + i];
1007  pixel[2] = *(image->getPixelData() + (i * 4) + 0);
1008  pixel[1] = *(image->getPixelData() + (i * 4) + 1);
1009  pixel[0] = *(image->getPixelData() + (i * 4) + 2);
1010  pixel[3] = *(image->getPixelData() + (i * 4) + 3);
1011  }
1012 
1013  Atom property = XInternAtom(m_display, "_NET_WM_ICON", 0);
1014  if(!XChangeProperty(m_display, m_window, property, XA_CARDINAL, 32, PropModeReplace, (const unsigned char*)&iconData[0], iconData.size()))
1015  g_logger.error("Couldn't set app icon");
1016 }
1017 
1018 void X11Window::setClipboardText(const std::string& text)
1019 {
1020  m_clipboardText = text;
1021  Atom clipboard = XInternAtom(m_display, "CLIPBOARD", False);
1022  XSetSelectionOwner(m_display, clipboard, m_window, CurrentTime);
1023  XFlush(m_display);
1024 }
1025 
1027 {
1028  return Size(XDisplayWidth(m_display, m_screen), XDisplayHeight(m_display, m_screen));
1029 }
1030 
1032 {
1033  Atom clipboard = XInternAtom(m_display, "CLIPBOARD", False);
1034  Window ownerWindow = XGetSelectionOwner(m_display, clipboard);
1035  if(ownerWindow == m_window)
1036  return m_clipboardText;
1037 
1038  std::string clipboardText;
1039  if(ownerWindow != None) {
1040  XConvertSelection(m_display, clipboard, XA_STRING, XA_PRIMARY, ownerWindow, CurrentTime);
1041  XFlush(m_display);
1042 
1043  // hack to wait SelectioNotify event, otherwise we will get wrong clipboard pastes
1044  // TODO: fix this in a correct way
1045  stdext::millisleep(100);
1046 
1047  // check for data
1048  Atom type;
1049  int format;
1050  ulong len, bytesLeft;
1051  char *data;
1052  XGetWindowProperty(m_display, ownerWindow,
1053  XA_PRIMARY, 0, 10000000L, 0, XA_STRING,
1054  &type,
1055  &format,
1056  &len,
1057  &bytesLeft,
1058  (uchar**)&data);
1059  if(len > 0) {
1060  if(stdext::is_valid_utf8(data))
1061  clipboardText = stdext::utf8_to_latin1(data);
1062  else
1063  clipboardText = data;
1064  }
1065  }
1066 
1067  return clipboardText;
1068 }
1069 
1071 {
1072 #ifndef OPENGL_ES
1073  return "X11-GLX";
1074 #else
1075  return "X11-EGL";
1076 #endif
1077 }
1078 
1079 #endif
LSB_BIT_SET
#define LSB_BIT_SET(p, n)
Definition: x11window.cpp:30
Fw::KeyUp
@ KeyUp
Definition: const.h:72
Fw::KeyComma
@ KeyComma
Definition: const.h:97
Fw::KeyNumpad9
@ KeyNumpad9
Definition: const.h:175
Fw::KeyRightParen
@ KeyRightParen
Definition: const.h:94
Fw::KeyUnknown
@ KeyUnknown
Definition: const.h:58
stdext::latin1_to_utf8
std::string latin1_to_utf8(const std::string &src)
Definition: string.cpp:170
Fw::KeyEscape
@ KeyEscape
Definition: const.h:59
X11Window::X11Window
X11Window()
Definition: x11window.cpp:32
Fw::KeyBackspace
@ KeyBackspace
Definition: const.h:61
Fw::KeyF10
@ KeyF10
Definition: const.h:163
PlatformWindow::m_position
Point m_position
Definition: platformwindow.h:115
Fw::KeyEnter
@ KeyEnter
Definition: const.h:63
X11Window::init
void init()
Definition: x11window.cpp:211
Fw::KeyR
@ KeyR
Definition: const.h:135
Fw::KeyCapsLock
@ KeyCapsLock
Definition: const.h:78
X11Window::internalLoadMouseCursor
int internalLoadMouseCursor(const ImagePtr &image, const Point &hotSpot)
Definition: x11window.cpp:892
Fw::KeyMenu
@ KeyMenu
Definition: const.h:84
Fw::KeyNumpad1
@ KeyNumpad1
Definition: const.h:167
X11Window::setMinimumSize
void setMinimumSize(const Size &minimumSize)
Definition: x11window.cpp:936
Fw::KeyN
@ KeyN
Definition: const.h:131
Fw::KeyI
@ KeyI
Definition: const.h:126
TPoint::y
T y
Definition: point.h:83
Fw::KeyB
@ KeyB
Definition: const.h:119
Fw::MouseWheelInputEvent
@ MouseWheelInputEvent
Definition: const.h:243
Fw::KeyNumpad6
@ KeyNumpad6
Definition: const.h:172
X11Window::getPlatformType
std::string getPlatformType()
Definition: x11window.cpp:1070
Fw::KeyZ
@ KeyZ
Definition: const.h:143
Fw::KeyNumpad3
@ KeyNumpad3
Definition: const.h:169
Fw::Key7
@ Key7
Definition: const.h:108
Fw::KeyW
@ KeyW
Definition: const.h:140
Fw::KeyExclamation
@ KeyExclamation
Definition: const.h:86
PlatformWindow::m_focused
stdext::boolean< false > m_focused
Definition: platformwindow.h:123
X11Window::show
void show()
Definition: x11window.cpp:541
Image::load
static ImagePtr load(std::string file)
Definition: image.cpp:39
Fw::KeyGreater
@ KeyGreater
Definition: const.h:115
Fw::KeyColon
@ KeyColon
Definition: const.h:111
X11Window::move
void move(const Point &pos)
Definition: x11window.cpp:524
X11Window::setVerticalSync
void setVerticalSync(bool enable)
Definition: x11window.cpp:969
Fw::MouseMidButton
@ MouseMidButton
Definition: const.h:250
uint32
uint32_t uint32
Definition: types.h:35
Fw::KeyPeriod
@ KeyPeriod
Definition: const.h:99
Fw::KeyNumpad5
@ KeyNumpad5
Definition: const.h:171
Fw::KeyP
@ KeyP
Definition: const.h:133
Fw::KeyF9
@ KeyF9
Definition: const.h:162
Fw::Key3
@ Key3
Definition: const.h:104
Fw::KeyF2
@ KeyF2
Definition: const.h:155
Fw::KeyAsterisk
@ KeyAsterisk
Definition: const.h:95
X11Window::hideMouse
void hideMouse()
Definition: x11window.cpp:855
resourcemanager.h
Fw::KeyRight
@ KeyRight
Definition: const.h:75
Logger::error
void error(const std::string &what)
Definition: logger.h:54
Fw::KeyInsert
@ KeyInsert
Definition: const.h:64
Fw::KeyT
@ KeyT
Definition: const.h:137
Fw::KeyBackslash
@ KeyBackslash
Definition: const.h:145
Fw::KeyX
@ KeyX
Definition: const.h:141
Fw::KeyC
@ KeyC
Definition: const.h:120
Fw::KeyTextInputEvent
@ KeyTextInputEvent
Definition: const.h:236
Fw::Key
Key
Definition: const.h:57
Fw::KeyNumberSign
@ KeyNumberSign
Definition: const.h:88
Fw::KeyL
@ KeyL
Definition: const.h:129
Fw::KeyNumpad2
@ KeyNumpad2
Definition: const.h:168
Fw::KeyLeft
@ KeyLeft
Definition: const.h:74
Fw::KeyRightCurly
@ KeyRightCurly
Definition: const.h:152
stdext::format
std::string format()
Definition: format.h:82
PlatformWindow::updateUnmaximizedCoords
void updateUnmaximizedCoords()
Definition: platformwindow.cpp:61
TSize::width
int width() const
Definition: size.h:43
PlatformWindow::m_inputEvent
InputEvent m_inputEvent
Definition: platformwindow.h:118
Fw::MousePressInputEvent
@ MousePressInputEvent
Definition: const.h:240
Fw::KeyNumpad8
@ KeyNumpad8
Definition: const.h:174
Fw::Key8
@ Key8
Definition: const.h:109
Fw::KeySemicolon
@ KeySemicolon
Definition: const.h:112
x11window.h
Fw::MouseLeftButton
@ MouseLeftButton
Definition: const.h:248
stdext::millisleep
void millisleep(size_t ms)
Definition: time.cpp:45
Fw::KeySlash
@ KeySlash
Definition: const.h:100
Fw::MouseMoveInputEvent
@ MouseMoveInputEvent
Definition: const.h:242
Fw::KeyScrollLock
@ KeyScrollLock
Definition: const.h:77
PlatformWindow::releaseAllKeys
void releaseAllKeys()
Definition: platformwindow.cpp:139
Fw::KeyShift
@ KeyShift
Definition: const.h:80
PlatformWindow::m_fullscreen
stdext::boolean< false > m_fullscreen
Definition: platformwindow.h:124
Fw::KeyQ
@ KeyQ
Definition: const.h:134
Logger::fatal
void fatal(const std::string &what)
Definition: logger.h:55
X11Window::setTitle
void setTitle(const std::string &title)
Definition: x11window.cpp:930
Fw::KeyDollar
@ KeyDollar
Definition: const.h:89
InputEvent::type
Fw::InputEventType type
Definition: inputevent.h:42
Fw::Key2
@ Key2
Definition: const.h:103
Fw::KeyAtSign
@ KeyAtSign
Definition: const.h:117
Fw::KeyPause
@ KeyPause
Definition: const.h:66
Fw::KeyD
@ KeyD
Definition: const.h:121
Fw::KeyLeftCurly
@ KeyLeftCurly
Definition: const.h:150
Fw::KeyLess
@ KeyLess
Definition: const.h:113
Fw::KeyU
@ KeyU
Definition: const.h:138
Fw::KeyJ
@ KeyJ
Definition: const.h:127
Fw::KeyH
@ KeyH
Definition: const.h:125
Fw::KeyEnd
@ KeyEnd
Definition: const.h:69
X11Window::getDisplaySize
Size getDisplaySize()
Definition: x11window.cpp:1026
stdext::is_valid_utf8
bool is_valid_utf8(const std::string &src)
Definition: string.cpp:75
Fw::KeyF12
@ KeyF12
Definition: const.h:165
PlatformWindow::m_onInputEvent
OnInputEventCallback m_onInputEvent
Definition: platformwindow.h:129
Fw::KeyAlt
@ KeyAlt
Definition: const.h:81
g_logger
Logger g_logger
Definition: logger.cpp:35
PlatformWindow::m_mouseButtonStates
stdext::boolean< false > m_mouseButtonStates[4]
Definition: platformwindow.h:119
Fw::KeyF11
@ KeyF11
Definition: const.h:164
Fw::KeyF4
@ KeyF4
Definition: const.h:157
Fw::KeyPlus
@ KeyPlus
Definition: const.h:96
X11Window::setMouseCursor
void setMouseCursor(int cursorId)
Definition: x11window.cpp:874
X11Window::hide
void hide()
Definition: x11window.cpp:553
Fw::KeyS
@ KeyS
Definition: const.h:136
Fw::KeyNumpad4
@ KeyNumpad4
Definition: const.h:170
PlatformWindow::processKeyDown
void processKeyDown(Fw::Key keyCode)
Definition: platformwindow.cpp:69
Fw::KeyO
@ KeyO
Definition: const.h:132
Fw::KeyHome
@ KeyHome
Definition: const.h:68
image.h
Size
TSize< int > Size
Definition: size.h:107
Fw::KeyA
@ KeyA
Definition: const.h:118
TPoint::x
T x
Definition: point.h:83
Fw::KeyGrave
@ KeyGrave
Definition: const.h:149
Fw::KeyY
@ KeyY
Definition: const.h:142
Fw::KeyQuote
@ KeyQuote
Definition: const.h:87
PlatformWindow::m_visible
stdext::boolean< false > m_visible
Definition: platformwindow.h:122
ulong
unsigned long ulong
Definition: types.h:32
Fw::KeyF7
@ KeyF7
Definition: const.h:160
Fw::KeyF
@ KeyF
Definition: const.h:123
Fw::KeyLeftParen
@ KeyLeftParen
Definition: const.h:93
stdext::utf8_to_latin1
std::string utf8_to_latin1(const std::string &src)
Definition: string.cpp:146
Fw::MouseRightButton
@ MouseRightButton
Definition: const.h:249
Fw::MouseWheelUp
@ MouseWheelUp
Definition: const.h:255
Fw::Key9
@ Key9
Definition: const.h:110
PlatformWindow::m_size
Size m_size
Definition: platformwindow.h:113
Fw::KeyBar
@ KeyBar
Definition: const.h:151
Fw::KeyRightBracket
@ KeyRightBracket
Definition: const.h:146
Fw::KeyNumpad7
@ KeyNumpad7
Definition: const.h:173
Fw::KeyMinus
@ KeyMinus
Definition: const.h:98
X11Window::restoreMouseCursor
void restoreMouseCursor()
Definition: x11window.cpp:886
X11Window::setIcon
void setIcon(const std::string &file)
Definition: x11window.cpp:987
InputEvent::keyText
std::string keyText
Definition: inputevent.h:48
Fw::Key0
@ Key0
Definition: const.h:101
Fw::KeyF8
@ KeyF8
Definition: const.h:161
Fw::NoInputEvent
@ NoInputEvent
Definition: const.h:235
PlatformWindow::m_onResize
OnResizeCallback m_onResize
Definition: platformwindow.h:128
PlatformWindow::m_onClose
std::function< void()> m_onClose
Definition: platformwindow.h:127
TSize::height
int height() const
Definition: size.h:44
uchar
unsigned char uchar
Definition: types.h:29
Fw::KeyM
@ KeyM
Definition: const.h:130
Fw::KeyEqual
@ KeyEqual
Definition: const.h:114
Fw::KeyPrintScreen
@ KeyPrintScreen
Definition: const.h:67
Fw::KeyG
@ KeyG
Definition: const.h:124
X11Window::setClipboardText
void setClipboardText(const std::string &text)
Definition: x11window.cpp:1018
stdext::shared_object_ptr
Definition: shared_object.h:39
Fw::KeyV
@ KeyV
Definition: const.h:139
PlatformWindow::m_keyMap
std::map< int, Fw::Key > m_keyMap
Definition: platformwindow.h:107
Fw::KeyE
@ KeyE
Definition: const.h:122
X11Window::poll
void poll()
Definition: x11window.cpp:584
Fw::KeyNumpad0
@ KeyNumpad0
Definition: const.h:166
Fw::KeyF6
@ KeyF6
Definition: const.h:159
Fw::KeyQuestion
@ KeyQuestion
Definition: const.h:116
Fw::KeyAmpersand
@ KeyAmpersand
Definition: const.h:91
Fw::Key1
@ Key1
Definition: const.h:102
X11Window::maximize
void maximize()
Definition: x11window.cpp:560
Fw::KeyDown
@ KeyDown
Definition: const.h:73
PlatformWindow::m_maximized
stdext::boolean< false > m_maximized
Definition: platformwindow.h:125
Fw::MouseReleaseInputEvent
@ MouseReleaseInputEvent
Definition: const.h:241
Fw::KeyCaret
@ KeyCaret
Definition: const.h:147
X11Window::swapBuffers
void swapBuffers()
Definition: x11window.cpp:841
InputEvent::mousePos
Point mousePos
Definition: inputevent.h:50
X11Window::resize
void resize(const Size &size)
Definition: x11window.cpp:533
Fw::KeyApostrophe
@ KeyApostrophe
Definition: const.h:92
Fw::Key5
@ Key5
Definition: const.h:106
Fw::KeyPageUp
@ KeyPageUp
Definition: const.h:70
Fw::KeyTilde
@ KeyTilde
Definition: const.h:153
X11Window::terminate
void terminate()
Definition: x11window.cpp:220
Fw::Key4
@ Key4
Definition: const.h:105
TPoint< int >
X11Window::getClipboardText
std::string getClipboardText()
Definition: x11window.cpp:1031
Fw::KeyLeftBracket
@ KeyLeftBracket
Definition: const.h:144
PlatformWindow::processKeyUp
void processKeyUp(Fw::Key keyCode)
Definition: platformwindow.cpp:106
Fw::KeyPercent
@ KeyPercent
Definition: const.h:90
Fw::MouseWheelDown
@ MouseWheelDown
Definition: const.h:256
InputEvent::mouseButton
Fw::MouseButton mouseButton
Definition: inputevent.h:46
InputEvent::mouseMoved
Point mouseMoved
Definition: inputevent.h:51
TSize< int >
Fw::Key6
@ Key6
Definition: const.h:107
stdext::readULE32
uint32_t readULE32(const uchar *addr)
Definition: math.h:35
Fw::KeyMeta
@ KeyMeta
Definition: const.h:83
Fw::KeyF5
@ KeyF5
Definition: const.h:158
X11Window::setFullscreen
void setFullscreen(bool fullscreen)
Definition: x11window.cpp:946
Fw::KeyF1
@ KeyF1
Definition: const.h:154
PlatformWindow::fireKeysPress
void fireKeysPress()
Definition: platformwindow.cpp:157
Fw::KeyCtrl
@ KeyCtrl
Definition: const.h:79
Fw::KeyF3
@ KeyF3
Definition: const.h:156
InputEvent::wheelDirection
Fw::MouseWheelDirection wheelDirection
Definition: inputevent.h:45
Fw::KeyUnderscore
@ KeyUnderscore
Definition: const.h:148
Fw::KeyK
@ KeyK
Definition: const.h:128
PlatformWindow::m_minimumSize
Size m_minimumSize
Definition: platformwindow.h:114
uint8
uint8_t uint8
Definition: types.h:37
Fw::KeyDelete
@ KeyDelete
Definition: const.h:65
Fw::KeyPageDown
@ KeyPageDown
Definition: const.h:71
InputEvent::reset
void reset(Fw::InputEventType eventType=Fw::NoInputEvent)
Definition: inputevent.h:34
X11Window::showMouse
void showMouse()
Definition: x11window.cpp:850
Fw::KeyTab
@ KeyTab
Definition: const.h:60
Logger::warning
void warning(const std::string &what)
Definition: logger.h:53
Fw::KeyNumLock
@ KeyNumLock
Definition: const.h:76
Fw::KeySpace
@ KeySpace
Definition: const.h:85