int runDaemon ( const char * display_name ) { Display * display; Window root; int rr_event_base = 0, rr_error_base = 0; XcmeContext_s * c = XcmeContext_New( ); XcmeContext_Setup2( c, display_name, 0 ); display = XcmeContext_DisplayGet( c ); if(!display) return 1; root = RootWindow( display, DefaultScreen( display ) ); #ifdef HAVE_XRANDR XRRQueryExtension( display, &rr_event_base, &rr_error_base ); XRRSelectInput( display, root, RRScreenChangeNotifyMask | RRCrtcChangeNotifyMask | RROutputChangeNotifyMask | RROutputPropertyNotifyMask); #endif for(;;) { XEvent event; XNextEvent( display, &event); /* we rely on any color server doing X11 setup by its own */ if(XcmColorServerCapabilities( display ) & XCM_COLOR_SERVER_MANAGEMENT) continue; #ifdef HAVE_XRANDR if(event.type == rr_event_base + RRNotify) { XRRNotifyEvent *rrn = (XRRNotifyEvent *) &event; if(rrn->subtype == RRNotify_OutputChange || rrn->subtype == RR_Rotate_0) { fprintf( stderr,"detected RRNotify_OutputChange event -> update\n"); updateOutputConfiguration( display ); } } #else { Atom net_desktop_geometry = XInternAtom( display, "_NET_DESKTOP_GEOMETRY", False ); if( event.type == PropertyNotify && event.xproperty.atom == net_desktop_geometry) { fprintf( stderr,"detected _NET_DESKTOP_GEOMETRY event -> update\n"); updateOutputConfiguration( display ); } } #endif } XcmeContext_Release( &c ); return 0; }
bool C4AbstractApp::Init(int argc, char * argv[]) { // Set locale setlocale(LC_ALL,""); gtk_init(&argc, &argv); GdkPixbuf* icon = gdk_pixbuf_new_from_resource("/org/openclonk/engine/oc.ico", NULL); gtk_window_set_default_icon(icon); g_object_unref(icon); // Try to figure out the location of the executable Priv->argc=argc; Priv->argv=argv; #ifdef GDK_WINDOWING_X11 Display * const dpy = gdk_x11_display_get_xdisplay(gdk_display_get_default()); int xrandr_error_base; if (!XRRQueryExtension(dpy, &Priv->xrandr_event, &xrandr_error_base) || !XRRQueryVersion(dpy, &Priv->xrandr_major_version, &Priv->xrandr_minor_version)) { Priv->xrandr_major_version = -1; Priv->xrandr_minor_version = 0; } if (Priv->xrandr_major_version >= 0) { XRRSelectInput(dpy, DefaultRootWindow(dpy), RRScreenChangeNotifyMask); } else Log("The Xrandr extension is missing. Resolution switching will not work."); #endif // Custom initialization return DoInit (argc, argv); }
void psb_xrandr_thread(void* arg) { VADriverContextP ctx = (VADriverContextP)arg; INIT_DRIVER_DATA; int event_base, error_base; XEvent event; XRRQueryExtension(psb_xrandr_info->dpy, &event_base, &error_base); XRRSelectInput(psb_xrandr_info->dpy, psb_xrandr_info->root, RRScreenChangeNotifyMask | RRCrtcChangeNotifyMask | RROutputChangeNotifyMask | RROutputPropertyNotifyMask); drv_debug_msg(VIDEO_DEBUG_GENERAL, "Xrandr: psb xrandr thread start\n"); while (1) { if (XCheckIfEvent(psb_xrandr_info->dpy, (XEvent *)&event, outputChangePredicate, NULL)) { if (event.type == ClientMessage) { drv_debug_msg(VIDEO_DEBUG_GENERAL, "Xrandr: receive ClientMessage event, thread should exit\n"); XClientMessageEvent *evt; evt = (XClientMessageEvent*) & event; if (evt->message_type == psb_xrandr_info->psb_exit_atom) { drv_debug_msg(VIDEO_DEBUG_GENERAL, "Xrandr: xrandr thread exit safely\n"); pthread_exit(NULL); } } switch (event.type - event_base) { case RRNotify_OutputChange: XRRUpdateConfiguration(&event); drv_debug_msg(VIDEO_DEBUG_GENERAL, "Xrandr: receive RRNotify_OutputChange event, refresh output/crtc info\n"); driver_data->xrandr_update = 1; psb_xrandr_refresh(ctx); break; default: break; } } usleep(200000); } }
void screen_init(int which) { struct screen_ctx *sc; Window *wins, w0, w1; XWindowAttributes winattr; XSetWindowAttributes rootattr; unsigned int nwins, i; sc = xcalloc(1, sizeof(*sc)); sc->which = which; sc->visual = DefaultVisual(X_Dpy, sc->which); sc->colormap = DefaultColormap(X_Dpy, sc->which); sc->rootwin = RootWindow(X_Dpy, sc->which); xu_ewmh_net_supported(sc); xu_ewmh_net_supported_wm_check(sc); conf_screen(sc); screen_update_geometry(sc); TAILQ_INIT(&sc->mruq); group_init(sc); rootattr.cursor = Conf.cursor[CF_NORMAL]; rootattr.event_mask = SubstructureRedirectMask|SubstructureNotifyMask| PropertyChangeMask|EnterWindowMask|LeaveWindowMask| ColormapChangeMask|BUTTONMASK; XChangeWindowAttributes(X_Dpy, sc->rootwin, CWEventMask|CWCursor, &rootattr); /* Deal with existing clients. */ XQueryTree(X_Dpy, sc->rootwin, &w0, &w1, &wins, &nwins); for (i = 0; i < nwins; i++) { XGetWindowAttributes(X_Dpy, wins[i], &winattr); if (winattr.override_redirect || winattr.map_state != IsViewable) continue; (void)client_init(wins[i], sc, winattr.map_state != IsUnmapped); } XFree(wins); screen_updatestackingorder(sc); if (HasRandr) XRRSelectInput(X_Dpy, sc->rootwin, RRScreenChangeNotifyMask); TAILQ_INSERT_TAIL(&Screenq, sc, entry); XSync(X_Dpy, False); }
static void randrd(void) { XRRScreenResources *resources; XRROutputInfo *info; XRROutputChangeNotifyEvent *rrocevt; XRRNotifyEvent *rrevt; char *new_edidhash; Window root; XEvent evt; exec_script(script, "init", "", current_edidhash); XRRSelectInput(dpy, DefaultRootWindow(dpy), RROutputChangeNotifyMask); while (!quit) { root = RootWindow(dpy, DefaultScreen(dpy)); resources = XRRGetScreenResources(dpy, root); while (XPending(dpy)) { XNextEvent(dpy, &evt); if (evt.type != rr_event_base + RRNotify) continue; rrevt = (XRRNotifyEvent *)&evt; if (rrevt->subtype != RRNotify_OutputChange) continue; new_edidhash = getedidhash1(resources); if (new_edidhash == NULL) continue; if (!strcmp(current_edidhash, new_edidhash)) { free(new_edidhash); continue; } free(current_edidhash); current_edidhash = new_edidhash; rrocevt = (XRROutputChangeNotifyEvent *)&evt; info = XRRGetOutputInfo(rrocevt->display, resources, rrocevt->output); syslog(LOG_INFO, "%s %s", info->name, connstates[info->connection]); exec_script(script, connstates[info->connection], info->name, new_edidhash); XRRFreeOutputInfo(info); } XRRFreeScreenResources(resources); sleep(interval); } }
int Display::GetDisplayCount(DisplaySearchHandle* handle, bool extended, bool applicationOnly, bool edidInfo) { OVR_UNUSED4(handle, extended, applicationOnly, edidInfo); static int extendedCount = -1; static int numScreens = -1; Linux::LinuxDisplaySearchHandle* localHandle = (Linux::LinuxDisplaySearchHandle*)handle; if (localHandle == NULL) { OVR::LogError("[Linux Display] No search handle passed into GetDisplayCount. Return 0 rifts."); return 0; } if (X11Display == NULL) { OVR::LogError("[Linux Display] Unable to open X Display!"); return 0; } int screen_count = XScreenCount(X11Display); if (screen_count != numScreens) { numScreens = screen_count; extended = true; for (int screen = 0; screen < numScreens; ++screen) { // Be sure we're subscribed to config changes on all screens. XRRSelectInput(X11Display, XRootWindow(X11Display, screen), RRScreenChangeNotifyMask | RRCrtcChangeNotifyMask | RROutputChangeNotifyMask | RROutputPropertyNotifyMask); } } XEvent event_return = XEvent(); if (XCheckTypedEvent(X11Display, BaseRREvent + RRScreenChangeNotify, &event_return)) { extended = true; } if (extendedCount == -1 || extended) { extendedCount = discoverExtendedRifts(localHandle->cachedDescriptorArray, Linux::LinuxDisplaySearchHandle::DescArraySize, edidInfo); } localHandle->extended = true; localHandle->extendedDisplayCount = extendedCount; int totalCount = extendedCount; localHandle->application = false; localHandle->applicationDisplayCount = 0; localHandle->displayCount = totalCount; return totalCount; }
gboolean _cogl_xlib_renderer_connect (CoglRenderer *renderer, CoglError **error) { CoglXlibRenderer *xlib_renderer = _cogl_xlib_renderer_get_data (renderer); CoglX11Renderer *x11_renderer = (CoglX11Renderer *) xlib_renderer; int damage_error; int randr_error; if (!assert_xlib_display (renderer, error)) return FALSE; if (getenv ("COGL_X11_SYNC")) XSynchronize (xlib_renderer->xdpy, TRUE); /* Check whether damage events are supported on this display */ if (!XDamageQueryExtension (xlib_renderer->xdpy, &x11_renderer->damage_base, &damage_error)) x11_renderer->damage_base = -1; /* Check whether randr is supported on this display */ if (!XRRQueryExtension (xlib_renderer->xdpy, &x11_renderer->randr_base, &randr_error)) x11_renderer->randr_base = -1; xlib_renderer->trap_state = NULL; if (renderer->xlib_enable_event_retrieval) { _cogl_poll_renderer_add_fd (renderer, ConnectionNumber (xlib_renderer->xdpy), COGL_POLL_FD_EVENT_IN, prepare_xlib_events_timeout, dispatch_xlib_events, renderer); } XRRSelectInput(xlib_renderer->xdpy, DefaultRootWindow (xlib_renderer->xdpy), RRScreenChangeNotifyMask | RRCrtcChangeNotifyMask | RROutputPropertyNotifyMask); update_outputs (renderer, FALSE); register_xlib_renderer (renderer); cogl_xlib_renderer_add_filter (renderer, randr_filter, renderer); return TRUE; }
static void ExtInitRR(int available) { Rotation rot; if (!available) return; /* Listen for RandR events */ XRRSelectInput(disp, WinGetXwin(VROOT), RRScreenChangeNotifyMask); XRRRotations(disp, Dpy.screen, &rot); Mode.screen.rotation = rot; #if 0 /* Debug */ if (EDebug(EDBUG_TYPE_VERBOSE)) { XRRScreenResources *psr; XRRCrtcInfo *pci; XRROutputInfo *poi; int i; psr = XRRGetScreenResources(disp, WinGetXwin(VROOT)); if (!psr) return; Eprintf("CRTC ID X,Y WxH mode rot nout\n"); for (i = 0; i < psr->ncrtc; i++) { pci = XRRGetCrtcInfo(disp, psr, psr->crtcs[i]); if (!pci) break; Eprintf("%3d %#04lx %4d,%4d %4ux%4u %#04lx %4d %5d\n", i, psr->crtcs[i], pci->x, pci->y, pci->width, pci->height, pci->mode, pci->rotation, pci->noutput); XRRFreeCrtcInfo(pci); } Eprintf("OUTP ID Name WxH crtc ncrtc nclon nmode\n"); for (i = 0; i < psr->noutput; i++) { poi = XRRGetOutputInfo(disp, psr, psr->outputs[i]); if (!poi) break; Eprintf("%3d %#04lx %-8s %4lux%4lu %#04lx %4d %5d %5d\n", i, psr->outputs[i], poi->name, poi->mm_width, poi->mm_height, poi->crtc, poi->ncrtc, poi->nclone, poi->nmode); XRRFreeOutputInfo(poi); } XRRFreeScreenResources(psr); } #endif }
static void *settings_thread_proc(void *arg) { Display *settings_disp = XOpenDisplay(XDisplayName(NULL));; if (settings_disp != NULL) { logger(LOG_LEVEL_DEBUG, "%s [%u]: %s\n", __FUNCTION__, __LINE__, "XOpenDisplay success."); pthread_cleanup_push(settings_cleanup_proc, settings_disp); int event_base = 0; int error_base = 0; if (XRRQueryExtension(settings_disp, &event_base, &error_base)) { Window root = XDefaultRootWindow(settings_disp); unsigned long event_mask = RRScreenChangeNotifyMask; XRRSelectInput(settings_disp, root, event_mask); XEvent ev; while(settings_disp != NULL) { XNextEvent(settings_disp, &ev); if (ev.type == event_base + RRScreenChangeNotifyMask) { logger(LOG_LEVEL_DEBUG, "%s [%u]: Received XRRScreenChangeNotifyEvent.\n", __FUNCTION__, __LINE__); pthread_mutex_lock(&xrandr_mutex); if (xrandr_resources != NULL) { XRRFreeScreenResources(xrandr_resources); } xrandr_resources = XRRGetScreenResources(settings_disp, root); if (xrandr_resources == NULL) { logger(LOG_LEVEL_WARN, "%s [%u]: XRandR could not get screen resources!\n", __FUNCTION__, __LINE__); } pthread_mutex_unlock(&xrandr_mutex); } else { logger(LOG_LEVEL_WARN, "%s [%u]: XRandR is not currently available!\n", __FUNCTION__, __LINE__); } } } // Execute the thread cleanup handler. pthread_cleanup_pop(1); } else { logger(LOG_LEVEL_ERROR, "%s [%u]: XOpenDisplay failure!\n", __FUNCTION__, __LINE__); } return NULL; }
int _glfwPlatformCreateWindow(_GLFWwindow* window, const _GLFWwndconfig* wndconfig, const _GLFWfbconfig* fbconfig) { window->refreshRate = wndconfig->refreshRate; if (!_glfwCreateContext(window, wndconfig, fbconfig)) return GL_FALSE; if (!createWindow(window, wndconfig)) return GL_FALSE; if (wndconfig->mode == GLFW_FULLSCREEN) { #if defined(_GLFW_HAS_XRANDR) // Request screen change notifications if (_glfwLibrary.X11.RandR.available) { XRRSelectInput(_glfwLibrary.X11.display, window->X11.handle, RRScreenChangeNotifyMask); } #endif /*_GLFW_HAS_XRANDR*/ _glfwPlatformShowWindow(window); enterFullscreenMode(window); } // Retrieve and set initial cursor position { Window cursorWindow, cursorRoot; int windowX, windowY, rootX, rootY; unsigned int mask; XQueryPointer(_glfwLibrary.X11.display, window->X11.handle, &cursorRoot, &cursorWindow, &rootX, &rootY, &windowX, &windowY, &mask); // TODO: Probably check for some corner cases here. window->cursorPosX = windowX; window->cursorPosY = windowY; } return GL_TRUE; }
void initialize_xrandr(void) { if (xrandr_present && dpy) { #if LIBVNCSERVER_HAVE_LIBXRANDR Rotation rot; X_LOCK; xrandr_width = XDisplayWidth(dpy, scr); xrandr_height = XDisplayHeight(dpy, scr); XRRRotations(dpy, scr, &rot); xrandr_rotation = (int) rot; if (xrandr || xrandr_maybe) { XRRSelectInput(dpy, rootwin, RRScreenChangeNotifyMask); } else { XRRSelectInput(dpy, rootwin, 0); } X_UNLOCK; #endif } else if (xrandr) { rfbLog("-xrandr mode specified, but no RANDR support on\n"); rfbLog(" display or in client library. Disabling -xrandr " "mode.\n"); xrandr = 0; } }
/** Init screen geo */ void screen_init_geo(void) { int i; int s = screen_count(); sgeo = xcalloc(s, sizeof(XRectangle)); spgeo = xcalloc(s, sizeof(XRectangle)); for(i = 0; i < s; ++i) sgeo[i] = screen_get_geo(i); spgeo[0].x = 0; spgeo[0].y = 0; spgeo[0].width = MAXW; spgeo[0].height = MAXH; #ifdef HAVE_XINERAMA XineramaScreenInfo *xsi; int n; if(XineramaIsActive(dpy)) { xsi = XineramaQueryScreens(dpy, &n); for(i = 0; i < n; ++i) { spgeo[i].x = xsi[i].x_org; spgeo[i].y = xsi[i].y_org; spgeo[i].width = xsi[i].width; spgeo[i].height = xsi[i].height; } XFree(xsi); } #endif /* HAVE_XINERAMA */ #ifdef HAVE_XRANDR /* Init xrandr stuff */ int d; XRRSelectInput(dpy, ROOT, 1); XRRQueryExtension(dpy, &xrandr_event, &d); #endif /* HAVE_XRANDR */ ewmh_set_desktop_geometry(); return; }
bool _cg_xlib_renderer_connect(cg_renderer_t *renderer, cg_error_t **error) { cg_xlib_renderer_t *xlib_renderer = _cg_xlib_renderer_get_data(renderer); cg_x11_renderer_t *x11_renderer = (cg_x11_renderer_t *)xlib_renderer; int damage_error; int randr_error; if (!assert_xlib_display(renderer, error)) return false; if (getenv("CG_X11_SYNC")) XSynchronize(xlib_renderer->xdpy, true); /* Check whether damage events are supported on this display */ if (!XDamageQueryExtension( xlib_renderer->xdpy, &x11_renderer->damage_base, &damage_error)) x11_renderer->damage_base = -1; /* Check whether randr is supported on this display */ if (!XRRQueryExtension( xlib_renderer->xdpy, &x11_renderer->randr_base, &randr_error)) x11_renderer->randr_base = -1; xlib_renderer->trap_state = NULL; if (renderer->xlib_enable_event_retrieval) { _cg_loop_add_fd(renderer, ConnectionNumber(xlib_renderer->xdpy), CG_POLL_FD_EVENT_IN, prepare_xlib_events_timeout, dispatch_xlib_events, renderer); } XRRSelectInput(xlib_renderer->xdpy, DefaultRootWindow(xlib_renderer->xdpy), RRScreenChangeNotifyMask | RRCrtcChangeNotifyMask | RROutputPropertyNotifyMask); update_outputs(renderer, false); register_xlib_renderer(renderer); cg_xlib_renderer_add_filter(renderer, randr_filter, renderer); return true; }
/* function: queryextensions_x11display * Initializes extension variables of <x11display_t>. * It is expected that memory of all extension variables is set to zero * before you call this function. */ static int queryextensions_x11display(x11display_t * x11disp) { int major ; int minor ; int dummy ; Bool isSupported ; isSupported = XQueryExtension(x11disp->sys_display, "DOUBLE-BUFFER", &dummy, &x11disp->xdbe.eventbase, &x11disp->xdbe.errorbase) ; if (isSupported) { isSupported = XdbeQueryExtension(x11disp->sys_display, &major, &minor) ; if (isSupported) { x11disp->xdbe.isSupported = true ; x11disp->xdbe.version_major = (uint16_t) major ; x11disp->xdbe.version_minor = (uint16_t) minor ; } } isSupported = XQueryExtension(x11disp->sys_display, "RANDR", &dummy, &x11disp->xrandr.eventbase, &x11disp->xrandr.errorbase) ; if (isSupported) { isSupported = XRRQueryVersion(x11disp->sys_display, &major, &minor) ; if (isSupported) { x11disp->xrandr.isSupported = true ; x11disp->xrandr.version_major = (uint16_t) major ; x11disp->xrandr.version_minor = (uint16_t) minor ; // prepare receiving events for (int i = ScreenCount(x11disp->sys_display); (--i) >= 0 ;) { XRRSelectInput(x11disp->sys_display, RootWindow(x11disp->sys_display,i), RRScreenChangeNotifyMask) ; } } } isSupported = XQueryExtension(x11disp->sys_display, "RENDER", &dummy, &x11disp->xrender.eventbase, &x11disp->xrender.errorbase) ; if (isSupported) { isSupported = XRenderQueryVersion(x11disp->sys_display, &major, &minor) ; if (isSupported) { x11disp->xrender.isSupported = true ; x11disp->xrender.version_major = (uint16_t) major ; x11disp->xrender.version_minor = (uint16_t) minor ; } } return 0 ; }
static void init_randr_support (GdkX11Screen *x11_screen) { /* NB: This is also needed for XSettings, so don't remove. */ XSelectInput (GDK_SCREEN_XDISPLAY (x11_screen), x11_screen->xroot_window, StructureNotifyMask); #ifdef HAVE_RANDR if (!GDK_X11_DISPLAY (GDK_SCREEN_DISPLAY (x11_screen))->have_randr12) return; XRRSelectInput (GDK_SCREEN_XDISPLAY (x11_screen), x11_screen->xroot_window, RRScreenChangeNotifyMask | RRCrtcChangeNotifyMask | RROutputPropertyNotifyMask); #endif }
void eventNotifier::run() { int rr_event_base; int rr_error_base; XRRQueryExtension (m_pDpy, &rr_event_base, &rr_error_base); XRRSelectInput( m_pDpy, m_screen, RRCrtcChangeNotifyMask | RROutputChangeNotifyMask | RROutputPropertyNotifyMask ); while (!m_bStop){ XEvent event; XNextEvent (m_pDpy, &event); if (event.type == rr_event_base + RRNotify){ prologue (&event, "RRScreenChangeNotify"); do_RRNotify(&event); } } }
static void init_randr_support (GdkScreen *screen) { GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen); XSelectInput (GDK_SCREEN_XDISPLAY (screen), x11_screen->xroot_window, StructureNotifyMask); #ifdef HAVE_RANDR if (!GDK_X11_DISPLAY (gdk_screen_get_display (screen))->have_randr12) return; XRRSelectInput (GDK_SCREEN_XDISPLAY (screen), x11_screen->xroot_window, RRScreenChangeNotifyMask | RRCrtcChangeNotifyMask | RROutputPropertyNotifyMask); #endif }
// 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; }
// Create the X11 window (and its colormap) // static GLboolean createWindow(_GLFWwindow* window, const _GLFWwndconfig* wndconfig) { unsigned long wamask; XSetWindowAttributes wa; XVisualInfo* visual = _GLFW_X11_CONTEXT_VISUAL; // Every window needs a colormap // Create one based on the visual used by the current context // TODO: Decouple this from context creation window->x11.colormap = XCreateColormap(_glfw.x11.display, _glfw.x11.root, visual->visual, AllocNone); // Create the actual window { wamask = CWBorderPixel | CWColormap | CWEventMask; wa.colormap = window->x11.colormap; wa.border_pixel = 0; wa.event_mask = StructureNotifyMask | KeyPressMask | KeyReleaseMask | PointerMotionMask | ButtonPressMask | ButtonReleaseMask | ExposureMask | FocusChangeMask | VisibilityChangeMask | EnterWindowMask | LeaveWindowMask | PropertyChangeMask; if (wndconfig->monitor == NULL) { // HACK: This is a workaround for windows without a background pixel // not getting any decorations on certain older versions of Compiz // running on Intel hardware wa.background_pixel = BlackPixel(_glfw.x11.display, _glfw.x11.screen); wamask |= CWBackPixel; } window->x11.handle = XCreateWindow(_glfw.x11.display, _glfw.x11.root, 0, 0, wndconfig->width, wndconfig->height, 0, // Border width visual->depth, // Color depth InputOutput, visual->visual, wamask, &wa); if (!window->x11.handle) { // TODO: Handle all the various error codes here and translate them // to GLFW errors _glfwInputError(GLFW_PLATFORM_ERROR, "X11: Failed to create window"); return GL_FALSE; } if (wndconfig->undecorated) { Atom motif_hints_atom = XInternAtom(_glfw.x11.display, "_MOTIF_WM_HINTS", False); MotifWmHints motif_hints; motif_hints.flags = MWM_HINTS_DECORATIONS; motif_hints.decorations = 0; XChangeProperty(_glfw.x11.display, window->x11.handle, motif_hints_atom, motif_hints_atom, 32, PropModeReplace, (unsigned char *)&motif_hints, sizeof(MotifWmHints) / sizeof(long)); } } if (window->monitor && !_glfw.x11.hasEWMH) { // This is the butcher's way of removing window decorations // Setting the override-redirect attribute on a window makes the window // manager ignore the window completely (ICCCM, section 4) // The good thing is that this makes undecorated fullscreen windows // easy to do; the bad thing is that we have to do everything manually // and some things (like iconify/restore) won't work at all, as those // are tasks usually performed by the window manager XSetWindowAttributes attributes; attributes.override_redirect = True; XChangeWindowAttributes(_glfw.x11.display, window->x11.handle, CWOverrideRedirect, &attributes); window->x11.overrideRedirect = GL_TRUE; } // Declare the WM protocols supported by GLFW { int count = 0; Atom protocols[2]; // The WM_DELETE_WINDOW ICCCM protocol // Basic window close notification protocol if (_glfw.x11.WM_DELETE_WINDOW != None) protocols[count++] = _glfw.x11.WM_DELETE_WINDOW; // The _NET_WM_PING EWMH protocol // Tells the WM to ping the GLFW window and flag the application as // unresponsive if the WM doesn't get a reply within a few seconds if (_glfw.x11.NET_WM_PING != None) protocols[count++] = _glfw.x11.NET_WM_PING; if (count > 0) { XSetWMProtocols(_glfw.x11.display, window->x11.handle, protocols, count); } } // Set ICCCM WM_HINTS property { XWMHints* hints = XAllocWMHints(); if (!hints) { _glfwInputError(GLFW_OUT_OF_MEMORY, "X11: Failed to allocate WM hints"); return GL_FALSE; } hints->flags = StateHint; hints->initial_state = NormalState; XSetWMHints(_glfw.x11.display, window->x11.handle, hints); XFree(hints); } // Set ICCCM WM_NORMAL_HINTS property (even if no parts are set) { XSizeHints* hints = XAllocSizeHints(); hints->flags = 0; if (wndconfig->monitor) { hints->flags |= PPosition; _glfwPlatformGetMonitorPos(wndconfig->monitor, &hints->x, &hints->y); } if (!wndconfig->resizable) { hints->flags |= (PMinSize | PMaxSize); hints->min_width = hints->max_width = wndconfig->width; hints->min_height = hints->max_height = wndconfig->height; } XSetWMNormalHints(_glfw.x11.display, window->x11.handle, hints); XFree(hints); } if (_glfw.x11.xi2.available) { // Select for XInput2 events XIEventMask eventmask; unsigned char mask[] = { 0 }; eventmask.deviceid = 2; eventmask.mask_len = sizeof(mask); eventmask.mask = mask; XISetMask(mask, XI_Motion); XISelectEvents(_glfw.x11.display, window->x11.handle, &eventmask, 1); } _glfwPlatformSetWindowTitle(window, wndconfig->title); XRRSelectInput(_glfw.x11.display, window->x11.handle, RRScreenChangeNotifyMask); return GL_TRUE; }
// Create the X11 window (and its colormap) // static GLboolean createWindow(_GLFWwindow* window, const _GLFWwndconfig* wndconfig) { unsigned long wamask; XSetWindowAttributes wa; XVisualInfo* visual = _GLFW_X11_CONTEXT_VISUAL; // Every window needs a colormap // Create one based on the visual used by the current context // TODO: Decouple this from context creation window->x11.colormap = XCreateColormap(_glfw.x11.display, _glfw.x11.root, visual->visual, AllocNone); // Create the actual window { wamask = CWBorderPixel | CWColormap | CWEventMask; wa.colormap = window->x11.colormap; wa.border_pixel = 0; wa.event_mask = StructureNotifyMask | KeyPressMask | KeyReleaseMask | PointerMotionMask | ButtonPressMask | ButtonReleaseMask | ExposureMask | FocusChangeMask | VisibilityChangeMask | EnterWindowMask | LeaveWindowMask | PropertyChangeMask; if (wndconfig->monitor == NULL) { // HACK: This is a workaround for windows without a background pixel // not getting any decorations on certain older versions of // Compiz running on Intel hardware wa.background_pixel = BlackPixel(_glfw.x11.display, _glfw.x11.screen); wamask |= CWBackPixel; } _glfwGrabXErrorHandler(); window->x11.handle = XCreateWindow(_glfw.x11.display, _glfw.x11.root, 0, 0, wndconfig->width, wndconfig->height, 0, // Border width visual->depth, // Color depth InputOutput, visual->visual, wamask, &wa); _glfwReleaseXErrorHandler(); if (!window->x11.handle) { _glfwInputXError(GLFW_PLATFORM_ERROR, "X11: Failed to create window"); return GL_FALSE; } if (!wndconfig->decorated) { MotifWmHints hints; hints.flags = MWM_HINTS_DECORATIONS; hints.decorations = 0; XChangeProperty(_glfw.x11.display, window->x11.handle, _glfw.x11.MOTIF_WM_HINTS, _glfw.x11.MOTIF_WM_HINTS, 32, PropModeReplace, (unsigned char*) &hints, sizeof(MotifWmHints) / sizeof(long)); } XSaveContext(_glfw.x11.display, window->x11.handle, _glfw.x11.context, (XPointer) window); } if (window->monitor && !_glfw.x11.hasEWMH) { // This is the butcher's way of removing window decorations // Setting the override-redirect attribute on a window makes the window // manager ignore the window completely (ICCCM, section 4) // The good thing is that this makes undecorated fullscreen windows // easy to do; the bad thing is that we have to do everything manually // and some things (like iconify/restore) won't work at all, as those // are tasks usually performed by the window manager XSetWindowAttributes attributes; attributes.override_redirect = True; XChangeWindowAttributes(_glfw.x11.display, window->x11.handle, CWOverrideRedirect, &attributes); window->x11.overrideRedirect = GL_TRUE; } // Declare the WM protocols supported by GLFW { int count = 0; Atom protocols[2]; // The WM_DELETE_WINDOW ICCCM protocol // Basic window close notification protocol if (_glfw.x11.WM_DELETE_WINDOW) protocols[count++] = _glfw.x11.WM_DELETE_WINDOW; // The _NET_WM_PING EWMH protocol // Tells the WM to ping the GLFW window and flag the application as // unresponsive if the WM doesn't get a reply within a few seconds if (_glfw.x11.NET_WM_PING) protocols[count++] = _glfw.x11.NET_WM_PING; if (count > 0) { XSetWMProtocols(_glfw.x11.display, window->x11.handle, protocols, count); } } if (_glfw.x11.NET_WM_PID) { const pid_t pid = getpid(); XChangeProperty(_glfw.x11.display, window->x11.handle, _glfw.x11.NET_WM_PID, XA_CARDINAL, 32, PropModeReplace, (unsigned char*) &pid, 1); } // Set ICCCM WM_HINTS property { XWMHints* hints = XAllocWMHints(); if (!hints) { _glfwInputError(GLFW_OUT_OF_MEMORY, "X11: Failed to allocate WM hints"); return GL_FALSE; } hints->flags = StateHint; hints->initial_state = NormalState; XSetWMHints(_glfw.x11.display, window->x11.handle, hints); XFree(hints); } // Set ICCCM WM_NORMAL_HINTS property (even if no parts are set) { XSizeHints* hints = XAllocSizeHints(); hints->flags = 0; if (wndconfig->monitor) { hints->flags |= PPosition; _glfwPlatformGetMonitorPos(wndconfig->monitor, &hints->x, &hints->y); } else { // HACK: Explicitly setting PPosition to any value causes some WMs, // notably Compiz and Metacity, to honor the position of // unmapped windows set by XMoveWindow hints->flags |= PPosition; hints->x = hints->y = 0; } if (!wndconfig->resizable) { hints->flags |= (PMinSize | PMaxSize); hints->min_width = hints->max_width = wndconfig->width; hints->min_height = hints->max_height = wndconfig->height; } XSetWMNormalHints(_glfw.x11.display, window->x11.handle, hints); XFree(hints); } // Set ICCCM WM_CLASS property // HACK: Until a mechanism for specifying the application name is added, the // initial window title is used as the window class name if (strlen(wndconfig->title)) { XClassHint* hint = XAllocClassHint(); hint->res_name = (char*) wndconfig->title; hint->res_class = (char*) wndconfig->title; XSetClassHint(_glfw.x11.display, window->x11.handle, hint); XFree(hint); } if (_glfw.x11.xi.available) { // Select for XInput2 events XIEventMask eventmask; unsigned char mask[] = { 0 }; eventmask.deviceid = 2; eventmask.mask_len = sizeof(mask); eventmask.mask = mask; XISetMask(mask, XI_Motion); XISelectEvents(_glfw.x11.display, window->x11.handle, &eventmask, 1); } if (_glfw.x11.XdndAware) { // Announce support for Xdnd (drag and drop) const Atom version = 5; XChangeProperty(_glfw.x11.display, window->x11.handle, _glfw.x11.XdndAware, XA_ATOM, 32, PropModeReplace, (unsigned char*) &version, 1); } _glfwPlatformSetWindowTitle(window, wndconfig->title); XRRSelectInput(_glfw.x11.display, window->x11.handle, RRScreenChangeNotifyMask); _glfwPlatformGetWindowPos(window, &window->x11.xpos, &window->x11.ypos); _glfwPlatformGetWindowSize(window, &window->x11.width, &window->x11.height); return GL_TRUE; }
/* * Class: jogamp_newt_driver_x11_RandR13 * Method: setMonitorMode0 * Signature: (JJJIIIII)Z */ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_RandR13_setMonitorMode0 (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jlong screenResources, jlong monitorInfo, jint crt_id, jint jmode_id, jint rotation, jint x, jint y) { jboolean res = JNI_FALSE; Display * dpy = (Display *) (intptr_t) display; Window root = RootWindow(dpy, (int)screen_idx); XRRScreenResources *resources = (XRRScreenResources *) (intptr_t) screenResources; RRCrtc crtc = findRRCrtc( resources, (RRCrtc)(intptr_t)crt_id ); if( 0 == crtc ) { // n/a DBG_PRINT("RandR13_setMonitorMode0.0: n/a: resources %p (%d), crt_id %#lx \n", resources, (NULL == resources ? 0 : resources->ncrtc), (RRCrtc)(intptr_t)crt_id); return res; } XRRCrtcInfo *xrrCrtcInfo = (XRRCrtcInfo *) (intptr_t) monitorInfo; if( NULL == xrrCrtcInfo ) { // n/a DBG_PRINT("RandR13_setMonitorMode0.1: n/a: resources %p (%d), xrrCrtcInfo %p, crtc %#lx\n", resources, (NULL == resources ? 0 : resources->ncrtc), xrrCrtcInfo, crtc); return res; } if( None == xrrCrtcInfo->mode || 0 == xrrCrtcInfo->noutput ) { // disabled DBG_PRINT("RandR13_setMonitorMode0: disabled: mode %d, noutput %d\n", xrrCrtcInfo->mode, xrrCrtcInfo->noutput); return res; } if( 0 >= jmode_id ) { // oops .. DBG_PRINT("RandR13_setMonitorMode0: inv. modeId: modeId %d\n", jmode_id); return res; } RRMode mode_id = (RRMode)(intptr_t)jmode_id; XRRModeInfo *mode_info = findMode(resources, mode_id); if( NULL == mode_info ) { // oops .. DBG_PRINT("RandR13_setMonitorMode0: inv. mode_id: mode_id %#lx\n", mode_id); return res; } if( 0 > x || 0 > y ) { x = xrrCrtcInfo->x; y = xrrCrtcInfo->y; } Rotation xrotation = NewtScreen_Degree2XRotation(env, rotation); int rot_change = xrrCrtcInfo->rotation != xrotation; DBG_PRINT("RandR13_setMonitorMode0: crt %#lx, noutput %d -> 0x%X, mode %#lx -> %#lx, pos %d / %d, rotation %d -> %d (change %d)\n", crtc, xrrCrtcInfo->noutput, xrrCrtcInfo->outputs[0], xrrCrtcInfo->mode, mode_id, x, y, (int)xrrCrtcInfo->rotation, (int)xrotation, rot_change); XRRSelectInput (dpy, root, RRScreenChangeNotifyMask); Status status = RRSetConfigSuccess; int pre_fb_width=0, pre_fb_height=0; int fb_width=0, fb_height=0; int fb_width_mm=0, fb_height_mm=0; crtc_t *root_crtc = get_screen_size1(dpy, root, &fb_width, &fb_height, resources, crtc, xrrCrtcInfo, xrotation, x, y, mode_info); Bool fb_change = get_screen_sizemm(dpy, screen_idx, fb_width, fb_height, &fb_width_mm, &fb_height_mm, &pre_fb_width, &pre_fb_height); DBG_PRINT("RandR13_setMonitorMode0: crt %#lx, fb[change %d: %d x %d -> %d x %d [%d x %d mm]\n", crtc, fb_change, pre_fb_width, pre_fb_height, fb_width, fb_height, fb_width_mm, fb_height_mm); if(fb_change) { // Disable CRTC first, since new size differs from current // and we shall avoid invalid intermediate configuration (see spec)! #if 0 { // Disable all CRTCs (Not required!) crtc_t * iter_crtc; for(iter_crtc=root_crtc; RRSetConfigSuccess == status && NULL!=iter_crtc; iter_crtc=iter_crtc->next) { if( None == iter_crtc->mode_id || NULL == iter_crtc->mode_info || 0 == iter_crtc->crtc_info->noutput ) { // disabled continue; } status = XRRSetCrtcConfig (dpy, resources, iter_crtc->crtc_id, CurrentTime, 0, 0, None, RR_Rotate_0, NULL, 0); } } #else status = XRRSetCrtcConfig (dpy, resources, crtc, CurrentTime, 0, 0, None, RR_Rotate_0, NULL, 0); #endif DBG_PRINT("RandR13_setMonitorMode0: crt %#lx disable: %d -> %d\n", crtc, status, RRSetConfigSuccess == status); if( RRSetConfigSuccess == status ) { XRRSetScreenSize (dpy, root, fb_width, fb_height, fb_width_mm, fb_height_mm); DBG_PRINT("RandR13_setMonitorMode0: crt %#lx screen-size\n", crtc); } } if( RRSetConfigSuccess == status ) { #if 0 { // Enable/Set all CRTCs (Not required!) crtc_t * iter_crtc; for(iter_crtc=root_crtc; RRSetConfigSuccess == status && NULL!=iter_crtc; iter_crtc=iter_crtc->next) { if( None == iter_crtc->mode_id || NULL == iter_crtc->mode_info || 0 == iter_crtc->crtc_info->noutput ) { // disabled continue; } status = XRRSetCrtcConfig( dpy, resources, iter_crtc->crtc_id, CurrentTime, iter_crtc->x, iter_crtc->y, iter_crtc->mode_id, iter_crtc->rotation, iter_crtc->crtc_info->outputs, iter_crtc->crtc_info->noutput ); } } #else status = XRRSetCrtcConfig( dpy, resources, crtc, CurrentTime, x, y, mode_id, xrotation, xrrCrtcInfo->outputs, xrrCrtcInfo->noutput ); #endif DBG_PRINT("RandR13_setMonitorMode0: crt %#lx set-config: %d -> %d\n", crtc, status, RRSetConfigSuccess == status); } res = status == RRSetConfigSuccess; DBG_PRINT("RandR13_setMonitorMode0: FIN: %d -> ok %d\n", status, res); destroyCrtcChain(root_crtc, crtc); root_crtc=NULL; return res; }
// function create GUI window bool StWindowImpl::create() { myKeysState.reset(); // replace default XError handler to ignore some errors XSetErrorHandler(stXErrorHandler); myInitState = STWIN_INITNOTSTART; // X-server implementation // create window on unix systems throw X-server int dummy; // open a connection to the X server StXDisplayH stXDisplay = new StXDisplay(); if(!stXDisplay->isOpened()) { stXDisplay.nullify(); stError("X, could not open display"); myInitState = STWIN_ERROR_X_OPENDISPLAY; return false; } myMaster.stXDisplay = stXDisplay; Display* hDisplay = stXDisplay->hDisplay; #if defined(ST_HAVE_EGL) myMaster.hRC = new StWinGlrc(eglGetDisplay(hDisplay), attribs.IsGlDebug, attribs.GlDepthSize); if(!myMaster.hRC->isValid()) { myMaster.close(); mySlave.close(); myInitState = STWIN_ERROR_X_GLRC_CREATE; return false; } XVisualInfo aVisInfo; aVisInfo.visualid = 0; if (eglGetConfigAttrib(myMaster.hRC->getDisplay(), myMaster.hRC->getConfig(), EGL_NATIVE_VISUAL_ID, (EGLint* )&aVisInfo.visualid) != EGL_TRUE) { myMaster.close(); mySlave.close(); myInitState = STWIN_ERROR_X_GLRC_CREATE; return false; } int aNbVisuals = 0; stXDisplay->hVisInfo = XGetVisualInfo(hDisplay, VisualIDMask, &aVisInfo, &aNbVisuals); #else // GLX // make sure OpenGL's GLX extension supported if(!glXQueryExtension(hDisplay, &dummy, &dummy)) { myMaster.close(); stError("X, server has no OpenGL GLX extension"); myInitState = STWIN_ERROR_X_NOGLX; return false; } int anAttribsBuff[] = { GLX_STEREO, attribs.IsGlStereo ? True : False, GLX_X_RENDERABLE, True, GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, GLX_RENDER_TYPE, GLX_RGBA_BIT, GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR, GLX_RED_SIZE, 8, GLX_GREEN_SIZE, 8, GLX_BLUE_SIZE, 8, GLX_ALPHA_SIZE, 0, GLX_DEPTH_SIZE, attribs.GlDepthSize, GLX_STENCIL_SIZE, 0, GLX_DOUBLEBUFFER, True, //GLX_SAMPLE_BUFFERS, 1, //GLX_SAMPLES, 4, None }; // FBConfigs were added in GLX version 1.3 int aGlxMajor = 0; int aGlxMinor = 0; const bool hasFBCfg = glXQueryVersion(hDisplay, &aGlxMajor, &aGlxMinor) && ((aGlxMajor == 1 && aGlxMinor >= 3) || (aGlxMajor > 1)); int aFBCount = 0; GLXFBConfig* aFBCfgList = NULL; if(hasFBCfg) { aFBCfgList = glXChooseFBConfig(hDisplay, DefaultScreen(hDisplay), anAttribsBuff, &aFBCount); } if(aFBCfgList == NULL && hasFBCfg && attribs.IsGlStereo) { ST_ERROR_LOG("X, no Quad Buffered visual"); anAttribsBuff[1] = False; aFBCfgList = glXChooseFBConfig(hDisplay, DefaultScreen(hDisplay), anAttribsBuff, &aFBCount); } if(aFBCfgList != NULL && aFBCount >= 1) { stXDisplay->FBCfg = aFBCfgList[0]; stXDisplay->hVisInfo = glXGetVisualFromFBConfig(hDisplay, stXDisplay->FBCfg); } else { // try to use glXChooseVisual... pointless? int aDblBuff[] = { GLX_RGBA, GLX_DEPTH_SIZE, attribs.GlDepthSize, GLX_DOUBLEBUFFER, None }; if(attribs.IsGlStereo) { // find an appropriate visual int aQuadBuff[] = { GLX_RGBA, GLX_DEPTH_SIZE, attribs.GlDepthSize, GLX_DOUBLEBUFFER, GLX_STEREO, None }; stXDisplay->hVisInfo = glXChooseVisual(hDisplay, DefaultScreen(hDisplay), aQuadBuff); if(stXDisplay->hVisInfo == NULL) { ST_ERROR_LOG("X, no Quad Buffered visual"); stXDisplay->hVisInfo = glXChooseVisual(hDisplay, DefaultScreen(hDisplay), aDblBuff); if(stXDisplay->hVisInfo == NULL) { myMaster.close(); stError("X, no RGB visual with depth buffer"); myInitState = STWIN_ERROR_X_NORGB; return false; } } } else { // find an appropriate visual // find an OpenGL-capable RGB visual with depth buffer stXDisplay->hVisInfo = glXChooseVisual(hDisplay, DefaultScreen(hDisplay), aDblBuff); if(stXDisplay->hVisInfo == NULL) { myMaster.close(); stError("X, no RGB visual with depth buffer"); myInitState = STWIN_ERROR_X_NORGB; return false; } } } XFree(aFBCfgList); #endif if(attribs.Slave != StWinSlave_slaveOff) { // just copy handle mySlave.stXDisplay = stXDisplay; } // create an X window with the selected visual XSetWindowAttributes aWinAttribsX = createDefaultAttribs(stXDisplay); updateChildRect(); Window aParentWin = (Window )myParentWin; if(aParentWin == 0 && !attribs.IsNoDecor) { aWinAttribsX.override_redirect = False; myMaster.hWindow = XCreateWindow(hDisplay, stXDisplay->getRootWindow(), myRectNorm.left(), myRectNorm.top(), myRectNorm.width(), myRectNorm.height(), 0, stXDisplay->getDepth(), InputOutput, stXDisplay->getVisual(), CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect, &aWinAttribsX); if(myMaster.hWindow == 0) { myMaster.close(); stError("X, XCreateWindow failed for Master"); myInitState = STWIN_ERROR_X_CREATEWIN; return false; } aParentWin = myMaster.hWindow; XSetStandardProperties(hDisplay, myMaster.hWindow, myWindowTitle.toCString(), myWindowTitle.toCString(), None, NULL, 0, NULL); // setup WM_CLASS in sync with .desktop StartupWMClass entity // to ensure Window Manager would show an propriate icon for application XClassHint* aClassHint = XAllocClassHint(); if(aClassHint != NULL) { StString aName = StProcess::getProcessName(); StString aClass("sView"); // const_cast should be harmless here and it seems to be just broken signature of XClassHint structure aClassHint->res_name = const_cast<char* >(aName.toCString()); aClassHint->res_class = const_cast<char* >(aClass.toCString()); XSetClassHint(hDisplay, myMaster.hWindow, aClassHint); XFree(aClassHint); } } aWinAttribsX.override_redirect = True; // GL window always undecorated myMaster.hWindowGl = XCreateWindow(hDisplay, (aParentWin != 0) ? aParentWin : stXDisplay->getRootWindow(), 0, 0, myRectNorm.width(), myRectNorm.height(), 0, stXDisplay->getDepth(), InputOutput, stXDisplay->getVisual(), CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect, &aWinAttribsX); if(myMaster.hWindowGl == 0) { myMaster.close(); stError("X, XCreateWindow failed for Master"); myInitState = STWIN_ERROR_X_CREATEWIN; return false; } XSetStandardProperties(hDisplay, myMaster.hWindowGl, "master window", "master window", None, NULL, 0, NULL); if(attribs.Slave != StWinSlave_slaveOff) { aWinAttribsX.event_mask = NoEventMask; // we do not parse any events to slave window! aWinAttribsX.override_redirect = True; // slave window always undecorated mySlave.hWindowGl = XCreateWindow(hDisplay, stXDisplay->getRootWindow(), getSlaveLeft(), getSlaveTop(), getSlaveWidth(), getSlaveHeight(), 0, stXDisplay->getDepth(), InputOutput, stXDisplay->getVisual(), CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect, &aWinAttribsX); if(mySlave.hWindowGl == 0) { myMaster.close(); mySlave.close(); stError("X, XCreateWindow failed for Slave"); myInitState = STWIN_ERROR_X_CREATEWIN; return false; } XSetStandardProperties(hDisplay, mySlave.hWindowGl, "slave window", "slave window", None, NULL, 0, NULL); } int isGlCtx = myMaster.glCreateContext(attribs.Slave != StWinSlave_slaveOff ? &mySlave : NULL, myRectNorm, attribs.GlDepthSize, attribs.IsGlStereo, attribs.IsGlDebug); if(isGlCtx != STWIN_INIT_SUCCESS) { myMaster.close(); mySlave.close(); myInitState = isGlCtx; return false; } myGlContext = new StGLContext(myResMgr); if(!myGlContext->stglInit()) { myMaster.close(); mySlave.close(); stError("Critical error - broken GL context!\nInvalid OpenGL driver?"); myInitState = STWIN_ERROR_X_GLRC_CREATE; return false; } // handle close window event if(myMaster.hWindow != 0) { XSetWMProtocols(hDisplay, myMaster.hWindow, &(stXDisplay->wndDestroyAtom), 1); } // Announce XDND support myMaster.setupXDND(); // Initialize XRandr events reception if(XRRQueryExtension(hDisplay, &myMaster.xrandrEventBase, &dummy)) { XRRSelectInput(hDisplay, stXDisplay->getRootWindow(), RRScreenChangeNotifyMask | RRCrtcChangeNotifyMask | RROutputPropertyNotifyMask); myMaster.isRecXRandrEvents = true; } else { myMaster.isRecXRandrEvents = false; } // request the X window to be displayed on the screen if(attribs.Slave != StWinSlave_slaveOff) { // request the X window to be displayed on the screen if(!attribs.IsSlaveHidden && (!isSlaveIndependent() || myMonitors.size() > 1)) { XMapWindow(hDisplay, mySlave.hWindowGl); //XIfEvent(hDisplay, &myXEvent, stXWaitMapped, (char* )mySlave.hWindowGl); } // always hise mouse cursor on slave window mySlave.setupNoCursor(); } if(!attribs.IsHidden) { if(myMaster.hWindow != 0) { XMapWindow(hDisplay, myMaster.hWindow); //XIfEvent(hDisplay, &myXEvent, stXWaitMapped, (char* )myMaster.hWindow); } XMapWindow(hDisplay, myMaster.hWindowGl); //XIfEvent(hDisplay, &myXEvent, stXWaitMapped, (char* )myMaster.hWindowGl); } // setup default icon if((Window )myParentWin == 0) { XpmCreatePixmapFromData(hDisplay, myMaster.hWindow, (char** )sview_xpm, &myMaster.iconImage, &myMaster.iconShape, NULL); XWMHints anIconHints; anIconHints.flags = IconPixmapHint | IconMaskHint; anIconHints.icon_pixmap = myMaster.iconImage; anIconHints.icon_mask = myMaster.iconShape; XSetWMHints(hDisplay, myMaster.hWindow, &anIconHints); } // we need this call to go around bugs if(!attribs.IsFullScreen && myMaster.hWindow != 0) { XMoveResizeWindow(hDisplay, myMaster.hWindow, myRectNorm.left(), myRectNorm.top(), myRectNorm.width(), myRectNorm.height()); } // flushes the output buffer, most client apps needn't use this cause buffer is automatically flushed as needed by calls to XNextEvent()... XFlush(hDisplay); myMonitors.registerUpdater(true); myIsUpdated = true; myInitState = STWIN_INIT_SUCCESS; return true; }
// 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; }
static struct lock * lockscreen(Display *dpy, struct xrandr *rr, int screen) { char curs[] = {0, 0, 0, 0, 0, 0, 0, 0}; int i, ptgrab, kbgrab; struct lock *lock; XColor color, dummy; XSetWindowAttributes wa; Cursor invisible; if (dpy == NULL || screen < 0 || !(lock = malloc(sizeof(struct lock)))) return NULL; lock->screen = screen; lock->root = RootWindow(dpy, lock->screen); for (i = 0; i < NUMCOLS; i++) { XAllocNamedColor(dpy, DefaultColormap(dpy, lock->screen), colorname[i], &color, &dummy); lock->colors[i] = color.pixel; } /* init */ wa.override_redirect = 1; wa.background_pixel = lock->colors[INIT]; lock->win = XCreateWindow(dpy, lock->root, 0, 0, DisplayWidth(dpy, lock->screen), DisplayHeight(dpy, lock->screen), 0, DefaultDepth(dpy, lock->screen), CopyFromParent, DefaultVisual(dpy, lock->screen), CWOverrideRedirect | CWBackPixel, &wa); lock->pmap = XCreateBitmapFromData(dpy, lock->win, curs, 8, 8); invisible = XCreatePixmapCursor(dpy, lock->pmap, lock->pmap, &color, &color, 0, 0); XDefineCursor(dpy, lock->win, invisible); /* Try to grab mouse pointer *and* keyboard for 600ms, else fail the lock */ for (i = 0, ptgrab = kbgrab = -1; i < 6; i++) { if (ptgrab != GrabSuccess) { ptgrab = XGrabPointer(dpy, lock->root, False, ButtonPressMask | ButtonReleaseMask | PointerMotionMask, GrabModeAsync, GrabModeAsync, None, invisible, CurrentTime); } if (kbgrab != GrabSuccess) { kbgrab = XGrabKeyboard(dpy, lock->root, True, GrabModeAsync, GrabModeAsync, CurrentTime); } /* input is grabbed: we can lock the screen */ if (ptgrab == GrabSuccess && kbgrab == GrabSuccess) { XMapRaised(dpy, lock->win); if (rr->active) XRRSelectInput(dpy, lock->win, RRScreenChangeNotifyMask); XSelectInput(dpy, lock->root, SubstructureNotifyMask); return lock; } /* retry on AlreadyGrabbed but fail on other errors */ if ((ptgrab != AlreadyGrabbed && ptgrab != GrabSuccess) || (kbgrab != AlreadyGrabbed && kbgrab != GrabSuccess)) break; usleep(100000); } /* we couldn't grab all input: fail out */ if (ptgrab != GrabSuccess) fprintf(stderr, "slock: unable to grab mouse pointer for screen %d\n", screen); if (kbgrab != GrabSuccess) fprintf(stderr, "slock: unable to grab keyboard for screen %d\n", screen); return NULL; }
/* Returns NULL if screen could not be created. For instance, if * the driver does not support Xrandr 1.2. */ MateRRScreen * mate_rr_screen_new (GdkScreen *gdk_screen, MateRRScreenChanged callback, gpointer data, GError **error) { #ifdef HAVE_RANDR Display *dpy = GDK_SCREEN_XDISPLAY (gdk_screen); int event_base; int ignore; #endif g_return_val_if_fail (error == NULL || *error == NULL, NULL); _mate_desktop_init_i18n (); #ifdef HAVE_RANDR if (XRRQueryExtension (dpy, &event_base, &ignore)) { MateRRScreen *screen = g_new0 (MateRRScreen, 1); screen->gdk_screen = gdk_screen; screen->gdk_root = gdk_screen_get_root_window (gdk_screen); screen->xroot = gdk_x11_drawable_get_xid (screen->gdk_root); screen->xdisplay = dpy; screen->xscreen = gdk_x11_screen_get_xscreen (screen->gdk_screen); screen->connector_type_atom = XInternAtom (dpy, "ConnectorType", FALSE); screen->callback = callback; screen->data = data; screen->randr_event_base = event_base; XRRQueryVersion (dpy, &screen->rr_major_version, &screen->rr_minor_version); if (screen->rr_major_version > 1 || (screen->rr_major_version == 1 && screen->rr_minor_version < 2)) { g_set_error (error, MATE_RR_ERROR, MATE_RR_ERROR_NO_RANDR_EXTENSION, "RANDR extension is too old (must be at least 1.2)"); g_free (screen); return NULL; } screen->info = screen_info_new (screen, TRUE, error); if (!screen->info) { g_free (screen); return NULL; } if (screen->callback) { XRRSelectInput (screen->xdisplay, screen->xroot, RRScreenChangeNotifyMask); gdk_x11_register_standard_event_type (gdk_screen_get_display (gdk_screen), event_base, RRNotify + 1); gdk_window_add_filter (screen->gdk_root, screen_on_event, screen); } return screen; } else { #endif /* HAVE_RANDR */ g_set_error (error, MATE_RR_ERROR, MATE_RR_ERROR_NO_RANDR_EXTENSION, _("RANDR extension is not present")); return NULL; #ifdef HAVE_RANDR } #endif }
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; }
/* 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); } } }
// 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; }
JNIEXPORT void JNICALL Java_org_lwjgl_system_linux_Xrandr_nXRRSelectInput(JNIEnv *__env, jclass clazz, jlong displayAddress, jlong w, jint mask) { Display *display = (Display *)(intptr_t)displayAddress; UNUSED_PARAMS(__env, clazz) XRRSelectInput(display, (Window)w, mask); }
static void setup_display(void) { XGCValues gv; XSetWindowAttributes attr; XColor dummy; XModifierKeymap *modmap; /* used in scanning windows (XQueryTree) */ unsigned int i, j, nwins; Window dw1, dw2, *wins; XWindowAttributes winattr; LOG_ENTER("setup_display()"); dpy = XOpenDisplay(opt_display); if (!dpy) { LOG_ERROR("can't open display %s\n", opt_display); exit(1); } XSetErrorHandler(handle_xerror); /* XSynchronize(dpy, True); */ /* Standard & EWMH atoms */ ewmh_init(); font = XLoadQueryFont(dpy, opt_font); if (!font) font = XLoadQueryFont(dpy, DEF_FONT); if (!font) { LOG_ERROR("couldn't find a font to use: try starting with -fn fontname\n"); exit(1); } move_curs = XCreateFontCursor(dpy, XC_fleur); resize_curs = XCreateFontCursor(dpy, XC_plus); /* find out which modifier is NumLock - we'll use this when grabbing * every combination of modifiers we can think of */ modmap = XGetModifierMapping(dpy); for (i = 0; i < 8; i++) { for (j = 0; j < (unsigned int)modmap->max_keypermod; j++) { if (modmap->modifiermap[i*modmap->max_keypermod+j] == XKeysymToKeycode(dpy, XK_Num_Lock)) { numlockmask = (1<<i); LOG_DEBUG("XK_Num_Lock is (1<<0x%02x)\n", i); } } } XFreeModifiermap(modmap); /* set up GC parameters - same for each screen */ gv.function = GXinvert; gv.subwindow_mode = IncludeInferiors; gv.line_width = 1; /* opt_bw */ gv.font = font->fid; /* set up root window attributes - same for each screen */ attr.event_mask = ChildMask | EnterWindowMask | ColormapChangeMask; /* SHAPE extension? */ #ifdef SHAPE { int e_dummy; have_shape = XShapeQueryExtension(dpy, &shape_event, &e_dummy); } #endif /* Xrandr extension? */ #ifdef RANDR { int e_dummy; have_randr = XRRQueryExtension(dpy, &randr_event_base, &e_dummy); if (!have_randr) { LOG_DEBUG("XRandR is not supported on this display.\n"); } } #endif /* now set up each screen in turn */ num_screens = ScreenCount(dpy); if (num_screens < 0) { LOG_ERROR("Can't count screens\n"); exit(1); } screens = xmalloc(num_screens * sizeof(ScreenInfo)); for (i = 0; i < (unsigned int)num_screens; i++) { char *ds, *colon, *dot; ds = DisplayString(dpy); /* set up DISPLAY environment variable to use */ colon = strrchr(ds, ':'); screens[i].display = xmalloc(14 + strlen(ds)); strcpy(screens[i].display, "DISPLAY="); strcat(screens[i].display, ds); if (colon && num_screens > 1) { colon = strrchr(screens[i].display, ':'); dot = strchr(colon, '.'); if (!dot) dot = colon + strlen(colon); snprintf(dot, 5, ".%d", i); } screens[i].screen = i; screens[i].root = RootWindow(dpy, i); #ifdef RANDR if (have_randr) { XRRSelectInput(dpy, screens[i].root, RRScreenChangeNotifyMask); } #endif #ifdef VWM screens[i].vdesk = KEY_TO_VDESK(XK_1); #endif XAllocNamedColor(dpy, DefaultColormap(dpy, i), opt_fg, &screens[i].fg, &dummy); XAllocNamedColor(dpy, DefaultColormap(dpy, i), opt_bg, &screens[i].bg, &dummy); #ifdef VWM XAllocNamedColor(dpy, DefaultColormap(dpy, i), opt_fc, &screens[i].fc, &dummy); #endif screens[i].invert_gc = XCreateGC(dpy, screens[i].root, GCFunction | GCSubwindowMode | GCLineWidth | GCFont, &gv); XChangeWindowAttributes(dpy, screens[i].root, CWEventMask, &attr); grab_keys_for_screen(&screens[i]); screens[i].docks_visible = 1; /* scan all the windows on this screen */ LOG_XENTER("XQueryTree(screen=%d)", i); XQueryTree(dpy, screens[i].root, &dw1, &dw2, &wins, &nwins); LOG_XDEBUG("%d windows\n", nwins); LOG_XLEAVE(); for (j = 0; j < nwins; j++) { XGetWindowAttributes(dpy, wins[j], &winattr); if (!winattr.override_redirect && winattr.map_state == IsViewable) make_new_client(wins[j], &screens[i]); } XFree(wins); ewmh_init_screen(&screens[i]); } ewmh_set_net_active_window(NULL); LOG_LEAVE(); }