mirror of
https://github.com/brl/mutter.git
synced 2025-07-02 17:21:57 +00:00
Stop shaping the frame window
In preparation for switching to handling the output shape purely by what we paint, stop applying a shape to the frame of the window. Even when we restore handling the output shape, this will change the behavior with respect to input; transparent areas between the frame and the contents will stop clicks rather than passing them through, but that is arguably at least as expected considering how that we decorate shaped windows with a frame all around. https://bugzilla.gnome.org/show_bug.cgi?id=644930
This commit is contained in:
188
src/ui/frames.c
188
src/ui/frames.c
@ -862,39 +862,6 @@ meta_frames_unflicker_bg (MetaFrames *frames,
|
||||
set_background_none (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), frame->xwindow);
|
||||
}
|
||||
|
||||
#ifdef HAVE_SHAPE
|
||||
static void
|
||||
apply_cairo_region_to_window (Display *display,
|
||||
Window xwindow,
|
||||
cairo_region_t *region,
|
||||
int op)
|
||||
{
|
||||
int n_rects, i;
|
||||
XRectangle *rects;
|
||||
|
||||
n_rects = cairo_region_num_rectangles (region);
|
||||
rects = g_new (XRectangle, n_rects);
|
||||
|
||||
for (i = 0; i < n_rects; i++)
|
||||
{
|
||||
cairo_rectangle_int_t rect;
|
||||
|
||||
cairo_region_get_rectangle (region, i, &rect);
|
||||
|
||||
rects[i].x = rect.x;
|
||||
rects[i].y = rect.y;
|
||||
rects[i].width = rect.width;
|
||||
rects[i].height = rect.height;
|
||||
}
|
||||
|
||||
XShapeCombineRectangles (display, xwindow,
|
||||
ShapeBounding, 0, 0, rects, n_rects,
|
||||
op, YXBanded);
|
||||
|
||||
g_free (rects);
|
||||
}
|
||||
#endif
|
||||
|
||||
static cairo_region_t *
|
||||
get_bounds_region (MetaFrames *frames,
|
||||
MetaUIFrame *frame,
|
||||
@ -996,161 +963,6 @@ get_bounds_region (MetaFrames *frames,
|
||||
return bounds_region;
|
||||
}
|
||||
|
||||
static cairo_region_t *
|
||||
get_client_region (MetaFrameGeometry *fgeom,
|
||||
int window_width,
|
||||
int window_height)
|
||||
{
|
||||
cairo_rectangle_int_t rect;
|
||||
|
||||
rect.x = fgeom->left_width;
|
||||
rect.y = fgeom->top_height;
|
||||
rect.width = window_width - fgeom->right_width - rect.x;
|
||||
rect.height = window_height - fgeom->bottom_height - rect.y;
|
||||
|
||||
return cairo_region_create_rectangle (&rect);
|
||||
}
|
||||
|
||||
void
|
||||
meta_frames_apply_shapes (MetaFrames *frames,
|
||||
Window xwindow,
|
||||
int new_window_width,
|
||||
int new_window_height,
|
||||
gboolean window_has_shape)
|
||||
{
|
||||
#ifdef HAVE_SHAPE
|
||||
/* Apply shapes as if window had new_window_width, new_window_height */
|
||||
MetaUIFrame *frame;
|
||||
MetaFrameGeometry fgeom;
|
||||
cairo_region_t *window_region;
|
||||
Display *display;
|
||||
|
||||
frame = meta_frames_lookup_window (frames, xwindow);
|
||||
g_return_if_fail (frame != NULL);
|
||||
|
||||
display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
||||
|
||||
meta_frames_calc_geometry (frames, frame, &fgeom);
|
||||
|
||||
if (!(fgeom.top_left_corner_rounded_radius != 0 ||
|
||||
fgeom.top_right_corner_rounded_radius != 0 ||
|
||||
fgeom.bottom_left_corner_rounded_radius != 0 ||
|
||||
fgeom.bottom_right_corner_rounded_radius != 0 ||
|
||||
window_has_shape))
|
||||
{
|
||||
if (frame->shape_applied)
|
||||
{
|
||||
meta_topic (META_DEBUG_SHAPES,
|
||||
"Unsetting shape mask on frame 0x%lx\n",
|
||||
frame->xwindow);
|
||||
|
||||
XShapeCombineMask (display, frame->xwindow,
|
||||
ShapeBounding, 0, 0, None, ShapeSet);
|
||||
frame->shape_applied = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_topic (META_DEBUG_SHAPES,
|
||||
"Frame 0x%lx still doesn't need a shape mask\n",
|
||||
frame->xwindow);
|
||||
}
|
||||
|
||||
return; /* nothing to do */
|
||||
}
|
||||
|
||||
window_region = get_bounds_region (frames, frame,
|
||||
&fgeom,
|
||||
new_window_width, new_window_height);
|
||||
|
||||
if (window_has_shape)
|
||||
{
|
||||
/* The client window is oclock or something and has a shape
|
||||
* mask. To avoid a round trip to get its shape region, we
|
||||
* create a fake window that's never mapped, build up our shape
|
||||
* on that, then combine. Wasting the window is assumed cheaper
|
||||
* than a round trip, but who really knows for sure.
|
||||
*/
|
||||
XSetWindowAttributes attrs;
|
||||
Window shape_window;
|
||||
Window client_window;
|
||||
cairo_region_t *client_region;
|
||||
GdkScreen *screen;
|
||||
int screen_number;
|
||||
|
||||
meta_topic (META_DEBUG_SHAPES,
|
||||
"Frame 0x%lx needs to incorporate client shape\n",
|
||||
frame->xwindow);
|
||||
|
||||
screen = gtk_widget_get_screen (GTK_WIDGET (frames));
|
||||
screen_number = gdk_x11_screen_get_screen_number (screen);
|
||||
|
||||
attrs.override_redirect = True;
|
||||
|
||||
shape_window = XCreateWindow (display,
|
||||
RootWindow (display, screen_number),
|
||||
-5000, -5000,
|
||||
new_window_width,
|
||||
new_window_height,
|
||||
0,
|
||||
CopyFromParent,
|
||||
CopyFromParent,
|
||||
(Visual *)CopyFromParent,
|
||||
CWOverrideRedirect,
|
||||
&attrs);
|
||||
|
||||
/* Copy the client's shape to the temporary shape_window */
|
||||
meta_core_get (display, frame->xwindow,
|
||||
META_CORE_GET_CLIENT_XWINDOW, &client_window,
|
||||
META_CORE_GET_END);
|
||||
|
||||
XShapeCombineShape (display, shape_window, ShapeBounding,
|
||||
fgeom.left_width,
|
||||
fgeom.top_height,
|
||||
client_window,
|
||||
ShapeBounding,
|
||||
ShapeSet);
|
||||
|
||||
/* Punch the client area out of the normal frame shape,
|
||||
* then union it with the shape_window's existing shape
|
||||
*/
|
||||
client_region = get_client_region (&fgeom,
|
||||
new_window_width,
|
||||
new_window_height);
|
||||
|
||||
cairo_region_subtract (window_region, client_region);
|
||||
|
||||
cairo_region_destroy (client_region);
|
||||
|
||||
apply_cairo_region_to_window (display, shape_window,
|
||||
window_region, ShapeUnion);
|
||||
|
||||
/* Now copy shape_window shape to the real frame */
|
||||
XShapeCombineShape (display, frame->xwindow, ShapeBounding,
|
||||
0, 0,
|
||||
shape_window,
|
||||
ShapeBounding,
|
||||
ShapeSet);
|
||||
|
||||
XDestroyWindow (display, shape_window);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No shape on the client, so just do simple stuff */
|
||||
|
||||
meta_topic (META_DEBUG_SHAPES,
|
||||
"Frame 0x%lx has shaped corners\n",
|
||||
frame->xwindow);
|
||||
|
||||
apply_cairo_region_to_window (display, frame->xwindow,
|
||||
window_region, ShapeSet);
|
||||
}
|
||||
|
||||
frame->shape_applied = TRUE;
|
||||
|
||||
cairo_region_destroy (window_region);
|
||||
#endif /* HAVE_SHAPE */
|
||||
}
|
||||
|
||||
cairo_region_t *
|
||||
meta_frames_get_frame_bounds (MetaFrames *frames,
|
||||
Window xwindow,
|
||||
|
Reference in New Issue
Block a user