Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions src/manager/event_manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down
29 changes: 14 additions & 15 deletions src/manager/utils.ts
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -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 {
Expand All @@ -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));
}

/**
Expand Down Expand Up @@ -67,14 +71,9 @@ type RoundedCornersEffectType = InstanceType<typeof RoundedCornersEffect>;
* @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
Expand Down