summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJulien <contact@julienpro.com>2023-04-15 15:54:51 +0200
committerJulien <contact@julienpro.com>2023-04-15 16:02:38 +0200
commitb90fc746b6a4229b0d6e91594f6c646d708dbe1c (patch)
tree74ae00893addc056f0ecee5f5e10a871797f510b
parent7fd3b73946c2da348c022a91004da130a8d365fb (diff)
First version
-rw-r--r--.gitignore1
-rw-r--r--README.md245
-rw-r--r--callbacks.py46
-rw-r--r--config.ini12
-rw-r--r--db.py1877
-rwxr-xr-xlidecli.py150
-rwxr-xr-xtools/kde-shortcut-diff.py42
7 files changed, 2373 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..c18dd8d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+__pycache__/
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..f78a68c
--- /dev/null
+++ b/README.md
@@ -0,0 +1,245 @@
+# LideCLI - The Linux Desktop CLI
+
+![image](https://user-images.githubusercontent.com/121452426/231865865-d56446e6-6095-4238-9fcd-091bd15a9c59.png)
+
+Lidecli (Linux Desktop CLI) is an unified command-line tool to interact with X, Wayland, Window Managers and Desktop Environments.
+Currently, interacting with your Desktop Environment/Window Manager is not "so easy". Depending of the DE you use, you need to mix the following techniques/tools:
+
+- you need to code (for instance, with AwesomeWM, you need to do everything with LUA)
+- you need to interact with the API provided by your DE, usually with ugly D-BUS calls
+- you need to play with tools like wmctrl, xdotool, etc. working only for X and not for Wayland.
+
+The goal of Lidecli is to provide a library of commands to interact with the DE/WM you use. This library is searchable and each command is tagged, so you'll know what is the underlying tool(s) the command is using.
+
+## Usage
+
+The code is a Python 3 script. You just need to clone this repository. Some examples of usage:
+
+**Show the list of all supported commands**
+```
+./lidecli.py -l
+```
+
+**Show the list of all commands compatible/using a tool (search by tag)**
+```
+./lidecli.py -t wmctrl -l
+```
+
+**Show the list of all commands for X but not for KDE**
+```
+./lidecli.py -t x11 -n kde -l
+```
+
+**Show the help of a command**
+```
+./lidecli.py x-win-id-maximize -h
+```
+
+**Launch a command**
+```
+./lidecli.py x-win-name-maximize Firefox
+```
+
+## Command currently implemented
+
+As I am currently using KDE Plasma (very great except its command-line API) on X, the current database contains around 170 ready-to-use commands, mainly using **KDE API with qdbus**, and **wmctrl**, **xprop** or **xwininfo**.
+
+### KDE status
+
+Currently, almost all KDE commands available through `qdbus org.kde.kglobalaccel /component/kwin org.kde.kglobalaccel.Component.invokeShortcut` have been implemented. To get a precise status, there is a script in the `tools` folder that outputs the list of commands remaining to be implemented.
+
+## Contributing
+
+It's particularly easy to contribute and to add your custom commands, whatever your current dekstop environment.
+
+### Defining a command
+
+The database is a simple Python file called `db.py`. This file contains all defined commands. Each command has the following properties:
+
+- Its calling name (eg. `kde-move-id-desktop-up`)
+- A description for the end-user
+- A list of `forwarded_arguments` (arguments needed to run the command)
+- A potential list of `forwarded_options`
+- The command to be launched
+- The DEs and versions where it has been tested successfully ("versions_working")
+- The DEs and versions where it has been tested unsuccessfully ("versions_not_working")
+- A list of tags
+
+**Simple example of a command**
+
+```
+{
+ "name": "x-list-windows-wmctrl",
+ "description": "Get Windows list with wmctrl",
+ "versions_working": [("x11", "all")],
+ "versions_not_working": [],
+ "command": "wmctrl -l",
+ "tags": ["x11", "windows", "wmctrl"]
+},
+
+```
+This is self-explanatory.
+
+### Basic conventions
+
+With Lidecli, we try to comply with some basic conventions.
+
+### Command name conventions
+
+- The name of the command starts by the main subsystem involved. Here it's X, so the command starts by `x-`. On Wayland it would be `wayland-`. For a simple KDE d-bus call, it would just start by "kde-".
+- The second word of the command name is usually the action performed: list, toggle, get, focus, set, etc.
+- The next one or two words is the subject of the action: windows, desktops, screens, monitors, etc.
+- You'll find many commands containing "win-id" or "win-name", like `x-win-id-maximize` and `x-win-name-maximize`. The first one allows you to maximize a window specified by it's ID, the second one by its name (eg `./lidecli.py x-win-name-maximize Firefox`).
+
+### Tags conventions
+
+Tags are very useful to find a command, so they must be set properly. Usually, the first ones are the main subsystem involved (x11, wayland, kde...). Then, there is a tag defining the subject of the action: windows, desktops, screens, etc.
+Finally, there are one or two tags to define the underlying tools needed to run the command: wmctrl, qdbus, etc.
+
+If a command supports a JSON output, you should add "json" at the end of the tag list.
+
+### Support of several commands
+
+In the simple WMCtrl example above, you'll notice that the command executed effectively is specified in the "command" key. Lidecli supports also a "commands" key, where you can define a list of commands to execute. See the detailed example below.
+
+### Forwarded options
+
+You can "forward" options to the executed command. Let's take the example below.
+
+```
+{
+ "name": "kde-monitors",
+ "description": "Get the list of the monitors and their configuration",
+ "command": "kscreen-doctor",
+ "versions_working": [("kde", "5.27.3")],
+ "versions_not_working": [],
+ "forwarded_options": [
+ { "param": "-o", "description": "", "default": True },
+ { "param": "-j", "description": "Get the output as JSON" }
+ ],
+ "tags": ["x11", "wayland", "kde", "monitors", "json"],
+}
+
+```
+
+Here, when you launch `./lidecli.py kde-monitors`, the executed command will be `kscreen-doctor -o`.
+However, if you launch `./lidecli.py kde-monistors -j`, the executed command will be `kscreen-doctor -j`.
+
+### Forwarded arguments
+
+Arguments can be forwarded to the command launched. More importantly, they can be positionned where you want, using `#1#` for the first argument, `#2#` for the second argument, etc.
+
+Example:
+
+```
+{
+ "name": "x-get-winid",
+ "description": "From the class name of a window, output the Win ID",
+ "forwarded_arguments": [
+ { "name": "Label", "description": "Part of the class name to look for"}
+ ],
+ "versions_working": [("x11", "all")],
+ "versions_not_working": [],
+ "command": "wmctrl -l |grep -v wmctrl | grep -v x-get-winid | grep '#1#' | cut -d ' ' -f1",
+ "tags": ["x11", "windows", "wmctrl"]
+},
+
+```
+
+Here, the command is doing a grep on the output of `wmctrl -l`, with a `grep '#1#'` where `#1#` will be replaced by the first argument passed to the `x-get-winid` command.
+If you launch `./lidecli.py x-get-winid Firefox`, then the command executed will be: `wmctrl -l |grep -v wmctrl | grep -v x-get-winid | grep 'Firefox' | cut -d ' ' -f1`
+
+If you just to put the argument(s) at the end of the command line, it's not mandatory to add `#1#`. By default, all needed arguments mentionned will be forwarded to the end of the command launched.
+
+### Custom Python callbacks
+
+Lidecli supports custom Python callbacks, mainly to parse the output of a command.
+
+Let's take the example below:
+```
+ {
+ "name": "x-is-win-maximized",
+ "description": "Check if a Window is maximized",
+ "forwarded_arguments": [
+ { "name": "WinID", "description": "The windows ID"}
+ ],
+ "versions_working": [("x11", "all")],
+ "versions_not_working": [],
+ "command": "xprop -id",
+ "callback": {
+ "function": "xprop_parser",
+ "output_key": "win_maximized"
+ },
+ "tags": ["x11", "windows", "xprop"]
+ },
+```
+
+Here, the command `xprop -id <WinID>` will be launched. Then its output will be send to the `xprop_parser` function of the file `callbacks.py`.
+
+A callback should return a dictionary of values. The result returned to the end-user will be the `output_key` of this dictionary.
+
+In this case, we just need to write one parser function for xprop, and then returns the relevant key in our various commands.
+
+### Saving temporarily the results of commands
+
+It may be useful to save temporarily the result of a command. It's particularly useful to save the current focused Window to be restored later, so when you launch the command through a keybinding, your focused window is not lost.
+
+Lidecli has the option "-s" which save the result of the command in a "register" for later use. There are 9 registers (1 to 9), the last one being reserved for the commands defined in `db.py`. The registers 1 to 8 can be used freely by any other scripts.
+
+Let's say you need a bash script to move all your windows without losing the focus of the current one.
+
+```
+#!/bin/bash
+
+# Get the ID of the focused Window and store it in the Register n°1
+./lidecli.py -s 1 x-current-focus-id
+
+## Do your stuff
+
+# Restore the focus by calling x-focus-id with the content of the register n°1
+./lidecli.py x-focus-id #s1#
+
+```
+
+You don't have to use Bash/environment variables. You can if you want, but registers might be easier.
+
+The temporary data is saved in the file `config.ini`. A later version of Lidecli may also use this config file to store other configuration variables.
+
+### Calling Lidecli from Lidecli
+
+In the `db.py` file, you'll notice that sometimes we use "./self" in the commands.
+./self just call Lidecli itself, to call another command. More details below.
+
+### Detailed example of a command launching multiple commands
+
+```
+{
+ "name": "kde-move-win-id-desktop-up",
+ "description": "Move a window specified by its ID one desktop up",
+ "forwarded_arguments": [
+ { "name": "WinID", "description": "The WinID to move"},
+ ],
+ "commands": [
+ "./self -s 9 x-current-focus-id",
+ "wmctrl -i -a #1#",
+ "qdbus org.kde.kglobalaccel /component/kwin org.kde.kglobalaccel.Component.invokeShortcut 'Window One Desktop Up'",
+ "./self x-focus-id #s9#",
+ ],
+ "versions_working": [("kde", "5.27.3")],
+ "versions_not_working": [],
+ "tags": ["x11", "kde", "desktops", "wmctrl", "qdbus" ]
+}
+```
+
+In this example, you'll notice several things.
+- First, there are several commands launched when kde-move-win-id-desktop-up is invoked. Let's detail each step.
+- ./self is used to call Lidecli itself, to get the currently focused window and store it in the reserved register.
+- After the `qdbus` call, the focus is restored using `./self x-focus-id #s9#`
+- The tags contain "x11" and "kde", but not "wayland". Indeed, this command contains several calls to `wmctrl` which would only work on X, not on Wayland, despite the `qdbus` command should work on both.
+
+## Feedbacks
+
+This tool is not perfect, but it may be a nice start to build a full library of CLI commands to interact with the various Desktop Environments.
+Your contributions would be welcomed!
+
+[!["Buy Me A Coffee"](https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png)](https://www.buymeacoffee.com/juienpro)
diff --git a/callbacks.py b/callbacks.py
new file mode 100644
index 0000000..70ea1da
--- /dev/null
+++ b/callbacks.py
@@ -0,0 +1,46 @@
+import re
+
+def xprop_parser(input):
+ result = {
+ "win_maximized": 0,
+ "win_maximized_horizontal": 0,
+ "win_maximized_vertical": 0,
+ "win_hidden": 0,
+ "win_minimized": 0,
+ "win_modal": 0,
+ "win_sticky": 0,
+ "win_shaded": 0,
+ "win_fullscreen": 0,
+ "win_above": 0,
+ "win_below": 0
+ }
+ match = re.search(r'_NET_WM_STATE\(ATOM\) = (.*)$', input, re.MULTILINE)
+ if match:
+ values = match.group(1).split(", ")
+ for v in values:
+ if v == '_NET_WM_STATE_MAXIMIZED_HORZ':
+ result['win_maximized_horizontal'] = 1
+ if v == '_NET_WM_STATE_MAXIMIZED_VERT':
+ result['win_maximized_vertical'] = 1
+ if v == '_NET_WM_STATE_MODAL':
+ result['win_modal'] = 1
+ if v == '_NET_WM_STATE_STICKY':
+ result['win_sticky'] = 1
+ if v == '_NET_WM_STATE_SHADED':
+ result['win_shaded'] = 1
+ if v == '_NET_WM_STATE_HIDDEN':
+ result['win_hidden'] = 1
+ if v == '_NET_WM_STATE_FULLSCREEN':
+ result['win_fullscreen'] = 1
+ if v == '_NET_WM_STATE_BELOW':
+ result['win_below'] = 1
+ if v == '_NET_WM_STATE_ABOVE':
+ result['win_above'] = 1
+
+ if result['win_maximized_horizontal'] == 1 and result['win_maximized_vertical'] == 1:
+ result['win_maximized'] = 1
+ if result['win_hidden'] == 1:
+ result['win_minimized'] = 1
+
+ return result
+
diff --git a/config.ini b/config.ini
new file mode 100644
index 0000000..90cea23
--- /dev/null
+++ b/config.ini
@@ -0,0 +1,12 @@
+[TMP_STORAGE]
+tmp_result_1 =
+tmp_result_2 =
+tmp_result_3 =
+tmp_result_4 =
+tmp_result_5 =
+tmp_result_6 =
+tmp_result_7 =
+tmp_result_8 =
+tmp_result_9 = 0x0540002d
+
+
diff --git a/db.py b/db.py
new file mode 100644
index 0000000..d405892
--- /dev/null
+++ b/db.py
@@ -0,0 +1,1877 @@
+def commands():
+ return [
+ {
+ "name": "kde-list-shortcuts",
+ "description": "Get all supported KWin configurable shortcuts",
+ "command": "qdbus org.kde.kglobalaccel /component/kwin org.kde.kglobalaccel.Component.shortcutNames",
+ "versions_working": [("kde", "5.27.3")],
+ "versions_not_working": [],
+ "tags": [ "x11", "wayland", "kde", "windows", "qdbus"]
+ },
+ {
+ "name": "kde-monitors",
+ "description": "Get the list of the monitors and their configuration",
+ "command": "kscreen-doctor",
+ "versions_working": [("kde", "5.27.3")],
+ "versions_not_working": [],
+ "forwarded_options": [
+ { "param": "-o", "description": "", "default": True },
+ { "param": "-j", "description": "Get the output as JSON" }
+ ],
+ "tags": ["x11", "wayland", "kde", "monitors", "json"],
+ },
+ {
+ "name": "kde-invoke-shortcuts",
+ "description": "Invoke a KWin conigurable shortcut",
+ "command": "qdbus org.kde.kglobalaccel /component/kwin org.kde.kglobalaccel.Component.invokeShortcut",
+ "forwarded_arguments": [
+ { "name": "Shortcut", "description": "The shortcut to execute"}
+ ],
+ "versions_working": [("kde", "5.27.3")],
+ "versions_not_working": [],
+ "tags": ["x11", "wayland", "kde", "windows", "qdbus" ]
+ },
+ {
+ "name": "sway-list-windows",
+ "description": "Get Windows list with Sway on Wayland",
+ "command": "swaymsg -t get_tree",
+ "versions_working": [],
+ "versions_not_working": [],
+ "tags": ["wayland", "sway", "windows"]
+ },
+ {
+ "name": "x-list-windows-wmctrl",
+ "description": "Get Windows list with wmctrl",
+ "versions_working": [("x11", "all")],
+ "versions_not_working": [],
+ "command": "wmctrl -l",
+ "tags": ["x11", "windows", "wmctrl"]
+ },
+ {
+ "name": "x-list-windows-xwininfo",
+ "description": "Get Windows list with xwininfo",
+ "versions_working": [("x11", "all")],
+ "versions_not_working": [],
+ "command": "xwininfo -root -tree | grep '\"[^\"]*\"'",
+ "tags": ["x11", "windows", "xwininfo"]
+ },
+ {
+ "name": "x-get-winid",
+ "description": "From the class name of a window, output the Win ID",
+ "forwarded_arguments": [
+ { "name": "Label", "description": "Part of the class name to look for"}
+ ],
+ "versions_working": [("x11", "all")],
+ "versions_not_working": [],
+ "command": "wmctrl -l |grep -v wmctrl | grep -v x-get-winid | grep '#1#' | cut -d ' ' -f1",
+ "tags": ["x11", "windows", "wmctrl"]
+ },
+ {
+ "name": "x-is-win-maximized",
+ "description": "Check if a Window is maximized",
+ "forwarded_arguments": [
+ { "name": "WinID", "description": "The windows ID"}
+ ],
+ "versions_working": [("x11", "all")],
+ "versions_not_working": [],
+ "command": "xprop -id #1#",
+ "callback": {
+ "function": "xprop_parser",
+ "output_key": "win_maximized"
+ },
+ "tags": ["x11", "windows", "xprop"]
+ },
+ {
+ "name": "x-is-win-maximized-h",
+ "description": "Check if a Window is maximized horizontally",
+ "forwarded_arguments": [
+ { "name": "WinID", "description": "The windows ID"}
+ ],
+ "versions_working": [("x11", "all")],
+ "versions_not_working": [],
+ "command": "xprop -id #1#",
+ "callback": {
+ "function": "xprop_parser",
+ "output_key": "win_maximized_horizontal"
+ },
+ "tags": ["x11", "windows", "xprop"]
+ },
+ {
+ "name": "x-is-win-maximized-v",
+ "description": "Check if a Window is maximized vertically",
+ "forwarded_arguments": [
+ { "name": "WinID", "description": "The windows ID"}
+ ],
+ "versions_working": [("x11", "all")],
+ "versions_not_working": [],
+ "command": "xprop -id #1#",
+ "callback": {
+ "function": "xprop_parser",
+ "output_key": "win_maximized_vertical"
+ },
+ "tags": ["x11", "windows", "xprop"]
+ },
+ {
+ "name": "x-is-win-minimized",
+ "description": "Check if a Window is minimized",
+ "forwarded_arguments": [
+ { "name": "WinID", "description": "The windows ID"}
+ ],
+ "versions_working": [("x11", "all")],
+ "versions_not_working": [],
+ "command": "xprop -id #1#",
+ "callback": {
+ "function": "xprop_parser",
+ "output_key": "win_minimized"
+ },
+ "tags": ["x11", "windows", "xprop"]
+ },
+ {
+ "name": "x-is-win-modal",
+ "description": "Check if a Window is modal",
+ "forwarded_arguments": [
+ { "name": "WinID", "description": "The windows ID"}
+ ],
+ "versions_working": [("x11", "all")],
+ "versions_not_working": [],
+ "command": "xprop -id #1#",
+ "callback": {
+ "function": "xprop_parser",
+ "output_key": "win_modal"
+ },
+ "tags": ["x11", "windows", "xprop"]
+ },
+ {
+ "name": "x-is-win-sticky",
+ "description": "Check if a Window is sticky",
+ "forwarded_arguments": [
+ { "name": "WinID", "description": "The windows ID"}
+ ],
+ "versions_working": [("x11", "all")],
+ "versions_not_working": [],
+ "command": "xprop -id #1#",
+ "callback": {
+ "function": "xprop_parser",
+ "output_key": "win_sticky"
+ },
+ "tags": ["x11", "windows", "xprop"]
+ },
+ {
+ "name": "x-is-win-shaded",
+ "description": "Check if a Window is shaded",
+ "forwarded_arguments": [
+ { "name": "WinID", "description": "The windows ID"}
+ ],
+ "versions_working": [("x11", "all")],
+ "versions_not_working": [],
+ "command": "xprop -id #1#",
+ "callback": {
+ "function": "xprop_parser",
+ "output_key": "win_shaded"
+ },
+ "tags": ["x11", "windows", "xprop"]
+ },
+ {
+ "name": "x-is-win-fullscreen",
+ "description": "Check if a Window is fullscreen",
+ "forwarded_arguments": [
+ { "name": "WinID", "description": "The windows ID"}
+ ],
+ "versions_working": [("x11", "all")],
+ "versions_not_working": [],
+ "command": "xprop -id #1#",
+ "callback": {
+ "function": "xprop_parser",
+ "output_key": "win_fullscreen"
+ },
+ "tags": ["x11", "windows", "xprop"]
+ },
+ {
+ "name": "x-is-win-above",
+ "description": "Check if a Window is above others",
+ "forwarded_arguments": [
+ { "name": "WinID", "description": "The windows ID"}
+ ],
+ "versions_working": [("x11", "all")],
+ "versions_not_working": [],
+ "command": "xprop -id #1#",
+ "callback": {
+ "function": "xprop_parser",
+ "output_key": "win_above"
+ },
+ "tags": ["x11", "windows", "xprop"]
+ },
+ {
+ "name": "x-is-win-below",
+ "description": "Check if a Window is below others",
+ "forwarded_arguments": [
+ { "name": "WinID", "description": "The windows ID"}
+ ],
+ "versions_working": [("x11", "all")],
+ "versions_not_working": [],
+ "command": "xprop -id #1#",
+ "callback": {
+ "function": "xprop_parser",
+ "output_key": "win_below"
+ },
+ "tags": ["x11", "windows", "xprop"]
+ },
+ {
+ "name": "x-focus-id",
+ "description": "Give focus to a Window (by ID)",
+ "forwarded_arguments": [
+ { "name": "WinID", "description": "The Window ID"}
+ ],
+ "command": "wmctrl -i -a #1#",
+ "versions_working": [("x11", "all")],
+ "versions_not_working": [],
+ "tags": ["x11", "windows", "wmctrl" ]
+ },
+ {
+ "name": "x-focus-name",
+ "description": "Give focus to a Window (by name)",
+ "forwarded_arguments": [
+ { "name": "WinName", "description": "The substring to match the Window Name"}
+ ],
+ "command": "wmctrl -a",
+ "versions_working": [("x11", "all")],
+ "versions_not_working": [],
+ "tags": ["x11", "windows", "wmctrl" ]
+ },
+ {
+ "name": "x-current-focus-id",
+ "description": "Get the WinID having the focus",
+ "command": "xprop -root _NET_ACTIVE_WINDOW |cut -d ' ' -f5",
+ "versions_working": [("x11", "all")],
+ "versions_not_working": [],
+ "tags": ["x11", "windows", "xprop" ]
+ },
+ {
+ "name": "x-set-win-id-fullscreen",
+ "description": "Set a Window specified by its WinID to full screen",
+ "forwarded_arguments": [
+ { "name": "WinID", "description": "The Window ID"}
+ ],
+ "command": "wmctrl -i #1# -b add,fullscreen",
+ "versions_working": [("x11", "all")],
+ "versions_not_working": [],
+ "tags": ["x11", "windows", "wmctrl" ]
+ },
+ {
+ "name": "x-set-win-name-fullscreen",
+ "description": "Set a Window specified by its name to full screen",
+ "forwarded_arguments": [
+ { "name": "WinName", "description": "The substring to match the Window name"}
+ ],
+ "command": "wmctrl #1# -b add,fullscreen",
+ "versions_working": [("x11", "all")],
+ "versions_not_working": [],
+ "tags": ["x11", "windows", "wmctrl" ]
+ },
+ {
+ "name": "x-unset-win-id-fullscreen",
+ "description": "Unset fullscreen for a Window specified by its WinID",
+ "forwarded_arguments": [
+ { "name": "WinID", "description": "The Window ID"}
+ ],
+ "command": "wmctrl -i #1# -b remove,fullscreen",
+ "versions_working": [("x11", "all")],
+ "versions_not_working": [],
+ "tags": ["x11", "windows", "wmctrl" ]
+ },
+ {
+ "name": "x-unset-win-name-fullscreen",
+ "description": "Unset fullscreen for a Window specified by its name",
+ "forwarded_arguments": [
+ { "name": "WinName", "description": "The substring to match the Window name"}
+ ],
+ "command": "wmctrl #1# -b remove,fullscreen",
+ "versions_working": [("x11", "all")],
+ "versions_not_working": [],
+ "tags": ["x11", "windows", "wmctrl" ]
+ },
+ {
+ "name": "kde-toggle-win-fullscreen",
+ "description": "Toogle fullscreen for the current Window",
+ "command": "qdbus org.kde.kglobalaccel /component/kwin org.kde.kglobalaccel.Component.invokeShortcut 'Window Fullscreen'",
+ "versions_working": [("kde", "5.27.3")],
+ "versions_not_working": [],
+ "tags": ["x11", "wayland", "kde", "windows", "qdbus" ]
+ },
+ {
+ "name": "kde-close-win",
+ "description": "Close the current window",
+ "command": "qdbus org.kde.kglobalaccel /component/kwin org.kde.kglobalaccel.Component.invokeShortcut 'Window Close'",
+ "versions_working": [("kde", "5.27.3")],
+ "versions_not_working": [],
+ "tags": ["x11", "wayland", "kde", "windows", "qdbus" ]
+ },
+ {
+ "name": "kde-kill-win",
+ "description": "Kill the current window",
+ "command": "qdbus org.kde.kglobalaccel /component/kwin org.kde.kglobalaccel.Component.invokeShortcut 'Kill Window'",
+ "versions_working": [("kde", "5.27.3")],
+ "versions_not_working": [],
+ "tags": ["x11", "wayland", "kde", "windows", "qdbus" ]
+ },
+ {
+ "name": "x-kill-win-id",
+ "description": "Kill a window specified by its WinID",
+ "forwarded_arguments": [
+ { "name": "WinID", "description": "The WinID to kill"}
+ ],
+ "command": "wmctrl -ic #1#",
+ "versions_working": [("x11", "all")],
+ "versions_not_working": [],
+ "tags": ["x11", "windows", "wmctrl" ]
+ },
+ {
+ "name": "x-kill-win-name",
+ "description": "Kill a window specified by its name",
+ "forwarded_arguments": [
+ { "name": "WinName", "description": "The part of the window name to kill"}
+ ],
+ "command": "wmctrl -c #1#",
+ "versions_working": [("x11", "all")],
+ "versions_not_working": [],
+ "tags": ["x11", "windows", "wmctrl" ]
+ },
+
+ {
+ "name": "kde-switch-to-desktop",
+ "description": "Switch to a particular desktop",
+ "forwarded_arguments": [
+ { "name": "DesktopIndex", "description": "The index of the desktop, starting from 1"}
+ ],
+ "command": "qdbus org.kde.kglobalaccel /component/kwin org.kde.kglobalaccel.Component.invokeShortcut 'Switch to Desktop #1#'",
+ "versions_working": [("kde", "5.27.3")],
+ "versions_not_working": [],
+ "tags": ["x11", "wayland", "kde", "desktops", "qdbus" ]
+ },
+ {
+ "name": "kde-move-current-win-to-desktop",
+ "description": "Move a window to a particular desktop",
+ "forwarded_arguments": [
+ { "name": "DesktopIndex", "description": "The index of the desktop, starting from 1"}
+ ],
+ "command": "qdbus org.kde.kglobalaccel /component/kwin org.kde.kglobalaccel.Component.invokeShortcut 'Window to Desktop #1#'",
+ "versions_working": [("kde", "5.27.3")],
+ "versions_not_working": [],
+ "tags": ["x11", "wayland", "kde", "desktops", "qdbus" ]
+ },
+ {
+ "name": "kde-move-win-id-to-desktop",
+ "description": "Move a window specified by ID to a particular desktop",
+ "forwarded_arguments": [
+ { "name": "WinID", "description": "The WinID to move"},
+ { "name": "DesktopIndex", "description": "The index of the desktop, starting from 1"}
+ ],
+ "commands": [
+ "./self -s 9 x-current-focus-id",
+ "wmctrl -i -a #1#",
+ "qdbus org.kde.kglobalaccel /component/kwin org.kde.kglobalaccel.Component.invokeShortcut 'Window to Desktop #2#'",
+ "./self x-focus-id #s9#",
+ ],
+ "versions_working": [("kde", "5.27.3")],
+ "versions_not_working": [],
+ "tags": ["x11", "kde", "windows", "desktops", "qdbus", "wmctrl" ]
+ },
+ {
+ "name": "kde-move-win-name-to-desktop",
+ "description": "Move a window specified by name to a particular desktop",
+ "forwarded_arguments": [
+ { "name": "WinName", "description": "A part of the name of the window to move"},
+ { "name": "DesktopIndex", "description": "The index of the desktop, starting from 1"}
+ ],
+ "commands": [
+ "./self -s 9 x-current-focus-id",
+ "wmctrl -a #1#'",
+ "qdbus org.kde.kglobalaccel /component/kwin org.kde.kglobalaccel.Component.invokeShortcut 'Window to Desktop #2#'",
+ "./self x-focus-id #s9#",
+ ],
+ "versions_working": [("kde", "5.27.3")],
+ "versions_not_working": [],
+ "tags": ["x11", "kde", "windows", "desktops", "qdbus", "wmctrl" ]
+ },
+ {
+ "name": "kde-switch-to-screen",
+ "description": "Switch to a particular screen",
+ "forwarded_arguments": [
+ { "name": "Number", "description": "The screen number to switch to"},
+ ],
+ "command": "qdbus org.kde.kglobalaccel /component/kwin org.kde.kglobalaccel.Component.invokeShortcut 'Switch to Screen #1#'",
+ "versions_working": [("kde", "5.27.3")],
+ "versions_not_working": [],
+ "tags": ["x11", "wayland", "kde", "screens", "qdbus" ]
+ },
+ {
+ "name": "kde-switch-to-previous-screen",
+ "description": "Switch to the previous screen",
+ "command": "qdbus org.kde.kglobalaccel /component/kwin org.kde.kglobalaccel.Component.invokeShortcut 'Switch to Previous Screen'",
+ "versions_working": [("kde", "5.27.3")],
+ "versions_not_working": [],
+ "tags": ["x11", "wayland", "kde", "screens", "qdbus" ]
+ },
+ {
+ "name": "kde-switch-to-next-screen",
+ "description": "Switch to the next screen",
+ "command": "qdbus org.kde.kglobalaccel /component/kwin org.kde.kglobalaccel.Component.invokeShortcut 'Switch to Next Screen'",
+ "versions_working": [("kde", "5.27.3")],
+ "versions_not_working": [],
+ "tags": ["x11", "wayland", "kde", "screens", "qdbus" ]
+ },
+ {
+ "name": "kde-switch-to-right-screen",
+ "description": "Switch to the screen at the right",
+ "command": "qdbus org.kde.kglobalaccel /component/kwin org.kde.kglobalaccel.Component.invokeShortcut 'Switch to Screen to the Right'",
+ "versions_working": [("kde", "5.27.3")],
+ "versions_not_working": [],
+ "tags": ["x11", "wayland", "kde", "screens", "qdbus" ]
+ },
+ {
+ "name": "kde-switch-to-left-screen",
+ "description": "Switch to the screen at the left",
+ "command": "qdbus org.kde.kglobalaccel /component/kwin org.kde.kglobalaccel.Component.invokeShortcut 'Switch to Screen to the Left'",
+ "versions_working": [("kde", "5.27.3")],
+ "versions_not_working": [],
+ "tags": ["x11", "wayland", "kde", "screens", "qdbus" ]
+ },
+ {
+ "name": "kde-switch-to-screen-below",
+ "description": "Switch to the screen below",
+ "command": "qdbus org.kde.kglobalaccel /component/kwin org.kde.kglobalaccel.Component.invokeShortcut 'Switch to Screen Below'",
+ "versions_working": [("kde", "5.27.3")],
+ "versions_not_working": [],
+ "tags": ["x11", "wayland", "kde", "screens", "qdbus" ]
+ },
+ {
+ "name": "kde-switch-to-screen-above",
+ "description": "Switch to the screen above",
+ "command": "qdbus org.kde.kglobalaccel /component/kwin org.kde.kglobalaccel.Component.invokeShortcut 'Switch to Screen Above'",
+ "versions_working": [("kde", "5.27.3")],
+ "versions_not_working": [],
+ "tags": ["x11", "wayland", "kde", "screens", "qdbus" ]
+ },
+ {
+ "name": "kde-toggle-win-decorate",
+ "description": "Toggle the decoration of the current Window",
+ "command": "qdbus org.kde.kglobalaccel /component/kwin org.kde.kglobalaccel.Component.invokeShortcut 'Window No Border'",
+ "versions_working": [("kde", "5.27.3")],
+ "versions_not_working": [],
+ "tags": ["x11", "wayland", "kde", "windows", "qdbus" ]
+ },
+ {
+ "name": "kde-toggle-win-id-decorate",
+ "description": "Toggle the decoration of a window specified by its ID",
+ "forwarded_arguments": [
+ { "name": "WinID", "description": "The WinID to decorate/undecorate"},
+ ],
+ "commands": [
+ "./self -s 9 x-current-focus-id",
+ "wmctrl -i -a #1#",
+ "qdbus org.kde.kglobalaccel /component/kwin org.kde.kglobalaccel.Component.invokeShortcut 'Window No Border'",
+ "./self x-focus-id #s9#",
+ ],
+ "versions_working": [("kde", "5.27.3")],
+ "versions_not_working": [],
+ "tags": ["x11", "kde", "windows", "qdbus", "wmctrl" ]
+ },
+ {
+ "name": "kde-toggle-win-name-decorate",
+ "description": "Toggle the decoration of a window specified by its name",
+ "forwarded_arguments": [
+ { "name": "WinName", "description": "The Win name to decorate/undecorate"},
+ ],
+ "commands": [
+ "./self -s 9 x-current-focus-id",
+ "wmctrl -a #1#",
+ "qdbus org.kde.kglobalaccel /component/kwin org.kde.kglobalaccel.Component.invokeShortcut 'Window No Border'",
+ "./self x-focus-id #s9#",
+ ],
+ "versions_working": [("kde", "5.27.3")],
+ "versions_not_working": [],
+ "tags": ["x11", "kde", "windows", "qdbus", "wmctrl" ]
+ },
+
+ {
+ "name": "kde-move-current-win-to-screen",
+ "description": "Move a window to a particular screen",
+ "forwarded_arguments": [
+ { "name": "screen_index", "description": "The index of the screen, starting from 0"}
+ ],
+ "command": "qdbus org.kde.kglobalaccel /component/kwin org.kde.kglobalaccel.Component.invokeShortcut 'Window to Screen #1#'",
+ "versions_working": [("kde", "5.27.3")],
+ "versions_not_working": [],
+ "tags": ["x11", "wayland", "kde", "screens", "qdbus" ]
+ },
+ {
+ "name": "kde-move-win-id-to-screen",
+ "description": "Move a window specified by ID to a particular screen",
+ "forwarded_arguments": [
+ { "name": "WinID", "description": "The WinID to move"},
+ { "name": "ScreenIndex", "description": "The index of the desktop, starting from 0"}
+ ],
+ "commands": [
+ "./self -s 9 x-current-focus-id",
+ "wmctrl -i -a #1#",
+ "qdbus org.kde.kglobalaccel /component/kwin org.kde.kglobalaccel.Component.invokeShortcut 'Window to Screen #2#'",
+ "./self x-focus-id #s9#",
+ ],
+ "versions_working": [("kde", "5.27.3")],
+ "versions_not_working": [],
+ "tags": ["x11", "kde", "screens", "windows", "qdbus", "wmctrl" ]
+ },
+ {
+ "name": "kde-move-win-name-to-screen",
+ "description": "Move a window specified by name to a particular screen",
+ "forwarded_arguments": [
+ { "name": "WinName", "description": "A part of the name of the window to move"},
+ { "name": "ScreenIndex", "description": "The index of the screen, starting from 0"}
+ ],
+ "commands": [
+ "./self -s 9 x-current-focus-id",
+ "wmctrl -a #1#'",
+ "qdbus org.kde.kglobalaccel /component/kwin org.kde.kglobalaccel.Component.invokeShortcut 'Window to Screen #2#'",
+ "./self x-focus-id #s9#",
+ ],
+ "versions_working": [("kde", "5.27.3")],
+ "versions_not_working": [],
+ "tags": ["x11", "kde", "screens", "windows", "qdbus", "wmctrl" ]
+ },
+ {
+ "name": "kde-move-win-to-all-desktop",
+ "description": "Move the current window to all desktops",
+ "command": "qdbus org.kde.kglobalaccel /component/kwin org.kde.kglobalaccel.Component.invokeShortcut 'Window On All Desktops'",
+ "versions_working": [("kde", "5.27.3")],
+ "versions_not_working": [],
+ "tags": ["x11", "wayland", "kde", "w