1 /*
2 * panel-xutils.c: X related utility methods.
3 *
4 * Copyright (C) 2003 Sun Microsystems, Inc.
5 * Copyright (C) 2012-2021 MATE Developers
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of the
10 * License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301, USA.
21 *
22 * Authors:
23 * Mark McLoughlin <mark@skynet.ie>
24 */
25
26 #include <config.h>
27
28 #ifndef HAVE_X11
29 #error file should only be built when HAVE_X11 is enabled
30 #endif
31
32 #include "panel-xutils.h"
33
34 #include <glib.h>
35 #include <gdk/gdk.h>
36 #include <gdk/gdkx.h>
37 #include <X11/Xlib.h>
38 #include <X11/Xatom.h>
39
40 static Atom net_wm_strut = None;
41 static Atom net_wm_strut_partial = None;
42
43 enum {
44 STRUT_LEFT = 0,
45 STRUT_RIGHT = 1,
46 STRUT_TOP = 2,
47 STRUT_BOTTOM = 3,
48 STRUT_LEFT_START = 4,
49 STRUT_LEFT_END = 5,
50 STRUT_RIGHT_START = 6,
51 STRUT_RIGHT_END = 7,
52 STRUT_TOP_START = 8,
53 STRUT_TOP_END = 9,
54 STRUT_BOTTOM_START = 10,
55 STRUT_BOTTOM_END = 11
56 };
57
58 void
panel_xutils_set_strut(GdkWindow * gdk_window,PanelOrientation orientation,guint32 strut,guint32 strut_start,guint32 strut_end)59 panel_xutils_set_strut (GdkWindow *gdk_window,
60 PanelOrientation orientation,
61 guint32 strut,
62 guint32 strut_start,
63 guint32 strut_end)
64 {
65 Display *xdisplay;
66 Window window;
67 gulong struts [12] = { 0, };
68 GdkDisplay *display;
69
70 g_return_if_fail (GDK_IS_WINDOW (gdk_window));
71 g_return_if_fail (GDK_IS_X11_DISPLAY (gdk_window_get_display (gdk_window)));
72
73 xdisplay = GDK_WINDOW_XDISPLAY (gdk_window);
74 window = GDK_WINDOW_XID (gdk_window);
75
76 if (net_wm_strut == None)
77 net_wm_strut = XInternAtom (xdisplay, "_NET_WM_STRUT", False);
78 if (net_wm_strut_partial == None)
79 net_wm_strut_partial = XInternAtom (xdisplay, "_NET_WM_STRUT_PARTIAL", False);
80
81 switch (orientation) {
82 case PANEL_ORIENTATION_LEFT:
83 struts [STRUT_LEFT] = strut;
84 struts [STRUT_LEFT_START] = strut_start;
85 struts [STRUT_LEFT_END] = strut_end;
86 break;
87 case PANEL_ORIENTATION_RIGHT:
88 struts [STRUT_RIGHT] = strut;
89 struts [STRUT_RIGHT_START] = strut_start;
90 struts [STRUT_RIGHT_END] = strut_end;
91 break;
92 case PANEL_ORIENTATION_TOP:
93 struts [STRUT_TOP] = strut;
94 struts [STRUT_TOP_START] = strut_start;
95 struts [STRUT_TOP_END] = strut_end;
96 break;
97 case PANEL_ORIENTATION_BOTTOM:
98 struts [STRUT_BOTTOM] = strut;
99 struts [STRUT_BOTTOM_START] = strut_start;
100 struts [STRUT_BOTTOM_END] = strut_end;
101 break;
102 }
103
104 display = gdk_window_get_display (gdk_window);
105 gdk_x11_display_error_trap_push (display);
106 XChangeProperty (xdisplay, window, net_wm_strut,
107 XA_CARDINAL, 32, PropModeReplace,
108 (guchar *) &struts, 4);
109 XChangeProperty (xdisplay, window, net_wm_strut_partial,
110 XA_CARDINAL, 32, PropModeReplace,
111 (guchar *) &struts, 12);
112 gdk_x11_display_error_trap_pop_ignored (display);
113 }
114
115 void
panel_xutils_unset_strut(GdkWindow * gdk_window)116 panel_xutils_unset_strut (GdkWindow *gdk_window)
117 {
118 GdkDisplay *display;
119 Display *xdisplay;
120 Window xwindow;
121
122 display = gdk_window_get_display (gdk_window);
123 xdisplay = gdk_x11_display_get_xdisplay (display);
124 xwindow = gdk_x11_window_get_xid (gdk_window);
125
126 if (net_wm_strut == None)
127 net_wm_strut = XInternAtom (xdisplay, "_NET_WM_STRUT", False);
128 if (net_wm_strut_partial == None)
129 net_wm_strut_partial = XInternAtom (xdisplay, "_NET_WM_STRUT_PARTIAL", False);
130
131 gdk_x11_display_error_trap_push (display);
132
133 XDeleteProperty (xdisplay, xwindow, net_wm_strut);
134 XDeleteProperty (xdisplay, xwindow, net_wm_strut_partial);
135
136 gdk_x11_display_error_trap_pop_ignored (display);
137 }
138
139 void
panel_warp_pointer(GdkWindow * gdk_window,int x,int y)140 panel_warp_pointer (GdkWindow *gdk_window,
141 int x,
142 int y)
143 {
144 Display *xdisplay;
145 Window window;
146 GdkDisplay *display;
147
148 g_return_if_fail (GDK_IS_WINDOW (gdk_window));
149 g_return_if_fail (GDK_IS_X11_DISPLAY (gdk_window_get_display (gdk_window)));
150
151 xdisplay = GDK_WINDOW_XDISPLAY (gdk_window);
152 window = GDK_WINDOW_XID (gdk_window);
153
154 display = gdk_window_get_display (gdk_window);
155 gdk_x11_display_error_trap_push (display);
156 XWarpPointer (xdisplay, None, window, 0, 0, 0, 0, x, y);
157 gdk_x11_display_error_trap_pop_ignored (display);
158 }
159
160 guint
panel_get_real_modifier_mask(guint mask)161 panel_get_real_modifier_mask (guint mask)
162 {
163 guint real_mask;
164 Display *display;
165 int i, min_keycode, max_keycode, keysyms_per_keycode;
166 int max_keycodes_per_modifier;
167 KeySym *keysyms_for_keycodes;
168 XModifierKeymap *modifier_keymap;
169
170 real_mask = mask & ((Mod5Mask << 1) - 1);
171
172 /* Already real */
173 if (mask == real_mask) {
174 return mask;
175 }
176
177 g_return_val_if_fail (GDK_IS_X11_DISPLAY (gdk_display_get_default ()), mask);
178 display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
179
180 XDisplayKeycodes (display, &min_keycode, &max_keycode);
181 keysyms_for_keycodes = XGetKeyboardMapping (display,
182 min_keycode,
183 max_keycode - min_keycode + 1,
184 &keysyms_per_keycode);
185
186 modifier_keymap = XGetModifierMapping (display);
187 max_keycodes_per_modifier = modifier_keymap->max_keypermod;
188
189 /* Loop through all the modifiers and find out which "real"
190 * (Mod2..Mod5) modifiers Super, Hyper, and Meta are mapped to.
191 * Note, Mod1 is used by the Alt modifier */
192 for (i = Mod2MapIndex * max_keycodes_per_modifier;
193 i < (Mod5MapIndex + 1) * max_keycodes_per_modifier;
194 i++) {
195 int keycode;
196 int j;
197 KeySym *keysyms_for_keycode;
198 int map_index;
199 int map_mask;
200
201 keycode = modifier_keymap->modifiermap[i];
202
203 /* The array is sparse, there may be some
204 * empty entries. Filter those out
205 * (along with any invalid entries) */
206 if (keycode < min_keycode || keycode > max_keycode)
207 continue;
208
209 keysyms_for_keycode = keysyms_for_keycodes +
210 (keycode - min_keycode) * keysyms_per_keycode;
211
212 map_index = i / max_keycodes_per_modifier;
213
214 g_assert (map_index <= Mod5MapIndex);
215
216 map_mask = 1 << map_index;
217
218 for (j = 0; j < keysyms_per_keycode; j++) {
219 switch (keysyms_for_keycode[j]) {
220 case XK_Super_L:
221 case XK_Super_R:
222 if (mask & GDK_SUPER_MASK)
223 real_mask |= map_mask;
224 break;
225 case XK_Hyper_L:
226 case XK_Hyper_R:
227 if (mask & GDK_HYPER_MASK)
228 real_mask |= map_mask;
229 break;
230 case XK_Meta_L:
231 case XK_Meta_R:
232 if (mask & GDK_META_MASK)
233 real_mask |= map_mask;
234 break;
235 default:
236 break;
237 }
238 }
239 }
240
241 XFreeModifiermap (modifier_keymap);
242 XFree (keysyms_for_keycodes);
243
244 return real_mask;
245 }
246