Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package cinnamon-screensaver for 
openSUSE:Factory checked in at 2026-03-26 21:08:23
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/cinnamon-screensaver (Old)
 and      /work/SRC/openSUSE:Factory/.cinnamon-screensaver.new.8177 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "cinnamon-screensaver"

Thu Mar 26 21:08:23 2026 rev:32 rq:1342644 version:6.6.1

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/cinnamon-screensaver/cinnamon-screensaver.changes    
    2025-01-20 17:15:05.363466072 +0100
+++ 
/work/SRC/openSUSE:Factory/.cinnamon-screensaver.new.8177/cinnamon-screensaver.changes
      2026-03-27 06:37:47.437004693 +0100
@@ -1,0 +2,13 @@
+Wed Mar 25 23:09:23 UTC 2026 - Dirk Müller <[email protected]>
+
+- update to 6.6.1:
+  * Make Caribou dependency optional (#489)
+  * Handle layout switching thru cinnamon, remove use of XApp.
+  * Switch to xapp-symbolic-icons (XSI)
+  * Refactor positioning of floating UI elements.
+  * unlock: Remove additional dimming when unlock dialog is
+    shown.
+  * unlock.py: Don't show password entry and unlock button until
+    prompted by pam.
+
+-------------------------------------------------------------------

Old:
----
  cinnamon-screensaver-6.4.0.tar.gz

New:
----
  cinnamon-screensaver-6.6.1.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ cinnamon-screensaver.spec ++++++
--- /var/tmp/diff_new_pack.2WiEGr/_old  2026-03-27 06:37:47.913024312 +0100
+++ /var/tmp/diff_new_pack.2WiEGr/_new  2026-03-27 06:37:47.917024477 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package cinnamon-screensaver
 #
-# Copyright (c) 2025 SUSE LLC
+# Copyright (c) 2026 SUSE LLC and contributors
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -18,7 +18,7 @@
 
 %define         appid org.cinnamon.ScreenSaver
 Name:           cinnamon-screensaver
-Version:        6.4.0
+Version:        6.6.1
 Release:        0
 Summary:        Cinnamon screensaver and locker
 License:        GPL-2.0-or-later

++++++ cinnamon-screensaver-6.4.0.tar.gz -> cinnamon-screensaver-6.6.1.tar.gz 
++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cinnamon-screensaver-6.4.0/debian/changelog 
new/cinnamon-screensaver-6.6.1/debian/changelog
--- old/cinnamon-screensaver-6.4.0/debian/changelog     2024-11-26 
14:51:33.000000000 +0100
+++ new/cinnamon-screensaver-6.6.1/debian/changelog     2025-12-16 
16:27:23.000000000 +0100
@@ -1,3 +1,29 @@
+cinnamon-screensaver (6.6.1) zena; urgency=medium
+
+  [ Balló György ]
+  * Make Caribou dependency optional (#489)
+
+ -- Clement Lefebvre <[email protected]>  Tue, 16 Dec 2025 15:27:17 +0000
+
+cinnamon-screensaver (6.6.0) zena; urgency=medium
+
+  [ Michael Webster ]
+  * Handle layout switching thru cinnamon, remove use of XApp. (#477)
+
+  [ Clement Lefebvre ]
+  * Switch to xapp-symbolic-icons (XSI)
+
+ -- Clement Lefebvre <[email protected]>  Tue, 25 Nov 2025 14:16:46 +0000
+
+cinnamon-screensaver (6.4.1) zara; urgency=medium
+
+  [ Michael Webster ]
+  * Refactor positioning of floating UI elements.
+  * unlock: Remove additional dimming when unlock dialog is shown.
+  * unlock.py: Don't show password entry and unlock button until prompted by 
pam.
+
+ -- Clement Lefebvre <[email protected]>  Tue, 05 Aug 2025 09:50:45 +0200
+
 cinnamon-screensaver (6.4.0) xia; urgency=medium
 
   [ Michael Webster ]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cinnamon-screensaver-6.4.0/debian/control 
new/cinnamon-screensaver-6.6.1/debian/control
--- old/cinnamon-screensaver-6.4.0/debian/control       2024-11-26 
14:51:33.000000000 +0100
+++ new/cinnamon-screensaver-6.6.1/debian/control       2025-12-16 
16:27:23.000000000 +0100
@@ -34,7 +34,6 @@
  gir1.2-gobject-2.0,
  gir1.2-gtk-3.0,
  gir1.2-pango-1.0,
- gir1.2-xapp-1.0,
  iso-flag-png,
  libxdo3,
  python3,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cinnamon-screensaver-6.4.0/meson.build 
new/cinnamon-screensaver-6.6.1/meson.build
--- old/cinnamon-screensaver-6.4.0/meson.build  2024-11-26 14:51:33.000000000 
+0100
+++ new/cinnamon-screensaver-6.6.1/meson.build  2025-12-16 16:27:23.000000000 
+0100
@@ -1,4 +1,4 @@
-project('cinnamon-screensaver', 'c', version : '6.4.0', meson_version : 
'>=0.56.0')
+project('cinnamon-screensaver', 'c', version : '6.6.1', meson_version : 
'>=0.56.0')
 
 cc = meson.get_compiler('c')
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cinnamon-screensaver-6.4.0/src/albumArt.py 
new/cinnamon-screensaver-6.6.1/src/albumArt.py
--- old/cinnamon-screensaver-6.4.0/src/albumArt.py      2024-11-26 
14:51:33.000000000 +0100
+++ new/cinnamon-screensaver-6.6.1/src/albumArt.py      2025-12-16 
16:27:23.000000000 +0100
@@ -21,10 +21,9 @@
     using a timer which randomizes its halign and valign properties
     as well as its current monitor.
     """
-    def __init__(self, away_message=None, initial_monitor=0):
-        super(AlbumArt, self).__init__(initial_monitor)
+    def __init__(self, initial_monitor=0, low_res=False):
+        super(AlbumArt, self).__init__(initial_monitor, Gtk.Align.END, 
Gtk.Align.CENTER)
         self.get_style_context().add_class("albumart")
-        self.set_halign(Gtk.Align.END)
 
         if not settings.get_show_albumart():
             return
@@ -34,7 +33,7 @@
 
         self.current_url = None
 
-        self.image = FramedImage(status.screen.get_low_res_mode(), 
scale_up=True)
+        self.image = FramedImage(low_res, scale_up=True)
         self.image.show()
         self.image.set_opacity(0.0)
         self.add(self.image)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/cinnamon-screensaver-6.4.0/src/cinnamon-screensaver.css 
new/cinnamon-screensaver-6.6.1/src/cinnamon-screensaver.css
--- old/cinnamon-screensaver-6.4.0/src/cinnamon-screensaver.css 2024-11-26 
14:51:33.000000000 +0100
+++ new/cinnamon-screensaver-6.6.1/src/cinnamon-screensaver.css 2025-12-16 
16:27:23.000000000 +0100
@@ -69,7 +69,7 @@
     border-style: solid;
     color: white;
     background-image: none;
-    background-color: transparent;
+    background-color: rgba(0, 0, 0, .6);
     border-image: none;
     border-width: 1px;
     box-shadow: none;
@@ -88,7 +88,7 @@
 }
 
 .csstage .passwordentry image.left {
-    padding-right: 10px;
+    padding-right: 14px;
 }
 
 /* Use :backdrop for alt-text keyboard layout */
@@ -104,7 +104,7 @@
     border-image: none;
     box-shadow: none;
     background-image: none;
-    background-color: transparent;
+    background-color: rgba(0, 0, 0, .6);
     border-radius: 20px;
     -gtk-outline-radius: 20px;
     outline-color: transparent;
@@ -123,7 +123,6 @@
 
 .csstage .passwordentry:focus,
 .csstage .transparentbutton:focus {
-    background-color: alpha(grey, .3);
     border-color: @theme_selected_bg_color;
     box-shadow: 1px 1px alpha(white, 0.1);
 }
@@ -138,21 +137,18 @@
 .csstage .passwordentry:hover:focus,
 .csstage .transparentbutton:hover:focus {
     border-color: @theme_selected_bg_color;
-    background-color: alpha(grey, .4);
     box-shadow: 1px 1px alpha(white, 0.1);
 }
 
 .csstage .passwordentry:active,
 .csstage .transparentbutton:active {
     border-color: @theme_selected_bg_color;
-    background-color: alpha(grey, .6);
     box-shadow: 1px 1px alpha(white, 0.1);
 }
 
 .csstage .passwordentry:active:focus,
 .csstage .transparentbutton:active:focus {
     border-color: @theme_selected_bg_color;
-    background-color: alpha(grey, .9);
     box-shadow: 1px 1px alpha(white, 0.1);
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cinnamon-screensaver-6.4.0/src/clock.py 
new/cinnamon-screensaver-6.6.1/src/clock.py
--- old/cinnamon-screensaver-6.4.0/src/clock.py 2024-11-26 14:51:33.000000000 
+0100
+++ new/cinnamon-screensaver-6.6.1/src/clock.py 2025-12-16 16:27:23.000000000 
+0100
@@ -21,10 +21,8 @@
     as well as its current monitor.
     """
     def __init__(self, away_message=None, initial_monitor=0, low_res=False):
-        super(ClockWidget, self).__init__(initial_monitor)
+        super(ClockWidget, self).__init__(initial_monitor, Gtk.Align.START, 
Gtk.Align.CENTER)
         self.get_style_context().add_class("clock")
-        self.set_halign(Gtk.Align.START)
-
         self.set_property("margin", 6)
 
         self.clock = None
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/cinnamon-screensaver-6.4.0/src/dbusdepot/cinnamonClient.py 
new/cinnamon-screensaver-6.6.1/src/dbusdepot/cinnamonClient.py
--- old/cinnamon-screensaver-6.4.0/src/dbusdepot/cinnamonClient.py      
2024-11-26 14:51:33.000000000 +0100
+++ new/cinnamon-screensaver-6.6.1/src/dbusdepot/cinnamonClient.py      
2025-12-16 16:27:23.000000000 +0100
@@ -1,27 +1,98 @@
 #!/usr/bin/python3
 
-from gi.repository import Gio, CScreensaver
+from gi.repository import Gio, CScreensaver, GObject
 
 from dbusdepot.baseClient import BaseClient
+from util import trackers
+
+# see cinnamon/files/usr/share/cinnamon/cinnamon-settings/bin/InputSources.py
+class CurrentInputSource:
+    def __init__(self, source):
+        self.type, self.id, self.index,         \
+            self.display_name, self.short_name, \
+            self.flag_name, self.xkbid,         \
+            self.xkb_layout, self.xkb_variant,  \
+            self.preferences,                   \
+            self.dupe_id, self.active           \
+                 = source
 
 class CinnamonClient(BaseClient):
     """
-    Simple client to talk to Cinnamon's dbus interface.  Currently
-    its only use is for attempting to force an exit from overview
-    and expo mode (both of which do a fullscreen grab and would prevent
-    the screensaver from acquiring one.)
+    Client to talk to Cinnamon's dbus interface.
+
+    Used to deactivate special modal cinnamon states and deal with
+    keyboard layout info.
     """
     CINNAMON_SERVICE = "org.Cinnamon"
     CINNAMON_PATH    = "/org/Cinnamon"
-
+    __gsignals__ = {
+        'current-input-source-changed': (GObject.SignalFlags.RUN_LAST, None, 
()),
+        'input-sources-changed': (GObject.SignalFlags.RUN_LAST, None, ())
+    }
     def __init__(self):
         super(CinnamonClient, self).__init__(Gio.BusType.SESSION,
                                              CScreensaver.CinnamonProxy,
                                              self.CINNAMON_SERVICE,
                                              self.CINNAMON_PATH)
+        self.sources = []
 
     def on_client_setup_complete(self):
-        pass
+        trackers.con_tracker_get().connect(self.proxy, "g-signal", 
self.on_cinnamon_signal)
+        self.update_layout_sources()
+
+    def on_cinnamon_signal(self, proxy, sender, signal, params, data=None):
+        if signal == "CurrentInputSourceChanged":
+            self.update_current_layout(params[0])
+        elif signal == "InputSourcesChanged":
+            self.update_layout_sources()
+
+    def update_layout_sources(self):
+        
self.proxy.GetInputSources(result_handler=self.get_input_sources_callback,
+                                   error_handler=self.get_input_sources_error)
+
+    def get_input_sources_callback(self, proxy, sources, data=None):
+        self.sources = []
+
+        for source in sources:
+            input_source = CurrentInputSource(source)
+            if input_source.type == "xkb":
+                self.sources.append(input_source)
+        self.emit("input-sources-changed")
+
+    def get_input_sources_error(self, proxy, error, data=None):
+        print("Failed to get keyboard layouts from Cinnamon - multiple layouts 
will not be available: %s" % error.message)
+
+    def has_multiple_keyboard_layouts(self):
+        return len(self.sources) > 1
+
+    def update_current_layout(self, layout):
+        for source in self.sources:
+            source.active = source.id == layout
+        self.emit("current-input-source-changed")
+
+    def get_current_layout_source(self):
+        for source in self.sources:
+            if source.active:
+                return source
+        return None
+
+    def activate_layout_index(self, index):
+        self.proxy.ActivateInputSourceIndex("(i)", index)
+
+    def activate_next_layout(self):
+        current = 0
+
+        for i in range(0, len(self.sources)):
+            source = self.sources[i]
+            if source.active:
+                current = i
+                break
+
+        new = current + 1
+        if new > len(self.sources) - 1:
+            new = 0
+
+        self.proxy.ActivateInputSourceIndex("(i)", self.sources[new].index)
 
     def exit_expo_and_overview(self):
         if self.ensure_proxy_alive():
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cinnamon-screensaver-6.4.0/src/floating.py 
new/cinnamon-screensaver-6.6.1/src/floating.py
--- old/cinnamon-screensaver-6.4.0/src/floating.py      2024-11-26 
14:51:33.000000000 +0100
+++ new/cinnamon-screensaver-6.6.1/src/floating.py      2025-12-16 
16:27:23.000000000 +0100
@@ -7,52 +7,32 @@
 from util import trackers
 from util import settings
 
-POSITIONING_TIMEOUT = 30
-ALIGNMENTS = [int(Gtk.Align.START), int(Gtk.Align.END), int(Gtk.Align.CENTER)]
+class PositionInfo():
+    def __init__(self, monitor, halign, valign):
+        self.monitor = monitor
+        self.halign = halign
+        self.valign = valign
 
 class Floating:
-    def __init__(self, initial_monitor=0):
+    def __init__(self, initial_monitor=0, halign=Gtk.Align.CENTER, 
valign=Gtk.Align.CENTER):
         super(Floating, self).__init__()
-        self.set_halign(Gtk.Align.CENTER)
-        self.set_valign(Gtk.Align.CENTER)
+        self.awake_position = PositionInfo(initial_monitor, halign, valign)
+        self.next_position = self.awake_position
         self.current_monitor = initial_monitor
+        self.apply_next_position()
 
     def start_positioning(self):
+        self.apply_next_position()
         self.show()
-        if settings.get_allow_floating():
-            trackers.timer_tracker_get().cancel(str(self) + "positioning")
-            trackers.timer_tracker_get().start_seconds(str(self) + 
"positioning",
-                                                       POSITIONING_TIMEOUT,
-                                                       
self.positioning_callback)
 
-    def stop_positioning(self):
-        if settings.get_allow_floating():
-            trackers.timer_tracker_get().cancel(str(self) + "positioning")
+    def set_next_position(self, monitor, halign, valign):
+        self.next_position = PositionInfo(monitor, halign, valign)
 
-    def positioning_callback(self):
-        current_halign = int(self.get_halign())
-        horizontal = current_halign
-
-        current_valign = int(self.get_valign())
-        vertical = current_valign
-
-        while horizontal == current_halign:
-            horizontal = ALIGNMENTS[random.randint(0, 2)]
-        while vertical == current_valign:
-            vertical = ALIGNMENTS[random.randint(0, 2)]
-
-        self.set_halign(Gtk.Align(horizontal))
-        self.set_valign(Gtk.Align(vertical))
-
-        if status.screen.get_n_monitors() > 1:
-            new_monitor = self.current_monitor
-            n = status.screen.get_n_monitors()
-
-            while new_monitor == self.current_monitor:
-                new_monitor = random.randint(0, n - 1)
-
-            self.current_monitor = new_monitor
-
-        self.queue_resize()
-
-        return True
+    def apply_next_position(self):
+        self.current_monitor = self.next_position.monitor
+        self.set_halign(self.next_position.halign)
+        self.set_valign(self.next_position.valign)
+
+    def set_awake_position(self, monitor):
+        self.awake_position.monitor = monitor
+        self.next_position = self.awake_position
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cinnamon-screensaver-6.4.0/src/monitorView.py 
new/cinnamon-screensaver-6.6.1/src/monitorView.py
--- old/cinnamon-screensaver-6.4.0/src/monitorView.py   2024-11-26 
14:51:33.000000000 +0100
+++ new/cinnamon-screensaver-6.6.1/src/monitorView.py   2025-12-16 
16:27:23.000000000 +0100
@@ -69,21 +69,8 @@
         significant gradient vertically framing the unlock dialog
         when Awake.
         """
-        if not status.Awake:
-            cr.set_source_rgba(0.0, 0.0, 0.0, 0.7)
-            cr.paint()
-            return False
-
-        r = widget.get_allocation()
-
-        pattern = cairo.LinearGradient(0, 0, 0, r.height)
-        pattern.add_color_stop_rgba (0, 0, 0, 0, .75)
-        pattern.add_color_stop_rgba (.35, 0, 0, 0, .9)
-        pattern.add_color_stop_rgba (.65, 0, 0, 0, .9)
-        pattern.add_color_stop_rgba (1, 0, 0, 0, .75)
-        cr.set_source(pattern)
+        cr.set_source_rgba(0.0, 0.0, 0.0, 0.7)
         cr.paint()
-
         return False
 
 class MonitorView(BaseWindow):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cinnamon-screensaver-6.4.0/src/osk.py 
new/cinnamon-screensaver-6.6.1/src/osk.py
--- old/cinnamon-screensaver-6.4.0/src/osk.py   2024-11-26 14:51:33.000000000 
+0100
+++ new/cinnamon-screensaver-6.6.1/src/osk.py   2025-12-16 16:27:23.000000000 
+0100
@@ -154,7 +154,7 @@
                       halign=Gtk.Align.CENTER,
                       valign=Gtk.Align.END)
 
-        activate_button = TransparentButton("input-keyboard-symbolic", 
Gtk.IconSize.LARGE_TOOLBAR)
+        activate_button = TransparentButton("xsi-input-keyboard-symbolic", 
Gtk.IconSize.LARGE_TOOLBAR)
         activate_button.connect("clicked", self.on_activate_button_clicked)
 
         box.pack_start(activate_button, False, False, 0)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cinnamon-screensaver-6.4.0/src/passwordEntry.py 
new/cinnamon-screensaver-6.6.1/src/passwordEntry.py
--- old/cinnamon-screensaver-6.4.0/src/passwordEntry.py 2024-11-26 
14:51:33.000000000 +0100
+++ new/cinnamon-screensaver-6.6.1/src/passwordEntry.py 2025-12-16 
16:27:23.000000000 +0100
@@ -33,20 +33,13 @@
         trackers.con_tracker_get().connect(self, "icon-press", 
self.on_icon_pressed)
 
         self.placeholder_text = placeholder_text
-        self.current_icon_name = None
-        self.current_flag_id = 0
-        self.original_group = 0
-
-        self.keyboard_controller = singletons.KeyboardLayoutController
-        trackers.con_tracker_get().connect(self.keyboard_controller,
-                                           "config-changed",
-                                           self.on_config_changed)
-
-        trackers.con_tracker_get().connect(self.keyboard_controller,
-                                           "layout-changed",
-                                           self.on_layout_changed)
+        self.lockscreen_layout_source = None
+        self.system_layout_source = None
 
-        self.set_lockscreen_keyboard_layout()
+        self.cinnamon = singletons.CinnamonClient
+        self.cinnamon.connect("current-input-source-changed", 
self.on_current_layout_changed)
+        self.cinnamon.connect("input-sources-changed", 
self.on_layout_sources_changed)
+        self.on_layout_sources_changed(self.cinnamon)
 
         trackers.con_tracker_get().connect(self,
                                            "destroy",
@@ -59,9 +52,6 @@
         update_layout_icon(), just so GtkEntry thinks there's an icon there,
         that way it allocates space for it, and responds to clicks in the area.
         """
-        if not self.keyboard_controller.get_enabled():
-            return False
-
         icon_rect = widget.get_icon_area(Gtk.EntryIconPosition.PRIMARY)
         x = icon_rect.x
         y = icon_rect.y + 2
@@ -69,15 +59,11 @@
         height = icon_rect.height - 4
 
         handled = False
-
         if settings.get_show_flags():
-            name = self.keyboard_controller.get_current_icon_name()
-
             ui_scale = self.get_scale_factor()
 
-            if name:
-                filename = "/usr/share/iso-flag-png/%s.png" % name
-
+            if self.lockscreen_layout_source.flag_name != "":
+                filename = "/usr/share/iso-flag-png/%s.png" % 
self.lockscreen_layout_source.flag_name
                 try:
                     pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(filename, 
-1, height * ui_scale)
 
@@ -98,26 +84,37 @@
 
                     cr.paint()
 
-                    self.keyboard_controller.render_cairo_subscript(cr,
-                                                                    render_x + 
(logical_width / 2),
-                                                                    render_y + 
(logical_height / 2),
-                                                                    
logical_width / 2,
-                                                                    
logical_height / 2,
-                                                                    
self.keyboard_controller.get_current_flag_id())
+                    if self.lockscreen_layout_source.dupe_id > 0:
+                        x = render_x + logical_width / 2
+                        y = render_y + logical_height / 2
+                        width = logical_width / 2 + 2
+                        height = logical_height / 2 + 2
+
+                        cr.set_source_rgba(0, 0, 0, 0.5)
+                        cr.rectangle(x, y, width, height)
+                        cr.fill()
+
+                        cr.set_source_rgba(1.0, 1.0, 1.0, 0.8)
+                        cr.rectangle(x + 1, y + 1, width - 2, height - 2)
+                        cr.fill()
+
+                        cr.set_source_rgba(0.0, 0.0, 0.0, 1.0)
+                        cr.select_font_face("sans", cairo.FontSlant.NORMAL, 
cairo.FontWeight.BOLD)
+                        cr.set_font_size(height - 2.0)
+
+                        dupe_str = str(self.lockscreen_layout_source.dupe_id)
+
+                        ext = cr.text_extents(dupe_str)
+                        cr.move_to((x + (width / 2.0) - (ext.width / 2.0)),
+                                   (y + (height / 2.0) + (ext.height / 2.0)))
+                        cr.show_text(dupe_str)
 
                     handled = True
                 except GLib.Error:
                     pass
 
         if not handled:
-            if settings.get_use_layout_variant_names():
-                name = self.keyboard_controller.get_current_variant_label()
-            else:
-                name = self.keyboard_controller.get_current_short_group_label()
-
-            if settings.get_show_upper_case_layout():
-                name = name.upper()
-
+            name = self.lockscreen_layout_source.short_name
             ctx = widget.get_style_context()
             ctx.save()
 
@@ -167,16 +164,27 @@
         self.progress_pulse()
         return True
 
-    def on_layout_changed(self, controller, layout):
+    def on_current_layout_changed(self, cinnamon):
+        if not self.cinnamon.has_multiple_keyboard_layouts():
+            return
+
+        self.lockscreen_layout_source = 
self.cinnamon.get_current_layout_source()
+
         self.grab_focus()
         self.update_layout_icon()
 
-    def on_config_changed(self, controller):
+    def on_layout_sources_changed(self, cinnamon):
+        self.system_layout_source = self.cinnamon.get_current_layout_source()
+        self.lockscreen_layout_source = self.system_layout_source
+
+        if not self.cinnamon.has_multiple_keyboard_layouts():
+            return
+
         self.set_lockscreen_keyboard_layout()
 
     def on_icon_pressed(self, entry, icon_pos, event):
         if icon_pos == Gtk.EntryIconPosition.PRIMARY:
-            self.keyboard_controller.next_group()
+            self.cinnamon.activate_next_layout()
         elif icon_pos == Gtk.EntryIconPosition.SECONDARY:
             if self.get_input_purpose() == Gtk.InputPurpose.FREE_FORM:
                 self.set_visibility(False)
@@ -195,62 +203,46 @@
         also ensures a redraw at the correct time to update the flag image.
         """
         self.set_icon_from_icon_name(Gtk.EntryIconPosition.PRIMARY, 
"screensaver-blank")
-        self.set_icon_tooltip_text(Gtk.EntryIconPosition.PRIMARY, 
self.keyboard_controller.get_current_name())
-
-        self.update_saved_group(self.keyboard_controller.get_current_group())
+        self.set_icon_tooltip_text(Gtk.EntryIconPosition.PRIMARY, 
self.lockscreen_layout_source.display_name)
 
     def on_destroy(self, widget, data=None):
         self.stop_progress()
 
-        trackers.con_tracker_get().disconnect(self.keyboard_controller,
-                                              "config-changed",
-                                              self.on_config_changed)
-
-        trackers.con_tracker_get().disconnect(self.keyboard_controller,
-                                              "layout-changed",
-                                              self.on_layout_changed)
-
         self.restore_original_layout()
 
     def set_lockscreen_keyboard_layout(self):
-        if not self.keyboard_controller.get_enabled():
-            return
-
         # If there are multiple keyboard layouts, we want to store
         # the one the user ends up using in the unlock widget, as they'll
         # want to use the same one each time, at least until they change
         # their password.
 
-        saved_group = settings.get_kb_group()
-        self.original_group = self.keyboard_controller.get_current_group()
+        saved_index = settings.get_kb_group()
+        new_index = 0
 
-        new_group = 0
-
-        if saved_group == -1:
-            new_group = self.original_group
+        if saved_index == -1:
+            new_index = self.system_layout_source.index
+            settings.set_kb_group(new_index)
         else:
-            new_group = saved_group
+            new_index = saved_index
 
-        self.keyboard_controller.set_current_group(new_group)
-        self.update_saved_group(new_group)
-        self.update_layout_icon()
+        if new_index != self.system_layout_source.index:
+            self.cinnamon.activate_layout_index(new_index)
 
-        trackers.con_tracker_get().connect(self,
-                                           "draw",
-                                           self.on_draw)
+        self.update_layout_icon()
 
-    def update_saved_group(self, group):
-        settings.set_kb_group(group)
+        trackers.con_tracker_get().connect_after(self,
+                                                 "draw",
+                                                 self.on_draw)
 
     def restore_original_layout(self):
         """
         Called when the unlock dialog is destroyed, restores
         the group that was active before the screensaver was activated.
         """
-        if not self.keyboard_controller.get_enabled():
-            return
+        if settings.get_kb_group() != self.lockscreen_layout_source.index:
+            settings.set_kb_group(self.lockscreen_layout_source.index)
 
-        self.keyboard_controller.set_current_group(self.original_group)
+        self.cinnamon.activate_layout_index(self.system_layout_source.index)
 
     def grab_focus(self):
         Gtk.Widget.grab_focus(self)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cinnamon-screensaver-6.4.0/src/playerControl.py 
new/cinnamon-screensaver-6.6.1/src/playerControl.py
--- old/cinnamon-screensaver-6.4.0/src/playerControl.py 2024-11-26 
14:51:33.000000000 +0100
+++ new/cinnamon-screensaver-6.6.1/src/playerControl.py 2025-12-16 
16:27:23.000000000 +0100
@@ -40,7 +40,7 @@
         vbox.pack_start(button_box, True, True, 0)
         vbox.set_valign(Gtk.Align.CENTER)
 
-        self.previous_button = 
TransparentButton("media-skip-backward-symbolic", Gtk.IconSize.BUTTON)
+        self.previous_button = 
TransparentButton("xsi-media-skip-backward-symbolic", Gtk.IconSize.BUTTON)
         self.previous_button.show()
         trackers.con_tracker_get().connect(self.previous_button,
                                            "clicked",
@@ -55,7 +55,7 @@
                                            self.on_play_pause_clicked)
         button_box.pack_start(self.play_pause_button, True, True, 2)
 
-        self.next_button = TransparentButton("media-skip-forward-symbolic", 
Gtk.IconSize.BUTTON)
+        self.next_button = 
TransparentButton("xsi-media-skip-forward-symbolic", Gtk.IconSize.BUTTON)
         self.next_button.show()
         trackers.con_tracker_get().connect(self.next_button,
                                            "clicked",
@@ -111,9 +111,9 @@
 
     def get_play_pause_icon_name(self, status):
         if status == PlaybackStatus.Playing:
-            icon_name = "media-playback-pause-symbolic"
+            icon_name = "xsi-media-playback-pause-symbolic"
         else:
-            icon_name = "media-playback-start-symbolic"
+            icon_name = "xsi-media-playback-start-symbolic"
 
         return icon_name
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cinnamon-screensaver-6.4.0/src/singletons.py 
new/cinnamon-screensaver-6.6.1/src/singletons.py
--- old/cinnamon-screensaver-6.4.0/src/singletons.py    2024-11-26 
14:51:33.000000000 +0100
+++ new/cinnamon-screensaver-6.6.1/src/singletons.py    2025-12-16 
16:27:23.000000000 +0100
@@ -48,12 +48,6 @@
 Backgrounds.load_from_preferences(settings.bg_settings)
 settings.bg_settings.connect("changed", lambda s,k: 
Backgrounds.load_from_preferences(s))
 
-# We use XAppKbdLayoutController as a wrapper around libgnomekbd to supply the 
icon theme
-# with icons, as well as providing correct group names.
-gi.require_version('XApp', '1.0')
-from gi.repository import XApp
-KeyboardLayoutController = XApp.KbdLayoutController()
-
 # This sets up synchronously, as we need to know the fractional scaling state 
before
 # setting up the screensaver.
 MuffinClient = _MuffinClient()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cinnamon-screensaver-6.4.0/src/stage.py 
new/cinnamon-screensaver-6.6.1/src/stage.py
--- old/cinnamon-screensaver-6.4.0/src/stage.py 2024-11-26 14:51:33.000000000 
+0100
+++ new/cinnamon-screensaver-6.6.1/src/stage.py 2025-12-16 16:27:23.000000000 
+0100
@@ -9,18 +9,25 @@
 import status
 import constants as c
 import singletons
+from floating import Floating
 from monitorView import MonitorView
 from unlock import UnlockDialog
 from clock import ClockWidget
 from albumArt import AlbumArt
 from audioPanel import AudioPanel
 from infoPanel import InfoPanel
-from osk import OnScreenKeyboard
-from floating import ALIGNMENTS
 from util import utils, trackers, settings
 from util.eventHandler import EventHandler
 from util.utils import DEBUG
 
+try:
+    from osk import OnScreenKeyboard
+except Exception as e:
+    print("Failed to import on-screen keyboard: %s" % str(e))
+    OnScreenKeyboard = None
+
+FLOATER_POSITIONING_TIMEOUT = 30
+
 class Stage(Gtk.Window):
     """
     The Stage is the toplevel window of the entire screensaver while
@@ -75,6 +82,7 @@
         self.osk = None
 
         self.floaters = []
+        self.floaters_need_update = False
 
         self.event_handler = EventHandler(manager)
 
@@ -272,10 +280,13 @@
                 print("Problem setting up clock widget: %s" % str(e))
                 self.clock_widget = None
 
-            try:
-                self.setup_osk()
-            except Exception as e:
-                print("Problem setting up on-screen keyboard: %s" % str(e))
+            if OnScreenKeyboard:
+                try:
+                    self.setup_osk()
+                except Exception as e:
+                    print("Problem setting up on-screen keyboard: %s" % str(e))
+                    self.osk = None
+            else:
                 self.osk = None
 
             trackers.timer_tracker_get().start("setup-delayed-components",
@@ -298,7 +309,28 @@
             self.audio_panel = None
             self.info_panel = None
 
+        self.start_float_timer()
+
+    def start_float_timer(self):
+        if settings.get_allow_floating():
+            if status.Debug:
+                timeout = 5
+            else:
+                timeout = FLOATER_POSITIONING_TIMEOUT
+            trackers.timer_tracker_get().start_seconds("floater-update", 
timeout, self.update_floaters)
+
+    def update_floaters(self):
+        self.floaters_need_update = True
+        self.overlay.queue_allocate()
+        return GLib.SOURCE_CONTINUE
+
+    def stop_float_timer(self):
+        trackers.timer_tracker_get().cancel("floater-update")
+        self.floaters_need_update = False
+
     def destroy_children(self):
+        self.stop_float_timer()
+
         try:
             self.destroy_monitor_views()
         except Exception as e:
@@ -312,14 +344,12 @@
 
         try:
             if self.clock_widget is not None:
-                self.clock_widget.stop_positioning()
                 self.clock_widget.destroy()
         except Exception as e:
             print(e)
 
         try:
             if self.albumart_widget is not None:
-                self.albumart_widget.stop_positioning()
                 self.albumart_widget.destroy()
         except Exception as e:
             print(e)
@@ -496,7 +526,7 @@
         Initially invisible, regardless - its visibility is controlled via its
         own positioning timer.
         """
-        self.albumart_widget = AlbumArt(None, 
status.screen.get_mouse_monitor())
+        self.albumart_widget = AlbumArt(status.screen.get_mouse_monitor(), 
status.screen.get_low_res_mode())
         self.add_child_widget(self.albumart_widget)
 
         self.floaters.append(self.albumart_widget)
@@ -644,21 +674,13 @@
 
         utils.clear_clipboards(self.unlock_dialog)
 
-        if self.clock_widget is not None:
-            self.clock_widget.stop_positioning()
-        if self.albumart_widget is not None:
-            self.albumart_widget.stop_positioning()
+        self.stop_float_timer()
 
         status.Awake = True
 
         if self.info_panel:
             self.info_panel.refresh_power_state()
 
-        if self.clock_widget is not None:
-            self.clock_widget.show()
-        if self.albumart_widget is not None:
-            self.albumart_widget.show()
-
         self.unlock_dialog.show()
 
         if self.audio_panel is not None:
@@ -677,10 +699,6 @@
 
         if self.unlock_dialog is not None:
             self.unlock_dialog.hide()
-        if self.clock_widget is not None:
-            self.clock_widget.hide()
-        if self.albumart_widget is not None:
-            self.albumart_widget.hide()
         if self.audio_panel is not None:
             self.audio_panel.hide()
         if self.info_panel is not None:
@@ -691,6 +709,7 @@
         status.Awake = False
 
         self.update_monitor_views()
+        self.start_float_timer()
 
         if self.info_panel is not None:
             self.info_panel.refresh_power_state()
@@ -700,13 +719,6 @@
         Updates all of our MonitorViews based on the power
         or Awake states.
         """
-
-        if not status.Awake:
-            if self.clock_widget is not None and settings.get_show_clock():
-                self.clock_widget.start_positioning()
-            if self.albumart_widget is not None and 
settings.get_show_albumart():
-                self.albumart_widget.start_positioning()
-
         for monitor in self.monitors:
                 monitor.show()
 
@@ -846,7 +858,7 @@
 
             return True
 
-        if isinstance(child, ClockWidget) or isinstance(child, AlbumArt):
+        if isinstance(child, Floating):
             """
             ClockWidget and AlbumArt behave differently depending on if 
status.Awake is True or not.
 
@@ -856,19 +868,36 @@
             valign, and current monitor every so many seconds, calling a 
queue_resize on itself after
             each timer tick (which forces this function to run).
             """
-            min_rect, nat_rect = child.get_preferred_size()
+            if settings.get_allow_floating():
+                if self.floaters_need_update:
+                    alignments = [int(Gtk.Align.START), int(Gtk.Align.END), 
int(Gtk.Align.CENTER)]
+                    n_monitors = status.screen.get_n_monitors()
+                    alignment_positions = []
+                    for i in range(n_monitors):
+                        for halign in alignments:
+                            for valign in alignments:
+                                alignment_positions.append((i, halign, valign))
 
-            if status.Awake:
-                current_monitor = status.screen.get_mouse_monitor()
-            else:
-                current_monitor = child.current_monitor
+                    for floater in self.floaters:
+                        position = alignment_positions.pop(random.randint(0, 
len(alignment_positions) - 1))
+                        floater.set_next_position(*position)
 
-            monitor_rect = status.screen.get_monitor_geometry(current_monitor)
+                    self.floaters_need_update = False
 
+                child.apply_next_position()
+
+            min_rect, nat_rect = child.get_preferred_size()
+            current_monitor = child.current_monitor
+            monitor_rect = status.screen.get_monitor_geometry(current_monitor)
             region_w = monitor_rect.width / 3
-            region_h = monitor_rect.height
+            region_h = monitor_rect.height / 3
 
             if status.Awake:
+                current_monitor = status.screen.get_mouse_monitor()
+                monitor_rect = 
status.screen.get_monitor_geometry(current_monitor)
+                region_w = monitor_rect.width / 3
+                region_h = monitor_rect.height / 3
+
                 """
                 If we're Awake, force the clock to track to the active 
monitor, and be aligned to
                 the left-center.  The albumart widget aligns right-center.
@@ -882,38 +911,8 @@
                 if unlock_nw > region_w:
                     region_w = (monitor_rect.width - unlock_nw) / 2
 
-                region_h = monitor_rect.height
-
-                if isinstance(child, ClockWidget):
-                    child.set_halign(Gtk.Align.START)
-                else:
-                    child.set_halign(Gtk.Align.END)
-
-                child.set_valign(Gtk.Align.CENTER)
-            else:
-                if settings.get_allow_floating():
-                    for floater in self.floaters:
-                        """
-                        Don't let our floating widgets end up in the same spot.
-                        """
-                        if floater is child:
-                            continue
-                        if floater.get_halign() != child.get_halign() and 
floater.get_valign() != child.get_valign():
-                            continue
-
-                        region_h = monitor_rect.height / 3
-
-                        fa = floater.get_halign()
-                        ca = child.get_halign()
-                        while fa == ca:
-                            ca = ALIGNMENTS[random.randint(0, 2)]
-                        child.set_halign(ca)
-
-                        fa = floater.get_valign()
-                        ca = child.get_valign()
-                        while fa == ca:
-                            ca = ALIGNMENTS[random.randint(0, 2)]
-                        child.set_valign(ca)
+                child.set_awake_position(current_monitor)
+                child.apply_next_position()
 
             # Restrict the widget size to the allowable region sizes if 
necessary.
             allocation.width = min(nat_rect.width, region_w)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cinnamon-screensaver-6.4.0/src/unlock.py 
new/cinnamon-screensaver-6.6.1/src/unlock.py
--- old/cinnamon-screensaver-6.4.0/src/unlock.py        2024-11-26 
14:51:33.000000000 +0100
+++ new/cinnamon-screensaver-6.6.1/src/unlock.py        2025-12-16 
16:27:23.000000000 +0100
@@ -171,6 +171,8 @@
 
 
         self.box.show_all()
+        self.password_entry.hide()
+        self.auth_unlock_button.hide()
 
     def initialize_auth_client(self):
         return self.auth_client.initialize()
@@ -187,6 +189,9 @@
         self.set_busy(False)
         self.auth_message_label.set_text(_("Incorrect password"))
 
+        self.password_entry.hide()
+        self.auth_unlock_button.hide()
+
         self.emit("authenticate-failure")
         self.emit("uninhibit-timeout")
 
@@ -211,6 +216,9 @@
             self.update_authinfo_label()
 
     def on_authentication_prompt_changed(self, auth_client, prompt):
+        self.password_entry.show_all()
+        self.auth_unlock_button.show_all()
+
         if "password:" in prompt.lower():
             prompt = _("Please enter your password...")
         else:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/cinnamon-screensaver-6.4.0/src/widgets/powerWidget.py 
new/cinnamon-screensaver-6.6.1/src/widgets/powerWidget.py
--- old/cinnamon-screensaver-6.4.0/src/widgets/powerWidget.py   2024-11-26 
14:51:33.000000000 +0100
+++ new/cinnamon-screensaver-6.6.1/src/widgets/powerWidget.py   2025-12-16 
16:27:23.000000000 +0100
@@ -101,38 +101,35 @@
         if state in (UPOWER_STATE_CHARGING, UPOWER_STATE_DISCHARGING,
                      UPOWER_STATE_PENDING_CHARGE, 
UPOWER_STATE_PENDING_DISCHARGE):
             if percentage < 10:
-                names = ["battery-level-0", "battery-caution"]
+                names = ["xsi-battery-level-0"]
             elif percentage < 20:
-                names = ["battery-level-10", "battery-low"]
+                names = ["xsi-battery-level-10"]
             elif percentage < 30:
-                names = ["battery-level-20", "battery-low"]
+                names = ["xsi-battery-level-20"]
             elif percentage < 40:
-                names = ["battery-level-30", "battery-good"]
+                names = ["xsi-battery-level-30"]
             elif percentage < 50:
-                names = ["battery-level-40", "battery-good"]
+                names = ["xsi-battery-level-40"]
             elif percentage < 60:
-                names = ["battery-level-50", "battery-good"]
+                names = ["xsi-battery-level-50"]
             elif percentage < 70:
-                names = ["battery-level-60", "battery-full"]
+                names = ["xsi-battery-level-60"]
             elif percentage < 80:
-                names = ["battery-level-70", "battery-full"]
+                names = ["xsi-battery-level-70"]
             elif percentage < 90:
-                names = ["battery-level-80", "battery-full"]
+                names = ["xsi-battery-level-80"]
             elif percentage < 99:
-                names = ["battery-level-90", "battery-full"]
+                names = ["xsi-battery-level-90"]
             else:
-                names = ["battery-level-100", "battery-full"]
+                names = ["xsi-battery-level-100"]
 
             if state in (UPOWER_STATE_CHARGING, UPOWER_STATE_PENDING_CHARGE):
                 names[0] += "-charging"
-                names[1] += "-charging"
 
             names[0] += "-symbolic"
-            names[1] += "-symbolic"
+
         elif state == UPOWER_STATE_FULLY_CHARGED:
-            names = ["battery-level-100-charged-symbolic",
-                     "battery-full-charged-symbolic",
-                     "battery-full-charging-symbolic"]
+            names = ["xsi-battery-level-100-charged-symbolic"]
         else:
             names = (battery.get_property("icon-name"),)
 

Reply via email to