/[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 1139 - (show annotations)
Wed Mar 15 15:16:18 2006 UTC (18 years, 3 months ago) by astrand
File MIME type: text/plain
File size: 10114 byte(s)
Set _NET_WM_NAME

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 hidden atom
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_MINIMIZED)
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_hidden_atom;
253 xevent.xclient.data.l[2] = 0;
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
262 /*
263 * Deal with the max atoms
264 */
265 xevent.type = ClientMessage;
266 xevent.xclient.window = wnd;
267 xevent.xclient.message_type = g_net_wm_state_atom;
268 xevent.xclient.format = 32;
269 if (state == SEAMLESSRDP_MAXIMIZED)
270 xevent.xclient.data.l[0] = _NET_WM_STATE_ADD;
271 else
272 xevent.xclient.data.l[0] = _NET_WM_STATE_REMOVE;
273 xevent.xclient.data.l[1] = g_net_wm_state_maximized_vert_atom;
274 xevent.xclient.data.l[2] = g_net_wm_state_maximized_horz_atom;
275 xevent.xclient.data.l[3] = 0;
276 xevent.xclient.data.l[4] = 0;
277 status = XSendEvent(g_display, DefaultRootWindow(g_display), False,
278 SubstructureNotifyMask | SubstructureRedirectMask, &xevent);
279 if (!status)
280 return -1;
281
282 return 0;
283 }
284
285
286 int
287 ewmh_get_window_desktop(Window wnd)
288 {
289 unsigned long nitems_return;
290 unsigned char *prop_return;
291 int desktop;
292
293 if (get_property_value(wnd, "_NET_WM_DESKTOP", 1, &nitems_return, &prop_return) < 0)
294 return (-1);
295
296 if (nitems_return != 1)
297 {
298 fprintf(stderr, "_NET_WM_DESKTOP has bad length\n");
299 return (-1);
300 }
301
302 desktop = *prop_return;
303 XFree(prop_return);
304 return desktop;
305 }
306
307
308 int
309 ewmh_move_to_desktop(Window wnd, unsigned int desktop)
310 {
311 Status status;
312 XEvent xevent;
313
314 xevent.type = ClientMessage;
315 xevent.xclient.window = wnd;
316 xevent.xclient.message_type = g_net_wm_desktop_atom;
317 xevent.xclient.format = 32;
318 xevent.xclient.data.l[0] = desktop;
319 xevent.xclient.data.l[1] = 0;
320 xevent.xclient.data.l[2] = 0;
321 xevent.xclient.data.l[3] = 0;
322 xevent.xclient.data.l[4] = 0;
323 status = XSendEvent(g_display, DefaultRootWindow(g_display), False,
324 SubstructureNotifyMask | SubstructureRedirectMask, &xevent);
325 if (!status)
326 return -1;
327
328 return 0;
329 }
330
331 void
332 ewmh_set_wm_name(Window wnd, const char *title)
333 {
334 int len;
335
336 len = strlen(title);
337 XChangeProperty(g_display, wnd, g_net_wm_name_atom, g_utf8_string_atom,
338 8, PropModeReplace, (unsigned char *) title, len);
339 }
340
341
342 void
343 ewmh_set_window_popup(Window wnd)
344 {
345 Atom atoms[2] = { g_net_wm_state_skip_taskbar_atom, g_net_wm_state_skip_pager_atom };
346
347 XChangeProperty(g_display, wnd, g_net_wm_state_atom, XA_ATOM, 32, PropModeAppend, atoms, 2);
348 }
349
350 #endif /* MAKE_PROTO */
351
352
353 #if 0
354
355 /* FIXME: _NET_MOVERESIZE_WINDOW is for pagers, not for
356 applications. We should implement _NET_WM_MOVERESIZE instead */
357
358 int
359 ewmh_net_moveresize_window(Window wnd, int x, int y, int width, int height)
360 {
361 Status status;
362 XEvent xevent;
363 Atom moveresize;
364
365 moveresize = XInternAtom(g_display, "_NET_MOVERESIZE_WINDOW", False);
366 if (!moveresize)
367 {
368 return -1;
369 }
370
371 xevent.type = ClientMessage;
372 xevent.xclient.window = wnd;
373 xevent.xclient.message_type = moveresize;
374 xevent.xclient.format = 32;
375 xevent.xclient.data.l[0] = StaticGravity | (1 << 8) | (1 << 9) | (1 << 10) | (1 << 11);
376 xevent.xclient.data.l[1] = x;
377 xevent.xclient.data.l[2] = y;
378 xevent.xclient.data.l[3] = width;
379 xevent.xclient.data.l[4] = height;
380
381 status = XSendEvent(g_display, DefaultRootWindow(g_display), False,
382 SubstructureNotifyMask | SubstructureRedirectMask, &xevent);
383 if (!status)
384 return -1;
385 return 0;
386 }
387
388 #endif

  ViewVC Help
Powered by ViewVC 1.1.26