diff options
author | Jess VanDerwalker <washu@sonic.net> | 2012-07-25 11:16:55 -0700 |
---|---|---|
committer | Jess VanDerwalker <washu@sonic.net> | 2012-07-25 13:05:30 -0700 |
commit | d80dff4e181f830753500257a5e3dfc99a4ee390 (patch) | |
tree | ba332a47771cde9e8a3cb005824af3a2ba11199a | |
parent | 5b1f36b97142f6fb3139e31e744fdf691ab4290c (diff) |
libxcwm: Support for WM_TRANSIENT_FOR and WM_SIZE_HINTS added
Getting values of ICCCM properties has been changed to use the
xcb_icccm.h functions available to simplify library code.
On receiving a mapping event, WM_TRANSIENT_FOR and WM_SIZE_HINTS for
window are checked for the window, and values in xcwm_window_t are
set.
Enumeration added for different EWMH window types, currently only
XCWM_WINDOW_TYPE_DIALOG and XCWM_WINDOW_TYPE_NORMAL are used. A
xcwm_sizing_t structure was added to hold WM_SIZE_HINT data for the
window.
Signed-off-by: Jess VanDerwalker <washu@sonic.net>
Reviewed-by: Jeremy Huddleston Sequoia <jeremyhu@apple.com>
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | include/xcwm/window.h | 63 | ||||
-rw-r--r-- | src/libxcwm/window.c | 140 | ||||
-rw-r--r-- | src/libxcwm/xcwm_internal.h | 1 |
4 files changed, 160 insertions, 46 deletions
diff --git a/configure.ac b/configure.ac index bcb58fe..2db540d 100644 --- a/configure.ac +++ b/configure.ac @@ -20,7 +20,7 @@ AC_PROG_OBJC AC_PROG_INSTALL # Checks for libraries. -PKG_CHECK_MODULES(XCB, xcb-damage xcb-composite xcb-event xcb-xtest xcb-image xcb-keysyms xcb-icccm xcb-atom) +PKG_CHECK_MODULES(XCB, xcb-damage xcb-composite xcb-event xcb-xtest xcb-image xcb-keysyms xcb-icccm xcb-atom xcb-ewmh) AC_CHECK_FUNC(dispatch_async, AC_DEFINE([HAVE_LIBDISPATCH], 1, [Define to 1 if you have the libdispatch (GCD) available]) diff --git a/include/xcwm/window.h b/include/xcwm/window.h index 71b5c2b..af2774d 100644 --- a/include/xcwm/window.h +++ b/include/xcwm/window.h @@ -41,14 +41,53 @@ struct xcwm_rect_t { }; typedef struct xcwm_rect_t xcwm_rect_t; +/** + * Enumeration for different possible window types + */ +enum xcwm_window_type_t { + XCWM_WINDOW_TYPE_UNKNOWN = 0, + XCWM_WINDOW_TYPE_COMBO, + XCWM_WINDOW_TYPE_DESKTOP, + XCWM_WINDOW_TYPE_DIALOG, + XCWM_WINDOW_TYPE_DND, + XCWM_WINDOW_TYPE_DOCK, + XCWM_WINDOW_TYPE_DROPDOWN_MENU, + XCWM_WINDOW_TYPE_MENU, + XCWM_WINDOW_TYPE_NORMAL, + XCWM_WINDOW_TYPE_NOTIFICATION, + XCWM_WINDOW_TYPE_POPUP_MENU, + XCWM_WINDOW_TYPE_SPLASH, + XCWM_WINDOW_TYPE_TOOLBAR, + XCWM_WINDOW_TYPE_TOOLTIP, + XCWM_WINDOW_TYPE_UTILITY, +}; +typedef enum xcwm_window_type_t xcwm_window_type_t; + +/** + * Structure defining min/max size for window and resizing + * increments. A value of 0 in any field implies the field is unset. + */ +struct xcwm_window_sizing_t { + uint32_t min_width; + uint32_t min_height; + uint32_t max_width; + uint32_t max_height; + uint32_t width_inc; + uint32_t height_inc; +}; +typedef struct xcwm_window_sizing_t xcwm_window_sizing_t; + /* Structure for holding data for a window */ struct xcwm_window_t { xcb_drawable_t window_id; xcwm_context_t *context; + xcwm_window_type_t type; /* The type of this window */ struct xcwm_window_t *parent; + struct xcwm_window_t *transient_for; /* Window this one is transient for */ xcb_damage_damage_t damage; xcwm_rect_t *bounds; xcwm_rect_t *dmg_bounds; + xcwm_window_sizing_t *sizing; /* Sizing information for the window */ char *name; /* The name of the window */ int wm_delete_set; /* Flag for WM_DELETE_WINDOW, 1 if set */ int override_redirect; @@ -104,6 +143,14 @@ xcwm_window_configure(xcwm_window_t *window, int x, int y, int height, int width); /** + * Get the window's type. + * @param window Window to get type for. + * @return The type of the window. + */ +xcwm_window_type_t +xcwm_window_get_window_type(xcwm_window_t const *window); + +/** * Get the context for this window. * @param window The window to get context from. * @return The context of the window. @@ -120,6 +167,14 @@ xcwm_window_t * xcwm_window_get_parent(xcwm_window_t const *window); /** + * Get the window the given window is transient for. + * @param window + * @return This windows "transient for" window, NULL if none. + */ +xcwm_window_t const * +xcwm_window_get_transient_for(xcwm_window_t const *window); + +/** * Determine if window has override redirect flag set. * @param window * @return 1 if override redirect set on window, else 0. @@ -168,4 +223,12 @@ xcwm_window_get_damaged_rect(xcwm_window_t const *window); char * xcwm_window_copy_name(xcwm_window_t const *window); +/** + * Get the sizing information for the window. + * @param window The window to get sizing data for. + * @return The structure containing the sizing data + */ +xcwm_window_sizing_t const * +xcwm_window_get_sizing(xcwm_window_t const *window); + #endif /* _XCWM_WINDOW_H_ */ diff --git a/src/libxcwm/window.c b/src/libxcwm/window.c index e5c6699..bf6c70c 100644 --- a/src/libxcwm/window.c +++ b/src/libxcwm/window.c @@ -29,6 +29,8 @@ #include <xcb/xfixes.h> #include <xcb/damage.h> +#include <xcb/xcb_icccm.h> +#include <xcb/xcb_ewmh.h> #include <xcwm/xcwm.h> #include "xcwm_internal.h" @@ -47,6 +49,10 @@ set_wm_name_in_context(xcb_connection_t *conn, xcwm_window_t *window); void set_wm_delete_win_in_context(xcb_connection_t *conn, xcwm_window_t *window); +/* Determine values of window WM_SIZE_HINTS */ +void +set_wm_size_hints_for_window(xcb_connection_t *conn, xcwm_window_t *window); + /* Initialize damage on a window */ void init_damage_on_window(xcb_connection_t *conn, xcwm_window_t *window); @@ -303,6 +309,13 @@ _xcwm_window_release(xcwm_window_t *window) /* Accessor functions into xcwm_window_t */ +xcwm_window_type_t +xcwm_window_get_window_type(xcwm_window_t const *window) +{ + + return window->type; +} + xcwm_context_t * xcwm_window_get_context(xcwm_window_t const *window) { @@ -317,6 +330,13 @@ xcwm_window_get_parent(xcwm_window_t const *window) return window->parent; } +xcwm_window_t const * +xcwm_window_get_transient_for(xcwm_window_t const *window) +{ + + return window->transient_for; +} + int xcwm_window_is_override_redirect(xcwm_window_t const *window) { @@ -359,6 +379,13 @@ xcwm_window_copy_name(xcwm_window_t const *window) return strdup(window->name); } +xcwm_window_sizing_t const * +xcwm_window_get_sizing(xcwm_window_t const *window) +{ + + return window->sizing; +} + /* Resize the window on server side */ void _xcwm_resize_window(xcb_connection_t *conn, xcb_window_t window, @@ -386,81 +413,104 @@ _xcwm_map_window(xcb_connection_t *conn, xcwm_window_t *window) void set_icccm_properties(xcb_connection_t *conn, xcwm_window_t *window) { + xcb_get_property_cookie_t cookie; + xcb_window_t transient; + xcb_generic_error_t *error; + uint8_t success; + set_wm_name_in_context(conn, window); set_wm_delete_win_in_context(conn, window); + set_wm_size_hints_for_window(conn, window); + + /* Get the window this one is transient for */ + cookie = xcb_icccm_get_wm_transient_for(conn, window->window_id); + success = xcb_icccm_get_wm_transient_for_reply(conn, cookie, + &transient, &error); + if (success) { + window->transient_for = _xcwm_get_window_node_by_window_id(transient); + /* FIXME: Currently we assume that any window that is + * transient for another is a dialog. */ + window->type = XCWM_WINDOW_TYPE_DIALOG; + } else { + window->transient_for = NULL; + window->type = XCWM_WINDOW_TYPE_NORMAL; + } } void set_wm_name_in_context(xcb_connection_t *conn, xcwm_window_t *window) { xcb_get_property_cookie_t cookie; - xcb_get_property_reply_t *reply; + xcb_icccm_get_text_property_reply_t reply; xcb_generic_error_t *error; - char *value; - int length; - - cookie = xcb_get_property(conn, - 0, - window->window_id, - XCB_ATOM_WM_NAME, - XCB_GET_PROPERTY_TYPE_ANY, - 0, - 128); - reply = xcb_get_property_reply(conn, cookie, &error); - if (!reply) { - window->name = NULL; + + cookie = xcb_icccm_get_wm_name(conn, window->window_id); + if (!xcb_icccm_get_wm_name_reply(conn, cookie, &reply, &error)) { + window->name = malloc(sizeof(char)); + window->name[0] = '\0'; return; } - length = xcb_get_property_value_length(reply); - value = (char *)xcb_get_property_value(reply); - window->name = malloc(sizeof(char) * (length + 1)); - strncpy(window->name, value, length); - window->name[length] = '\0'; + window->name = malloc(sizeof(char) * (reply.name_len + 1)); + strncpy(window->name, reply.name, reply.name_len); + window->name[reply.name_len] = '\0'; + xcb_icccm_get_text_property_reply_wipe(&reply); } void set_wm_delete_win_in_context(xcb_connection_t *conn, xcwm_window_t *window) { xcb_get_property_cookie_t cookie; - xcb_get_property_reply_t *reply; - xcb_atom_t *prop_atoms; - int prop_length; + xcb_icccm_get_wm_protocols_reply_t reply; xcb_generic_error_t *error; int i; /* Get the WM_PROTOCOLS */ - cookie = xcb_get_property(conn, - 0, - window->window_id, - _wm_atoms->wm_protocols_atom, - XCB_ATOM_ATOM, - 0, - UINT_MAX); - - reply = xcb_get_property_reply(conn, cookie, &error); - - if (!reply) { + cookie = xcb_icccm_get_wm_protocols(conn, window->window_id, + _wm_atoms->wm_protocols_atom); + + if (xcb_icccm_get_wm_protocols_reply(conn, cookie, &reply, &error) == 1) { + /* See if the WM_DELETE_WINDOW is in WM_PROTOCOLS */ + for (i = 0; i < reply.atoms_len; i++) { + if (reply.atoms[i] == _wm_atoms->wm_delete_window_atom) { + window->wm_delete_set = 1; + break; + } + } + } else { window->wm_delete_set = 0; return; } - prop_length = xcb_get_property_value_length(reply); - prop_atoms = (xcb_atom_t *)xcb_get_property_value(reply); - free(reply); - - /* See if the WM_DELETE_WINDOW is in WM_PROTOCOLS */ - for (i = 0; i < prop_length; i++) { - if (prop_atoms[i] == _wm_atoms->wm_delete_window_atom) { - window->wm_delete_set = 1; - return; - } - } - window->wm_delete_set = 0; + xcb_icccm_get_wm_protocols_reply_wipe(&reply); return; } void +set_wm_size_hints_for_window(xcb_connection_t *conn, xcwm_window_t *window) +{ + xcb_get_property_cookie_t cookie; + xcb_size_hints_t hints; + + if (window->sizing) { + free(window->sizing); + } + window->sizing = malloc(sizeof(xcwm_window_sizing_t)); + assert(window->sizing); + cookie = xcb_icccm_get_wm_normal_hints(conn, window->window_id); + if (!xcb_icccm_get_wm_normal_hints_reply(conn, cookie, &hints, NULL)) { + memset(window->sizing, 0, sizeof(*window->sizing); + return; + } + window->sizing->min_width = hints.min_width; + window->sizing->min_height = hints.min_height;; + window->sizing->max_width = hints.max_width; + window->sizing->max_height = hints.max_height; + window->sizing->width_inc = hints.width_inc; + window->sizing->height_inc = hints.height_inc; +} + +void init_damage_on_window(xcb_connection_t *conn, xcwm_window_t *window) { xcb_damage_damage_t damage_id; diff --git a/src/libxcwm/xcwm_internal.h b/src/libxcwm/xcwm_internal.h index 5bd58f9..ab149e5 100644 --- a/src/libxcwm/xcwm_internal.h +++ b/src/libxcwm/xcwm_internal.h @@ -52,6 +52,7 @@ typedef struct xcwm_event_connetion { typedef struct xcwm_wm_atoms { xcb_atom_t wm_protocols_atom; xcb_atom_t wm_delete_window_atom; + xcb_atom_t wm_transient_for_atom; } xcwm_wm_atoms; /** |