/[rdesktop]/sourceforge.net/trunk/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

Diff of /sourceforge.net/trunk/rdesktop/ewmhints.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1013 by astrand, Mon Sep 12 12:36:45 2005 UTC revision 1199 by astrand, Mon Mar 27 08:17:34 2006 UTC
# Line 22  Line 22 
22  */  */
23    
24  #include <X11/Xlib.h>  #include <X11/Xlib.h>
25    #include <X11/Xatom.h>
26    #include <X11/Xutil.h>
27  #include "rdesktop.h"  #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  extern Display *g_display;  extern Display *g_display;
34    
35    static Atom g_net_wm_state_maximized_vert_atom, g_net_wm_state_maximized_horz_atom,
36            g_net_wm_state_hidden_atom, g_net_wm_name_atom, g_utf8_string_atom,
37            g_net_wm_state_skip_taskbar_atom, g_net_wm_state_skip_pager_atom, g_net_wm_state_modal_atom;
38    
39    Atom g_net_wm_state_atom, g_net_wm_desktop_atom;
40    
41  /*  /*
42     Get window property value (32 bit format)     Get window property value (32 bit format)
43     Returns zero on success, -1 on error     Returns zero on success, -1 on error
44  */  */
45  static int  static int
46  get_property_value(char *propname, long max_length,  get_property_value(Window wnd, char *propname, long max_length,
47                     unsigned long *nitems_return, unsigned char **prop_return)                     unsigned long *nitems_return, unsigned char **prop_return, int nowarn)
48  {  {
49          int result;          int result;
50          Atom property;          Atom property;
# Line 47  get_property_value(char *propname, long Line 59  get_property_value(char *propname, long
59                  return (-1);                  return (-1);
60          }          }
61    
62          result = XGetWindowProperty(g_display, DefaultRootWindow(g_display), property, 0,       /* long_offset */          result = XGetWindowProperty(g_display, wnd, property, 0,        /* long_offset */
63                                      max_length, /* long_length */                                      max_length, /* long_length */
64                                      False,      /* delete */                                      False,      /* delete */
65                                      AnyPropertyType,    /* req_type */                                      AnyPropertyType,    /* req_type */
# Line 63  get_property_value(char *propname, long Line 75  get_property_value(char *propname, long
75    
76          if (actual_type_return == None || actual_format_return == 0)          if (actual_type_return == None || actual_format_return == 0)
77          {          {
78                  fprintf(stderr, "Root window is missing property %s\n", propname);                  if (!nowarn)
79                            fprintf(stderr, "Window is missing property %s\n", propname);
80                  return (-1);                  return (-1);
81          }          }
82    
# Line 93  get_current_desktop(void) Line 106  get_current_desktop(void)
106          unsigned char *prop_return;          unsigned char *prop_return;
107          int current_desktop;          int current_desktop;
108    
109          if (get_property_value("_NET_CURRENT_DESKTOP", 1, &nitems_return, &prop_return) < 0)          if (get_property_value
110                (DefaultRootWindow(g_display), "_NET_CURRENT_DESKTOP", 1, &nitems_return,
111                 &prop_return, 0) < 0)
112                  return (-1);                  return (-1);
113    
114          if (nitems_return != 1)          if (nitems_return != 1)
# Line 125  get_current_workarea(uint32 * x, uint32 Line 140  get_current_workarea(uint32 * x, uint32
140          const uint32 net_workarea_height_offset = 3;          const uint32 net_workarea_height_offset = 3;
141          const uint32 max_prop_length = 32 * 4;  /* Max 32 desktops */          const uint32 max_prop_length = 32 * 4;  /* Max 32 desktops */
142    
143          if (get_property_value("_NET_WORKAREA", max_prop_length, &nitems_return, &prop_return) < 0)          if (get_property_value
144                (DefaultRootWindow(g_display), "_NET_WORKAREA", max_prop_length, &nitems_return,
145                 &prop_return, 0) < 0)
146                  return (-1);                  return (-1);
147    
148          if (nitems_return % 4)          if (nitems_return % 4)
# Line 153  get_current_workarea(uint32 * x, uint32 Line 170  get_current_workarea(uint32 * x, uint32
170  }  }
171    
172    
173    
174    void
175    ewmh_init()
176    {
177            /* FIXME: Use XInternAtoms */
178            g_net_wm_state_maximized_vert_atom =
179                    XInternAtom(g_display, "_NET_WM_STATE_MAXIMIZED_VERT", False);
180            g_net_wm_state_maximized_horz_atom =
181                    XInternAtom(g_display, "_NET_WM_STATE_MAXIMIZED_HORZ", False);
182            g_net_wm_state_hidden_atom = XInternAtom(g_display, "_NET_WM_STATE_HIDDEN", False);
183            g_net_wm_state_skip_taskbar_atom =
184                    XInternAtom(g_display, "_NET_WM_STATE_SKIP_TASKBAR", False);
185            g_net_wm_state_skip_pager_atom = XInternAtom(g_display, "_NET_WM_STATE_SKIP_PAGER", False);
186            g_net_wm_state_modal_atom = XInternAtom(g_display, "_NET_WM_STATE_MODAL", False);
187            g_net_wm_state_atom = XInternAtom(g_display, "_NET_WM_STATE", False);
188            g_net_wm_desktop_atom = XInternAtom(g_display, "_NET_WM_DESKTOP", False);
189            g_net_wm_name_atom = XInternAtom(g_display, "_NET_WM_NAME", False);
190            g_utf8_string_atom = XInternAtom(g_display, "UTF8_STRING", False);
191    }
192    
193    
194    /*
195       Get the window state: normal/minimized/maximized.
196    */
197    #ifndef MAKE_PROTO
198    int
199    ewmh_get_window_state(Window w)
200    {
201            unsigned long nitems_return;
202            unsigned char *prop_return;
203            uint32 *return_words;
204            unsigned long item;
205            BOOL maximized_vert, maximized_horz, hidden;
206    
207            maximized_vert = maximized_horz = hidden = False;
208    
209            if (get_property_value(w, "_NET_WM_STATE", 64, &nitems_return, &prop_return, 0) < 0)
210                    return SEAMLESSRDP_NORMAL;
211    
212            return_words = (uint32 *) prop_return;
213    
214            for (item = 0; item < nitems_return; item++)
215            {
216                    if (return_words[item] == g_net_wm_state_maximized_vert_atom)
217                            maximized_vert = True;
218                    if (return_words[item] == g_net_wm_state_maximized_horz_atom)
219                            maximized_horz = True;
220                    if (return_words[item] == g_net_wm_state_hidden_atom)
221                            hidden = True;
222            }
223    
224            XFree(prop_return);
225    
226            if (maximized_vert && maximized_horz)
227                    return SEAMLESSRDP_MAXIMIZED;
228            else if (hidden)
229                    return SEAMLESSRDP_MINIMIZED;
230            else
231                    return SEAMLESSRDP_NORMAL;
232    }
233    
234    static int
235    ewmh_modify_state(Window wnd, int add, Atom atom1, Atom atom2)
236    {
237            Status status;
238            XEvent xevent;
239    
240            int result;
241            unsigned long nitems;
242            unsigned char *props;
243            uint32 state;
244    
245            /* The spec states that the window manager must respect any
246               _NET_WM_STATE attributes on a withdrawn window. In order words, we
247               modify the attributes directly for withdrawn windows and ask the WM
248               to do it for active windows. */
249            result = get_property_value(wnd, "WM_STATE", 64, &nitems, &props, 1);
250            if ((result >= 0) && nitems)
251            {
252                    state = *(uint32 *) props;
253                    XFree(props);
254            }
255    
256            if ((result < 0) || !nitems || (state == WithdrawnState))
257            {
258                    if (add)
259                    {
260                            Atom atoms[2];
261    
262                            atoms[0] = atom1;
263                            nitems = 1;
264                            if (atom2)
265                            {
266                                    atoms[1] = atom2;
267                                    nitems = 2;
268                            }
269    
270                            XChangeProperty(g_display, wnd, g_net_wm_state_atom, XA_ATOM,
271                                            32, PropModeAppend, (unsigned char *) atoms, nitems);
272                    }
273                    else
274                    {
275                            Atom *atoms;
276                            int i;
277    
278                            if (get_property_value(wnd, "_NET_WM_STATE", 64, &nitems, &props, 1) < 0)
279                                    return 0;
280    
281                            atoms = (Atom *) props;
282    
283                            for (i = 0; i < nitems; i++)
284                            {
285                                    if ((atoms[i] == atom1) || (atom2 && (atoms[i] == atom2)))
286                                    {
287                                            if (i != (nitems - 1))
288                                                    memmove(&atoms[i], &atoms[i + 1],
289                                                            sizeof(Atom) * (nitems - i - 1));
290                                            nitems--;
291                                            i--;
292                                    }
293                            }
294    
295                            XChangeProperty(g_display, wnd, g_net_wm_state_atom, XA_ATOM,
296                                            32, PropModeReplace, (unsigned char *) atoms, nitems);
297    
298                            XFree(props);
299                    }
300    
301                    return 0;
302            }
303    
304            xevent.type = ClientMessage;
305            xevent.xclient.window = wnd;
306            xevent.xclient.message_type = g_net_wm_state_atom;
307            xevent.xclient.format = 32;
308            if (add)
309                    xevent.xclient.data.l[0] = _NET_WM_STATE_ADD;
310            else
311                    xevent.xclient.data.l[0] = _NET_WM_STATE_REMOVE;
312            xevent.xclient.data.l[1] = atom1;
313            xevent.xclient.data.l[2] = atom2;
314            xevent.xclient.data.l[3] = 0;
315            xevent.xclient.data.l[4] = 0;
316            status = XSendEvent(g_display, DefaultRootWindow(g_display), False,
317                                SubstructureNotifyMask | SubstructureRedirectMask, &xevent);
318            if (!status)
319                    return -1;
320    
321            return 0;
322    }
323    
324    /*
325       Set the window state: normal/minimized/maximized.
326       Returns -1 on failure.
327    */
328    int
329    ewmh_change_state(Window wnd, int state)
330    {
331            /*
332             * Deal with the max atoms
333             */
334            if (state == SEAMLESSRDP_MAXIMIZED)
335            {
336                    if (ewmh_modify_state
337                        (wnd, 1, g_net_wm_state_maximized_vert_atom,
338                         g_net_wm_state_maximized_horz_atom) < 0)
339                            return -1;
340            }
341            else
342            {
343                    if (ewmh_modify_state
344                        (wnd, 0, g_net_wm_state_maximized_vert_atom,
345                         g_net_wm_state_maximized_horz_atom) < 0)
346                            return -1;
347            }
348    
349            return 0;
350    }
351    
352    
353    int
354    ewmh_get_window_desktop(Window wnd)
355    {
356            unsigned long nitems_return;
357            unsigned char *prop_return;
358            int desktop;
359    
360            if (get_property_value(wnd, "_NET_WM_DESKTOP", 1, &nitems_return, &prop_return, 0) < 0)
361                    return (-1);
362    
363            if (nitems_return != 1)
364            {
365                    fprintf(stderr, "_NET_WM_DESKTOP has bad length\n");
366                    return (-1);
367            }
368    
369            desktop = *prop_return;
370            XFree(prop_return);
371            return desktop;
372    }
373    
374    
375    int
376    ewmh_move_to_desktop(Window wnd, unsigned int desktop)
377    {
378            Status status;
379            XEvent xevent;
380    
381            xevent.type = ClientMessage;
382            xevent.xclient.window = wnd;
383            xevent.xclient.message_type = g_net_wm_desktop_atom;
384            xevent.xclient.format = 32;
385            xevent.xclient.data.l[0] = desktop;
386            xevent.xclient.data.l[1] = 0;
387            xevent.xclient.data.l[2] = 0;
388            xevent.xclient.data.l[3] = 0;
389            xevent.xclient.data.l[4] = 0;
390            status = XSendEvent(g_display, DefaultRootWindow(g_display), False,
391                                SubstructureNotifyMask | SubstructureRedirectMask, &xevent);
392            if (!status)
393                    return -1;
394    
395            return 0;
396    }
397    
398    void
399    ewmh_set_wm_name(Window wnd, const char *title)
400    {
401            int len;
402    
403            len = strlen(title);
404            XChangeProperty(g_display, wnd, g_net_wm_name_atom, g_utf8_string_atom,
405                            8, PropModeReplace, (unsigned char *) title, len);
406    }
407    
408    
409    int
410    ewmh_set_window_popup(Window wnd)
411    {
412            if (ewmh_modify_state
413                (wnd, 1, g_net_wm_state_skip_taskbar_atom, g_net_wm_state_skip_pager_atom) < 0)
414                    return -1;
415            return 0;
416    }
417    
418    int
419    ewmh_set_window_modal(Window wnd)
420    {
421            if (ewmh_modify_state(wnd, 1, g_net_wm_state_modal_atom, 0) < 0)
422                    return -1;
423            return 0;
424    }
425    
426    #endif /* MAKE_PROTO */
427    
428    
429  #if 0  #if 0
430    
431  /* FIXME: _NET_MOVERESIZE_WINDOW is for pagers, not for  /* FIXME: _NET_MOVERESIZE_WINDOW is for pagers, not for

Legend:
Removed from v.1013  
changed lines
  Added in v.1199

  ViewVC Help
Powered by ViewVC 1.1.26