10 #include <X11/XKBlib.h>
11 #include <X11/Xatom.h>
12 #include <X11/Xutil.h>
13 #include <X11/keysym.h>
25 #ifdef WITH_INPUT_NDOF
36 #if defined(WITH_GL_EGL)
38 # include <EGL/eglext.h>
43 #ifdef WITH_XF86KEYSYM
44 # include <X11/XF86keysym.h>
47 #ifdef WITH_X11_XFIXES
48 # include <X11/extensions/Xfixes.h>
50 # define WITH_XWAYLAND_HACK
54 #ifdef WITH_X11_XINPUT
55 # include <X11/extensions/XInput2.h>
70 #ifdef WITH_X11_XINPUT
71 # define USE_XINPUT_HOTPLUG
75 #define USE_UNITY_WORKAROUND
79 #define USE_NON_LATIN_KB_WORKAROUND
83 return ptr[bit >> 3] & (1 << (bit & 7));
89 const XkbDescPtr xkb_descr,
90 const KeyCode keycode);
96 #ifdef WITH_XWAYLAND_HACK
97 static bool use_xwayland_hack =
false;
105 m_display = XOpenDisplay(
nullptr);
108 std::cerr <<
"Unable to open a display" << std::endl;
112 #ifdef USE_X11_ERROR_HANDLERS
117 #if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
124 #define GHOST_INTERN_ATOM_IF_EXISTS(atom) \
126 m_atom.atom = XInternAtom(m_display, #atom, True); \
129 #define GHOST_INTERN_ATOM(atom) \
131 m_atom.atom = XInternAtom(m_display, #atom, False); \
155 #ifdef WITH_X11_XINPUT
156 m_atom.TABLET = XInternAtom(m_display, XI_TABLET, False);
159 #undef GHOST_INTERN_ATOM_IF_EXISTS
160 #undef GHOST_INTERN_ATOM
164 m_last_release_keycode = 0;
165 m_last_release_time = 0;
169 if (gettimeofday(&tv,
nullptr) == -1) {
174 m_start_time =
uint64_t(tv.tv_sec) * 1000 + tv.tv_usec / 1000;
178 int xkb_opcode, xkb_event, xkb_error;
179 int xkb_major = XkbMajorVersion, xkb_minor = XkbMinorVersion;
181 use_xkb = XkbQueryExtension(
182 m_display, &xkb_opcode, &xkb_event, &xkb_error, &xkb_major, &xkb_minor);
184 XkbSetDetectableAutoRepeat(m_display,
true,
nullptr);
186 m_xkb_descr = XkbGetMap(m_display, 0, XkbUseCoreKbd);
188 XkbGetNames(m_display, XkbKeyNamesMask, m_xkb_descr);
189 XkbGetControls(m_display, XkbPerKeyRepeatMask | XkbRepeatKeysMask, m_xkb_descr);
193 #ifdef WITH_XWAYLAND_HACK
194 use_xwayland_hack = getenv(
"WAYLAND_DISPLAY") !=
nullptr;
197 #ifdef WITH_X11_XINPUT
200 memset(&m_xinput_version, 0,
sizeof(m_xinput_version));
201 XExtensionVersion *version = XGetExtensionVersion(m_display, INAME);
202 if (version && (version != (XExtensionVersion *)NoSuchExtension)) {
203 if (version->present) {
204 m_xinput_version = *version;
210 # ifdef USE_XINPUT_HOTPLUG
211 if (m_xinput_version.present) {
212 XEventClass class_presence;
214 DevicePresence(m_display, xi_presence, class_presence);
215 XSelectExtensionEvent(
216 m_display, RootWindow(m_display, DefaultScreen(m_display)), &class_presence, 1);
221 refreshXInputDevices();
227 #if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
233 #ifdef WITH_X11_XINPUT
235 clearXInputDevices();
239 ::eglTerminate(::eglGetDisplay(m_display));
243 XkbFreeKeyboard(m_xkb_descr, XkbAllComponentsMask,
true);
246 XCloseDisplay(m_display);
254 #ifdef WITH_INPUT_NDOF
270 if (gettimeofday(&tv,
nullptr) == -1) {
275 return uint64_t(tv.tv_sec) * 1000 + tv.tv_usec / 1000 - m_start_time;
304 width = DisplayWidth(m_display, DefaultScreen(m_display));
305 height = DisplayHeight(m_display, DefaultScreen(m_display));
334 const bool exclusive,
335 const bool is_dialog,
397 #if defined(WITH_GL_PROFILE_CORE)
399 const char *version_major = (
char *)glewGetString(GLEW_VERSION_MAJOR);
400 if (version_major !=
nullptr && version_major[0] ==
'1') {
401 fprintf(stderr,
"Error: GLEW version 2.0 and above is required.\n");
407 const int profile_mask =
409 # if defined(WITH_GL_PROFILE_CORE)
410 EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT;
411 # elif defined(WITH_GL_PROFILE_COMPAT)
412 EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT;
417 # if defined(WITH_GL_PROFILE_CORE)
418 GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
419 # elif defined(WITH_GL_PROFILE_COMPAT)
420 GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
428 for (
int minor = 5; minor >= 0; --minor) {
429 #if defined(WITH_GL_EGL)
432 EGLNativeWindowType(
nullptr),
433 EGLNativeDisplayType(m_display),
438 (debug_context ? EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR : 0),
445 (GLXFBConfig)
nullptr,
450 (debug_context ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
454 if (
context->initializeDrawingContext()) {
460 #if defined(WITH_GL_EGL)
463 EGLNativeWindowType(
nullptr),
464 EGLNativeDisplayType(m_display),
469 (debug_context ? EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR : 0),
476 (GLXFBConfig)
nullptr,
481 (debug_context ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
485 if (
context->initializeDrawingContext()) {
505 #if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
506 static void destroyIMCallback(XIM , XPointer
ptr, XPointer )
511 *(XIM *)
ptr =
nullptr;
515 bool GHOST_SystemX11::openX11_IM()
521 XSetLocaleModifiers(
"");
523 m_xim = XOpenIM(m_display,
nullptr, (
char *)GHOST_X11_RES_NAME, (
char *)GHOST_X11_RES_CLASS);
529 destroy.callback = (XIMProc)destroyIMCallback;
530 destroy.client_data = (XPointer)&m_xim;
531 XSetIMValues(m_xim, XNDestroyCallback, &destroy,
nullptr);
550 vector<GHOST_IWindow *>::const_iterator win_it = win_vec.begin();
551 vector<GHOST_IWindow *>::const_iterator win_end = win_vec.end();
553 for (; win_it != win_end; ++win_it) {
564 int fd = ConnectionNumber(display);
570 if (maxSleep == -1) {
571 select(fd + 1, &fds,
nullptr,
nullptr,
nullptr);
576 tv.tv_sec = maxSleep / 1000;
577 tv.tv_usec = (maxSleep - tv.tv_sec * 1000) * 1000;
579 select(fd + 1, &fds,
nullptr,
nullptr, &tv);
591 switch (event->type) {
594 data->timestamp =
event->xbutton.time;
597 data->timestamp =
event->xmotion.time;
601 data->timestamp =
event->xkey.time;
604 data->timestamp =
event->xproperty.time;
608 data->timestamp =
event->xcrossing.time;
611 data->timestamp =
event->xselectionclear.time;
620 Time GHOST_SystemX11::lastEventTime(Time default_time)
623 data.timestamp = default_time;
627 return data.timestamp;
635 bool anyProcessed =
false;
640 if (waitForEvent && m_dirty_windows.empty() && !XPending(m_display)) {
659 while (XPending(m_display)) {
661 XNextEvent(m_display, &xevent);
663 #if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
667 if (
ELEM(xevent.type, FocusIn, KeyPress)) {
668 if (!m_xim && openX11_IM()) {
674 if (window && !window->getX11_XIC() && window->createX11_XIC()) {
676 if (xevent.type == KeyPress)
680 XSetICFocus(window->getX11_XIC());
686 if ((XFilterEvent(&xevent, (
Window)
nullptr) == True)) {
693 if (xevent.type == KeyRelease) {
694 m_last_release_keycode = xevent.xkey.keycode;
695 m_last_release_time = xevent.xkey.time;
697 else if (xevent.type == KeyPress) {
698 if ((xevent.xkey.keycode == m_last_release_keycode) &&
699 ((xevent.xkey.time <= m_last_release_time))) {
704 processEvent(&xevent);
707 #ifdef USE_UNITY_WORKAROUND
714 if (xevent.type == FocusIn) {
718 if (window && XPending(m_display) >= 2) {
719 XNextEvent(m_display, &xevent);
721 if (xevent.type == KeymapNotify) {
726 XPeekEvent(m_display, &xev_next);
728 if (
ELEM(xev_next.type, KeyPress, KeyRelease)) {
730 const static KeySym modifiers[] = {
741 for (
int i = 0; i < (int)
ARRAY_SIZE(modifiers); i++) {
742 KeyCode kc = XKeysymToKeycode(m_display, modifiers[i]);
743 if (kc != 0 && ((xevent.xkeymap.key_vector[kc >> 3] >> (kc & 7)) & 1) != 0) {
759 if (generateWindowExposeEvents()) {
763 #ifdef WITH_INPUT_NDOF
769 }
while (waitForEvent && !anyProcessed);
774 #ifdef WITH_X11_XINPUT
775 static bool checkTabletProximity(Display *display, XDevice *device)
782 if (device ==
nullptr) {
789 state = XQueryDeviceState(display, device);
794 XInputClass *cls =
state->data;
796 for (
int loop = 0; loop <
state->num_classes; loop++) {
797 switch (cls->c_class) {
799 XValuatorState *val_state = (XValuatorState *)cls;
804 if ((val_state->mode & 2) == 0) {
805 XFreeDeviceState(
state);
810 cls = (XInputClass *)((
char *)cls + cls->length);
812 XFreeDeviceState(
state);
818 void GHOST_SystemX11::processEvent(XEvent *xe)
824 bool is_repeat =
false;
825 if (
ELEM(xe->type, KeyPress, KeyRelease)) {
826 XKeyEvent *xke = &(xe->xkey);
829 bool is_repeat_keycode =
false;
831 if (m_xkb_descr !=
nullptr) {
833 is_repeat_keycode = (
835 (xke->keycode < (XkbPerKeyBitArraySize << 3)) &&
836 bit_is_on(m_xkb_descr->ctrls->per_key_repeat, xke->keycode));
840 switch (XLookupKeysym(xke, 0)) {
857 is_repeat_keycode =
true;
862 if (is_repeat_keycode) {
863 if (xe->type == KeyPress) {
864 if (m_keycode_last_repeat_key == xke->keycode) {
867 m_keycode_last_repeat_key = xke->keycode;
870 if (m_keycode_last_repeat_key == xke->keycode) {
871 m_keycode_last_repeat_key = (
uint)-1;
876 else if (xe->type == EnterNotify) {
878 m_keycode_last_repeat_key = (
uint)-1;
881 #ifdef USE_XINPUT_HOTPLUG
883 if (m_xinput_version.present) {
884 XEventClass class_presence;
887 DevicePresence(m_display, xi_presence, class_presence);
888 (
void)class_presence;
890 if (xe->type == xi_presence) {
891 XDevicePresenceNotifyEvent *notify_event = (XDevicePresenceNotifyEvent *)xe;
892 if (
ELEM(notify_event->devchange,
897 refreshXInputDevices();
902 vector<GHOST_IWindow *>::const_iterator win_it = win_vec.begin();
903 vector<GHOST_IWindow *>::const_iterator win_end = win_vec.end();
905 for (; win_it != win_end; ++win_it) {
907 window_xinput->refreshXInputDevices();
919 #ifdef WITH_X11_XINPUT
926 bool any_proximity =
false;
928 for (GHOST_TabletX11 &xtablet : m_xtablets) {
929 if (checkTabletProximity(xe->xany.display, xtablet.Device)) {
930 any_proximity =
true;
934 if (!any_proximity) {
942 XExposeEvent &xee = xe->xexpose;
944 if (xee.count == 0) {
954 XMotionEvent &xme = xe->xmotion;
975 if (x_new != xme.x_root || y_new != xme.y_root) {
982 if (x_new != xme.x_root && xme.time > m_last_warp_x) {
983 x_accum += (xme.x_root - x_new);
984 m_last_warp_x = lastEventTime(xme.time) + 25;
986 if (y_new != xme.y_root && xme.time > m_last_warp_y) {
987 y_accum += (xme.y_root - y_new);
988 m_last_warp_y = lastEventTime(xme.time) + 25;
999 xme.x_root + x_accum,
1000 xme.y_root + y_accum,
1017 XKeyEvent *xke = &(xe->xkey);
1019 char *utf8_buf =
nullptr;
1022 #if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
1029 char utf8_array[16 * 6 + 5];
1038 #ifdef USE_NON_LATIN_KB_WORKAROUND
1064 const unsigned int mode_switch_mask = XkbKeysymToModifiers(xke->display, XK_Mode_switch);
1065 const unsigned int number_hack_forbidden_kmods_mask = mode_switch_mask | ShiftMask;
1066 if ((xke->keycode >= 10 && xke->keycode < 20) &&
1067 ((xke->state & number_hack_forbidden_kmods_mask) == 0)) {
1068 key_sym = XLookupKeysym(xke, ShiftMask);
1069 if (!((key_sym >= XK_0) && (key_sym <= XK_9))) {
1070 key_sym = XLookupKeysym(xke, 0);
1074 key_sym = XLookupKeysym(xke, 0);
1077 if (!XLookupString(xke, &ascii, 1, &key_sym_str,
nullptr)) {
1136 if ((xke->keycode >= 10 && xke->keycode < 20) &&
1137 ((key_sym = XLookupKeysym(xke, ShiftMask)) >= XK_0) && (key_sym <= XK_9)) {
1142 key_sym = XLookupKeysym(xke, 0);
1147 if (!XLookupString(xke, &ascii, 1,
nullptr,
nullptr)) {
1152 #if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
1157 if (xke->type == KeyPress) {
1158 utf8_buf = utf8_array;
1159 #if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
1161 xic = window->getX11_XIC();
1166 if (!(
len = Xutf8LookupString(
1167 xic, xke, utf8_buf,
sizeof(utf8_array) - 5, &key_sym, &status))) {
1171 if (status == XBufferOverflow) {
1172 utf8_buf = (
char *)malloc(
len + 5);
1173 len = Xutf8LookupString(xic, xke, utf8_buf,
len, &key_sym, &status);
1176 if (
ELEM(status, XLookupChars, XLookupBoth)) {
1177 if ((
unsigned char)utf8_buf[0] >= 32) {
1184 else if (status == XLookupKeySym) {
1189 printf(
"Bad keycode lookup. Keysym 0x%x Status: %s\n",
1190 (
unsigned int)key_sym,
1191 (status == XLookupNone ?
"XLookupNone" :
1192 status == XLookupKeySym ?
"XLookupKeySym" :
1195 printf(
"'%.*s' %p %p\n",
len, utf8_buf, xic, m_xim);
1202 if (!utf8_buf[0] && ascii) {
1203 utf8_buf[0] = ascii;
1210 #if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
1213 if (xke->type == KeyPress && xic) {
1218 if ((
uchar)utf8_buf[i++] > 0x7f) {
1219 for (; i <
len; ++i) {
1221 if (c < 0x80 || c > 0xbf) {
1238 if (utf8_buf != utf8_array) {
1247 case ButtonRelease: {
1248 XButtonEvent &xbe = xe->xbutton;
1254 if (xbe.button == Button4) {
1255 if (xbe.type == ButtonPress) {
1260 if (xbe.button == Button5) {
1261 if (xbe.type == ButtonPress) {
1268 if (xbe.button == Button1) {
1271 else if (xbe.button == Button2) {
1274 else if (xbe.button == Button3) {
1280 else if (xbe.button == 6) {
1283 else if (xbe.button == 7) {
1286 else if (xbe.button == 8) {
1289 else if (xbe.button == 9) {
1302 case ConfigureNotify: {
1310 XFocusChangeEvent &xfe = xe->xfocus;
1321 #if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
1322 XIC xic = window->getX11_XIC();
1324 if (xe->type == FocusIn)
1334 case ClientMessage: {
1335 XClientMessageEvent &xcme = xe->xclient;
1337 if (((Atom)xcme.data.l[0]) ==
m_atom.WM_DELETE_WINDOW) {
1340 else if (((Atom)xcme.data.l[0]) ==
m_atom.WM_TAKE_FOCUS) {
1341 XWindowAttributes attr;
1355 if (XGetWindowAttributes(m_display, xcme.window, &attr) == True) {
1356 if (XGetInputFocus(m_display, &fwin, &revert_to) == True) {
1357 if (attr.map_state == IsViewable) {
1358 if (fwin != xcme.window) {
1359 XSetInputFocus(m_display, xcme.window, RevertToParent, xcme.data.l[1]);
1369 if (window->getDropTarget()->GHOST_HandleClientMessage(xe) ==
false) {
1384 case GraphicsExpose:
1396 XCrossingEvent &xce = xe->xcrossing;
1397 if (xce.mode == NotifyNormal) {
1409 if (xce.type == EnterNotify) {
1440 case ReparentNotify:
1442 case SelectionRequest: {
1444 Atom target, utf8_string,
string, compound_text, c_string;
1445 XSelectionRequestEvent *xse = &xe->xselectionrequest;
1447 target = XInternAtom(m_display,
"TARGETS", False);
1448 utf8_string = XInternAtom(m_display,
"UTF8_STRING", False);
1449 string = XInternAtom(m_display,
"STRING", False);
1450 compound_text = XInternAtom(m_display,
"COMPOUND_TEXT", False);
1451 c_string = XInternAtom(m_display,
"C_STRING", False);
1454 if (xse->property ==
None) {
1455 xse->property = xse->target;
1458 nxe.xselection.type = SelectionNotify;
1459 nxe.xselection.requestor = xse->requestor;
1460 nxe.xselection.property = xse->property;
1461 nxe.xselection.display = xse->display;
1462 nxe.xselection.selection = xse->selection;
1463 nxe.xselection.target = xse->target;
1464 nxe.xselection.time = xse->time;
1467 if (
ELEM(xse->target, utf8_string,
string, compound_text, c_string)) {
1468 if (xse->selection == XInternAtom(m_display,
"PRIMARY", False)) {
1469 XChangeProperty(m_display,
1478 else if (xse->selection == XInternAtom(m_display,
"CLIPBOARD", False)) {
1479 XChangeProperty(m_display,
1489 else if (xse->target == target) {
1492 alist[1] = utf8_string;
1494 alist[3] = compound_text;
1495 alist[4] = c_string;
1496 XChangeProperty(m_display,
1502 (
unsigned char *)alist,
1508 nxe.xselection.property =
None;
1512 XSendEvent(m_display, xse->requestor, 0, 0, &nxe);
1518 #ifdef WITH_X11_XINPUT
1519 for (GHOST_TabletX11 &xtablet : m_xtablets) {
1520 if (
ELEM(xe->type, xtablet.MotionEvent, xtablet.PressEvent)) {
1521 XDeviceMotionEvent *
data = (XDeviceMotionEvent *)xe;
1522 if (
data->deviceid != xtablet.ID) {
1526 const unsigned char axis_first =
data->first_axis;
1527 const unsigned char axes_end = axis_first +
data->axes_count;
1541 # define AXIS_VALUE_GET(axis, val) \
1542 ((axis_first <= axis && axes_end > axis) && \
1543 ((void)(val = data->axis_data[axis - axis_first]), true))
1545 if (AXIS_VALUE_GET(2, axis_value)) {
1557 if (AXIS_VALUE_GET(3, axis_value)) {
1559 ((
float)xtablet.XtiltLevels);
1561 if (AXIS_VALUE_GET(4, axis_value)) {
1563 ((
float)xtablet.YtiltLevels);
1566 # undef AXIS_VALUE_GET
1568 else if (xe->type == xtablet.ProxInEvent) {
1569 XProximityNotifyEvent *
data = (XProximityNotifyEvent *)xe;
1570 if (
data->deviceid != xtablet.ID) {
1576 else if (xe->type == xtablet.ProxOutEvent) {
1595 memset((
void *)m_keyboard_vector, 0,
sizeof(m_keyboard_vector));
1597 XQueryKeymap(m_display, (
char *)m_keyboard_vector);
1601 const static KeyCode shift_l = XKeysymToKeycode(m_display, XK_Shift_L);
1602 const static KeyCode shift_r = XKeysymToKeycode(m_display, XK_Shift_R);
1603 const static KeyCode control_l = XKeysymToKeycode(m_display, XK_Control_L);
1604 const static KeyCode control_r = XKeysymToKeycode(m_display, XK_Control_R);
1605 const static KeyCode alt_l = XKeysymToKeycode(m_display, XK_Alt_L);
1606 const static KeyCode alt_r = XKeysymToKeycode(m_display, XK_Alt_R);
1607 const static KeyCode super_l = XKeysymToKeycode(m_display, XK_Super_L);
1608 const static KeyCode super_r = XKeysymToKeycode(m_display, XK_Super_R);
1612 ((m_keyboard_vector[shift_l >> 3] >> (shift_l & 7)) & 1) != 0);
1614 ((m_keyboard_vector[shift_r >> 3] >> (shift_r & 7)) & 1) != 0);
1617 ((m_keyboard_vector[control_l >> 3] >> (control_l & 7)) & 1) != 0);
1619 ((m_keyboard_vector[control_r >> 3] >> (control_r & 7)) & 1) != 0);
1625 (((m_keyboard_vector[super_l >> 3] >> (super_l & 7)) & 1) ||
1626 ((m_keyboard_vector[super_r >> 3] >> (super_r & 7)) & 1)) != 0);
1633 Window root_return, child_return;
1635 unsigned int mask_return;
1637 if (XQueryPointer(m_display,
1638 RootWindow(m_display, DefaultScreen(m_display)),
1645 &mask_return) == True) {
1665 unsigned int mask_return;
1668 if (XQueryPointer(display,
1669 RootWindow(display, DefaultScreen(display)),
1676 &mask_return) == False) {
1701 #ifdef WITH_XWAYLAND_HACK
1715 #ifdef WITH_XWAYLAND_HACK
1716 if (use_xwayland_hack) {
1717 if (child_return !=
None) {
1718 XFixesHideCursor(m_display, child_return);
1723 #if defined(WITH_X11_XINPUT) && defined(USE_X11_XINPUT_WARP)
1724 if ((m_xinput_version.present) && (m_xinput_version.major_version >= 2)) {
1727 if (XIGetClientPointer(m_display,
None, &device_id) != False) {
1728 XIWarpPointer(m_display, device_id,
None,
None, 0, 0, 0, 0, relx, rely);
1734 XWarpPointer(m_display,
None,
None, 0, 0, 0, 0, relx, rely);
1737 #ifdef WITH_XWAYLAND_HACK
1738 if (use_xwayland_hack) {
1739 if (child_return !=
None) {
1740 XFixesShowCursor(m_display, child_return);
1745 XSync(m_display, 0);
1752 GHOST_ASSERT((bad_wind !=
nullptr),
"addDirtyWindow() nullptr ptr trapped (window)");
1754 m_dirty_windows.push_back(bad_wind);
1757 bool GHOST_SystemX11::generateWindowExposeEvents()
1759 vector<GHOST_WindowX11 *>::const_iterator w_start = m_dirty_windows.begin();
1760 vector<GHOST_WindowX11 *>::const_iterator w_end = m_dirty_windows.end();
1761 bool anyProcessed =
false;
1763 for (; w_start != w_end; ++w_start) {
1766 (*w_start)->validate();
1770 anyProcessed =
true;
1774 m_dirty_windows.clear();
1775 return anyProcessed;
1779 XkbDescPtr xkb_descr,
1780 const KeyCode keycode)
1791 #define GXMAP(k, x, y) \
1800 if ((key >= XK_A) && (key <= XK_Z)) {
1803 else if ((key >= XK_a) && (key <= XK_z)) {
1806 else if ((key >= XK_0) && (key <= XK_9)) {
1809 else if ((key >= XK_F1) && (key <= XK_F24)) {
1895 #ifdef WITH_XF86KEYSYM
1901 # ifdef XF86XK_AudioForward
1906 #ifdef WITH_GHOST_DEBUG
1907 printf(
"%s: unknown key: %lu / 0x%lx\n", __func__, key, key);
1919 #define MAKE_ID(a, b, c, d) ((int)(d) << 24 | (int)(c) << 16 | (b) << 8 | (a))
1923 GHOST_ASSERT(XkbKeyNameLength == 4,
"Name length is invalid!");
1924 if (keycode >= xkb_descr->min_key_code && keycode <= xkb_descr->max_key_code) {
1925 const char *id_str = xkb_descr->names->keys[keycode].name;
1926 const uint32_t id =
MAKE_ID(id_str[0], id_str[1], id_str[2], id_str[3]);
1928 case MAKE_ID(
'T',
'L',
'D',
'E'):
1930 #ifdef WITH_GHOST_DEBUG
1932 printf(
"%s unhandled keycode: %.*s\n", __func__, XkbKeyNameLength, id_str);
1937 else if (keycode != 0) {
1947 #define XCLIB_XCOUT_NONE 0
1948 #define XCLIB_XCOUT_SENTCONVSEL 1
1949 #define XCLIB_XCOUT_INCR 2
1950 #define XCLIB_XCOUT_FALLBACK 3
1951 #define XCLIB_XCOUT_FALLBACK_UTF8 4
1952 #define XCLIB_XCOUT_FALLBACK_COMP 5
1953 #define XCLIB_XCOUT_FALLBACK_TEXT 6
1959 unsigned char **txt,
1966 unsigned long pty_size, pty_items;
1967 unsigned char *ltxt = *txt;
1970 vector<GHOST_IWindow *>::const_iterator win_it = win_vec.begin();
1984 XConvertSelection(m_display, sel, target,
m_atom.XCLIP_OUT, win, CurrentTime);
1989 if (evt->type != SelectionNotify) {
1993 if (target ==
m_atom.UTF8_STRING && evt->xselection.property ==
None) {
1997 if (target ==
m_atom.COMPOUND_TEXT && evt->xselection.property ==
None) {
2001 if (target ==
m_atom.TEXT && evt->xselection.property ==
None) {
2007 XGetWindowProperty(m_display,
2021 if (pty_type ==
m_atom.INCR) {
2023 XDeleteProperty(m_display, win,
m_atom.XCLIP_OUT);
2032 if (pty_format != 8) {
2038 XGetWindowProperty(m_display,
2052 XDeleteProperty(m_display, win,
m_atom.XCLIP_OUT);
2055 ltxt = (
unsigned char *)malloc(pty_items);
2056 memcpy(ltxt,
buffer, pty_items);
2077 if (evt->type != PropertyNotify) {
2082 if (evt->xproperty.state != PropertyNewValue) {
2087 XGetWindowProperty(m_display,
2100 if (pty_format != 8) {
2105 XDeleteProperty(m_display, win,
m_atom.XCLIP_OUT);
2109 if (pty_size == 0) {
2112 XDeleteProperty(m_display, win,
m_atom.XCLIP_OUT);
2124 XGetWindowProperty(m_display,
2140 ltxt = (
unsigned char *)malloc(*
len);
2144 ltxt = (
unsigned char *)realloc(ltxt, *
len);
2148 memcpy(<xt[*
len - pty_items],
buffer, pty_items);
2154 XDeleteProperty(m_display, win,
m_atom.XCLIP_OUT);
2163 Atom target =
m_atom.UTF8_STRING;
2168 unsigned long sel_len = 0;
2172 if (selection == True) {
2176 sseln =
m_atom.CLIPBOARD;
2180 vector<GHOST_IWindow *>::const_iterator win_it = win_vec.begin();
2185 owner = XGetSelectionOwner(m_display, sseln);
2187 if (sseln ==
m_atom.CLIPBOARD) {
2196 if (owner ==
None) {
2201 vector<XEvent> restore_events;
2205 bool restore_this_event =
false;
2207 XNextEvent(m_display, &evt);
2208 restore_this_event = (evt.type != SelectionNotify);
2214 if (restore_this_event) {
2215 restore_events.push_back(evt);
2227 target =
m_atom.COMPOUND_TEXT;
2247 while (!restore_events.empty()) {
2248 XPutBackEvent(m_display, &restore_events.back());
2249 restore_events.pop_back();
2254 char *tmp_data = (
char *)malloc(sel_len + 1);
2255 memcpy(tmp_data, (
char *)sel_buf, sel_len);
2256 tmp_data[sel_len] =
'\0';
2258 if (sseln ==
m_atom.STRING) {
2275 vector<GHOST_IWindow *>::const_iterator win_it = win_vec.begin();
2280 if (selection == False) {
2281 XSetSelectionOwner(m_display,
m_atom.CLIPBOARD, m_window, CurrentTime);
2282 owner = XGetSelectionOwner(m_display,
m_atom.CLIPBOARD);
2291 XSetSelectionOwner(m_display,
m_atom.PRIMARY, m_window, CurrentTime);
2292 owner = XGetSelectionOwner(m_display,
m_atom.PRIMARY);
2301 if (owner != m_window) {
2302 fprintf(stderr,
"failed to own primary\n");
2356 XFillRectangle(display,
2364 XFillRectangle(display,
2372 XDrawString(display,
2397 data = strdup(text);
2398 for (tok = strtok(
data, seps); tok !=
nullptr; tok = strtok(
nullptr, seps)) {
2403 data = strdup(text);
2404 *
str = (
char **)malloc((
size_t)(*count) *
sizeof(
char *));
2405 for (i = 0, tok = strtok(
data, seps); tok !=
nullptr; tok = strtok(
nullptr, seps), i++) {
2406 (*str)[i] = strdup(tok);
2412 const char *message,
2413 const char *help_label,
2414 const char *continue_label,
2418 char **text_splitted =
nullptr;
2420 split(message,
"\n", &text_splitted, &textLines);
2427 int screen = DefaultScreen(m_display);
2428 window = XCreateSimpleWindow(m_display,
2429 RootWindow(m_display, screen),
2435 BlackPixel(m_display, screen),
2436 WhitePixel(m_display, screen));
2440 hints.flags = PSize | PMinSize | PMaxSize;
2441 hints.min_width = hints.max_width = hints.base_width = dialog_data.
width;
2442 hints.min_height = hints.max_height = hints.base_height = dialog_data.
height;
2443 XSetWMNormalHints(m_display, window, &hints);
2448 Atom wm_Name = XInternAtom(m_display,
"_NET_WM_NAME", False);
2449 Atom utf8Str = XInternAtom(m_display,
"UTF8_STRING", False);
2451 Atom winType = XInternAtom(m_display,
"_NET_WM_WINDOW_TYPE", False);
2452 Atom typeDialog = XInternAtom(m_display,
"_NET_WM_WINDOW_TYPE_DIALOG", False);
2454 XChangeProperty(m_display,
2460 (
const unsigned char *)title,
2461 (
int)strlen(title));
2464 m_display, window, winType, XA_ATOM, 32, PropModeReplace, (
unsigned char *)&typeDialog, 1);
2468 XGCValues buttonBorderGCValues;
2469 buttonBorderGCValues.foreground = BlackPixel(m_display, screen);
2470 buttonBorderGCValues.background = WhitePixel(m_display, screen);
2471 XGCValues buttonGCValues;
2472 buttonGCValues.foreground = WhitePixel(m_display, screen);
2473 buttonGCValues.background = BlackPixel(m_display, screen);
2475 GC buttonBorderGC = XCreateGC(m_display, window, GCForeground, &buttonBorderGCValues);
2476 GC buttonGC = XCreateGC(m_display, window, GCForeground, &buttonGCValues);
2478 XSelectInput(m_display, window, ExposureMask | ButtonPressMask | ButtonReleaseMask);
2479 XMapWindow(m_display, window);
2482 XNextEvent(m_display, &
e);
2483 if (
e.type == Expose) {
2484 for (
int i = 0; i < textLines; i++) {
2485 XDrawString(m_display,
2487 DefaultGC(m_display, screen),
2491 (
int)strlen(text_splitted[i]));
2493 dialog_data.
drawButton(m_display, window, buttonBorderGC, buttonGC, 1, continue_label);
2495 dialog_data.
drawButton(m_display, window, buttonBorderGC, buttonGC, 2, help_label);
2498 else if (
e.type == ButtonRelease) {
2504 string cmd =
"xdg-open \"" + string(link) +
"\"";
2505 if (system(cmd.c_str()) != 0) {
2506 GHOST_PRINTF(
"GHOST_SystemX11::showMessageBox: Unable to run system command [%s]",
2515 for (
int i = 0; i < textLines; i++) {
2516 free(text_splitted[i]);
2518 free(text_splitted);
2520 XDestroyWindow(m_display, window);
2521 XFreeGC(m_display, buttonBorderGC);
2522 XFreeGC(m_display, buttonGC);
2555 char error_code_str[512];
2557 XGetErrorText(display, event->error_code, error_code_str,
sizeof(error_code_str));
2560 "Received X11 Error:\n"
2561 "\terror code: %d\n"
2562 "\trequest code: %d\n"
2563 "\tminor code: %d\n"
2564 "\terror text: %s\n",
2566 event->request_code,
2581 fprintf(stderr,
"Ignoring Xlib error: error IO\n");
2587 #ifdef WITH_X11_XINPUT
2589 static bool is_filler_char(
char c)
2591 return isspace(
c) ||
ELEM(
c,
'_',
'-',
';',
':');
2595 static bool match_token(
const char *haystack,
const char *needle)
2598 for (h = haystack; *h;) {
2599 while (*h && is_filler_char(*h)) {
2606 for (n = needle; *n && *h && tolower(*h) == tolower(*n); n++) {
2609 if (!*n && (is_filler_char(*h) || !*h)) {
2613 while (*h && !is_filler_char(*h)) {
2633 static const char *tablet_stylus_whitelist[] = {
"stylus",
"wizardpen",
"acecad",
"pen",
nullptr};
2635 static const char *type_blacklist[] = {
"pad",
"cursor",
"touch",
nullptr};
2638 for (i = 0; type_blacklist[i] !=
nullptr; i++) {
2639 if (
type && (strcasecmp(
type, type_blacklist[i]) == 0)) {
2645 for (i = 0; tablet_stylus_whitelist[i] !=
nullptr; i++) {
2646 if (
type && match_token(
type, tablet_stylus_whitelist[i])) {
2650 if (
type && match_token(
type,
"eraser")) {
2653 for (i = 0; tablet_stylus_whitelist[i] !=
nullptr; i++) {
2654 if (name && match_token(name, tablet_stylus_whitelist[i])) {
2658 if (name && match_token(name,
"eraser")) {
2667 void GHOST_SystemX11::refreshXInputDevices()
2669 if (m_xinput_version.present) {
2671 clearXInputDevices();
2678 XDeviceInfo *device_info = XListInputDevices(m_display, &device_count);
2680 for (
int i = 0; i < device_count; ++i) {
2681 char *device_type = device_info[i].type ? XGetAtomName(m_display, device_info[i].
type) :
2683 GHOST_TTabletMode tablet_mode = tablet_mode_from_name(device_info[i].name, device_type);
2688 XFree((
void *)device_type);
2695 GHOST_TabletX11 xtablet = {tablet_mode};
2696 xtablet.ID = device_info[i].id;
2697 xtablet.Device = XOpenDevice(m_display, xtablet.ID);
2699 if (xtablet.Device !=
nullptr) {
2701 XAnyClassPtr ici = device_info[i].inputclassinfo;
2703 if (ici !=
nullptr) {
2704 for (
int j = 0; j < device_info[i].num_classes; ++j) {
2705 if (ici->c_class == ValuatorClass) {
2706 XValuatorInfo *xvi = (XValuatorInfo *)ici;
2707 if (xvi->axes !=
nullptr) {
2708 xtablet.PressureLevels = xvi->axes[2].max_value;
2710 if (xvi->num_axes > 3) {
2713 xtablet.XtiltLevels = xvi->axes[3].max_value;
2714 xtablet.YtiltLevels = xvi->axes[4].max_value;
2717 xtablet.XtiltLevels = 0;
2718 xtablet.YtiltLevels = 0;
2725 ici = (XAnyClassPtr)(((
char *)ici) + ici->length);
2729 m_xtablets.push_back(xtablet);
2733 XFreeDeviceList(device_info);
2740 void GHOST_SystemX11::clearXInputDevices()
2742 for (GHOST_TabletX11 &xtablet : m_xtablets) {
2744 XCloseDevice(m_display, xtablet.Device);
typedef float(TangentPoint)[2]
void BLI_kdtree_nd_() free(KDTree *tree)
#define GHOST_OPENGL_EGL_CONTEXT_FLAGS
#define GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY
#define GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY
#define GHOST_OPENGL_GLX_CONTEXT_FLAGS
#define GHOST_PRINTF(x,...)
#define GHOST_ASSERT(x, info)
static void DeviceAdded(uint32_t unused)
static void DeviceRemoved(uint32_t unused)
static char * txt_select_buffer
static Bool init_timestamp_scanner(Display *, XEvent *event, XPointer arg)
static void split(const char *text, const char *seps, char ***str, int *count)
int GHOST_X11_ApplicationErrorHandler(Display *display, XErrorEvent *event)
#define XCLIB_XCOUT_FALLBACK_UTF8
static char * txt_cut_buffer
#define XCLIB_XCOUT_FALLBACK
#define GHOST_INTERN_ATOM(atom)
static void SleepTillEvent(Display *display, int64_t maxSleep)
#define XCLIB_XCOUT_FALLBACK_COMP
static GHOST_TKey ghost_key_from_keysym_or_keycode(const KeySym key, const XkbDescPtr xkb_descr, const KeyCode keycode)
#define MAKE_ID(a, b, c, d)
static uchar bit_is_on(const uchar *ptr, int bit)
#define XCLIB_XCOUT_SENTCONVSEL
#define XCLIB_XCOUT_FALLBACK_TEXT
static GHOST_TKey ghost_key_from_keycode(const XkbDescPtr xkb_descr, const KeyCode keycode)
int GHOST_X11_ApplicationIOErrorHandler(Display *)
static GHOST_TSuccess getCursorPosition_impl(Display *display, int32_t &x, int32_t &y, Window *child_return)
#define GHOST_INTERN_ATOM_IF_EXISTS(atom)
static GHOST_TKey ghost_key_from_keysym(const KeySym key)
#define GHOST_X11_ERROR_HANDLERS_OVERRIDE(var)
#define GHOST_X11_ERROR_HANDLERS_RESTORE(var)
@ GHOST_kEventWindowClose
@ GHOST_kEventWindowActivate
@ GHOST_kEventWindowUpdate
@ GHOST_kEventWindowDeactivate
@ GHOST_kTabletModeEraser
@ GHOST_kTabletModeStylus
@ GHOST_glAlphaBackground
@ GHOST_kKeyNumpadAsterisk
GHOST_TDrawingContextType
@ GHOST_kModifierKeyRightControl
@ GHOST_kModifierKeyLeftControl
@ GHOST_kModifierKeyRightAlt
@ GHOST_kModifierKeyRightShift
@ GHOST_kModifierKeyLeftAlt
@ GHOST_kModifierKeyLeftShift
@ GHOST_kButtonMaskButton4
@ GHOST_kButtonMaskButton7
@ GHOST_kButtonMaskButton6
@ GHOST_kButtonMaskButton5
@ GHOST_kButtonMaskMiddle
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei width
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble top
__forceinline const avxb select(const avxb &m, const avxb &t, const avxb &f)
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
static btDbvtVolume bounds(btDbvtNode **leaves, int count)
bool isInsideButton(XEvent &e, uint button_num)
void drawButton(Display *display, Window &window, GC &borderGC, GC &buttonGC, uint button_num, const char *label)
uint button_text_offset_y
static GHOST_ISystem * getSystem()
virtual bool isDebugEnabled()=0
GHOST_IWindow * createWindow(const char *title, int32_t left, int32_t top, uint32_t width, uint32_t height, GHOST_TWindowState state, GHOST_TDrawingContextType type, GHOST_GLSettings glSettings, const bool exclusive=false, const bool is_dialog=false, const GHOST_IWindow *parentWindow=0)
GHOST_TSuccess disposeContext(GHOST_IContext *context)
void getClipboard_xcout(const XEvent *evt, Atom sel, Atom target, unsigned char **txt, unsigned long *len, unsigned int *context) const
GHOST_IContext * createOffscreenContext(GHOST_GLSettings glSettings)
void addDirtyWindow(GHOST_WindowX11 *bad_wind)
char * getClipboard(bool selection) const
Atom _NET_WM_STATE_MAXIMIZED_VERT
GHOST_TSuccess getCursorPosition(int32_t &x, int32_t &y) const
GHOST_TSuccess getButtons(GHOST_Buttons &buttons) const
void getMainDisplayDimensions(uint32_t &width, uint32_t &height) const
void putClipboard(const char *buffer, bool selection) const
GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys &keys) const
GHOST_TSuccess setCursorPosition(int32_t x, int32_t y)
Atom _NET_WM_STATE_FULLSCREEN
void getAllDisplayDimensions(uint32_t &width, uint32_t &height) const
uint64_t getMilliSeconds() const
uint8_t getNumDisplays() const
bool processEvents(bool waitForEvent)
struct GHOST_SystemX11::@1294 m_atom
GHOST_TSuccess showMessageBox(const char *title, const char *message, const char *help_label, const char *continue_label, const char *link, GHOST_DialogOptions dialog_options) const
Atom _NET_WM_STATE_MAXIMIZED_HORZ
virtual GHOST_TSuccess exit()
virtual GHOST_TSuccess init()
GHOST_TimerManager * getTimerManager() const
GHOST_WindowManager * m_windowManager
GHOST_TSuccess pushEvent(GHOST_IEvent *event)
GHOST_DisplayManager * m_displayManager
bool fireTimers(uint64_t time)
GHOST_TSuccess addWindow(GHOST_IWindow *window)
const std::vector< GHOST_IWindow * > & getWindows() const
GHOST_TSuccess setActiveWindow(GHOST_IWindow *window)
void setWindowInactive(const GHOST_IWindow *window)
GHOST_TWindowState m_post_state
void getClientBounds(GHOST_Rect &bounds) const
GHOST_TSuccess setState(GHOST_TWindowState state)
GHOST_TabletData & GetTabletData()
GHOST_TSuccess getCursorGrabBounds(GHOST_Rect &bounds)
void setCursorGrabAccum(int32_t x, int32_t y)
GHOST_TAxisFlag getCursorGrabAxis() const
bool getCursorGrabModeIsWarp() const
void getCursorGrabAccum(int32_t &x, int32_t &y) const
SyclQueue void void size_t num_bytes void
ccl_global float * buffer
unsigned __int64 uint64_t
void set(GHOST_TModifierKey mask, bool down)