/[rdesktop]/sourceforge.net/branches/seamlessrdp-branch/rdesktop/ewmhints.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /sourceforge.net/branches/seamlessrdp-branch/rdesktop/ewmhints.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1141 - (show annotations)
Thu Mar 16 08:09:41 2006 UTC (18 years, 3 months ago) by ossman_
File MIME type: text/plain
File size: 9477 byte(s)
Spec says that the wm doesn't have to respect requests to change
_NET_WM_STATE_HIDDEN, so we shouldn't rely on it.

1 /* -*- c-basic-offset: 8 -*-
2 rdesktop: A Remote Desktop Protocol client.
3
4 Support functions for Extended Window Manager Hints,
5 http://www.freedesktop.org/wiki/Standards_2fwm_2dspec
6
7 Copyright (C) Peter Astrand <astrand@cendio.se> 2005
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 #include <X11/Xlib.h>
25 #include <X11/Xatom.h>
26 #include "rdesktop.h"
27
28 #define _NET_WM_STATE_REMOVE 0 /* remove/unset property */
29 #define _NET_WM_STATE_ADD 1 /* add/set property */
30 #define _NET_WM_STATE_TOGGLE 2 /* toggle property */
31
32 extern Display *g_display;
33
34 static Atom g_net_wm_state_maximized_vert_atom, g_net_wm_state_maximized_horz_atom,
35 g_net_wm_state_hidden_atom, g_net_wm_name_atom, g_utf8_string_atom,
36 g_net_wm_state_skip_taskbar_atom, g_net_wm_state_skip_pager_atom;
37
38 Atom g_net_wm_state_atom, g_net_wm_desktop_atom;
39
40 /*
41 Get window property value (32 bit format)
42 Returns zero on success, -1 on error
43 */
44 static int
45 get_property_value(Window wnd, char *propname, long max_length,
46 unsigned long *nitems_return, unsigned char **prop_return)
47 {
48 int result;
49 Atom property;
50 Atom actual_type_return;
51 int actual_format_return;
52 unsigned long bytes_after_return;
53
54 property = XInternAtom(g_display, propname, True);
55 if (property == None)
56 {
57 fprintf(stderr, "Atom %s does not exist\n", propname);
58 return (-1);
59 }
60
61 result = XGetWindowProperty(g_display, wnd, property, 0, /* long_offset */
62 max_length, /* long_length */
63 False, /* delete */
64 AnyPropertyType, /* req_type */
65 &actual_type_return,
66 &actual_format_return,
67 nitems_return, &bytes_after_return, prop_return);
68
69 if (result != Success)
70 {
71 fprintf(stderr, "XGetWindowProperty failed\n");
72 return (-1);
73 }
74
75 if (actual_type_return == None || actual_format_return == 0)
76 {
77 fprintf(stderr, "Window is missing property %s\n", propname);
78 return (-1);
79 }
80
81 if (bytes_after_return)
82 {
83 fprintf(stderr, "%s is too big for me\n", propname);
84 return (-1);
85 }
86
87 if (actual_format_return != 32)
88 {
89 fprintf(stderr, "%s has bad format\n", propname);
90 return (-1);
91 }
92
93 return (0);
94 }
95
96 /*
97 Get current desktop number
98 Returns -1 on error
99 */
100 static int
101 get_current_desktop(void)
102 {
103 unsigned long nitems_return;
104 unsigned char *prop_return;
105 int current_desktop;
106
107 if (get_property_value
108 (DefaultRootWindow(g_display), "_NET_CURRENT_DESKTOP", 1, &nitems_return,
109 &prop_return) < 0)
110 return (-1);
111
112 if (nitems_return != 1)
113 {
114 fprintf(stderr, "_NET_CURRENT_DESKTOP has bad length\n");
115 return (-1);
116 }
117
118 current_desktop = *prop_return;
119 XFree(prop_return);
120 return current_desktop;
121 }
122
123 /*
124 Get workarea geometry
125 Returns zero on success, -1 on error
126 */
127
128 int
129 get_current_workarea(uint32 * x, uint32 * y, uint32 * width, uint32 * height)
130 {
131 int current_desktop;
132 unsigned long nitems_return;
133 unsigned char *prop_return;
134 uint32 *return_words;
135 const uint32 net_workarea_x_offset = 0;
136 const uint32 net_workarea_y_offset = 1;
137 const uint32 net_workarea_width_offset = 2;
138 const uint32 net_workarea_height_offset = 3;
139 const uint32 max_prop_length = 32 * 4; /* Max 32 desktops */
140
141 if (get_property_value
142 (DefaultRootWindow(g_display), "_NET_WORKAREA", max_prop_length, &nitems_return,
143 &prop_return) < 0)
144 return (-1);
145
146 if (nitems_return % 4)
147 {
148 fprintf(stderr, "_NET_WORKAREA has odd length\n");
149 return (-1);
150 }
151
152 current_desktop = get_current_desktop();
153
154 if (current_desktop < 0)
155 return -1;
156
157 return_words = (uint32 *) prop_return;
158
159 *x = return_words[current_desktop * 4 + net_workarea_x_offset];
160 *y = return_words[current_desktop * 4 + net_workarea_y_offset];
161 *width = return_words[current_desktop * 4 + net_workarea_width_offset];
162 *height = return_words[current_desktop * 4 + net_workarea_height_offset];
163
164 XFree(prop_return);
165
166 return (0);
167
168 }
169
170
171
172 void
173 ewmh_init()
174 {
175 /* FIXME: Use XInternAtoms */
176 g_net_wm_state_maximized_vert_atom =
177 XInternAtom(g_display, "_NET_WM_STATE_MAXIMIZED_VERT", False);
178 g_net_wm_state_maximized_horz_atom =
179 XInternAtom(g_display, "_NET_WM_STATE_MAXIMIZED_HORZ", False);
180 g_net_wm_state_hidden_atom = XInternAtom(g_display, "_NET_WM_STATE_HIDDEN", False);
181 g_net_wm_state_skip_taskbar_atom =
182 XInternAtom(g_display, "_NET_WM_STATE_SKIP_TASKBAR", False);
183 g_net_wm_state_skip_pager_atom = XInternAtom(g_display, "_NET_WM_STATE_SKIP_PAGER", False);
184 g_net_wm_state_atom = XInternAtom(g_display, "_NET_WM_STATE", False);
185 g_net_wm_desktop_atom = XInternAtom(g_display, "_NET_WM_DESKTOP", False);
186 g_net_wm_name_atom = XInternAtom(g_display, "_NET_WM_NAME", False);
187 g_utf8_string_atom = XInternAtom(g_display, "UTF8_STRING", False);
188 }
189
190
191 /*
192 Get the window state: normal/minimized/maximized.
193 */
194 #ifndef MAKE_PROTO
195 int
196 ewmh_get_window_state(Window w)
197 {
198 unsigned long nitems_return;
199 unsigned char *prop_return;
200 uint32 *return_words;
201 unsigned long item;
202 BOOL maximized_vert, maximized_horz, hidden;
203
204 maximized_vert = maximized_horz = hidden = False;
205
206 if (get_property_value(w, "_NET_WM_STATE", 64, &nitems_return, &prop_return) < 0)
207 return SEAMLESSRDP_NORMAL;
208
209 return_words = (uint32 *) prop_return;
210
211 for (item = 0; item < nitems_return; item++)
212 {
213 if (return_words[item] == g_net_wm_state_maximized_vert_atom)
214 maximized_vert = True;
215 if (return_words[item] == g_net_wm_state_maximized_horz_atom)
216 maximized_horz = True;
217 if (return_words[item] == g_net_wm_state_hidden_atom)
218 hidden = True;
219 }
220
221 XFree(prop_return);
222
223 if (maximized_vert && maximized_horz)
224 return SEAMLESSRDP_MAXIMIZED;
225 else if (hidden)
226 return SEAMLESSRDP_MINIMIZED;
227 else
228 return SEAMLESSRDP_NORMAL;
229 }
230
231 /*
232 Set the window state: normal/minimized/maximized.
233 Returns -1 on failure.
234 */
235 int
236 ewmh_change_state(Window wnd, int state)
237 {
238 Status status;
239 XEvent xevent;
240
241 /*
242 * Deal with the max atoms
243 */
244 xevent.type = ClientMessage;
245 xevent.xclient.window = wnd;
246 xevent.xclient.message_type = g_net_wm_state_atom;
247 xevent.xclient.format = 32;
248 if (state == SEAMLESSRDP_MAXIMIZED)
249 xevent.xclient.data.l[0] = _NET_WM_STATE_ADD;
250 else
251 xevent.xclient.data.l[0] = _NET_WM_STATE_REMOVE;
252 xevent.xclient.data.l[1] = g_net_wm_state_maximized_vert_atom;
253 xevent.xclient.data.l[2] = g_net_wm_state_maximized_horz_atom;
254 xevent.xclient.data.l[3] = 0;
255 xevent.xclient.data.l[4] = 0;
256 status = XSendEvent(g_display, DefaultRootWindow(g_display), False,
257 SubstructureNotifyMask | SubstructureRedirectMask, &xevent);
258 if (!status)
259 return -1;
260
261 return 0;
262 }
263
264
265 int
266 ewmh_get_window_desktop(Window wnd)
267 {
268 unsigned long nitems_return;
269 unsigned char *prop_return;
270 int desktop;
271
272 if (get_property_value(wnd, "_NET_WM_DESKTOP", 1, &nitems_return, &prop_return) < 0)
273 return (-1);
274
275 if (nitems_return != 1)
276 {
277 fprintf(stderr, "_NET_WM_DESKTOP has bad length\n");
278 return (-1);
279 }
280
281 desktop = *prop_return;
282 XFree(prop_return);
283 return desktop;
284 }
285
286
287 int
288 ewmh_move_to_desktop(Window wnd, unsigned int desktop)
289 {
290 Status status;
291 XEvent xevent;
292
293 xevent.type = ClientMessage;
294 xevent.xclient.window = wnd;
295 xevent.xclient.message_type = g_net_wm_desktop_atom;
296 xevent.xclient.format = 32;
297 xevent.xclient.data.l[0] = desktop;
298 xevent.xclient.data.l[1] = 0;
299 xevent.xclient.data.l[2] = 0;
300 xevent.xclient.data.l[3] = 0;
301 xevent.xclient.data.l[4] = 0;
302 status = XSendEvent(g_display, DefaultRootWindow(g_display), False,
303 SubstructureNotifyMask | SubstructureRedirectMask, &xevent);
304 if (!status)
305 return -1;
306
307 return 0;
308 }
309
310 void
311 ewmh_set_wm_name(Window wnd, const char *title)
312 {
313 int len;
314
315 len = strlen(title);
316 XChangeProperty(g_display, wnd, g_net_wm_name_atom, g_utf8_string_atom,
317 8, PropModeReplace, (unsigned char *) title, len);
318 }
319
320
321 void
322 ewmh_set_window_popup(Window wnd)
323 {
324 Atom atoms[2] = { g_net_wm_state_skip_taskbar_atom, g_net_wm_state_skip_pager_atom };
325
326 XChangeProperty(g_display, wnd, g_net_wm_state_atom, XA_ATOM, 32, PropModeAppend, atoms, 2);
327 }
328
329 #endif /* MAKE_PROTO */
330
331
332 #if 0
333
334 /* FIXME: _NET_MOVERESIZE_WINDOW is for pagers, not for
335 applications. We should implement _NET_WM_MOVERESIZE instead */
336
337 int
338 ewmh_net_moveresize_window(Window wnd, int x, int y, int width, int height)
339 {
340 Status status;
341 XEvent xevent;
342 Atom moveresize;
343
344 moveresize = XInternAtom(g_display, "_NET_MOVERESIZE_WINDOW", False);
345 if (!moveresize)
346 {
347 return -1;
348 }
349
350 xevent.type = ClientMessage;
351 xevent.xclient.window = wnd;
352 xevent.xclient.message_type = moveresize;
353 xevent.xclient.format = 32;
354 xevent.xclient.data.l[0] = StaticGravity | (1 << 8) | (1 << 9) | (1 << 10) | (1 << 11);
355 xevent.xclient.data.l[1] = x;
356 xevent.xclient.data.l[2] = y;
357 xevent.xclient.data.l[3] = width;
358 xevent.xclient.data.l[4] = height;
359
360 status = XSendEvent(g_display, DefaultRootWindow(g_display), False,
361 SubstructureNotifyMask | SubstructureRedirectMask, &xevent);
362 if (!status)
363 return -1;
364 return 0;
365 }
366
367 #endif

  ViewVC Help
Powered by ViewVC 1.1.26