fix(services/spotlight): improve MPRIS artwork handling and scope keyword searches to single plugin
- mpris: native MediaArt cache lookup, dedupe play/pause emission, safe cleanup, artwork polling for already-playing browser players, drop os.system seek fallback - spotlight: scope plugin keyword and detect() matches to a single plugin via search_single instead of global search; register clipboard keywords (clip/clipboard)
This commit is contained in:
43 files changed
+1227
-637
No files matched your search
@@ -344,7 +344,6 @@ class FlatScale(Gtk.DrawingArea, Widget):
|
||||
self._anim_bubble_open.min_value = p
|
||||
self._anim_bubble_open.max_value = 1.0
|
||||
self._anim_bubble_open.value = p
|
||||
self._anim_bubble_open._start_time = None
|
||||
self._anim_bubble_open.play()
|
||||
|
||||
def _bubble_close(self):
|
||||
@@ -356,7 +355,6 @@ class FlatScale(Gtk.DrawingArea, Widget):
|
||||
self._anim_bubble_close.min_value = start
|
||||
self._anim_bubble_close.max_value = 1.0
|
||||
self._anim_bubble_close.value = start
|
||||
self._anim_bubble_close._start_time = None
|
||||
self._anim_bubble_close.play()
|
||||
|
||||
def _sync_bubble_progress(self):
|
||||
@@ -578,9 +576,9 @@ class FlatScale(Gtk.DrawingArea, Widget):
|
||||
)
|
||||
cr.fill()
|
||||
|
||||
# Percentage bubble (drag only) — pass slider_left_x as "slider_top_y"
|
||||
slider_left_x = slider_cx - slider_thickness / 2
|
||||
self._draw_bubble(cr, slider_cy, slider_left_x, styles)
|
||||
# Percentage bubble (drag only)
|
||||
max_thickness = max(self._anim_press.min_value, self._anim_press.max_value)
|
||||
self._draw_bubble(cr, slider_cx, slider_cy, max_thickness, styles)
|
||||
|
||||
return False
|
||||
|
||||
|
||||
@@ -80,3 +80,7 @@ class AnimatedScrollable(ScrolledWindow):
|
||||
value = self.height_animator.value
|
||||
value = 0 if value < 0 else value
|
||||
return value, value
|
||||
|
||||
def destroy(self):
|
||||
self.height_animator.stop()
|
||||
super().destroy()
|
||||
@@ -403,3 +403,14 @@ class BatteryControl(Box):
|
||||
|
||||
def on_profile_changed(self, service, *args):
|
||||
self.update_energy_mode_buttons()
|
||||
|
||||
def destroy(self):
|
||||
try:
|
||||
self.battery_service.disconnect_by_func(self.on_battery_changed)
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
self.battery_service.disconnect_by_func(self.on_profile_changed)
|
||||
except Exception:
|
||||
pass
|
||||
super().destroy()
|
||||
@@ -69,13 +69,16 @@ class PopupWindow(WaylandWindow):
|
||||
if not self._pointing_widget:
|
||||
return
|
||||
|
||||
# Cleanly (re)connect: always drop any existing handlers first so that
|
||||
# repeated calls while visible do not stack duplicate connections.
|
||||
try:
|
||||
self._pointing_widget.disconnect_by_func(self.do_handle_size_allocate)
|
||||
self.disconnect_by_func(self.do_handle_size_allocate)
|
||||
except Exception as e:
|
||||
if "nothing connected" not in str(e):
|
||||
logger.error(f"Error disconnecting signal: {e}")
|
||||
|
||||
if not self.get_visible():
|
||||
try:
|
||||
self._pointing_widget.disconnect_by_func(self.do_handle_size_allocate)
|
||||
self.disconnect_by_func(self.do_handle_size_allocate)
|
||||
except Exception as e:
|
||||
if "nothing connected" not in str(e):
|
||||
logger.error(f"Error disconnecting signal: {e}")
|
||||
return
|
||||
|
||||
self._pointing_widget.connect("size-allocate", self.do_handle_size_allocate)
|
||||
@@ -92,6 +95,18 @@ class PopupWindow(WaylandWindow):
|
||||
return None
|
||||
return self.do_reposition(self.do_calculate_edges())
|
||||
|
||||
def destroy(self):
|
||||
if self._pointing_widget:
|
||||
try:
|
||||
self._pointing_widget.disconnect_by_func(self.do_handle_size_allocate)
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
self.disconnect_by_func(self.do_handle_size_allocate)
|
||||
except Exception:
|
||||
pass
|
||||
super().destroy()
|
||||
|
||||
def do_calculate_edges(self):
|
||||
move_axe = "x"
|
||||
parent_window = self.get_parent_window()
|
||||
|
||||
Reference in new issue
Block a user