[Techtalk] Using XChangeProperty function?

Almut Behrens almut-behrens at gmx.net
Thu May 15 02:47:59 EST 2003


On Wed, May 14, 2003 at 10:10:30AM -0500, Vera Childs wrote:
> I've never done XWindows programming before, but I've been tasked to make a
> Java program that stays on top of all other windows on the Linux platform
> (...)
> 
> The C code:
> ---
> ... includes and other variables ...
> 
> Window win;
> Display dpy;
> Atom stateAbove;
> 
> ... stuff to set everything up ...
> 
> if (win) {
>     stateAbove = XInternAtom(dpy, "_NET_WM_STATE_ABOVE", False);
>     XChangeProperty(dpy, win, XInternAtom(dpy, "_NET_WM_STATE", False),
> XA_ATOM, 32, PropModeReplace, (unsigned char *) &stateAbove, 1);
> }


This piece of code looks quite allright to me.  Have you actually
verified whether the property does in fact get changed for the window
in question? If you haven't done so already, you could for example use
xprop to display the list of window properties. Among them, you should
see something like "_NET_WM_STATE(Atom) = _NET_WM_STATE_ABOVE", if the
above code succeeded.
(xprop allows both the interactive selection of the window and the
specification via window ID, e.g. "xprop -id 0x000001 -spy". The
0x000001 would of course have to be the real ID, which you can
determine using xwininfo ...)

More importantly, though, you probably need to inform the window
manager of the changed property -- at least that's what I suppose. This
is typically done by sending the root window a so-called ClientMessage
with the appropriate bits of information. A client message is sent with
XSendEvent(), for which you need to set up an XEvent structure/union
containing the info you need to send. The code fragment would look
something like:

  XEvent ev;
  ev.xclient.type = ClientMessage;
  ev.xclient.message_type = atom_wm_state;
                            // XInternAtom(..., "_NET_WM_STATE", ...)
  ev.xclient.window = client_window;
  ev.xclient.format = 32;
  ev.xclient.data.l[0] = d0;
  ev.xclient.data.l[1] = d1;
  ev.xclient.data.l[2] = d2;
  ev.xclient.data.l[3] = d3;
  ev.xclient.data.l[4] = d4;

  XSendEvent(dpy, root_window, False,
             SubstructureRedirectMask | SubstructureNotifyMask, &ev);

The tricky part is what to put into the data array of the ClientMessage
event...  The Extended Window Manager Hints specification
(http://www.freedesktop.org/standards/wm-spec.html) says:

  "To change the state of a mapped window, a Client MUST send a
  _NET_WM_STATE client message to the root window (window is the
  respective window, type _NET_WM_STATE, format 32, l[0]=<the action,
  as listed below>, l[1]=<First property to alter>, l[2]=<Second
  property to alter>). This message allows two properties to be changed
  simultaneously, specifically to allow both horizontal and vertical
  maximisation to be altered together. l[2] MUST be set to zero if only
  one property is to be changed. l[0], the action, MUST be one of:
  
  _NET_WM_STATE_REMOVE        0    /* remove/unset property */
  _NET_WM_STATE_ADD           1    /* add/set property */
  _NET_WM_STATE_TOGGLE        2    /* toggle property  */"

>From this, it is still not entirely clear to me what is needed, in
particular, is <First property to alter> the atom (number), or the
index into the list of atoms assigned to _NET_WM_STATE, or what...?
Anyway, setting

  ev.xclient.data.l[0] = 1;
  ev.xclient.data.l[1] = stateAbove;  // variable from your code
  ev.xclient.data.l[2] = 0;
  (l[3] and l[4] unused here)

might be a good starting point for further experiments... or further
googling ;)

(also see the man pages for XSendEvent, XEvent, XClientMessageEvent)


If that doesn't get you any further, there's also a dedicated mailing
list, where you might want to post specific questions:

http://mail.gnome.org/mailman/listinfo/wm-spec-list

Good luck,
Almut



More information about the Techtalk mailing list