int GetXI2OpCode() { Display *dpy = nux::GetGraphicsDisplay()->GetX11Display(); int opcode, event_base, error_base; if (!XQueryExtension(dpy, "XFIXES", &opcode, &event_base, &error_base)) { LOG_ERROR(logger) << "Missing XFixes"; return -1; } if (!XQueryExtension (dpy, "XInputExtension", &opcode, &event_base, &error_base)) { LOG_ERROR(logger) << "Missing XInput"; return -1; } int maj = MAJOR; int min = MINOR; if (XIQueryVersion(dpy, &maj, &min) == BadRequest) { LOG_ERROR(logger) << "Need XInput version 2.3"; return -1; } return opcode; }
/** * Initialises appropriate X extensions. */ static void initialise_extensions (void) { int major = 2, minor = 0; if (XIQueryVersion(gdk_x11_get_default_xdisplay (), &major, &minor) == BadRequest) { g_error("XI2 not available. Server supports %d.%d\n", major, minor); } }
static Status EInputQueryVersion(Display * dpy, int *major_version_return, int *minor_version_return) { *major_version_return = XI_2_Major; *minor_version_return = XI_2_Minor; return XIQueryVersion(dpy, major_version_return, minor_version_return); }
static void meta_backend_x11_post_init (MetaBackend *backend) { MetaBackendX11 *x11 = META_BACKEND_X11 (backend); MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); int major, minor; priv->xdisplay = clutter_x11_get_default_display (); priv->source = x_event_source_new (backend); if (!XSyncQueryExtension (priv->xdisplay, &priv->xsync_event_base, &priv->xsync_error_base) || !XSyncInitialize (priv->xdisplay, &major, &minor)) meta_fatal ("Could not initialize XSync"); { int major = 2, minor = 3; gboolean has_xi = FALSE; if (XQueryExtension (priv->xdisplay, "XInputExtension", &priv->xinput_opcode, &priv->xinput_error_base, &priv->xinput_event_base)) { if (XIQueryVersion (priv->xdisplay, &major, &minor) == Success) { int version = (major * 10) + minor; if (version >= 22) has_xi = TRUE; } } if (!has_xi) meta_fatal ("X server doesn't have the XInput extension, version 2.2 or newer\n"); } take_touch_grab (backend); priv->xcb = XGetXCBConnection (priv->xdisplay); if (!xkb_x11_setup_xkb_extension (priv->xcb, XKB_X11_MIN_MAJOR_XKB_VERSION, XKB_X11_MIN_MINOR_XKB_VERSION, XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS, NULL, NULL, &priv->xkb_event_base, &priv->xkb_error_base)) meta_fatal ("X server doesn't have the XKB extension, version %d.%d or newer\n", XKB_X11_MIN_MAJOR_XKB_VERSION, XKB_X11_MIN_MINOR_XKB_VERSION); g_signal_connect_object (clutter_device_manager_get_default (), "device-added", G_CALLBACK (on_device_added), backend, 0); META_BACKEND_CLASS (meta_backend_x11_parent_class)->post_init (backend); }
void QXcbConnection::initializeXInput2() { Display *xDisplay = static_cast<Display *>(m_xlib_display); if (XQueryExtension(xDisplay, "XInputExtension", &m_xiOpCode, &m_xiEventBase, &m_xiErrorBase)) { int xiMajor = 2; m_xi2Minor = 2; // try 2.2 first, needed for TouchBegin/Update/End if (XIQueryVersion(xDisplay, &xiMajor, &m_xi2Minor) == BadRequest) { m_xi2Minor = 0; // for tablet support 2.0 is enough m_xi2Enabled = XIQueryVersion(xDisplay, &xiMajor, &m_xi2Minor) != BadRequest; } else { m_xi2Enabled = true; } if (m_xi2Enabled) { #ifndef QT_NO_TABLETEVENT // Tablet support: Find the stylus-related devices. xi2SetupTabletDevices(); #endif // QT_NO_TABLETEVENT } } }
static void clutter_backend_x11_create_device_manager (ClutterBackendX11 *backend_x11) { ClutterEventTranslator *translator; ClutterBackend *backend; #ifdef HAVE_XINPUT_2 if (clutter_enable_xinput) { int event_base, first_event, first_error; if (XQueryExtension (backend_x11->xdpy, "XInputExtension", &event_base, &first_event, &first_error)) { int major = 2; int minor = 3; if (XIQueryVersion (backend_x11->xdpy, &major, &minor) != BadRequest) { CLUTTER_NOTE (BACKEND, "Creating XI2 device manager"); backend_x11->has_xinput = TRUE; backend_x11->device_manager = g_object_new (CLUTTER_TYPE_DEVICE_MANAGER_XI2, "backend", backend_x11, "opcode", event_base, NULL); backend_x11->xi_minor = minor; } } } if (backend_x11->device_manager == NULL) #endif /* HAVE_XINPUT_2 */ { CLUTTER_NOTE (BACKEND, "Creating Core device manager"); backend_x11->has_xinput = FALSE; backend_x11->device_manager = g_object_new (CLUTTER_TYPE_DEVICE_MANAGER_X11, "backend", backend_x11, NULL); backend_x11->xi_minor = -1; } backend = CLUTTER_BACKEND (backend_x11); backend->device_manager = backend_x11->device_manager; translator = CLUTTER_EVENT_TRANSLATOR (backend_x11->device_manager); _clutter_backend_add_event_translator (backend, translator); }
int main() { /* Connect to the X server */ Display *display = XOpenDisplay(NULL); Window win_root = XDefaultRootWindow(display); /* XInput Extension available? */ int opcode, event, error; if (!XQueryExtension(display, "XInputExtension", &opcode, &event, &error)) { printf("X Input extension not available.\n"); return -1; } /* Which version of XI2? We support 2.0 */ int major = 2, minor = 0; if (XIQueryVersion(display, &major, &minor) == BadRequest) { printf("XI2 not available. Server supports %d.%d\n", major, minor); return -1; } XIDetachSlaveInfo info; info.type = XIDetachSlave; info.deviceid = 10; XIAnyHierarchyChangeInfo any_info; any_info.type = XIDetachSlave; any_info.detach = info; XIChangeHierarchy(display, &any_info, 1); printf("Detached slave device 10\n"); int master_id = get_master_keyboard_id(display); if (master_id == -1){ printf("No master keyboard available.\n"); return -1; } std::this_thread::sleep_for(std::chrono::seconds(10)); XIAttachSlaveInfo attach_info; attach_info.type = XIAttachSlave; attach_info.deviceid = 10; attach_info.new_master = master_id; XIAnyHierarchyChangeInfo any_attach_info; any_attach_info.type = XIAttachSlave; any_attach_info.attach = attach_info; XIChangeHierarchy(display, &any_attach_info, 1); printf("Attached slave device 10\n"); XCloseDisplay(display); }
void extensions_init(void) { int event, error; if (!XQueryExtension(display, "XInputExtension", &xi_ext_opcode, &event, &error)) bail("XInput extension is not available."); int major_op = 2; int minor_op = 2; int result = XIQueryVersion(display, &major_op, &minor_op); if (result == BadRequest) bail("XI2 is not supported in a sufficient version (or at all)."); else if (result != Success) bail("Failed to query XI2 extension."); }
/* Return 1 if XI2 is available, 0 otherwise */ static int has_xi2(Display *dpy) { int major, minor; int rc; /* We support XI 2.2 */ major = 2; minor = 2; rc = XIQueryVersion(dpy, &major, &minor); if (rc == BadRequest) { MLOGE("No XI2 support. Server supports version %d.%d only.\n", major, minor); return 0; } return 1; }
GdkDeviceManager * _gdk_x11_device_manager_new (GdkDisplay *display) { if (!g_getenv ("GDK_CORE_DEVICE_EVENTS")) { #ifdef XINPUT_2 int opcode, firstevent, firsterror; Display *xdisplay; xdisplay = GDK_DISPLAY_XDISPLAY (display); if (XQueryExtension (xdisplay, "XInputExtension", &opcode, &firstevent, &firsterror)) { int major, minor; major = 2; minor = 3; if (!_gdk_disable_multidevice && XIQueryVersion (xdisplay, &major, &minor) != BadRequest) { GdkX11DeviceManagerXI2 *device_manager_xi2; GDK_NOTE (INPUT, g_message ("Creating XI2 device manager")); device_manager_xi2 = g_object_new (GDK_TYPE_X11_DEVICE_MANAGER_XI2, "display", display, "opcode", opcode, "major", major, "minor", minor, NULL); return GDK_DEVICE_MANAGER (device_manager_xi2); } } #endif /* XINPUT_2 */ } GDK_NOTE (INPUT, g_message ("Creating core device manager")); return g_object_new (GDK_TYPE_X11_DEVICE_MANAGER_CORE, "display", display, NULL); }
XLibWindowManagerAdapterPrivate::XLibWindowManagerAdapterPrivate( XLibWindowManagerAdapter *q) :q_ptr(q) { Window root; Status status; int xi_major = 2; int xi_minor = 2; m_mods.modifiers = XIAnyModifier; m_mods.status = 0; m_display = XOpenDisplay(NULL); Q_ASSERT_X(m_display, "XLibWindowManagerAdapter", "Failed to open connection to X server"); status = XIQueryVersion(m_display, &xi_major, &xi_minor); Q_ASSERT_X(status == Success, "XLibWindowManagerAdapter", "Failed to query XInput version"); if (xi_major < 2 || xi_minor < 2) { qFatal("XInput version of the server is too old (%d.%d)" , xi_major, xi_minor); } root = XDefaultRootWindow(m_display); XSelectInput(m_display, root, PropertyChangeMask); XMapWindow(m_display, root); XFlush(m_display); m_mask.deviceid = XIAllMasterDevices; m_mask.mask_len = XIMaskLen(XI_LASTEVENT); m_mask.mask = (unsigned char*)calloc(m_mask.mask_len, sizeof(unsigned char)); XISetMask(m_mask.mask, XI_TouchBegin); XISetMask(m_mask.mask, XI_TouchUpdate); XISetMask(m_mask.mask, XI_TouchEnd); XISetMask(m_mask.mask, XI_TouchOwnership); XISetMask(m_mask.mask, XI_HierarchyChanged); XIGrabTouchBegin(m_display, XIAllMasterDevices, root, 0, &m_mask, 1, &m_mods); }
/* Return 1 if XI2 is available, 0 otherwise */ static int has_xi2(Display *dpy) { int major, minor; int rc; /* We support XI 2.0 */ major = 2; minor = 0; rc = XIQueryVersion(dpy, &major, &minor); if (rc == BadRequest) { printf("No XI2 support. Server supports version %d.%d only.\n", major, minor); return 0; } else if (rc != Success) { fprintf(stderr, "Internal Error! This is a bug in Xlib.\n"); } printf("XI2 supported. Server provides version %d.%d.\n", major, minor); return 1; }
// This function will add zero or more KeyboardMouse objects to devices. void Init(std::vector<Core::Device*>& devices, void* const hwnd) { Display* dpy = XOpenDisplay(nullptr); // xi_opcode is important; it will be used to identify XInput events by // the polling loop in UpdateInput. int xi_opcode, event, error; // verify that the XInput extension is available if (!XQueryExtension(dpy, "XInputExtension", &xi_opcode, &event, &error)) return; // verify that the XInput extension is at at least version 2.0 int major = 2, minor = 0; if (XIQueryVersion(dpy, &major, &minor) != Success) return; // register all master devices with Dolphin XIDeviceInfo* all_masters; XIDeviceInfo* current_master; int num_masters; all_masters = XIQueryDevice(dpy, XIAllMasterDevices, &num_masters); for (int i = 0; i < num_masters; i++) { current_master = &all_masters[i]; if (current_master->use == XIMasterPointer) // Since current_master is a master pointer, its attachment must // be a master keyboard. devices.push_back(new KeyboardMouse((Window)hwnd, xi_opcode, current_master->deviceid, current_master->attachment)); } XCloseDisplay(dpy); XIFreeDeviceInfo(all_masters); }
bool Output::setup(const int width, const int height) { #if 0 /* Check if the XInput Extension is available */ int event, error; if (!XQueryExtension(display, "XInputExtension", &opcode, &event, &error)) { printf("X Input extension not available.\n"); return false; } ROS_INFO_STREAM("XInputExtension available"); /* Check for XI2 support */ int major = 2, minor = 0; if (XIQueryVersion(display, &major, &minor) == BadRequest) { printf("XI2 not available. Server supports %d.%d\n", major, minor); return false; } ROS_INFO_STREAM("XI2 available"); #endif /* bm::setupX(display, win, width, height, opcode); gc = XCreateGC(display, win, 0, NULL); ximage = XGetImage(display, DefaultRootWindow(display), 0, 0, width, height, AllPlanes, ZPixmap); screen = DefaultScreenOfDisplay(display); XStoreName(display, win, name.c_str()); ROS_INFO_STREAM(name << " created window " << CLVAL << display << " " << ximage <<CLNRM); if (!get_toplevel_parent(display, win, toplevel_parent)) { ROS_ERROR_STREAM(name << " couldn't get toplevel parent"); return false; } */ return true; }
int main () { Display *dpy; int rc; int major = 2; int minor = 2; dpy = XOpenDisplay(NULL); rc = XIQueryVersion(dpy, &major, &minor); if (rc == Success) printf("XI2 supported. (%d.%d)\n", major, minor); else if (rc == BadRequest) printf("No XI2 support. (%d.%d only)\n", major, minor); else printf("Internal error\n"); return 0; }
gboolean supports_xinput2_devices (int *opcode) { int major, minor; if (supports_xinput_devices_with_opcode (opcode) == FALSE) return FALSE; gdk_error_trap_push (); major = 2; minor = 0; if (XIQueryVersion (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), &major, &minor) != Success) { gdk_error_trap_pop_ignored (); return FALSE; } gdk_error_trap_pop_ignored (); if ((major * 1000 + minor) < (2000)) return FALSE; return TRUE; }
void _ecore_x_input_init(void) { #ifdef ECORE_XI2 int event, error; int major = 2, minor = 0; if (!XQueryExtension(_ecore_x_disp, "XInputExtension", &_ecore_x_xi2_opcode, &event, &error)) { _ecore_x_xi2_opcode = -1; return; } if (XIQueryVersion(_ecore_x_disp, &major, &minor) == BadRequest) { _ecore_x_xi2_opcode = -1; return; } _ecore_x_xi2_devs = XIQueryDevice(_ecore_x_disp, XIAllDevices, &_ecore_x_xi2_num); #endif /* ifdef ECORE_XI2 */ } /* _ecore_x_input_init */
static int xwinitxi2(struct fb *fb) { int major = 2; int minor = 2; int xi_opcode, event, error; XIEventMask evmask[1]; unsigned char mask[(XI_LASTEVENT + 7)/8] = {0}; if(!XQueryExtension(fb->hw->display, "XInputExtension", &xi_opcode, &event, &error)) { printf("XInputExtension is not available\n"); return -1; } if(XIQueryVersion(fb->hw->display, &major, &minor) == BadRequest) { printf("XI2 is not supported, server supports version %d.%d only\n", major, minor); return -1; } XISetMask(mask, XI_RawMotion); evmask[0].deviceid = XIAllMasterDevices; evmask[0].mask_len = sizeof(mask); evmask[0].mask = mask; XISelectEvents(fb->hw->display, DefaultRootWindow(fb->hw->display), evmask, 1); XFlush(fb->hw->display); return 0; }
void XInputMTInputDevice::start() { Status status; SDLDisplayEngine * pEngine = Player::get()->getDisplayEngine(); glm::vec2 size(pEngine->getSize()); glm::vec2 windowSize(pEngine->getWindowSize()); m_DisplayScale.x = size.x/windowSize.x; m_DisplayScale.y = size.y/windowSize.y; SDL_SysWMinfo info; SDL_VERSION(&info.version); int rc = SDL_GetWMInfo(&info); AVG_ASSERT(rc != -1); s_pDisplay = info.info.x11.display; m_SDLLockFunc = info.info.x11.lock_func; m_SDLUnlockFunc = info.info.x11.unlock_func; m_SDLLockFunc(); // XInput Extension available? int event, error; bool bOk = XQueryExtension(s_pDisplay, "XInputExtension", &m_XIOpcode, &event, &error); if (!bOk) { throw Exception(AVG_ERR_MT_INIT, "XInput multitouch event source: X Input extension not available."); } // Which version of XI2? int major; int minor; status = XIQueryVersion(s_pDisplay, &major, &minor); if (status == BadRequest) { throw Exception(AVG_ERR_MT_INIT, "XInput 2.1 multitouch event source: Server does not support XI2"); } if (major < 2 || minor < 1) { throw Exception(AVG_ERR_MT_INIT, "XInput multitouch event source: Supported version is " +toString(major)+"."+toString(minor)+". At least 2.1 is needed."); } findMTDevice(); // SDL grabs the pointer in full screen mode. This breaks touchscreen usage. // Can't use SDL_WM_GrabInput(SDL_GRAB_OFF) because it doesn't work in full // screen mode. Get the display connection and do it manually. XUngrabPointer(info.info.x11.display, CurrentTime); XIEventMask mask; mask.deviceid = m_DeviceID; mask.mask_len = XIMaskLen(XI_LASTEVENT); mask.mask = (unsigned char *)calloc(mask.mask_len, sizeof(char)); memset(mask.mask, 0, mask.mask_len); XISetMask(mask.mask, XI_TouchBegin); XISetMask(mask.mask, XI_TouchUpdate); XISetMask(mask.mask, XI_TouchEnd); status = XISelectEvents(s_pDisplay, info.info.x11.window, &mask, 1); AVG_ASSERT(status == Success); m_SDLUnlockFunc(); SDL_SetEventFilter(XInputMTInputDevice::filterEvent); XIDetachSlaveInfo detInfo; detInfo.type = XIDetachSlave; detInfo.deviceid = m_DeviceID; XIChangeHierarchy(s_pDisplay, (XIAnyHierarchyChangeInfo *)&detInfo, 1); pEngine->setXIMTInputDevice(this); MultitouchInputDevice::start(); AVG_TRACE(Logger::category::CONFIG, Logger::severity::INFO, "XInput Multitouch event source created."); }
// Initialize X11 display and look for supported X11 extensions // static GLFWbool initExtensions(void) { _glfw.x11.vidmode.handle = dlopen("libXxf86vm.so.1", RTLD_LAZY | RTLD_GLOBAL); if (_glfw.x11.vidmode.handle) { _glfw.x11.vidmode.QueryExtension = (PFN_XF86VidModeQueryExtension) dlsym(_glfw.x11.vidmode.handle, "XF86VidModeQueryExtension"); _glfw.x11.vidmode.GetGammaRamp = (PFN_XF86VidModeGetGammaRamp) dlsym(_glfw.x11.vidmode.handle, "XF86VidModeGetGammaRamp"); _glfw.x11.vidmode.SetGammaRamp = (PFN_XF86VidModeSetGammaRamp) dlsym(_glfw.x11.vidmode.handle, "XF86VidModeSetGammaRamp"); _glfw.x11.vidmode.GetGammaRampSize = (PFN_XF86VidModeGetGammaRampSize) dlsym(_glfw.x11.vidmode.handle, "XF86VidModeGetGammaRampSize"); _glfw.x11.vidmode.available = XF86VidModeQueryExtension(_glfw.x11.display, &_glfw.x11.vidmode.eventBase, &_glfw.x11.vidmode.errorBase); } _glfw.x11.xi.handle = dlopen("libXi.so", RTLD_LAZY | RTLD_GLOBAL); if (_glfw.x11.xi.handle) { _glfw.x11.xi.QueryVersion = (PFN_XIQueryVersion) dlsym(_glfw.x11.xi.handle, "XIQueryVersion"); _glfw.x11.xi.SelectEvents = (PFN_XISelectEvents) dlsym(_glfw.x11.xi.handle, "XISelectEvents"); if (XQueryExtension(_glfw.x11.display, "XInputExtension", &_glfw.x11.xi.majorOpcode, &_glfw.x11.xi.eventBase, &_glfw.x11.xi.errorBase)) { _glfw.x11.xi.major = 2; _glfw.x11.xi.minor = 0; if (XIQueryVersion(_glfw.x11.display, &_glfw.x11.xi.major, &_glfw.x11.xi.minor) == Success) { _glfw.x11.xi.available = GLFW_TRUE; } } } // Check for RandR extension if (XRRQueryExtension(_glfw.x11.display, &_glfw.x11.randr.eventBase, &_glfw.x11.randr.errorBase)) { if (XRRQueryVersion(_glfw.x11.display, &_glfw.x11.randr.major, &_glfw.x11.randr.minor)) { // The GLFW RandR path requires at least version 1.3 if (_glfw.x11.randr.major > 1 || _glfw.x11.randr.minor >= 3) _glfw.x11.randr.available = GLFW_TRUE; } else { _glfwInputError(GLFW_PLATFORM_ERROR, "X11: Failed to query RandR version"); } } if (_glfw.x11.randr.available) { XRRScreenResources* sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root); if (!sr->ncrtc || !XRRGetCrtcGammaSize(_glfw.x11.display, sr->crtcs[0])) { // This is either a headless system or an older Nvidia binary driver // with broken gamma support // Flag it as useless and fall back to Xf86VidMode gamma, if // available _glfwInputError(GLFW_PLATFORM_ERROR, "X11: Detected broken RandR gamma ramp support"); _glfw.x11.randr.gammaBroken = GLFW_TRUE; } if (!sr->ncrtc || !sr->noutput || !sr->nmode) { // This is either a headless system or broken Cygwin/X RandR // Flag it as useless and fall back to Xlib display functions _glfwInputError(GLFW_PLATFORM_ERROR, "X11: Detected broken RandR monitor support"); _glfw.x11.randr.monitorBroken = GLFW_TRUE; } XRRFreeScreenResources(sr); XRRSelectInput(_glfw.x11.display, _glfw.x11.root, RROutputChangeNotifyMask); } if (XineramaQueryExtension(_glfw.x11.display, &_glfw.x11.xinerama.major, &_glfw.x11.xinerama.minor)) { if (XineramaIsActive(_glfw.x11.display)) _glfw.x11.xinerama.available = GLFW_TRUE; } // Check if Xkb is supported on this display _glfw.x11.xkb.major = 1; _glfw.x11.xkb.minor = 0; _glfw.x11.xkb.available = XkbQueryExtension(_glfw.x11.display, &_glfw.x11.xkb.majorOpcode, &_glfw.x11.xkb.eventBase, &_glfw.x11.xkb.errorBase, &_glfw.x11.xkb.major, &_glfw.x11.xkb.minor); if (_glfw.x11.xkb.available) { Bool supported; if (XkbSetDetectableAutoRepeat(_glfw.x11.display, True, &supported)) { if (supported) _glfw.x11.xkb.detectable = GLFW_TRUE; } } _glfw.x11.x11xcb.handle = dlopen("libX11-xcb.so.1", RTLD_LAZY | RTLD_GLOBAL); if (_glfw.x11.x11xcb.handle) { _glfw.x11.x11xcb.XGetXCBConnection = (PFN_XGetXCBConnection) dlsym(_glfw.x11.x11xcb.handle, "XGetXCBConnection"); } // Update the key code LUT // FIXME: We should listen to XkbMapNotify events to track changes to // the keyboard mapping. createKeyTables(); // Detect whether an EWMH-conformant window manager is running detectEWMH(); // String format atoms _glfw.x11.NULL_ = XInternAtom(_glfw.x11.display, "NULL", False); _glfw.x11.UTF8_STRING = XInternAtom(_glfw.x11.display, "UTF8_STRING", False); _glfw.x11.COMPOUND_STRING = XInternAtom(_glfw.x11.display, "COMPOUND_STRING", False); _glfw.x11.ATOM_PAIR = XInternAtom(_glfw.x11.display, "ATOM_PAIR", False); // Custom selection property atom _glfw.x11.GLFW_SELECTION = XInternAtom(_glfw.x11.display, "GLFW_SELECTION", False); // ICCCM standard clipboard atoms _glfw.x11.TARGETS = XInternAtom(_glfw.x11.display, "TARGETS", False); _glfw.x11.MULTIPLE = XInternAtom(_glfw.x11.display, "MULTIPLE", False); _glfw.x11.CLIPBOARD = XInternAtom(_glfw.x11.display, "CLIPBOARD", False); // Clipboard manager atoms _glfw.x11.CLIPBOARD_MANAGER = XInternAtom(_glfw.x11.display, "CLIPBOARD_MANAGER", False); _glfw.x11.SAVE_TARGETS = XInternAtom(_glfw.x11.display, "SAVE_TARGETS", False); // Xdnd (drag and drop) atoms _glfw.x11.XdndAware = XInternAtom(_glfw.x11.display, "XdndAware", False); _glfw.x11.XdndEnter = XInternAtom(_glfw.x11.display, "XdndEnter", False); _glfw.x11.XdndPosition = XInternAtom(_glfw.x11.display, "XdndPosition", False); _glfw.x11.XdndStatus = XInternAtom(_glfw.x11.display, "XdndStatus", False); _glfw.x11.XdndActionCopy = XInternAtom(_glfw.x11.display, "XdndActionCopy", False); _glfw.x11.XdndDrop = XInternAtom(_glfw.x11.display, "XdndDrop", False); _glfw.x11.XdndFinished = XInternAtom(_glfw.x11.display, "XdndFinished", False); _glfw.x11.XdndSelection = XInternAtom(_glfw.x11.display, "XdndSelection", False); _glfw.x11.XdndTypeList = XInternAtom(_glfw.x11.display, "XdndTypeList", False); _glfw.x11.text_uri_list = XInternAtom(_glfw.x11.display, "text/uri-list", False); // ICCCM, EWMH and Motif window property atoms // These can be set safely even without WM support // The EWMH atoms that require WM support are handled in detectEWMH _glfw.x11.WM_PROTOCOLS = XInternAtom(_glfw.x11.display, "WM_PROTOCOLS", False); _glfw.x11.WM_STATE = XInternAtom(_glfw.x11.display, "WM_STATE", False); _glfw.x11.WM_DELETE_WINDOW = XInternAtom(_glfw.x11.display, "WM_DELETE_WINDOW", False); _glfw.x11.NET_WM_ICON = XInternAtom(_glfw.x11.display, "_NET_WM_ICON", False); _glfw.x11.NET_WM_PING = XInternAtom(_glfw.x11.display, "_NET_WM_PING", False); _glfw.x11.NET_WM_PID = XInternAtom(_glfw.x11.display, "_NET_WM_PID", False); _glfw.x11.NET_WM_NAME = XInternAtom(_glfw.x11.display, "_NET_WM_NAME", False); _glfw.x11.NET_WM_ICON_NAME = XInternAtom(_glfw.x11.display, "_NET_WM_ICON_NAME", False); _glfw.x11.NET_WM_BYPASS_COMPOSITOR = XInternAtom(_glfw.x11.display, "_NET_WM_BYPASS_COMPOSITOR", False); _glfw.x11.MOTIF_WM_HINTS = XInternAtom(_glfw.x11.display, "_MOTIF_WM_HINTS", False); return GLFW_TRUE; }
static void x11_init(void) { memset(keys, 0, KEYMAX); memset(mouse, 0, 3); display = XOpenDisplay(0); screen = DefaultScreen(display); xvis = glXChooseVisual(display, screen, xAttrList); if(!xvis) { printf("glXChooseVisual() failed.\n"); exit(1); } glx_context = glXCreateContext(display, xvis, 0, GL_TRUE); memset(&xwin_attr, 0, sizeof(XSetWindowAttributes)); xwin_attr.colormap = XCreateColormap(display, RootWindow(display, xvis->screen), xvis->visual, AllocNone); xwin_attr.event_mask = ExposureMask | StructureNotifyMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | KeyPressMask | KeyReleaseMask; x11_window(); static char buf[] = { 0,0,0,0,0,0,0,0 }; XColor black = { .red=0, .green=0, .blue=0 }; Pixmap bitmap = XCreateBitmapFromData(display, window, buf, 2, 2); cursor_none = XCreatePixmapCursor(display, bitmap, bitmap, &black, &black, 0, 0); int event, error; if (!XQueryExtension(display, "XInputExtension", &opcode, &event, &error)) { printf("X Input extension not available.\n"); return; } #ifdef ASD /* Which version of XI2? We support 2.0 */ int major = 2, minor = 0; if (XIQueryVersion(display, &major, &minor) == BadRequest) { printf("XI2 not available. Server supports %d.%d\n", major, minor); return; } XIEventMask eventmask; unsigned char mask[3] = { 0,0,0 }; /* the actual mask */ eventmask.deviceid = XIAllDevices; eventmask.mask_len = sizeof(mask); /* always in bytes */ eventmask.mask = mask; /* now set the mask */ // XISetMask(mask, XI_ButtonPress); // XISetMask(mask, XI_ButtonRelease); XISetMask(mask, XI_RawMotion); // XISetMask(mask, XI_KeyPress); // mask = mask | KeyReleaseMask | KeyPressMask; /* select on the window */ Window root = DefaultRootWindow(display); XISelectEvents(display, root, &eventmask, 1); // XSetDeviceMode(display, mouse, Relative); #endif } void print_rawmotion(XIRawEvent *event) { int i; double *raw_valuator = event->raw_values, *valuator = event->valuators.values; for (i = 0; i < event->valuators.mask_len * 8; i++) { if (XIMaskIsSet(event->valuators.mask, i)) { switch(i) { case 0: mickey_x += *valuator; break; case 1: mickey_y += *valuator; break; default: break; } valuator++; raw_valuator++; } } }
int main (int argc, char** argv) { /* Connect to the X server */ Display *display = XOpenDisplay(NULL); int screen_num; XGCValues values; Colormap colormap; /* Check if the XInput Extension is available */ int opcode, event, error; if (!XQueryExtension(display, "XInputExtension", &opcode, &event, &error)) { printf("X Input extension not available.\n"); return -1; } /* Check for XI2 support */ int major = 2, minor = 0; if (XIQueryVersion(display, &major, &minor) == BadRequest) { printf("XI2 not available. Server supports %d.%d\n", major, minor); return -1; } /* Get screen size from display structure macro */ screen_num = DefaultScreen(display); int display_width = DisplayWidth(display, screen_num); int display_height = DisplayHeight(display, screen_num); printf("screen_num: %d\n", screen_num); printf("display_width: %d\n", display_width); printf("display_height: %d\n", display_height); /* set window dimensions */ int width = display_width/4*3; int height = display_height/4*3; int border_width = 3; printf("width: %d\n", width); printf("height: %d\n", height); /* create opaque window */ Window win = XCreateSimpleWindow(display, DefaultRootWindow(display), 0, 0, width, height, border_width, WhitePixel(display, screen_num), BlackPixel(display,screen_num)); printf("win: %d\n", (int)win); /* Display window */ XMapWindow(display, win); XSync( display, False ); /* Set default values for pens (GCs) to draw lines with */ values.foreground = WhitePixel(display, screen_num); values.line_width = 10; values.line_style = LineSolid; values.cap_style = CapRound; /* Create colormap */ colormap = DefaultColormap(display, screen_num); /* Set up MPX events */ XIEventMask eventmask; unsigned char mask[1] = { 0 }; eventmask.deviceid = XIAllMasterDevices; eventmask.mask_len = sizeof(mask); eventmask.mask = mask; /* Events we want to listen for */ XISetMask(mask, XI_Motion); XISetMask(mask, XI_ButtonPress); XISetMask(mask, XI_ButtonRelease); XISetMask(mask, XI_KeyPress); XISetMask(mask, XI_KeyRelease); /* Register events on the window */ XISelectEvents(display, win, &eventmask, 1); /* Maximum pointer count */ const unsigned int numPointers = 0xFF; Pointer pointers[numPointers]; /* Initialize pointers */ int i; for(i=0; i<numPointers; i++) { pointers[i].down = 0; pointers[i].p.x = -1; pointers[i].p.y = -1; pointers[i].lastp.x = -1; pointers[i].lastp.y = -1; } /* Event loop */ while(1) { XEvent ev; /* Get next event; blocks until an event occurs */ XNextEvent(display, &ev); if (ev.xcookie.type == GenericEvent && ev.xcookie.extension == opcode && XGetEventData(display, &ev.xcookie)) { XIDeviceEvent* evData = (XIDeviceEvent*)(ev.xcookie.data); int deviceID = evData->deviceid; Pointer *pointer = &pointers[deviceID]; switch(ev.xcookie.evtype) { case XI_Motion: printf("motion\n"); if(pointer->down) { /* Draw a line from the last point to the next one; multiple lines of these create a stroke */ XDrawLine(display, win, pointer->gc, pointer->lastp.x, pointer->lastp.y, evData->event_x, evData->event_y); // Comment out the following for interesting structures pointer->lastp.x = evData->event_x; pointer->lastp.y = evData->event_y; } break; case XI_ButtonPress: printf("click - "); printf("button: %d - ", evData->detail); printf("abs X:%f Y:%f - ", evData->root_x, evData->root_y); printf("win X:%f Y:%f\n", evData->event_x, evData->event_y); /* Create random color for each stroke */ values.foreground = rand() % 0xFFFFFF; pointer->gc = XCreateGC(display, win, GCForeground|GCLineWidth|GCLineStyle|GCCapStyle, &values); XDrawLine(display, win, pointer->gc, evData->event_x, evData->event_y, evData->event_x, evData->event_y); pointer->down = 1; pointer->p.x = evData->event_x; pointer->p.y = evData->event_y; pointer->lastp.x = evData->event_x; pointer->lastp.y = evData->event_y; break; case XI_ButtonRelease: printf("unclick\n"); pointer->down = 0; break; case XI_KeyPress: printf("key down\n"); break; case XI_KeyRelease: printf("key up\n"); break; } } XFreeEventData(display, &ev.xcookie); } XDestroyWindow(display, win); return 0; }
void X11Extras::x11ResetMouseAccelerationChange() { //QTextStream out(stdout); int xi_opcode, event, error; xi_opcode = event = error = 0; Display *display = this->display(); bool result = XQueryExtension(display, "XInputExtension", &xi_opcode, &event, &error); if (!result) { Logger::LogInfo(tr("xinput extension was not found. No mouse acceleration changes will occur.")); //out << tr("xinput extension was not found. No mouse acceleration changes will occur.") << endl; } else { int ximajor = 2, ximinor = 0; if (XIQueryVersion(display, &ximajor, &ximinor) != Success) { Logger::LogInfo(tr("xinput version must be at least 2.0. No mouse acceleration changes will occur.")); //out << tr("xinput version must be at least 2.0. No mouse acceleration changes will occur.") << endl; } } if (result) { XIDeviceInfo *all_devices = 0; XIDeviceInfo *current_devices = 0; XIDeviceInfo *mouse_device = 0; int num_devices = 0; all_devices = XIQueryDevice(display, XIAllDevices, &num_devices); for (int i=0; i < num_devices; i++) { current_devices = &all_devices[i]; if (current_devices->use == XISlavePointer && QString::fromUtf8(current_devices->name) == mouseDeviceName) { Logger::LogInfo(tr("Virtual pointer found with id=%1.").arg(current_devices->deviceid)); //out << tr("Virtual pointer found with id=%1.").arg(current_devices->deviceid) // << endl; mouse_device = current_devices; } } if (mouse_device) { XDevice *device = XOpenDevice(display, mouse_device->deviceid); int num_feedbacks = 0; int feedback_id = -1; XFeedbackState *feedbacks = XGetFeedbackControl(display, device, &num_feedbacks); XFeedbackState *temp = feedbacks; for (int i=0; (i < num_feedbacks) && (feedback_id == -1); i++) { if (temp->c_class == PtrFeedbackClass) { feedback_id = temp->id; } if (i+1 < num_feedbacks) { temp = (XFeedbackState*) ((char*) temp + temp->length); } } XFree(feedbacks); feedbacks = temp = 0; if (feedback_id <= -1) { Logger::LogInfo(tr("PtrFeedbackClass was not found for virtual pointer." "No change to mouse acceleration will occur for device with id=%1").arg(device->device_id)); //out << tr("PtrFeedbackClass was not found for virtual pointer." // "No change to mouse acceleration will occur for device with id=%1").arg(device->device_id) // << endl; result = false; } else { Logger::LogInfo(tr("Changing mouse acceleration for device with id=%1").arg(device->device_id)); //out << tr("Changing mouse acceleration for device with id=%1").arg(device->device_id) // << endl; XPtrFeedbackControl feedback; feedback.c_class = PtrFeedbackClass; feedback.length = sizeof(XPtrFeedbackControl); feedback.id = feedback_id; feedback.threshold = 0; feedback.accelNum = 1; feedback.accelDenom = 1; XChangeFeedbackControl(display, device, DvAccelNum|DvAccelDenom|DvThreshold, (XFeedbackControl*) &feedback); XSync(display, false); } XCloseDevice(display, device); } if (all_devices) { XIFreeDeviceInfo(all_devices); } } }
int main(int argc, char **argv) { int doDaemonize = 1; int i; for (i = 1; i < argc; i++) { if (strcmp(argv[i], "--debug") == 0) { doDaemonize = 0; debugMode = 1; } } if (doDaemonize) { daemonize(); } /* Connect to X server */ if ((display = XOpenDisplay((char *) NULL)) == NULL) { fprintf(stderr, "Couldn't connect to X server\n"); exit(1); } absXAtom = XInternAtom(display, "Abs X", FALSE); absYAtom = XInternAtom(display, "Abs Y", FALSE); floatAtom = XInternAtom(display, "FLOAT", FALSE); /* Read X data */ screenNum = DefaultScreen(display); root = RootWindow(display, screenNum); lastScreenWidth = DisplayWidth(display, screenNum); lastScreenHeight = DisplayHeight(display, screenNum); /* We have two threads accessing X */ XInitThreads(); int opcode, event, error; if (!XQueryExtension(display, "RANDR", &opcode, &event, &error)) { printf("X RANDR extension not available.\n"); XCloseDisplay(display); exit(1); } /* Which version of XRandR? We support 1.3 */ int major = 1, minor = 3; if (!XRRQueryVersion(display, &major, &minor)) { printf("XRandR version not available.\n"); XCloseDisplay(display); exit(1); } else if(!(major>1 || (major == 1 && minor >= 3))) { printf("XRandR 1.3 not available. Server supports %d.%d\n", major, minor); XCloseDisplay(display); exit(1); } /* XInput Extension available? */ if (!XQueryExtension(display, "XInputExtension", &opcode, &event, &error)) { printf("X Input extension not available.\n"); XCloseDisplay(display); exit(1); } /* Which version of XI2? We support 2.0 */ major = 2; minor = 0; if (XIQueryVersion(display, &major, &minor) == BadRequest) { printf("XI2 not available. Server supports %d.%d\n", major, minor); XCloseDisplay(display); exit(1); } XRRSelectInput(display, root, RRScreenChangeNotifyMask | RROutputChangeNotifyMask | RROutputPropertyNotifyMask | RRCrtcChangeNotifyMask); /* Register for XInput device change events */ XIEventMask eventmask; unsigned char mask[2] = { 0, 0 }; /* the actual mask */ eventmask.deviceid = XIAllDevices; eventmask.mask_len = sizeof(mask); /* always in bytes */ eventmask.mask = mask; /* now set the mask */ XISetMask(mask, XI_HierarchyChanged); /* select on the window */ XISelectEvents(display, root, &eventmask, 1); loadSettings(&profiles, NULL, NULL); handleDeviceChange(); sigemptyset(&signalSet); sigaddset(&signalSet, SIGUSR1); pthread_sigmask (SIG_BLOCK, &signalSet, NULL); if(pthread_create(&signalThread, NULL, signalThreadFunction, NULL)) { printf("Couldn't create signal thread.\n"); } xLoop(); freeSettings(&profiles); XCloseDisplay(display); return 0; }
// Initialize X11 display and look for supported X11 extensions // static GLboolean initExtensions(void) { Bool supported; // Find or create window manager atoms _glfw.x11.WM_STATE = XInternAtom(_glfw.x11.display, "WM_STATE", False); _glfw.x11.WM_DELETE_WINDOW = XInternAtom(_glfw.x11.display, "WM_DELETE_WINDOW", False); _glfw.x11.MOTIF_WM_HINTS = XInternAtom(_glfw.x11.display, "_MOTIF_WM_HINTS", False); // Check for XF86VidMode extension _glfw.x11.vidmode.available = XF86VidModeQueryExtension(_glfw.x11.display, &_glfw.x11.vidmode.eventBase, &_glfw.x11.vidmode.errorBase); // Check for RandR extension _glfw.x11.randr.available = XRRQueryExtension(_glfw.x11.display, &_glfw.x11.randr.eventBase, &_glfw.x11.randr.errorBase); if (_glfw.x11.randr.available) { if (!XRRQueryVersion(_glfw.x11.display, &_glfw.x11.randr.versionMajor, &_glfw.x11.randr.versionMinor)) { _glfwInputError(GLFW_PLATFORM_ERROR, "X11: Failed to query RandR version"); return GL_FALSE; } // The GLFW RandR path requires at least version 1.3 if (_glfw.x11.randr.versionMajor == 1 && _glfw.x11.randr.versionMinor < 3) { _glfw.x11.randr.available = GL_FALSE; } } if (XQueryExtension(_glfw.x11.display, "XInputExtension", &_glfw.x11.xi.majorOpcode, &_glfw.x11.xi.eventBase, &_glfw.x11.xi.errorBase)) { _glfw.x11.xi.versionMajor = 2; _glfw.x11.xi.versionMinor = 0; if (XIQueryVersion(_glfw.x11.display, &_glfw.x11.xi.versionMajor, &_glfw.x11.xi.versionMinor) != BadRequest) { _glfw.x11.xi.available = GL_TRUE; } } // Check if Xkb is supported on this display _glfw.x11.xkb.versionMajor = 1; _glfw.x11.xkb.versionMinor = 0; if (!XkbQueryExtension(_glfw.x11.display, &_glfw.x11.xkb.majorOpcode, &_glfw.x11.xkb.eventBase, &_glfw.x11.xkb.errorBase, &_glfw.x11.xkb.versionMajor, &_glfw.x11.xkb.versionMinor)) { _glfwInputError(GLFW_PLATFORM_ERROR, "X11: The keyboard extension is not available"); return GL_FALSE; } if (!XkbSetDetectableAutoRepeat(_glfw.x11.display, True, &supported)) { _glfwInputError(GLFW_PLATFORM_ERROR, "X11: Failed to set detectable key repeat"); return GL_FALSE; } if (!supported) { _glfwInputError(GLFW_PLATFORM_ERROR, "X11: Detectable key repeat is not supported"); return GL_FALSE; } // Update the key code LUT // FIXME: We should listen to XkbMapNotify events to track changes to // the keyboard mapping. updateKeyCodeLUT(); // Detect whether an EWMH-conformant window manager is running detectEWMH(); // Find or create string format atoms _glfw.x11.UTF8_STRING = XInternAtom(_glfw.x11.display, "UTF8_STRING", False); _glfw.x11.COMPOUND_STRING = XInternAtom(_glfw.x11.display, "COMPOUND_STRING", False); _glfw.x11.ATOM_PAIR = XInternAtom(_glfw.x11.display, "ATOM_PAIR", False); // Find or create selection property atom _glfw.x11.GLFW_SELECTION = XInternAtom(_glfw.x11.display, "GLFW_SELECTION", False); // Find or create standard clipboard atoms _glfw.x11.TARGETS = XInternAtom(_glfw.x11.display, "TARGETS", False); _glfw.x11.MULTIPLE = XInternAtom(_glfw.x11.display, "MULTIPLE", False); _glfw.x11.CLIPBOARD = XInternAtom(_glfw.x11.display, "CLIPBOARD", False); // Find or create clipboard manager atoms _glfw.x11.CLIPBOARD_MANAGER = XInternAtom(_glfw.x11.display, "CLIPBOARD_MANAGER", False); _glfw.x11.SAVE_TARGETS = XInternAtom(_glfw.x11.display, "SAVE_TARGETS", False); return GL_TRUE; }
// Initialize X11 display and look for supported X11 extensions // static GLboolean initDisplay(void) { Bool supported; _glfw.x11.display = XOpenDisplay(NULL); if (!_glfw.x11.display) { _glfwInputError(GLFW_API_UNAVAILABLE, "X11: Failed to open X display"); return GL_FALSE; } // As the API currently doesn't understand multiple display devices, we hard-code // this choice and hope for the best _glfw.x11.screen = DefaultScreen(_glfw.x11.display); _glfw.x11.root = RootWindow(_glfw.x11.display, _glfw.x11.screen); // Find or create window manager atoms _glfw.x11.WM_STATE = XInternAtom(_glfw.x11.display, "WM_STATE", False); _glfw.x11.WM_DELETE_WINDOW = XInternAtom(_glfw.x11.display, "WM_DELETE_WINDOW", False); // Check for XF86VidMode extension _glfw.x11.vidmode.available = XF86VidModeQueryExtension(_glfw.x11.display, &_glfw.x11.vidmode.eventBase, &_glfw.x11.vidmode.errorBase); // Check for RandR extension _glfw.x11.randr.available = XRRQueryExtension(_glfw.x11.display, &_glfw.x11.randr.eventBase, &_glfw.x11.randr.errorBase); if (_glfw.x11.randr.available) { if (!XRRQueryVersion(_glfw.x11.display, &_glfw.x11.randr.versionMajor, &_glfw.x11.randr.versionMinor)) { _glfwInputError(GLFW_PLATFORM_ERROR, "X11: Failed to query RandR version"); return GL_FALSE; } // The GLFW RandR path requires at least version 1.3 if (_glfw.x11.randr.versionMajor == 1 && _glfw.x11.randr.versionMinor < 3) { _glfw.x11.randr.available = GL_FALSE; } } if (XQueryExtension(_glfw.x11.display, "XInputExtension", &_glfw.x11.xi2.majorOpcode, &_glfw.x11.xi2.eventBase, &_glfw.x11.xi2.errorBase)) { _glfw.x11.xi2.versionMajor = 2; _glfw.x11.xi2.versionMinor = 0; if (XIQueryVersion(_glfw.x11.display, &_glfw.x11.xi2.versionMajor, &_glfw.x11.xi2.versionMinor) != BadRequest) { _glfw.x11.xi2.available = GL_TRUE; } } // Check if Xkb is supported on this display _glfw.x11.xkb.versionMajor = 1; _glfw.x11.xkb.versionMinor = 0; if (!XkbQueryExtension(_glfw.x11.display, &_glfw.x11.xkb.majorOpcode, &_glfw.x11.xkb.eventBase, &_glfw.x11.xkb.errorBase, &_glfw.x11.xkb.versionMajor, &_glfw.x11.xkb.versionMinor)) { _glfwInputError(GLFW_PLATFORM_ERROR, "X11: The keyboard extension is not available"); return GL_FALSE; } if (!XkbSetDetectableAutoRepeat(_glfw.x11.display, True, &supported)) { _glfwInputError(GLFW_PLATFORM_ERROR, "X11: Failed to set detectable key repeat"); return GL_FALSE; } if (!supported) { _glfwInputError(GLFW_PLATFORM_ERROR, "X11: Detectable key repeat is not supported"); return GL_FALSE; } // Update the key code LUT // FIXME: We should listen to XkbMapNotify events to track changes to // the keyboard mapping. updateKeyCodeLUT(); // Detect whether an EWMH-conformant window manager is running detectEWMH(); // Find or create string format atoms _glfw.x11.UTF8_STRING = XInternAtom(_glfw.x11.display, "UTF8_STRING", False); _glfw.x11.COMPOUND_STRING = XInternAtom(_glfw.x11.display, "COMPOUND_STRING", False); // Find or create selection property atom _glfw.x11.selection.property = XInternAtom(_glfw.x11.display, "GLFW_SELECTION", False); // Find or create standard clipboard atoms _glfw.x11.TARGETS = XInternAtom(_glfw.x11.display, "TARGETS", False); _glfw.x11.CLIPBOARD = XInternAtom(_glfw.x11.display, "CLIPBOARD", False); // Find or create selection target atoms _glfw.x11.selection.formats[_GLFW_CLIPBOARD_FORMAT_UTF8] = _glfw.x11.UTF8_STRING; _glfw.x11.selection.formats[_GLFW_CLIPBOARD_FORMAT_COMPOUND] = _glfw.x11.COMPOUND_STRING; _glfw.x11.selection.formats[_GLFW_CLIPBOARD_FORMAT_STRING] = XA_STRING; return GL_TRUE; }
// Look for and initialize supported X11 extensions // static GLFWbool initExtensions(void) { _glfw.x11.vidmode.handle = _glfw_dlopen("libXxf86vm.so.1"); if (_glfw.x11.vidmode.handle) { _glfw.x11.vidmode.QueryExtension = (PFN_XF86VidModeQueryExtension) _glfw_dlsym(_glfw.x11.vidmode.handle, "XF86VidModeQueryExtension"); _glfw.x11.vidmode.GetGammaRamp = (PFN_XF86VidModeGetGammaRamp) _glfw_dlsym(_glfw.x11.vidmode.handle, "XF86VidModeGetGammaRamp"); _glfw.x11.vidmode.SetGammaRamp = (PFN_XF86VidModeSetGammaRamp) _glfw_dlsym(_glfw.x11.vidmode.handle, "XF86VidModeSetGammaRamp"); _glfw.x11.vidmode.GetGammaRampSize = (PFN_XF86VidModeGetGammaRampSize) _glfw_dlsym(_glfw.x11.vidmode.handle, "XF86VidModeGetGammaRampSize"); _glfw.x11.vidmode.available = XF86VidModeQueryExtension(_glfw.x11.display, &_glfw.x11.vidmode.eventBase, &_glfw.x11.vidmode.errorBase); } #if defined(__CYGWIN__) _glfw.x11.xi.handle = _glfw_dlopen("libXi-6.so"); #else _glfw.x11.xi.handle = _glfw_dlopen("libXi.so.6"); #endif if (_glfw.x11.xi.handle) { _glfw.x11.xi.QueryVersion = (PFN_XIQueryVersion) _glfw_dlsym(_glfw.x11.xi.handle, "XIQueryVersion"); _glfw.x11.xi.SelectEvents = (PFN_XISelectEvents) _glfw_dlsym(_glfw.x11.xi.handle, "XISelectEvents"); if (XQueryExtension(_glfw.x11.display, "XInputExtension", &_glfw.x11.xi.majorOpcode, &_glfw.x11.xi.eventBase, &_glfw.x11.xi.errorBase)) { _glfw.x11.xi.major = 2; _glfw.x11.xi.minor = 0; if (XIQueryVersion(_glfw.x11.display, &_glfw.x11.xi.major, &_glfw.x11.xi.minor) == Success) { _glfw.x11.xi.available = GLFW_TRUE; } } } #if defined(__CYGWIN__) _glfw.x11.randr.handle = _glfw_dlopen("libXrandr-2.so"); #else _glfw.x11.randr.handle = _glfw_dlopen("libXrandr.so.2"); #endif if (_glfw.x11.randr.handle) { _glfw.x11.randr.AllocGamma = (PFN_XRRAllocGamma) _glfw_dlsym(_glfw.x11.randr.handle, "XRRAllocGamma"); _glfw.x11.randr.FreeGamma = (PFN_XRRFreeGamma) _glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeGamma"); _glfw.x11.randr.FreeCrtcInfo = (PFN_XRRFreeCrtcInfo) _glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeCrtcInfo"); _glfw.x11.randr.FreeGamma = (PFN_XRRFreeGamma) _glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeGamma"); _glfw.x11.randr.FreeOutputInfo = (PFN_XRRFreeOutputInfo) _glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeOutputInfo"); _glfw.x11.randr.FreeScreenResources = (PFN_XRRFreeScreenResources) _glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeScreenResources"); _glfw.x11.randr.GetCrtcGamma = (PFN_XRRGetCrtcGamma) _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetCrtcGamma"); _glfw.x11.randr.GetCrtcGammaSize = (PFN_XRRGetCrtcGammaSize) _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetCrtcGammaSize"); _glfw.x11.randr.GetCrtcInfo = (PFN_XRRGetCrtcInfo) _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetCrtcInfo"); _glfw.x11.randr.GetOutputInfo = (PFN_XRRGetOutputInfo) _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetOutputInfo"); _glfw.x11.randr.GetOutputPrimary = (PFN_XRRGetOutputPrimary) _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetOutputPrimary"); _glfw.x11.randr.GetScreenResourcesCurrent = (PFN_XRRGetScreenResourcesCurrent) _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetScreenResourcesCurrent"); _glfw.x11.randr.QueryExtension = (PFN_XRRQueryExtension) _glfw_dlsym(_glfw.x11.randr.handle, "XRRQueryExtension"); _glfw.x11.randr.QueryVersion = (PFN_XRRQueryVersion) _glfw_dlsym(_glfw.x11.randr.handle, "XRRQueryVersion"); _glfw.x11.randr.SelectInput = (PFN_XRRSelectInput) _glfw_dlsym(_glfw.x11.randr.handle, "XRRSelectInput"); _glfw.x11.randr.SetCrtcConfig = (PFN_XRRSetCrtcConfig) _glfw_dlsym(_glfw.x11.randr.handle, "XRRSetCrtcConfig"); _glfw.x11.randr.SetCrtcGamma = (PFN_XRRSetCrtcGamma) _glfw_dlsym(_glfw.x11.randr.handle, "XRRSetCrtcGamma"); _glfw.x11.randr.UpdateConfiguration = (PFN_XRRUpdateConfiguration) _glfw_dlsym(_glfw.x11.randr.handle, "XRRUpdateConfiguration"); if (XRRQueryExtension(_glfw.x11.display, &_glfw.x11.randr.eventBase, &_glfw.x11.randr.errorBase)) { if (XRRQueryVersion(_glfw.x11.display, &_glfw.x11.randr.major, &_glfw.x11.randr.minor)) { // The GLFW RandR path requires at least version 1.3 if (_glfw.x11.randr.major > 1 || _glfw.x11.randr.minor >= 3) _glfw.x11.randr.available = GLFW_TRUE; } else { _glfwInputError(GLFW_PLATFORM_ERROR, "X11: Failed to query RandR version"); } } } if (_glfw.x11.randr.available) { XRRScreenResources* sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root); if (!sr->ncrtc || !XRRGetCrtcGammaSize(_glfw.x11.display, sr->crtcs[0])) { // This is likely an older Nvidia driver with broken gamma support // Flag it as useless and fall back to xf86vm gamma, if available _glfw.x11.randr.gammaBroken = GLFW_TRUE; } if (!sr->ncrtc) { // A system without CRTCs is likely a system with broken RandR // Disable the RandR monitor path and fall back to core functions _glfw.x11.randr.monitorBroken = GLFW_TRUE; } XRRFreeScreenResources(sr); } if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken) { XRRSelectInput(_glfw.x11.display, _glfw.x11.root, RROutputChangeNotifyMask); } #if defined(__CYGWIN__) _glfw.x11.xcursor.handle = _glfw_dlopen("libXcursor-1.so"); #else _glfw.x11.xcursor.handle = _glfw_dlopen("libXcursor.so.1"); #endif if (_glfw.x11.xcursor.handle) { _glfw.x11.xcursor.ImageCreate = (PFN_XcursorImageCreate) _glfw_dlsym(_glfw.x11.xcursor.handle, "XcursorImageCreate"); _glfw.x11.xcursor.ImageDestroy = (PFN_XcursorImageDestroy) _glfw_dlsym(_glfw.x11.xcursor.handle, "XcursorImageDestroy"); _glfw.x11.xcursor.ImageLoadCursor = (PFN_XcursorImageLoadCursor) _glfw_dlsym(_glfw.x11.xcursor.handle, "XcursorImageLoadCursor"); } #if defined(__CYGWIN__) _glfw.x11.xinerama.handle = _glfw_dlopen("libXinerama-1.so"); #else _glfw.x11.xinerama.handle = _glfw_dlopen("libXinerama.so.1"); #endif if (_glfw.x11.xinerama.handle) { _glfw.x11.xinerama.IsActive = (PFN_XineramaIsActive) _glfw_dlsym(_glfw.x11.xinerama.handle, "XineramaIsActive"); _glfw.x11.xinerama.QueryExtension = (PFN_XineramaQueryExtension) _glfw_dlsym(_glfw.x11.xinerama.handle, "XineramaQueryExtension"); _glfw.x11.xinerama.QueryScreens = (PFN_XineramaQueryScreens) _glfw_dlsym(_glfw.x11.xinerama.handle, "XineramaQueryScreens"); if (XineramaQueryExtension(_glfw.x11.display, &_glfw.x11.xinerama.major, &_glfw.x11.xinerama.minor)) { if (XineramaIsActive(_glfw.x11.display)) _glfw.x11.xinerama.available = GLFW_TRUE; } } _glfw.x11.xkb.major = 1; _glfw.x11.xkb.minor = 0; _glfw.x11.xkb.available = XkbQueryExtension(_glfw.x11.display, &_glfw.x11.xkb.majorOpcode, &_glfw.x11.xkb.eventBase, &_glfw.x11.xkb.errorBase, &_glfw.x11.xkb.major, &_glfw.x11.xkb.minor); if (_glfw.x11.xkb.available) { Bool supported; if (XkbSetDetectableAutoRepeat(_glfw.x11.display, True, &supported)) { if (supported) _glfw.x11.xkb.detectable = GLFW_TRUE; } } #if defined(__CYGWIN__) _glfw.x11.x11xcb.handle = _glfw_dlopen("libX11-xcb-1.so"); #else _glfw.x11.x11xcb.handle = _glfw_dlopen("libX11-xcb.so.1"); #endif if (_glfw.x11.x11xcb.handle) { _glfw.x11.x11xcb.GetXCBConnection = (PFN_XGetXCBConnection) _glfw_dlsym(_glfw.x11.x11xcb.handle, "XGetXCBConnection"); } #if defined(__CYGWIN__) _glfw.x11.xrender.handle = _glfw_dlopen("libXrender-1.so"); #else _glfw.x11.xrender.handle = _glfw_dlopen("libXrender.so.1"); #endif if (_glfw.x11.xrender.handle) { _glfw.x11.xrender.QueryExtension = (PFN_XRenderQueryExtension) _glfw_dlsym(_glfw.x11.xrender.handle, "XRenderQueryExtension"); _glfw.x11.xrender.QueryVersion = (PFN_XRenderQueryVersion) _glfw_dlsym(_glfw.x11.xrender.handle, "XRenderQueryVersion"); _glfw.x11.xrender.FindVisualFormat = (PFN_XRenderFindVisualFormat) _glfw_dlsym(_glfw.x11.xrender.handle, "XRenderFindVisualFormat"); if (XRenderQueryExtension(_glfw.x11.display, &_glfw.x11.xrender.errorBase, &_glfw.x11.xrender.eventBase)) { if (XRenderQueryVersion(_glfw.x11.display, &_glfw.x11.xrender.major, &_glfw.x11.xrender.minor)) { _glfw.x11.xrender.available = GLFW_TRUE; } } } // Update the key code LUT // FIXME: We should listen to XkbMapNotify events to track changes to // the keyboard mapping. createKeyTables(); // Detect whether an EWMH-conformant window manager is running detectEWMH(); // String format atoms _glfw.x11.NULL_ = XInternAtom(_glfw.x11.display, "NULL", False); _glfw.x11.UTF8_STRING = XInternAtom(_glfw.x11.display, "UTF8_STRING", False); _glfw.x11.ATOM_PAIR = XInternAtom(_glfw.x11.display, "ATOM_PAIR", False); // Custom selection property atom _glfw.x11.GLFW_SELECTION = XInternAtom(_glfw.x11.display, "GLFW_SELECTION", False); // ICCCM standard clipboard atoms _glfw.x11.TARGETS = XInternAtom(_glfw.x11.display, "TARGETS", False); _glfw.x11.MULTIPLE = XInternAtom(_glfw.x11.display, "MULTIPLE", False); _glfw.x11.PRIMARY = XInternAtom(_glfw.x11.display, "PRIMARY", False); _glfw.x11.INCR = XInternAtom(_glfw.x11.display, "INCR", False); _glfw.x11.CLIPBOARD = XInternAtom(_glfw.x11.display, "CLIPBOARD", False); // Clipboard manager atoms _glfw.x11.CLIPBOARD_MANAGER = XInternAtom(_glfw.x11.display, "CLIPBOARD_MANAGER", False); _glfw.x11.SAVE_TARGETS = XInternAtom(_glfw.x11.display, "SAVE_TARGETS", False); // Xdnd (drag and drop) atoms _glfw.x11.XdndAware = XInternAtom(_glfw.x11.display, "XdndAware", False); _glfw.x11.XdndEnter = XInternAtom(_glfw.x11.display, "XdndEnter", False); _glfw.x11.XdndPosition = XInternAtom(_glfw.x11.display, "XdndPosition", False); _glfw.x11.XdndStatus = XInternAtom(_glfw.x11.display, "XdndStatus", False); _glfw.x11.XdndActionCopy = XInternAtom(_glfw.x11.display, "XdndActionCopy", False); _glfw.x11.XdndDrop = XInternAtom(_glfw.x11.display, "XdndDrop", False); _glfw.x11.XdndFinished = XInternAtom(_glfw.x11.display, "XdndFinished", False); _glfw.x11.XdndSelection = XInternAtom(_glfw.x11.display, "XdndSelection", False); _glfw.x11.XdndTypeList = XInternAtom(_glfw.x11.display, "XdndTypeList", False); _glfw.x11.text_uri_list = XInternAtom(_glfw.x11.display, "text/uri-list", False); // ICCCM, EWMH and Motif window property atoms // These can be set safely even without WM support // The EWMH atoms that require WM support are handled in detectEWMH _glfw.x11.WM_PROTOCOLS = XInternAtom(_glfw.x11.display, "WM_PROTOCOLS", False); _glfw.x11.WM_STATE = XInternAtom(_glfw.x11.display, "WM_STATE", False); _glfw.x11.WM_DELETE_WINDOW = XInternAtom(_glfw.x11.display, "WM_DELETE_WINDOW", False); _glfw.x11.NET_WM_ICON = XInternAtom(_glfw.x11.display, "_NET_WM_ICON", False); _glfw.x11.NET_WM_PING = XInternAtom(_glfw.x11.display, "_NET_WM_PING", False); _glfw.x11.NET_WM_PID = XInternAtom(_glfw.x11.display, "_NET_WM_PID", False); _glfw.x11.NET_WM_NAME = XInternAtom(_glfw.x11.display, "_NET_WM_NAME", False); _glfw.x11.NET_WM_ICON_NAME = XInternAtom(_glfw.x11.display, "_NET_WM_ICON_NAME", False); _glfw.x11.NET_WM_BYPASS_COMPOSITOR = XInternAtom(_glfw.x11.display, "_NET_WM_BYPASS_COMPOSITOR", False); _glfw.x11.NET_WM_WINDOW_OPACITY = XInternAtom(_glfw.x11.display, "_NET_WM_WINDOW_OPACITY", False); _glfw.x11.MOTIF_WM_HINTS = XInternAtom(_glfw.x11.display, "_MOTIF_WM_HINTS", False); // The compositing manager selection name contains the screen number { char name[32]; snprintf(name, sizeof(name), "_NET_WM_CM_S%u", _glfw.x11.screen); _glfw.x11.NET_WM_CM_Sx = XInternAtom(_glfw.x11.display, name, False); } return GLFW_TRUE; }
/* Main function, contains kernel driver event loop */ int main(int argc, char **argv) { char* devname = 0; int doDaemonize = 1; int doWait = 0; int clickMode = 2; int i; for (i = 1; i < argc; i++) { if (strcmp(argv[i], "--debug") == 0) { doDaemonize = 0; debugMode = 1; } else if (strcmp(argv[i], "--wait") == 0) { doWait = 1; } else if (strcmp(argv[i], "--click=first") == 0) { clickMode = 0; } else if (strcmp(argv[i], "--click=second") == 0) { clickMode = 1; } else if (strcmp(argv[i], "--click=center") == 0) { clickMode = 2; } else { devname = argv[i]; } } initGestures(clickMode); if (doDaemonize) { daemonize(); } if (doWait) { /* Wait until all necessary things are loaded */ sleep(10); } /* Connect to X server */ if ((display = XOpenDisplay(NULL)) == NULL) { fprintf(stderr, "Couldn't connect to X server\n"); exit(1); } /* Read X data */ screenNum = DefaultScreen(display); root = RootWindow(display, screenNum); // realDisplayWidth = DisplayWidth(display, screenNum); // realDisplayHeight = DisplayHeight(display, screenNum); WM_CLASS = XInternAtom(display, "WM_CLASS", 0); /* Get notified about new windows */ XSelectInput(display, root, StructureNotifyMask | SubstructureNotifyMask); //TODO load blacklist and profiles from file(s) /* Device file name */ if (devname == 0) { devname = "/dev/twofingtouch"; } /* Try to read from device file */ int fileDesc; if ((fileDesc = open(devname, O_RDONLY)) < 0) { perror("twofing"); return 1; } fd_set fileDescSet; FD_ZERO(&fileDescSet); int eventQueueDesc = XConnectionNumber(display); while (1) { /* Perform initialization at beginning and after module has been re-loaded */ int rd, i; struct input_event ev[64]; char name[256] = "Unknown"; /* Read device name */ ioctl(fileDesc, EVIOCGNAME(sizeof(name)), name); printf("Input device name: \"%s\"\n", name); //TODO activate again? //XSetErrorHandler(invalidWindowHandler); int opcode, event, error; if (!XQueryExtension(display, "RANDR", &opcode, &event, &error)) { printf("X RANDR extension not available.\n"); XCloseDisplay(display); exit(1); } /* Which version of XRandR? We support 1.3 */ int major = 1, minor = 3; if (!XRRQueryVersion(display, &major, &minor)) { printf("XRandR version not available.\n"); XCloseDisplay(display); exit(1); } else if(!(major>1 || (major == 1 && minor >= 3))) { printf("XRandR 1.3 not available. Server supports %d.%d\n", major, minor); XCloseDisplay(display); exit(1); } /* XInput Extension available? */ if (!XQueryExtension(display, "XInputExtension", &opcode, &event, &error)) { printf("X Input extension not available.\n"); XCloseDisplay(display); exit(1); } /* Which version of XI2? We support 2.1 */ major = 2; minor = 1; if (XIQueryVersion(display, &major, &minor) == BadRequest) { printf("XI 2.1 not available. Server supports %d.%d\n", major, minor); XCloseDisplay(display); exit(1); } screenWidth = XDisplayWidth(display, screenNum); screenHeight = XDisplayHeight(display, screenNum); int n; XIDeviceInfo *info = XIQueryDevice(display, XIAllDevices, &n); if (!info) { printf("No XInput devices available\n"); exit(1); } /* Go through input devices and look for that with the same name as the given device */ int devindex; for (devindex = 0; devindex < n; devindex++) { if (info[devindex].use == XIMasterPointer || info[devindex].use == XIMasterKeyboard) continue; if (strcmp(info[devindex].name, name) == 0) { deviceID = info[devindex].deviceid; break; } } if (deviceID == -1) { printf("Input device not found in XInput device list.\n"); exit(1); } XIFreeDeviceInfo(info); if(debugMode) printf("XInput device id is %i.\n", deviceID); /* Prepare by reading calibration */ readCalibrationData(1); /* Receive device property change events */ XIEventMask device_mask2; unsigned char mask_data2[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; device_mask2.deviceid = deviceID; device_mask2.mask_len = sizeof(mask_data2); device_mask2.mask = mask_data2; XISetMask(device_mask2.mask, XI_PropertyEvent); XISetMask(device_mask2.mask, XI_ButtonPress); //XISetMask(device_mask2.mask, XI_TouchBegin); //XISetMask(device_mask2.mask, XI_TouchUpdate); //XISetMask(device_mask2.mask, XI_TouchEnd); XISelectEvents(display, root, &device_mask2, 1); /* Recieve events when screen size changes */ XRRSelectInput(display, root, RRScreenChangeNotifyMask); /* Receive touch events */ /* Needed for XTest to work correctly */ XTestGrabControl(display, True); /* Needed for some reason to receive events */ /* XGrabPointer(display, root, False, 0, GrabModeAsync, GrabModeAsync, None, None, CurrentTime); XUngrabPointer(display, CurrentTime);*/ grab(display, deviceID); printf("Reading input from device ... (interrupt to exit)\n"); /* We perform raw event reading here as X touch events don't seem too reliable */ int currentSlot = 0; /* If we use the legacy protocol, we collect all data of one finger into tempFingerInfo and set it to the correct slot once MT_SYNC occurs. */ FingerInfo tempFingerInfo = { .rawX=0, .rawY=0, .rawZ=0, .id = -1, .slotUsed = 0, .setThisTime = 0 }; while (1) { FD_SET(fileDesc, &fileDescSet); FD_SET(eventQueueDesc, &fileDescSet); select(MAX(fileDesc, eventQueueDesc) + 1, &fileDescSet, NULL, NULL, getEasingStepTimeVal()); checkEasingStep(); if(FD_ISSET(fileDesc, &fileDescSet)) { rd = read(fileDesc, ev, sizeof(struct input_event) * 64); if (rd < (int) sizeof(struct input_event)) { printf("Data stream stopped\n"); break; } for (i = 0; i < rd / sizeof(struct input_event); i++) { if (ev[i].type == EV_SYN) { if (0 == ev[i].code) { // Ev_Sync event end /* All finger data received, so process now. */ if(useLegacyProtocol) { /* Clear slots not set this time */ int i; for(i = 0; i < 2; i++) { if(fingerInfos[i].setThisTime) { fingerInfos[i].setThisTime = 0; } else { /* Clear slot */ fingerInfos[i].slotUsed = 0; } } tempFingerInfo.slotUsed = 0; } processFingers(); } else if (2 == ev[i].code) { // MT_Sync : Multitouch event end if(!useLegacyProtocol) { /* This messsage indicates we use legacy protocol, so switch */ useLegacyProtocol = 1; currentSlot = -1; tempFingerInfo.slotUsed = 0; if(debugMode) printf("Switch to legacy protocol.\n"); } else { if(tempFingerInfo.slotUsed) { /* Finger info for one finger collected in tempFingerInfo, so save it to fingerInfos. */ /* Look for slot to put the data into by looking at the tracking ids */ int index = -1; int i; for(i = 0; i < 2; i++) { if(fingerInfos[i].slotUsed && fingerInfos[i].id == tempFingerInfo.id) { index = i; break; } } if(index == -1) { for(i = 0; i < 2; i++) { if(!fingerInfos[i].slotUsed) { /* "Empty" slot, so we can add it. */ index = i; fingerInfos[i].id = tempFingerInfo.id; fingerInfos[i].slotUsed = 1; break; } } } if(index != -1) { /* Copy temporary data to slot */ fingerInfos[index].setThisTime = 1; fingerInfos[index].rawX = tempFingerInfo.rawX; fingerInfos[index].rawY = tempFingerInfo.rawY; fingerInfos[index].rawZ = tempFingerInfo.rawZ; } } } } } else if (ev[i].type == EV_MSC && (ev[i].code == MSC_RAW || ev[i].code == MSC_SCAN)) { } else if (ev[i].code == 47) { currentSlot = ev[i].value; if(currentSlot < 0 || currentSlot > 1) currentSlot = -1; } else { /* Set finger info values for current finger */ if (ev[i].code == 57) { /* ABS_MT_TRACKING_ID */ if(currentSlot != -1) { if(ev[i].value == -1) { fingerInfos[currentSlot].slotUsed = 0; } else { fingerInfos[currentSlot].id = ev[i].value; fingerInfos[currentSlot].slotUsed = 1; } } else if(useLegacyProtocol) { tempFingerInfo.id = ev[i].value; tempFingerInfo.slotUsed = 1; } }; if (ev[i].code == 53) { if(currentSlot != -1) { fingerInfos[currentSlot].rawX = ev[i].value; } else if(useLegacyProtocol) { tempFingerInfo.rawX = ev[i].value; } }; if (ev[i].code == 54) { if(currentSlot != -1) { fingerInfos[currentSlot].rawY = ev[i].value; } else if(useLegacyProtocol) { tempFingerInfo.rawY = ev[i].value; } }; if (ev[i].code == 58) { if(currentSlot != -1) { fingerInfos[currentSlot].rawZ = ev[i].value; } else if(useLegacyProtocol) { tempFingerInfo.rawZ = ev[i].value; } }; } } } if(FD_ISSET(eventQueueDesc, &fileDescSet)) { handleXEvent(); } } /* Stream stopped, probably because module has been unloaded */ close(fileDesc); /* Clean up */ releaseButton(); ungrab(display, deviceID); /* Wait until device file is there again */ while ((fileDesc = open(devname, O_RDONLY)) < 0) { sleep(1); } } }
// Initialize X11 display and look for supported X11 extensions // static GLFWbool initExtensions(void) { // Find or create window manager atoms _glfw.x11.WM_PROTOCOLS = XInternAtom(_glfw.x11.display, "WM_PROTOCOLS", False); _glfw.x11.WM_STATE = XInternAtom(_glfw.x11.display, "WM_STATE", False); _glfw.x11.WM_DELETE_WINDOW = XInternAtom(_glfw.x11.display, "WM_DELETE_WINDOW", False); _glfw.x11.MOTIF_WM_HINTS = XInternAtom(_glfw.x11.display, "_MOTIF_WM_HINTS", False); #if defined(_GLFW_HAS_XF86VM) // Check for XF86VidMode extension _glfw.x11.vidmode.available = XF86VidModeQueryExtension(_glfw.x11.display, &_glfw.x11.vidmode.eventBase, &_glfw.x11.vidmode.errorBase); #endif /*_GLFW_HAS_XF86VM*/ // Check for RandR extension if (XRRQueryExtension(_glfw.x11.display, &_glfw.x11.randr.eventBase, &_glfw.x11.randr.errorBase)) { if (XRRQueryVersion(_glfw.x11.display, &_glfw.x11.randr.major, &_glfw.x11.randr.minor)) { // The GLFW RandR path requires at least version 1.3 if (_glfw.x11.randr.major > 1 || _glfw.x11.randr.minor >= 3) _glfw.x11.randr.available = GLFW_TRUE; } else { _glfwInputError(GLFW_PLATFORM_ERROR, "X11: Failed to query RandR version"); } } if (_glfw.x11.randr.available) { XRRScreenResources* sr = XRRGetScreenResources(_glfw.x11.display, _glfw.x11.root); if (!sr->ncrtc || !XRRGetCrtcGammaSize(_glfw.x11.display, sr->crtcs[0])) { // This is either a headless system or an older Nvidia binary driver // with broken gamma support // Flag it as useless and fall back to Xf86VidMode gamma, if // available _glfwInputError(GLFW_PLATFORM_ERROR, "X11: RandR gamma ramp support seems broken"); _glfw.x11.randr.gammaBroken = GLFW_TRUE; } XRRFreeScreenResources(sr); XRRSelectInput(_glfw.x11.display, _glfw.x11.root, RROutputChangeNotifyMask); } if (XineramaQueryExtension(_glfw.x11.display, &_glfw.x11.xinerama.major, &_glfw.x11.xinerama.minor)) { if (XineramaIsActive(_glfw.x11.display)) _glfw.x11.xinerama.available = GLFW_TRUE; } #if defined(_GLFW_HAS_XINPUT) if (XQueryExtension(_glfw.x11.display, "XInputExtension", &_glfw.x11.xi.majorOpcode, &_glfw.x11.xi.eventBase, &_glfw.x11.xi.errorBase)) { _glfw.x11.xi.major = 2; _glfw.x11.xi.minor = 0; if (XIQueryVersion(_glfw.x11.display, &_glfw.x11.xi.major, &_glfw.x11.xi.minor) != BadRequest) { _glfw.x11.xi.available = GLFW_TRUE; } } #endif /*_GLFW_HAS_XINPUT*/ // Check if Xkb is supported on this display _glfw.x11.xkb.major = 1; _glfw.x11.xkb.minor = 0; _glfw.x11.xkb.available = XkbQueryExtension(_glfw.x11.display, &_glfw.x11.xkb.majorOpcode, &_glfw.x11.xkb.eventBase, &_glfw.x11.xkb.errorBase, &_glfw.x11.xkb.major, &_glfw.x11.xkb.minor); if (_glfw.x11.xkb.available) { Bool supported; if (XkbSetDetectableAutoRepeat(_glfw.x11.display, True, &supported)) { if (supported) _glfw.x11.xkb.detectable = GLFW_TRUE; } } // Update the key code LUT // FIXME: We should listen to XkbMapNotify events to track changes to // the keyboard mapping. createKeyTables(); // Detect whether an EWMH-conformant window manager is running detectEWMH(); // Find or create string format atoms _glfw.x11.NULL_ = XInternAtom(_glfw.x11.display, "NULL", False); _glfw.x11.UTF8_STRING = XInternAtom(_glfw.x11.display, "UTF8_STRING", False); _glfw.x11.COMPOUND_STRING = XInternAtom(_glfw.x11.display, "COMPOUND_STRING", False); _glfw.x11.ATOM_PAIR = XInternAtom(_glfw.x11.display, "ATOM_PAIR", False); // Find or create selection property atom _glfw.x11.GLFW_SELECTION = XInternAtom(_glfw.x11.display, "GLFW_SELECTION", False); // Find or create standard clipboard atoms _glfw.x11.TARGETS = XInternAtom(_glfw.x11.display, "TARGETS", False); _glfw.x11.MULTIPLE = XInternAtom(_glfw.x11.display, "MULTIPLE", False); _glfw.x11.CLIPBOARD = XInternAtom(_glfw.x11.display, "CLIPBOARD", False); // Find or create clipboard manager atoms _glfw.x11.CLIPBOARD_MANAGER = XInternAtom(_glfw.x11.display, "CLIPBOARD_MANAGER", False); _glfw.x11.SAVE_TARGETS = XInternAtom(_glfw.x11.display, "SAVE_TARGETS", False); // Find Xdnd (drag and drop) atoms, if available _glfw.x11.XdndAware = XInternAtom(_glfw.x11.display, "XdndAware", True); _glfw.x11.XdndEnter = XInternAtom(_glfw.x11.display, "XdndEnter", True); _glfw.x11.XdndPosition = XInternAtom(_glfw.x11.display, "XdndPosition", True); _glfw.x11.XdndStatus = XInternAtom(_glfw.x11.display, "XdndStatus", True); _glfw.x11.XdndActionCopy = XInternAtom(_glfw.x11.display, "XdndActionCopy", True); _glfw.x11.XdndDrop = XInternAtom(_glfw.x11.display, "XdndDrop", True); _glfw.x11.XdndLeave = XInternAtom(_glfw.x11.display, "XdndLeave", True); _glfw.x11.XdndFinished = XInternAtom(_glfw.x11.display, "XdndFinished", True); _glfw.x11.XdndSelection = XInternAtom(_glfw.x11.display, "XdndSelection", True); return GLFW_TRUE; }
GlobalShortcutX::GlobalShortcutX() { bRunning=false; display = NULL; #ifdef Q_OS_LINUX QString dir = QLatin1String("/dev/input"); QFileSystemWatcher *fsw = new QFileSystemWatcher(QStringList(dir), this); connect(fsw, SIGNAL(directoryChanged(const QString &)), this, SLOT(directoryChanged(const QString &))); directoryChanged(dir); if (qsKeyboards.isEmpty()) { foreach(QFile *f, qmInputDevices) delete f; qmInputDevices.clear(); delete fsw; qWarning("GlobalShortcutX: Unable to open any keyboard input devices under /dev/input, falling back to XInput"); } else { return; } #endif display = XOpenDisplay(NULL); if (! display) { qWarning("GlobalShortcutX: Unable to open dedicated display connection."); return; } for (int i=0; i < ScreenCount(display); ++i) qsRootWindows.insert(RootWindow(display, i)); #ifndef NO_XINPUT2 int evt, error; if (XQueryExtension(display, "XInputExtension", &iXIopcode, &evt, &error)) { int major = 2; int minor = 0; int rc = XIQueryVersion(display, &major, &minor); if (rc != BadRequest) { qWarning("GlobalShortcutX: Using XI2 %d.%d", major, minor); queryXIMasterList(); XIEventMask evmask; unsigned char mask[(XI_LASTEVENT + 7)/8]; memset(&evmask, 0, sizeof(evmask)); memset(mask, 0, sizeof(mask)); XISetMask(mask, XI_RawButtonPress); XISetMask(mask, XI_RawButtonRelease); XISetMask(mask, XI_RawKeyPress); XISetMask(mask, XI_RawKeyRelease); XISetMask(mask, XI_HierarchyChanged); evmask.deviceid = XIAllDevices; evmask.mask_len = sizeof(mask); evmask.mask = mask; foreach(Window w, qsRootWindows) XISelectEvents(display, w, &evmask, 1); XFlush(display); connect(new QSocketNotifier(ConnectionNumber(display), QSocketNotifier::Read, this), SIGNAL(activated(int)), this, SLOT(displayReadyRead(int))); return; }