From 9e513c8fc861a5a0e880dc72507ab5c72ac60adc Mon Sep 17 00:00:00 2001 From: fuleyi Date: Tue, 3 Jun 2025 13:51:13 +0800 Subject: [PATCH] feat: implement keyboard device management - Added Keyboard struct and associated methods for creating and managing keyboard devices. - Introduced error handling for device creation and validation. - Implemented functions to enable/disable keyboards and check their status. - Added utility function to identify keyboard devices in the X11 environment. Log: This enhancement improves keyboard device handling within the dxinput package. pms: BUG-315763 --- dxinput/keyboard.go | 51 ++++++++++++++++++++++++++++++++++++++++++++ dxinput/utils/type.c | 49 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+) diff --git a/dxinput/keyboard.go b/dxinput/keyboard.go index c131969..d49d343 100644 --- a/dxinput/keyboard.go +++ b/dxinput/keyboard.go @@ -5,9 +5,60 @@ package dxinput import ( + "errors" + "fmt" + + . "github.com/linuxdeepin/dde-api/dxinput/common" + "github.com/linuxdeepin/dde-api/dxinput/kwayland" "github.com/linuxdeepin/dde-api/dxinput/utils" ) func SetKeyboardRepeat(enabled bool, delay, interval uint32) error { return utils.SetKeyboardRepeat(enabled, delay, interval) } + +type Keyboard struct { + Id int32 + Name string +} + +func NewKeyboard(id int32) (*Keyboard, error) { + infos := utils.ListDevice() + if infos == nil { + return nil, errors.New("no device") + } + + info := infos.Get(id) + + if info == nil { + return nil, fmt.Errorf("invalid device id: %v", id) + } + return NewKeyboardDevInfo(info) +} + +func NewKeyboardDevInfo(dev *DeviceInfo) (*Keyboard, error) { + if dev == nil || dev.Type != DevTypeKeyboard { + return nil, fmt.Errorf("not a keyboard device(%d - %s)", dev.Id, dev.Name) + } + + return &Keyboard{ + Id: dev.Id, + Name: dev.Name, + }, nil +} + +func (m *Keyboard) Enable(enabled bool) error { + if globalWayland { + return kwayland.Enable(fmt.Sprintf("%s%d", kwayland.SysNamePrefix, m.Id), enabled) + } + + return enableDevice(m.Id, enabled) +} + +func (m *Keyboard) IsEnabled() bool { + if globalWayland { + return kwayland.CanEnabled(fmt.Sprintf("%s%d", kwayland.SysNamePrefix, m.Id)) + } + + return isDeviceEnabled(m.Id) +} diff --git a/dxinput/utils/type.c b/dxinput/utils/type.c index 2323b82..3fd1cd7 100644 --- a/dxinput/utils/type.c +++ b/dxinput/utils/type.c @@ -16,6 +16,7 @@ static int is_mouse_device(int deviceid); static int is_touchpad_device(int deviceid); static int is_touchscreen_device(int deviceid); static int is_wacom_device(int deviceid); +static int is_keyboard_device(int deviceid); static XIDeviceInfo* get_xdevice_by_id(int deviceid); static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; @@ -64,6 +65,11 @@ query_device_type(int deviceid) return TYPE_MOUSE; } + if (is_keyboard_device(deviceid)) { + return TYPE_KEYBOARD; + } + + return TYPE_UNKNOWN; } @@ -127,6 +133,49 @@ is_touchpad_device(int deviceid) is_property_exist(deviceid, "libinput Tapping Enabled")); } +static int +is_keyboard_device(int deviceid) +{ + Display *display; + int num_devices, i; + + pthread_mutex_lock(&mutex); + // 打开 X11 显示 + display = XOpenDisplay(NULL); + if (display == NULL) { + fprintf(stderr, "Open display failed at check prop exist\n"); + pthread_mutex_unlock(&mutex); + return 0; + } + + // 获取所有输入设备 + XIDeviceInfo *devices = XIQueryDevice(display, deviceid, &num_devices); + if (devices == NULL || num_devices != 1) { + fprintf(stderr, "Error getting device information.\n"); + pthread_mutex_unlock(&mutex); + XCloseDisplay(display); + return 0; + } + + if(devices[0].use != XISlaveKeyboard) + { + fprintf(stderr, "Device is not keyboard.\n"); + pthread_mutex_unlock(&mutex); + XIFreeDeviceInfo(devices); + XCloseDisplay(display); + return 0; + } + + // 释放设备信息内存 + XIFreeDeviceInfo(devices); + + // 关闭 X11 显示 + XCloseDisplay(display); + pthread_mutex_unlock(&mutex); + + return 1; +} + // TODO: support libinput static int is_wacom_device(int deviceid)