feat: reserve classroom shell and restore dock interaction
This commit is contained in:
+135
-107
@@ -1,6 +1,7 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import subprocess
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
import gi
|
||||
@@ -48,10 +49,7 @@ def enabled(config, key, default=False):
|
||||
|
||||
|
||||
def launch(command):
|
||||
subprocess.Popen(
|
||||
command,
|
||||
start_new_session=True,
|
||||
)
|
||||
subprocess.Popen(command, start_new_session=True)
|
||||
|
||||
|
||||
def notify(title, message):
|
||||
@@ -68,7 +66,10 @@ def themed_icon(*names):
|
||||
|
||||
for name in names:
|
||||
if theme.has_icon(name):
|
||||
return Gtk.Image.new_from_icon_name(name, Gtk.IconSize.DIALOG)
|
||||
return Gtk.Image.new_from_icon_name(
|
||||
name,
|
||||
Gtk.IconSize.DIALOG,
|
||||
)
|
||||
|
||||
return Gtk.Image.new_from_icon_name(
|
||||
"application-x-executable",
|
||||
@@ -79,21 +80,23 @@ def themed_icon(*names):
|
||||
def custom_icon(filename, size):
|
||||
path = ICON_DIR / filename
|
||||
|
||||
if path.exists():
|
||||
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
|
||||
str(path),
|
||||
size,
|
||||
size,
|
||||
True,
|
||||
)
|
||||
return Gtk.Image.new_from_pixbuf(pixbuf)
|
||||
if not path.exists():
|
||||
return None
|
||||
|
||||
return None
|
||||
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
|
||||
str(path),
|
||||
size,
|
||||
size,
|
||||
True,
|
||||
)
|
||||
|
||||
return Gtk.Image.new_from_pixbuf(pixbuf)
|
||||
|
||||
|
||||
class ClassroomDock(Gtk.Window):
|
||||
class ClassroomShell(Gtk.Window):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
screen = self.get_screen()
|
||||
visual = screen.get_rgba_visual()
|
||||
|
||||
@@ -101,29 +104,83 @@ class ClassroomDock(Gtk.Window):
|
||||
self.set_visual(visual)
|
||||
|
||||
self.set_app_paintable(True)
|
||||
self.config = read_device_config()
|
||||
|
||||
self.set_name("classroom-dock")
|
||||
self.set_name("classroom-shell")
|
||||
self.set_decorated(False)
|
||||
self.set_resizable(False)
|
||||
|
||||
self.config = read_device_config()
|
||||
|
||||
GtkLayerShell.init_for_window(self)
|
||||
GtkLayerShell.set_layer(self, GtkLayerShell.Layer.TOP)
|
||||
GtkLayerShell.set_layer(
|
||||
self,
|
||||
GtkLayerShell.Layer.TOP,
|
||||
)
|
||||
|
||||
GtkLayerShell.set_anchor(
|
||||
self,
|
||||
GtkLayerShell.Edge.BOTTOM,
|
||||
True,
|
||||
)
|
||||
|
||||
GtkLayerShell.set_margin(
|
||||
GtkLayerShell.set_anchor(
|
||||
self,
|
||||
GtkLayerShell.Edge.BOTTOM,
|
||||
12,
|
||||
GtkLayerShell.Edge.LEFT,
|
||||
True,
|
||||
)
|
||||
GtkLayerShell.set_anchor(
|
||||
self,
|
||||
GtkLayerShell.Edge.RIGHT,
|
||||
True,
|
||||
)
|
||||
|
||||
GtkLayerShell.set_keyboard_interactivity(self, False)
|
||||
GtkLayerShell.set_exclusive_zone(self, 76)
|
||||
GtkLayerShell.set_keyboard_interactivity(
|
||||
self,
|
||||
False,
|
||||
)
|
||||
|
||||
layout = Gtk.Overlay()
|
||||
layout.set_size_request(-1, 76)
|
||||
|
||||
dock = self.build_dock()
|
||||
|
||||
dock_align = Gtk.Alignment(
|
||||
xalign=0.5,
|
||||
yalign=0.5,
|
||||
xscale=0,
|
||||
yscale=0,
|
||||
)
|
||||
dock_align.add(dock)
|
||||
layout.add(dock_align)
|
||||
|
||||
self.clock = Gtk.Label()
|
||||
self.clock.get_style_context().add_class("clock")
|
||||
|
||||
clock_align = Gtk.Alignment(
|
||||
xalign=1.0,
|
||||
yalign=0.5,
|
||||
xscale=0,
|
||||
yscale=0,
|
||||
)
|
||||
clock_align.set_padding(
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
20,
|
||||
)
|
||||
clock_align.add(self.clock)
|
||||
|
||||
layout.add_overlay(clock_align)
|
||||
layout.set_overlay_pass_through(clock_align, True)
|
||||
|
||||
self.add(layout)
|
||||
|
||||
self.update_time()
|
||||
GLib.timeout_add_seconds(
|
||||
15,
|
||||
self.update_time,
|
||||
)
|
||||
|
||||
def build_dock(self):
|
||||
dock = Gtk.Box(
|
||||
orientation=Gtk.Orientation.HORIZONTAL,
|
||||
spacing=10,
|
||||
@@ -133,7 +190,6 @@ class ClassroomDock(Gtk.Window):
|
||||
dock.pack_start(
|
||||
self.make_button(
|
||||
self.browser_icon(),
|
||||
"Browser",
|
||||
lambda *_: launch(
|
||||
["/usr/local/bin/classroom-browser"]
|
||||
),
|
||||
@@ -143,11 +199,14 @@ class ClassroomDock(Gtk.Window):
|
||||
0,
|
||||
)
|
||||
|
||||
if enabled(self.config, "DVD_ENABLED", False):
|
||||
if enabled(
|
||||
self.config,
|
||||
"DVD_ENABLED",
|
||||
False,
|
||||
):
|
||||
dock.pack_start(
|
||||
self.make_button(
|
||||
self.dvd_icon(),
|
||||
"DVD",
|
||||
lambda *_: notify(
|
||||
"DVD",
|
||||
"DVD support is being prepared.",
|
||||
@@ -161,7 +220,6 @@ class ClassroomDock(Gtk.Window):
|
||||
dock.pack_start(
|
||||
self.make_button(
|
||||
self.sanctuary_icon(),
|
||||
"Sanctuary",
|
||||
lambda *_: notify(
|
||||
"Sanctuary",
|
||||
"Sanctuary live view is being prepared.",
|
||||
@@ -172,19 +230,42 @@ class ClassroomDock(Gtk.Window):
|
||||
0,
|
||||
)
|
||||
|
||||
self.add(dock)
|
||||
return dock
|
||||
|
||||
def make_button(self, image, callback):
|
||||
button = Gtk.Button()
|
||||
button.set_relief(Gtk.ReliefStyle.NONE)
|
||||
button.get_style_context().add_class(
|
||||
"dock-button"
|
||||
)
|
||||
|
||||
button.add(image)
|
||||
button.connect("clicked", callback)
|
||||
|
||||
return button
|
||||
|
||||
def browser_icon(self):
|
||||
image = custom_icon("browser.svg", 28)
|
||||
image = custom_icon(
|
||||
"browser.svg",
|
||||
28,
|
||||
)
|
||||
|
||||
if image is not None:
|
||||
return image
|
||||
|
||||
image = themed_icon("web-browser-symbolic", "internet-web-browser-symbolic")
|
||||
image = themed_icon(
|
||||
"web-browser-symbolic",
|
||||
"internet-web-browser-symbolic",
|
||||
)
|
||||
image.set_pixel_size(28)
|
||||
|
||||
return image
|
||||
|
||||
def dvd_icon(self):
|
||||
image = custom_icon("dvd.svg", 40)
|
||||
image = custom_icon(
|
||||
"dvd.svg",
|
||||
40,
|
||||
)
|
||||
|
||||
if image is not None:
|
||||
return image
|
||||
@@ -194,6 +275,7 @@ class ClassroomDock(Gtk.Window):
|
||||
"media-optical",
|
||||
)
|
||||
image.set_pixel_size(28)
|
||||
|
||||
return image
|
||||
|
||||
def sanctuary_icon(self):
|
||||
@@ -203,9 +285,16 @@ class ClassroomDock(Gtk.Window):
|
||||
False,
|
||||
)
|
||||
|
||||
filename = "live.svg" if is_live else "live-off.svg"
|
||||
filename = (
|
||||
"live.svg"
|
||||
if is_live
|
||||
else "live-off.svg"
|
||||
)
|
||||
|
||||
image = custom_icon(filename, 38)
|
||||
image = custom_icon(
|
||||
filename,
|
||||
38,
|
||||
)
|
||||
|
||||
if image is not None:
|
||||
return image
|
||||
@@ -218,79 +307,18 @@ class ClassroomDock(Gtk.Window):
|
||||
|
||||
return image
|
||||
|
||||
def make_button(self, image, tooltip, callback):
|
||||
button = Gtk.Button()
|
||||
button.set_relief(Gtk.ReliefStyle.NONE)
|
||||
button.get_style_context().add_class("dock-button")
|
||||
|
||||
button.add(image)
|
||||
button.connect("clicked", callback)
|
||||
|
||||
return button
|
||||
|
||||
class ClassroomClock(Gtk.Window):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
screen = self.get_screen()
|
||||
visual = screen.get_rgba_visual()
|
||||
|
||||
if visual is not None:
|
||||
self.set_visual(visual)
|
||||
|
||||
self.set_app_paintable(True)
|
||||
|
||||
self.set_name("classroom-clock")
|
||||
self.set_decorated(False)
|
||||
self.set_resizable(False)
|
||||
|
||||
GtkLayerShell.init_for_window(self)
|
||||
GtkLayerShell.set_layer(self, GtkLayerShell.Layer.TOP)
|
||||
|
||||
GtkLayerShell.set_anchor(
|
||||
self,
|
||||
GtkLayerShell.Edge.BOTTOM,
|
||||
True,
|
||||
)
|
||||
|
||||
GtkLayerShell.set_anchor(
|
||||
self,
|
||||
GtkLayerShell.Edge.RIGHT,
|
||||
True,
|
||||
)
|
||||
|
||||
GtkLayerShell.set_margin(
|
||||
self,
|
||||
GtkLayerShell.Edge.BOTTOM,
|
||||
16,
|
||||
)
|
||||
|
||||
GtkLayerShell.set_margin(
|
||||
self,
|
||||
GtkLayerShell.Edge.RIGHT,
|
||||
20,
|
||||
)
|
||||
|
||||
GtkLayerShell.set_keyboard_interactivity(self, False)
|
||||
|
||||
self.label = Gtk.Label()
|
||||
self.label.get_style_context().add_class("clock")
|
||||
self.add(self.label)
|
||||
|
||||
self.update_time()
|
||||
GLib.timeout_add_seconds(15, self.update_time)
|
||||
|
||||
def update_time(self):
|
||||
from datetime import datetime
|
||||
|
||||
self.label.set_text(
|
||||
self.clock.set_text(
|
||||
datetime.now().strftime("%-I:%M %p")
|
||||
)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def load_css():
|
||||
provider = Gtk.CssProvider()
|
||||
provider.load_from_path(str(CSS_FILE))
|
||||
provider.load_from_path(
|
||||
str(CSS_FILE)
|
||||
)
|
||||
|
||||
screen = Gdk.Screen.get_default()
|
||||
|
||||
@@ -304,15 +332,15 @@ def load_css():
|
||||
def main():
|
||||
load_css()
|
||||
|
||||
dock = ClassroomDock()
|
||||
dock.connect("destroy", Gtk.main_quit)
|
||||
dock.show_all()
|
||||
|
||||
clock = ClassroomClock()
|
||||
clock.show_all()
|
||||
shell = ClassroomShell()
|
||||
shell.connect(
|
||||
"destroy",
|
||||
Gtk.main_quit,
|
||||
)
|
||||
shell.show_all()
|
||||
|
||||
Gtk.main()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
main()
|
||||
|
||||
Reference in New Issue
Block a user