<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>1a1a1a &amp;mdash; in ♥️ with linux</title>
    <link>https://inlovewithlinux.com/tag:1a1a1a</link>
    <description>After 20 years with macOS, I returned to Linux &lt;span&gt;many&lt;/span&gt; days ago, including &lt;strong&gt;some&lt;/strong&gt; days without hopping  on openSUSE.</description>
    <pubDate>Sun, 31 May 2026 03:59:21 +0200</pubDate>
    <item>
      <title>Personalise GNOME</title>
      <link>https://inlovewithlinux.com/personalise-gnome</link>
      <description>&lt;![CDATA[I switched from openSUSE to Debian stable a week ago. As great as Debian is, it unfortunately has the disadvantage that I could no longer use Niri. That left SwayWM or GNOME.&#xA;&#xA;After a few days, I realised that I don&#39;t really need a tiling window manager, I just like working with workspaces.&#xA;&#xA;So the choice fell on GNOME, which I have grown to like very much and, above all, which looks really good. I never warmed to KDE, but everyone has their own preferences.&#xA;&#xA;Since I only learned programming with Turbo Pascal and DBase, the AI had to help out a bit.&#xA;&#xA;I would be delighted if some experts would take a look at the scripts. In my opinion, what the AI has written looks good, but perhaps it could be even better with a real brain.&#xA;&#xA;Files:&#xA;&#xA;You can find all scripts of the following instructions on Codeberg in my dotfiles.&#xA;&#xA;Problem 1: Start apps on a certain workspace&#xA;&#xA;GNOME has workspaces, but I missed being able to start a programme on a workspace with a keyboard shortcut. For example, Tuba (Mastodon) is always on workspace two.&#xA;&#xA;Unfortunately, GNOME does not offer this by default.&#xA;&#xA;Solution 1: Extensions, bash and keybindings&#xA;&#xA;Update: 21.09.2025&#xA;&#xA;I changed everything to a combination of the Auto Move Extension and changing the shortcuts of the dash app via dconf.&#xA;&#xA;For an example:&#xA;&#xA;In the extension I assigned Tuba to Workspace 2 and changed the shortcut of application 4 in the dash to SUPER+SHIFT+T.&#xA;&#xA;Now every time I press SUPER+SHIFT+T either Tuba starts or the app is focused on workspace 2.&#xA;&#xA;Problem 2: Sync Settings&#xA;&#xA;I use two computers: a desktop on my desk and a Framework 12 laptop. GNOME stores its settings in dconf. So I needed a tool that would export certain settings (e.g., keyboard shortcuts), push them to git, and import them back onto the other computer.&#xA;&#xA;Solution 2: Export dconf and sync over git&#xA;&#xA;The AI also helped after I spent a long time explaining what I needed.&#xA;&#xA;!/bin/bash&#xA;set -euo pipefail&#xA;&#xA;---------- CONFIG ----------&#xA;GITHUB=&#34;$HOME/.dotdrop&#34;&#x9;&#x9;&#x9;&#xA;REMOTE=&#34;$GITHUB/dotfiles/Gnome&#34;&#x9;&#xA;mkdir -p &#34;$REMOTE&#34;&#xA;&#xA;DCONFPATHS=(&#xA;  &#34;/org/gnome/desktop/wm/keybindings/&#34;&#xA;  &#34;/org/gnome/mutter/keybindings/&#34;&#xA;  &#34;/org/gnome/settings-daemon/plugins/media-keys/&#34;&#xA;  &#34;/org/gnome/shell/&#34;&#xA;)&#xA;----------------------------&#xA;&#xA;Build readable path list&#xA;PATHLIST=&#34;&#34;&#xA;for p in &#34;${DCONFPATHS[@]}&#34;; do PATHLIST+=&#34;$p&#34;$&#39;\n&#39;; done&#xA;&#xA;---------- ACTION HANDLERS ----------&#xA;actionexport() {&#xA;  cd &#34;$GITHUB&#34;&#xA;  git pull --ff-only || { echo &#34;Git pull failed – aborting.&#34;   &amp;2; exit 1; }&#xA;&#xA;  for path in &#34;${DCONFPATHS[@]}&#34;; do&#xA;    filename=$(echo &#34;$path&#34; | tr &#39;/&#39; &#39;&#39;).conf&#xA;    dconf dump &#34;$path&#34;   &#34;$REMOTE/$filename&#34;&#xA;  done&#xA;  echo &#34;Exported to $REMOTE&#34;&#xA;&#xA;  # exportierte Dateien committen&#xA;  git add &#34;$REMOTE/&#34;&#xA;  git commit -m &#34;Export GNOME shortcuts $(date +%F-%T)&#34;&#xA;  git push&#xA;}&#xA;&#xA;actionimport() {&#xA;  cd &#34;$GITHUB&#34;&#xA;  git pull --ff-only || { echo &#34;Git pull failed – aborting.&#34;   &amp;2; exit 1; }&#xA;&#xA;  for path in &#34;${DCONFPATHS[@]}&#34;; do&#xA;    filename=$(echo &#34;$path&#34; | tr &#39;/&#39; &#39;&#39;).conf&#xA;    file=&#34;$REMOTE/$filename&#34;&#xA;    [[ -f &#34;$file&#34; ]] &amp;&amp; dconf load &#34;$path&#34;  &#34;$file&#34; || echo &#34;File not found: $file&#34; &amp;2&#xA;  done&#xA;  echo &#34;Imported from $REMOTE&#34;&#xA;}&#xA;&#xA;actionopen() {&#xA;  echo &#34;Storage location: $REMOTE&#34;&#xA;  xdg-open &#34;$REMOTE&#34; || true&#xA;}&#xA;&#xA;---------- CLI ENTRY ----------&#xA;case &#34;${1:-}&#34; in&#xA;  export)  actionexport ;;&#xA;  import)  actionimport ;;&#xA;  open)    actionopen ;;&#xA;  )       echo &#34;Usage: $0 {export|import|open}&#34;   &amp;2; exit 1 ;;&#xA;esac&#xA;&#xA;In my case, I export to the .dotdrop directory and sync this with Codeberg via git. Since I also use the dotdrop tool, this directory was the obvious choice.&#xA;&#xA;Problem 3: Power-Screen&#xA;&#xA;I was used to using wlogout in niri or swaywm. Of course, in GNOME wlogout works too, but it didn&#39;t really function properly. For example, there is no transparent background.&#xA;&#xA;Solution 3: Simple Python Script&#xA;&#xA;After a long dialogue, the AI created a simple Python script that uses images from the Papyrus icon set.&#xA;&#xA;Set as a shortcut to SUPER+SHIFT+E... Works.&#xA;&#xA;!/usr/bin/env python3&#xA;coded with the help of AI&#xA;&#xA;import gi, subprocess, os&#xA;gi.requireversion(&#39;Gtk&#39;, &#39;4.0&#39;)&#xA;from gi.repository import Gtk, Gdk, GdkPixbuf&#xA;&#xA;ICONDIR = &#34;/usr/share/icons/Papirus-Dark/24x24@2x/actions&#34;&#xA;&#xA;class PowerPanel(Gtk.Application):&#xA;    def init(self):&#xA;        super().init(applicationid=&#39;org.nasendackel.Powerpanel&#39;)&#xA;        self.win   = None&#xA;        self.cmds  = {&#xA;            &#39;system-suspend.svg&#39;:     &#39;systemctl suspend&#39;,&#xA;            &#39;system-shutdown.svg&#39;:    &#39;systemctl poweroff&#39;,&#xA;            &#39;system-reboot.svg&#39;:      &#39;systemctl reboot&#39;,&#xA;            &#39;system-lock-screen.svg&#39;: &#39;dbus-send --type=methodcall --dest=org.gnome.ScreenSaver /org/gnome/ScreenSaver org.gnome.ScreenSaver.Lock&#39;,&#xA;            &#39;system-log-out.svg&#39;:   &#39;gnome-session-quit --no-prompt&#39;&#xA;        }&#xA;&#xA;    def doactivate(self):&#xA;        self.win = Gtk.ApplicationWindow(application=self)&#xA;        self.win.setdefaultsize(530, 120)&#xA;        self.win.setresizable(False)&#xA;        self.win.setdecorated(False)&#xA;&#xA;        esc = Gtk.EventControllerKey()&#xA;        esc.connect(&#39;key-pressed&#39;, self.onesc)&#xA;        self.win.addcontroller(esc)&#xA;&#xA;        css = Gtk.CssProvider()&#xA;        css.loadfromdata(b&#39;&#39;&#39;&#xA;        window { background: transparent; }&#xA;        button {&#xA;            background: #1a1a1a;&#xA;            border: none;&#xA;            outline: none;&#xA;            border-radius:12px;&#xA;            border:1px solid #fff;&#xA;            }&#xA;        button:focus { background: #A51D2D; }&#xA;        &#39;&#39;&#39;)&#xA;        display = Gdk.Display.getdefault()&#xA;        Gtk.StyleContext.addproviderfordisplay(&#xA;            display, css, Gtk.STYLEPROVIDERPRIORITYAPPLICATION)&#xA;&#xA;        box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=20)&#xA;        for name in [&#39;system-suspend.svg&#39;,&#39;system-shutdown.svg&#39;,&#39;system-reboot.svg&#39;,&#xA;                     &#39;system-lock-screen.svg&#39;,&#39;system-log-out.svg&#39;]:&#xA;            pixbuf = GdkPixbuf.Pixbuf.newfromfileatscale(&#xA;                        os.path.join(ICONDIR, name), 120, 120, True)&#xA;            texture = Gdk.Texture.newforpixbuf(pixbuf)&#xA;            picture = Gtk.Picture.newforpaintable(texture)&#xA;            picture.setcanshrink(True)&#xA;            btn = Gtk.Button()&#xA;            btn.setchild(picture)&#xA;            btn.setsizerequest(120,80)&#xA;            btn.connect(&#39;clicked&#39;, self.onclicked, self.cmds[name])&#xA;            box.append(btn)&#xA;        self.win.setchild(box)&#xA;        self.win.present()&#xA;&#xA;    def onesc(self, ctrl, keyval, keycode, state):&#xA;        if keyval == Gdk.KEYEscape:&#xA;            self.quit()&#xA;            return Gdk.EVENTSTOP&#xA;        return Gdk.EVENTPROPAGATE&#xA;&#xA;    def on_clicked(self, btn, cmd):&#xA;        subprocess.Popen(cmd, shell=True)&#xA;        self.quit()&#xA;&#xA;if name == &#39;main&#39;:&#xA;    PowerPanel().run()&#xA;&#xA;gnome]]&gt;</description>
      <content:encoded><![CDATA[<p>I switched from <a href="https://www.opensuse.org/">openSUSE</a> to <a href="https://www.debian.org/">Debian stable</a> a week ago. As great as Debian is, it unfortunately has the disadvantage that I could no longer use <a href="https://github.com/YaLTeR/niri">Niri</a>. That left <a href="https://swaywm.org/">SwayWM</a> or <a href="https://www.gnome.org/">GNOME</a>.</p>

<p><strong>After a few days, I realised that I don&#39;t really need a tiling window manager, I just like working with workspaces.</strong></p>

<p>So the choice fell on GNOME, which I have grown to like very much and, above all, which looks really good. I never warmed to KDE, but everyone has their own preferences.</p>

<p><strong>Since I only learned programming with Turbo Pascal and DBase, the AI had to help out a bit.</strong></p>

<p><strong>I would be delighted if some experts would take a look at the scripts. In my opinion, what the AI has written looks good, but perhaps it could be even better with a real brain.</strong></p>

<h2 id="files">Files:</h2>

<p>You can find all scripts of the following instructions on Codeberg in my <a href="https://codeberg.org/Nasendackel/dotfiles" title="dotfiles">dotfiles.</a></p>

<h2 id="problem-1-start-apps-on-a-certain-workspace">Problem 1: Start apps on a certain workspace</h2>

<p>GNOME has workspaces, but I missed being able to start a programme on a workspace with a keyboard shortcut. For example, Tuba (Mastodon) is always on workspace two.</p>

<p>Unfortunately, GNOME does not offer this by default.</p>

<h2 id="solution-1-extensions-bash-and-keybindings">Solution 1: Extensions, bash and keybindings</h2>

<p><strong>Update: 21.09.2025</strong></p>

<p>I changed everything to a combination of the <a href="https://gitlab.gnome.org/GNOME/gnome-shell-extensions">Auto Move Extension</a> and changing the shortcuts of the dash app via dconf.</p>

<p><strong>For an example:</strong></p>

<p>In the extension I assigned Tuba to Workspace 2 and changed the shortcut of application 4 in the dash to SUPER+SHIFT+T.</p>

<p><img src="/posts/250920/gnome01.png" alt=""></p>

<p>Now every time I press SUPER+SHIFT+T either Tuba starts or the app is focused on workspace 2.</p>

<h2 id="problem-2-sync-settings">Problem 2: Sync Settings</h2>

<p>I use two computers: a desktop on my desk and a Framework 12 laptop. GNOME stores its settings in dconf. So I needed a tool that would export certain settings (e.g., keyboard shortcuts), push them to git, and import them back onto the other computer.</p>

<h2 id="solution-2-export-dconf-and-sync-over-git">Solution 2: Export dconf and sync over git</h2>

<p>The AI also helped after I spent a long time explaining what I needed.</p>

<pre><code>#!/bin/bash
set -euo pipefail

# ---------- CONFIG ----------
GITHUB=&#34;$HOME/.dotdrop&#34;			
REMOTE=&#34;$GITHUB/dotfiles/Gnome&#34;	
mkdir -p &#34;$REMOTE&#34;

DCONFPATHS=(
  &#34;/org/gnome/desktop/wm/keybindings/&#34;
  &#34;/org/gnome/mutter/keybindings/&#34;
  &#34;/org/gnome/settings-daemon/plugins/media-keys/&#34;
  &#34;/org/gnome/shell/&#34;
)
# ----------------------------

# Build readable path list
PATH_LIST=&#34;&#34;
for p in &#34;${DCONFPATHS[@]}&#34;; do PATH_LIST+=&#34;$p&#34;$&#39;\n&#39;; done

# ---------- ACTION HANDLERS ----------
action_export() {
  cd &#34;$GITHUB&#34;
  git pull --ff-only || { echo &#34;Git pull failed – aborting.&#34; &gt;&amp;2; exit 1; }

  for path in &#34;${DCONFPATHS[@]}&#34;; do
    filename=$(echo &#34;$path&#34; | tr &#39;/&#39; &#39;_&#39;).conf
    dconf dump &#34;$path&#34; &gt; &#34;$REMOTE/$filename&#34;
  done
  echo &#34;Exported to $REMOTE&#34;

  # exportierte Dateien committen
  git add &#34;$REMOTE/*&#34;
  git commit -m &#34;Export GNOME shortcuts $(date +%F-%T)&#34;
  git push
}

action_import() {
  cd &#34;$GITHUB&#34;
  git pull --ff-only || { echo &#34;Git pull failed – aborting.&#34; &gt;&amp;2; exit 1; }

  for path in &#34;${DCONFPATHS[@]}&#34;; do
    filename=$(echo &#34;$path&#34; | tr &#39;/&#39; &#39;_&#39;).conf
    file=&#34;$REMOTE/$filename&#34;
    [[ -f &#34;$file&#34; ]] &amp;&amp; dconf load &#34;$path&#34; &lt; &#34;$file&#34; || echo &#34;File not found: $file&#34; &gt;&amp;2
  done
  echo &#34;Imported from $REMOTE&#34;
}

action_open() {
  echo &#34;Storage location: $REMOTE&#34;
  xdg-open &#34;$REMOTE&#34; || true
}

# ---------- CLI ENTRY ----------
case &#34;${1:-}&#34; in
  export)  action_export ;;
  import)  action_import ;;
  open)    action_open ;;
  *)       echo &#34;Usage: $0 {export|import|open}&#34; &gt;&amp;2; exit 1 ;;
esac
</code></pre>

<p>In my case, I export to the .dotdrop directory and sync this with Codeberg via git. Since I also use the dotdrop tool, this directory was the obvious choice.</p>

<h2 id="problem-3-power-screen">Problem 3: Power-Screen</h2>

<p>I was used to using <a href="https://github.com/ArtsyMacaw/wlogout">wlogout</a> in niri or swaywm. Of course, in GNOME wlogout works too, but it didn&#39;t really function properly. For example, there is no transparent background.</p>

<h2 id="solution-3-simple-python-script">Solution 3: Simple Python Script</h2>

<p>After a long dialogue, the AI created a simple Python script that uses images from the Papyrus icon set.</p>

<p>Set as a shortcut to SUPER+SHIFT+E... Works.</p>

<pre><code>#!/usr/bin/env python3
# coded with the help of AI

import gi, subprocess, os
gi.require_version(&#39;Gtk&#39;, &#39;4.0&#39;)
from gi.repository import Gtk, Gdk, GdkPixbuf

ICON_DIR = &#34;/usr/share/icons/Papirus-Dark/24x24@2x/actions&#34;

class PowerPanel(Gtk.Application):
    def __init__(self):
        super().__init__(application_id=&#39;org.nasendackel.Powerpanel&#39;)
        self.win   = None
        self.cmds  = {
            &#39;system-suspend.svg&#39;:     &#39;systemctl suspend&#39;,
            &#39;system-shutdown.svg&#39;:    &#39;systemctl poweroff&#39;,
            &#39;system-reboot.svg&#39;:      &#39;systemctl reboot&#39;,
            &#39;system-lock-screen.svg&#39;: &#39;dbus-send --type=method_call --dest=org.gnome.ScreenSaver /org/gnome/ScreenSaver org.gnome.ScreenSaver.Lock&#39;,
            &#39;system-log-out.svg&#39;:   &#39;gnome-session-quit --no-prompt&#39;
        }

    def do_activate(self):
        self.win = Gtk.ApplicationWindow(application=self)
        self.win.set_default_size(530, 120)
        self.win.set_resizable(False)
        self.win.set_decorated(False)

        esc = Gtk.EventControllerKey()
        esc.connect(&#39;key-pressed&#39;, self.on_esc)
        self.win.add_controller(esc)

        css = Gtk.CssProvider()
        css.load_from_data(b&#39;&#39;&#39;
        window { background: transparent; }
        button {
            background: #1a1a1a;
            border: none;
            outline: none;
            border-radius:12px;
            border:1px solid #fff;
            }
        button:focus { background: #A51D2D; }
        &#39;&#39;&#39;)
        display = Gdk.Display.get_default()
        Gtk.StyleContext.add_provider_for_display(
            display, css, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)

        box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=20)
        for name in [&#39;system-suspend.svg&#39;,&#39;system-shutdown.svg&#39;,&#39;system-reboot.svg&#39;,
                     &#39;system-lock-screen.svg&#39;,&#39;system-log-out.svg&#39;]:
            pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
                        os.path.join(ICON_DIR, name), 120, 120, True)
            texture = Gdk.Texture.new_for_pixbuf(pixbuf)
            picture = Gtk.Picture.new_for_paintable(texture)
            picture.set_can_shrink(True)
            btn = Gtk.Button()
            btn.set_child(picture)
            btn.set_size_request(120,80)
            btn.connect(&#39;clicked&#39;, self.on_clicked, self.cmds[name])
            box.append(btn)
        self.win.set_child(box)
        self.win.present()

    def on_esc(self, ctrl, keyval, keycode, state):
        if keyval == Gdk.KEY_Escape:
            self.quit()
            return Gdk.EVENT_STOP
        return Gdk.EVENT_PROPAGATE

    def on_clicked(self, btn, cmd):
        subprocess.Popen(cmd, shell=True)
        self.quit()

if __name__ == &#39;__main__&#39;:
    PowerPanel().run()
</code></pre>

<p><img src="/posts/250920/gnome02.png" alt=""></p>

<p><a href="https://inlovewithlinux.com/tag:gnome" class="hashtag"><span>#</span><span class="p-category">gnome</span></a></p>
]]></content:encoded>
      <guid>https://inlovewithlinux.com/personalise-gnome</guid>
      <pubDate>Sun, 21 Sep 2025 00:00:10 +0200</pubDate>
    </item>
  </channel>
</rss>