diff --git a/schemas/org.gnome.shell.extensions.quick-settings-tweaks.gschema.xml b/schemas/org.gnome.shell.extensions.quick-settings-tweaks.gschema.xml index 57888ab..ce86a6b 100644 --- a/schemas/org.gnome.shell.extensions.quick-settings-tweaks.gschema.xml +++ b/schemas/org.gnome.shell.extensions.quick-settings-tweaks.gschema.xml @@ -41,6 +41,9 @@ true + + false + diff --git a/src/features/widget/notifications.ts b/src/features/widget/notifications.ts index 6df05de..e49e34d 100644 --- a/src/features/widget/notifications.ts +++ b/src/features/widget/notifications.ts @@ -358,6 +358,7 @@ export class NotificationsWidgetFeature extends FeatureBase { removeShadow: boolean header: boolean scrollStyle: StyledScroll.Options + leftOfQuickSettings: boolean override loadSettings(loader: SettingLoader): void { this.enabled = loader.loadBoolean("notifications-enabled") this.useNativeControls = loader.loadBoolean("notifications-use-native-controls") @@ -367,10 +368,14 @@ export class NotificationsWidgetFeature extends FeatureBase { this.removeShadow = loader.loadBoolean("notifications-remove-shadow") this.header = loader.loadBoolean("notifications-show-header") this.scrollStyle = StyledScroll.Options.fromLoader(loader, "notifications") + this.leftOfQuickSettings = loader.loadBoolean("notifications-left-of-quick-settings") } // #endregion settings notificationWidget: NotificationWidget + sideBySideBox: St.BoxLayout + gridParent: Clutter.Actor + gridNextSibling: Clutter.Actor override reload(key: string): void { switch (key) { case "notifications-max-height": @@ -387,6 +392,10 @@ export class NotificationsWidgetFeature extends FeatureBase { if (!this.enabled) return this.notificationWidget!._updateScrollStyle() break + case "notifications-left-of-quick-settings": + if (!this.enabled) return + this._syncPlacement() + break default: super.reload() break @@ -400,14 +409,113 @@ export class NotificationsWidgetFeature extends FeatureBase { this.notificationWidget = new NotificationWidget(this) ) - // Add to grid - Global.QuickSettingsGrid.add_child(this.notificationWidget) - Global.QuickSettingsGrid.layout_manager.child_set_property( - Global.QuickSettingsGrid, this.notificationWidget, "column-span", 2 - ) + this._syncPlacement() } override onUnload(): void { + this._teardownSideBySide() this.notificationWidget = null } + + private _syncPlacement(): void { + if (!this.notificationWidget) return + if (this.leftOfQuickSettings) { + this._setupSideBySide() + } else { + this._teardownSideBySide() + this._attachToGrid() + } + } + + private _attachToGrid(): void { + if (!this.notificationWidget) return + const grid = Global.QuickSettingsGrid + if (!grid) return + if (this.notificationWidget.get_parent() !== grid) { + this.notificationWidget.get_parent()?.remove_child(this.notificationWidget) + grid.add_child(this.notificationWidget) + } + const layout = grid.layout_manager + if (layout && "child_set_property" in layout) { + layout.child_set_property( + grid, + this.notificationWidget, + "column-span", + 2 + ) + } + } + + private _setupSideBySide(): void { + if (!this.notificationWidget) return + const grid = Global.QuickSettingsGrid + if (!grid) return + + // If we already have a container just make sure the widget sits there + if (this.sideBySideBox) { + if (this.notificationWidget.get_parent() !== this.sideBySideBox) { + this.notificationWidget.reparent(this.sideBySideBox) + } + return + } + + const parent = grid.get_parent() + if (!parent) return + + if (this.notificationWidget.get_parent()) { + this.notificationWidget.get_parent().remove_child(this.notificationWidget) + } + + this.gridParent = parent + this.gridNextSibling = grid.get_next_sibling() + parent.remove_child(grid) + + const sideBySide = new St.BoxLayout({ + vertical: false, + x_expand: true, + y_expand: true, + style_class: "QSTWEAKS-notifications-left-layout", + }) + this.sideBySideBox = sideBySide + + if (this.gridNextSibling && this.gridNextSibling.get_parent() === parent) { + parent.insert_child_above(sideBySide, this.gridNextSibling) + } else { + parent.add_child(sideBySide) + } + + this.notificationWidget.x_expand = true + this.notificationWidget.y_expand = true + sideBySide.add_child(this.notificationWidget) + + grid.x_expand = true + grid.y_expand = true + sideBySide.add_child(grid) + } + + private _teardownSideBySide(): void { + if (!this.sideBySideBox) return + const container = this.sideBySideBox + const grid = Global.QuickSettingsGrid + + if (this.notificationWidget && this.notificationWidget.get_parent() === container) { + container.remove_child(this.notificationWidget) + } + + if (grid && grid.get_parent() === container) { + container.remove_child(grid) + if (this.gridParent) { + if (this.gridNextSibling && this.gridNextSibling.get_parent() === this.gridParent) { + this.gridParent.insert_child_above(grid, this.gridNextSibling) + } else { + this.gridParent.add_child(grid) + } + } + } + + container.destroy() + this.sideBySideBox = null + this.gridParent = null + this.gridNextSibling = null + } } // #endregion NotificationsWidgetFeature diff --git a/src/prefPages/widgets.ts b/src/prefPages/widgets.ts index d45a821..7dc6ddc 100644 --- a/src/prefPages/widgets.ts +++ b/src/prefPages/widgets.ts @@ -350,6 +350,13 @@ export const WidgetsPage = GObject.registerClass({ bind: "notifications-show-scrollbar", sensitiveBind: "notifications-enabled", }), + SwitchRow({ + settings, + title: _("Show notifications on the left"), + subtitle: _("Place the notifications panel to the left of the Quick Settings panel instead of below it"), + bind: "notifications-left-of-quick-settings", + sensitiveBind: "notifications-enabled", + }), ]) // weather diff --git a/src/styles/notification-widget.scss b/src/styles/notification-widget.scss index 8296960..25ab631 100644 --- a/src/styles/notification-widget.scss +++ b/src/styles/notification-widget.scss @@ -97,3 +97,17 @@ } } } + +#{$p}-notifications-left-layout { + spacing: 12px; + min-width: 0; + + > * { + min-width: 0; + } + + #{$p}-notifications { + min-width: 360px; + max-width: 460px; + } +}