Skip to content
Merged
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
3 changes: 3 additions & 0 deletions safeeyes/config/locale/safeeyes.pot
Original file line number Diff line number Diff line change
Expand Up @@ -561,3 +561,6 @@ msgstr ""
#, python-format
msgid "Old stylesheet found at '%(old)s', ignoring. For custom styles, create a new stylesheet in '%(new)s' instead."
msgstr ""

msgid "Customizing the postpone and skip shortcuts does not work on Wayland."
msgstr ""
16 changes: 0 additions & 16 deletions safeeyes/config/style/safeeyes_style.css
Original file line number Diff line number Diff line change
Expand Up @@ -109,19 +109,3 @@
opacity: 0.9;
border-color: transparent;
}

.btn_menu {
border-width: 0px;
border-radius: 0px;
border-image: None;
background: white;
border-color: transparent;
}

.btn_menu:hover {
border-width: 0px;
border-radius: 0px;
border-image: None;
background: whitesmoke;
border-color: transparent;
}
60 changes: 31 additions & 29 deletions safeeyes/plugins/trayicon/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
from safeeyes import utility
from safeeyes.translations import translate as _
import threading
import time
import typing

"""
Expand Down Expand Up @@ -429,6 +428,9 @@ def set_xayatanalabel(self, label):
class TrayIcon:
"""Create and show the tray icon along with the tray menu."""

_animation_timeout_id: typing.Optional[int] = None
_animation_icon_enabled: bool = False

def __init__(self, context, plugin_config):
self.context = context
self.on_show_settings = context["api"]["show_settings"]
Expand All @@ -446,7 +448,6 @@ def __init__(self, context, plugin_config):
self.idle_condition = threading.Condition()
self.lock = threading.Lock()
self.allow_disabling = plugin_config["allow_disabling"]
self.animate = False
self.menu_locked = False

session_bus = Gio.bus_get_sync(Gio.BusType.SESSION)
Expand Down Expand Up @@ -785,35 +786,37 @@ def __schedule_resume(self, time_minutes):
if not self.active:
utility.execute_main_thread(self.on_enable_clicked)

def start_animation(self):
if not self.active or not self.animate:
return
utility.execute_main_thread(
lambda: self.sni_service.set_icon("io.github.slgobinath.SafeEyes-disabled")
)
time.sleep(0.5)
utility.execute_main_thread(
lambda: self.sni_service.set_icon("io.github.slgobinath.SafeEyes-enabled")
)
if self.animate and self.active:
time.sleep(0.5)
if self.animate and self.active:
utility.start_thread(self.start_animation)
def start_animation(self) -> None:
if self._animation_timeout_id is not None:
self.stop_animation()

self._animation_icon_enabled = False

self._animation_timeout_id = GLib.timeout_add(500, self._do_animate)

def _do_animate(self) -> bool:
if not self.active:
self._animation_timeout_id = None
return GLib.SOURCE_REMOVE

if self._animation_icon_enabled:
self.sni_service.set_icon("io.github.slgobinath.SafeEyes-enabled")
else:
self.sni_service.set_icon("io.github.slgobinath.SafeEyes-disabled")

self._animation_icon_enabled = not self._animation_icon_enabled

return GLib.SOURCE_CONTINUE

def stop_animation(self) -> None:
if self._animation_timeout_id is not None:
GLib.source_remove(self._animation_timeout_id)
self._animation_timeout_id = None

def stop_animation(self):
self.animate = False
if self.active:
utility.execute_main_thread(
lambda: self.sni_service.set_icon(
"io.github.slgobinath.SafeEyes-enabled"
)
)
self.sni_service.set_icon("io.github.slgobinath.SafeEyes-enabled")
else:
utility.execute_main_thread(
lambda: self.sni_service.set_icon(
"io.github.slgobinath.SafeEyes-disabled"
)
)
self.sni_service.set_icon("io.github.slgobinath.SafeEyes-disabled")


def init(ctx, safeeyes_cfg, plugin_config):
Expand All @@ -839,7 +842,6 @@ def on_pre_break(break_obj):
"""Disable the menu if strict_break is enabled."""
if safeeyes_config.get("strict_break"):
tray_icon.lock_menu()
tray_icon.animate = True
tray_icon.start_animation()


Expand Down
57 changes: 50 additions & 7 deletions safeeyes/ui/break_screen.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,15 @@ def __init__(self, application, context, on_skipped, on_postponed):
self.enable_postpone = False
self.enable_shortcut = False
self.is_pretified = False
self.keycode_shortcut_postpone = 65
self.keycode_shortcut_skip = 9
self.keycode_shortcut_postpone = 65 # Space
self.keycode_shortcut_skip = 9 # Escape
self.on_postponed = on_postponed
self.on_skipped = on_skipped
self.shortcut_disable_time = 2
self.strict_break = False
self.windows = []
self.show_skip_button = False
self.show_postpone_button = False

if not self.context["is_wayland"]:
self.x11_display = Display()
Expand All @@ -69,6 +71,17 @@ def initialize(self, config):
self.enable_postpone = config.get("allow_postpone", False)
self.keycode_shortcut_postpone = config.get("shortcut_postpone", 65)
self.keycode_shortcut_skip = config.get("shortcut_skip", 9)

if self.context["is_wayland"] and (
self.keycode_shortcut_postpone != 65 or self.keycode_shortcut_skip != 9
):
logging.warning(
_(
"Customizing the postpone and skip shortcuts does not work on "
"Wayland."
)
)

self.shortcut_disable_time = config.get("shortcut_disable_time", 2)
self.strict_break = config.get("strict_break", False)

Expand Down Expand Up @@ -146,7 +159,12 @@ def __show_break_screen(self, message, image_path, widget, tray_actions):
logging.info("Show break screens in %d display(s)", len(monitors))

skip_button_disabled = self.context.get("skip_button_disabled", False)
self.show_skip_button = not self.strict_break and not skip_button_disabled

postpone_button_disabled = self.context.get("postpone_button_disabled", False)
self.show_postpone_button = (
self.enable_postpone and not postpone_button_disabled
)

i = 0

Expand All @@ -157,6 +175,15 @@ def __show_break_screen(self, message, image_path, widget, tray_actions):
window = builder.get_object("window_main")
window.set_application(self.application)
window.connect("close-request", self.on_window_delete)

if self.context["is_wayland"]:
# Note: in theory, this could also be used on X11
# however, that already has its own implementation below
controller = Gtk.EventControllerKey()
controller.connect("key_pressed", self.on_key_pressed_wayland)
controller.set_propagation_phase(Gtk.PropagationPhase.CAPTURE)
window.add_controller(controller)

window.set_title("SafeEyes-" + str(i))
lbl_message = builder.get_object("lbl_message")
lbl_count = builder.get_object("lbl_count")
Expand All @@ -182,15 +209,15 @@ def __show_break_screen(self, message, image_path, widget, tray_actions):
toolbar_button.show()

# Add the buttons
if self.enable_postpone and not postpone_button_disabled:
if self.show_postpone_button:
# Add postpone button
btn_postpone = Gtk.Button.new_with_label(_("Postpone"))
btn_postpone.get_style_context().add_class("btn_postpone")
btn_postpone.connect("clicked", self.on_postpone_clicked)
btn_postpone.set_visible(True)
box_buttons.append(btn_postpone)

if not self.strict_break and not skip_button_disabled:
if self.show_skip_button:
# Add the skip button
btn_skip = Gtk.Button.new_with_label(_("Skip"))
btn_skip.get_style_context().add_class("btn_skip")
Expand All @@ -214,6 +241,11 @@ def __show_break_screen(self, message, image_path, widget, tray_actions):
window.fullscreen_on_monitor(monitor)
window.present()

# this ensures that none of the buttons is in focus immediately
# otherwise, pressing space presses that button instead of triggering the
# shortcut
window.set_focus(None)

if not self.context["is_wayland"]:
self.__window_set_keep_above_x11(window)

Expand Down Expand Up @@ -284,20 +316,31 @@ def __lock_keyboard_x11(self):
if self.enable_shortcut and event.type == X.KeyPress:
if (
event.detail == self.keycode_shortcut_skip
and not self.strict_break
and self.show_skip_button
):
self.skip_break()
break
elif (
self.enable_postpone
and event.detail == self.keycode_shortcut_postpone
event.detail == self.keycode_shortcut_postpone
and self.show_postpone_button
):
self.postpone_break()
break
else:
# Reduce the CPU usage by sleeping for a second
time.sleep(1)

def on_key_pressed_wayland(self, event_controller_key, keyval, keycode, state):
if self.enable_shortcut:
if keyval == Gdk.KEY_space and self.show_postpone_button:
self.postpone_break()
return True
elif keyval == Gdk.KEY_Escape and self.show_skip_button:
self.skip_break()
return True

return False

def __release_keyboard_x11(self):
"""Release the locked keyboard."""
logging.info("Unlock the keyboard")
Expand Down