[metacity/wip/gtk-theme: 14/41] Only shadow ARGB windows with a frame outside the frame
- From: Alberts Muktupāvels <muktupavels src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [metacity/wip/gtk-theme: 14/41] Only shadow ARGB windows with a frame outside the frame
- Date: Wed, 7 Jan 2015 12:37:17 +0000 (UTC)
commit 46e11a9bf9591773226b28211955e9c8db84ee24
Author: Owen W. Taylor <otaylor fishsoup net>
Date: Tue Mar 22 15:36:12 2011 -0400
Only shadow ARGB windows with a frame outside the frame
An ARGB window with a frame is likely something like a transparent
terminal. It looks awful (and breaks transparency) to draw a big
opaque black shadow under the window, so clip out the region under
the terminal from the shadow we draw.
Add meta_window_get_frame_bounds() to get a cairo region for the
outer bounds of the frame of a window, and modify the frame handling
code to notice changes to the frame shape and discard a cached
region. meta_frames_apply_shapes() is refactored so we can extract
meta_frames_get_frame_bounds() from it.
https://bugzilla.gnome.org/show_bug.cgi?id=635268
NOTE: Applied only partially, compositor part is still missing...
src/core/frame-private.h | 4 +-
src/core/frame.c | 22 +++++-
src/core/window-private.h | 4 +
src/core/window.c | 46 ++++++++++--
src/include/ui.h | 6 ++
src/include/window.h | 3 +
src/ui/frames.c | 188 +++++++++++++++++++++++++++++----------------
src/ui/frames.h | 4 +
src/ui/ui.c | 12 +++
9 files changed, 210 insertions(+), 79 deletions(-)
---
diff --git a/src/core/frame-private.h b/src/core/frame-private.h
index fe9cdb7..1bd30c2 100644
--- a/src/core/frame-private.h
+++ b/src/core/frame-private.h
@@ -60,11 +60,13 @@ MetaFrameFlags meta_frame_get_flags (MetaFrame *frame);
/* These should ONLY be called from meta_window_move_resize_internal */
void meta_frame_calc_borders (MetaFrame *frame,
MetaFrameBorders *borders);
-void meta_frame_sync_to_window (MetaFrame *frame,
+gboolean meta_frame_sync_to_window (MetaFrame *frame,
int gravity,
gboolean need_move,
gboolean need_resize);
+cairo_region_t *meta_frame_get_frame_bounds (MetaFrame *frame);
+
void meta_frame_set_screen_cursor (MetaFrame *frame,
MetaCursor cursor);
diff --git a/src/core/frame.c b/src/core/frame.c
index 176fad0..85a2a19 100644
--- a/src/core/frame.c
+++ b/src/core/frame.c
@@ -317,7 +317,7 @@ meta_frame_calc_borders (MetaFrame *frame,
borders);
}
-static void
+static gboolean
update_shape (MetaFrame *frame)
{
if (frame->need_reapply_frame_shape)
@@ -328,10 +328,14 @@ update_shape (MetaFrame *frame)
frame->rect.height,
frame->window->has_shape);
frame->need_reapply_frame_shape = FALSE;
+
+ return TRUE;
}
+ else
+ return FALSE;
}
-void
+gboolean
meta_frame_sync_to_window (MetaFrame *frame,
int resize_gravity,
gboolean need_move,
@@ -339,8 +343,7 @@ meta_frame_sync_to_window (MetaFrame *frame,
{
if (!(need_move || need_resize))
{
- update_shape (frame);
- return;
+ return update_shape (frame);
}
meta_topic (META_DEBUG_GEOMETRY,
@@ -390,6 +393,17 @@ meta_frame_sync_to_window (MetaFrame *frame,
meta_ui_repaint_frame (frame->window->screen->ui,
frame->xwindow);
}
+
+ return need_resize;
+}
+
+cairo_region_t *
+meta_frame_get_frame_bounds (MetaFrame *frame)
+{
+ return meta_ui_get_frame_bounds (frame->window->screen->ui,
+ frame->xwindow,
+ frame->rect.width,
+ frame->rect.height);
}
void
diff --git a/src/core/window-private.h b/src/core/window-private.h
index 91a6257..aa12e3c 100644
--- a/src/core/window-private.h
+++ b/src/core/window-private.h
@@ -39,6 +39,7 @@
#include "stack.h"
#include "iconcache.h"
#include <X11/Xutil.h>
+#include <cairo.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
typedef struct _MetaGroup MetaGroup;
@@ -315,6 +316,9 @@ struct _MetaWindow
/* if TRUE, application is buggy and SYNC resizing is turned off */
guint disable_sync : 1;
+ /* if non-NULL, the bounds of the window frame */
+ cairo_region_t *frame_bounds;
+
/* Note: can be NULL */
GSList *struts;
diff --git a/src/core/window.c b/src/core/window.c
index 0d909ac..23fb504 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -506,6 +506,7 @@ meta_window_new_with_attrs (MetaDisplay *display,
window->shaken_loose = FALSE;
window->have_focus_click_grab = FALSE;
window->disable_sync = FALSE;
+ window->frame_bounds = NULL;
window->unmaps_pending = 0;
@@ -1174,6 +1175,9 @@ meta_window_free (MetaWindow *window,
if (window->mini_icon)
g_object_unref (G_OBJECT (window->mini_icon));
+ if (window->frame_bounds)
+ cairo_region_destroy (window->frame_bounds);
+
meta_icon_cache_free (&window->icon_cache);
g_free (window->sm_client_id);
@@ -3354,6 +3358,7 @@ meta_window_move_resize_internal (MetaWindow *window,
int frame_size_dy;
int size_dx;
int size_dy;
+ gboolean frame_shape_changed = FALSE;
gboolean is_configure_request;
gboolean do_gravity_adjust;
gboolean is_user_action;
@@ -3654,9 +3659,10 @@ meta_window_move_resize_internal (MetaWindow *window,
meta_window_set_gravity (window, StaticGravity);
if (configure_frame_first && window->frame)
- meta_frame_sync_to_window (window->frame,
- gravity,
- need_move_frame, need_resize_frame);
+ frame_shape_changed = meta_frame_sync_to_window (window->frame,
+ gravity,
+ need_move_frame,
+ need_resize_frame);
values.border_width = 0;
values.x = client_move_x;
@@ -3711,9 +3717,10 @@ meta_window_move_resize_internal (MetaWindow *window,
}
if (!configure_frame_first && window->frame)
- meta_frame_sync_to_window (window->frame,
- gravity,
- need_move_frame, need_resize_frame);
+ frame_shape_changed = meta_frame_sync_to_window (window->frame,
+ gravity,
+ need_move_frame,
+ need_resize_frame);
/* Put gravity back to be nice to lesser window managers */
if (use_static_gravity)
@@ -3754,6 +3761,12 @@ meta_window_move_resize_internal (MetaWindow *window,
* b) all constraints are obeyed by window->rect and frame->rect
*/
+ if (frame_shape_changed && window->frame_bounds)
+ {
+ cairo_region_destroy (window->frame_bounds);
+ window->frame_bounds = NULL;
+ }
+
if (meta_prefs_get_attach_modal_dialogs ())
meta_window_foreach_transient (window, move_attached_dialog, NULL);
}
@@ -8541,3 +8554,24 @@ meta_window_is_client_decorated (MetaWindow *window)
*/
return window->has_custom_frame_extents;
}
+
+/**
+ * meta_window_get_frame_bounds:
+ *
+ * Gets a region representing the outer bounds of the window's frame.
+ *
+ * Return value: (transfer none) (allow-none): a #cairo_region_t
+ * holding the outer bounds of the window, or %NULL if the window
+ * doesn't have a frame.
+ */
+cairo_region_t *
+meta_window_get_frame_bounds (MetaWindow *window)
+{
+ if (!window->frame_bounds)
+ {
+ if (window->frame)
+ window->frame_bounds = meta_frame_get_frame_bounds (window->frame);
+ }
+
+ return window->frame_bounds;
+}
diff --git a/src/include/ui.h b/src/include/ui.h
index 68d4168..d2dd07c 100644
--- a/src/include/ui.h
+++ b/src/include/ui.h
@@ -26,6 +26,7 @@
#include "common.h"
#include <X11/Xlib.h>
#include <X11/Xutil.h>
+#include <cairo.h>
#include <glib.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
@@ -100,6 +101,11 @@ void meta_ui_apply_frame_shape (MetaUI *ui,
int new_window_height,
gboolean window_has_shape);
+cairo_region_t *meta_ui_get_frame_bounds (MetaUI *ui,
+ Window xwindow,
+ int window_width,
+ int window_height);
+
void meta_ui_queue_frame_draw (MetaUI *ui,
Window xwindow);
diff --git a/src/include/window.h b/src/include/window.h
index 011f6eb..20e34ad 100644
--- a/src/include/window.h
+++ b/src/include/window.h
@@ -21,6 +21,7 @@
#define META_WINDOW_H
#include <glib.h>
+#include <cairo.h>
#include <X11/Xlib.h>
#include "boxes.h"
@@ -36,4 +37,6 @@ Window meta_window_get_xwindow (MetaWindow *window);
MetaWindow *meta_window_get_transient_for (MetaWindow *window);
gboolean meta_window_is_maximized (MetaWindow *window);
+cairo_region_t *meta_window_get_frame_bounds (MetaWindow *window);
+
#endif
diff --git a/src/ui/frames.c b/src/ui/frames.c
index fff98b6..0a4c5a1 100644
--- a/src/ui/frames.c
+++ b/src/ui/frames.c
@@ -872,57 +872,22 @@ apply_cairo_region_to_window (Display *display,
}
#endif
-void
-meta_frames_apply_shapes (MetaFrames *frames,
- Window xwindow,
- int new_window_width,
- int new_window_height,
- gboolean window_has_shape)
+static cairo_region_t *
+get_bounds_region (MetaFrames *frames,
+ MetaUIFrame *frame,
+ MetaFrameGeometry *fgeom,
+ int window_width,
+ int window_height)
{
-#ifdef HAVE_SHAPE
- /* Apply shapes as if window had new_window_width, new_window_height */
- MetaUIFrame *frame;
- MetaFrameGeometry fgeom;
- cairo_rectangle_int_t rect;
cairo_region_t *corners_region;
- cairo_region_t *window_region;
-
- frame = meta_frames_lookup_window (frames, xwindow);
- g_return_if_fail (frame != NULL);
-
- 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 (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), 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 */
- }
+ cairo_region_t *bounds_region;
+ cairo_rectangle_int_t rect;
corners_region = cairo_region_create ();
- if (fgeom.top_left_corner_rounded_radius != 0)
+ if (fgeom->top_left_corner_rounded_radius != 0)
{
- const int corner = fgeom.top_left_corner_rounded_radius;
+ const int corner = fgeom->top_left_corner_rounded_radius;
const float radius = sqrt(corner) + corner;
int i;
@@ -938,16 +903,16 @@ meta_frames_apply_shapes (MetaFrames *frames,
}
}
- if (fgeom.top_right_corner_rounded_radius != 0)
+ if (fgeom->top_right_corner_rounded_radius != 0)
{
- const int corner = fgeom.top_right_corner_rounded_radius;
+ const int corner = fgeom->top_right_corner_rounded_radius;
const float radius = sqrt(corner) + corner;
int i;
for (i=0; i<corner; i++)
{
const int width = floor(0.5 + radius - sqrt(radius*radius - (radius-(i+0.5))*(radius-(i+0.5))));
- rect.x = new_window_width - width;
+ rect.x = window_width - width;
rect.y = i;
rect.width = width;
rect.height = 1;
@@ -956,9 +921,9 @@ meta_frames_apply_shapes (MetaFrames *frames,
}
}
- if (fgeom.bottom_left_corner_rounded_radius != 0)
+ if (fgeom->bottom_left_corner_rounded_radius != 0)
{
- const int corner = fgeom.bottom_left_corner_rounded_radius;
+ const int corner = fgeom->bottom_left_corner_rounded_radius;
const float radius = sqrt(corner) + corner;
int i;
@@ -966,7 +931,7 @@ meta_frames_apply_shapes (MetaFrames *frames,
{
const int width = floor(0.5 + radius - sqrt(radius*radius - (radius-(i+0.5))*(radius-(i+0.5))));
rect.x = 0;
- rect.y = new_window_height - i - 1;
+ rect.y = window_height - i - 1;
rect.width = width;
rect.height = 1;
@@ -974,17 +939,17 @@ meta_frames_apply_shapes (MetaFrames *frames,
}
}
- if (fgeom.bottom_right_corner_rounded_radius != 0)
+ if (fgeom->bottom_right_corner_rounded_radius != 0)
{
- const int corner = fgeom.bottom_right_corner_rounded_radius;
+ const int corner = fgeom->bottom_right_corner_rounded_radius;
const float radius = sqrt(corner) + corner;
int i;
for (i=0; i<corner; i++)
{
const int width = floor(0.5 + radius - sqrt(radius*radius - (radius-(i+0.5))*(radius-(i+0.5))));
- rect.x = new_window_width - width;
- rect.y = new_window_height - i - 1;
+ rect.x = window_width - width;
+ rect.y = window_height - i - 1;
rect.width = width;
rect.height = 1;
@@ -992,19 +957,90 @@ meta_frames_apply_shapes (MetaFrames *frames,
}
}
- window_region = cairo_region_create ();
+ bounds_region = cairo_region_create ();
rect.x = 0;
rect.y = 0;
- rect.width = new_window_width;
- rect.height = new_window_height;
+ rect.width = window_width;
+ rect.height = window_height;
- cairo_region_union_rectangle (window_region, &rect);
+ cairo_region_union_rectangle (bounds_region, &rect);
- cairo_region_subtract (window_region, corners_region);
+ cairo_region_subtract (bounds_region, corners_region);
cairo_region_destroy (corners_region);
+ 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
@@ -1056,14 +1092,9 @@ meta_frames_apply_shapes (MetaFrames *frames,
/* Punch the client area out of the normal frame shape,
* then union it with the shape_window's existing shape
*/
- client_region = cairo_region_create ();
-
- rect.x = fgeom.left_width;
- rect.y = fgeom.top_height;
- rect.width = new_window_width - fgeom.right_width - rect.x;
- rect.height = new_window_height - fgeom.bottom_height - rect.y;
-
- cairo_region_union_rectangle (client_region, &rect);
+ client_region = get_client_region (&fgeom,
+ new_window_width,
+ new_window_height);
cairo_region_subtract (window_region, client_region);
@@ -1099,6 +1130,27 @@ meta_frames_apply_shapes (MetaFrames *frames,
#endif /* HAVE_SHAPE */
}
+cairo_region_t *
+meta_frames_get_frame_bounds (MetaFrames *frames,
+ Window xwindow,
+ int window_width,
+ int window_height)
+{
+ MetaUIFrame *frame;
+ MetaFrameGeometry fgeom;
+
+ frame = meta_frames_lookup_window (frames, xwindow);
+ g_return_val_if_fail (frame != NULL, NULL);
+
+ meta_frames_calc_geometry (frames, frame, &fgeom);
+
+ return get_bounds_region (frames,
+ frame,
+ &fgeom,
+ window_width,
+ window_height);
+}
+
void
meta_frames_move_resize_frame (MetaFrames *frames,
Window xwindow,
diff --git a/src/ui/frames.h b/src/ui/frames.h
index d4b2dee..9ab997f 100644
--- a/src/ui/frames.h
+++ b/src/ui/frames.h
@@ -148,6 +148,10 @@ void meta_frames_apply_shapes (MetaFrames *frames,
int new_window_width,
int new_window_height,
gboolean window_has_shape);
+cairo_region_t *meta_frames_get_frame_bounds (MetaFrames *frames,
+ Window xwindow,
+ int window_width,
+ int window_height);
void meta_frames_move_resize_frame (MetaFrames *frames,
Window xwindow,
int x,
diff --git a/src/ui/ui.c b/src/ui/ui.c
index 8351dfb..fc379ce 100644
--- a/src/ui/ui.c
+++ b/src/ui/ui.c
@@ -465,6 +465,18 @@ meta_ui_apply_frame_shape (MetaUI *ui,
window_has_shape);
}
+cairo_region_t *
+meta_ui_get_frame_bounds (MetaUI *ui,
+ Window xwindow,
+ int window_width,
+ int window_height)
+{
+ return meta_frames_get_frame_bounds (ui->frames,
+ xwindow,
+ window_width,
+ window_height);
+}
+
void
meta_ui_queue_frame_draw (MetaUI *ui,
Window xwindow)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]