From 6061c88e2b290e3dcc417ee409646ec17a4b7e7f Mon Sep 17 00:00:00 2001 From: retrozinndev Date: Wed, 21 May 2025 14:40:16 -0300 Subject: [PATCH] :boom: fix(popup-window): outside-click not working this commit applies another method of doing this function. The checks happen in the same layer, instead of two layers --- ags/runner/Runner.ts | 30 ++++++++---- ags/widget/BackgroundWindow.ts | 5 +- ags/widget/CustomDialog.ts | 2 + ags/widget/PopupWindow.ts | 90 +++++++++++++++++++++++++++++----- ags/window/AppsWindow.ts | 5 +- ags/window/CenterWindow.ts | 5 +- ags/window/ControlCenter.ts | 9 ++-- 7 files changed, 111 insertions(+), 35 deletions(-) diff --git a/ags/runner/Runner.ts b/ags/runner/Runner.ts index 37ec63f..3c27622 100644 --- a/ags/runner/Runner.ts +++ b/ags/runner/Runner.ts @@ -4,6 +4,7 @@ import { PopupWindow, PopupWindowProps } from "../widget/PopupWindow"; import { updateApps } from "../scripts/apps"; import { ResultWidget, ResultWidgetProps } from "../widget/runner/ResultWidget"; import { Windows } from "../windows"; +import AstalHyprland from "gi://AstalHyprland"; export namespace Runner { export type RunnerProps = { @@ -13,6 +14,7 @@ export type RunnerProps = { height?: number; entryPlaceHolder?: string; initialText?: string; + resultsLimit?: number; showResultsPlaceHolderOnStartup?: boolean; }; @@ -57,7 +59,7 @@ export function getPlugins(): Array { return [...plugins.values()]; } -/** Removes a plugin from the runner plugin list +/** Removes a plugin from the runner plugins list * @returns true if plugin was removed or false if plugin wasn't found */ export function removePlugin(plugin: Plugin): boolean { @@ -75,7 +77,8 @@ export function openDefault(initialText?: string) { return Runner.openRunner({ entryPlaceHolder: "Start typing...", showResultsPlaceHolderOnStartup: false, - initialText + initialText, + resultsLimit: 24 } as Runner.RunnerProps, () => [ new ResultWidget({ @@ -145,6 +148,8 @@ export function openRunner(props?: RunnerProps, placeholder?: () => Array Array plugin.handle( + const results = calledPlugins.map(plugin => plugin.handle( plugin.prefix ? input.replace(plugin.prefix, "") : input) ).filter(value => value !== undefined && value !== null).flat(1); + + return props?.resultsLimit != null && + props.resultsLimit !== Infinity ? + results.splice(0, props.resultsLimit) + : results; } function updateResultsList(entryText: string) { @@ -213,10 +223,12 @@ export function openRunner(props?: RunnerProps, placeholder?: () => Array PopupWindow({ namespace: "runner", monitor: mon, - widthRequest: props?.width ?? 750, - heightRequest: props?.height ?? 450, - marginTop: 240, - anchor: Astal.WindowAnchor.TOP | Astal.WindowAnchor.BOTTOM, + widthRequest: props?.width ?? 780, + heightRequest: props?.height ?? defaultHeight, + marginTop: (AstalHyprland.get_default().get_monitor(mon)?.height / 2) - 220, + exclusivity: Astal.Exclusivity.IGNORE, + halign: Gtk.Align.CENTER, + valign: Gtk.Align.START, setup: () => { // Init plugins plugins.forEach(plugin => plugin.init && plugin.init()); @@ -246,7 +258,7 @@ export function openRunner(props?: RunnerProps, placeholder?: () => Array Array void; keymode?: Astal.Keymode; + exclusivity?: Astal.Exclusivity; }; /** Creates a fullscreen GtkWindow that is used for making @@ -35,8 +36,8 @@ export function BackgroundWindow(props: BackgroundWindowProps) { monitor: props.monitor, layer: props.layer ?? Astal.Layer.OVERLAY, anchor: TOP | LEFT | BOTTOM | RIGHT, - keymode: props.keymode ?? Astal.Keymode.NONE, - exclusivity: Astal.Exclusivity.IGNORE, + keymode: props.keymode, + exclusivity: props.exclusivity ?? Astal.Exclusivity.IGNORE, onKeyPressEvent: (self, event: Gdk.Event) => { event.get_keyval()[1] === Gdk.KEY_Escape && props.onAction?.(self); diff --git a/ags/widget/CustomDialog.ts b/ags/widget/CustomDialog.ts index 9669dc3..55523b6 100644 --- a/ags/widget/CustomDialog.ts +++ b/ags/widget/CustomDialog.ts @@ -36,6 +36,8 @@ export function CustomDialog(props: CustomDialogProps = { cssBackgroundWindow: props.cssBackground ?? "background: rgba(0, 0, 0, .3);", exclusivity: Astal.Exclusivity.IGNORE, layer: Astal.Layer.OVERLAY, + halign: Gtk.Align.CENTER, + valign: Gtk.Align.CENTER, widthRequest: props.widthRequest ?? 400, heightRequest: props.heightRequest ?? 220, onDestroy: props.onFinish, diff --git a/ags/widget/PopupWindow.ts b/ags/widget/PopupWindow.ts index 1857df6..755f51f 100644 --- a/ags/widget/PopupWindow.ts +++ b/ags/widget/PopupWindow.ts @@ -1,37 +1,84 @@ import { Binding } from "astal"; -import { Astal, Gdk, Widget } from "astal/gtk3"; +import { Astal, Gdk, Gtk, Widget } from "astal/gtk3"; import { BackgroundWindow } from "./BackgroundWindow"; type PopupWindowSpecificProps = { onDestroy?: (self: Widget.Window) => void; - onKeyPressEvent?: (win: Widget.Window, event: Gdk.Event) => void; + onKeyPressEvent?: (self: Widget.Window, event: Gdk.Event) => void; + onButtonPressEvent?: (self: Gtk.Widget, event: Gdk.Event) => void; /** Stylesheet for the background of the popup-window */ cssBackgroundWindow?: string; }; -export type PopupWindowProps = Omit & PopupWindowSpecificProps; +export type PopupWindowProps = Pick & PopupWindowSpecificProps; + +const { TOP, LEFT, RIGHT, BOTTOM } = Astal.WindowAnchor; export function PopupWindow(props: PopupWindowProps): Widget.Window { props.layer = props.layer ?? Astal.Layer.OVERLAY; - const bgWindow = BackgroundWindow({ + const bgWindow = props.cssBackgroundWindow ? BackgroundWindow({ monitor: props.monitor ?? 0, - layer: props.layer!, - css: props.cssBackgroundWindow ?? "", - onAction: () => window.close() - }); + layer: props.layer, + css: props.cssBackgroundWindow, + }) : undefined; - const window = new Widget.Window({ + return new Widget.Window({ ...props, namespace: props?.namespace ?? "popup-window", className: `popup-window ${(props.namespace instanceof Binding ? props.namespace.get() : props.namespace) || ""}`, keymode: Astal.Keymode.EXCLUSIVE, - layer: props.layer!, + anchor: TOP | LEFT | RIGHT | BOTTOM, + exclusivity: props.exclusivity ?? Astal.Exclusivity.NORMAL, + halign: undefined, + valign: undefined, + focusOnMap: true, + widthRequest: undefined, + heightRequest: undefined, + marginTop: undefined, + marginBottom: undefined, + marginLeft: undefined, + marginRight: undefined, onDestroy: (self) => { - bgWindow.close(); + bgWindow?.close(); props.onDestroy?.(self); }, + onButtonPressEvent: (self, event) => { + if((event.get_button()[1] === Gdk.BUTTON_PRIMARY || + event.get_button()[1] === Gdk.BUTTON_SECONDARY)) { + + const [ , x, y ] = event.get_coords(); + const allocation = (self.get_child()! as Widget.Box).get_child()!.get_allocation(); + + if((x < allocation.x || x > (allocation.x + allocation.width)) || + (y < allocation.y || y > (allocation.y + allocation.height))) { + + self.close(); + } + } + }, onKeyPressEvent: (self, event: Gdk.Event) => { if(event.get_keyval()[1] === Gdk.KEY_Escape) { self.close(); @@ -40,7 +87,24 @@ export function PopupWindow(props: PopupWindowProps): Widget.Window { props.onKeyPressEvent?.(self, event); }, + child: new Widget.Box({ + expand: props.expand ?? false, + halign: props.halign, + valign: props.valign, + hexpand: true, + css: `box { + margin-left: ${props.marginLeft ?? 0}px; + margin-right: ${props.marginRight ?? 0}px; + margin-top: ${props.marginTop ?? 0}px; + margin-bottom: ${props.marginBottom ?? 0}px; + }`, + + child: new Widget.Box({ + onButtonPressEvent: props.onButtonPressEvent ?? (() => true), + widthRequest: props.widthRequest, + heightRequest: props.heightRequest, + child: props.child + } as Widget.BoxProps) + } as Widget.BoxProps) } as Widget.WindowProps); - - return window; } diff --git a/ags/window/AppsWindow.ts b/ags/window/AppsWindow.ts index 2336ff5..fb71139 100644 --- a/ags/window/AppsWindow.ts +++ b/ags/window/AppsWindow.ts @@ -4,8 +4,6 @@ import { cleanExec, getAppIcon, getApps, getAstalApps } from "../scripts/apps"; import AstalApps from "gi://AstalApps"; import { PopupWindow } from "../widget/PopupWindow"; -const { TOP, LEFT, RIGHT, BOTTOM } = Astal.WindowAnchor; - export const AppsWindow = (mon: number): (Widget.Window) => { const searchString = new Variable(""); const searchSubscription = searchString.subscribe((str: string) => { @@ -111,10 +109,9 @@ export const AppsWindow = (mon: number): (Widget.Window) => { namespace: "apps-window", layer: Astal.Layer.OVERLAY, exclusivity: Astal.Exclusivity.IGNORE, - anchor: TOP | LEFT | RIGHT | BOTTOM, monitor: mon, - cssBackgroundWindow: "background: rgba(0, 0, 0, .2)", marginTop: 64, + cssBackgroundWindow: "background: rgba(0, 0, 0, .2)", onDestroy: () => { searchSubscription?.(); searchString.drop(); diff --git a/ags/window/CenterWindow.ts b/ags/window/CenterWindow.ts index 0a81ff2..039a2c9 100644 --- a/ags/window/CenterWindow.ts +++ b/ags/window/CenterWindow.ts @@ -1,4 +1,4 @@ -import { Astal, Gtk, Widget } from "astal/gtk3"; +import { Gtk, Widget } from "astal/gtk3"; import { bind, GLib } from "astal"; import { getDateTime } from "../scripts/time"; @@ -10,7 +10,8 @@ import AstalMpris from "gi://AstalMpris"; export const CenterWindow = (mon: number) => PopupWindow({ namespace: "center-window", marginTop: 10, - anchor: Astal.WindowAnchor.TOP, + halign: Gtk.Align.CENTER, + valign: Gtk.Align.START, monitor: mon, child: new Widget.Box({ className: "center-window-container", diff --git a/ags/window/ControlCenter.ts b/ags/window/ControlCenter.ts index 0baac90..bacad1a 100644 --- a/ags/window/ControlCenter.ts +++ b/ags/window/ControlCenter.ts @@ -3,16 +3,15 @@ import { QuickActions } from "../widget/control-center/QuickActions"; import { Tiles } from "../widget/control-center/Tiles"; import { Sliders } from "../widget/control-center/Sliders"; import { NotifHistory } from "../widget/control-center/NotifHistory"; -import { PopupWindow } from "../widget/PopupWindow"; +import { PopupWindow, PopupWindowProps } from "../widget/PopupWindow"; export const ControlCenter = (mon: number) => PopupWindow({ namespace: "control-center", className: "control-center", - exclusivity: Astal.Exclusivity.NORMAL, - anchor: Astal.WindowAnchor.TOP | Astal.WindowAnchor.RIGHT | Astal.WindowAnchor.BOTTOM, + halign: Gtk.Align.END, + valign: Gtk.Align.START, layer: Astal.Layer.OVERLAY, - focusOnMap: true, marginTop: 10, marginRight: 10, marginBottom: 10, @@ -34,4 +33,4 @@ export const ControlCenter = (mon: number) => PopupWindow({ NotifHistory() ] } as Widget.BoxProps) -} as Widget.WindowProps); +} as PopupWindowProps);