ags(runner): make runner work by keyboard keys, focus entry on type + style improvements

This commit is contained in:
retrozinndev
2025-03-10 20:22:48 -03:00
parent 03813021a8
commit 902361d74e
4 changed files with 76 additions and 82 deletions
+1 -1
View File
@@ -153,7 +153,7 @@ scrollbar trough {
background: colors.$bg-translucent;
border-top-left-radius: 8px;
border-bottom-left-radius: 8px;
padding: 0 2px;
padding: 2px;
& slider {
@include mixins.reset-props;
+4 -5
View File
@@ -32,15 +32,14 @@
}
& list {
& eventbox:focus > box,
& eventbox:hover > box,
& listboxchild:selected eventbox > box,
& listboxchild:active eventbox > box {
& > *:selected > .result,
& > *:active > .result,
& > *:hover > .result {
background: colors.$bg-secondary;
}
}
& list eventbox > .result {
& list .result {
padding: 10px;
background: colors.$bg-primary;
margin: 2px 0;
+11 -21
View File
@@ -14,9 +14,8 @@ type ResultWidgetProps = {
};
@register({ GTypeName: "ResultWidget" })
class ResultWidget extends Widget.EventBox {
private readonly connections: Array<number>;
public readonly onClick: ((() => void)|undefined);
class ResultWidget extends Widget.Box {
public readonly onClick: (() => void);
public readonly icon: (string|undefined);
public readonly setup: ((() => void)|undefined);
public readonly closeOnClick: boolean = true;
@@ -26,32 +25,25 @@ class ResultWidget extends Widget.EventBox {
super();
if(props.icon)
this.icon = props.icon;
if(props.onClick)
this.onClick = props.onClick;
if(props.setup)
this.setup = props.setup;
if(props.closeOnClick !== undefined)
this.closeOnClick = props.closeOnClick;
this.connections = [
this.connect("click", () => {
this.onClick && this.onClick();
this.onClick = () => {
props.onClick && props.onClick();
this.closeOnClick && closeRunner();
}),
};
this.connect("destroy-event", () => this.connections.map((id: number) =>
this.disconnect(id)))
];
this.set_class_name("result");
this.set_hexpand(true);
this.add(new Widget.Box({
className: "result",
hexpand: true,
children: [
new Widget.Icon({
this.add(new Widget.Icon({
visible: Boolean(props.icon),
icon: props.icon || "image-missing"
} as Widget.IconProps),
new Widget.Box({
} as Widget.IconProps));
this.add(new Widget.Box({
orientation: Gtk.Orientation.VERTICAL,
valign: Gtk.Align.CENTER,
children: [
@@ -69,8 +61,6 @@ class ResultWidget extends Widget.EventBox {
label: props.description || ""
} as Widget.LabelProps)
]
} as Widget.BoxProps),
]
} as Widget.BoxProps));
}
}
+42 -37
View File
@@ -1,4 +1,4 @@
import { Variable } from "astal";
import { AstalIO, timeout, Variable } from "astal";
import { Gdk, Gtk, Widget } from "astal/gtk3";
import { PopupWindow, PopupWindowProps } from "../widget/PopupWindow";
import { updateApps } from "../scripts/apps";
@@ -8,6 +8,7 @@ import { handleApplications } from "../scripts/runner/apps";
import { ResultWidget, ResultWidgetProps } from "../widget/runner/ResultWidget";
export let runnerInstance: (Widget.Window|null) = null;
let onClickTimeout: (AstalIO.Time|undefined);
export function closeRunner(gtkWindow?: Widget.Window) {
const window = gtkWindow ? gtkWindow : runnerInstance;
@@ -64,6 +65,13 @@ export namespace Runner {
className: "search",
onChanged: (entry) => entryText.set(entry.text),
placeholderText: props?.entryPlaceHolder || "",
onActivate: (_) => {
const resultWidget = resultsList.get_selected_row()?.get_child();
if(resultWidget instanceof ResultWidget) {
resultWidget.onClick();
_.isFocus = false;
}
},
primary_icon_name: "system-search"
} as Widget.EntryProps);
@@ -82,33 +90,6 @@ export namespace Runner {
: pluginResult)
: null;
[
new Widget.Box({
className: "not-found",
orientation: Gtk.Orientation.VERTICAL,
visible: entryText((text: string) => text.trim().length > 0),
expand: true,
children: [
new Widget.Icon({
icon: "software-update-urgent-symbolic"
} as Widget.IconProps),
new Widget.Label({
label: "Couldn't find any results with this search. Maybe try pressing F5 and searching again?",
truncate: false,
wrap: true
} as Widget.LabelProps)
]
} as Widget.BoxProps),
new Widget.Box({
className: "placeholder",
orientation: Gtk.Orientation.VERTICAL,
expand: true,
visible: Boolean(props?.resultsPlaceholder),
children: props?.resultsPlaceholder &&
props?.resultsPlaceholder()
} as Widget.BoxProps)
];
if(resultsList.get_children().length > 0) {
resultsList.get_children().map((listItem: Gtk.Widget) => {
resultsList.remove(listItem);
@@ -116,10 +97,34 @@ export namespace Runner {
});
}
if(results && results.length > 0)
if(results && results.length > 0 && searchEntry.text.trim().length > 0) {
results.map((resultWidget: ResultWidget) => {
resultsList.insert(resultWidget, -1);
const listBoxChild = resultsList.get_row_at_index(resultsList.get_children().length - 1)!;
const resWidget = listBoxChild.get_child();
if(listBoxChild && resWidget instanceof ResultWidget) {
resultsList.connect("row-activated", (_, row: Gtk.ListBoxRow) => {
const rWidget = row.get_child()!;
if(rWidget instanceof ResultWidget) {
if(!onClickTimeout) {
rWidget.onClick();
// Timeout, so it doesn't fire the executable a hundred times :skull:
onClickTimeout = timeout(500, () => onClickTimeout = undefined);
}
}
});
}
});
} else {
if(props?.resultsPlaceholder) {
const widgets = props.resultsPlaceholder();
resultsList.get_children().map((res) =>
resultsList.remove(res));
widgets.map((widget) => resultsList.insert(widget, -1));
}
}
selectedResultIndex = 0;
resultsList.select_row(resultsList.get_row_at_index(selectedResultIndex));
@@ -133,17 +138,17 @@ export namespace Runner {
widthRequest: props?.width || 750,
heightRequest: props?.height || 450,
onKeyPressEvent: (_, event: Gdk.Event) => {
const keyVal = event.get_keyval()[1];
if(!searchEntry.has_focus && keyVal !== Gdk.KEY_F5
&& keyVal !== Gdk.KEY_Down && keyVal !== Gdk.KEY_Up
&& keyVal !== Gdk.KEY_KP_Enter && keyVal !== Gdk.KEY_ISO_Enter) {
searchEntry.grab_focus_without_selecting();
}
event.get_keyval()[1] === Gdk.KEY_F5 &&
updateApps();
if(event.get_keyval()[1] === Gdk.KEY_Down) {
resultsList.get_children().length > 0 &&
resultsList.select_row(resultsList.get_row_at_index(
(selectedResultIndex + 1) > (resultsList.get_children().length - 1) ?
0
: selectedResultIndex + 1
));
}
},
closeAction: (_) => closeRunner(_),
onClose: () => subs.map(sub => sub()),