Skip to content

Commit 522ad73

Browse files
owtaylorvkareh
authored andcommitted
Convert frame region handling to cairo regions
It's useful to get frame shapes and manipulate them within Mutter, for example so that the compositor can use them to clip drawing. For this, we'll need the regions as cairo regions not X regions, so convert frame shaping code to work in terms of cairo_region_t. https://bugzilla.gnome.org/show_bug.cgi?id=635268
1 parent 93b5dd1 commit 522ad73

File tree

1 file changed

+79
-43
lines changed

1 file changed

+79
-43
lines changed

src/ui/frames.c

Lines changed: 79 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -780,6 +780,39 @@ meta_frames_unflicker_bg (MetaFrames *frames,
780780
set_background_none (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), frame->xwindow);
781781
}
782782

783+
#ifdef HAVE_SHAPE
784+
static void
785+
apply_cairo_region_to_window (Display *display,
786+
Window xwindow,
787+
cairo_region_t *region,
788+
int op)
789+
{
790+
int n_rects, i;
791+
XRectangle *rects;
792+
793+
n_rects = cairo_region_num_rectangles (region);
794+
rects = g_new (XRectangle, n_rects);
795+
796+
for (i = 0; i < n_rects; i++)
797+
{
798+
cairo_rectangle_int_t rect;
799+
800+
cairo_region_get_rectangle (region, i, &rect);
801+
802+
rects[i].x = rect.x;
803+
rects[i].y = rect.y;
804+
rects[i].width = rect.width;
805+
rects[i].height = rect.height;
806+
}
807+
808+
XShapeCombineRectangles (display, xwindow,
809+
ShapeBounding, 0, 0, rects, n_rects,
810+
ShapeSet, YXBanded);
811+
812+
g_free (rects);
813+
}
814+
#endif
815+
783816
void
784817
meta_frames_apply_shapes (MetaFrames *frames,
785818
Window xwindow,
@@ -794,6 +827,9 @@ meta_frames_apply_shapes (MetaFrames *frames,
794827
XRectangle xrect;
795828
Region corners_xregion;
796829
Region window_xregion;
830+
cairo_rectangle_int_t rect;
831+
cairo_region_t *corners_region;
832+
cairo_region_t *window_region;
797833
gint scale;
798834

799835
frame = meta_frames_lookup_window (frames, xwindow);
@@ -827,7 +863,7 @@ meta_frames_apply_shapes (MetaFrames *frames,
827863
return; /* nothing to do */
828864
}
829865

830-
corners_xregion = XCreateRegion ();
866+
corners_region = cairo_region_create ();
831867
scale = gdk_window_get_scale_factor (frame->window);
832868

833869
if (fgeom.top_left_corner_rounded_radius != 0)
@@ -839,12 +875,12 @@ meta_frames_apply_shapes (MetaFrames *frames,
839875
for (i=0; i<corner; i++)
840876
{
841877
const int width = floor(0.5 + radius - sqrt(radius*radius - (radius-(i+0.5))*(radius-(i+0.5))));
842-
xrect.x = 0;
843-
xrect.y = i;
844-
xrect.width = width;
845-
xrect.height = 1;
878+
rect.x = 0;
879+
rect.y = i;
880+
rect.width = width;
881+
rect.height = 1;
846882

847-
XUnionRectWithRegion (&xrect, corners_xregion, corners_xregion);
883+
cairo_region_union_rectangle (corners_region, &rect);
848884
}
849885
}
850886

@@ -857,12 +893,12 @@ meta_frames_apply_shapes (MetaFrames *frames,
857893
for (i=0; i<corner; i++)
858894
{
859895
const int width = floor(0.5 + radius - sqrt(radius*radius - (radius-(i+0.5))*(radius-(i+0.5))));
860-
xrect.x = new_window_width - width;
861-
xrect.y = i;
862-
xrect.width = width;
863-
xrect.height = 1;
896+
rect.x = new_window_width - width;
897+
rect.y = i;
898+
rect.width = width;
899+
rect.height = 1;
864900

865-
XUnionRectWithRegion (&xrect, corners_xregion, corners_xregion);
901+
cairo_region_union_rectangle (corners_region, &rect);
866902
}
867903
}
868904

@@ -875,12 +911,12 @@ meta_frames_apply_shapes (MetaFrames *frames,
875911
for (i=0; i<corner; i++)
876912
{
877913
const int width = floor(0.5 + radius - sqrt(radius*radius - (radius-(i+0.5))*(radius-(i+0.5))));
878-
xrect.x = 0;
879-
xrect.y = new_window_height - i - 1;
880-
xrect.width = width;
881-
xrect.height = 1;
914+
rect.x = 0;
915+
rect.y = new_window_height - i - 1;
916+
rect.width = width;
917+
rect.height = 1;
882918

883-
XUnionRectWithRegion (&xrect, corners_xregion, corners_xregion);
919+
cairo_region_union_rectangle (corners_region, &rect);
884920
}
885921
}
886922

@@ -893,27 +929,27 @@ meta_frames_apply_shapes (MetaFrames *frames,
893929
for (i=0; i<corner; i++)
894930
{
895931
const int width = floor(0.5 + radius - sqrt(radius*radius - (radius-(i+0.5))*(radius-(i+0.5))));
896-
xrect.x = new_window_width - width;
897-
xrect.y = new_window_height - i - 1;
898-
xrect.width = width;
899-
xrect.height = 1;
932+
rect.x = new_window_width - width;
933+
rect.y = new_window_height - i - 1;
934+
rect.width = width;
935+
rect.height = 1;
900936

901-
XUnionRectWithRegion (&xrect, corners_xregion, corners_xregion);
937+
cairo_region_union_rectangle (corners_region, &rect);
902938
}
903939
}
904940

905-
window_xregion = XCreateRegion ();
941+
window_region = cairo_region_create ();
906942

907-
xrect.x = 0;
908-
xrect.y = 0;
909-
xrect.width = new_window_width;
910-
xrect.height = new_window_height;
943+
rect.x = 0;
944+
rect.y = 0;
945+
rect.width = new_window_width;
946+
rect.height = new_window_height;
911947

912-
XUnionRectWithRegion (&xrect, window_xregion, window_xregion);
948+
cairo_region_union_rectangle (window_region, &rect);
913949

914-
XSubtractRegion (window_xregion, corners_xregion, window_xregion);
950+
cairo_region_subtract (window_region, corners_region);
915951

916-
XDestroyRegion (corners_xregion);
952+
cairo_region_destroy (corners_region);
917953

918954
if (window_has_shape)
919955
{
@@ -926,7 +962,7 @@ meta_frames_apply_shapes (MetaFrames *frames,
926962
XSetWindowAttributes attrs;
927963
Window shape_window;
928964
Window client_window;
929-
Region client_xregion;
965+
cairo_region_t *client_region;
930966
GdkScreen *screen;
931967
int screen_number;
932968

@@ -966,21 +1002,21 @@ meta_frames_apply_shapes (MetaFrames *frames,
9661002
/* Punch the client area out of the normal frame shape,
9671003
* then union it with the shape_window's existing shape
9681004
*/
969-
client_xregion = XCreateRegion ();
1005+
client_region = cairo_region_create ();
9701006

971-
xrect.x = fgeom.left_width;
972-
xrect.y = fgeom.top_height;
973-
xrect.width = new_window_width - fgeom.right_width - xrect.x;
974-
xrect.height = new_window_height - fgeom.bottom_height - xrect.y;
1007+
rect.x = fgeom.left_width;
1008+
rect.y = fgeom.top_height;
1009+
rect.width = new_window_width - fgeom.right_width - rect.x;
1010+
rect.height = new_window_height - fgeom.bottom_height - rect.y;
9751011

976-
XUnionRectWithRegion (&xrect, client_xregion, client_xregion);
1012+
cairo_region_union_rectangle (client_region, &rect);
9771013

978-
XSubtractRegion (window_xregion, client_xregion, window_xregion);
1014+
cairo_region_subtract (window_region, client_region);
9791015

980-
XDestroyRegion (client_xregion);
1016+
cairo_region_destroy (client_region);
9811017

982-
XShapeCombineRegion (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), shape_window,
983-
ShapeBounding, 0, 0, window_xregion, ShapeUnion);
1018+
apply_cairo_region_to_window (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), shape_window,
1019+
window_region, ShapeUnion);
9841020

9851021
/* Now copy shape_window shape to the real frame */
9861022
XShapeCombineShape (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), frame->xwindow, ShapeBounding,
@@ -999,13 +1035,13 @@ meta_frames_apply_shapes (MetaFrames *frames,
9991035
"Frame 0x%lx has shaped corners\n",
10001036
frame->xwindow);
10011037

1002-
XShapeCombineRegion (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), frame->xwindow,
1003-
ShapeBounding, 0, 0, window_xregion, ShapeSet);
1038+
apply_cairo_region_to_window (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), frame->xwindow,
1039+
window_region, ShapeSet);
10041040
}
10051041

10061042
frame->shape_applied = TRUE;
10071043

1008-
XDestroyRegion (window_xregion);
1044+
cairo_region_destroy (window_region);
10091045
#endif /* HAVE_SHAPE */
10101046
}
10111047

0 commit comments

Comments
 (0)