diff --git a/src/manager/event_manager.ts b/src/manager/event_manager.ts index a772683..e937e89 100644 --- a/src/manager/event_manager.ts +++ b/src/manager/event_manager.ts @@ -11,6 +11,7 @@ import {logDebug} from '../utils/log.js'; import {prefs} from '../utils/settings.js'; import {hasMetaWindow, type RoundedWindowActor} from '../utils/types.js'; import * as handlers from './event_handlers.js'; +import {unwrapActor} from './utils.js'; /** * The rounded corners effect has to perform some actions when differen events @@ -141,11 +142,15 @@ function disconnectAll(object?: GObject.Object | null) { function applyEffectTo(actor: RoundedWindowActor) { // In wayland sessions, the surface actor of XWayland clients is sometimes // not ready when the window is created. In this case, we wait until it is - // ready before applying the effect. - if (!actor.firstChild) { - const id = actor.connect('notify::first-child', () => { - applyEffectTo(actor); + // ready before applying the effect. `child-added` is used instead of + // `notify::first-child` because another extension may already occupy the + // first child slot. + if (!unwrapActor(actor)) { + const id = actor.connect('child-added', () => { + if (!unwrapActor(actor)) return; + actor.disconnect(id); + applyEffectTo(actor); }); return; diff --git a/src/manager/utils.ts b/src/manager/utils.ts index 37d822f..8e5ff49 100644 --- a/src/manager/utils.ts +++ b/src/manager/utils.ts @@ -1,6 +1,5 @@ /** @file Provides various utility functions used withing signal handling code. */ -import type St from 'gi://St'; import type {RoundedCornersEffect} from '../effect/rounded_corners_effect.js'; import type { BoxShadow, @@ -10,6 +9,7 @@ import type { import Gio from 'gi://Gio'; import Meta from 'gi://Meta'; +import St from 'gi://St'; import {boxShadowCss} from '../utils/box_shadow.js'; import { @@ -22,16 +22,20 @@ import {logDebug} from '../utils/log.js'; import {getPref} from '../utils/settings.js'; /** - * Get the actor that rounded corners should be applied to. - * In Wayland, the effect is applied to WindowActor, but in X11, it is applied - * to WindowActor.first_child. + * Get the actor that rounded corners should be applied to: the MetaSurfaceActor + * holding the window contents, rather than the window actor itself. The effect + * is an offscreen effect, so attaching it to the window actor would also + * capture actors that other extensions insert into it, such as Blur my Shell's + * blur actor, which then has nothing left to blur. MetaSurfaceActor isn't + * introspectable, so it is matched by skipping those injected actors, which are + * always StWidgets. * * @param actor - The window actor to unwrap. - * @returns The correct actor that the effect should be applied to. + * @returns The actor to apply the effect to, or `undefined` if the window + * contents don't exist yet. */ export function unwrapActor(actor: RoundedWindowActor) { - const type = actor.metaWindow.get_client_type(); - return type === Meta.WindowClientType.X11 ? actor.get_first_child() : actor; + return actor.get_children().find(child => !(child instanceof St.Widget)); } /** @@ -67,14 +71,9 @@ type RoundedCornersEffectType = InstanceType; * @returns The corresponding Clutter.Effect object. */ export function getRoundedCornersEffect(actor: RoundedWindowActor) { - const win = actor.metaWindow; - const name = ROUNDED_CORNERS_EFFECT; - const isXwayland = - win.get_client_type() === Meta.WindowClientType.X11 && actor.firstChild; - - return isXwayland - ? (actor.firstChild.get_effect(name) as RoundedCornersEffectType) - : (actor.get_effect(name) as RoundedCornersEffectType); + return unwrapActor(actor)?.get_effect( + ROUNDED_CORNERS_EFFECT, + ) as RoundedCornersEffectType | null; } /** Compute outer bounds for rounded corners of a window