diff options
Diffstat (limited to 'rounded_corners_40.5.patch')
-rw-r--r-- | rounded_corners_40.5.patch | 841 |
1 files changed, 841 insertions, 0 deletions
diff --git a/rounded_corners_40.5.patch b/rounded_corners_40.5.patch new file mode 100644 index 000000000000..e89b33c4f6ce --- /dev/null +++ b/rounded_corners_40.5.patch @@ -0,0 +1,841 @@ +diff --git a/data/org.gnome.mutter.gschema.xml.in b/data/org.gnome.mutter.gschema.xml.in +index 23fa9f3ad..a7a002eeb 100644 +--- a/data/org.gnome.mutter.gschema.xml.in ++++ b/data/org.gnome.mutter.gschema.xml.in +@@ -2,6 +2,49 @@ + <schema id="org.gnome.mutter" path="/org/gnome/mutter/" + gettext-domain="@GETTEXT_DOMAIN@"> + ++ <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.c b/src/compositor/compositor.c +index 1770550d4..c8bd5f425 100644 +--- a/src/compositor/compositor.c ++++ b/src/compositor/compositor.c +@@ -1022,7 +1022,11 @@ 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); ++ } + } + + static void +@@ -1188,6 +1192,32 @@ 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; ++ ++ if (pref == META_PREF_CORNER_RADIUS || ++ pref == META_PREF_CLIP_EDGE_PADDING) ++ { ++ for (l = priv->windows; l; l = l->next) ++ { ++ if (pref == META_PREF_CORNER_RADIUS) ++ meta_window_actor_update_corner_radius(l->data); ++ else ++ 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)); ++ } ++ } ++} ++ + static void + meta_compositor_init (MetaCompositor *compositor) + { +@@ -1218,6 +1248,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 +1275,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); + } + +diff --git a/src/compositor/meta-shadow-factory.c b/src/compositor/meta-shadow-factory.c +index d6424d3be..b67bdda79 100644 +--- a/src/compositor/meta-shadow-factory.c ++++ b/src/compositor/meta-shadow-factory.c +@@ -118,12 +118,12 @@ static guint signals[LAST_SIGNAL] = { 0 }; + /* The first element in this array also defines the default parameters + * for newly created classes */ + MetaShadowClassInfo default_shadow_classes[] = { +- { "normal", { 10, -1, 0, 3, 128 }, { 8, -1, 0, 2, 64 } }, +- { "dialog", { 10, -1, 0, 3, 128 }, { 8, -1, 0, 2, 64 } }, +- { "modal_dialog", { 10, -1, 0, 3, 128 }, { 8, -1, 0, 2, 64 } }, +- { "utility", { 10, -1, 0, 3, 128 }, { 8, -1, 0, 2, 64 } }, +- { "border", { 10, -1, 0, 3, 128 }, { 8, -1, 0, 2, 64 } }, +- { "menu", { 10, -1, 0, 3, 128 }, { 8, -1, 0, 2, 64 } }, ++ { "normal", { 10, -1, 2, 4, 94 }, { 8, -1, 0, 2, 54 } }, ++ { "dialog", { 10, -1, 2, 4, 94 }, { 8, -1, 0, 2, 54 } }, ++ { "modal_dialog", { 10, -1, 2, 4, 94 }, { 8, -1, 0, 2, 54 } }, ++ { "utility", { 10, -1, 2, 4, 94 }, { 8, -1, 0, 2, 54 } }, ++ { "border", { 10, -1, 2, 4, 94 }, { 8, -1, 0, 2, 54 } }, ++ { "menu", { 10, -1, 2, 4, 94 }, { 8, -1, 0, 2, 54 } }, + + { "popup-menu", { 1, -1, 0, 0, 128 }, { 1, -1, 0, 0, 128 } }, + { "dropdown-menu", { 1, -1, 0, 0, 128 }, { 1, -1, 0, 0, 128 } }, +diff --git a/src/compositor/meta-window-actor-private.h b/src/compositor/meta-window-actor-private.h +index 64741e416..220de0895 100644 +--- a/src/compositor/meta-window-actor-private.h ++++ b/src/compositor/meta-window-actor-private.h +@@ -99,4 +99,11 @@ 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_corner_radius(MetaWindowActor *self); ++void meta_window_actor_update_clip_padding(MetaWindowActor *self); ++ + #endif /* META_WINDOW_ACTOR_PRIVATE_H */ +diff --git a/src/compositor/meta-window-actor-x11.c b/src/compositor/meta-window-actor-x11.c +index e18b1b28b..a1a7a22a1 100644 +--- a/src/compositor/meta-window-actor-x11.c ++++ b/src/compositor/meta-window-actor-x11.c +@@ -401,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 +@@ -535,6 +537,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. +@@ -691,6 +696,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)); + } +@@ -1033,14 +1040,19 @@ update_shape_region (MetaWindowActorX11 *actor_x11) + { + region = cairo_region_reference (window->shape_region); + } +- else ++ 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 + * we have an implicit shape of one rectangle covering the + * entire window. */ + region = cairo_region_create_rectangle (&client_area); +- } +- ++ } ++ + if (window->shape_region || window->frame) + build_and_scan_frame_mask (actor_x11, region); + +@@ -1148,6 +1160,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) + { +@@ -1155,8 +1184,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 +@@ -1296,7 +1330,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..3a7395564 100644 +--- a/src/compositor/meta-window-actor.c ++++ b/src/compositor/meta-window-actor.c +@@ -41,6 +41,8 @@ + #include "wayland/meta-wayland-surface.h" + #endif + ++#include "meta_clip_effect.h" ++ + typedef enum + { + INITIALLY_FROZEN, +@@ -55,6 +57,11 @@ typedef struct _MetaWindowActorPrivate + + MetaSurfaceActor *surface; + ++ MetaClipEffect *round_clip_effect; ++ gboolean effect_setuped; ++ gboolean should_clip; ++ int clip_padding[4]; ++ + int geometry_scale; + + /* +@@ -119,6 +126,129 @@ 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; ++} ++ ++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; ++ MetaWindowType window_type = meta_window_get_window_type(window); ++ ++ if (meta_window_get_client_type(window) == META_WINDOW_CLIENT_TYPE_WAYLAND || ++ meta_prefs_in_black_list(window->res_name)) ++ { ++ return FALSE; ++ } ++ ++ switch (window_type) ++ { ++ case META_WINDOW_NORMAL: ++ case META_WINDOW_DIALOG: ++ case META_WINDOW_MODAL_DIALOG: ++ case META_WINDOW_SPLASHSCREEN: ++ return TRUE; ++ default: ++ return FALSE; ++ } ++} ++ ++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_corner_radius(MetaWindowActor *self) ++{ ++ MetaWindowActorPrivate *priv = meta_window_actor_get_instance_private(self); ++ if(priv->round_clip_effect) ++ meta_clip_effect_update_corner_texture(priv->round_clip_effect); ++} ++ ++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); ++} ++ + static void + meta_window_actor_class_init (MetaWindowActorClass *klass) + { +@@ -216,6 +346,8 @@ 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; + } + + static void +@@ -470,6 +602,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; +@@ -675,6 +808,9 @@ 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)); + clutter_actor_destroy (CLUTTER_ACTOR (self)); + } + else +@@ -803,6 +939,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..e0772d984 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" +@@ -62,6 +64,9 @@ + #define KEY_WORKSPACES_ONLY_ON_PRIMARY "workspaces-only-on-primary" + #define KEY_LOCATE_POINTER "locate-pointer" + ++#define KEY_ROUND_CORNERS_RADIUS "round-corners-radius" ++#define KEY_CLIP_EDGE_PADDING "window-edge-padding" ++ + /* These are the different schemas we are keeping + * a GSettings instance for */ + #define SCHEMA_GENERAL "org.gnome.desktop.wm.preferences" +@@ -119,6 +124,11 @@ 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 JsonNode *clip_edge_padding = NULL; ++/* NULL-terminated array */ ++static char **black_list = NULL; ++ + /* NULL-terminated array */ + static char **workspace_names = NULL; + +@@ -149,6 +159,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 +464,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 +494,14 @@ static MetaStringArrayPreference preferences_string_array[] = + iso_next_group_handler, + NULL, + }, ++ { ++ { "black-list", ++ SCHEMA_MUTTER, ++ META_PREF_BLACK_LIST, ++ }, ++ NULL, ++ &black_list, ++ }, + { { NULL, 0, 0 }, NULL }, + }; + +@@ -514,6 +542,14 @@ static MetaIntPreference preferences_int[] = + }, + &cursor_size + }, ++ { ++ { ++ "round-corners-radius", ++ SCHEMA_MUTTER, ++ META_PREF_CORNER_RADIUS, ++ }, ++ &round_corner_radius, ++ }, + { { NULL, 0, 0 }, NULL }, + }; + +@@ -1587,6 +1623,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 +1869,15 @@ 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"; + } + + return "(unknown)"; +@@ -2226,3 +2346,51 @@ 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; ++} +\ No newline at end of file +diff --git a/src/meson.build b/src/meson.build +index 284bdf522..4b314fe5d 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 +@@ -967,6 +981,7 @@ mutter_built_sources += mutter_enum_types + + libmutter = shared_library(libmutter_name, + 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..ecbc1b484 100644 +--- a/src/meta/prefs.h ++++ b/src/meta/prefs.h +@@ -106,6 +106,10 @@ 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, + } MetaPreference; + + typedef void (* MetaPrefsChangedFunc) (MetaPreference pref, +@@ -236,6 +240,15 @@ 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); ++ + /** + * 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); + } + |