diff options
Diffstat (limited to 'src/ui/frames.c')
-rw-r--r-- | src/ui/frames.c | 116 |
1 files changed, 100 insertions, 16 deletions
diff --git a/src/ui/frames.c b/src/ui/frames.c index 5691d242..c6e636dd 100644 --- a/src/ui/frames.c +++ b/src/ui/frames.c @@ -40,6 +40,10 @@ #define DEFAULT_INNER_BUTTON_BORDER 3 +#ifndef M_PI +#define M_PI 3.14159265358979323846264338327 +#endif + static void meta_frames_destroy (GtkWidget *widget); static void meta_frames_finalize (GObject *object); static void meta_frames_style_updated (GtkWidget *widget); @@ -841,22 +845,6 @@ meta_ui_frame_get_corner_radiuses (MetaFrames *frames, *bottom_right = fgeom.bottom_right_corner_rounded_radius + sqrt(fgeom.bottom_right_corner_rounded_radius); } -void -meta_frames_get_corner_radiuses (MetaFrames *frames, - Window xwindow, - float *top_left, - float *top_right, - float *bottom_left, - float *bottom_right) -{ - MetaUIFrame *frame; - - frame = meta_frames_lookup_window (frames, xwindow); - - meta_ui_frame_get_corner_radiuses (frames, frame, top_left, top_right, - bottom_left, bottom_right); -} - static void apply_cairo_region_to_window (Display *display, Window xwindow, @@ -2461,6 +2449,102 @@ find_frame_to_draw (MetaFrames *frames, return NULL; } +#define TAU (2*M_PI) + +/* + * Draw the opaque and semi-opaque pixels of this frame into a mask. + * + * (0,0) in Cairo coordinates is assumed to be the top left corner of the + * invisible border. + * + * The parts of @cr's surface in the clip region are assumed to be + * initialized to fully-transparent, and the clip region is assumed to + * contain the invisible border and the visible parts of the frame, but + * not the client area. + * + * This function uses @cr to draw pixels of arbitrary color (it will + * typically be drawing in a %CAIRO_FORMAT_A8 surface, so the color is + * discarded anyway) with appropriate alpha values to reproduce this + * frame's alpha channel, as a mask to be applied to an opaque pixmap. + * + * @frame: This frame + * @xwindow: The X window for the frame, which has the client window as a child + * @width: The width of the framed window including any invisible borders + * @height: The height of the framed window including any invisible borders + * @cr: Used to draw the resulting mask + */ +void +meta_frames_get_mask (MetaFrames *frames, + Window xwindow, + guint width, + guint height, + cairo_t *cr) +{ + MetaUIFrame *frame = meta_frames_lookup_window (frames, xwindow); + float top_left, top_right, bottom_left, bottom_right; + int x, y; + MetaFrameBorders borders; + + if (frame == NULL) + meta_bug ("No such frame 0x%lx\n", xwindow); + + cairo_save (cr); + + meta_ui_frame_get_borders (frames, frame, &borders); + meta_ui_frame_get_corner_radiuses (frames, frame, + &top_left, &top_right, + &bottom_left, &bottom_right); + + /* top left */ + x = borders.invisible.left; + y = borders.invisible.top; + + cairo_arc (cr, + x + top_left, + y + top_left, + top_left, + 2 * TAU / 4, + 3 * TAU / 4); + + /* top right */ + x = width - borders.invisible.right - top_right; + y = borders.invisible.top; + + cairo_arc (cr, + x, + y + top_right, + top_right, + 3 * TAU / 4, + 4 * TAU / 4); + + /* bottom right */ + x = width - borders.invisible.right - bottom_right; + y = height - borders.invisible.bottom - bottom_right; + + cairo_arc (cr, + x, + y, + bottom_right, + 0 * TAU / 4, + 1 * TAU / 4); + + /* bottom left */ + x = borders.invisible.left; + y = height - borders.invisible.bottom - bottom_left; + + cairo_arc (cr, + x + bottom_left, + y, + bottom_left, + 1 * TAU / 4, + 2 * TAU / 4); + + cairo_set_source_rgba (cr, 1, 1, 1, 1); + cairo_fill (cr); + + cairo_restore (cr); +} + static gboolean meta_frames_draw (GtkWidget *widget, cairo_t *cr) |