ReactOS  0.4.14-dev-390-g34947ad
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 */
37 static int
38 get_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;
42  Atom property;
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 */
94 static 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 
122 int
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 
166 void
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
190 int
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)
219  return SEAMLESSRDP_MAXIMIZED;
220  else if (hidden)
221  return SEAMLESSRDP_MINIMIZED;
222  else
223  return SEAMLESSRDP_NORMAL;
224 }
225 
226 static int
227 ewmh_modify_state(RDPCLIENT * This, Window wnd, int add, Atom atom1, Atom atom2)
228 {
229  Status status;
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 */
320 int
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 
345 int
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 
367 int
368 ewmh_move_to_desktop(RDPCLIENT * This, Window wnd, unsigned int desktop)
369 {
370  Status status;
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 
390 void
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 
401 int
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 
410 int
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 
426 int
427 ewmh_net_moveresize_window(RDPCLIENT * This, Window wnd, int x, int y, int width, int height)
428 {
429  Status status;
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
int ewmh_set_window_popup(RDPCLIENT *This, Window wnd)
Definition: ewmhints.c:402
int add
Definition: i386-dis.c:3122
int ewmh_change_state(RDPCLIENT *This, Window wnd, int state)
Definition: ewmhints.c:321
GLint GLint GLsizei width
Definition: gl.h:1546
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:6102
int get_current_workarea(RDPCLIENT *This, uint32 *x, uint32 *y, uint32 *width, uint32 *height)
Definition: ewmhints.c:123
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
unsigned int uint32
Definition: types.h:32
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
#define SEAMLESSRDP_MAXIMIZED
Definition: constants.h:569
_Out_ RTL_ATOM * Atom
Definition: class.h:54
__u32 hidden
Definition: mkdosfs.c:371
#define _NET_WM_STATE_ADD
Definition: ewmhints.c:30
Definition: window.c:29
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 _NET_WM_STATE_REMOVE
Definition: ewmhints.c:29
#define None
Definition: i386-dis.c:444
unsigned int BOOL
Definition: ntddk_ex.h:94
_Check_return_opt_ _CRTIMP int __cdecl fprintf(_Inout_ FILE *_File, _In_z_ _Printf_format_string_ const char *_Format,...)
#define SEAMLESSRDP_NORMAL
Definition: constants.h:567
int ewmh_get_window_state(RDPCLIENT *This, Window w)
Definition: ewmhints.c:191
void ewmh_init(RDPCLIENT *This)
Definition: ewmhints.c:167
#define True
Definition: types.h:24
#define False
Definition: types.h:25
static int get_current_desktop(RDPCLIENT *This)
Definition: ewmhints.c:95
static int state
Definition: maze.c:121
GLenum GLsizei len
Definition: glext.h:6722
GLint GLint GLsizei GLsizei height
Definition: gl.h:1546
Status
Definition: gdiplustypes.h:24
int ewmh_set_window_modal(RDPCLIENT *This, Window wnd)
Definition: ewmhints.c:411
static ATOM item
Definition: dde.c:856
static int ewmh_modify_state(RDPCLIENT *This, Window wnd, int add, Atom atom1, Atom atom2)
Definition: ewmhints.c:227
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
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
static const WCHAR props[]
Definition: wbemdisp.c:288
void ewmh_set_wm_name(RDPCLIENT *This, Window wnd, const char *title)
Definition: ewmhints.c:391
FILE * stderr
int ewmh_get_window_desktop(RDPCLIENT *This, Window wnd)
Definition: ewmhints.c:346
int ewmh_move_to_desktop(RDPCLIENT *This, Window wnd, unsigned int desktop)
Definition: ewmhints.c:368
GLuint64EXT * result
Definition: glext.h:11304
static SERVICE_STATUS status
Definition: service.c:31
static char title[]
Definition: ps.c:92
#define SEAMLESSRDP_MINIMIZED
Definition: constants.h:568
Definition: ps.c:97