gboolean _gdk_x11_window_simulate_button (GdkWindow *window, gint x, gint y, guint button, /*1..3*/ GdkModifierType modifiers, GdkEventType button_pressrelease) { GdkScreen *screen; XButtonEvent xev = { 0, /* type */ 0, /* serial */ 1, /* send_event */ }; gboolean success; g_return_val_if_fail (button_pressrelease == GDK_BUTTON_PRESS || button_pressrelease == GDK_BUTTON_RELEASE, FALSE); g_return_val_if_fail (window != NULL, FALSE); if (!GDK_WINDOW_IS_MAPPED (window)) return FALSE; screen = gdk_window_get_screen (window); if (x < 0 && y < 0) { x = window->width / 2; y = window->height / 2; } /* Convert to impl coordinates */ x = x + window->abs_x; y = y + window->abs_y; xev.type = button_pressrelease == GDK_BUTTON_PRESS ? ButtonPress : ButtonRelease; xev.display = GDK_WINDOW_XDISPLAY (window); xev.window = GDK_WINDOW_XID (window); xev.root = RootWindow (xev.display, GDK_X11_SCREEN (screen)->screen_num); xev.subwindow = 0; xev.time = 0; xev.x = x; xev.y = y; xev.x_root = 0; xev.y_root = 0; xev.state = modifiers; xev.button = button; gdk_x11_display_error_trap_push (GDK_WINDOW_DISPLAY (window)); xev.same_screen = XTranslateCoordinates (xev.display, xev.window, xev.root, xev.x, xev.y, &xev.x_root, &xev.y_root, &xev.subwindow); if (!xev.subwindow) xev.subwindow = xev.window; success = xev.same_screen; success &= 0 != XWarpPointer (xev.display, None, xev.window, 0, 0, 0, 0, xev.x, xev.y); success &= 0 != XSendEvent (xev.display, xev.window, True, button_pressrelease == GDK_BUTTON_PRESS ? ButtonPressMask : ButtonReleaseMask, (XEvent*) &xev); XSync (xev.display, False); success &= 0 == gdk_x11_display_error_trap_pop(GDK_WINDOW_DISPLAY (window)); return success; }
static void fetch_net_wm_check_window (GdkScreen *screen) { GdkX11Screen *x11_screen; GdkDisplay *display; Window window; GTimeVal tv; gint error; x11_screen = GDK_X11_SCREEN (screen); display = x11_screen->display; g_return_if_fail (GDK_X11_DISPLAY (display)->trusted_client); if (x11_screen->wmspec_check_window != None) return; /* already have it */ g_get_current_time (&tv); if (ABS (tv.tv_sec - x11_screen->last_wmspec_check_time) < 15) return; /* we've checked recently */ window = get_net_supporting_wm_check (x11_screen, x11_screen->xroot_window); if (window == None) return; if (window != get_net_supporting_wm_check (x11_screen, window)) return; gdk_x11_display_error_trap_push (display); /* Find out if this WM goes away, so we can reset everything. */ XSelectInput (x11_screen->xdisplay, window, StructureNotifyMask); error = gdk_x11_display_error_trap_pop (display); if (!error) { /* We check the window property again because after XGetWindowProperty() * and before XSelectInput() the window may have been recycled in such a * way that XSelectInput() doesn't fail but the window is no longer what * we want. */ if (window != get_net_supporting_wm_check (x11_screen, window)) return; x11_screen->wmspec_check_window = window; x11_screen->last_wmspec_check_time = tv.tv_sec; x11_screen->need_refetch_net_supported = TRUE; x11_screen->need_refetch_wm_name = TRUE; /* Careful, reentrancy */ _gdk_x11_screen_window_manager_changed (screen); } }
/** * gdk_x11_xatom_to_atom_for_display: * @display: (type GdkX11Display): A #GdkDisplay * @xatom: an X atom * * Convert from an X atom for a #GdkDisplay to the corresponding * #GdkAtom. * * Return value: (transfer none): the corresponding #GdkAtom. * * Since: 2.2 **/ GdkAtom gdk_x11_xatom_to_atom_for_display (GdkDisplay *display, Atom xatom) { GdkX11Display *display_x11; GdkAtom virtual_atom = GDK_NONE; g_return_val_if_fail (GDK_IS_DISPLAY (display), GDK_NONE); if (xatom == None) return GDK_NONE; if (gdk_display_is_closed (display)) return GDK_NONE; display_x11 = GDK_X11_DISPLAY (display); if (xatom < G_N_ELEMENTS (xatoms_offset) - N_CUSTOM_PREDEFINED) return INDEX_TO_ATOM (xatom); if (display_x11->atom_to_virtual) virtual_atom = GDK_POINTER_TO_ATOM (g_hash_table_lookup (display_x11->atom_to_virtual, GUINT_TO_POINTER (xatom))); if (!virtual_atom) { /* If this atom doesn't exist, we'll die with an X error unless * we take precautions */ char *name; gdk_x11_display_error_trap_push (display); name = XGetAtomName (GDK_DISPLAY_XDISPLAY (display), xatom); if (gdk_x11_display_error_trap_pop (display)) { g_warning (G_STRLOC " invalid X atom: %ld", xatom); } else { virtual_atom = gdk_atom_intern (name, FALSE); XFree (name); insert_atom_pair (display, virtual_atom, xatom); } } return virtual_atom; }
gint _gdk_x11_display_send_xevent (GdkDisplay *display, Window window, gboolean propagate, glong event_mask, XEvent *event_send) { gboolean result; if (gdk_display_is_closed (display)) return FALSE; gdk_x11_display_error_trap_push (display); result = XSendEvent (GDK_DISPLAY_XDISPLAY (display), window, propagate, event_mask, event_send); XSync (GDK_DISPLAY_XDISPLAY (display), False); if (gdk_x11_display_error_trap_pop (display)) return FALSE; return result; }
XDevice* device_is_touchpad (XDeviceInfo *deviceinfo) { GdkDisplay *display; XDevice *device; display = gdk_display_get_default (); if (deviceinfo->type != XInternAtom (GDK_DISPLAY_XDISPLAY (display), XI_TOUCHPAD, True)) return NULL; gdk_x11_display_error_trap_push (display); device = XOpenDevice (GDK_DISPLAY_XDISPLAY (display), deviceinfo->id); if (gdk_x11_display_error_trap_pop (display) || (device == NULL)) return NULL; if (device_has_property (device, "libinput Tapping Enabled") || device_has_property (device, "Synaptics Off")) { return device; } XCloseDevice (GDK_DISPLAY_XDISPLAY (display), device); return NULL; }
static void fetch_net_wm_check_window (GdkScreen *screen) { GdkX11Screen *x11_screen; GdkDisplay *display; Atom type; gint format; gulong n_items; gulong bytes_after; guchar *data; Window *xwindow; GTimeVal tv; gint error; x11_screen = GDK_X11_SCREEN (screen); display = x11_screen->display; g_return_if_fail (GDK_X11_DISPLAY (display)->trusted_client); g_get_current_time (&tv); if (ABS (tv.tv_sec - x11_screen->last_wmspec_check_time) < 15) return; /* we've checked recently */ x11_screen->last_wmspec_check_time = tv.tv_sec; data = NULL; XGetWindowProperty (x11_screen->xdisplay, x11_screen->xroot_window, gdk_x11_get_xatom_by_name_for_display (display, "_NET_SUPPORTING_WM_CHECK"), 0, G_MAXLONG, False, XA_WINDOW, &type, &format, &n_items, &bytes_after, &data); if (type != XA_WINDOW) { if (data) XFree (data); return; } xwindow = (Window *)data; if (x11_screen->wmspec_check_window == *xwindow) { XFree (xwindow); return; } gdk_x11_display_error_trap_push (display); /* Find out if this WM goes away, so we can reset everything. */ XSelectInput (x11_screen->xdisplay, *xwindow, StructureNotifyMask); error = gdk_x11_display_error_trap_pop (display); if (!error) { x11_screen->wmspec_check_window = *xwindow; x11_screen->need_refetch_net_supported = TRUE; x11_screen->need_refetch_wm_name = TRUE; /* Careful, reentrancy */ _gdk_x11_screen_window_manager_changed (GDK_SCREEN (x11_screen)); } else if (error == BadWindow) { /* Leftover property, try again immediately, new wm may be starting up */ x11_screen->last_wmspec_check_time = 0; } XFree (xwindow); }
static gboolean init_randr15 (GdkScreen *screen, gboolean *changed) { #ifdef HAVE_RANDR15 GdkDisplay *display = gdk_screen_get_display (screen); GdkX11Display *x11_display = GDK_X11_DISPLAY (display); GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen); XRRScreenResources *resources; RROutput primary_output = None; RROutput first_output = None; int i; gboolean randr12_compat = FALSE; XRRMonitorInfo *rr_monitors; int num_rr_monitors; int old_primary; if (!x11_display->have_randr15) return FALSE; resources = XRRGetScreenResourcesCurrent (x11_screen->xdisplay, x11_screen->xroot_window); if (!resources) return FALSE; rr_monitors = XRRGetMonitors (x11_screen->xdisplay, x11_screen->xroot_window, True, &num_rr_monitors); if (!rr_monitors) return FALSE; for (i = 0; i < x11_display->monitors->len; i++) { GdkX11Monitor *monitor = x11_display->monitors->pdata[i]; monitor->add = FALSE; monitor->remove = TRUE; } for (i = 0; i < num_rr_monitors; i++) { RROutput output = rr_monitors[i].outputs[0]; XRROutputInfo *output_info; GdkX11Monitor *monitor; GdkRectangle geometry; GdkRectangle newgeo; char *name; int refresh_rate = 0; gdk_x11_display_error_trap_push (display); output_info = XRRGetOutputInfo (x11_screen->xdisplay, resources, output); if (gdk_x11_display_error_trap_pop (display)) continue; if (output_info == NULL) continue; /* Non RandR1.2+ X driver have output name "default" */ randr12_compat |= !g_strcmp0 (output_info->name, "default"); if (output_info->connection == RR_Disconnected) { XRRFreeOutputInfo (output_info); continue; } if (first_output == None) first_output = output; if (output_info->crtc) { XRRCrtcInfo *crtc = XRRGetCrtcInfo (x11_screen->xdisplay, resources, output_info->crtc); int j; for (j = 0; j < resources->nmode; j++) { XRRModeInfo *xmode = &resources->modes[j]; if (xmode->id == crtc->mode) { if (xmode->hTotal != 0 && xmode->vTotal != 0) refresh_rate = (1000 * xmode->dotClock) / (xmode->hTotal * xmode->vTotal); break; } } XRRFreeCrtcInfo (crtc); } monitor = find_monitor_by_output (x11_display, output); if (monitor) monitor->remove = FALSE; else { monitor = g_object_new (GDK_TYPE_X11_MONITOR, "display", display, NULL); monitor->output = output; monitor->add = TRUE; g_ptr_array_add (x11_display->monitors, monitor); } gdk_monitor_get_geometry (GDK_MONITOR (monitor), &geometry); name = g_strndup (output_info->name, output_info->nameLen); newgeo.x = rr_monitors[i].x / x11_screen->window_scale; newgeo.y = rr_monitors[i].y / x11_screen->window_scale; newgeo.width = rr_monitors[i].width / x11_screen->window_scale; newgeo.height = rr_monitors[i].height / x11_screen->window_scale; if (newgeo.x != geometry.x || newgeo.y != geometry.y || newgeo.width != geometry.width || newgeo.height != geometry.height || rr_monitors[i].mwidth != gdk_monitor_get_width_mm (GDK_MONITOR (monitor)) || rr_monitors[i].mheight != gdk_monitor_get_height_mm (GDK_MONITOR (monitor)) || g_strcmp0 (name, gdk_monitor_get_model (GDK_MONITOR (monitor)))) *changed = TRUE; gdk_monitor_set_position (GDK_MONITOR (monitor), newgeo.x, newgeo.y); gdk_monitor_set_size (GDK_MONITOR (monitor), newgeo.width, newgeo.height); g_object_notify (G_OBJECT (monitor), "workarea"); gdk_monitor_set_physical_size (GDK_MONITOR (monitor), rr_monitors[i].mwidth, rr_monitors[i].mheight); gdk_monitor_set_subpixel_layout (GDK_MONITOR (monitor), translate_subpixel_order (output_info->subpixel_order)); gdk_monitor_set_refresh_rate (GDK_MONITOR (monitor), refresh_rate); gdk_monitor_set_scale_factor (GDK_MONITOR (monitor), x11_screen->window_scale); gdk_monitor_set_model (GDK_MONITOR (monitor), name); g_free (name); if (rr_monitors[i].primary) primary_output = monitor->output; XRRFreeOutputInfo (output_info); } XRRFreeMonitors (rr_monitors); XRRFreeScreenResources (resources); /* non RandR 1.2+ X driver doesn't return any usable multihead data */ if (randr12_compat) { for (i = 0; i < x11_display->monitors->len; i++) { GdkX11Monitor *monitor = x11_display->monitors->pdata[i]; if (monitor->remove) gdk_display_monitor_removed (display, GDK_MONITOR (monitor)); } g_ptr_array_remove_range (x11_display->monitors, 0, x11_display->monitors->len); return FALSE; } for (i = x11_display->monitors->len - 1; i >= 0; i--) { GdkX11Monitor *monitor = x11_display->monitors->pdata[i]; if (monitor->add) { gdk_display_monitor_added (display, GDK_MONITOR (monitor)); *changed = TRUE; } else if (monitor->remove) { g_object_ref (monitor); g_ptr_array_remove (x11_display->monitors, monitor); gdk_display_monitor_removed (display, GDK_MONITOR (monitor)); g_object_unref (monitor); *changed = TRUE; } } old_primary = x11_display->primary_monitor; x11_display->primary_monitor = 0; for (i = 0; i < x11_display->monitors->len; ++i) { GdkX11Monitor *monitor = x11_display->monitors->pdata[i]; if (monitor->output == primary_output) { x11_display->primary_monitor = i; break; } /* No RandR1.3+ available or no primary set, fall back to prefer LVDS as primary if present */ if (primary_output == None && g_ascii_strncasecmp (gdk_monitor_get_model (GDK_MONITOR (monitor)), "LVDS", 4) == 0) { x11_display->primary_monitor = i; break; } /* No primary specified and no LVDS found */ if (monitor->output == first_output) x11_display->primary_monitor = i; } if (x11_display->primary_monitor != old_primary) *changed = TRUE; return x11_display->monitors->len > 0; #endif return FALSE; }
gboolean _gdk_x11_window_simulate_key (GdkWindow *window, gint x, gint y, guint keyval, GdkModifierType modifiers, GdkEventType key_pressrelease) { GdkScreen *screen; GdkKeymapKey *keys = NULL; gboolean success; gint n_keys = 0; XKeyEvent xev = { 0, /* type */ 0, /* serial */ 1, /* send_event */ }; g_return_val_if_fail (key_pressrelease == GDK_KEY_PRESS || key_pressrelease == GDK_KEY_RELEASE, FALSE); g_return_val_if_fail (window != NULL, FALSE); if (!GDK_WINDOW_IS_MAPPED (window)) return FALSE; screen = gdk_window_get_screen (window); if (x < 0 && y < 0) { x = window->width / 2; y = window->height / 2; } /* Convert to impl coordinates */ x = x + window->abs_x; y = y + window->abs_y; xev.type = key_pressrelease == GDK_KEY_PRESS ? KeyPress : KeyRelease; xev.display = GDK_WINDOW_XDISPLAY (window); xev.window = GDK_WINDOW_XID (window); xev.root = RootWindow (xev.display, GDK_X11_SCREEN (screen)->screen_num); xev.subwindow = 0; xev.time = 0; xev.x = MAX (x, 0); xev.y = MAX (y, 0); xev.x_root = 0; xev.y_root = 0; xev.state = modifiers; xev.keycode = 0; success = gdk_keymap_get_entries_for_keyval (gdk_keymap_get_for_display (gdk_window_get_display (window)), keyval, &keys, &n_keys); success &= n_keys > 0; if (success) { gint i; for (i = 0; i < n_keys; i++) if (keys[i].group == 0 && (keys[i].level == 0 || keys[i].level == 1)) { xev.keycode = keys[i].keycode; if (keys[i].level == 1) { /* Assume shift takes us to level 1 */ xev.state |= GDK_SHIFT_MASK; } break; } if (i >= n_keys) /* no match for group==0 and level==0 or 1 */ xev.keycode = keys[0].keycode; } g_free (keys); if (!success) return FALSE; gdk_x11_display_error_trap_push (GDK_WINDOW_DISPLAY (window)); xev.same_screen = XTranslateCoordinates (xev.display, xev.window, xev.root, xev.x, xev.y, &xev.x_root, &xev.y_root, &xev.subwindow); if (!xev.subwindow) xev.subwindow = xev.window; success &= xev.same_screen; if (x >= 0 && y >= 0) success &= 0 != XWarpPointer (xev.display, None, xev.window, 0, 0, 0, 0, xev.x, xev.y); success &= 0 != XSendEvent (xev.display, xev.window, True, key_pressrelease == GDK_KEY_PRESS ? KeyPressMask : KeyReleaseMask, (XEvent*) &xev); XSync (xev.display, False); success &= 0 == gdk_x11_display_error_trap_pop (GDK_WINDOW_DISPLAY (window)); return success; }