From 64e05c236fa9eb3826b0a34624d34a8cabac8129 Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Thu, 26 Jan 2017 10:43:49 +0100 Subject: [PATCH] xwindow: Add support for input shape from SHAPE 1.1 Signed-off-by: Uli Schlachter --- awesome.c | 10 ++++++ globalconf.h | 2 ++ xwindow.c | 91 ++++++++++++++++++++++++++++++++++------------------ 3 files changed, 71 insertions(+), 32 deletions(-) diff --git a/awesome.c b/awesome.c index 8aac69e6..56c8022b 100644 --- a/awesome.c +++ b/awesome.c @@ -661,6 +661,16 @@ main(int argc, char **argv) /* check for shape extension */ query = xcb_get_extension_data(globalconf.connection, &xcb_shape_id); globalconf.have_shape = query && query->present; + if (globalconf.have_shape) + { + xcb_shape_query_version_reply_t *reply = + xcb_shape_query_version_reply(globalconf.connection, + xcb_shape_query_version_unchecked(globalconf.connection), + NULL); + globalconf.have_input_shape = reply && (reply->major_version > 1 || + (reply->major_version == 1 && reply->minor_version >= 1)); + p_delete(&reply); + } event_init(); diff --git a/globalconf.h b/globalconf.h index 037af7c3..77e3a76b 100644 --- a/globalconf.h +++ b/globalconf.h @@ -106,6 +106,8 @@ typedef struct bool have_xtest; /** Check for SHAPE extension */ bool have_shape; + /** Check for SHAPE extension with input shape support */ + bool have_input_shape; /** Check for XKB extension */ bool have_xkb; uint8_t event_base_shape; diff --git a/xwindow.c b/xwindow.c index f1ec2881..2de67011 100644 --- a/xwindow.c +++ b/xwindow.c @@ -265,44 +265,70 @@ xwindow_get_shape(xcb_window_t win, enum xcb_shape_sk_t kind) { if (!globalconf.have_shape) return NULL; - - xcb_shape_query_extents_cookie_t ecookie = xcb_shape_query_extents(globalconf.connection, win); - xcb_shape_get_rectangles_cookie_t rcookie = xcb_shape_get_rectangles(globalconf.connection, win, kind); - xcb_shape_query_extents_reply_t *extents = xcb_shape_query_extents_reply(globalconf.connection, ecookie, NULL); - xcb_shape_get_rectangles_reply_t *rects_reply = xcb_shape_get_rectangles_reply(globalconf.connection, rcookie, NULL); - - if (!extents || !rects_reply) - { - free(extents); - free(rects_reply); - /* Create a cairo surface in an error state */ - return cairo_image_surface_create(CAIRO_FORMAT_INVALID, -1, -1); - } + if (kind == XCB_SHAPE_SK_INPUT && !globalconf.have_input_shape) + return NULL; int16_t x, y; uint16_t width, height; - bool shaped; - if (kind == XCB_SHAPE_SK_BOUNDING) + xcb_shape_get_rectangles_cookie_t rcookie = xcb_shape_get_rectangles(globalconf.connection, win, kind); + if (kind == XCB_SHAPE_SK_INPUT) { - x = extents->bounding_shape_extents_x; - y = extents->bounding_shape_extents_y; - width = extents->bounding_shape_extents_width; - height = extents->bounding_shape_extents_height; - shaped = extents->bounding_shaped; - } else { - assert(kind == XCB_SHAPE_SK_CLIP); - x = extents->clip_shape_extents_x; - y = extents->clip_shape_extents_y; - width = extents->clip_shape_extents_width; - height = extents->clip_shape_extents_height; - shaped = extents->clip_shaped; + /* We cannot query the size/existence of an input shape... */ + xcb_get_geometry_reply_t *geom = xcb_get_geometry_reply(globalconf.connection, + xcb_get_geometry(globalconf.connection, win), NULL); + if (!geom) + { + xcb_discard_reply(globalconf.connection, rcookie.sequence); + /* Create a cairo surface in an error state */ + return cairo_image_surface_create(CAIRO_FORMAT_INVALID, -1, -1); + } + x = 0; + y = 0; + width = geom->width; + height = geom->height; + } + else + { + xcb_shape_query_extents_cookie_t ecookie = xcb_shape_query_extents(globalconf.connection, win); + xcb_shape_query_extents_reply_t *extents = xcb_shape_query_extents_reply(globalconf.connection, ecookie, NULL); + bool shaped; + + if (!extents) + { + xcb_discard_reply(globalconf.connection, rcookie.sequence); + /* Create a cairo surface in an error state */ + return cairo_image_surface_create(CAIRO_FORMAT_INVALID, -1, -1); + } + + if (kind == XCB_SHAPE_SK_BOUNDING) + { + x = extents->bounding_shape_extents_x; + y = extents->bounding_shape_extents_y; + width = extents->bounding_shape_extents_width; + height = extents->bounding_shape_extents_height; + shaped = extents->bounding_shaped; + } else { + assert(kind == XCB_SHAPE_SK_CLIP); + x = extents->clip_shape_extents_x; + y = extents->clip_shape_extents_y; + width = extents->clip_shape_extents_width; + height = extents->clip_shape_extents_height; + shaped = extents->clip_shaped; + } + p_delete(&extents); + + if (!shaped) + { + xcb_discard_reply(globalconf.connection, rcookie.sequence); + return NULL; + } } - if (!shaped) + xcb_shape_get_rectangles_reply_t *rects_reply = xcb_shape_get_rectangles_reply(globalconf.connection, rcookie, NULL); + if (!rects_reply) { - free(extents); - free(rects_reply); - return NULL; + /* Create a cairo surface in an error state */ + return cairo_image_surface_create(CAIRO_FORMAT_INVALID, -1, -1); } cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_A1, width, height); @@ -318,7 +344,6 @@ xwindow_get_shape(xcb_window_t win, enum xcb_shape_sk_t kind) cairo_fill(cr); cairo_destroy(cr); - free(extents); free(rects_reply); return surface; } @@ -356,6 +381,8 @@ xwindow_set_shape(xcb_window_t win, int width, int height, enum xcb_shape_sk_t k { if (!globalconf.have_shape) return; + if (kind == XCB_SHAPE_SK_INPUT && !globalconf.have_input_shape) + return; xcb_pixmap_t pixmap = XCB_NONE; if (surf)