Skip to content

Commit 43f9852

Browse files
committed
feat: add shortcut manager plugin
- Add dde-app-shortcuts config module for built-in app shortcuts and translations. - Route logout shortcut through dde-shortcut-tool power show-ui. - Lazily create dde-shortcut-tool controllers and expose static command metadata. - Keep power shortcut actions stateless and initialize dependencies per action. - Skip Display1 initialization on Wayland to avoid shortcut command DBus timeout. - Print Treeland bind error names on commit failure. Log: add shortcut manager plugin Pms: TASK-390447 Change-Id: I4c8ad94a31d4703d78bafb756e5c6b81c36375fd
1 parent 7c4f7f3 commit 43f9852

239 files changed

Lines changed: 17802 additions & 3 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

debian/control

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Build-Depends: debhelper (>= 11),
1010
qt6-wayland-dev,
1111
qt6-wayland-private-dev,
1212
qt6-wayland-dev-tools,
13+
qt6-tools-dev,
1314
libsystemd-dev,
1415
libpcap-dev,
1516
libnet-dev,
@@ -19,9 +20,13 @@ Build-Depends: debhelper (>= 11),
1920
libx11-dev,
2021
libxcb-randr0-dev,
2122
libxcb1-dev,
22-
treeland-protocols,
2323
wlr-protocols,
2424
wayland-protocols,
25+
libxcb-keysyms1-dev,
26+
libxcb-xtest0-dev,
27+
libwayland-dev,
28+
treeland-protocols (>> 0.5.7),
29+
python3,
2530
Standards-Version: 4.1.3
2631
Homepage: https://github.com/linuxdeepin
2732

@@ -30,7 +35,21 @@ Architecture: any
3035
Depends:
3136
${shlibs:Depends},
3237
${misc:Depends},
33-
deepin-service-manager (>= 1.0.5)
38+
deepin-service-manager (>> 1.0.21),
39+
dbus
3440
Breaks: dde-daemon (<< 6.1.87)
3541
Replaces: dde-daemon (<< 6.1.87)
3642
Description: deepin desktop-environment plugins service
43+
This package provides various system service plugins for Deepin Desktop
44+
Environment, including:
45+
- dde-shortcut: Global keyboard shortcut and gesture management for X11 and Wayland
46+
- thememanager: Theme management service
47+
- wallpaperslideshow: Wallpaper slideshow service
48+
- xsettings: X11 settings management
49+
.
50+
The dde-shortcut plugin provides:
51+
- Global keyboard shortcut management for X11 and Wayland
52+
- Gesture shortcut support (Wayland only)
53+
- Dynamic configuration via DConfig
54+
- DBus interface for shortcut registration and management
55+
- Integration with Deepin Desktop Environment

debian/dde-services.postinst

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#!/bin/sh
2+
set -e
3+
4+
# Reload shortcut configurations for all active user sessions when files under
5+
# /usr/share/deepin/org.deepin.dde.keybinding/ change. Failures are logged via
6+
# `logger` instead of being silently dropped so packagers can diagnose them.
7+
reload_shortcuts_for_sessions() {
8+
for user_session in /run/user/*/bus; do
9+
[ -S "$user_session" ] || continue
10+
11+
user_id=$(basename "$(dirname "$user_session")")
12+
user_name=$(getent passwd "$user_id" | cut -d: -f1)
13+
if [ -z "$user_name" ]; then
14+
logger -t dde-services-trigger "no passwd entry for uid $user_id, skipping"
15+
continue
16+
fi
17+
18+
# runuser does not invoke PAM session like `su -`, so it works for
19+
# users without a login shell and avoids reloading the full env.
20+
# Capture stdout+stderr and the exit code separately — POSIX sh has
21+
# no `pipefail`, so `cmd | logger` always returns logger's status
22+
# and would mask dbus-send failures behind a successful pipe.
23+
output=$(runuser -u "$user_name" -- env \
24+
DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$user_id/bus" \
25+
XDG_RUNTIME_DIR="/run/user/$user_id" \
26+
dbus-send --session --type=method_call \
27+
--dest=org.deepin.dde.Keybinding1 \
28+
/org/deepin/dde/Keybinding1 \
29+
org.deepin.dde.Keybinding1.ReloadConfigs \
30+
2>&1) || rc=$?
31+
rc=${rc:-0}
32+
33+
if [ -n "$output" ]; then
34+
printf '%s\n' "$output" | logger -t dde-services-trigger -p user.warning
35+
fi
36+
if [ "$rc" -ne 0 ]; then
37+
logger -t dde-services-trigger -p user.warning \
38+
"ReloadConfigs failed for uid=$user_id user=$user_name (exit=$rc)"
39+
fi
40+
unset rc output
41+
done
42+
}
43+
44+
if [ "$1" = "triggered" ]; then
45+
# Never propagate a per-user reload failure to dpkg — the trigger is
46+
# already declared `interest-noawait`, but `set -e` would still abort the
47+
# postinst on a non-zero subshell. Swallow at the function boundary only.
48+
reload_shortcuts_for_sessions || true
49+
exit 0
50+
fi
51+
52+
#DEBHELPER#
53+
54+
exit 0

debian/dde-services.triggers

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
interest-noawait /usr/share/deepin/org.deepin.dde.keybinding

src/plugin-qt/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ add_subdirectory("thememanager")
66
add_subdirectory("wallpapercache")
77
add_subdirectory("wallpaperslideshow")
88
add_subdirectory("xsettings")
9-
add_subdirectory("power")
9+
add_subdirectory("power")
10+
add_subdirectory("shortcut")
Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
# Shortcut Manager Plugin for deepin-service-manager
2+
cmake_minimum_required(VERSION 3.16)
3+
4+
set(PLUGIN_NAME plugin-dde-shortcut)
5+
6+
set(CMAKE_CXX_STANDARD 17)
7+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
8+
set(CMAKE_AUTOMOC ON)
9+
10+
find_package(Qt6 REQUIRED COMPONENTS Core DBus Gui WaylandClient)
11+
find_package(Dtk6 REQUIRED COMPONENTS Core DConfig)
12+
find_package(PkgConfig REQUIRED)
13+
find_package(TreelandProtocols REQUIRED)
14+
15+
pkg_check_modules(XCB REQUIRED xcb xcb-keysyms xcb-xtest)
16+
pkg_check_modules(X11 REQUIRED x11)
17+
pkg_check_modules(WAYLAND_CLIENT REQUIRED wayland-client)
18+
19+
# Set source file path (using sources from plugin directory)
20+
set(SHORTCUT_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src)
21+
22+
# Common sources shared between plugin and debug binary
23+
set(SHORTCUT_COMMON_SOURCES
24+
${SHORTCUT_SRC_DIR}/core/shortcutmanager.cpp
25+
${SHORTCUT_SRC_DIR}/core/keybindingmanager.cpp
26+
${SHORTCUT_SRC_DIR}/core/gesturemanager.cpp
27+
${SHORTCUT_SRC_DIR}/core/qkeysequenceconverter.cpp
28+
${SHORTCUT_SRC_DIR}/core/actionexecutor.cpp
29+
${SHORTCUT_SRC_DIR}/core/translationmanager.cpp
30+
${SHORTCUT_SRC_DIR}/config/configloader.cpp
31+
${SHORTCUT_SRC_DIR}/backend/abstractkeyhandler.h
32+
${SHORTCUT_SRC_DIR}/backend/abstractgesturehandler.h
33+
${SHORTCUT_SRC_DIR}/backend/specialkeyhandler.cpp
34+
${SHORTCUT_SRC_DIR}/backend/x11/x11keyhandler.cpp
35+
${SHORTCUT_SRC_DIR}/backend/x11/x11helper.cpp
36+
${SHORTCUT_SRC_DIR}/backend/x11/modifierkeymonitor.cpp
37+
${SHORTCUT_SRC_DIR}/backend/wayland/treelandshortcutwrapper.cpp
38+
${SHORTCUT_SRC_DIR}/backend/wayland/waylandkeyhandler.cpp
39+
${SHORTCUT_SRC_DIR}/backend/wayland/waylandgesturehandler.cpp
40+
)
41+
42+
# Plugin sources (plugin-specific + common)
43+
set(PLUGIN_SOURCES
44+
plugin.cpp
45+
pluginshortcutmanager.cpp
46+
pluginshortcutmanager.h
47+
${SHORTCUT_COMMON_SOURCES}
48+
)
49+
50+
# Create plugin library
51+
add_library(${PLUGIN_NAME} SHARED ${PLUGIN_SOURCES})
52+
53+
# Wayland Protocol Generation
54+
qt6_generate_wayland_protocol_client_sources(
55+
${PLUGIN_NAME}
56+
FILES
57+
${TREELAND_PROTOCOLS_DATA_DIR}/treeland-shortcut-manager-v2.xml
58+
)
59+
60+
# Add generated protocol files
61+
target_sources(${PLUGIN_NAME} PRIVATE
62+
${CMAKE_CURRENT_BINARY_DIR}/wayland-treeland-shortcut-manager-v2-protocol.c
63+
)
64+
65+
target_link_libraries(${PLUGIN_NAME} PRIVATE
66+
Qt6::Core
67+
Qt6::DBus
68+
Qt6::Gui
69+
Qt6::WaylandClient
70+
Dtk6::Core
71+
${XCB_LIBRARIES}
72+
${X11_LIBRARIES}
73+
${WAYLAND_CLIENT_LIBRARIES}
74+
)
75+
76+
target_include_directories(${PLUGIN_NAME} PRIVATE
77+
${CMAKE_CURRENT_SOURCE_DIR}
78+
${SHORTCUT_SRC_DIR}
79+
${XCB_INCLUDE_DIRS}
80+
${X11_INCLUDE_DIRS}
81+
${WAYLAND_CLIENT_INCLUDE_DIRS}
82+
)
83+
84+
# Install plugin
85+
install(TARGETS ${PLUGIN_NAME}
86+
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/deepin-service-manager)
87+
88+
# Install configuration files
89+
install(FILES plugin-dde-shortcut.json
90+
DESTINATION share/deepin-service-manager/user)
91+
92+
# Install DConfig configuration files
93+
# Shortcut configs use org.deepin.shortcut.json; gesture configs use org.deepin.gesture.json
94+
file(GLOB SHORTCUT_CONFIG_SUBDIRS
95+
"${CMAKE_CURRENT_SOURCE_DIR}/configs/org.deepin.dde.keybinding.shortcut.*"
96+
)
97+
file(GLOB GESTURE_CONFIG_SUBDIRS
98+
"${CMAKE_CURRENT_SOURCE_DIR}/configs/org.deepin.dde.keybinding.gesture.*"
99+
)
100+
101+
# Install JSON config file for each subdirectory
102+
# Note: BASE must be the absolute path to the configs directory so that
103+
# dtk_add_config_meta_files can correctly calculate the relative path of subdirectories
104+
foreach(SUBDIR_PATH ${SHORTCUT_CONFIG_SUBDIRS})
105+
dtk_add_config_meta_files(
106+
APPID "org.deepin.dde.keybinding"
107+
BASE "${CMAKE_CURRENT_SOURCE_DIR}/configs"
108+
FILES "${SUBDIR_PATH}/org.deepin.shortcut.json"
109+
)
110+
endforeach()
111+
112+
foreach(SUBDIR_PATH ${GESTURE_CONFIG_SUBDIRS})
113+
dtk_add_config_meta_files(
114+
APPID "org.deepin.dde.keybinding"
115+
BASE "${CMAKE_CURRENT_SOURCE_DIR}/configs"
116+
FILES "${SUBDIR_PATH}/org.deepin.gesture.json"
117+
)
118+
endforeach()
119+
120+
install(FILES configs/org.deepin.dde.keybinding.ini
121+
DESTINATION share/deepin/org.deepin.dde.keybinding)
122+
123+
# ============ i18n Translation Support ============
124+
# Install i18n extraction tool
125+
install(PROGRAMS tools/extract_shortcuts_i18n.py
126+
DESTINATION bin
127+
RENAME extract_shortcuts_i18n)
128+
129+
# Install CMake helper module
130+
install(FILES cmake/DdeShortcutI18n.cmake
131+
DESTINATION lib/${CMAKE_LIBRARY_ARCHITECTURE}/cmake/DdeShortcutI18n
132+
RENAME DdeShortcutI18nConfig.cmake)
133+
134+
# i18n integration
135+
find_package(Qt6 REQUIRED COMPONENTS LinguistTools)
136+
include(cmake/DdeShortcutI18n.cmake)
137+
138+
set(I18N_LANGUAGES
139+
"zh_CN" "zh_HK" "zh_TW" "en_US" "ast" "az" "bg" "bo" "ca" "cs" "da"
140+
"de" "el" "es" "et" "eu" "fa" "fi" "fr" "gl" "he" "hi" "hr" "hu"
141+
"hy" "id" "it" "ja" "ka" "kk" "ko" "ky" "lt" "lv" "ms" "nb" "ne"
142+
"nl" "pa" "pl" "pt_BR" "pt" "ro" "ru" "sk" "sl" "sq" "sr" "sv" "th"
143+
"tr" "ug" "uk" "vi"
144+
)
145+
146+
dde_shortcut_add_translations(
147+
APP_ID "org.deepin.dde.keybinding"
148+
CONFIG_DIR "${CMAKE_CURRENT_SOURCE_DIR}/configs"
149+
LANGUAGES ${I18N_LANGUAGES}
150+
)
151+
152+
# subdirectory
153+
add_subdirectory(tools)
154+
add_subdirectory(dde-app-shortcuts)
155+
156+
# ============ Debug Standalone Binary (Optional) ============
157+
option(BUILD_SHORTCUT_DEBUG_BINARY "Build standalone debug binary for dde-shortcut" ON)
158+
159+
if(BUILD_SHORTCUT_DEBUG_BINARY)
160+
message(STATUS "Building standalone debug binary: dde-shortcut-debug")
161+
162+
# Create standalone executable (reuse common sources)
163+
add_executable(dde-shortcut-debug
164+
${SHORTCUT_SRC_DIR}/main.cpp
165+
${SHORTCUT_COMMON_SOURCES}
166+
# Reuse Wayland protocol files generated for plugin
167+
${CMAKE_CURRENT_BINARY_DIR}/wayland-treeland-shortcut-manager-v2-protocol.c
168+
${CMAKE_CURRENT_BINARY_DIR}/qwayland-treeland-shortcut-manager-v2.cpp
169+
)
170+
171+
# Enable AUTOMOC for debug binary
172+
set_target_properties(dde-shortcut-debug PROPERTIES AUTOMOC ON)
173+
174+
# Add dependency on plugin to ensure protocol files are generated first
175+
add_dependencies(dde-shortcut-debug ${PLUGIN_NAME})
176+
177+
target_link_libraries(dde-shortcut-debug PRIVATE
178+
Qt6::Core
179+
Qt6::DBus
180+
Qt6::Gui
181+
Qt6::WaylandClient
182+
Dtk6::Core
183+
${XCB_LIBRARIES}
184+
${X11_LIBRARIES}
185+
${WAYLAND_CLIENT_LIBRARIES}
186+
xcb-xtest # Explicitly link xcb-xtest
187+
)
188+
189+
target_include_directories(dde-shortcut-debug PRIVATE
190+
${CMAKE_CURRENT_SOURCE_DIR}
191+
${SHORTCUT_SRC_DIR}
192+
${CMAKE_CURRENT_BINARY_DIR} # For generated Wayland headers
193+
${XCB_INCLUDE_DIRS}
194+
${X11_INCLUDE_DIRS}
195+
${WAYLAND_CLIENT_INCLUDE_DIRS}
196+
)
197+
endif()

0 commit comments

Comments
 (0)