✨ feat(plugins): add Process plugin for managing running processes with live updates
This commit is contained in:
4 files changed
+381
-80
No files matched your search
@@ -74,9 +74,8 @@ class Launcher(Window):
|
||||
self.visible = False # Launcher visibility state
|
||||
self.opened_with_trigger = False # Whether launcher was opened with a trigger
|
||||
|
||||
# Focus management for header buttons
|
||||
self.focus_mode = "search" # "search", "results", "header"
|
||||
self.header_button_index = 0 # 0 = config, 1 = close
|
||||
# Focus management
|
||||
self.focus_mode = "search" # "search", "results"
|
||||
|
||||
# Setup UI
|
||||
main_box = Box(
|
||||
@@ -190,10 +189,6 @@ class Launcher(Window):
|
||||
|
||||
# Reset focus mode to search
|
||||
self.focus_mode = "search"
|
||||
self.header_button_index = 0
|
||||
|
||||
# Remove focus styling from header buttons
|
||||
self._clear_header_focus()
|
||||
|
||||
# Focus search entry without selecting text
|
||||
if trigger_keyword:
|
||||
@@ -280,7 +275,6 @@ class Launcher(Window):
|
||||
# Reset focus to search when user types
|
||||
if self.focus_mode != "search":
|
||||
self.focus_mode = "search"
|
||||
self._clear_header_focus()
|
||||
|
||||
query = entry.get_text().strip()
|
||||
self.query = query
|
||||
@@ -884,13 +878,8 @@ class Launcher(Window):
|
||||
self._update_selection()
|
||||
return True
|
||||
|
||||
# Enter - activate selected result or header button
|
||||
# Enter - activate selected result
|
||||
if keyval == Gdk.KEY_Return:
|
||||
# Check if we're in header mode
|
||||
if self.focus_mode == "header":
|
||||
# Activate the selected header button
|
||||
self.header_buttons[self.header_button_index].emit("clicked")
|
||||
return True
|
||||
|
||||
# Check for Shift+Enter for alternative actions
|
||||
if event.state & Gdk.ModifierType.SHIFT_MASK:
|
||||
@@ -925,24 +914,18 @@ class Launcher(Window):
|
||||
self._activate_selected()
|
||||
return True
|
||||
|
||||
# Tab - cycle through focus areas, results, and header buttons
|
||||
# Tab - cycle through focus areas and results
|
||||
if keyval == Gdk.KEY_Tab:
|
||||
if event.state & Gdk.ModifierType.SHIFT_MASK:
|
||||
# Shift+Tab - reverse direction
|
||||
if self.focus_mode == "header":
|
||||
# Navigate between header buttons in reverse
|
||||
self._navigate_header_buttons_backward()
|
||||
elif self.focus_mode == "results":
|
||||
if self.focus_mode == "results":
|
||||
# Navigate through results in reverse
|
||||
self._navigate_results_backward()
|
||||
else:
|
||||
self._cycle_focus_backward()
|
||||
else:
|
||||
# Tab - forward direction
|
||||
if self.focus_mode == "header":
|
||||
# Navigate between header buttons forward
|
||||
self._navigate_header_buttons_forward()
|
||||
elif self.focus_mode == "results":
|
||||
if self.focus_mode == "results":
|
||||
# Navigate through results forward
|
||||
self._navigate_results_forward()
|
||||
else:
|
||||
@@ -1173,45 +1156,19 @@ class Launcher(Window):
|
||||
return False # Don't repeat the idle callback
|
||||
|
||||
def _cycle_focus_forward(self):
|
||||
"""Cycle focus forward: search -> results -> header (first button)"""
|
||||
"""Cycle focus forward: search -> results"""
|
||||
if self.focus_mode == "search":
|
||||
if self.results:
|
||||
self.focus_mode = "results"
|
||||
self._update_selection()
|
||||
else:
|
||||
self.focus_mode = "header"
|
||||
self.header_button_index = 0
|
||||
self._update_header_focus()
|
||||
elif self.focus_mode == "results":
|
||||
self.focus_mode = "header"
|
||||
self.header_button_index = 0
|
||||
self._update_header_focus()
|
||||
|
||||
def _cycle_focus_backward(self):
|
||||
"""Cycle focus backward: search -> header (last button) -> results -> search"""
|
||||
if self.focus_mode == "search":
|
||||
self.focus_mode = "header"
|
||||
self.header_button_index = len(self.header_buttons) - 1
|
||||
self._update_header_focus()
|
||||
elif self.focus_mode == "results":
|
||||
"""Cycle focus backward: results -> search"""
|
||||
if self.focus_mode == "results":
|
||||
self.focus_mode = "search"
|
||||
self._clear_header_focus()
|
||||
self._focus_search_entry_without_selection()
|
||||
|
||||
def _update_header_focus(self):
|
||||
"""Update focus to the selected header button."""
|
||||
# Remove focus from all buttons first
|
||||
self._clear_header_focus()
|
||||
|
||||
# Add focus style to selected button
|
||||
selected_button = self.header_buttons[self.header_button_index]
|
||||
selected_button.add_style_class("focused")
|
||||
selected_button.grab_focus()
|
||||
|
||||
def _clear_header_focus(self):
|
||||
"""Remove focus styling from all header buttons."""
|
||||
for button in self.header_buttons:
|
||||
button.remove_style_class("focused")
|
||||
|
||||
def _focus_search_entry_without_selection(self):
|
||||
"""Focus search entry and position cursor at end without selecting text."""
|
||||
@@ -1259,35 +1216,7 @@ class Launcher(Window):
|
||||
# Also try with a small delay as backup
|
||||
GLib.timeout_add(CURSOR_POSITION_DELAY_MS, clear_selection)
|
||||
|
||||
def _navigate_header_buttons_forward(self):
|
||||
"""Navigate to next header button or exit header mode."""
|
||||
if self.header_button_index < len(self.header_buttons) - 1:
|
||||
# Move to next button
|
||||
self.header_button_index += 1
|
||||
self._update_header_focus()
|
||||
else:
|
||||
# Exit header mode and go to search
|
||||
self.focus_mode = "search"
|
||||
self._clear_header_focus()
|
||||
self._focus_search_entry_without_selection()
|
||||
|
||||
def _navigate_header_buttons_backward(self):
|
||||
"""Navigate to previous header button or exit header mode."""
|
||||
if self.header_button_index > 0:
|
||||
# Move to previous button
|
||||
self.header_button_index -= 1
|
||||
self._update_header_focus()
|
||||
else:
|
||||
# Exit header mode and go to results or search
|
||||
if self.results:
|
||||
self.focus_mode = "results"
|
||||
self.selected_index = len(self.results) - 1 # Go to last result
|
||||
self._clear_header_focus()
|
||||
self._update_selection()
|
||||
else:
|
||||
self.focus_mode = "search"
|
||||
self._clear_header_focus()
|
||||
self._focus_search_entry_without_selection()
|
||||
|
||||
def _navigate_results_forward(self):
|
||||
"""Navigate to next result or wrap around to first result."""
|
||||
|
||||
Reference in new issue
Block a user