Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions scripts/build-deb
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ Section: utils
Priority: optional
Architecture: all
Maintainer: GaimsDevSoftware <noreply@gaims.dev>
Depends: python3 (>= 3.11), python3-gi, gir1.2-gtk-3.0, avahi-utils, python3-cryptography, python3-protobuf, pipewire-bin | pulseaudio-utils
Recommends: android-tools-adb
Depends: python3 (>= 3.11), python3-gi, gir1.2-gtk-3.0, avahi-utils, python3-cryptography, python3-protobuf, pipewire-bin | pulseaudio-utils, gir1.2-ayatanaappindicator3-0.1 | gir1.2-appindicator3-0.1
Recommends: android-tools-adb, gnome-shell-extension-appindicator
Description: Google TV and Android TV remote for Linux
TellyKeys is a GTK desktop remote for Google TV and Android TV with pairing,
D-pad controls, app shortcuts, text input, and experimental voice search.
Expand Down
2 changes: 2 additions & 0 deletions scripts/build-rpm
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,9 @@ Requires: avahi-tools
Requires: python3-cryptography
Requires: python3-protobuf
Requires: pipewire-utils
Requires: libappindicator-gtk3
Recommends: android-tools
Recommends: gnome-shell-extension-appindicator

%description
TellyKeys is a GTK desktop remote for Google TV and Android TV with pairing,
Expand Down
46 changes: 42 additions & 4 deletions src/tellykeys/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import argparse
import asyncio
import importlib
import os
import socket
import threading
Expand Down Expand Up @@ -175,6 +176,8 @@ def __init__(self, use_tray: bool = False, start_hidden: bool = False) -> None:
self.current_status: TvStatus | None = None
self.use_tray = use_tray
self.tray_icon: Gtk.StatusIcon | None = None
self.app_indicator = None
self._tray_show_item: Gtk.MenuItem | None = None
self.remote = TellyKeysRemote()
self.remote.set_microphone_source(self.settings.microphone_source)
self.remote.set_client_name(self.settings.remote_name or default_remote_name())
Expand Down Expand Up @@ -1762,17 +1765,43 @@ def launch(self, target: str) -> None:
self.run_remote_call(self.remote.launch, target)

def setup_tray(self) -> None:
# Prefer libappindicator (StatusNotifierItem). The legacy Gtk.StatusIcon
# is a no-op on GNOME and on Wayland generally, so it is only a fallback
# for desktops where it still works (e.g. some X11 setups).
if self._setup_app_indicator():
return
self._setup_status_icon()

def _setup_app_indicator(self) -> bool:
for name in ("AyatanaAppIndicator3", "AppIndicator3"):
try:
gi.require_version(name, "0.1")
ind = importlib.import_module(f"gi.repository.{name}")
except (ValueError, ImportError):
continue
self.app_indicator = ind.Indicator.new(
"tellykeys",
"tellykeys",
ind.IndicatorCategory.APPLICATION_STATUS,
)
self.app_indicator.set_status(ind.IndicatorStatus.ACTIVE)
self.app_indicator.set_title("TellyKeys")
self.app_indicator.set_menu(self._build_tray_menu())
# Where the host supports it, a middle-click toggles the window.
if self._tray_show_item is not None:
self.app_indicator.set_secondary_activate_target(self._tray_show_item)
return True
return False

def _setup_status_icon(self) -> None:
self.tray_icon = Gtk.StatusIcon.new_from_icon_name("tellykeys")
self.tray_icon.set_title("TellyKeys")
self.tray_icon.set_tooltip_text("TellyKeys")
self.tray_icon.set_visible(True)
self.tray_icon.connect("activate", self.on_tray_activate)
self.tray_icon.connect("popup-menu", self.on_tray_popup)

def on_tray_activate(self, _icon: Gtk.StatusIcon) -> None:
self.toggle_window()

def on_tray_popup(self, _icon: Gtk.StatusIcon, button: int, activate_time: int) -> None:
def _build_tray_menu(self) -> Gtk.Menu:
menu = Gtk.Menu()
items = [
("Show TellyKeys", lambda *_: self.show_window()),
Expand All @@ -1787,7 +1816,16 @@ def on_tray_popup(self, _icon: Gtk.StatusIcon, button: int, activate_time: int)
item = Gtk.MenuItem(label=label)
item.connect("activate", callback)
menu.append(item)
if label == "Show TellyKeys":
self._tray_show_item = item
menu.show_all()
return menu

def on_tray_activate(self, _icon: Gtk.StatusIcon) -> None:
self.toggle_window()

def on_tray_popup(self, _icon: Gtk.StatusIcon, button: int, activate_time: int) -> None:
menu = self._build_tray_menu()
menu.popup(None, None, None, None, button, activate_time)

def toggle_window(self) -> None:
Expand Down