/[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 1118 - (show annotations)
Tue Mar 14 13:56:50 2006 UTC (18 years, 3 months ago) by astrand
File MIME type: text/plain
File size: 8114 byte(s)
Implemented support for changing state normal/minimized/maximized via EWMH. Also, sending notifications to server when local state changes.

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 "rdesktop.h"
26
27 #define _NET_WM_STATE_REMOVE 0 /* remove/unset property */
28 #define _NET_WM_STATE_ADD 1 /* add/set property */
29 #define _NET_WM_STATE_TOGGLE 2 /* toggle property */
30
31 extern Display *g_display;
32 static Atom g_net_wm_state_maximized_vert_atom, g_net_wm_state_maximized_horz_atom,
33 g_net_wm_state_hidden_atom;
34 Atom g_net_wm_state_atom;
35
36 /*
37 Get window property value (32 bit format)
38 Returns zero on success, -1 on error
39 */
40 static int
41 get_property_value(Window wnd, char *propname, long max_length,
42 unsigned long *nitems_return, unsigned char **prop_return)
43 {
44 int result;
45 Atom property;
46 Atom actual_type_return;
47 int actual_format_return;
48 unsigned long bytes_after_return;
49
50 property = XInternAtom(g_display, propname, True);
51 if (property == None)
52 {
53 fprintf(stderr, "Atom %s does not exist\n", propname);
54 return (-1);
55 }
56
57 result = XGetWindowProperty(g_display, wnd, property, 0, /* long_offset */
58 max_length, /* long_length */
59 False, /* delete */
60 AnyPropertyType, /* req_type */
61 &actual_type_return,
62 &actual_format_return,
63 nitems_return, &bytes_after_return, prop_return);
64
65 if (result != Success)
66 {
67 fprintf(stderr, "XGetWindowProperty failed\n");
68 return (-1);
69 }
70
71 if (actual_type_return == None || actual_format_return == 0)
72 {
73 fprintf(stderr, "Window is missing property %s\n", propname);
74 return (-1);
75 }
76
77 if (bytes_after_return)
78 {
79 fprintf(stderr, "%s is too big for me\n", propname);
80 return (-1);
81 }
82
83 if (actual_format_return != 32)
84 {
85 fprintf(stderr, "%s has bad format\n", propname);
86 return (-1);
87 }
88
89 return (0);
90 }
91
92 /*
93 Get current desktop number
94 Returns -1 on error
95 */
96 static int
97 get_current_desktop(void)
98 {
99 unsigned long nitems_return;
100 unsigned char *prop_return;
101 int current_desktop;
102
103 if (get_property_value
104 (DefaultRootWindow(g_display), "_NET_CURRENT_DESKTOP", 1, &nitems_return,
105 &prop_return) < 0)
106 return (-1);
107
108 if (nitems_return != 1)
109 {
110 fprintf(stderr, "_NET_CURRENT_DESKTOP has bad length\n");
111 return (-1);
112 }
113
114 current_desktop = *prop_return;
115 XFree(prop_return);
116 return current_desktop;
117 }
118
119 /*
120 Get workarea geometry
121 Returns zero on success, -1 on error
122 */
123
124 int
125 get_current_workarea(uint32 * x, uint32 * y, uint32 * width, uint32 * height)
126 {
127 int current_desktop;
128 unsigned long nitems_return;
129 unsigned char *prop_return;
130 uint32 *return_words;
131 const uint32 net_workarea_x_offset = 0;
132 const uint32 net_workarea_y_offset = 1;
133 const uint32 net_workarea_width_offset = 2;
134 const uint32 net_workarea_height_offset = 3;
135 const uint32 max_prop_length = 32 * 4; /* Max 32 desktops */
136
137 if (get_property_value
138 (DefaultRootWindow(g_display), "_NET_WORKAREA", max_prop_length, &nitems_return,
139 &prop_return) < 0)
140 return (-1);
141
142 if (nitems_return % 4)
143 {
144 fprintf(stderr, "_NET_WORKAREA has odd length\n");
145 return (-1);
146 }
147
148 current_desktop = get_current_desktop();
149
150 if (current_desktop < 0)
151 return -1;
152
153 return_words = (uint32 *) prop_return;
154
155 *x = return_words[current_desktop * 4 + net_workarea_x_offset];
156 *y = return_words[current_desktop * 4 + net_workarea_y_offset];
157 *width = return_words[current_desktop * 4 + net_workarea_width_offset];
158 *height = return_words[current_desktop * 4 + net_workarea_height_offset];
159
160 XFree(prop_return);
161
162 return (0);
163
164 }
165
166
167
168 void
169 ewmh_init()
170 {
171 g_net_wm_state_maximized_vert_atom =
172 XInternAtom(g_display, "_NET_WM_STATE_MAXIMIZED_VERT", False);
173 g_net_wm_state_maximized_horz_atom =
174 XInternAtom(g_display, "_NET_WM_STATE_MAXIMIZED_HORZ", False);
175 g_net_wm_state_hidden_atom = XInternAtom(g_display, "_NET_WM_STATE_HIDDEN", False);
176 g_net_wm_state_atom = XInternAtom(g_display, "_NET_WM_STATE", False);
177 }
178
179
180 /*
181 Get the window state: normal/minimized/maximized.
182 */
183 #ifndef MAKE_PROTO
184 int
185 ewmh_get_window_state(Window w)
186 {
187 unsigned long nitems_return;
188 unsigned char *prop_return;
189 uint32 *return_words;
190 unsigned long item;
191 BOOL maximized_vert, maximized_horz, hidden;
192
193 maximized_vert = maximized_horz = hidden = False;
194
195 if (get_property_value(w, "_NET_WM_STATE", 64, &nitems_return, &prop_return) < 0)
196 return SEAMLESSRDP_NORMAL;
197
198 return_words = (uint32 *) prop_return;
199
200 for (item = 0; item < nitems_return; item++)
201 {
202 if (return_words[item] == g_net_wm_state_maximized_vert_atom)
203 maximized_vert = True;
204 if (return_words[item] == g_net_wm_state_maximized_horz_atom)
205 maximized_horz = True;
206 if (return_words[item] == g_net_wm_state_hidden_atom)
207 hidden = True;
208 }
209
210 XFree(prop_return);
211
212 if (maximized_vert && maximized_horz)
213 return SEAMLESSRDP_MAXIMIZED;
214 else if (hidden)
215 return SEAMLESSRDP_MINIMIZED;
216 else
217 return SEAMLESSRDP_NORMAL;
218 }
219
220 /*
221 Set the window state: normal/minimized/maximized.
222 Returns -1 on failure.
223 */
224 int
225 ewmh_change_state(Window wnd, int state)
226 {
227 Status status;
228 XEvent xevent;
229
230 /*
231 * Deal with the hidden atom
232 */
233 xevent.type = ClientMessage;
234 xevent.xclient.window = wnd;
235 xevent.xclient.message_type = g_net_wm_state_atom;
236 xevent.xclient.format = 32;
237 if (state == SEAMLESSRDP_MINIMIZED)
238 xevent.xclient.data.l[0] = _NET_WM_STATE_ADD;
239 else
240 xevent.xclient.data.l[0] = _NET_WM_STATE_REMOVE;
241 xevent.xclient.data.l[1] = g_net_wm_state_hidden_atom;
242 xevent.xclient.data.l[2] = 0;
243 xevent.xclient.data.l[3] = 0;
244 xevent.xclient.data.l[4] = 0;
245 status = XSendEvent(g_display, DefaultRootWindow(g_display), False,
246 SubstructureNotifyMask | SubstructureRedirectMask, &xevent);
247 if (!status)
248 return -1;
249
250
251 /*
252 * Deal with the max atoms
253 */
254 xevent.type = ClientMessage;
255 xevent.xclient.window = wnd;
256 xevent.xclient.message_type = g_net_wm_state_atom;
257 xevent.xclient.format = 32;
258 if (state == SEAMLESSRDP_MAXIMIZED)
259 xevent.xclient.data.l[0] = _NET_WM_STATE_ADD;
260 else
261 xevent.xclient.data.l[0] = _NET_WM_STATE_REMOVE;
262 xevent.xclient.data.l[1] = g_net_wm_state_maximized_vert_atom;
263 xevent.xclient.data.l[2] = g_net_wm_state_maximized_horz_atom;
264 xevent.xclient.data.l[3] = 0;
265 xevent.xclient.data.l[4] = 0;
266 status = XSendEvent(g_display, DefaultRootWindow(g_display), False,
267 SubstructureNotifyMask | SubstructureRedirectMask, &xevent);
268 if (!status)
269 return -1;
270
271 return 0;
272 }
273
274 #endif /* MAKE_PROTO */
275
276
277 #if 0
278
279 /* FIXME: _NET_MOVERESIZE_WINDOW is for pagers, not for
280 applications. We should implement _NET_WM_MOVERESIZE instead */
281
282 int
283 ewmh_net_moveresize_window(Window wnd, int x, int y, int width, int height)
284 {
285 Status status;
286 XEvent xevent;
287 Atom moveresize;
288
289 moveresize = XInternAtom(g_display, "_NET_MOVERESIZE_WINDOW", False);
290 if (!moveresize)
291 {
292 return -1;
293 }
294
295 xevent.type = ClientMessage;
296 xevent.xclient.window = wnd;
297 xevent.xclient.message_type = moveresize;
298 xevent.xclient.format = 32;
299 xevent.xclient.data.l[0] = StaticGravity | (1 << 8) | (1 << 9) | (1 << 10) | (1 << 11);
300 xevent.xclient.data.l[1] = x;
301 xevent.xclient.data.l[2] = y;
302 xevent.xclient.data.l[3] = width;
303 xevent.xclient.data.l[4] = height;
304
305 status = XSendEvent(g_display, DefaultRootWindow(g_display), False,
306 SubstructureNotifyMask | SubstructureRedirectMask, &xevent);
307 if (!status)
308 return -1;
309 return 0;
310 }
311
312 #endif

  ViewVC Help
Powered by ViewVC 1.1.26