diff --git a/po/ar.po b/po/ar.po index dd19a243..5a48b0fb 100644 --- a/po/ar.po +++ b/po/ar.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: 12\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-01-14 10:38+0100\n" +"POT-Creation-Date: 2025-09-16 11:35+0800\n" "PO-Revision-Date: 2023-12-10 10:05+0000\n" "Last-Translator: Nadjib Chergui \n" "Language-Team: Arabic \n" "Language-Team: Czech \n" "Language-Team: German \n" "Language-Team: Esperanto \n" "Language-Team: Spanish \n" "Language-Team: Finnish \n" "Language-Team: French \n" "Language-Team: Hungarian \n" "Language-Team: Indonesian \n" "Language-Team: Italian \n" "Language-Team: Japanese \n" "Language-Team: Norwegian Bokmål \n" "Language-Team: Dutch \n" "Language-Team: Polish \n" "Language-Team: Portuguese \n" "Language-Team: Portuguese (Brazil) \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=CHARSET\n" +"Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: src/preferences/pages/blacklist.ui:6 src/preferences/pages/blacklist.ui:10 @@ -52,7 +52,7 @@ msgid "Unfocused window" msgstr "" #: src/preferences/pages/edit-shadow.ui:66 -msgid "Focused shadow prefrences" +msgid "Focused shadow preferences" msgstr "" #: src/preferences/pages/edit-shadow.ui:69 @@ -81,7 +81,7 @@ msgid "Opacity" msgstr "" #: src/preferences/pages/edit-shadow.ui:206 -msgid "Unfocused shadow prefrences" +msgid "Unfocused shadow preferences" msgstr "" #: src/preferences/pages/general.ui:6 diff --git a/po/ru.po b/po/ru.po index 8bed41fe..8212f325 100644 --- a/po/ru.po +++ b/po/ru.po @@ -1,7 +1,7 @@ msgid "" msgstr "" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-01-14 10:38+0100\n" +"POT-Creation-Date: 2025-09-16 11:35+0800\n" "PO-Revision-Date: 2023-03-09 15:37+0000\n" "Last-Translator: Evgeniy Khramov \n" "Language-Team: Russian \n" "Language-Team: Turkish \n" "Language-Team: Ukrainian \n" "Language-Team: Chinese (Simplified) { - if (constraint instanceof Clutter.BindConstraint) { - constraint.offset = offsets[i]; - } - }); + // Update BindConstraint for the shadow + const shadow = windowInfo.shadow; + const offsets = computeShadowActorOffset(actor, windowContentOffset); + const constraints = shadow.get_constraints(); + constraints.forEach((constraint, i) => { + if (constraint instanceof Clutter.BindConstraint) { + constraint.offset = offsets[i]; + } + }); - refreshShadow(actor); + refreshShadow(actor); + } } /** Refresh rounded corners settings for all windows. */ diff --git a/src/manager/event_manager.ts b/src/manager/event_manager.ts index 49f979ec..559a022d 100644 --- a/src/manager/event_manager.ts +++ b/src/manager/event_manager.ts @@ -38,14 +38,25 @@ export function enableEffect() { global.display, 'window-created', (_: Meta.Display, win: Meta.Window) => { + if (!win) { + logDebug('window-created signal received with null window'); + return; + } + const actor: Meta.WindowActor = win.get_compositor_private(); + if (!actor) { + logDebug('No compositor private actor found for window'); + return; + } // If wm_class_instance of Meta.Window is null, wait for it to be // set before applying the effect. - if (win?.get_wm_class_instance() == null) { + if (win.get_wm_class_instance() == null) { const notifyId = win.connect('notify::wm-class', () => { - applyEffectTo(actor); - win.disconnect(notifyId); + if (win.get_wm_class_instance() != null) { + applyEffectTo(actor); + win.disconnect(notifyId); + } }); } else { applyEffectTo(actor); @@ -111,11 +122,27 @@ function connect( * @param object - If object is provided, only disconnect signals from it. */ function disconnectAll(object?: GObject.Object) { - for (const connection of connections) { + const toRemove: number[] = []; + + for (let i = 0; i < connections.length; i++) { + const connection = connections[i]; if (object === undefined || connection.object === object) { - connection.object.disconnect(connection.id); + try { + // Check if the object still exists and has the signal handler + if (connection.object && typeof connection.object.disconnect === 'function') { + connection.object.disconnect(connection.id); + } + } catch (e) { + logDebug(`Failed to disconnect signal ${connection.id}: ${e}`); + } + toRemove.push(i); } } + + // Remove disconnected connections from the array (in reverse order to maintain indices) + for (let i = toRemove.length - 1; i >= 0; i--) { + connections.splice(toRemove[i], 1); + } } /** @@ -128,15 +155,23 @@ function disconnectAll(object?: GObject.Object) { * @param actor - The window actor to apply the effect to. */ function applyEffectTo(actor: RoundedWindowActor) { + if (!actor || !actor.metaWindow) { + logDebug('applyEffectTo called with null actor or metaWindow'); + return; + } + // 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); - actor.disconnect(id); - }); - + try { + const id = actor.connect('notify::first-child', () => { + applyEffectTo(actor); + actor.disconnect(id); + }); + } catch (e) { + logDebug(`Failed to connect notify::first-child signal: ${e}`); + } return; } @@ -175,8 +210,25 @@ function applyEffectTo(actor: RoundedWindowActor) { * @param actor - The window actor to remove the effect from. */ function removeEffectFrom(actor: RoundedWindowActor) { - disconnectAll(actor); - disconnectAll(actor.metaWindow); + if (!actor) { + logDebug('removeEffectFrom called with null actor'); + return; + } + + try { + disconnectAll(actor); + if (actor.metaWindow) { + disconnectAll(actor.metaWindow); + } + + // Also disconnect from texture to prevent GC callback issues + const texture = actor.get_texture(); + if (texture) { + disconnectAll(texture); + } + } catch (e) { + logDebug(`Error disconnecting signals: ${e}`); + } handlers.onRemoveEffect(actor); } diff --git a/src/manager/utils.ts b/src/manager/utils.ts index 7350f891..b76d741b 100644 --- a/src/manager/utils.ts +++ b/src/manager/utils.ts @@ -67,10 +67,14 @@ type RoundedCornersEffectType = InstanceType; export function getRoundedCornersEffect( actor: Meta.WindowActor, ): RoundedCornersEffectType | null { + if (!actor || !actor.metaWindow) { + return null; + } + const win = actor.metaWindow; const name = ROUNDED_CORNERS_EFFECT; return win.get_client_type() === Meta.WindowClientType.X11 - ? (actor.firstChild.get_effect(name) as RoundedCornersEffectType) + ? (actor.firstChild?.get_effect(name) as RoundedCornersEffectType) : (actor.get_effect(name) as RoundedCornersEffectType); } @@ -267,7 +271,7 @@ export function shouldEnableEffect( // Skip libhandy/libadwaita applications according to settings. const appType = win._appType ?? getAppType(win); win._appType = appType; // Cache the result. - logDebug(`Check Type of window:${win.title} => ${appType}`); + logDebug(`Check Type of window:${win.title || 'unknown'} => ${appType}`); if (getPref('skip-libadwaita-app') && appType === 'LibAdwaita') { return false; diff --git a/src/utils/types.ts b/src/utils/types.ts index 76f25a18..95cf5281 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -2,6 +2,7 @@ import type Meta from 'gi://Meta'; import type St from 'gi://St'; +import type GObject from 'gi://GObject'; /** Bounds of rounded corners */ export type Bounds = { @@ -52,5 +53,6 @@ export type RoundedWindowActor = Meta.WindowActor & { rwcCustomData?: { shadow: St.Bin; unminimizedTimeoutId: number; + propertyBindings?: GObject.Binding[]; }; };