💥 fix(runner): wrong scrolling positions, focus escaping to the listbox

This commit is contained in:
retrozinndev
2025-08-10 00:35:17 -03:00
parent fd58ebd5b3
commit 052854a407
+44 -44
View File
@@ -225,14 +225,12 @@ function selectNextItem(listbox: Gtk.ListBox) {
return; return;
const viewport = listbox.parent as Gtk.Viewport; const viewport = listbox.parent as Gtk.Viewport;
const vadjustment = viewport.vadjustment; const vadjustment = (viewport.parent as Gtk.ScrolledWindow).get_vadjustment();
const [, , nextRowY] = nextRow.translate_coordinates(viewport, const nextRowVAllocation = (nextRow.get_allocation().y + nextRow.get_allocation().height);
nextRow.get_allocation().x, nextRow.get_allocation().y);
listbox.select_row(nextRow as Gtk.ListBoxRow); listbox.select_row(nextRow as Gtk.ListBoxRow);
if(vadjustment.value < nextRowY) if(nextRowVAllocation > viewport.get_allocation().height)
vadjustment.set_value(nextRowY - vadjustment.value); vadjustment.set_value(nextRow.get_allocation().y - viewport.get_allocation().height + nextRow.get_allocation().height);}
}
export function openRunner(props: RunnerProps, placeholders?: Array<Result>): Astal.Window { export function openRunner(props: RunnerProps, placeholders?: Array<Result>): Astal.Window {
props.width ??= 780; props.width ??= 780;
@@ -245,16 +243,16 @@ export function openRunner(props: RunnerProps, placeholders?: Array<Result>): As
<PopupWindow namespace={"runner"} monitor={mon} widthRequest={props.width} <PopupWindow namespace={"runner"} monitor={mon} widthRequest={props.width}
heightRequest={props.height} exclusivity={Astal.Exclusivity.IGNORE} halign={Gtk.Align.CENTER} heightRequest={props.height} exclusivity={Astal.Exclusivity.IGNORE} halign={Gtk.Align.CENTER}
marginTop={(AstalHyprland.get_default().get_monitor(mon)?.height / 2) - (props.height! / 2)} marginTop={(AstalHyprland.get_default().get_monitor(mon)?.height / 2) - (props.height! / 2)}
valign={Gtk.Align.START} $={() => { valign={Gtk.Align.START} hexpand orientation={Gtk.Orientation.VERTICAL}
$={() => {
plugins.forEach(plugin => plugins.forEach(plugin =>
plugin.init?.()); plugin.init?.());
props.initialText && props.initialText &&
Runner.setEntryText(props.initialText); Runner.setEntryText(props.initialText);
}} actionKeyPressed={(self, keyval) => { }} actionKeyPressed={(self, keyval) => {
const listbox = ((getPopupWindowContainer(self).get_first_child()! const listbox = ((getPopupWindowContainer(self).get_last_child() as Gtk.ScrolledWindow)
.get_last_child()! as Gtk.ScrolledWindow).get_child()! as Gtk.Viewport) .get_child() as Gtk.Viewport).get_child() as Gtk.ListBox;
.get_child()! as Gtk.ListBox;
switch(keyval) { switch(keyval) {
case Gdk.KEY_F5: case Gdk.KEY_F5:
@@ -279,8 +277,10 @@ export function openRunner(props: RunnerProps, placeholders?: Array<Result>): As
return; return;
} }
!gtkEntry?.hasFocus && if(!gtkEntry?.hasFocus) {
gtkEntry?.grab_focus(); gtkEntry?.grab_focus();
listbox.grab_focus();
}
}} actionClosed={() => { }} actionClosed={() => {
[...plugins.values()].forEach(plugin => plugin?.onClose?.()); [...plugins.values()].forEach(plugin => plugin?.onClose?.());
root.dispose(); root.dispose();
@@ -288,45 +288,45 @@ export function openRunner(props: RunnerProps, placeholders?: Array<Result>): As
instance = null; instance = null;
gtkEntry = null; gtkEntry = null;
}}> }}>
<Gtk.Box class={`runner main`} orientation={Gtk.Orientation.VERTICAL} hexpand <Gtk.SearchEntry class={"search"} placeholderText={props.entryPlaceHolder ?? ""}
valign={Gtk.Align.START}> $={(self) => gtkEntry = self} searchDelay={0} onSearchChanged={(self) => {
const listbox = ((self.get_next_sibling()! as Gtk.ScrolledWindow)
.get_child() as Gtk.Viewport).get_child() as Gtk.ListBox;
updateResultsList(listbox, self.text, placeholders);
<Gtk.SearchEntry class={"search"} placeholderText={props.entryPlaceHolder ?? ""} listbox.get_row_at_index(0) &&
$={(self) => gtkEntry = self} searchDelay={0} onSearchChanged={(self) => { listbox.select_row(listbox.get_row_at_index(0));
const listbox = self.get_next_sibling()?.get_first_child()?.get_first_child() as Gtk.ListBox; }} onActivate={(self) => {
updateResultsList(listbox, self.text, placeholders); const listbox = ((self.get_next_sibling() as Gtk.ScrolledWindow)
.get_child() as Gtk.Viewport).get_child() as Gtk.ListBox;
const resultWidget = listbox.get_selected_row()?.get_child();
listbox.get_row_at_index(0) && if(resultWidget instanceof ResultWidget && !clickTimeout) {
listbox.select_row(listbox.get_row_at_index(0)); clickTimeout = timeout(250, () => clickTimeout = undefined);
}} onActivate={(self) => { resultWidget.actionClick();
const listbox = self.parent.get_last_child()?.get_first_child()?.get_first_child() as Gtk.ListBox; resultWidget.closeOnClick &&
const resultWidget = listbox.get_selected_row()?.get_child(); Runner.close();
}
if(resultWidget instanceof ResultWidget) { }} onStopSearch={() => Runner.close()} // close Runner on Escape
resultWidget.actionClick(); />
resultWidget.closeOnClick && <Gtk.ScrolledWindow class={"results-scrollable"} vscrollbarPolicy={Gtk.PolicyType.AUTOMATIC}
hscrollbarPolicy={Gtk.PolicyType.NEVER} hexpand vexpand propagateNaturalHeight visible={false}
maxContentHeight={props.height} focusable={false}>
<Gtk.ListBox hexpand activateOnSingleClick selectionMode={Gtk.SelectionMode.SINGLE}
onRowActivated={(_, row) => {
const child = row.get_child()!;
if(child instanceof ResultWidget && !clickTimeout) {
clickTimeout = timeout(250, () => clickTimeout = undefined);
child.actionClick?.();
child.closeOnClick &&
Runner.close(); Runner.close();
} }
}} onStopSearch={() => Runner.close()} // close Runner on Escape }}
/> />
<Gtk.ScrolledWindow class={"results-scrollable"} vscrollbarPolicy={Gtk.PolicyType.AUTOMATIC} </Gtk.ScrolledWindow>
hscrollbarPolicy={Gtk.PolicyType.NEVER} hexpand vexpand propagateNaturalHeight visible={false}
maxContentHeight={props.height}>
<Gtk.ListBox hexpand activateOnSingleClick selectionMode={Gtk.SelectionMode.SINGLE}
onRowActivated={(_, row) => {
const child = row.get_child()!;
if(child instanceof ResultWidget && !clickTimeout) {
clickTimeout = timeout(250, () => clickTimeout = undefined);
child.actionClick?.();
child.closeOnClick &&
Runner.close();
}
}}
/>
</Gtk.ScrolledWindow>
</Gtk.Box>
</PopupWindow> as Astal.Window </PopupWindow> as Astal.Window
)(); )();