dotcli: Enable shortcuts to be discovered by diff.
This commit is contained in:
1
.config/dot/.claude/scheduled_tasks.lock
Normal file
1
.config/dot/.claude/scheduled_tasks.lock
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"sessionId":"d1732179-27b7-49fb-82af-6669b783a444","pid":45537,"procStart":"7266197","acquiredAt":1783288905666}
|
||||||
102
.config/dot/.claude/tasks/0010-kde-shortcuts-diff-broadscan.md
Normal file
102
.config/dot/.claude/tasks/0010-kde-shortcuts-diff-broadscan.md
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
---
|
||||||
|
blocked-by: [0005-kde-shortcuts-mechanism, 0009-kde-shortcut-completion]
|
||||||
|
---
|
||||||
|
|
||||||
|
## What to build
|
||||||
|
|
||||||
|
`dot kde diff`'s broad-scan (the pass that reports *undeclared* drift, not
|
||||||
|
just already-declared entries) currently only walks schema-backed
|
||||||
|
identifiers via `iter_schema_identifiers`. Shortcuts are treated the same
|
||||||
|
as freeform in `cmd_diff` -- checked only when already present in the
|
||||||
|
manifest -- per the code comment at the top of that loop. That comment is
|
||||||
|
overstated for shortcuts: unlike freeform, which genuinely has no
|
||||||
|
enumeration source, shortcuts *are* enumerable via `kglobalaccel`'s
|
||||||
|
`allMainComponents`/`allActionsForComponent`, and `iter_shortcut_identifiers`
|
||||||
|
(added in 0009 for tab-completion) already walks exactly that.
|
||||||
|
|
||||||
|
Add a second broad-scan pass in `cmd_diff`, after the existing schema-backed
|
||||||
|
one, over `sorted(set(iter_shortcut_identifiers()))`: for each identifier,
|
||||||
|
compare `shortcutKeys` against `defaultShortcutKeys` (the same live/default
|
||||||
|
read already used for declared shortcuts), and tag `declared`/`undeclared`
|
||||||
|
exactly like the schema loop. Remove the shortcuts branch from the
|
||||||
|
manifest-only loop below it (now redundant), leaving that loop for freeform
|
||||||
|
only, since freeform is the only mechanism that still can't be enumerated.
|
||||||
|
|
||||||
|
Tolerate two failure modes without aborting the whole command:
|
||||||
|
- The enumeration call itself (`allMainComponents`) failing (no live
|
||||||
|
session, no `busctl`) -- print one diagnostic to stderr and skip the
|
||||||
|
shortcuts block entirely, same as any other reported problem in `diff`.
|
||||||
|
- An individual action failing to resolve (`_resolve_shortcut_action_id`
|
||||||
|
raising because its owning app hasn't registered with kglobalaccel this
|
||||||
|
session) -- print that one identifier's error to stderr and continue,
|
||||||
|
matching the schema loop's existing per-identifier tolerance.
|
||||||
|
|
||||||
|
Update `DIFF_USAGE` to reflect that shortcuts now participate in broad-scan
|
||||||
|
alongside schema-backed settings, leaving only freeform as declared-only.
|
||||||
|
|
||||||
|
## Acceptance criteria
|
||||||
|
|
||||||
|
- [x] `dot kde diff` reports undeclared shortcut drift (a shortcut changed
|
||||||
|
from its packaged default but never `dot kde save`d) without requiring
|
||||||
|
it to be in the manifest first
|
||||||
|
- [x] Already-declared shortcut drift is still reported, tagged `declared`,
|
||||||
|
with no duplicate line from the old manifest-only loop
|
||||||
|
- [x] A shortcut belonging to an app that hasn't registered with kglobalaccel
|
||||||
|
this session produces one stderr diagnostic for that identifier and
|
||||||
|
does not stop the rest of the scan (schema block, other shortcuts,
|
||||||
|
freeform block) from completing
|
||||||
|
- [x] If the `allMainComponents` enumeration itself fails (no `busctl`, no
|
||||||
|
live session), `diff` prints one diagnostic, skips the shortcuts block,
|
||||||
|
and still completes the schema and freeform passes, exiting 0
|
||||||
|
- [x] Freeform remains declared-only (unchanged) -- only its loop comment and
|
||||||
|
the removed shortcuts branch change
|
||||||
|
- [x] `DIFF_USAGE` text updated to describe shortcuts as broad-scanned
|
||||||
|
- [x] Verified manually against the real session (consistent with the
|
||||||
|
shortcuts mechanism's existing test carve-out, 0005/0009) -- no new
|
||||||
|
automated tests
|
||||||
|
- [x] Full existing test suite still passes unchanged
|
||||||
|
|
||||||
|
## Implementation Notes
|
||||||
|
|
||||||
|
- `cmd_diff` (`commands/kde/kde.py`) gained a second broad-scan pass between
|
||||||
|
the existing schema-backed loop and the manifest-only loop: it walks
|
||||||
|
`sorted(set(iter_shortcut_identifiers()))` (the same enumeration
|
||||||
|
`cmd_complete` already uses), compares `shortcutKeys` against
|
||||||
|
`defaultShortcutKeys` per identifier, and tags `declared`/`undeclared`
|
||||||
|
exactly like the schema loop.
|
||||||
|
- The manifest-only loop below it lost its `shortcuts` branch entirely
|
||||||
|
(`resolve_mechanism` returning `"shortcuts"` now just falls through
|
||||||
|
`if mechanism != "freeform": continue`), since the new broad-scan pass
|
||||||
|
already reports every declared shortcut mismatch -- keeping the old branch
|
||||||
|
would have double-printed them.
|
||||||
|
- Two failure modes, handled at different granularity: `iter_shortcut_identifiers()`
|
||||||
|
itself is wrapped in `try/except (RuntimeError, OSError)` -- a failure there
|
||||||
|
(no live session, missing `busctl`) prints one diagnostic and skips the
|
||||||
|
whole shortcuts block, letting the schema and freeform passes still run.
|
||||||
|
Inside the per-identifier loop, `read_shortcut_value` raising `RuntimeError`
|
||||||
|
(an app that hasn't registered with kglobalaccel this session yet) prints
|
||||||
|
one diagnostic for that identifier and continues, matching the schema
|
||||||
|
loop's existing per-identifier tolerance.
|
||||||
|
- Real-world validation on this machine: manually ran the same enumeration in
|
||||||
|
a throwaway script before implementing, confirming 29 of 278 registered
|
||||||
|
shortcuts differed from default (the Meta+1-9 desktop-switch remap,
|
||||||
|
Meta+Shift+1-9 window-to-desktop binds, and Meta+A/Meta+Shift+A activity
|
||||||
|
switching) -- all 29 were `dot kde save`d into the manifest in the same
|
||||||
|
session as a prerequisite for testing this cleanly. After implementing,
|
||||||
|
`dot kde diff` reported all 30 shortcuts (29 plus the pre-existing
|
||||||
|
`ksmserver.Lock Session`) as `declared` with correct default values, and
|
||||||
|
~34 unrelated `RuntimeError`s for apps not launched this session (Konsole,
|
||||||
|
Spectacle, Dolphin, etc.) printed to stderr without aborting the scan.
|
||||||
|
Removing one entry (`kwin.Switch to Desktop 1`) from the manifest and
|
||||||
|
re-running confirmed it flips to `undeclared` with the same live/default
|
||||||
|
values, then restoring the manifest flipped it back to `declared` --
|
||||||
|
confirms both tags work and the manifest was left untouched by `diff`
|
||||||
|
itself (read-only, as documented).
|
||||||
|
- Full test suite re-run after the change: 101/101 pass, unchanged from
|
||||||
|
before this task. No automated tests added for the new pass itself, per
|
||||||
|
the shortcuts mechanism's existing carve-out (0005's Implementation Notes:
|
||||||
|
a live `kglobalaccel` D-Bus session isn't practically substitutable without
|
||||||
|
disproportionate mock infrastructure) -- the existing tests already
|
||||||
|
exercise `dot kde diff` against the real live session and continued to
|
||||||
|
pass with the new pass active, incidentally covering that it doesn't break
|
||||||
|
anything even though it isn't asserting on the new pass's own output.
|
||||||
BIN
.config/dot/commands/kde/__pycache__/kde.cpython-314.pyc
Normal file
BIN
.config/dot/commands/kde/__pycache__/kde.cpython-314.pyc
Normal file
Binary file not shown.
@@ -38,23 +38,85 @@ APPLY_USAGE = """usage: dot kde apply
|
|||||||
DIFF_USAGE = """usage: dot kde diff
|
DIFF_USAGE = """usage: dot kde diff
|
||||||
|
|
||||||
Scans every schema-backed setting reachable through the kcfg mapping
|
Scans every schema-backed setting reachable through the kcfg mapping
|
||||||
table and reports each one whose live value differs from its
|
table, and every shortcut registered with kglobalaccel, reporting each
|
||||||
schema-declared default, tagged declared (present in the manifest)
|
one whose live value differs from its default, tagged declared
|
||||||
or undeclared. Also reports already-declared freeform and shortcut
|
(present in the manifest) or undeclared. Also reports already-declared
|
||||||
settings whose live value differs from their default (neither has a
|
freeform settings whose live value differs from their default (no
|
||||||
schema/mapping table to broad-scan, so both are only checked when
|
schema to broad-scan, so it's only checked when already declared).
|
||||||
already declared). Read-only -- never writes the manifest or the
|
Read-only -- never writes the manifest or the live system.
|
||||||
live system.
|
|
||||||
help show this message"""
|
help show this message"""
|
||||||
|
|
||||||
Setting = namedtuple("Setting", ["file", "group", "key"])
|
Setting = namedtuple("Setting", ["file", "group", "key"])
|
||||||
|
|
||||||
|
|
||||||
def parse_identifier(identifier):
|
def _split_on_known_prefix(rest, candidates):
|
||||||
parts = identifier.split(".", 2)
|
matches = [c for c in candidates if rest == c or rest.startswith(c + ".")]
|
||||||
if len(parts) != 3:
|
if not matches:
|
||||||
|
return None
|
||||||
|
|
||||||
|
prefix = max(matches, key=len)
|
||||||
|
remainder = rest[len(prefix):].lstrip(".")
|
||||||
|
if not remainder:
|
||||||
|
return None
|
||||||
|
return prefix, remainder
|
||||||
|
|
||||||
|
|
||||||
|
def _known_schema_groups(file, kcfg_map):
|
||||||
|
groups = set()
|
||||||
|
for path in kcfg_map.get(file, []):
|
||||||
|
root = _parse_kcfg(path)
|
||||||
|
if root is None:
|
||||||
|
continue
|
||||||
|
for group_elem in root.iter(f"{KCFG_NS}group"):
|
||||||
|
name = group_elem.get("name")
|
||||||
|
if name:
|
||||||
|
groups.add(name)
|
||||||
|
return groups
|
||||||
|
|
||||||
|
|
||||||
|
def _split_schema_group_key(file, rest, kcfg_map):
|
||||||
|
match = _split_on_known_prefix(rest, _known_schema_groups(file, kcfg_map))
|
||||||
|
if match is not None:
|
||||||
|
return match
|
||||||
|
|
||||||
|
# No schema group matches -- freeform. Its group is never known to contain
|
||||||
|
# a dot (there's no schema to have told us otherwise), so the boundary is
|
||||||
|
# just the first remaining dot.
|
||||||
|
group, _, key = rest.partition(".")
|
||||||
|
if not key:
|
||||||
|
raise ValueError(f"invalid identifier {file}.{rest!r} (expected file.group.key)")
|
||||||
|
return group, key
|
||||||
|
|
||||||
|
|
||||||
|
def _split_shortcut_group_key(rest):
|
||||||
|
(components,) = _kglobalaccel_call("allMainComponents", None)
|
||||||
|
match = _split_on_known_prefix(rest, [component[0] for component in components])
|
||||||
|
if match is None:
|
||||||
|
raise RuntimeError(
|
||||||
|
f"no live kglobalaccel component matches {rest!r} "
|
||||||
|
"(the owning application may need to run once to register its shortcuts with kglobalaccel)"
|
||||||
|
)
|
||||||
|
return match
|
||||||
|
|
||||||
|
|
||||||
|
# Only the file segment is unambiguous (rc file names never contain a dot).
|
||||||
|
# The group/key boundary can't be found by counting dots -- both KConfig group
|
||||||
|
# names (e.g. "org.kde.kdecoration2") and kglobalaccel componentUnique names
|
||||||
|
# (e.g. "org.kde.dolphin.desktop") routinely contain their own dots -- so it's
|
||||||
|
# resolved against known-good data instead: the live kglobalaccel component
|
||||||
|
# list for shortcuts, the kcfg schema's declared group names for everything
|
||||||
|
# else (falling back to freeform's first-dot split when no schema matches).
|
||||||
|
def parse_identifier(identifier, kcfg_map):
|
||||||
|
file, sep, rest = identifier.partition(".")
|
||||||
|
if not sep or not rest:
|
||||||
raise ValueError(f"invalid identifier {identifier!r} (expected file.group.key)")
|
raise ValueError(f"invalid identifier {identifier!r} (expected file.group.key)")
|
||||||
return Setting(*parts)
|
|
||||||
|
if file == "kglobalshortcutsrc":
|
||||||
|
group, key = _split_shortcut_group_key(rest)
|
||||||
|
else:
|
||||||
|
group, key = _split_schema_group_key(file, rest, kcfg_map)
|
||||||
|
|
||||||
|
return Setting(file, group, key)
|
||||||
|
|
||||||
|
|
||||||
def load_manifest(path):
|
def load_manifest(path):
|
||||||
@@ -137,7 +199,7 @@ def iter_schema_identifiers(kcfg_map):
|
|||||||
for entry in group_elem.findall(f"{KCFG_NS}entry"):
|
for entry in group_elem.findall(f"{KCFG_NS}entry"):
|
||||||
key = entry.get("key") or entry.get("name")
|
key = entry.get("key") or entry.get("name")
|
||||||
if key:
|
if key:
|
||||||
yield f"{rcfile}.{group}.{key}"
|
yield Setting(rcfile, group, key)
|
||||||
|
|
||||||
|
|
||||||
def resolve_mechanism(setting, kcfg_map):
|
def resolve_mechanism(setting, kcfg_map):
|
||||||
@@ -233,7 +295,7 @@ def iter_shortcut_identifiers():
|
|||||||
(components,) = _kglobalaccel_call("allMainComponents", None)
|
(components,) = _kglobalaccel_call("allMainComponents", None)
|
||||||
for component in components:
|
for component in components:
|
||||||
for action in _actions_for_component(component[0]):
|
for action in _actions_for_component(component[0]):
|
||||||
yield f"kglobalshortcutsrc.{action[0]}.{action[1]}"
|
yield Setting("kglobalshortcutsrc", action[0], action[1])
|
||||||
|
|
||||||
|
|
||||||
def _resolve_shortcut_action_id(component_unique, action_unique):
|
def _resolve_shortcut_action_id(component_unique, action_unique):
|
||||||
@@ -279,7 +341,7 @@ def write_shortcut_value(component_unique, action_unique, value):
|
|||||||
|
|
||||||
|
|
||||||
def save_one(identifier, kcfg_map):
|
def save_one(identifier, kcfg_map):
|
||||||
setting = parse_identifier(identifier)
|
setting = parse_identifier(identifier, kcfg_map)
|
||||||
mechanism, default = resolve_mechanism(setting, kcfg_map)
|
mechanism, default = resolve_mechanism(setting, kcfg_map)
|
||||||
if mechanism == "shortcuts":
|
if mechanism == "shortcuts":
|
||||||
return read_shortcut_value(setting.group, setting.key)
|
return read_shortcut_value(setting.group, setting.key)
|
||||||
@@ -287,7 +349,7 @@ def save_one(identifier, kcfg_map):
|
|||||||
|
|
||||||
|
|
||||||
def apply_one(identifier, value, kcfg_map):
|
def apply_one(identifier, value, kcfg_map):
|
||||||
setting = parse_identifier(identifier)
|
setting = parse_identifier(identifier, kcfg_map)
|
||||||
mechanism, _default = resolve_mechanism(setting, kcfg_map)
|
mechanism, _default = resolve_mechanism(setting, kcfg_map)
|
||||||
if mechanism == "shortcuts":
|
if mechanism == "shortcuts":
|
||||||
write_shortcut_value(setting.group, setting.key, value)
|
write_shortcut_value(setting.group, setting.key, value)
|
||||||
@@ -355,8 +417,8 @@ def cmd_diff(args, manifest_path, schema_dir):
|
|||||||
kcfg_map = build_kcfg_map(schema_dir)
|
kcfg_map = build_kcfg_map(schema_dir)
|
||||||
manifest = load_manifest(manifest_path)
|
manifest = load_manifest(manifest_path)
|
||||||
|
|
||||||
for identifier in sorted(set(iter_schema_identifiers(kcfg_map))):
|
for setting in sorted(set(iter_schema_identifiers(kcfg_map))):
|
||||||
setting = parse_identifier(identifier)
|
identifier = f"{setting.file}.{setting.group}.{setting.key}"
|
||||||
default = find_schema_default(kcfg_map.get(setting.file, []), setting)
|
default = find_schema_default(kcfg_map.get(setting.file, []), setting)
|
||||||
try:
|
try:
|
||||||
live = read_live_value(setting, default)
|
live = read_live_value(setting, default)
|
||||||
@@ -370,24 +432,48 @@ def cmd_diff(args, manifest_path, schema_dir):
|
|||||||
tag = "declared" if identifier in manifest else "undeclared"
|
tag = "declared" if identifier in manifest else "undeclared"
|
||||||
print(f"{tag} {identifier} = {live} (default: {default})")
|
print(f"{tag} {identifier} = {live} (default: {default})")
|
||||||
|
|
||||||
# Freeform and shortcuts settings have no schema/mapping table to enumerate,
|
# Shortcuts are enumerable via kglobalaccel's allMainComponents/
|
||||||
# so unlike the schema-backed loop above, they can only be checked by walking
|
# allActionsForComponent (the same source iter_shortcut_identifiers already
|
||||||
# identifiers already in the manifest -- neither ever surfaces an undeclared
|
# walks for tab-completion), so unlike freeform they can participate in
|
||||||
# setting via broad scan.
|
# broad undeclared-drift discovery too.
|
||||||
for identifier in manifest:
|
try:
|
||||||
|
shortcut_settings = sorted(set(iter_shortcut_identifiers()))
|
||||||
|
except (RuntimeError, OSError) as e:
|
||||||
|
print(f"dot kde diff: shortcuts scan unavailable: {e}", file=sys.stderr)
|
||||||
|
shortcut_settings = []
|
||||||
|
|
||||||
|
for setting in shortcut_settings:
|
||||||
|
identifier = f"{setting.file}.{setting.group}.{setting.key}"
|
||||||
try:
|
try:
|
||||||
setting = parse_identifier(identifier)
|
live = read_shortcut_value(setting.group, setting.key)
|
||||||
|
default = read_shortcut_value(setting.group, setting.key, method="defaultShortcutKeys")
|
||||||
|
except RuntimeError as e:
|
||||||
|
print(f"dot kde diff: {e}", file=sys.stderr)
|
||||||
|
continue
|
||||||
|
|
||||||
|
if live == default:
|
||||||
|
continue
|
||||||
|
|
||||||
|
tag = "declared" if identifier in manifest else "undeclared"
|
||||||
|
print(f"{tag} {identifier} = {live} (default: {default})")
|
||||||
|
|
||||||
|
# Freeform settings have no schema to enumerate from, so unlike the
|
||||||
|
# schema-backed and shortcuts scans above, they can only be checked by
|
||||||
|
# walking identifiers already in the manifest -- they never surface an
|
||||||
|
# undeclared setting via broad scan. Shortcuts entries are skipped here
|
||||||
|
# (rather than re-parsed) since the broad-scan pass above already reports
|
||||||
|
# every declared shortcut mismatch; parsing one here would also mean an
|
||||||
|
# extra live kglobalaccel round-trip per entry for no benefit.
|
||||||
|
for identifier in manifest:
|
||||||
|
if identifier.split(".", 1)[0] == "kglobalshortcutsrc":
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
setting = parse_identifier(identifier, kcfg_map)
|
||||||
mechanism, default = resolve_mechanism(setting, kcfg_map)
|
mechanism, default = resolve_mechanism(setting, kcfg_map)
|
||||||
if mechanism == "shortcuts":
|
if mechanism != "freeform":
|
||||||
live = read_shortcut_value(setting.group, setting.key)
|
continue
|
||||||
default = read_shortcut_value(setting.group, setting.key, method="defaultShortcutKeys")
|
live = read_live_value(setting, default)
|
||||||
if live == default:
|
if live == "":
|
||||||
continue
|
|
||||||
elif mechanism == "freeform":
|
|
||||||
live = read_live_value(setting, default)
|
|
||||||
if live == "":
|
|
||||||
continue
|
|
||||||
else:
|
|
||||||
continue
|
continue
|
||||||
except (ValueError, RuntimeError) as e:
|
except (ValueError, RuntimeError) as e:
|
||||||
print(f"dot kde diff: {e}", file=sys.stderr)
|
print(f"dot kde diff: {e}", file=sys.stderr)
|
||||||
@@ -400,19 +486,19 @@ def cmd_diff(args, manifest_path, schema_dir):
|
|||||||
|
|
||||||
def cmd_complete(schema_dir):
|
def cmd_complete(schema_dir):
|
||||||
kcfg_map = build_kcfg_map(schema_dir)
|
kcfg_map = build_kcfg_map(schema_dir)
|
||||||
for identifier in sorted(set(iter_schema_identifiers(kcfg_map))):
|
for setting in sorted(set(iter_schema_identifiers(kcfg_map))):
|
||||||
print(identifier)
|
print(f"{setting.file}.{setting.group}.{setting.key}")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Fish's completion runs this on every TAB press, in shells that may have no
|
# Fish's completion runs this on every TAB press, in shells that may have no
|
||||||
# live KDE session (or no busctl at all) -- a broken shortcuts source must
|
# live KDE session (or no busctl at all) -- a broken shortcuts source must
|
||||||
# never cost the schema-backed candidates already printed above.
|
# never cost the schema-backed candidates already printed above.
|
||||||
shortcut_identifiers = sorted(set(iter_shortcut_identifiers()))
|
shortcut_settings = sorted(set(iter_shortcut_identifiers()))
|
||||||
except (RuntimeError, OSError):
|
except (RuntimeError, OSError):
|
||||||
shortcut_identifiers = []
|
shortcut_settings = []
|
||||||
|
|
||||||
for identifier in shortcut_identifiers:
|
for setting in shortcut_settings:
|
||||||
print(identifier)
|
print(f"{setting.file}.{setting.group}.{setting.key}")
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|||||||
@@ -1,2 +1,29 @@
|
|||||||
kxkbrc.Layout.Options=caps:escape_shifted_capslock
|
kxkbrc.Layout.Options=caps:escape_shifted_capslock
|
||||||
kglobalshortcutsrc.ksmserver.Lock Session=Meta+X Screensaver
|
kglobalshortcutsrc.ksmserver.Lock Session=Meta+X Screensaver
|
||||||
|
kglobalshortcutsrc.kwin.Window to Desktop 1=Meta+!
|
||||||
|
kglobalshortcutsrc.kwin.Window to Desktop 2=Meta+@
|
||||||
|
kglobalshortcutsrc.kwin.Window to Desktop 3=Meta+#
|
||||||
|
kglobalshortcutsrc.kwin.Window to Desktop 4=Meta+$
|
||||||
|
kglobalshortcutsrc.kwin.Window to Desktop 5=Meta+%
|
||||||
|
kglobalshortcutsrc.kwin.Window to Desktop 6=Meta+^
|
||||||
|
kglobalshortcutsrc.kwin.Window to Desktop 7=Meta+&
|
||||||
|
kglobalshortcutsrc.kwin.Window to Desktop 8=Meta+*
|
||||||
|
kglobalshortcutsrc.kwin.Window to Desktop 9=Meta+(
|
||||||
|
kglobalshortcutsrc.kwin.Switch to Desktop 1=Meta+1
|
||||||
|
kglobalshortcutsrc.kwin.Switch to Desktop 2=Meta+2
|
||||||
|
kglobalshortcutsrc.kwin.Switch to Desktop 3=Meta+3
|
||||||
|
kglobalshortcutsrc.kwin.Switch to Desktop 4=Meta+4
|
||||||
|
kglobalshortcutsrc.kwin.Switch to Desktop 5=Meta+5
|
||||||
|
kglobalshortcutsrc.kwin.Switch to Desktop 6=Meta+6
|
||||||
|
kglobalshortcutsrc.kwin.Switch to Desktop 7=Meta+7
|
||||||
|
kglobalshortcutsrc.kwin.Switch to Desktop 8=Meta+8
|
||||||
|
kglobalshortcutsrc.kwin.Switch to Desktop 9=Meta+9
|
||||||
|
kglobalshortcutsrc.plasmashell.activate task manager entry 1=
|
||||||
|
kglobalshortcutsrc.plasmashell.activate task manager entry 2=
|
||||||
|
kglobalshortcutsrc.plasmashell.activate task manager entry 3=
|
||||||
|
kglobalshortcutsrc.plasmashell.activate task manager entry 4=
|
||||||
|
kglobalshortcutsrc.plasmashell.activate task manager entry 5=
|
||||||
|
kglobalshortcutsrc.plasmashell.activate task manager entry 6=
|
||||||
|
kglobalshortcutsrc.plasmashell.activate task manager entry 7=
|
||||||
|
kglobalshortcutsrc.plasmashell.activate task manager entry 8=
|
||||||
|
kglobalshortcutsrc.plasmashell.activate task manager entry 9=
|
||||||
|
|||||||
Reference in New Issue
Block a user