diff options
author | LuoYi | 2021-11-10 11:21:09 +0800 |
---|---|---|
committer | LuoYi | 2021-11-10 11:21:09 +0800 |
commit | d51c25288e64de45415d84a073f0f859a746940b (patch) | |
tree | 977100258b6bcb21d6f2053f6b71219814bd3761 /rounded_corners.patch | |
parent | 7218870add342087c12eba80304f3dee4f1d8261 (diff) | |
download | aur-d51c25288e64de45415d84a073f0f859a746940b.tar.gz |
Bumping version to 41.1
Diffstat (limited to 'rounded_corners.patch')
-rw-r--r-- | rounded_corners.patch | 1759 |
1 files changed, 1759 insertions, 0 deletions
diff --git a/rounded_corners.patch b/rounded_corners.patch new file mode 100644 index 000000000000..25f13a2fa546 --- /dev/null +++ b/rounded_corners.patch @@ -0,0 +1,1759 @@ +diff --git a/data/org.gnome.mutter.gschema.xml.in b/data/org.gnome.mutter.gschema.xml.in +index 23fa9f3ad..eee73e708 100644 +--- a/data/org.gnome.mutter.gschema.xml.in ++++ b/data/org.gnome.mutter.gschema.xml.in +@@ -2,6 +2,78 @@ + <schema id="org.gnome.mutter" path="/org/gnome/mutter/" + gettext-domain="@GETTEXT_DOMAIN@"> + ++ <key name="blur-sigmal" type="i"> ++ <default>20</default> ++ <range min="0" max="100"/> ++ <summary>Blur sigmal</summary> ++ </key> ++ ++ <key name="blur-brightness" type="i"> ++ <default>100</default> ++ <range min="0" max="100"/> ++ <summary>Blur brightness</summary> ++ </key> ++ ++ <key name="blur-list" type="as"> ++ <default>[]</default> ++ <summary>windows will enable blur effect</summary> ++ </key> ++ ++ <key name="blur-window-opacity" type="i"> ++ <default>80</default> ++ <range min="0" max="100"/> ++ <summary>Blur brightness</summary> ++ </key> ++ ++ <key name="border-width" type="i"> ++ <default>0</default> ++ <range min="0" max="100"/> ++ <summary>Window border</summary> ++ </key> ++ ++ <key name="round-corners-radius" type="i"> ++ <default>12</default> ++ <range min="2" max="100"/> ++ <summary>Round Corners Radius</summary> ++ </key> ++ ++ <key name="clip-edge-padding" type="s"> ++ <default>"{\"global\": [0, 0, 0, 0], \"apps\": {}}"</default> ++ <summary>padding of window will be clipped</summary> ++ <description> ++ A JSON string, Represents the clipping range of the window edge. ++ The array represents the clipping range of the four sides (left, ++ right, top, bottom) of the window. ++ ++ The key of "apps" object represent the instance part of the window's ++ `WM_CLASS` property, as same as the output of `xprop WM_CLASS|cut -d ++ \" -f 2` ++ ++ This is a example: ++ ++ { ++ 'global': [1, 2, 3, 4], ++ 'apps': { ++ 'code': [5, 6, 7, 8], ++ 'typora': [9, 10, 11, 12] ++ } ++ } ++ ++ For all window, cut the left, right, top and bottom sides by 1, 2 ++ , 3 and 4 pixels respectively. But for Visual Studio Code and ++ Typora, we will cut different pixels. ++ </description> ++ </key> ++ ++ <key name="black-list" type="as"> ++ <default>["qq.exe", "tim.exe"]</default> ++ <summary>window here will not be rounded</summary> ++ <description> ++ The contents of the list represent the instance part of the window's ++ `WM_CLASS`, as same as the output of `xprop WM_CLASS|cut -d \" -f 2` ++ </description> ++ </key> ++ + <key name="overlay-key" type="s"> + <default>'Super_L'</default> + <summary>Modifier to use for extended window management operations</summary> +diff --git a/src/compositor/compositor-private.h b/src/compositor/compositor-private.h +index 580618e48..f62de1924 100644 +--- a/src/compositor/compositor-private.h ++++ b/src/compositor/compositor-private.h +@@ -82,6 +82,8 @@ gboolean meta_compositor_is_switching_workspace (MetaCompositor *compositor); + + MetaLaters * meta_compositor_get_laters (MetaCompositor *compositor); + ++void meta_compositor_update_blur_behind(MetaCompositor *compositor); ++ + /* + * This function takes a 64 bit time stamp from the monotonic clock, and clamps + * it to the scope of the X server clock, without losing the granularity. +diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c +index 1770550d4..552d7bb24 100644 +--- a/src/compositor/compositor.c ++++ b/src/compositor/compositor.c +@@ -84,6 +84,8 @@ + #include "wayland/meta-wayland-private.h" + #endif + ++#include "core/meta-workspace-manager-private.h" ++ + enum + { + PROP_0, +@@ -615,6 +617,10 @@ meta_compositor_add_window (MetaCompositor *compositor, + * before we first paint. + */ + priv->windows = g_list_append (priv->windows, window_actor); ++ ++ if (window->client_type == META_WINDOW_CLIENT_TYPE_X11) ++ meta_window_actor_create_blur_actor(window_actor); ++ + sync_actor_stacking (compositor); + } + +@@ -661,6 +667,7 @@ meta_compositor_queue_frame_drawn (MetaCompositor *compositor, + MetaWindowActor *window_actor = meta_window_actor_from_window (window); + + meta_window_actor_queue_frame_drawn (window_actor, no_delay_frame); ++ meta_compositor_update_blur_behind(compositor); + } + + void +@@ -992,6 +999,20 @@ meta_compositor_sync_stack (MetaCompositor *compositor, + + sync_actor_stacking (compositor); + ++ MetaWorkspaceManager *manager = priv->display->workspace_manager; ++ MetaWorkspace *active_workspace = manager->active_workspace; ++ ++ for (GList *l = priv->windows; l; l = l->next) ++ { ++ MetaWindow *window = meta_window_actor_get_meta_window(l->data); ++ MetaWorkspace *workspace = meta_window_get_workspace(window); ++ if (workspace == active_workspace) ++ { ++ meta_window_actor_set_blur_behind(l->data); ++ meta_window_actor_update_blur_position_size(l->data); ++ } ++ } ++ + top_window_actor = get_top_visible_window_actor (compositor); + + if (priv->top_window_actor == top_window_actor) +@@ -1022,7 +1043,17 @@ meta_compositor_sync_window_geometry (MetaCompositor *compositor, + changes = meta_window_actor_sync_actor_geometry (window_actor, did_placement); + + if (changes & META_WINDOW_ACTOR_CHANGE_SIZE) ++ { ++ if (meta_window_actor_should_clip(window_actor)) ++ meta_window_actor_update_clipped_bounds(window_actor); + meta_plugin_manager_event_size_changed (priv->plugin_mgr, window_actor); ++ meta_window_actor_update_blur_position_size(window_actor); ++ } ++ ++ if (changes & META_WINDOW_ACTOR_CHANGE_POSITION) ++ meta_window_actor_update_blur_position_size(window_actor); ++ ++ meta_compositor_update_blur_behind(compositor); + } + + static void +@@ -1188,6 +1219,44 @@ meta_compositor_get_property (GObject *object, + } + } + ++static void ++prefs_changed_cb(MetaPreference pref, ++ gpointer user_data) ++{ ++ MetaCompositor *compositor = user_data; ++ MetaCompositorPrivate *priv = ++ meta_compositor_get_instance_private (compositor); ++ GList *l; ++ ++ for (l = priv->windows; l; l = l->next) ++ { ++ switch (pref) ++ { ++ case META_PREF_CORNER_RADIUS: ++ case META_PREF_CLIP_EDGE_PADDING: ++ case META_PREF_BORDER_WIDTH: ++ if (pref == META_PREF_CLIP_EDGE_PADDING) ++ meta_window_actor_update_clip_padding (l->data); ++ ++ meta_window_actor_update_clipped_bounds (l->data); ++ meta_window_actor_update_glsl (l->data); ++ clutter_actor_queue_redraw (CLUTTER_ACTOR (l->data)); ++ break; ++ case META_PREF_BLUR_SIGMAL: ++ meta_window_actor_update_blur_sigmal (l->data); ++ break; ++ case META_PREF_BLUR_BRIGHTNESS: ++ meta_window_actor_update_blur_brightness (l->data); ++ break; ++ case META_PREF_BLUR_WINDOW_OPACITY: ++ meta_window_actor_update_blur_window_opacity (l->data); ++ break; ++ default: ++ break; ++ } ++ } ++} ++ + static void + meta_compositor_init (MetaCompositor *compositor) + { +@@ -1218,6 +1287,8 @@ meta_compositor_constructed (GObject *object) + + priv->laters = meta_laters_new (compositor); + ++ meta_prefs_add_listener(prefs_changed_cb, compositor); ++ + G_OBJECT_CLASS (meta_compositor_parent_class)->constructed (object); + } + +@@ -1243,6 +1314,8 @@ meta_compositor_dispose (GObject *object) + g_clear_pointer (&priv->feedback_group, clutter_actor_destroy); + g_clear_pointer (&priv->windows, g_list_free); + ++ meta_prefs_remove_listener(prefs_changed_cb, compositor); ++ + G_OBJECT_CLASS (meta_compositor_parent_class)->dispose (object); + } + +@@ -1576,3 +1649,20 @@ meta_compositor_get_laters (MetaCompositor *compositor) + + return priv->laters; + } ++ ++void meta_compositor_update_blur_behind(MetaCompositor *compositor) ++{ ++ MetaCompositorPrivate *priv = ++ meta_compositor_get_instance_private (compositor); ++ ++ MetaWorkspaceManager *manager = priv->display->workspace_manager; ++ MetaWorkspace *active_workspace = manager->active_workspace; ++ ++ for (GList *l = priv->windows; l; l = l->next) ++ { ++ MetaWindow *window = meta_window_actor_get_meta_window(l->data); ++ MetaWorkspace *workspace = meta_window_get_workspace(window); ++ if (workspace == active_workspace) ++ meta_window_actor_set_blur_behind(l->data); ++ } ++} +\ No newline at end of file +diff --git a/src/compositor/meta-window-actor-private.h b/src/compositor/meta-window-actor-private.h +index 64741e416..98495f3d7 100644 +--- a/src/compositor/meta-window-actor-private.h ++++ b/src/compositor/meta-window-actor-private.h +@@ -99,4 +99,15 @@ void meta_window_actor_update_regions (MetaWindowActor *self); + + gboolean meta_window_actor_can_freeze_commits (MetaWindowActor *self); + ++gboolean meta_window_actor_should_clip (MetaWindowActor *self); ++void meta_window_actor_update_clipped_bounds (MetaWindowActor *window_actor); ++void meta_window_actor_update_glsl (MetaWindowActor *self); ++void meta_window_actor_get_corner_rect (MetaWindowActor *self, MetaRectangle *rect); ++void meta_window_actor_update_clip_padding (MetaWindowActor *self); ++void meta_window_actor_create_blur_actor (MetaWindowActor *self); ++void meta_window_actor_set_blur_behind (MetaWindowActor *self); ++void meta_window_actor_update_blur_position_size (MetaWindowActor *self); ++void meta_window_actor_update_blur_sigmal (MetaWindowActor *self); ++void meta_window_actor_update_blur_brightness (MetaWindowActor *self); ++void meta_window_actor_update_blur_window_opacity (MetaWindowActor *self); + #endif /* META_WINDOW_ACTOR_PRIVATE_H */ +diff --git a/src/compositor/meta-window-actor-wayland.c b/src/compositor/meta-window-actor-wayland.c +index 641c924db..28f1920f8 100644 +--- a/src/compositor/meta-window-actor-wayland.c ++++ b/src/compositor/meta-window-actor-wayland.c +@@ -24,10 +24,36 @@ + #include "compositor/meta-window-actor-wayland.h" + #include "meta/meta-window-actor.h" + #include "wayland/meta-wayland-surface.h" ++#include "meta/meta-shadow-factory.h" ++#include "ui/frames.h" ++#include "compositor/compositor-private.h" + + struct _MetaWindowActorWayland + { + MetaWindowActor parent; ++ ++ /* copy from meta-window-actor-x11.c */ ++ MetaShadow *focused_shadow; ++ MetaShadow *unfocused_shadow; ++ gboolean recompute_focused_shadow; ++ gboolean recompute_unfocused_shadow; ++ ++ /* The region we should clip to when painting the shadow */ ++ cairo_region_t *shadow_clip; ++ /* The frame region */ ++ cairo_region_t *frame_bounds; ++ /* A region that matches the shape of the window, including frame bounds */ ++ cairo_region_t *shape_region; ++ ++ MetaWindowShape *shadow_shape; ++ ++ gboolean need_reshape; ++ ++ MetaShadowFactory *shadow_factory; ++ gulong shadow_factory_changed_handler_id; ++ gulong size_changed_id; ++ gulong repaint_scheduled_id; ++ + }; + + G_DEFINE_TYPE (MetaWindowActorWayland, meta_window_actor_wayland, META_TYPE_WINDOW_ACTOR) +@@ -88,18 +114,54 @@ meta_window_actor_wayland_rebuild_surface_tree (MetaWindowActor *actor) + &traverse_data); + } + ++static void ++surface_size_changed (MetaSurfaceActor *actor, ++ gpointer user_data) ++{ ++ MetaWindowActorWayland *actor_wayland = META_WINDOW_ACTOR_WAYLAND (user_data); ++ actor_wayland->need_reshape = TRUE; ++} ++ ++static void ++surface_repaint_scheduled (MetaSurfaceActor *actor, ++ gpointer user_data) ++{ ++ MetaWindowActorWayland *actor_wayland = META_WINDOW_ACTOR_WAYLAND (user_data); ++ MetaWindow *window = meta_window_actor_get_meta_window (META_WINDOW_ACTOR(actor_wayland)); ++ meta_compositor_update_blur_behind( meta_display_get_compositor (window->display)); ++} ++ ++ + static void + meta_window_actor_wayland_assign_surface_actor (MetaWindowActor *actor, + MetaSurfaceActor *surface_actor) + { + MetaWindowActorClass *parent_class = + META_WINDOW_ACTOR_CLASS (meta_window_actor_wayland_parent_class); ++ MetaSurfaceActor *prev_surface_actor; ++ MetaWindowActorWayland *actor_wayland = META_WINDOW_ACTOR_WAYLAND (actor); ++ + + g_warn_if_fail (!meta_window_actor_get_surface (actor)); + ++ prev_surface_actor = meta_window_actor_get_surface (actor); ++ if (prev_surface_actor) ++ g_clear_signal_handler (&META_WINDOW_ACTOR_WAYLAND (actor)->size_changed_id, ++ prev_surface_actor); ++ + parent_class->assign_surface_actor (actor, surface_actor); + + meta_window_actor_wayland_rebuild_surface_tree (actor); ++ ++ actor_wayland->size_changed_id = ++ g_signal_connect (surface_actor, "size-changed", ++ G_CALLBACK (surface_size_changed), ++ actor_wayland); ++ ++ actor_wayland->repaint_scheduled_id = ++ g_signal_connect (surface_actor, "repaint-scheduled", ++ G_CALLBACK (surface_repaint_scheduled), ++ actor_wayland); + } + + static void +@@ -115,10 +177,287 @@ meta_window_actor_wayland_queue_frame_drawn (MetaWindowActor *actor, + { + } + ++static const char * ++get_shadow_class (MetaWindowActorWayland *actor_x11) ++{ ++ MetaWindow *window = ++ meta_window_actor_get_meta_window (META_WINDOW_ACTOR (actor_x11)); ++ MetaWindowType window_type; ++ ++ window_type = meta_window_get_window_type (window); ++ switch (window_type) ++ { ++ case META_WINDOW_DROPDOWN_MENU: ++ case META_WINDOW_COMBO: ++ return "dropdown-menu"; ++ case META_WINDOW_POPUP_MENU: ++ return "popup-menu"; ++ default: ++ { ++ MetaFrameType frame_type; ++ ++ frame_type = meta_window_get_frame_type (window); ++ return meta_frame_type_to_string (frame_type); ++ } ++ } ++} ++ ++static void ++invalidate_shadow (MetaWindowActorWayland *actor_wayland) ++{ ++ actor_wayland->recompute_focused_shadow = TRUE; ++ actor_wayland->recompute_unfocused_shadow = TRUE; ++ ++ if (meta_window_actor_is_frozen (META_WINDOW_ACTOR (actor_wayland))) ++ return; ++ ++ clutter_actor_queue_redraw (CLUTTER_ACTOR (actor_wayland)); ++ clutter_actor_invalidate_paint_volume (CLUTTER_ACTOR (actor_wayland)); ++} ++ ++static void ++update_shape_region (MetaWindowActorWayland *actor_wayland) ++{ ++ MetaWindow *window = ++ meta_window_actor_get_meta_window (META_WINDOW_ACTOR (actor_wayland)); ++ cairo_region_t *region = NULL; ++ cairo_rectangle_int_t client_area; ++ ++ if (meta_window_actor_should_clip(META_WINDOW_ACTOR(actor_wayland)) && !window->frame) ++ { ++ meta_window_actor_get_corner_rect(META_WINDOW_ACTOR(actor_wayland), &client_area); ++ region = cairo_region_create_rectangle(&client_area); ++ } ++ else ++ { ++ return; ++ } ++ ++ g_clear_pointer (&actor_wayland->shape_region, cairo_region_destroy); ++ actor_wayland->shape_region = region; ++ ++ g_clear_pointer (&actor_wayland->shadow_shape, meta_window_shape_unref); ++ ++ invalidate_shadow (actor_wayland); ++} ++ ++static cairo_region_t * ++meta_window_get_clipped_frame_bounds(MetaWindow *window) ++{ ++ g_return_val_if_fail(window, NULL); ++ ++ MetaWindowActor *actor = meta_window_actor_from_window(window); ++ if (actor && !window->frame_bounds) ++ { ++ MetaRectangle rect; ++ meta_window_actor_get_corner_rect(actor, &rect); ++ window->frame_bounds = ++ meta_ui_frame_get_bounds_clipped(&rect, ++ meta_prefs_get_round_corner_radius()); ++ } ++ return window->frame_bounds; ++} ++ ++static void ++update_frame_bounds (MetaWindowActorWayland *actor_wayland) ++{ ++ MetaWindow *window = ++ meta_window_actor_get_meta_window (META_WINDOW_ACTOR (actor_wayland)); ++ ++ g_clear_pointer (&actor_wayland->frame_bounds, cairo_region_destroy); ++ ++ if (meta_window_actor_should_clip(META_WINDOW_ACTOR(actor_wayland))) ++ actor_wayland->frame_bounds = ++ cairo_region_copy(meta_window_get_clipped_frame_bounds(window)); ++} ++ ++static void ++get_shape_bounds (MetaWindowActorWayland *actor_wayland, ++ cairo_rectangle_int_t *bounds) ++{ ++ cairo_region_get_extents (actor_wayland->shape_region, bounds); ++} ++ ++static void ++check_needs_shadow (MetaWindowActorWayland *actor_wayland) ++{ ++ MetaWindow *window = ++ meta_window_actor_get_meta_window (META_WINDOW_ACTOR (actor_wayland)); ++ MetaShadow *old_shadow = NULL; ++ MetaShadow **shadow_location; ++ gboolean recompute_shadow; ++ gboolean should_have_shadow; ++ gboolean appears_focused; ++ ++ should_have_shadow = ++ meta_window_actor_should_clip (META_WINDOW_ACTOR (actor_wayland)); ++ appears_focused = meta_window_appears_focused (window); ++ ++ if (appears_focused) ++ { ++ recompute_shadow = actor_wayland->recompute_focused_shadow; ++ actor_wayland->recompute_focused_shadow = FALSE; ++ shadow_location = &actor_wayland->focused_shadow; ++ } ++ else ++ { ++ recompute_shadow = actor_wayland->recompute_unfocused_shadow; ++ actor_wayland->recompute_unfocused_shadow = FALSE; ++ shadow_location = &actor_wayland->unfocused_shadow; ++ } ++ ++ if (!should_have_shadow || recompute_shadow) ++ { ++ if (*shadow_location != NULL) ++ { ++ old_shadow = *shadow_location; ++ *shadow_location = NULL; ++ } ++ } ++ ++ if (!*shadow_location && should_have_shadow) ++ { ++ MetaShadowFactory *factory = actor_wayland->shadow_factory; ++ const char *shadow_class = get_shadow_class (actor_wayland); ++ cairo_rectangle_int_t shape_bounds; ++ ++ if (!actor_wayland->shadow_shape) ++ { ++ actor_wayland->shadow_shape = ++ meta_window_shape_new (actor_wayland->shape_region); ++ } ++ ++ get_shape_bounds (actor_wayland, &shape_bounds); ++ *shadow_location = ++ meta_shadow_factory_get_shadow (factory, ++ actor_wayland->shadow_shape, ++ shape_bounds.width, shape_bounds.height, ++ shadow_class, appears_focused); ++ } ++ ++ if (old_shadow) ++ meta_shadow_unref (old_shadow); ++} ++ ++static void ++get_shadow_params (MetaWindowActorWayland *actor_wayland, ++ gboolean appears_focused, ++ MetaShadowParams *params) ++{ ++ const char *shadow_class = get_shadow_class (actor_wayland); ++ ++ meta_shadow_factory_get_params (actor_wayland->shadow_factory, ++ shadow_class, appears_focused, ++ params); ++} ++ ++static gboolean ++clip_shadow_under_window (MetaWindowActorWayland *actor_wayland) ++{ ++ return TRUE; ++} ++ + static void + meta_window_actor_wayland_before_paint (MetaWindowActor *actor, + ClutterStageView *stage_view) + { ++ MetaWindowActorWayland *actor_wayland = META_WINDOW_ACTOR_WAYLAND (actor); ++ ++ if (meta_window_actor_should_clip (actor)) ++ { ++ update_frame_bounds (actor_wayland); ++ if (actor_wayland->need_reshape) ++ { ++ update_shape_region (actor_wayland); ++ actor_wayland->need_reshape = FALSE; ++ } ++ check_needs_shadow (actor_wayland); ++ } ++} ++ ++static void ++get_shadow_bounds (MetaWindowActorWayland *actor_x11, ++ gboolean appears_focused, ++ cairo_rectangle_int_t *bounds) ++{ ++ MetaShadow *shadow; ++ cairo_rectangle_int_t shape_bounds; ++ MetaShadowParams params; ++ ++ shadow = appears_focused ? actor_x11->focused_shadow ++ : actor_x11->unfocused_shadow; ++ ++ get_shape_bounds (actor_x11, &shape_bounds); ++ get_shadow_params (actor_x11, appears_focused, ¶ms); ++ ++ meta_shadow_get_bounds (shadow, ++ params.x_offset + shape_bounds.x, ++ params.y_offset + shape_bounds.y, ++ shape_bounds.width, ++ shape_bounds.height, ++ bounds); ++} ++ ++/* Copy from ./meta-window-actor-x11.c ++ * to draw shadows for rounded wayland clients ++ * because oragin shadows has been cutted out ++ */ ++static void ++meta_window_actor_wayland_paint (ClutterActor *actor, ++ ClutterPaintContext *paint_context) ++{ ++ MetaWindowActorWayland *actor_wayland = META_WINDOW_ACTOR_WAYLAND (actor); ++ MetaWindow *window; ++ gboolean appears_focused; ++ MetaShadow *shadow; ++ ++ window = meta_window_actor_get_meta_window (META_WINDOW_ACTOR (actor_wayland)); ++ appears_focused = meta_window_appears_focused (window); ++ shadow = appears_focused ? actor_wayland->focused_shadow ++ : actor_wayland->unfocused_shadow; ++ ++ if (shadow && meta_window_actor_should_clip (META_WINDOW_ACTOR (actor_wayland))) ++ { ++ MetaShadowParams params; ++ cairo_rectangle_int_t shape_bounds; ++ cairo_region_t *clip = actor_wayland->shadow_clip; ++ CoglFramebuffer *framebuffer; ++ ++ meta_window_actor_get_corner_rect(META_WINDOW_ACTOR(actor_wayland), &shape_bounds); ++ get_shadow_params (actor_wayland, appears_focused, ¶ms); ++ ++ /* The frame bounds are already subtracted from actor_wayland->shadow_clip ++ * if that exists. ++ */ ++ if (!clip && clip_shadow_under_window (actor_wayland)) ++ { ++ cairo_rectangle_int_t bounds; ++ ++ get_shadow_bounds (actor_wayland, appears_focused, &bounds); ++ clip = cairo_region_create_rectangle (&bounds); ++ ++ if (actor_wayland->frame_bounds) ++ cairo_region_subtract (clip, actor_wayland->frame_bounds); ++ } ++ ++ framebuffer = clutter_paint_context_get_framebuffer (paint_context); ++ meta_shadow_paint (shadow, ++ framebuffer, ++ params.x_offset + shape_bounds.x, ++ params.y_offset + shape_bounds.y, ++ shape_bounds.width, ++ shape_bounds.height, ++ (clutter_actor_get_paint_opacity (actor) * ++ params.opacity * window->opacity) / (255 * 255), ++ clip, ++ clip_shadow_under_window (actor_wayland)); ++ ++ if (clip && clip != actor_wayland->shadow_clip) ++ cairo_region_destroy (clip); ++ } ++ ++ CLUTTER_ACTOR_CLASS (meta_window_actor_wayland_parent_class)->paint (actor, ++ paint_context); + } + + static void +@@ -149,15 +488,34 @@ meta_window_actor_wayland_can_freeze_commits (MetaWindowActor *actor) + return FALSE; + } + ++static void ++meta_window_actor_wayland_constructed (GObject *object) ++{ ++ MetaWindowActorWayland *actor_wayland = META_WINDOW_ACTOR_WAYLAND (object); ++ ++ /* ++ * Start off with an empty shape region to maintain the invariant that it's ++ * always set. ++ */ ++ actor_wayland->shape_region = cairo_region_create (); ++ ++ G_OBJECT_CLASS (meta_window_actor_wayland_parent_class)->constructed (object); ++} ++ + static void + meta_window_actor_wayland_dispose (GObject *object) + { + MetaWindowActor *window_actor = META_WINDOW_ACTOR (object); ++ MetaWindowActorWayland *actor_wayland = META_WINDOW_ACTOR_WAYLAND (object); ++ + MetaSurfaceActor *surface_actor = + meta_window_actor_get_surface (window_actor); + GList *children; + GList *l; + ++ g_clear_signal_handler (&actor_wayland->size_changed_id, surface_actor); ++ g_clear_signal_handler (&actor_wayland->repaint_scheduled_id, surface_actor); ++ + children = clutter_actor_get_children (CLUTTER_ACTOR (window_actor)); + for (l = children; l; l = l->next) + { +@@ -167,7 +525,17 @@ meta_window_actor_wayland_dispose (GObject *object) + child_actor != CLUTTER_ACTOR (surface_actor)) + clutter_actor_remove_child (CLUTTER_ACTOR (window_actor), child_actor); + } ++ ++ g_clear_pointer (&actor_wayland->shape_region, cairo_region_destroy); ++ g_clear_pointer (&actor_wayland->shadow_clip, cairo_region_destroy); ++ g_clear_pointer (&actor_wayland->frame_bounds, cairo_region_destroy); ++ ++ g_clear_pointer (&actor_wayland->focused_shadow, meta_shadow_unref); ++ g_clear_pointer (&actor_wayland->unfocused_shadow, meta_shadow_unref); ++ g_clear_pointer (&actor_wayland->shadow_shape, meta_window_shape_unref); + ++ g_clear_signal_handler (&actor_wayland->shadow_factory_changed_handler_id, ++ actor_wayland->shadow_factory); + G_OBJECT_CLASS (meta_window_actor_wayland_parent_class)->dispose (object); + } + +@@ -175,6 +543,7 @@ static void + meta_window_actor_wayland_class_init (MetaWindowActorWaylandClass *klass) + { + MetaWindowActorClass *window_actor_class = META_WINDOW_ACTOR_CLASS (klass); ++ ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + window_actor_class->assign_surface_actor = meta_window_actor_wayland_assign_surface_actor; +@@ -187,10 +556,19 @@ meta_window_actor_wayland_class_init (MetaWindowActorWaylandClass *klass) + window_actor_class->update_regions = meta_window_actor_wayland_update_regions; + window_actor_class->can_freeze_commits = meta_window_actor_wayland_can_freeze_commits; + ++ actor_class->paint = meta_window_actor_wayland_paint; ++ ++ object_class->constructed = meta_window_actor_wayland_constructed; + object_class->dispose = meta_window_actor_wayland_dispose; + } + + static void + meta_window_actor_wayland_init (MetaWindowActorWayland *self) + { ++ self->shadow_factory = meta_shadow_factory_get_default (); ++ self->shadow_factory_changed_handler_id = ++ g_signal_connect_swapped (self->shadow_factory, ++ "changed", ++ G_CALLBACK (invalidate_shadow), ++ self); + } +diff --git a/src/compositor/meta-window-actor-x11.c b/src/compositor/meta-window-actor-x11.c +index e4769e087..60d376858 100644 +--- a/src/compositor/meta-window-actor-x11.c ++++ b/src/compositor/meta-window-actor-x11.c +@@ -142,7 +142,8 @@ surface_repaint_scheduled (MetaSurfaceActor *actor, + gpointer user_data) + { + MetaWindowActorX11 *actor_x11 = META_WINDOW_ACTOR_X11 (user_data); +- ++ MetaWindow *window = meta_window_actor_get_meta_window (META_WINDOW_ACTOR(actor_x11)); ++ meta_compositor_update_blur_behind( meta_display_get_compositor (window->display)); + actor_x11->repaint_scheduled = TRUE; + } + +@@ -400,6 +401,8 @@ surface_size_changed (MetaSurfaceActor *actor, + MetaWindowActorX11 *actor_x11 = META_WINDOW_ACTOR_X11 (user_data); + + meta_window_actor_x11_update_shape (actor_x11); ++ ++ meta_window_actor_update_glsl(META_WINDOW_ACTOR(actor_x11)); + } + + static void +@@ -538,6 +541,9 @@ has_shadow (MetaWindowActorX11 *actor_x11) + if (meta_window_get_frame (window)) + return TRUE; + ++ if (meta_window_actor_should_clip(META_WINDOW_ACTOR(actor_x11))) ++ return TRUE; ++ + /* + * Do not add shadows to non-opaque (ARGB32) windows, as we can't easily + * generate shadows for them. +@@ -694,6 +700,8 @@ clip_shadow_under_window (MetaWindowActorX11 *actor_x11) + + if (window->frame) + return TRUE; ++ if (meta_window_actor_should_clip(META_WINDOW_ACTOR(actor_x11))) ++ return TRUE; + + return meta_window_actor_is_opaque (META_WINDOW_ACTOR (actor_x11)); + } +@@ -1036,6 +1044,11 @@ update_shape_region (MetaWindowActorX11 *actor_x11) + { + region = cairo_region_reference (window->shape_region); + } ++ else if (meta_window_actor_should_clip(META_WINDOW_ACTOR(actor_x11)) && !window->frame) ++ { ++ meta_window_actor_get_corner_rect(META_WINDOW_ACTOR(actor_x11), &client_area); ++ region = cairo_region_create_rectangle(&client_area); ++ } + else + { + /* If we don't have a shape on the server, that means that +@@ -1043,7 +1056,7 @@ update_shape_region (MetaWindowActorX11 *actor_x11) + * entire window. */ + region = cairo_region_create_rectangle (&client_area); + } +- ++ + if (window->shape_region || window->frame) + build_and_scan_frame_mask (actor_x11, region); + +@@ -1151,6 +1164,23 @@ update_opaque_region (MetaWindowActorX11 *actor_x11) + cairo_region_destroy (opaque_region); + } + ++static cairo_region_t * ++meta_window_get_clipped_frame_bounds(MetaWindow *window) ++{ ++ g_return_val_if_fail(window, NULL); ++ ++ MetaWindowActor *actor = meta_window_actor_from_window(window); ++ if (actor && !window->frame_bounds) ++ { ++ MetaRectangle rect; ++ meta_window_actor_get_corner_rect(actor, &rect); ++ window->frame_bounds = ++ meta_ui_frame_get_bounds_clipped(&rect, ++ meta_prefs_get_round_corner_radius()); ++ } ++ return window->frame_bounds; ++} ++ + static void + update_frame_bounds (MetaWindowActorX11 *actor_x11) + { +@@ -1158,8 +1188,13 @@ update_frame_bounds (MetaWindowActorX11 *actor_x11) + meta_window_actor_get_meta_window (META_WINDOW_ACTOR (actor_x11)); + + g_clear_pointer (&actor_x11->frame_bounds, cairo_region_destroy); +- actor_x11->frame_bounds = +- cairo_region_copy (meta_window_get_frame_bounds (window)); ++ ++ if (meta_window_actor_should_clip(META_WINDOW_ACTOR(actor_x11))) ++ actor_x11->frame_bounds = ++ cairo_region_copy(meta_window_get_clipped_frame_bounds(window)); ++ else ++ actor_x11->frame_bounds = ++ cairo_region_copy (meta_window_get_frame_bounds (window)); + } + + static void +@@ -1304,7 +1339,10 @@ meta_window_actor_x11_paint (ClutterActor *actor, + cairo_region_t *clip = actor_x11->shadow_clip; + CoglFramebuffer *framebuffer; + +- get_shape_bounds (actor_x11, &shape_bounds); ++ if (meta_window_actor_should_clip(META_WINDOW_ACTOR(actor_x11))) ++ meta_window_actor_get_corner_rect(META_WINDOW_ACTOR(actor_x11), &shape_bounds); ++ else ++ get_shape_bounds (actor_x11, &shape_bounds); + get_shadow_params (actor_x11, appears_focused, ¶ms); + + /* The frame bounds are already subtracted from actor_x11->shadow_clip +diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c +index d4fc9a43a..f4eb9ae37 100644 +--- a/src/compositor/meta-window-actor.c ++++ b/src/compositor/meta-window-actor.c +@@ -41,6 +41,9 @@ + #include "wayland/meta-wayland-surface.h" + #endif + ++#include "meta_clip_effect.h" ++#include "shell-blur-effect.h" ++ + typedef enum + { + INITIALLY_FROZEN, +@@ -55,6 +58,15 @@ typedef struct _MetaWindowActorPrivate + + MetaSurfaceActor *surface; + ++ MetaClipEffect *round_clip_effect; ++ gboolean effect_setuped; ++ gboolean should_clip; ++ int clip_padding[4]; ++ ClutterActor *blur_actor; ++ MetaShellBlurEffect *blur_effect; ++ ++ ulong visible_changed_id; ++ ulong wm_class_changed_id; + int geometry_scale; + + /* +@@ -119,6 +131,245 @@ G_DEFINE_ABSTRACT_TYPE_WITH_CODE (MetaWindowActor, meta_window_actor, CLUTTER_TY + G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init) + G_IMPLEMENT_INTERFACE (META_TYPE_SCREEN_CAST_WINDOW, screen_cast_window_iface_init)); + ++static gboolean _meta_window_actor_should_clip(MetaWindowActor *self); ++ ++static MetaClipEffect* ++create_clip_effect(MetaWindowActor *self) ++{ ++ MetaWindowActorPrivate *priv = meta_window_actor_get_instance_private(self); ++ if ((priv->should_clip = _meta_window_actor_should_clip(self))) ++ return meta_clip_effect_new(); ++ else ++ return NULL; ++} ++ ++void ++meta_window_actor_update_blur_position_size(MetaWindowActor *self) ++{ ++ MetaWindowActorPrivate *priv = ++ meta_window_actor_get_instance_private (self); ++ ++ if (!priv->blur_actor) ++ return; ++ ++ MetaRectangle buf_rect; ++ MetaRectangle frame_rect; ++ meta_window_get_frame_rect (priv->window, &frame_rect); ++ meta_window_get_buffer_rect (priv->window, &buf_rect); ++ ++ if (meta_window_get_maximized (priv->window) || ++ meta_window_is_fullscreen (priv->window)) ++ { ++ clutter_actor_set_position (priv->blur_actor, ++ frame_rect.x, ++ frame_rect.y); ++ clutter_actor_set_size (priv->blur_actor, ++ frame_rect.width, ++ frame_rect.height); ++ meta_shell_blur_effect_set_skip (priv->blur_effect, true); ++ } ++ else ++ { ++ clutter_actor_set_position (priv->blur_actor, ++ frame_rect.x + priv->clip_padding[0] - 1, ++ frame_rect.y + priv->clip_padding[2] - 1); ++ clutter_actor_set_size (priv->blur_actor, ++ frame_rect.width - priv->clip_padding[0] - priv->clip_padding[1] + 1, ++ frame_rect.height - priv->clip_padding[2] - priv->clip_padding[3] + 1); ++ meta_shell_blur_effect_set_skip (priv->blur_effect, false); ++ } ++} ++ ++void ++meta_window_actor_set_blur_behind (MetaWindowActor *self) ++{ ++ MetaWindowActorPrivate *priv = ++ meta_window_actor_get_instance_private (self); ++ ++ if (!priv->blur_actor) ++ return; ++ ++ ClutterActor *parent = clutter_actor_get_parent (CLUTTER_ACTOR(self)); ++ clutter_actor_set_child_below_sibling (parent, priv->blur_actor, CLUTTER_ACTOR(self)); ++} ++ ++static gboolean ++meta_window_is_normal (MetaWindowActor *actor) ++{ ++ MetaWindowActorPrivate *priv = meta_window_actor_get_instance_private (actor); ++ MetaWindowType type = meta_window_get_window_type (priv->window); ++ ++switch (type) ++ { ++ case META_WINDOW_NORMAL: ++ case META_WINDOW_DIALOG: ++ case META_WINDOW_MODAL_DIALOG: ++ case META_WINDOW_SPLASHSCREEN: ++ return TRUE; ++ default: ++ return FALSE; ++ } ++} ++ ++ ++/* ++ * in wayland, `res-name` property of MetaWindow is empty when MetaWindow ++ * has been added to MetaWindowActor. So we have to create create blur actor ++ * in on_wm_class_changed callback. ++ * ++ * in xorg, `res-name` property of MetaWindow has been setted when MetaWindow, ++ * so we can create blur actor when window actor be created. ++ */ ++void ++meta_window_actor_create_blur_actor (MetaWindowActor *self) ++{ ++ MetaWindowActorPrivate *priv = ++ meta_window_actor_get_instance_private (self); ++ ++ if (!meta_window_is_normal (self)) ++ return; ++ if (!meta_prefs_in_blur_list (priv->window->res_name)) ++ return; ++ ++ priv->blur_actor = clutter_actor_new (); ++ priv->blur_effect = meta_shell_blur_effect_new (); ++ ++ meta_shell_blur_effect_set_brightness (priv->blur_effect, ++ meta_prefs_get_blur_brightness()); ++ meta_shell_blur_effect_set_sigma (priv->blur_effect, ++ meta_prefs_get_blur_sigmal()); ++ meta_shell_blur_effect_set_mode (priv->blur_effect, SHELL_BLUR_MODE_BACKGROUND); ++ clutter_actor_add_effect_with_name (priv->blur_actor, ++ "ShellBlurEffect", ++ CLUTTER_EFFECT(priv->blur_effect)); ++ ++ ClutterActor *parent = clutter_actor_get_parent (CLUTTER_ACTOR(self)); ++ clutter_actor_insert_child_below (parent, priv->blur_actor, CLUTTER_ACTOR(self)); ++ int opa = meta_prefs_get_blur_window_opacity(); ++ meta_window_set_opacity(priv->window, opa); ++} ++ ++static void ++check_meta_window_surface_actor(MetaWindowActor *self) ++{ ++ MetaWindowActorPrivate *priv = meta_window_actor_get_instance_private(self); ++ MetaSurfaceActor *surface = meta_window_actor_get_surface(self); ++ ++ if (!priv->effect_setuped && surface && priv->round_clip_effect) ++ { ++ clutter_actor_add_effect_with_name(CLUTTER_ACTOR(surface), ++ "Rounded Corners Effect(Surface)", ++ CLUTTER_EFFECT(priv->round_clip_effect)); ++ priv->effect_setuped = true; ++ } ++} ++ ++void ++meta_window_actor_update_glsl(MetaWindowActor *self) ++{ ++ MetaRectangle frame_rect; ++ MetaRectangle buf_rect; ++ MetaWindow *window = meta_window_actor_get_meta_window(self); ++ MetaWindowActorPrivate *priv = meta_window_actor_get_instance_private(self); ++ ++ if(!priv->round_clip_effect) ++ return; ++ ++ check_meta_window_surface_actor(self); ++ ++ if (!meta_window_actor_should_clip(self)) ++ { ++ meta_clip_effect_skip(priv->round_clip_effect); ++ return; ++ } ++ ++ meta_window_get_frame_rect(window, &frame_rect); ++ meta_window_get_buffer_rect(window, &buf_rect); ++ ++ cairo_rectangle_int_t bounds; ++ bounds.x = frame_rect.x - buf_rect.x; ++ bounds.y = frame_rect.y - buf_rect.y; ++ bounds.width = frame_rect.width; ++ bounds.height = frame_rect.height; ++ ++ if (bounds.width <= 0 || bounds.height <= 0) ++ return; ++ ++ if (priv->clip_padding[0] == -1 && window->res_name) ++ meta_prefs_get_clip_edge_padding(window->res_name, priv->clip_padding); ++ ++ meta_clip_effect_set_bounds(priv->round_clip_effect, &bounds, priv->clip_padding); ++} ++ ++static gboolean ++_meta_window_actor_should_clip(MetaWindowActor *self) ++{ ++ MetaWindowActorPrivate *priv = meta_window_actor_get_instance_private (self); ++ MetaWindow *window = priv->window; ++ ++ if (/* meta_window_get_client_type(window) == META_WINDOW_CLIENT_TYPE_WAYLAND || */ ++ meta_prefs_in_black_list(window->res_name)) ++ { ++ return FALSE; ++ } ++ ++ return meta_window_is_normal(self); ++} ++ ++gboolean ++meta_window_actor_should_clip(MetaWindowActor *self) ++{ ++ MetaWindowActorPrivate *priv = meta_window_actor_get_instance_private (self); ++ ++ return priv->should_clip && ++ !(meta_window_get_maximized(priv->window)|| ++ meta_window_is_fullscreen(priv->window)); ++} ++ ++void ++meta_window_actor_get_corner_rect(MetaWindowActor *self, ++ MetaRectangle *rect) ++{ ++ MetaWindowActorPrivate *priv = meta_window_actor_get_instance_private(self); ++ g_return_if_fail(priv->round_clip_effect); ++ meta_clip_effect_get_bounds(priv->round_clip_effect, rect); ++} ++ ++void meta_window_actor_update_clip_padding(MetaWindowActor *self) ++{ ++ MetaWindowActorPrivate *priv = meta_window_actor_get_instance_private(self); ++ if(priv->round_clip_effect) ++ meta_prefs_get_clip_edge_padding(priv->window->res_name, ++ priv->clip_padding); ++} ++ ++void ++meta_window_actor_update_blur_sigmal (MetaWindowActor *self) ++{ ++ MetaWindowActorPrivate *priv = meta_window_actor_get_instance_private(self); ++ if (priv->blur_actor) ++ meta_shell_blur_effect_set_sigma (priv->blur_effect, ++ meta_prefs_get_blur_sigmal()); ++} ++ ++void ++meta_window_actor_update_blur_brightness (MetaWindowActor *self) ++{ ++ MetaWindowActorPrivate *priv = meta_window_actor_get_instance_private(self); ++ if (priv->blur_actor) ++ meta_shell_blur_effect_set_brightness (priv->blur_effect, ++ meta_prefs_get_blur_brightness()); ++} ++ ++void ++meta_window_actor_update_blur_window_opacity (MetaWindowActor *self) ++{ ++ MetaWindowActorPrivate *priv = meta_window_actor_get_instance_private(self); ++ if (priv->blur_actor) ++ meta_window_set_opacity (priv->window, ++ meta_prefs_get_blur_window_opacity()); ++} ++ + static void + meta_window_actor_class_init (MetaWindowActorClass *klass) + { +@@ -216,6 +467,11 @@ meta_window_actor_init (MetaWindowActor *self) + meta_window_actor_get_instance_private (self); + + priv->geometry_scale = 1; ++ priv->effect_setuped = FALSE; ++ priv->clip_padding[0] = -1; ++ ++ priv->blur_actor = NULL; ++ priv->blur_effect = NULL; + } + + static void +@@ -368,6 +624,11 @@ meta_window_actor_real_assign_surface_actor (MetaWindowActor *self, + meta_window_actor_set_frozen (self, TRUE); + else + meta_window_actor_sync_thawed_state (self); ++ ++ if (priv->blur_actor) ++ { ++ meta_window_actor_update_opacity (self); ++ } + } + + void +@@ -399,6 +660,31 @@ init_surface_actor (MetaWindowActor *self) + meta_window_actor_assign_surface_actor (self, surface_actor); + } + ++static void ++on_visible_changed (MetaWindowActor *self) ++{ ++ MetaWindowActorPrivate *priv = meta_window_actor_get_instance_private (self); ++ ++ if (!priv->blur_actor) ++ return; ++ ++ if (priv->visible) ++ clutter_actor_show(priv->blur_actor); ++ else ++ clutter_actor_hide(priv->blur_actor); ++} ++ ++static void ++on_wm_class_changed (MetaWindow *self, ++ gpointer user_data) ++{ ++ MetaWindowActor *actor = meta_window_actor_from_window (self); ++ MetaWindowActorPrivate *priv = meta_window_actor_get_instance_private (actor); ++ ++ meta_window_actor_create_blur_actor(actor); ++ g_clear_signal_handler(&priv->wm_class_changed_id, self); ++} ++ + static void + meta_window_actor_constructed (GObject *object) + { +@@ -406,6 +692,7 @@ meta_window_actor_constructed (GObject *object) + MetaWindowActorPrivate *priv = + meta_window_actor_get_instance_private (self); + MetaWindow *window = priv->window; ++ MetaWindowClientType type = meta_window_get_client_type (window); + + priv->compositor = window->display->compositor; + +@@ -424,6 +711,15 @@ meta_window_actor_constructed (GObject *object) + priv->first_frame_state = DRAWING_FIRST_FRAME; + + meta_window_actor_sync_actor_geometry (self, priv->window->placed); ++ ++ priv->visible_changed_id = ++ g_signal_connect (object, "notify::visible", G_CALLBACK (on_visible_changed), NULL); ++ ++ if (type == META_WINDOW_CLIENT_TYPE_WAYLAND) ++ { ++ priv->wm_class_changed_id = ++ g_signal_connect (window, "notify::wm-class", G_CALLBACK (on_wm_class_changed), object); ++ } + } + + static void +@@ -442,6 +738,7 @@ meta_window_actor_dispose (GObject *object) + + priv->disposed = TRUE; + ++ g_clear_signal_handler(&priv->visible_changed_id, object); + meta_compositor_remove_window_actor (compositor, self); + + g_clear_object (&priv->window); +@@ -470,6 +767,7 @@ meta_window_actor_set_property (GObject *object, + { + case PROP_META_WINDOW: + priv->window = g_value_dup_object (value); ++ priv->round_clip_effect = create_clip_effect(self); + g_signal_connect_object (priv->window, "notify::appears-focused", + G_CALLBACK (window_appears_focused_notify), self, 0); + break; +@@ -662,6 +960,20 @@ start_simple_effect (MetaWindowActor *self, + return TRUE; + } + ++static void ++meta_window_actor_remove_blur (MetaWindowActor *self) ++{ ++ MetaWindowActorPrivate *priv = ++ meta_window_actor_get_instance_private (self); ++ ++ if (!priv->blur_actor) ++ return; ++ ++ ClutterActor *parent = clutter_actor_get_parent (CLUTTER_ACTOR (self)); ++ clutter_actor_remove_effect (priv->blur_actor, CLUTTER_EFFECT (priv->blur_effect)); ++ clutter_actor_remove_child (parent, priv->blur_actor); ++} ++ + static void + meta_window_actor_after_effects (MetaWindowActor *self) + { +@@ -675,6 +987,12 @@ meta_window_actor_after_effects (MetaWindowActor *self) + + if (priv->needs_destroy) + { ++ if (priv->round_clip_effect) ++ { ++ clutter_actor_remove_effect (CLUTTER_ACTOR(self), ++ CLUTTER_EFFECT(priv->round_clip_effect)); ++ meta_window_actor_remove_blur(self); ++ } + clutter_actor_destroy (CLUTTER_ACTOR (self)); + } + else +@@ -803,6 +1121,19 @@ meta_window_actor_queue_destroy (MetaWindowActor *self) + clutter_actor_destroy (CLUTTER_ACTOR (self)); + } + ++void ++meta_window_actor_update_clipped_bounds(MetaWindowActor *window_actor) ++{ ++ MetaWindowActorPrivate *priv = ++ meta_window_actor_get_instance_private(window_actor); ++ MetaWindow *window = priv->window; ++ ++ if (window && window->frame_bounds) { ++ cairo_region_destroy(window->frame_bounds); ++ window->frame_bounds = NULL; ++ } ++} ++ + MetaWindowActorChanges + meta_window_actor_sync_actor_geometry (MetaWindowActor *self, + gboolean did_placement) +diff --git a/src/core/prefs.c b/src/core/prefs.c +index 60d7a278a..6c27d4556 100644 +--- a/src/core/prefs.c ++++ b/src/core/prefs.c +@@ -33,6 +33,8 @@ + #include <string.h> + #include <stdlib.h> + ++#include <json-glib/json-glib.h> ++ + #include "compositor/meta-plugin-manager.h" + #include "core/keybindings-private.h" + #include "core/meta-accel-parse.h" +@@ -119,6 +121,16 @@ static gboolean show_fallback_app_menu = TRUE; + static GDesktopVisualBellType visual_bell_type = G_DESKTOP_VISUAL_BELL_FULLSCREEN_FLASH; + static MetaButtonLayout button_layout; + ++static int round_corner_radius = 8; ++static int border_width = 0; ++static int blur_sigmal = 20; ++static int blur_window_opacity = 80; ++static int blur_brightness = 100; ++static JsonNode *clip_edge_padding = NULL; ++/* NULL-terminated array */ ++static char **black_list = NULL; ++static char **blur_list = NULL; ++ + /* NULL-terminated array */ + static char **workspace_names = NULL; + +@@ -149,6 +161,7 @@ static gboolean mouse_button_mods_handler (GVariant*, gpointer*, gpointer); + static gboolean button_layout_handler (GVariant*, gpointer*, gpointer); + static gboolean overlay_key_handler (GVariant*, gpointer*, gpointer); + static gboolean locate_pointer_key_handler (GVariant*, gpointer*, gpointer); ++static gboolean clip_edge_padding_handler (GVariant*, gpointer*, gpointer); + + static gboolean iso_next_group_handler (GVariant*, gpointer*, gpointer); + +@@ -453,6 +466,15 @@ static MetaStringPreference preferences_string[] = + locate_pointer_key_handler, + NULL, + }, ++ { ++ { ++ "clip-edge-padding", ++ SCHEMA_MUTTER, ++ META_PREF_CLIP_EDGE_PADDING, ++ }, ++ clip_edge_padding_handler, ++ NULL, ++ }, + { { NULL, 0, 0 }, NULL }, + }; + +@@ -474,6 +496,22 @@ static MetaStringArrayPreference preferences_string_array[] = + iso_next_group_handler, + NULL, + }, ++ { ++ { "black-list", ++ SCHEMA_MUTTER, ++ META_PREF_BLACK_LIST, ++ }, ++ NULL, ++ &black_list, ++ }, ++ { ++ { "blur-list", ++ SCHEMA_MUTTER, ++ META_PREF_BLUR_LIST, ++ }, ++ NULL, ++ &blur_list, ++ }, + { { NULL, 0, 0 }, NULL }, + }; + +@@ -514,6 +552,46 @@ static MetaIntPreference preferences_int[] = + }, + &cursor_size + }, ++ { ++ { ++ "round-corners-radius", ++ SCHEMA_MUTTER, ++ META_PREF_CORNER_RADIUS, ++ }, ++ &round_corner_radius, ++ }, ++ { ++ { ++ "border-width", ++ SCHEMA_MUTTER, ++ META_PREF_BORDER_WIDTH, ++ }, ++ &border_width, ++ }, ++ { ++ { ++ "blur-sigmal", ++ SCHEMA_MUTTER, ++ META_PREF_BLUR_SIGMAL, ++ }, ++ &blur_sigmal, ++ }, ++ { ++ { ++ "blur-brightness", ++ SCHEMA_MUTTER, ++ META_PREF_BLUR_BRIGHTNESS, ++ }, ++ &blur_brightness, ++ }, ++ { ++ { ++ "blur-window-opacity", ++ SCHEMA_MUTTER, ++ META_PREF_BLUR_WINDOW_OPACITY, ++ }, ++ &blur_window_opacity, ++ }, + { { NULL, 0, 0 }, NULL }, + }; + +@@ -1587,6 +1665,81 @@ locate_pointer_key_handler (GVariant *value, + return TRUE; + } + ++static gboolean ++clip_edge_padding_handler (GVariant *value, ++ gpointer *result, ++ gpointer data) ++{ ++ /* json string looks like this: ++ * ++ * { ++ * // array represent the clip padding of window: [left, right, top, bottom] ++ * "global": [1, 1, 1, 1], ++ * // special app settings, ++ * "apps": { ++ * // second part in `WM_CLASS` property of a window ++ * "Typora": [0, 0, 0, 0], ++ * ... ++ * } ++ * } ++ */ ++ ++ JsonNode *json; ++ JsonObject *obj; ++ JsonArray *arr; ++ JsonNode *element; ++ JsonObject *apps_obj; ++ GList *app_names; ++ ++ const char *string_value; ++ GError *error = NULL; ++ ++ *result = NULL; ++ string_value = g_variant_get_string(value, NULL); ++ json = json_from_string(string_value, &error); ++ ++ if (error) ++ { ++ meta_topic(META_DEBUG_PREFS, "Failed to parse value for clip-edge-padding: %s", error->message); ++ g_error_free(error); ++ return FALSE; ++ } ++ ++ if (!JSON_NODE_HOLDS_OBJECT(json)) ++ goto failed; ++ ++ obj = json_node_get_object(json); ++ arr = json_object_get_array_member(obj, "global"); ++ if (!arr || json_array_get_length(arr) != 4) ++ goto failed; ++ ++ if (!(element = json_object_get_member(obj, "apps"))) ++ goto failed; ++ if (!JSON_NODE_HOLDS_OBJECT(element)) ++ goto failed; ++ apps_obj = json_node_get_object(element); ++ ++ app_names = json_object_get_members(apps_obj); ++ for (GList *l = app_names; l != NULL; l = l->next) ++ { ++ arr = json_object_get_array_member(apps_obj, l->data); ++ if (!arr || json_array_get_length(arr) != 4) ++ goto failed; ++ } ++ ++ if (clip_edge_padding != NULL) ++ json_node_unref(clip_edge_padding); ++ clip_edge_padding = json; ++ queue_changed(META_PREF_CLIP_EDGE_PADDING); ++ ++ return TRUE; ++ ++failed: ++ meta_topic(META_DEBUG_PREFS, "Failed to parse value for clip-edge-padding"); ++ json_node_unref(json); ++ return FALSE; ++} ++ + static gboolean + iso_next_group_handler (GVariant *value, + gpointer *result, +@@ -1758,6 +1911,30 @@ meta_preference_to_string (MetaPreference pref) + + case META_PREF_CHECK_ALIVE_TIMEOUT: + return "CHECK_ALIVE_TIMEOUT"; ++ ++ case META_PREF_CORNER_RADIUS: ++ return "CORNER_RADIUS"; ++ ++ case META_PREF_CLIP_EDGE_PADDING: ++ return "CLIP_EDGE_PADDING"; ++ ++ case META_PREF_BLACK_LIST: ++ return "BLACK_LIST"; ++ ++ case META_PREF_BORDER_WIDTH: ++ return "BORDER_WIDTH"; ++ ++ case META_PREF_BLUR_SIGMAL: ++ return "BLUR_SIGMAL"; ++ ++ case META_PREF_BLUR_BRIGHTNESS: ++ return "BLUR_BRIGHTNESS"; ++ ++ case META_PREF_BLUR_LIST: ++ return "BLUR_LIST"; ++ ++ case META_PREF_BLUR_WINDOW_OPACITY: ++ return "BLUR_WINDOW_OPACITY"; + } + + return "(unknown)"; +@@ -2226,3 +2403,88 @@ meta_prefs_set_force_fullscreen (gboolean whether) + { + force_fullscreen = whether; + } ++ ++int ++meta_prefs_get_round_corner_radius (void) ++{ ++ return round_corner_radius; ++} ++ ++#define SET_PADDING(arr, v0, v1, v2, v3) \ ++ { (arr)[0] = (v0); (arr)[1] = (v1); (arr)[2] = (v2); (arr)[3] = (v3); } ++ ++void ++meta_prefs_get_clip_edge_padding (const char *name, int padding[4]) ++{ ++ JsonObject *obj; ++ JsonArray *arr; ++ ++ if (!clip_edge_padding || !name) { ++ SET_PADDING(padding, 0, 0, 0, 0); ++ return; ++ } ++ ++ obj = json_node_get_object(clip_edge_padding); ++ arr = json_object_get_array_member(obj, "global"); ++ obj = json_object_get_object_member(obj, "apps"); ++ ++ if (json_object_has_member(obj, name)) ++ arr = json_object_get_array_member(obj, name); ++ ++ // array: { left, right, top, bottom } ++ SET_PADDING(padding, ++ json_array_get_int_element(arr, 0) + 1, ++ json_array_get_int_element(arr, 1), ++ json_array_get_int_element(arr, 2) + 1, ++ json_array_get_int_element(arr, 3)); ++} ++ ++gboolean ++meta_prefs_in_black_list(const char *name) ++{ ++ g_return_val_if_fail(black_list, FALSE); ++ ++ int len = g_strv_length(black_list); ++ ++ for (int i = 0; i < len; i++) ++ if (g_strcmp0(name, black_list[i]) == 0) ++ return TRUE; ++ return FALSE; ++} ++ ++int ++meta_prefs_get_border_width(void) ++{ ++ return border_width; ++} ++ ++int ++meta_prefs_get_blur_sigmal(void) ++{ ++ return blur_sigmal; ++} ++ ++double ++meta_prefs_get_blur_brightness(void) ++{ ++ return (double) blur_brightness * 0.01; ++} ++ ++int ++meta_prefs_get_blur_window_opacity(void) ++{ ++ return blur_window_opacity * 255 * 0.01; ++} ++ ++gboolean ++meta_prefs_in_blur_list(const char *name) ++{ ++ g_return_val_if_fail(blur_list, FALSE); ++ ++ int len = g_strv_length(blur_list); ++ ++ for (int i = 0; i < len; i++) ++ if (g_strcmp0(name, blur_list[i]) == 0) ++ return TRUE; ++ return FALSE; ++} +\ No newline at end of file +diff --git a/src/meson.build b/src/meson.build +index 284bdf522..a0c5e2d4b 100644 +--- a/src/meson.build ++++ b/src/meson.build +@@ -163,6 +163,18 @@ if get_option('verbose') + ] + endif + ++libshell_enums = gnome.mkenums_simple('shell-enum-types', ++ sources: [ ++ 'shell-blur-effect.h', ++ ] ++) ++ ++libshell_src = [ ++ libshell_enums, ++ 'shell-blur-effect.h', ++ 'shell-blur-effect.c', ++] ++ + mutter_sources = [ + 'backends/edid.h', + 'backends/edid-parse.c', +@@ -444,6 +456,8 @@ mutter_sources = [ + 'x11/window-x11-private.h', + 'x11/xprops.c', + 'x11/xprops.h', ++ 'meta_clip_effect.c', ++ 'meta_clip_effect.h', + ] + + if have_egl +@@ -966,7 +980,8 @@ subdir('meta') + mutter_built_sources += mutter_enum_types + + libmutter = shared_library(libmutter_name, +- mutter_sources, ++ # mutter_sources, ++ mutter_sources + libshell_src, + mutter_built_sources, + version: '0.0.0', + soversion: 0, +diff --git a/src/meta/prefs.h b/src/meta/prefs.h +index e2c8b46cf..f1ee72576 100644 +--- a/src/meta/prefs.h ++++ b/src/meta/prefs.h +@@ -106,6 +106,15 @@ typedef enum + META_PREF_DRAG_THRESHOLD, + META_PREF_LOCATE_POINTER, + META_PREF_CHECK_ALIVE_TIMEOUT, ++ ++ META_PREF_CORNER_RADIUS, ++ META_PREF_CLIP_EDGE_PADDING, ++ META_PREF_BLACK_LIST, ++ META_PREF_BORDER_WIDTH, ++ META_PREF_BLUR_SIGMAL, ++ META_PREF_BLUR_BRIGHTNESS, ++ META_PREF_BLUR_LIST, ++ META_PREF_BLUR_WINDOW_OPACITY, + } MetaPreference; + + typedef void (* MetaPrefsChangedFunc) (MetaPreference pref, +@@ -236,6 +245,30 @@ int meta_prefs_get_draggable_border_width (void); + META_EXPORT + int meta_prefs_get_drag_threshold (void); + ++META_EXPORT ++int meta_prefs_get_round_corner_radius (void); ++ ++META_EXPORT ++void meta_prefs_get_clip_edge_padding (const char *name, int padding[4]); ++ ++META_EXPORT ++gboolean meta_prefs_in_black_list(const char *name); ++ ++META_EXPORT ++int meta_prefs_get_border_width(void); ++ ++META_EXPORT ++int meta_prefs_get_blur_sigmal(void); ++ ++META_EXPORT ++double meta_prefs_get_blur_brightness(void); ++ ++META_EXPORT ++int meta_prefs_get_blur_window_opacity(void); ++ ++META_EXPORT ++gboolean meta_prefs_in_blur_list(const char *name); ++ + /** + * MetaKeyBindingAction: + * @META_KEYBINDING_ACTION_NONE: FILLME +diff --git a/src/ui/frames.c b/src/ui/frames.c +index 48b2a361c..8be6a8f8b 100644 +--- a/src/ui/frames.c ++++ b/src/ui/frames.c +@@ -711,6 +711,27 @@ meta_ui_frame_get_bounds (MetaUIFrame *frame) + return get_visible_region (frame, &fgeom); + } + ++cairo_region_t * ++meta_ui_frame_get_bounds_clipped (const MetaRectangle *bounds, ++ float radius) ++{ ++ MetaFrameGeometry fgeom; ++ ++ fgeom.borders.invisible.left = bounds->x; ++ fgeom.borders.invisible.top = bounds->y; ++ fgeom.borders.invisible.bottom = 0; ++ fgeom.borders.invisible.right = 0; ++ fgeom.width = bounds->width + bounds->x; ++ fgeom.height = bounds->height + bounds->y; ++ ++ fgeom.top_left_corner_rounded_radius = radius; ++ fgeom.top_right_corner_rounded_radius = radius; ++ fgeom.bottom_left_corner_rounded_radius = radius; ++ fgeom.bottom_right_corner_rounded_radius = radius; ++ ++ return get_visible_region (NULL, &fgeom); ++} ++ + void + meta_ui_frame_move_resize (MetaUIFrame *frame, + int x, int y, int width, int height) +diff --git a/src/ui/frames.h b/src/ui/frames.h +index 73dee1737..03b19ba40 100644 +--- a/src/ui/frames.h ++++ b/src/ui/frames.h +@@ -135,6 +135,10 @@ void meta_ui_frame_get_borders (MetaUIFrame *frame, + + cairo_region_t * meta_ui_frame_get_bounds (MetaUIFrame *frame); + ++cairo_region_t * ++meta_ui_frame_get_bounds_clipped (const MetaRectangle *bounds, ++ float radius); ++ + void meta_ui_frame_get_mask (MetaUIFrame *frame, + cairo_rectangle_int_t *frame_rect, + cairo_t *cr); +diff --git a/src/wayland/meta-window-wayland.c b/src/wayland/meta-window-wayland.c +index 12e9567d9..7138330bc 100644 +--- a/src/wayland/meta-window-wayland.c ++++ b/src/wayland/meta-window-wayland.c +@@ -1002,6 +1002,9 @@ meta_window_wayland_finish_move_resize (MetaWindow *window, + gravity = META_GRAVITY_STATIC; + meta_window_move_resize_internal (window, flags, gravity, rect); + ++ if (flags & META_MOVE_RESIZE_RESIZE_ACTION) ++ meta_window_actor_update_glsl(meta_window_actor_from_window(window)); ++ + g_clear_pointer (&acked_configuration, meta_wayland_window_configuration_free); + } + |