Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 21 additions & 2 deletions debian/control
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Build-Depends: debhelper (>= 11),
qt6-wayland-dev,
qt6-wayland-private-dev,
qt6-wayland-dev-tools,
qt6-tools-dev,
libsystemd-dev,
libpcap-dev,
libnet-dev,
Expand All @@ -19,9 +20,13 @@ Build-Depends: debhelper (>= 11),
libx11-dev,
libxcb-randr0-dev,
libxcb1-dev,
treeland-protocols,
wlr-protocols,
wayland-protocols,
libxcb-keysyms1-dev,
libxcb-xtest0-dev,
libwayland-dev,
treeland-protocols (>> 0.5.7),
python3,
Standards-Version: 4.1.3
Homepage: https://github.com/linuxdeepin

Expand All @@ -30,7 +35,21 @@ Architecture: any
Depends:
${shlibs:Depends},
${misc:Depends},
deepin-service-manager (>= 1.0.5)
deepin-service-manager (>> 1.0.21),
dbus
Breaks: dde-daemon (<< 6.1.87)
Replaces: dde-daemon (<< 6.1.87)
Description: deepin desktop-environment plugins service
This package provides various system service plugins for Deepin Desktop
Environment, including:
- dde-shortcut: Global keyboard shortcut and gesture management for X11 and Wayland
- thememanager: Theme management service
- wallpaperslideshow: Wallpaper slideshow service
- xsettings: X11 settings management
.
The dde-shortcut plugin provides:
- Global keyboard shortcut management for X11 and Wayland
- Gesture shortcut support (Wayland only)
- Dynamic configuration via DConfig
- DBus interface for shortcut registration and management
- Integration with Deepin Desktop Environment
54 changes: 54 additions & 0 deletions debian/dde-services.postinst
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#!/bin/sh
set -e

# Reload shortcut configurations for all active user sessions when files under
# /usr/share/deepin/org.deepin.dde.keybinding/ change. Failures are logged via
# `logger` instead of being silently dropped so packagers can diagnose them.
reload_shortcuts_for_sessions() {
for user_session in /run/user/*/bus; do
[ -S "$user_session" ] || continue

user_id=$(basename "$(dirname "$user_session")")
user_name=$(getent passwd "$user_id" | cut -d: -f1)
if [ -z "$user_name" ]; then
logger -t dde-services-trigger "no passwd entry for uid $user_id, skipping"
continue
fi

# runuser does not invoke PAM session like `su -`, so it works for
# users without a login shell and avoids reloading the full env.
# Capture stdout+stderr and the exit code separately — POSIX sh has
# no `pipefail`, so `cmd | logger` always returns logger's status
# and would mask dbus-send failures behind a successful pipe.
output=$(runuser -u "$user_name" -- env \
DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$user_id/bus" \
XDG_RUNTIME_DIR="/run/user/$user_id" \
dbus-send --session --type=method_call \
--dest=org.deepin.dde.Keybinding1 \
/org/deepin/dde/Keybinding1 \
org.deepin.dde.Keybinding1.ReloadConfigs \
2>&1) || rc=$?
rc=${rc:-0}

if [ -n "$output" ]; then
printf '%s\n' "$output" | logger -t dde-services-trigger -p user.warning
fi
if [ "$rc" -ne 0 ]; then
logger -t dde-services-trigger -p user.warning \
"ReloadConfigs failed for uid=$user_id user=$user_name (exit=$rc)"
fi
unset rc output
done
}

if [ "$1" = "triggered" ]; then
# Never propagate a per-user reload failure to dpkg — the trigger is
# already declared `interest-noawait`, but `set -e` would still abort the
# postinst on a non-zero subshell. Swallow at the function boundary only.
reload_shortcuts_for_sessions || true
exit 0
fi

#DEBHELPER#

exit 0
1 change: 1 addition & 0 deletions debian/dde-services.triggers
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
interest-noawait /usr/share/deepin/org.deepin.dde.keybinding
3 changes: 2 additions & 1 deletion src/plugin-qt/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ add_subdirectory("thememanager")
add_subdirectory("wallpapercache")
add_subdirectory("wallpaperslideshow")
add_subdirectory("xsettings")
add_subdirectory("power")
add_subdirectory("power")
add_subdirectory("shortcut")
197 changes: 197 additions & 0 deletions src/plugin-qt/shortcut/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
# Shortcut Manager Plugin for deepin-service-manager
cmake_minimum_required(VERSION 3.16)

set(PLUGIN_NAME plugin-dde-shortcut)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_AUTOMOC ON)

find_package(Qt6 REQUIRED COMPONENTS Core DBus Gui WaylandClient)
find_package(Dtk6 REQUIRED COMPONENTS Core DConfig)
find_package(PkgConfig REQUIRED)
find_package(TreelandProtocols REQUIRED)

pkg_check_modules(XCB REQUIRED xcb xcb-keysyms xcb-xtest)
pkg_check_modules(X11 REQUIRED x11)
pkg_check_modules(WAYLAND_CLIENT REQUIRED wayland-client)

# Set source file path (using sources from plugin directory)
set(SHORTCUT_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src)

# Common sources shared between plugin and debug binary
set(SHORTCUT_COMMON_SOURCES
${SHORTCUT_SRC_DIR}/core/shortcutmanager.cpp
${SHORTCUT_SRC_DIR}/core/keybindingmanager.cpp
${SHORTCUT_SRC_DIR}/core/gesturemanager.cpp
${SHORTCUT_SRC_DIR}/core/qkeysequenceconverter.cpp
${SHORTCUT_SRC_DIR}/core/actionexecutor.cpp
${SHORTCUT_SRC_DIR}/core/translationmanager.cpp
${SHORTCUT_SRC_DIR}/config/configloader.cpp
${SHORTCUT_SRC_DIR}/backend/abstractkeyhandler.h
${SHORTCUT_SRC_DIR}/backend/abstractgesturehandler.h
${SHORTCUT_SRC_DIR}/backend/specialkeyhandler.cpp
${SHORTCUT_SRC_DIR}/backend/x11/x11keyhandler.cpp
${SHORTCUT_SRC_DIR}/backend/x11/x11helper.cpp
${SHORTCUT_SRC_DIR}/backend/x11/modifierkeymonitor.cpp
${SHORTCUT_SRC_DIR}/backend/wayland/treelandshortcutwrapper.cpp
${SHORTCUT_SRC_DIR}/backend/wayland/waylandkeyhandler.cpp
${SHORTCUT_SRC_DIR}/backend/wayland/waylandgesturehandler.cpp
)

# Plugin sources (plugin-specific + common)
set(PLUGIN_SOURCES
plugin.cpp
pluginshortcutmanager.cpp
pluginshortcutmanager.h
${SHORTCUT_COMMON_SOURCES}
)

# Create plugin library
add_library(${PLUGIN_NAME} SHARED ${PLUGIN_SOURCES})

# Wayland Protocol Generation
qt6_generate_wayland_protocol_client_sources(
${PLUGIN_NAME}
FILES
${TREELAND_PROTOCOLS_DATA_DIR}/treeland-shortcut-manager-v2.xml
)

# Add generated protocol files
target_sources(${PLUGIN_NAME} PRIVATE
${CMAKE_CURRENT_BINARY_DIR}/wayland-treeland-shortcut-manager-v2-protocol.c
)

target_link_libraries(${PLUGIN_NAME} PRIVATE
Qt6::Core
Qt6::DBus
Qt6::Gui
Qt6::WaylandClient
Dtk6::Core
${XCB_LIBRARIES}
${X11_LIBRARIES}
${WAYLAND_CLIENT_LIBRARIES}
)

target_include_directories(${PLUGIN_NAME} PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${SHORTCUT_SRC_DIR}
${XCB_INCLUDE_DIRS}
${X11_INCLUDE_DIRS}
${WAYLAND_CLIENT_INCLUDE_DIRS}
)

# Install plugin
install(TARGETS ${PLUGIN_NAME}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/deepin-service-manager)

# Install configuration files
install(FILES plugin-dde-shortcut.json
DESTINATION share/deepin-service-manager/user)

# Install DConfig configuration files
# Shortcut configs use org.deepin.shortcut.json; gesture configs use org.deepin.gesture.json
file(GLOB SHORTCUT_CONFIG_SUBDIRS
"${CMAKE_CURRENT_SOURCE_DIR}/configs/org.deepin.dde.keybinding.shortcut.*"
)
file(GLOB GESTURE_CONFIG_SUBDIRS
"${CMAKE_CURRENT_SOURCE_DIR}/configs/org.deepin.dde.keybinding.gesture.*"
)

# Install JSON config file for each subdirectory
# Note: BASE must be the absolute path to the configs directory so that
# dtk_add_config_meta_files can correctly calculate the relative path of subdirectories
foreach(SUBDIR_PATH ${SHORTCUT_CONFIG_SUBDIRS})
dtk_add_config_meta_files(
APPID "org.deepin.dde.keybinding"
BASE "${CMAKE_CURRENT_SOURCE_DIR}/configs"
FILES "${SUBDIR_PATH}/org.deepin.shortcut.json"
)
endforeach()

foreach(SUBDIR_PATH ${GESTURE_CONFIG_SUBDIRS})
dtk_add_config_meta_files(
APPID "org.deepin.dde.keybinding"
BASE "${CMAKE_CURRENT_SOURCE_DIR}/configs"
FILES "${SUBDIR_PATH}/org.deepin.gesture.json"
)
endforeach()

install(FILES configs/org.deepin.dde.keybinding.ini
DESTINATION share/deepin/org.deepin.dde.keybinding)

# ============ i18n Translation Support ============
# Install i18n extraction tool
install(PROGRAMS tools/extract_shortcuts_i18n.py
DESTINATION bin
RENAME extract_shortcuts_i18n)

# Install CMake helper module
install(FILES cmake/DdeShortcutI18n.cmake
DESTINATION lib/${CMAKE_LIBRARY_ARCHITECTURE}/cmake/DdeShortcutI18n
RENAME DdeShortcutI18nConfig.cmake)

# i18n integration
find_package(Qt6 REQUIRED COMPONENTS LinguistTools)
include(cmake/DdeShortcutI18n.cmake)

set(I18N_LANGUAGES
"zh_CN" "zh_HK" "zh_TW" "en_US" "ast" "az" "bg" "bo" "ca" "cs" "da"
"de" "el" "es" "et" "eu" "fa" "fi" "fr" "gl" "he" "hi" "hr" "hu"
"hy" "id" "it" "ja" "ka" "kk" "ko" "ky" "lt" "lv" "ms" "nb" "ne"
"nl" "pa" "pl" "pt_BR" "pt" "ro" "ru" "sk" "sl" "sq" "sr" "sv" "th"
"tr" "ug" "uk" "vi"
)

dde_shortcut_add_translations(
APP_ID "org.deepin.dde.keybinding"
CONFIG_DIR "${CMAKE_CURRENT_SOURCE_DIR}/configs"
LANGUAGES ${I18N_LANGUAGES}
)

# subdirectory
add_subdirectory(tools)
add_subdirectory(dde-app-shortcuts)

# ============ Debug Standalone Binary (Optional) ============
option(BUILD_SHORTCUT_DEBUG_BINARY "Build standalone debug binary for dde-shortcut" ON)

if(BUILD_SHORTCUT_DEBUG_BINARY)
message(STATUS "Building standalone debug binary: dde-shortcut-debug")

# Create standalone executable (reuse common sources)
add_executable(dde-shortcut-debug
${SHORTCUT_SRC_DIR}/main.cpp
${SHORTCUT_COMMON_SOURCES}
# Reuse Wayland protocol files generated for plugin
${CMAKE_CURRENT_BINARY_DIR}/wayland-treeland-shortcut-manager-v2-protocol.c
${CMAKE_CURRENT_BINARY_DIR}/qwayland-treeland-shortcut-manager-v2.cpp
)

# Enable AUTOMOC for debug binary
set_target_properties(dde-shortcut-debug PROPERTIES AUTOMOC ON)

# Add dependency on plugin to ensure protocol files are generated first
add_dependencies(dde-shortcut-debug ${PLUGIN_NAME})

target_link_libraries(dde-shortcut-debug PRIVATE
Qt6::Core
Qt6::DBus
Qt6::Gui
Qt6::WaylandClient
Dtk6::Core
${XCB_LIBRARIES}
${X11_LIBRARIES}
${WAYLAND_CLIENT_LIBRARIES}
xcb-xtest # Explicitly link xcb-xtest
)

target_include_directories(dde-shortcut-debug PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${SHORTCUT_SRC_DIR}
${CMAKE_CURRENT_BINARY_DIR} # For generated Wayland headers
${XCB_INCLUDE_DIRS}
${X11_INCLUDE_DIRS}
${WAYLAND_CLIENT_INCLUDE_DIRS}
)
endif()
Loading
Loading