ReactOS 0.4.15-dev-7958-gcd0bb1a
ewmhints.c
Go to the documentation of this file.
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 along
20 with this program; if not, write to the Free Software Foundation, Inc.,
21 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22*/
23
24#include <X11/Xlib.h>
25#include <X11/Xatom.h>
26#include <X11/Xutil.h>
27#include "rdesktop.h"
28
29#define _NET_WM_STATE_REMOVE 0 /* remove/unset property */
30#define _NET_WM_STATE_ADD 1 /* add/set property */
31#define _NET_WM_STATE_TOGGLE 2 /* toggle property */
32
33/*
34 Get window property value (32 bit format)
35 Returns zero on success, -1 on error
36*/
37static int
38get_property_value(RDPCLIENT * This, Window wnd, char *propname, long max_length,
39 unsigned long *nitems_return, unsigned char **prop_return, int nowarn)
40{
41 int result;
43 Atom actual_type_return;
44 int actual_format_return;
45 unsigned long bytes_after_return;
46
47 property = XInternAtom(This->display, propname, True);
48 if (property == None)
49 {
50 fprintf(stderr, "Atom %s does not exist\n", propname);
51 return (-1);
52 }
53
54 result = XGetWindowProperty(This->display, wnd, property, 0, /* long_offset */
55 max_length, /* long_length */
56 False, /* delete */
57 AnyPropertyType, /* req_type */
58 &actual_type_return,
59 &actual_format_return,
60 nitems_return, &bytes_after_return, prop_return);
61
62 if (result != Success)
63 {
64 fprintf(stderr, "XGetWindowProperty failed\n");
65 return (-1);
66 }
67
68 if (actual_type_return == None || actual_format_return == 0)
69 {
70 if (!nowarn)
71 fprintf(stderr, "Window is missing property %s\n", propname);
72 return (-1);
73 }
74
75 if (bytes_after_return)
76 {
77 fprintf(stderr, "%s is too big for me\n", propname);
78 return (-1);
79 }
80
81 if (actual_format_return != 32)
82 {
83 fprintf(stderr, "%s has bad format\n", propname);
84 return (-1);
85 }
86
87 return (0);
88}
89
90/*
91 Get current desktop number
92 Returns -1 on error
93*/
94static int
96{
97 unsigned long nitems_return;
98 unsigned char *prop_return;
99 int current_desktop;
100
102 (This, DefaultRootWindow(This->display), "_NET_CURRENT_DESKTOP", 1, &nitems_return,
103 &prop_return, 0) < 0)
104 return (-1);
105
106 if (nitems_return != 1)
107 {
108 fprintf(stderr, "_NET_CURRENT_DESKTOP has bad length\n");
109 return (-1);
110 }
111
112 current_desktop = *prop_return;
113 XFree(prop_return);
114 return current_desktop;
115}
116
117/*
118 Get workarea geometry
119 Returns zero on success, -1 on error
120 */
121
122int
124{
125 int current_desktop;
126 unsigned long nitems_return;
127 unsigned char *prop_return;
128 uint32 *return_words;
129 const uint32 net_workarea_x_offset = 0;
130 const uint32 net_workarea_y_offset = 1;
131 const uint32 net_workarea_width_offset = 2;
132 const uint32 net_workarea_height_offset = 3;
133 const uint32 max_prop_length = 32 * 4; /* Max 32 desktops */
134
136 (This, DefaultRootWindow(This->display), "_NET_WORKAREA", max_prop_length, &nitems_return,
137 &prop_return, 0) < 0)
138 return (-1);
139
140 if (nitems_return % 4)
141 {
142 fprintf(stderr, "_NET_WORKAREA has odd length\n");
143 return (-1);
144 }
145
146 current_desktop = get_current_desktop(This);
147
148 if (current_desktop < 0)
149 return -1;
150
151 return_words = (uint32 *) prop_return;
152
153 *x = return_words[current_desktop * 4 + net_workarea_x_offset];
154 *y = return_words[current_desktop * 4 + net_workarea_y_offset];
155 *width = return_words[current_desktop * 4 + net_workarea_width_offset];
156 *height = return_words[current_desktop * 4 + net_workarea_height_offset];
157
158 XFree(prop_return);
159
160 return (0);
161
162}
163
164
165
166void
168{
169 /* FIXME: Use XInternAtoms */
170 This->ewmhints.state_maximized_vert_atom =
171 XInternAtom(This->display, "_NET_WM_STATE_MAXIMIZED_VERT", False);
172 This->ewmhints.state_maximized_horz_atom =
173 XInternAtom(This->display, "_NET_WM_STATE_MAXIMIZED_HORZ", False);
174 This->ewmhints.state_hidden_atom = XInternAtom(This->display, "_NET_WM_STATE_HIDDEN", False);
175 This->ewmhints.state_skip_taskbar_atom =
176 XInternAtom(This->display, "_NET_WM_STATE_SKIP_TASKBAR", False);
177 This->ewmhints.state_skip_pager_atom = XInternAtom(This->display, "_NET_WM_STATE_SKIP_PAGER", False);
178 This->ewmhints.state_modal_atom = XInternAtom(This->display, "_NET_WM_STATE_MODAL", False);
179 This->net_wm_state_atom = XInternAtom(This->display, "_NET_WM_STATE", False);
180 This->net_wm_desktop_atom = XInternAtom(This->display, "_NET_WM_DESKTOP", False);
181 This->ewmhints.name_atom = XInternAtom(This->display, "_NET_WM_NAME", False);
182 This->ewmhints.utf8_string_atom = XInternAtom(This->display, "UTF8_STRING", False);
183}
184
185
186/*
187 Get the window state: normal/minimized/maximized.
188*/
189#ifndef MAKE_PROTO
190int
192{
193 unsigned long nitems_return;
194 unsigned char *prop_return;
195 uint32 *return_words;
196 unsigned long item;
197 BOOL maximized_vert, maximized_horz, hidden;
198
199 maximized_vert = maximized_horz = hidden = False;
200
201 if (get_property_value(This, w, "_NET_WM_STATE", 64, &nitems_return, &prop_return, 0) < 0)
202 return SEAMLESSRDP_NORMAL;
203
204 return_words = (uint32 *) prop_return;
205
206 for (item = 0; item < nitems_return; item++)
207 {
208 if (return_words[item] == This->ewmhints.state_maximized_vert_atom)
209 maximized_vert = True;
210 if (return_words[item] == This->ewmhints.state_maximized_horz_atom)
211 maximized_horz = True;
212 if (return_words[item] == This->ewmhints.state_hidden_atom)
213 hidden = True;
214 }
215
216 XFree(prop_return);
217
218 if (maximized_vert && maximized_horz)
220 else if (hidden)
222 else
223 return SEAMLESSRDP_NORMAL;
224}
225
226static int
227ewmh_modify_state(RDPCLIENT * This, Window wnd, int add, Atom atom1, Atom atom2)
228{
230 XEvent xevent;
231
232 int result;
233 unsigned long nitems;
234 unsigned char *props;
235 uint32 state = WithdrawnState;
236
237 /* The spec states that the window manager must respect any
238 _NET_WM_STATE attributes on a withdrawn window. In order words, we
239 modify the attributes directly for withdrawn windows and ask the WM
240 to do it for active windows. */
241 result = get_property_value(This, wnd, "WM_STATE", 64, &nitems, &props, 1);
242 if ((result >= 0) && nitems)
243 {
244 state = *(uint32 *) props;
245 XFree(props);
246 }
247
248 if (state == WithdrawnState)
249 {
250 if (add)
251 {
252 Atom atoms[2];
253
254 atoms[0] = atom1;
255 nitems = 1;
256 if (atom2)
257 {
258 atoms[1] = atom2;
259 nitems = 2;
260 }
261
262 XChangeProperty(This->display, wnd, This->net_wm_state_atom, XA_ATOM,
263 32, PropModeAppend, (unsigned char *) atoms, nitems);
264 }
265 else
266 {
267 Atom *atoms;
268 int i;
269
270 if (get_property_value(This, wnd, "_NET_WM_STATE", 64, &nitems, &props, 1) < 0)
271 return 0;
272
273 atoms = (Atom *) props;
274
275 for (i = 0; i < nitems; i++)
276 {
277 if ((atoms[i] == atom1) || (atom2 && (atoms[i] == atom2)))
278 {
279 if (i != (nitems - 1))
280 memmove(&atoms[i], &atoms[i + 1],
281 sizeof(Atom) * (nitems - i - 1));
282 nitems--;
283 i--;
284 }
285 }
286
287 XChangeProperty(This->display, wnd, This->net_wm_state_atom, XA_ATOM,
288 32, PropModeReplace, (unsigned char *) atoms, nitems);
289
290 XFree(props);
291 }
292
293 return 0;
294 }
295
296 xevent.type = ClientMessage;
297 xevent.xclient.window = wnd;
298 xevent.xclient.message_type = This->net_wm_state_atom;
299 xevent.xclient.format = 32;
300 if (add)
301 xevent.xclient.data.l[0] = _NET_WM_STATE_ADD;
302 else
303 xevent.xclient.data.l[0] = _NET_WM_STATE_REMOVE;
304 xevent.xclient.data.l[1] = atom1;
305 xevent.xclient.data.l[2] = atom2;
306 xevent.xclient.data.l[3] = 0;
307 xevent.xclient.data.l[4] = 0;
308 status = XSendEvent(This->display, DefaultRootWindow(This->display), False,
309 SubstructureNotifyMask | SubstructureRedirectMask, &xevent);
310 if (!status)
311 return -1;
312
313 return 0;
314}
315
316/*
317 Set the window state: normal/minimized/maximized.
318 Returns -1 on failure.
319*/
320int
322{
323 /*
324 * Deal with the max atoms
325 */
327 {
329 (This, wnd, 1, This->ewmhints.state_maximized_vert_atom,
330 This->ewmhints.state_maximized_horz_atom) < 0)
331 return -1;
332 }
333 else
334 {
336 (This, wnd, 0, This->ewmhints.state_maximized_vert_atom,
337 This->ewmhints.state_maximized_horz_atom) < 0)
338 return -1;
339 }
340
341 return 0;
342}
343
344
345int
347{
348 unsigned long nitems_return;
349 unsigned char *prop_return;
350 int desktop;
351
352 if (get_property_value(This, wnd, "_NET_WM_DESKTOP", 1, &nitems_return, &prop_return, 0) < 0)
353 return (-1);
354
355 if (nitems_return != 1)
356 {
357 fprintf(stderr, "_NET_WM_DESKTOP has bad length\n");
358 return (-1);
359 }
360
361 desktop = *prop_return;
362 XFree(prop_return);
363 return desktop;
364}
365
366
367int
368ewmh_move_to_desktop(RDPCLIENT * This, Window wnd, unsigned int desktop)
369{
371 XEvent xevent;
372
373 xevent.type = ClientMessage;
374 xevent.xclient.window = wnd;
375 xevent.xclient.message_type = This->net_wm_desktop_atom;
376 xevent.xclient.format = 32;
377 xevent.xclient.data.l[0] = desktop;
378 xevent.xclient.data.l[1] = 0;
379 xevent.xclient.data.l[2] = 0;
380 xevent.xclient.data.l[3] = 0;
381 xevent.xclient.data.l[4] = 0;
382 status = XSendEvent(This->display, DefaultRootWindow(This->display), False,
383 SubstructureNotifyMask | SubstructureRedirectMask, &xevent);
384 if (!status)
385 return -1;
386
387 return 0;
388}
389
390void
392{
393 int len;
394
395 len = strlen(title);
396 XChangeProperty(This->display, wnd, This->ewmhints.name_atom, This->ewmhints.utf8_string_atom,
397 8, PropModeReplace, (unsigned char *) title, len);
398}
399
400
401int
403{
405 (This, wnd, 1, This->ewmhints.state_skip_taskbar_atom, This->ewmhints.state_skip_pager_atom) < 0)
406 return -1;
407 return 0;
408}
409
410int
412{
413 if (ewmh_modify_state(This, wnd, 1, This->ewmhints.state_modal_atom, 0) < 0)
414 return -1;
415 return 0;
416}
417
418#endif /* MAKE_PROTO */
419
420
421#if 0
422
423/* FIXME: _NET_MOVERESIZE_WINDOW is for pagers, not for
424 applications. We should implement _NET_WM_MOVERESIZE instead */
425
426int
427ewmh_net_moveresize_window(RDPCLIENT * This, Window wnd, int x, int y, int width, int height)
428{
430 XEvent xevent;
431 Atom moveresize;
432
433 moveresize = XInternAtom(This->display, "_NET_MOVERESIZE_WINDOW", False);
434 if (!moveresize)
435 {
436 return -1;
437 }
438
439 xevent.type = ClientMessage;
440 xevent.xclient.window = wnd;
441 xevent.xclient.message_type = moveresize;
442 xevent.xclient.format = 32;
443 xevent.xclient.data.l[0] = StaticGravity | (1 << 8) | (1 << 9) | (1 << 10) | (1 << 11);
444 xevent.xclient.data.l[1] = x;
445 xevent.xclient.data.l[2] = y;
446 xevent.xclient.data.l[3] = width;
447 xevent.xclient.data.l[4] = height;
448
449 status = XSendEvent(This->display, DefaultRootWindow(This->display), False,
450 SubstructureNotifyMask | SubstructureRedirectMask, &xevent);
451 if (!status)
452 return -1;
453 return 0;
454}
455
456#endif
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
static int state
Definition: maze.c:121
#define SEAMLESSRDP_MAXIMIZED
Definition: constants.h:569
#define SEAMLESSRDP_MINIMIZED
Definition: constants.h:568
#define SEAMLESSRDP_NORMAL
Definition: constants.h:567
void ewmh_init(void)
unsigned int uint32
Definition: types.h:32
#define False
Definition: types.h:25
#define True
Definition: types.h:24
@ None
Definition: install.h:14
_Out_ RTL_ATOM * Atom
Definition: class.h:54
@ Success
Definition: eventcreate.c:712
void ewmh_set_wm_name(RDPCLIENT *This, Window wnd, const char *title)
Definition: ewmhints.c:391
#define _NET_WM_STATE_REMOVE
Definition: ewmhints.c:29
int ewmh_move_to_desktop(RDPCLIENT *This, Window wnd, unsigned int desktop)
Definition: ewmhints.c:368
int ewmh_set_window_modal(RDPCLIENT *This, Window wnd)
Definition: ewmhints.c:411
int ewmh_set_window_popup(RDPCLIENT *This, Window wnd)
Definition: ewmhints.c:402
static int ewmh_modify_state(RDPCLIENT *This, Window wnd, int add, Atom atom1, Atom atom2)
Definition: ewmhints.c:227
static int get_property_value(RDPCLIENT *This, Window wnd, char *propname, long max_length, unsigned long *nitems_return, unsigned char **prop_return, int nowarn)
Definition: ewmhints.c:38
int ewmh_change_state(RDPCLIENT *This, Window wnd, int state)
Definition: ewmhints.c:321
int get_current_workarea(RDPCLIENT *This, uint32 *x, uint32 *y, uint32 *width, uint32 *height)
Definition: ewmhints.c:123
static int get_current_desktop(RDPCLIENT *This)
Definition: ewmhints.c:95
int ewmh_get_window_state(RDPCLIENT *This, Window w)
Definition: ewmhints.c:191
#define _NET_WM_STATE_ADD
Definition: ewmhints.c:30
int ewmh_get_window_desktop(RDPCLIENT *This, Window wnd)
Definition: ewmhints.c:346
unsigned int BOOL
Definition: ntddk_ex.h:94
Status
Definition: gdiplustypes.h:25
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLint GLint GLsizei GLsizei height
Definition: gl.h:1546
GLint GLint GLsizei width
Definition: gl.h:1546
GLenum GLsizei len
Definition: glext.h:6722
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:6102
GLuint64EXT * result
Definition: glext.h:11304
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define stderr
Definition: stdio.h:100
_Check_return_opt_ _CRTIMP int __cdecl fprintf(_Inout_ FILE *_File, _In_z_ _Printf_format_string_ const char *_Format,...)
__u32 hidden
Definition: mkdosfs.c:13
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
static ATOM item
Definition: dde.c:856
static char title[]
Definition: ps.c:92
Definition: window.c:28
Definition: ps.c:97
static const WCHAR props[]
Definition: wbemdisp.c:288