aboutsummaryrefslogtreecommitdiffstats
path: root/matchbox2/mb-wm-client-window.c
diff options
context:
space:
mode:
Diffstat (limited to 'matchbox2/mb-wm-client-window.c')
-rw-r--r--matchbox2/mb-wm-client-window.c978
1 files changed, 978 insertions, 0 deletions
diff --git a/matchbox2/mb-wm-client-window.c b/matchbox2/mb-wm-client-window.c
new file mode 100644
index 0000000..19aa703
--- /dev/null
+++ b/matchbox2/mb-wm-client-window.c
@@ -0,0 +1,978 @@
+/*
+ * Matchbox Window Manager II - A lightweight window manager not for the
+ * desktop.
+ *
+ * Authored By Matthew Allum <mallum@o-hand.com>
+ *
+ * Copyright (c) 2005 OpenedHand Ltd - http://o-hand.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "mb-wm.h"
+
+/* Via Xatomtype.h */
+#define NumPropWMHintsElements 9 /* number of elements in this structure */
+#define NumPropWMSizeHintsElements 18
+
+enum {
+ COOKIE_WIN_TYPE = 0,
+ COOKIE_WIN_ATTR,
+ COOKIE_WIN_GEOM,
+ COOKIE_WIN_NAME,
+ COOKIE_WIN_NAME_UTF8,
+ COOKIE_WIN_WM_HINTS,
+ COOKIE_WIN_WM_NORMAL_HINTS,
+ COOKIE_WIN_TRANSIENCY,
+ COOKIE_WIN_PROTOS,
+ COOKIE_WIN_MACHINE,
+ COOKIE_WIN_PID,
+ COOKIE_WIN_ICON,
+ COOKIE_WIN_ACTIONS,
+ COOKIE_WIN_USER_TIME,
+ COOKIE_WIN_CM_TRANSLUCENCY,
+ COOKIE_WIN_NET_STATE,
+ COOKIE_WIN_MWM_HINTS,
+
+ N_COOKIES
+};
+
+#define PROP_MOTIF_WM_HINTS_ELEMENTS 5
+#define MWM_HINTS_DECORATIONS (1L << 1)
+
+#define MWM_DECOR_BORDER (1L << 1)
+#define MWM_DECOR_RESIZEH (1L << 2)
+#define MWM_DECOR_TITLE (1L << 3)
+#define MWM_DECOR_MENU (1L << 4)
+#define MWM_DECOR_MINIMIZE (1L << 5)
+#define MWM_DECOR_MAXIMIZE (1L << 6)
+
+static void
+mb_wm_client_window_class_init (MBWMObjectClass *klass)
+{
+ MBWMClientWindowClass *rw_class;
+
+ MBWM_MARK();
+
+ rw_class = (MBWMClientWindowClass *)klass;
+
+#if MBWM_WANT_DEBUG
+ klass->klass_name = "MBWMClientWindow";
+#endif
+}
+
+static void
+mb_wm_client_window_destroy (MBWMObject *this)
+{
+ MBWMClientWindow * win = MB_WM_CLIENT_WINDOW (this);
+ MBWMList * l = win->icons;
+
+ if (win->name)
+ XFree (win->name);
+
+ if (win->machine)
+ XFree (win->machine);
+
+ while (l)
+ {
+ mb_wm_rgba_icon_free ((MBWMRgbaIcon *)l->data);
+ l = l->next;
+ }
+}
+
+static int
+mb_wm_client_window_init (MBWMObject *this, va_list vap)
+{
+ MBWMClientWindow *win = MB_WM_CLIENT_WINDOW (this);
+ MBWMObjectProp prop;
+ MBWindowManager *wm = NULL;
+ Window xwin = None;
+
+ prop = va_arg(vap, MBWMObjectProp);
+ while (prop)
+ {
+ switch (prop)
+ {
+ case MBWMObjectPropWm:
+ wm = va_arg(vap, MBWindowManager *);
+ break;
+ case MBWMObjectPropXwindow:
+ xwin = va_arg(vap, Window);
+ break;
+ default:
+ MBWMO_PROP_EAT (vap, prop);
+ }
+
+ prop = va_arg(vap, MBWMObjectProp);
+ }
+
+ if (!wm || !xwin)
+ {
+ fprintf (stderr, "--- error, no wm or xwin ---\n");
+ return 0;
+ }
+
+ win->xwindow = xwin;
+ win->wm = wm;
+
+ mb_wm_client_window_sync_properties (win, MBWM_WINDOW_PROP_ALL);
+
+ return 1;
+}
+
+int
+mb_wm_client_window_class_type ()
+{
+ static int type = 0;
+
+ if (UNLIKELY(type == 0))
+ {
+ static MBWMObjectClassInfo info = {
+ sizeof (MBWMClientWindowClass),
+ sizeof (MBWMClientWindow),
+ mb_wm_client_window_init,
+ mb_wm_client_window_destroy,
+ mb_wm_client_window_class_init
+ };
+
+ type = mb_wm_object_register_class (&info, MB_WM_TYPE_OBJECT, 0);
+ }
+
+ return type;
+}
+
+MBWMClientWindow*
+mb_wm_client_window_new (MBWindowManager *wm, Window xwin)
+{
+ MBWMClientWindow *win;
+
+ win = MB_WM_CLIENT_WINDOW (mb_wm_object_new (MB_WM_TYPE_CLIENT_WINDOW,
+ MBWMObjectPropWm, wm,
+ MBWMObjectPropXwindow, xwin,
+ NULL));
+ return win;
+}
+
+/*
+ * Creates MBWMIcon from raw _NET_WM_ICON property data, returning
+ * pointer to where the next icon might be in the data
+ */
+static unsigned long *
+icon_from_net_wm_icon (unsigned long * data, MBWMRgbaIcon ** mb_icon)
+{
+ MBWMRgbaIcon * icon = mb_wm_rgba_icon_new ();
+ size_t byte_len;
+
+ *mb_icon = icon;
+
+ if (!icon)
+ return data;
+
+ icon->width = *data++;
+ icon->height = *data++;
+
+ byte_len = sizeof (unsigned long) * icon->width * icon->height;
+
+ icon->pixels = malloc (byte_len);
+
+ if (!icon->pixels)
+ {
+ mb_wm_rgba_icon_free (icon);
+ *mb_icon = NULL;
+ return (data - 2);
+ }
+
+ memcpy (icon->pixels, data, byte_len);
+
+ MBWM_DBG("@@@ Icon %d x %d @@@", icon->width, icon->height);
+
+ return (data + icon->width * icon->height);
+}
+
+Bool
+mb_wm_client_window_sync_properties ( MBWMClientWindow *win,
+ unsigned long props_req)
+{
+ MBWMCookie cookies[N_COOKIES];
+ MBWindowManager *wm = win->wm;
+ Atom actual_type_return, *result_atom = NULL;
+ int actual_format_return;
+ unsigned long nitems_return;
+ unsigned long bytes_after_return;
+ unsigned int foo;
+ int x_error_code;
+ Window xwin;
+ int changes = 0;
+
+ MBWMClientWindowAttributes *xwin_attr = NULL;
+
+ xwin = win->xwindow;
+
+ if (props_req & MBWM_WINDOW_PROP_WIN_TYPE)
+ cookies[COOKIE_WIN_TYPE]
+ = mb_wm_property_atom_req(wm, xwin,
+ wm->atoms[MBWM_ATOM_NET_WM_WINDOW_TYPE]);
+
+ if (props_req & MBWM_WINDOW_PROP_NET_STATE)
+ cookies[COOKIE_WIN_NET_STATE]
+ = mb_wm_property_atom_req(wm, xwin,
+ wm->atoms[MBWM_ATOM_NET_WM_STATE]);
+
+ if (props_req & MBWM_WINDOW_PROP_ATTR)
+ cookies[COOKIE_WIN_ATTR]
+ = mb_wm_xwin_get_attributes (wm, xwin);
+
+ if (props_req & MBWM_WINDOW_PROP_GEOMETRY)
+ cookies[COOKIE_WIN_GEOM]
+ = mb_wm_xwin_get_geometry (wm, (Drawable)xwin);
+
+ if (props_req & MBWM_WINDOW_PROP_NAME)
+ {
+ cookies[COOKIE_WIN_NAME]
+ = mb_wm_property_req (wm,
+ xwin,
+ wm->atoms[MBWM_ATOM_WM_NAME],
+ 0,
+ 2048L,
+ False,
+ XA_STRING);
+
+ cookies[COOKIE_WIN_NAME_UTF8] =
+ mb_wm_property_utf8_req(wm, xwin,
+ wm->atoms[MBWM_ATOM_NET_WM_NAME]);
+ }
+
+ if (props_req & MBWM_WINDOW_PROP_WM_HINTS)
+ {
+ cookies[COOKIE_WIN_WM_HINTS]
+ = mb_wm_property_req (wm,
+ xwin,
+ wm->atoms[MBWM_ATOM_WM_HINTS],
+ 0,
+ 1024L,
+ False,
+ XA_WM_HINTS);
+ }
+
+ if (props_req & MBWM_WINDOW_PROP_WM_NORMAL_HINTS)
+ {
+ cookies[COOKIE_WIN_WM_NORMAL_HINTS]
+ = mb_wm_property_req (wm,
+ xwin,
+ wm->atoms[MBWM_ATOM_WM_NORMAL_HINTS],
+ 0,
+ 1024L,
+ False,
+ XA_WM_SIZE_HINTS);
+ }
+
+ if (props_req & MBWM_WINDOW_PROP_MWM_HINTS)
+ {
+ cookies[COOKIE_WIN_MWM_HINTS]
+ = mb_wm_property_req (wm,
+ xwin,
+ wm->atoms[MBWM_ATOM_MOTIF_WM_HINTS],
+ 0,
+ PROP_MOTIF_WM_HINTS_ELEMENTS,
+ False,
+ wm->atoms[MBWM_ATOM_MOTIF_WM_HINTS]);
+ }
+
+ if (props_req & MBWM_WINDOW_PROP_TRANSIENCY)
+ {
+ cookies[COOKIE_WIN_TRANSIENCY]
+ = mb_wm_property_req (wm,
+ xwin,
+ wm->atoms[MBWM_ATOM_WM_TRANSIENT_FOR],
+ 0,
+ 1L,
+ False,
+ XA_WINDOW);
+ }
+
+ if (props_req & MBWM_WINDOW_PROP_PROTOS)
+ {
+ cookies[COOKIE_WIN_PROTOS]
+ = mb_wm_property_atom_req(wm, xwin,
+ wm->atoms[MBWM_ATOM_WM_PROTOCOLS]);
+ }
+
+ if (props_req & MBWM_WINDOW_PROP_CLIENT_MACHINE)
+ {
+ cookies[COOKIE_WIN_MACHINE]
+ = mb_wm_property_req (wm,
+ xwin,
+ wm->atoms[MBWM_ATOM_WM_CLIENT_MACHINE],
+ 0,
+ 2048L,
+ False,
+ XA_STRING);
+ }
+
+ if (props_req & MBWM_WINDOW_PROP_NET_PID)
+ {
+ cookies[COOKIE_WIN_PID]
+ = mb_wm_property_cardinal_req (wm,
+ xwin,
+ wm->atoms[MBWM_ATOM_NET_WM_PID]);
+ }
+
+ if (props_req & MBWM_WINDOW_PROP_NET_ICON)
+ {
+ cookies[COOKIE_WIN_ICON]
+ = mb_wm_property_cardinal_req (wm,
+ xwin,
+ wm->atoms[MBWM_ATOM_NET_WM_ICON]);
+ }
+
+ if (props_req & MBWM_WINDOW_PROP_NET_USER_TIME)
+ {
+ cookies[COOKIE_WIN_USER_TIME]
+ = mb_wm_property_cardinal_req (wm,
+ xwin,
+ wm->atoms[MBWM_ATOM_NET_WM_USER_TIME]);
+ }
+
+ if (props_req & MBWM_WINDOW_PROP_CM_TRANSLUCENCY)
+ {
+ cookies[COOKIE_WIN_CM_TRANSLUCENCY]
+ = mb_wm_property_cardinal_req (wm,
+ xwin,
+ wm->atoms[MBWM_ATOM_CM_TRANSLUCENCY]);
+ }
+
+ /* bundle all pending requests to server and wait for replys */
+ XSync(wm->xdpy, False);
+
+ if (props_req & MBWM_WINDOW_PROP_WIN_TYPE)
+ {
+ mb_wm_property_reply (wm,
+ cookies[COOKIE_WIN_TYPE],
+ &actual_type_return,
+ &actual_format_return,
+ &nitems_return,
+ &bytes_after_return,
+ (unsigned char **)&result_atom,
+ &x_error_code);
+
+ if (x_error_code
+ || actual_type_return != XA_ATOM
+ || actual_format_return != 32
+ || nitems_return != 1
+ || result_atom == NULL
+ )
+ {
+ MBWM_DBG("### Warning net type prop failed ###");
+ }
+ else
+ {
+ if (win->net_type != result_atom[0])
+ changes |= MBWM_WINDOW_PROP_WIN_TYPE;
+
+ win->net_type = result_atom[0];
+ }
+
+ if (result_atom)
+ XFree(result_atom);
+
+ result_atom = NULL;
+ }
+
+ if (props_req & MBWM_WINDOW_PROP_NET_STATE)
+ {
+ mb_wm_property_reply (wm,
+ cookies[COOKIE_WIN_NET_STATE],
+ &actual_type_return,
+ &actual_format_return,
+ &nitems_return,
+ &bytes_after_return,
+ (unsigned char **)&result_atom,
+ &x_error_code);
+
+ if (x_error_code
+ || actual_type_return != XA_ATOM
+ || actual_format_return != 32
+ || nitems_return <= 0
+ || result_atom == NULL
+ )
+ {
+ MBWM_DBG("### Warning net type state failed ###");
+ }
+ else
+ {
+ int i;
+ win->ewmh_state = 0;
+
+ for (i = 0; i < nitems_return; ++i)
+ {
+ if (result_atom[i] == wm->atoms[MBWM_ATOM_NET_WM_STATE_MODAL])
+ win->ewmh_state |= MBWMClientWindowEWMHStateModal;
+ else if (result_atom[i] ==
+ wm->atoms[MBWM_ATOM_NET_WM_STATE_STICKY])
+ win->ewmh_state |= MBWMClientWindowEWMHStateSticky;
+ else if (result_atom[i] ==
+ wm->atoms[MBWM_ATOM_NET_WM_STATE_MAXIMIZED_VERT])
+ win->ewmh_state |= MBWMClientWindowEWMHStateMaximisedVert;
+ else if (result_atom[i] ==
+ wm->atoms[MBWM_ATOM_NET_WM_STATE_MAXIMIZED_HORZ])
+ win->ewmh_state |= MBWMClientWindowEWMHStateMaximisedHorz;
+ else if (result_atom[i] ==
+ wm->atoms[MBWM_ATOM_NET_WM_STATE_SHADED])
+ win->ewmh_state |= MBWMClientWindowEWMHStateShaded;
+ else if (result_atom[i] ==
+ wm->atoms[MBWM_ATOM_NET_WM_STATE_SKIP_TASKBAR])
+ win->ewmh_state |= MBWMClientWindowEWMHStateSkipTaskbar;
+ else if (result_atom[i] ==
+ wm->atoms[MBWM_ATOM_NET_WM_STATE_SKIP_PAGER])
+ win->ewmh_state |= MBWMClientWindowEWMHStateSkipPager;
+ else if (result_atom[i] ==
+ wm->atoms[MBWM_ATOM_NET_WM_STATE_HIDDEN])
+ win->ewmh_state |= MBWMClientWindowEWMHStateHidden;
+ else if (result_atom[i] ==
+ wm->atoms[MBWM_ATOM_NET_WM_STATE_FULLSCREEN])
+ win->ewmh_state |= MBWMClientWindowEWMHStateFullscreen;
+ else if (result_atom[i] ==
+ wm->atoms[MBWM_ATOM_NET_WM_STATE_ABOVE])
+ win->ewmh_state |= MBWMClientWindowEWMHStateAbove;
+ else if (result_atom[i] ==
+ wm->atoms[MBWM_ATOM_NET_WM_STATE_BELOW])
+ win->ewmh_state |= MBWMClientWindowEWMHStateBelow;
+ else if (result_atom[i] ==
+ wm->atoms[MBWM_ATOM_NET_WM_STATE_DEMANDS_ATTENTION])
+ win->ewmh_state |= MBWMClientWindowEWMHStateDemandsAttention;
+ }
+ }
+
+ changes |= MBWM_WINDOW_PROP_NET_STATE;
+
+ if (result_atom)
+ XFree(result_atom);
+
+ result_atom = NULL;
+ }
+
+ if (props_req & MBWM_WINDOW_PROP_GEOMETRY)
+ {
+ if (!mb_wm_xwin_get_geometry_reply (wm,
+ cookies[COOKIE_WIN_GEOM],
+ &win->x_geometry,
+ &foo,
+ &win->depth,
+ &x_error_code))
+ {
+ MBWM_DBG("### Warning Get Geometry Failed ( %i ) ###",
+ x_error_code);
+ MBWM_DBG("### Cookie ID was %li ###",
+ cookies[COOKIE_WIN_GEOM]);
+ goto abort;
+ }
+
+ MBWM_DBG("@@@ New Window Obj @@@");
+ MBWM_DBG("Win: %lx", win->xwindow);
+ MBWM_DBG("Type: %lx",win->net_type);
+ MBWM_DBG("Geom: +%i+%i,%ix%i",
+ win->x_geometry.x,
+ win->x_geometry.y,
+ win->x_geometry.width,
+ win->x_geometry.height);
+
+ /* FIXME is it right that we directly/immeditaly update
+ * win->geometry here, perhaps that should be left as a
+ * responsability for a signal handler? */
+ win->geometry = win->x_geometry;
+ }
+
+ if (props_req & MBWM_WINDOW_PROP_ATTR)
+ {
+ xwin_attr = mb_wm_xwin_get_attributes_reply (wm,
+ cookies[COOKIE_WIN_ATTR],
+ &x_error_code);
+
+ if (!xwin_attr || x_error_code)
+ {
+ MBWM_DBG("### Warning Get Attr Failed ( %i ) ###", x_error_code);
+ goto abort;
+ }
+
+ win->visual = xwin_attr->visual;
+ win->colormap = xwin_attr->colormap;
+
+ /* Window gravity should not be set from the window attribute
+ * but using the WM_NORMAL_HINTS atom
+ */
+
+ /* win->gravity = xwin_attr->win_gravity;*/
+ win->override_redirect = xwin_attr->override_redirect;
+ win->window_class = xwin_attr->class;
+ }
+
+ if (props_req & MBWM_WINDOW_PROP_NAME)
+ {
+ if (win->name)
+ XFree(win->name);
+
+ /* Prefer UTF8 Naming... */
+ win->name
+ = mb_wm_property_get_reply_and_validate (wm,
+ cookies[COOKIE_WIN_NAME_UTF8],
+ wm->atoms[MBWM_ATOM_UTF8_STRING],
+ 8,
+ 0,
+ NULL,
+ &x_error_code);
+
+ /* FIXME: Validate the UTF8 */
+
+ if (!win->name)
+ {
+ /* FIXME: Should flag up name could be in some wacko encoding ? */
+ win->name
+ = mb_wm_property_get_reply_and_validate (wm,
+ cookies[COOKIE_WIN_NAME],
+ XA_STRING,
+ 8,
+ 0,
+ NULL,
+ &x_error_code);
+ }
+
+ if (win->name == NULL)
+ win->name = strdup("unknown");
+
+ MBWM_DBG("@@@ New Window Name: '%s' @@@", win->name);
+
+ changes |= MBWM_WINDOW_PROP_NAME;
+ }
+
+ if (props_req & MBWM_WINDOW_PROP_WM_HINTS)
+ {
+ XWMHints *wmhints = NULL;
+
+ /* NOTE: pre-R3 X strips group element so will faill for that */
+ wmhints = mb_wm_property_get_reply_and_validate (wm,
+ cookies[COOKIE_WIN_WM_HINTS],
+ XA_WM_HINTS,
+ 32,
+ NumPropWMHintsElements,
+ NULL,
+ &x_error_code);
+
+ if (wmhints)
+ {
+ MBWM_DBG("@@@ New Window WM Hints @@@");
+
+ if (wmhints->flags & InputHint)
+ {
+ win->want_key_input = wmhints->input;
+ MBWM_DBG("Want key input: %s", wmhints->input ? "yes" : "no" );
+ }
+
+ if (wmhints->flags & StateHint)
+ {
+ win->initial_state = wmhints->initial_state;
+ MBWM_DBG("Initial State : %i", wmhints->initial_state );
+ }
+
+ if (wmhints->flags & IconPixmapHint)
+ {
+ win->icon_pixmap = wmhints->icon_pixmap;
+ MBWM_DBG("Icon Pixmap : %lx", wmhints->icon_pixmap );
+ }
+
+ if (wmhints->flags & IconMaskHint)
+ {
+ win->icon_pixmap_mask = wmhints->icon_mask;
+ MBWM_DBG("Icon Mask : %lx", wmhints->icon_mask );
+ }
+
+ if (wmhints->flags & WindowGroupHint)
+ {
+ win->xwin_group = wmhints->window_group;
+ MBWM_DBG("Window Group : %lx", wmhints->window_group );
+ }
+
+ /* NOTE: we ignore icon window stuff */
+
+ XFree(wmhints);
+
+ /* FIXME: should track better if thus has changed or not */
+ changes |= MBWM_WINDOW_PROP_WM_HINTS;
+ }
+ }
+ if (props_req & MBWM_WINDOW_PROP_WM_NORMAL_HINTS)
+ {
+ XSizeHints *sizehints = NULL;
+
+ sizehints = mb_wm_property_get_reply_and_validate (wm,
+ cookies[COOKIE_WIN_WM_NORMAL_HINTS],
+ XA_WM_SIZE_HINTS,
+ 32,
+ NumPropWMSizeHintsElements,
+ NULL,
+ &x_error_code);
+ if (sizehints)
+ {
+ MBWM_DBG("@@@ New Window WM Normal Hints @@@");
+
+ if (sizehints->flags & PWinGravity)
+ {
+ win->gravity = sizehints->win_gravity;
+ MBWM_DBG("Window Gravity : %i", sizehints->win_gravity);
+ }
+
+ win->user_pos = (sizehints->flags & USPosition) ? True : False;
+ MBWM_DBG ("User positioning : %s", win->user_pos ? "yes" : "no");
+
+ /* May be used to recover other information */
+
+ XFree (sizehints);
+
+ changes |= MBWM_WINDOW_PROP_WM_NORMAL_HINTS;
+ }
+
+ }
+
+ if (props_req & MBWM_WINDOW_PROP_MWM_HINTS)
+ {
+ /*
+ * Handle the Motif decoration hint (Gtk uses it).
+ *
+ * We currently only differentiate between decorated and undecorated
+ * windows, but do not allow finer customisation of the decor.
+ */
+ typedef struct
+ {
+ unsigned long flags;
+ unsigned long functions;
+ unsigned long decorations;
+ long inputMode;
+ unsigned long status;
+ } MotifWmHints;
+
+ MotifWmHints *mwmhints = NULL;
+
+ mwmhints =
+ mb_wm_property_get_reply_and_validate (wm,
+ cookies[COOKIE_WIN_MWM_HINTS],
+ wm->atoms[MBWM_ATOM_MOTIF_WM_HINTS],
+ 32,
+ PROP_MOTIF_WM_HINTS_ELEMENTS,
+ NULL,
+ &x_error_code);
+
+ if (mwmhints)
+ {
+ MBWM_DBG("@@@ New Window Motif WM Hints @@@");
+
+ if (mwmhints->flags & MWM_HINTS_DECORATIONS)
+ {
+ if (mwmhints->decorations == 0)
+ {
+ win->undecorated = TRUE;
+ }
+ }
+
+ XFree(mwmhints);
+
+ /* FIXME: should track better if thus has changed or not */
+ changes |= MBWM_WINDOW_PROP_MWM_HINTS;
+ }
+ }
+
+ if (props_req & MBWM_WINDOW_PROP_TRANSIENCY)
+ {
+ Window *trans_win = NULL;
+
+ trans_win
+ = mb_wm_property_get_reply_and_validate (wm,
+ cookies[COOKIE_WIN_TRANSIENCY],
+ MBWM_ATOM_WM_TRANSIENT_FOR,
+ 32,
+ 1,
+ NULL,
+ &x_error_code);
+
+ if (trans_win)
+ {
+ MBWM_DBG("@@@ Window transient for %lx @@@", *trans_win);
+
+ if (*trans_win != win->xwin_transient_for)
+ changes |= MBWM_WINDOW_PROP_TRANSIENCY;
+
+ win->xwin_transient_for = *trans_win;
+ XFree(trans_win);
+ }
+ else MBWM_DBG("@@@ Window transient for nothing @@@");
+
+ changes |= MBWM_WINDOW_PROP_TRANSIENCY;
+ }
+
+ if (props_req & MBWM_WINDOW_PROP_PROTOS)
+ {
+ mb_wm_property_reply (wm,
+ cookies[COOKIE_WIN_PROTOS],
+ &actual_type_return,
+ &actual_format_return,
+ &nitems_return,
+ &bytes_after_return,
+ (unsigned char **)&result_atom,
+ &x_error_code);
+
+ if (x_error_code
+ || actual_type_return != XA_ATOM
+ || actual_format_return != 32
+ || result_atom == NULL
+ )
+ {
+ MBWM_DBG("### Warning wm protocols prop failed ###");
+ }
+ else
+ {
+ int i;
+
+ for (i = 0; i < nitems_return; ++i)
+ {
+ if (result_atom[i] == wm->atoms[MBWM_ATOM_WM_TAKE_FOCUS])
+ win->protos |= MBWMClientWindowProtosFocus;
+ else if (result_atom[i] ==
+ wm->atoms[MBWM_ATOM_WM_DELETE_WINDOW])
+ win->protos |= MBWMClientWindowProtosDelete;
+ else if (result_atom[i] ==
+ wm->atoms[MBWM_ATOM_NET_WM_CONTEXT_HELP])
+ win->protos |= MBWMClientWindowProtosContextHelp;
+ else if (result_atom[i] ==
+ wm->atoms[MBWM_ATOM_NET_WM_CONTEXT_ACCEPT])
+ win->protos |= MBWMClientWindowProtosContextAccept;
+ else if (result_atom[i] ==
+ wm->atoms[MBWM_ATOM_NET_WM_CONTEXT_CUSTOM])
+ win->protos |= MBWMClientWindowProtosContextCustom;
+ else if (result_atom[i] ==
+ wm->atoms[MBWM_ATOM_NET_WM_PING])
+ win->protos |= MBWMClientWindowProtosPing;
+ else if (result_atom[i] ==
+ wm->atoms[MBWM_ATOM_NET_WM_SYNC_REQUEST])
+ win->protos |= MBWMClientWindowProtosSyncRequest;
+ else
+ MBWM_DBG("Unhandled WM Protocol %d", result_atom[i]);
+ }
+ }
+
+ if (result_atom)
+ XFree(result_atom);
+
+ changes |= MBWM_WINDOW_PROP_PROTOS;
+
+ result_atom = NULL;
+ }
+
+ if (props_req & MBWM_WINDOW_PROP_CLIENT_MACHINE)
+ {
+ if (win->machine)
+ XFree(win->machine);
+
+ win->machine
+ = mb_wm_property_get_reply_and_validate (wm,
+ cookies[COOKIE_WIN_MACHINE],
+ XA_STRING,
+ 8,
+ 0,
+ NULL,
+ &x_error_code);
+
+ if (!win->machine)
+ {
+ MBWM_DBG("### Warning wm client machine prop failed ###");
+ }
+ else
+ {
+ MBWM_DBG("@@@ Client machine %s @@@", win->machine);
+ }
+ }
+
+ if (props_req & MBWM_WINDOW_PROP_NET_PID)
+ {
+ unsigned int *pid = NULL;
+
+ mb_wm_property_reply (wm,
+ cookies[COOKIE_WIN_PID],
+ &actual_type_return,
+ &actual_format_return,
+ &nitems_return,
+ &bytes_after_return,
+ (unsigned char **)&pid,
+ &x_error_code);
+
+ if (x_error_code
+ || actual_type_return != XA_CARDINAL
+ || actual_format_return != 32
+ || pid == NULL
+ )
+ {
+ MBWM_DBG("### Warning net pid prop failed ###");
+ }
+ else
+ {
+ win->pid = (pid_t) *pid;
+ MBWM_DBG("@@@ pid %d @@@", win->pid);
+ }
+
+ if (pid)
+ XFree(pid);
+ }
+
+ if (props_req & MBWM_WINDOW_PROP_CM_TRANSLUCENCY)
+ {
+ int *translucency = NULL;
+
+ mb_wm_property_reply (wm,
+ cookies[COOKIE_WIN_CM_TRANSLUCENCY],
+ &actual_type_return,
+ &actual_format_return,
+ &nitems_return,
+ &bytes_after_return,
+ (unsigned char **)&translucency,
+ &x_error_code);
+
+ if (x_error_code
+ || actual_type_return != XA_CARDINAL
+ || actual_format_return != 32
+ || translucency == NULL
+ )
+ {
+ MBWM_DBG("### no CM_TRANSLUCENCY prop ###");
+ win->translucency = -1;
+ }
+ else
+ {
+ win->translucency = *translucency;
+ MBWM_DBG("@@@ translucency %d @@@", win->translucency);
+ }
+
+ changes |= MBWM_WINDOW_PROP_CM_TRANSLUCENCY;
+
+ if (translucency)
+ XFree (translucency);
+ }
+
+ if (props_req & MBWM_WINDOW_PROP_NET_ICON)
+ {
+ unsigned long *icons = NULL;
+
+ mb_wm_property_reply (wm,
+ cookies[COOKIE_WIN_ICON],
+ &actual_type_return,
+ &actual_format_return,
+ &nitems_return,
+ &bytes_after_return,
+ (unsigned char **)&icons,
+ &x_error_code);
+
+ if (x_error_code
+ || actual_type_return != XA_CARDINAL
+ || actual_format_return != 32
+ || icons == NULL
+ )
+ {
+ MBWM_DBG("### Warning net icon prop failed ###");
+ }
+ else
+ {
+ MBWMList *l = win->icons;
+ MBWMList *list_end = NULL;
+ unsigned long *p = icons;
+ unsigned long *p_end = icons + nitems_return;
+
+ while (l)
+ {
+ MBWMRgbaIcon * ic = l->data;
+
+ mb_wm_rgba_icon_free (ic);
+
+ l = l->next;
+ }
+
+ while (p < p_end)
+ {
+ l = mb_wm_util_malloc0 (sizeof (MBWMList));
+ p = icon_from_net_wm_icon (p, (MBWMRgbaIcon **)&l->data);
+
+ if (list_end)
+ {
+ l->prev = list_end;
+ list_end->next = l;
+ }
+ else
+ {
+ win->icons = l;
+ }
+
+ list_end = l;
+ }
+ }
+
+ if (icons)
+ XFree(icons);
+
+ changes |= MBWM_WINDOW_PROP_NET_ICON;
+
+ }
+
+ if (props_req & MBWM_WINDOW_PROP_NET_USER_TIME)
+ {
+ unsigned long *user_time = NULL;
+
+ mb_wm_property_reply (wm,
+ cookies[COOKIE_WIN_USER_TIME],
+ &actual_type_return,
+ &actual_format_return,
+ &nitems_return,
+ &bytes_after_return,
+ (unsigned char **)&user_time,
+ &x_error_code);
+
+ if (x_error_code
+ || actual_type_return != XA_CARDINAL
+ || actual_format_return != 32
+ || user_time == NULL
+ )
+ {
+ MBWM_DBG("### Warning _NET_WM_USER_TIME failed ###");
+ }
+ else
+ {
+ win->user_time = *user_time;
+ MBWM_DBG("@@@ user time %d @@@", win->user_time);
+ }
+
+ if (user_time)
+ XFree(user_time);
+ }
+
+
+ if (changes)
+ mb_wm_object_signal_emit (MB_WM_OBJECT (win), changes);
+
+ abort:
+
+ if (xwin_attr)
+ XFree(xwin_attr);
+
+ return True;
+}
+
+Bool
+mb_wm_client_window_is_state_set (MBWMClientWindow *win,
+ MBWMClientWindowEWMHState state)
+{
+ return (win->ewmh_state & state) ? True : False;
+}
+