Fix input and bounding shapes

1) We need to select for shape events
2) For decorated windows, we don't want to apply any input
   shape, because the frame is always rectangular and eats
   all the input
3) For undecorated windows, the "has input shape" check is
   wrong if the window has a bounding shape but not an input
   shape
This commit is contained in:
Giovanni Campagna 2014-02-25 01:06:26 +01:00
parent bdbeafc222
commit a3a2109c0c
2 changed files with 55 additions and 23 deletions

View File

@ -1760,21 +1760,27 @@ meta_window_actor_update_input_region (MetaWindowActor *self,
MetaWindowActorPrivate *priv = self->priv;
cairo_region_t *region = NULL;
if (priv->window->frame != NULL && priv->window->input_region != NULL)
if (priv->window->frame != NULL)
{
region = meta_frame_get_frame_bounds (priv->window->frame);
cairo_region_subtract_rectangle (region, client_area);
/* input_region is in client window coordinates, so translate the
/* client area is in client window coordinates, so translate the
* input region into that coordinate system and back */
cairo_region_translate (region, -client_area->x, -client_area->y);
cairo_region_union (region, priv->window->input_region);
cairo_region_union_rectangle (region, client_area);
cairo_region_translate (region, client_area->x, client_area->y);
}
else if (priv->window->input_region != NULL)
else if (priv->window->shape_region != NULL ||
priv->window->input_region != NULL)
{
region = cairo_region_reference (priv->window->input_region);
if (priv->window->shape_region != NULL)
{
region = cairo_region_copy (priv->window->shape_region);
if (priv->window->input_region != NULL)
cairo_region_intersect (region, priv->window->input_region);
}
else
region = cairo_region_reference (priv->window->input_region);
}
else
{

View File

@ -350,11 +350,43 @@ meta_window_set_input_region (MetaWindow *window,
meta_compositor_window_shape_changed (window->display->compositor, window);
}
#if 0
/* Print out a region; useful for debugging */
static void
print_region (cairo_region_t *region)
{
int n_rects;
int i;
n_rects = cairo_region_num_rectangles (region);
g_print ("[");
for (i = 0; i < n_rects; i++)
{
cairo_rectangle_int_t rect;
cairo_region_get_rectangle (region, i, &rect);
g_print ("+%d+%dx%dx%d ",
rect.x, rect.y, rect.width, rect.height);
}
g_print ("]\n");
}
#endif
void
meta_window_x11_update_input_region (MetaWindow *window)
{
cairo_region_t *region = NULL;
/* Decorated windows don't have an input region, because
we don't shape the frame to match the client windows
(so the events are blocked by the frame anyway)
*/
if (window->decorated)
{
if (window->input_region)
meta_window_set_input_region (window, NULL);
return;
}
#ifdef HAVE_SHAPE
if (META_DISPLAY_HAS_SHAPE (window->display))
{
@ -363,17 +395,6 @@ meta_window_x11_update_input_region (MetaWindow *window)
XRectangle *rects = NULL;
int n_rects, ordering;
int x_bounding, y_bounding, x_clip, y_clip;
unsigned w_bounding, h_bounding, w_clip, h_clip;
int bounding_shaped, clip_shaped;
meta_error_trap_push (window->display);
XShapeQueryExtents (window->display->xdisplay, window->xwindow,
&bounding_shaped, &x_bounding, &y_bounding,
&w_bounding, &h_bounding,
&clip_shaped, &x_clip, &y_clip,
&w_clip, &h_clip);
rects = XShapeGetRectangles (window->display->xdisplay,
window->xwindow,
ShapeInput,
@ -388,10 +409,10 @@ meta_window_x11_update_input_region (MetaWindow *window)
{
if (n_rects > 1 ||
(n_rects == 1 &&
(rects[0].x != x_bounding ||
rects[0].y != y_bounding ||
rects[0].width != w_bounding ||
rects[0].height != h_bounding)))
(rects[0].x != 0 ||
rects[0].y != 0 ||
rects[0].width != window->rect.width ||
rects[0].height != window->rect.height)))
region = region_create_from_x_rectangles (rects, n_rects);
XFree (rects);
@ -1453,6 +1474,11 @@ meta_window_x11_new (MetaDisplay *display,
XISelectEvents (display->xdisplay, xwindow, &mask, 1);
}
#ifdef HAVE_SHAPE
if (META_DISPLAY_HAS_SHAPE (display))
XShapeSelectInput (display->xdisplay, xwindow, ShapeNotifyMask);
#endif
/* Get rid of any borders */
if (attrs.border_width != 0)
XSetWindowBorderWidth (display->xdisplay, xwindow, 0);