💥 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
This commit is contained in:
retrozinndev
2025-05-21 14:40:16 -03:00
parent 1f6da17363
commit 6061c88e2b
7 changed files with 111 additions and 35 deletions
+21 -9
View File
@@ -4,6 +4,7 @@ import { PopupWindow, PopupWindowProps } from "../widget/PopupWindow";
import { updateApps } from "../scripts/apps"; import { updateApps } from "../scripts/apps";
import { ResultWidget, ResultWidgetProps } from "../widget/runner/ResultWidget"; import { ResultWidget, ResultWidgetProps } from "../widget/runner/ResultWidget";
import { Windows } from "../windows"; import { Windows } from "../windows";
import AstalHyprland from "gi://AstalHyprland";
export namespace Runner { export namespace Runner {
export type RunnerProps = { export type RunnerProps = {
@@ -13,6 +14,7 @@ export type RunnerProps = {
height?: number; height?: number;
entryPlaceHolder?: string; entryPlaceHolder?: string;
initialText?: string; initialText?: string;
resultsLimit?: number;
showResultsPlaceHolderOnStartup?: boolean; showResultsPlaceHolderOnStartup?: boolean;
}; };
@@ -57,7 +59,7 @@ export function getPlugins(): Array<Runner.Plugin> {
return [...plugins.values()]; 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 * @returns true if plugin was removed or false if plugin wasn't found
*/ */
export function removePlugin(plugin: Plugin): boolean { export function removePlugin(plugin: Plugin): boolean {
@@ -75,7 +77,8 @@ export function openDefault(initialText?: string) {
return Runner.openRunner({ return Runner.openRunner({
entryPlaceHolder: "Start typing...", entryPlaceHolder: "Start typing...",
showResultsPlaceHolderOnStartup: false, showResultsPlaceHolderOnStartup: false,
initialText initialText,
resultsLimit: 24
} as Runner.RunnerProps, } as Runner.RunnerProps,
() => [ () => [
new ResultWidget({ new ResultWidget({
@@ -145,6 +148,8 @@ export function openRunner(props?: RunnerProps, placeholder?: () => Array<Result
primary_icon_name: "system-search" primary_icon_name: "system-search"
} as Widget.EntryProps); } as Widget.EntryProps);
const defaultHeight = 300;
const resultsList: Gtk.ListBox = new Gtk.ListBox({ const resultsList: Gtk.ListBox = new Gtk.ListBox({
visible: true, visible: true,
expand: true expand: true
@@ -174,9 +179,14 @@ export function openRunner(props?: RunnerProps, placeholder?: () => Array<Result
} }
} }
return calledPlugins.map(plugin => plugin.handle( const results = calledPlugins.map(plugin => plugin.handle(
plugin.prefix ? input.replace(plugin.prefix, "") : input) plugin.prefix ? input.replace(plugin.prefix, "") : input)
).filter(value => value !== undefined && value !== null).flat(1); ).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) { function updateResultsList(entryText: string) {
@@ -213,10 +223,12 @@ export function openRunner(props?: RunnerProps, placeholder?: () => Array<Result
instance = Windows.createWindowForFocusedMonitor((mon: number): (Widget.Window) => PopupWindow({ instance = Windows.createWindowForFocusedMonitor((mon: number): (Widget.Window) => PopupWindow({
namespace: "runner", namespace: "runner",
monitor: mon, monitor: mon,
widthRequest: props?.width ?? 750, widthRequest: props?.width ?? 780,
heightRequest: props?.height ?? 450, heightRequest: props?.height ?? defaultHeight,
marginTop: 240, marginTop: (AstalHyprland.get_default().get_monitor(mon)?.height / 2) - 220,
anchor: Astal.WindowAnchor.TOP | Astal.WindowAnchor.BOTTOM, exclusivity: Astal.Exclusivity.IGNORE,
halign: Gtk.Align.CENTER,
valign: Gtk.Align.START,
setup: () => { setup: () => {
// Init plugins // Init plugins
plugins.forEach(plugin => plugin.init && plugin.init()); plugins.forEach(plugin => plugin.init && plugin.init());
@@ -246,7 +258,7 @@ export function openRunner(props?: RunnerProps, placeholder?: () => Array<Result
child: new Widget.Box({ child: new Widget.Box({
className: "runner main", className: "runner main",
orientation: Gtk.Orientation.VERTICAL, orientation: Gtk.Orientation.VERTICAL,
expand: false, hexpand: true,
valign: Gtk.Align.START, valign: Gtk.Align.START,
children: [ children: [
gtkEntry, gtkEntry,
@@ -256,7 +268,7 @@ export function openRunner(props?: RunnerProps, placeholder?: () => Array<Result
hscroll: Gtk.PolicyType.NEVER, hscroll: Gtk.PolicyType.NEVER,
expand: true, expand: true,
propagateNaturalHeight: true, propagateNaturalHeight: true,
maxContentHeight: props?.height ?? 450, maxContentHeight: props?.height ?? defaultHeight,
child: resultsList child: resultsList
}) })
] ]
+3 -2
View File
@@ -18,6 +18,7 @@ export type BackgroundWindowProps = {
/** Function that is called when the user clicks on the window with secodary mouse button */ /** Function that is called when the user clicks on the window with secodary mouse button */
onClickSecondary?: (window: Widget.Window) => void; onClickSecondary?: (window: Widget.Window) => void;
keymode?: Astal.Keymode; keymode?: Astal.Keymode;
exclusivity?: Astal.Exclusivity;
}; };
/** Creates a fullscreen GtkWindow that is used for making /** Creates a fullscreen GtkWindow that is used for making
@@ -35,8 +36,8 @@ export function BackgroundWindow(props: BackgroundWindowProps) {
monitor: props.monitor, monitor: props.monitor,
layer: props.layer ?? Astal.Layer.OVERLAY, layer: props.layer ?? Astal.Layer.OVERLAY,
anchor: TOP | LEFT | BOTTOM | RIGHT, anchor: TOP | LEFT | BOTTOM | RIGHT,
keymode: props.keymode ?? Astal.Keymode.NONE, keymode: props.keymode,
exclusivity: Astal.Exclusivity.IGNORE, exclusivity: props.exclusivity ?? Astal.Exclusivity.IGNORE,
onKeyPressEvent: (self, event: Gdk.Event) => { onKeyPressEvent: (self, event: Gdk.Event) => {
event.get_keyval()[1] === Gdk.KEY_Escape && event.get_keyval()[1] === Gdk.KEY_Escape &&
props.onAction?.(self); props.onAction?.(self);
+2
View File
@@ -36,6 +36,8 @@ export function CustomDialog(props: CustomDialogProps = {
cssBackgroundWindow: props.cssBackground ?? "background: rgba(0, 0, 0, .3);", cssBackgroundWindow: props.cssBackground ?? "background: rgba(0, 0, 0, .3);",
exclusivity: Astal.Exclusivity.IGNORE, exclusivity: Astal.Exclusivity.IGNORE,
layer: Astal.Layer.OVERLAY, layer: Astal.Layer.OVERLAY,
halign: Gtk.Align.CENTER,
valign: Gtk.Align.CENTER,
widthRequest: props.widthRequest ?? 400, widthRequest: props.widthRequest ?? 400,
heightRequest: props.heightRequest ?? 220, heightRequest: props.heightRequest ?? 220,
onDestroy: props.onFinish, onDestroy: props.onFinish,
+77 -13
View File
@@ -1,37 +1,84 @@
import { Binding } from "astal"; import { Binding } from "astal";
import { Astal, Gdk, Widget } from "astal/gtk3"; import { Astal, Gdk, Gtk, Widget } from "astal/gtk3";
import { BackgroundWindow } from "./BackgroundWindow"; import { BackgroundWindow } from "./BackgroundWindow";
type PopupWindowSpecificProps = { type PopupWindowSpecificProps = {
onDestroy?: (self: Widget.Window) => void; 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 */ /** Stylesheet for the background of the popup-window */
cssBackgroundWindow?: string; cssBackgroundWindow?: string;
}; };
export type PopupWindowProps = Omit<Widget.WindowProps, "keymode"> & PopupWindowSpecificProps; export type PopupWindowProps = Pick<Widget.WindowProps,
"child"
| "monitor"
| "css"
| "layer"
| "exclusivity"
| "marginLeft"
| "marginTop"
| "marginRight"
| "marginBottom"
| "expand"
| "cursor"
| "canFocus"
| "hasFocus"
| "tooltipMarkup"
| "namespace"
| "widthRequest"
| "heightRequest"
| "halign"
| "valign"
| "vexpand"
| "hexpand"> & PopupWindowSpecificProps;
const { TOP, LEFT, RIGHT, BOTTOM } = Astal.WindowAnchor;
export function PopupWindow(props: PopupWindowProps): Widget.Window { export function PopupWindow(props: PopupWindowProps): Widget.Window {
props.layer = props.layer ?? Astal.Layer.OVERLAY; props.layer = props.layer ?? Astal.Layer.OVERLAY;
const bgWindow = BackgroundWindow({ const bgWindow = props.cssBackgroundWindow ? BackgroundWindow({
monitor: props.monitor ?? 0, monitor: props.monitor ?? 0,
layer: props.layer!, layer: props.layer,
css: props.cssBackgroundWindow ?? "", css: props.cssBackgroundWindow,
onAction: () => window.close() }) : undefined;
});
const window = new Widget.Window({ return new Widget.Window({
...props, ...props,
namespace: props?.namespace ?? "popup-window", namespace: props?.namespace ?? "popup-window",
className: `popup-window ${(props.namespace instanceof Binding ? className: `popup-window ${(props.namespace instanceof Binding ?
props.namespace.get() : props.namespace) || ""}`, props.namespace.get() : props.namespace) || ""}`,
keymode: Astal.Keymode.EXCLUSIVE, 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) => { onDestroy: (self) => {
bgWindow.close(); bgWindow?.close();
props.onDestroy?.(self); 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) => { onKeyPressEvent: (self, event: Gdk.Event) => {
if(event.get_keyval()[1] === Gdk.KEY_Escape) { if(event.get_keyval()[1] === Gdk.KEY_Escape) {
self.close(); self.close();
@@ -40,7 +87,24 @@ export function PopupWindow(props: PopupWindowProps): Widget.Window {
props.onKeyPressEvent?.(self, event); props.onKeyPressEvent?.(self, event);
}, },
} as Widget.WindowProps); 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;
}`,
return window; 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);
} }
+1 -4
View File
@@ -4,8 +4,6 @@ import { cleanExec, getAppIcon, getApps, getAstalApps } from "../scripts/apps";
import AstalApps from "gi://AstalApps"; import AstalApps from "gi://AstalApps";
import { PopupWindow } from "../widget/PopupWindow"; import { PopupWindow } from "../widget/PopupWindow";
const { TOP, LEFT, RIGHT, BOTTOM } = Astal.WindowAnchor;
export const AppsWindow = (mon: number): (Widget.Window) => { export const AppsWindow = (mon: number): (Widget.Window) => {
const searchString = new Variable<string>(""); const searchString = new Variable<string>("");
const searchSubscription = searchString.subscribe((str: string) => { const searchSubscription = searchString.subscribe((str: string) => {
@@ -111,10 +109,9 @@ export const AppsWindow = (mon: number): (Widget.Window) => {
namespace: "apps-window", namespace: "apps-window",
layer: Astal.Layer.OVERLAY, layer: Astal.Layer.OVERLAY,
exclusivity: Astal.Exclusivity.IGNORE, exclusivity: Astal.Exclusivity.IGNORE,
anchor: TOP | LEFT | RIGHT | BOTTOM,
monitor: mon, monitor: mon,
cssBackgroundWindow: "background: rgba(0, 0, 0, .2)",
marginTop: 64, marginTop: 64,
cssBackgroundWindow: "background: rgba(0, 0, 0, .2)",
onDestroy: () => { onDestroy: () => {
searchSubscription?.(); searchSubscription?.();
searchString.drop(); searchString.drop();
+3 -2
View File
@@ -1,4 +1,4 @@
import { Astal, Gtk, Widget } from "astal/gtk3"; import { Gtk, Widget } from "astal/gtk3";
import { bind, GLib } from "astal"; import { bind, GLib } from "astal";
import { getDateTime } from "../scripts/time"; import { getDateTime } from "../scripts/time";
@@ -10,7 +10,8 @@ import AstalMpris from "gi://AstalMpris";
export const CenterWindow = (mon: number) => PopupWindow({ export const CenterWindow = (mon: number) => PopupWindow({
namespace: "center-window", namespace: "center-window",
marginTop: 10, marginTop: 10,
anchor: Astal.WindowAnchor.TOP, halign: Gtk.Align.CENTER,
valign: Gtk.Align.START,
monitor: mon, monitor: mon,
child: new Widget.Box({ child: new Widget.Box({
className: "center-window-container", className: "center-window-container",
+4 -5
View File
@@ -3,16 +3,15 @@ import { QuickActions } from "../widget/control-center/QuickActions";
import { Tiles } from "../widget/control-center/Tiles"; import { Tiles } from "../widget/control-center/Tiles";
import { Sliders } from "../widget/control-center/Sliders"; import { Sliders } from "../widget/control-center/Sliders";
import { NotifHistory } from "../widget/control-center/NotifHistory"; import { NotifHistory } from "../widget/control-center/NotifHistory";
import { PopupWindow } from "../widget/PopupWindow"; import { PopupWindow, PopupWindowProps } from "../widget/PopupWindow";
export const ControlCenter = (mon: number) => PopupWindow({ export const ControlCenter = (mon: number) => PopupWindow({
namespace: "control-center", namespace: "control-center",
className: "control-center", className: "control-center",
exclusivity: Astal.Exclusivity.NORMAL, halign: Gtk.Align.END,
anchor: Astal.WindowAnchor.TOP | Astal.WindowAnchor.RIGHT | Astal.WindowAnchor.BOTTOM, valign: Gtk.Align.START,
layer: Astal.Layer.OVERLAY, layer: Astal.Layer.OVERLAY,
focusOnMap: true,
marginTop: 10, marginTop: 10,
marginRight: 10, marginRight: 10,
marginBottom: 10, marginBottom: 10,
@@ -34,4 +33,4 @@ export const ControlCenter = (mon: number) => PopupWindow({
NotifHistory() NotifHistory()
] ]
} as Widget.BoxProps) } as Widget.BoxProps)
} as Widget.WindowProps); } as PopupWindowProps);