Plasma 6 method to refresh kglobalaccel shortcuts?

I have a script that changes some default Plasma shortcuts for me, related to the task switcher dialog (moving the Alt+Grave and Alt+Tilde or Alt+Shift+Grave from the “Main” tab to the “Alternative” tab so moving through windows of the same app uses a different visual).

The script works, in the sense that it places the correct updated lines in kglobalshortcutsrc using kwriteconfig${KDE_SESSION_VERSION}. You can log out and log back in, and the shortcuts the script modified will be in place and active, as they should be.

In Plasma 5, I found a simple way to restart the kgobalaccel5 process to refresh its understanding of the currently active shortcuts, to avoid needing to log out. (I don’t know that this is the best/safest way, I just know that it works.)

killall kglobalaccel5 && sleep 2 && kstart5 kglobalaccel5

But with Plasma 6 I found that there is no existing process similar to this or kglobalaccel or kglobalaccel6, since it has apparently been merged into KWin itself, so there’s nothing separate expected to be running. There is a plasma-kglobalaccel user service, but restarting that service doesn’t update the active shortcuts.

The KWin reconfigure DBus command activates the updated task switcher settings that I change in the kwinrc file, but that command has no effect on the active shortcuts after updating the kglobalshortcutsrc file.

Is there some sort of equivalent DBus command to get Plasma or KWin to recognize that the shortcuts in kglobalshortcutsrc have been changed from a script? I tried to dig around in the DBus viewer but couldn’t find anything that seemed to do the job.

Any good reference links or insights on this would be appreciated.

The kglobalacceld API is run under KWin. I believe the DBus API call qdbus org.kde.KWin /KWin org.kde.KWin.reconfigure should reload all the configuration including shortcut keys.

That being said, if you update the shortcut keys using the DBus API calls
org.kde.kglobalaccel /kglobalaccel org.kde.KGlobalAccel.setShortcut -instead of editing some configuration file - then it should become effective immediately.

1 Like

I have been attempting to figure out how to use the DBus calls like setShortcut with no success. GPT-4 is usually good at digesting documentation and explaining how to use something that’s new to me, but the API documentation I found is so cryptic and abstract that it hasn’t been able to give me a working example. I’ll never grasp why API documentation never includes actual usage examples.

I’m sure once I see some examples I’ll figure out what I was misunderstanding about the usage syntax, but until I see those examples it is far more confusing than it was figuring out how to use kwriteconfig5 to change shortcuts in the RC file.

I am planning on putting together a full explanation (for humans like me that are bad at reading API documentation) showing how to use these DBus calls to set shortcuts, in a GitHub gist and/or a post on Reddit. So if anyone is feeling generous enough to explain how to use setShortcut or link to a good set of known working examples, please do so.

Just last night I figured out how to use org.kde.keyboard to connect to a signal and obtain the currently active keyboard layout index and layout list array, so I must not be entirely brain dead. But setShortcut still eludes my understanding.

You must have a write-up ahead of you :slightly_smiling_face: And, automating Plasma configuration is a popular topic.

Configuration files

Both the Plasma shell and KDE applications are configured mainly via their GUIs, although their configurations are stored in human-readable configuration files, which can also be edited manually to change the settings, and backed up and restored to transfer the settings. KDE applications use the KConfig framework to access their configuration files, and all configuration files are stored at paths relative to the same predetermined directories and share the same syntax: Each line can have a key-value pair. Lines are organized under groups that start with the group’s name in square brackets and ends when the next group begins or when the end of the configuration file is reached. Both keys and values may contain white spaces but all white spaces immediately before and after an equals sign, and at the end of a line are ignored. The KConfig framework provides a central configuration system, and consists of two parts: KConfigCore allows applications to access their configuration files, and KConfigGui allows applications to be hooked to the configuration system so that they are automatically initialized from their configuration files, and settings changed via their GUIs are automatically propagated to their configuration files.

KDE follows the XDG Base Directory Specification while storing its files. Therefore, system-wide and user-specific configuration files are stored at paths that are relative to the directories included in $XDG_CONFIG_DIRS and $XDG_CONFIG_HOME respectively, which roughly correspond to the paths below:

$XDG_CONFIG_DIRS:
  
    ~/.config/kdedefaults
    /etc/xdg
    /usr/share/kde-settings/kde-profile/default/xdg
  
$XDG_CONFIG_HOME:
  
    ~/.config

KDE applications may be built with the KParts framework, which is a library that implements a plugin framework that allows GUI components, which are also called kparts or KDE parts, to be reused. Applications built with the KParts framework, such as okular, are implemented as a kpart embedded in a frontend, and have one configuration file for the kpart (e.g. ~/.config/okularpartrc), which applies to all instances of the kpart embedded in different applications, and one configuration file for the application itself (e.g. ~/.config/okularrc). For example, text editor or terminal emulator features can be readily implemented by embedding katepart or konsolepart in an application. KParts are analogous to Bonobo components in GNOME and ActiveX controls in Microsoft’s Component Object Model.


Additionally, KDE applications may be built with the KXMLGUI framework, which consists of several libraries that allow GUI components such as menus, toolbars, icons, tooltips, etc., to be described in an XML file, which is parsed by the setupGUI() function of the KXmlGuiWindow class to construct the GUI. This allows a GUI to be redesigned by modifying the XML file rather than the source code. An XML file describing user modifications to the default GUI of an application is (arguably) considered a data file rather than a configuration file, and therefore is stored at a path that is relative to the $XDG_DATA_HOME/kxmlgui5 directory, with the .rc suffix in its file name (e.g. ~/.local/share/kxmlgui5/okular/{part.rc,shell.rc}), which roughly corresponds to:

$XDG_DATA_HOME/kxmlgui5
  
    ~/.local/share/kxmlgui5

So, all user-specific settings for the Plasma shell and KDE applications can be rougly backed up and restored by copying the associated configuration files foundunder ~/.config and ~/.local/share/kxmlgui5.

Shortcuts

One of the most important configuration categories for humans since think-and-type interface of a keyboards can be much more efficient than look-and-click interface of pointy devices.

If automation isn’t required, shortcuts are set either via the System Settings application, or by manually editing the configuration files.

Since Plasma uses human-readable configuration files, the kwriteconfig6 utility is the intended utility to make setting shortcuts (as well as other plasma configurations) scriptable, I think. However, the setShortcut method available via D-Bus is an alternative way to do it, although maybe not the best way on Plasma.

These are the methods exposed by the KGlobalAccel interface on D-Bus:

$ busctl --user introspect org.kde.kglobalaccel /kglobalaccel org.kde.KGlobalAccel
NAME                           TYPE      SIGNATURE RESULT/VALUE  FLAGS
.action                        method    i         as            -
.actionList                    method    (ai)      as            -
.activateGlobalShortcutContext method    ss        -             -
.allActionsForComponent        method    as        aas           -
.allComponents                 method    -         ao            -
.allMainComponents             method    -         aas           -
.blockGlobalShortcuts          method    b         -             -
.defaultShortcut               method    as        ai            -
.defaultShortcutKeys           method    as        a(ai)         -
.doRegister                    method    as        -             -
.getComponent                  method    s         o             -
.getGlobalShortcutsByKey       method    i         a(ssssssaiai) -
.globalShortcutAvailable       method    (ai)s     b             -
.globalShortcutsByKey          method    (ai)(i)   a(ssssssaiai) -
.isGlobalShortcutAvailable     method    is        b             -
.setForeignShortcut            method    asai      -             -
.setForeignShortcutKeys        method    asa(ai)   -             -
.setInactive                   method    as        -             -
.setShortcut                   method    asaiu     ai            -
.setShortcutKeys               method    asa(ai)u  a(ai)         -
.shortcut                      method    as        ai            -
.shortcutKeys                  method    as        a(ai)         -
.unRegister                    method    as        -             -
.unregister                    method    ss        b             -
.yourShortcutGotChanged        signal    asai      -             -
.yourShortcutsChanged          signal    asa(ai)   -             -

So, the setShortcut method accepts asaiu (arrays of strings, array of integers, and unsigned integer), and returns ai (array of integers):

  • The array of strings, as the first argument, collectively describe the action.
  • The array of integers, as the second argument, are the shortcuts that are to be bound to the action, where a single shortcut can be used if alternative shortcuts aren’t desired. Each shortcut is an integer obtained by adding the values corresponding to key names in tables keys and modifiers, e.g. Pressing the Super key (i.e. Qt::MetaModifier = 0x10000000 = 268435456) and ‘m’ key (i.e. Qt::Key_M = 0x4d = 77) results in the keycode 268435533.
  • loadFlag, as the last argument, can take either the value of 0, which autoloads the saved global shortcut, or the value of 4, which prevents autoloading, so that the outcome of setShortcut call will persist.
  • And the array of integers, as the return value, is the updated set of assigned shortcuts for the action.

An example command:
$ gdbus call --session --dest org.kde.kglobalaccel --object-path /kglobalaccel --method org.kde.KGlobalAccel.setShortcut "['kwin', 'Window Move Center', 'KWin', 'Move Window to the Center']" "[268435533]" 4
  
([268435533],)

The set of strings that describe an action that already has an assigned shortcut can be found out by running the `action` method specified by the same interface, and passing the keycode of the already assigned shortcut as the only argument:
$ gdbus call --session --dest org.kde.kglobalaccel --object-path /kglobalaccel --method org.kde.KGlobalAccel.action '268435533'
  
(['kwin', 'Window Move Center', 'KWin', 'Move Window to the Center'],)

The equivalent qdbus command is:

$ qdbus org.kde.kglobalaccel /kglobalaccel org.kde.KGlobalAccel.action '268435533'

kwin
Window Move Center
KWin
Move Window to the Center

There are multiple CLI utilities that implement the D-Bus protocol:

  • As far as I can tell, the qdbus utility cannot accept array of integers as arguments: Cannot call method 'setShortcut' because type 'QDBusRawType::ai' is unknown to this tool.
  • The syntax of the dbus-send utility requires explicit notation for the D-Bus type system rather than the dense notation of gdbus, e.g. array:string:"kwin","Window Move Center","KWin","Move Window to the Center".
4 Likes

@frovo104

Indeed a will have quite an extensive write-up to complete when I actually get these commands working.

This post alone is going to be far more helpful than anything else I’ve been able to find on the web. Especially those context notes about types.

One piece that still seems to be missing is how to convert key names into that array of int that these methods want for some reason, which is not very human-friendly. Or to convert the int back into key names. I’ll keep looking into that.

I will let you know how it goes. Thanks for taking the time to post that comment.

Even with all that excellent info, it’s still a nightmare trying to figure out how to correctly form the commands. I’ve only figured out some things for gdbus so far. I ran into the same thing with qdbus apparently not liking the “ai” argument type, and can’t get dbus-send to accept the argument with the more verbose syntax. But finally got some gdbus commands to seem to work.

Unfortunately when I run them they seem to put the correct new shortcuts in place, but they do not activate correctly, leaving the Alt+Grave shortcut toggling between only the last two windows of an app, and with no visual dialog. The only way to fix this is to open the Task Switcher panel, change some other setting in a way that activates the “Apply” button, and apply the settings. The Task Switcher settings already shows the new shortcuts when I open it. They just don’t work quite right.

Using Kate to look at the kglobalshortcutsrc file before and after applying the fix, and running a diff, reveals no differences whatsoever. So either there’s something I still don’t understand about how to use the DBus commands, or I’m actually running up against some kind of bug.

I’ll have to stick to the kwriteconfig{5/6} until I have some sort of clue as to why these commands don’t ultimately activate the modified shortcuts correctly.

First I zero out the existing shortcuts to avoid reassignment conflicts, then I set them to what I want. I’ve tried both setShortcut and setShortcutKeys. The only difference seems to be the type each method wants to see for the keys.

gdbus call --session --dest org.kde.kglobalaccel --object-path /kglobalaccel \
    --method org.kde.KGlobalAccel.setShortcutKeys \
    "['kwin', 'Walk Through Windows', 'KWin', 'Walk Through Windows']" \
    "[([0, 0, 0, 0],)]" 4

gdbus call --session --dest org.kde.kglobalaccel --object-path /kglobalaccel \
    --method org.kde.KGlobalAccel.setShortcutKeys \
    "['kwin', 'Walk Through Windows Reverse', 'KWin', 'Walk Through Windows Reverse']" \
    "[([0, 0, 0, 0],)]" 4

gdbus call --session --dest org.kde.kglobalaccel --object-path /kglobalaccel \
    --method org.kde.KGlobalAccel.setShortcutKeys \
    "['kwin', 'Walk Through Windows Alternative', 'KWin', 'Walk Through Windows Alternative']" \
    "[([0, 0, 0, 0],)]" 4

gdbus call --session --dest org.kde.kglobalaccel --object-path /kglobalaccel \
    --method org.kde.KGlobalAccel.setShortcutKeys \
    "['kwin', 'Walk Through Windows Alternative Reverse', 'KWin', 'Walk Through Windows Alternative Reverse']" \
    "[([0, 0, 0, 0],)]" 4


gdbus call --session --dest org.kde.kglobalaccel --object-path /kglobalaccel \
    --method org.kde.KGlobalAccel.setShortcutKeys \
    "['kwin', 'Walk Through Windows', 'KWin', 'Walk Through Windows']" \
    "[([201326688, 0, 0, 0],)]" 4

gdbus call --session --dest org.kde.kglobalaccel --object-path /kglobalaccel \
    --method org.kde.KGlobalAccel.setShortcutKeys \
    "['kwin', 'Walk Through Windows Reverse', 'KWin', 'Walk Through Windows Reverse']" \
    "[([201326718, 0, 0, 0],)]" 4

gdbus call --session --dest org.kde.kglobalaccel --object-path /kglobalaccel \
    --method org.kde.KGlobalAccel.setShortcutKeys \
    "['kwin', 'Walk Through Windows Alternative', 'KWin', 'Walk Through Windows Alternative']" \
    "[([134217824, 0, 0, 0],)]" 4

gdbus call --session --dest org.kde.kglobalaccel --object-path /kglobalaccel \
    --method org.kde.KGlobalAccel.setShortcutKeys \
    "['kwin', 'Walk Through Windows Alternative Reverse', 'KWin', 'Walk Through Windows Alternative Reverse']" \
    "[([134217854, 0, 0, 0],)]" 4

It seems the setShortcut method is deprecated since KF 5.90, and kept in the build not to break the public D-Bus API. So, the setShortcutKeys method is more preferable.

It does that indeed. qdbus org.kde.KWin /KWin reconfigure doesn’t help, but the shortcut set via the D-Bus API functions (mostly) normally after restarting, or after the “Apply” workaround via the System Settings application, apparently.


The task switching actions have Alt-Tab and Shift-Alt-Tab as the default shortcuts, there is a pane dedicated to task switching in the System Settings application, and there are also explicitly defined alternative shortcuts for them to allow different task switching GUIs/effects (compact, icons, thumbnails, etc.) to be used, so these factors may be causing the complications with task switching shortcuts. Actions that don’t have default shortcuts or aren’t being used in any way in the current session may not require the restart or the “Apply” workaround. For example, the command below sets two shortcuts, which become effective immediately after the command, and the shortcuts are propagated to ~/.config/kglobalshortcutsrc as tab-delimited shortcuts in the first field after the equals sign:

gdbus call --session --dest org.kde.kglobalaccel --object-path /kglobalaccel \
  --method org.kde.KGlobalAccel.setShortcutKeys \
  "['kwin', 'Window Move Center', 'KWin', 'Move Window to the Center']" \
  "[([$KEYCODE_1, 0, 0, 0],), ([$KEYCODE_2, 0, 0, 0],)]" 4


So, the setShortcutKeys method in the D-Bus API works, but still using the kwriteconfig6 utility or modifying the configuration files manually look like the intended way of configuring Plasma.

2 Likes

It seems the setShortcut method is deprecated since KF 5.90

Ohhhh, that’s really good info.

The task switching actions have Alt-Tab and Shift-Alt-Tab as the default shortcuts

I am specifically trying to mess with the “in current app” shortcuts, which use the Grave key (Tilde without shift), above Tab. And trying to just move the default shortcuts for that from the “Main” tab to the “Alternative” tab, so that in-app switching can use the thumbnail grid UI while “app” switching (not native to Plasma but enforced by a KWin script called “Application Switcher” that groups “apps” together like macOS) continues to use “Large Icons”.

Thus, from my own perspective, bringing a sense of sanity to app switching in Plasma, similar to how I use it in macOS.

I did see some escaped tabs showing up in kglobalshortcutsrc at one point, but didn’t quite understand what was going on. So that’s how the “active” alternative shortcuts are delimited, and there can be four different active shortcuts, while the shortcut after the comma is the default shortcut that it would revert to? That kind of clears up some part of this, although I normally only want to set a single active shortcut.

The shortcuts for in-app switching in the “Alternative” tab are normally not set to anything by default (showing “None”). And I take the step of setting the same shortcuts in “Main” (well, all of them actually) to be “None”. Still, the result is that in-app switching ends up behaving like the broken task switching in Budgie, flipping between only two windows.

Until I go into the GUI panel and do the “Apply” thing. But all settings in there look absolutely correct before I change some setting and hit “Apply”.

So, the setShortcutKeys method in the D-Bus API works, but still using the kwriteconfig6 utility or modifying the configuration files manually look like the intended way of configuring Plasma.

Technically the D-Bus calls work, just like kwriteconfig6, but they aren’t working in the practical sense. It’s bizarre to me that Plasma devs have allowed it to be this complicated to set some shortcuts from a script without needing to log out.

I feel confident that these techniques probably work fine from within an actual Qt app, so maybe nobody is paying any attention to making sure the terminal commands work.

Ultimately there should be some way to do the equivalent of the “Apply” step from a script to fix things, but the usual “reconfigure” command, or variations targeted at different D-Bus addresses as a destination, is not doing the same thing as clicking that “Apply” button.

I hate to try to do things like restarting Plasmashell. That has caused problems in previous testing. Apps not launching anymore after the shell restart.

Well, something good has come from that example with multiple arrays of ints in one command. I seem to be able to disable and re-enable the modifier-only Meta shortcut attached to the app launcher, while leaving the secondary default shortcut of Alt+F1 in place and active. This is another thing I needed to figure out, since apparently the trick of putting “Meta=” with nothing after it in kwinrc stopped working when the modifier-only shortcuts were finally merged into the Shortcuts settings panel in Plasma 6.1.

No strange side effects seen in this case.

To disable the Meta shortcut:

gdbus call --session --dest org.kde.kglobalaccel \
--object-path /kglobalaccel \
--method org.kde.KGlobalAccel.setShortcutKeys \
"['plasmashell', 'activate application launcher', \
'plasmashell', 'Activate Application Launcher']" \
"[([0, 0, 0, 0],), ([150994992, 0, 0, 0],)]" 4

Returns:

([([0, 0, 0, 0],), ([150994992, 0, 0, 0],)],)

And to re-enable Meta:

gdbus call --session --dest org.kde.kglobalaccel \
--object-path /kglobalaccel \
--method org.kde.KGlobalAccel.setShortcutKeys \
"['plasmashell', 'activate application launcher', \
'plasmashell', 'Activate Application Launcher']" \
"[([16777250, 0, 0, 0],), ([150994992, 0, 0, 0],)]" 4

Returns:

([([16777250, 0, 0, 0],), ([150994992, 0, 0, 0],)],)

The ‘16777250’ represents the Meta key, and ‘150994992’ represents the Alt+F1 shortcut combo.

I can detect whether this is necessary by using the action method.

gdbus call --session --dest org.kde.kglobalaccel \
--object-path /kglobalaccel \
--method org.kde.KGlobalAccel.action 16777250

Returns this if the Meta key shortcut is active:

(['plasmashell', 'activate application launcher', 'plasmashell', 'Activate Application Launcher'],)

And this if the Meta key is not an active shortcut key:

(@as [],)

Since you have to push two different arrays for the two active shortcuts on the same action, I am now pretty confused about all the extra zeros that need to be in each array of integers. No idea what they represent.

It’s not clear to me yet if there is some sort of clue here about why my other attempts at changing shortcuts didn’t have good results.

good to hear there are still people using those

Arays of integers in those commands are key sequences, and gdbus denotes structs with parentheses (and requires another comma before the closing parenthesis). So, it’s a conventional (or root) key binding when the last 3 keycodes are 0, and a sequential (or prefixed) key binding when they are not. Some day Plasma will support modal key bindings, and won’t necessarily lack a good text editor either cough

When titles of terminal emulator windows are set appropriately by the CLI shell (or by the programs themselves), binding the Super key to the “Present Windows” desktop effect, and using the “Filter Windows” search bar on the top while viewing all open windows on a thumbnail grid allows a user to switch to another window very efficiently by just typing a few letters in the name of the program in the target window since the focus is already on the search bar when the Super key is pressed.

The main considerations for me while deciding on the key binding customizations are as follows:

  • The Super key should be the main modifier key used for OS key bindings since the other modifiers are commonly used by applications. And, whenever possible, key bindings shouldn’t use other modifier keys in addition to the Super key because pressing multiple modifier keys with the left hand isn’t as comfortable as pressing only the Super key.

  • Apart from opening the run dialog and the Present Windows (or Overview), and running custom commands via key bindings, the tasks that are most frequently performed on a desktop, in the decreasing order of frequency, are tiling windows left/right, switching to the next/previous window in the current workspace, switching to the left/right workspace, maximizing/minimizing/ centering windows, and moving windows to the left/right workspace.

  • The window switcher, which is referred to as the task switcher in the System Settings application, arranges window thumbnails horizontally, where it places a new thumbnail next to the previous one until it fills the row and starts another. So, the i/o keys, which are next to each other on the keyboard, are used to reflect the horizontal modality. There is no need to define navigation cluster bindings for switching between windows since arrows already work after the window switcher is activated by Alt-Tab using the left hand.

  • Similarly, the Pager widget on the left side of the panel shows the available workspaces, which are referred to as virtual desktops in the System Settings application, as horizontally placed rectangles when the panel height is set to 20, where the current workspace is indicated with a blue shade. And, the current workspace indicator moves left/right upon switching between workspaces. So, the ,/. keys, which are next to each other on the keyboard, are used to reflect the horizontal modality. The default navigation cluster bindings for switching between workspaces use the PgUp/PgDn keys, which are more suitable for a vertical modality, but since one of them isn’t more on the left or right of the other on the keyboard, their default bindings can also be used for a horizontal modality, as they are also commonly used so for switching between browser tabs. The same thing isn’t true for the n/p keys, which are commonly associated with the next/previous mnemonic, since n is more on the left and p is more on the right on the keyboard, and therefore they are incompatible with a left-to-right horizontal modality where n (“next”) is on the left but refers to the right. Note that the commands to switch between workspaces use both the left/right and up/down directions, although a vertical modality is more appropriate for the commands that move windows to different monitors since having a monitor physically placed above another may be required, but having a workspace above another is a preference.

  • I’ve been using the standard US layout for quite a while now, and standard 104/105 key keyboards. I don’t use the numpad, but the rest of the keyboard should be pretty standard. I typically define a homerow binding and a navigation cluster binding for a command so that both free and touch-typing stances will have options. I make only two modifications to the standard US layout by swapping the CapsLock and LeftCtrl, and using the RightAlt as another RightCtrl, which are regreattable but kind of unavoidable unless you have a spare pinky.

The rest is better handled by applications: switching between buffers of an editor, tabs of a browser, etc.

1 Like

I did find the QKeySequence in the code and was about to look it up. So it was pretty much what I was assuming, multiple combos or a combo and then keys in a sequence, which is why they are usually “0, 0, 0” for conventional shortcuts. Makes sense. I never really got into multi-combo sequences because it’s just too much to remember. But nice that they are supported by the infrastructure.

That treatise on logical task switching was excellent. I enjoyed that. Very well though out. I’m sure it works well for you.

I used Windows for over a decade during the 90s and early 2000s, so of course my understanding of task switching was just Alt+Tabbing through potentially a couple of dozen different individual windows. Usually when there were more than a few windows, clicking on the right window in the task bar was far more efficient. I didn’t really use keyboard shortcuts until I started using BeOS, which had based their keyboard shortcuts on macOS. So on a PC laptop, BeOS used the Alt key as the primary modifier.

Moving to Mac OS X after that was quite smooth, since the shortcuts were physically the same. Then I spent 20 years slowly building up common shortcuts as reflexes in muscle memory. Attempting to use Linux for anything productive was painful, because it uses the Windows-style task switching (between windows).

The app overviews in GNOME and now Plasma are quite nice, but just like in macOS I don’t usually find them very useful. I rarely used Exposé in macOS. For one thing, my eyes are not “fast”, and get overwhelmed by too much detail on the screen, and a lot of windows tend to start really looking the same, especially as they shrink. I also have a poor working memory, so if I had to remember the name of each window I wanted to switch to, even partially, I’d be far less efficient.

The task switching style I got used to in macOS is something that seems to aggravate an awful lot of folks who try to use macOS after coming from Windows or Linux, because it feels “constrictive” if you’re used to individual window switching. But once I started to finally work with it instead of against it, grouped-application task switching became a much simpler thing for me. Maybe not always as efficient as possible, but understandable, and requiring limited mental effort. Because all I’m doing when switching apps is looking at a unique icon. Not window contents or previews. Until I switch windows within one “app”. Where distinguishing between those windows tends to be much easier. Or there are just one, two, or three windows of the app open, so it’s easy to remember and get to the right one in that limited “corral”.

I like to think about it like a farmyard where each type of animal is herded into their own corral. If I want to see the horses, I go to the horse corral. If the horse I want to see isn’t next to the fence already, I call over the one I want with Alt+Grave. No big deal. It’s a very calming way of task switching, for me.

This can of course also work with multiple workspaces, but I spent a long time on macOS having no real need for more than one workspace with this “grouped” way of moving around between tasks. It was very disappointing coming to Linux and not having that task switching style available as an option.

I did eventually discover that GNOME can do this, and even better than macOS, if you have the “Switch applications” shortcut as the main task switching shortcut. It completely changes the task switcher dialog in GNOME, so that each “application” is represented by its icon, just like in macOS. Unfortunately most distros have the “Switch windows” shortcut as the main shortcut, so it took me a long time to realize there was an alternative.

So I was stuck in GNOME for a long time, partly because I like that style of task switching. Then Natalie Clarius put together a KWin script for me that mimics this in Plasma 5, and later I adapted the script to work with both Plasma 5 and 6. But the Plasma task switcher settings also have to be tweaked to make everything make sense when combined with the KWin script. Thus why I disable the in-app shortcuts on “Main” and enable them on the “Alternative” tab.

One of the main problems I still have is a bug with the Plasma task switcher continuing to use the “Main” tab box UI (large icons) when I don’t let go of the Alt key before moving from Alt+Tabbing to Alt+Graving, where it should use the “Alternative” tab box UI choice (thumbnail grid). That bug still hasn’t been addressed at all in Plasma 6.

Another one is this bug, where switching from Alt+Tabbing to Alt+Graving without letting go of the Alt key will unexpectedly switch to the application whose windows you’re Alt+Graving through.

https://bugs.kde.org/show_bug.cgi?id=454413

That doesn’t happen in GNOME, where you can Alt+Tab to the app icon, then Alt+Grave through its window thumbnails, and no switching happens until you finally release the Alt key. In this way, you can choose to bring only a single window of an app forward, rather than the entire app group. This is useful on occasion, but I can’t do it in Plasma.

In GNOME, you can even hit Escape while holding the Alt key and it won’t switch windows at all. Nice if you just want to remind yourself something about a window that is open in another “app”, but don’t actually want to switch to it right then. This is not the case in Plasma, even with the KWin script, which can’t stop the task switcher from immediately switching apps when changing the shortcut.

Anway, Plasma 6.1 is still more than good enough in combination with the KWin script that I’ve finally broken free of years of GNOME.

And I guess I should follow up on the talk about all the macOS shortcuts I have in muscle memory, because that’s an important part of this puzzle. Years ago I found Kinto.sh by Ben Reaves, and it worked so well that I contributed to it and then eventually created my own project that used its keymapper config as a base. I called my project Toshy. Just like Kinto, it does a great job at overlaying all kinds of general and app-specific shortcuts in Linux with non-destructive remaps that get Linux to react like macOS would when using an Apple keyboard on a Mac.

GitHub - RedBearAK/toshy: Keymapper config to make Linux work like a 'Tosh! (short URL https://toshy.app)

This plus the task switching fixes allows me to live in Linux with limited irritation, at least as far as keyboard shortcuts and task switching goes. But that makes up for a lot of other minor irritations.

One of the few things the keymapper config can’t fix is this issue with having dual visualization options in Plasma’s task switcher. I have a special option for the Toshy installer that tries to fix all that automatically. That’s going to require a log out until I can perfect the D-Bus calls without causing the in-app task switching bug.

The task switcher is buggier than I thought. Currently, it allows the task filter to be toggled between “All windows” and “Current application” with the shortcut keys while the Alt key remains depressed, but the visualization doesn’t change along with the filter, it remains stuck with whichever one of the main or alternative version was first used. Toggling the filter is achieved by using the “Only one window per application” option in one of the main or alternative action and not in the other. However, since thumbnails of windows of the current application aren’t displayed if the task switcher was started with large icons, the “Show selected window” option can be used instead to see the windows themselves instead of the thumbnails, which is not even a workaround, and also leaves rendering artifacts on some windows after the task switcher closes on my end. The bug prevents the visualization to adapt to the filter, or prevent launching a different task switcher seamlessly I guess.

However, I can say that in my experience, getting efficient with as many generic functionalities as possible by self organizing and breaking contrived habits helps with overcoming vendor lock-ins and using free software comfortably.

Competition and customization, especially and paradoxically in markets freely dominated by outnumbered competitors, used to be originality, but it’s the new world with robots and everything now I guess :thinking:

1 Like

I took the enums you linked to and made a Python script to translate between the encoded Plasma shortcut integers and shortcut strings like “Meta+Ctrl+Tilde”. A string argument of modifier names and a key name will produce the integer encoding, and vice versa.

Shortcut string encoded to integer:

./plasma_shortcuts_converter.py Alt+Ctrl+Meta

Converting string of keys to integer...

Detected special case: Multi-mod-only shortcut string.
One mod will be treated as non-mod "key" for integer value.
Pre-sorting for consistent integer conversion result...

String argument given:  Alt+Ctrl+Meta
Sorted Shortcut:        Meta+Ctrl+Alt

Full Mod Name(s):       MetaModifier, ControlModifier
Full Key Name:          Key_Alt

Encoded to Integer:     352321571

Gdbus a(ai) argument syntax: "([352321571, 0, 0, 0],)"

Integer decoded to shortcut string:

./plasma_shortcuts_converter.py 352321571

Converting integer to its component key(s)...

Integer argument given:     352321571

Extracted Mod(s) int:       335544320
     Control hex value:       0x4000000
        Meta hex value:       0x10000000
    Full Mod Name(s):       ControlModifier, MetaModifier

Extracted Key int value:    16777251
  Extracted Key hex value:    0x1000023
          Full Key Name:    Key_Alt

Normalized Shortcut Combo:  'Meta+Ctrl+Alt'

For the moment it’s available as part of another project:

It handles a number of quirks like not needing to use the literal key name AsciiTilde or AsciiCircum to get a match, and translates Grave to QuoteLeft. And mod-only shortcuts will produce the same integer encoding regardless of the order, by conforming to the way Plasma orders the modifiers in the Shortcuts panel:

Meta+Ctrl = 285212705
Ctrl+Meta = 285212705

Not that it matters, the different integer from the shortcut keys being in another order would still bring up the same action from a gdbus call to org.kde.KGlobalAccel.action. But it makes the output less confusing.

If the capitalization of a key name is not quite correct, a substring search will try to suggest the correct key name.

Overall, I tried to make it simple to use and clear in its output. There may be other tools out there to do the same thing, but I’m not aware of any. Maybe this will be useful to someone.

1 Like

or maybe just sh for a practical convenience utility that won’t be integrated to a larger system

#!/usr/bin/sh

# Name the keys arbitrarily in the file:
#   SUPER=0x10000000
#   ALT=0x08000000
#   K=0x4b
#   N3=0x33
#   ...
. /path/to/qtkeys.txt

case $1 in
  # Encode:
  #   $ qtkeycodec SUPER ALT K
  #   402653259
  *[^0-9]*)
    keys=''
    for k in $@; do
      keys=$keys+$k
    done
    echo $((keys))
    ;;

  # Decode:
  #   $ qtkeycodec 402653259
  #   SUPER+ALT+K
  *)
    keycode=$1
    keys=''

    [ $keycode -ge $((SUPER)) ] && { keys=SUPER; keycode=$((keycode-SUPER)); }
    [ $keycode -ge $((ALT)) ] && { keys=$keys+ALT; keycode=$((keycode-ALT)); }
    [ $keycode -ge $((CTRL)) ] && { keys=$keys+CTRL; keycode=$((keycode-CTRL)); }
    [ $keycode -ge $((SHIFT)) ] && { keys=$keys+SHIFT; keycode=$((keycode-SHIFT)); }

    while read k; do
      [ $((${k#*=})) -eq $((keycode)) ] && { keys=$keys+${k%=*}; echo $keys; break; }
    done < /path/to/qtkeys.txt
    ;;
esac
1 Like