chore: move kwinscript to its own dir

This commit is contained in:
Mikhail Zolotukhin 2021-11-01 19:09:12 +03:00
parent 89e30723e4
commit 3000934a96
55 changed files with 85 additions and 486 deletions

View File

@ -1,31 +0,0 @@
#!/usr/bin/env sh
# SPDX-FileCopyrightText: 2021 Mikhail Zolotukhin <mail@genda.life>
#
# SPDX-License-Identifier: MIT
set -e
# Make necessary directories
mkdir -p "${npm_package_config_build_dir:=build}/script/contents/code"
echo "Checking using TS Compiler..."
npx tsc --noEmit --incremental
echo "Bundling using esbuild..."
npx esbuild \
--bundle src/index.ts \
--outfile="$npm_package_config_build_dir/script/contents/code/index.mjs" \
--format=esm \
--platform=neutral
# Copy resources to the build directory with correct paths
cp -rv res/ui "$npm_package_config_build_dir/script/contents"
cp -rv res/config "$npm_package_config_build_dir/script/contents"
# Copy and update metadata
METADATA_FILE="$npm_package_config_build_dir/script/metadata.desktop"
cp -v res/metadata.desktop "$METADATA_FILE"
sed -i "s/\$VER/${npm_package_version:-1.0}/" "$METADATA_FILE"

View File

@ -1,21 +0,0 @@
#!/usr/bin/env sh
# SPDX-FileCopyrightText: 2021 Mikhail Zolotukhin <mail@genda.life>
#
# SPDX-License-Identifier: MIT
set -e
EXTRACT_DIR="${npm_package_config_build_dir:-build}/extracted-package"
# Make directory for extraction
mkdir -p "$EXTRACT_DIR"
# Extract built package
tar xf "${npm_package_config_build_dir:-build}/package/bismuth.tar.gz" --directory="$EXTRACT_DIR"
# Run installation script
cd "$EXTRACT_DIR"
./install.sh
cd - > /dev/null

View File

@ -1,70 +0,0 @@
#!/bin/sh
# SPDX-FileCopyrightText: 2018-2019 Eon S. Jeon <esjeon@hyunmu.am>
#
# SPDX-License-Identifier: MIT
#set -x
file_path="$1"
plugin_name="$2"
#
# Functions
#
_invoke() {
method="$1"
shift 1
dbus-send --session --print-reply=literal \
--dest="org.kde.KWin" \
"/Scripting" "org.kde.kwin.Scripting.${method}" \
"$@"
}
check_loaded() {
_invoke "isScriptLoaded" string:"${plugin_name}" \
| awk '{ print $2 }'
}
unload_script() {
_invoke "unloadScript" string:"${plugin_name}"
}
#
# Main
#
if [ "${file_path}" = "unload" ]; then
unload_script
[ "$(check_loaded)" = "false" ] && exit
echo "$(basename $0): Failed to unload script: ${plugin_name}" >&2
exit 1
fi
file_path="$(realpath "${file_path}")"
if [ ! -f "${file_path}" ]; then
echo "$(basename $0): File does not exist: ${file_path}" >&2
exit 1
fi
if [ "$(check_loaded)" != "false" ]; then
unload_script
fi
# randomized file_path
# (KWin doesn't reload files, and keep running old versions.)
file_path_random="${file_path}.$$.qml"
trap "{ rm -vf ${file_path_random}; }" EXIT
cp -v "${file_path}" "${file_path_random}"
# load script and run
_invoke "loadDeclarativeScript" string:"${file_path_random}" string:"${plugin_name}"
_invoke "start"
if [ "$(check_loaded)" = "false" ]; then
echo "$(basename $0): Failed to load script: ${file_path}, ${plugin_name}" >&2
exit 1
fi

View File

@ -1,40 +0,0 @@
#!/usr/bin/env sh
# SPDX-FileCopyrightText: 2021 Mikhail Zolotukhin <mail@genda.life>
#
# SPDX-License-Identifier: MIT
set -e
KWINPKG_NAME="bismuth.kwinscript"
FINAL_ARCHIVE_NAME="bismuth.tar.gz"
# Temporary change directory for archive tools
cd "./${npm_package_config_build_dir:-build}/script"
# Remove old packages
rm -f "$KWINPKG_NAME"
# Create new .kwinscript package
zip -qr "$KWINPKG_NAME" ./contents/ ./metadata.desktop
# Get back to the original directory
cd - > /dev/null
# Create subdir for final package
mkdir -p "./${npm_package_config_build_dir:-build}/package"
cd "./${npm_package_config_build_dir:-build}/package"
# Copy necessary files for package
cp -v "../script/$KWINPKG_NAME" "$KWINPKG_NAME"
cp -v "../../res/install.sh" install.sh
mkdir -p icons/ && cp -v "../../res/icons/bismuth.svg" icons/bismuth.svg
# Create installation archive for the end user
tar -czf "$FINAL_ARCHIVE_NAME" \
"$KWINPKG_NAME" \
install.sh \
icons/bismuth.svg
# Get back to the original directory
cd - > /dev/null

View File

@ -1,237 +0,0 @@
#!/usr/bin/env python3
# SPDX-FileCopyrightText: 2018-2019 Eon S. Jeon <esjeon@hyunmu.am>
#
# SPDX-License-Identifier: MIT
#
# * Requirements:
# - pyside2
# - dbus-python
#
import argparse
import sys
from PySide2.QtGui import QKeySequence
import dbus
# TODO: manually syncing key bindings? sucks!
# split this into a data file, which then can be translated into
# typescript code or included in other places.
BISMUTH_DEFAULT_BINDINGS = [
("Down/Next" , "j" ),
("Up/Prev" , "k" ),
("Left" , "h" ),
("Right" , "l" ),
("Move Down/Next", "shift+j"),
("Move Up/Prev" , "shift+k"),
("Move Left" , "shift+h"),
("Move Right" , "shift+l"),
("Grow Height" , "ctrl+j" ),
("Shrink Height" , "ctrl+k" ),
("Shrink Width" , "ctrl+h" ),
("Grow Width" , "ctrl+l" ),
("Increase" , "i" ),
("Decrease" , "d" ),
("Float" , "f" ),
("Float All" , "shift+f"),
("Cycle Layout" , "\\" ),
("Set master" , "return" ),
('Tile Layout' , 't'),
('Monocle Layout' , 'm'),
('Spread Layout' , None),
('Stair Layout' , None),
('Floating Layout', None),
]
NUMBER_SHIFT_MAP = ")!@#$%^&*()"
VERBOSE = True
def parse_arguments() -> argparse.Namespace:
# common arguments
parser = argparse.ArgumentParser(
description='A helper script for managing Krohnkite shortcuts')
parser.add_argument('--quiet', '-q', action='store_true',
help='Suppress output')
subparsers = parser.add_subparsers(dest="command",
help='Commands')
#
# register command
#
parser_register = subparsers.add_parser('register',
help='Register Krohnkite-related shortcuts')
parser_register.add_argument('--bind', '-b', action='append', dest='binds',
metavar='ACTION=KEY', type=str,
help='''Use a different key for specified action. The final result is MOD+KEY = ACTION.
This option can be specified multiple times.''')
parser_register.add_argument('--force', '-f', action='store_true',
help='Remove any conflicting shortcuts before registering new ones')
parser_register.add_argument('--modifier', '-m', default='meta', dest='modifier',
type=str,
help='A modifier key to use. Defaults to meta.')
#
# unregister command
#
parser_unregister = subparsers.add_parser('unregister',
help='''Remove all Krohnkite shortcuts from KWin.
This doesn't reset other key bindings changed by this script.''')
#
# register-desktops command
#
parser_register_desktops = subparsers.add_parser('register-desktops',
help='''Set virtual desktop shortcuts to MOD+NUMBER, which is a recommended setup.''')
parser_register_desktops.add_argument('--force', '-f', action='store_true',
help='Remove any conflicting shortcuts before registering new ones')
parser_register_desktops.add_argument('--modifier', '-m', default='meta', dest='modifier', type=str,
help='''A modifier key to use. Defaults to meta.''')
if len(sys.argv) == 1:
parser.print_help(sys.stderr)
sys.exit(1)
return parser.parse_args()
def parse_kvpair(s: str):
'''Parses simple "A=B"-style expression'''
return tuple(s.split("=", 2))
def get_keycode(keycomb: str):
keyseq = QKeySequence.fromString(keycomb)
return keyseq[0]
def is_key_valid(keycomb: str) -> bool:
# NOTE: this might be internal detail that should not be accessed.
return get_keycode(keycomb) != 0x1FFFFFF
def register_shortcut(action_id, keycomb, force=False):
if force is True:
unregister_colliding_shortcut(keycomb)
keycode = get_keycode(keycomb)
if VERBOSE:
print("register [{2:<14}] to '{1}/{0}'.".format(action_id[1], action_id[2], keycomb))
kglobalaccel.setForeignShortcut(action_id, [keycode])
def register_bismuth_shortcut(action: str, keycomb_full: str):
action = "Krohnkite: " + action
keycode = get_keycode(keycomb_full)
if VERBOSE: print("register [{1:<14}] to '{0}'.".format(action, keycomb_full))
kglobalaccel.setForeignShortcut(["kwin", action, "KWin", ""], [keycode])
def unregister_bismuth_shortcut(action: str):
action = "Krohnkite: " + action
if VERBOSE: print("unregister '{}'.".format(action))
kglobalaccel.setForeignShortcut(["kwin", action, "KWin", ""], [])
def is_shortcut_colliding(keycomb_full: str) -> bool:
action_id = kglobalaccel.action(get_keycode(keycomb_full))
return not not action_id
def unregister_colliding_shortcut(keycomb_full: str):
action_id = kglobalaccel.action(get_keycode(keycomb_full))
if len(action_id) > 0:
if VERBOSE: print("unregister [{:<14}] bound to '{}'".format(keycomb_full, action_id[1]))
kglobalaccel.setForeignShortcut(action_id, [])
def unregister_all_bismuth_shortcuts():
names = [
str(name) for name
in kwin_component.shortcutNames()
if name.startswith('Krohnkite:')
]
for name in names:
kglobalaccel.unregister("kwin", name)
def is_shortcut_already_bound(keycomb_full: str) -> bool:
'''Check if the given key combination is already bound to something. '''
action_id = kglobalaccel.action(get_keycode(keycomb_full))
return not not action_id
def register_desktop_shortcuts(modifier, force):
for i in range(1,10):
action = "Switch to Desktop {}".format(i)
keycomb = "{}+{}".format(modifier, i)
register_shortcut(["kwin", action, "KWin", action], keycomb, force=force)
action = "Window to Desktop {}".format(i)
keycomb = "{}+{}".format(modifier, NUMBER_SHIFT_MAP[i])
register_shortcut(["kwin", action, "KWin", action], keycomb, force=force)
def main():
config = parse_arguments()
global VERBOSE
VERBOSE = False if config.quiet else True
if config.command == 'register':
binds = dict(BISMUTH_DEFAULT_BINDINGS)
if config.binds is not None:
# parse ACTION=KEY parameter
custom_binds = (parse_kvpair(b) for b in config.binds)
# read-through custom binds
for action, keycomb in custom_binds:
if action not in binds:
print("invalid action '{}'",format(action))
sys.exit(1)
elif keycomb.lower() == "none":
binds[action] = None
elif is_key_valid(config.modifier + '+' + keycomb):
binds[action] = keycomb
else:
print("invalid key '{}' for action '{}'".format(action, keycomb))
sys.exit(1)
if config.force is True:
for keycomb in binds.values():
if keycomb is not None:
unregister_colliding_shortcut(config.modifier + '+' + keycomb)
# register shortcuts
for action, keycomb in binds.items():
if keycomb is None:
unregister_bismuth_shortcut(action)
else:
keycomb_full = config.modifier + '+' + keycomb
if is_shortcut_colliding(keycomb):
print("skipping {} due to shortcut collision...".format(keycomb_full))
else:
register_bismuth_shortcut(action, keycomb_full)
elif config.command == 'unregister':
unregister_all_bismuth_shortcuts()
elif config.command == 'register-desktops':
register_desktop_shortcuts(config.modifier, config.force)
else:
pass
session_bus = dbus.SessionBus()
kglobalaccel_obj = session_bus.get_object('org.kde.kglobalaccel', '/kglobalaccel')
kglobalaccel = dbus.Interface(kglobalaccel_obj, dbus_interface='org.kde.KGlobalAccel')
kwin_component_obj = session_bus.get_object('org.kde.kglobalaccel', '/component/kwin')
kwin_component = dbus.Interface(kwin_component_obj, dbus_interface='org.kde.kglobalaccel.Component')
if __name__ == '__main__':
main()

View File

@ -1,16 +0,0 @@
#!/usr/bin/env sh
# SPDX-FileCopyrightText: 2021 Mikhail Zolotukhin <mail@genda.life>
# SPDX-FileCopyrightText: 2018-2019 Eon S. Jeon <esjeon@hyunmu.am>
#
# SPDX-License-Identifier: MIT
set -e
# Load script to KWin
bin/load-script.sh "${npm_package_config_build_dir:=build}/contents/ui/main.qml" \
"${npm_package_name:=Bismuth}-test"
# Remove unnecessary files
find "$npm_package_config_build_dir" \
'(' -name "*.qmlc" -o -name "*.jsc" ')' -delete

View File

@ -1,11 +0,0 @@
#!/usr/bin/env sh
# SPDX-FileCopyrightText: 2021 Mikhail Zolotukhin <mail@genda.life>
# SPDX-FileCopyrightText: 2018-2019 Eon S. Jeon <esjeon@hyunmu.am>
#
# SPDX-License-Identifier: MIT
set -e
# Unload script from KWin
bin/load-script.sh "unload" "${npm_package_name:-Bismuth}-test"

View File

@ -1,43 +0,0 @@
#!/bin/bash
# SPDX-FileCopyrightText: 2018-2019 Eon S. Jeon <esjeon@hyunmu.am>
#
# SPDX-License-Identifier: MIT
set -mx
display=${1:-1}
edition=${2:-user}
case "$edition" in
user|user-lts|dev-stable|dev-unstable);;
*)
echo "invalid edition: $edition" >&2
exit 1
;;
esac
projdir=$(realpath "$(dirname "$0")/..")
ctname="bismuth-$edition"
Xephyr \
-dpi 96 \
-screen 1366x768 \
:"$display" &
ctid=$(docker ps -aq --filter "name=$ctname")
if [[ -z "$ctid" ]]; then
docker run \
--name "$ctname" \
-e DISPLAY=":$display" \
-v "$projdir":"/mnt" \
-v "/tmp/.X11-unix":"/tmp/.X11-unix" \
"kdeneon/plasma":"$edition" &
# HACK: stop CPU hoggig bluetooth service invocation. This is a bug.
(sleep 1; docker exec -u root "$ctname" rm '/usr/share/dbus-1/services/org.bluez.obex.service') &
else
docker start "$ctname"
fi
fg Xephyr
wait

View File

@ -3,13 +3,6 @@
"version": "1.1.0",
"description": "A dynamic tiling extension for KWin",
"private": true,
"directories": {
"build": "build",
"test": "test"
},
"config": {
"build_dir": "build"
},
"devDependencies": {
"@types/jest": "^27.0.1",
"@typescript-eslint/eslint-plugin": "^4.29.3",
@ -33,16 +26,14 @@
"typescript": "^4.4.3"
},
"scripts": {
"clean": "bin/clean.sh",
"build": "bin/build.sh",
"clean": "scripts/clean.sh",
"build": "scripts/build.sh",
"prestart": "npm run build",
"start": "bin/start.sh",
"stop": "bin/stop.sh",
"prepackage": "npm run build",
"package": "bin/package.sh",
"package": "scripts/package.sh",
"prescript-install": "npm run package",
"script-install": "bin/install.sh",
"script-uninstall": "bin/uninstall.sh",
"script-install": "scripts/install.sh",
"script-uninstall": "scripts/uninstall.sh",
"preinstall-and-restart-kwin-x11": "npm run script-install",
"install-and-restart-kwin-x11": "kwin_x11 --replace",
"postinstall-and-restart-kwin-x11": "bash -ic \"kwin_x11 --replace & disown\"",

37
scripts/build.sh Executable file
View File

@ -0,0 +1,37 @@
#!/usr/bin/env sh
# SPDX-FileCopyrightText: 2021 Mikhail Zolotukhin <mail@genda.life>
# SPDX-License-Identifier: MIT
set -e
echo "🏗️ Building KWin Script..."
KWINSCRIPT_SOURCEDIR="src/kwinscript"
KWINSCRIPT_BUILDDIR="build/kwinscript"
# Make necessary directories
mkdir -p "$KWINSCRIPT_BUILDDIR/contents/code"
echo "👮 Checking using TS Compiler..."
npx tsc --noEmit --incremental
echo "🎁 Bundling using esbuild..."
npx esbuild \
--bundle "$KWINSCRIPT_SOURCEDIR/index.ts" \
--outfile="$KWINSCRIPT_BUILDDIR/contents/code/index.mjs" \
--format=esm \
--platform=neutral
# Copy resources to the build directory with correct paths
echo "📑 Preparing UI and metadata files..."
cp -r "$KWINSCRIPT_SOURCEDIR/res/ui" "$KWINSCRIPT_BUILDDIR/contents"
cp -r "$KWINSCRIPT_SOURCEDIR/res/config" "$KWINSCRIPT_BUILDDIR/contents"
# Copy and update metadata
METADATA_FILE="$KWINSCRIPT_BUILDDIR/metadata.desktop"
cp "$KWINSCRIPT_SOURCEDIR/res/metadata.desktop" "$METADATA_FILE"
sed -i "s/\$VER/${npm_package_version:-1.0}/" "$METADATA_FILE"

View File

@ -1,13 +1,12 @@
#!/usr/bin/env sh
# SPDX-FileCopyrightText: 2021 Mikhail Zolotukhin <mail@genda.life>
#
# SPDX-License-Identifier: MIT
set -e
# Remove build directory and package-lock
rm -vrf "${npm_package_config_build_dir:=build}"
rm -vrf "build"
rm -vf package-lock.json
rm -vrf node_modules/

11
scripts/install.sh Executable file
View File

@ -0,0 +1,11 @@
#!/usr/bin/env sh
# SPDX-FileCopyrightText: 2021 Mikhail Zolotukhin <mail@genda.life>
# SPDX-License-Identifier: MIT
set -e
echo "📦 Installing the KWin Script..."
KWINPKG_FILE="bismuth.kwinscript"
plasmapkg2 -u "$KWINPKG_FILE" > /dev/null || plasmapkg2 -i "$KWINPKG_FILE" > /dev/null

27
scripts/package.sh Executable file
View File

@ -0,0 +1,27 @@
#!/usr/bin/env sh
# SPDX-FileCopyrightText: 2021 Mikhail Zolotukhin <mail@genda.life>
# SPDX-License-Identifier: MIT
set -e
echo "Packaging KWin Script..."
KWINPKG_NAME="bismuth.kwinscript"
FINAL_ARCHIVE_NAME="bismuth.tar.gz"
# Temporary change directory for archive tools
cd "./build/kwinscript"
# Remove old packages
rm -f "$KWINPKG_NAME"
# Create new .kwinscript package
zip -qr "$KWINPKG_NAME" ./contents/ ./metadata.desktop
# Get back to the original directory
cd - > /dev/null
# TODO: Packaging for KCM

View File

@ -2,9 +2,12 @@
# SPDX-FileCopyrightText: 2021 Mikhail Zolotukhin <mail@genda.life>
# SPDX-FileCopyrightText: 2018-2019 Eon S. Jeon <esjeon@hyunmu.am>
#
# SPDX-License-Identifier: MIT
set -e
echo "🔥 Uninstalling KWin Script..."
plasmapkg2 -t kwinscript -r "${npm_package_name:-Bismuth}"
# TODO: Uninstalling KCM

View File

Before

Width:  |  Height:  |  Size: 754 B

After

Width:  |  Height:  |  Size: 754 B

0
res/install.sh → src/kwinscript/res/install.sh Executable file → Normal file
View File