/[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 1143 - (show annotations)
Thu Mar 16 08:41:53 2006 UTC (18 years, 1 month ago) by ossman_
File MIME type: text/plain
File size: 10267 byte(s)
Set _NET_WM_STATE atoms via the window manager (as required by the spec.).
Unfortunately, this means we have to wait for the window to leave the
withdrawn state.

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 static int
232 ewmh_add_state(Window wnd, Atom atom1, Atom atom2)
233 {
234 Status status;
235 XEvent xevent;
236
237 xevent.type = ClientMessage;
238 xevent.xclient.window = wnd;
239 xevent.xclient.message_type = g_net_wm_state_atom;
240 xevent.xclient.format = 32;
241 xevent.xclient.data.l[0] = _NET_WM_STATE_ADD;
242 xevent.xclient.data.l[1] = atom1;
243 xevent.xclient.data.l[2] = atom2;
244 xevent.xclient.data.l[3] = 0;
245 xevent.xclient.data.l[4] = 0;
246 status = XSendEvent(g_display, DefaultRootWindow(g_display), False,
247 SubstructureNotifyMask | SubstructureRedirectMask, &xevent);
248 if (!status)
249 return -1;
250
251 return 0;
252 }
253
254 static int
255 ewmh_remove_state(Window wnd, Atom atom1, Atom atom2)
256 {
257 Status status;
258 XEvent xevent;
259
260 xevent.type = ClientMessage;
261 xevent.xclient.window = wnd;
262 xevent.xclient.message_type = g_net_wm_state_atom;
263 xevent.xclient.format = 32;
264 xevent.xclient.data.l[0] = _NET_WM_STATE_REMOVE;
265 xevent.xclient.data.l[1] = atom1;
266 xevent.xclient.data.l[2] = atom2;
267 xevent.xclient.data.l[3] = 0;
268 xevent.xclient.data.l[4] = 0;
269 status = XSendEvent(g_display, DefaultRootWindow(g_display), False,
270 SubstructureNotifyMask | SubstructureRedirectMask, &xevent);
271 if (!status)
272 return -1;
273
274 return 0;
275 }
276
277 /*
278 Set the window state: normal/minimized/maximized.
279 Returns -1 on failure.
280 */
281 int
282 ewmh_change_state(Window wnd, int state)
283 {
284 /*
285 * Deal with the max atoms
286 */
287 if (state == SEAMLESSRDP_MAXIMIZED)
288 {
289 if (ewmh_add_state
290 (wnd, g_net_wm_state_maximized_vert_atom,
291 g_net_wm_state_maximized_horz_atom) < 0)
292 return -1;
293 }
294 else
295 {
296 if (ewmh_remove_state
297 (wnd, g_net_wm_state_maximized_vert_atom,
298 g_net_wm_state_maximized_horz_atom) < 0)
299 return -1;
300 }
301
302 return 0;
303 }
304
305
306 int
307 ewmh_get_window_desktop(Window wnd)
308 {
309 unsigned long nitems_return;
310 unsigned char *prop_return;
311 int desktop;
312
313 if (get_property_value(wnd, "_NET_WM_DESKTOP", 1, &nitems_return, &prop_return) < 0)
314 return (-1);
315
316 if (nitems_return != 1)
317 {
318 fprintf(stderr, "_NET_WM_DESKTOP has bad length\n");
319 return (-1);
320 }
321
322 desktop = *prop_return;
323 XFree(prop_return);
324 return desktop;
325 }
326
327
328 int
329 ewmh_move_to_desktop(Window wnd, unsigned int desktop)
330 {
331 Status status;
332 XEvent xevent;
333
334 xevent.type = ClientMessage;
335 xevent.xclient.window = wnd;
336 xevent.xclient.message_type = g_net_wm_desktop_atom;
337 xevent.xclient.format = 32;
338 xevent.xclient.data.l[0] = desktop;
339 xevent.xclient.data.l[1] = 0;
340 xevent.xclient.data.l[2] = 0;
341 xevent.xclient.data.l[3] = 0;
342 xevent.xclient.data.l[4] = 0;
343 status = XSendEvent(g_display, DefaultRootWindow(g_display), False,
344 SubstructureNotifyMask | SubstructureRedirectMask, &xevent);
345 if (!status)
346 return -1;
347
348 return 0;
349 }
350
351 void
352 ewmh_set_wm_name(Window wnd, const char *title)
353 {
354 int len;
355
356 len = strlen(title);
357 XChangeProperty(g_display, wnd, g_net_wm_name_atom, g_utf8_string_atom,
358 8, PropModeReplace, (unsigned char *) title, len);
359 }
360
361
362 int
363 ewmh_set_window_popup(Window wnd)
364 {
365 if (ewmh_add_state(wnd, g_net_wm_state_skip_taskbar_atom, g_net_wm_state_skip_pager_atom) <
366 0)
367 return -1;
368 return 0;
369 }
370
371 #endif /* MAKE_PROTO */
372
373
374 #if 0
375
376 /* FIXME: _NET_MOVERESIZE_WINDOW is for pagers, not for
377 applications. We should implement _NET_WM_MOVERESIZE instead */
378
379 int
380 ewmh_net_moveresize_window(Window wnd, int x, int y, int width, int height)
381 {
382 Status status;
383 XEvent xevent;
384 Atom moveresize;
385
386 moveresize = XInternAtom(g_display, "_NET_MOVERESIZE_WINDOW", False);
387 if (!moveresize)
388 {
389 return -1;
390 }
391
392 xevent.type = ClientMessage;
393 xevent.xclient.window = wnd;
394 xevent.xclient.message_type = moveresize;
395 xevent.xclient.format = 32;
396 xevent.xclient.data.l[0] = StaticGravity | (1 << 8) | (1 << 9) | (1 << 10) | (1 << 11);
397 xevent.xclient.data.l[1] = x;
398 xevent.xclient.data.l[2] = y;
399 xevent.xclient.data.l[3] = width;
400 xevent.xclient.data.l[4] = height;
401
402 status = XSendEvent(g_display, DefaultRootWindow(g_display), False,
403 SubstructureNotifyMask | SubstructureRedirectMask, &xevent);
404 if (!status)
405 return -1;
406 return 0;
407 }
408
409 #endif

  ViewVC Help
Powered by ViewVC 1.1.26