/* * panel-xutils.c: X related utility methods. * * Copyright (C) 2003 Sun Microsystems, Inc. * Copyright (C) 2012-2021 MATE Developers * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301, USA. * * Authors: * Mark McLoughlin */ #include #ifndef HAVE_X11 #error file should only be built when HAVE_X11 is enabled #endif #include "panel-xutils.h" #include #include #include #include #include static Atom net_wm_strut = None; static Atom net_wm_strut_partial = None; static Atom gnome_wm_strut_area = None; enum { STRUT_LEFT = 0, STRUT_RIGHT = 1, STRUT_TOP = 2, STRUT_BOTTOM = 3, STRUT_LEFT_START = 4, STRUT_LEFT_END = 5, STRUT_RIGHT_START = 6, STRUT_RIGHT_END = 7, STRUT_TOP_START = 8, STRUT_TOP_END = 9, STRUT_BOTTOM_START = 10, STRUT_BOTTOM_END = 11 }; enum { STRUT_AREA_X = 0, STRUT_AREA_Y, STRUT_AREA_WIDTH, STRUT_AREA_HEIGHT, STRUT_AREA_LAST }; void panel_xutils_set_strut (GdkWindow *gdk_window, PanelOrientation orientation, guint32 strut, guint32 strut_start, guint32 strut_end, GdkRectangle *rect, int scale) { Display *xdisplay; Window window; gulong struts [12] = { 0, }; gulong area [STRUT_AREA_LAST]; GdkDisplay *display; g_return_if_fail (GDK_IS_WINDOW (gdk_window)); g_return_if_fail (GDK_IS_X11_DISPLAY (gdk_window_get_display (gdk_window))); xdisplay = GDK_WINDOW_XDISPLAY (gdk_window); window = GDK_WINDOW_XID (gdk_window); if (net_wm_strut == None) net_wm_strut = XInternAtom (xdisplay, "_NET_WM_STRUT", False); if (net_wm_strut_partial == None) net_wm_strut_partial = XInternAtom (xdisplay, "_NET_WM_STRUT_PARTIAL", False); if (gnome_wm_strut_area == None) gnome_wm_strut_area = XInternAtom (xdisplay, "_GNOME_WM_STRUT_AREA", False); strut *= scale; strut_start *= scale; strut_end *= scale; switch (orientation) { case PANEL_ORIENTATION_LEFT: struts [STRUT_LEFT] = strut; struts [STRUT_LEFT_START] = strut_start; struts [STRUT_LEFT_END] = strut_end; break; case PANEL_ORIENTATION_RIGHT: struts [STRUT_RIGHT] = strut; struts [STRUT_RIGHT_START] = strut_start; struts [STRUT_RIGHT_END] = strut_end; break; case PANEL_ORIENTATION_TOP: struts [STRUT_TOP] = strut; struts [STRUT_TOP_START] = strut_start; struts [STRUT_TOP_END] = strut_end; break; case PANEL_ORIENTATION_BOTTOM: struts [STRUT_BOTTOM] = strut; struts [STRUT_BOTTOM_START] = strut_start; struts [STRUT_BOTTOM_END] = strut_end; break; } area [STRUT_AREA_X] = rect->x * scale; area [STRUT_AREA_Y] = rect->y * scale; area [STRUT_AREA_WIDTH] = rect->width * scale; area [STRUT_AREA_HEIGHT] = rect->height * scale; display = gdk_window_get_display (gdk_window); gdk_x11_display_error_trap_push (display); XChangeProperty (xdisplay, window, net_wm_strut, XA_CARDINAL, 32, PropModeReplace, (guchar *) &struts, 4); XChangeProperty (xdisplay, window, net_wm_strut_partial, XA_CARDINAL, 32, PropModeReplace, (guchar *) &struts, 12); XChangeProperty (xdisplay, window, gnome_wm_strut_area, XA_CARDINAL, 32, PropModeReplace, (guchar *) &area, 4); gdk_x11_display_error_trap_pop_ignored (display); } void panel_xutils_unset_strut (GdkWindow *gdk_window) { GdkDisplay *display; Display *xdisplay; Window xwindow; display = gdk_window_get_display (gdk_window); xdisplay = gdk_x11_display_get_xdisplay (display); xwindow = gdk_x11_window_get_xid (gdk_window); if (net_wm_strut == None) net_wm_strut = XInternAtom (xdisplay, "_NET_WM_STRUT", False); if (net_wm_strut_partial == None) net_wm_strut_partial = XInternAtom (xdisplay, "_NET_WM_STRUT_PARTIAL", False); if (gnome_wm_strut_area == None) gnome_wm_strut_area = XInternAtom (xdisplay, "_GNOME_WM_STRUT_AREA", False); gdk_x11_display_error_trap_push (display); XDeleteProperty (xdisplay, xwindow, net_wm_strut); XDeleteProperty (xdisplay, xwindow, net_wm_strut_partial); XDeleteProperty (xdisplay, xwindow, gnome_wm_strut_area); gdk_x11_display_error_trap_pop_ignored (display); } void panel_warp_pointer (GdkWindow *gdk_window, int x, int y) { Display *xdisplay; Window window; GdkDisplay *display; g_return_if_fail (GDK_IS_WINDOW (gdk_window)); g_return_if_fail (GDK_IS_X11_DISPLAY (gdk_window_get_display (gdk_window))); xdisplay = GDK_WINDOW_XDISPLAY (gdk_window); window = GDK_WINDOW_XID (gdk_window); display = gdk_window_get_display (gdk_window); gdk_x11_display_error_trap_push (display); XWarpPointer (xdisplay, None, window, 0, 0, 0, 0, x, y); gdk_x11_display_error_trap_pop_ignored (display); } guint panel_get_real_modifier_mask (guint mask) { guint real_mask; Display *display; int i, min_keycode, max_keycode, keysyms_per_keycode; int max_keycodes_per_modifier; KeySym *keysyms_for_keycodes; XModifierKeymap *modifier_keymap; real_mask = mask & ((Mod5Mask << 1) - 1); /* Already real */ if (mask == real_mask) { return mask; } g_return_val_if_fail (GDK_IS_X11_DISPLAY (gdk_display_get_default ()), mask); display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); XDisplayKeycodes (display, &min_keycode, &max_keycode); keysyms_for_keycodes = XGetKeyboardMapping (display, min_keycode, max_keycode - min_keycode + 1, &keysyms_per_keycode); modifier_keymap = XGetModifierMapping (display); max_keycodes_per_modifier = modifier_keymap->max_keypermod; /* Loop through all the modifiers and find out which "real" * (Mod2..Mod5) modifiers Super, Hyper, and Meta are mapped to. * Note, Mod1 is used by the Alt modifier */ for (i = Mod2MapIndex * max_keycodes_per_modifier; i < (Mod5MapIndex + 1) * max_keycodes_per_modifier; i++) { int keycode; int j; KeySym *keysyms_for_keycode; int map_index; int map_mask; keycode = modifier_keymap->modifiermap[i]; /* The array is sparse, there may be some * empty entries. Filter those out * (along with any invalid entries) */ if (keycode < min_keycode || keycode > max_keycode) continue; keysyms_for_keycode = keysyms_for_keycodes + (keycode - min_keycode) * keysyms_per_keycode; map_index = i / max_keycodes_per_modifier; g_assert (map_index <= Mod5MapIndex); map_mask = 1 << map_index; for (j = 0; j < keysyms_per_keycode; j++) { switch (keysyms_for_keycode[j]) { case XK_Super_L: case XK_Super_R: if (mask & GDK_SUPER_MASK) real_mask |= map_mask; break; case XK_Hyper_L: case XK_Hyper_R: if (mask & GDK_HYPER_MASK) real_mask |= map_mask; break; case XK_Meta_L: case XK_Meta_R: if (mask & GDK_META_MASK) real_mask |= map_mask; break; default: break; } } } XFreeModifiermap (modifier_keymap); XFree (keysyms_for_keycodes); return real_mask; }