ukui-settings-daemon/0000775000175000017500000000000015167655063013572 5ustar fengfengukui-settings-daemon/gen_project.sh0000775000175000017500000000636015167654733016440 0ustar fengfeng#!/bin/bash #sample: #生成: #./gen_project.sh master #./gen_project.sh 9x0 #./gen_project.sh tablet #改动放回源文件夹 #./gen_project.sh back master #./gen_project.sh back 9x0 #./gen_project.sh back tablet branch_name=("master" "9x0" "tablet" "2203update" "ubuntu" "tablet" "3.1.4") get_branch=0 projectDir="projectDir" source_project_name="$projectDir/ukui-settings-daemon_[_project_name].pro" source_control_name="$projectDir/control_[_project_name]" source_common_name="$projectDir/common_[_project_name].pri" source_changlog_name="$projectDir/changelog_[_project_name]" dest_project_name="" dest_control_name="" dest_common_name="" dest_changlog_name="" for name in ${branch_name[*]} do if [ $1 == $name ] then if [ $# -eq 1 ];then project_name=$1 echo "准备提取:$1 版本的工程文件与依赖文件" let get_branch=1 rm 当前* touch 当前_$1 elif [ $2 == "back" ];then project_name=$1 let get_branch=2 else let get_branch=0 fi fi done if [ $get_branch -eq 0 ]; then echo "请输出正确的版本:${branch_name[*]}" elif [ $get_branch -eq 2 ]; then echo "退回完毕" dest_project_name=${source_project_name//"_[_project_name]"/} dest_control_name=${source_control_name//"_[_project_name]"/} dest_common_name=${source_common_name//"_[_project_name]"/} dest_changlog_name=${source_changlog_name//"_[_project_name]"/} dest_project_name=${dest_project_name//"$projectDir/"/} dest_control_name=${dest_control_name//"$projectDir/"/"debian/"} dest_common_name=${dest_common_name//"$projectDir/"/"common/"} dest_changlog_name=${dest_changlog_name//"$projectDir/"/"debian/"} source_project_name=${source_project_name//"[_project_name]"/$project_name} source_control_name=${source_control_name//"[_project_name]"/$project_name} source_common_name=${source_common_name//"[_project_name]"/$project_name} source_changlog_name=${source_changlog_name//"[_project_name]"/$project_name} echo $dest_common_name echo $source_common_name cp -v $dest_project_name $source_project_name cp -v $dest_control_name $source_control_name cp -v $dest_common_name $source_common_name cp -v $dest_changlog_name $source_changlog_name echo "退回完毕" else dest_project_name=${source_project_name//"_[_project_name]"/} dest_control_name=${source_control_name//"_[_project_name]"/} dest_common_name=${source_common_name//"_[_project_name]"/} dest_changlog_name=${source_changlog_name//"_[_project_name]"/} dest_project_name=${dest_project_name//"$projectDir/"/} dest_control_name=${dest_control_name//"$projectDir/"/"debian/"} dest_common_name=${dest_common_name//"$projectDir/"/"common/"} dest_changlog_name=${dest_changlog_name//"$projectDir/"/"debian/"} source_project_name=${source_project_name//"[_project_name]"/$project_name} source_control_name=${source_control_name//"[_project_name]"/$project_name} source_common_name=${source_common_name//"[_project_name]"/$project_name} source_changlog_name=${source_changlog_name//"[_project_name]"/$project_name} cp -v $source_project_name $dest_project_name cp -v $source_control_name $dest_control_name cp -v $source_common_name $dest_common_name cp -v $source_changlog_name $dest_changlog_name echo "生成 $project_name 版本完成 :$dest_project_name " fi ukui-settings-daemon/debian/0000775000175000017500000000000015167715207015011 5ustar fengfengukui-settings-daemon/debian/ukui-settings-daemon-common.manpages0000664000175000017500000000020515167655063024070 0ustar fengfengman/authoritydbus.1 man/save-param.1 man/touchpad-state.1 man/ukui-settings-daemon.1 man/ukydisplayswitch.1 man/usd-locate-pointer.1 ukui-settings-daemon/debian/ukui-settings-daemon.postinst0000775000175000017500000000112615167655063022700 0ustar fengfeng#!/bin/sh set -e PowerIgnorePath="/etc/systemd/logind.conf.d/" PowerIgnorePathFile="power-ignore.conf" touchpad_udev="/etc/udev/hwdb.d/61-keyboard.hwdb" dpy=$(echo $DISPLAY) if [ ! -d "$PowerIgnorePath" ];then mkdir $PowerIgnorePath fi if [ ! -f "$PowerIgnorePath$PowerIgnorePathFile" ];then touch $PowerIgnorePath$PowerIgnorePathFile echo "[Login]" >> $PowerIgnorePath$PowerIgnorePathFile echo "HandlePowerKey=ignore" >> $PowerIgnorePath$PowerIgnorePathFile fi if [ -f"$touchpad_udev" ];then rm -rf $touchpad_udev fi glib-compile-schemas /usr/share/glib-2.0/schemas/ #DEBHELPER# ukui-settings-daemon/debian/ukui-settings-daemon.install0000664000175000017500000000010415167655063022453 0ustar fengfeng/etc/ /usr/bin/ /usr/lib/*/ukui-settings-daemon/ /usr/share/dbus-1/ ukui-settings-daemon/debian/ukui-settings-daemon-common.install0000664000175000017500000000014615167655063023747 0ustar fengfeng/usr/share/glib-2.0/ /usr/share/locale/ /usr/share/ukui-settings-daemon/ /usr/share/ukydisplayswitch/ ukui-settings-daemon/debian/copyright0000664000175000017500000001253315167655063016753 0ustar fengfengFormat: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: ukui-settings-daemon Upstream-Contact: Shang Xiaoyang Source: https://gitee.com/openkylin/ukui-settings-daemon Files: * Copyright: 2021, 2023, KylinSoft Co., Ltd. License: GPL-3+ Files: common/touch-calibrate.cpp common/touch-calibrate.h Copyright: 2019, 2023, Tianjin KYLIN Information Technology Co., Ltd. License: GPL-2+ Files: plugins/clipboard/list.c plugins/clipboard/list.h plugins/clipboard/main.cpp plugins/clipboard/xutils.c Copyright: 2001, 2004, Red Hat, Inc. License: NTP Files: plugins/kds/main.cpp Copyright: 2019, 2023, Tianjin KYLIN Information Technology Co., Ltd. License: GPL-2+ Files: plugins/kds/qtlockedfile/* Copyright: 2016, The Qt Company Ltd. License: GPL-3 Files: plugins/kds/qtsingleapplication/* Copyright: 2016, The Qt Company Ltd. License: GPL-3 Files: plugins/keybindings/dconf-util.c plugins/keybindings/dconf-util.h Copyright: 2012, Stefano Karapetsas License: GPL-2+ Files: plugins/locate-pointer/* Copyright: 2008, Carlos Garnacho License: GPL-2+ Files: plugins/locate-pointer/usd-locate-pointer.h Copyright: 2001, Jonathan Blandford License: NTP Files: plugins/media-keys/transform_key.h Copyright: 2023, KylinSoft Co., Ltd. 2004, Jarosław Staniek 2001, Ellis Whitehead License: LGPL-2.1+ Files: plugins/save-param/calibrate-touch-device.cpp plugins/save-param/calibrate-touch-device.h plugins/save-param/main.cpp plugins/save-param/main.h Copyright: 2019, 2023, Tianjin KYLIN Information Technology Co., Ltd. License: GPL-2+ Files: plugins/save-param/xrandr-config.cpp plugins/save-param/xrandr-config.h plugins/save-param/xrandr-output.cpp plugins/save-param/xrandr-output.h Copyright: 2023, KylinSoft Co., Ltd. 2018, Kai Uwe Broulik 2016, Sebastian Kügler 2012, Alejandro Fiestas Olivares License: GPL-3+ Files: plugins/xrandr/xrandr-config.cpp plugins/xrandr/xrandr-config.h plugins/xrandr/xrandr-manager.cpp plugins/xrandr/xrandr-manager.h plugins/xrandr/xrandr-output.cpp plugins/xrandr/xrandr-output.h Copyright: 2023, KylinSoft Co., Ltd. 2018, Kai Uwe Broulik 2016, Sebastian Kügler 2012, Alejandro Fiestas Olivares License: GPL-3+ Files: plugins/xsettings/fontconfig-monitor.c plugins/xsettings/fontconfig-monitor.h Copyright: 2008, Red Hat, Inc. License: GPL-2+ Files: plugins/xsettings/xsettings-common.c plugins/xsettings/xsettings-common.h Copyright: 2001, 2004, Red Hat, Inc. License: NTP License: GPL-2+ This software is Copyright (c) 2024 by foo. This is free software, licensed under: The GNU General Public License, Version 2, June 1991 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 dated June, 1991, or (at your option) any later version. On Debian systems, the complete text of version 2 of the GNU General Public License can be found in '/usr/share/common-licenses/GPL-2'. License: GPL-3 This software is Copyright (c) 2024 by foo. This is free software, licensed under: The GNU General Public License, Version 3, June 2007 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 3 dated June, 2007. On Debian systems, the complete text of version 3 of the GNU General Public License can be found in '/usr/share/common-licenses/GPL-3'. License: GPL-3+ This software is Copyright (c) 2024 by foo. This is free software, licensed under: The GNU General Public License, Version 3, June 2007 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 3 dated June, 2007, or (at your option) any later version. On Debian systems, the complete text of version 3 of the GNU General Public License can be found in '/usr/share/common-licenses/GPL-3'. License: LGPL-2.1+ This software is Copyright (c) 2024 by foo. This is free software, licensed under: The GNU Lesser General Public License, Version 2.1, February 1999 This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; version 2.1 of the License, or (at your option) any later version. On Debian systems, the complete text of version 2.1 of the GNU Lesser General Public License can be found in '/usr/share/common-licenses/LGPL-2.1'. License: NTP Permission to use, copy, modify, and distribute this software and its documentation for any purpose with or without fee is hereby granted, provided that the above copyright notice appears in all copies and that both the copyright notice and this permission notice appear in supporting documentation, and that the name(TrademarkedName) not be used in advertising or publicity pertainingto distribution of the software without specific, written prior permission.(TrademarkedName) makes no representations about the suitabilitythis software for any purpose. It is provided "as is" without express or implied warranty. ukui-settings-daemon/debian/watch0000664000175000017500000000026115167655744016052 0ustar fengfengVersion: 5 Source: https://gitee.com/openkylin/ukui-settings-daemon/releases/ Matching-Pattern: download/debian/\d[\d.]*(?:-\d+)?/ukui-settings-daemon_(\d[\d.]*)\.orig\.tar\.gz ukui-settings-daemon/debian/changelog0000664000175000017500000001077415167657205016677 0ustar fengfengukui-settings-daemon (4.0.0.5-0ubuntu1) resolute; urgency=medium * New upstream release for UKUI 4.20. - Fix FTBFS caused by Qt 6 API and private module syntax changes. - media-keys: remove legacy mediakey-manager implementation. - media-keys: remove unsafe KWindowSystem usage from OSD windows. * d/control: bump standard-vertion to 4.7.3 and remove rules-requires-root=no. -- handsome_feng Wed, 15 Apr 2026 17:35:49 +0800 ukui-settings-daemon (4.0.0.4-1) unstable; urgency=medium * Fix the FTBFS with kf6. -- handsome_feng Thu, 06 Nov 2025 17:57:04 +0800 ukui-settings-daemon (4.0.0.3-1) unstable; urgency=medium * Set c++20 to fix FTBFS with kf6. (Closes: #1119781) -- handsome_feng Wed, 05 Nov 2025 09:49:13 +0800 ukui-settings-daemon (4.0.0.2-1) unstable; urgency=medium * New upstream release: - Completed migration from Qt5/KF5 to Qt6/KF6. (Closes: #1079812) * debian/control: qt5 => qt6, kf5 => kf6. * debian/rules: set buildsystem to qmake6. -- handsome_feng Wed, 19 Mar 2025 11:58:04 +0800 ukui-settings-daemon (4.0.0.1-1) unstable; urgency=medium * Fix crash in realpath. (LP: #2082048) -- handsome_feng Fri, 27 Sep 2024 22:11:03 +0800 ukui-settings-daemon (4.0.0.0-1) unstable; urgency=medium * Fix ftbfs with gcc-14. (Closes: #1075597) -- handsome_feng Fri, 23 Aug 2024 21:45:33 +0800 ukui-settings-daemon (3.22.0.1-1) unstable; urgency=medium * New upstream release. -- handsome_feng Tue, 23 Jan 2024 16:49:40 +0800 ukui-settings-daemon (3.22.0.0-1) unstable; urgency=medium * New upstream release. (Closes: #1051424) -- handsome_feng Thu, 18 Jan 2024 14:14:46 +0800 ukui-settings-daemon (3.1.1.1-2) unstable; urgency=medium * add adapt-to-libkscreen-5.27.patch. (Closes: #1029613) -- handsome_feng Mon, 30 Jan 2023 10:39:43 +0800 ukui-settings-daemon (3.1.1.1-1) unstable; urgency=medium * New upstream bugfix release. (Closes: 1006678) -- handsome_feng Thu, 03 Mar 2022 14:25:48 +0800 ukui-settings-daemon (3.1.1-1) unstable; urgency=medium * New upstream release. -- handsome_feng Wed, 23 Feb 2022 18:17:09 +0800 ukui-settings-daemon (3.0.3-1) unstable; urgency=medium * New upstream release. * d/control: don't depend xserver-xorg-input-synaptics on s390x. -- handsome_feng Thu, 24 Dec 2020 06:39:28 +0000 ukui-settings-daemon (3.0.2-1) unstable; urgency=medium * Upload to unstable. * New upstream release. * d/control: drop libdbus-glib-1 from build-depends. (Closes: #955959) -- handsome_feng Mon, 07 Dec 2020 20:29:17 +0800 ukui-settings-daemon (3.0.1-1) experimental; urgency=medium * New upstream release. -- handsome_feng Thu, 27 Aug 2020 13:38:20 +0800 ukui-settings-daemon (3.0.0-1) experimental; urgency=medium * New upstream release. -- handsome_feng Wed, 26 Aug 2020 20:53:16 +0800 ukui-settings-daemon (1.2.1-1) unstable; urgency=medium * New upstream bugfix release. - Fix the wrong command when do action of shutdown and logout. - Fix the numlock issue. - Fix that the settings of cursor theme didn't work. -- handsome_feng Thu, 26 Mar 2020 12:00:00 +0800 ukui-settings-daemon (1.2.0-1) unstable; urgency=medium * New upstream release. * debian/control: - Bump standards-version to 4.5.0. - Use debhelper-compat. * debian/copyright: - Remove COPYING from copyright. -- handsome_feng Mon, 24 Feb 2020 11:47:45 +0800 ukui-settings-daemon (1.1.7-2) unstable; urgency=medium * Don't set click actions since ukwm take over that. * debian/control: - Bump standards-version to 4.4.0. - Bump compat level to 12. - mate-polkit -> ukui-polkit. -- handsome_feng Wed, 07 Aug 2019 15:22:43 +0800 ukui-settings-daemon (1.1.6-1fakesync1) disco-proposed; urgency=medium * Fake sync due to mismatching orig tarball. -- Logan Rosen Thu, 17 Jan 2019 22:21:48 -0500 ukui-settings-daemon (1.1.6-1) unstable; urgency=medium * Initial release. (Closes: #903944) -- handsome_feng Tue, 17 Jul 2018 11:43:08 +0800 ukui-settings-daemon/debian/source/0000775000175000017500000000000015167657176016323 5ustar fengfengukui-settings-daemon/debian/source/format0000664000175000017500000000001415167657176017531 0ustar fengfeng3.0 (quilt) ukui-settings-daemon/debian/rules0000775000175000017500000000017215167655063016074 0ustar fengfeng#!/usr/bin/make -f export QT_SELECT=qt6 export DEB_BUILD_MAINT_OPTIONS = hardening=+all %: dh $@ --buildsystem=qmake6 ukui-settings-daemon/debian/control0000664000175000017500000000717315167656431016427 0ustar fengfengSource: ukui-settings-daemon Section: x11 Maintainer: Kylin Team Uploaders: handsome_feng , xibowen , Build-Depends: debhelper-compat (=13), intltool, kwayland-dev, libcanberra-dev, libcanberra-gtk-common-dev, libcanberra-gtk3-dev, libcolord-dev, libddcutil-dev(>=0.9.9-5kylin1), libgeoclue-2-dev, libgnome-desktop-3-dev, libgsettings-qt-dev, libgudev-1.0-dev, libimlib2-dev, libkf6config-dev, libkf6globalaccel-dev, libkf6windowsystem-dev, libkscreen-dev, libkysdk-applications-dev, liblcms2-dev, libmate-desktop-dev, libmatekbd-dev, libmatemixer-dev, libnotify-dev, libpulse-dev, libqt5x11extras5-dev, libwayland-client0, libwnck-3-dev, libx11-dev, libxcb-randr0-dev, libxcb-util-dev, libxcb1-dev, libxkbcommon-dev, libxklavier-dev, libxtst-dev, pkgconf, qmake6, qt6-base-dev, qt6-base-private-dev, qt6-sensors-dev, qt6-svg-dev, qt6-tools-dev, qtchooser, xserver-xorg-dev, Standards-Version: 4.7.3 Homepage: https://gitee.com/openkylin/ukui-settings-daemon Vcs-Git: https://gitee.com/openkylin/ukui-settings-daemon.git Vcs-Browser: https://gitee.com/openkylin/ukui-settings-daemon Package: ukui-settings-daemon Architecture: any Depends: colord, imwheel, libglib2.0-bin, mate-desktop-common (>= 1.18), ukui-polkit, ukui-settings-daemon-common (= ${source:Version}), x11-xserver-utils, xinput, xserver-xorg-input-synaptics [!s390x], ${misc:Depends}, ${shlibs:Depends}, Replaces: kylin-display-switch (<=3.1.0), Breaks: kylin-display-switch (<=3.1.0), Description: daemon handling the UKUI session settings This package contains the daemon which is responsible for setting the various parameters of a UKUI session and the applications that run under it. It handles the following kinds of settings: . * Keyboard: layout, accessibility options, shortcuts, media keys * Clipboard management * Theming: background, icons, GTK+ applications * Cleanup of unused files * Mouse: cursors, speed, accessibility options * Startup of other daemons: screensaver, sound daemon * Typing break . It also sets various application settings through X resources and freedesktop.org XSETTINGS. Package: ukui-settings-daemon-common Architecture: all Depends: ${misc:Depends}, Description: daemon handling the UKUI session settings (common files) This package contains the daemon which is responsible for setting the various parameters of a UKUI session and the applications that run under it. It handles the following kinds of settings: . * Keyboard: layout, accessibility options, shortcuts, media keys * Clipboard management * Theming: background, icons, GTK+ applications * Cleanup of unused files * Mouse: cursors, speed, accessibility options * Startup of other daemons: screensaver, sound daemon * Typing break . It also sets various application settings through X resources and freedesktop.org XSETTINGS. . This package contains the architecture independent files. ukui-settings-daemon/LICENSE0000664000175000017500000001674415167655063014613 0ustar fengfeng GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. ukui-settings-daemon/README.md0000664000175000017500000012102715167655063015054 0ustar fengfeng# ukui-settings-daemon ## 1 引言 `ukui-settings-daemon` 是`UKUI`桌面环境下的底层守护程序; 负责设置`UKUI`会话的各种参数以及运行的应用程序。 本文档为用户配置服务的介绍,针对组件的结构,模块设计,程序接口进行介绍。 ### 项目安装依赖 1. 执行: `sudo mk-build-deps -ir debian/control` 会安装项目所有依赖 ### 项目运行 1. 项目打包 - 根目录下执行如下命令,在上层目录生成 `deb` 文件 ```shell debuild -D ``` 2. 项目安装 上层目录生成 `deb` 二进制文件后,进入上层目录,执行 `sudo dpkg -i ./ukui-settings-daemon_xxxx.deb` 3. 项目运行 安装后运行:`ukui-settings-daemon --replace` ## 模块介绍 | 模块 | 功能 | 插件名称 | |--|--|--| | 磁盘监控 | 实现系统中磁盘空间的监听报警功能。并提醒用户清空回收站 |housekeeping| |远程服务|开启、关闭本地远程服务|sharing| |光标提醒|在登录系统后,根据设置按下ctrl时以圆圈的方式提醒光标位置|usd-locate-pointer| |系统快捷键|实现系统快捷键、自定义快捷键|media-key| |用户自定义快捷键|实现用户自定义快捷键|keybindings| |媒体按键|向多媒体播放器传递播放信号|mpris| |输入设备管理|实时设置鼠标、触摸板的参数,并在用户登录时恢复至用户使用的参数|input-device-manager| |键盘参数管理|实时设置键盘的参数,并在用户登录时恢复至用户使用的参数|keyboard| |显示模式切换模块|通过ui交互获取用户选择的显示模式,并进行显示|kds| |显示器管理模块|登录或者插拔显示器时,恢复用户配置|xrandr| |色温管理|依据参数在特定时刻调整显示器色温值|color| ## 接口介绍 控制面板后台部分使用的接口分为gsettings与DBus,提供给内外部进行使用。 ### gsettings 应用程序可以使用gsettings来保存用户配置信息并且确保用户隔离。程序在运行中进行设置、修改gsettings的已有的键值,但是不能通过程序代码创建新的键值,gsettings在一个叫做schema的规范文件中创建,schema(主题)文档其实是一个规范的xml文档。 应用程序通过信号槽来监视文件改动,并根据改动的key处理对应事件。 控制面板后台使用到如下schema: - org.ukui.peripherals-keyboard - org.ukui.peripherals-mouse - org.ukui.peripherals-touchpad - org.ukui.SettingsDaemon.plugins.color - org.ukui.SettingsDaemon.plugins.housekeeping - org.ukui.SettingsDaemon.plugins.media-keys ### org.ukui.peripherals-keyboard #### **repeat** 取值范围:true,false。 用户打开控制面板,设置按键重复设置时,即设置此值。值为true时,长按按键重复输出按键,值为false时,长按按键不重复输出按键。 #### **rate** 取值范围10-110。 repeat为true时,此值为连续输出字符的速度。 #### **delay** 取值范围200-2100 当repeat为true时,延迟此值时间后,按照rate设置的速度连续输出字符。 #### **capslock-state** 实时记录用户设置的大写锁定按键,在开机时恢复为该值的设置。 #### **numlock-state** 实时记录用户设置的数字按键,在开机时恢复为该值的设置。 ### **org.ukui.peripherals-mouse** #### **left-handed** 设置鼠标主按键位置,当用户设置为左键时,左键为选择按键,当用户设置为右键时,右键为选择按键。 #### **wheel-speed** 实时响应该键值的数值,提取键值设置为鼠标滚轮速度。 #### **double-click** 实时响应该键值的数值,提取键值设置为双击间隔时长。 #### **motion-acceleration** 实时响应该键值的数值,提取键值设置为指针速速度。 #### **mouse-accel** 实时响应该键值的数值,提取键值设置为指针加速度。 #### **locate-pointer** 实时响应该键值的数值,并根据该键值具体情况,按下ctrl显示鼠标具体位置。 ### **org.ukui.peripherals-touchpad** #### **disable-on-external-mouse** 取值范围:true,false。 功能: 当用户开启插入鼠标时禁用触摸板,则在鼠标接入时,触摸板将不会生效。 #### **disable-while-typing** 取值范围:true,false。 功能:当用户开启打字时禁用触摸板,则打字期间触摸板将不会有任何影响。 #### **vertical-two-finger-scrolling** 取值范围:true,false。 功能:用户开选择垂直双指滑动时,该键值为ture,双指在触摸板滑动时,滚动条可根据情况进行滑动。 #### **horizontal-two-finger-scrolling** 取值范围:true,false。 功能:用户开选择水平双指滑动时,该键值为ture,双指在触摸板滑动时,滚动条可根据情况进行滑动。 #### **horizontal-edge-scrolling** 取值范围:true,false。 功能:用户开选择水平边际滑动时,该键值为ture,手指在触摸板边缘滑动时,滚动条可根据情况进行滑动。 #### **vertical-edge-scrolling** 取值范围:true,false。 功能:用户开选择水平垂直滑动时,设置该键值为ture,手指在触摸板边缘滑动时,滚动条可根据情况进行滑动。 ### **org.ukui.SettingsDaemon.plugins.color** #### **eye-care** 取值范围:true,false。 开启时使用 eye-care-value设置色温以达到护眼效果。 #### **eye-care-value** 取值范围:1100~6500k(暖->冷) 护眼模式对应的色温值。 #### **night-light-enabled** 取值范围:true,false。 夜间模式打开时,该值设置为true,夜间模式关闭时此值为false。 #### **night-light-allday** 取值范围:true,false。 时间选择全天时,该键值为true,跟随日出日落,或者自定义时,该值为false。 #### **night-light-temperature** 取值范围:1100~6500k(暖->冷) 设置根据该键值,在特定时间依据该键值设置色温。 #### **night-light-schedule-automatic** 取值范围:true,false。 设置为true时,根据night-light-schedule-automatic-from,night-light-schedule-automatic-to自动计算出时间段进入夜间模式。 #### night-light-schedule-automatic-from** 取值范围:00~23.98 夜间模式开始时间。 #### night-light-schedule-automatic-to** 取值范围:00~23.98 夜间模式结束时间。 #### **night-light-****schedule-from** 取值范围:00~23.98 自定义夜间模式开始时间。 #### **nig****ht-light-schedule****-to** 取值范围:00~23.98 自定义夜间模式结束时间。 ## **DBus** D-BUS是一种消息总线系统,是进程相互通信(IPC)的一种简单方式。除了进程间通信,D-BUS还有助于协调进程生命周期;它使编写“单实例”应用程序或守护程序变得简单而可靠,并在需要应用程序和守护程序的服务时按需启动它们。 BUS同时提供系统守护进程(用于“添加新硬件设备”或“打印机队列更改”等事件)和每个用户登录会话守护进程(用于用户应用程序之间的一般IPC需求)。此外,消息总线构建在通用的一对一消息传递框架之上,任何两个应用程序都可以使用该框架直接通信(无需通过消息总线守护进程)。目前,通信应用程序位于一台计算机上,或者通过适合在防火墙后与共享NFS主目录一起使用的未加密TCP/IP进行通信。(需要更好的远程传输方面的帮助-传输机制具有良好的抽象性和可扩展性)。 ### **接口** #### **/org/ukui/SettingsDaemon/GammaManager** 通过调整drm的gamma值来管理色温与亮度 ##### **方法** int setScreenBrightness(QString appName, QString screenName, int screenBrightness); 功能:设置指定显示器的亮度 参数: appName 使用此接口的进程名称 screenName 显示器名称 screenBrightness 指定亮度 返回值:类型int int setAllScreenBrightness(QString appName,int screenBrightness); 功能:设置全部显示器的亮度 参数: appName 使用此接口的进程名称 screenBrightness 指定亮度 OutputGammaInfo getScreensGamma(QString appName); 功能:废弃 OutputGammaInfoList getScreensGammaList(QString appName); 功能:获取全部显示器的gamma信息 参数: appName 使用此接口的进程名称 返回值:显示器信息提取接口:名称,rgb转化的色温,亮度,设置色温 ps:rgb转化的色温是通过drm接口获取gamma的rgb通道,然后反算为色温,色温是通过映射表内插为rgb通道设置到色温。 [('HDMI-1', 4120, 100, 4121), ('DP-2', 4120, 100, 4121)] QHash getScreensGammaInfo(QString appName); int setColorTemperature(QString appName, int colorTemp); #### **信号** void screenGammaChanged(QString screenName, int screenBrightness, int screenGamma); gamma值的改变。 void screenBrightnessChanged(QString screenName, int screenBrightness); 指定显示器信号改变 void allScreenBrightnessChanged(QString screenName,int screenBrightness); 指定所有显示器亮度改变 #### **/org/ukui/SettingsDaemon/MediaKeys** 对外提供快捷键的设置接口 ##### **方法** mediaKeyForOtherApp(int32 action, String appName) ##### **信号** #### **/org/ukui/SettingsDaemon/Sharing** 远程协助 ##### **方法** DisableService(String serviceName) EnableService(String serviceName) ##### **信号** #### **/org/ukui/SettingsDaemon/xrandr** 显示器相关设置 ##### **方法** getScreenMode(String appName) 参数:使用此接口的进程名称 返回值:类型int 0:第一屏模式 1:镜像屏幕模式 2:拓展屏幕模式 3:其他屏幕模式 功能:获取当前屏幕模式 getScreenParam(String appName) 参数:使用此接口的进程名称 返回值:json格式的字符串 功能:获取当前屏幕参数 setScreenMode(String modeName, String appName) 参数: modeName:模式名称 “firstScreenMode”:第一屏模式 “cloneScreenMode”:镜像屏幕模式 “extendScreenMode”:拓展屏幕模式 “secondScreenMode”:其他屏幕模式 appName:调用此接口的程序名(后续考虑加密) 返回值: 功能:设置当前屏幕模式 setScreensParam(String screensParam, String appName) > 参数: screensParam:Json格式的屏幕参数 appName:调用此接口的进程名称(后续考虑加密) 返回值:无 功能:设置当前屏幕参数 参数示例 ```c++ [ { "enabled": true, "id": "e2add05191c5c70db7824c9cd76e19f5", "metadata": { "fullname": "xrandr-LEN LI2224A-U5619HB8", "name": "DP-2" }, "mode": { "refresh": 59.93387985229492, "size": { "height": 1080, "width": 1920 } }, "pos": { "x": 0, "y": 0 }, "primary": false, "rotation": 1, "scale": 1 } ] ``` ##### **信号** ##### screenModeChanged(int32) 参数 - 0:第一屏模式 - 1:镜像屏幕模式 - 2:拓展屏幕模式 - 3:其他屏幕模式 屏幕模式发生改变时发送信号 ##### screensParamChanged(String) 屏幕信息发生改变时发送信号 > 参数 Json格式的屏幕参数 ## 详细设计 ### 加载流程 main函数启动后,通过遍历包含settings-daemon关键字段的gsettings,并找出后缀名称并根据后缀名称加载对应的so文件。 ### **函数说明** #### **main.cpp** int main (int argc, char* argv[]) 参数 argc 参数个数, argv 参数地址 返回值:int 功能:程序入口,调用**PluginManager**类激活各个功能。 void handler(int no) 参数 no 异常代码 返回值:无 功能:捕获kill信号,释放资源 #### plugin-manager.cpp 功能:遍历加载控制面板后台所有功能组件,并逐个初始化,激活。 PluginManager::**PluginManager** 参数:无 功能:构造函数,初始化资源 PluginManager::**~PluginManager** 参数:无 功能:析构函数,释放资源 PluginManager* PluginManager::**getInstance** 参数:无 返回值:PluginManager* 功能:获取实例 bool PluginManager::**managerStart** 参数:无 功能:用于初始化后,开始装载模块插件,并进行激活各个功能模块。 void PluginManager::**managerStop** 参数:无 功能:程序退出时释放插件资源。 static bool register_manager 参数:PluginManager 功能:检查dbus服务中是否有org.ukui.settingsdaemon服务,并以此判断ukui-settings-daemon是否已经启动。 #### plugin-interface.h 所有模块基于此类,暴露出activate接口与deactivate接口。功能模块通过实现activate执行自身业务逻辑,通过实现**deactivate** 退出模块并主动释放资源。 virtual **~PluginInterface**_() {}; 虚析构函数 void **activate** () = 0; 纯虚函数,需要功能模块自己实现功能,实现自身业务逻辑。 **deactivate** () = 0; 纯虚函数,需要功能模块自己实现功能,退出模块,并主动释放资源 ## 磁盘容量监控(housekeeping)设计说明 ### **程序模块说明** 磁盘容量监控根据用户设置的报警阈值,在登录后,以及每隔两分钟检测磁盘剩余,当满足设置阈值时弹窗告知用户当前剩余容量,用户可选择清空回收站释放一定资源空间 ### **函数说明** #### **housekeeping-plugin.cpp** PluginInterface *createSettingsPlugin 参数:无 返回值:PluginInterface * 功能:创建插件接口 PluginInterface *HousekeepingPlugin::getInstance 参数:无 返回值:PluginInterface * 功能:获取实例 HousekeepingPlugin::activate 参数:无 返回值:无 功能:激活插件功能(由main加载参数时遍历处理) HousekeepingPlugin::deactivate 参数:无 返回值:无 功能:注销插件,释放资源 #### **housekeeping-manager.cpp** HousekeepingManager::HousekeepingManager 参数:无 返回值:无 功能:构造方法,初始化资源 HousekeepingManager::~HousekeepingManager 参数:无 返回值:无 功能:注销插件,释放资源 HousekeepingManager::HousekeepingManagerStart 参数:无 返回值:无 功能:检测当前容量,开启定时器固定时间触发功能。 HousekeepingManager::HousekeepingManagerStop 参数:无 返回值:无 功能:注销插件,释放资源 #### **ldsm-trash-empty.cpp** 实现容量监控报警弹窗,并根据功能清空回收站。 LdsmTrashEmpty::**LdsmTrashEmpty**(QWidget *parent) : QDialog(parent), ui(new Ui::LdsmTrashEmpty) LdsmTrashEmpty::~**_LdsmTrashEmpty_**() void LdsmTrashEmpty::**checkButtonCancel**() 执行取消按钮 void LdsmTrashEmpty::**checkButtonTrashEmpty**() 执行清空回收站 void LdsmTrashEmpty::**deleteContents**(const QString path) void LdsmTrashEmpty::**connectEvent**() 建立信号槽绑定按钮与事件的关系 void LdsmTrashEmpty::**usdLdsmTrashEmpty**() 功能:判断回收站是否为空,不为空则显示清空回收站按钮。 void LdsmTrashEmpty::**windowLayoutInit**() 容量监控弹窗初始化 ## **模式切换**(**kds**)设计说明 ### **模块说明** 从显示器参数管理提供的DBus接口中获取当前屏幕数量,并将用户设置的模式通过DBus发送到显示器参数管理模块。 ### **函数说明** #### **main.cpp** main() #### **widget.cpp** Widget::**Widget**(QWidget *parent) :QWidget(parent),ui(new Ui::Widget) 参数:parent父窗口 返回值:无 功能:构造函数 Widget::~**_Widget_**() 参数:无 返回值:无 功能:析构函数 void Widget::**screensParamChangedSignal**(QString screensParam) 参数:显示器模式 返回值:无 功能:该方法为链接xrandr提供的屏幕模式改变信号的槽函数,当接收到该信号后关闭页面,并退出。 void Widget::**beginSetup**() 参数:无 返回值:无 功能:初始化窗口参数,窗口资源,并建立信号的链接。 void Widget::**setupComponent**() 参数:无 返回值:无 功能:调用xrandr提供的DBus接口,查询当前屏幕参数,查询当前屏幕模式,并设置初始值。 void Widget::**setupConnect**() 参数:无 返回值:无 功能:链接界面按钮的click事件,并实现具体选项的功能 QString Widget::**getScreensParam**() 参数:无 返回值:无 功能:获取屏幕参数,被**setupComponent**()使用 int Widget::**getCurrentStatus**() 参数:无 返回值:无 功能:获取当前屏幕所处模式,传递给**initCurrentStatus**使用 void Widget::**initCurrentStatus**(int id) 参数:初始屏幕模式 返回值:无 功能:窗口打开标记当前所处的模式, void Widget::**setScreenModeByDbus**(QString modeName) 参数:需要设置的屏幕模式 返回值:无 功能:当用户选需要设置的显示模式时,调用xrandr提供的DBus接口:setScreenMode,将用户选择的模式传递给xrandr组件,由xrandr组件实现具体功能。 ## **键盘参数管理****(****keyboard****)设计说明** ### **模块说明** 针对控制面板的键盘设置项:按键重复,延迟,速度,按键提示提供接口,当用户操作控制面板时,由控制面板设置对应的参数,后台监控到参数改动时设置对应参数。 并且记录用户对与大小写,数字键的操作,当用户按下按键时,记录状态,重启后恢复用户的操作习惯。 ### **算法及流程** ### **keyboard-manager.cpp** static KeyboardManager *KeyboardManagerNew() 参数:无 返回值:无 功能:工厂模式,实例化一个mKeyboardManager对象,调用其他所需函数接口。 bool KeyboardManager::KeyboardManagerStart() 参数:无 返回值:无 功能:keyboard的启动函数,调用相关初始化函数进行启动项设置。 void KeyboardManager::numlock_install_xkb_callback () 参数:无 返回值:无 功能:keyboard键盘大小写设置,开机检测是否开启大小写键,回调其函数调用x事件进行相关设定。 void KeyboardManager::start_keyboard_idle_cb () 参数:无 返回值:无 功能:键盘设置的初始化函数,启动监盘时从此处开始进行,调用gsettings的相关配置文件,进行读取初始化。 void apply_settings (QString); 参数:str 返回值:无 功能:读取系统下的gsettings配置文件,进行读取设置相关参数与键盘功能是否开启,如大小写等。 void XkbEventsFilter(int keyCode); 参数:int 返回值:无 功能:在x服务事件下的,一些键值事件的处理。 void KeyboardManager::KeyboardManagerStop() 参数:无 返回值:无 功能:keyboard组件的disactive之前的操作,通过KeyboardManagerStop函数对其相关功能的关闭。 #### **keybindings-plugin.cpp** PluginInterface *createSettingsPlugin 参数:无 返回值:PluginInterface * 功能:创建插件接口 PluginInterface *KeyboardPlugin::getInstance 参数:无 返回值:PluginInterface * 功能:获取实例交于main.cpp的方法使用 KeyboardPlugin::activate 参数:无 返回值:无 功能:激活插件功能(由main加载参数时遍历处理) KeyboardPlugin::deactivate 参数:无 返回值:无 功能:注销插件,释放资源 KeyboardManager::KeyboardManager(QObject * parent) 参数:父窗口指针,当父窗口被delete时,会自动释放其关联的子窗口。 返回值:无 功能:构造函数 KeyboardManager::~KeyboardManager() 参数:无 返回值:无 功能:析构函数 KeyboardManager *KeyboardManager::KeyboardManagerNew() 参数:无 返回值:无 功能:实例化键盘管理 bool KeyboardManager::KeyboardManagerStart() 参数:无 返回值:无 功能:开启定时器,并绑定超时信号到槽方法start_keyboard_idle_cb。 void KeyboardManager::KeyboardManagerStop() 参数:无 返回值:无 功能:释放资源。 void KeyboardManager::start_keyboard_idle_cb () 参数:无 返回值:无 功能:依次调用usd_keyboar_manager_apply_settings应用当前参数配置,并针对org.ukui.peripherals-keyboard的改变信号与槽函数apply_settings建立关联。 void KeyboardXkb::usd_keyboard_xkb_init(KeyboardManager* kbd_manager) 参数:无 返回值:无 功能:针对org.mate.peripherals-keyboard-xkb.general、org.mate.peripherals-keyboard-xkb.kbd建立相关槽函数,当发生改变时借由mate进行实现。 void numlock_xkb_init (KeyboardManager *manager) 参数:无 返回值:无 功能:字母灯状态初始化 usd_keyboard_manager_apply_settings (this); 参数:无 返回值:无 功能:应用当前所有配置 void KeyboardManager::apply_settings (QString keys) 参数:无 返回值:无 功能:并针对org.ukui.peripherals-keyboard的改变信号的槽函数,当产生改变信号后由此方法实现改变的键值。 ## **系统快捷键****(****media-keys****)设计说明** ### **模块说明** 快捷键,又叫快速键或热键,指通过某些特定的按键、[按键](https://baike.baidu.com/item/%E6%8C%89%E9%94%AE/7194192)顺序或按键组合来完成一个操作,很多快捷键往往与如 Ctrl 键、Shift 键、Alt 键、Fn 键、 Enter键等配合使用。利用快捷键可以代替[鼠标](https://baike.baidu.com/item/%E9%BC%A0%E6%A0%87/122323)做一些工作,用户可以方便快速的完成一些操作。 ### **算法及流程** ### **mediakey-manager.cpp** bool MediaKeysManager::mediaKeysStart(GError*) 参数:GError 返回值:无 功能:mediakey激活之后的启动函数,此处开始调用相关的快捷键初始化接口,对其相关功能与配置进行初始化操作。 void mediaKeysStop(); 参数:无 返回值:无 功能:mediakey组件相关功能的注销函数,此时相关功能处理挂起失效状态,还未注销其后台进程。 void initScreens(); 参数:无 返回值:无 功能:初始化screen,调用函数gdk_display_get_default与gdk_display_get_default_screen(display)接口。 void MediaKeysManager::initXeventMonitor() 参数:无 返回值:无 功能:x服务下对keypress的监控响应与keyrelease事件的释放功能。 bool MediaKeysManager::getScreenLockState() 参数:无 返回值:无 功能:函数内部写有dbus接口,通过调用回调的mDbusScreensaveMessage获取当前的ScreenLockState的状态。 void doMicSoundAction() 参数:无 返回值:无 功能:键盘中声音快捷键设置的函数入口,通过键盘音量键,设置音量的大小与提示框的ui可视化显示。 void doBrightAction(int) 参数:int 返回值:无 功能:键盘中可视化亮度快捷键设置的函数入口,键盘的亮度调节功能,设置亮度的变化与可视化ui窗口的显示。 void doPowerOffAction(); 参数:无 返回值:无 功能:对屏幕键盘的快捷键函数接口,按下电源power键,对屏幕的息屏相关操作的处理。 void doTouchpadAction(int); 参数:int 返回值:无 功能:对笔记本触摸板的相关设置,通过控制面板,调用读取触摸板的gesttings的配置文件org.ukui.peripherals-touchpad接口进行读与属性的设置。 #### **keybindings-plugin.cpp** PluginInterface *createSettingsPlugin 参数:无 返回值:PluginInterface * 功能:创建插件接口 PluginInterface *HousekeepingPlugin::getInstance 参数:无 返回值:PluginInterface * 功能:获取实例 KeybindingsPlugin::activate 参数:无 返回值:无 功能:激活插件功能(由main加载参数时遍历处理) KeybindingsPlugin::deactivate 参数:无 返回值:无 功能:注销插件,释放资源 ## **定位器参数管理****(****input-device-manager****)设计说明** ### **模块说明** ## **代码文件说明** ### **input-device-manager.cpp** Void managerStart() 参数:无 返回值:无 功能:组件启动入口函数 Bool initDeviceFactor() 参数:bool 返回值:无 功能:初始化设备工厂,根据环境(X/Wayland)创建不同设备工厂 Void eliminateSpecialDevice() 参数:无 返回值:无 功能:剔除和触摸板product ID 一致的mouse 设备 Void clearUpDeviceList() 参数:无 返回值:无 功能:清空设备列表 Void connctGsettings() 参数:无 返回值: 无 功能:gsettings 监听 Void classifyDevice(InputDevice* device) 参数:Inputdevice* 返回值:无 功能:根据设备类型进行筛选,放入对应的list Void disconnectAll() 参数:无 返回值:无 功能:断开所有连接 Bool deleteDevice(QVariant deviceId) 参数:QVariant 返回值:bool 功能:根据设备ID 删除对应设备 Bool existMouse() 参数:无 返回值:bool 功能:检测鼠标设备是否存在 Void disbleTouchpadMousePresent() 参数:无 返回值:无 功能:插入鼠标禁用触摸板 Void deviceAdd(InputDevice* device) 参数:InputDevice* 返回值:无 功能:添加设备 Void deviceRemove(QVariant deviceId) 参数:QVariant 返回值:无 功能:设备拔出时的处理 Void onMouseChanged(const QString& , QVariant) 参数:const QString& , QVariant 返回值:无 功能:鼠标gsettings 值变化的处理 Void onTouchpadChanged(const QString& , QVariant) 参数:const QString& , QVariant 返回值:无 功能:触摸板gsettings值变化的处理 ### **input-device/input-x-device/input-wayland-device(.cpp)** InputXDevice InputWaylandDevice 继承自InputDevice,公共函数如下: virtual void setEnable(QVariant value) = 0; 参数:QVarint 返回值:无 功能:设置设备使能状态 virtual void setLeftMode(QVariant value) = 0; 参数:QVarint 返回值:无 功能:设置设备左右手模式 virtual void setNaturalScroll(QVariant value) = 0; 参数:QVarint 返回值:无 功能:设置设备滚动方向 virtual void setTapclick(QVariant value) = 0; 参数:QVarint 返回值:无 功能:设置设备轻触点击 virtual void setTapDrag(QVariant value) = 0; 参数:QVarint 返回值:无 功能:设置设备轻触拖拽 virtual void setDisableTyping(QVariant value) = 0; 参数:QVarint 返回值:无 功能:设置设备打字禁用 virtual void setAccelSpeed(QVariant value) = 0; 参数:QVarint 返回值:无 功能:设置设备光标加速 virtual void setAcceleration(QVariant value) = 0; 参数:QVarint 返回值:无 功能:设置设备光标速度 virtual void setMiddleButtonEmulation(QVariant value) = 0; 参数:QVarint 返回值:无 功能:设置设备模拟中键点击 virtual void setScrolling(QVariant value) = 0; 参数:QVarint 返回值:无 功能:设置设备滚动状态 virtual void setDisableTpMoPresent(QVariant value) = 0; 参数:QVarint 返回值:无 功能:设置插入鼠标禁用触摸板 virtual void setWheelSpeed(QVariant value) = 0; 参数:QVarint 返回值:无 功能:设置设备滚轮速度 virtual QVariant getProductId() = 0; 参数:无 返回值:QVariant 功能:获取设备ProductID ### **input-device-factor.cpp** void initInputDevices() 参数:无 返回值:无 功能:初始化设备列表 void connectMonitor() 参数:无 返回值:无 功能:启动设备监听 InputDevice* createInputDevice(QVariant deviceId, DeviceType type, QString name); 参数:QVariant , DeviceType ,QString 返回值:InputDevice* 功能:创建InputDevice设备 InputDevice* filterDevice(XDeviceInfo device / QDBusInterface * interface) 参数:XDeviceInfo (x环境)或者 QDBusInterface* (wayland) 返回值:InputDevice* 功能:根据设备属性过滤设备 ### **input-device-helper.cpp** bool supportXinputExtension(); 参数:无 返回值:bool 功能:检测是否支持X扩展 Atom properyToAtom(const char* propery); 参数:const char* 返回值:Atom 功能:属性name 转换Atom Atom deviceHadProperty(int device, const char* propName); 参数:int ,const char* 返回值:const char* 功能:功能:检测设备属性是否存在,返回此属性原子 Atom deviceHadProperty(int device, Atom prop); 参数:int , Atom 返回值:Atom 功能:检测设备属性是否存在,返回此属性原子 QVariantList getDeviceProp(int device, const char *property); 参数:int , const char* 返回值:QVariantList 功能: 获取设备属性值列表 QVariantList getDeviceProp(int device, Atom prop); 参数:int , Atom 返回值:QVariantList 功能: 获取设备属性值列表 void setDeviceProp(int device, const char *property ,QVariantList value); 参数:int , const char* ,QVariantList 返回值:无 功能: 设置设备属性 void setDeviceProp(int device, Atom prop, QVariantList value); 参数:int , Atom ,QVariantList 返回值:无 功能: 设置设备属性 int getDeviceButtonMap(int device, unsigned char** map); 参数:int , unsigned char** 返回值:int 功能: 获取设备的button map,存入map void setDeviceButtonMap(int device, int buttons, unsigned char* map); 参数:int , int , unsigned char* 返回值:无 功能:设置按钮映射 void disable(int device); 参数:int 返回值:无 功能:禁用设备 void enabel(int device); 参数:int 返回值:无 功能:启用设备 ### **input-gsettings.cpp** 管理输入设备的gsettings。 ### **input-monitor.cpp** X环境下监听设备插拔。 ### **input-process-settings.cpp** 部分设备属性通过其他进程实现。 ### **keybindings-plugin.cpp** PluginInterface *createSettingsPlugin 参数:无 返回值:PluginInterface * 功能:创建插件接口 PluginInterface *InputDevicePlugin::getInstance 参数:无 返回值:PluginInterface * 功能:获取实例 InputDevicePlugin::activate 参数:无 返回值:无 功能:激活插件功能(由main加载参数时遍历处理) InputDevicePlugin::deactivate 参数:无 返回值:无 功能:注销插件,释放资源 ## **多媒体快捷键****(****mpris****)设计说明** ### **模块说明** 特殊媒体快捷按键,可以控制一些媒体播放器的快捷键,如: 播放、暂停、停止等。 ### **mpris-manager.cpp** bool MprisManagerStart(GError **error) 参数:GError 返回值:无 功能:媒体快捷键的函数启动初始化入口,实现了对dbus信号等的接收,对象的实例化,与回调的过程。 void MprisManagerStop() 参数:无 返回值:无 功能:mpris快捷键功能资源的释放与stop过程。 void MprisManager::serviceRegisteredSlot(const QString& service) 参数:const str 返回值:无 功能:A media player was just run and should be added to the head of @mPlayerQuque.。 void MprisManager::serviceUnregisteredSlot(const QString& service) 参数:const str 返回值:无 功能:if anyone dbus service that from @busNames quit,this func will be called。 void keyPressed(QString,QString) 参数:str 返回值:无 功能:after catch MediaPlayerKeyPressed() signal, this function will be called。 ## **声音提醒****(**sound**)设计说明** ### **模块说明** 提示音设置,listen for org.mate.sound。 ### **sound-manager.cpp** bool SoundManagerStart(GError **error) 参数:GError 返回值:无 功能:Starting sound manager begin,use gsettings that We listen for change of the selected theme。 void SoundManagerStop() 参数:无 返回值:无 功能:Stopping sound manager,释放了一些所需要的object资源。 void SoundManager::trigger_flush () 参数:无 返回值:无 功能:We delay the flushing a bit so that we can coalesce multiple changes into a single cache flush 。 bool SoundManager::register_directory_callback (const QString path, GError **error) 参数:const str,GError 返回值:bool 功能:对注册服务之后收到事件的回调,,并建立其对file_monitor_changed_cb接口的connect。 #### **keybindings-plugin.cpp** PluginInterface *createSettingsPlugin 参数:无 返回值:PluginInterface * 功能:创建插件接口 PluginInterface *HousekeepingPlugin::getInstance 参数:无 返回值:PluginInterface * 功能:获取实例 KeybindingsPlugin::activate 参数:无 返回值:无 功能:激活插件功能(由main加载参数时遍历处理) KeybindingsPlugin::deactivate 参数:无 返回值:无 功能:注销插件,释放资源 ## **光标提醒****(****usd-locate-pointer****)设计说明** ### **模块说明** 对光标事件的设置,使用gdk的应用对光标的start、pause、rewind、fps、duration、running等可视化事件的处理配置。 参数:无 返回值:PluginInterface * 功能:创建插件接口 PluginInterface *HousekeepingPlugin::getInstance 参数:无 返回值:PluginInterface * 功能:获取实例 KeybindingsPlugin::activate 参数:无 返回值:无 功能:激活插件功能(由main加载参数时遍历处理) KeybindingsPlugin::deactivate 参数:无 返回值:无 功能:注销插件,释放资源 ## **热插拔设备管理****(****xinput****)设计说明** ### **模块说明** xinput对输入设备的管理,主要通过预定设计的配置文件去管理与驱动一些input设备,可以降低出现问题的概率与多次热插拔之后响应速率延时的问题。 ### **算法及流程** ### **xinputmanager.cpp** void updateButtonMap() 参数:无 返回值:无 功能:更新触控笔映射 void XinputManager::SetPenRotation(int device_id) 参数:int 返回值:无 功能:触控笔函数的处理接口,通过对输入设备id的获取与识别,对其进行相关的屏幕触控映射处理。 int EventSift(XIHierarchyEvent *event, int flag) 参数:XIHierarchyEvent ,int 返回值:int 功能:筛选出发生事件的设备ID,所有设备的事件信息与当前发生的事件,若失败返回-1,成功则返回获取到的id值。 void ListeningToInputEvent() 参数:无 返回值:无 功能:ListeningToInputEvent此函数主要对其所有输入设备的事件进行监控。 #### **keybindings-plugin.cpp** PluginInterface *createSettingsPlugin 参数:无 返回值:PluginInterface * 功能:创建插件接口 PluginInterface *HousekeepingPlugin::getInstance 参数:无 返回值:PluginInterface * 功能:获取实例 KeybindingsPlugin::activate 参数:无 返回值:无 功能:激活插件功能(由main加载参数时遍历处理) KeybindingsPlugin::deactivate 参数:无 返回值:无 功能:注销插件,释放资源 ## **显示器伽马参数管理****(****原color****)设计说明** ### **模块说明** 色温管理模块监听并读取控制面板设置参数:gsettings:org.ukui.SettingsDaemon.plugins.color,dbus:/org/ukui/SettingsDaemon/GammaManager 每分钟对比一次当前时间与预设的日出日落时间如果处于日落之后、日出之前则将当前显示器色温调整为预设色温。日出之后、日落之前则调整为正常状态。 日出日落的时间根据选项进行提取,如果是自定义则提取用户设置的值: 如果跟随日出日落则提取则提取系统缺省值。 #### **启动流程** 软件启动时,获取当前的桌面环境,如果是X则走X分支使用gamma管理色温,如果是wayland则走kwin接口设置色温。 ### **gamma-manager-plugin.cpp** 插件入口,根据环境变量加载gamma-manager.cpp或者gamma-manager-wayland.cpp ### **gamma-manager.cpp** x相关设置逻辑 ### **gamma-manager-wayland.cpp** wayland设置, ### **gamma-manager-location.cpp** 地理位置相关问题,提供给gamma-manager,gamma-manager-wayland使用 ### **gamma-manager-helper.cpp** 设置gtk相关配置 ### **gamma-manager-gtkconfig.cpp** ## **显示器参数管理****(****xrandr****)设计说明** ### **模块说明** 该模块记录用户设置的每组显示器参数,当接入已配置过的显示器时通过《显示参数恢复功能》恢复用户设置的参数,当显示器从未接入过,或者配置文件损坏时按照《缺省显示规则_》_进行设置,参数设置成功后,按照触摸设备映射规则进行重新映射触摸屏、触控笔与显示器的关系。 #### **显示参数恢复功能** 该功能将接入过的显示器参数保存至唯一码命名的配置文件,并根据当前的显示模式保存至:实时参数文件夹,第一屏参数文件夹,其他屏幕参数文件夹,镜像屏参数文件夹,通过此种方法可恢复用户在任意模式下的屏幕参数并进行恢复,无需用户再次针对特定屏幕组合进行设置,从而达到一次设置终身使用的效果。 #### **唯一码生成方式** 根据显示器的edid信息生成MD5-hash编码,当有多个显示器接入时采用多个显示器的信息生成显示器组MD5-hash编码。 #### **缺省显示规则** 第一屏 最大分辨率显示首个识别到的屏幕,设置为主屏并放置到(0,0)点坐标进行显示。 其他屏 最大分辨率显示器最后一个识别到的屏幕,设置为主屏并放置到(0,0)点坐标进行显示。 镜像屏幕 取出多个屏幕中共同存在的最大分辨率,并同时设置到(0,0)点进行显示。 拓展屏幕 将第一个识别到的屏幕设置为主屏,并放到(0,0)点,剩余的屏幕放到(第一个屏幕宽,0)坐标进行显示。 #### **触摸设备****映射****规则** 当插件启动以及显示参数(分辨率、角度)发生变化时会触发此功能,对触摸设备进行重新映射。 **映射规则:** 首先读取控制面板生成的触摸配置文件,按照配置内取到的映射关系进行映射。 当配置文件内的映射关系全部处理完毕后,仍有部分设备没有映射时则按照如下规则进行映射: 按照屏幕绝对尺寸和触摸设备尺寸误差2%进行匹配映射先进行映射。对于剩余设备直接映射。 触摸屏与触控笔可映射到同一显示器。 #### **启动流程** 软件启动时,获取当前的屏幕唯一码然后根据配置文件存在情况进行设置:如存在则读取恢复,如不存在则设置为缺省参数进行设置。 #### **事件循环流程** 当用户修改屏幕参数时,根据当前屏幕模式将参数实时保存至对应的文件夹内。 当用户切换模式时,取出该模式下的对应参数进行设置,如对应参数文件夹的配置不存在时,则按照缺省规则进行显示,并将参数文件复制一份到实时参数文件夹。 当接入屏幕时,首先识别出唯一码,而后读取实时参数文件夹下以唯一码命名的参数文件并设置显示器,如文件不存在则按照缺省规则进行显示。 ### **xrandr-manager.cpp** void XrandrManager::StartXrandrIdleCb() 参数:无 返回值:无 功能:屏幕事件相关的初始化回调函数,对screen设备的读取配置信息,模式的设置等相关入口。 void XrandrManager::applyConfig() 参数:无 返回值:无 功能:函数apply的入口,设置了autoRemapTouchscreen的功能与sendScreenModeToDbus的信号发送。 void XrandrManager::outputConnectedWithoutConfigFile(KScreen::Output *newOutput, char outputCount) 参数:KScreen::Output *newOutput, char outputCount 返回值:无 功能:接入时没有配置文件的处理函数,即处理预定设置,单屏位最优分辨率,多屏幕为镜像模式。 void XrandrManager::setScreenModeToFirst(bool isFirstMode) 参数:bool 返回值:无 功能:设置屏幕为第一屏的函数入口,通过遍历input设备找到第一个屏幕(默认为内屏)。 void XrandrManager::RotationChangedEvent(const QString &rotation) 参数:const str 返回值:无 功能:获取status-manager发来的信号的dbus值,通过对pc与rotation信号的解析,设置屏幕旋转的角度与模式。 void XrandrManager::SaveConfigTimerHandle() 参数:无 返回值:无 功能:处理来自控制面板操作的接口,获取控制面板中对screen参数的设定,写入相应的配置文件进行保存映射。 void XrandrManager::autoRemapTouchscreen() 参数:无 返回值:无 功能:处理触摸屏的配置映射关系,读取配置文件映射关系映射,配置文件不满足所有设备时,进行按照设备物理尺寸匹配进行自动映射。 #### **keybindings-plugin.cpp** PluginInterface *createSettingsPlugin 参数:无 返回值:PluginInterface * 功能:创建插件接口 PluginInterface *HousekeepingPlugin::getInstance 参数:无 返回值:PluginInterface * 功能:获取实例 KeybindingsPlugin::activate 参数:无 返回值:无 功能:激活插件功能(由main加载参数时遍历处理) KeybindingsPlugin::deactivate 参数:无 返回值:无 功能:注销插件,释放资源 ## **GDK参数设置**(**xsettings**)设计说明** ### **模块说明** 设置底层系统主题变量,设定了一些光标等ui事件的gdk主题。 ## 代码统计 wc -l `find ./ -name "*.c";find -name "*.h";find -name "*.cpp"` 整理前:39196 wc -c `find ./ -name "*.c";find -name "*.h";find -name "*.cpp"` 整理前:1242208 ukui-settings-daemon/doc/0000775000175000017500000000000015167654733014342 5ustar fengfengukui-settings-daemon/doc/debian.md0000664000175000017500000000040315167654733016103 0ustar fengfeng### 生成debian过程 1. 安装必需的包 ```shell sudo apt install build-essential sudo apt install debmake ``` 2. 生成debian目录 ```shell debmake -e "team+kylin@tracker.debian.org" -p "ukui-settings-daemon" -f "Kylin Team" -u 0.0.1 -m -n -x1 ``` ukui-settings-daemon/man/0000775000175000017500000000000015167655063014345 5ustar fengfengukui-settings-daemon/man/authoritydbus.10000664000175000017500000000071615167654733017344 0ustar fengfeng.\" .\" authoritydbus manual page .\" Copyright (c) 2020 KylinSoftCo.Ltd .\" .TH AUTHORITYDBUS 1 "June 25 2020" "" .SH NAME authoritydbus \- Perform the settings that require the right to be raised. .SH AUTHOR \fBauthoritydbus\fR was written by Junhao Sun . .PP This manual page was originally written Junhao Sun . .PP This manual page was adopted for UKUI by Junhao Sun . ukui-settings-daemon/man/usd-locate-pointer.10000664000175000017500000000131315167654733020146 0ustar fengfeng.\" UKUI manpages .\" usd-datetime-mechanism -man .\" .TH usd-locate-pointer 1 "Oct 2014" "" "UKUI-SETTINGS-DAEMON" .SH NAME usd-locate-pointer \- create ripples around mouse pointer .SH SYNOPSIS usd-locate-pointer .SH DESCRIPTION The \fIusd-locate-pointer\fR utility is a program that creates ripples (like throwing a stone into water) around the mouse pointer. This helps to locate the position of the mousepointer. .PP With \fIukui-settings-daemon\fR i is possible to assign a hotkey for evoking the \fIusd-locate-pointer\fR command. .SH AUTHOR This manual page has been written by Mike Gabriel . It has been originally written for the Debian project (but may be used by others)ukui-settings-daemon/man/touchpad-state.10000664000175000017500000000111415167655063017351 0ustar fengfeng.\" .\" touchpad-state manual page .\" Copyright (C) 2023 KylinSoft Co., Ltd. .\" .TH touchpad-state 1 "Nov 2020" "" "UKUI-SETTINGS-DAEMON" .SH NAME touchpad-state \- Modify touchpad status .SH SYNOPSIS touchpad-state .SH DESCRIPTION The \fItouchpad-state\fR It is used to set the state of the touchpad, and it is more convenient to control the switch of the touchpad. .PP With \fItouchpad-state --off\fR Used to turn off the touchpad .PP With \fItouchpad-state --on\fR Used to open the touchpad .SH AUTHOR This manual page has been written by Shang Xiaoyang. ukui-settings-daemon/man/save-param.10000664000175000017500000000066515167654733016475 0ustar fengfeng.\" .\" save-param manual page .\" Copyright (c) 2020 KylinSoftCo.Ltd .\" .TH SAVE-PARAM 1 "June 25 2020" "" .SH NAME save-param \- Save the monitor parameter when updating usd .SH AUTHOR \fBsave-param\fR was written by Junhao Sun . .PP This manual page was originally written Junhao Sun . .PP This manual page was adopted for UKUI by Junhao Sun . ukui-settings-daemon/man/ukui-settings-daemon.10000664000175000017500000000175515167654733020516 0ustar fengfeng.\" .\" ukui₋settings-daemon manual page .\" Copyright (c) 2020 KylinSoftCo.Ltd .\" .TH UKUI-SETTINGS-DAEMON 1 "June 25 2020" "" .SH NAME ukui-settings-daemon \- Handles the UKUI session settings .SH SYNOPSIS \fBukui-settings-daemon\fR [\fB\-\-debug\fR] [\fB\-\-replace\fR] [\fB\-\-display\fR=\fIDISPLAY\fR] .SH DESCRIPTION \fIukui-settings-daemon\fR is responsible for setting the various preference parameters of a UKUI session and the applications that run under it. .SH OPTIONS .PP Help options .TP \-?, \fB\-\-help\fR Show this help message .PP Application options .TP \fB\-\^\-debug\fR Enable debugging code .TP \fB\-\^\-replace\fR Replaces the current running daemon .TP \fB\-\^\-display\fR=\fIDISPLAY\fR X display to use .PP .SH AUTHOR \fBukui-settings-daemon\fR was written by Junhao Sun . .PP This manual page was originally written Junhao Sun . .PP This manual page was adopted for UKUI by Junhao Sun . ukui-settings-daemon/man/ukydisplayswitch.10000664000175000017500000000070315167654733020052 0ustar fengfeng.\" .\" ukydisplayswitch manual page .\" Copyright (c) 2020 KylinSoftCo.Ltd .\" .TH ukydisplayswitch 1 "June 25 2020" "" .SH NAME ukydisplayswitch \- Toggle display mode of the monitor .SH AUTHOR \fBukydisplayswitch\fR was written by Junhao Sun . .PP This manual page was originally written Junhao Sun . .PP This manual page was adopted for UKUI by Junhao Sun . ukui-settings-daemon/common/0000775000175000017500000000000015167655403015060 5ustar fengfengukui-settings-daemon/common/x11-head.h0000664000175000017500000000423015167655063016542 0ustar fengfeng#ifndef _X11_HEAD_H__ #define _X11_HEAD_H__ /* -*- Mode: C; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifdef __cplusplus extern "C" { #endif #include // 基础Xlib库 #include // Xlib内部接口(通常不推荐直接使用) #include // X键盘扩展 #include // 键码和符号定义 #include // X原子 #include // X输入扩展 #include // X输入扩展2 #include // X屏幕重设大小扩展 #include // X修正扩展 #include // X记录扩展(注意:这里重复了,应去除一个) #include // X光标库 #include // GDK库 #include // GLib库 #include // Gudev库 #ifdef Always #undef Always #endif #ifdef FontChange #undef FontChange #endif #ifdef Unsorted #undef Unsorted #endif #ifdef Expose #undef Expose #endif #ifdef FocusIn #undef FocusIn #endif #ifdef FocusOut #undef FocusOut #endif #ifdef KeyPress #undef KeyPress #endif #ifdef KeyRelease #undef KeyRelease #endif #ifdef CursorShape #undef CursorShape #endif #ifdef Bool #undef Bool #endif #ifdef None #undef None #endif #ifdef max #undef max #endif #ifdef min #undef min #endif #ifdef Data #undef Data #endif #ifdef __cplusplus } #endif #endif ukui-settings-daemon/common/config.h0000664000175000017500000001104315167655063016477 0ustar fengfeng/* -*- Mode: C; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef USD_CONFIG_H #define USD_CONFIG_H /* config.h. Generated from config.h.in by configure. */ /* config.h.in. Generated from configure.ac by autoheader. */ /* always defined to indicate that i18n is enabled */ #define ENABLE_NLS 1 /* enable profiling */ /* #undef ENABLE_PROFILING */ /* Name of default gettext domain */ #define GETTEXT_PACKAGE "ukui-settings-daemon" /* Warn on use of APIs added after GLib 2.36 */ #define GLIB_VERSION_MAX_ALLOWED GLIB_VERSION_2_36 /* Warn on use of APIs deprecated before GLib 2.36 */ #define GLIB_VERSION_MIN_REQUIRED GLIB_VERSION_2_36 /* Define to 1 if you have the `bind_textdomain_codeset' function. */ #define HAVE_BIND_TEXTDOMAIN_CODESET 1 /* Define to 1 if you have the Mac OS X function CFLocaleCopyCurrent in the CoreFoundation framework. */ /* #undef HAVE_CFLOCALECOPYCURRENT */ /* Define to 1 if you have the Mac OS X function CFPreferencesCopyAppValue in the CoreFoundation framework. */ /* #undef HAVE_CFPREFERENCESCOPYAPPVALUE */ /* Define to 1 if you have the `dcgettext' function. */ #define HAVE_DCGETTEXT 1 /* Define to 1 if you have the header file. */ #define HAVE_DLFCN_H 1 /* Define if the GNU gettext() function is already present or preinstalled. */ #define HAVE_GETTEXT 1 /* Define to 1 if you have the header file. */ #define HAVE_INTTYPES_H 1 /* Define if your file defines LC_MESSAGES. */ #define HAVE_LC_MESSAGES 1 /* Define if libcanberra-gtk3 is available */ #define HAVE_LIBCANBERRA 1 /* Define if libmatemixer is available */ #define HAVE_LIBMATEMIXER 1 /* Define if libnotify is available */ #define HAVE_LIBNOTIFY 1 /* Define to 1 if you have the header file. */ #define HAVE_LOCALE_H 1 /* Define to 1 if you have the header file. */ #define HAVE_MEMORY_H 1 /* Defined if PolicyKit support is enabled */ #define HAVE_POLKIT 1 /* Define if PulseAudio support is available */ /* #undef HAVE_PULSE */ /* Define to 1 if you have the header file. */ #define HAVE_STDINT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDLIB_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STRINGS_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STRING_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_STAT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_TYPES_H 1 /* Define to 1 if you have the header file. */ #define HAVE_UNISTD_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_X11_EXTENSIONS_XF86MISC_H */ /* Define to 1 if you have the header file. */ #define HAVE_X11_EXTENSIONS_XKB_H 1 /* Define to the sub-directory where libtool stores uninstalled libraries. */ #define LT_OBJDIR ".libs/" /* Name of package */ #define PACKAGE "ukui-settings-daemon" /* Define to the address where bug reports for this package should be sent. */ #define PACKAGE_BUGREPORT "http://www.ukui.org/" /* Define to the full name of this package. */ #define PACKAGE_NAME "ukui-settings-daemon" /* Define to the full name and version of this package. */ #define PACKAGE_STRING "ukui-settings-daemon 1.1.1" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "ukui-settings-daemon" /* Define to the home page for this package. */ #define PACKAGE_URL "" /* Define to the version of this package. */ #define PACKAGE_VERSION "3.0.0" /* Define if smartcard support should be enabled */ #define SMARTCARD_SUPPORT 1 /* Define to 1 if you have the ANSI C header files. */ #define STDC_HEADERS 1 /* Version number of package */ #define VERSION "3.0.0" /* Define to 1 if the X Window System is missing or not being used. */ /* #undef X_DISPLAY_MISSING */ #endif //USD_CONFIG_H ukui-settings-daemon/common/eggaccelerators.c0000664000175000017500000006366315167655063020376 0ustar fengfeng/* -*- Mode: C; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "config.h" #include "eggaccelerators.h" #include #include #include #include #include enum { EGG_MODMAP_ENTRY_SHIFT = 0, EGG_MODMAP_ENTRY_LOCK = 1, EGG_MODMAP_ENTRY_CONTROL = 2, EGG_MODMAP_ENTRY_MOD1 = 3, EGG_MODMAP_ENTRY_MOD2 = 4, EGG_MODMAP_ENTRY_MOD3 = 5, EGG_MODMAP_ENTRY_MOD4 = 6, EGG_MODMAP_ENTRY_MOD5 = 7, EGG_MODMAP_ENTRY_LAST = 8 }; #define MODMAP_ENTRY_TO_MODIFIER(x) (1 << (x)) typedef struct { EggVirtualModifierType mapping[EGG_MODMAP_ENTRY_LAST]; } EggModmap; const EggModmap* egg_keymap_get_modmap (GdkKeymap *keymap); static inline gboolean is_alt (const gchar *string) { return ((string[0] == '<') && (string[1] == 'a' || string[1] == 'A') && (string[2] == 'l' || string[2] == 'L') && (string[3] == 't' || string[3] == 'T') && (string[4] == '>')); } static inline gboolean is_ctl (const gchar *string) { return ((string[0] == '<') && (string[1] == 'c' || string[1] == 'C') && (string[2] == 't' || string[2] == 'T') && (string[3] == 'l' || string[3] == 'L') && (string[4] == '>')); } static inline gboolean is_modx (const gchar *string) { return ((string[0] == '<') && (string[1] == 'm' || string[1] == 'M') && (string[2] == 'o' || string[2] == 'O') && (string[3] == 'd' || string[3] == 'D') && (string[4] >= '1' && string[4] <= '5') && (string[5] == '>')); } static inline gboolean is_ctrl (const gchar *string) { return ((string[0] == '<') && (string[1] == 'c' || string[1] == 'C') && (string[2] == 't' || string[2] == 'T') && (string[3] == 'r' || string[3] == 'R') && (string[4] == 'l' || string[4] == 'L') && (string[5] == '>')); } static inline gboolean is_shft (const gchar *string) { return ((string[0] == '<') && (string[1] == 's' || string[1] == 'S') && (string[2] == 'h' || string[2] == 'H') && (string[3] == 'f' || string[3] == 'F') && (string[4] == 't' || string[4] == 'T') && (string[5] == '>')); } static inline gboolean is_shift (const gchar *string) { return ((string[0] == '<') && (string[1] == 's' || string[1] == 'S') && (string[2] == 'h' || string[2] == 'H') && (string[3] == 'i' || string[3] == 'I') && (string[4] == 'f' || string[4] == 'F') && (string[5] == 't' || string[5] == 'T') && (string[6] == '>')); } static inline gboolean is_control (const gchar *string) { return ((string[0] == '<') && (string[1] == 'c' || string[1] == 'C') && (string[2] == 'o' || string[2] == 'O') && (string[3] == 'n' || string[3] == 'N') && (string[4] == 't' || string[4] == 'T') && (string[5] == 'r' || string[5] == 'R') && (string[6] == 'o' || string[6] == 'O') && (string[7] == 'l' || string[7] == 'L') && (string[8] == '>')); } static inline gboolean is_release (const gchar *string) { return ((string[0] == '<') && (string[1] == 'r' || string[1] == 'R') && (string[2] == 'e' || string[2] == 'E') && (string[3] == 'l' || string[3] == 'L') && (string[4] == 'e' || string[4] == 'E') && (string[5] == 'a' || string[5] == 'A') && (string[6] == 's' || string[6] == 'S') && (string[7] == 'e' || string[7] == 'E') && (string[8] == '>')); } static inline gboolean is_meta (const gchar *string) { return ((string[0] == '<') && (string[1] == 'm' || string[1] == 'M') && (string[2] == 'e' || string[2] == 'E') && (string[3] == 't' || string[3] == 'T') && (string[4] == 'a' || string[4] == 'A') && (string[5] == '>')); } static inline gboolean is_super (const gchar *string) { return ((string[0] == '<') && (string[1] == 's' || string[1] == 'S') && (string[2] == 'u' || string[2] == 'U') && (string[3] == 'p' || string[3] == 'P') && (string[4] == 'e' || string[4] == 'E') && (string[5] == 'r' || string[5] == 'R') && (string[6] == '>')); } static inline gboolean is_win (const gchar *string) { return ((string[0] == '<') && (string[1] == 'w' || string[1] == 'W') && (string[2] == 'i' || string[2] == 'I') && (string[3] == 'n' || string[3] == 'N') && (string[4] == '>')); } static inline gboolean is_hyper (const gchar *string) { return ((string[0] == '<') && (string[1] == 'h' || string[1] == 'H') && (string[2] == 'y' || string[2] == 'Y') && (string[3] == 'p' || string[3] == 'P') && (string[4] == 'e' || string[4] == 'E') && (string[5] == 'r' || string[5] == 'R') && (string[6] == '>')); } static inline gboolean is_primary(const gchar* string) { return ((string[0] == '<') && (string[1] == 'p' || string[1] == 'P') && (string[2] == 'r' || string[2] == 'R') && (string[3] == 'i' || string[3] == 'I') && (string[4] == 'm' || string[4] == 'M') && (string[5] == 'a' || string[5] == 'A') && (string[6] == 'r' || string[6] == 'R') && (string[7] == 'y' || string[7] == 'Y') && (string[8] == '>')); } static inline gboolean is_keycode (const gchar *string) { return ((string[0] == '0') && (string[1] == 'x')); } /** * egg_accelerator_parse_virtual: * @accelerator: string representing an accelerator * @accelerator_key: return location for accelerator keyval * @accelerator_codes: return location for a 0-terminated array * of accelerator keycodes * @accelerator_mods: return location for accelerator modifier mask * * Parses a string representing a virtual accelerator. The format * looks like "<Control>a" or "<Shift><Alt>F1" or * "<Release>z" (the last one is for key release). The parser * is fairly liberal and allows lower or upper case, and also * abbreviations such as "<Ctl>" and "<Ctrl>". * * If the parse fails, @accelerator_key and @accelerator_mods will * be set to 0 (zero) and %FALSE will be returned. If the string contains * only modifiers, @accelerator_key will be set to 0 but %TRUE will be * returned. * * The virtual vs. concrete accelerator distinction is a relic of * how the X Window System works; there are modifiers Mod2-Mod5 that * can represent various keyboard keys (numlock, meta, hyper, etc.), * the virtual modifier represents the keyboard key, the concrete * modifier the actual Mod2-Mod5 bits in the key press event. * * Returns: %TRUE on success. */ gboolean egg_accelerator_parse_virtual (const gchar *accelerator, guint *accelerator_key, guint **accelerator_codes, EggVirtualModifierType *accelerator_mods) { guint keyval; GdkModifierType mods; gint len; gboolean bad_keyval; if (accelerator_key) *accelerator_key = 0; if (accelerator_mods) *accelerator_mods = 0; if (accelerator_codes) *accelerator_codes = NULL; g_return_val_if_fail (accelerator != NULL, FALSE); bad_keyval = FALSE; keyval = 0; mods = 0; len = strlen (accelerator); while (len) { if (*accelerator == '<') { if (len >= 9 && is_release (accelerator)) { accelerator += 9; len -= 9; mods |= EGG_VIRTUAL_RELEASE_MASK; } else if (len >= 9 && is_primary (accelerator)) { accelerator += 9; len -= 9; mods |= EGG_VIRTUAL_CONTROL_MASK; } else if (len >= 9 && is_control (accelerator)) { accelerator += 9; len -= 9; mods |= EGG_VIRTUAL_CONTROL_MASK; } else if (len >= 7 && is_shift (accelerator)) { accelerator += 7; len -= 7; mods |= EGG_VIRTUAL_SHIFT_MASK; } else if (len >= 6 && is_shft (accelerator)) { accelerator += 6; len -= 6; mods |= EGG_VIRTUAL_SHIFT_MASK; } else if (len >= 6 && is_ctrl (accelerator)) { accelerator += 6; len -= 6; mods |= EGG_VIRTUAL_CONTROL_MASK; } else if (len >= 6 && is_modx (accelerator)) { static const guint mod_vals[] = { EGG_VIRTUAL_ALT_MASK, EGG_VIRTUAL_MOD2_MASK, EGG_VIRTUAL_MOD3_MASK, EGG_VIRTUAL_MOD4_MASK, EGG_VIRTUAL_MOD5_MASK }; len -= 6; accelerator += 4; mods |= mod_vals[*accelerator - '1']; accelerator += 2; } else if (len >= 5 && is_ctl (accelerator)) { accelerator += 5; len -= 5; mods |= EGG_VIRTUAL_CONTROL_MASK; } else if (len >= 5 && is_alt (accelerator)) { accelerator += 5; len -= 5; mods |= EGG_VIRTUAL_ALT_MASK; } else if (len >= 6 && is_meta (accelerator)) { accelerator += 6; len -= 6; mods |= EGG_VIRTUAL_META_MASK; } else if (len >= 7 && is_hyper (accelerator)) { accelerator += 7; len -= 7; mods |= EGG_VIRTUAL_HYPER_MASK; } else if (len >= 7 && is_super (accelerator)) { accelerator += 7; len -= 7; mods |= EGG_VIRTUAL_SUPER_MASK; } else if (len >= 5 && is_win (accelerator)) { accelerator += 5; len -= 5; mods |= EGG_VIRTUAL_MOD4_MASK; } else { gchar last_ch; last_ch = *accelerator; while (last_ch && last_ch != '>') { last_ch = *accelerator; accelerator += 1; len -= 1; } } } else { if(len == 1) { if(g_strcmp0(accelerator, "A") == 0) keyval = gdk_keyval_from_name ("a"); else if(g_strcmp0(accelerator, "B") == 0) keyval = gdk_keyval_from_name ("b"); else if(g_strcmp0(accelerator, "C") == 0) keyval = gdk_keyval_from_name ("c"); else if(g_strcmp0(accelerator, "D") == 0) keyval = gdk_keyval_from_name ("d"); else if(g_strcmp0(accelerator, "E") == 0) keyval = gdk_keyval_from_name ("e"); else if(g_strcmp0(accelerator, "F") == 0) keyval = gdk_keyval_from_name ("f"); else if(g_strcmp0(accelerator, "G") == 0) keyval = gdk_keyval_from_name ("g"); else if(g_strcmp0(accelerator, "H") == 0) keyval = gdk_keyval_from_name ("h"); else if(g_strcmp0(accelerator, "I") == 0) keyval = gdk_keyval_from_name ("i"); else if(g_strcmp0(accelerator, "J") == 0) keyval = gdk_keyval_from_name ("j"); else if(g_strcmp0(accelerator, "K") == 0) keyval = gdk_keyval_from_name ("k"); else if(g_strcmp0(accelerator, "L") == 0) keyval = gdk_keyval_from_name ("l"); else if(g_strcmp0(accelerator, "M") == 0) keyval = gdk_keyval_from_name ("m"); else if(g_strcmp0(accelerator, "N") == 0) keyval = gdk_keyval_from_name ("n"); else if(g_strcmp0(accelerator, "O") == 0) keyval = gdk_keyval_from_name ("o"); else if(g_strcmp0(accelerator, "P") == 0) keyval = gdk_keyval_from_name ("p"); else if(g_strcmp0(accelerator, "Q") == 0) keyval = gdk_keyval_from_name ("q"); else if(g_strcmp0(accelerator, "R") == 0) keyval = gdk_keyval_from_name ("r"); else if(g_strcmp0(accelerator, "S") == 0) keyval = gdk_keyval_from_name ("s"); else if(g_strcmp0(accelerator, "T") == 0) keyval = gdk_keyval_from_name ("t"); else if(g_strcmp0(accelerator, "U") == 0) keyval = gdk_keyval_from_name ("u"); else if(g_strcmp0(accelerator, "V") == 0) keyval = gdk_keyval_from_name ("v"); else if(g_strcmp0(accelerator, "W") == 0) keyval = gdk_keyval_from_name ("w"); else if(g_strcmp0(accelerator, "X") == 0) keyval = gdk_keyval_from_name ("x"); else if(g_strcmp0(accelerator, "Y") == 0) keyval = gdk_keyval_from_name ("y"); else if(g_strcmp0(accelerator, "Z") == 0) keyval = gdk_keyval_from_name ("z"); else if(g_strcmp0(accelerator, ".") == 0) keyval = gdk_keyval_from_name ("period"); else if(g_strcmp0(accelerator, ",") == 0) keyval = gdk_keyval_from_name ("comma"); else keyval = gdk_keyval_from_name (accelerator); } else if(len == 2 || len == 3) { if(g_strcmp0(accelerator, "Esc") == 0) keyval = gdk_keyval_from_name ("Escape"); else if(g_strcmp0(accelerator, "f1") == 0) keyval = gdk_keyval_from_name ("F1"); else if(g_strcmp0(accelerator, "f2") == 0) keyval = gdk_keyval_from_name ("F2"); else if(g_strcmp0(accelerator, "f3") == 0) keyval = gdk_keyval_from_name ("F3"); else if(g_strcmp0(accelerator, "f4") == 0) keyval = gdk_keyval_from_name ("F4"); else if(g_strcmp0(accelerator, "f5") == 0) keyval = gdk_keyval_from_name ("F5"); else if(g_strcmp0(accelerator, "f6") == 0) keyval = gdk_keyval_from_name ("F6"); else if(g_strcmp0(accelerator, "f7") == 0) keyval = gdk_keyval_from_name ("F7"); else if(g_strcmp0(accelerator, "f8") == 0) keyval = gdk_keyval_from_name ("F8"); else if(g_strcmp0(accelerator, "f9") == 0) keyval = gdk_keyval_from_name ("F9"); else if(g_strcmp0(accelerator, "f10") == 0) keyval = gdk_keyval_from_name ("F10"); else if(g_strcmp0(accelerator, "f11") == 0) keyval = gdk_keyval_from_name ("F11"); else if(g_strcmp0(accelerator, "f12") == 0) keyval = gdk_keyval_from_name ("F12"); else keyval = gdk_keyval_from_name (accelerator); }else keyval = gdk_keyval_from_name (accelerator); if (keyval == 0) { /* If keyval is 0, then maybe it's a keycode. Check for 0x## */ if (len >= 4 && is_keycode (accelerator)) { char keystring[5]; gchar *endptr; gint tmp_keycode; memcpy (keystring, accelerator, 4); keystring [4] = '\000'; tmp_keycode = strtol (keystring, &endptr, 16); if (endptr == NULL || *endptr != '\000') { bad_keyval = TRUE; } else if (accelerator_codes != NULL) { /* 0x00 is an invalid keycode too. */ if (tmp_keycode == 0) { bad_keyval = TRUE; } else { *accelerator_codes = g_new0 (guint, 2); (*accelerator_codes)[0] = tmp_keycode; } } } else { bad_keyval = TRUE; } } else if (accelerator_codes != NULL) { GdkKeymapKey *keys; gint n_keys, i, j; if (!gdk_keymap_get_entries_for_keyval (gdk_keymap_get_default(), keyval, &keys, &n_keys)) { bad_keyval = TRUE; } else { *accelerator_codes = g_new0 (guint, n_keys + 1); for (i = 0, j = 0; i < n_keys; ++i) { if (keys[i].level == 0) (*accelerator_codes)[j++] = keys[i].keycode; } if (j == 0) { g_free (*accelerator_codes); *accelerator_codes = NULL; bad_keyval = TRUE; } g_free (keys); } } accelerator += len; len -= len; } } if (accelerator_key) *accelerator_key = gdk_keyval_to_lower (keyval); if (accelerator_mods) *accelerator_mods = mods; return !bad_keyval; } /** * egg_virtual_accelerator_name: * @accelerator_key: accelerator keyval * @accelerator_mods: accelerator modifier mask * @returns: a newly-allocated accelerator name * * Converts an accelerator keyval and modifier mask * into a string parseable by egg_accelerator_parse_virtual(). * For example, if you pass in #GDK_q and #EGG_VIRTUAL_CONTROL_MASK, * this function returns "<Control>q". * * The caller of this function must free the returned string. */ gchar* egg_virtual_accelerator_name (guint accelerator_key, guint keycode, EggVirtualModifierType accelerator_mods) { gchar *gtk_name; GdkModifierType gdkmods = 0; egg_keymap_resolve_virtual_modifiers (NULL, accelerator_mods, &gdkmods); gtk_name = gtk_accelerator_name (accelerator_key, gdkmods); if (!accelerator_key) { gchar *name; name = g_strdup_printf ("%s0x%02x", gtk_name, keycode); g_free (gtk_name); return name; } return gtk_name; } /** * egg_virtual_accelerator_label: * @accelerator_key: accelerator keyval * @accelerator_mods: accelerator modifier mask * @returns: a newly-allocated accelerator label * * Converts an accelerator keyval and modifier mask * into a (possibly translated) string that can be displayed to * a user. * For example, if you pass in #GDK_q and #EGG_VIRTUAL_CONTROL_MASK, * and you use a German locale, this function returns "Strg+Q". * * The caller of this function must free the returned string. */ gchar* egg_virtual_accelerator_label (guint accelerator_key, guint keycode, EggVirtualModifierType accelerator_mods) { gchar *gtk_label; GdkModifierType gdkmods = 0; egg_keymap_resolve_virtual_modifiers (NULL, accelerator_mods, &gdkmods); gtk_label = gtk_accelerator_get_label (accelerator_key, gdkmods); if (!accelerator_key) { gchar *label; label = g_strdup_printf ("%s0x%02x", gtk_label, keycode); g_free (gtk_label); return label; } return gtk_label; } void egg_keymap_resolve_virtual_modifiers (GdkKeymap *keymap, EggVirtualModifierType virtual_mods, GdkModifierType *concrete_mods) { GdkModifierType concrete; int i; const EggModmap *modmap; g_return_if_fail (concrete_mods != NULL); g_return_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap)); modmap = egg_keymap_get_modmap (keymap); /* Not so sure about this algorithm. */ concrete = 0; for (i = 0; i < EGG_MODMAP_ENTRY_LAST; ++i) { if (modmap->mapping[i] & virtual_mods) concrete |= MODMAP_ENTRY_TO_MODIFIER (i); } *concrete_mods = concrete; } void egg_keymap_virtualize_modifiers (GdkKeymap *keymap, GdkModifierType concrete_mods, EggVirtualModifierType *virtual_mods) { GdkModifierType virtual; int i; const EggModmap *modmap; g_return_if_fail (virtual_mods != NULL); g_return_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap)); modmap = egg_keymap_get_modmap (keymap); /* Not so sure about this algorithm. */ virtual = 0; for (i = 0; i < EGG_MODMAP_ENTRY_LAST; ++i) { if (MODMAP_ENTRY_TO_MODIFIER (i) & concrete_mods) { EggVirtualModifierType cleaned; cleaned = modmap->mapping[i] & ~(EGG_VIRTUAL_MOD2_MASK | EGG_VIRTUAL_MOD3_MASK | EGG_VIRTUAL_MOD4_MASK | EGG_VIRTUAL_MOD5_MASK); if (cleaned != 0) { virtual |= cleaned; } else { /* Rather than dropping mod2->mod5 if not bound, * go ahead and use the concrete names */ virtual |= modmap->mapping[i]; } } } *virtual_mods = virtual; } static void reload_modmap (GdkKeymap *keymap, EggModmap *modmap) { XModifierKeymap *xmodmap; int map_size; int i; /* FIXME multihead */ xmodmap = XGetModifierMapping (gdk_x11_get_default_xdisplay ()); memset (modmap->mapping, 0, sizeof (modmap->mapping)); /* there are 8 modifiers in the order shift, shift lock, * control, mod1-5 with up to max_keypermod bindings each */ map_size = 8 * xmodmap->max_keypermod; for (i = 3 * xmodmap->max_keypermod; i < map_size; ++i) { /* get the key code at this point in the map, * see if its keysym is one we're interested in */ int keycode = xmodmap->modifiermap[i]; GdkKeymapKey *keys; guint *keyvals; int n_entries; int j; EggVirtualModifierType mask; keys = NULL; keyvals = NULL; n_entries = 0; gdk_keymap_get_entries_for_keycode (keymap, keycode, &keys, &keyvals, &n_entries); mask = 0; for (j = 0; j < n_entries; ++j) { if (keyvals[j] == GDK_KEY_Num_Lock) mask |= EGG_VIRTUAL_NUM_LOCK_MASK; else if (keyvals[j] == GDK_KEY_Scroll_Lock) mask |= EGG_VIRTUAL_SCROLL_LOCK_MASK; else if (keyvals[j] == GDK_KEY_Meta_L || keyvals[j] == GDK_KEY_Meta_R) mask |= EGG_VIRTUAL_META_MASK; else if (keyvals[j] == GDK_KEY_Hyper_L || keyvals[j] == GDK_KEY_Hyper_R) mask |= EGG_VIRTUAL_HYPER_MASK; else if (keyvals[j] == GDK_KEY_Super_L || keyvals[j] == GDK_KEY_Super_R) mask |= EGG_VIRTUAL_SUPER_MASK; else if (keyvals[j] == GDK_KEY_Mode_switch) mask |= EGG_VIRTUAL_MODE_SWITCH_MASK; } /* Mod1Mask is 1 << 3 for example, i.e. the * fourth modifier, i / keyspermod is the modifier * index */ modmap->mapping[i/xmodmap->max_keypermod] |= mask; g_free (keyvals); g_free (keys); } /* Add in the not-really-virtual fixed entries */ modmap->mapping[EGG_MODMAP_ENTRY_SHIFT] |= EGG_VIRTUAL_SHIFT_MASK; modmap->mapping[EGG_MODMAP_ENTRY_CONTROL] |= EGG_VIRTUAL_CONTROL_MASK; modmap->mapping[EGG_MODMAP_ENTRY_LOCK] |= EGG_VIRTUAL_LOCK_MASK; modmap->mapping[EGG_MODMAP_ENTRY_MOD1] |= EGG_VIRTUAL_ALT_MASK; modmap->mapping[EGG_MODMAP_ENTRY_MOD2] |= EGG_VIRTUAL_MOD2_MASK; modmap->mapping[EGG_MODMAP_ENTRY_MOD3] |= EGG_VIRTUAL_MOD3_MASK; modmap->mapping[EGG_MODMAP_ENTRY_MOD4] |= EGG_VIRTUAL_MOD4_MASK; modmap->mapping[EGG_MODMAP_ENTRY_MOD5] |= EGG_VIRTUAL_MOD5_MASK; XFreeModifiermap (xmodmap); } const EggModmap* egg_keymap_get_modmap (GdkKeymap *keymap) { EggModmap *modmap; if (keymap == NULL) keymap = gdk_keymap_get_default (); /* This is all a hack, much simpler when we can just * modify GDK directly. */ modmap = g_object_get_data (G_OBJECT (keymap), "egg-modmap"); if (modmap == NULL) { modmap = g_new0 (EggModmap, 1); /* FIXME modify keymap change events with an event filter * and force a reload if we get one */ reload_modmap (keymap, modmap); g_object_set_data_full (G_OBJECT (keymap), "egg-modmap", modmap, g_free); } g_assert (modmap != NULL); return modmap; } ukui-settings-daemon/common/touch-calibrate.h0000664000175000017500000001114415167655063020302 0ustar fengfeng/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * Copyright (C) 2023 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * */ #ifndef TOUCHCALIBRATE_H #define TOUCHCALIBRATE_H #include #include #include #include #include #include #include #include #include extern "C"{ #include "clib-syslog.h" } #include "usd_base_class.h" //添加product 识别,但对于同型号触摸屏product id和 name 完全一致,无法区分 struct Product { int32_t vid = 0; int32_t pid = 0; bool isValid = false; //有效性,是否需要有效匹配product bool operator ==(const Product& other) { return (this->vid == other.vid && this->pid == other.pid); } bool operator !=(const Product& other) { return (this->vid != other.vid || this->pid != other.pid); } }; struct TouchDevice { QString name; QString node; int id; int width = 0; int height = 0; bool isMapped = false; //已映射 Product product; }; struct ScreenInfo { QString name; int width = 0; int height = 0; bool isMapped = false; }; struct TouchConfig { QString sTouchName; //触摸屏的名称 QString sTouchSerial; //触摸屏的序列号 QString sMonitorName; //显示器的名称 Product product; //配置存储的ProductId };//配置文件中记录的映射关系信息 typedef QSharedPointer TouchDevicePtr; typedef QList TouchDeviceList; typedef QSharedPointer ScreenInfoPtr; typedef QMap ScreenInfoMap; typedef QSharedPointer TouchConfigPtr; typedef QList TouchConfigList; class TouchCalibrate : public QObject { Q_OBJECT public: explicit TouchCalibrate(const QString& path, QObject *parent = nullptr); ~TouchCalibrate(); private: bool initDisplay(); /** * @brief 获取已连接屏幕信息 */ void getScreenList(); /** * @brief 获取触摸设备信息 */ void getTouchDeviceList(); /** * @brief 获取屏幕映射信息 */ void getTouchConfigure(); /** * @brief touchscreen 映射 */ void calibrateTouchScreen(); /** * @brief tablet 映射 */ void calibrateTablet(); /** * @brief calibrateDevice * @param id 触摸设备ID * @param output 屏幕名称 */ void calibrateDevice(int id, const QString &output); /** * @brief checkMatch * @param output_width * @param output_height * @param input_width * @param input_height * @return 尺寸比较 */ bool checkMatch(double output_width, double output_height, double input_width, double input_height); /** * @brief 获取设备节点 * @param id * @return */ QString getDeviceNode(int id); /** * @brief 获取触摸设备尺寸 * @param node * @param width * @param height */ void getTouchSize(const char *node, int &width, int &height); /** * @brief 获取设备productId ,分为vid,pid * @param id * @return */ QVariantList getDeviceProductId(int id); /** * @brief createTouchDevice * @param device * @return */ void addTouchDevice(const XDeviceInfo& device, TouchDeviceList& touchList); /** * @brief autoMaticMapping 触摸笔,触摸屏,非配置部分映射 * @param touchMap 触摸设备 * @param screenMap 屏幕信息 */ void autoMaticMapping(TouchDeviceList& touchList, ScreenInfoMap& screenMap); public: void calibrate(); Q_SIGNALS: private: Display *m_display = nullptr; QString m_touchConfigPath; ScreenInfoMap m_screenInfoMap; TouchDeviceList m_touchScreenList; TouchDeviceList m_tabletList; TouchConfigList m_touchConfigList; }; #endif // TOUCHCALIBRATE_H ukui-settings-daemon/common/plugin-interface.h0000664000175000017500000000205215167655063020466 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef PLUGIN_INTERFACE_H #define PLUGIN_INTERFACE_H #include namespace UkuiSettingsDaemon { class PluginInterface; } class PluginInterface { public: virtual ~PluginInterface() {} virtual void activate () = 0; virtual void deactivate () = 0; }; #endif // PLUGIN_INTERFACE_H ukui-settings-daemon/common/plugin-manager-interface.h0000664000175000017500000000206015167655063022075 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef BASEMANAGER_H #define BASEMANAGER_H #include namespace UkuiSettingsDaemon { class ManagerInterface; } class ManagerInterface: public QObject { Q_OBJECT public: virtual ~ManagerInterface() {} virtual bool Start () = 0; virtual void Stop () = 0; }; #endif // BASEMANAGER_H ukui-settings-daemon/common/common.pri0000664000175000017500000000322315167655063017066 0ustar fengfengQT += core gui dbus gui-private gui core-private CONFIG += c++20 no_keywords gui-private link_pkgconfig xrandr CONFIG -= app_bundle INCLUDEPATH += -I $$PWD/ PLUGIN_INSTALL_DIRS = $$[QT_INSTALL_LIBS]/ukui-settings-daemon EXTRA_CFLAGS +=-Wno-date-time PKGCONFIG += glib-2.0 gio-2.0 libxklavier x11 xrandr xtst atk gdk-3.0 gtk+-3.0 xi gudev-1.0 exists(/usr/include/kysdk/kysdk-system/libkysysinfo.h) { DEFINES += KY_SDK_SYSINFO PKGCONFIG += kysdk-sysinfo } exists(/usr/include/kysdk/kysdk-system/libkycpu.h) { DEFINES += KY_SDK_HARDWARE PKGCONFIG += kysdk-hardware } QMAKE_CXXFLAGS += -Wno-unused-parameter SOURCES += \ $$PWD/clib-syslog.c \ $$PWD/QGSettings/qconftype.cpp \ $$PWD/QGSettings/qgsettings.cpp \ $$PWD/rfkillswitch.cpp \ $$PWD/touch-calibrate.cpp \ $$PWD/usd_base_class.cpp \ $$PWD/xeventmonitor.cpp \ $$PWD/eggaccelerators.c \ $$PWD/ukui-input-helper.c \ $$PWD/ukui-keygrab.cpp HEADERS += \ $$PWD/clib-syslog.h \ $$PWD/plugin-interface.h \ $$PWD/QGSettings/qconftype.h \ $$PWD/QGSettings/qgsettings.h \ $$PWD/rfkillswitch.h \ $$PWD/touch-calibrate.h \ $$PWD/usd_base_class.h \ $$PWD/usd_global_define.h \ $$PWD/xeventmonitor.h \ $$PWD/eggaccelerators.h \ $$PWD/ukui-input-helper.h \ $$PWD/ukui-keygrab.h \ $$PWD/config.h \ $$PWD/xrandroutput.h \ $$PWD/plugin-manager-interface.h \ $$PWD/x11-head.h RESOURCES += \ $$PWD/ukui_icon.qrc ukui-settings-daemon/common/ukui-input-helper.c0000664000175000017500000000732515167655063020624 0ustar fengfeng/* -*- Mode: C; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "ukui-input-helper.h" #include #include #include #include gboolean supports_xinput_devices (void) { gint op_code, event, error; return XQueryExtension (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "XInputExtension", &op_code, &event, &error); } static gboolean device_has_property (XDevice *device, const char *property_name) { Atom realtype, prop; int realformat; unsigned long nitems, bytes_after; unsigned char *data; prop = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), property_name, True); if (!prop) return FALSE; gdk_x11_display_error_trap_push (gdk_display_get_default()); if ((XGetDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), device, prop, 0, 1, False, XA_INTEGER, &realtype, &realformat, &nitems, &bytes_after, &data) == Success) && (realtype != None)) { gdk_x11_display_error_trap_pop_ignored (gdk_display_get_default()); XFree (data); return TRUE; } gdk_x11_display_error_trap_pop_ignored (gdk_display_get_default()); return FALSE; } XDevice* device_is_touchpad (XDeviceInfo *deviceinfo) { XDevice *device; if (deviceinfo->type != XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), XI_TOUCHPAD, True)) return NULL; gdk_x11_display_error_trap_push (gdk_display_get_default()); device = XOpenDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), deviceinfo->id); if (gdk_x11_display_error_trap_pop (gdk_display_get_default()) || (device == NULL)) return NULL; if (device_has_property (device, "libinput Tapping Enabled") || device_has_property (device, "Synaptics Off")) { return device; } XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), device); return NULL; } gboolean touchpad_is_present (void) { XDeviceInfo *device_info; int n_devices; int i; gboolean retval; if (supports_xinput_devices () == FALSE) return TRUE; retval = FALSE; device_info = XListInputDevices (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), &n_devices); if (device_info == NULL) return FALSE; for (i = 0; i < n_devices; i++) { XDevice *device; device = device_is_touchpad (&device_info[i]); if (device != NULL) { retval = TRUE; break; } } if (device_info != NULL) XFreeDeviceList (device_info); return retval; } ukui-settings-daemon/common/clib-syslog.c0000664000175000017500000003307615167655063017466 0ustar fengfeng/* -*- Mode: C; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "clib-syslog.h" #include static char sysCategory[128] = {0}; static int sysFacility = 0; void syslog_init(const char *category, int facility) { if (NULL == category) { return; } memset(sysCategory, 0, sizeof sysCategory); strncpy(sysCategory, category, sizeof sysCategory - 1); sysFacility = facility; } //LOG_DEBUG,最低级 void syslog_info(int logLevel, const char *moduleName, const char *fileName, const char *functionName, int line, const char* fmt, ...) { //if (logLevel > LOG_LEVEL) return; static char hadInit=0; char buf[2048] = {0}; char *logLevelstr = NULL; unsigned long tagLen = 0; va_list para; va_start(para, fmt); if (!hadInit){ hadInit = 1; syslog_init("ukui-settings-daemon", LOG_LOCAL6); } memset(buf, 0, sizeof buf); openlog("", LOG_NDELAY, sysFacility); switch (logLevel) { case LOG_EMERG: logLevelstr = "EMERG"; break; case LOG_ALERT: logLevelstr = "ALERT"; break; case LOG_CRIT: logLevelstr = "CRIT"; break; case LOG_ERR: logLevelstr = "ERROR"; break; case LOG_WARNING: logLevelstr = "WARNING"; break; case LOG_NOTICE: logLevelstr = "NOTICE"; break; case LOG_INFO: logLevelstr = "INFO"; break; case LOG_DEBUG: logLevelstr = "DEBUG"; break; default: logLevelstr = "UNKNOWN"; } snprintf(buf, sizeof buf - 1, "%s [%s] %s->%s %s line:%-5d ", logLevelstr, sysCategory, moduleName,fileName, functionName, line); tagLen = strlen(buf); vsnprintf(buf + tagLen, sizeof buf - 1 - tagLen, (const char*)fmt, para); syslog(logLevel,"%s",buf); printf ("%s\n",buf); closelog(); va_end(para); } //////////////////flock//////////////////////////// /// \brief is_leap_year /// \param year /// \return /// int is_leap_year(int year){ if(year%400==0 || (year%4==0 && year%100!=0)){ return 1; } return 0; } /// /// \brief nolocks_localtime /// \param tmp /// \param t /// \param tz /// \param dst /// void nolocks_localtime(struct tm *tmp, time_t t, time_t tz, int dst) { const time_t secs_min = 60; const time_t secs_hour = 3600; const time_t secs_day = 3600*24; t -= tz; /* Adjust for timezone. */ t += 3600*dst; /* Adjust for daylight time. */ time_t days = t / secs_day; /* Days passed since epoch. */ time_t seconds = t % secs_day; /* Remaining seconds. */ tmp->tm_isdst = dst; tmp->tm_hour = seconds / secs_hour; tmp->tm_min = (seconds % secs_hour) / secs_min; tmp->tm_sec = (seconds % secs_hour) % secs_min; /* 1/1/1970 was a Thursday, that is, day 4 from the POV of the tm structure * where sunday = 0, so to calculate the day of the week we have to add 4 * and take the modulo by 7. */ tmp->tm_wday = (days+4)%7; /* Calculate the current year. */ tmp->tm_year = 1970; while(1) { /* Leap years have one day more. */ time_t days_this_year = 365 + is_leap_year(tmp->tm_year); if (days_this_year > days) break; days -= days_this_year; tmp->tm_year++; } tmp->tm_yday = days; /* Number of day of the current year. */ /* We need to calculate in which month and day of the month we are. To do * so we need to skip days according to how many days there are in each * month, and adjust for the leap year that has one more day in February. */ int mdays[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; mdays[1] += is_leap_year(tmp->tm_year); tmp->tm_mon = 0; while(days >= mdays[tmp->tm_mon]) { days -= mdays[tmp->tm_mon]; tmp->tm_mon++; } tmp->tm_mday = days+1; /* Add 1 since our 'days' is zero-based. */ tmp->tm_year -= 1970; /* Surprisingly tm_year is year-1900. */ } uint verify_file(char *pFileName) { return !strncmp(pFileName, "/home", strlen("/home")); } /// /// \brief CreateDir /// \param sPathName /// \return /// //使用realpath设计缺陷,指定缓冲区大小为PATH_MAX, 而非定义一个常量。 //参考:https://www.man7.org/linux/man-pages/man3/realpath.3.html (BUGS) int CreateDir(const char *sPathName) { char DirName[256]; char canonical_filename[PATH_MAX] = {""}; strcpy(DirName, sPathName); int i,len = strlen(DirName); for(i=1; i 0) { // canonical_filename = malloc(path_size); // if (canonical_filename == NULL) { // return -ENOMEM; // } memset(canonical_filename,0,path_size); realpath_res = realpath(DirName, canonical_filename); } if(strlen(canonical_filename)<=0){ return -1; } if(!verify_file(canonical_filename)){ return -1; } if(mkdir(canonical_filename, 0755)==-1) { // printf("mkdir canonical_filename :%s error\n",canonical_filename); return -1; } else { // printf("DirName %s create OK\n",DirName); } } else{ // printf("Dir %s exist\n",DirName); } DirName[i] = '/'; } } return 0; } /// /// \brief checkLogDir /// \param dir /// \param logFileName /// void checkLogDir(const char *dir, char *logFileName){ static uint hadCreaterDir = 0; char *path; char logDir[128]=""; if (hadCreaterDir) { path = getenv("HOME"); snprintf(logDir,sizeof(logDir),"%s/.log/%s/",path,dir); memcpy(logFileName, logDir, strlen(logDir)); return; } hadCreaterDir = 1; path = getenv("HOME"); snprintf(logDir,sizeof(logDir),"%s/.log/%s/",path,dir); if (0 != access(logDir,F_OK)){ CreateDir(logDir); } else { // printf("dir %s exist\n", logDir); } memcpy(logFileName, logDir, strlen(logDir)); } //按照星期进行处理 char getWeek(){ time_t t; struct tm tmTime; time(&t); // localtime_r(&t, tmTime);//虽然线程安全但是容易死锁 nolocks_localtime(&tmTime,t,-8*3600,0); // printf("[%d-%02d-%02d %02d:%02d:%02d]today is %d\n",tmTime.tm_year+1970,tmTime.tm_mon+1,tmTime.tm_mday,tmTime.tm_hour,tmTime.tm_min,tmTime.tm_sec,tmTime.tm_wday); return tmTime.tm_wday; } //加写锁 int wlock(int fd, int wait) { struct flock lock; lock.l_type = F_WRLCK; lock.l_whence = SEEK_SET; lock.l_start = 0; lock.l_len = 0; lock.l_pid = -1; return fcntl(fd, wait ? F_SETLKW : F_SETLK, &lock); } //加读锁 int rlock(int fd, int wait) { struct flock lock; lock.l_type = F_RDLCK; lock.l_whence = SEEK_SET; lock.l_start = 0; lock.l_len = 0; lock.l_pid = -1; return fcntl(fd, wait ? F_SETLKW : F_SETLK, &lock); } //解锁 int ulock(int fd) { struct flock lock; lock.l_type = F_UNLCK; lock.l_whence = SEEK_SET; lock.l_start = 0; lock.l_len = 0; lock.l_pid = -1; return fcntl(fd, F_SETLK, &lock); } /* 以星期为划分,最多存七天的日志 当本次星期时间与上次不一致且并非初始值时,以清空文件的方式打开文件。 由于settings-daemon日志并不频繁,所以不需要进行缓冲区设置。 */ void write_log_to_file(char *buf, __uint16_t buf_len) { static int lastWeekDay = 0xff; static int hadError = 0; int month = 0; int day = 0; const char *pWeekName[7] = {"SUN.log","MON.log","TUE.log","WED.log","THU.log","FRI.log","SAT.log"}; FILE *lockfp; int fd; int writeLen = buf_len; int rtWeekDay; char logFileName[128]; char *plogFile = NULL; char *prealpathRes = NULL; char logMsg[2048]; char readMsg[2048]=""; time_t t; struct tm tmTime; int reWriteTimes = 0; if (hadError) { return; } REWRITE: t = writeLen; time(&t); // localtime_r(&t, tmTime);//虽然线程安全但是容易死锁 memset(logMsg,0x00,sizeof(logMsg)); memset(logFileName,0x00,sizeof(logFileName)); nolocks_localtime(&tmTime,t,-8*3600,0); rtWeekDay = getWeek(); checkLogDir("usd", logFileName); strcat(logFileName,pWeekName[rtWeekDay]); if (0 != access(logFileName, F_OK)) { return; } prealpathRes = realpath(logFileName, plogFile); if(prealpathRes == NULL) { hadError = 1; syslog_info(LOG_ERR, "CORE", __FILE__, __FUNCTION__, __LINE__, "%s", "realpath check fail"); return; } if (/*strlen(prealpathRes) >= sizeof(logFileName) ||*/ !verify_file(prealpathRes)) { free(prealpathRes); prealpathRes = NULL; hadError = 1; syslog_info(LOG_ERR, "CORE", __FILE__, __FUNCTION__, __LINE__, "%s", "strlen check fail"); return; } if(rtWeekDay!=lastWeekDay && lastWeekDay!=0xff){ fd = open(prealpathRes, O_TRUNC | O_RDWR); } else { fd = open(prealpathRes, O_RDWR | O_APPEND, S_IRUSR | S_IWUSR);//去掉 | O_CREAT,不再进行创建 } free(prealpathRes); prealpathRes = NULL; if(fd <= 0) { return; } lastWeekDay = rtWeekDay; if (wlock(fd, 1) == -1) { //加锁失败,可能是因为其他已上锁,需要close操作。 if (fd > 0) { close(fd); } return; } lockfp = fdopen(fd,"w+"); if (lockfp == NULL) { if (fd > 0) { close(fd); } return; } snprintf(logMsg,sizeof(logMsg),"{%04d-%02d-%02d %02d:%02d:%02d}:%s\n",tmTime.tm_year+1970, tmTime.tm_mon+1, tmTime.tm_mday,tmTime.tm_hour, tmTime.tm_min,tmTime.tm_sec,buf); writeLen = write(fd,(const void*)logMsg,strlen(logMsg)); fseek(lockfp,0L,SEEK_SET);//kill程序后,可能会因为资源释放,导致访问底层的malloc异常报错_IO_file_seekoff-》_IO_doallocbuf-》_IO_file_doallocate-》malloc if (fgets(readMsg, sizeof(readMsg), lockfp)) { month = (readMsg[6]-0x30)*10 + readMsg[7]-0x30; day = (readMsg[9]-0x30)*10 + readMsg[10]-0x30; if (month!=(tmTime.tm_mon+1) || day!=tmTime.tm_mday) { if (0 == reWriteTimes) { reWriteTimes++; lastWeekDay=0xfe; fflush(lockfp); ulock(fd); fclose (lockfp); close(fd); goto REWRITE; } } } printf("%s",logMsg); fflush(lockfp); ulock(fd); fclose (lockfp); close(fd); } void syslog_to_self_dir(int logLevel, const char *moduleName, const char *fileName, const char *functionName, int line, const char* fmt, ...) { char buf[2048] = {0}; char *logLevelstr = NULL; unsigned long tagLen = 0; va_list para; va_start(para, fmt); memset(buf, 0, sizeof buf); switch (logLevel) { case LOG_EMERG: logLevelstr = "EMERG"; break; case LOG_ALERT: logLevelstr = "ALERT"; break; case LOG_CRIT: logLevelstr = "CRIT"; break; case LOG_ERR: logLevelstr = "ERROR"; break; case LOG_WARNING: logLevelstr = "WARNING"; break; case LOG_NOTICE: logLevelstr = "NOTICE"; break; case LOG_INFO: logLevelstr = "INFO"; break; case LOG_DEBUG: logLevelstr = "DEBUG"; break; default: logLevelstr = "UNKNOWN"; } snprintf(buf, sizeof buf - 1, "[%s] %s->%s %s line:%-5d", logLevelstr, moduleName,fileName, functionName, line); tagLen = strlen(buf); vsnprintf(buf + tagLen, sizeof buf - 1 - tagLen, (const char*)fmt, para); write_log_to_file(buf,strlen(buf)); va_end(para); } //////////Other function//////////////// int CheckProcessAlive(const char *pName){ int ret = 0; char Cmd[512] = {0}; char *pAck = NULL; char CmdAck[120]; FILE * pPipe; ret = (int)pAck; if (strlen(pName) > 400) { return 0; } //ef列出所有进程,|grep %s | 仅显示含%s的进程, |grep -v grep过滤掉含grep的进程(本条指令),|wc -l 查看行数 sprintf(Cmd, "ps -ef |grep %s|grep -v grep|wc -l",pName); pPipe = popen(Cmd,"r"); if (pPipe) { pAck = fgets(CmdAck,sizeof(CmdAck),pPipe); ret = atoi(CmdAck); pclose(pPipe); } return ret; } ukui-settings-daemon/common/xeventmonitor.cpp0000664000175000017500000001643515167655063020520 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ //#include #include #include #include "xeventmonitor.h" // Virtual button codes that are not defined by X11. #define Button1 1 #define Button2 2 #define Button3 3 #define WheelUp 4 #define WheelDown 5 #define WheelLeft 6 #define WheelRight 7 #define XButton1 8 #define XButton2 9 XEventMonitor *XEventMonitor::instance_ = new XEventMonitor(); const static QVector ModifiersVec{ XK_Control_L, XK_Control_R, XK_Shift_L, XK_Shift_R, XK_Super_L, XK_Super_R, XK_Alt_L, XK_Alt_R }; class XEventMonitorPrivate { public: XEventMonitorPrivate(XEventMonitor *parent); virtual ~XEventMonitorPrivate(); void run(); protected: XEventMonitor *q_ptr; QSet modifiers; bool filterWheelEvent(int detail); static void callback(XPointer trash, XRecordInterceptData* data); void handleRecordEvent(XRecordInterceptData *); void emitButtonSignal(const char *member, xEvent *event); void emitKeySignal(const char *member, xEvent *event); void updateModifier(xEvent *event, bool isAdd); private: Q_DECLARE_PUBLIC(XEventMonitor) }; XEventMonitorPrivate::XEventMonitorPrivate(XEventMonitor *parent) : q_ptr(parent) { } XEventMonitorPrivate::~XEventMonitorPrivate() { } void XEventMonitorPrivate::emitButtonSignal(const char *member, xEvent *event) { int x = event->u.keyButtonPointer.rootX; int y = event->u.keyButtonPointer.rootY; QMetaObject::invokeMethod(q_ptr, member, Qt::DirectConnection, Q_ARG(int, x), Q_ARG(int, y)); } #include void XEventMonitorPrivate::emitKeySignal(const char *member, xEvent *event) { Display *display = XOpenDisplay(NULL); int keyCode = event->u.u.detail; KeySym keySym = XkbKeycodeToKeysym(display, event->u.u.detail, 0, 0); QString keyStrSplice; for(auto modifier : modifiers) { keyStrSplice += QString(XKeysymToString(modifier)) + "+"; } //按键是修饰键 if(ModifiersVec.contains(keySym) && !modifiers.isEmpty()) keyStrSplice.remove(keyStrSplice.length() - 1, 1); else keyStrSplice += XKeysymToString(keySym); QMetaObject::invokeMethod(q_ptr, member, Qt::AutoConnection, Q_ARG(int, keyCode)); QMetaObject::invokeMethod(q_ptr, member, Qt::AutoConnection, Q_ARG(QString, keyStrSplice)); XCloseDisplay(display); } void XEventMonitorPrivate::run() { Display* display = XOpenDisplay(0); if (display == 0) { fprintf(stderr, "unable to open display\n"); return; } // Receive from ALL clients, including future clients. XRecordClientSpec clients = XRecordAllClients; XRecordRange* range = XRecordAllocRange(); if (range == 0) { fprintf(stderr, "unable to allocate XRecordRange\n"); return; } // Receive KeyPress, KeyRelease, ButtonPress, ButtonRelease and MotionNotify events. memset(range, 0, sizeof(XRecordRange)); range->device_events.first = XI_KeyPress; range->device_events.last = MotionNotify; // And create the XRECORD context. XRecordContext context = XRecordCreateContext(display, 0, &clients, 1, &range, 1); if (context == 0) { fprintf(stderr, "XRecordCreateContext failed\n"); return; } XFree(range); XSync(display, True); Display* display_datalink = XOpenDisplay(0); if (display_datalink == 0) { fprintf(stderr, "unable to open second display\n"); XCloseDisplay (display_datalink); return; } if (!XRecordEnableContext(display_datalink, context, callback, (XPointer) this)) { fprintf(stderr, "XRecordEnableContext() failed\n"); XCloseDisplay (display_datalink); return; } XCloseDisplay (display_datalink); } void XEventMonitorPrivate::callback(XPointer ptr, XRecordInterceptData* data) { ((XEventMonitorPrivate *) ptr)->handleRecordEvent(data); } void XEventMonitorPrivate::handleRecordEvent(XRecordInterceptData* data) { if (data->category == XRecordFromServer) { xEvent * event = (xEvent *)data->data; switch (event->u.u.type) { // case ButtonPress: // if (filterWheelEvent(event->u.u.detail)) { // emitButtonSignal("buttonPress", event); // } // break; // case MotionNotify: // emitButtonSignal("buttonDrag", event); // break; // case ButtonRelease: // if (filterWheelEvent(event->u.u.detail)) { // emitButtonSignal("buttonRelease", event); // } // break; // case KeyPress: // updateModifier(event, true); // emitKeySignal("keyPress", event); // break; case XI_KeyRelease: // updateModifier(event, false); // emitKeySignal("keyRelease", event); QMetaObject::invokeMethod(q_ptr, "keyRelease", Qt::AutoConnection, Q_ARG(int, event->u.u.detail)); break; default: break; } } fflush(stdout); XRecordFreeData(data); } bool XEventMonitorPrivate::filterWheelEvent(int detail) { return detail != WheelUp && detail != WheelDown && detail != WheelLeft && detail != WheelRight; } void XEventMonitorPrivate::updateModifier(xEvent *event, bool isAdd) { Display *display = XOpenDisplay(NULL); KeySym keySym = XkbKeycodeToKeysym(display, event->u.u.detail, 0, 0); if(ModifiersVec.contains(keySym)) { if(isAdd) { modifiers.insert(keySym); } else { modifiers.remove(keySym); } } XCloseDisplay(display); } XEventMonitor::XEventMonitor(QObject *parent) : QThread(parent), d_ptr(new XEventMonitorPrivate(this)) { Q_D(XEventMonitor); } XEventMonitor::~XEventMonitor() { requestInterruption(); quit(); wait(); } void XEventMonitor::run() { if(!isInterruptionRequested()) { d_ptr->run(); } } bool checkCapsState() { //判断大写键状态 Display *display = XOpenDisplay(NULL); bool capsState = false; if(display) { unsigned int n; XkbGetIndicatorState(display, XkbUseCoreKbd, &n); capsState = (n & 0x01) == 1; } XCloseDisplay (display); return capsState; } ukui-settings-daemon/common/rfkillswitch.cpp0000664000175000017500000002307615167655063020303 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "rfkillswitch.h" #include #include #include #include #include #include RfkillSwitch *RfkillSwitch::m_rfkillInstance = new RfkillSwitch(); bool RfkillSwitch::isVirtualWlan(QString dp){ QDir dir(VIRTUAL_PATH); if (!dir.exists()){ return false; } dir.setFilter(QDir::Dirs); dir.setSorting(QDir::Name); int count = dir.count(); if (count <= 0){ return false; } QFileInfoList fileinfoList = dir.entryInfoList(); for(QFileInfo fileinfo : fileinfoList){ if (fileinfo.fileName() == "." || fileinfo.fileName() == ".."){ continue; } if (QString::compare(fileinfo.fileName(), dp) == 0){ return true; } } return false; } int RfkillSwitch::getCurrentWlanMode(){ struct rfkill_event event; ssize_t len; int fd; int bls = 0, unbls = 0; QList status; fd = open("/dev/rfkill", O_RDONLY); if (fd < 0) { qCritical("Can't open RFKILL control device"); return -1; } if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) { qCritical("Can't set RFKILL control device to non-blocking"); close(fd); return -1; } while (1) { len = read(fd, &event, sizeof(event)); if (len < 0) { if (errno == EAGAIN) break; qWarning("Reading of RFKILL events failed"); break; } if (len != RFKILL_EVENT_SIZE_V1) { qWarning("Wrong size of RFKILL event\n"); continue; } // printf("%u - %u: %u\n", event.idx, event.type, event.soft); if (event.type != RFKILL_TYPE_WLAN) continue; if (isVirtualWlan(QString(getRFkillName(event.idx)))){ continue; } status.append(event.soft ? 1 : 0); } close(fd); if (status.length() == 0){ return -1; } for (int s : status){ s ? bls++ : unbls++; } if (bls == status.length()){ //block return 0; } else if (unbls == status.length()){ //unblock return 1; } else { //not block & not unblock return 0; } } int RfkillSwitch::getCurrentFlightMode(){ struct rfkill_event event; ssize_t len; int fd; int bls = 0, unbls = 0; QList status; fd = open("/dev/rfkill", O_RDONLY); if (fd < 0) { qCritical("Can't open RFKILL control device"); return -1; } if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) { qCritical("Can't set RFKILL control device to non-blocking"); close(fd); return -1; } while (1) { len = read(fd, &event, sizeof(event)); if (len < 0) { if (errno == EAGAIN) break; qWarning("Reading of RFKILL events failed"); break; } if (len != RFKILL_EVENT_SIZE_V1) { qWarning("Wrong size of RFKILL event\n"); continue; } if (isVirtualWlan(QString(getRFkillName(event.idx)))){ continue; } // printf("%u: %u\n", event.idx, event.soft); status.append(event.soft ? 1 : 0); } close(fd); if (status.length() == 0){ return -1; } for (int s : status){ s ? bls++ : unbls++; } if (bls == status.length()){ //block return 1; } else if (unbls == status.length()){ //unblock return 0; } else { //not block & not unblock return 0; } } QString RfkillSwitch::toggleFlightMode(bool enable){ struct rfkill_event event; int fd; ssize_t len; __u8 block; fd = open("/dev/rfkill", O_RDWR); if (fd < 0) { return QString("Can't open RFKILL control device"); } block = enable ? 1 : 0; memset(&event, 0, sizeof(event)); event.op= RFKILL_OP_CHANGE_ALL; /* RFKILL_TYPE_ALL = 0 */ event.type = RFKILL_TYPE_ALL; event.soft = block; len = write(fd, &event, sizeof(event)); if (len < 0){ return QString("Failed to change RFKILL state"); } close(fd); return block ? QString("block"):QString("unblock"); } QString RfkillSwitch::getWifiState() { if(!wifiDeviceIsPresent()){ return ""; } QString cmd = "nmcli radio wifi"; QProcess process; process.start(cmd); process.waitForStarted(); process.waitForFinished(); QString wifiState = QString::fromLocal8Bit(process.readAllStandardOutput()); wifiState.replace("\n",""); return wifiState; } bool RfkillSwitch::wifiDeviceIsPresent() { QDBusInterface m_interface( "org.freedesktop.NetworkManager", "/org/freedesktop/NetworkManager", "org.freedesktop.NetworkManager", QDBusConnection::systemBus() ); //先获取所有的网络设备的设备路径 QDBusReply> obj_reply = m_interface.call("GetAllDevices"); if (!obj_reply.isValid()) { qDebug()<<"execute dbus method 'GetAllDevices' is invalid in func getObjectPath()"; return false; } QList obj_paths = obj_reply.value(); //再判断有无有线设备和无线设备的路径 Q_FOREACH(QDBusObjectPath obj_path, obj_paths) { QDBusInterface interface( "org.freedesktop.NetworkManager", obj_path.path(), "org.freedesktop.DBus.Introspectable", QDBusConnection::systemBus() ); QDBusReply reply = interface.call("Introspect"); if (reply.isValid()) { if (reply.value().indexOf("org.freedesktop.NetworkManager.Device.Wireless") != -1) { //表明有wifi设备 return true; } } } return false; } void RfkillSwitch::turnWifiOn() { QString cmd = "nmcli radio wifi on"; QProcess::execute(cmd); } void RfkillSwitch::turnWifiOff() { QString cmd = "nmcli radio wifi off"; QProcess::execute(cmd); } int RfkillSwitch::getCurrentBluetoothMode() { struct rfkill_event event; ssize_t len; int fd; int bls = 0, unbls = 0; QList status; fd = open("/dev/rfkill", O_RDONLY); if (fd < 0) { qCritical("Can't open RFKILL control device"); return -1; } if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) { qCritical("Can't set RFKILL control device to non-blocking"); close(fd); return -1; } while (1) { len = read(fd, &event, sizeof(event)); if (len < 0) { qWarning("Reading of RFKILL events failed"); break; } if (len != RFKILL_EVENT_SIZE_V1) { qWarning("Wrong size of RFKILL event\n"); continue; } // printf("%u - %u: %u\n", event.idx, event.type, event.soft); if (event.type != RFKILL_TYPE_BLUETOOTH) continue; status.append(event.soft ? 1 : 0); } close(fd); if (status.length() == 0){ return -1; } for (int s : status){ s ? bls++ : unbls++; } if (bls == status.length()){ //block return 0; } else if (unbls == status.length()){ //unblock return 1; } else { //not block & not unblock return 0; } } QString RfkillSwitch::toggleBluetoothMode(bool enable) { struct rfkill_event event; int fd; ssize_t len; __u8 block; fd = open("/dev/rfkill", O_RDWR); if (fd < 0) { return QString("Can't open RFKILL control device"); } block = enable ? 0 : 1; memset(&event, 0, sizeof(event)); event.op= RFKILL_OP_CHANGE_ALL; event.type = RFKILL_TYPE_BLUETOOTH; event.soft = block; len = write(fd, &event, sizeof(event)); if (len < 0){ close(fd); return QString("Failed to change RFKILL state"); } close(fd); return block ? QString("blocked") : QString("unblocked"); } const char * getRFkillName(__u32 idx){ static char name[128] = {}; char *pos, filename[64]; int fd; snprintf(filename, sizeof(filename) - 1, "/sys/class/rfkill/rfkill%u/name", idx); fd = open(filename, O_RDONLY); if (fd < 0) return NULL; memset(name, 0, sizeof(name)); read(fd, name, sizeof(name) - 1); pos = strchr(name, '\n'); if (pos) *pos = '\0'; close(fd); return name; } const char * getRFkillType(__u32 idx){ static char name[128] = {}; char *pos, filename[64]; int fd; snprintf(filename, sizeof(filename) - 1, "/sys/class/rfkill/rfkill%u/type", idx); fd = open(filename, O_RDONLY); if (fd < 0) return NULL; memset(name, 0, sizeof(name)); read(fd, name, sizeof(name) - 1); pos = strchr(name, '\n'); if (pos) *pos = '\0'; close(fd); return name; } ukui-settings-daemon/common/touch-calibrate.cpp0000664000175000017500000003036415167655063020642 0ustar fengfeng/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * Copyright (C) 2023 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * */ #include "touch-calibrate.h" //尺寸检测 bool TouchCalibrate::checkMatch(double output_width, double output_height, double input_width, double input_height) { double w_diff, h_diff; w_diff = ABS(1 - (output_width / input_width)); h_diff = ABS(1 - (output_height / input_height)); SYS_LOG(LOG_DEBUG,"w_diff--------%f,h_diff----------%f", w_diff, h_diff); if (w_diff < MAX_SIZE_MATCH_DIFF && h_diff < MAX_SIZE_MATCH_DIFF) { return true; } return false; } QVariantList TouchCalibrate::getDeviceProductId(int id) { QVariantList valueList; Atom real_type; int real_format; unsigned long nitems; unsigned long bytes_after; unsigned char* data = nullptr; unsigned char* dataPtr = nullptr; Atom prop = XInternAtom(UsdBaseClass::getQx11Info(), "Device Product ID", False); if (Success == XIGetProperty(UsdBaseClass::getQx11Info(), id, prop, 0, 1000, False, AnyPropertyType, &real_type, &real_format, &nitems, &bytes_after, &data)) { dataPtr = data; for (int i = 0; i < nitems; ++i) { if (real_type == XA_INTEGER && real_format == 32) { valueList << *(reinterpret_cast(dataPtr)); } dataPtr += real_format / 8; } XFree(data); } return valueList; } //获取设备节点 QString TouchCalibrate::getDeviceNode(int id) { QString node; Atom prop; Atom act_type; int act_format; unsigned long nitems, bytes_after; unsigned char *data; prop = XInternAtom(m_display, "Device Node", False); if (!prop) { return node; } if (XIGetProperty(m_display, id, prop, 0, 1000, False, AnyPropertyType, &act_type, &act_format, &nitems, &bytes_after, &data) == Success) { node = QString::fromLatin1(reinterpret_cast(data)); XFree(data); } return node; } //获取触摸设备物理尺寸 void TouchCalibrate::getTouchSize(const char* node, int& width, int& height) { const char *udevSubsystems[] = {"input", NULL}; GUdevClient *udevClient = g_udev_client_new(udevSubsystems); if (!udevClient) { SYS_LOG(LOG_DEBUG, " Failed to new udev client."); return; } GUdevDevice *udevDevice = g_udev_client_query_by_device_file(udevClient, node); if (g_udev_device_has_property(udevDevice, "ID_INPUT_WIDTH_MM")) { width = g_udev_device_get_property_as_uint64(udevDevice, "ID_INPUT_WIDTH_MM"); } if (g_udev_device_has_property(udevDevice, "ID_INPUT_HEIGHT_MM")) { height = g_udev_device_get_property_as_uint64(udevDevice, "ID_INPUT_HEIGHT_MM"); } g_clear_object(&udevClient); } TouchCalibrate::TouchCalibrate(const QString& path, QObject *parent) : QObject(parent) , m_display(XOpenDisplay(NULL)) , m_touchConfigPath(path) { } TouchCalibrate::~TouchCalibrate() { if (m_display) { XCloseDisplay(m_display); } m_screenInfoMap.clear(); m_touchScreenList.clear(); m_tabletList.clear(); m_touchConfigList.clear(); } bool TouchCalibrate::initDisplay() { } //获取屏幕列表 void TouchCalibrate::getScreenList() { int event_base, error_base, major, minor; Window root; XRRScreenResources *res; if (!XRRQueryExtension(m_display, &event_base, &error_base) || !XRRQueryVersion(m_display, &major, &minor)) { SYS_LOG(LOG_ERR, "RandR extension missing."); return; } root = DefaultRootWindow(m_display); if (major >= 1 && minor >= 5) { res = XRRGetScreenResources(m_display, root); if (!res) { SYS_LOG(LOG_ERR, "get screen resources failed"); return; } for (int o = 0; o < res->noutput; ++o) { XRROutputInfo *output = XRRGetOutputInfo(m_display, res, res->outputs[o]); if (!output){ SYS_LOG(LOG_ERR, "could not get output."); continue; } if (output->connection == RR_Connected) { ScreenInfoPtr screen(new ScreenInfo); screen->name = QString::fromLatin1(output->name); screen->width = output->mm_width; screen->height = output->mm_height; m_screenInfoMap.insert(screen->name, screen); SYS_LOG(LOG_DEBUG, "%s width : %d height : %d", screen->name.toLatin1().data(), screen->width, screen->height); } XRRFreeOutputInfo(output); } XRRFreeScreenResources(res); } } void TouchCalibrate::addTouchDevice(const XDeviceInfo& device, TouchDeviceList& touchList) { const QString& node = getDeviceNode(device.id); const QVariantList& product = getDeviceProductId(device.id); if (!node.isEmpty()) { TouchDevicePtr dev = TouchDevicePtr(new TouchDevice); dev->id = device.id; dev->name = QString::fromLatin1(device.name); dev->node = node; getTouchSize(node.toLatin1().data(), dev->width, dev->height); if (product.count() > 1) { dev->product.isValid = true; dev->product.vid = product[0].toInt(); dev->product.pid = product[1].toInt(); } touchList.append(dev); SYS_LOG(LOG_DEBUG, "%s id : %d node: %s width : %d height : %d", dev->name.toLatin1().data(), dev->id, dev->node.toLatin1().data(), dev->width, dev->height); } } // 获取触摸设备列表 void TouchCalibrate::getTouchDeviceList() { int ndevices; XDeviceInfo* deviceList = XListInputDevices(m_display ,&ndevices); for (int i = 0 ; i < ndevices ; ++i) { XDeviceInfo device = deviceList[i]; if (device.type == XInternAtom(m_display, XI_TOUCHSCREEN, False)) { addTouchDevice(device, m_touchScreenList); } else if (device.type == XInternAtom(m_display, XI_TABLET, False)) { addTouchDevice(device, m_tabletList); } } XFreeDeviceList(deviceList); } //获取触摸配置 void TouchCalibrate::getTouchConfigure() { QFileInfo file(m_touchConfigPath); if(file.exists()) { QSettings *configSettings = new QSettings(m_touchConfigPath, QSettings::IniFormat); int mapNum = configSettings->value("/COUNT/num").toInt(); if (mapNum < 1) { return; } for (int i = 0; i < mapNum ;++i) { QString mapName = QString("/MAP%1/%2"); QString touchName = configSettings->value(mapName.arg(i+1).arg("name")).toString(); if(touchName.isEmpty()) { continue; } QString scrname = configSettings->value(mapName.arg(i+1).arg("scrname")).toString(); if(scrname.isEmpty()) { continue; } // serial 不判空,暂不关注,无法通过序列号匹配屏幕 QString serial = configSettings->value(mapName.arg(i+1).arg("serial")).toString(); TouchConfigPtr touchConfig(new TouchConfig); touchConfig->sTouchName = touchName; touchConfig->sMonitorName = scrname; touchConfig->sTouchSerial = serial; //读取配置中productId,如果无此配置则无效,不进行product比较 const QStringList& productList = configSettings->value(mapName.arg(i+1).arg("productId")).toString().split(" "); if (productList.count() > 1) { touchConfig->product.isValid = true; touchConfig->product.vid = productList[0].toInt(); touchConfig->product.pid = productList[1].toInt(); } m_touchConfigList.append(touchConfig); } configSettings->deleteLater(); } } //进行映射 void TouchCalibrate::calibrate() { if (!m_display) { SYS_LOG(LOG_DEBUG, "Failed to get x display"); return; } //获取设备 getScreenList(); getTouchDeviceList(); getTouchConfigure(); calibrateTouchScreen(); calibrateTablet(); } void TouchCalibrate::autoMaticMapping(TouchDeviceList &touchList, ScreenInfoMap &screenMap) { //如果配置文件无法覆盖所有的屏幕组合,继续通过比较触摸设备和屏幕物理尺寸进行映射 TouchDeviceList::iterator it_tc = touchList.begin(); while (it_tc != touchList.end()) { if ((*it_tc)->isMapped) { ++it_tc; continue; } ScreenInfoMap::iterator it_sc = screenMap.begin(); while (it_sc != screenMap.end()) { if (it_sc.value()->isMapped || (*it_tc)->isMapped) { ++it_sc; continue; } if (checkMatch(it_sc.value()->width, it_sc.value()->height, (*it_tc)->width, (*it_tc)->height)) { calibrateDevice((*it_tc)->id, it_sc.value()->name); (*it_tc)->isMapped = true; it_sc.value()->isMapped = true; } ++it_sc; } ++it_tc; } //通过配置文件,尺寸比较后,仍然无法映射所有触摸设备与屏幕,则对剩下的设备进行随机映射 it_tc = touchList.begin(); while (it_tc != touchList.end()) { if ((*it_tc)->isMapped) { ++it_tc; continue; } ScreenInfoMap::iterator it_sc = screenMap.begin(); while (it_sc != screenMap.end()) { if (it_sc.value()->isMapped || (*it_tc)->isMapped) { ++it_sc; continue; } //此处不再比较触摸设备与屏幕大小,为映射过的设备和屏幕进行随机映射 calibrateDevice((*it_tc)->id, it_sc.value()->name); ++it_sc; } ++it_tc; } } //touchscreen void TouchCalibrate::calibrateTouchScreen() { //首先配置文件映射 Q_FOREACH (const TouchConfigPtr& touchConfig, m_touchConfigList) { Q_FOREACH (const TouchDevicePtr& touch , m_touchScreenList) { if (touch->name == touchConfig->sTouchName) { if (touchConfig->product.isValid) { // 检查配置里product id 是否有效,无效则不进行判断 if (touchConfig->product != touch->product) { continue; } } const ScreenInfoPtr& screen = m_screenInfoMap.value(touchConfig->sMonitorName); if (screen.data()) { calibrateDevice(touch->id, screen->name); touch->isMapped = true; screen->isMapped = true; } } } } autoMaticMapping(m_touchScreenList, m_screenInfoMap); } //tablet void TouchCalibrate::calibrateTablet() { //触摸笔映射,重置屏幕映射 ScreenInfoMap::iterator it_sc = m_screenInfoMap.begin(); while (it_sc != m_screenInfoMap.end()) { if (it_sc.value()->isMapped) { it_sc.value()->isMapped = false; } ++it_sc; } autoMaticMapping(m_tabletList, m_screenInfoMap); } void TouchCalibrate::calibrateDevice(int id, const QString& output) { QStringList arguments; arguments << "--map-to-output" << QString::number(id) << output; QProcess process; process.setProgram("xinput"); process.setArguments(arguments); if (!process.startDetached()) { SYS_LOG(LOG_DEBUG, "xinput map to output failed"); } SYS_LOG(LOG_DEBUG, "xinput touch device map to output [%d : %s]", id, output.toLatin1().data()); } ukui-settings-daemon/common/clib-syslog.h0000664000175000017500000000754015167655403017466 0ustar fengfeng/* -*- Mode: C; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef CLIB_SYSLOG_H #define CLIB_SYSLOG_H #include #include #include #include #include #include #include #include #include #include #include #include "usd_global_define.h" #define LOG_LEVEL LOG_DEBUG #ifdef __cplusplus extern "C" { #endif #include #define SYS_LOG(logLevel,...) {\ syslog_info(logLevel, MODULE_NAME, __FILE__, __func__, __LINE__, ##__VA_ARGS__);\ } #define USD_LOG(logLevel,...) {\ syslog_to_self_dir(logLevel, MODULE_NAME, __FILE__, __func__, __LINE__, ##__VA_ARGS__);\ } #define USD_LOG_SHOW_OUTPUT(output) USD_LOG(LOG_DEBUG,":%s (%s)(%s) use [%s] mode at (%dx%d) id %d primary id:%s,rotation:%d", \ output->name().toLatin1().data(), output->isConnected()? "connect":"disconnect", output->isEnabled()? "Enable":"Disable", \ output->currentModeId().toLatin1().data(), output->pos().x(), output->pos().y(),output->id(), output->hash().toLatin1().data(), output->rotation()) #define USD_LOG_SHOW_OUTPUT_NOID(output) USD_LOG(LOG_DEBUG,":%s (%s)(%s) use [%s] mode at (%dx%d) ", \ output->name().toLatin1().data(), output->isConnected()? "connect":"disconnect", output->isEnabled()? "Enale":"Disable", \ output->currentModeId().toLatin1().data(), output->pos().x(), output->pos().y()) #define USD_LOG_SHOW_PARAM1(a) USD_LOG(LOG_DEBUG,"%s : %d",#a,a) #define USD_LOG_SHOW_PARAMF(a) USD_LOG(LOG_DEBUG,"%s : %f",#a,a) #define USD_LOG_SHOW_PARAMS(a) USD_LOG(LOG_DEBUG,"[%s] : [%s]",#a,a) #define USD_LOG_SHOW_PARAM2(a,b) USD_LOG(LOG_DEBUG,"%s : %d,%s : %d",#a,a,#b, b) #define USD_LOG_SHOW_PARAM3(a,b,c) USD_LOG(LOG_DEBUG,"%s : %d,%s : %d",#a, a, #b, b, #c, c) #define USD_LOG_SHOW_PARAM4(a,b,c,d) USD_LOG(LOG_DEBUG,"%s : %d,%s : %d",#a, a, #b, b, #c, c, #d, d) #define SYS_LOG_SHOW_PARAM1(a) SYS_LOG(LOG_DEBUG,"%s : %d",#a,a) #define SYS_LOG_SHOW_PARAMS(a) SYS_LOG(LOG_DEBUG,"%s : %s",#a,a) #define SYS_LOG_SHOW_PARAM2(a,b) SYS_LOG(LOG_DEBUG,"%s : %d,%s : %d",#a,a,#b, b) #define SYS_LOG_SHOW_PARAM3(a,b,c) SYS_LOG(LOG_DEBUG,"%s : %d,%s : %d",#a, a, #b, b, #c, c) #define SYS_LOG_SHOW_PARAM4(a,b,c,d) SYS_LOG(LOG_DEBUG,"%s : %d,%s : %d",#a, a, #b, b, #c, c, #d, d) #define USD_LOG_SHOW_PARAM2F(a,b) USD_LOG(LOG_DEBUG,"%s : %f,%s : %f",#a,a,#b, b) #define CHECK_PROJECT(A) ifdef A #define CHECK_OVER endif /* * 日志参数初始化 * @param category: 标签 * @param facility: 设备文件 * @return * void */ void syslog_init(const char *category, int facility); /* * 日志输出到system log,默认LOG_INFO级别 * @param loglevel: 日志级别 * @param file: 文件名 * @param function: 函数 * @param line: 函数 * @param fmt: 格式化字符串 * @return * void */ void syslog_info(int logLevel, const char *moduleName, const char *fileName, const char *functionName, int line, const char* fmt, ...); void syslog_to_self_dir(int logLevel, const char *moduleName, const char *fileName, const char *functionName, int line, const char* fmt, ...); /* * 检测进程是否存在 */ int CheckProcessAlive(const char *pName); #ifdef __cplusplus } #endif //__cplusplus #endif ukui-settings-daemon/common/rfkillswitch.h0000664000175000017500000000435515167655063017747 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef RFKILLSWITCH_H #define RFKILLSWITCH_H #include #include #include extern "C" { #include #include #include #define RFKILL_EVENT_SIZE_V1 8 #define VIRTUAL_PATH "/sys/devices/virtual/ieee80211" const char * getRFkillType(__u32 idx); const char * getRFkillName(__u32 idx); struct rfkill_event { __u32 idx; __u8 type; __u8 op; __u8 soft, hard; }; enum rfkill_operation { RFKILL_OP_ADD = 0, RFKILL_OP_DEL, RFKILL_OP_CHANGE, RFKILL_OP_CHANGE_ALL, }; enum rfkill_type { RFKILL_TYPE_ALL = 0, RFKILL_TYPE_WLAN, RFKILL_TYPE_BLUETOOTH, RFKILL_TYPE_UWB, RFKILL_TYPE_WIMAX, RFKILL_TYPE_WWAN, RFKILL_TYPE_GPS, RFKILL_TYPE_FM, RFKILL_TYPE_NFC, NUM_RFKILL_TYPES, }; } /* 无线设备软开关 */ class RfkillSwitch : public QObject { Q_OBJECT public: explicit RfkillSwitch(){} RfkillSwitch(const RfkillSwitch&){} RfkillSwitch& operator==(const RfkillSwitch&){} static RfkillSwitch* instance(){return m_rfkillInstance;} public: bool isVirtualWlan(QString dp); int getCurrentFlightMode(); QString toggleFlightMode(bool enable); int getCurrentWlanMode(); QString getWifiState(); bool wifiDeviceIsPresent(); void turnWifiOff(); void turnWifiOn(); int getCurrentBluetoothMode(); QString toggleBluetoothMode(bool enable); private: static RfkillSwitch* m_rfkillInstance; Q_SIGNALS: }; #endif // RFKILLSWITCH_H ukui-settings-daemon/common/xrandroutput.h0000664000175000017500000001240115167655063020010 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef MATEOUPUT_H #define MATEOUPUT_H #include #include #include #include "clib-syslog.h" #define OUTPUT_ID "outputId" #define OUTPUT_NAME "name" #define CRTC_ID "crtc" #define MODE_ID "modeId" #define TRANSFORM_CHANGED "transformChanged" #define OUTPUT_SCALE "scale" #define OUTPUT_WIDTHMM "widthmm" #define OUTPUT_HEIGHTMM "heightmm" #define OUTPUT_WIDTH "width" #define OUTPUT_HEIGHT "height" #define OUTPUT_ROTATION "rotation" #define OUTPUT_CLEAR "clear" #define OUTPUT_RATE "rate" #define OUTPUT_PRIMARY "primary" #define OUTPUT_ENABLE "enable" //output所在的位置,如果output有0,1,2,4 crtc 有0,1,2,3。如果是 前三个,则一一对应,如果操作crtc的count就需要通过diff处理。 #define OUTPUT_SPACE "space" #define DEFINE_QSTRING(var) QString var; QString get##var(){return var;} void set##var(QString e){var = e;} #define DEFINE_BOOL(var) bool var; bool get##var(){return var;} void set##var(bool e){var = e;} #define DEFINE_DOUBLE(var) private: double var; public: double get##var(){return var;} void set##var(double e){var = e;} //#define DEFINE_QSTRING(var) QString get##var(){return var;} void set##var(QString e){e = var;} typedef struct UsdOutputMode_tag { int m_modeId; int m_height; int m_width; double m_rate; }UsdOutputMode; class UsdOuputProperty : public QObject{ Q_OBJECT Q_PROPERTY(QString name READ getname WRITE setname) Q_PROPERTY(QString enable READ getenable WRITE setenable) Q_PROPERTY(QString vendor READ getvendor WRITE setvendor) Q_PROPERTY(QString product READ getproduct WRITE setproduct) Q_PROPERTY(QString serial READ getserial WRITE setserial) Q_PROPERTY(QString width READ getwidth WRITE setwidth) Q_PROPERTY(QString height READ getheight WRITE setheight) Q_PROPERTY(QString rate READ getrate WRITE setrate) Q_PROPERTY(QString x READ getx WRITE setx) Q_PROPERTY(QString y READ gety WRITE sety) Q_PROPERTY(QString rotation READ getrotation WRITE setrotation) Q_PROPERTY(QString primary READ getprimary WRITE setprimary) Q_PROPERTY(bool seted READ getseted WRITE setseted) Q_PROPERTY(double scale READ getscale WRITE setscale) public: UsdOuputProperty(){ // qDebug()<<"**********************************88" <<"new"; } ~UsdOuputProperty(){ // qDebug()<<"**********************************88" <<"delete"; } void addMode(UsdOutputMode mode) { this->m_modes.append(mode); } void updateCloneMode(UsdOutputMode outputMode){ UsdOutputMode tempMode; for (int kmode = 0; kmode < this->m_cloneModes.count(); kmode ++) { if (this->m_cloneModes[kmode].m_height = outputMode.m_height && this->m_cloneModes[kmode].m_width == outputMode.m_width) { if (outputMode.m_rate < m_cloneModes[kmode].m_rate) { return; } else { this->m_cloneModes[kmode].m_rate = outputMode.m_rate; this->m_cloneModes[kmode].m_modeId = outputMode.m_modeId; return; } } } tempMode.m_height = outputMode.m_height; tempMode.m_modeId = outputMode.m_modeId; tempMode.m_rate = outputMode.m_modeId; tempMode.m_width = outputMode.m_width; // USD_LOG(LOG_DEBUG,"%s:add clone mode:%dx%d",this->property(OUTPUT_NAME).toString().toLatin1().data(),tempMode.m_height, tempMode.m_width); this->m_cloneModes.append(tempMode); } void showAllElement(){ USD_LOG_SHOW_PARAMS(name.toLatin1().data()); USD_LOG_SHOW_PARAMS(width.toLatin1().data()); USD_LOG_SHOW_PARAMS(height.toLatin1().data()); USD_LOG_SHOW_PARAMS(x.toLatin1().data()); USD_LOG_SHOW_PARAMS(y.toLatin1().data()); USD_LOG_SHOW_PARAMS(rate.toLatin1().data()); USD_LOG_SHOW_PARAMS(enable.toLatin1().data()); } private: DEFINE_QSTRING(name) DEFINE_QSTRING(vendor) DEFINE_QSTRING(product) DEFINE_QSTRING(serial) DEFINE_QSTRING(width) DEFINE_QSTRING(height) DEFINE_QSTRING(rate) DEFINE_QSTRING(x) DEFINE_QSTRING(y) DEFINE_QSTRING(rotation) DEFINE_QSTRING(primary) DEFINE_QSTRING(enable) DEFINE_BOOL(seted) DEFINE_DOUBLE(scale) QList m_modes; QList m_cloneModes; int maxSize; }; class OutputsConfig{ public: QString m_clone; int m_screenWidth = 0; int m_screenHeight = 0; int m_foundInCrtc = 0; QString m_dpi; QList m_outputList; }; #endif // MATEOUPUT_H ukui-settings-daemon/common/xeventmonitor.h0000664000175000017500000000450015167655063020153 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef XEVENTMONITOR_H #define XEVENTMONITOR_H #include #include #include extern "C"{ #include #include #include #include #include } #include "usd_base_class.h" class XEventMonitorPrivate; class XEventMonitor : public QThread { Q_OBJECT public: static XEventMonitor *instance() { return instance_; } private: XEventMonitor(QObject *parent = 0); ~XEventMonitor(); Q_SIGNALS: /// /// \brief 鼠标按下 /// \param x /// \param y /// void buttonPress(int x, int y); /// /// \brief 鼠标拖动 /// \param x /// \param y /// void buttonDrag(int x, int y); /// /// \brief 鼠标松开 /// \param x /// \param y /// void buttonRelease(int x, int y); /// /// \brief keyPress /// \param 按键键码,不包含修饰键 /// void keyPress(int keyCode); void keyRelease(int keyCode); /// /// \brief keyPress /// \param 按键名称,如果是组合键,则包含修饰键的名称,如Ctrl_L+r /// void keyPress(const QString &key); void keyRelease(const QString &key); /// /// /// //void keyPress(const xEvent *event); //void keyRelease(const xEvent *event); protected: void run(); private: Q_DECLARE_PRIVATE(XEventMonitor) XEventMonitorPrivate *d_ptr; static XEventMonitor *instance_; }; /** * @brief 检查大写开关状态 * @return 开(true),关(false) */ bool checkCapsState(); #endif ukui-settings-daemon/common/usd_base_class.cpp0000664000175000017500000003576415167655063020557 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include "clib-syslog.h" #include "usd_base_class.h" #include #include #include #include #include #include #include #include #include #define STR_EQUAL 0 #define DBUS_SERVICE "org.freedesktop.UPower" #define DBUS_OBJECT "/org/freedesktop/UPower" #define DBUS_INTERFACE "org.freedesktop.DBus.Properties" #define POWER_OFF_CONFIG_FILE "/sys/class/dmi/id/modalias" QString g_motify_poweroff; #define UBC_UNSET 999 #include "rfkillswitch.h" UsdBaseClass::UsdBaseClass() { } UsdBaseClass::~UsdBaseClass() { } bool UsdBaseClass::isMasterSP1() { return false; } bool UsdBaseClass::isUseXEventAsShutKey() { return true; } bool UsdBaseClass::isTablet() { static int ret = UBC_UNSET; if (ret!=UBC_UNSET) { return ret; } ret = false; #ifdef KY_SDK_SYSINFO if ((kdk_system_get_productFeatures()&2) == 2) { ret = true; } #endif return ret; } bool UsdBaseClass::isLoongarch() { #ifdef KY_SDK_HARDWARE QString cpuMode = kdk_cpu_get_model(); USD_LOG(LOG_DEBUG,"GetCpuModelName : %s",cpuMode.toStdString().c_str()); if(cpuMode.toLower().contains("loongson-3a4000")){ return true; } #endif return false; } bool UsdBaseClass::is9X0() { #ifdef USD_9X0 return true; #endif return false; } bool UsdBaseClass::isWayland() { static int isWaylandBackend = -1; char *pdata; if (isWaylandBackend != -1) { return isWaylandBackend; } pdata = getenv("XDG_SESSION_TYPE"); USD_LOG_SHOW_PARAMS(pdata); if (pdata) { if (!strncmp(pdata,"x11",3)) { isWaylandBackend = 0; USD_LOG(LOG_DEBUG,"x11"); } else { isWaylandBackend = 1; USD_LOG(LOG_DEBUG,"wayland"); } } return isWaylandBackend; } bool UsdBaseClass::isXcb() { if (QGuiApplication::platformName().startsWith(QLatin1String("xcb"))) { USD_LOG(LOG_DEBUG,"is xcb app"); return true; } return false; } bool UsdBaseClass::isNotebook() { QDBusMessage msg = QDBusMessage::createMethodCall(DBUS_SERVICE,DBUS_OBJECT,DBUS_INTERFACE,"Get"); msg<(v); QVariant result = dv.variant(); return result.toBool(); } return false; } bool UsdBaseClass::readPowerOffConfig() { QDir dir; QFile file; QString filePath = POWER_OFF_CONFIG_FILE; file.setFileName(filePath); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) false; QTextStream pstream(&file); g_motify_poweroff = pstream.readAll(); file.close(); return true; } bool UsdBaseClass::isPowerOff() { const QStringList devName ={"pnPF215T"}; if(g_motify_poweroff.isEmpty()) readPowerOffConfig(); for(auto devNameTmp : devName) { if (g_motify_poweroff.contains(devNameTmp, Qt::CaseSensitive)) { return true; } } return false; } bool UsdBaseClass::isJJW7200() { static int ret = UBC_UNSET; char *pAck = NULL; char CmdAck[256] = ""; FILE * pPipe; if (ret != UBC_UNSET) { return ret; } pPipe = popen("lspci | grep -i VGA |grep 7200","r"); if (pPipe) { pAck = fgets(CmdAck, sizeof(CmdAck)-1, pPipe); if (strlen(CmdAck) > 3) { ret = true; } else{ ret = false; } pclose(pPipe); } else { ret = false; } return ret; } int UsdBaseClass::getDPI() { static int ret = 0; char *dpi = NULL; if (ret) { return ret; } dpi = XGetDefault(UsdBaseClass::getQx11Info(), "Xft", "dpi"); if (dpi) { QString qDpi = QString::fromLatin1(dpi); if (qDpi == "192") { ret = 192; } else { ret = 96; } } else { ret = 96; } return ret; } double UsdBaseClass::getScale(double scaling) { double scale = 0.0; if (scaling <= 2.15) scale = getScoreScale(scaling); else if (scaling <= 3.15) scale = getScoreScale(scaling - 1) + 1; else if (scaling <= 4.15) scale = getScoreScale(scaling - 2) + 2; else if (scaling <= 5.15) scale = getScoreScale(scaling - 3) + 3; else if (scaling <= 6.15) scale = getScoreScale(scaling -4 ) + 4; else scale = 6;// 根据目前大屏及8K屏幕,最高考虑6倍缩放 return scale/2; } double UsdBaseClass::getScaleWithSize(int heightmm, int widthmm, int height, int width) { double inch = 0.0; double scale = 0.0; double screenArea = height * width; inch = sqrt(heightmm * heightmm + widthmm * widthmm) / 25.4; if (inch <= 10.00) { scale = qSqrt(screenArea) / qSqrt(1024 * 576); } else if (10.00 < inch && inch <= 15.00) { // 10 < inch <= 15 : 1366x768 scale = qSqrt(screenArea) / qSqrt(1366 * 768); } else if (15.00 < inch && inch <= 20.00) { // 15 < inch <= 20 : 1600x900 scale = qSqrt(screenArea) / qSqrt(1600 * 900); } else if (20.00 < inch && inch <= 30.00) { // 20 < inch <= 30 : 1920x1080 scale = qSqrt(screenArea) / qSqrt(1920 * 1080); } else if (30 < inch && inch<= 60) { // 30 < inch <= 60 : scale = qSqrt(screenArea) / qSqrt(1600 * 900); } else { // inch > 60 scale = qSqrt(screenArea) / qSqrt(1280 * 720); } return getScale(scale); } double UsdBaseClass::getScoreScale(double scaling) { double scale = 0.0; if (scaling <= 1.15) scale = 1; else if (scaling <= 1.4) scale = 1.25; else if (scaling <= 1.65) scale = 1.5; else if (scaling <= 1.9) scale = 1.75; else scale = 2; return scale; } bool UsdBaseClass::isEdu() { #ifdef KY_SDK_SYSINFO static int ret = UBC_UNSET; static QString projectCode = nullptr; QString deviceName = "-edu"; if (ret != UBC_UNSET) { return ret; } if (nullptr == projectCode) { char *kdkProjectName= kdk_system_get_projectName(); if (kdkProjectName == NULL) { ret = 0; return ret; } projectCode = QString::fromLatin1(kdkProjectName); projectCode = projectCode.toLower(); USD_LOG(LOG_DEBUG,"projectCode:%s",projectCode.toLatin1().data()); } if (projectCode.contains(deviceName)) { ret = 1; } else { ret = 0; } return ret; #else return false; #endif } void UsdBaseClass::writeUserConfigToLightDM(QString group, QString key, QVariant value, QString userName) { QDir dirCheck; QString user = QDir::home().dirName(); if (!userName.isEmpty()) { user = userName; } // qDebug()<isWritable()); usdSettings->beginGroup(group); usdSettings->setValue(key, value); usdSettings->endGroup(); usdSettings->sync(); usdSettings->deleteLater(); QFile::setPermissions(configFile,QFileDevice::Permission(0x6666)); } QVariant UsdBaseClass::readUserConfigToLightDM(QString group, QString key, QString userName) { QVariant ret; QString user = QDir::home().dirName(); if (!userName.isEmpty()) { user = userName; } QString configFile = QString("/var/lib/lightdm-data/%1/usd/config/ukui-settings-daemon.settings").arg(user); QSettings *usdSettings = new QSettings(configFile, QSettings::IniFormat); usdSettings->beginGroup(group); ret = usdSettings->value(key); usdSettings->endGroup(); usdSettings->sync(); usdSettings->deleteLater(); return ret; } bool UsdBaseClass::isWaylandWithKscreen() { return isWayland(); } /* *Normally, brightness are controlled by OS, but the following laptop hardware has control over them */ bool UsdBaseClass::brightnessControlByHardware(int &step) { static int ret = -1; static int hardwareStep; //:rnLXKT-ZXE-N70: n70,n80z,n79 QList m_appointBrightness = {":rnLXKT-ZXE-N70:"}; if (ret != -1) { step = hardwareStep; return ret; } if (g_motify_poweroff.isEmpty()) { readPowerOffConfig(); } Q_FOREACH (const QString &str, m_appointBrightness) { if (g_motify_poweroff.contains(str)) { ret = 1; hardwareStep = 5; step = hardwareStep; return ret; } } ret = false; return ret; } /* *Normally, the flight mode is controlled by hardware, but the following laptop hardware has surrendered control */ bool UsdBaseClass::flightModeControlByHardware(int &mode) { static int ret = -1; QList m_flightControlByHardware = {":rnLXKT-ZXE-N70:"}; if (ret != -1) { mode = RfkillSwitch::instance()->getCurrentFlightMode(); return ret; } if (g_motify_poweroff.isEmpty()) { readPowerOffConfig(); } Q_FOREACH (const QString &str, m_flightControlByHardware) { if (g_motify_poweroff.contains(str)) { ret = false; break; } } mode = RfkillSwitch::instance()->getCurrentFlightMode(); ret = ret == -1 ? true : ret; return ret; } /* *Normally, touchpads are controlled by OS, but the following laptop hardware has control over them */ bool UsdBaseClass::touchpadControlByHardware(int &state) { static int ret = -1; QList m_touchpadControlByHardware = {":rnLXKT-ZXE-N70:"}; if (ret == false) { return ret; } if (g_motify_poweroff.isEmpty()) { readPowerOffConfig(); } Q_FOREACH (const QString &str, m_touchpadControlByHardware) { if (g_motify_poweroff.contains(str)) { bool readOK; QVariant touchpadState; touchpadState = UsdBaseClass::readInfoFromFile(EC_TOUCHPADSTATE); state = touchpadState.toUInt(&readOK); if (readOK) { state = 0; } else { state = touchpadState.toUInt(); } ret = true; return ret; } } ret = false; return ret; } /* *Normally, power mode are controlled by OS, but the following laptop hardware has control over them */ bool UsdBaseClass::powerModeControlByHardware(int &mode) { static int ret = -1; QList m_appointPowerMode = {":rnLXKT-ZXE-N70:",":rn1DZX2SM-A351"}; if (ret == false) { return ret; } if (g_motify_poweroff.isEmpty()) { readPowerOffConfig(); } Q_FOREACH (const QString &str, m_appointPowerMode) { if (g_motify_poweroff.contains(str)) { QVariant hardMode; QFile file(PERFORMANCE_MODE); USD_LOG(LOG_DEBUG,"%s contanis %s",g_motify_poweroff.toLatin1().data(), str.toLatin1().data()); if (file.exists()) { hardMode = UsdBaseClass::readInfoFromFile(PERFORMANCE_MODE); /*TODO 此类机型只有两种模式 */ switch (hardMode.toInt()) { case 1: mode = 0;//perfromace break; case 2: mode = 2;//eco break; default: break; } ret = true; return ret; } else { mode = -1; ret = true; return ret; } } } ret = false; return ret; } QVariant UsdBaseClass::readInfoFromFile(QString filePath) { QString strData = ""; QFile file(filePath); if (!file.exists()) { return false; } if (file.open(QIODevice::ReadOnly)) { strData = QString::fromLocal8Bit(file.readAll()); file.close(); } return strData; } bool UsdBaseClass::isVirt() { QString ret; QProcess process; process.start("systemd-detect-virt"); process.waitForStarted(); process.waitForFinished(); ret = process.readAllStandardOutput(); if (ret.contains("microsoft",Qt::CaseInsensitive) || ret.contains("oracle",Qt::CaseInsensitive) || ret.contains("kvm",Qt::CaseInsensitive)) { return true; } USD_LOG_SHOW_PARAMS(ret.toLatin1().data()); QFile ctFile("/usr/local/ctyun/clink/Mirror/Registry/Default"); if (ctFile.exists()) { return true; } QFile fvendor("/sys/devices/virtual/dmi/id/chassis_vendor"); QFile ftag("/sys/devices/virtual/dmi/id/chassis_asset_tag"); QString strVendor; QString strTag; if (fvendor.exists()) { if (fvendor.open(QIODevice::ReadOnly)) { strVendor= fvendor.readAll(); fvendor.close(); } } USD_LOG_SHOW_PARAMS(strVendor.toLatin1().data()); if (ftag.exists()) { if (ftag.open(QIODevice::ReadOnly)) { strTag = ftag.readAll(); ftag.close(); } } USD_LOG_SHOW_PARAMS(strVendor.toLatin1().data()); if (strVendor.contains("Huawei Inc.",Qt::CaseInsensitive) || strTag.contains("HUAWEICLOUD",Qt::CaseInsensitive)) { return true; } return false; } Display *UsdBaseClass::getQx11Info() { static Display *display = nullptr; if (display != nullptr) { return display; } if (auto *x11Application = qGuiApp->nativeInterface()) { display = x11Application->display(); } return display; } ukui-settings-daemon/common/ukui_icon.qrc0000664000175000017500000000454015167654733017564 0ustar fengfeng ukui_res/ukui/ukui-bluetooth-off.svg ukui_res/ukui/ukui-bluetooth-on.svg ukui_res/ukui/ukui-camera-off.svg ukui_res/ukui/ukui-camera-on.svg ukui_res/ukui/ukui-capslock-off.svg ukui_res/ukui/ukui-capslock-on.svg ukui_res/ukui/ukui-Fn-off.svg ukui_res/ukui/ukui-Fn-on.svg ukui_res/ukui/ukui-microphone-off.svg ukui_res/ukui/ukui-microphone-on.svg ukui_res/ukui/ukui-numlock-off.svg ukui_res/ukui/ukui-numlock-on.svg ukui_res/ukui/ukui-sound.svg ukui_res/ukui/ukui-touchpad-off.svg ukui_res/ukui/ukui-touchpad-on.svg ukui_res/ukui/ukui-wifi-off.svg ukui_res/ukui/ukui-wifi-on.svg ukui_res/ukui_intel/ukui-bluetooth-off.svg ukui_res/ukui_intel/ukui-bluetooth-on.svg ukui_res/ukui_intel/ukui-camera-off.svg ukui_res/ukui_intel/ukui-camera-on.svg ukui_res/ukui_intel/ukui-capslock-off.svg ukui_res/ukui_intel/ukui-capslock-on-symbolic.svg ukui_res/ukui_intel/ukui-capslock-on.svg ukui_res/ukui_intel/ukui-Fn-off.svg ukui_res/ukui_intel/ukui-Fn-on.svg ukui_res/ukui_intel/ukui-microphone-off.svg ukui_res/ukui_intel/ukui-microphone-on.svg ukui_res/ukui_intel/ukui-numlock-off.svg ukui_res/ukui_intel/ukui-numlock-on.svg ukui_res/ukui_intel/ukui-sound.svg ukui_res/ukui_intel/ukui-touchpad-off.svg ukui_res/ukui_intel/ukui-touchpad-on.svg ukui_res/ukui_intel/ukui-wifi-off.svg ukui_res/ukui_intel/ukui-airplane-on.svg ukui_res/ukui_intel/ukui-airplane-off.svg ukui_res/ukui/ukui-airplane-on.svg ukui_res/ukui/ukui-airplane-off.svg ukui_res/ukui/ukui-performance-symbolic.svg ukui_res/ukui/ukui-eco-symbolic.svg ukui-settings-daemon/common/QGSettings/0000775000175000017500000000000015167655063017112 5ustar fengfengukui-settings-daemon/common/QGSettings/qgsettings.cpp0000664000175000017500000001636015167655063022014 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "qgsettings.h" #include "qconftype.h" #include #include #include #include #include "clib-syslog.h" struct QGSettingsPrivate { QByteArray path; GSettingsSchema *schema; QByteArray schemaId; GSettings *settings; gulong signalHandlerId; static void settingChanged(GSettings *settings, const gchar *key, gpointer userData); }; void QGSettingsPrivate::settingChanged(GSettings *, const gchar *key, gpointer userData) { QGSettings *self = (QGSettings *)userData; /** * 这里不属于 QObject的子类,只能通过此方法强制调用 QObject 子类的方法或信号 * * Qt::QueuedConnection 发送一个QEvent,并在应用程序进入主事件循环后立即调用该成员。 * Qt::DirectConnection 立即调用 * Qt::BlockingQueuedConnection 则将以与Qt::QueuedConnection相同的方式调用该方法,除了当前线程将阻塞直到事件被传递。使用此连接类型在同一线程中的对象之间进行通信将导致死锁 * Qt::AutoConnection 则如果obj与调用者位于同一个线程中,则会同步调用该成员; 否则它将异步调用该成员 * */ QMetaObject::invokeMethod(self, "changed", Qt::AutoConnection, Q_ARG(QString, key)); } static bool is_item_in_schema (const gchar* const* items, const QByteArray & item) { while (*items) { if (g_strcmp0 (*items++, item) == 0) { return true; } } return false; } QGSettings::QGSettings(const QByteArray &schemaId, const QByteArray &path, QObject *parent) : QObject(parent) { mPriv = new QGSettingsPrivate; mPriv->schemaId = schemaId; mPriv->path = path; if (false == is_item_in_schema (g_settings_list_schemas(), schemaId)){ mPriv->settings = nullptr; return; } if (mPriv->path.isEmpty()) { mPriv->settings = g_settings_new(mPriv->schemaId.constData()); } else { mPriv->settings = g_settings_new_with_path(mPriv->schemaId.constData(), mPriv->path.constData()); } g_object_get(mPriv->settings, "settings-schema", &mPriv->schema, NULL); mPriv->signalHandlerId = g_signal_connect(mPriv->settings, "changed", G_CALLBACK(QGSettingsPrivate::settingChanged), this); } QGSettings::~QGSettings() { if (mPriv->schema) { g_settings_sync (); g_signal_handler_disconnect(mPriv->settings, mPriv->signalHandlerId); g_object_unref (mPriv->settings); g_settings_schema_unref (mPriv->schema); } delete mPriv; } QVariant QGSettings::get(const QString &key) const { gchar *gkey = unqtify_name(key); if (mPriv->settings == nullptr) { return -1; } if (!keys().contains(gkey)) { USD_LOG(LOG_ERR, "can't find int key:%s in %s", gkey, mPriv->schemaId.data()); return QVariant(0); } GVariant *value = g_settings_get_value(mPriv->settings, gkey); if( NULL == value) { USD_LOG(LOG_DEBUG,"g_settings_get_value is failed"); return QVariant(0); } QVariant qvalue = qconf_types_to_qvariant(value); g_variant_unref(value); g_free(gkey); return qvalue; } void QGSettings::set(const QString &key, const QVariant &value) { if (mPriv->settings == nullptr) { return; } gchar *gkey = unqtify_name(key); if (keys().contains(gkey)) { if (!trySet(key, value)) USD_LOG(LOG_ERR,"unable to set key '%s' to value '%s'", key.toUtf8().constData(), value.toString().toUtf8().constData()); } else { USD_LOG(LOG_ERR, "can't find int key:%s in %s", gkey, mPriv->schemaId.data()); } } bool QGSettings::trySet(const QString &key, const QVariant &value) { gchar *gkey = unqtify_name(key); bool success = false; /* fetch current value to find out the exact type */ GVariant *cur = g_settings_get_value(mPriv->settings, gkey); GVariant *new_value = qconf_types_collect_from_variant(g_variant_get_type (cur), value); if (new_value) success = g_settings_set_value(mPriv->settings, gkey, new_value); g_free(gkey); g_variant_unref (cur); return success; } void QGSettings::setEnum(const QString& key,int value) { if (mPriv->settings == nullptr) { return ; } g_settings_set_enum (mPriv->settings,key.toLatin1().data(),value); } int QGSettings::getEnum(const QString& key) { int enumNum; if (mPriv->settings == nullptr) { return -1; } enumNum = g_settings_get_enum (mPriv->settings,key.toLatin1().data()); return enumNum; } char **QGSettings::getStrv(const QString& key) { return g_settings_get_strv(mPriv->settings,key.toLatin1().data()); } void QGSettings::delay() { g_settings_delay(mPriv->settings); } void QGSettings::apply() { g_settings_apply(mPriv->settings); } QStringList QGSettings::keys() const { QStringList list; //gchar **keys = g_settings_list_keys(mPriv->settings); gchar **keys = g_settings_schema_list_keys(mPriv->schema); for (int i = 0; keys[i]; i++) list.append(keys[i]); // list.append(qtify_name(keys[i])); g_strfreev(keys); return list; } QVariantList QGSettings::choices(const QString &qkey) const { gchar *key = unqtify_name (qkey); GSettingsSchemaKey *schema_key = g_settings_schema_get_key (mPriv->schema, key); GVariant *range = g_settings_schema_key_get_range(schema_key); g_settings_schema_key_unref (schema_key); g_free(key); if (range == NULL) return QVariantList(); const gchar *type; GVariant *value; g_variant_get(range, "(&sv)", &type, &value); QVariantList choices; if (g_str_equal(type, "enum")) { GVariantIter iter; GVariant *child; g_variant_iter_init (&iter, value); while ((child = g_variant_iter_next_value(&iter))) { choices.append(qconf_types_to_qvariant(child)); g_variant_unref(child); } } g_variant_unref (value); g_variant_unref (range); return choices; } void QGSettings::reset(const QString &qkey) { gchar *key = unqtify_name(qkey); g_settings_reset(mPriv->settings, key); g_free(key); } bool QGSettings::isSchemaInstalled(const QByteArray &schemaId) { GSettingsSchemaSource *source = g_settings_schema_source_get_default (); GSettingsSchema *schema = g_settings_schema_source_lookup (source, schemaId.constData(), TRUE); if (schema) { g_settings_schema_unref (schema); return true; } else { return false; } } ukui-settings-daemon/common/QGSettings/qconftype.cpp0000664000175000017500000002325115167655063021631 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "qconftype.h" #include #include "clib-syslog.h" /** * GVariant Type Name/Code C++ Type Name QVariant Type Name * -------------------------------------------------------------------------- * boolean b bool QVariant::Bool * byte y char QVariant::Char * int16 n int QVariant::Int * uint16 q unsigned int QVariant::UInt * int32 i int QVariant::Int * uint32 u unsigned int QVariant::UInt * int64 x long long QVariant::LongLong * uint64 t unsigned long long QVariant::ULongLong * double d double QVariant::Double * string s QString QVariant::String * string array* as QStringList QVariant::StringList * byte array ay QByteArray QVariant::ByteArray * dictionary a{ss} QVariantMap QVariant::Map */ QVariant::Type qconf_types_convert(const GVariantType *gtype) { switch (g_variant_type_peek_string(gtype)[0]) { case G_VARIANT_CLASS_BOOLEAN: return QVariant::Bool; case G_VARIANT_CLASS_BYTE: return QVariant::Char; case G_VARIANT_CLASS_INT16: return QVariant::Int; case G_VARIANT_CLASS_UINT16: return QVariant::UInt; case G_VARIANT_CLASS_INT32: return QVariant::Int; case G_VARIANT_CLASS_UINT32: return QVariant::UInt; case G_VARIANT_CLASS_INT64: return QVariant::LongLong; case G_VARIANT_CLASS_UINT64: return QVariant::ULongLong; case G_VARIANT_CLASS_DOUBLE: return QVariant::Double; case G_VARIANT_CLASS_STRING: return QVariant::String; case G_VARIANT_CLASS_ARRAY: if (g_variant_type_equal(gtype, G_VARIANT_TYPE_STRING_ARRAY)) return QVariant::StringList; else if (g_variant_type_equal(gtype, G_VARIANT_TYPE_BYTESTRING)) return QVariant::ByteArray; else if (g_variant_type_equal(gtype, G_VARIANT_TYPE ("a{ss}"))) return QVariant::Map; // fall through default: USD_LOG(LOG_DEBUG,"invalid:%d,%s",g_variant_type_peek_string(gtype)[0],gtype); return QVariant::Invalid; } } GVariant *qconf_types_collect_from_variant(const GVariantType *gtype, const QVariant &v) { switch (g_variant_type_peek_string(gtype)[0]) { case G_VARIANT_CLASS_BOOLEAN: return g_variant_new_boolean(v.toBool()); case G_VARIANT_CLASS_BYTE: return g_variant_new_byte(v.toChar().cell()); case G_VARIANT_CLASS_INT16: return g_variant_new_int16(v.toInt()); case G_VARIANT_CLASS_UINT16: return g_variant_new_uint16(v.toUInt()); case G_VARIANT_CLASS_INT32: return g_variant_new_int32(v.toInt()); case G_VARIANT_CLASS_UINT32: return g_variant_new_uint32(v.toUInt()); case G_VARIANT_CLASS_INT64: return g_variant_new_int64(v.toLongLong()); case G_VARIANT_CLASS_UINT64: return g_variant_new_int64(v.toULongLong()); case G_VARIANT_CLASS_DOUBLE: return g_variant_new_double(v.toDouble()); case G_VARIANT_CLASS_STRING: return g_variant_new_string(v.toString().toUtf8()); case G_VARIANT_CLASS_ARRAY: if (g_variant_type_equal(gtype, G_VARIANT_TYPE_STRING_ARRAY)) { const QStringList list = v.toStringList(); GVariantBuilder builder; g_variant_builder_init(&builder, G_VARIANT_TYPE_STRING_ARRAY); Q_FOREACH(const QString& string, list) g_variant_builder_add(&builder, "s", string.toUtf8().constData()); return g_variant_builder_end(&builder); } else if (g_variant_type_equal(gtype, G_VARIANT_TYPE_BYTESTRING)) { const QByteArray array = v.toByteArray(); gsize size = array.size(); gpointer data; data = g_memdup(array.data(), size); return g_variant_new_from_data(G_VARIANT_TYPE_BYTESTRING, data, size, TRUE, g_free, data); } else if (g_variant_type_equal(gtype, G_VARIANT_TYPE("a{ss}"))) { GVariantBuilder builder; g_variant_builder_init(&builder, G_VARIANT_TYPE ("a{ss}")); QMapIterator it(v.toMap()); while (it.hasNext()) { it.next(); QByteArray key = it.key().toUtf8(); QByteArray val = it.value().toByteArray(); g_variant_builder_add (&builder, "{ss}", key.constData(), val.constData()); } return g_variant_builder_end (&builder); } // fall through case G_VARIANT_CLASS_TUPLE: if (g_variant_type_equal(gtype, "(dd)")) { QVariantList doubleList = v.value(); if (doubleList.count() == 2) { return g_variant_new ("(dd)", doubleList[0].toDouble(), doubleList[1].toDouble()); } else { return NULL; } } break; default: return NULL; } } QVariant qconf_types_to_qvariant(GVariant *value) { switch (g_variant_classify(value)) { case G_VARIANT_CLASS_BOOLEAN: return QVariant((bool) g_variant_get_boolean(value)); case G_VARIANT_CLASS_BYTE: return QVariant((char) g_variant_get_byte(value)); case G_VARIANT_CLASS_INT16: return QVariant((int) g_variant_get_int16(value)); case G_VARIANT_CLASS_UINT16: return QVariant((unsigned int) g_variant_get_uint16(value)); case G_VARIANT_CLASS_INT32: return QVariant((int) g_variant_get_int32(value)); case G_VARIANT_CLASS_UINT32: return QVariant((unsigned int) g_variant_get_uint32(value)); case G_VARIANT_CLASS_INT64: return QVariant((long long) g_variant_get_int64(value)); case G_VARIANT_CLASS_UINT64: return QVariant((unsigned long long) g_variant_get_uint64(value)); case G_VARIANT_CLASS_DOUBLE: return QVariant(g_variant_get_double(value)); case G_VARIANT_CLASS_STRING: return QVariant(g_variant_get_string(value, NULL)); case G_VARIANT_CLASS_ARRAY: if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING_ARRAY)) { GVariantIter iter; QStringList list; const gchar *str; g_variant_iter_init (&iter, value); while (g_variant_iter_next (&iter, "&s", &str)) list.append (str); return QVariant(list); } else if (g_variant_is_of_type(value, G_VARIANT_TYPE_BYTESTRING)) { return QVariant(QByteArray(g_variant_get_bytestring(value))); } else if (g_variant_is_of_type(value, G_VARIANT_TYPE("a{ss}"))) { GVariantIter iter; QMap map; const gchar *key; const gchar *val; g_variant_iter_init (&iter, value); while (g_variant_iter_next (&iter, "{&s&s}", &key, &val)) map.insert(key, QVariant(val)); return map; } break; // fall throughsudo apt install qtbase5-dev qt5-qmake qtchooser qtscript5-dev qttools5-dev-tools qtbase5-dev-tools libgsettings-qt-dev case G_VARIANT_CLASS_TUPLE: if (g_variant_is_of_type(value, G_VARIANT_TYPE("(dd)"))) { QVariantList varList; QVariant var; double latitude,longitude; g_variant_get(value, "(dd)", &latitude, &longitude); varList.append(latitude); varList.append(longitude); var = varList; return var; } default: g_assert_not_reached(); break; } g_assert_not_reached(); // return QVariant((bool) g_variant_get_boolean(value)); } // trans 'aa-bb' to 'aaBb' QString qtify_name(const char *name) { bool next_cap = false; QString result; while (*name) { if (*name == '-') { next_cap = true; } else if (next_cap) { result.append(QChar(*name).toUpper().toLatin1()); next_cap = false; } else { result.append(*name); } name++; } return result; } gchar * unqtify_name(const QString &name) { const gchar *p; QByteArray bytes; GString *str; bytes = name.toUtf8(); str = g_string_new (NULL); for (p = bytes.constData(); *p; p++) { const QChar c(*p); if (c.isUpper()) { g_string_append_c (str, '-'); g_string_append_c (str, c.toLower().toLatin1()); } else { g_string_append_c (str, *p); } } return g_string_free(str, FALSE); } ukui-settings-daemon/common/QGSettings/qgsettings.h0000664000175000017500000000744015167655063021460 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef QGSETTINGS_H #define QGSETTINGS_H #include #include /** * gsettings 的 key 必须是小写字符和下划线组成 * 此类将所有key转为驼峰方式 */ class QGSettings : public QObject { Q_OBJECT public: /* 根据 schemaId 和 path 创建QGSettings对象 */ explicit QGSettings(const QByteArray& schemaId, const QByteArray& path=QByteArray(), QObject *parent = nullptr); ~QGSettings(); /** * 根据key获取值, key不存在则报错 * */ QVariant get (const QString& key) const; /** * 根据 key 设定值 */ void set (const QString& key, const QVariant& value); /** * 将QGSettings对象更改为'delay-apply'模式。 * 在此模式下,对设置的更改不会立即传播到后端, * 而是在本地保存,直到调用apply()。 */ void delay(); /** * 应用对设置所做的任何更改。 * 这个函数什么都不做,除非设置是在“延迟-应用”模式; * 看到delay ()。在正常情况下,总是立即应用设置。 */ void apply(); /** * @brief setEnum * @param key * @param value * 在设置中查找枚举类型的nick以获取值并将其写入键。 * 给出一个不包含在架构中的键来进行设置或未将其标记为枚举类型, * 或者将值设为不是该命名类型的有效值是程序员的错误。 * 执行写操作后,直接使用g_settings_get_string() * 访问密钥将返回与值关联的'nick'。 */ void setEnum(const QString& key,int value); /** * 获取存储在key设置中的值,并将其转换为它表示的枚举值。 * 为了使用此函数,值的类型必须为字符串,并且必须在模式文件中将其标记为枚举类型。 * 给出不包含在设置模式中或未标记为枚举类型的密钥是程序员的错误。 * 如果配置数据库中存储的值不是该枚举类型的有效值,则此函数将返回默认值。 */ int getEnum(const QString& key); /** * g_settings_get()字符串数组的便捷变体。 * 给出一个key 未指定为的架构中的字符串类型数组是程序员的错误settings 。 * return: 一个新分配的,NULL终止的字符串数组,该值存储在key 中settings */ char **getStrv(const QString& key); /** * */ bool trySet (const QString& key, const QVariant& value); /** * 获取 key 的列表 */ QStringList keys() const; /** * */ QVariantList choices (const QString& key) const; /** * 将 key 设为默认值 */ void reset (const QString& key); /** * 根据给定 id 检查是否存在schema */ static bool isSchemaInstalled (const QByteArray& schemaId); Q_SIGNALS: /** * key 的值改变时发射信号 * */ void changed (const QString& key); private: struct QGSettingsPrivate* mPriv; friend struct QGSettingsPrivate; }; #endif // QGSETTINGS_H ukui-settings-daemon/common/QGSettings/qconftype.h0000664000175000017500000000242015167655063021271 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef QCONFTYPE_H #define QCONFTYPE_H #include #include QVariant::Type qconf_types_convert (const GVariantType* gtype); GVariant* qconf_types_collect (const GVariantType* gtype, const void* argument); GVariant* qconf_types_collect_from_variant(const GVariantType* gtype, const QVariant& v); QVariant qconf_types_to_qvariant (GVariant* value); void qconf_types_unpack (GVariant* value, void* argument); QString qtify_name(const char *name); gchar * unqtify_name(const QString &name); #endif // QCONFTYPE_H ukui-settings-daemon/common/ukui-input-helper.h0000664000175000017500000000210615167655063020621 0ustar fengfeng/* -*- Mode: C; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef __USD_INPUT_HELPER_H #define __USD_INPUT_HELPER_H #include #include #include gboolean supports_xinput_devices (void); XDevice *device_is_touchpad (XDeviceInfo *deviceinfo); gboolean touchpad_is_present (void); #endif /* __USD_INPUT_HELPER_H */ ukui-settings-daemon/common/usd_global_define.h0000664000175000017500000001434515167655063020667 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef USD_GLOBAL_DEFINE_H #define USD_GLOBAL_DEFINE_H #define USD_BTN_PRESS 2 #define USD_BTN_RELEASE 3 /****dbus****/ /*com.kylin.statusmanager.interface*/ #define DBUS_STATUSMANAGER_NAME "com.kylin.statusmanager.interface" #define DBUS_STATUSMANAGER_PATH "/" #define DBUS_STATUSMANAGER_INTERFACE "com.kylin.statusmanager.interface" #define DBUS_STATUSMANAGER_GET_MODE "get_current_tabletmode" #define DBUS_STATUSMANAGER_GET_ROTATION "get_current_rotation" /*****/ /*org.ukui.SettingsDaemon.xrandr*/ #define DBUS_XRANDR_NAME "org.ukui.SettingsDaemon" #define DBUS_XRANDR_PATH "/org/ukui/SettingsDaemon/xrandr" #define DBUS_XRANDR_INTERFACE "org.ukui.SettingsDaemon.xrandr" #define DBUS_XRANDR_GET_MODE "getScreenMode" #define DBUS_XRANDR_SET_MODE "setScreenMode" #define DBUS_XRANDR_GET_SCREEN_PARAM "getScreensParam" /*****/ /*org.ukui.SettingsDaemon.gammaManager*/ #define DBUS_GM_NAME "org.ukui.SettingsDaemon" #define DBUS_GM_PATH "/org/ukui/SettingsDaemon/GammaManager" #define DBUS_GM_INTERFACE "org.ukui.SettingsDaemon.GammaManager" #define DBUS_GM_SCREENCHANGED "screenBrightnessChanged" /*****/ /*com.control.center.qt.systemdbus*/ #define DBUS_CONTROL_CENTER_NAME "com.control.center.qt.systemdbus" #define DBUS_CONTROL_CENTER_PATH "/" #define DBUS_CONTROL_CENTER_INTERFACE "com.control.center.interface" /*****/ /*com.settings.daemon.qt.systemdbus*/ #define SETTINGS_DAEMON_SYSTEMDBUS_NAME "com.settings.daemon.qt.systemdbus" #define SETTINGS_DAEMON_SYSTEMDBUS_PATH "/" #define SETTINGS_DAEMON_SYSTEMDBUS_INTERFACE "com.settings.daemon.interface" /**/ //dbus 配置 #define GNOME_SESSION_MANAGER "org.gnome.SessionManager.Presence" #define SESSION_MANAGER_PATH "/org/gnome/SessionManager/Presence" /**/ #define DBUS_GC_BRIGHTNESS_PATH "/GlobalBrightness" #define DBUS_GC_BRIGHTNESS_INTERFACE "org.ukui.SettingsDaemon.Brightness" #define DBUS_GC_BRIGHTNESS_SIGNAL_PRIMARYCHANGED_START "primaryBrightnessChangedStart" #define DBUS_GC_BRIGHTNESS_SIGNAL_PRIMARYCHANGED "primaryBrightnessChanged" #define DBUS_GC_BRIGHTNESS_SIGNAL_PRIMARYCHANGED_END "primaryBrightnessChangedEnd" #define DBUS_GC_BRIGHTNESS_SIGNAL_ENABLECHANGED "enableChanged" /**/ #define DBUS_GC_SIGNAL_PATH "/GlobaSignal" #define DBUS_GC_SIGNAL_INTERFACE "org.ukui.SettingsDaemon.GlobalSignal" #define DBUS_GC_SIGNAL_SIGNAL_Active "Active" //gsettings /*com.kylin.statusmanager.interface*/ /****dbus end****/ #define MIN_GAMMA_BRIGHTNESS 0.35 #define MAX_GAMMA_BRIGHTNESS 0.65 /****gsettings****/ //ukui.style #define UKUI_STYLE_SCHEMA "org.ukui.style" #define SYSTEM_FONT_SIZE "system-font-size" #define SYSTEM_FONT "system-font" //MATE_INTERFACE #define MATE_INTERFACE_SCHEMA "org.mate.interface" //auto-brightness gsettings #define AUTO_BRIGHTNESS_SCHEMA "org.ukui.SettingsDaemon.plugins.auto-brightness" #define AUTO_BRIGHTNESS_KEY "auto-brightness" #define DYNAMIC_BRIGHTNESS_KEY "dynamic-brightness" #define HAD_SENSOR_KEY "have-sensor" #define DEBUG_MODE_KEY "debug-mode" #define DEBUG_LUX_KEY "debug-lux" #define DELAYMS_KEY "delayms" #define POWER_MANAGER_SCHEMA "org.ukui.power-manager" #define BRIGHTNESS_AC_KEY "brightness-ac" /*Xorg shutkey name*/ //xsettings #define GSETTINGS_XSETTINGS_SCHEMA "org.ukui.SettingsDaemon.plugins.xsettings" #define SCALING_FACTOR_KEY "scaling-factor" //mouse #define GSETTINGS_MOUSE_SCHEMA "org.ukui.peripherals-mouse" #define CURSOR_THEME_KEY "cursor-theme" #define CURSOR_SIZE_KEY "cursor-size" //xsettings #define GSETTINGS_GLOBALMANAGER_SCHEMA "org.ukui.SettingsDaemon.plugins.globalManager" #define HIDE_POWEROFF_UI "disable-power-operation" #define DISABLE_POWEROFF_OPTIONS "disable-shutdown-option" #define UKUI_LITE_FUNCTION "ukui-lite-function" #define UKUI_LITE_ANIMATION "ukui-lite-animation" /* * 变量 */ #define MAX_SIZE_MATCH_DIFF 0.05 //session #define SESSION_BUSY 0 #define SESSION_IDLE 3 #define LEFT_SHIFT 0x32 #define LEFT_CTRL 0x25 #define LEFT_ALT 0x40 #define RIGHT_SHIFT 0x3E #define RIGHT_ALT 0x6C #define RIGHT_CTRL 0x69 #define MATE_KEY 0x85 #define xEventHandleHadRelase(action) bool action##HadRelease = false #define xEventHandleRelease(action) action##HadRelease = false; #define xEventHandle(action) \ if (false == action##HadRelease) { \ doAction(action); \ action##HadRelease = true; \ } #define STATE_OFF 0 #define STATE_ON 1 #define STATE_TOGGLE 2 /*Xorg shutkey nameEnd*/ #define TIME_LIMIT(time) \ static QTime startTime = QTime::currentTime(); \ static int elapsed = -1; \ elapsed = startTime.msecsTo(QTime::currentTime()); \ if(elapsed > 0 && elapsed <= time){ \ /*USD_LOG(LOG_ERR,"time in TIME_LIMIT");*/ \ return; \ } \ startTime = QTime::currentTime(); #endif // USD_GLOBAL_DEFINE_H ukui-settings-daemon/common/ukui_res/0000775000175000017500000000000015167654733016713 5ustar fengfengukui-settings-daemon/common/ukui_res/ukui/0000775000175000017500000000000015167654733017670 5ustar fengfengukui-settings-daemon/common/ukui_res/ukui/ukui-bluetooth-off.svg0000664000175000017500000000137415167654733024146 0ustar fengfeng ukui-settings-daemon/common/ukui_res/ukui/ukui-sound.svg0000664000175000017500000000235415167654733022520 0ustar fengfeng ukui-settings-daemon/common/ukui_res/ukui/ukui-wifi-on.svg0000664000175000017500000000231015167654733022730 0ustar fengfeng ukui-settings-daemon/common/ukui_res/ukui/ukui-microphone-on.svg0000664000175000017500000000233315167654733024142 0ustar fengfeng ukui-settings-daemon/common/ukui_res/ukui/ukui-camera-off.svg0000664000175000017500000000340315167654733023364 0ustar fengfeng ukui-settings-daemon/common/ukui_res/ukui/ukui-microphone-off.svg0000664000175000017500000000247015167654733024302 0ustar fengfeng ukui-settings-daemon/common/ukui_res/ukui/ukui-bluetooth-on.svg0000664000175000017500000000125615167654733024007 0ustar fengfeng ukui-settings-daemon/common/ukui_res/ukui/ukui-touchpad-off.svg0000664000175000017500000000232415167654733023744 0ustar fengfeng ukui-settings-daemon/common/ukui_res/ukui/ukui-performance-symbolic.svg0000664000175000017500000000046415167654733025510 0ustar fengfengukui-settings-daemon/common/ukui_res/ukui/ukui-Fn-off.svg0000664000175000017500000000415015167654733022477 0ustar fengfeng Fn ukui-settings-daemon/common/ukui_res/ukui/ukui-numlock-off.svg0000664000175000017500000000417715167654733023615 0ustar fengfeng 1 ukui-settings-daemon/common/ukui_res/ukui/ukui-capslock-on.svg0000664000175000017500000000405415167654733023600 0ustar fengfeng A ukui-settings-daemon/common/ukui_res/ukui/ukui-airplane-off.svg0000664000175000017500000001437115167654733023735 0ustar fengfeng ukui-settings-daemon/common/ukui_res/ukui/ukui-capslock-off.svg0000664000175000017500000000421615167654733023736 0ustar fengfeng A ukui-settings-daemon/common/ukui_res/ukui/ukui-touchpad-on.svg0000664000175000017500000000215415167654733023607 0ustar fengfeng ukui-settings-daemon/common/ukui_res/ukui/ukui-wifi-off.svg0000664000175000017500000000244215167654733023074 0ustar fengfeng ukui-settings-daemon/common/ukui_res/ukui/ukui-camera-on.svg0000664000175000017500000000322415167654733023227 0ustar fengfeng ukui-settings-daemon/common/ukui_res/ukui/ukui-eco-symbolic.svg0000664000175000017500000000255015167654733023753 0ustar fengfeng ukui-settings-daemon/common/ukui_res/ukui/ukui-Fn-on.svg0000664000175000017500000000400615167654733022341 0ustar fengfeng Fn ukui-settings-daemon/common/ukui_res/ukui/ukui-airplane-on.svg0000664000175000017500000001424515167654733023577 0ustar fengfeng ukui-settings-daemon/common/ukui_res/ukui/ukui-numlock-on.svg0000664000175000017500000000403515167654733023450 0ustar fengfeng 1 ukui-settings-daemon/common/ukui_res/ukui_intel/0000775000175000017500000000000015167654733021063 5ustar fengfengukui-settings-daemon/common/ukui_res/ukui_intel/ukui-bluetooth-off.svg0000664000175000017500000000241715167654733025340 0ustar fengfeng ukui-settings-daemon/common/ukui_res/ukui_intel/ukui-sound.svg0000664000175000017500000000176515167654733023720 0ustar fengfeng ukui-settings-daemon/common/ukui_res/ukui_intel/ukui-microphone-on.svg0000664000175000017500000000076215167654733025341 0ustar fengfeng ukui-settings-daemon/common/ukui_res/ukui_intel/ukui-capslock-on-symbolic.svg0000664000175000017500000000251415167654733026611 0ustar fengfeng ukui-settings-daemon/common/ukui_res/ukui_intel/ukui-camera-off.svg0000664000175000017500000000273415167654733024565 0ustar fengfeng ukui-settings-daemon/common/ukui_res/ukui_intel/ukui-microphone-off.svg0000664000175000017500000000311115167654733025466 0ustar fengfeng ukui-settings-daemon/common/ukui_res/ukui_intel/ukui-bluetooth-on.svg0000664000175000017500000000234515167654733025202 0ustar fengfeng ukui-settings-daemon/common/ukui_res/ukui_intel/ukui-touchpad-off.svg0000664000175000017500000000547315167654733025147 0ustar fengfeng ukui-settings-daemon/common/ukui_res/ukui_intel/ukui-Fn-off.svg0000664000175000017500000000750515167654733023701 0ustar fengfeng ukui-settings-daemon/common/ukui_res/ukui_intel/ukui-numlock-off.svg0000664000175000017500000000371615167654733025006 0ustar fengfeng ukui-settings-daemon/common/ukui_res/ukui_intel/ukui-capslock-on.svg0000664000175000017500000000071615167654733024774 0ustar fengfeng ukui-settings-daemon/common/ukui_res/ukui_intel/ukui-airplane-off.svg0000664000175000017500000000261715167654733025130 0ustar fengfeng ukui-settings-daemon/common/ukui_res/ukui_intel/ukui-capslock-off.svg0000664000175000017500000000077615167654733025140 0ustar fengfeng ukui-settings-daemon/common/ukui_res/ukui_intel/ukui-touchpad-on.svg0000664000175000017500000000050115167654733024774 0ustar fengfeng ukui-settings-daemon/common/ukui_res/ukui_intel/ukui-wifi-off.svg0000664000175000017500000000430615167654733024270 0ustar fengfeng ukui-settings-daemon/common/ukui_res/ukui_intel/ukui-camera-on.svg0000664000175000017500000000076115167654733024425 0ustar fengfeng ukui-settings-daemon/common/ukui_res/ukui_intel/ukui-Fn-on.svg0000664000175000017500000000742515167654733023544 0ustar fengfeng ukui-settings-daemon/common/ukui_res/ukui_intel/ukui-airplane-on.svg0000664000175000017500000000223115167654733024762 0ustar fengfeng ukui-settings-daemon/common/ukui_res/ukui_intel/ukui-numlock-on.svg0000664000175000017500000000363615167654733024651 0ustar fengfeng ukui-settings-daemon/common/eggaccelerators.h0000664000175000017500000000633215167655063020371 0ustar fengfeng/* -*- Mode: C; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef __EGG_ACCELERATORS_H__ #define __EGG_ACCELERATORS_H__ #include #ifdef __cplusplus extern "C" { #endif /* Where a value is also in GdkModifierType we coincide, * otherwise we don't overlap. */ typedef enum { EGG_VIRTUAL_SHIFT_MASK = 1 << 0, EGG_VIRTUAL_LOCK_MASK = 1 << 1, EGG_VIRTUAL_CONTROL_MASK = 1 << 2, EGG_VIRTUAL_ALT_MASK = 1 << 3, /* fixed as Mod1 */ EGG_VIRTUAL_MOD2_MASK = 1 << 4, EGG_VIRTUAL_MOD3_MASK = 1 << 5, EGG_VIRTUAL_MOD4_MASK = 1 << 6, EGG_VIRTUAL_MOD5_MASK = 1 << 7, #if 0 GDK_BUTTON1_MASK = 1 << 8, GDK_BUTTON2_MASK = 1 << 9, GDK_BUTTON3_MASK = 1 << 10, GDK_BUTTON4_MASK = 1 << 11, GDK_BUTTON5_MASK = 1 << 12, /* 13, 14 are used by Xkb for the keyboard group */ #endif EGG_VIRTUAL_MODE_SWITCH_MASK = 1 << 23, EGG_VIRTUAL_NUM_LOCK_MASK = 1 << 24, EGG_VIRTUAL_SCROLL_LOCK_MASK = 1 << 25, /* Also in GdkModifierType */ EGG_VIRTUAL_SUPER_MASK = 1 << 26, EGG_VIRTUAL_HYPER_MASK = 1 << 27, EGG_VIRTUAL_META_MASK = 1 << 28, /* Also in GdkModifierType */ EGG_VIRTUAL_RELEASE_MASK = 1 << 30, /* 28-31 24-27 20-23 16-19 12-15 8-11 4-7 0-3 * 5 f 8 0 0 0 f f */ EGG_VIRTUAL_MODIFIER_MASK = 0x5f8000ff } EggVirtualModifierType; gboolean egg_accelerator_parse_virtual (const gchar *accelerator, guint *accelerator_key, guint **accelerator_codes, EggVirtualModifierType *accelerator_mods); void egg_keymap_resolve_virtual_modifiers (GdkKeymap *keymap, EggVirtualModifierType virtual_mods, GdkModifierType *concrete_mods); void egg_keymap_virtualize_modifiers (GdkKeymap *keymap, GdkModifierType concrete_mods, EggVirtualModifierType *virtual_mods); gchar* egg_virtual_accelerator_name (guint accelerator_key, guint keycode, EggVirtualModifierType accelerator_mods); gchar* egg_virtual_accelerator_label (guint accelerator_key, guint keycode, EggVirtualModifierType accelerator_mods); #ifdef __cplusplus } #endif #endif /* __EGG_ACCELERATORS_H__ */ ukui-settings-daemon/common/ukui-keygrab.cpp0000664000175000017500000001761715167655063020201 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "config.h" #include "ukui-keygrab.h" #ifdef HAVE_X11_EXTENSIONS_XKB_H #include #include #include #include #endif #include "eggaccelerators.h" /* these are the mods whose combinations are ignored by the keygrabbing code */ static GdkModifierType usd_ignored_mods = (GdkModifierType)0; /* these are the ones we actually use for global keys, we always only check * for these set */ static GdkModifierType usd_used_mods = (GdkModifierType)0; static void setup_modifiers (void) { if (usd_used_mods == 0 || usd_ignored_mods == 0) { GdkModifierType dynmods; /* default modifiers */ usd_ignored_mods = \ GdkModifierType(0x2000 /*Xkb modifier*/ | GDK_LOCK_MASK | GDK_HYPER_MASK); usd_used_mods = \ GdkModifierType(GDK_SHIFT_MASK | GDK_CONTROL_MASK |\ GDK_MOD1_MASK | GDK_MOD2_MASK | GDK_MOD3_MASK | GDK_MOD4_MASK |\ GDK_MOD5_MASK | GDK_SUPER_MASK | GDK_META_MASK); /* NumLock can be assigned to varying keys so we need to * resolve and ignore it specially */ dynmods = (GdkModifierType)0; egg_keymap_resolve_virtual_modifiers (gdk_keymap_get_for_display(gdk_display_get_default()), EGG_VIRTUAL_NUM_LOCK_MASK, &dynmods); usd_ignored_mods = GdkModifierType (usd_ignored_mods | dynmods); usd_used_mods = GdkModifierType (usd_used_mods & ~dynmods); dynmods = (GdkModifierType)0; egg_keymap_resolve_virtual_modifiers (gdk_keymap_get_for_display(gdk_display_get_default()), EGG_VIRTUAL_SCROLL_LOCK_MASK, &dynmods); usd_ignored_mods = GdkModifierType (usd_ignored_mods | dynmods); usd_used_mods = GdkModifierType (usd_used_mods & ~dynmods); } } static void grab_key_real (guint keycode, GdkWindow *root, bool grab, int mask) { if (grab) { XGrabKey (GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), keycode, mask, GDK_WINDOW_XID (root), True, GrabModeAsync, GrabModeAsync); } else { XUngrabKey (GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), keycode, mask, GDK_WINDOW_XID (root)); } } /* Grab the key. In order to ignore USD_IGNORED_MODS we need to grab * all combinations of the ignored modifiers and those actually used * for the binding (if any). * * inspired by all_combinations from ukui-panel/ukui-panel/global-keys.c * * This may generate X errors. The correct way to use this is like: * * gdk_error_trap_push (); * * grab_key_unsafe (key, grab, screens); * * gdk_flush (); * if (gdk_error_trap_pop ()) * g_warning ("Grab failed, another application may already have access to key '%u'", * key->keycode); * * This is not done in the function itself, to allow doing multiple grab_key * operations with one flush only. */ #define N_BITS 32 void grab_key_unsafe (Key *key, bool grab, QList *screens) { int indexes[N_BITS]; /* indexes of bits we need to flip */ int i; int bit; int bits_set_cnt; int uppervalue; guint mask; setup_modifiers (); mask = usd_ignored_mods & ~key->state & GDK_MODIFIER_MASK; bit = 0; /* store the indexes of all set bits in mask in the array */ for (i = 0; mask; ++i, mask >>= 1) { if (mask & 0x1) { indexes[bit++] = i; } } bits_set_cnt = bit; uppervalue = 1 << bits_set_cnt; /* grab all possible modifier combinations for our mask */ for (i = 0; i < uppervalue; ++i) { QList::iterator l,begin,end; int j; int result = 0; /* map bits in the counter to those in the mask */ for (j = 0; j < bits_set_cnt; ++j) { if (i & (1 << j)) { result |= (1 << indexes[j]); } } l = begin = screens->begin(); end = screens->end(); for (; l != end; ++l) { GdkScreen *screen = *l; GdkWindow *window = gdk_screen_get_root_window (screen); guint *code = key->keycodes ; for (; code&&(*code); ++code) { grab_key_real (*code, window, grab, result | key->state); } } } } static gboolean have_xkb (Display *dpy) { static int have_xkb = -1; if (have_xkb == -1) { #ifdef HAVE_X11_EXTENSIONS_XKB_H int opcode, error_base, major, minor, xkb_event_base; have_xkb = XkbQueryExtension (dpy, &opcode, &xkb_event_base, &error_base, &major, &minor) && XkbUseExtension (dpy, &major, &minor); #else have_xkb = 0; #endif } return have_xkb; } gboolean key_uses_keycode (const Key *key, guint keycode) { if (key->keycodes != NULL) { guint *c; for (c = key->keycodes; *c; ++c) { if (*c == keycode) return TRUE; } } return FALSE; } gboolean match_key (Key *key, XEvent *event) { guint keyval; GdkModifierType consumed; gint group; if (key == NULL) return FALSE; setup_modifiers (); #ifdef HAVE_X11_EXTENSIONS_XKB_H if (have_xkb (event->xkey.display)) group = XkbGroupForCoreState (event->xkey.state); else #endif group = (event->xkey.state & GDK_KEY_Mode_switch) ? 1 : 0; /* Check if we find a keysym that matches our current state */ if (gdk_keymap_translate_keyboard_state (gdk_keymap_get_for_display(gdk_display_get_default()), event->xkey.keycode, (GdkModifierType)event->xkey.state, group, &keyval, NULL, NULL, &consumed)) { guint lower, upper; gdk_keyval_convert_case (keyval, &lower, &upper); /* If we are checking against the lower version of the * keysym, we might need the Shift state for matching, * so remove it from the consumed modifiers */ if (lower == key->keysym) consumed = GdkModifierType (consumed & ~GDK_SHIFT_MASK); return ((lower == key->keysym || upper == key->keysym) && (event->xkey.state & ~consumed & usd_used_mods) == key->state); } /* The key we passed doesn't have a keysym, so try with just the keycode */ return (key != NULL && key->state == (event->xkey.state & usd_used_mods) && key_uses_keycode (key, event->xkey.keycode)); } ukui-settings-daemon/common/usd_base_class.h0000664000175000017500000000572315167655063020214 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef USDBASECLASS_H #define USDBASECLASS_H #include #include #ifdef KY_SDK_SYSINFO #include #endif #ifdef KY_SDK_HARDWARE #include #endif #include "x11-head.h" extern QString g_motify_poweroff; //lenovo N70Z #define EC_TOUCHPADSTATE "/sys/devices/platform/lenovo_ec/touchpad" //触摸板状态节点 #define PERFORMANCE_MODE "/sys/devices/platform/lenovo_ec/mode" //性能模式节点 class UsdBaseClass: public QObject { Q_OBJECT public: UsdBaseClass(); ~UsdBaseClass(); enum eScreenMode { firstScreenMode = 0, cloneScreenMode, extendScreenMode, secondScreenMode}; Q_ENUM(eScreenMode) enum BatteryState { Connected = 1, Disconnect}; Q_ENUM(BatteryState) enum PowerMode { PerformanceMode = 0, AutoMode, EcoMode}; Q_ENUM(PowerMode) static bool isTablet(); static bool isMasterSP1(); static bool is9X0(); static bool isWayland(); static bool isXcb(); static bool isNotebook(); static bool isLoongarch();//unuse static bool isUseXEventAsShutKey(); static bool readPowerOffConfig(); static bool isPowerOff(); static bool isJJW7200(); static int getDPI(); static double getScaleWithSize(int heightmm, int widthmm, int height, int width); static double getScale(double scaling); static double getScoreScale(double scaling); static bool isEdu(); static void writeUserConfigToLightDM(QString group, QString key, QVariant value, QString userName = ""); static QVariant readUserConfigToLightDM(QString group, QString key, QString userName = ""); static bool isWaylandWithKscreen(); /* * 针对EC自己控制的硬件设备,usd先获取控制权是否在EC,然后读取状态进行状态显示。 */ static bool brightnessControlByHardware(int &step); static bool flightModeControlByHardware(int &mode); static bool touchpadControlByHardware(int &state); static bool powerModeControlByHardware(int &mode); static QVariant readInfoFromFile(QString filePath); static bool isVirt(); static Display *getQx11Info(); private: }; #endif // USDBASECLASS_H ukui-settings-daemon/common/ukui-keygrab.h0000664000175000017500000000272615167655063017641 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef __USD_COMMON_KEYGRAB_H #define __USD_COMMON_KEYGRAB_H #include #ifdef signals #undef signals #endif #ifdef __cplusplus extern "C" { #endif #include #include #include #include typedef struct { guint keysym; guint state; guint *keycodes; } Key; void grab_key_unsafe (Key *key, bool grab, QList *screens); gboolean match_key (Key *key, XEvent *event); gboolean key_uses_keycode (const Key *key, guint keycode); #ifdef __cplusplus } #endif #endif /* __USD_COMMON_KEYGRAB_H */ ukui-settings-daemon/projectDir/0000775000175000017500000000000015167655403015675 5ustar fengfengukui-settings-daemon/projectDir/control_master0000664000175000017500000000673215167654733020670 0ustar fengfengSource: ukui-settings-daemon Section: x11 Priority: optional Maintainer: Kylin Team Uploaders: handsome_feng Build-Depends: debhelper-compat (=12), pkg-config, intltool, qt5-qmake, qtchooser, qtbase5-dev, qtbase5-dev-tools, qttools5-dev-tools, libgsettings-qt-dev, libqt5x11extras5-dev, libqt5sensors5-dev, libkf5config-dev, libqt5svg5-dev, libxklavier-dev, libxtst-dev, libmate-desktop-dev, libgnome-desktop-3-dev, libmatemixer-dev, libmatekbd-dev, libpulse-dev, libwnck-3-dev, libcanberra-gtk3-dev, libcanberra-gtk-common-dev, libcanberra-dev, libwayland-client0, libnotify-dev, libgeoclue-2-dev, libcolord-dev, liblcms2-dev, libimlib2-dev, xserver-xorg-dev, libgudev-1.0-dev, libxcb1-dev, libxcb-util-dev, libx11-dev, libkf5windowsystem-dev, libkf5screen-dev, libxkbcommon-dev, libkf5globalaccel-dev, libqt5x11extras5-dev, libukui-common-dev, Standards-Version: 4.6.0.1 Rules-Requires-Root: no Homepage: http://www.ukui.org/ Vcs-Git: https://github.com/ukui/ukui-settings-daemon.git Vcs-Browser: https://github.com/ukui/ukui-settings-daemon Package: ukui-settings-daemon Architecture: any Depends: mate-desktop-common (>= 1.18), ukui-settings-daemon-common (= ${source:Version}), colord, imwheel, ukui-polkit, x11-xserver-utils, xserver-xorg-input-synaptics [!s390x], libglib2.0-bin, ${misc:Depends}, ${shlibs:Depends}, Conflicts: kylin-display-switch Replaces: kylin-display-switch Description: daemon handling the UKUI session settings This package contains the daemon which is responsible for setting the various parameters of a UKUI session and the applications that run under it. It handles the following kinds of settings: . * Keyboard: layout, accessibility options, shortcuts, media keys * Clipboard management * Theming: background, icons, GTK+ applications * Cleanup of unused files * Mouse: cursors, speed, accessibility options * Startup of other daemons: screensaver, sound daemon * Typing break . It also sets various application settings through X resources and freedesktop.org XSETTINGS. Package: ukui-settings-daemon-common Architecture: all Depends: ${misc:Depends}, Description: daemon handling the UKUI session settings (common files) This package contains the daemon which is responsible for setting the various parameters of a UKUI session and the applications that run under it. It handles the following kinds of settings: . * Keyboard: layout, accessibility options, shortcuts, media keys * Clipboard management * Theming: background, icons, GTK+ applications * Cleanup of unused files * Mouse: cursors, speed, accessibility options * Startup of other daemons: screensaver, sound daemon * Typing break . It also sets various application settings through X resources and freedesktop.org XSETTINGS. . This package contains the architecture independent files. ukui-settings-daemon/projectDir/ukui-settings-daemon_2203update.pro0000664000175000017500000000325015167654733024351 0ustar fengfeng#------------------------------------------------- # # Project created by QtCreator 2020-03-16T09:30:00 # #------------------------------------------------- TEMPLATE = subdirs TRANSLATIONS += daemon/res/i18n/zh_CN.ts CONFIG += ordered SUBDIRS += \ $$PWD/plugins/a11y-keyboard/a11y-keyboard.pro \ $$PWD/plugins/a11y-settings/a11y-settings.pro \ # $$PWD/plugins/auto-brightness/auto-brightness.pro \ # $$PWD/plugins/background/background.pro \ 不开启 $$PWD/plugins/clipboard/clipboard.pro \ $$PWD/plugins/color/color.pro \ $$PWD/plugins/housekeeping/housekeeping.pro \ $$PWD/plugins/keyboard/keyboard.pro \ $$PWD/plugins/keybindings/keybindings.pro \ $$PWD/plugins/media-keys/media-keys.pro \ $$PWD/plugins/mouse/mouse.pro \ $$PWD/plugins/mpris/mpris.pro \ $$PWD/plugins/sound/sound.pro \ $$PWD/plugins/sharing/sharing.pro \ $$PWD/plugins/tablet-mode/tablet-mode.pro \ $$PWD/plugins/xrandr/xrandr.pro \ $$PWD/plugins/xrdb/xrdb.pro \ $$PWD/plugins/xinput/xinput.pro \ $$PWD/plugins/xsettings/xsettings.pro \ $$PWD/plugins/locate-pointer/usd-locate-pointer.pro \ $$PWD/plugins/kds/kds.pro\ $$PWD/plugins/authority/authority.pro\ # $$PWD/plugins/save-param/save-param.pro\ $$PWD/daemon/daemon.pro include($$PWD/data/data.pri) OTHER_FILES += \ $$PWD/LICENSE \ $$PWD/README.md # Automating generation .qm files from .ts files CONFIG(release, debug|release) { !system($$PWD/translate_generation.sh): error("Failed to generate translation") } ukui-settings-daemon/projectDir/common_9x0.pri0000664000175000017500000000212315167655403020377 0ustar fengfengQT += core gui dbus x11extras CONFIG += c++11 no_keywords link_pkgconfig x11extras CONFIG -= app_bundle INCLUDEPATH += -I $$PWD/ PLUGIN_INSTALL_DIRS = $$[QT_INSTALL_LIBS]/ukui-settings-daemon DEFINES += USD_9X0 EXTRA_CFLAGS +=-Wno-date-time PKGCONFIG += glib-2.0 gio-2.0 libxklavier x11 xrandr xtst atk gdk-3.0 gtk+-3.0 xi QMAKE_CXXFLAGS += -Wno-unused-parameter SOURCES += \ $$PWD/clib-syslog.c \ $$PWD/QGSettings/qconftype.cpp \ $$PWD/QGSettings/qgsettings.cpp \ $$PWD/usd_base_class.cpp \ $$PWD/xeventmonitor.cpp \ $$PWD/eggaccelerators.c \ $$PWD/ukui-input-helper.c \ $$PWD/ukui-keygrab.cpp HEADERS += \ $$PWD/clib-syslog.h \ $$PWD/plugin-interface.h \ $$PWD/QGSettings/qconftype.h \ $$PWD/QGSettings/qgsettings.h \ $$PWD/usd_base_class.h \ $$PWD/xeventmonitor.h \ $$PWD/eggaccelerators.h \ $$PWD/ukui-input-helper.h \ $$PWD/ukui-keygrab.h \ $$PWD/config.h ukui-settings-daemon/projectDir/control_3.1.40000664000175000017500000000673215167654733020040 0ustar fengfengSource: ukui-settings-daemon Section: x11 Priority: optional Maintainer: Kylin Team Uploaders: handsome_feng Build-Depends: debhelper-compat (=12), pkg-config, intltool, qt5-qmake, qtchooser, qtbase5-dev, qtbase5-dev-tools, qttools5-dev-tools, libgsettings-qt-dev, libqt5x11extras5-dev, libqt5sensors5-dev, libkf5config-dev, libqt5svg5-dev, libxklavier-dev, libxtst-dev, libmate-desktop-dev, libgnome-desktop-3-dev, libmatemixer-dev, libmatekbd-dev, libpulse-dev, libwnck-3-dev, libcanberra-gtk3-dev, libcanberra-gtk-common-dev, libcanberra-dev, libwayland-client0, libnotify-dev, libgeoclue-2-dev, libcolord-dev, liblcms2-dev, libimlib2-dev, xserver-xorg-dev, libgudev-1.0-dev, libxcb1-dev, libxcb-util-dev, libx11-dev, libkf5windowsystem-dev, libkf5screen-dev, libxkbcommon-dev, libkf5globalaccel-dev, libqt5x11extras5-dev, libukui-common-dev, Standards-Version: 4.6.0.1 Rules-Requires-Root: no Homepage: http://www.ukui.org/ Vcs-Git: https://github.com/ukui/ukui-settings-daemon.git Vcs-Browser: https://github.com/ukui/ukui-settings-daemon Package: ukui-settings-daemon Architecture: any Depends: mate-desktop-common (>= 1.18), ukui-settings-daemon-common (= ${source:Version}), colord, imwheel, ukui-polkit, x11-xserver-utils, xserver-xorg-input-synaptics [!s390x], libglib2.0-bin, ${misc:Depends}, ${shlibs:Depends}, Conflicts: kylin-display-switch Replaces: kylin-display-switch Description: daemon handling the UKUI session settings This package contains the daemon which is responsible for setting the various parameters of a UKUI session and the applications that run under it. It handles the following kinds of settings: . * Keyboard: layout, accessibility options, shortcuts, media keys * Clipboard management * Theming: background, icons, GTK+ applications * Cleanup of unused files * Mouse: cursors, speed, accessibility options * Startup of other daemons: screensaver, sound daemon * Typing break . It also sets various application settings through X resources and freedesktop.org XSETTINGS. Package: ukui-settings-daemon-common Architecture: all Depends: ${misc:Depends}, Description: daemon handling the UKUI session settings (common files) This package contains the daemon which is responsible for setting the various parameters of a UKUI session and the applications that run under it. It handles the following kinds of settings: . * Keyboard: layout, accessibility options, shortcuts, media keys * Clipboard management * Theming: background, icons, GTK+ applications * Cleanup of unused files * Mouse: cursors, speed, accessibility options * Startup of other daemons: screensaver, sound daemon * Typing break . It also sets various application settings through X resources and freedesktop.org XSETTINGS. . This package contains the architecture independent files. ukui-settings-daemon/projectDir/ukui-settings-daemon_master.pro0000664000175000017500000000325015167654733024053 0ustar fengfeng#------------------------------------------------- # # Project created by QtCreator 2020-03-16T09:30:00 # #------------------------------------------------- TEMPLATE = subdirs TRANSLATIONS += daemon/res/i18n/zh_CN.ts CONFIG += ordered SUBDIRS += \ $$PWD/plugins/a11y-keyboard/a11y-keyboard.pro \ $$PWD/plugins/a11y-settings/a11y-settings.pro \ # $$PWD/plugins/auto-brightness/auto-brightness.pro \ # $$PWD/plugins/background/background.pro \ 不开启 $$PWD/plugins/clipboard/clipboard.pro \ $$PWD/plugins/color/color.pro \ $$PWD/plugins/housekeeping/housekeeping.pro \ $$PWD/plugins/keyboard/keyboard.pro \ $$PWD/plugins/keybindings/keybindings.pro \ $$PWD/plugins/media-keys/media-keys.pro \ $$PWD/plugins/mouse/mouse.pro \ $$PWD/plugins/mpris/mpris.pro \ $$PWD/plugins/sound/sound.pro \ $$PWD/plugins/sharing/sharing.pro \ $$PWD/plugins/tablet-mode/tablet-mode.pro \ $$PWD/plugins/xrandr/xrandr.pro \ $$PWD/plugins/xrdb/xrdb.pro \ $$PWD/plugins/xinput/xinput.pro \ $$PWD/plugins/xsettings/xsettings.pro \ $$PWD/plugins/locate-pointer/usd-locate-pointer.pro \ $$PWD/plugins/kds/kds.pro\ $$PWD/plugins/authority/authority.pro\ # $$PWD/plugins/save-param/save-param.pro\ $$PWD/daemon/daemon.pro include($$PWD/data/data.pri) OTHER_FILES += \ $$PWD/LICENSE \ $$PWD/README.md # Automating generation .qm files from .ts files CONFIG(release, debug|release) { !system($$PWD/translate_generation.sh): error("Failed to generate translation") } ukui-settings-daemon/projectDir/ukui-settings-daemon_3.1.4.pro0000664000175000017500000000325015167654733023223 0ustar fengfeng#------------------------------------------------- # # Project created by QtCreator 2020-03-16T09:30:00 # #------------------------------------------------- TEMPLATE = subdirs TRANSLATIONS += daemon/res/i18n/zh_CN.ts CONFIG += ordered SUBDIRS += \ $$PWD/plugins/a11y-keyboard/a11y-keyboard.pro \ $$PWD/plugins/a11y-settings/a11y-settings.pro \ # $$PWD/plugins/auto-brightness/auto-brightness.pro \ # $$PWD/plugins/background/background.pro \ 不开启 $$PWD/plugins/clipboard/clipboard.pro \ $$PWD/plugins/color/color.pro \ $$PWD/plugins/housekeeping/housekeeping.pro \ $$PWD/plugins/keyboard/keyboard.pro \ $$PWD/plugins/keybindings/keybindings.pro \ $$PWD/plugins/media-keys/media-keys.pro \ $$PWD/plugins/mouse/mouse.pro \ $$PWD/plugins/mpris/mpris.pro \ $$PWD/plugins/sound/sound.pro \ $$PWD/plugins/sharing/sharing.pro \ $$PWD/plugins/tablet-mode/tablet-mode.pro \ $$PWD/plugins/xrandr/xrandr.pro \ $$PWD/plugins/xrdb/xrdb.pro \ $$PWD/plugins/xinput/xinput.pro \ $$PWD/plugins/xsettings/xsettings.pro \ $$PWD/plugins/locate-pointer/usd-locate-pointer.pro \ $$PWD/plugins/kds/kds.pro\ $$PWD/plugins/authority/authority.pro\ # $$PWD/plugins/save-param/save-param.pro\ $$PWD/daemon/daemon.pro include($$PWD/data/data.pri) OTHER_FILES += \ $$PWD/LICENSE \ $$PWD/README.md # Automating generation .qm files from .ts files CONFIG(release, debug|release) { !system($$PWD/translate_generation.sh): error("Failed to generate translation") } ukui-settings-daemon/projectDir/changelog_ubuntu0000664000175000017500000000035415167654733021160 0ustar fengfengukui-settings-daemon (3.1.2-1.3) jammy; urgency=medium * BUG号:无 * 需求说明: * 其他改动说明:优化编译 * 其他改动影响域:无 -- sunjunhao Fri, 15 Apr 2022 17:07:56 +0800 ukui-settings-daemon/projectDir/ukui-settings-daemon_9x0.pro0000664000175000017500000000261215167654733023201 0ustar fengfeng#------------------------------------------------- # # Project created by QtCreator 2020-03-16T09:30:00 # #------------------------------------------------- TEMPLATE = subdirs TRANSLATIONS += daemon/res/i18n/zh_CN.ts CONFIG += ordered SUBDIRS += \ # $$PWD/plugins/a11y-keyboard/a11y-keyboard.pro \ # $$PWD/plugins/a11y-settings/a11y-settings.pro \ # $$PWD/plugins/background/background.pro \ $$PWD/plugins/clipboard/clipboard.pro \ # $$PWD/plugins/color/color.pro \ $$PWD/plugins/housekeeping/housekeeping.pro \ $$PWD/plugins/keyboard/keyboard.pro \ $$PWD/plugins/keybindings/keybindings.pro \ $$PWD/plugins/media-keys/media-keys.pro \ $$PWD/plugins/mouse/mouse.pro \ $$PWD/plugins/mpris/mpris.pro \ $$PWD/plugins/sound/sound.pro \ $$PWD/plugins/tablet-mode/tablet-mode.pro \ $$PWD/plugins/xrandr/xrandr.pro \ $$PWD/plugins/xrdb/xrdb.pro \ $$PWD/plugins/xsettings/xsettings.pro \ $$PWD/plugins/locate-pointer/usd-locate-pointer.pro \ $$PWD/daemon/daemon.pro include($$PWD/data/data.pri) OTHER_FILES += \ $$PWD/LICENSE \ $$PWD/README.md # Automating generation .qm files from .ts files CONFIG(release, debug|release) { !system($$PWD/translate_generation.sh): error("Failed to generate translation") } ukui-settings-daemon/projectDir/changelog_3.1.40000664000175000017500000002745615167654733020315 0ustar fengfengukui-settings-daemon (3.14.0.0~0512) v101; urgency=medium * BUG号:无 * 需求说明:83242【控制面板】增加鼠标滚轴方向设置功能 * 其他改动说明:无 * 其他改动影响域:无 -- sun Thu, 12 May 2022 09:52:40 +0800 ukui-settings-daemon (3.1.0-1.55) v101; urgency=medium * BUG号: * 需求说明: * 其他改动说明:优化触摸类设备的映射机制 * 其他改动影响域:无 -- sunjunhao Sat, 07 May 2022 09:45:45 +0800 ukui-settings-daemon (3.1.0-1.54) v101; urgency=medium * BUG号: 115949 【显示器】快捷键设置亮度为任意值后重启,亮度状态并没有保持 116025 【护眼中心】【亮度调节】关闭智能亮度调节后重启机器,ui处显示该功能关闭,但是亮度会自动调节 114902 【护眼中心】手动调整亮度后,重启智能调节开关后,亮度会先增加1,然后进行自动调节(必现) 115161 【peony】【平板模式】竖屏平板模式下关闭自动旋转,将屏幕变为横屏再变为竖屏,平板桌面显示异常 114779 【护眼中心】【usd】短暂遮挡传感器,背光亮度会停留在53/短暂增大亮度,背光亮度会停留在63 * 需求说明: * 其他改动说明:第一屏同等分辨率,优先选取最大的刷新率进行设置。 * 其他改动影响域:无 -- sunjunhao Fri, 06 May 2022 16:19:39 +0800 ukui-settings-daemon (3.1.0-1.53) v101; urgency=medium * BUG号: * 需求说明: * 其他改动说明:第一屏同等分辨率,优先选取最大的刷新率进行设置。 * 其他改动影响域:无 -- sunjunhao Fri, 06 May 2022 10:22:59 +0800 ukui-settings-daemon (3.1.0-1.52) v101; urgency=medium * BUG号: * 需求说明: * 其他改动说明:移除多余gpiod依赖,主线暂时不上自动背光。 * 其他改动影响域:无 -- sunjunhao Thu, 05 May 2022 16:53:25 +0800 ukui-settings-daemon (3.1.0-1.51) v101; urgency=medium * BUG号: * 需求说明:77064 窗管实现一键切换机制(需要kwin配合) * 其他改动说明:优化首次运行时获取屏幕参数的时机。 * 其他改动影响域:无 -- sunjunhao Thu, 05 May 2022 16:38:44 +0800 ukui-settings-daemon (3.1.0-1.50) v101; urgency=medium * BUG号:116907 【中移联想】【双屏】【x13 AMD】接入HDMI后,切换扩展屏无响应,仍然显示镜像模式 *116890 【中移联想】【锁屏】【x13 AMD】 接HDMI 显示器后,锁屏和屏保界面显示异常 * 需求说明: * 其他改动说明:优化编译 * 其他改动影响域:无 -- sunjunhao Fri, 29 Apr 2022 08:15:15 +0800 ukui-settings-daemon (3.1.0-1.49) v101; urgency=medium * BUG号:无 * 需求说明:79112 动态背光控制功能集成Intel提供的patch,提供接口(需要mv版本的硬件支持) * 其他改动说明:优化编译 * 其他改动影响域:无 -- sunjunhao Tue, 19 Apr 2022 19:00:48 +0800 ukui-settings-daemon (3.1.0-1.46) v101; urgency=medium * BUG号:114902 【护眼中心】手动调整亮度后,重启智能调节开关后,亮度会先增加1,然后进行自动调节(必现) * 114779 【护眼中心】【usd】短暂遮挡传感器,背光亮度会停留在53/短暂增大亮度,背光亮度会停留在63 * 115161 【peony】【平板模式】竖屏平板模式下关闭自动旋转,将屏幕变为横屏再变为竖屏,平板桌面显示异常 * 需求说明: * 其他改动说明: * 其他改动影响域:无 -- sunjunhao Fri, 15 Apr 2022 11:36:50 +0800 ukui-settings-daemon (3.1.0-1.45) v101; urgency=medium * BUG号:无 * 需求说明: * 其他改动说明:删除postinst文件的无效命令 * 其他改动影响域:无 -- sunjunhao Fri, 15 Apr 2022 11:36:50 +0800 ukui-settings-daemon (3.1.0-1.44) v101; urgency=medium * BUG号:无 * 需求说明:11534 子 【护眼中心】新增智能自动亮度调节 / 【护眼中心】新增智能自动亮度调节 * 其他改动说明:无 * 其他改动影响域:无 -- sunjunhao Tue, 29 Mar 2022 13:44:47 +0800 ukui-settings-daemon (3.1.0-1.43) v101; urgency=medium * BUG号:无 * 需求说明:无 * 其他改动说明:修复dbus提权的安全问题 * 其他改动影响域:无 -- sundagao Tue, 08 Mar 2022 10:14:38 +0800 ukui-settings-daemon (3.1.0-1.41) v101; urgency=medium * BUG号:无 * 需求说明:无 * 其他改动说明:功耗问题 * 其他改动影响域:无 -- sundagao Thu, 03 Mar 2022 15:49:00 +0800 ukui-settings-daemon (3.1.0-1.40) v101; urgency=medium * BUG号:107432 【快捷键】升级后,快捷键及功能热键全部失效(2/2units) * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Tue, 22 Feb 2022 13:56:34 +0800 ukui-settings-daemon (3.1.0-1.39) v101; urgency=medium * BUG号:107101 【控制面板】【显示器】连接外接显示器,拓展模式下,在平板触控,触摸映射到了拓展屏上(必现) * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Tue, 22 Feb 2022 13:37:39 +0800 ukui-settings-daemon (3.1.0-1.38) v101; urgency=medium * BUG号:106951 【触控笔】连接外显扩展模式下使用触控笔会出现偏移(必现) * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Mon, 21 Feb 2022 09:17:49 +0800 ukui-settings-daemon (3.1.0-1.37) v101; urgency=medium * BUG号:106966 【快捷键】重启后,热键F3\F4\F5\F6\F7无功能(偶现:目前两台机器各出现一次) * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Sat, 19 Feb 2022 14:45:16 +0800 ukui-settings-daemon (3.1.0-1.36) v101; urgency=medium * BUG号:HZ 95808 【终端】鼠标大小设置中,在移动到终端标题栏大小会变化(主线同样存在) 106028 【镜像独有】【PTOF】【TM】【旋转】PC模式切换到平板模式开启自动旋转,旋转设备后使用触摸/触控笔概率会出现偏移(2/20 times 2/2 units) * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Fri, 28 Jan 2022 14:11:44 +0800 ukui-settings-daemon (3.1.0-1.35) v101; urgency=medium * BUG号:105291 【显示器】按下win+p后释放p不释放win,接着按下tab键,系统投屏弹窗显示在多任务视图窗口(必现) 87053 【S】【PTOF】【显示】win+p打开系统投屏选择窗,该选择窗可被拖动,且使用触摸屏点击投屏选择框以外的区域无法将其关闭(必现) * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Thu, 27 Jan 2022 10:32:01 +0800 ukui-settings-daemon (3.1.0-1.33) v101; urgency=medium * BUG号:101919 高 一般【自适应升级】【显示器】多屏显示在自适应升级注销重新登录后,升级前设置的扩展模式变为镜像模式 101257 中等 一般【显示】【自适应升级】更新升级后显示模块分辨率没有保存 102186 中等 一般【显示】【自适应升级】更新升级后控制面板-显示-夜间模式没有保存数据 * 需求说明:无 * 其他改动说明:触摸屏映射优化 * 其他改动影响域:触摸映射 -- sundagao Tue, 18 Jan 2022 09:23:06 +0800 ukui-settings-daemon (3.1.0-1.31) v101; urgency=medium * BUG号:HZ 95808 【终端】鼠标大小设置中,在移动到终端标题栏大小会变化(主线同样存在) * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Thu, 06 Jan 2022 16:28:11 +0800 ukui-settings-daemon (3.1.0-1.30) v101; urgency=medium * BUG号:95487 【触摸】【触摸映射】【控制面板】手动设置触摸映射后重启设备,登录后没有保持之前的映射关系;设置触摸映射后删除配置文件重启设备没有恢复默认自动映射关系(可以使用触摸映射设置回来)(必现) 95486 【触摸】【触摸映射】【控制面板】自动映射/手动映射后 插拔触摸线/修改分辨率/方向后,触摸落点偏移(可以使用触摸映射设置回来)(必现) 95485 【触摸】【自动映射】【控制面板】已连接A显示器(A为主屏)B显示器,设置扩展模式,连接B触摸线,在B显示器触摸的映射区域为屏A+屏B的范围(预期:接入的第2块触摸屏对应接入第2块显示器,可以使用触摸映射设置回来)(必现) * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Tue, 28 Dec 2021 17:39:14 +0800 ukui-settings-daemon (3.1.0-1.29) v101; urgency=medium * BUG号:无 * 需求说明:无 * 其他改动说明:镜像模式下控制面板切换分辨率,切换另外的显示模式,在切换回来,分辨率没有回复 * 其他改动影响域:双屏切换配置保存 -- sundagao Wed, 15 Dec 2021 13:52:59 +0800 ukui-settings-daemon (3.1.0-1.28) v101; urgency=medium * BUG号:95487 【触摸】【触摸映射】【控制面板】手动设置触摸映射后重启设备,登录后没有保持之前的映射关系;设置触摸映射后删除配置文件重启设备没有恢复默认自动映射关系(可以使用触摸映射设置回来)(必现) * 需求号:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Mon, 13 Dec 2021 16:32:06 +0800 ukui-settings-daemon (3.1.0-1.27) v101; urgency=medium * BUG号:93538 【SP2 UI走查】【OSD】UI待按照设计稿优化,间距尺寸等 * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Tue, 07 Dec 2021 17:16:54 +0800 ukui-settings-daemon (3.1.0-1.26) v101; urgency=medium * BUG号:89404 【需求-触摸-7467】【触摸】【显示】控制面板设置旋转方向为 顺/逆时针90度、上下颠倒,旋转方向后触摸偏移(必现) 93707 【显示】【USD】【必现】存在状态异常的配置文件时,连接1个显示器开机,打开控制面板-显示器,插上4K显示器,USD崩溃,产生core文件 92571 【触摸板】打开插入鼠标时禁用触摸板,拔掉鼠标后触摸板仍然不可用 * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Mon, 06 Dec 2021 18:45:38 +0800 ukui-settings-daemon (3.1.0-1.25) v101; urgency=medium * New upstream release. * fix bug#95916 【20.04-pro】【USD】系统缺少kylin-screenshot包时USD无法正常启动,提示段错误 -- Allen Fri, 10 Dec 2021 16:00:22 +0800 ukui-settings-daemon (1.2.0-1) unstable; urgency=medium * New upstream release. * debian/control: - Bump standards-version to 4.5.0. - Use debhelper-compat. * debian/copyright: - Remove COPYING from copyright. -- handsome_feng Mon, 24 Feb 2020 11:47:45 +0800 ukui-settings-daemon (1.1.7-2) unstable; urgency=medium * Don't set click actions since ukwm take over that. * debian/control: - Bump standards-version to 4.4.0. - Bump compat level to 12. - mate-polkit -> ukui-polkit. -- handsome_feng Wed, 07 Aug 2019 15:22:43 +0800 ukui-settings-daemon/projectDir/changelog_tablet0000664000175000017500000002643015167654733021114 0ustar fengfengukui-settings-daemon (3.1.0-1.54) v101; urgency=medium * BUG号: 115949 【显示器】快捷键设置亮度为任意值后重启,亮度状态并没有保持 116025 【护眼中心】【亮度调节】关闭智能亮度调节后重启机器,ui处显示该功能关闭,但是亮度会自动调节 114902 【护眼中心】手动调整亮度后,重启智能调节开关后,亮度会先增加1,然后进行自动调节(必现) 115161 【peony】【平板模式】竖屏平板模式下关闭自动旋转,将屏幕变为横屏再变为竖屏,平板桌面显示异常 114779 【护眼中心】【usd】短暂遮挡传感器,背光亮度会停留在53/短暂增大亮度,背光亮度会停留在63 * 需求说明: * 其他改动说明:第一屏同等分辨率,优先选取最大的刷新率进行设置。 * 其他改动影响域:无 -- sunjunhao Fri, 06 May 2022 16:19:39 +0800 ukui-settings-daemon (3.1.0-1.53) v101; urgency=medium * BUG号: * 需求说明: * 其他改动说明:第一屏同等分辨率,优先选取最大的刷新率进行设置。 * 其他改动影响域:无 -- sunjunhao Fri, 06 May 2022 10:22:59 +0800 ukui-settings-daemon (3.1.0-1.52) v101; urgency=medium * BUG号: * 需求说明: * 其他改动说明:移除多余gpiod依赖,主线暂时不上自动背光。 * 其他改动影响域:无 -- sunjunhao Thu, 05 May 2022 16:53:25 +0800 ukui-settings-daemon (3.1.0-1.51) v101; urgency=medium * BUG号: * 需求说明:77064 窗管实现一键切换机制(需要kwin配合) * 其他改动说明:优化首次运行时获取屏幕参数的时机。 * 其他改动影响域:无 -- sunjunhao Thu, 05 May 2022 16:38:44 +0800 ukui-settings-daemon (3.1.0-1.50) v101; urgency=medium * BUG号:116907 【中移联想】【双屏】【x13 AMD】接入HDMI后,切换扩展屏无响应,仍然显示镜像模式 *116890 【中移联想】【锁屏】【x13 AMD】 接HDMI 显示器后,锁屏和屏保界面显示异常 * 需求说明: * 其他改动说明:优化编译 * 其他改动影响域:无 -- sunjunhao Fri, 29 Apr 2022 08:15:15 +0800 ukui-settings-daemon (3.1.0-1.49) v101; urgency=medium * BUG号:无 * 需求说明:79112 动态背光控制功能集成Intel提供的patch,提供接口(需要mv版本的硬件支持) * 其他改动说明:优化编译 * 其他改动影响域:无 -- sunjunhao Tue, 19 Apr 2022 19:00:48 +0800 ukui-settings-daemon (3.1.0-1.46) v101; urgency=medium * BUG号:114902 【护眼中心】手动调整亮度后,重启智能调节开关后,亮度会先增加1,然后进行自动调节(必现) * 114779 【护眼中心】【usd】短暂遮挡传感器,背光亮度会停留在53/短暂增大亮度,背光亮度会停留在63 * 115161 【peony】【平板模式】竖屏平板模式下关闭自动旋转,将屏幕变为横屏再变为竖屏,平板桌面显示异常 * 需求说明: * 其他改动说明: * 其他改动影响域:无 -- sunjunhao Fri, 15 Apr 2022 11:36:50 +0800 ukui-settings-daemon (3.1.0-1.45) v101; urgency=medium * BUG号:无 * 需求说明: * 其他改动说明:删除postinst文件的无效命令 * 其他改动影响域:无 -- sunjunhao Fri, 15 Apr 2022 11:36:50 +0800 ukui-settings-daemon (3.1.0-1.44) v101; urgency=medium * BUG号:无 * 需求说明:11534 子 【护眼中心】新增智能自动亮度调节 / 【护眼中心】新增智能自动亮度调节 * 其他改动说明:无 * 其他改动影响域:无 -- sunjunhao Tue, 29 Mar 2022 13:44:47 +0800 ukui-settings-daemon (3.1.0-1.43) v101; urgency=medium * BUG号:无 * 需求说明:无 * 其他改动说明:修复dbus提权的安全问题 * 其他改动影响域:无 -- sundagao Tue, 08 Mar 2022 10:14:38 +0800 ukui-settings-daemon (3.1.0-1.41) v101; urgency=medium * BUG号:无 * 需求说明:无 * 其他改动说明:功耗问题 * 其他改动影响域:无 -- sundagao Thu, 03 Mar 2022 15:49:00 +0800 ukui-settings-daemon (3.1.0-1.40) v101; urgency=medium * BUG号:107432 【快捷键】升级后,快捷键及功能热键全部失效(2/2units) * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Tue, 22 Feb 2022 13:56:34 +0800 ukui-settings-daemon (3.1.0-1.39) v101; urgency=medium * BUG号:107101 【控制面板】【显示器】连接外接显示器,拓展模式下,在平板触控,触摸映射到了拓展屏上(必现) * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Tue, 22 Feb 2022 13:37:39 +0800 ukui-settings-daemon (3.1.0-1.38) v101; urgency=medium * BUG号:106951 【触控笔】连接外显扩展模式下使用触控笔会出现偏移(必现) * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Mon, 21 Feb 2022 09:17:49 +0800 ukui-settings-daemon (3.1.0-1.37) v101; urgency=medium * BUG号:106966 【快捷键】重启后,热键F3\F4\F5\F6\F7无功能(偶现:目前两台机器各出现一次) * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Sat, 19 Feb 2022 14:45:16 +0800 ukui-settings-daemon (3.1.0-1.36) v101; urgency=medium * BUG号:HZ 95808 【终端】鼠标大小设置中,在移动到终端标题栏大小会变化(主线同样存在) 106028 【镜像独有】【PTOF】【TM】【旋转】PC模式切换到平板模式开启自动旋转,旋转设备后使用触摸/触控笔概率会出现偏移(2/20 times 2/2 units) * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Fri, 28 Jan 2022 14:11:44 +0800 ukui-settings-daemon (3.1.0-1.35) v101; urgency=medium * BUG号:105291 【显示器】按下win+p后释放p不释放win,接着按下tab键,系统投屏弹窗显示在多任务视图窗口(必现) 87053 【S】【PTOF】【显示】win+p打开系统投屏选择窗,该选择窗可被拖动,且使用触摸屏点击投屏选择框以外的区域无法将其关闭(必现) * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Thu, 27 Jan 2022 10:32:01 +0800 ukui-settings-daemon (3.1.0-1.33) v101; urgency=medium * BUG号:101919 高 一般【自适应升级】【显示器】多屏显示在自适应升级注销重新登录后,升级前设置的扩展模式变为镜像模式 101257 中等 一般【显示】【自适应升级】更新升级后显示模块分辨率没有保存 102186 中等 一般【显示】【自适应升级】更新升级后控制面板-显示-夜间模式没有保存数据 * 需求说明:无 * 其他改动说明:触摸屏映射优化 * 其他改动影响域:触摸映射 -- sundagao Tue, 18 Jan 2022 09:23:06 +0800 ukui-settings-daemon (3.1.0-1.31) v101; urgency=medium * BUG号:HZ 95808 【终端】鼠标大小设置中,在移动到终端标题栏大小会变化(主线同样存在) * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Thu, 06 Jan 2022 16:28:11 +0800 ukui-settings-daemon (3.1.0-1.30) v101; urgency=medium * BUG号:95487 【触摸】【触摸映射】【控制面板】手动设置触摸映射后重启设备,登录后没有保持之前的映射关系;设置触摸映射后删除配置文件重启设备没有恢复默认自动映射关系(可以使用触摸映射设置回来)(必现) 95486 【触摸】【触摸映射】【控制面板】自动映射/手动映射后 插拔触摸线/修改分辨率/方向后,触摸落点偏移(可以使用触摸映射设置回来)(必现) 95485 【触摸】【自动映射】【控制面板】已连接A显示器(A为主屏)B显示器,设置扩展模式,连接B触摸线,在B显示器触摸的映射区域为屏A+屏B的范围(预期:接入的第2块触摸屏对应接入第2块显示器,可以使用触摸映射设置回来)(必现) * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Tue, 28 Dec 2021 17:39:14 +0800 ukui-settings-daemon (3.1.0-1.29) v101; urgency=medium * BUG号:无 * 需求说明:无 * 其他改动说明:镜像模式下控制面板切换分辨率,切换另外的显示模式,在切换回来,分辨率没有回复 * 其他改动影响域:双屏切换配置保存 -- sundagao Wed, 15 Dec 2021 13:52:59 +0800 ukui-settings-daemon (3.1.0-1.28) v101; urgency=medium * BUG号:95487 【触摸】【触摸映射】【控制面板】手动设置触摸映射后重启设备,登录后没有保持之前的映射关系;设置触摸映射后删除配置文件重启设备没有恢复默认自动映射关系(可以使用触摸映射设置回来)(必现) * 需求号:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Mon, 13 Dec 2021 16:32:06 +0800 ukui-settings-daemon (3.1.0-1.27) v101; urgency=medium * BUG号:93538 【SP2 UI走查】【OSD】UI待按照设计稿优化,间距尺寸等 * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Tue, 07 Dec 2021 17:16:54 +0800 ukui-settings-daemon (3.1.0-1.26) v101; urgency=medium * BUG号:89404 【需求-触摸-7467】【触摸】【显示】控制面板设置旋转方向为 顺/逆时针90度、上下颠倒,旋转方向后触摸偏移(必现) 93707 【显示】【USD】【必现】存在状态异常的配置文件时,连接1个显示器开机,打开控制面板-显示器,插上4K显示器,USD崩溃,产生core文件 92571 【触摸板】打开插入鼠标时禁用触摸板,拔掉鼠标后触摸板仍然不可用 * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Mon, 06 Dec 2021 18:45:38 +0800 ukui-settings-daemon (3.1.0-1.25) v101; urgency=medium * New upstream release. * fix bug#95916 【20.04-pro】【USD】系统缺少kylin-screenshot包时USD无法正常启动,提示段错误 -- Allen Fri, 10 Dec 2021 16:00:22 +0800 ukui-settings-daemon (1.2.0-1) unstable; urgency=medium * New upstream release. * debian/control: - Bump standards-version to 4.5.0. - Use debhelper-compat. * debian/copyright: - Remove COPYING from copyright. -- handsome_feng Mon, 24 Feb 2020 11:47:45 +0800 ukui-settings-daemon (1.1.7-2) unstable; urgency=medium * Don't set click actions since ukwm take over that. * debian/control: - Bump standards-version to 4.4.0. - Bump compat level to 12. - mate-polkit -> ukui-polkit. -- handsome_feng Wed, 07 Aug 2019 15:22:43 +0800 ukui-settings-daemon/projectDir/ukui-settings-daemon_tablet.pro0000664000175000017500000000324715167654733024041 0ustar fengfeng#------------------------------------------------- # # Project created by QtCreator 2020-03-16T09:30:00 # #------------------------------------------------- TEMPLATE = subdirs TRANSLATIONS += daemon/res/i18n/zh_CN.ts CONFIG += ordered SUBDIRS += \ $$PWD/plugins/a11y-keyboard/a11y-keyboard.pro \ $$PWD/plugins/a11y-settings/a11y-settings.pro \ $$PWD/plugins/auto-brightness/auto-brightness.pro \ # $$PWD/plugins/background/background.pro \ 不开启 $$PWD/plugins/clipboard/clipboard.pro \ $$PWD/plugins/color/color.pro \ $$PWD/plugins/housekeeping/housekeeping.pro \ $$PWD/plugins/keyboard/keyboard.pro \ $$PWD/plugins/keybindings/keybindings.pro \ $$PWD/plugins/media-keys/media-keys.pro \ $$PWD/plugins/mouse/mouse.pro \ $$PWD/plugins/mpris/mpris.pro \ $$PWD/plugins/sound/sound.pro \ $$PWD/plugins/sharing/sharing.pro \ $$PWD/plugins/tablet-mode/tablet-mode.pro \ $$PWD/plugins/xrandr/xrandr.pro \ $$PWD/plugins/xrdb/xrdb.pro \ $$PWD/plugins/xinput/xinput.pro \ $$PWD/plugins/xsettings/xsettings.pro \ $$PWD/plugins/locate-pointer/usd-locate-pointer.pro \ $$PWD/plugins/kds/kds.pro\ $$PWD/plugins/authority/authority.pro\ # $$PWD/plugins/save-param/save-param.pro\ $$PWD/daemon/daemon.pro include($$PWD/data/data.pri) OTHER_FILES += \ $$PWD/LICENSE \ $$PWD/README.md # Automating generation .qm files from .ts files CONFIG(release, debug|release) { !system($$PWD/translate_generation.sh): error("Failed to generate translation") } ukui-settings-daemon/projectDir/common_master.pri0000664000175000017500000000240715167655403021257 0ustar fengfengQT += core gui dbus x11extras CONFIG += c++11 no_keywords link_pkgconfig x11extras debug CONFIG -= app_bundle INCLUDEPATH += -I $$PWD/ LIBS += -lukui-com4cxx PLUGIN_INSTALL_DIRS = $$[QT_INSTALL_LIBS]/ukui-settings-daemon EXTRA_CFLAGS +=-Wno-date-time PKGCONFIG += glib-2.0 gio-2.0 libxklavier x11 xrandr xtst atk gdk-3.0 gtk+-3.0 xi QMAKE_CXXFLAGS += -Wno-unused-parameter SOURCES += \ $$PWD/clib-syslog.c \ $$PWD/QGSettings/qconftype.cpp \ $$PWD/QGSettings/qgsettings.cpp \ $$PWD/rfkillswitch.cpp \ $$PWD/usd_base_class.cpp \ $$PWD/xeventmonitor.cpp \ $$PWD/eggaccelerators.c \ $$PWD/ukui-input-helper.c \ $$PWD/ukui-keygrab.cpp HEADERS += \ $$PWD/clib-syslog.h \ $$PWD/plugin-interface.h \ $$PWD/QGSettings/qconftype.h \ $$PWD/QGSettings/qgsettings.h \ $$PWD/rfkillswitch.h \ $$PWD/usd_base_class.h \ $$PWD/usd_global_define.h \ $$PWD/xeventmonitor.h \ $$PWD/eggaccelerators.h \ $$PWD/ukui-input-helper.h \ $$PWD/ukui-keygrab.h \ $$PWD/config.h \ $$PWD/xrandroutput.h RESOURCES += \ $$PWD/ukui_icon.qrc ukui-settings-daemon/projectDir/control_9x00000664000175000017500000000625115167654733020011 0ustar fengfengSource: ukui-settings-daemon Section: x11 Priority: optional Maintainer: Kylin Team Uploaders: handsome_feng Build-Depends: debhelper-compat (=12), pkg-config, intltool, qt5-qmake, qtchooser, qtbase5-dev, qtbase5-dev-tools, qttools5-dev-tools, libgsettings-qt-dev, libqt5x11extras5-dev, libqt5sensors5-dev, libkf5config-dev, libqt5svg5-dev, libxklavier-dev, libxtst-dev, libmate-desktop-dev, libgnome-desktop-3-dev, libmatemixer-dev, libmatekbd-dev, libpulse-dev, libwnck-3-dev, libcanberra-gtk3-dev, libcanberra-gtk-common-dev, libcanberra-dev, libwayland-client0, libnotify-dev, libgeoclue-2-dev, libcolord-dev, liblcms2-dev, libimlib2-dev, xserver-xorg-dev, libgudev-1.0-dev, libkf5screen-dev, libkf5globalaccel-dev, Standards-Version: 4.5.0 Rules-Requires-Root: no Homepage: http://www.ukui.org/ Vcs-Git: https://github.com/ukui/ukui-settings-daemon.git Vcs-Browser: https://github.com/ukui/ukui-settings-daemon Package: ukui-settings-daemon Architecture: any Depends: mate-desktop-common (>= 1.18), ukui-settings-daemon-common (= ${source:Version}), imwheel, ukui-polkit, x11-xserver-utils, ukui-qt5xcb-plugin, libglib2.0-bin, ${misc:Depends}, ${shlibs:Depends}, Description: daemon handling the UKUI session settings This package contains the daemon which is responsible for setting the various parameters of a UKUI session and the applications that run under it. It handles the following kinds of settings: . * Keyboard: layout, accessibility options, shortcuts, media keys * Clipboard management * Theming: background, icons, GTK+ applications * Cleanup of unused files * Mouse: cursors, speed, accessibility options * Startup of other daemons: screensaver, sound daemon * Typing break . It also sets various application settings through X resources and freedesktop.org XSETTINGS. Package: ukui-settings-daemon-common Architecture: all Depends: ${misc:Depends}, Description: daemon handling the UKUI session settings (common files) This package contains the daemon which is responsible for setting the various parameters of a UKUI session and the applications that run under it. It handles the following kinds of settings: . * Keyboard: layout, accessibility options, shortcuts, media keys * Clipboard management * Theming: background, icons, GTK+ applications * Cleanup of unused files * Mouse: cursors, speed, accessibility options * Startup of other daemons: screensaver, sound daemon * Typing break . It also sets various application settings through X resources and freedesktop.org XSETTINGS. . This package contains the architecture independent files. ukui-settings-daemon/projectDir/common_tablet.pri0000664000175000017500000000240715167655403021237 0ustar fengfengQT += core gui dbus x11extras CONFIG += c++11 no_keywords link_pkgconfig x11extras debug CONFIG -= app_bundle INCLUDEPATH += -I $$PWD/ LIBS += -lukui-com4cxx PLUGIN_INSTALL_DIRS = $$[QT_INSTALL_LIBS]/ukui-settings-daemon EXTRA_CFLAGS +=-Wno-date-time PKGCONFIG += glib-2.0 gio-2.0 libxklavier x11 xrandr xtst atk gdk-3.0 gtk+-3.0 xi QMAKE_CXXFLAGS += -Wno-unused-parameter SOURCES += \ $$PWD/clib-syslog.c \ $$PWD/QGSettings/qconftype.cpp \ $$PWD/QGSettings/qgsettings.cpp \ $$PWD/rfkillswitch.cpp \ $$PWD/usd_base_class.cpp \ $$PWD/xeventmonitor.cpp \ $$PWD/eggaccelerators.c \ $$PWD/ukui-input-helper.c \ $$PWD/ukui-keygrab.cpp HEADERS += \ $$PWD/clib-syslog.h \ $$PWD/plugin-interface.h \ $$PWD/QGSettings/qconftype.h \ $$PWD/QGSettings/qgsettings.h \ $$PWD/rfkillswitch.h \ $$PWD/usd_base_class.h \ $$PWD/usd_global_define.h \ $$PWD/xeventmonitor.h \ $$PWD/eggaccelerators.h \ $$PWD/ukui-input-helper.h \ $$PWD/ukui-keygrab.h \ $$PWD/config.h \ $$PWD/xrandroutput.h RESOURCES += \ $$PWD/ukui_icon.qrc ukui-settings-daemon/projectDir/changelog_2203update0000664000175000017500000002006415167654733021427 0ustar fengfengukui-settings-daemon (3.1.0-1.43update3) v101; urgency=medium * BUG号:无 * 需求说明:无 * 其他改动说明:优化初次启动时的屏幕参数处理机制 * 其他改动影响域:登录时的显示参数保存获取方式 -- sunjunhao Fri, 06 May 2022 15:37:30 +0800 ukui-settings-daemon (3.1.0-1.43update2) v101; urgency=medium * BUG号:无 * 需求说明:无 * 其他改动说明:优化提权的配置文件,避免漏洞 * 其他改动影响域:无 -- sunjunhao Thu, 05 May 2022 14:48:36 +0800 ukui-settings-daemon (3.1.0-1.43) v101; urgency=medium * BUG号:无 * 需求说明:无 * 其他改动说明:修复dbus提权的安全问题 * 其他改动影响域:无 -- sundagao Tue, 08 Mar 2022 10:14:38 +0800 ukui-settings-daemon (3.1.0-1.41) v101; urgency=medium * BUG号:无 * 需求说明:无 * 其他改动说明:功耗问题 * 其他改动影响域:无 -- sundagao Thu, 03 Mar 2022 15:49:00 +0800 ukui-settings-daemon (3.1.0-1.40) v101; urgency=medium * BUG号:107432 【快捷键】升级后,快捷键及功能热键全部失效(2/2units) * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Tue, 22 Feb 2022 13:56:34 +0800 ukui-settings-daemon (3.1.0-1.39) v101; urgency=medium * BUG号:107101 【控制面板】【显示器】连接外接显示器,拓展模式下,在平板触控,触摸映射到了拓展屏上(必现) * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Tue, 22 Feb 2022 13:37:39 +0800 ukui-settings-daemon (3.1.0-1.38) v101; urgency=medium * BUG号:106951 【触控笔】连接外显扩展模式下使用触控笔会出现偏移(必现) * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Mon, 21 Feb 2022 09:17:49 +0800 ukui-settings-daemon (3.1.0-1.37) v101; urgency=medium * BUG号:106966 【快捷键】重启后,热键F3\F4\F5\F6\F7无功能(偶现:目前两台机器各出现一次) * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Sat, 19 Feb 2022 14:45:16 +0800 ukui-settings-daemon (3.1.0-1.36) v101; urgency=medium * BUG号:HZ 95808 【终端】鼠标大小设置中,在移动到终端标题栏大小会变化(主线同样存在) 106028 【镜像独有】【PTOF】【TM】【旋转】PC模式切换到平板模式开启自动旋转,旋转设备后使用触摸/触控笔概率会出现偏移(2/20 times 2/2 units) * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Fri, 28 Jan 2022 14:11:44 +0800 ukui-settings-daemon (3.1.0-1.35) v101; urgency=medium * BUG号:105291 【显示器】按下win+p后释放p不释放win,接着按下tab键,系统投屏弹窗显示在多任务视图窗口(必现) 87053 【S】【PTOF】【显示】win+p打开系统投屏选择窗,该选择窗可被拖动,且使用触摸屏点击投屏选择框以外的区域无法将其关闭(必现) * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Thu, 27 Jan 2022 10:32:01 +0800 ukui-settings-daemon (3.1.0-1.33) v101; urgency=medium * BUG号:101919 高 一般【自适应升级】【显示器】多屏显示在自适应升级注销重新登录后,升级前设置的扩展模式变为镜像模式 101257 中等 一般【显示】【自适应升级】更新升级后显示模块分辨率没有保存 102186 中等 一般【显示】【自适应升级】更新升级后控制面板-显示-夜间模式没有保存数据 * 需求说明:无 * 其他改动说明:触摸屏映射优化 * 其他改动影响域:触摸映射 -- sundagao Tue, 18 Jan 2022 09:23:06 +0800 ukui-settings-daemon (3.1.0-1.31) v101; urgency=medium * BUG号:HZ 95808 【终端】鼠标大小设置中,在移动到终端标题栏大小会变化(主线同样存在) * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Thu, 06 Jan 2022 16:28:11 +0800 ukui-settings-daemon (3.1.0-1.30) v101; urgency=medium * BUG号:95487 【触摸】【触摸映射】【控制面板】手动设置触摸映射后重启设备,登录后没有保持之前的映射关系;设置触摸映射后删除配置文件重启设备没有恢复默认自动映射关系(可以使用触摸映射设置回来)(必现) 95486 【触摸】【触摸映射】【控制面板】自动映射/手动映射后 插拔触摸线/修改分辨率/方向后,触摸落点偏移(可以使用触摸映射设置回来)(必现) 95485 【触摸】【自动映射】【控制面板】已连接A显示器(A为主屏)B显示器,设置扩展模式,连接B触摸线,在B显示器触摸的映射区域为屏A+屏B的范围(预期:接入的第2块触摸屏对应接入第2块显示器,可以使用触摸映射设置回来)(必现) * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Tue, 28 Dec 2021 17:39:14 +0800 ukui-settings-daemon (3.1.0-1.29) v101; urgency=medium * BUG号:无 * 需求说明:无 * 其他改动说明:镜像模式下控制面板切换分辨率,切换另外的显示模式,在切换回来,分辨率没有回复 * 其他改动影响域:双屏切换配置保存 -- sundagao Wed, 15 Dec 2021 13:52:59 +0800 ukui-settings-daemon (3.1.0-1.28) v101; urgency=medium * BUG号:95487 【触摸】【触摸映射】【控制面板】手动设置触摸映射后重启设备,登录后没有保持之前的映射关系;设置触摸映射后删除配置文件重启设备没有恢复默认自动映射关系(可以使用触摸映射设置回来)(必现) * 需求号:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Mon, 13 Dec 2021 16:32:06 +0800 ukui-settings-daemon (3.1.0-1.27) v101; urgency=medium * BUG号:93538 【SP2 UI走查】【OSD】UI待按照设计稿优化,间距尺寸等 * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Tue, 07 Dec 2021 17:16:54 +0800 ukui-settings-daemon (3.1.0-1.26) v101; urgency=medium * BUG号:89404 【需求-触摸-7467】【触摸】【显示】控制面板设置旋转方向为 顺/逆时针90度、上下颠倒,旋转方向后触摸偏移(必现) 93707 【显示】【USD】【必现】存在状态异常的配置文件时,连接1个显示器开机,打开控制面板-显示器,插上4K显示器,USD崩溃,产生core文件 92571 【触摸板】打开插入鼠标时禁用触摸板,拔掉鼠标后触摸板仍然不可用 * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Mon, 06 Dec 2021 18:45:38 +0800 ukui-settings-daemon (3.1.0-1.25) v101; urgency=medium * New upstream release. * fix bug#95916 【20.04-pro】【USD】系统缺少kylin-screenshot包时USD无法正常启动,提示段错误 -- Allen Fri, 10 Dec 2021 16:00:22 +0800 ukui-settings-daemon (1.2.0-1) unstable; urgency=medium * New upstream release. * debian/control: - Bump standards-version to 4.5.0. - Use debhelper-compat. * debian/copyright: - Remove COPYING from copyright. -- handsome_feng Mon, 24 Feb 2020 11:47:45 +0800 ukui-settings-daemon (1.1.7-2) unstable; urgency=medium * Don't set click actions since ukwm take over that. * debian/control: - Bump standards-version to 4.4.0. - Bump compat level to 12. - mate-polkit -> ukui-polkit. -- handsome_feng Wed, 07 Aug 2019 15:22:43 +0800 ukui-settings-daemon/projectDir/control_tablet0000664000175000017500000000675215167654733020652 0ustar fengfengSource: ukui-settings-daemon Section: x11 Priority: optional Maintainer: Kylin Team Uploaders: handsome_feng Build-Depends: debhelper-compat (=12), pkg-config, intltool, qt5-qmake, qtchooser, qtbase5-dev, qtbase5-dev-tools, qttools5-dev-tools, libgsettings-qt-dev, libqt5x11extras5-dev, libqt5sensors5-dev, libkf5config-dev, libqt5svg5-dev, libxklavier-dev, libxtst-dev, libmate-desktop-dev, libgnome-desktop-3-dev, libmatemixer-dev, libmatekbd-dev, libpulse-dev, libwnck-3-dev, libcanberra-gtk3-dev, libcanberra-gtk-common-dev, libcanberra-dev, libwayland-client0, libnotify-dev, libgeoclue-2-dev, libcolord-dev, liblcms2-dev, libimlib2-dev, xserver-xorg-dev, libgudev-1.0-dev, libxcb1-dev, libxcb-util-dev, libx11-dev, libkf5windowsystem-dev, libkf5screen-dev, libxkbcommon-dev, libkf5globalaccel-dev, libqt5x11extras5-dev, libukui-common-dev, Standards-Version: 4.6.0.1 Rules-Requires-Root: no Homepage: http://www.ukui.org/ Vcs-Git: https://github.com/ukui/ukui-settings-daemon.git Vcs-Browser: https://github.com/ukui/ukui-settings-daemon Package: ukui-settings-daemon Architecture: any Depends: mate-desktop-common (>= 1.18), ukui-settings-daemon-common (= ${source:Version}), colord, imwheel, ukui-polkit, x11-xserver-utils, xserver-xorg-input-synaptics [!s390x], libglib2.0-bin, gpiod, ${misc:Depends}, ${shlibs:Depends}, Conflicts: kylin-display-switch Replaces: kylin-display-switch Description: daemon handling the UKUI session settings This package contains the daemon which is responsible for setting the various parameters of a UKUI session and the applications that run under it. It handles the following kinds of settings: . * Keyboard: layout, accessibility options, shortcuts, media keys * Clipboard management * Theming: background, icons, GTK+ applications * Cleanup of unused files * Mouse: cursors, speed, accessibility options * Startup of other daemons: screensaver, sound daemon * Typing break . It also sets various application settings through X resources and freedesktop.org XSETTINGS. Package: ukui-settings-daemon-common Architecture: all Depends: ${misc:Depends}, Description: daemon handling the UKUI session settings (common files) This package contains the daemon which is responsible for setting the various parameters of a UKUI session and the applications that run under it. It handles the following kinds of settings: . * Keyboard: layout, accessibility options, shortcuts, media keys * Clipboard management * Theming: background, icons, GTK+ applications * Cleanup of unused files * Mouse: cursors, speed, accessibility options * Startup of other daemons: screensaver, sound daemon * Typing break . It also sets various application settings through X resources and freedesktop.org XSETTINGS. . This package contains the architecture independent files. ukui-settings-daemon/projectDir/common_3.1.4.pri0000664000175000017500000000240715167655403020427 0ustar fengfengQT += core gui dbus x11extras CONFIG += c++11 no_keywords link_pkgconfig x11extras debug CONFIG -= app_bundle INCLUDEPATH += -I $$PWD/ LIBS += -lukui-com4cxx PLUGIN_INSTALL_DIRS = $$[QT_INSTALL_LIBS]/ukui-settings-daemon EXTRA_CFLAGS +=-Wno-date-time PKGCONFIG += glib-2.0 gio-2.0 libxklavier x11 xrandr xtst atk gdk-3.0 gtk+-3.0 xi QMAKE_CXXFLAGS += -Wno-unused-parameter SOURCES += \ $$PWD/clib-syslog.c \ $$PWD/QGSettings/qconftype.cpp \ $$PWD/QGSettings/qgsettings.cpp \ $$PWD/rfkillswitch.cpp \ $$PWD/usd_base_class.cpp \ $$PWD/xeventmonitor.cpp \ $$PWD/eggaccelerators.c \ $$PWD/ukui-input-helper.c \ $$PWD/ukui-keygrab.cpp HEADERS += \ $$PWD/clib-syslog.h \ $$PWD/plugin-interface.h \ $$PWD/QGSettings/qconftype.h \ $$PWD/QGSettings/qgsettings.h \ $$PWD/rfkillswitch.h \ $$PWD/usd_base_class.h \ $$PWD/usd_global_define.h \ $$PWD/xeventmonitor.h \ $$PWD/eggaccelerators.h \ $$PWD/ukui-input-helper.h \ $$PWD/ukui-keygrab.h \ $$PWD/config.h \ $$PWD/xrandroutput.h RESOURCES += \ $$PWD/ukui_icon.qrc ukui-settings-daemon/projectDir/changelog_ukui3200000664000175000017500000003134215167654733021041 0ustar fengfengukui-settings-daemon (3.1.0-1.53) v101; urgency=medium * BUG号: * 需求说明: * 其他改动说明:第一屏同等分辨率,优先选取最大的刷新率进行设置。 * 其他改动影响域:无 -- sunjunhao Fri, 06 May 2022 10:22:59 +0800 ukui-settings-daemon (3.1.0-1.52) v101; urgency=medium * BUG号: * 需求说明: * 其他改动说明:移除多余gpiod依赖,主线暂时不上自动背光。 * 其他改动影响域:无 -- sunjunhao Thu, 05 May 2022 16:53:25 +0800 ukui-settings-daemon (3.1.0-1.51) v101; urgency=medium * BUG号: * 需求说明:77064 窗管实现一键切换机制(需要kwin配合) * 其他改动说明:优化首次运行时获取屏幕参数的时机。 * 其他改动影响域:无 -- sunjunhao Thu, 05 May 2022 16:38:44 +0800 ukui-settings-daemon (3.1.0-1.50) v101; urgency=medium * BUG号:116907 【中移联想】【双屏】【x13 AMD】接入HDMI后,切换扩展屏无响应,仍然显示镜像模式 *116890 【中移联想】【锁屏】【x13 AMD】 接HDMI 显示器后,锁屏和屏保界面显示异常 * 需求说明: * 其他改动说明:优化编译 * 其他改动影响域:无 -- sunjunhao Fri, 29 Apr 2022 08:15:15 +0800 ukui-settings-daemon (3.1.0-1.49) v101; urgency=medium * BUG号:无 * 需求说明:79112 动态背光控制功能集成Intel提供的patch,提供接口(需要mv版本的硬件支持) * 其他改动说明:优化编译 * 其他改动影响域:无 -- sunjunhao Tue, 19 Apr 2022 19:00:48 +0800 ukui-settings-daemon (3.1.2-1.3) jammy; urgency=medium * BUG号:无 * 需求说明: * 其他改动说明:优化编译 * 其他改动影响域:无 -- sunjunhao Fri, 15 Apr 2022 17:07:56 +0800 ukui-settings-daemon (3.1.0-1.48) jammy; urgency=medium * BUG号:114902 【护眼中心】手动调整亮度后,重启智能调节开关后,亮度会先增加1,然后进行自动调节(必现) * 114779 【护眼中心】【usd】短暂遮挡传感器,背光亮度会停留在53/短暂增大亮度,背光亮度会停留在63 * 115161 【peony】【平板模式】竖屏平板模式下关闭自动旋转,将屏幕变为横屏再变为竖屏,平板桌面显示异常 * 需求说明: * 其他改动说明: * 其他改动影响域:无 -- sunjunhao Fri, 15 Apr 2022 11:36:50 +0800 ukui-settings-daemon (3.1.0-1.46) v101; urgency=medium * BUG号:114902 【护眼中心】手动调整亮度后,重启智能调节开关后,亮度会先增加1,然后进行自动调节(必现) * 114779 【护眼中心】【usd】短暂遮挡传感器,背光亮度会停留在53/短暂增大亮度,背光亮度会停留在63 * 115161 【peony】【平板模式】竖屏平板模式下关闭自动旋转,将屏幕变为横屏再变为竖屏,平板桌面显示异常 * 需求说明: * 其他改动说明: * 其他改动影响域:无 -- sunjunhao Fri, 15 Apr 2022 11:36:50 +0800 ukui-settings-daemon (3.1.2-1.3) jammy; urgency=medium * BUG号:无 * 需求说明: * 其他改动说明:优化编译 * 其他改动影响域:无 -- sunjunhao Fri, 15 Apr 2022 11:36:50 +0800 ukui-settings-daemon (3.1.0-1.45) v101; urgency=medium * BUG号:无 * 需求说明: * 其他改动说明:删除postinst文件的无效命令 * 其他改动影响域:无 -- sunjunhao Fri, 15 Apr 2022 11:36:50 +0800 ukui-settings-daemon (3.1.2-1.2) v101; urgency=medium * BUG号:无 * 需求说明: * 其他改动说明:去掉save-param功能 * 其他改动影响域:无 -- sunjunhao Fri, 15 Apr 2022 11:36:50 +0800 ukui-settings-daemon (3.1.2-1.1) v101; urgency=medium * BUG号:99663 【UKUI V3.1】【侧边栏】快捷键设置飞行模式侧边栏没有同步变化 * 99639 【UKUI V3.1】【侧边栏】飞行模式用户之间存在隔离 * 需求说明: * 其他改动说明:固定缺省拓展模式主屏为edp,优化多媒体快捷键的停止播放按键,增加判断试用模式的popen方法,替换之前的打开文件方案,/prop/cmdline无法被当做普通文件打开 * 其他改动影响域:笔记本缺省拓展模式的主屏设置,试用模式的判断方式(housekeeping),多媒体按键的优化 -- sunjunhao Thu, 14 Apr 2022 08:27:24 +0800 ukui-settings-daemon (3.1.0-1.44) v101; urgency=medium * BUG号:无 * 需求说明:11534 子 【护眼中心】新增智能自动亮度调节 / 【护眼中心】新增智能自动亮度调节 * 其他改动说明:无 * 其他改动影响域:无 -- sunjunhao Tue, 29 Mar 2022 13:44:47 +0800 ukui-settings-daemon (3.1.0-1.43) v101; urgency=medium * BUG号:无 * 需求说明:无 * 其他改动说明:修复dbus提权的安全问题 * 其他改动影响域:无 -- sundagao Tue, 08 Mar 2022 10:14:38 +0800 ukui-settings-daemon (3.1.0-1.41) v101; urgency=medium * BUG号:无 * 需求说明:无 * 其他改动说明:功耗问题 * 其他改动影响域:无 -- sundagao Thu, 03 Mar 2022 15:49:00 +0800 ukui-settings-daemon (3.1.0-1.40) v101; urgency=medium * BUG号:107432 【快捷键】升级后,快捷键及功能热键全部失效(2/2units) * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Tue, 22 Feb 2022 13:56:34 +0800 ukui-settings-daemon (3.1.0-1.39) v101; urgency=medium * BUG号:107101 【控制面板】【显示器】连接外接显示器,拓展模式下,在平板触控,触摸映射到了拓展屏上(必现) * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Tue, 22 Feb 2022 13:37:39 +0800 ukui-settings-daemon (3.1.0-1.38) v101; urgency=medium * BUG号:106951 【触控笔】连接外显扩展模式下使用触控笔会出现偏移(必现) * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Mon, 21 Feb 2022 09:17:49 +0800 ukui-settings-daemon (3.1.0-1.37) v101; urgency=medium * BUG号:106966 【快捷键】重启后,热键F3\F4\F5\F6\F7无功能(偶现:目前两台机器各出现一次) * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Sat, 19 Feb 2022 14:45:16 +0800 ukui-settings-daemon (3.1.0-1.36) v101; urgency=medium * BUG号:HZ 95808 【终端】鼠标大小设置中,在移动到终端标题栏大小会变化(主线同样存在) 106028 【镜像独有】【PTOF】【TM】【旋转】PC模式切换到平板模式开启自动旋转,旋转设备后使用触摸/触控笔概率会出现偏移(2/20 times 2/2 units) * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Fri, 28 Jan 2022 14:11:44 +0800 ukui-settings-daemon (3.1.0-1.35) v101; urgency=medium * BUG号:105291 【显示器】按下win+p后释放p不释放win,接着按下tab键,系统投屏弹窗显示在多任务视图窗口(必现) 87053 【S】【PTOF】【显示】win+p打开系统投屏选择窗,该选择窗可被拖动,且使用触摸屏点击投屏选择框以外的区域无法将其关闭(必现) * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Thu, 27 Jan 2022 10:32:01 +0800 ukui-settings-daemon (3.1.0-1.33) v101; urgency=medium * BUG号:101919 高 一般【自适应升级】【显示器】多屏显示在自适应升级注销重新登录后,升级前设置的扩展模式变为镜像模式 101257 中等 一般【显示】【自适应升级】更新升级后显示模块分辨率没有保存 102186 中等 一般【显示】【自适应升级】更新升级后控制面板-显示-夜间模式没有保存数据 * 需求说明:无 * 其他改动说明:触摸屏映射优化 * 其他改动影响域:触摸映射 -- sundagao Tue, 18 Jan 2022 09:23:06 +0800 ukui-settings-daemon (3.1.0-1.31) v101; urgency=medium * BUG号:HZ 95808 【终端】鼠标大小设置中,在移动到终端标题栏大小会变化(主线同样存在) * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Thu, 06 Jan 2022 16:28:11 +0800 ukui-settings-daemon (3.1.0-1.30) v101; urgency=medium * BUG号:95487 【触摸】【触摸映射】【控制面板】手动设置触摸映射后重启设备,登录后没有保持之前的映射关系;设置触摸映射后删除配置文件重启设备没有恢复默认自动映射关系(可以使用触摸映射设置回来)(必现) 95486 【触摸】【触摸映射】【控制面板】自动映射/手动映射后 插拔触摸线/修改分辨率/方向后,触摸落点偏移(可以使用触摸映射设置回来)(必现) 95485 【触摸】【自动映射】【控制面板】已连接A显示器(A为主屏)B显示器,设置扩展模式,连接B触摸线,在B显示器触摸的映射区域为屏A+屏B的范围(预期:接入的第2块触摸屏对应接入第2块显示器,可以使用触摸映射设置回来)(必现) * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Tue, 28 Dec 2021 17:39:14 +0800 ukui-settings-daemon (3.1.0-1.29) v101; urgency=medium * BUG号:无 * 需求说明:无 * 其他改动说明:镜像模式下控制面板切换分辨率,切换另外的显示模式,在切换回来,分辨率没有回复 * 其他改动影响域:双屏切换配置保存 -- sundagao Wed, 15 Dec 2021 13:52:59 +0800 ukui-settings-daemon (3.1.0-1.28) v101; urgency=medium * BUG号:95487 【触摸】【触摸映射】【控制面板】手动设置触摸映射后重启设备,登录后没有保持之前的映射关系;设置触摸映射后删除配置文件重启设备没有恢复默认自动映射关系(可以使用触摸映射设置回来)(必现) * 需求号:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Mon, 13 Dec 2021 16:32:06 +0800 ukui-settings-daemon (3.1.0-1.27) v101; urgency=medium * BUG号:93538 【SP2 UI走查】【OSD】UI待按照设计稿优化,间距尺寸等 * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Tue, 07 Dec 2021 17:16:54 +0800 ukui-settings-daemon (3.1.0-1.26) v101; urgency=medium * BUG号:89404 【需求-触摸-7467】【触摸】【显示】控制面板设置旋转方向为 顺/逆时针90度、上下颠倒,旋转方向后触摸偏移(必现) 93707 【显示】【USD】【必现】存在状态异常的配置文件时,连接1个显示器开机,打开控制面板-显示器,插上4K显示器,USD崩溃,产生core文件 92571 【触摸板】打开插入鼠标时禁用触摸板,拔掉鼠标后触摸板仍然不可用 * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Mon, 06 Dec 2021 18:45:38 +0800 ukui-settings-daemon (3.1.0-1.25) v101; urgency=medium * New upstream release. * fix bug#95916 【20.04-pro】【USD】系统缺少kylin-screenshot包时USD无法正常启动,提示段错误 -- Allen Fri, 10 Dec 2021 16:00:22 +0800 ukui-settings-daemon (1.2.0-1) unstable; urgency=medium * New upstream release. * debian/control: - Bump standards-version to 4.5.0. - Use debhelper-compat. * debian/copyright: - Remove COPYING from copyright. -- handsome_feng Mon, 24 Feb 2020 11:47:45 +0800 ukui-settings-daemon (1.1.7-2) unstable; urgency=medium * Don't set click actions since ukwm take over that. * debian/control: - Bump standards-version to 4.4.0. - Bump compat level to 12. - mate-polkit -> ukui-polkit. -- handsome_feng Wed, 07 Aug 2019 15:22:43 +0800 ukui-settings-daemon (1.1.6-1fakesync1) disco-proposed; urgency=medium * Fake sync due to mismatching orig tarball. -- Logan Rosen Thu, 17 Jan 2019 22:21:48 -0500 ukui-settings-daemon (1.1.6-1) unstable; urgency=medium * Initial release. (Closes: #903944) -- handsome_feng Tue, 17 Jul 2018 11:43:08 +0800 ukui-settings-daemon/projectDir/control_2203update0000664000175000017500000000673215167654733021166 0ustar fengfengSource: ukui-settings-daemon Section: x11 Priority: optional Maintainer: Kylin Team Uploaders: handsome_feng Build-Depends: debhelper-compat (=12), pkg-config, intltool, qt5-qmake, qtchooser, qtbase5-dev, qtbase5-dev-tools, qttools5-dev-tools, libgsettings-qt-dev, libqt5x11extras5-dev, libqt5sensors5-dev, libkf5config-dev, libqt5svg5-dev, libxklavier-dev, libxtst-dev, libmate-desktop-dev, libgnome-desktop-3-dev, libmatemixer-dev, libmatekbd-dev, libpulse-dev, libwnck-3-dev, libcanberra-gtk3-dev, libcanberra-gtk-common-dev, libcanberra-dev, libwayland-client0, libnotify-dev, libgeoclue-2-dev, libcolord-dev, liblcms2-dev, libimlib2-dev, xserver-xorg-dev, libgudev-1.0-dev, libxcb1-dev, libxcb-util-dev, libx11-dev, libkf5windowsystem-dev, libkf5screen-dev, libxkbcommon-dev, libkf5globalaccel-dev, libqt5x11extras5-dev, libukui-common-dev, Standards-Version: 4.6.0.1 Rules-Requires-Root: no Homepage: http://www.ukui.org/ Vcs-Git: https://github.com/ukui/ukui-settings-daemon.git Vcs-Browser: https://github.com/ukui/ukui-settings-daemon Package: ukui-settings-daemon Architecture: any Depends: mate-desktop-common (>= 1.18), ukui-settings-daemon-common (= ${source:Version}), colord, imwheel, ukui-polkit, x11-xserver-utils, xserver-xorg-input-synaptics [!s390x], libglib2.0-bin, ${misc:Depends}, ${shlibs:Depends}, Conflicts: kylin-display-switch Replaces: kylin-display-switch Description: daemon handling the UKUI session settings This package contains the daemon which is responsible for setting the various parameters of a UKUI session and the applications that run under it. It handles the following kinds of settings: . * Keyboard: layout, accessibility options, shortcuts, media keys * Clipboard management * Theming: background, icons, GTK+ applications * Cleanup of unused files * Mouse: cursors, speed, accessibility options * Startup of other daemons: screensaver, sound daemon * Typing break . It also sets various application settings through X resources and freedesktop.org XSETTINGS. Package: ukui-settings-daemon-common Architecture: all Depends: ${misc:Depends}, Description: daemon handling the UKUI session settings (common files) This package contains the daemon which is responsible for setting the various parameters of a UKUI session and the applications that run under it. It handles the following kinds of settings: . * Keyboard: layout, accessibility options, shortcuts, media keys * Clipboard management * Theming: background, icons, GTK+ applications * Cleanup of unused files * Mouse: cursors, speed, accessibility options * Startup of other daemons: screensaver, sound daemon * Typing break . It also sets various application settings through X resources and freedesktop.org XSETTINGS. . This package contains the architecture independent files. ukui-settings-daemon/projectDir/changelog_ukui3140000664000175000017500000003134215167654733021044 0ustar fengfengukui-settings-daemon (3.1.0-1.53) v101; urgency=medium * BUG号: * 需求说明: * 其他改动说明:第一屏同等分辨率,优先选取最大的刷新率进行设置。 * 其他改动影响域:无 -- sunjunhao Fri, 06 May 2022 10:22:59 +0800 ukui-settings-daemon (3.1.0-1.52) v101; urgency=medium * BUG号: * 需求说明: * 其他改动说明:移除多余gpiod依赖,主线暂时不上自动背光。 * 其他改动影响域:无 -- sunjunhao Thu, 05 May 2022 16:53:25 +0800 ukui-settings-daemon (3.1.0-1.51) v101; urgency=medium * BUG号: * 需求说明:77064 窗管实现一键切换机制(需要kwin配合) * 其他改动说明:优化首次运行时获取屏幕参数的时机。 * 其他改动影响域:无 -- sunjunhao Thu, 05 May 2022 16:38:44 +0800 ukui-settings-daemon (3.1.0-1.50) v101; urgency=medium * BUG号:116907 【中移联想】【双屏】【x13 AMD】接入HDMI后,切换扩展屏无响应,仍然显示镜像模式 *116890 【中移联想】【锁屏】【x13 AMD】 接HDMI 显示器后,锁屏和屏保界面显示异常 * 需求说明: * 其他改动说明:优化编译 * 其他改动影响域:无 -- sunjunhao Fri, 29 Apr 2022 08:15:15 +0800 ukui-settings-daemon (3.1.0-1.49) v101; urgency=medium * BUG号:无 * 需求说明:79112 动态背光控制功能集成Intel提供的patch,提供接口(需要mv版本的硬件支持) * 其他改动说明:优化编译 * 其他改动影响域:无 -- sunjunhao Tue, 19 Apr 2022 19:00:48 +0800 ukui-settings-daemon (3.1.2-1.3) jammy; urgency=medium * BUG号:无 * 需求说明: * 其他改动说明:优化编译 * 其他改动影响域:无 -- sunjunhao Fri, 15 Apr 2022 17:07:56 +0800 ukui-settings-daemon (3.1.0-1.48) jammy; urgency=medium * BUG号:114902 【护眼中心】手动调整亮度后,重启智能调节开关后,亮度会先增加1,然后进行自动调节(必现) * 114779 【护眼中心】【usd】短暂遮挡传感器,背光亮度会停留在53/短暂增大亮度,背光亮度会停留在63 * 115161 【peony】【平板模式】竖屏平板模式下关闭自动旋转,将屏幕变为横屏再变为竖屏,平板桌面显示异常 * 需求说明: * 其他改动说明: * 其他改动影响域:无 -- sunjunhao Fri, 15 Apr 2022 11:36:50 +0800 ukui-settings-daemon (3.1.0-1.46) v101; urgency=medium * BUG号:114902 【护眼中心】手动调整亮度后,重启智能调节开关后,亮度会先增加1,然后进行自动调节(必现) * 114779 【护眼中心】【usd】短暂遮挡传感器,背光亮度会停留在53/短暂增大亮度,背光亮度会停留在63 * 115161 【peony】【平板模式】竖屏平板模式下关闭自动旋转,将屏幕变为横屏再变为竖屏,平板桌面显示异常 * 需求说明: * 其他改动说明: * 其他改动影响域:无 -- sunjunhao Fri, 15 Apr 2022 11:36:50 +0800 ukui-settings-daemon (3.1.2-1.3) jammy; urgency=medium * BUG号:无 * 需求说明: * 其他改动说明:优化编译 * 其他改动影响域:无 -- sunjunhao Fri, 15 Apr 2022 11:36:50 +0800 ukui-settings-daemon (3.1.0-1.45) v101; urgency=medium * BUG号:无 * 需求说明: * 其他改动说明:删除postinst文件的无效命令 * 其他改动影响域:无 -- sunjunhao Fri, 15 Apr 2022 11:36:50 +0800 ukui-settings-daemon (3.1.2-1.2) v101; urgency=medium * BUG号:无 * 需求说明: * 其他改动说明:去掉save-param功能 * 其他改动影响域:无 -- sunjunhao Fri, 15 Apr 2022 11:36:50 +0800 ukui-settings-daemon (3.1.2-1.1) v101; urgency=medium * BUG号:99663 【UKUI V3.1】【侧边栏】快捷键设置飞行模式侧边栏没有同步变化 * 99639 【UKUI V3.1】【侧边栏】飞行模式用户之间存在隔离 * 需求说明: * 其他改动说明:固定缺省拓展模式主屏为edp,优化多媒体快捷键的停止播放按键,增加判断试用模式的popen方法,替换之前的打开文件方案,/prop/cmdline无法被当做普通文件打开 * 其他改动影响域:笔记本缺省拓展模式的主屏设置,试用模式的判断方式(housekeeping),多媒体按键的优化 -- sunjunhao Thu, 14 Apr 2022 08:27:24 +0800 ukui-settings-daemon (3.1.0-1.44) v101; urgency=medium * BUG号:无 * 需求说明:11534 子 【护眼中心】新增智能自动亮度调节 / 【护眼中心】新增智能自动亮度调节 * 其他改动说明:无 * 其他改动影响域:无 -- sunjunhao Tue, 29 Mar 2022 13:44:47 +0800 ukui-settings-daemon (3.1.0-1.43) v101; urgency=medium * BUG号:无 * 需求说明:无 * 其他改动说明:修复dbus提权的安全问题 * 其他改动影响域:无 -- sundagao Tue, 08 Mar 2022 10:14:38 +0800 ukui-settings-daemon (3.1.0-1.41) v101; urgency=medium * BUG号:无 * 需求说明:无 * 其他改动说明:功耗问题 * 其他改动影响域:无 -- sundagao Thu, 03 Mar 2022 15:49:00 +0800 ukui-settings-daemon (3.1.0-1.40) v101; urgency=medium * BUG号:107432 【快捷键】升级后,快捷键及功能热键全部失效(2/2units) * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Tue, 22 Feb 2022 13:56:34 +0800 ukui-settings-daemon (3.1.0-1.39) v101; urgency=medium * BUG号:107101 【控制面板】【显示器】连接外接显示器,拓展模式下,在平板触控,触摸映射到了拓展屏上(必现) * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Tue, 22 Feb 2022 13:37:39 +0800 ukui-settings-daemon (3.1.0-1.38) v101; urgency=medium * BUG号:106951 【触控笔】连接外显扩展模式下使用触控笔会出现偏移(必现) * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Mon, 21 Feb 2022 09:17:49 +0800 ukui-settings-daemon (3.1.0-1.37) v101; urgency=medium * BUG号:106966 【快捷键】重启后,热键F3\F4\F5\F6\F7无功能(偶现:目前两台机器各出现一次) * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Sat, 19 Feb 2022 14:45:16 +0800 ukui-settings-daemon (3.1.0-1.36) v101; urgency=medium * BUG号:HZ 95808 【终端】鼠标大小设置中,在移动到终端标题栏大小会变化(主线同样存在) 106028 【镜像独有】【PTOF】【TM】【旋转】PC模式切换到平板模式开启自动旋转,旋转设备后使用触摸/触控笔概率会出现偏移(2/20 times 2/2 units) * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Fri, 28 Jan 2022 14:11:44 +0800 ukui-settings-daemon (3.1.0-1.35) v101; urgency=medium * BUG号:105291 【显示器】按下win+p后释放p不释放win,接着按下tab键,系统投屏弹窗显示在多任务视图窗口(必现) 87053 【S】【PTOF】【显示】win+p打开系统投屏选择窗,该选择窗可被拖动,且使用触摸屏点击投屏选择框以外的区域无法将其关闭(必现) * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Thu, 27 Jan 2022 10:32:01 +0800 ukui-settings-daemon (3.1.0-1.33) v101; urgency=medium * BUG号:101919 高 一般【自适应升级】【显示器】多屏显示在自适应升级注销重新登录后,升级前设置的扩展模式变为镜像模式 101257 中等 一般【显示】【自适应升级】更新升级后显示模块分辨率没有保存 102186 中等 一般【显示】【自适应升级】更新升级后控制面板-显示-夜间模式没有保存数据 * 需求说明:无 * 其他改动说明:触摸屏映射优化 * 其他改动影响域:触摸映射 -- sundagao Tue, 18 Jan 2022 09:23:06 +0800 ukui-settings-daemon (3.1.0-1.31) v101; urgency=medium * BUG号:HZ 95808 【终端】鼠标大小设置中,在移动到终端标题栏大小会变化(主线同样存在) * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Thu, 06 Jan 2022 16:28:11 +0800 ukui-settings-daemon (3.1.0-1.30) v101; urgency=medium * BUG号:95487 【触摸】【触摸映射】【控制面板】手动设置触摸映射后重启设备,登录后没有保持之前的映射关系;设置触摸映射后删除配置文件重启设备没有恢复默认自动映射关系(可以使用触摸映射设置回来)(必现) 95486 【触摸】【触摸映射】【控制面板】自动映射/手动映射后 插拔触摸线/修改分辨率/方向后,触摸落点偏移(可以使用触摸映射设置回来)(必现) 95485 【触摸】【自动映射】【控制面板】已连接A显示器(A为主屏)B显示器,设置扩展模式,连接B触摸线,在B显示器触摸的映射区域为屏A+屏B的范围(预期:接入的第2块触摸屏对应接入第2块显示器,可以使用触摸映射设置回来)(必现) * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Tue, 28 Dec 2021 17:39:14 +0800 ukui-settings-daemon (3.1.0-1.29) v101; urgency=medium * BUG号:无 * 需求说明:无 * 其他改动说明:镜像模式下控制面板切换分辨率,切换另外的显示模式,在切换回来,分辨率没有回复 * 其他改动影响域:双屏切换配置保存 -- sundagao Wed, 15 Dec 2021 13:52:59 +0800 ukui-settings-daemon (3.1.0-1.28) v101; urgency=medium * BUG号:95487 【触摸】【触摸映射】【控制面板】手动设置触摸映射后重启设备,登录后没有保持之前的映射关系;设置触摸映射后删除配置文件重启设备没有恢复默认自动映射关系(可以使用触摸映射设置回来)(必现) * 需求号:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Mon, 13 Dec 2021 16:32:06 +0800 ukui-settings-daemon (3.1.0-1.27) v101; urgency=medium * BUG号:93538 【SP2 UI走查】【OSD】UI待按照设计稿优化,间距尺寸等 * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Tue, 07 Dec 2021 17:16:54 +0800 ukui-settings-daemon (3.1.0-1.26) v101; urgency=medium * BUG号:89404 【需求-触摸-7467】【触摸】【显示】控制面板设置旋转方向为 顺/逆时针90度、上下颠倒,旋转方向后触摸偏移(必现) 93707 【显示】【USD】【必现】存在状态异常的配置文件时,连接1个显示器开机,打开控制面板-显示器,插上4K显示器,USD崩溃,产生core文件 92571 【触摸板】打开插入鼠标时禁用触摸板,拔掉鼠标后触摸板仍然不可用 * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Mon, 06 Dec 2021 18:45:38 +0800 ukui-settings-daemon (3.1.0-1.25) v101; urgency=medium * New upstream release. * fix bug#95916 【20.04-pro】【USD】系统缺少kylin-screenshot包时USD无法正常启动,提示段错误 -- Allen Fri, 10 Dec 2021 16:00:22 +0800 ukui-settings-daemon (1.2.0-1) unstable; urgency=medium * New upstream release. * debian/control: - Bump standards-version to 4.5.0. - Use debhelper-compat. * debian/copyright: - Remove COPYING from copyright. -- handsome_feng Mon, 24 Feb 2020 11:47:45 +0800 ukui-settings-daemon (1.1.7-2) unstable; urgency=medium * Don't set click actions since ukwm take over that. * debian/control: - Bump standards-version to 4.4.0. - Bump compat level to 12. - mate-polkit -> ukui-polkit. -- handsome_feng Wed, 07 Aug 2019 15:22:43 +0800 ukui-settings-daemon (1.1.6-1fakesync1) disco-proposed; urgency=medium * Fake sync due to mismatching orig tarball. -- Logan Rosen Thu, 17 Jan 2019 22:21:48 -0500 ukui-settings-daemon (1.1.6-1) unstable; urgency=medium * Initial release. (Closes: #903944) -- handsome_feng Tue, 17 Jul 2018 11:43:08 +0800 ukui-settings-daemon/projectDir/changelog_master0000664000175000017500000002702715167654733021137 0ustar fengfengukui-settings-daemon (3.1.0-1.55) v101; urgency=medium * BUG号: * 需求说明: * 其他改动说明:优化触摸类设备的映射机制 * 其他改动影响域:无 -- sunjunhao Sat, 07 May 2022 09:45:45 +0800 ukui-settings-daemon (3.1.0-1.54) v101; urgency=medium * BUG号: 115949 【显示器】快捷键设置亮度为任意值后重启,亮度状态并没有保持 116025 【护眼中心】【亮度调节】关闭智能亮度调节后重启机器,ui处显示该功能关闭,但是亮度会自动调节 114902 【护眼中心】手动调整亮度后,重启智能调节开关后,亮度会先增加1,然后进行自动调节(必现) 115161 【peony】【平板模式】竖屏平板模式下关闭自动旋转,将屏幕变为横屏再变为竖屏,平板桌面显示异常 114779 【护眼中心】【usd】短暂遮挡传感器,背光亮度会停留在53/短暂增大亮度,背光亮度会停留在63 * 需求说明: * 其他改动说明:第一屏同等分辨率,优先选取最大的刷新率进行设置。 * 其他改动影响域:无 -- sunjunhao Fri, 06 May 2022 16:19:39 +0800 ukui-settings-daemon (3.1.0-1.53) v101; urgency=medium * BUG号: * 需求说明: * 其他改动说明:第一屏同等分辨率,优先选取最大的刷新率进行设置。 * 其他改动影响域:无 -- sunjunhao Fri, 06 May 2022 10:22:59 +0800 ukui-settings-daemon (3.1.0-1.52) v101; urgency=medium * BUG号: * 需求说明: * 其他改动说明:移除多余gpiod依赖,主线暂时不上自动背光。 * 其他改动影响域:无 -- sunjunhao Thu, 05 May 2022 16:53:25 +0800 ukui-settings-daemon (3.1.0-1.51) v101; urgency=medium * BUG号: * 需求说明:77064 窗管实现一键切换机制(需要kwin配合) * 其他改动说明:优化首次运行时获取屏幕参数的时机。 * 其他改动影响域:无 -- sunjunhao Thu, 05 May 2022 16:38:44 +0800 ukui-settings-daemon (3.1.0-1.50) v101; urgency=medium * BUG号:116907 【中移联想】【双屏】【x13 AMD】接入HDMI后,切换扩展屏无响应,仍然显示镜像模式 *116890 【中移联想】【锁屏】【x13 AMD】 接HDMI 显示器后,锁屏和屏保界面显示异常 * 需求说明: * 其他改动说明:优化编译 * 其他改动影响域:无 -- sunjunhao Fri, 29 Apr 2022 08:15:15 +0800 ukui-settings-daemon (3.1.0-1.49) v101; urgency=medium * BUG号:无 * 需求说明:79112 动态背光控制功能集成Intel提供的patch,提供接口(需要mv版本的硬件支持) * 其他改动说明:优化编译 * 其他改动影响域:无 -- sunjunhao Tue, 19 Apr 2022 19:00:48 +0800 ukui-settings-daemon (3.1.0-1.46) v101; urgency=medium * BUG号:114902 【护眼中心】手动调整亮度后,重启智能调节开关后,亮度会先增加1,然后进行自动调节(必现) * 114779 【护眼中心】【usd】短暂遮挡传感器,背光亮度会停留在53/短暂增大亮度,背光亮度会停留在63 * 115161 【peony】【平板模式】竖屏平板模式下关闭自动旋转,将屏幕变为横屏再变为竖屏,平板桌面显示异常 * 需求说明: * 其他改动说明: * 其他改动影响域:无 -- sunjunhao Fri, 15 Apr 2022 11:36:50 +0800 ukui-settings-daemon (3.1.0-1.45) v101; urgency=medium * BUG号:无 * 需求说明: * 其他改动说明:删除postinst文件的无效命令 * 其他改动影响域:无 -- sunjunhao Fri, 15 Apr 2022 11:36:50 +0800 ukui-settings-daemon (3.1.0-1.44) v101; urgency=medium * BUG号:无 * 需求说明:11534 子 【护眼中心】新增智能自动亮度调节 / 【护眼中心】新增智能自动亮度调节 * 其他改动说明:无 * 其他改动影响域:无 -- sunjunhao Tue, 29 Mar 2022 13:44:47 +0800 ukui-settings-daemon (3.1.0-1.43) v101; urgency=medium * BUG号:无 * 需求说明:无 * 其他改动说明:修复dbus提权的安全问题 * 其他改动影响域:无 -- sundagao Tue, 08 Mar 2022 10:14:38 +0800 ukui-settings-daemon (3.1.0-1.41) v101; urgency=medium * BUG号:无 * 需求说明:无 * 其他改动说明:功耗问题 * 其他改动影响域:无 -- sundagao Thu, 03 Mar 2022 15:49:00 +0800 ukui-settings-daemon (3.1.0-1.40) v101; urgency=medium * BUG号:107432 【快捷键】升级后,快捷键及功能热键全部失效(2/2units) * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Tue, 22 Feb 2022 13:56:34 +0800 ukui-settings-daemon (3.1.0-1.39) v101; urgency=medium * BUG号:107101 【控制面板】【显示器】连接外接显示器,拓展模式下,在平板触控,触摸映射到了拓展屏上(必现) * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Tue, 22 Feb 2022 13:37:39 +0800 ukui-settings-daemon (3.1.0-1.38) v101; urgency=medium * BUG号:106951 【触控笔】连接外显扩展模式下使用触控笔会出现偏移(必现) * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Mon, 21 Feb 2022 09:17:49 +0800 ukui-settings-daemon (3.1.0-1.37) v101; urgency=medium * BUG号:106966 【快捷键】重启后,热键F3\F4\F5\F6\F7无功能(偶现:目前两台机器各出现一次) * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Sat, 19 Feb 2022 14:45:16 +0800 ukui-settings-daemon (3.1.0-1.36) v101; urgency=medium * BUG号:HZ 95808 【终端】鼠标大小设置中,在移动到终端标题栏大小会变化(主线同样存在) 106028 【镜像独有】【PTOF】【TM】【旋转】PC模式切换到平板模式开启自动旋转,旋转设备后使用触摸/触控笔概率会出现偏移(2/20 times 2/2 units) * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Fri, 28 Jan 2022 14:11:44 +0800 ukui-settings-daemon (3.1.0-1.35) v101; urgency=medium * BUG号:105291 【显示器】按下win+p后释放p不释放win,接着按下tab键,系统投屏弹窗显示在多任务视图窗口(必现) 87053 【S】【PTOF】【显示】win+p打开系统投屏选择窗,该选择窗可被拖动,且使用触摸屏点击投屏选择框以外的区域无法将其关闭(必现) * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Thu, 27 Jan 2022 10:32:01 +0800 ukui-settings-daemon (3.1.0-1.33) v101; urgency=medium * BUG号:101919 高 一般【自适应升级】【显示器】多屏显示在自适应升级注销重新登录后,升级前设置的扩展模式变为镜像模式 101257 中等 一般【显示】【自适应升级】更新升级后显示模块分辨率没有保存 102186 中等 一般【显示】【自适应升级】更新升级后控制面板-显示-夜间模式没有保存数据 * 需求说明:无 * 其他改动说明:触摸屏映射优化 * 其他改动影响域:触摸映射 -- sundagao Tue, 18 Jan 2022 09:23:06 +0800 ukui-settings-daemon (3.1.0-1.31) v101; urgency=medium * BUG号:HZ 95808 【终端】鼠标大小设置中,在移动到终端标题栏大小会变化(主线同样存在) * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Thu, 06 Jan 2022 16:28:11 +0800 ukui-settings-daemon (3.1.0-1.30) v101; urgency=medium * BUG号:95487 【触摸】【触摸映射】【控制面板】手动设置触摸映射后重启设备,登录后没有保持之前的映射关系;设置触摸映射后删除配置文件重启设备没有恢复默认自动映射关系(可以使用触摸映射设置回来)(必现) 95486 【触摸】【触摸映射】【控制面板】自动映射/手动映射后 插拔触摸线/修改分辨率/方向后,触摸落点偏移(可以使用触摸映射设置回来)(必现) 95485 【触摸】【自动映射】【控制面板】已连接A显示器(A为主屏)B显示器,设置扩展模式,连接B触摸线,在B显示器触摸的映射区域为屏A+屏B的范围(预期:接入的第2块触摸屏对应接入第2块显示器,可以使用触摸映射设置回来)(必现) * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Tue, 28 Dec 2021 17:39:14 +0800 ukui-settings-daemon (3.1.0-1.29) v101; urgency=medium * BUG号:无 * 需求说明:无 * 其他改动说明:镜像模式下控制面板切换分辨率,切换另外的显示模式,在切换回来,分辨率没有回复 * 其他改动影响域:双屏切换配置保存 -- sundagao Wed, 15 Dec 2021 13:52:59 +0800 ukui-settings-daemon (3.1.0-1.28) v101; urgency=medium * BUG号:95487 【触摸】【触摸映射】【控制面板】手动设置触摸映射后重启设备,登录后没有保持之前的映射关系;设置触摸映射后删除配置文件重启设备没有恢复默认自动映射关系(可以使用触摸映射设置回来)(必现) * 需求号:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Mon, 13 Dec 2021 16:32:06 +0800 ukui-settings-daemon (3.1.0-1.27) v101; urgency=medium * BUG号:93538 【SP2 UI走查】【OSD】UI待按照设计稿优化,间距尺寸等 * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Tue, 07 Dec 2021 17:16:54 +0800 ukui-settings-daemon (3.1.0-1.26) v101; urgency=medium * BUG号:89404 【需求-触摸-7467】【触摸】【显示】控制面板设置旋转方向为 顺/逆时针90度、上下颠倒,旋转方向后触摸偏移(必现) 93707 【显示】【USD】【必现】存在状态异常的配置文件时,连接1个显示器开机,打开控制面板-显示器,插上4K显示器,USD崩溃,产生core文件 92571 【触摸板】打开插入鼠标时禁用触摸板,拔掉鼠标后触摸板仍然不可用 * 需求说明:无 * 其他改动说明:无 * 其他改动影响域:无 -- sundagao Mon, 06 Dec 2021 18:45:38 +0800 ukui-settings-daemon (3.1.0-1.25) v101; urgency=medium * New upstream release. * fix bug#95916 【20.04-pro】【USD】系统缺少kylin-screenshot包时USD无法正常启动,提示段错误 -- Allen Fri, 10 Dec 2021 16:00:22 +0800 ukui-settings-daemon (1.2.0-1) unstable; urgency=medium * New upstream release. * debian/control: - Bump standards-version to 4.5.0. - Use debhelper-compat. * debian/copyright: - Remove COPYING from copyright. -- handsome_feng Mon, 24 Feb 2020 11:47:45 +0800 ukui-settings-daemon (1.1.7-2) unstable; urgency=medium * Don't set click actions since ukwm take over that. * debian/control: - Bump standards-version to 4.4.0. - Bump compat level to 12. - mate-polkit -> ukui-polkit. -- handsome_feng Wed, 07 Aug 2019 15:22:43 +0800 ukui-settings-daemon/plugins/0000775000175000017500000000000015167654733015256 5ustar fengfengukui-settings-daemon/plugins/xinput/0000775000175000017500000000000015167655063016602 5ustar fengfengukui-settings-daemon/plugins/xinput/xinputplugin.h0000664000175000017500000000251415167655063021523 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef XINPUTPLUGIN_H #define XINPUTPLUGIN_H #include "plugin-interface.h" #include "xinputmanager.h" #include extern "C"{ #include "clib-syslog.h" } class XinputPlugin : public PluginInterface { public: XinputPlugin(); XinputPlugin(XinputPlugin&)=delete; ~XinputPlugin(); static XinputPlugin *instance(); virtual void activate(); virtual void deactivate(); private: XinputManager *m_pXinputManager = nullptr; static XinputPlugin *_instance; }; extern "C" Q_DECL_EXPORT PluginInterface *createSettingsPlugin(); #endif // XINPUTPLUGIN_H ukui-settings-daemon/plugins/xinput/xinputplugin.cpp0000664000175000017500000000361015167655063022054 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "xinputplugin.h" #include #include #include "usd_base_class.h" XinputPlugin* XinputPlugin::_instance = nullptr; XinputPlugin* XinputPlugin::instance() { QMutex mutex; mutex.lock(); if(nullptr == _instance) _instance = new XinputPlugin; mutex.unlock(); return _instance; } XinputPlugin::XinputPlugin() { if (UsdBaseClass::isWayland()) { USD_LOG(LOG_DEBUG,"is wayland exit..."); return; } if (!m_pXinputManager) { m_pXinputManager = new XinputManager(nullptr); } USD_LOG(LOG_ERR, "Loading Xinput plugins"); } XinputPlugin::~XinputPlugin() { } void XinputPlugin::activate() { if (UsdBaseClass::isWayland()) { USD_LOG(LOG_DEBUG,"is wayland exit..."); return; } USD_LOG(LOG_ERR,"activating Xinput plugins"); m_pXinputManager->start(); } void XinputPlugin::deactivate() { if (UsdBaseClass::isWayland()) { USD_LOG(LOG_DEBUG,"is wayland exit..."); return; } m_pXinputManager->stop(); } PluginInterface *createSettingsPlugin() { return dynamic_cast(XinputPlugin::instance()); } ukui-settings-daemon/plugins/background/0000775000175000017500000000000015167655063017372 5ustar fengfengukui-settings-daemon/plugins/background/background-plugin.cpp0000664000175000017500000000333015167655063023510 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include "background-plugin.h" #include "clib-syslog.h" PluginInterface* BackgroundPlugin::mInstance = nullptr; BackgroundPlugin::BackgroundPlugin() { return; manager = new BackgroundManager(); return; } BackgroundPlugin::~BackgroundPlugin() { return; USD_LOG(LOG_DEBUG, "background plugin free..."); if(manager){ delete manager; manager = nullptr; } } PluginInterface *BackgroundPlugin::getInstance() { if (nullptr == mInstance) { mInstance = new BackgroundPlugin(); } return mInstance; } void BackgroundPlugin::activate() { return; USD_LOG (LOG_DEBUG, "Activating %s plugin compilation time:[%s] [%s]",MODULE_NAME,__DATE__,__TIME__); manager->BackgroundManagerStart(); } void BackgroundPlugin::deactivate() { USD_LOG (LOG_DEBUG, "Deactivating background plugin"); } PluginInterface* createSettingsPlugin() { return BackgroundPlugin::getInstance(); } ukui-settings-daemon/plugins/background/background-manager.h0000664000175000017500000000356715167655063023305 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef BACKGROUND_MANAGER_H #define BACKGROUND_MANAGER_H #include #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif #include "clib-syslog.h" #ifdef __cplusplus } #endif class BackgroundManager : public QObject { Q_OBJECT public: BackgroundManager(); ~BackgroundManager(); public: void BackgroundManagerStart(); void SetBackground(); void initGSettings(); void setSolidColorBackground(); void draw_background(); private: void scaleBg(const QRect &geometry); void virtualGeometryChangedProcess(const QRect &geometry); public Q_SLOTS: void setup_Background(const QString &key); void screenAddedProcess(QScreen *screen); void screenRemovedProcess(QScreen *screen); void StartXrandrIdleCb(); private: QTimer *mAcitveTime = nullptr; QGSettings *bSettingOld; QScreen *m_screen; QString Filename; Display *dpy = NULL; Pixmap pix = NULL; Window root = NULL; Screen *scn = NULL; }; #endif // BACKGROUND_MANAGER_H ukui-settings-daemon/plugins/background/background.pro0000664000175000017500000000141415167655063022233 0ustar fengfeng#------------------------------------------------- # # Project created by QtCreator 2020-04-16T09:30:00 # #------------------------------------------------- QT += core widgets dbus x11extras gui TEMPLATE = lib TARGET = background CONFIG += no_keywords c++20 create_prl plugin link_pkgconfig app_bundle debug DEFINES += MODULE_NAME=\\\"backGround\\\" include($$PWD/../../common/common.pri) PKGCONFIG += \ gio-2.0 \ gtk+-3.0 \ glib-2.0 \ imlib2 SOURCES += \ $$PWD/background-plugin.cpp \ $$PWD/background-manager.cpp HEADERS += \ $$PWD/background-plugin.h \ $$PWD/background-manager.h background_lib.path = $${PLUGIN_INSTALL_DIRS} background_lib.files += $$OUT_PWD/libbackground.so INSTALLS += background_lib ukui-settings-daemon/plugins/background/background-manager.cpp0000664000175000017500000001405515167655063023632 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include "background-manager.h" #include #include #include "clib-syslog.h" #define BACKGROUND "org.mate.background" #define PICTURE_FILE_NAME "picture-filename" #define COLOR_FILE_NAME "primary-color" #define CAN_DRAW_BACKGROUND "draw-background" BackgroundManager::BackgroundManager() { m_screen = QApplication::screens().at(0); mAcitveTime = new QTimer(this); } BackgroundManager::~BackgroundManager() { if (mAcitveTime) { delete mAcitveTime; mAcitveTime = nullptr; } } void BackgroundManager::initGSettings(){ // connect(qApp,SIGNAL(screenAdded(QScreen *)),this, SLOT(screenAddedProcess(QScreen*))); //connect(qApp, SLOT(screenRemoved(QScreen *)),this, SLOT(screenRemovedProcess(QScreen *))); // connect(m_screen, &QScreen::virtualGeometryChanged, this,&BackgroundManager::virtualGeometryChangedProcess); } /* void BackgroundManager::SetBackground() { Pixmap pix; Window root; Screen *scn; QScreen *screen; Imlib_Image img; int ScnNum, width = 0,height = 0; dpy = gdk_x11_get_default_xdisplay(); img = imlib_load_image(Filename.toLatin1().data()); if (!img) { USD_LOG(LOG_DEBUG,"%s:Unable to load image\n", Filename.toLatin1().data()); return ; } imlib_context_set_image(img); if (!dpy) return ; ScnNum = QApplication::screens().length(); width = DisplayWidth(dpy, 0); height = DisplayHeight(dpy, 0); scn = DefaultScreenOfDisplay(dpy); root = DefaultRootWindow(dpy); pix = XCreatePixmap(dpy, root, width, height, DefaultDepthOfScreen(scn)); imlib_context_set_display(dpy); imlib_context_set_visual(DefaultVisualOfScreen(scn)); imlib_context_set_colormap(DefaultColormapOfScreen(scn)); imlib_context_set_drawable(pix); ScnNum = QApplication::screens().length(); for(int i = 0; i < ScnNum; i++){ screen = QApplication::screens().at(i); //qDebug()<geometry(); imlib_render_image_on_drawable_at_size(screen->geometry().x() * 2, screen->geometry().y() * 2, screen->geometry().width() *2, screen->geometry().height() * 2); } XSetWindowBackgroundPixmap(dpy, root, pix); XClearWindow(dpy, root); while (XPending(dpy)) { XEvent ev; XNextEvent(dpy, &ev); } XFreePixmap(dpy, pix); imlib_free_image(); } */ void BackgroundManager::setup_Background(const QString &key) { if(key.compare(QString::fromLocal8Bit(PICTURE_FILE_NAME))==0) Filename = bSettingOld->get(PICTURE_FILE_NAME).toString(); if(key.compare(QString::fromLocal8Bit(COLOR_FILE_NAME))==0) Filename = bSettingOld->get(COLOR_FILE_NAME).toString(); SetBackground(); } void BackgroundManager::SetBackground() { setSolidColorBackground(); draw_background(); } void BackgroundManager::setSolidColorBackground() { Imlib_Image img; if (!dpy){ dpy = XOpenDisplay(NULL); if(!dpy) return; } int width = 0; int height = 0; int screen = DefaultScreen(dpy); if(!scn) scn = DefaultScreenOfDisplay(dpy); if(!root) root = DefaultRootWindow(dpy); width = DisplayWidth (dpy, screen); height = DisplayHeight(dpy, screen); pix = XCreatePixmap(dpy, root, width, height, DefaultDepthOfScreen(scn)); imlib_context_set_display(dpy); imlib_context_set_visual(DefaultVisualOfScreen(scn)); imlib_context_set_colormap(DefaultColormapOfScreen(scn)); imlib_context_set_drawable(pix); img = imlib_create_image(width, height); imlib_context_set_image(img); imlib_context_set_color(0, 0,0, 255);//black imlib_image_fill_rectangle(0, 0, width, height); imlib_context_set_image(img); for(QScreen *screen : QApplication::screens()){ //在每个屏幕上绘制背景 QRect rect = screen->geometry(); imlib_render_image_on_drawable_at_size(rect.x()*screen->devicePixelRatio(), rect.y()*screen->devicePixelRatio(), rect.width()*screen->devicePixelRatio(),rect.height()*screen->devicePixelRatio()); } imlib_free_image(); } void BackgroundManager::draw_background() { XSetWindowBackgroundPixmap(dpy, root, pix); XClearWindow(dpy, root); while (XPending(dpy)) { XEvent ev; XNextEvent(dpy, &ev); } XFreePixmap(dpy, pix); XCloseDisplay(dpy); dpy = NULL; pix = NULL; root = NULL; scn = NULL; } void BackgroundManager::screenAddedProcess(QScreen *screen) { mAcitveTime->start(3000); //SetBackground(); } void BackgroundManager::screenRemovedProcess(QScreen *screen) { mAcitveTime->start(3000); //SetBackground(); } void BackgroundManager::virtualGeometryChangedProcess(const QRect &geometry) { mAcitveTime->start(3000); //SetBackground(); } /** * @brief XrandrManager::StartXrandrIdleCb * 开始时间回调函数 */ void BackgroundManager::StartXrandrIdleCb() { mAcitveTime->stop(); SetBackground(); } void BackgroundManager::BackgroundManagerStart() { connect(mAcitveTime, &QTimer::timeout, this,&BackgroundManager::StartXrandrIdleCb); mAcitveTime->start(10000); initGSettings(); } ukui-settings-daemon/plugins/background/background-plugin.h0000664000175000017500000000254615167655063023165 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef BACKGROUNDPLUGIN_H #define BACKGROUNDPLUGIN_H #include "background-manager.h" #include "plugin-interface.h" #include class BackgroundPlugin : public PluginInterface { public: ~BackgroundPlugin(); static PluginInterface* getInstance(); virtual void activate (); virtual void deactivate (); private: BackgroundPlugin(); BackgroundPlugin(BackgroundPlugin&)=delete; private: BackgroundManager *manager; static PluginInterface* mInstance; }; extern "C" Q_DECL_EXPORT PluginInterface* createSettingsPlugin(); #endif // BACKGROUNDPLUGIN_H ukui-settings-daemon/plugins/keyboard/0000775000175000017500000000000015167655063017053 5ustar fengfengukui-settings-daemon/plugins/keyboard/keyboard-plugin.h0000775000175000017500000000253515167655063022330 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef KEYBOARDPLUGIN_H #define KEYBOARDPLUGIN_H #include "keyboard-wayland-manager.h" #include "keyboard-manager.h" #include "plugin-interface.h" class KeyboardPlugin : public PluginInterface { public: ~KeyboardPlugin(); static PluginInterface * getInstance(); virtual void activate(); virtual void deactivate(); private: KeyboardPlugin(); KeyboardPlugin(KeyboardPlugin&)=delete; private: ManagerInterface *KeyboardManager = nullptr; static PluginInterface * mInstance; }; extern "C" Q_DECL_EXPORT PluginInterface * createSettingsPlugin(); #endif // KEYBOARDPLUGIN_H ukui-settings-daemon/plugins/keyboard/keyboard-xkb.cpp0000775000175000017500000002436715167655063022160 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include "keyboard-xkb.h" #include "clib-syslog.h" #define MATEKBD_DESKTOP_SCHEMA "org.mate.peripherals-keyboard-xkb.general" #define MATEKBD_KBD_SCHEMA "org.mate.peripherals-keyboard-xkb.kbd" #define KNOWN_FILES_KEY "known-file-list" #define DISABLE_INDICATOR_KEY "disable-indicator" KeyboardManager *KeyboardXkb::manager = KeyboardManager::KeyboardManagerNew(); static void *pa_callback_user_data = NULL; static XklConfigRegistry* xkl_registry = NULL; static MatekbdDesktopConfig current_desktop_config; static MatekbdKeyboardConfig current_kbd_config; /* never terminated */ static MatekbdKeyboardConfig initial_sys_kbd_config; static PostActivationCallback pa_callback = NULL; static XklEngine* xkl_engine; static bool inited_ok = false; KeyboardXkb::KeyboardXkb() { USD_LOG(LOG_DEBUG,"Keyboard Xkb initializing!"); } KeyboardXkb::~KeyboardXkb() { USD_LOG(LOG_DEBUG,"Keyboard Xkb free"); if(settings_desktop) { delete settings_desktop; settings_desktop = nullptr; } if(settings_kbd) { delete settings_kbd; settings_kbd = nullptr; } } void KeyboardXkb::usd_keyboard_xkb_analyze_sysconfig (void) { if (!inited_ok) return; matekbd_keyboard_config_init (&initial_sys_kbd_config, xkl_engine); matekbd_keyboard_config_load_from_x_initial (&initial_sys_kbd_config,NULL); } void KeyboardXkb::apply_desktop_settings (void) { if (!inited_ok) return; manager->usd_keyboard_manager_apply_settings (manager); matekbd_desktop_config_load_from_gsettings (¤t_desktop_config); /* again, probably it would be nice to compare things before activating them */ matekbd_desktop_config_activate (¤t_desktop_config); } bool KeyboardXkb::try_activating_xkb_config_if_new (MatekbdKeyboardConfig *current_sys_kbd_config) { /* Activate - only if different! */ if (!matekbd_keyboard_config_equals (¤t_kbd_config, current_sys_kbd_config)) { if (matekbd_keyboard_config_activate (¤t_kbd_config)) { if (pa_callback != NULL) { (*pa_callback) (pa_callback_user_data); return TRUE; } } else { return FALSE; } } return TRUE; } static void g_strv_behead (gchar **arr) { if (arr == NULL || *arr == NULL) return; g_free (*arr); memmove (arr, arr + 1, g_strv_length (arr) * sizeof (gchar *)); } bool KeyboardXkb::filter_xkb_config (void) { XklConfigItem *item; char *lname; char *vname; char **lv; bool any_change = FALSE; xkl_debug (100, "Filtering configuration against the registry\n"); if (!xkl_registry) { xkl_registry = xkl_config_registry_get_instance (xkl_engine); /* load all materials, unconditionally! */ if (!xkl_config_registry_load (xkl_registry, TRUE)){ g_object_unref (xkl_registry); xkl_registry = NULL; return FALSE; } } lv = current_kbd_config.layouts_variants; item = xkl_config_item_new (); while (*lv) { xkl_debug (100, "Checking [%s]\n", *lv); if (matekbd_keyboard_config_split_items (*lv, &lname, &vname)) { bool should_be_dropped = FALSE; snprintf (item->name ,sizeof (item->name), "%s",lname); if (!xkl_config_registry_find_layout(xkl_registry, item)) { xkl_debug (100, "Bad layout [%s]\n",lname); should_be_dropped = TRUE; } else if (vname) { snprintf (item->name,sizeof (item->name), "%s", vname); if (!xkl_config_registry_find_variant (xkl_registry, lname, item)) { xkl_debug (100,"Bad variant [%s(%s)]\n",lname, vname); should_be_dropped = TRUE; } } if (should_be_dropped) { g_strv_behead (lv); any_change = TRUE; continue; } } lv++; } g_object_unref (item); return any_change; } static void activation_error (void) { Display *dpy = UsdBaseClass::getQx11Info(); char const *vendor = ServerVendor (dpy);//GDK_DISPLAY_XDISPLAY (gdk_display_get_default ())); int release = VendorRelease (dpy);//GDK_DISPLAY_XDISPLAY (gdk_display_get_default ())); QMessageBox *dialog; /* VNC viewers will not work, do not barrage them with warnings */ if (NULL != vendor && NULL != strstr (vendor, "VNC")) return; QString message = QObject::tr("Error activating XKB configuration.\n" "It can happen under various circumstances:\n" " • a bug in libxklavier library\n" " • a bug in X server (xkbcomp, xmodmap utilities)\n" " • X server with incompatible libxkbfile implementation\n\n" "X server version data:\n %1 \n %2 \n" "If you report this situation as a bug, please include:\n" " • The result of xprop -root | grep XKB \n" " • The result of gsettings list-keys org.mate.peripherals-keyboard-xkb.kbd ").arg(vendor).arg(release); dialog = new QMessageBox(); dialog->setButtonText(QMessageBox::Close,QObject::tr("Close")); dialog->setButtonText(QMessageBox::Warning,QObject::tr("Error")); dialog->setText(message); dialog->show(); dialog->close(); delete dialog; dialog = nullptr; } void KeyboardXkb::apply_xkb_settings (void) { MatekbdKeyboardConfig current_sys_kbd_config; if (!inited_ok) return; matekbd_keyboard_config_init (¤t_sys_kbd_config, xkl_engine); matekbd_keyboard_config_load_from_gsettings (¤t_kbd_config, &initial_sys_kbd_config); matekbd_keyboard_config_load_from_x_current (¤t_sys_kbd_config, NULL); if (!try_activating_xkb_config_if_new (¤t_sys_kbd_config)) { if (filter_xkb_config ()) { if (!try_activating_xkb_config_if_new(¤t_sys_kbd_config)) { qWarning ("Could not activate the filtered XKB configuration"); activation_error (); } } else { qWarning("Could not activate the XKB configuration"); activation_error (); } } else xkl_debug (100, "Actual KBD configuration was not changed: redundant notification\n"); matekbd_keyboard_config_term (¤t_sys_kbd_config); } void KeyboardXkb::apply_desktop_settings_cb (QString key) { apply_desktop_settings (); } void KeyboardXkb::apply_desktop_settings_mate_cb(GSettings *settings,char *key) { apply_desktop_settings (); } void KeyboardXkb::apply_xkb_settings_cb (QString key) { apply_xkb_settings (); } void KeyboardXkb::apply_xkb_settings_mate_cb (GSettings *settings,char *key) { apply_xkb_settings (); } GdkFilterReturn usd_keyboard_xkb_evt_filter (GdkXEvent * xev, GdkEvent * event,gpointer data) { KeyboardXkb *xkb = (KeyboardXkb *)data; XEvent *xevent = (XEvent *) xev; xkl_engine_filter_events (xkl_engine, xevent); return GDK_FILTER_CONTINUE; } /* When new Keyboard is plugged in - reload the settings */ void KeyboardXkb::usd_keyboard_new_device (XklEngine * engine) { apply_desktop_settings (); apply_xkb_settings (); } void KeyboardXkb::usd_keyboard_xkb_init(KeyboardManager* kbd_manager) { USD_LOG(LOG_DEBUG,"init --- XKB"); Display *display; display = UsdBaseClass::getQx11Info(); manager = kbd_manager; xkl_engine = xkl_engine_get_instance (display); if (xkl_engine) { inited_ok = TRUE; settings_desktop = new QGSettings(MATEKBD_DESKTOP_SCHEMA); settings_kbd = new QGSettings(MATEKBD_KBD_SCHEMA); matekbd_desktop_config_init (¤t_desktop_config,xkl_engine); matekbd_keyboard_config_init (¤t_kbd_config,xkl_engine); xkl_engine_backup_names_prop (xkl_engine); usd_keyboard_xkb_analyze_sysconfig (); matekbd_desktop_config_start_listen (¤t_desktop_config, G_CALLBACK (apply_desktop_settings_mate_cb),NULL); matekbd_keyboard_config_start_listen (¤t_kbd_config,G_CALLBACK (apply_xkb_settings_mate_cb),NULL); QObject::connect(settings_desktop,SIGNAL(changed(QString)),this,SLOT(apply_desktop_settings_cb(QString))); QObject::connect(settings_kbd,SIGNAL(changed(QString)),this,SLOT(apply_xkb_settings_cb(QString))); // gdk_window_add_filter (NULL, (GdkFilterFunc)usd_keyboard_xkb_evt_filter, this); if (xkl_engine_get_features (xkl_engine) &XKLF_DEVICE_DISCOVERY) g_signal_connect (xkl_engine, "X-new-device", G_CALLBACK(usd_keyboard_new_device), NULL); xkl_engine_start_listen (xkl_engine, XKLL_MANAGE_LAYOUTS |XKLL_MANAGE_WINDOW_STATES); apply_desktop_settings (); apply_xkb_settings (); } } void KeyboardXkb::usd_keyboard_xkb_shutdown (void) { pa_callback = NULL; pa_callback_user_data = NULL; manager = NULL; if (!inited_ok) return; xkl_engine_stop_listen (xkl_engine, XKLL_MANAGE_LAYOUTS | XKLL_MANAGE_WINDOW_STATES); gdk_window_remove_filter (NULL, (GdkFilterFunc)usd_keyboard_xkb_evt_filter, NULL); if (xkl_registry) { g_object_unref (xkl_registry); } g_object_unref (xkl_engine); xkl_engine = NULL; inited_ok = FALSE; } ukui-settings-daemon/plugins/keyboard/keyboard.pro0000775000175000017500000000272115167655063021402 0ustar fengfeng#------------------------------------------------- # # Project created by QtCreator 2020-04-20T09:30:00 # #------------------------------------------------- QT += gui QT += core widgets TARGET = keyboard TEMPLATE = lib DEFINES += KEYBOARD_LIBRARY CONFIG += c++20 no_keywords link_pkgconfig plugin DEFINES += QT_DEPRECATED_WARNINGS MODULE_NAME=\\\"keyboard\\\" include($$PWD/../../common/common.pri) PKGCONFIG += \ gtk+-3.0 \ glib-2.0 harfbuzz gmodule-2.0 \ libxklavier gobject-2.0 gio-2.0 \ cairo cairo-gobject gsettings-qt \ kysdk-waylandhelper KWaylandClient INCLUDEPATH += \ -I ukui-settings-daemon/ \ -I /usr/include/libmatekbd \ -I /usr/include/KF6/KWindowSystem LIBS += \ -L/usr/lib/*-linux-gnu -lmatekbdui -lmatekbd \ -Wl,--export-dynamic -lgmodule-2.0 \ -pthread -lgdk-3 -lpangocairo-1.0 \ -lpango-1.0 -lharfbuzz -lgdk_pixbuf-2.0 \ -lcairo-gobject -lcairo -lgio-2.0 -lgobject-2.0 \ -lwayland-client -lKF6WindowSystem SOURCES += \ keyboard-manager.cpp \ keyboard-plugin.cpp \ keyboard-wayland-manager.cpp \ keyboard-widget.cpp \ keyboard-xkb.cpp HEADERS += \ keyboard-manager.h \ keyboard-wayland-manager.h \ keyboard-widget.h \ keyboard-xkb.h \ keyboard-plugin.h keyboard_lib.path = $${PLUGIN_INSTALL_DIRS} keyboard_lib.files = $$OUT_PWD/libkeyboard.so INSTALLS += keyboard_lib FORMS += \ keyboardwidget.ui ukui-settings-daemon/plugins/keyboard/keyboard-wayland-manager.h0000775000175000017500000000615215167655063024100 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef KeyboardWaylandManager_H #define KeyboardWaylandManager_H #include #include #include #include #include #include #include #include #include #include #include "xeventmonitor.h" #include "keyboard-xkb.h" #include "keyboard-widget.h" #include "usd_base_class.h" #include "plugin-manager-interface.h" /**************************/ #include // #include #include #include #include using namespace KWayland::Client; /**************************/ #ifdef HAVE_X11_EXTENSIONS_XF86MISC_H #include #endif #ifdef HAVE_X11_EXTENSIONS_XKB_H #include #include #endif class KeyState; class KeyboardXkb; class KeyboardWaylandManager : public ManagerInterface { Q_OBJECT private: KeyboardWaylandManager()=delete; KeyboardWaylandManager(KeyboardWaylandManager&)=delete; KeyboardWaylandManager&operator=(const KeyboardWaylandManager&)=delete; KeyboardWaylandManager(QObject *parent = nullptr); public: ~KeyboardWaylandManager(); static KeyboardWaylandManager *KeyboardWaylandManagerNew(); virtual bool Start(); virtual void Stop(); public Q_SLOTS: void start_keyboard_idle_cb (); void apply_settings (QString); void onKeyStateChange(quint32 key, Keyboard::KeyState state); private: friend void apply_repeat (KeyboardWaylandManager *manager); private: QTimer *time; static KeyboardWaylandManager *mKeyboardWaylandManager; QGSettings *settings; QGSettings *ksettings; int old_state; bool stInstalled; KeyboardWidget* m_statusWidget; KeyState* m_keyState; quint32 m_capsLock; quint32 m_numLock; }; class KeyState : public QObject { Q_OBJECT public: explicit KeyState(QObject* parent = nullptr); //连接状态改变信号 void connectInit(); Q_SIGNALS: void keyStateChange(quint32, Keyboard::KeyState); private: Registry m_registry; }; #endif // KeyboardWaylandManager_H ukui-settings-daemon/plugins/keyboard/keyboard-xkb.h0000775000175000017500000000435415167655063021617 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef KEYBOARDXKB_H #define KEYBOARDXKB_H #include "keyboard-manager.h" #include "config.h" #include #include #include #include #include #include "QGSettings/qgsettings.h" extern "C"{ #include #include } typedef void (*PostActivationCallback) (void* userData); class KeyboardManager; class KeyboardXkb : public QObject { Q_OBJECT public Q_SLOTS: static void apply_desktop_settings_cb (QString); static void apply_xkb_settings_cb(QString); public: KeyboardXkb(); KeyboardXkb(KeyboardXkb&)=delete; ~KeyboardXkb(); static KeyboardManager * manager; public: void usd_keyboard_xkb_init(KeyboardManager* kbd_manager); void usd_keyboard_xkb_shutdown(void); static void apply_desktop_settings (void); static void usd_keyboard_new_device (XklEngine * engine); static void apply_desktop_settings_mate_cb(GSettings *settings, gchar *key); static void apply_xkb_settings_mate_cb (GSettings *settings, gchar *key); static void apply_xkb_settings (void); friend GdkFilterReturn usd_keyboard_xkb_evt_filter (GdkXEvent * xev, GdkEvent * event,gpointer data); void usd_keyboard_xkb_analyze_sysconfig (void); static bool try_activating_xkb_config_if_new (MatekbdKeyboardConfig *current_sys_kbd_config); static bool filter_xkb_config (void); public: QGSettings* settings_desktop; QGSettings* settings_kbd; }; #endif // KEYBOARDXKB_H ukui-settings-daemon/plugins/keyboard/keyboard-plugin.cpp0000775000175000017500000000404115167655063022655 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "keyboard-plugin.h" #include "clib-syslog.h" PluginInterface * KeyboardPlugin::mInstance=nullptr; KeyboardPlugin::KeyboardPlugin() { USD_LOG(LOG_DEBUG,"KeyboardPlugin initializing!"); if (UsdBaseClass::isXcb()) { KeyboardManager = KeyboardManager::KeyboardManagerNew(); } else { //wayland KeyboardManager = KeyboardWaylandManager::KeyboardWaylandManagerNew(); } } KeyboardPlugin::~KeyboardPlugin() { USD_LOG(LOG_DEBUG,"Keyboard plugin free"); if (KeyboardManager){ delete KeyboardManager; KeyboardManager = nullptr; } } void KeyboardPlugin::activate() { bool res; USD_LOG (LOG_DEBUG, "Activating %s plugin compilation time:[%s] [%s]",MODULE_NAME,__DATE__,__TIME__); if (KeyboardManager) { res = KeyboardManager->Start(); } if(!res){ USD_LOG(LOG_ERR,"Unable to start Keyboard Manager!") } } PluginInterface * KeyboardPlugin::getInstance() { if(nullptr == mInstance){ mInstance = new KeyboardPlugin(); } return mInstance; } void KeyboardPlugin::deactivate() { USD_LOG(LOG_DEBUG,"Deactivating Keyboard Plugin"); if (KeyboardManager) { KeyboardManager->Stop(); } } PluginInterface *createSettingsPlugin() { return KeyboardPlugin::getInstance(); } ukui-settings-daemon/plugins/keyboard/keyboard-wayland-manager.cpp0000664000175000017500000002304515167655063024430 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "keyboard-wayland-manager.h" #include "clib-syslog.h" #include "config.h" #include "rfkillswitch.h" #include "usd_base_class.h" #include "clib-syslog.h" #define USD_KEYBOARD_SCHEMA "org.ukui.peripherals-keyboard" #define UKCCOSD_SCHEMA "org.ukui.control-center.osd" #define KYCCOSD_SCHEMA "org.kylin.control-center.osd" #define KDSOSD_SCHEMA "org.ukui.kds.osd" #define SHOW_TIP_KEY "show-lock-tip" #define KEY_REPEAT "repeat" #define KEY_CLICK "click" #define KEY_RATE "rate" #define KEY_DELAY "delay" #define KEY_CLICK_VOLUME "click-volume" #define KEY_BELL_PITCH "bell-pitch" #define KEY_BELL_DURATION "bell-duration" #define KEY_BELL_MODE "bell-mode" #define KEY_NUMLOCK_STATE "numlock-state" #define KEY_CAPSLOCK_STATE "capslock-state" #define KEY_NUMLOCK_REMEMBER "remember-numlock-state" #define KEY_DEFAULT_RATE 25 #define KEY_DEFAULT_DELAY 660 KeyboardWaylandManager *KeyboardWaylandManager::mKeyboardWaylandManager = nullptr; KeyboardWaylandManager::KeyboardWaylandManager(QObject * parent) { settings = new QGSettings(USD_KEYBOARD_SCHEMA); stInstalled = true; time = new QTimer(this); const QByteArray id(UKCCOSD_SCHEMA); const QByteArray idd(KYCCOSD_SCHEMA); const QByteArray iid(KDSOSD_SCHEMA); if (QGSettings::isSchemaInstalled(id)){ ksettings = new QGSettings(id); } else if (QGSettings::isSchemaInstalled(idd)){ ksettings = new QGSettings(idd); } else if (QGSettings::isSchemaInstalled(iid)){ ksettings = new QGSettings(iid); } else { stInstalled = false; } m_statusWidget = new KeyboardWidget(); m_keyState = new KeyState(this); m_capsLock = Keystate::State::Unlocked; m_numLock = Keystate::State::Unlocked; } KeyboardWaylandManager::~KeyboardWaylandManager() { if (settings) { delete settings; settings = nullptr; } if (time) { delete time; time = nullptr; } if (m_statusWidget) { delete m_statusWidget; m_statusWidget = nullptr; } if (ksettings) { delete ksettings; ksettings = nullptr; } if(m_statusWidget) { delete m_statusWidget; m_statusWidget = nullptr; } } KeyboardWaylandManager *KeyboardWaylandManager::KeyboardWaylandManagerNew() { if (nullptr == mKeyboardWaylandManager) mKeyboardWaylandManager = new KeyboardWaylandManager(nullptr); return mKeyboardWaylandManager; } bool KeyboardWaylandManager::Start() { USD_LOG(LOG_DEBUG,"-- Keyboard Start Manager --"); connect(time,SIGNAL(timeout()),this,SLOT(start_keyboard_idle_cb())); time->start(1500); return true; } void KeyboardWaylandManager::Stop() { USD_LOG(LOG_DEBUG,"-- Keyboard Stop Manager --"); } static gboolean xkb_set_keyboard_autorepeat_rate(int delay, int rate) { int interval = (rate <= 0) ? 1000000 : 1000/rate; Display *dpy = UsdBaseClass::getQx11Info(); if (delay <= 0) { delay = 1; } return XkbSetAutoRepeatRate(dpy, XkbUseCoreKbd, delay, interval); } void apply_repeat (KeyboardWaylandManager *manager) { bool repeat; int rate; int delay; //Display *dpy = UsdBaseClass::getQx11Info(); repeat = manager->settings->get(KEY_REPEAT).toBool(); rate = manager->settings->get(KEY_RATE).toInt(); delay = manager->settings->get(KEY_DELAY).toInt(); if (rate < 0) rate = KEY_DEFAULT_RATE; if (delay < 0) delay = KEY_DEFAULT_DELAY; USD_LOG(LOG_DEBUG,"repeat = %d, rate = %d, delay = %d", repeat, rate, delay); if (UsdBaseClass::isWayland()) { QDBusMessage message = QDBusMessage::createMethodCall(QStringLiteral("org.ukui.KWin"), QStringLiteral("/KWin"), QStringLiteral("org.ukui.KWin"), QStringLiteral("setKeyboardRepeat")); QList args; args.append(repeat); args.append(rate); args.append(delay); message.setArguments(args); QDBusConnection::sessionBus().asyncCall(message); } } void KeyboardWaylandManager::apply_settings (QString keys) { /** * Fix by HB* system reboot but rnumlock not available; **/ if (keys.compare(QString::fromLocal8Bit(KEY_CLICK)) == 0|| keys.compare(QString::fromLocal8Bit(KEY_CLICK_VOLUME)) == 0 || keys.compare(QString::fromLocal8Bit(KEY_BELL_PITCH)) == 0 || keys.compare(QString::fromLocal8Bit(KEY_BELL_DURATION)) == 0 || keys.compare(QString::fromLocal8Bit(KEY_BELL_MODE)) == 0) { USD_LOG(LOG_DEBUG,"Bell setting '%s' changed, applying bell settings", keys.toLatin1().data()); // apply_bell (this); } else if (keys.compare(QString::fromLocal8Bit(KEY_NUMLOCK_REMEMBER)) == 0) { USD_LOG(LOG_DEBUG,"Remember Num-Lock state '%s' changed, applying num-lock settings", keys.toLatin1().data()); // apply_numlock (this); } else if (keys.compare(QString::fromLocal8Bit(KEY_NUMLOCK_STATE)) == 0) { USD_LOG(LOG_DEBUG,"Num-Lock state '%s' changed, will apply at next startup", keys.toLatin1().data()); } else if (keys.compare(QString::fromLocal8Bit(KEY_REPEAT)) == 0 || keys.compare(QString::fromLocal8Bit(KEY_RATE)) == 0 || keys.compare(QString::fromLocal8Bit(KEY_DELAY)) == 0) { USD_LOG(LOG_DEBUG,"Key repeat setting '%s' changed, applying key repeat settings", keys.toLatin1().data()); apply_repeat (this); } else { // USD_LOG(LOG_DEBUG,"Unhandled settings change, key '%s'", key); } } void KeyboardWaylandManager::onKeyStateChange(quint32 key , Keyboard::KeyState state) { switch (key) { case key: if(state != m_capsLock) { m_capsLock = state; if (stInstalled && !ksettings->get(SHOW_TIP_KEY).toBool()){ //提示关闭时不弹窗 return; } if(m_capsLock == Keystate::State::Locked) { m_statusWidget->setIcons("ukui-capslock-on"); } else { m_statusWidget->setIcons("ukui-capslock-off"); } m_statusWidget->showWidget(); } break; case Keystate::Key::NumLock: if(state != m_numLock) { m_numLock = state; if (stInstalled && !ksettings->get(SHOW_TIP_KEY).toBool()){ //提示关闭时不弹窗 return; } if(m_numLock == Keystate::State::Locked) { m_statusWidget->setIcons("ukui-numlock-on"); } else { m_statusWidget->setIcons("ukui-numlock-off"); } m_statusWidget->showWidget(); } break; case Keystate::Key::ScrollLock: break; default: break; } } void KeyboardWaylandManager::start_keyboard_idle_cb () { //wayland time->stop(); m_keyState->connectInit(); connect(settings,SIGNAL(changed(QString)),this,SLOT(apply_settings(QString))); connect(m_keyState ,&KeyState::keyStateChange,this,&KeyboardWaylandManager::onKeyStateChange); apply_repeat (this); } KeyState::KeyState(QObject* parent) { } #if 0 void KeyState::connectInit() { //获取wl_display 连接 ConnectionThread* connection = ConnectionThread::fromApplication(); if (connection) { m_registry.create(connection); m_registry.setup(); QObject::connect(&m_registry,&Registry::interfacesAnnounced,[this]{ const bool hasKeystate = m_registry.hasInterface(Registry::Interface::Keystate); if(hasKeystate){ auto keyStateInterface = m_registry.interface(Registry::Interface::Keystate); Keystate *keystate = m_registry.createKeystate(keyStateInterface.name,keyStateInterface.version); QObject::connect(keystate,&Keystate::stateChanged,keystate,[=](Keystate::Key key,Keystate::State state){ // qDebug()<<"key: "<fetchStates(); } else { USD_LOG(LOG_DEBUG,"wl_display no interface keystate "); } }); } else { USD_LOG(LOG_ERR, "get wl_display error ."); } } #endif void KeyState::connectInit() { Registry *registry = new Registry(this); connect(registry, &Registry::seatAnnounced, this ,[this, registry](quint32 name){ Seat *s = registry->createSeat(name, 2, this); connect(s, &Seat::hasKeyboardChanged, this, [](quint32 key, Keyboard::KeyState state){ USD_LOG_SHOW_PARAM1(key); Q_EMIT keyStateChange(key,state); }); }); } ukui-settings-daemon/plugins/keyboard/keyboard-widget.h0000664000175000017500000000352515167655063022312 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef KEYBOARDWIDGET_H #define KEYBOARDWIDGET_H #include #include #include #include #include #include namespace Ui { class KeyboardWidget; } class KeyboardWidget : public QWidget { Q_OBJECT public: explicit KeyboardWidget(QWidget *parent = nullptr); ~KeyboardWidget(); void setIcons(QString icon); void showWidget(); protected: void paintEvent(QPaintEvent *event); void resizeEvent(QResizeEvent* even); private: void initWidgetInfo(); void geometryChangedHandle(); QPixmap drawLightColoredPixmap(const QPixmap &source, const QString &style); void repaintWidget(); double getGlobalOpacity(); public Q_SLOTS: void timeoutHandle(); void onStyleChanged(const QString&); private: Ui::KeyboardWidget *ui; QFrame* m_frame; QString m_iconName; QString m_LocalIconPath; QLabel *m_btnStatus; QTimer *m_timer; QGSettings *m_styleSettings; }; #endif // KEYBOARDWIDGET_H ukui-settings-daemon/plugins/keyboard/keyboard-manager.cpp0000664000175000017500000004151615167655063022776 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "keyboard-manager.h" #include "clib-syslog.h" #include "config.h" #include "rfkillswitch.h" #define USD_KEYBOARD_SCHEMA "org.ukui.peripherals-keyboard" #define UKCCOSD_SCHEMA "org.ukui.control-center.osd" #define KYCCOSD_SCHEMA "org.kylin.control-center.osd" #define KDSOSD_SCHEMA "org.ukui.kds.osd" #define SHOW_TIP_KEY "show-lock-tip" #define KEY_REPEAT "repeat" #define KEY_CLICK "click" #define KEY_RATE "rate" #define KEY_DELAY "delay" #define KEY_CLICK_VOLUME "click-volume" #define KEY_BELL_PITCH "bell-pitch" #define KEY_BELL_DURATION "bell-duration" #define KEY_BELL_MODE "bell-mode" #define KEY_NUMLOCK_STATE "numlock-state" #define KEY_CAPSLOCK_STATE "capslock-state" #define KEY_NUMLOCK_REMEMBER "remember-numlock-state" typedef enum { NUMLOCK_STATE_OFF = 0, NUMLOCK_STATE_ON = 1, NUMLOCK_STATE_UNKNOWN = 2 } NumLockState; static void numlock_set_xkb_state (NumLockState new_state); static void capslock_set_xkb_state(gboolean lock_state); KeyboardManager *KeyboardManager::mKeyboardManager = nullptr; KeyboardXkb *KeyboardManager::mKeyXkb = nullptr; KeyboardManager::KeyboardManager(QObject * parent) { if (mKeyXkb == nullptr) mKeyXkb = new KeyboardXkb; settings = new QGSettings(USD_KEYBOARD_SCHEMA); stInstalled = true; time = new QTimer(this); const QByteArray id(UKCCOSD_SCHEMA); const QByteArray idd(KYCCOSD_SCHEMA); const QByteArray iid(KDSOSD_SCHEMA); ifaceScreenSaver = new QDBusInterface("org.ukui.ScreenSaver", \ "/", \ "org.ukui.ScreenSaver", \ QDBusConnection::sessionBus()); if (QGSettings::isSchemaInstalled(id)){ ksettings = new QGSettings(id); } else if (QGSettings::isSchemaInstalled(idd)){ ksettings = new QGSettings(idd); } else if (QGSettings::isSchemaInstalled(iid)){ ksettings = new QGSettings(iid); } else { stInstalled = false; } m_statusWidget = new KeyboardWidget(); } KeyboardManager::~KeyboardManager() { if (mKeyXkb) { delete mKeyXkb; mKeyXkb = nullptr; } if (settings) { delete settings; settings = nullptr; } if (time) { delete time; time = nullptr; } if (m_statusWidget) { delete m_statusWidget; m_statusWidget = nullptr; } if (ksettings) { delete ksettings; ksettings = nullptr; } } KeyboardManager *KeyboardManager::KeyboardManagerNew() { if (nullptr == mKeyboardManager) mKeyboardManager = new KeyboardManager(nullptr); return mKeyboardManager; } bool KeyboardManager::Start() { USD_LOG(LOG_DEBUG,"-- Keyboard Start Manager --"); connect(time,SIGNAL(timeout()),this,SLOT(start_keyboard_idle_cb())); time->start(1500); return true; } void KeyboardManager::Stop() { USD_LOG(LOG_DEBUG,"-- Keyboard Stop Manager --"); old_state = 0; numlock_set_xkb_state((NumLockState)old_state); capslock_set_xkb_state(FALSE); // mKeyXkb->usd_keyboard_xkb_shutdown (); } #ifdef HAVE_X11_EXTENSIONS_XF86MISC_H static gboolean xfree86_set_keyboard_autorepeat_rate(int delay, int rate) { gboolean res = FALSE; int event_base_return; int error_base_return; if (XF86MiscQueryExtension (GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), &event_base_return, &error_base_return) == True) { /* load the current settings */ XF86MiscKbdSettings kbdsettings; XF86MiscGetKbdSettings (GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), &kbdsettings); /* assign the new values */ kbdsettings.delay = delay; kbdsettings.rate = rate; XF86MiscSetKbdSettings (GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), &kbdsettings); res = TRUE; } return res; } #endif /* HAVE_X11_EXTENSIONS_XF86MISC_H */ void numlock_xkb_init (KeyboardManager *manager) { Display *dpy = UsdBaseClass::getQx11Info(); gboolean have_xkb; int opcode, error_base, major, minor; have_xkb = XkbQueryExtension (dpy, &opcode, &manager->xkb_event_base, &error_base, &major, &minor) && XkbUseExtension (dpy, &major, &minor); if (have_xkb) { XkbSelectEventDetails (dpy, XkbUseCoreKbd, XkbStateNotifyMask, XkbModifierLockMask, XkbModifierLockMask); } else { qWarning ("XKB extension not available"); } manager->have_xkb = have_xkb; } static NumLockState numlock_get_settings_state (QGSettings *settings) { int curr_state; curr_state = settings->getEnum(KEY_NUMLOCK_STATE); return (NumLockState)curr_state; } static void capslock_set_xkb_state(gboolean lock_state) { unsigned int caps_mask; Display *dpy = UsdBaseClass::getQx11Info(); caps_mask = XkbKeysymToModifiers (dpy, XK_Caps_Lock); XkbLockModifiers (dpy, XkbUseCoreKbd, caps_mask, lock_state ? caps_mask : 0); XSync (dpy, FALSE); } static unsigned numlock_NumLock_modifier_mask (void) { Display *dpy = UsdBaseClass::getQx11Info(); return XkbKeysymToModifiers (dpy, XK_Num_Lock); } static void numlock_set_xkb_state (NumLockState new_state) { unsigned int num_mask; Display *dpy = UsdBaseClass::getQx11Info(); if (new_state != NUMLOCK_STATE_ON && new_state != NUMLOCK_STATE_OFF) return; num_mask = numlock_NumLock_modifier_mask (); XkbLockModifiers (dpy, XkbUseCoreKbd, num_mask, new_state ? num_mask : 0); } void apply_bell (KeyboardManager *manager) { QGSettings *settings; XKeyboardControl kbdcontrol; bool click; int bell_volume; int bell_pitch; int bell_duration; char *volume_string; QString volume_strings; int click_volume; Display *dpy = UsdBaseClass::getQx11Info(); settings = manager->settings; click = settings->get(KEY_CLICK).toBool(); click_volume = settings->get(KEY_CLICK_VOLUME).toInt(); bell_pitch = settings->get(KEY_BELL_PITCH).toInt(); bell_duration = settings->get(KEY_BELL_DURATION).toInt(); volume_strings = settings->get(KEY_BELL_MODE).toChar(); volume_string = volume_strings.toLatin1().data(); bell_volume = (volume_string && !strcmp (volume_string, "on")) ? 50 : 0; /* as percentage from 0..100 inclusive */ if (click_volume < 0) { click_volume = 0; } else if (click_volume > 100) { click_volume = 100; } kbdcontrol.key_click_percent = click ? click_volume : 0; kbdcontrol.bell_percent = bell_volume; kbdcontrol.bell_pitch = bell_pitch; kbdcontrol.bell_duration = bell_duration; try { XChangeKeyboardControl (dpy,KBKeyClickPercent | KBBellPercent | KBBellPitch | KBBellDuration, &kbdcontrol); XSync (dpy, FALSE); } catch (int x) { } } void apply_numlock (KeyboardManager *manager) { QGSettings *settings; bool rnumlock; Display *dpy = UsdBaseClass::getQx11Info(); qDebug ("Applying the num-lock settings"); settings = manager->settings; rnumlock = settings->get(KEY_NUMLOCK_REMEMBER).toBool(); manager->old_state = settings->getEnum(KEY_NUMLOCK_STATE); try { if(true == UsdBaseClass::isTablet() && rnumlock) { numlock_set_xkb_state (NUMLOCK_STATE_OFF); } else { numlock_set_xkb_state ((NumLockState)manager->old_state); } XSync (dpy, FALSE); } catch (int x) { } } static gboolean xkb_set_keyboard_autorepeat_rate(int delay, int rate) { int interval = (rate <= 0) ? 1000000 : 1000/rate; Display *dpy = UsdBaseClass::getQx11Info(); if (delay <= 0) { delay = 1; } return XkbSetAutoRepeatRate(dpy, XkbUseCoreKbd, delay, interval); } void apply_repeat (KeyboardManager *manager) { bool repeat; int rate; int delay; Display *dpy = UsdBaseClass::getQx11Info(); repeat = manager->settings->get(KEY_REPEAT).toBool(); rate = manager->settings->get(KEY_RATE).toInt(); delay = manager->settings->get(KEY_DELAY).toInt(); try { if (repeat) { gboolean rate_set = FALSE; XAutoRepeatOn (dpy); /* Use XKB in preference */ rate_set = xkb_set_keyboard_autorepeat_rate (delay, rate); if (!rate_set) { USD_LOG(LOG_DEBUG,"Neither XKeyboard not Xfree86's keyboard extensions are available,\n" "no way to support keyboard autorepeat rate settings"); } } else { XAutoRepeatOff (dpy); } XSync (dpy, FALSE); } catch (int x) { USD_LOG(LOG_ERR,"ERROR"); } } void KeyboardManager::apply_settings (QString keys) { /** * Fix by HB* system reboot but rnumlock not available; **/ char *key; if(!keys.isEmpty()) key = keys.toLatin1().data(); else key=NULL; #ifdef HAVE_X11_EXTENSIONS_XKB_H bool rnumlock; rnumlock = settings->get(KEY_NUMLOCK_REMEMBER).toBool(); if (rnumlock == 0 || key == NULL) { if (have_xkb && rnumlock) { numlock_set_xkb_state (numlock_get_settings_state (settings)); capslock_set_xkb_state(settings->get(KEY_CAPSLOCK_STATE).toBool()); USD_LOG(LOG_DEBUG,"apply keyboard ok."); } } #endif /* HAVE_X11_EXTENSIONS_XKB_H */ if (keys.compare(QString::fromLocal8Bit(KEY_CLICK)) == 0|| keys.compare(QString::fromLocal8Bit(KEY_CLICK_VOLUME)) == 0 || keys.compare(QString::fromLocal8Bit(KEY_BELL_PITCH)) == 0 || keys.compare(QString::fromLocal8Bit(KEY_BELL_DURATION)) == 0 || keys.compare(QString::fromLocal8Bit(KEY_BELL_MODE)) == 0) { USD_LOG(LOG_DEBUG,"Bell setting '%s' changed, applying bell settings", key); apply_bell (this); } else if (keys.compare(QString::fromLocal8Bit(KEY_NUMLOCK_REMEMBER)) == 0) { USD_LOG(LOG_DEBUG,"Remember Num-Lock state '%s' changed, applying num-lock settings", key); apply_numlock (this); } else if (keys.compare(QString::fromLocal8Bit(KEY_NUMLOCK_STATE)) == 0) { USD_LOG(LOG_DEBUG,"Num-Lock state '%s' changed, will apply at next startup", key); } else if (keys.compare(QString::fromLocal8Bit(KEY_REPEAT)) == 0 || keys.compare(QString::fromLocal8Bit(KEY_RATE)) == 0 || keys.compare(QString::fromLocal8Bit(KEY_DELAY)) == 0) { USD_LOG(LOG_DEBUG,"Key repeat setting '%s' changed, applying key repeat settings", key); apply_repeat (this); } else { // USD_LOG(LOG_DEBUG,"Unhandled settings change, key '%s'", key); } } void KeyboardManager::usd_keyboard_manager_apply_settings (KeyboardManager *manager) { apply_settings(NULL); } void KeyboardManager::XkbEventsFilter(int keyCode) { NumLockState numlockState; bool capsLockState; if (keyCode != 77 && keyCode != 66) { return ; } if (isCloudDesktopTop()) { return; } Display *display = XOpenDisplay(NULL); if(keyCode == 77) { unsigned int numLockedMods; XkbGetIndicatorState(display, XkbUseCoreKbd, &numLockedMods); if(numLockedMods == 2 || numLockedMods==3) { numlockState = NUMLOCK_STATE_ON; } else { numlockState = NUMLOCK_STATE_OFF; } USD_LOG(LOG_ERR,"old_state=%d,locked_mods=%d,numlockState=%d", old_state,numLockedMods,numlockState); if (numlockState != old_state) { settings->setEnum(KEY_NUMLOCK_STATE, numlockState); old_state = numlockState; } if (stInstalled && !ksettings->get(SHOW_TIP_KEY).toBool()){ USD_LOG(LOG_DEBUG,"MediaKey Tip is Closed\n"); XCloseDisplay (display); return; } if (ifaceScreenSaver->isValid()){ QDBusReplyreply = ifaceScreenSaver->call("GetLockState"); if (reply.isValid()){ if (reply.value()){ qWarning("MediaKey Tip is Closed because ScreenLock\n"); XCloseDisplay (display); return; } } } if(numlockState) { m_statusWidget->setIcons("ukui-numlock-on-symbolic"); m_statusWidget->showWidget(); } else { m_statusWidget->setIcons("ukui-numlock-off-symbolic"); m_statusWidget->showWidget(); } }else if(keyCode == 66) { unsigned int capsLockedMods; XkbGetIndicatorState(display, XkbUseCoreKbd, &capsLockedMods); if(capsLockedMods == 1 || capsLockedMods == 3){ settings->set(KEY_CAPSLOCK_STATE,true); capsLockState = true; } else{ settings->set(KEY_CAPSLOCK_STATE,false); capsLockState = false; } if (stInstalled && !ksettings->get(SHOW_TIP_KEY).toBool()){ qWarning("MediaKey Tip is Closed\n"); XCloseDisplay (display); return; } if (ifaceScreenSaver->isValid()){ QDBusReplyreply = ifaceScreenSaver->call("GetLockState"); if (reply.isValid()){ if (reply.value()){ qWarning("MediaKey Tip is Closed because ScreenLock\n"); XCloseDisplay (display); return; } } } if(capsLockState) { m_statusWidget->setIcons("ukui-capslock-on-symbolic"); m_statusWidget->showWidget(); } else { m_statusWidget->setIcons("ukui-capslock-off-symbolic"); m_statusWidget->showWidget(); } } XCloseDisplay (display); } bool KeyboardManager::isCloudDesktopTop() { QDBusInterface kwinInterface("org.ukui.KWin", "/KWin", "org.ukui.KWin", QDBusConnection::sessionBus()); if(!kwinInterface.isValid()) { USD_LOG(LOG_DEBUG,"interface is unvalid"); return false; } QDBusReply replay = kwinInterface.call("isDisableGlobalShortcuts"); if(replay.isValid()) { USD_LOG(LOG_DEBUG,"isDisableGlobalShortcuts is valid :%d",replay.value()); return replay.value(); } USD_LOG(LOG_DEBUG,"isDisableGlobalShortcuts is unvalid"); return false; } void KeyboardManager::numlock_install_xkb_callback () { if (!have_xkb) return; // connect(XEventMonitor::instance(), static_cast(&XEventMonitor::keyRelease), // this, &KeyboardManager::XkbEventsFilter); connect(XEventMonitor::instance(), SIGNAL(keyRelease(int)), this, SLOT(XkbEventsFilter(int))); } void KeyboardManager::start_keyboard_idle_cb () { time->stop(); have_xkb = 0; settings->set(KEY_NUMLOCK_REMEMBER,TRUE); XEventMonitor::instance()->start(); /* Essential - xkb initialization should happen before */ mKeyXkb->usd_keyboard_xkb_init (this); #ifdef HAVE_X11_EXTENSIONS_XKB_H numlock_xkb_init (this); #endif /* HAVE_X11_EXTENSIONS_XKB_H */ /* apply current settings before we install the callback */ usd_keyboard_manager_apply_settings (this); // QObject::connect(settings, &QGSettings::changed, this, &KeyboardManager::apply_settings); connect(settings,SIGNAL(changed(QString)),this,SLOT(apply_settings(QString))); #ifdef HAVE_X11_EXTENSIONS_XKB_H numlock_install_xkb_callback(); #endif /* HAVE_X11_EXTENSIONS_XKB_H */ apply_repeat (this); apply_numlock (this); apply_bell(this); } ukui-settings-daemon/plugins/keyboard/keyboard-widget.cpp0000664000175000017500000002172615167655063022650 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "keyboard-widget.h" #include "ui_keyboardwidget.h" #include #include #include #include #include "clib-syslog.h" #include #include #include #include #include #include #include #include #include "usd_base_class.h" #include "ukuistylehelper/ukuistylehelper.h" #include "windowmanager/windowmanager.h" #define QT_THEME_SCHEMA "org.ukui.style" #define PANEL_SCHEMA "org.ukui.panel.settings" #define PANEL_SIZE_KEY "panelsize" #define DEFAULT_LOCALE_ICON_NAME ":/ukui_res/ukui/" #define INTEL_LOCALE_ICON_NAME ":/ukui_res/ukui_intel/" KeyboardWidget::KeyboardWidget(QWidget *parent) : QWidget(parent), ui(new Ui::KeyboardWidget) { ui->setupUi(this); initWidgetInfo(); } KeyboardWidget::~KeyboardWidget() { if (ui) { delete ui; ui = nullptr; } } void KeyboardWidget::initWidgetInfo() { setWindowFlags(Qt::FramelessWindowHint | Qt::Tool | Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint | Qt::Popup); setAttribute(Qt::WA_TranslucentBackground, true); setAutoFillBackground(true); if(UsdBaseClass::isTablet()) { m_LocalIconPath = INTEL_LOCALE_ICON_NAME; } else { m_LocalIconPath = DEFAULT_LOCALE_ICON_NAME; } m_styleSettings = new QGSettings(QT_THEME_SCHEMA); connect(m_styleSettings,SIGNAL(changed(const QString&)), this,SLOT(onStyleChanged(const QString&))); m_timer = new QTimer(this); connect(m_timer,SIGNAL(timeout()),this,SLOT(timeoutHandle())); connect(QApplication::primaryScreen(), &QScreen::geometryChanged, this, &KeyboardWidget::geometryChangedHandle); connect(static_cast(QCoreApplication::instance()), &QApplication::primaryScreenChanged, this, &KeyboardWidget::geometryChangedHandle); this->setFixedSize(92,92); m_frame = new QFrame(this); m_frame->setFixedSize(QSize(72,72)); m_frame->move(10,10); m_btnStatus = new QLabel(m_frame); m_btnStatus->setFixedSize(QSize(48,48)); m_btnStatus->move((m_frame->width() - m_btnStatus->width())/2,(m_frame->height() - m_btnStatus->height())/2); geometryChangedHandle(); } void KeyboardWidget::timeoutHandle() { m_timer->stop(); hide(); } void KeyboardWidget::showWidget() { show(); geometryChangedHandle(); QWindow* window = this->windowHandle(); if (window) { kdk::WindowManager::setSkipSwitcher(window, true); kdk::WindowManager::setSkipTaskBar(window, true); } if (false == UsdBaseClass::isWayland()) { KX11Extras::setType(this->winId(),NET::Notification); } repaintWidget(); m_timer->start(2500); } void KeyboardWidget::setIcons(QString icon) { m_iconName = icon; } void KeyboardWidget::geometryChangedHandle() { int x=QApplication::primaryScreen()->geometry().x(); int y=QApplication::primaryScreen()->geometry().y(); int width = QApplication::primaryScreen()->size().width(); int height = QApplication::primaryScreen()->size().height(); int pSize = 0; const QByteArray id(PANEL_SCHEMA); if (QGSettings::isSchemaInstalled(id)){ QGSettings * settings = new QGSettings(id); pSize = settings->get(PANEL_SIZE_KEY).toInt(); delete settings; settings = nullptr; } int ax,ay; ax = x+width - this->width() - 200; ay = y+height - this->height() - pSize - 8; setGeometry(QRect(ax, ay, this->width(), this->height())); kdk::WindowManager::setGeometry(this->windowHandle(),QRect(ax, ay, this->width(), this->height())); } void KeyboardWidget::onStyleChanged(const QString& key) { Q_UNUSED(key) if(!this->isHidden()) { hide(); repaintWidget(); show(); } } QPixmap KeyboardWidget::drawLightColoredPixmap(const QPixmap &source, const QString &style) { int value = 255; if(style == "ukui-light") { value = 0; } QColor gray(255,255,255); QColor standard (0,0,0); QImage img = source.toImage(); for (int x = 0; x < img.width(); x++) { for (int y = 0; y < img.height(); y++) { auto color = img.pixelColor(x, y); if (color.alpha() > 0) { if (qAbs(color.red()-gray.red())<20 && qAbs(color.green()-gray.green())<20 && qAbs(color.blue()-gray.blue())<20) { color.setRed(value); color.setGreen(value); color.setBlue(value); img.setPixelColor(x, y, color); } else { color.setRed(value); color.setGreen(value); color.setBlue(value); img.setPixelColor(x, y, color); } } } } return QPixmap::fromImage(img); } void KeyboardWidget::repaintWidget() { if(m_styleSettings->get("style-name").toString() == "ukui-light"){ setPalette(QPalette(QColor("#F5F5F5")));//设置窗口背景 } else{ setPalette(QPalette(QColor("#232426")));//设置窗口背景色 } QString m_LocalIconName; m_LocalIconName = m_LocalIconPath + m_iconName + QString(".svg"); QPixmap m_pixmap = QIcon::fromTheme(m_iconName,QIcon(m_LocalIconName)).pixmap(QSize(48,48)); m_btnStatus->setPixmap(drawLightColoredPixmap(m_pixmap,m_styleSettings->get("style-name").toString())); } void KeyboardWidget::resizeEvent(QResizeEvent* event) { // m_btnStatus->move((width() - m_btnStatus->width())/2,(height() - m_btnStatus->height())/2); QWidget::resizeEvent(event); } double KeyboardWidget::getGlobalOpacity() { double transparency=0.0; if(QGSettings::isSchemaInstalled(QString("org.ukui.control-center.personalise").toLocal8Bit())) { QGSettings gsetting(QString("org.ukui.control-center.personalise").toLocal8Bit()); if(gsetting.keys().contains(QString("transparency"))) transparency=gsetting.get("transparency").toDouble(); } return transparency; } QT_BEGIN_NAMESPACE extern void qt_blurImage(QImage &blurImage, qreal radius, bool quality, int transposed); QT_END_NAMESPACE void KeyboardWidget::paintEvent(QPaintEvent *event) { QPainter painter(this); QPainterPath rectPath; rectPath.addRoundedRect(this->rect().adjusted(10, 10, -10, -10), 12, 12); // 画一个黑底 QPixmap pixmap(this->rect().size()); pixmap.fill(Qt::transparent); QPainter pixmapPainter(&pixmap); pixmapPainter.setRenderHint(QPainter::Antialiasing); pixmapPainter.setPen(Qt::transparent); pixmapPainter.setBrush(this->palette().base()); pixmapPainter.setCompositionMode(QPainter::CompositionMode_Difference); pixmapPainter.setOpacity(0.16); pixmapPainter.drawPath(rectPath); pixmapPainter.end(); // 模糊这个黑底 QImage img = pixmap.toImage(); qt_blurImage(img, 8, false, false); // 挖掉中心 pixmap = QPixmap::fromImage(img); QPainter pixmapPainter2(&pixmap); pixmapPainter2.setRenderHint(QPainter::Antialiasing); pixmapPainter2.setCompositionMode(QPainter::CompositionMode_Clear); pixmapPainter2.setPen(Qt::transparent); pixmapPainter2.setBrush(Qt::transparent); pixmapPainter2.drawPath(rectPath); // 绘制阴影 painter.drawPixmap(this->rect(), pixmap, pixmap.rect()); //绘制描边 QPainterPath linePath; linePath.addRoundedRect(QRect(9,9,m_frame->width()+1,m_frame->height()+1),12,12); painter.setCompositionMode(QPainter::CompositionMode_Difference); painter.setPen(this->palette().color(QPalette::ColorRole::BrightText)); painter.setRenderHint(QPainter::Antialiasing); painter.setBrush(Qt::transparent); painter.setOpacity(0.15); painter.drawPath(linePath); //毛玻璃 qreal opacity = getGlobalOpacity(); painter.setRenderHint(QPainter::Antialiasing); painter.setPen(Qt::transparent); painter.setBrush(this->palette().base()); painter.setOpacity(opacity); painter.drawPath(linePath); KWindowEffects::enableBlurBehind(this->windowHandle(), true, QRegion(linePath.toFillPolygon().toPolygon())); QWidget::paintEvent(event); } ukui-settings-daemon/plugins/keyboard/keyboard-manager.h0000775000175000017500000000546515167655063022451 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef KEYBOARDMANAGER_H #define KEYBOARDMANAGER_H #include #include #include #include #include #include #include #include #include #include #include "xeventmonitor.h" #include "keyboard-xkb.h" #include "keyboard-widget.h" #include "usd_base_class.h" #include "plugin-manager-interface.h" #ifdef HAVE_X11_EXTENSIONS_XF86MISC_H #include #endif #ifdef HAVE_X11_EXTENSIONS_XKB_H #include #include #endif class KeyboardXkb; class KeyboardManager : public ManagerInterface { Q_OBJECT private: KeyboardManager()=delete; KeyboardManager(KeyboardManager&)=delete; KeyboardManager&operator=(const KeyboardManager&)=delete; KeyboardManager(QObject *parent = nullptr); bool isCloudDesktopTop(); public: ~KeyboardManager(); static KeyboardManager *KeyboardManagerNew(); virtual bool Start(); virtual void Stop(); void usd_keyboard_manager_apply_settings(KeyboardManager *manager); void numlock_install_xkb_callback (); public Q_SLOTS: void start_keyboard_idle_cb (); void apply_settings (QString); void XkbEventsFilter(int keyCode); private: friend void numlock_xkb_init (KeyboardManager *manager); friend void apply_bell (KeyboardManager *manager); friend void apply_numlock (KeyboardManager *manager); friend void apply_repeat (KeyboardManager *manager); friend void numlock_install_xkb_callback (KeyboardManager *manager); private: QTimer *time; static KeyboardManager *mKeyboardManager; static KeyboardXkb *mKeyXkb; bool have_xkb; int xkb_event_base; QGSettings *settings; QGSettings *ksettings; int old_state; bool stInstalled; KeyboardWidget* m_statusWidget; QDBusInterface * ifaceScreenSaver; }; #endif // KEYBOARDMANAGER_H ukui-settings-daemon/plugins/keyboard/keyboardwidget.ui0000664000175000017500000000061615167654733022424 0ustar fengfeng KeyboardWidget 0 0 400 300 Form ukui-settings-daemon/plugins/README.md0000664000175000017500000000000015167654733016523 0ustar fengfengukui-settings-daemon/plugins/housekeeping/0000775000175000017500000000000015167655063017741 5ustar fengfengukui-settings-daemon/plugins/housekeeping/usd-ldsm-dialog.ui0000664000175000017500000000065415167654733023275 0ustar fengfeng LdsmDialog 0 0 800 600 LdsmDialog ukui-settings-daemon/plugins/housekeeping/housekeeping.pro0000664000175000017500000000202015167655063023143 0ustar fengfengQT += gui QT += core widgets TARGET = housekeeping TEMPLATE = lib DEFINES += HOUSEKEPPING_LIBRARY MODULE_NAME=\\\"housekeeping\\\" CONFIG += c++20 no_keywords link_pkgconfig plugin DEFINES += QT_DEPRECATED_WARNINGS include($$PWD/../../common/common.pri) PKGCONFIG += gtk+-3.0 glib-2.0 harfbuzz gmodule-2.0 \ libxklavier gobject-2.0 gio-2.0 gio-unix-2.0 \ cairo cairo-gobject INCLUDEPATH += \ -I $$PWD/../.. \ -I ukui-settings-daemon/ SOURCES += \ housekeeping-manager.cpp \ housekeeping-plugin.cpp \ ldsm-trash-empty.cpp \ usd-disk-space.cpp \ usd-ldsm-dialog.cpp HEADERS += \ housekeeping-manager.h \ housekeeping-plugin.h \ ldsm-trash-empty.h \ usd-disk-space.h \ usd-ldsm-dialog.h housekeeping_lib.path = $${PLUGIN_INSTALL_DIRS} housekeeping_lib.files = $$OUT_PWD/libhousekeeping.so INSTALLS += housekeeping_lib FORMS += \ ldsm-trash-empty.ui \ usd-ldsm-dialog.ui RESOURCES += \ trash_empty.qrc ukui-settings-daemon/plugins/housekeeping/ldsm-trash-empty.cpp0000664000175000017500000001553615167655063023671 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "ldsm-trash-empty.h" #include "ui_ldsm-trash-empty.h" #include #include #include #include #include #include // #include #include #include #include #include #include #include "clib-syslog.h" LdsmTrashEmpty::LdsmTrashEmpty(QWidget *parent) : QDialog(parent), ui(new Ui::LdsmTrashEmpty) { ui->setupUi(this); m_fontSetting = new QGSettings(UKUI_STYLE_SCHEMA, QByteArray(), this); connect(m_fontSetting, SIGNAL(changed(QString)), this, SLOT(updateText(QString))); windowLayoutInit(); connectEvent(); } LdsmTrashEmpty::~LdsmTrashEmpty() { if (ui) { delete ui; ui = nullptr; } if (first_text) { delete first_text; first_text = nullptr; } if (second_text) { delete second_text; second_text = nullptr; } if (trash_empty) { delete trash_empty; trash_empty = nullptr; } if (cancel) { delete cancel; cancel = nullptr; } } void LdsmTrashEmpty::windowLayoutInit() { QFont font; Qt::WindowFlags flags=Qt::Dialog; flags |=Qt::WindowMinMaxButtonsHint; flags |=Qt::WindowCloseButtonHint; QRect desk_rect; if (QGuiApplication::screenAt(QCursor::pos()) == nullptr) { desk_rect = QGuiApplication::primaryScreen()->geometry(); } else { desk_rect = QGuiApplication::screenAt(QCursor::pos())->geometry(); } setWindowFlags(flags); setAttribute(Qt::WA_AlwaysShowToolTips, true); setFixedSize(650,180); setWindowTitle(tr("Emptying the trash")); setWindowIcon(QIcon::fromTheme("user-trash-full")); int dialog_width=width(); int dialog_height=height(); int rect_width=desk_rect.width(); int rect_height=desk_rect.height(); this->move((rect_width-dialog_width)/2+desk_rect.left(),(rect_height-dialog_height)/2+desk_rect.top()); first_text=new QLabel(this); second_text=new QLabel(this); trash_empty=new QPushButton(this); cancel=new QPushButton(this); second_text_area = new QScrollArea(this); first_text->setProperty("Name","first_text_label"); second_text->setProperty("Name","second_text_label"); trash_empty->setProperty("Name","trash_empty_button"); cancel->setProperty("Name","cancel_button"); first_text->setGeometry(66,20,560,30); font.setBold(true); first_text->setFont(font); first_text->setText(tr("Empty all of the items from the trash?")); second_text_area->setGeometry(66,50,560,30*2); second_text_area->setWidget(second_text); second_text_area->setFrameShape(QFrame::NoFrame); second_text_area->setWidgetResizable(true); second_text->setGeometry(66,50,560,30*2); second_text->setWordWrap(true); second_text->setAlignment(Qt::AlignLeft); second_text->setText(tr("If you choose to empty the trash, all items in it will be permanently lost." \ "Please note that you can also delete them separately.")); cancel->setGeometry(dialog_width-110,dialog_height-55,96,36); cancel->setText(tr("cancel")); trash_empty->setGeometry(dialog_width-240,dialog_height-55,96,36); trash_empty->setText(tr("Empty Trash")); updateText(""); } void LdsmTrashEmpty::usdLdsmTrashEmpty() { this->exec(); } void LdsmTrashEmpty::connectEvent() { connect(trash_empty,SIGNAL(clicked()),this,SLOT(checkButtonTrashEmpty())); connect(cancel,SIGNAL(clicked()),this,SLOT(checkButtonCancel())); } void LdsmTrashEmpty::deleteContents(const QString path) { QDir dir(path); QFileInfoList fileList; QFileInfo curFile; if(!dir.exists()) return; fileList=dir.entryInfoList(QDir::Files|QDir::Dirs|QDir::Readable|QDir::Writable| QDir::Hidden|QDir::NoDotAndDotDot,QDir::Name); while(fileList.size()>0) { int infoNum=fileList.size(); for(int i=infoNum-1;i>=0;i--) { curFile=fileList[i]; if(curFile.isFile()) { QFile fileTemp(curFile.filePath()); fileTemp.remove(); } if(curFile.isDir()) { QDir dirTemp(curFile.filePath()); dirTemp.removeRecursively(); } fileList.removeAt(i); } } } void LdsmTrashEmpty::updateText(QString key) { USD_LOG(LOG_DEBUG,"get key:%s",key.toLatin1().data()); resetFont(trash_empty, tr("Empty Trash")); resetFont(first_text, tr("Empty all of the items from the trash?")); resetFont(cancel, tr("cancel")); } void LdsmTrashEmpty::resetFont(QWidget *pWid, QString str) { QPushButton *pBtn = nullptr; QLabel *pLbl = nullptr; int fontWidth = 0; int btnWidth = 0; USD_LOG(LOG_DEBUG,"get Wid:%s",pWid->property("Name").toString().toLatin1().data()); if (pWid->property("Name").toString().contains("button")) { pBtn = static_cast(pWid); } else if (pWid->property("Name").toString().contains("label")) { pLbl = static_cast(pWid); } else { return; } QFontMetrics qFm(pWid->font()); fontWidth = qFm.horizontalAdvance(str); if (pBtn != nullptr) { btnWidth = pBtn->width() - 7; if (fontWidth >= btnWidth) { QString elideNote = qFm.elidedText(pBtn->text(), Qt::ElideRight, btnWidth); pBtn->setText(elideNote); pBtn->setToolTip(str); } else { pBtn->setText(str); pBtn->setToolTip(""); } } else { btnWidth = pLbl->width() - 7; if (fontWidth >= btnWidth) { QString elideNote = qFm.elidedText(pLbl->text(), Qt::ElideRight, btnWidth); pLbl->setText(elideNote); pLbl->setToolTip(str); } else { pLbl->setText(str); pLbl->setToolTip(""); } } } void LdsmTrashEmpty::checkButtonTrashEmpty() { QString trash_path; trash_path=QDir::homePath()+"/.local/share/Trash"; deleteContents(trash_path); this->accept(); } void LdsmTrashEmpty::checkButtonCancel() { this->accept(); } ukui-settings-daemon/plugins/housekeeping/usd-ldsm-dialog.h0000664000175000017500000000506315167655063023103 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef USDLDSMDIALOG_H #define USDLDSMDIALOG_H #include #include #include #include #include #include #include "QGSettings/qgsettings.h" #define SETTINGS_SCHEMA "org.ukui.SettingsDaemon.plugins.housekeeping" #define SETTINGS_IGNORE_PATHS "ignore-paths" #define LDSM_DIALOG_IGNORE 10 #define LDSM_DIALOG_RESPONSE_ANALYZE 30 #define LDSM_DIALOG_RESPONSE_EMPTY_TRASH 40 QT_BEGIN_NAMESPACE namespace Ui { class LdsmDialog; } QT_END_NAMESPACE class LdsmDialog : public QDialog { Q_OBJECT public: LdsmDialog(QWidget *parent = nullptr); LdsmDialog(bool other_usable_partitions,bool other_partitions,bool display_baobab,bool has_trash, long space_remaining,QString partition_name,QString mount_path, QWidget *parent = nullptr); ~LdsmDialog(); private: Ui::LdsmDialog *ui; QLabel* picture_label; QLabel* primary_label; QScrollArea *scroll_area; QCheckBox* ignore_check_button; QPushButton* trash_empty = nullptr; QPushButton* ignore_button; QPushButton* analyze_button; QDialog* m_dialog; QGSettings* m_fontSetting; bool other_usable_partitions; bool other_partitions; bool has_trash; long space_remaining; /*char *partition_name; char *mount_path;*/ QString partition_name; QString mount_path; public: void checkButtonClicked(int); void checkButtonIgnore (); void checkButtonAnalyze (); void checkButtonTrashEmpty(); public Q_SLOTS: void updateText(QString key); void resetFont(QWidget *pWid, QString str); private: void windowLayoutInit(bool display_baobab); QString getPrimaryText(); QString getCheckButtonText(); void allConnectEvent(bool display_baobab); }; #endif // USDLDSMDIALOG_H ukui-settings-daemon/plugins/housekeeping/housekeeping-manager.h0000664000175000017500000000320615167655063024211 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef HOUSEKEEPINGMANAGER_H #define HOUSEKEEPINGMANAGER_H #include #include #include #include #include #include #include "usd-disk-space.h" extern "C"{ #include "config.h" } class HousekeepingManager : public QObject { Q_OBJECT public: HousekeepingManager(); HousekeepingManager(HousekeepingManager&)=delete; ~HousekeepingManager(); bool HousekeepingManagerStart(); void HousekeepingManagerStop(); public: void settings_changed_callback(QString); void do_cleanup_soon(); void purge_thumbnail_cache (); void do_cleanup (); void do_cleanup_once (); private: static HousekeepingManager *mHouseManager; static DiskSpace *mDisk; QTimer *long_term_handler; QTimer *short_term_handler; QGSettings *settings; }; #endif // HOUSEKEEPINGMANAGER_H ukui-settings-daemon/plugins/housekeeping/ldsm-trash-empty.h0000664000175000017500000000321315167655063023323 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef LDSMTRASHEMPTY_H #define LDSMTRASHEMPTY_H #include #include #include #include #include #include "QGSettings/qgsettings.h" namespace Ui { class LdsmTrashEmpty; } class LdsmTrashEmpty : public QDialog { Q_OBJECT public: explicit LdsmTrashEmpty(QWidget *parent = nullptr); ~LdsmTrashEmpty(); void usdLdsmTrashEmpty(); public Q_SLOTS: void checkButtonCancel(); void checkButtonTrashEmpty(); void updateText(QString key); void resetFont(QWidget *pWid, QString str); private: Ui::LdsmTrashEmpty *ui; QLabel *first_text; QLabel *second_text; QScrollArea *second_text_area; QPushButton *trash_empty; QPushButton *cancel; QGSettings* m_fontSetting; private: void windowLayoutInit(); void connectEvent(); void deleteContents(const QString path); }; #endif // LDSMTRASHEMPTY_H ukui-settings-daemon/plugins/housekeeping/ldsm-trash-empty.ui0000664000175000017500000000061315167654733023515 0ustar fengfeng LdsmTrashEmpty 0 0 517 326 Dialog ukui-settings-daemon/plugins/housekeeping/usd-ldsm-dialog.cpp0000664000175000017500000002357015167655063023441 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "usd-ldsm-dialog.h" #include "ui_usd-ldsm-dialog.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "clib-syslog.h" #include "usd_global_define.h" LdsmDialog::LdsmDialog(QWidget *parent) : QDialog(parent) , ui(new Ui::LdsmDialog) { ui->setupUi(this); } LdsmDialog::LdsmDialog(bool other_usable_partitions,bool other_partitions,bool display_baobab,bool has_trash, long space_remaining,QString partition_name,QString mount_path, QWidget *parent) : QDialog(parent) , ui(new Ui::LdsmDialog) { ui->setupUi(this); this->other_usable_partitions=other_usable_partitions; this->other_partitions=other_partitions; this->has_trash=has_trash; this->space_remaining=space_remaining; this->partition_name=partition_name; this->mount_path=mount_path; this->analyze_button=nullptr; m_fontSetting = new QGSettings(UKUI_STYLE_SCHEMA, QByteArray(), this); connect(m_fontSetting, SIGNAL(changed(QString)), this, SLOT(updateText(QString))); windowLayoutInit(display_baobab); allConnectEvent(display_baobab); } LdsmDialog::~LdsmDialog() { if (ui) { delete ui; ui = nullptr; } if (picture_label) { delete picture_label; picture_label = nullptr; } if (primary_label) { delete primary_label; primary_label = nullptr; } if (ignore_check_button) { delete ignore_check_button; ignore_check_button = nullptr; } if (ignore_button) { delete ignore_button; ignore_button = nullptr; } if(this->has_trash) { delete trash_empty; trash_empty = nullptr; } if(analyze_button) { delete analyze_button; analyze_button = nullptr; } } void LdsmDialog::windowLayoutInit(bool display_baobab) { QFont font; Qt::WindowFlags flags=Qt::Dialog; QRect desk_rect; if (QGuiApplication::screenAt(QCursor::pos()) == nullptr) { desk_rect = QGuiApplication::primaryScreen()->geometry(); } else { desk_rect = QGuiApplication::screenAt(QCursor::pos())->geometry(); } flags |=Qt::WindowMinMaxButtonsHint; flags |=Qt::WindowCloseButtonHint; setWindowFlags(flags); setAttribute(Qt::WA_AlwaysShowToolTips, true); setFixedSize(660,210); setWindowIcon(QIcon::fromTheme("dialog-warning")); int dialog_width=width(); int dialog_height=height(); int rect_width=desk_rect.width(); int rect_height=desk_rect.height(); setWindowTitle(tr("Low Disk Space")); this->move((rect_width-dialog_width)/2+desk_rect.left(),(rect_height-dialog_height)/2+desk_rect.top()); picture_label = new QLabel(this); primary_label = new QLabel(this); scroll_area = new QScrollArea(this); ignore_check_button = new QCheckBox(this); ignore_button=new QPushButton(this); picture_label->setProperty("Name", "picture_label"); primary_label->setProperty("Name", "primary_label"); scroll_area->setProperty("Name", "scroll_area"); scroll_area->setFrameShape(QFrame::NoFrame); ignore_check_button->setProperty("Name", "ignore_check_button"); ignore_button->setProperty("Name", "ignore_button"); //warning picture picture_label->setGeometry(20,40,32,32); picture_label->setAlignment(Qt::AlignCenter); picture_label->setStyleSheet(QString("border-image:url(../ldsm_dialog/warning.png);")); //warning information text scroll_area->setGeometry(50, 20, 560, 40*2); scroll_area->setWidget(primary_label); scroll_area->setWidgetResizable(true); primary_label->setGeometry(50, 20, 560, 40*2); primary_label->setWordWrap(true); primary_label->setAlignment(Qt::AlignLeft); primary_label->setText(getPrimaryText()); // primary_label->adjustSize(); //gsettings set box ignore_check_button->setGeometry(70,120,400,30); ignore_check_button->setText(getCheckButtonText()); ignore_button->setGeometry(dialog_width-110,dialog_height-55,96,36); ignore_button->setText(tr("Confirm")); if(this->has_trash){ trash_empty = new QPushButton(this); trash_empty->setProperty("Name", "trash_empty_button"); trash_empty->setGeometry(dialog_width-240,dialog_height-55,96,36); trash_empty->setText(tr("Empty Trash")); } if(display_baobab){ analyze_button = new QPushButton(this); analyze_button->setText(tr("Examine")); if(this->has_trash) analyze_button->setGeometry(dialog_width-320,dialog_height-55,96,36); else analyze_button->setGeometry(dialog_width-215,dialog_height-55,96,36); } updateText(""); } QString LdsmDialog::getPrimaryText() { char* free_space = g_format_size(space_remaining); return QString(tr("The remaining space of drive \"%1\" is less than %2, "\ "clear the garbage or move the data to another disk in time.")).arg(partition_name).arg(free_space); } QString LdsmDialog::getCheckButtonText() { return QString(tr("Messages that no longer remind this disk")); } void LdsmDialog::allConnectEvent(bool display_baobab) { connect(ignore_check_button, &QCheckBox::stateChanged, this, &LdsmDialog::checkButtonClicked); connect(ignore_button, &QPushButton::clicked, this, &LdsmDialog::checkButtonIgnore); if(has_trash) connect(trash_empty, &QPushButton::clicked, this, &LdsmDialog::checkButtonTrashEmpty); if(display_baobab) connect(analyze_button, &QPushButton::clicked, this, &LdsmDialog::checkButtonAnalyze); if(sender() == ignore_button) { USD_LOG(LOG_DEBUG,"Ignore button pressed!"); } else { USD_LOG(LOG_DEBUG,"Other button pressed!"); } } //update gsettings "ignore-paths" key contents bool update_ignore_paths(QList** ignore_paths,QString mount_path,bool ignore) { bool found=(*ignore_paths)->contains(mount_path.toLatin1().data()); if(ignore && found==false){ (*ignore_paths)->push_front(mount_path.toLatin1().data()); return true; } if(!ignore && found==true){ (*ignore_paths)->removeOne(mount_path.toLatin1().data()); return true; } return false; } /****************slots*********************/ void LdsmDialog::checkButtonIgnore() { done(LDSM_DIALOG_IGNORE); } void LdsmDialog::checkButtonTrashEmpty() { done(LDSM_DIALOG_RESPONSE_EMPTY_TRASH); } void LdsmDialog::updateText(QString key) { USD_LOG(LOG_DEBUG,"get key:%s",key.toLatin1().data()); if(has_trash) { resetFont(trash_empty, tr("Empty Trash")); } resetFont(ignore_button, tr("Confirm")); } void LdsmDialog::resetFont(QWidget *pWid, QString str) { QPushButton *pBtn = nullptr; QLabel *pLbl = nullptr; int fontWidth = 0; int btnWidth = 0; if (pWid->property("Name").toString().contains("button")) { pBtn = static_cast(pWid); } else if (pWid->property("Name").toString().contains("label")) { pLbl = static_cast(pWid); } else { return; } QFontMetrics qFm(pWid->font()); fontWidth = qFm.horizontalAdvance(str); if (pBtn != nullptr) { btnWidth = pBtn->width() - 7; if (fontWidth >= btnWidth) { QString elideNote = qFm.elidedText(pBtn->text(), Qt::ElideRight, btnWidth); pBtn->setText(elideNote); pBtn->setToolTip(str); } else { pBtn->setText(str); pBtn->setToolTip(""); } } else { btnWidth = pLbl->width() - 7; if (fontWidth >= btnWidth) { QString elideNote = qFm.elidedText(pLbl->text(), Qt::ElideRight, btnWidth); pLbl->setText(elideNote); pLbl->setToolTip(str); } else { pLbl->setText(str); pLbl->setToolTip(""); } } } void LdsmDialog::checkButtonAnalyze() { done(LDSM_DIALOG_RESPONSE_ANALYZE); } void LdsmDialog::checkButtonClicked(int state) { QGSettings* settings; QStringList ignore_list; QStringList ignoreStr; QList* ignore_paths; bool ignore,updated; int i; QList::iterator l; ignore_paths =new QList(); settings = new QGSettings(SETTINGS_SCHEMA); //get contents from "ignore-paths" key if (!settings->get(SETTINGS_IGNORE_PATHS).toStringList().isEmpty()) ignore_list.append(settings->get(SETTINGS_IGNORE_PATHS).toStringList()); for(auto str: ignore_list){ if(!str.isEmpty()) ignore_paths->push_back(str); } ignore = state; updated = update_ignore_paths(&ignore_paths, mount_path, ignore); if(updated){ for(l = ignore_paths->begin(); l != ignore_paths->end(); ++l){ ignoreStr.append(*l); } //set latest contents to gsettings "ignore-paths" key settings->set(SETTINGS_IGNORE_PATHS, QVariant::fromValue(ignoreStr)); } //free QList Memory if(ignore_paths){ ignore_paths->clear(); } delete settings; } ukui-settings-daemon/plugins/housekeeping/warning.png0000664000175000017500000000034015167654733022114 0ustar fengfengPNG  IHDR g PLTEe-g tRNS@fIDATU 0 P2ܙ%KQzD'SiQOeט =~(ؖ -0i ((ZڑćȄ 14u(a}*Q8*3W. */ #include "usd-disk-space.h" #include #include "qtimer.h" #include "syslog.h" #include "clib-syslog.h" #define GIGABYTE 1024 * 1024 * 1024 #define CHECK_EVERY_X_SECONDS 120 * 1000 #define DISK_SPACE_ANALYZER "ukui-disk-usage-analyzer" #define SETTINGS_HOUSEKEEPING_SCHEMA "org.ukui.SettingsDaemon.plugins.housekeeping" #define SETTINGS_FREE_PC_NOTIFY_KEY "free-percent-notify" #define SETTINGS_FREE_PC_NOTIFY_AGAIN_KEY "free-percent-notify-again" #define SETTINGS_FREE_SIZE_NO_NOTIFY "free-size-gb-no-notify" #define SETTINGS_MIN_NOTIFY_PERIOD "min-notify-period" #define SETTINGS_IGNORE_PATHS "ignore-paths" static guint64 *time_read; DiskSpace::DiskSpace() { ldsm_timeout_cb = new QTimer(); trash_empty=new LdsmTrashEmpty(); ldsm_notified_hash=NULL; ldsm_monitor = NULL; free_percent_notify = 0.05; free_percent_notify_again = 0.01; free_size_gb_no_notify = 2; min_notify_period = 10; ignore_paths = NULL; done = FALSE; connect(ldsm_timeout_cb, &QTimer::timeout, this, &DiskSpace::ldsm_check_all_mounts); ldsm_timeout_cb->start(); if (QGSettings::isSchemaInstalled(SETTINGS_HOUSEKEEPING_SCHEMA)) { settings = new QGSettings(SETTINGS_HOUSEKEEPING_SCHEMA); } this->dialog = nullptr; } DiskSpace::~DiskSpace() { delete trash_empty; delete settings; } static gint ldsm_ignore_path_compare (gconstpointer a, gconstpointer b) { return g_strcmp0 ((const gchar *)a, (const gchar *)b); } bool DiskSpace::ldsm_mount_is_user_ignore (const char *path) { if (g_slist_find_custom (ignore_paths, path, (GCompareFunc) ldsm_ignore_path_compare) != NULL) return TRUE; else return FALSE; } //static gboolean //ldsm_is_hash_item_in_ignore_paths (gpointer key, // gpointer value, // gpointer user_data) //{ // return this->ldsm_mount_is_user_ignore ((char *)key); //} void DiskSpace::usdLdsmGetConfig() { // 先取得清理提醒的百分比时机 free_percent_notify = settings->get(SETTINGS_FREE_PC_NOTIFY_KEY).toDouble(); if (free_percent_notify >= 1 || free_percent_notify < 0) { /* FIXME define min and max in gschema! */ qWarning ("housekeeping: Invalid configuration of free_percent_notify: %f\n" \ "Using sensible default", free_percent_notify); free_percent_notify = 0.05; } // 取得第二次提醒的百分比时机 free_percent_notify_again = settings->get(SETTINGS_FREE_PC_NOTIFY_AGAIN_KEY).toDouble(); if (free_percent_notify_again >= 1 || free_percent_notify_again < 0) { /* FIXME define min and max in gschema! */ qWarning ("housekeeping: Invalid configuration of free_percent_notify_again: %f\n" \ "Using sensible default\n", free_percent_notify_again); free_percent_notify_again = 0.01; } // 取得不通知的g free_size_gb_no_notify = settings->get(SETTINGS_FREE_SIZE_NO_NOTIFY).toUInt(); // 取得最小通知周期 min_notify_period = settings->get(SETTINGS_MIN_NOTIFY_PERIOD).toInt(); USD_LOG(LOG_DEBUG,"free_percent_notify:%f,free_size_gb_no_notify:%d",free_percent_notify,free_size_gb_no_notify); if (ignore_paths != NULL) { g_slist_foreach (ignore_paths, (GFunc) g_free, NULL); g_slist_free (ignore_paths); ignore_paths = NULL; } } static void ldsm_free_mount_info (gpointer data) { LdsmMountInfo *mount = (LdsmMountInfo *)data; g_return_if_fail (mount != NULL); g_unix_mount_free (mount->mount); g_free (mount); } void DiskSpace::usdLdsmUpdateConfig(QString key) { usdLdsmGetConfig(); } static gboolean is_hash_item_not_in_mounts(QHash &hash, GList* user_data) { for (GList *l = (GList *) user_data; l != NULL; l = l->next) { GUnixMountEntry *mount = (GUnixMountEntry *)l->data; const char *path; path = g_unix_mount_get_mount_path (mount); // 找到了,返回false if (hash.find(path) !=hash.end() ) return FALSE; } return TRUE; } static gboolean is_in (const gchar *value, const gchar *set[]) { int i; for (i = 0; set[i] != NULL; i++) { if (strcmp (set[i], value) == 0) return TRUE; } return FALSE; } bool DiskSpace::ldsm_mount_should_ignore (GUnixMountEntry *mount) { const gchar *fs, *device, *path; path = g_unix_mount_get_mount_path (mount); if (ldsm_mount_is_user_ignore (path)) return TRUE; /* This is borrowed from GLib and used as a way to determine * which mounts we should ignore by default. GLib doesn't * expose this in a way that allows it to be used for this * purpose */ /* We also ignore network filesystems */ const gchar *ignore_fs[] = { "adfs", "afs", "auto", "autofs", "autofs4", "cifs", "cxfs", "devfs", "devpts", "ecryptfs", "fdescfs", "gfs", "gfs2", "kernfs", "linprocfs", "linsysfs", "lustre", "lustre_lite", "ncpfs", "nfs", "nfs4", "nfsd", "ocfs2", "proc", "procfs", "ptyfs", "rpc_pipefs", "selinuxfs", "smbfs", "sysfs", "tmpfs", "usbfs", "zfs", NULL }; const gchar *ignore_devices[] = { "none", "sunrpc", "devpts", "nfsd", "/dev/loop", "/dev/vn", NULL }; fs = g_unix_mount_get_fs_type (mount); device = g_unix_mount_get_device_path (mount); if (is_in (fs, ignore_fs)) return TRUE; if (is_in (device, ignore_devices)) return TRUE; return FALSE; } bool DiskSpace::ldsm_mount_has_space (LdsmMountInfo *mount) { double free_space; bool percent_flag = false; bool size_falg = false; free_space = (double) mount->buf.f_bavail / (double) mount->buf.f_blocks; /* enough free space, nothing to do */ if (free_space > free_percent_notify) percent_flag = true; if (((gint64) mount->buf.f_frsize * (gint64) mount->buf.f_bavail) > ((gint64) free_size_gb_no_notify * GIGABYTE) || ((double) mount->buf.f_blocks *(gint64) mount->buf.f_frsize) < ((gint64) free_size_gb_no_notify * GIGABYTE)) { size_falg = true; } USD_LOG(LOG_DEBUG,"%s:(percent_flag:%d,size_falg:%d),f_frsize:%d,f_bavail:%d,f_blocks:%d,%f",g_unix_mount_get_mount_path(mount->mount),percent_flag,size_falg, mount->buf.f_frsize,mount->buf.f_bavail,mount->buf.f_blocks,free_percent_notify); /* If it returns false, then this volume is low on space */ return (percent_flag && size_falg); } static bool ldsm_mount_is_virtual (LdsmMountInfo *mount) { if (mount->buf.f_blocks == 0) { /* Filesystems with zero blocks are virtual */ return true; } return false; } static gchar* ldsm_get_fs_id_for_path (const gchar *path) { GFile *file; GFileInfo *fileinfo; gchar *attr_id_fs; file = g_file_new_for_path (path); fileinfo = g_file_query_info (file, G_FILE_ATTRIBUTE_ID_FILESYSTEM, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, NULL); if (fileinfo) { attr_id_fs = g_strdup (g_file_info_get_attribute_string (fileinfo, G_FILE_ATTRIBUTE_ID_FILESYSTEM)); g_object_unref (fileinfo); } else { attr_id_fs = NULL; } g_object_unref (file); return attr_id_fs; } static gboolean ldsm_mount_has_trash (LdsmMountInfo *mount) { const gchar *user_data_dir; gchar *user_data_attr_id_fs; gchar *path_attr_id_fs; gboolean mount_uses_user_trash = FALSE; gchar *trash_files_dir; gboolean has_trash = FALSE; GDir *dir; const gchar *path; user_data_dir = g_get_user_data_dir (); user_data_attr_id_fs = ldsm_get_fs_id_for_path (user_data_dir); path = g_unix_mount_get_mount_path (mount->mount); path_attr_id_fs = ldsm_get_fs_id_for_path (path); if (g_strcmp0 (user_data_attr_id_fs, path_attr_id_fs) == 0) { /* The volume that is low on space is on the same volume as our home * directory. This means the trash is at $XDG_DATA_HOME/Trash, * not at the root of the volume which is full. */ mount_uses_user_trash = TRUE; } g_free (user_data_attr_id_fs); g_free (path_attr_id_fs); /* I can't think of a better way to find out if a volume has any trash. Any suggestions? */ if (mount_uses_user_trash) { trash_files_dir = g_build_filename (g_get_user_data_dir (), "Trash", "files", NULL); } else { gchar *uid; uid = g_strdup_printf ("%d", getuid ()); trash_files_dir = g_build_filename (path, ".Trash", uid, "files", NULL); if (!g_file_test (trash_files_dir, G_FILE_TEST_IS_DIR)) { gchar *trash_dir; g_free (trash_files_dir); trash_dir = g_strdup_printf (".Trash-%s", uid); trash_files_dir = g_build_filename (path, trash_dir, "files", NULL); g_free (trash_dir); if (!g_file_test (trash_files_dir, G_FILE_TEST_IS_DIR)) { g_free (trash_files_dir); g_free (uid); return has_trash; } } g_free (uid); } dir = g_dir_open (trash_files_dir, 0, NULL); if (dir) { if (g_dir_read_name (dir)) has_trash = TRUE; g_dir_close (dir); } g_free (trash_files_dir); return has_trash; } static void ldsm_analyze_path (const gchar *path) { const gchar *argv[] = { DISK_SPACE_ANALYZER, path, NULL }; g_spawn_async (NULL, (gchar **) argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, NULL); } bool DiskSpace::ldsm_notify_for_mount (LdsmMountInfo *mount, bool multiple_volumes, bool other_usable_volumes) { gchar *name, *program; signed long free_space; int response; bool has_trash; bool has_disk_analyzer; bool retval = TRUE; char *path; /* Don't show a dialog if one is already displayed */ if (dialog) return retval; name = g_unix_mount_guess_name (mount->mount); free_space = (gint64) mount->buf.f_frsize * (gint64) mount->buf.f_bavail; has_trash = ldsm_mount_has_trash (mount); path = g_strdup (g_unix_mount_get_mount_path (mount->mount)); program = g_find_program_in_path (DISK_SPACE_ANALYZER); has_disk_analyzer = (program != NULL); g_free (program); dialog = new LdsmDialog (other_usable_volumes, multiple_volumes, has_disk_analyzer, has_trash, free_space, name, path); g_free (name); // dialog->show(); response = dialog->exec(); delete dialog; dialog = nullptr; switch (response) { case GTK_RESPONSE_CANCEL: retval = false; break; case LDSM_DIALOG_RESPONSE_ANALYZE: retval = false; ldsm_analyze_path (path); break; case LDSM_DIALOG_RESPONSE_EMPTY_TRASH: retval = false; trash_empty->usdLdsmTrashEmpty();//调清空回收站dialog break; case GTK_RESPONSE_NONE: case GTK_RESPONSE_DELETE_EVENT: retval = true; break; case LDSM_DIALOG_IGNORE: retval = true; break; default: retval = false; } free (path); return retval; } // 目前希望吧GList mounts替换为QList void DiskSpace::ldsm_maybe_warn_mounts (GList *mounts, bool multiple_volumes, bool other_usable_volumes) { GList *l; for (l = mounts; l != NULL; l = l->next) { LdsmMountInfo *mount_info = (LdsmMountInfo *)l->data; LdsmMountInfo *previous_mount_info; gdouble free_space; gdouble previous_free_space; time_t curr_time; const char *path; gboolean show_notify; QString every_two_minutes_check; gdouble free_space_check; if (done) { /* Don't show any more dialogs if the user took action with the last one. The user action * might free up space on multiple volumes, making the next dialog redundant. */ ldsm_free_mount_info (mount_info); continue; } path = g_unix_mount_get_mount_path (mount_info->mount); previous_mount_info = (LdsmMountInfo *)g_hash_table_lookup (ldsm_notified_hash, path); if (previous_mount_info != NULL) previous_free_space = (gdouble) previous_mount_info->buf.f_bavail / (gdouble) previous_mount_info->buf.f_blocks; // liutong // 找m_notified_hash中(mount_info->mount)得到的path QHash::iterator it = m_notified_hash.find(path); if (it != m_notified_hash.end()) { // 如果找到了,就计算上一次的 //LdsmMountInfo* ptmp = it.value() previous_free_space = (gdouble) ((*it)->buf.f_bavail) / (gdouble) ((*it)->buf.f_blocks); } free_space = (gdouble) mount_info->buf.f_bavail / (gdouble) mount_info->buf.f_blocks; if (previous_mount_info == NULL) { /* We haven't notified for this mount yet */ show_notify = TRUE; mount_info->notify_time = time (NULL); m_notified_hash.insert(path, mount_info); } else if ((previous_free_space - free_space) > free_percent_notify_again) { /* We've notified for this mount before and free space has decreased sufficiently since last time to notify again */ curr_time = time (NULL); if (difftime (curr_time, previous_mount_info->notify_time) > (gdouble)(min_notify_period * 60)) { show_notify = TRUE; mount_info->notify_time = curr_time; }else { /* It's too soon to show the dialog again. However, we still replace the LdsmMountInfo * struct in the hash table, but give it the notfiy time from the previous dialog. * This will stop the notification from reappearing unnecessarily as soon as the timeout expires. */ show_notify = FALSE; mount_info->notify_time = previous_mount_info->notify_time; } m_notified_hash.insert(path, mount_info); } else { /* We've notified for this mount before, but the free space hasn't decreased sufficiently to notify again */ ldsm_free_mount_info (mount_info); show_notify = FALSE; } if (show_notify) { if (ldsm_notify_for_mount (mount_info, multiple_volumes, other_usable_volumes)) done = TRUE; } free_space_check = (gint64) mount_info->buf.f_frsize * (gint64) mount_info->buf.f_bavail; // every_two_minutes_check = QString().sprintf("The volume \"%1\" has %s disk space remaining.", // g_format_size(free_space_check)).arg(g_unix_mount_guess_name(mount_info->mount)); // printf("%s\n",every_two_minutes_check.toStdString().data()); } } bool DiskSpace::ldsmGetIgnorePath(const gchar *path) { // 取得清理忽略的目录 QStringList ignoreList = settings->get(SETTINGS_IGNORE_PATHS).toStringList(); for (QString it : ignoreList) { if (it.compare(path) == 0) return true; } return false; } bool DiskSpace::ldsm_check_all_mounts () { GList *mounts; GList *l; GList *check_mounts = NULL; GList *full_mounts = NULL; guint number_of_mounts; guint number_of_full_mounts; gboolean multiple_volumes = FALSE; gboolean other_usable_volumes = FALSE; /* We iterate through the static mounts in /etc/fstab first, seeing if * they're mounted by checking if the GUnixMountPoint has a corresponding GUnixMountEntry. * Iterating through the static mounts means we automatically ignore dynamically mounted media. */ ldsm_timeout_cb->stop(); ldsm_timeout_cb->start(CHECK_EVERY_X_SECONDS); mounts = g_unix_mount_points_get (time_read); for (l = mounts; l != NULL; l = l->next) { GUnixMountPoint *mount_point = (GUnixMountPoint *)l->data; GUnixMountEntry *mount; LdsmMountInfo *mount_info; const gchar *path; path = g_unix_mount_point_get_mount_path (mount_point); mount = g_unix_mount_at (path, time_read); USD_LOG(LOG_DEBUG,"find path:%s ",path); g_unix_mount_point_free (mount_point); if (mount == NULL) { USD_LOG(LOG_DEBUG,"skip path:%s cuz can't find mount",path); /* The GUnixMountPoint is not mounted */ continue; } mount_info = g_new0 (LdsmMountInfo, 1); mount_info->mount = mount; path = g_unix_mount_get_mount_path (mount); if (g_strcmp0 (path, "/boot/efi") == 0 || g_strcmp0 (path, "/boot") == 0 ){ USD_LOG(LOG_DEBUG,"skip path:%s ",path); ldsm_free_mount_info (mount_info); continue; } if (ldsmGetIgnorePath(path)){ USD_LOG(LOG_DEBUG,"skip path:%s cuz ldsmGetIgnorePath",path); ldsm_free_mount_info (mount_info); continue; } if (g_unix_mount_is_readonly (mount)) { USD_LOG(LOG_DEBUG,"skip path:%s cuz g_unix_mount_is_readonly",path); ldsm_free_mount_info (mount_info); continue; } if (ldsm_mount_should_ignore (mount)) { ldsm_free_mount_info (mount_info); USD_LOG(LOG_DEBUG,"skip path:%s cuz ldsm_mount_should_ignore",path); continue; } if (statvfs (path, &mount_info->buf) != 0) { USD_LOG(LOG_DEBUG,"skip path:%s cuz statvfs",path); ldsm_free_mount_info (mount_info); continue; } if (ldsm_mount_is_virtual (mount_info)) { USD_LOG(LOG_DEBUG,"skip path:%s cuz ldsm_mount_is_virtual",path); ldsm_free_mount_info (mount_info); continue; } check_mounts = g_list_prepend (check_mounts, mount_info); } g_list_free (mounts); number_of_mounts = g_list_length (check_mounts); if (number_of_mounts > 1) multiple_volumes = TRUE; for (l = check_mounts; l != NULL; l = l->next) { LdsmMountInfo *mount_info = (LdsmMountInfo *)l->data; if (!ldsm_mount_has_space (mount_info)) { full_mounts = g_list_prepend (full_mounts, mount_info); } else { ldsm_free_mount_info (mount_info); } } number_of_full_mounts = g_list_length (full_mounts); if (number_of_mounts > number_of_full_mounts){ other_usable_volumes = TRUE; } ldsm_maybe_warn_mounts (full_mounts, multiple_volumes, other_usable_volumes); g_list_free (check_mounts); g_list_free (full_mounts); return TRUE; } void DiskSpace::ldsm_mounts_changed (GObject *monitor,gpointer data,DiskSpace *disk) { GList *mounts; /* remove the saved data for mounts that got removed */ mounts = g_unix_mounts_get (time_read); is_hash_item_not_in_mounts(disk->m_notified_hash, mounts); g_list_free_full (mounts, (GDestroyNotify) g_unix_mount_free); /* check the status now, for the new mounts */ disk->ldsm_check_all_mounts(); } void DiskSpace::UsdLdsmSetup(bool check_now) { if (!m_notified_hash.empty() || ldsm_timeout_cb || ldsm_monitor) { qWarning ("Low disk space monitor already initialized."); //return; } usdLdsmGetConfig(); connect(settings, SIGNAL(changed(QString)), this, SLOT(usdLdsmUpdateConfig(QString))); #if GLIB_CHECK_VERSION (2, 44, 0) ldsm_monitor = g_unix_mount_monitor_get (); #else ldsm_monitor = g_unix_mount_monitor_new (); g_unix_mount_monitor_set_rate_limit (ldsm_monitor, 1000); #endif /*g_signal_connect (ldsm_monitor, "mounts-changed", G_CALLBACK (DIskSpace::ldsm_mounts_changed), this);*/ if (check_now) ldsm_check_all_mounts (); //ldsm_timeout_cb->start(CHECK_EVERY_X_SECONDS); } void DiskSpace::cleanNotifyHash() { for(auto it=m_notified_hash.begin();it!=m_notified_hash.end();it++) { auto p = it.value(); if (nullptr != p) { delete p; } } m_notified_hash.clear(); } void DiskSpace::UsdLdsmClean() { cleanNotifyHash(); if (ldsm_monitor) g_object_unref (ldsm_monitor); ldsm_monitor = NULL; if (settings) { g_object_unref (settings); } if (ignore_paths) { g_slist_foreach (ignore_paths, (GFunc) g_free, NULL); g_slist_free (ignore_paths); ignore_paths = NULL; } } #ifdef TEST int main (int argc, char **argv) { GMainLoop *loop; DIskSpace *mDisk; mDisk = DIskSpace::DiskSpaceNew(); gtk_init (&argc, &argv); loop = g_main_loop_new (NULL, FALSE); mDisk->UsdLdsmSetup (true); g_main_loop_run (loop); mDisk->UsdLdsmClean (); g_main_loop_unref (loop); delete mDisk; return 0; } #endif ukui-settings-daemon/plugins/housekeeping/housekeeping-manager.cpp0000664000175000017500000001754615167655063024560 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "housekeeping-manager.h" #include "clib-syslog.h" #include "qtimer.h" #include #include /* General */ #define INTERVAL_ONCE_A_DAY 24*60*60*1000 #define INTERVAL_TWO_MINUTES 1 //#define INTERVAL_TWO_MINUTES 60*2000 /* Thumbnail cleaner */ #define THUMB_CACHE_SCHEMA "org.mate.thumbnail-cache" #define THUMB_CACHE_KEY_AGE "maximum-age" #define THUMB_CACHE_KEY_SIZE "maximum-size" HousekeepingManager *HousekeepingManager::mHouseManager = nullptr; DiskSpace *HousekeepingManager::mDisk = nullptr; typedef struct { long now; long max_age; signed long total_size; signed long max_size; } PurgeData; typedef struct { time_t mtime; char *path; long size; } ThumbData; /* * 初始化DIskSpace, QGSettings,两个QTimer */ HousekeepingManager::HousekeepingManager() { mDisk = new DiskSpace(); settings = new QGSettings(THUMB_CACHE_SCHEMA); long_term_handler = new QTimer(this); short_term_handler = new QTimer(this); connect(long_term_handler, &QTimer::timeout, this, &HousekeepingManager::do_cleanup); connect(short_term_handler, &QTimer::timeout, this, &HousekeepingManager::do_cleanup_once); } /* * 清理DIskSpace, QGSettings,两个QTimer */ HousekeepingManager::~HousekeepingManager() { if (mDisk) { delete mDisk; mDisk = nullptr; } if (settings) { delete settings; settings = nullptr; } if (long_term_handler) { delete long_term_handler; long_term_handler = nullptr; } if (short_term_handler) { delete short_term_handler; short_term_handler = nullptr; } } static GList * read_dir_for_purge (const char *path, GList *files) { GFile *read_path; GFileEnumerator *enum_dir; if (opendir(path) == NULL) return files; read_path = g_file_new_for_path (path); enum_dir = g_file_enumerate_children (read_path, G_FILE_ATTRIBUTE_STANDARD_NAME "," G_FILE_ATTRIBUTE_TIME_MODIFIED "," G_FILE_ATTRIBUTE_STANDARD_SIZE, G_FILE_QUERY_INFO_NONE, NULL, NULL); if (enum_dir != NULL) { GFileInfo *info; while ((info = g_file_enumerator_next_file (enum_dir, NULL, NULL)) != NULL) { const char *name; name = g_file_info_get_name (info); if (strlen (name) == 36 && strcmp (name + 32, ".png") == 0) { ThumbData *td; GFile *entry; char *entry_path; GTimeVal mod_time; entry = g_file_get_child (read_path, name); entry_path = g_file_get_path (entry); g_object_unref (entry); g_file_info_get_modification_time (info, &mod_time); td = g_new0 (ThumbData, 1); td->path = entry_path; td->mtime = mod_time.tv_sec; td->size = g_file_info_get_size (info); files = g_list_prepend (files, td); } g_object_unref (info); } g_object_unref (enum_dir); } g_object_unref (read_path); return files; } static void purge_old_thumbnails (ThumbData *info, PurgeData *purge_data) { if ((purge_data->now - info->mtime) > purge_data->max_age) { g_unlink (info->path); info->size = 0; } else { purge_data->total_size += info->size; } } static int sort_file_mtime (ThumbData *file1, ThumbData *file2) { return file1->mtime - file2->mtime; } static void thumb_data_free (gpointer data) { ThumbData *info = (ThumbData *)data; if (info) { g_free (info->path); g_free (info); } } void HousekeepingManager::purge_thumbnail_cache () { char *path; GList *files; PurgeData purge_data; GTimeVal current_time; purge_data.max_age = settings->get(THUMB_CACHE_KEY_AGE).toInt() * 24 * 60 * 60; purge_data.max_size = settings->get(THUMB_CACHE_KEY_SIZE).toInt() * 1024 * 1024; /* if both are set to -1, we don't need to read anything */ if ((purge_data.max_age < 0) && (purge_data.max_size < 0)) return; path = g_build_filename (g_get_user_cache_dir (), "thumbnails", "normal", NULL); files = read_dir_for_purge (path, NULL); g_free (path); path = g_build_filename (g_get_user_cache_dir (), "thumbnails", "large", NULL); files = read_dir_for_purge (path, files); g_free (path); path = g_build_filename (g_get_user_cache_dir (), "thumbnails", "fail", "ukui-thumbnail-factory", NULL); files = read_dir_for_purge (path, files); g_free (path); g_get_current_time (¤t_time); purge_data.now = current_time.tv_sec; purge_data.total_size = 0; if (purge_data.max_age >= 0) g_list_foreach (files, (GFunc) purge_old_thumbnails, &purge_data); if ((purge_data.total_size > purge_data.max_size) && (purge_data.max_size >= 0)) { GList *scan; files = g_list_sort (files, (GCompareFunc) sort_file_mtime); for (scan = files; scan && (purge_data.total_size > purge_data.max_size); scan = scan->next) { ThumbData *info = (ThumbData *)scan->data; g_unlink (info->path); purge_data.total_size -= info->size; } } g_list_foreach (files, (GFunc) thumb_data_free, NULL); g_list_free (files); } void HousekeepingManager::do_cleanup () { purge_thumbnail_cache (); } void HousekeepingManager::do_cleanup_once () { do_cleanup (); short_term_handler->stop(); } void HousekeepingManager::do_cleanup_soon() { short_term_handler->start(INTERVAL_TWO_MINUTES); } void HousekeepingManager::settings_changed_callback(QString key) { do_cleanup_soon(); } bool HousekeepingManager::HousekeepingManagerStart() { mDisk->UsdLdsmSetup(false); connect (settings, &QGSettings::changed, this,&HousekeepingManager::settings_changed_callback); /* Clean once, a few minutes after start-up */ do_cleanup_soon(); long_term_handler->start(INTERVAL_ONCE_A_DAY); return true; } void HousekeepingManager::HousekeepingManagerStop() { // 时间 if (short_term_handler) { short_term_handler->stop(); } // 时间 if (long_term_handler) { long_term_handler->stop(); /* Do a clean-up on shutdown if and only if the size or age * limits have been set to a paranoid level of cleaning (zero) */ if ((settings->get(THUMB_CACHE_KEY_AGE).toInt() == 0) || (settings->get(THUMB_CACHE_KEY_SIZE).toInt() == 0)) { do_cleanup (); } } mDisk->UsdLdsmClean(); } ukui-settings-daemon/plugins/housekeeping/usd-disk-space.h0000664000175000017500000000550115167655063022727 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef DISKSPACE_H #define DISKSPACE_H #include #include #include #include "usd-ldsm-dialog.h" #include "config.h" #include #include #include #include #include #include #include #include #include #include #include typedef struct { GUnixMountEntry *mount; struct statvfs buf; time_t notify_time; } LdsmMountInfo; class DiskSpace : public QObject { Q_OBJECT public: DiskSpace(); ~DiskSpace(); void UsdLdsmSetup (bool check_now); void UsdLdsmClean (); void usdLdsmGetConfig (); bool ldsm_mount_is_user_ignore (const char *path); bool ldsm_mount_should_ignore (GUnixMountEntry *mount); bool ldsm_mount_has_space (LdsmMountInfo *mount); void ldsm_maybe_warn_mounts (GList *mounts, bool multiple_volumes, bool other_usable_volumes); bool ldsm_notify_for_mount (LdsmMountInfo *mount, bool multiple_volumes, bool other_usable_volumes); static void ldsm_mounts_changed (GObject *monitor,gpointer data,DiskSpace *disk); bool ldsmGetIgnorePath(const gchar *path); bool ldsm_check_all_mounts(); public Q_SLOTS: void usdLdsmUpdateConfig(QString); private: void cleanNotifyHash(); DiskSpace *mDisk; GHashTable *ldsm_notified_hash ; QHash m_notified_hash; QTimer *ldsm_timeout_cb; GUnixMountMonitor *ldsm_monitor; double free_percent_notify; double free_percent_notify_again; unsigned int free_size_gb_no_notify; unsigned int min_notify_period; GSList *ignore_paths; QGSettings *settings; LdsmDialog *dialog; LdsmTrashEmpty *trash_empty; QVariantList ignoreList; bool done; }; #endif // DISKSPACE_H ukui-settings-daemon/plugins/housekeeping/trash_empty.qrc0000664000175000017500000000014515167654733023012 0ustar fengfeng warning.png ukui-settings-daemon/plugins/housekeeping/housekeeping-plugin.cpp0000664000175000017500000000663015167655063024434 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include "usd_base_class.h" #include "housekeeping-plugin.h" #include "clib-syslog.h" PluginInterface *HousekeepingPlugin::mInstance=nullptr; QString getCurrentUserName() { QString name; if (name.isEmpty()) { QStringList envList = QProcess::systemEnvironment(); for(const QString& env : envList){ if (env.startsWith("USERNAME")) { QStringList strList = env.split('='); if (strList.size() > 2) { name = strList[1]; } } } } if (!name.isEmpty()) return name; QProcess process; process.start("whoami", QStringList()); process.waitForFinished(); name = QString::fromLocal8Bit(process.readAllStandardOutput()).trimmed(); return name.isEmpty() ? QString("User") : name; } HousekeepingPlugin::HousekeepingPlugin() { if (isInTrialMode()) { USD_LOG(LOG_DEBUG,"TrialMode..."); return; } userName = getCurrentUserName(); if (userName.compare("lightdm") != 0) { mHouseManager = new HousekeepingManager(); if (!mHouseManager) USD_LOG(LOG_ERR,"Unable to start Housekeeping Manager!"); } } HousekeepingPlugin::~HousekeepingPlugin() { if (mHouseManager) { delete mHouseManager; mHouseManager = nullptr; } } bool HousekeepingPlugin::isInTrialMode() { QString str = ""; QStringList symbList ; QFile file("/proc/cmdline"); if (file.open(QIODevice::ReadOnly)) { QByteArray data = file.readAll(); str = QString::fromLocal8Bit(data); symbList = str.split("\r\n"); } USD_LOG(LOG_DEBUG,"cmdline:%s",str.toLatin1().data()); file.close(); if (str.contains("boot=casper")) { return true; } if (getuid() == 999) return true; return false; } void HousekeepingPlugin::activate() { if (isInTrialMode()) {//TrialMode disable this plugin USD_LOG(LOG_DEBUG,"TrialMode..."); return; } if (userName.compare("lightdm") != 0) { USD_LOG(LOG_DEBUG,"Housekeeping Manager Is Start"); mHouseManager->HousekeepingManagerStart(); } } PluginInterface *HousekeepingPlugin::getInstance() { if (nullptr == mInstance) { mInstance = new HousekeepingPlugin(); } return mInstance; } void HousekeepingPlugin::deactivate() { if(isInTrialMode()) { return; } if (mHouseManager) { mHouseManager->HousekeepingManagerStop(); } } PluginInterface *createSettingsPlugin() { return HousekeepingPlugin::getInstance(); } ukui-settings-daemon/plugins/housekeeping/housekeeping-plugin.h0000664000175000017500000000261615167655063024101 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef HOUSEKEPPINGPLUGIN_H #define HOUSEKEPPINGPLUGIN_H #include "housekeeping-manager.h" #include "plugin-interface.h" class HousekeepingPlugin : public PluginInterface { public: ~HousekeepingPlugin(); static PluginInterface *getInstance(); virtual void activate(); virtual void deactivate(); bool isInTrialMode(); private: HousekeepingPlugin(); HousekeepingPlugin(HousekeepingPlugin&)=delete; private: QString userName; HousekeepingManager *mHouseManager; static PluginInterface *mInstance; }; extern "C" Q_DECL_EXPORT PluginInterface *createSettingsPlugin(); #endif // HOUSEKEPPINGPLUGIN_H ukui-settings-daemon/plugins/keybindings/0000775000175000017500000000000015167655063017561 5ustar fengfengukui-settings-daemon/plugins/keybindings/dconf-util.h0000775000175000017500000000264015167654733022006 0ustar fengfeng/* * dconf-util.h: helper API for dconf * * Copyright (C) 2012 Stefano Karapetsas * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. * * Authors: * Stefano Karapetsas * Vincent Untz */ #ifndef __DCONF_UTIL_H__ #define __DCONF_UTIL_H__ #include G_BEGIN_DECLS gboolean dconf_util_write_sync (const gchar *key, GVariant *value, GError **error); gboolean dconf_util_recursive_reset (const gchar *dir, GError **error); gchar **dconf_util_list_subdirs (const gchar *dir, gboolean remove_trailing_slash); G_END_DECLS #endif /* __DCONF_UTIL_H__ */ ukui-settings-daemon/plugins/keybindings/keybindings-wayland-manager.h0000664000175000017500000000555315167655063025315 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef KEYBINDINGSWAYLANDMANAGER_H #define KEYBINDINGSWAYLANDsMANAGER_H #include #include #include #include #include #include #include #include #include "usd_base_class.h" extern "C" { #include #include #include #include } class ShortCutKeyBind; class KeybindingsWaylandManager { private: KeybindingsWaylandManager(); KeybindingsWaylandManager(KeybindingsWaylandManager&)=delete; public: ~KeybindingsWaylandManager(); static KeybindingsWaylandManager *KeybindingsWaylandManagerNew(); bool start(); void stop(); public: static void bindings_callback (DConfClient *client, gchar *prefix, const gchar **changes, gchar *tag, KeybindingsWaylandManager *manager); private: QStringList getCustomShortcutPath(); void registerShortcutAll(); void unRegisterShortcutAll(); void clearShortcutList(); void clearKglobalShortcutAll(); private: static KeybindingsWaylandManager *m_keybinding; DConfClient *m_dconfClient = nullptr; QList m_shortcutList; }; /*************ShortCutKeyBind**************/ class ShortCutKeyBind : public QObject { Q_OBJECT public: ShortCutKeyBind(QString settingsPath, QString actionName, QString bindKey, QString execName,QString componetName ,QObject *parent = nullptr); ~ShortCutKeyBind(); QString settingPath(){return m_settingsPath;} QAction* action(){return m_action;} private: void setUp(); void setShortcut(); static void parsingDesktop(QString); QList listFromString(); private: QString m_settingsPath; QString m_actionName;//名称唯一 QString m_bindKey;//绑定组合键 QString m_execName;//组合键动作 QString m_componentName;//组名称 QAction *m_action; }; #endif // KEYBINDINGSWAYLANDMANAGER_H ukui-settings-daemon/plugins/keybindings/keybindings-manager.h0000664000175000017500000000570315167655063023655 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef KEYBINDINGSMANAGER_H #define KEYBINDINGSMANAGER_H #include #include #include #include #include #include #include #include #include #include #include #include extern "C"{ #include "ukui-keygrab.h" #include "eggaccelerators.h" #include "dconf-util.h" #include #include #include #include #include #include #include #include #include } typedef struct { char *binding_str; char *action; char *settings_path; Key key; Key previous_key; } Binding; class KeybindingsManager : public QObject { Q_OBJECT private: KeybindingsManager(); KeybindingsManager(KeybindingsManager&)=delete; public: ~KeybindingsManager(); static KeybindingsManager *KeybindingsManagerNew(); bool start(); void stop(); void get_screens_list(); public: static void bindings_callback (DConfClient *client, gchar *prefix, const gchar **changes, gchar *tag, KeybindingsManager *manager); static bool key_already_used (KeybindingsManager *manager,Binding *binding); static void binding_register_keys (KeybindingsManager *manager); static void binding_unregister_keys (KeybindingsManager *manager); static void bindings_clear(KeybindingsManager *manager); static void bindings_get_entries(KeybindingsManager *manager); static bool bindings_get_entry (KeybindingsManager *manager,const char *settings_path); friend GdkFilterReturn keybindings_filter (GdkXEvent *gdk_xevent, GdkEvent *event, KeybindingsManager *manager); private: static KeybindingsManager *mKeybinding; DConfClient *client; GSList *binding_list; QList *screens; QGSettings *dconfSet; GMainLoop *loop; }; #endif // KEYBINDINGSMANAGER_H ukui-settings-daemon/plugins/keybindings/keybindings-plugin.cpp0000664000175000017500000000451015167655063024067 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "keybindings-plugin.h" #include "clib-syslog.h" #include "usd_base_class.h" PluginInterface *KeybindingsPlugin::mInstance=nullptr; KeybindingsPlugin::KeybindingsPlugin() { USD_LOG(LOG_DEBUG,"KeybindingsPlugin initializing"); if (true) { //wayland m_waylandKeyManager = KeybindingsWaylandManager::KeybindingsWaylandManagerNew(); } else { m_xKeyManager = KeybindingsManager::KeybindingsManagerNew(); } } KeybindingsPlugin::~KeybindingsPlugin() { USD_LOG(LOG_DEBUG,"KeybindingsPlugin free"); if(m_xKeyManager){ delete m_xKeyManager; m_xKeyManager = nullptr; } if (m_waylandKeyManager) { delete m_waylandKeyManager; m_waylandKeyManager = nullptr; } } void KeybindingsPlugin::activate() { bool res; USD_LOG (LOG_DEBUG, "Activating %s plugin compilation time:[%s] [%s]",MODULE_NAME,__DATE__,__TIME__); if (m_xKeyManager) { res = m_xKeyManager->start(); } if (m_waylandKeyManager) { m_waylandKeyManager->start(); } if(!res) USD_LOG(LOG_ERR,"Unable to start Keybindings manager"); } PluginInterface *KeybindingsPlugin::getInstance() { if(nullptr == mInstance) mInstance = new KeybindingsPlugin(); return mInstance; } void KeybindingsPlugin::deactivate() { if (m_xKeyManager) { m_xKeyManager->stop(); } if (m_waylandKeyManager) { m_waylandKeyManager->stop(); } USD_LOG(LOG_DEBUG,"Dectivating Keybindings Plugin"); } PluginInterface *createSettingsPlugin() { return KeybindingsPlugin::getInstance(); } ukui-settings-daemon/plugins/keybindings/keybindings-manager.cpp0000664000175000017500000004417715167655063024220 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include "keybindings-manager.h" #include "config.h" #include "clib-syslog.h" #include #include #include #include "usd_base_class.h" #define DESKTOP_APP_DIR "/usr/share/applications/" //#define GSETTINGS_KEYBINDINGS_DIR "/org/ukui/desktop/session/" #define GSETTINGS_KEYBINDINGS_DIR "/org/ukui/desktop/keybindings/" #define CUSTOM_KEYBINDING_SCHEMA "org.ukui.control-center.keybinding" KeybindingsManager *KeybindingsManager::mKeybinding = nullptr; KeybindingsManager::KeybindingsManager() { } KeybindingsManager::~KeybindingsManager() { } KeybindingsManager *KeybindingsManager::KeybindingsManagerNew() { if(nullptr == mKeybinding) mKeybinding = new KeybindingsManager(); return mKeybinding; } /** * @brief parse_binding * Whether the binding exists * 获取此绑定的条目 * @return */ static bool parse_binding (Binding *binding) { gboolean success; if(!binding) return false; binding->key.keysym = 0; binding->key.state = 0; g_free (binding->key.keycodes); binding->key.keycodes = NULL; if (binding->binding_str == NULL || binding->binding_str[0] == '\0' || g_strcmp0 (binding->binding_str, "Disabled") == 0 || g_strcmp0 (binding->binding_str, "disabled") == 0 ) { return false; } success = egg_accelerator_parse_virtual (binding->binding_str, &binding->key.keysym, &binding->key.keycodes, (EggVirtualModifierType *)&binding->key.state); if (!success) USD_LOG(LOG_DEBUG,"Key binding (%s) is invalid", binding->settings_path); return success; } static gint compare_bindings (gconstpointer a, gconstpointer b) { Binding *key_a = (Binding *) a; char *key_b = (char *) b; return g_strcmp0 (key_b, key_a->settings_path); } /** * @brief KeybindingsManager::bindings_get_entry * Gets binding shortcut data * 获取绑定快捷键数据 * @return */ bool KeybindingsManager::bindings_get_entry (KeybindingsManager *manager,const char *settings_path) { GSettings *settings; Binding *new_binding; GSList *tmp_elem; char *action = nullptr; char *key = nullptr; if (!settings_path) { return false; } /* Get entries for this binding * 获取此绑定的条目 */ settings = g_settings_new_with_path (CUSTOM_KEYBINDING_SCHEMA, settings_path); action = g_settings_get_string (settings, "action"); key = g_settings_get_string (settings, "binding"); g_object_unref (settings); if (action==nullptr || key==nullptr) { USD_LOG(LOG_DEBUG,"Key binding (%s) is incomplete", settings_path); return false; } tmp_elem = g_slist_find_custom (manager->binding_list, settings_path, compare_bindings); if (!tmp_elem) { new_binding = g_new0 (Binding, 1); } else { new_binding = (Binding *) tmp_elem->data; g_free (new_binding->binding_str); g_free (new_binding->action); g_free (new_binding->settings_path); new_binding->previous_key.keysym = new_binding->key.keysym; new_binding->previous_key.state = new_binding->key.state; new_binding->previous_key.keycodes = new_binding->key.keycodes; new_binding->key.keycodes = NULL; } new_binding->binding_str = key; new_binding->action = action; new_binding->settings_path = g_strdup (settings_path); if (parse_binding (new_binding)) { if (!tmp_elem) manager->binding_list = g_slist_prepend (manager->binding_list, new_binding); } else { g_free (new_binding->binding_str); g_free (new_binding->action); g_free (new_binding->settings_path); g_free (new_binding->previous_key.keycodes); g_free (new_binding); if (tmp_elem) manager->binding_list = g_slist_delete_link (manager->binding_list, tmp_elem); return false; } return true; } /** * @brief KeybindingsManager::bindings_clear * Clear binding cache * 清除绑定缓存 */ void KeybindingsManager::bindings_clear (KeybindingsManager *manager) { GSList *l; if (manager->binding_list != NULL) { for (l = manager->binding_list; l; l = l->next) { Binding *b = (Binding *)l->data; g_free (b->binding_str); g_free (b->action); g_free (b->settings_path); g_free (b->previous_key.keycodes); g_free (b->key.keycodes); g_free (b); } g_slist_free (manager->binding_list); manager->binding_list = NULL; } } void KeybindingsManager::bindings_get_entries (KeybindingsManager *manager) { gchar **custom_list = NULL; gint i; bindings_clear(manager); custom_list = dconf_util_list_subdirs (GSETTINGS_KEYBINDINGS_DIR, FALSE); if (custom_list != NULL) { for (i = 0; custom_list[i] != NULL; i++) { gchar *settings_path; settings_path = g_strdup_printf("%s%s", GSETTINGS_KEYBINDINGS_DIR, custom_list[i]); bindings_get_entry (manager,settings_path); g_free (settings_path); } g_strfreev (custom_list); } } /** * @brief same_keycode * Is it the same key code * 是否为相同的键码 * @return */ static bool same_keycode (const Key *key, const Key *other) { if (key->keycodes != NULL && other->keycodes != NULL) { unsigned int *c; for (c = key->keycodes; *c; ++c) { if (key_uses_keycode (other, *c)) return true; } } return false; } /** * @brief same_key * Compare whether the keys are shortcuts * 对比按键是否为快捷键 * @return */ static bool same_key (const Key *key, const Key *other) { if (key->state == other->state) { if (key->keycodes != NULL && other->keycodes != NULL) { unsigned int *c1, *c2; for (c1 = key->keycodes, c2 = other->keycodes; *c1 || *c2; ++c1, ++c2) { if (*c1 != *c2) return false; } } else if (key->keycodes != NULL || other->keycodes != NULL) return false; return true; } return false; } /** * @brief KeybindingsManager::key_already_used * @English Compare the shortcuts already used * @简体 已经使用的快捷键 进行比对 * @return */ bool KeybindingsManager::key_already_used (KeybindingsManager*manager,Binding *binding) { GSList *li; for (li = manager->binding_list; li != NULL; li = li->next) { Binding *tmp_binding = (Binding*) li->data; if (tmp_binding != binding && same_keycode (&tmp_binding->key, &binding->key) && tmp_binding->key.state == binding->key.state) { return true; } } return false; } /** * @brief KeybindingsManager::binding_unregister_keys * Unbind key * 注销绑定按键 */ void KeybindingsManager::binding_unregister_keys (KeybindingsManager *manager) { GSList *li; bool need_flush = FALSE; USD_LOG(LOG_DEBUG,"run here..."); gdk_x11_display_error_trap_push (gdk_display_get_default()); try { for (li = manager->binding_list; li != NULL; li = li->next) { Binding *binding = (Binding *) li->data; USD_LOG(LOG_DEBUG,"run here..."); if (binding->key.keycodes) { need_flush = TRUE; grab_key_unsafe (&binding->key, FALSE, manager->screens); } } if (need_flush) gdk_display_flush(gdk_display_get_default()); } catch (...) { } gdk_x11_display_error_trap_pop_ignored(gdk_display_get_default()); } /** * @brief KeybindingsManager::binding_register_keys * Bind register key * 绑定寄存器按键 */ void KeybindingsManager::binding_register_keys (KeybindingsManager *manager) { GSList *li; bool need_flush = false; gdk_x11_display_error_trap_push (gdk_display_get_default()); /* Now check for changes and grab new key if not already used * 现在检查更改并获取新密钥(如果尚未使用) */ for (li = manager->binding_list; li != NULL; li = li->next) { Binding *binding = (Binding *) li->data; if (!same_key (&binding->previous_key, &binding->key)) { /* Ungrab key if it changed and not clashing with previously set binding */ if (!key_already_used (manager,binding)) { gint i; need_flush = true; if (binding->previous_key.keycodes) { grab_key_unsafe (&binding->previous_key, FALSE, manager->screens); } grab_key_unsafe (&binding->key, TRUE, manager->screens); binding->previous_key.keysym = binding->key.keysym; binding->previous_key.state = binding->key.state; g_free (binding->previous_key.keycodes); for (i = 0; binding->key.keycodes&&binding->key.keycodes[i]; ++i); binding->previous_key.keycodes = g_new0 (guint, i); for (i = 0; binding->key.keycodes&&binding->key.keycodes[i]; ++i) binding->previous_key.keycodes[i] = binding->key.keycodes[i]; } else USD_LOG(LOG_DEBUG,"Key binding (%s) is already in use", binding->binding_str); } } if (need_flush) gdk_display_flush (gdk_display_get_default()); if(gdk_x11_display_error_trap_pop (gdk_display_get_default())) USD_LOG(LOG_DEBUG,"Grab failed for some keys, another application may already have access the them."); } /** * @brief keybindings_filter 键盘事件回调函数 * @param gdk_xevent GDK XEvent事件 * @param event GDK Event事件 * @param manager 类 * @return 未处理事件,请继续处理 */ GdkFilterReturn keybindings_filter (GdkXEvent *gdk_xevent, GdkEvent *event, KeybindingsManager *manager) { XEvent *xevent = (XEvent *) gdk_xevent; GSList *li; // USD_LOG(LOG_DEBUG,"had event :%d",xevent->type); if (xevent->type != XI_KeyPress/*KeyPress*/) { return GDK_FILTER_CONTINUE; } for (li = manager->binding_list; li != NULL; li = li->next) { Binding *binding = (Binding *) li->data; if (match_key (&binding->key, xevent)) { GError *error = NULL; gboolean retval; gchar **argv = NULL; if (binding->action == NULL) return GDK_FILTER_CONTINUE; if (!g_shell_parse_argv (binding->action, NULL, &argv, &error)) { return GDK_FILTER_CONTINUE; } GDesktopAppInfo *info = g_desktop_app_info_new_from_filename(binding->action); retval = g_app_info_launch_uris((GAppInfo *)info, NULL, NULL, NULL); g_strfreev (argv); /* Run failed popup * 运行失败弹窗 */ if (!retval) { QString strs = QObject::tr("Error while trying to run \"%1\";\n which is linked to the key \"%2\""). arg(binding->action).arg(binding->binding_str); QMessageBox *msgbox = new QMessageBox(); msgbox->setWindowTitle(QObject::tr("Shortcut message box")); msgbox->setText(strs); msgbox->setStandardButtons(QMessageBox::Yes); msgbox->setButtonText(QMessageBox::Yes,QObject::tr("Yes")); msgbox->exec(); delete msgbox; msgbox = nullptr; } return GDK_FILTER_REMOVE; } } return GDK_FILTER_CONTINUE; } static void show_path (DConfClient *client, const gchar *path) { if (dconf_is_key (path, NULL)) { g_autoptr(GVariant) value = NULL; g_autofree gchar *value_str = NULL; value = dconf_client_read (client, path); if (value != NULL) value_str = g_variant_print (value, TRUE); USD_LOG(LOG_DEBUG," %s\n", value_str != NULL ? value_str : "unset"); } } /** * @brief KeybindingsManager::bindings_callback dconf监听快捷键改变回调函数 * @param client * @param prefix * @param changes * @param tag * @param manager 类 */ void KeybindingsManager::bindings_callback (DConfClient *client, gchar *prefix, const gchar **changes, gchar *tag, KeybindingsManager *manager) { Q_UNUSED(client); Q_UNUSED(changes); if (strncmp(GSETTINGS_KEYBINDINGS_DIR,prefix,strlen(GSETTINGS_KEYBINDINGS_DIR))) { return; } USD_LOG(LOG_DEBUG,"keybindings: received 'changed' signal from dconf. gchar:%s changes:%s tag:%s ",prefix, changes[0], tag); for (const gchar **item = changes; *changes; ++changes) { g_autofree gchar *full = NULL; full = g_strconcat (prefix, *item, NULL); USD_LOG (LOG_DEBUG,"prefix%s full%s\n", prefix, full); show_path (client, full); } binding_unregister_keys (manager); bindings_get_entries (manager); binding_register_keys (manager); } /** * @brief get_screens_list 获取gdkscreen屏幕并存放链表 * @return 返回列表 */ void KeybindingsManager::get_screens_list (void) { GdkScreen *screen = gdk_screen_get_default (); screens->append(screen); } bool KeybindingsManager::start() { USD_LOG(LOG_DEBUG,"-- Keybindings Manager Start --"); QList::iterator l, begin, end; GdkDisplay *dpy; GdkScreen *screen; GdkWindow *window; Display *xdpy; Window xwindow; XWindowAttributes atts; gdk_init(NULL,NULL); dpy = gdk_display_get_default (); // xdpy = GDK_DISPLAY_XDISPLAY (dpy); xdpy = UsdBaseClass::getQx11Info(); screen = gdk_display_get_default_screen(dpy); window = gdk_screen_get_root_window (screen); xwindow = GDK_WINDOW_XID (window); /* Monitor keyboard events * 监听键盘事件 */ gdk_window_add_filter (window, (GdkFilterFunc) keybindings_filter, this); try { /* Add KeyPressMask to the currently reportable event masks * 将KeyPressMask添加到当前可报告的事件掩码 */ gdk_x11_display_error_trap_push (gdk_display_get_default()); XGetWindowAttributes (xdpy, xwindow, &atts); XSelectInput (xdpy, xwindow, atts.your_event_mask | KeyPressMask); gdk_x11_display_error_trap_pop_ignored(gdk_display_get_default()); } catch (int) { USD_LOG(LOG_DEBUG,"had a error in here..."); } screens = new QList(); get_screens_list (); binding_list = NULL; bindings_get_entries (this); binding_register_keys(this); /* Link to dconf, receive a shortcut key change signal from dconf * 链接dconf, 从dconf收到更改快捷键信号 */ { char ** childs; int len; QList vals; client = dconf_client_new (); dconf_client_watch_fast (client, GSETTINGS_KEYBINDINGS_DIR); dconf_client_watch_sync (client, GSETTINGS_KEYBINDINGS_DIR); g_signal_connect (client, "changed", G_CALLBACK (bindings_callback), this); #if 0 //无效,无法使用gsetings的方法监控dconf childs = dconf_client_list (client, GSETTINGS_KEYBINDINGS_DIR, &len); for (int i = 0; childs[i] != NULL; i++){ USD_LOG(LOG_DEBUG,"val:%s",childs[i]); if (dconf_is_rel_dir (childs[i], NULL)) { USD_LOG(LOG_DEBUG,"val:"); char * val = g_strdup (childs[i]); vals.append(val); USD_LOG(LOG_DEBUG,"val:%s",val); } } USD_LOG(LOG_DEBUG,"len:%d",len); for (char * path : vals){ USD_LOG(LOG_DEBUG,"val:%s",path); char tempbuf[128]=""; memcpy(tempbuf, GSETTINGS_KEYBINDINGS_DIR, strlen(GSETTINGS_KEYBINDINGS_DIR)); strcat(tempbuf, path); USD_LOG(LOG_DEBUG,"path:%s, tempbuf%s",path, tempbuf); const QByteArray ba(GSETTINGS_KEYBINDINGS_DIR,strlen(GSETTINGS_KEYBINDINGS_DIR)); const QByteArray bba(tempbuf,strlen(tempbuf)); USD_LOG(LOG_DEBUG,"ba[%s] bba[%s]",ba.data(),bba.data()); QGSettings * settings = new QGSettings(ba, bba); connect(settings, &QGSettings::changed, this, [=] (const QString &key){ USD_LOG(LOG_DEBUG,"key=%s",key.toLatin1().data()); }); } #endif } return true; } void KeybindingsManager::stop() { USD_LOG(LOG_DEBUG,"Stopping keybindings manager"); if (client != NULL) { g_object_unref (client); client = NULL; } QList::iterator l,end; l = screens->begin(); GdkScreen *screen = *l; gdk_window_remove_filter (gdk_screen_get_root_window (screen), (GdkFilterFunc) keybindings_filter, this); binding_unregister_keys (this); bindings_clear (this); screens->clear(); delete screens; screens = NULL; } ukui-settings-daemon/plugins/keybindings/keybindings-plugin.h0000664000175000017500000000300615167655063023533 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef KEYBINDINGSPLUGIN_H #define KEYBINDINGSPLUGIN_H //(xlib 宏定义与qt5.15版本枚举冲突)keybindings-wayland-manager.h #include "keybindings-wayland-manager.h" #include "keybindings-manager.h" #include "plugin-interface.h" class KeybindingsPlugin : public PluginInterface { public: ~KeybindingsPlugin(); static PluginInterface *getInstance(); virtual void activate(); virtual void deactivate(); private: KeybindingsPlugin(); KeybindingsPlugin(KeybindingsPlugin&)=delete; private: KeybindingsManager *m_xKeyManager = nullptr; KeybindingsWaylandManager* m_waylandKeyManager = nullptr; static PluginInterface *mInstance; }; extern "C" Q_DECL_EXPORT PluginInterface * createSettingsPlugin(); #endif // KEYBINDINGSPLUGIN_H ukui-settings-daemon/plugins/keybindings/keybindings-wayland-manager.cpp0000664000175000017500000001773615167655063025656 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include "keybindings-wayland-manager.h" #include "clib-syslog.h" #define GSETTINGS_KEYBINDINGS_DIR "/org/ukui/desktop/keybindings/" #define CUSTOM_KEYBINDING_SCHEMA "org.ukui.control-center.keybinding" #define ACTION "action" #define BINDING "binding" #define NAME "name" #define CUSTOM_COMPONET_NAME "usd_keybindings" KeybindingsWaylandManager *KeybindingsWaylandManager::m_keybinding = nullptr; KeybindingsWaylandManager::KeybindingsWaylandManager() { } KeybindingsWaylandManager::~KeybindingsWaylandManager() { if (m_dconfClient) { dconf_client_unwatch_fast(m_dconfClient, GSETTINGS_KEYBINDINGS_DIR); dconf_client_unwatch_sync(m_dconfClient, GSETTINGS_KEYBINDINGS_DIR); g_object_unref (m_dconfClient); m_dconfClient = nullptr; } clearShortcutList(); } KeybindingsWaylandManager *KeybindingsWaylandManager::KeybindingsWaylandManagerNew() { if(nullptr == m_keybinding) m_keybinding = new KeybindingsWaylandManager(); return m_keybinding; } void KeybindingsWaylandManager::bindings_callback (DConfClient *client, gchar *prefix, const gchar **changes, gchar *tag, KeybindingsWaylandManager *manager) { Q_UNUSED(client) Q_UNUSED(changes) Q_UNUSED(tag) if (strncmp(GSETTINGS_KEYBINDINGS_DIR,prefix,strlen(GSETTINGS_KEYBINDINGS_DIR))) { return; } //卸载所有自定义快捷键 manager->unRegisterShortcutAll(); //重新注册已定义的热键 manager->registerShortcutAll(); qDebug()< seq = QKeySequence::listFromString(list.at(0)); KGlobalAccel::self()->setDefaultShortcut(&action, seq); KGlobalAccel::self()->setShortcut(&action, seq); KGlobalAccel::self()->removeAllShortcuts(&action); } settings.endGroup(); } void KeybindingsWaylandManager::unRegisterShortcutAll() { if(m_shortcutList.isEmpty()){ return; } for(ShortCutKeyBind* bind : m_shortcutList){ KGlobalAccel::self()->removeAllShortcuts(bind->action()); } qDeleteAll(m_shortcutList); m_shortcutList.clear(); } void KeybindingsWaylandManager::clearShortcutList() { if(m_shortcutList.isEmpty()){ return; } qDeleteAll(m_shortcutList); m_shortcutList.clear(); } void KeybindingsWaylandManager::stop() { USD_LOG(LOG_DEBUG,"Stopping keybindings manager"); if (m_dconfClient) { dconf_client_unwatch_fast(m_dconfClient, GSETTINGS_KEYBINDINGS_DIR); dconf_client_unwatch_sync(m_dconfClient, GSETTINGS_KEYBINDINGS_DIR); g_object_unref (m_dconfClient); m_dconfClient = nullptr; } clearShortcutList(); } /*********************ShortCutKeyBind***********************/ ShortCutKeyBind::ShortCutKeyBind(QString settingsPath, QString actionName, QString bindKey, QString execName,QString componetName,QObject* parent) :m_settingsPath(settingsPath), m_actionName(actionName), m_bindKey(bindKey), m_execName(execName), m_componentName(componetName), QObject(parent) { m_action = new QAction(this); m_action->setObjectName(m_actionName); m_action->setProperty("componentName", m_componentName); setUp(); } ShortCutKeyBind::~ShortCutKeyBind() { } void ShortCutKeyBind::setUp() { setShortcut(); } void ShortCutKeyBind::setShortcut() { QList seq = listFromString(); KGlobalAccel::self()->setDefaultShortcut(m_action, seq); KGlobalAccel::self()->setShortcut(m_action, seq); connect(m_action, &QAction::triggered,this,[this]() { USD_LOG(LOG_DEBUG,"shortcut action name %s",m_execName.toLatin1().data()); parsingDesktop(m_execName); }); } QList ShortCutKeyBind::listFromString() { m_bindKey.replace("<",""); m_bindKey.replace(">","+"); if(m_bindKey.contains("Win")){ m_bindKey.replace("Win","Meta"); } return QKeySequence::listFromString(m_bindKey); } void ShortCutKeyBind::parsingDesktop(QString exec) { if(exec.contains("desktop")){ QSettings setting(exec,QSettings::IniFormat); setting.beginGroup("Desktop Entry"); QString name = setting.value("Name").toString(); QString type = setting.value("Type").toString(); QString exec = setting.value("Exec").toString(); setting.endGroup(); Q_UNUSED(name) Q_UNUSED(type) QProcess process; process.startDetached(exec); } } ukui-settings-daemon/plugins/keybindings/dconf-util.c0000775000175000017500000000475715167654733022014 0ustar fengfeng/* * dconf-util.c: helper API for dconf * * Copyright (C) 2012 Stefano Karapetsas * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. * * Authors: * Stefano Karapetsas * Vincent Untz */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include "dconf-util.h" static DConfClient * dconf_util_client_get (void) { return dconf_client_new (); } gboolean dconf_util_write_sync (const gchar *key, GVariant *value, GError **error) { gboolean ret; DConfClient *client = dconf_util_client_get (); ret = dconf_client_write_sync (client, key, value, NULL, NULL, error); g_object_unref (client); return ret; } gboolean dconf_util_recursive_reset (const gchar *dir, GError **error) { gboolean ret; DConfClient *client = dconf_util_client_get (); ret = dconf_client_write_sync (client, dir, NULL, NULL, NULL, error); g_object_unref (client); return ret; } gchar ** dconf_util_list_subdirs (const gchar *dir, gboolean remove_trailing_slash) { GArray *array; gchar **children; int len; int i; DConfClient *client = dconf_util_client_get (); array = g_array_new (TRUE, TRUE, sizeof (gchar *)); children = dconf_client_list (client, dir, &len); g_object_unref (client); for (i = 0; children[i] != NULL; i++) { if (dconf_is_rel_dir (children[i], NULL)) { char *val = g_strdup (children[i]); if (remove_trailing_slash) val[strlen (val) - 1] = '\0'; array = g_array_append_val (array, val); } } g_strfreev (children); return (gchar **) g_array_free (array, FALSE); } ukui-settings-daemon/plugins/keybindings/keybindings.pro0000664000175000017500000000176315167655063022620 0ustar fengfeng#------------------------------------------------- # # Project created by QtCreator 2020-05-24T09:30:00 # #------------------------------------------------- QT -= gui QT += core widgets TARGET = keybindings TEMPLATE = lib DEFINES += KEYBINDINGS_LIBRARY CONFIG += c++20 no_keywords link_pkgconfig plugin DEFINES += QT_DEPRECATED_WARNINGS MODULE_NAME=\\\"keybindings\\\" include($$PWD/../../common/common.pri) INCLUDEPATH += \ /usr/include/KF6/KGlobalAccel PKGCONFIG += \ gtk+-3.0 \ glib-2.0 \ gobject-2.0 \ gio-2.0 \ cairo \ gsettings-qt\ dconf SOURCES += \ dconf-util.c \ keybindings-manager.cpp \ keybindings-plugin.cpp \ keybindings-wayland-manager.cpp HEADERS += \ dconf-util.h \ keybindings-manager.h \ keybindings-plugin.h \ keybindings-wayland-manager.h keybindings_lib.path = $${PLUGIN_INSTALL_DIRS} keybindings_lib.files = $$OUT_PWD/libkeybindings.so INSTALLS += keybindings_lib ukui-settings-daemon/plugins/input-device-manager/0000775000175000017500000000000015167655063021257 5ustar fengfengukui-settings-daemon/plugins/input-device-manager/input-plugin.h0000664000175000017500000000255315167655063024070 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Authors: sundagao */ #ifndef INPUTPLUGIN_H #define INPUTPLUGIN_H #include "plugin-interface.h" #include "input-device-manager.h" class InputPlugin : public PluginInterface { private: InputPlugin(); InputPlugin(const InputPlugin&) = delete; InputPlugin& operator=(const InputPlugin&) = delete; public: ~InputPlugin(); static PluginInterface* getInstance(); virtual void activate(); virtual void deactivate(); private: InputDeviceManager* m_inputDeviceManager = nullptr; }; extern "C" Q_DECL_EXPORT PluginInterface* createSettingsPlugin(); #endif // INPUTPLUGIN_H ukui-settings-daemon/plugins/input-device-manager/input-x-device.h0000664000175000017500000000515015167655063024272 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Authors: sundagao */ #ifndef INPUTXDEVICE_H #define INPUTXDEVICE_H #include #include "input-common.h" #include "input-device.h" extern "C" { #include #include } class InputXDevice; class InputXDevice : public InputDevice { Q_OBJECT public: explicit InputXDevice(QVariant deviceId, DeviceType type, QString deviceName = "", QObject *parent = nullptr); void disable(); void enable(); private: void setProperty(const char *name, const QVariantList &value); void setProperty(Atom prop, const QVariantList &value); QVariantList getProperty(const char *name); QVariantList getProperty(Atom prop); Atom hasProperty(const char *name); void setLeftModeByButtonMap(bool leftMode); void setAccelByLibinput(Atom prop, double acceleration); void setAccelBySynaptic(Atom prop, double acceleration); void setAccelByFeedback(double acceleration); void setSynapticsTapAction(Atom prop); void setLibinputScrolling(Atom prop); void setSynapticsScrolling(); void setSendEventsMode(Atom prop,int mode, int value); public: /*get*/ QVariant getProductId() override; /*set function*/ void setEnable(QVariant value) override; void setLeftMode(QVariant value) override; void setNaturalScroll(QVariant value) override; void setTapclick(QVariant value) override; void setTapDrag(QVariant value) override; void setDisableTyping(QVariant value) override; void setAccelSpeed(QVariant value) override; void setAcceleration(QVariant value) override; void setMiddleButtonEmulation(QVariant value) override; void setScrolling(QVariant value) override; void setDisableTpMoPresent(QVariant value) override; void setWheelSpeed(QVariant value) override; private: void initDeviceProperty(); }; #endif // INPUTXDEVICE_H ukui-settings-daemon/plugins/input-device-manager/input-gsettings.h0000664000175000017500000000440115167655063024573 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Authors: sundagao */ #ifndef INPUTGSETTINGS_H #define INPUTGSETTINGS_H #include #include #include #include #include #include "input-common.h" #define GSETTINGS_INIT_RESULT "gsettings-init-result" //gsettings初始化结果 class InputGsettings : public QObject { Q_OBJECT typedef QSharedPointer GsettingsPtr; typedef QMap GsettingsMap; public: ~InputGsettings(); static InputGsettings* instance(); const QList getGsettingsKeys(DeviceType type); QVariant getGsettingsValue(const QString& key, DeviceType type = DeviceType::IN_MOUSE); void setGsettingsValue(const QString& key, const QVariant& value, DeviceType type = DeviceType::IN_MOUSE); void initGsettings(); bool resultInitGsettings(); private: explicit InputGsettings(QObject *parent = nullptr); InputGsettings(const InputGsettings&) = delete; InputGsettings& operator =(const InputGsettings&)=delete; private: void initMouseGsettings(); void initTouchpadGsettings(); void clearMapData(); private: GsettingsPtr m_mouseSettings; GsettingsPtr m_touchpadSettings; GsettingsMap m_mouseData; GsettingsMap m_touchpadData; public Q_SLOTS: void onMouseChanged(const QString&); void onTouchpadChanged(const QString&); Q_SIGNALS: void mouseChanged(const QString&, QVariant); void touchpadChanged(const QString&, QVariant); }; #endif // INPUTGSETTINGS_H ukui-settings-daemon/plugins/input-device-manager/input-device-manager.h0000664000175000017500000000561515167655063025443 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Authors: sundagao */ #ifndef INPUTDEVICEMANAGER_H #define INPUTDEVICEMANAGER_H #include #include #include #include "input-device.h" #include "input-gsettings.h" #include "input-device-factory.h" class InputDeviceFactor; class InputDeviceManager : public QObject { Q_OBJECT typedef QList DeviceList; public: explicit InputDeviceManager(QObject *parent = nullptr); ~InputDeviceManager(); void start(); void stop(); friend class InputXDeviceFactor; friend class InputWaylandDeviceFactor; private: bool initDeviceFactor(); /** * @brief 剔除特殊设备 * 新版内核 无效mouse设备跟随touchpad上报,product id 一致 */ void eliminateSpecialDevice(); /** * @brief 清空设备列表 */ void clearUpDeviceList(); /** * @brief gsettings 监听 */ void connctGsettings(); /** * @brief 根据设备类型筛选设备 * @param device */ void classifyDevice(InputDevice* device); /** * @brief 断开所有连接 */ void disconnectAll(); /** * @brief 删除设备 * @param deviceId 设备id * @return */ bool deleteDevice(QVariant deviceId); /** * @brief 检测鼠标存在 * @return true */ bool existMouse(); /** * @brief 测试打印设备列表 */ void testPrintDeviceList(); /** * @brief 检测鼠标存在禁用触摸板 初始化时,设备插入时,设备移除时。 */ void disbleTouchpadMousePresent(); /** * @brief deviceAdd * @param device */ void deviceAdd(InputDevice* device); /** * @brief deviceRemove * @param deviceId */ void deviceRemove(QVariant deviceId); private: private Q_SLOTS: void onMouseChanged(const QString&, QVariant); void onTouchpadChanged(const QString&, QVariant); void managerStart(); private: InputDeviceFactor* m_deviceFactor; InputGsettings* m_inputGsettings; DeviceList m_mouseList; DeviceList m_touchpadList; QTimer *m_timer; }; #endif // INPUTDEVICEMANAGER_H ukui-settings-daemon/plugins/input-device-manager/input-monitor.cpp0000664000175000017500000000710215167655063024607 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Authors: sundagao */ #include "input-monitor.h" #include extern "C" { #include #include #include "clib-syslog.h" } int eventSift(XIHierarchyEvent *event, int flag) { int id = 0; for (int i = 0; i < event->num_info; ++i) { if (event->info[i].flags & flag) { id = event->info[i].deviceid; } } return id; } InputMonitor::InputMonitor(QObject *parent) { } void InputMonitor::hierarchyChangedEvent(void *data) { XIHierarchyEvent* event = static_cast(data); if (event->flags & XISlaveAdded) { Q_EMIT deviceAdd(eventSift(event,XISlaveAdded)); } else if (event->flags & XISlaveRemoved) { Q_EMIT deviceRemove(eventSift(event,XISlaveRemoved)); } else if (event->flags & XIDeviceEnabled) { } else if (event->flags & XIDeviceDisabled) { } else if (event->flags & XISlaveAttached) { } else if (event->flags & XISlaveDetached) { } else if (event->flags & XIMasterAdded) { } else if (event->flags & XIMasterRemoved) { } } void InputMonitor::listeningStart() { Display *display = XOpenDisplay(NULL); if (!display) { USD_LOG(LOG_WARNING,"listeningStart is failed , because open display error"); return; } int xi_opcode ,event ,error; if (!XQueryExtension(display, "XInputExtension" , &xi_opcode , &event, &error)) { USD_LOG(LOG_WARNING,"X Input extension not available"); return; } XIEventMask m; m.deviceid = XIAllDevices; m.mask_len = XIMaskLen(XI_LASTEVENT); m.mask = (unsigned char*)calloc(m.mask_len, sizeof(char)); XISetMask(m.mask, XI_HierarchyChanged); Window win = DefaultRootWindow(display); XISelectEvents(display, win, &m, 1); XSync(display, False); free(m.mask); m_stop = false; while (true) { if (m_stop) { USD_LOG(LOG_DEBUG,"input montior has stopped ."); break; } XEvent ev; XGenericEventCookie *cookie = (XGenericEventCookie*)&ev.xcookie; XNextEvent(display, (XEvent*)&ev); if (XGetEventData(display, cookie) && cookie->type == GenericEvent && cookie->extension == xi_opcode) { switch (cookie->evtype) { case XI_HierarchyChanged: hierarchyChangedEvent(cookie->data); break; default: break; } } XFreeEventData(display, cookie); } XDestroyWindow(display, win); } InputMonitor *InputMonitor::instance() { static InputMonitor inputMonitor; return &inputMonitor; } void InputMonitor::startMonitor() { QTimer::singleShot(0, this, &InputMonitor::listeningStart); } void InputMonitor::stopMontior() { m_stop = true; } ukui-settings-daemon/plugins/input-device-manager/input-process-settings.cpp0000664000175000017500000000517215167655063026441 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Authors: sundagao */ #include "input-process-settings.h" #include #include #include #include extern "C" { #include "clib-syslog.h" } ProcessSettings::ProcessSettings(QObject *parent) : QObject(parent) { } ProcessSettings *ProcessSettings::instance() { static ProcessSettings instance; return &instance; } void ProcessSettings::setLocatePointer(bool state) { if (state) { if (!isProcessRunning("usd-locate-pointer")) { QString str = "usd-locate-pointer"; m_locatePointerRunning = QProcess::startDetached(str); } } else { if (isProcessRunning("usd-locate-pointer")) { QString str = "killall usd-locate-pointer"; QProcess::startDetached(str); } } } void ProcessSettings::setDisableWTypingSynaptics(bool state) { if (state) { if (!isProcessRunning("syndaemon")) { QString cmdStart = "syndaemon -i 0.3 -K -R"; QProcess::startDetached(cmdStart); } } else { if (isProcessRunning("syndaemon")) { QString cmdKill = "killall syndaemon"; QProcess::startDetached(cmdKill); } } } bool ProcessSettings::isProcessRunning(const QString& processName) { QDirIterator dirIterator("/proc", QDir::Dirs | QDir::NoDotAndDotDot); while (dirIterator.hasNext()) { dirIterator.next(); bool ok; dirIterator.fileName().toInt(&ok); if (!ok) { continue; } QFile comdLineFile("/proc/" + dirIterator.fileName() + "/cmdline"); if (comdLineFile.open(QIODevice::ReadOnly)) { QString processComm = comdLineFile.readLine().trimmed(); comdLineFile.close(); if (processComm.contains(processName)) { return true; } } } return false; } ukui-settings-daemon/plugins/input-device-manager/input-device-helper.h0000664000175000017500000000574715167655063025316 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Authors: sundagao */ #ifndef INPUTDEVICEHELPER_H #define INPUTDEVICEHELPER_H #include extern "C" { #include "x11-head.h" #include "clib-syslog.h" } #include "usd_base_class.h" #ifndef None #define None 0 #endif namespace InputDeviceHelper { /** * @brief supportXinputExtension 支持Xinput扩展 * @return bool */ bool supportXinputExtension(); /** * @brief properyToAtom 属性名称转换Atom * @param propery 属性名称 * @return Atom */ Atom properyToAtom(const char* propery); /** * @brief 检查属性是否存在 * @param device 设备ID * @param propName 属性名称 * @param prop Atom * @return 返回属性Atom,未找到返回None */ Atom deviceHadProperty(int device, const char* propName); Atom deviceHadProperty(int device, Atom prop); /** * @brief getDeviceProp 获取某一属性的值 * @param device 设备ID * @param prop Atom * @return 返回QvariantList */ QVariantList getDeviceProp(int device, const char *property); QVariantList getDeviceProp(int device, Atom prop); /** * @brief setDeviceProp 修改属性的值 * @param device * @param prop */ void setDeviceProp(int device, const char *property ,QVariantList value); void setDeviceProp(int device, Atom prop, QVariantList value); /** * @brief 获取按钮映射 * @param device * @return */ int getDeviceButtonMap(int device, unsigned char** map); /** * @brief 设置按钮映射 * @param device 设备id * @param buttons 映射按钮的数量 * @param map */ void setDeviceButtonMap(int device, int buttons, unsigned char* map); /** * @brief changePtrFeedbackControl * @param device * @param threshold * @param numerator * @param denominator */ void changePtrFeedbackControl(int device, int threshold, int numerator, int denominator); /** * @brief disable 禁用设备 * @param device 设备ID */ void disable(int device); /** * @brief enabel 启用设备 * @param device 设备ID */ void enabel(int device); } #endif // INPUTDEVICEHELPER_H ukui-settings-daemon/plugins/input-device-manager/input-device-factory.h0000664000175000017500000000514615167655063025477 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Authors: sundagao */ #ifndef INPUTDEVICEFACTORY_H #define INPUTDEVICEFACTORY_H #include #include #include #include "input-monitor.h" #include "input-device-manager.h" extern "C" { #include #include "clib-syslog.h" } class InputDeviceManager; class InputDeviceFactor : public QObject { Q_OBJECT public: virtual void initInputDevices() = 0; private: }; /*****X Device factor*****/ class InputXDeviceFactor : public InputDeviceFactor { Q_OBJECT public: explicit InputXDeviceFactor(QObject *parent = nullptr); ~InputXDeviceFactor(); void initInputDevices() override; private: void connectMonitor(); InputDevice* createInputDevice(QVariant deviceId, DeviceType type, QString name); InputDevice* filterDevice(XDeviceInfo device); private Q_SLOTS: void deviceAdd(int id); void deviceRemove(int id); private: QThread *m_monitorThread; InputMonitor* m_inputMonitor; InputDeviceManager* m_deviceManager; }; /*****wayland Device factor*****/ class InputWaylandDeviceFactor : public InputDeviceFactor { Q_OBJECT public: explicit InputWaylandDeviceFactor(QObject *parent = nullptr); ~InputWaylandDeviceFactor(); void initInputDevices() override; private: void connectMonitor(); InputDevice* createInputDevice(QVariant deviceId, DeviceType type, QString name); InputDevice* filterDevice(QDBusInterface * interface); void managerAddDevice(QString); private Q_SLOTS: void deviceAdd(QString device); void deviceRemove(QString device); private: QDBusInterface* m_deviceInterface = nullptr; InputDeviceManager* m_deviceManager = nullptr; }; /**********/ class InputDeviceFactorManager { public: static InputDeviceFactor* createDeviceFactor(InputDeviceManager* manager); }; #endif // INPUTDEVICEFACTORY_H ukui-settings-daemon/plugins/input-device-manager/input-wayland-device.cpp0000664000175000017500000001237215167655063026021 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Authors: sundagao */ #include "input-wayland-device.h" #include "input-gsettings.h" #include "input-device-function.h" #include extern "C" { #include "clib-syslog.h" } //外部全局变量,在input-device-funtion.cpp 定义 extern const DeviceFunctionMap deviceFuncMap; InputWaylandDevice::InputWaylandDevice(QVariant deviceId, DeviceType type, QString deviceName, QObject *parent) : InputDevice(deviceId, type, deviceName, parent) { m_interface = new QDBusInterface(QStringLiteral(KDE_KWIN_SERVICE), QStringLiteral(KDE_KWIN_OBJECT_PATH) + m_deviceId.toString(), QStringLiteral(KDE_KWIN_INTERFACE), QDBusConnection::sessionBus(), this); if (!m_interface->isValid()) { m_interface = new QDBusInterface(QStringLiteral(UKUI_KWIN_SERVICE), QStringLiteral(UKUI_KWIN_OBJECT_PATH) + m_deviceId.toString(), QStringLiteral(UKUI_KWIN_INTERFACE), QDBusConnection::sessionBus(), this); } initDeviceProperty(); } void InputWaylandDevice::disable() { setProperty("enabled", false); } void InputWaylandDevice::enable() { setProperty("enabled", true); } void InputWaylandDevice::setEnable(QVariant value) { setProperty("enabled", value); } void InputWaylandDevice::setLeftMode(QVariant value) { setProperty("leftHanded", value); } void InputWaylandDevice::setNaturalScroll(QVariant value) { setProperty("naturalScroll", value); } void InputWaylandDevice::setTapclick(QVariant value) { setProperty("tapToClick", value); } void InputWaylandDevice::setTapDrag(QVariant value) { setProperty("tapAndDrag", value); } void InputWaylandDevice::setDisableTyping(QVariant value) { setProperty("disableWhileTyping", value); } void InputWaylandDevice::setAccelSpeed(QVariant value) { setProperty("pointerAccelerationProfileAdaptive", value); setProperty("pointerAccelerationProfileFlat", !value.toBool()); } void InputWaylandDevice::setAcceleration(QVariant value) { double acceleration = value.toDouble(); if (acceleration <= 1.0) { acceleration = 1.0; } else if (acceleration >= 8.0) { acceleration = 8.0; } acceleration = (acceleration - 1.0) * 2.0 / 7.0 - 1; setProperty("pointerAcceleration", acceleration); } void InputWaylandDevice::setMiddleButtonEmulation(QVariant value) { setProperty("middleButtonEmulation", value); } void InputWaylandDevice::setScrolling(QVariant value) { Q_UNUSED(value) bool edgeScroll = getGsettingsValue(KEY_VERT_EDGE_SCROLL).toBool(); bool twoFingerScroll = getGsettingsValue(KEY_VERT_TWO_FINGER_SCROLL).toBool(); USD_LOG(LOG_DEBUG,"setScrolling edgeScroll: %d twoFingerScroll: %d",edgeScroll, twoFingerScroll ); setProperty("scrollEdge", edgeScroll); setProperty("scrollTwoFinger", twoFingerScroll); } void InputWaylandDevice::setDisableTpMoPresent(QVariant mousePresent) { QVariant value = getGsettingsValue(KEY_TOUCHPAD_DISBLE_O_E_MOUSE); if (value.toBool() && mousePresent.toBool()) { setEnable(false); } else { setEnable(true); } } void InputWaylandDevice::setWheelSpeed(QVariant value) { if (isMouse()) { setProperty("scrollFactor", value); } } QVariant InputWaylandDevice::getProductId() { return getProperty("product"); } void InputWaylandDevice::setProperty(const char *prop, QVariant value) { if (m_interface->isValid()) { USD_LOG(LOG_DEBUG,"set prop %s",prop); m_interface->setProperty(prop, value); } else { USD_LOG(LOG_WARNING,"wayland device interface is not valid ."); } } QVariant InputWaylandDevice::getProperty(const char *prop) { return m_interface->property(prop); } void InputWaylandDevice::initDeviceProperty() { //新增设备时初始化属性列表,根据gsetings 配置设置属性。 QList keys = InputGsettings::instance()->getGsettingsKeys(m_type); if (keys.isEmpty()) { USD_LOG(LOG_DEBUG,"get gsettings keys is empty ."); return; } for (const QString& key : keys) { QVariant value = getGsettingsValue(key); if (key == QStringLiteral(KEY_MOUSE_LOCATE_POINTER)) { InputDeviceFunction::setLocatePointer(value); } else { auto func = deviceFuncMap.value(key); if (func) { func(value,this); } } } } ukui-settings-daemon/plugins/input-device-manager/input-wayland-device.h0000664000175000017500000000454615167655063025472 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Authors: sundagao */ #ifndef INPUTWAYLANDDEVICE_H #define INPUTWAYLANDDEVICE_H #include #include #include "input-common.h" #include "input-device.h" #define UKUI_KWIN_SERVICE "org.ukui.KWin" #define UKUI_KWIN_OBJECT_PATH "/org/ukui/KWin/InputDevice/" #define UKUI_KWIN_INTERFACE "org.ukui.KWin.InputDevice" #define KDE_KWIN_SERVICE "org.kde.KWin" #define KDE_KWIN_OBJECT_PATH "/org/kde/KWin/InputDevice/" #define KDE_KWIN_INTERFACE "org.kde.KWin.InputDevice" class InputWaylandDevice : public InputDevice { Q_OBJECT public: explicit InputWaylandDevice(QVariant deviceId, DeviceType type, QString deviceName = "", QObject *parent = nullptr); public: void disable(); void enable(); public: void setEnable(QVariant value) override; void setLeftMode(QVariant value) override; void setNaturalScroll(QVariant value) override; void setTapclick(QVariant value) override; void setTapDrag(QVariant value) override; void setDisableTyping(QVariant value) override; void setAccelSpeed(QVariant value) override; void setAcceleration(QVariant value) override; void setMiddleButtonEmulation(QVariant value) override; void setScrolling(QVariant value) override; void setDisableTpMoPresent(QVariant value) override; void setWheelSpeed(QVariant value) override; public: QVariant getProductId() override; private: void setProperty(const char* prop, QVariant); QVariant getProperty(const char* prop); void initDeviceProperty(); Q_SIGNALS: private: QDBusInterface *m_interface; }; #endif // INPUTWAYLANDDEVICE_H ukui-settings-daemon/plugins/input-device-manager/input-x-device.cpp0000664000175000017500000003516215167655063024633 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Authors: sundagao */ #include #include "input-x-device.h" #include "input-device-helper.h" #include "input-gsettings.h" #include "input-process-settings.h" #include "input-device-function.h" extern "C" { #include "clib-syslog.h" } //libinput event mode #define EVENT_MODE_DISABLED 0 #define EVENT_MODE_DISABLED_ON_EXTERNAL_MOUSE 1 using namespace InputDeviceHelper; extern const DeviceFunctionMap deviceFuncMap; QVariantList variantList(QVariant value) { return QVariantList() << value; } InputXDevice::InputXDevice(QVariant deviceId, DeviceType type, QString deviceName, QObject* parent) : InputDevice(deviceId, type, deviceName, parent) { initDeviceProperty(); } void InputXDevice::disable() { InputDeviceHelper::disable(m_deviceId.toInt()); } void InputXDevice::enable() { InputDeviceHelper::enabel(m_deviceId.toInt()); } void InputXDevice::setProperty(const char *name, const QVariantList &value) { InputDeviceHelper::setDeviceProp(m_deviceId.toInt(), name, value); } void InputXDevice::setProperty(Atom prop, const QVariantList &value) { InputDeviceHelper::setDeviceProp(m_deviceId.toInt(), prop, value); } QVariantList InputXDevice::getProperty(const char *name) { return InputDeviceHelper::getDeviceProp(m_deviceId.toInt(),name); } QVariantList InputXDevice::getProperty(Atom prop) { return InputDeviceHelper::getDeviceProp(m_deviceId.toInt(),prop); } Atom InputXDevice::hasProperty(const char *name) { return InputDeviceHelper::deviceHadProperty(m_deviceId.toInt(),name); } //左右键映射 void InputXDevice::setLeftModeByButtonMap(bool leftMode) { unsigned char *map = nullptr; int buttons = InputDeviceHelper::getDeviceButtonMap(m_deviceId.toInt(),&map); if (!map || 0 == buttons) { USD_LOG(LOG_WARNING,"device : %d has no buttons.",m_deviceId.toInt()); USD_LOG(LOG_WARNING,"buttons map is null . set button map failed ."); return; } auto calculationMap = [] (int buttons , unsigned char* map, bool leftMode) -> void { const int left = 1; int right = qMin(buttons,3); if (map[left - 1] != left && map[left - 1] != right) { USD_LOG(LOG_WARNING,"The current mapping is weird. Swapping buttons is probably not a good idea."); return; } if (leftMode) { map[left - 1] = right; map[right - 1] = left; } else { map[left - 1] = left; map[right - 1] = right; } }; calculationMap(buttons, map, leftMode); InputDeviceHelper::setDeviceButtonMap(m_deviceId.toInt(),buttons,map); } void InputXDevice::setAccelByLibinput(Atom prop, double acceleration) { if (acceleration <= 1.0) { acceleration = 1.0; } else if (acceleration >= 8.0) { acceleration = 8.0; } acceleration = (acceleration - 1.0) * 2.0 / 7.0 - 1; InputDeviceHelper::setDeviceProp(m_deviceId.toInt(), prop, variantList(acceleration)); } void InputXDevice::setAccelBySynaptic(Atom prop, double acceleration) { if (acceleration <= 1.0) { acceleration = 1.0; } else if (acceleration >= 8.0) { acceleration = 8.0; } acceleration = 9.0 - acceleration; InputDeviceHelper::setDeviceProp(m_deviceId.toInt(), prop, variantList(acceleration)); } void InputXDevice::setAccelByFeedback(double acceleration) { //feefback光标速度设置 int numerator = -1; int denominator = -1; int threshold = -1; threshold = getGsettingsValue(KEY_MOTION_THRESHOLD).toInt(); /* Calculate acceleration */ if (acceleration >= 1.0) { /* we want to get the acceleration, with a resolution of 0.5 */ if ((acceleration - floor(acceleration)) < 0.25) { numerator = floor(acceleration); denominator = 1; } else if ((acceleration - floor(acceleration)) < 0.5) { numerator = ceil(2.0 * acceleration); denominator = 2; } else if ((acceleration - floor(acceleration)) < 0.75) { numerator = floor(2.0 *acceleration); denominator = 2; } else { numerator = ceil(acceleration); denominator = 1; } } else if (acceleration < 1.0 && acceleration > 0) { /* This we do to 1/10ths */ numerator = floor (acceleration * 10) + 1; denominator= 10; } InputDeviceHelper::changePtrFeedbackControl(m_deviceId.toInt(), threshold, numerator, denominator); } void InputXDevice::setSynapticsTapAction(Atom prop) { QVariantList list = getProperty(prop); if (list.isEmpty()) { USD_LOG(LOG_WARNING,"prop value is null ."); return; } bool state = getGsettingsValue(KEY_TOUCHPAD_TAP_TO_CLICK).toBool(); int oneTapAction = getGsettingsValue(KEY_TOUCHPAD_ONE_FINGER_TAP).toInt(); int twoTapAction = getGsettingsValue(KEY_TOUCHPAD_TWO_FINGER_TAP).toInt(); int threeTapActon = getGsettingsValue(KEY_TOUCHPAD_THREE_FINGER_TAP).toInt(); USD_LOG(LOG_DEBUG,"finger action is one : %d two : %d three : %d",oneTapAction,twoTapAction,threeTapActon); if (oneTapAction > 3 || oneTapAction < 1) { oneTapAction = 1; } if (twoTapAction > 3 || twoTapAction < 1) { twoTapAction = 3; } if (threeTapActon > 3 || threeTapActon < 1) { threeTapActon = 0; } //属性列表4,5,6代表单指,双指,三指对应的动作,1:鼠标左键,2:鼠标中键,3:鼠标右键 0:禁用 list[4] = state ? oneTapAction : 0; list[5] = state ? twoTapAction : 0; list[6] = state ? threeTapActon : 0; setProperty(prop,list); } void InputXDevice::setLibinputScrolling(Atom prop) { QVariantList list = getProperty(prop); if (list.isEmpty()) { USD_LOG(LOG_WARNING,"prop list value is null ."); return; } bool edgeScroll = getGsettingsValue(KEY_VERT_EDGE_SCROLL).toBool(); bool twoFingerScroll = getGsettingsValue(KEY_VERT_TWO_FINGER_SCROLL).toBool(); if (twoFingerScroll && !edgeScroll) { //双指滚动 list[0] = 1; list[1] = 0; } else if (edgeScroll && !twoFingerScroll) { //边缘滚动 list[0] = 0; list[1] = 1; } else if (!edgeScroll && !twoFingerScroll) { list[0] = 0; list[1] = 0; } setProperty(prop,list); } void InputXDevice::setSynapticsScrolling() { //Synaptics Scrolling Atom edgeProp = hasProperty("Synaptics Edge Scrolling"); Atom twoFingerProp = hasProperty("Synaptics Two-Finger Scrolling"); if (edgeProp) { QVariantList list = getProperty(edgeProp); if (list.isEmpty()) { USD_LOG(LOG_WARNING,"prop list value is null ."); return; } bool verScroll = getGsettingsValue(KEY_VERT_EDGE_SCROLL).toBool(); bool horScroll = getGsettingsValue(KEY_HORIZ_EDGE_SCROLL).toBool(); list[0] = verScroll ? 1 : 0; list[1] = horScroll ? 1 : 0; setProperty(edgeProp,list); } if (twoFingerProp) { QVariantList list = getProperty(twoFingerProp); if (list.isEmpty()) { USD_LOG(LOG_WARNING,"prop list value is null ."); return; } bool verScroll = getGsettingsValue(KEY_VERT_TWO_FINGER_SCROLL).toBool(); bool horScroll = getGsettingsValue(KEY_HORIZ_TWO_FINGER_SCROLL).toBool(); list[0] = verScroll ? 1 : 0; list[1] = horScroll ? 1 : 0; setProperty(twoFingerProp,list); } } void InputXDevice::setSendEventsMode(Atom prop, int mode, int value) { QVariantList list = getProperty(prop); if (list.isEmpty()) { USD_LOG(LOG_WARNING,"prop list value is null ."); return; } if (value) { list[mode] = 1; } else { list[mode] = 0; } setProperty(prop,list); } /*get property*/ QVariant InputXDevice::getProductId() { QVariantList list = getProperty("Device Product ID"); int product = 0; for (QVariant var : list){ product += var.toInt(); } return product; } /****************set function******************/ void InputXDevice::setEnable(QVariant value) { if (value.toBool()) { enable(); } else { disable(); } } void InputXDevice::setLeftMode(QVariant value) { if (Atom prop = hasProperty("libinput Left Handed Enabled")) { setProperty(prop, variantList(value)); } else { //无此属性,可通过按钮映射方式实现左手模式 setLeftModeByButtonMap(value.toBool()); } } //滚动方向 void InputXDevice::setNaturalScroll(QVariant value) { if (Atom prop = hasProperty("libinput Natural Scrolling Enabled")) { setProperty(prop, variantList(value)); } else if (Atom prop = hasProperty("Synaptics Scrolling Distance")) { //Synaptics QVariantList list = getProperty(prop); for (int i = 0; i < list.size(); ++i) { if (value.toBool()) { list[i] = -qAbs(list.at(i).toInt()); } else { list[i] = qAbs(list.at(i).toInt()); } } setProperty(prop, list); } } //触摸板轻触点击 void InputXDevice::setTapclick(QVariant value) { if (isTouchpad()) { if (Atom prop = hasProperty("libinput Tapping Enabled")) { setProperty(prop, variantList(value)); } else if (Atom prop = hasProperty("Synaptics Tap Action")) { setSynapticsTapAction(prop); } } } //触摸板轻触拖拽 void InputXDevice::setTapDrag(QVariant value) { if (isTouchpad()) { if (Atom prop = hasProperty("libinput Tapping Drag Enabled")) { setProperty(prop, variantList(value)); } else if (Atom prop = hasProperty("Synaptics Gestures")) { setProperty(prop, variantList(value)); } } } //打字禁用触摸板 void InputXDevice::setDisableTyping(QVariant value) { if (isTouchpad()) { if (Atom prop = hasProperty("libinput Disable While Typing Enabled")) { setProperty(prop, variantList(value)); } else if (Atom prop = hasProperty("Synaptics Off")){ Q_UNUSED(prop) //Syndaemon ProcessSettings::instance()->setDisableWTypingSynaptics(value.toBool()); } } } //光标加速配置文件 void InputXDevice::setAccelSpeed(QVariant value) { if (Atom prop = hasProperty("libinput Accel Profile Enabled")) { QVariantList list; if (value.toBool()) { list << 1 << 0; //0,1 平滑 } else { list << 0 << 1; //1,0 自适应 } setProperty(prop, list); } else if (Atom prop = hasProperty("Device Accel Profile")) { setProperty(prop, variantList(value)); } else { USD_LOG(LOG_WARNING,"property is not libinput or Synaptics"); } } //光标速度 void InputXDevice::setAcceleration(QVariant value) { //待确定速度标准 if (Atom prop = hasProperty("libinput Accel Speed")) { //光标速度值根据属性不同需要改动,慢-快[-1 ,1] setAccelByLibinput(prop, value.toDouble()); } else if (Atom prop = hasProperty("Device Accel Constant Deceleration")) { //[1 - 8] setAccelBySynaptic(prop, value.toDouble()); } else { //by feedback setAccelByFeedback(value.toDouble()); } } //左右键同时按下模拟右键 void InputXDevice::setMiddleButtonEmulation(QVariant value) { if (Atom prop = hasProperty("libinput Middle Emulation Enabled")) { setProperty(prop, variantList(value)); } else if (Atom prop = hasProperty("Evdev Middle Button Emulation")) { setProperty(prop, variantList(value)); } else { USD_LOG(LOG_WARNING,"property is not libinput or Synaptics"); } } //滚动 void InputXDevice::setScrolling(QVariant value) { Q_UNUSED(value) if (Atom prop = hasProperty("libinput Scroll Method Enabled")) { setLibinputScrolling(prop); } else { setSynapticsScrolling(); } } //插入鼠标禁用触摸板 void InputXDevice::setDisableTpMoPresent(QVariant mousePresent) { QVariant value = getGsettingsValue(KEY_TOUCHPAD_DISBLE_O_E_MOUSE); if (Atom prop = hasProperty("libinput Send Events Mode Enabled")) { setSendEventsMode(prop, EVENT_MODE_DISABLED_ON_EXTERNAL_MOUSE, value.toBool()); } else { if (value.toBool() && mousePresent.toBool()) { setGsettingsValue(KEY_TOUCHPAD_ENABLED, false); } else { setGsettingsValue(KEY_TOUCHPAD_ENABLED, true); } } } void InputXDevice::setWheelSpeed(QVariant value) { if (isMouse()) { if (Atom prop = hasProperty("libinput Button Scrolling Speed")) { // 与支撑确认,此属性取值范围 0 < x <= 20.0 ,用户设置入口为1-10,进行x2 setProperty(prop, variantList(2 * value.toFloat())); } else if (Atom prop = hasProperty("Synaptics Scrolling Distance")){ // Synaptics 滚动取值未定 // QVariantList list = getProperty(prop); // for (int i = 0; i < list.size(); ++i) { // int val = list[i].toInt(); // if (val >= 0) { // list[i] = qAbs(value.toInt()); // } else { // list[i] = -qAbs(value.toInt()); // } // } // setProperty(prop, list); } } } void InputXDevice::initDeviceProperty() { //新增设备时初始化属性列表,根据gsetings 配置设置属性。 QList keys = InputGsettings::instance()->getGsettingsKeys(m_type); if (keys.isEmpty()) { USD_LOG(LOG_DEBUG,"get gsettings keys is empty ."); return; } for (const QString& key : keys) { QVariant value = getGsettingsValue(key); if (key == QStringLiteral(KEY_MOUSE_LOCATE_POINTER)) { InputDeviceFunction::setLocatePointer(value); } else { auto func = deviceFuncMap.value(key); if (func) { func(value,this); } } } } ukui-settings-daemon/plugins/input-device-manager/input-device-factory.cpp0000664000175000017500000002215515167655063026031 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Authors: sundagao */ #include "input-device-factory.h" #include "input-device-helper.h" #include "input-x-device.h" #include "input-wayland-device.h" #include "usd_base_class.h" using namespace InputDeviceHelper; /*****X Factor*****/ InputXDeviceFactor::InputXDeviceFactor(QObject *parent) { m_deviceManager = reinterpret_cast(parent); m_monitorThread = new QThread(this); connectMonitor(); } InputXDeviceFactor::~InputXDeviceFactor() { disconnect(m_inputMonitor, &InputMonitor::deviceAdd, this, &InputXDeviceFactor::deviceAdd); disconnect(m_inputMonitor, &InputMonitor::deviceRemove, this, &InputXDeviceFactor::deviceRemove); m_inputMonitor->stopMontior(); } void InputXDeviceFactor::initInputDevices() { int ndevices; XDeviceInfo* deviceList = XListInputDevices(UsdBaseClass::getQx11Info(),&ndevices); for (int i = 0 ; i < ndevices ; ++i) { InputDevice* device = filterDevice(deviceList[i]); if (device) { m_deviceManager->deviceAdd(device); } } XFreeDeviceList(deviceList); } InputDevice *InputXDeviceFactor::createInputDevice(QVariant deviceId, DeviceType type, QString name) { return new InputXDevice(deviceId, type, name); } InputDevice* InputXDeviceFactor::filterDevice(XDeviceInfo device) { InputDevice *inputDevice = nullptr; if (device.type == properyToAtom(XI_MOUSE)){ //鼠标, 由于虚拟机内虚拟鼠标设备使用PS2协议,增加“VMware VMMouse”字段区分。 if (strstr(device.name,R"(PS/2)") && !strstr(device.name, "VMware VMMouse")) { //ps2 触摸板上报为鼠标设备,所以标记为IN_TOUCHPAD inputDevice = createInputDevice(int(device.id), DeviceType::IN_TOUCHPAD, device.name); } else if (strstr(device.name, "TrackPoint")) { //lenovo track point设备 } else { // mouse inputDevice = createInputDevice(int(device.id), DeviceType::IN_MOUSE, device.name); } } else if (device.type == properyToAtom(XI_TOUCHPAD)) {//触控板 inputDevice = createInputDevice(int(device.id), DeviceType::IN_TOUCHPAD, device.name); } else if (device.type == properyToAtom(XI_TOUCHSCREEN) //触控屏 || device.type == properyToAtom(XI_TABLET)) {//笔 //绝对坐标映射设备进行映射 QDBusInterface interface("org.ukui.SettingsDaemon", "/org/ukui/SettingsDaemon/xrandr", "org.ukui.SettingsDaemon.xrandr", QDBusConnection::sessionBus()); if (interface.isValid()) { interface.call("setScreenMap"); } }else if (device.type == properyToAtom(XI_JOYSTICK)) {//摇杆 //to be continued } return inputDevice; } void InputXDeviceFactor::connectMonitor() { //delete InputMonitor m_inputMonitor = InputMonitor::instance(); m_inputMonitor->moveToThread(m_monitorThread); connect(m_monitorThread, &QThread::started, InputMonitor::instance(), &InputMonitor::startMonitor); m_monitorThread->start(); connect(m_inputMonitor, &InputMonitor::deviceAdd, this, &InputXDeviceFactor::deviceAdd); connect(m_inputMonitor, &InputMonitor::deviceRemove, this, &InputXDeviceFactor::deviceRemove); } void InputXDeviceFactor::deviceAdd(int id) { int ndevices; XDeviceInfo* deviceList = XListInputDevices(UsdBaseClass::getQx11Info(),&ndevices); for (int i = 0 ; i < ndevices ; ++i) { if (id == deviceList[i].id) { InputDevice* device = filterDevice(deviceList[i]); if (device) { m_deviceManager->deviceAdd(device); } } } XFreeDeviceList(deviceList); } void InputXDeviceFactor::deviceRemove(int id) { m_deviceManager->deviceRemove(id); } /*********** InputWaylandDeviceFactor ***********/ #define UKUI_KWIN_OBJECT "/org/ukui/KWin/InputDevice" #define UKUI_KWIN_DEVICE_MANAGER "org.ukui.KWin.InputDeviceManager" #define KDE_KWIN_OBJECT "/org/kde/KWin/InputDevice" #define KDE_KWIN_DEVICE_MANAGER "org.kde.KWin.InputDeviceManager" InputWaylandDeviceFactor::InputWaylandDeviceFactor(QObject *parent) { m_deviceManager = reinterpret_cast(parent); m_deviceInterface = new QDBusInterface(QStringLiteral(KDE_KWIN_SERVICE), QStringLiteral(KDE_KWIN_OBJECT), QStringLiteral(KDE_KWIN_DEVICE_MANAGER), QDBusConnection::sessionBus(), this); if (!m_deviceInterface->isValid()) { m_deviceInterface = new QDBusInterface(QStringLiteral(UKUI_KWIN_SERVICE), QStringLiteral(UKUI_KWIN_OBJECT), QStringLiteral(UKUI_KWIN_DEVICE_MANAGER), QDBusConnection::sessionBus(), this); } if (m_deviceInterface->isValid()) { connectMonitor(); } } InputWaylandDeviceFactor::~InputWaylandDeviceFactor() { disconnect(m_deviceInterface, SIGNAL(deviceAdded(QString)),this, SLOT(deviceAdd(QString))); disconnect(m_deviceInterface, SIGNAL(deviceRemoved(QString)),this, SLOT(deviceRemove(QString))); } void InputWaylandDeviceFactor::initInputDevices() { if (m_deviceInterface->isValid()) { QStringList deviceList = m_deviceInterface->property("devicesSysNames").toStringList(); for (QString device : deviceList) { managerAddDevice(device); } } } void InputWaylandDeviceFactor::connectMonitor() { connect(m_deviceInterface, SIGNAL(deviceAdded(QString)),this, SLOT(deviceAdd(QString))); connect(m_deviceInterface, SIGNAL(deviceRemoved(QString)),this, SLOT(deviceRemove(QString))); } InputDevice *InputWaylandDeviceFactor::createInputDevice(QVariant deviceId, DeviceType type, QString name) { return new InputWaylandDevice(deviceId, type, name); } InputDevice *InputWaylandDeviceFactor::filterDevice(QDBusInterface * interface) { InputDevice *inputDevice = nullptr; if (interface->property("pointer").toBool() && !interface->property("keyboard").toBool()) { if (interface->property("touchpad").toBool()) { QString node = interface->property("sysName").toString(); QString name = interface->property("name").toString(); inputDevice = createInputDevice(node, DeviceType::IN_TOUCHPAD, name); } else if (interface->property("touch").toBool()) { //touch } else { QString node = interface->property("sysName").toString(); QString name = interface->property("name").toString(); inputDevice = createInputDevice(node, DeviceType::IN_MOUSE, name); } } else if (interface->property("keyboard").toBool()) { } return inputDevice; } void InputWaylandDeviceFactor::managerAddDevice(QString device) { QDBusInterface *interface = new QDBusInterface(KDE_KWIN_SERVICE, KDE_KWIN_OBJECT_PATH + device, KDE_KWIN_INTERFACE, QDBusConnection::sessionBus()); if (!interface->isValid()) { interface = new QDBusInterface(UKUI_KWIN_SERVICE, UKUI_KWIN_OBJECT_PATH + device, UKUI_KWIN_INTERFACE, QDBusConnection::sessionBus()); } if (interface->isValid()) { InputDevice* inputDevice = filterDevice(interface); if (inputDevice) { m_deviceManager->deviceAdd(inputDevice); } delete interface; interface = nullptr; } } void InputWaylandDeviceFactor::deviceAdd(QString device) { managerAddDevice(device); } void InputWaylandDeviceFactor::deviceRemove(QString device) { m_deviceManager->deviceRemove(device); } /*InputDeviceFactorManager*/ InputDeviceFactor *InputDeviceFactorManager::createDeviceFactor(InputDeviceManager* manager) { InputDeviceFactor* deviceFactor = nullptr; if (UsdBaseClass::isWayland()) { deviceFactor = new InputWaylandDeviceFactor(manager); } else { if (!supportXinputExtension()) { USD_LOG(LOG_WARNING,"X Input extension not available"); return nullptr; } deviceFactor = new InputXDeviceFactor(manager); } return deviceFactor; } ukui-settings-daemon/plugins/input-device-manager/input-gsettings.cpp0000664000175000017500000000774715167655063025146 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Authors: sundagao */ #include "input-gsettings.h" #include "clib-syslog.h" InputGsettings::InputGsettings(QObject *parent) : QObject(parent) { } InputGsettings::~InputGsettings() { clearMapData(); } InputGsettings *InputGsettings::instance() { static InputGsettings inputGsettings; return &inputGsettings; } const QList InputGsettings::getGsettingsKeys(DeviceType type) { switch (type) { case DeviceType::IN_MOUSE: return m_mouseData.keys(); break; case DeviceType::IN_TOUCHPAD: return m_touchpadData.keys(); break; default: break; } } QVariant InputGsettings::getGsettingsValue( const QString &key, DeviceType type) { switch (type) { case DeviceType::IN_MOUSE: return m_mouseData.value(key, QVariant(QVariant::Type::Invalid)); break; case DeviceType::IN_TOUCHPAD: return m_touchpadData.value(key, QVariant(QVariant::Type::Invalid)); break; default: break; } return QVariant(QVariant::Type::Invalid); } void InputGsettings::setGsettingsValue(const QString &key, const QVariant &value, DeviceType type) { switch (type) { case DeviceType::IN_MOUSE: m_mouseSettings->set(key, value); break; case DeviceType::IN_TOUCHPAD: m_touchpadSettings->set(key, value); break; default: break; } } void InputGsettings::initGsettings() { initMouseGsettings(); initTouchpadGsettings(); } bool InputGsettings::resultInitGsettings() { //包含GSETTINGS_INIT_RESULT ,配置初始化失败 return !(m_mouseData.contains(GSETTINGS_INIT_RESULT) && m_touchpadData.contains(GSETTINGS_INIT_RESULT)); } void InputGsettings::initMouseGsettings() { if (QGSettings::isSchemaInstalled(UKUI_MOUSE_SCHEMA)) { m_mouseSettings = GsettingsPtr(new QGSettings(UKUI_MOUSE_SCHEMA)); for (QString& key : m_mouseSettings->keys()) { m_mouseData.insert(key,m_mouseSettings->get(key)); } connect(m_mouseSettings.data(),SIGNAL(changed(const QString&)),this,SLOT(onMouseChanged(const QString&)),Qt::DirectConnection); } else { m_mouseData.insert(GSETTINGS_INIT_RESULT,false); } } void InputGsettings::initTouchpadGsettings() { if (QGSettings::isSchemaInstalled(UKUI_TOUCHPAD_SCHEMA)) { m_touchpadSettings = GsettingsPtr(new QGSettings(UKUI_TOUCHPAD_SCHEMA)); for (QString& key : m_touchpadSettings->keys()) { m_touchpadData.insert(key,m_touchpadSettings->get(key)); } connect(m_touchpadSettings.data(),SIGNAL(changed(const QString&)),this,SLOT(onTouchpadChanged(const QString&)),Qt::DirectConnection); } else { m_touchpadData.insert(GSETTINGS_INIT_RESULT,false); } } void InputGsettings::clearMapData() { GsettingsMap().swap(m_mouseData); GsettingsMap().swap(m_touchpadData); } //slots void InputGsettings::onMouseChanged(const QString &key) { QVariant value = m_mouseSettings->get(key); m_mouseData.insert(key,value); Q_EMIT mouseChanged(key,value); } void InputGsettings::onTouchpadChanged(const QString &key) { QVariant value = m_touchpadSettings->get(key); m_touchpadData.insert(key,value); Q_EMIT touchpadChanged(key,value); } ukui-settings-daemon/plugins/input-device-manager/input-process-settings.h0000664000175000017500000000265115167655063026105 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Authors: sundagao */ #ifndef PROCESSSETTINGS_H #define PROCESSSETTINGS_H #include #include class ProcessSettings : public QObject { Q_OBJECT public: static ProcessSettings* instance(); void setLocatePointer(bool state); void setDisableWTypingSynaptics(bool state); private: explicit ProcessSettings(QObject *parent = nullptr); ProcessSettings(const ProcessSettings&) = delete; ProcessSettings& operator =(const ProcessSettings&)=delete; private: bool m_locatePointerRunning = false; bool m_syndaemonRunning = false; bool isProcessRunning(const QString &processName); }; #endif // PROCESSSETTINGS_H ukui-settings-daemon/plugins/input-device-manager/input-plugin.cpp0000664000175000017500000000322415167655063024417 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Authors: sundagao */ #include "input-plugin.h" extern "C" { #include "clib-syslog.h" } InputPlugin::InputPlugin() { if (!m_inputDeviceManager) { m_inputDeviceManager = new InputDeviceManager; } } InputPlugin::~InputPlugin() { if (m_inputDeviceManager) { delete m_inputDeviceManager; m_inputDeviceManager = nullptr; } } PluginInterface *InputPlugin::getInstance() { static InputPlugin inputPlugin; return &inputPlugin; } void InputPlugin::activate() { if (m_inputDeviceManager) { USD_LOG(LOG_DEBUG,"input device manager is start."); m_inputDeviceManager->start(); } } void InputPlugin::deactivate() { if (m_inputDeviceManager) { USD_LOG(LOG_DEBUG,"input device manager is stop."); m_inputDeviceManager->stop(); } } PluginInterface* createSettingsPlugin() { return InputPlugin::getInstance(); } ukui-settings-daemon/plugins/input-device-manager/input-device-function.cpp0000664000175000017500000000543315167655063026207 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Authors: sundagao */ #include "input-device-function.h" #include "input-process-settings.h" extern const DeviceFunctionMap deviceFuncMap = { {KEY_LEFT_HANDED, InputDeviceFunction::setLeftMode}, {KEY_MOTION_ACCELERATION, InputDeviceFunction::setAcceleration}, {KEY_MOUSE_ACCEL, InputDeviceFunction::setAccelSpeed}, {KEY_MIDDLE_BUTTON_EMULATION, InputDeviceFunction::setMiddleButtonEmulation}, {KEY_MOUSE_WHEEL_SPEED, InputDeviceFunction::setWheelSpeed}, //imwheel {KEY_MOUSE_LOCATE_POINTER, InputDeviceFunction::setLocatePointer},//locatepointer {KEY_MOUSE_NATRUAL_SCROLLING, InputDeviceFunction::setNaturalScroll}, {KEY_TOUCHPAD_DISABLE_W_TYPING, InputDeviceFunction::setDisableTyping}, {KEY_TOUCHPAD_TAP_TO_CLICK, InputDeviceFunction::setTapclick}, {KEY_VERT_EDGE_SCROLL, InputDeviceFunction::setScrolling}, {KEY_VERT_TWO_FINGER_SCROLL, InputDeviceFunction::setScrolling}, {KEY_TOUCHPAD_ENABLED, InputDeviceFunction::setEnable}, {KEY_TOUCHPAD_DOUBLE_CLICK_DRAG, InputDeviceFunction::setTapDrag}, }; #define STATIC_FUNCTION_DEFINITION(name) \ void InputDeviceFunction::name(QVariant value, InputDevice* device) \ { \ if (device) { \ device->name(value); \ } \ } STATIC_FUNCTION_DEFINITION(setLeftMode) STATIC_FUNCTION_DEFINITION(setAcceleration) STATIC_FUNCTION_DEFINITION(setAccelSpeed) STATIC_FUNCTION_DEFINITION(setMiddleButtonEmulation) STATIC_FUNCTION_DEFINITION(setWheelSpeed) STATIC_FUNCTION_DEFINITION(setNaturalScroll) STATIC_FUNCTION_DEFINITION(setDisableTyping) STATIC_FUNCTION_DEFINITION(setTapclick) STATIC_FUNCTION_DEFINITION(setScrolling) STATIC_FUNCTION_DEFINITION(setEnable) STATIC_FUNCTION_DEFINITION(setTapDrag) //STATIC_FUNCTION_DEFINITION(setDisableTpMoPresent) void InputDeviceFunction::setLocatePointer(QVariant value, InputDevice*) { ProcessSettings::instance()->setLocatePointer(value.toBool()); } ukui-settings-daemon/plugins/input-device-manager/input-device.cpp0000664000175000017500000000272515167655063024365 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Authors: sundagao */ #include "input-device.h" #include "input-gsettings.h" InputDevice::InputDevice(QVariant id, DeviceType type, QString name, QObject *parent) : m_deviceId(id) , m_type(type) , m_deviceName(name) , QObject(parent) { } bool InputDevice::isMouse() { return m_type == DeviceType::IN_MOUSE; } bool InputDevice::isTouchpad() { return m_type == DeviceType::IN_TOUCHPAD; } QVariant InputDevice::getGsettingsValue(const QString &key) { return InputGsettings::instance()->getGsettingsValue(key, m_type); } void InputDevice::setGsettingsValue(const QString &key, const QVariant &value) { InputGsettings::instance()->setGsettingsValue(key, value, m_type); } ukui-settings-daemon/plugins/input-device-manager/input-common.h0000664000175000017500000000635115167655063024062 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Authors: sundagao */ #ifndef INPUTCOMMON_H #define INPUTCOMMON_H /* Keys with same names for both touchpad and mouse */ #define KEY_LEFT_HANDED "left-handed" /* a boolean for mouse, an enum for touchpad */ #define KEY_MOTION_ACCELERATION "motion-acceleration" #define KEY_MOTION_THRESHOLD "motion-threshold" /* Mouse settings */ #define UKUI_MOUSE_SCHEMA "org.ukui.peripherals-mouse" #define KEY_MOUSE_LOCATE_POINTER "locate-pointer" #define KEY_MIDDLE_BUTTON_EMULATION "middle-button-enabled" #define KEY_MOUSE_WHEEL_SPEED "wheel-speed" #define KEY_MOUSE_ACCEL "mouse-accel" #define KEY_MOUSE_NATRUAL_SCROLLING "natural-scroll" /* Touchpad settings */ #define UKUI_TOUCHPAD_SCHEMA "org.ukui.peripherals-touchpad" #define KEY_TOUCHPAD_DISABLE_W_TYPING "disable-while-typing" #define KEY_TOUCHPAD_TWO_FINGER_CLICK "two-finger-click" #define KEY_TOUCHPAD_THREE_FINGER_CLICK "three-finger-click" #define KEY_TOUCHPAD_NATURAL_SCROLL "natural-scroll" #define KEY_TOUCHPAD_TAP_TO_CLICK "tap-to-click" #define KEY_TOUCHPAD_ONE_FINGER_TAP "tap-button-one-finger" #define KEY_TOUCHPAD_TWO_FINGER_TAP "tap-button-two-finger" #define KEY_TOUCHPAD_THREE_FINGER_TAP "tap-button-three-finger" #define KEY_VERT_EDGE_SCROLL "vertical-edge-scrolling" #define KEY_HORIZ_EDGE_SCROLL "horizontal-edge-scrolling" #define KEY_VERT_TWO_FINGER_SCROLL "vertical-two-finger-scrolling" #define KEY_HORIZ_TWO_FINGER_SCROLL "horizontal-two-finger-scrolling" #define KEY_TOUCHPAD_ENABLED "touchpad-enabled" #define KEY_TOUCHPAD_DISBLE_O_E_MOUSE "disable-on-external-mouse" //插入鼠标,禁用触摸板 true/false #define KEY_TOUCHPAD_DOUBLE_CLICK_DRAG "double-click-drag" //点击两次拖动 true/false #define KEY_TOUCHPAD_BOTTOM_R_C_CLICK_M "bottom-right-corner-click-menu" //右下角点击菜单 true/false #define KEY_TOUCHPAD_MOUSE_SENSITVITY "mouse-sensitivity" //鼠标敏感度 1-4 四个档位 低中高最高 enum class DeviceType{ IN_NONE, //无 IN_MOUSE, //鼠标 IN_TOUCHPAD, //触控板 IN_TOUCHSCREEN, //触控屏 IN_TABLET, //触控笔 IN_JOYSTICK, //摇杆设备 IN_KEYBOARD, //键盘 //trackpoint 设备 IN_TRACKPOINT= 100 //联想红点设备 }; #endif // INPUTCOMMON_H ukui-settings-daemon/plugins/input-device-manager/input-device.h0000664000175000017500000000430015167655063024021 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Authors: sundagao */ #ifndef INPUTDEVICE_H #define INPUTDEVICE_H #include #include #include "input-common.h" class InputDevice : public QObject { Q_OBJECT public: explicit InputDevice(QVariant id, DeviceType type, QString name, QObject *parent); virtual ~InputDevice(){} bool isMouse(); bool isTouchpad(); QVariant getDeviceId(){return m_deviceId;} DeviceType getDeviceType(){return m_type;} QString getDeviceName(){return m_deviceName;} public: virtual void setEnable(QVariant value) = 0; virtual void setLeftMode(QVariant value) = 0; virtual void setNaturalScroll(QVariant value) = 0; virtual void setTapclick(QVariant value) = 0; virtual void setTapDrag(QVariant value) = 0; virtual void setDisableTyping(QVariant value) = 0; virtual void setAccelSpeed(QVariant value) = 0; virtual void setAcceleration(QVariant value) = 0; virtual void setMiddleButtonEmulation(QVariant value) = 0; virtual void setScrolling(QVariant value) = 0; virtual void setDisableTpMoPresent(QVariant value) = 0; virtual void setWheelSpeed(QVariant value) = 0; public: virtual QVariant getProductId() = 0; Q_SIGNALS: protected: QVariant getGsettingsValue(const QString& key); void setGsettingsValue(const QString& key, const QVariant& value); protected: QVariant m_deviceId; QString m_deviceName; DeviceType m_type; }; #endif // INPUTDEVICE_H ukui-settings-daemon/plugins/input-device-manager/input-monitor.h0000664000175000017500000000264015167655063024256 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Authors: sundagao */ #ifndef INPUTMONITOR_H #define INPUTMONITOR_H #include class InputMonitor : public QObject { Q_OBJECT public: static InputMonitor* instance(); void stopMontior(); private: explicit InputMonitor(QObject *parent = nullptr); InputMonitor(const InputMonitor&)=delete; InputMonitor& operator =(const InputMonitor&)=delete; private: void hierarchyChangedEvent(void *data); public Q_SLOTS: void startMonitor(); private Q_SLOTS: void listeningStart(); Q_SIGNALS: void deviceAdd(int id); void deviceRemove(int id); private: bool m_stop = false; }; #endif // INPUTMONITOR_H ukui-settings-daemon/plugins/input-device-manager/input-device-manager.cpp0000664000175000017500000001512515167655063025773 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Authors: sundagao */ #include "input-device-manager.h" #include "input-device-helper.h" #include "input-device-function.h" #define TEST_PRINT using namespace InputDeviceHelper; extern const DeviceFunctionMap deviceFuncMap; InputDeviceManager::InputDeviceManager(QObject *parent) : QObject(parent) { m_timer = new QTimer(this); } InputDeviceManager::~InputDeviceManager() { disconnectAll(); clearUpDeviceList(); } void InputDeviceManager::start() { connect(m_timer, &QTimer::timeout, this, &InputDeviceManager::managerStart); m_timer->start(); } void InputDeviceManager::stop() { disconnectAll(); clearUpDeviceList(); } bool InputDeviceManager::initDeviceFactor() { //初始化设备factor,获取设备列表 m_deviceFactor = InputDeviceFactorManager::createDeviceFactor(this); if (!m_deviceFactor) { return false; } m_deviceFactor->initInputDevices(); return true; } void InputDeviceManager::eliminateSpecialDevice() { for (InputDevice *touchpad : m_touchpadList) { QVariant touchProduct = touchpad->getProductId(); USD_LOG(LOG_DEBUG,"touchProduct : %d", touchProduct.toInt()); for (InputDevice* mouse : m_mouseList) { QVariant mouseProduct = mouse->getProductId(); USD_LOG(LOG_DEBUG,"mouseProduct : %d", mouseProduct.toInt()); if (touchProduct == mouseProduct) { m_mouseList.removeAll(mouse); } } } } //清空设备列表 void InputDeviceManager::clearUpDeviceList() { qDeleteAll(m_mouseList); m_mouseList.clear(); qDeleteAll(m_touchpadList); m_touchpadList.clear(); } void InputDeviceManager::connctGsettings() { //gsettings 改变 connect(m_inputGsettings,&InputGsettings::mouseChanged,this,&InputDeviceManager::onMouseChanged); connect(m_inputGsettings,&InputGsettings::touchpadChanged,this,&InputDeviceManager::onTouchpadChanged); } void InputDeviceManager::disconnectAll() { //断开监听 disconnect(m_inputGsettings,&InputGsettings::mouseChanged,this,&InputDeviceManager::onMouseChanged); disconnect(m_inputGsettings,&InputGsettings::touchpadChanged,this,&InputDeviceManager::onTouchpadChanged); } void InputDeviceManager::classifyDevice(InputDevice *device) { DeviceType type = device->getDeviceType(); switch (type) { case DeviceType::IN_MOUSE: m_mouseList.append(device); break; case DeviceType::IN_TOUCHPAD: m_touchpadList.append(device); break; case DeviceType::IN_TOUCHSCREEN: /* * * */ break; default: break; } } bool InputDeviceManager::deleteDevice(QVariant deviceId) { for (InputDevice* device : m_mouseList) { if (deviceId == device->getDeviceId()) { m_mouseList.removeOne(device); return true; } } for (InputDevice* device : m_touchpadList) { if (deviceId == device->getDeviceId()) { m_touchpadList.removeOne(device); return true; } } return false; } bool InputDeviceManager::existMouse() { return m_mouseList.count(); } void InputDeviceManager::testPrintDeviceList() { for (InputDevice* device : m_mouseList) { USD_LOG(LOG_DEBUG,"mouse device name : %s - device id %s",device->getDeviceName().toLatin1().data(),device->getDeviceId().toString().toLatin1().data()); } for (InputDevice* device : m_touchpadList) { USD_LOG(LOG_DEBUG,"touchpad device name : %s - device id %s",device->getDeviceName().toLatin1().data(),device->getDeviceId().toString().toLatin1().data()); } } #define device_function(list, key, value) \ auto func = deviceFuncMap.value(key); \ if (func) { \ for (InputDevice* device : list) { \ func(value, device); \ } \ } #define disable_touchpad_on_external_mouse(prama) \ for (InputDevice* device : m_touchpadList) {\ device->setDisableTpMoPresent(prama); \ } void InputDeviceManager::disbleTouchpadMousePresent() { disable_touchpad_on_external_mouse(QVariant(existMouse())); } void InputDeviceManager::onMouseChanged(const QString& key, QVariant value) { USD_LOG(LOG_DEBUG,"mouse property %s is changed",key.toLatin1().data()); if (key == QStringLiteral(KEY_MOUSE_LOCATE_POINTER)) { InputDeviceFunction::setLocatePointer(value); } else { device_function(m_mouseList, key, value); } } void InputDeviceManager::onTouchpadChanged(const QString &key, QVariant value) { USD_LOG(LOG_DEBUG,"touchpad property %s is changed",key.toLatin1().data()); if (key == QStringLiteral(KEY_TOUCHPAD_DISBLE_O_E_MOUSE)) { // 插入鼠标禁用触摸板 disable_touchpad_on_external_mouse(QVariant(existMouse())); } else { device_function(m_touchpadList, key, value); } } //slots void InputDeviceManager::deviceAdd(InputDevice* device) { classifyDevice(device); eliminateSpecialDevice(); disbleTouchpadMousePresent(); #ifdef TEST_PRINT testPrintDeviceList(); #endif } void InputDeviceManager::deviceRemove(QVariant deviceId) { deleteDevice(deviceId); disbleTouchpadMousePresent(); #ifdef TEST_PRINT testPrintDeviceList(); #endif } void InputDeviceManager::managerStart() { m_timer->stop(); m_inputGsettings = InputGsettings::instance(); m_inputGsettings->initGsettings(); //gsettings init failed if (!m_inputGsettings->resultInitGsettings()) { USD_LOG(LOG_WARNING,"input gsettings init failed ."); return; } //初始化设备工场 if (!initDeviceFactor()) { USD_LOG(LOG_WARNING,"init device factor failed ."); return; } //剔除与触摸板Product ID 一致的mouse设备 eliminateSpecialDevice(); //gsettings 改变 connctGsettings(); disbleTouchpadMousePresent(); #ifdef TEST_PRINT testPrintDeviceList(); #endif } ukui-settings-daemon/plugins/input-device-manager/input-device-helper.cpp0000664000175000017500000002124515167655063025640 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Authors: sundagao */ #include "input-device-helper.h" static Display* display = UsdBaseClass::getQx11Info(); Atom InputDeviceHelper::properyToAtom(const char* property) { return XInternAtom(display,property,False); } bool InputDeviceHelper::supportXinputExtension() { int xi_opcode ,event ,error; return XQueryExtension(display, "XInputExtension" , &xi_opcode , &event, &error); } Atom InputDeviceHelper::deviceHadProperty(int device, const char *property) { Atom prop = properyToAtom(property); return deviceHadProperty(device, prop); } Atom InputDeviceHelper::deviceHadProperty(int device, Atom prop) { int num_props; Atom found = None; Atom* props = XIListProperties(display,device,&num_props); if (prop == None || !props) { USD_LOG(LOG_WARNING,"get prop/props is failed"); return found; } for (int i = 0; i < num_props; ++i) { if (prop == props[i]) { found = prop; } } XFree(props); return found; } QVariantList InputDeviceHelper::getDeviceProp(int device, const char* property) { Atom prop = properyToAtom(property); return getDeviceProp(device, prop); } QVariantList InputDeviceHelper::getDeviceProp(int device, Atom prop) { QVariantList valueList; Atom real_type; int real_format; unsigned long nitems; unsigned long bytes_after; unsigned char* data = nullptr; unsigned char* dataPtr = nullptr; if (Success == XIGetProperty(display, device, prop, 0, 1000, False, AnyPropertyType, &real_type, &real_format, &nitems, &bytes_after, &data)) { dataPtr = data; Atom float_atom = properyToAtom("FLOAT"); for (int i = 0; i < nitems; ++i) { switch (real_type) { case XA_INTEGER: switch (real_format) { case 8: valueList << *(reinterpret_cast(dataPtr)); break; case 16: valueList << *(reinterpret_cast(dataPtr)); break; case 32: valueList << *(reinterpret_cast(dataPtr)); break; default: break; } break; default: if (float_atom == real_type && real_format == 32) { valueList << *(reinterpret_cast(dataPtr)); } else { USD_LOG(LOG_DEBUG,"property real type is not expanded. real type :%d",real_type); } break; } dataPtr += real_format / 8; } XFree(data); } else { USD_LOG(LOG_WARNING,"get device propetry failed ."); } return valueList; } void InputDeviceHelper::setDeviceProp(int device, const char *property, QVariantList value) { Atom prop = properyToAtom(property); return setDeviceProp(device, prop, value); } void InputDeviceHelper::setDeviceProp(int device, Atom prop ,QVariantList value) { if (prop == None) { USD_LOG(LOG_WARNING,"device property is none ."); return; } Atom real_type; int real_format; unsigned long nitems; unsigned long bytes_after; union { unsigned char *c; int16_t *s; int32_t *l; } data = {nullptr}; if (Success != XIGetProperty(display, device, prop, 0, 0, False, AnyPropertyType, &real_type, &real_format, &nitems, &bytes_after, &data.c)) { USD_LOG(LOG_WARNING,"get device propetry failed ."); return; } XFree(data.c); Atom float_atom = properyToAtom("FLOAT"); int count = value.count(); data.c = reinterpret_cast(calloc(count,sizeof(int32_t))); for (int i = 0; i < count; ++i) { switch (real_type) { //目前设置的属性fomat,以下case都已包含,如有需要可以添加 case XA_INTEGER: switch (real_format) { case 8: data.c[i] = value.at(i).toInt(); break; case 16: data.l[i] = value.at(i).toInt(); break; case 32: data.l[i] = value.at(i).toInt(); break; default: break; } break; default: if (float_atom == real_type && real_format == 32) { reinterpret_cast(data.l)[i] = value.at(i).toFloat(); } break; } } XIChangeProperty (display, device,prop, real_type, real_format, PropModeReplace, data.c, count); XSync(display,False); free(data.c); } int InputDeviceHelper::getDeviceButtonMap(int device, unsigned char** map) { int ndevice; int nbuttons = 0; XDeviceInfo* deviceInfos = nullptr; XDeviceInfo* deviceinfo = nullptr; deviceInfos = XListInputDevices(display,&ndevice); for (int i = 0; i < ndevice; ++i) { if (device == deviceInfos[i].id) { deviceinfo = &deviceInfos[i]; } } if (!deviceinfo) { USD_LOG(LOG_WARNING,"con't find device ."); XFreeDeviceList(deviceInfos); return nbuttons; } XDevice* dev = XOpenDevice(display,device); if (!dev) { USD_LOG(LOG_WARNING,"open device %d is failed",dev->device_id); return nbuttons; } for (int i = 0; i < deviceinfo->num_classes; ++i) { if (deviceinfo->inputclassinfo->c_class == ButtonClass) { nbuttons = reinterpret_cast(deviceinfo->inputclassinfo)->num_buttons; } } *map = reinterpret_cast(malloc(sizeof(unsigned char)*nbuttons)); nbuttons = XGetDeviceButtonMapping(display,dev,*map,nbuttons); XCloseDevice(display,dev); XFreeDeviceList(deviceInfos); return nbuttons; } void InputDeviceHelper::setDeviceButtonMap(int device, int nbuttons, unsigned char* map) { XDevice* dev = XOpenDevice(display,device); if (!dev) { USD_LOG(LOG_WARNING,"open device %d is failed",device); return; } XSetDeviceButtonMapping(display,dev,map,nbuttons); XCloseDevice(display,dev); XFree(map); } void InputDeviceHelper::changePtrFeedbackControl(int device , int threshold, int numerator, int denominator) { XDevice* dev = XOpenDevice(display, device); if (!dev) { USD_LOG(LOG_WARNING,"open device %d is failed",device); return; } int nFeedbacks; XFeedbackState *state = XGetFeedbackControl(display, dev, &nFeedbacks); if (!state) { USD_LOG(LOG_WARNING,"get feedback states failed ."); return; } int id = -1; for (int i = 0; i < nFeedbacks; ++i) { if (state->c_class == PtrFeedbackClass) { id = state->id; break; } state = reinterpret_cast((reinterpret_cast(state) + state->length)); } XFreeFeedbackList(state); if (-1 == id) { USD_LOG(LOG_WARNING,"unable find ptrfeedback ."); return ; } XPtrFeedbackControl feedback; feedback.c_class = PtrFeedbackClass; feedback.length = sizeof(XPtrFeedbackControl); feedback.id = id; feedback.threshold = threshold; feedback.accelNum = numerator; feedback.accelDenom = denominator; XChangeFeedbackControl(display, dev, DvAccelNum | DvAccelDenom | DvThreshold, (XFeedbackControl *)&feedback); } //禁用设备 void InputDeviceHelper::disable(int device) { Atom prop = properyToAtom("Device Enabled"); QVariantList list; list << false; setDeviceProp(device, prop, list); } //启用设备 void InputDeviceHelper::enabel(int device) { Atom prop = properyToAtom("Device Enabled"); QVariantList list; list << true; setDeviceProp(device, prop, list); } ukui-settings-daemon/plugins/input-device-manager/input-device-function.h0000664000175000017500000000347615167655063025661 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Authors: sundagao */ #ifndef INPUTDEVICEFUNCTION_H #define INPUTDEVICEFUNCTION_H #include "input-device.h" #include typedef QMap> DeviceFunctionMap; class InputDeviceFunction { public: /*static set fuction*/ #define STATIC_FUNCTION_DECLARATION(name) \ static void name(QVariant value, InputDevice* device = nullptr); \ STATIC_FUNCTION_DECLARATION(setLeftMode) STATIC_FUNCTION_DECLARATION(setAcceleration) STATIC_FUNCTION_DECLARATION(setAccelSpeed) STATIC_FUNCTION_DECLARATION(setMiddleButtonEmulation) STATIC_FUNCTION_DECLARATION(setWheelSpeed) STATIC_FUNCTION_DECLARATION(setLocatePointer) STATIC_FUNCTION_DECLARATION(setNaturalScroll) STATIC_FUNCTION_DECLARATION(setDisableTyping) STATIC_FUNCTION_DECLARATION(setTapclick) STATIC_FUNCTION_DECLARATION(setScrolling) STATIC_FUNCTION_DECLARATION(setEnable) STATIC_FUNCTION_DECLARATION(setTapDrag) // STATIC_FUNCTION_DECLARATION(setDisableTpMoPresent) }; #endif // INPUTDEVICEFUNCTION_H ukui-settings-daemon/plugins/input-device-manager/input-device-manager.pro0000664000175000017500000000320415167655063026004 0ustar fengfengQT += gui core TEMPLATE = lib TARGET = input-device-manager CONFIG += c++20 plugin include($$PWD/../../common/common.pri) # The following define makes your compiler emit warnings if you use # any Qt feature that has been marked deprecated (the exact warnings # depend on your compiler). Please consult the documentation of the # deprecated API in order to know how to port your code away from it. DEFINES += QT_DEPRECATED_WARNINGS DEFINES += INPUTDEVICEMANAGER_LIBRARY MODULE_NAME=\\\"input-device-manager\\\" # You can also make your code fail to compile if it uses deprecated APIs. # In order to do so, uncomment the following line. # You can also select to disable deprecated APIs only up to a certain version of Qt. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 SOURCES += \ input-device-factory.cpp \ input-device-function.cpp \ input-device-helper.cpp \ input-device-manager.cpp \ input-device.cpp \ input-monitor.cpp \ input-plugin.cpp \ input-gsettings.cpp \ input-process-settings.cpp \ input-wayland-device.cpp \ input-x-device.cpp HEADERS += \ input-common.h \ input-device-factory.h \ input-device-function.h \ input-device-helper.h \ input-device-manager.h \ input-device.h \ input-monitor.h \ input-plugin.h \ input-gsettings.h \ input-process-settings.h \ input-wayland-device.h \ input-x-device.h # Default rules for deployment. input-device-manager_lib.path = $${PLUGIN_INSTALL_DIRS} input-device-manager_lib.files = $$OUT_PWD/libinput-device-manager.so INSTALLS += input-device-manager_lib ukui-settings-daemon/plugins/auto-brightness/0000775000175000017500000000000015167655063020371 5ustar fengfengukui-settings-daemon/plugins/auto-brightness/autoBrightness-manager.h0000664000175000017500000000511515167655063025155 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef AUTOBRIGHTNESSMANAGER_H #define AUTOBRIGHTNESSMANAGER_H #include #include #include #include #include #include "brightThread.h" class AutoBrightnessManager : public QObject { Q_OBJECT private: AutoBrightnessManager(); AutoBrightnessManager(AutoBrightnessManager&)=delete; AutoBrightnessManager&operator=(const AutoBrightnessManager&)=delete; public: ~AutoBrightnessManager(); static AutoBrightnessManager *autoBrightnessManagerNew(); bool autoBrightnessManagerStart(); void autoBrightnessManagerStop(); public Q_SLOTS: void sensorReadingChangedSlot(); void sensorActiveChangedSlot(); void gsettingsChangedSlot(QString key); void idleModeChangeSlot(quint32 mode); void powerManagerSchemaChangedSlot(QString key); void brightnessThreadFinishedSlot(); private: bool sensorExist(); void setEnabled(bool enabled); void enableSensorAndSetGsettings(bool state); void adjustBrightnessWithLux(qreal lux); void enableDynamicBrightness(); //设置背光前先断开powerManager的信号,待设置成功后再进行链接。避免自己设置的回调。 void connectPowerManagerSchema(bool state); private: bool m_enableAutoBrightness; bool m_hadSensor; bool m_userIntervene;//暂时仅仅做记录或者调试模式使用,暂未复杂的用法,只是用户调整亮度后在下次空闲前不再调整亮度。 int m_enabled; QGSettings *m_autoBrightnessSettings; QGSettings *m_powerManagerSettings; QLightSensor *m_lightSensor; BrightThread *m_brightnessThread; static AutoBrightnessManager *m_autoBrightnessManager; }; #endif // AUTOBRIGHTNESSMANAGER_H ukui-settings-daemon/plugins/auto-brightness/brightThread.cpp0000664000175000017500000000711415167655063023507 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "brightThread.h" #include #include #include #include #include #include "usd_global_define.h" #include "QGSettings/qgsettings.h" extern "C"{ #include #include #include "clib-syslog.h" } //空闲模式不进行亮度处理 BrightThread::BrightThread(QObject *parent): m_stop(false) { bool ret = false; m_powerSettings = new QGSettings(POWER_MANAGER_SCHEMA); if (nullptr == m_powerSettings) { USD_LOG(LOG_DEBUG,"can't find %s", POWER_MANAGER_SCHEMA); } m_brightnessSettings = new QGSettings(AUTO_BRIGHTNESS_SCHEMA); if (nullptr == m_brightnessSettings) { return; } m_delayms = m_brightnessSettings->get(DELAYMS_KEY).toInt(&ret); if (false == ret) { USD_LOG(LOG_DEBUG,"can't find delayms"); m_delayms = 30; } USD_LOG_SHOW_PARAM1(m_delayms); } //待电源管理优化内部处理。 //需要电源管理重新建立一个设置背光的接口,包含目标亮度与设置时间,以及设置完毕的signal与实时亮度的dbus,signal。usd调用接口传递设置间隔和目标亮度给电源管理,有电源管理进行线性处理, //其他组件要想同步线性曲线,就监控实时亮度的dbus上的signal。 void BrightThread::run(){ int currentBrightnessValue; if (nullptr == m_powerSettings) { return; } if (false == m_powerSettings->keys().contains(BRIGHTNESS_AC_KEY)) { return; } currentBrightnessValue = m_powerSettings->get(BRIGHTNESS_AC_KEY).toInt(); USD_LOG(LOG_DEBUG,"start set brightness"); m_stop = false; while(currentBrightnessValue != m_destBrightness) { if (m_stop) { USD_LOG(LOG_DEBUG,"start set brightness interrupt."); return; } if (currentBrightnessValue>m_destBrightness){ currentBrightnessValue--; } else { currentBrightnessValue++; } m_powerSettings->set(BRIGHTNESS_AC_KEY, currentBrightnessValue); m_powerSettings->apply(); msleep(m_delayms);//30 ms效果较好。 } USD_LOG(LOG_DEBUG,"set brightness over"); } void BrightThread::stopImmediately(){ m_stop = true; } void BrightThread::setBrightness(int brightness) { m_destBrightness = brightness; // USD_LOG(LOG_DEBUG,brightness); USD_LOG_SHOW_PARAM1(brightness); } int BrightThread::getRealTimeBrightness() { if (false == m_powerSettings->keys().contains(BRIGHTNESS_AC_KEY)) { return -1; } return m_powerSettings->get(BRIGHTNESS_AC_KEY).toInt(); } BrightThread::~BrightThread() { if (m_powerSettings) { delete m_powerSettings; m_powerSettings = nullptr; } if (m_brightnessSettings) { delete m_brightnessSettings; m_brightnessSettings = nullptr; } } ukui-settings-daemon/plugins/auto-brightness/autoBrightness-plugin.cpp0000664000175000017500000000417315167655063025377 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "clib-syslog.h" #include "autoBrightness-plugin.h" PluginInterface *AutoBrightnessPlugin::m_instance = nullptr; AutoBrightnessManager *AutoBrightnessPlugin::m_autoBrightnessManager = nullptr; AutoBrightnessPlugin::AutoBrightnessPlugin() { USD_LOG(LOG_DEBUG,"AutoBrightness Plugin initializing"); if(nullptr == m_autoBrightnessManager) m_autoBrightnessManager = AutoBrightnessManager::autoBrightnessManagerNew(); } AutoBrightnessPlugin::~AutoBrightnessPlugin() { if(m_autoBrightnessManager) { delete m_autoBrightnessManager; m_autoBrightnessManager = nullptr; } if(m_instance) { delete m_instance; m_instance = nullptr; } } void AutoBrightnessPlugin::activate() { bool res; USD_LOG(LOG_DEBUG,"Activating AutoBrightness plugins"); res = m_autoBrightnessManager->autoBrightnessManagerStart(); if(!res) { USD_LOG(LOG_ERR,"Unable to start AutoBrightness manager"); } } PluginInterface *AutoBrightnessPlugin::getInstance() { if(nullptr == m_instance) { m_instance = new AutoBrightnessPlugin(); } return m_instance; } void AutoBrightnessPlugin::deactivate() { USD_LOG(LOG_DEBUG, "Deactivating AutoBrightness plugin"); m_autoBrightnessManager->autoBrightnessManagerStop(); } PluginInterface *createSettingsPlugin() { return AutoBrightnessPlugin::getInstance(); } ukui-settings-daemon/plugins/auto-brightness/auto-brightness.pro0000664000175000017500000000143415167655063024233 0ustar fengfengQT += gui widgets gui-private dbus TARGET = auto-brightness TEMPLATE = lib CONFIG += c++20 plugin link_pkgconfig DEFINES += TABLETMODE_LIBRARY QT_DEPRECATED_WARNINGS MODULE_NAME=\\\"auto-brightness\\\" LIBS += -lQt6Sensors include($$PWD/../../common/common.pri) INCLUDEPATH += \ -I $$PWD/../../common/ \ -I ukui-settings-daemon/ \ -I /usr/include/ PKGCONFIG += \ xrandr x11 \ glib-2.0 SOURCES += \ autoBrightness-manager.cpp \ autoBrightness-plugin.cpp \ brightThread.cpp HEADERS += \ autoBrightness-manager.h \ autoBrightness-plugin.h \ brightThread.h auto_brightness_lib.path = $${PLUGIN_INSTALL_DIRS} auto_brightness_lib.files = $$OUT_PWD/libauto-brightness.so INSTALLS += auto_brightness_lib ukui-settings-daemon/plugins/auto-brightness/autoBrightness-plugin.h0000664000175000017500000000267715167655063025053 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef AUTOBRIGHTNESSPLUGIN_H #define AUTOBRIGHTNESSPLUGIN_H #include #include "plugin-interface.h" #include "autoBrightness-manager.h" #include "clib-syslog.h" #include "brightThread.h" class AutoBrightnessPlugin : public PluginInterface { private: AutoBrightnessPlugin(); AutoBrightnessPlugin(AutoBrightnessPlugin&)=delete; public: ~AutoBrightnessPlugin(); static PluginInterface *getInstance(); virtual void activate(); virtual void deactivate(); private: static AutoBrightnessManager *m_autoBrightnessManager; static PluginInterface *m_instance; }; extern "C" Q_DECL_EXPORT PluginInterface *createSettingsPlugin(); #endif // AUTOBRIGHTNESSPLUGIN_H ukui-settings-daemon/plugins/auto-brightness/brightThread.h0000664000175000017500000000246215167655063023155 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef BRIGHTTHREAD_H #define BRIGHTTHREAD_H #include #include #include "QGSettings/qgsettings.h" class BrightThread : public QThread { Q_OBJECT public: BrightThread(QObject *parent = nullptr); ~BrightThread(); void stopImmediately(); void setBrightness(int brightness); int getRealTimeBrightness(); protected: void run(); private: int m_destBrightness; int m_delayms; QGSettings *m_powerSettings; QGSettings *m_brightnessSettings; bool m_stop; QMutex m_lock; }; #endif // BRIGHTTHREAD_H ukui-settings-daemon/plugins/auto-brightness/autoBrightness-manager.cpp0000664000175000017500000002426415167655063025516 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include "usd_base_class.h" #include "usd_global_define.h" #include "autoBrightness-manager.h" extern "C"{ #include #include #include } #define BRIGHTNESS_40_LOW_LIMIT 0 #define BRIGHTNESS_40_UP_LIMIT 70 #define BRIGHTNESS_80_LOW_LIMIT 90 #define BRIGHTNESS_80_UP_LIMIT 600 #define BRIGHTNESS_100_LOW_LIMIT 800 #define BRIGHTNESS_100_UP_LIMIT 9999999 AutoBrightnessManager *AutoBrightnessManager::m_autoBrightnessManager = nullptr; //如果开启自动背光,系统由空闲进入忙时,电源管理不进行亮度处理,由usd的光感模式处理 AutoBrightnessManager::AutoBrightnessManager(): m_enabled(0xff) , m_brightnessThread(NULL) ,m_userIntervene(false) { m_lightSensor = new QLightSensor(this); m_autoBrightnessSettings = new QGSettings(AUTO_BRIGHTNESS_SCHEMA); m_powerManagerSettings = new QGSettings(POWER_MANAGER_SCHEMA); m_lightSensor->start();//预先读取一次,为了确保sensor存在,取到后直接关闭。 } AutoBrightnessManager::~AutoBrightnessManager() { if (m_autoBrightnessManager) { delete m_autoBrightnessManager; m_autoBrightnessManager = nullptr; } if (m_lightSensor) { delete m_lightSensor; m_lightSensor = nullptr; } if (m_autoBrightnessSettings) { delete m_autoBrightnessSettings; m_autoBrightnessSettings = nullptr; } if (m_brightnessThread) { m_brightnessThread->stopImmediately(); m_brightnessThread->deleteLater(); } if (m_powerManagerSettings) { m_powerManagerSettings->deleteLater(); } } AutoBrightnessManager *AutoBrightnessManager::autoBrightnessManagerNew() { if (nullptr == m_autoBrightnessManager) { m_autoBrightnessManager = new AutoBrightnessManager(); } return m_autoBrightnessManager; } void AutoBrightnessManager::sensorReadingChangedSlot() { QLightReading * lightReading = m_lightSensor->reading(); if (nullptr == lightReading || false == m_lightSensor->isActive()) { USD_LOG(LOG_DEBUG, "lux read error...."); return; } qreal realTimeLux = lightReading->lux(); adjustBrightnessWithLux(realTimeLux); } void AutoBrightnessManager::sensorActiveChangedSlot() { USD_LOG_SHOW_PARAM1(m_lightSensor->isActive()); sensorReadingChangedSlot(); } void AutoBrightnessManager::setEnabled(bool enabled) { if (m_enabled == enabled) { return; } m_enabled = enabled; if (m_enabled) { m_lightSensor->setActive(true); m_lightSensor->start(); sensorActiveChangedSlot(); connect(m_lightSensor, SIGNAL(readingChanged()), this, SLOT(sensorReadingChangedSlot())); connect(m_lightSensor, SIGNAL(activeChanged()), this, SLOT(sensorActiveChangedSlot())); } else { if (m_brightnessThread) { m_brightnessThread->stopImmediately(); } m_lightSensor->setActive(false); m_lightSensor->stop(); disconnect(m_lightSensor, SIGNAL(readingChanged()), this, SLOT(sensorReadingChangedSlot())); disconnect(m_lightSensor, SIGNAL(activeChanged()), this, SLOT(sensorActiveChangedSlot())); } } void AutoBrightnessManager::gsettingsChangedSlot(QString key) { int debugLux = 0; if (key == AUTO_BRIGHTNESS_KEY) { m_enableAutoBrightness = m_autoBrightnessSettings->get(AUTO_BRIGHTNESS_KEY).toBool(); enableSensorAndSetGsettings(m_enableAutoBrightness); } else if (key == DYNAMIC_BRIGHTNESS_KEY){ // enableDynamicBrightness(); } else if (key == DEBUG_LUX_KEY) { if (m_autoBrightnessSettings->get(DEBUG_MODE_KEY).toBool()) { if (m_userIntervene) { return; } debugLux = m_autoBrightnessSettings->get(DEBUG_LUX_KEY).toInt(); adjustBrightnessWithLux(debugLux); } } else if (key == DEBUG_MODE_KEY) {//开启调试就要禁用自动 m_enableAutoBrightness =!(m_autoBrightnessSettings->get(DEBUG_MODE_KEY).toBool()); enableSensorAndSetGsettings(m_enableAutoBrightness); } } void AutoBrightnessManager::idleModeChangeSlot(quint32 mode) { USD_LOG_SHOW_PARAM1(mode); if (m_enableAutoBrightness == false) { USD_LOG_SHOW_PARAM1(m_enableAutoBrightness); return; } USD_LOG_SHOW_PARAM1(mode); if (mode == SESSION_BUSY) { setEnabled(true);//尽量操作硬件停止向上层发送数据,减少系统开销。 } else if (mode == SESSION_IDLE) { m_userIntervene = false; //用户干预后空闲模式才进行恢复自动控制 setEnabled(false); } } void AutoBrightnessManager::powerManagerSchemaChangedSlot(QString key) { if (key == BRIGHTNESS_AC_KEY) { USD_LOG(LOG_DEBUG, "brightness had changed by other"); m_userIntervene = true; setEnabled(false); } } void AutoBrightnessManager::brightnessThreadFinishedSlot() { USD_LOG(LOG_DEBUG,"brightness had finished..."); connectPowerManagerSchema(true); } bool AutoBrightnessManager::sensorExist() { bool ret = false; QDBusInterface sensorIft("net.hadess.SensorProxy", "/net/hadess/SensorProxy", "net.hadess.SensorProxy", QDBusConnection::systemBus()); if (sensorIft.isValid()) { ret = sensorIft.property("HasAmbientLight").toBool(); } USD_LOG_SHOW_PARAM1(ret); return ret; } void AutoBrightnessManager::enableSensorAndSetGsettings(bool state) { setEnabled(state); } void AutoBrightnessManager::adjustBrightnessWithLux(qreal realTimeLux) { int realTimeBrightness; if (realTimeLux <= 0.0) { USD_LOG(LOG_DEBUG,"realTime lux: %f = 0.0", realTimeLux); return; } USD_LOG(LOG_DEBUG,"realTime lux: %f", realTimeLux); realTimeBrightness = m_brightnessThread->getRealTimeBrightness(); if (realTimeBrightness < 0) { USD_LOG(LOG_DEBUG,"get brightness error"); return; } connectPowerManagerSchema(false); if(realTimeLux >= BRIGHTNESS_40_LOW_LIMIT && realTimeLux < BRIGHTNESS_40_UP_LIMIT) { //40% m_brightnessThread->setBrightness(40); } else if (realTimeLux >= BRIGHTNESS_40_UP_LIMIT && realTimeLux < BRIGHTNESS_80_LOW_LIMIT) { if (realTimeBrightness == 40 || realTimeBrightness == 80) { return; } m_brightnessThread->setBrightness(40); } else if (realTimeLux >= BRIGHTNESS_80_LOW_LIMIT && realTimeLux < BRIGHTNESS_80_UP_LIMIT) { //80% m_brightnessThread->setBrightness(80); } else if(realTimeLux >= BRIGHTNESS_80_UP_LIMIT && realTimeLux < BRIGHTNESS_100_LOW_LIMIT) { if (realTimeBrightness == 100 || realTimeBrightness == 80) { return; } m_brightnessThread->setBrightness(80); } else if(realTimeLux >= BRIGHTNESS_100_LOW_LIMIT) { //100% m_brightnessThread->setBrightness(100); } if (!m_brightnessThread->isRunning()) { m_brightnessThread->start();//运行中就不需要再次运行了, } } void AutoBrightnessManager::enableDynamicBrightness() { bool dynamicState = m_autoBrightnessSettings->get(DYNAMIC_BRIGHTNESS_KEY).toBool(); QDBusInterface iface("com.settings.daemon.qt.systemdbus", \ "/", \ "com.settings.daemon.interface", \ QDBusConnection::systemBus()); QDBusReply reply = iface.call("setDynamicBrightness", dynamicState); if(reply.isValid()) { USD_LOG_SHOW_PARAM1(reply.value()); } } void AutoBrightnessManager::connectPowerManagerSchema(bool state) { if (state) { connect(m_powerManagerSettings, SIGNAL(changed(QString)), this, SLOT(powerManagerSchemaChangedSlot(QString))); } else { disconnect(m_powerManagerSettings, SIGNAL(changed(QString)), this, SLOT(powerManagerSchemaChangedSlot(QString))); } } bool AutoBrightnessManager::autoBrightnessManagerStart() { USD_LOG(LOG_DEBUG, "AutoBrightnessManager Start"); m_hadSensor = sensorExist(); m_enableAutoBrightness = m_autoBrightnessSettings->get(AUTO_BRIGHTNESS_KEY).toBool(); m_autoBrightnessSettings->set(HAD_SENSOR_KEY, m_hadSensor); if (false == m_hadSensor) { if (m_enableAutoBrightness == true) { m_autoBrightnessSettings->set(AUTO_BRIGHTNESS_KEY, false); } USD_LOG(LOG_DEBUG, "can't find lux sensor..."); return true; } USD_LOG(LOG_DEBUG, "find lux sensor AutoBrightness:%d", m_enableAutoBrightness); //进入空闲时,停止传感器采集,退出空闲时根据auto-brightness的键值决定是否开启传感器采集,并直接设置亮度。(auto-brightness为true时退出空闲模式代替电源管理调节亮度) QDBusConnection::sessionBus().connect( QString(), QString(SESSION_MANAGER_PATH), GNOME_SESSION_MANAGER, "StatusChanged", this, SLOT(idleModeChangeSlot(quint32))); m_brightnessThread = new BrightThread(); enableSensorAndSetGsettings(m_enableAutoBrightness); connect(m_autoBrightnessSettings, SIGNAL(changed(QString)), this, SLOT(gsettingsChangedSlot(QString))); connect(m_brightnessThread, SIGNAL(finished()), this, SLOT(brightnessThreadFinishedSlot())); return true; } void AutoBrightnessManager::autoBrightnessManagerStop() { setEnabled(false); USD_LOG(LOG_DEBUG, "AutoBrightness Manager stop"); } ukui-settings-daemon/plugins/color/0000775000175000017500000000000015167655063016371 5ustar fengfengukui-settings-daemon/plugins/color/color-state.h0000664000175000017500000001112015167655063020771 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef COLORSTATE_H #define COLORSTATE_H #include #include #include #include #include #include #include #include "color-edid.h" #include "usd_base_class.h" extern "C" { #define MATE_DESKTOP_USE_UNSTABLE_API #include #include "clib-syslog.h" } #ifdef GDK_WINDOWING_X11 #include #endif class ColorState : public QObject { Q_OBJECT public: ColorState(); ColorState(ColorState&)=delete; ~ColorState(); bool ColorStateStart(); void ColorStateStop(); public: void ColorStateSetTemperature(guint temperature); static bool GetSystemIccProfile (ColorState *state, GFile *file); static gchar *SessionGetOutputId (ColorState *state, MateRROutput *output); static ColorEdid *SessionGetOutputEdid (ColorState *state, MateRROutput *output); static bool SessionUseOutputProfileForScreen (ColorState *state, MateRROutput *output); static bool SessionScreenSetIccProfile (ColorState *state, const gchar *filename, GError **error); static MateRROutput *SessionGetStateOutputById (ColorState *state, const gchar *device_id); static gboolean SessionCheckProfileDeviceMd (GFile *file); static bool ApplyCreateIccProfileForEdid (ColorState *state, CdDevice *device, ColorEdid *edid, GFile *file, GError **error); static bool SessionDeviceResetGamma (MateRROutput *output, guint color_temperature); static void SessionDeviceAssignProfileConnectCb (GObject *object, GAsyncResult *res, gpointer user_data); static void SessionAddStateOutput (ColorState *state, MateRROutput *output); static void SessionProfileGammaFindDeviceCb (GObject *object, GAsyncResult *res, gpointer user_data); static void SessionDeviceAssignConnectCb (GObject *object, GAsyncResult *res, gpointer user_data); static void SessionClientConnectCb (GObject *source_object, GAsyncResult *res, gpointer user_data); static void SessionSetGammaForAllDevices (ColorState *state); static void SessionGetDevicesCb (GObject *object, GAsyncResult *res, gpointer user_data); static void SessionDeviceAssign (ColorState *state, CdDevice *device); static void SessionDeviceChangedAssignCb (CdClient *client, CdDevice *device, ColorState *stata); static void SessionDeviceAddedAssignCb (CdClient *client, CdDevice *device, ColorState *state); static void MateRrScreenOutputChangedCb (MateRRScreen *screen, ColorState *state); private: GCancellable *cancellable; CdClient *client; MateRRScreen *state_screen; GHashTable *edid_cache; GdkWindow *gdk_window; GHashTable *device_assign_hash; guint color_temperature; }; #endif // COLORSTATE_H ukui-settings-daemon/plugins/color/color-manager.h0000664000175000017500000000746715167655063021306 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef COLORMANAGER_H #define COLORMANAGER_H #include #include #include #include #include #include #include "color-state.h" #include "color-profiles.h" #include "color-gtkconfig.h" #define USD_COLOR_TEMPERATURE_MIN 1000 /* Kelvin */ #define USD_COLOR_TEMPERATURE_DEFAULT 6500 /* Kelvin, is RGB [1.0,1.0,1.0] */ #define USD_COLOR_TEMPERATURE_MAX 10000 /* Kelvin */ class ColorManager : public QObject { Q_OBJECT private: ColorManager(); ColorManager(ColorManager&)=delete; ColorManager&operator=(const ColorManager&)=delete; public: ~ColorManager(); static ColorManager* ColorManagerNew(); bool ColorManagerStart(); void ColorManagerStop(); void StartGeoclue(); void StopGeoclue(); static void OnGeoclueSimpleReady (GObject *source_object, GAsyncResult *res, gpointer user_data); static void OnLocationNotify (GClueSimple *simple, GParamSpec *pspec, gpointer user_data); static void NightLightRecheck(ColorManager *manager); GDateTime *NightLightGetDateTimeNow(); void PollSmoothCreate (double temperature); void PollSmoothDestroy (); void NightLightSetTemperatureInternal (double temperature); void NightLightSetTemperature(double temperature); static bool NightLightSmoothCb (ColorManager *manager); void NightLightSetActive(bool active); bool UpdateCachedSunriseSunset(); bool ReadKwinColorTempConfig(); void checkTempWarmAndTheme(); public Q_SLOTS: void SettingsChangedCb(QString key); void qtSetingsChangedCb(QString key); void checkTime(); void doStopServerTimer(); void doNetworkStateCanged(uint state); private : void startService(); void stopService(); bool getNetworkState(); private: static ColorManager *mColorManager; ColorProfiles *mColorProfiles = nullptr; ColorState *mColorState = nullptr; UkuiGtkConfig *mColorGtkConfig; QGSettings *settings; QGSettings *gtk_settings; QGSettings *qt_settings; bool forced; GSource *source; bool geoclue_enabled; bool smooth_enabled; bool cached_active; double cached_sunrise; double cached_sunset; double cached_temperature; bool disabled_until_tmw; bool m_darkModeChangedBySelf; GDateTime *disabled_until_tmw_dt; GDateTime *datetime_override; GTimer *smooth_timer; QTimer *m_NightChecktimer; QTimer *m_stopServiceTimer; guint smooth_id; double smooth_target_temperature; GCancellable *cancellable; GClueClient *geoclue_client; GClueSimple *geoclue_simple; QHash mNightConfig; QDBusInterface *m_pNetworkBus = nullptr; int m_lastNetworkState = 0; bool m_getGeoclueSuccess = false; }; #endif // COLORMANAGER_H ukui-settings-daemon/plugins/color/color-plugin.cpp0000664000175000017500000000426715167655063021520 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include "color-plugin.h" #include "usd_base_class.h" PluginInterface *ColorPlugin::mInstance = nullptr; ColorPlugin::ColorPlugin() { if (UsdBaseClass::isWayland()) { USD_LOG(LOG_DEBUG,"is wayland exit..."); return; } USD_LOG (LOG_DEBUG , "new %s plugin compilation time:[%s] [%s]",MODULE_NAME,__DATE__,__TIME__); if(nullptr == mColorManager) mColorManager = ColorManager::ColorManagerNew(); } ColorPlugin::~ColorPlugin() { if (mColorManager) { delete mColorManager; mColorManager = nullptr; } } void ColorPlugin::activate() { if (UsdBaseClass::isWayland()) { USD_LOG(LOG_DEBUG,"is wayland exit..."); return; } USD_LOG (LOG_DEBUG, "Activating %s plugin compilation time:[%s] [%s]",MODULE_NAME,__DATE__,__TIME__); bool res = mColorManager->ColorManagerStart(); if (!res) qWarning("Unable to start Color manager!"); } void ColorPlugin::deactivate() { if (UsdBaseClass::isWayland()) { USD_LOG(LOG_DEBUG,"is wayland exit..."); return; } USD_LOG (LOG_DEBUG, "deactivate %s plugin compilation time:[%s] [%s]",MODULE_NAME,__DATE__,__TIME__); mColorManager->ColorManagerStop(); } PluginInterface *ColorPlugin::getInstance() { if(nullptr == mInstance) mInstance = new ColorPlugin(); return mInstance; } PluginInterface *createSettingsPlugin() { return ColorPlugin::getInstance(); } ukui-settings-daemon/plugins/color/color-gtkconfig.cpp0000664000175000017500000002121515167655063022165 0ustar fengfeng/* -*- Mode: C; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "color-gtkconfig.h" #include #include #include #include #include #include #include #include #include #include #include "clib-syslog.h" #define THEME_COLOR "theme-color" #define GTK_THEME "gtk-theme" UkuiGtkConfig::UkuiGtkConfig() { const QByteArray id(UKUI_STYLE_SCHEMA); const QByteArray id2(MATE_INTERFACE_SCHEMA); m_colorGsettings = new QGSettings(id); m_gtkThemeGsettings = new QGSettings(id2); } UkuiGtkConfig::~UkuiGtkConfig(){ delete m_colorGsettings; delete m_gtkThemeGsettings; }; void UkuiGtkConfig::getGsettingValue(){ QObject::connect(m_colorGsettings, SIGNAL(changed(QString))/*&QGSettings::changed*/, this, SLOT(doGsettingsChanged(QString))); } void UkuiGtkConfig::addImportStatementsToGtkCssUserFile(){ QString gtkStylePath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + QStringLiteral("/gtk-3.0"); QDir gtkStyle(gtkStylePath); if (!gtkStyle.exists(gtkStylePath)) { gtkStyle.mkdir(gtkStylePath); } QString gtkCssPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + QStringLiteral("/gtk-3.0/gtk.css"); QFile gtkCss(gtkCssPath); if (gtkCss.open(QIODevice::ReadWrite)) { QByteArray gtkCssContents = gtkCss.readAll().trimmed(); static const QVector importStatements{ QByteArrayLiteral("\n@import 'colors.css';"), }; for (const auto &statement : importStatements) { if (!gtkCssContents.contains(statement.trimmed())) { gtkCssContents.append(statement); } } gtkCss.remove(); gtkCss.open(QIODevice::WriteOnly | QIODevice::Text); gtkCss.write(gtkCssContents); } } void UkuiGtkConfig::modifyColorsCssFile(QString colorsDefinitions){ QString colorsCssPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + QStringLiteral("/gtk-3.0/colors.css"); QFile colorsCss(colorsCssPath); if (colorsCss.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text)) { QTextStream colorsCssStream(&colorsCss); colorsCssStream << endl << QStringLiteral("@define-color hover_bg_color_ukui ")+colorsDefinitions+QStringLiteral(";"); colorsCssStream << endl << QStringLiteral("@define-color hover_bd_color_ukui ")+colorsDefinitions+QStringLiteral(";"); colorsCssStream << endl << QStringLiteral("@define-color active_bg_color_ukui ")+colorsDefinitions+QStringLiteral(";"); colorsCssStream << endl << QStringLiteral("@define-color active_bd_color_ukui ")+colorsDefinitions+QStringLiteral(";"); colorsCssStream << endl << QStringLiteral("@define-color selected_bg_color_ukui ")+colorsDefinitions+QStringLiteral(";"); colorsCssStream << endl << QStringLiteral("@define-color selected_borders_color_ukui ")+colorsDefinitions+QStringLiteral(";"); colorsCssStream << endl << QStringLiteral("@define-color bt_hover_bg_color_ukui ")+colorsDefinitions+QStringLiteral(";"); colorsCssStream << endl << QStringLiteral("@define-color bt_hover_bd_color_ukui ")+colorsDefinitions+QStringLiteral(";"); colorsCssStream << endl << QStringLiteral("@define-color bt_active_bg_color_ukui ")+colorsDefinitions+QStringLiteral(";"); colorsCssStream << endl << QStringLiteral("@define-color bt_active_bd_color_ukui ")+colorsDefinitions+QStringLiteral(";"); colorsCssStream << endl << QStringLiteral("@define-color bt_selected_bg_color_ukui ")+colorsDefinitions+QStringLiteral(";"); colorsCssStream << endl << QStringLiteral("@define-color bt_selected_borders_color_ukui ")+colorsDefinitions+QStringLiteral(";"); colorsCssStream << endl << QStringLiteral("@define-color crb_active_bg_color_ukui ")+colorsDefinitions+QStringLiteral(";"); colorsCssStream << endl << QStringLiteral("@define-color crb_hover_bd_color_ukui ")+colorsDefinitions+QStringLiteral(";"); colorsCssStream << endl << QStringLiteral("@define-color crb_active_bd_color_ukui ")+colorsDefinitions+QStringLiteral(";"); colorsCssStream << endl << QStringLiteral("@define-color success_color_ukui ")+colorsDefinitions+QStringLiteral(";"); colorsCssStream << endl << QStringLiteral("@define-color base_active_bg_color_ukui ")+colorsDefinitions+QStringLiteral(";"); colorsCssStream << endl << QStringLiteral("@define-color base_prelight_bg_color_ukui ")+colorsDefinitions+QStringLiteral(";"); colorsCssStream << endl << QStringLiteral("@define-color base_selected_bg_color_ukui ")+colorsDefinitions+QStringLiteral(";"); colorsCssStream << endl << QStringLiteral("@define-color base_checked_bg_color_ukui ")+colorsDefinitions+QStringLiteral(";"); colorsCssStream << endl << QStringLiteral("@define-color base_active_border_color_ukui ")+colorsDefinitions+QStringLiteral(";"); colorsCssStream << endl << QStringLiteral("@define-color base_prelight_border_color_ukui ")+colorsDefinitions+QStringLiteral(";"); colorsCssStream << endl << QStringLiteral("@define-color base_active_bg_image_ukui ")+colorsDefinitions+QStringLiteral(";"); colorsCssStream << endl << QStringLiteral("@define-color base_checked_bg_image_ukui ")+colorsDefinitions+QStringLiteral(";"); colorsCssStream << endl << QStringLiteral("@define-color trough_filled_space_normal_color_ukui ")+colorsDefinitions+QStringLiteral(";"); colorsCssStream << endl << QStringLiteral("@define-color toolbar_button_bg_active_color_ukui ")+colorsDefinitions+QStringLiteral(";"); } } QString UkuiGtkConfig::converRGBToHex(QColor color){ QString RGBred = QString("%1").arg(color.red(),2,16,QChar('0')); QString RGBgreen = QString("%1").arg(color.green(),2,16,QChar('0')); QString RGBblue = QString("%1").arg(color.blue(),2,16,QChar('0')); QString RGBToHex = "#"+RGBred+RGBgreen+RGBblue; return RGBToHex; } void UkuiGtkConfig::doGsettingsChanged(QString key) { USD_LOG(LOG_DEBUG,".%s.",key.toLatin1().data()); if(key == THEME_COLOR){ USD_LOG(LOG_DEBUG,".."); qDebug() << endl << m_colorGsettings->get(THEME_COLOR).toString(); qDebug() << endl << m_gtkThemeGsettings->get(GTK_THEME).toString(); QString gtkTheme = m_gtkThemeGsettings->get(GTK_THEME).toString(); QString themeColor = m_colorGsettings->get(THEME_COLOR).toString(); if(gtkTheme == "ukui-white" || gtkTheme == "ukui-black"){ addImportStatementsToGtkCssUserFile(); QColor colorRGB; if (themeColor == "jamPurple") { colorRGB = QColor(120, 115, 245); qDebug() << endl << colorRGB << endl << themeColor; } else if (themeColor == "magenta") { colorRGB = QColor(235, 48, 150); qDebug() << endl << colorRGB << endl << themeColor; } else if (themeColor == "sunRed") { colorRGB = QColor(243, 34, 45); qDebug() << endl << colorRGB << endl << themeColor; } else if (themeColor == "sunsetOrange") { colorRGB = QColor(246, 140, 39); qDebug() << endl << colorRGB << endl << themeColor; } else if (themeColor == "dustGold") { colorRGB = QColor(249, 197, 61); qDebug() << endl << colorRGB << endl << themeColor; } else if (themeColor == "polarGreen") { colorRGB = QColor(82, 196, 41); qDebug() << endl << colorRGB << endl << themeColor; } else { colorRGB = QColor(55, 144, 250); qDebug() << endl << colorRGB << endl << themeColor; } QString colorHex = converRGBToHex(colorRGB); qDebug() << endl << colorRGB << endl << colorHex; modifyColorsCssFile(colorHex); } else { qDebug() << gtkTheme; } } } ukui-settings-daemon/plugins/color/color-manager.cpp0000664000175000017500000011320115167655063021621 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include #include "color-manager.h" #define PLUGIN_COLOR_SCHEMA "org.ukui.SettingsDaemon.plugins.color" #define COLOR_KEY_LAST_COORDINATES "night-light-last-coordinates" #define COLOR_KEY_ENABLED "night-light-enabled" #define COLOR_KEY_ALLDAY "night-light-allday" #define COLOR_KEY_AUTO_THEME "theme-schedule-automatic" #define COLOR_KEY_TEMPERATURE "night-light-temperature" #define COLOR_KEY_AUTOMATIC "night-light-schedule-automatic" #define COLOR_KEY_AUTOMATIC_FROM "night-light-schedule-automatic-from" #define COLOR_KEY_AUTOMATIC_TO "night-light-schedule-automatic-to" #define COLOR_KEY_FROM "night-light-schedule-from" #define COLOR_KEY_TO "night-light-schedule-to" #define COLOR_KEY_ACTIVE "active" #define COLOR_KEY_DARK_MODE "dark-mode" #define COLOR_KEY_ENABLED_DM "night-light-enabled-dm" #define COLOR_KEY_ALLDAY_DM "night-light-allday-dm" #define COLOR_KEY_AUTOMATIC_DM "night-light-schedule-automatic-dm" #define COLOR_KEY_STYLE_NAME_DM "style-name-dm" #define COLOR_KEY_REAL_TIME_TEMPERATURE "real-time-temperature" #define HAD_SET_EDU "had-set-edu" #define COLOR_KEY_AUTO_THEME_DM "theme-schedule-automatic-dm" #define GTK_THEME_SCHEMA "org.mate.interface" #define GTK_THEME_KEY "gtk-theme" #define QT_THEME_SCHEMA "org.ukui.style" #define QT_THEME_KEY "style-name" #define HAD_READ_KWIN "had-read-kwin-config" #define KWIN_COLOR_ACTIVE "Active" #define KWIN_NIGHT_TEMP "NightTemperature" #define KWIN_COLOR_MODE "Mode" #define KWIN_COLOR_START "EveningBeginFixed" #define KWIN_COLOR_END "MorningBeginFixed" #define KWIN_CURRENT_TEMP "CurrentColorTemperature" #define USD_NIGHT_LIGHT_SCHEDULE_TIMEOUT 5 /* seconds */ #define USD_NIGHT_LIGHT_POLL_TIMEOUT 60 /* seconds */ #define USD_NIGHT_LIGHT_POLL_SMEAR 1 /* hours */ #define USD_NIGHT_LIGHT_SMOOTH_SMEAR 5.f /* seconds */ #define USD_FRAC_DAY_MAX_DELTA (1.f/60.f) /* 1 minute */ #define USD_TEMPERATURE_MAX_DELTA (10.f) #define DESKTOP_ID "ukui-color-panel" #include #include enum theme_status_switch{ white_mode, black_mode }; double hour_minute_to_value(int hour, int minute) { double value = (double)minute/60; return (double)hour + value; } ColorManager *ColorManager::mColorManager = nullptr; ColorManager::ColorManager() { forced = false; smooth_id = 0; m_darkModeChangedBySelf = false; smooth_timer = nullptr; disabled_until_tmw = false; datetime_override = NULL; geoclue_enabled = true; smooth_enabled = true; cached_temperature = USD_COLOR_TEMPERATURE_DEFAULT; settings = new QGSettings (PLUGIN_COLOR_SCHEMA); cached_sunrise = settings->get(COLOR_KEY_AUTOMATIC_TO).toDouble(); cached_sunset = settings->get(COLOR_KEY_AUTOMATIC_FROM).toDouble(); gtk_settings = new QGSettings (GTK_THEME_SCHEMA); qt_settings = new QGSettings (QT_THEME_SCHEMA); m_NightChecktimer = new QTimer(this); m_stopServiceTimer = new QTimer(this); m_stopServiceTimer->setSingleShot(true); connect(m_stopServiceTimer, SIGNAL(timeout()), this, SLOT(doStopServerTimer())); stopService(); mColorGtkConfig = new UkuiGtkConfig(); } ColorManager::~ColorManager() { if (m_NightChecktimer) { delete m_NightChecktimer; m_NightChecktimer = nullptr; } if (settings) { delete settings; settings = nullptr; } if (gtk_settings) { delete gtk_settings; gtk_settings = nullptr; } if (qt_settings) { delete qt_settings; qt_settings = nullptr; } if (mColorState) { delete mColorState; mColorState = nullptr; } if (mColorProfiles) { delete mColorProfiles; mColorProfiles = nullptr; } if (mColorGtkConfig) { delete mColorGtkConfig; mColorGtkConfig = nullptr; } } ColorManager *ColorManager::ColorManagerNew() { if (nullptr == mColorManager) mColorManager = new ColorManager(); return mColorManager; } GDateTime *ColorManager::NightLightGetDateTimeNow() { if (datetime_override != NULL) return g_date_time_ref (datetime_override); return g_date_time_new_now_local(); } bool ColorManager::NightLightSmoothCb (ColorManager *manager) { double tmp; double frac; /* find fraction */ frac = g_timer_elapsed (manager->smooth_timer, NULL) / USD_NIGHT_LIGHT_SMOOTH_SMEAR; if (frac >= 1.f) { manager->NightLightSetTemperatureInternal (manager->smooth_target_temperature); manager->smooth_id = 0; USD_LOG(LOG_DEBUG,"set Temp...%f == %f",tmp,manager->smooth_target_temperature); return G_SOURCE_REMOVE; } /* set new temperature step using log curve */ tmp = manager->smooth_target_temperature - manager->cached_temperature; tmp *= frac; tmp += manager->cached_temperature; manager->NightLightSetTemperatureInternal (tmp); // USD_LOG(LOG_DEBUG,"set Temp...%f",tmp); return G_SOURCE_CONTINUE; } void ColorManager::PollSmoothCreate (double temperature) { g_assert (smooth_id == 0); smooth_target_temperature = temperature; smooth_timer = g_timer_new (); smooth_id = g_timeout_add (50, (GSourceFunc)NightLightSmoothCb, this); } void ColorManager::PollSmoothDestroy () { if (smooth_id != 0) { g_source_remove (smooth_id); smooth_id = 0; } if (smooth_timer != NULL) g_clear_pointer (&smooth_timer, g_timer_destroy); } void ColorManager::NightLightSetTemperatureInternal (double temperature) { if (ABS(cached_temperature - temperature) <= USD_TEMPERATURE_MAX_DELTA) { // USD_LOG(LOG_DEBUG,"set night light %f error ABS:%f delta:%f", temperature,ABS (cached_temperature - temperature),USD_TEMPERATURE_MAX_DELTA); if (cached_temperature != temperature) { cached_temperature = temperature; USD_LOG(LOG_DEBUG,"."); stopService(); } return; } if (mColorState == nullptr) { startService(); } settings->set(COLOR_KEY_REAL_TIME_TEMPERATURE,temperature); cached_temperature = temperature; mColorState->ColorStateSetTemperature (cached_temperature); } void ColorManager::NightLightSetTemperature(double temperature) { /* immediate */ if (!smooth_enabled) { USD_LOG(LOG_DEBUG,"set night light %f", temperature); NightLightSetTemperatureInternal (temperature); return; } /* Destroy any smooth transition, it will be recreated if neccessary */ PollSmoothDestroy (); /* small jump */ if (ABS (temperature - cached_temperature) < USD_TEMPERATURE_MAX_DELTA) { NightLightSetTemperatureInternal (temperature); return; } /* smooth out the transition */ PollSmoothCreate (temperature); USD_LOG(LOG_DEBUG,"set color temp to :%f",temperature); } void ColorManager::NightLightSetActive(bool active) { cached_active = active; /* ensure set to unity temperature */ if (!active){ NightLightSetTemperature (USD_COLOR_TEMPERATURE_DEFAULT); } } static gdouble deg2rad (gdouble degrees) { return (M_PI * degrees) / 180.f; } static gdouble rad2deg (gdouble radians) { return radians * (180.f / M_PI); } /* * Formulas taken from https://www.esrl.noaa.gov/gmd/grad/solcalc/calcdetails.html * * The returned values are fractional hours, so 6am would be 6.0 and 4:30pm * would be 16.5. * * The values returned by this function might not make sense for locations near * the polar regions. For example, in the north of Lapland there might not be * a sunrise at all. */ bool NightLightGetSunriseSunset (GDateTime *dt, double pos_lat, double pos_long, double *sunrise, double *sunset) { g_autoptr(GDateTime) dt_zero = g_date_time_new_utc (1900, 1, 1, 0, 0, 0); GTimeSpan ts = g_date_time_difference (dt, dt_zero); g_return_val_if_fail (pos_lat <= 90.f && pos_lat >= -90.f, false); g_return_val_if_fail (pos_long <= 180.f && pos_long >= -180.f, false); double tz_offset = (double) g_date_time_get_utc_offset (dt) / G_USEC_PER_SEC / 60 / 60; // B5 double date_as_number = ts / G_USEC_PER_SEC / 24 / 60 / 60 + 2; // B7 double time_past_local_midnight = 0; // E2, unused in this calculation double julian_day = date_as_number + 2415018.5 + time_past_local_midnight - tz_offset / 24; double julian_century = (julian_day - 2451545) / 36525; double geom_mean_long_sun = fmod (280.46646 + julian_century * (36000.76983 + julian_century * 0.0003032), 360); // I2 double geom_mean_anom_sun = 357.52911 + julian_century * (35999.05029 - 0.0001537 * julian_century); // J2 double eccent_earth_orbit = 0.016708634 - julian_century * (0.000042037 + 0.0000001267 * julian_century); // K2 double sun_eq_of_ctr = sin (deg2rad (geom_mean_anom_sun)) * (1.914602 - julian_century * (0.004817 + 0.000014 * julian_century)) + sin (deg2rad (2 * geom_mean_anom_sun)) * (0.019993 - 0.000101 * julian_century) + sin (deg2rad (3 * geom_mean_anom_sun)) * 0.000289; // L2 double sun_true_long = geom_mean_long_sun + sun_eq_of_ctr; // M2 double sun_app_long = sun_true_long - 0.00569 - 0.00478 * sin (deg2rad (125.04 - 1934.136 * julian_century)); // P2 double mean_obliq_ecliptic = 23 + (26 + ((21.448 - julian_century * (46.815 + julian_century * (0.00059 - julian_century * 0.001813)))) / 60) / 60; // Q2 double obliq_corr = mean_obliq_ecliptic + 0.00256 * cos (deg2rad (125.04 - 1934.136 * julian_century)); // R2 double sun_declin = rad2deg (asin (sin (deg2rad (obliq_corr)) * sin (deg2rad (sun_app_long)))); // T2 double var_y = tan (deg2rad (obliq_corr/2)) * tan (deg2rad (obliq_corr / 2)); // U2 double eq_of_time = 4 * rad2deg (var_y * sin (2 * deg2rad (geom_mean_long_sun)) - 2 * eccent_earth_orbit * sin (deg2rad (geom_mean_anom_sun)) + 4 * eccent_earth_orbit * var_y * sin (deg2rad (geom_mean_anom_sun)) * cos (2 * deg2rad (geom_mean_long_sun)) - 0.5 * var_y * var_y * sin (4 * deg2rad (geom_mean_long_sun)) - 1.25 * eccent_earth_orbit * eccent_earth_orbit * sin (2 * deg2rad (geom_mean_anom_sun))); // V2 double ha_sunrise = rad2deg (acos (cos (deg2rad (90.833)) / (cos (deg2rad (pos_lat)) * cos (deg2rad (sun_declin))) - tan (deg2rad (pos_lat)) * tan (deg2rad (sun_declin)))); // W2 double solar_noon = (720 - 4 * pos_long - eq_of_time + tz_offset * 60) / 1440; // X2 double sunrise_time = solar_noon - ha_sunrise * 4 / 1440; // Y2 double sunset_time = solar_noon + ha_sunrise * 4 / 1440; // Z2 /* convert to hours */ if (sunrise != NULL) *sunrise = sunrise_time * 24; if (sunset != NULL) *sunset = sunset_time * 24; return true; } double NightLightFracDayFromDt (GDateTime *dt) { return g_date_time_get_hour (dt) + (double) g_date_time_get_minute (dt) / 60.f + (double) g_date_time_get_second (dt) / 3600.f; } bool NightLightFracDayIsBetween (double value, double start, double end) { /* wrap end to the next day if it is before start, * considering equal values as a full 24h period */ if (end <= start) end += 24; /* wrap value to the next day if it is before the range */ if (value < start && value < end) value += 24; /* Check whether value falls into range; together with the 24h * wrap around above this means that TRUE is always returned when * start == end. */ return value >= start && value < end; } static double LinearInterpolate (double val1, double val2, double factor) { g_return_val_if_fail (factor >= 0.f, -1.f); g_return_val_if_fail (factor <= 1.f, -1.f); return ((val1 - val2) * factor) + val2; } bool ColorManager::UpdateCachedSunriseSunset() { bool ret = false; double latitude; double longitude; double sunrise; double sunset; g_autoptr(GVariant) tmp = NULL; g_autoptr(GDateTime) dt_now = NightLightGetDateTimeNow (); GSettings *setting = g_settings_new(PLUGIN_COLOR_SCHEMA); /* calculate the sunrise/sunset for the location */ tmp = g_settings_get_value (setting, COLOR_KEY_LAST_COORDINATES); g_clear_object(&setting); g_variant_get (tmp, "(dd)", &latitude, &longitude); if (latitude > 90.f || latitude < -90.f) return false; if (longitude > 180.f || longitude < -180.f) return false; if (!NightLightGetSunriseSunset (dt_now, latitude, longitude, &sunrise, &sunset)) { USD_LOG(LOG_DEBUG,"failed to get sunset/sunrise for %.3f,%.3f", longitude, longitude); return false; } // USD_LOG(LOG_DEBUG," get sunset/sunrise for %.3f,%.3f,%.3f~%.3f", // longitude, longitude,cached_sunset,cached_sunrise); /* anything changed */ if (ABS (cached_sunrise - sunrise) > USD_FRAC_DAY_MAX_DELTA) { cached_sunrise = sunrise; ret = true; settings->set(COLOR_KEY_AUTOMATIC_TO, cached_sunrise); USD_LOG(LOG_DEBUG,"set cached_sunrise..%f.",cached_sunrise); } if (ABS (cached_sunset - sunset) > USD_FRAC_DAY_MAX_DELTA) { cached_sunset = sunset; ret = true; settings->set(COLOR_KEY_AUTOMATIC_FROM, cached_sunset); USD_LOG(LOG_DEBUG,"set cached_sunset..%f.",cached_sunset); } return ret; } /*Active:1,使能,0禁用。 *0:全天,1跟随日出日落,2自定义 *Mode:1 自定义 *Mode:2--EveningBeginFixed(17:55:01)---跟随日出日落 *Mode:3--全天 */ bool ColorManager::ReadKwinColorTempConfig() { QVector nightColor; if (settings->keys().contains(HAD_READ_KWIN)) { if (settings->get(HAD_READ_KWIN).toBool() == true) { USD_LOG(LOG_DEBUG,"Kwin had read over.."); return false; } } else { USD_LOG(LOG_DEBUG,"can't find key:%s", HAD_READ_KWIN); return false; } QDBusInterface colorIft("org.ukui.KWin", "/ColorCorrect", "org.ukui.kwin.ColorCorrect", QDBusConnection::sessionBus()); QDBusMessage result = colorIft.call("nightColorInfo"); const QDBusArgument &dbusArgs = result.arguments().at(0).value().asVariant().value(); dbusArgs.beginArray(); while (!dbusArgs.atEnd()) { ColorInfo color; dbusArgs >> color; nightColor.push_back(color); } dbusArgs.endArray(); for (ColorInfo it : nightColor) { mNightConfig.insert(it.arg, it.out.variant()); } if (mNightConfig[KWIN_NIGHT_TEMP].toInt() > 4000 && mNightConfig[KWIN_NIGHT_TEMP].toInt() < 6500) { settings->set(COLOR_KEY_TEMPERATURE, mNightConfig[KWIN_NIGHT_TEMP].toInt()); } settings->set(COLOR_KEY_ENABLED,mNightConfig[KWIN_COLOR_ACTIVE].toBool()); if (3 == mNightConfig[KWIN_COLOR_MODE].toInt()) { settings->set(COLOR_KEY_ALLDAY, true); } else if (2 == mNightConfig[KWIN_COLOR_MODE].toInt() && mNightConfig[KWIN_COLOR_START].toString() == "17:55:01"){ settings->set(COLOR_KEY_AUTOMATIC, true); } else { QTime startTime = QTime::fromString(mNightConfig[KWIN_COLOR_START].toString(),"hh:mm:ss"); QTime endTime = QTime::fromString(mNightConfig[KWIN_COLOR_END].toString(),"hh:mm:ss"); settings->set(COLOR_KEY_FROM, hour_minute_to_value(startTime.hour(), startTime.minute())); settings->set(COLOR_KEY_TO, hour_minute_to_value(endTime.hour(), endTime.minute())); } USD_LOG_SHOW_PARAM1(mNightConfig[KWIN_COLOR_ACTIVE].toBool()); USD_LOG_SHOW_PARAM1(mNightConfig[KWIN_COLOR_MODE].toInt()); USD_LOG_SHOW_PARAMS(mNightConfig[KWIN_COLOR_START].toString().toLatin1().data()); USD_LOG_SHOW_PARAMS(mNightConfig[KWIN_COLOR_END].toString().toLatin1().data()); settings->set(HAD_READ_KWIN,true); mNightConfig[KWIN_COLOR_ACTIVE] = false; colorIft.call("setNightColorConfig", mNightConfig); mNightConfig[KWIN_NIGHT_TEMP] = mNightConfig[KWIN_CURRENT_TEMP]; mNightConfig[KWIN_COLOR_ACTIVE] = false; colorIft.call("setNightColorConfig", mNightConfig); return true; } void ColorManager::checkTempWarmAndTheme() { bool allDay = settings->get(COLOR_KEY_ALLDAY).toBool(); bool enable = settings->get(COLOR_KEY_ENABLED).toBool(); QString theme = qt_settings->get(QT_THEME_KEY).toString(); if (allDay && enable && theme == "ukui-dark") { m_darkModeChangedBySelf = true; settings->set(COLOR_KEY_DARK_MODE, true); settings->apply(); } } void ColorManager::NightLightRecheck(ColorManager *manager) { double frac_day; double schedule_from = -1.f; double schedule_to = -1.f; double theme_from = -1.f; double theme_to = -1.f; double smear = USD_NIGHT_LIGHT_POLL_SMEAR; /* hours */ int theme_now = -1; guint temperature; guint temp_smeared; GDateTime *dt_now = manager->NightLightGetDateTimeNow (); /* Forced mode, just set the temperature to night light. * Proper rechecking will happen once forced mode is disabled again */ if (manager->forced) { temperature = manager->settings->get(COLOR_KEY_TEMPERATURE).toUInt(); manager->NightLightSetTemperature (temperature); USD_LOG(LOG_DEBUG,"return ......."); return; } manager->m_getGeoclueSuccess = manager->UpdateCachedSunriseSunset();//不需要每次进行计算,经纬度更换后才需要进行计算 /* calculate the position of the sun */ if (manager->settings->get(COLOR_KEY_AUTO_THEME).toBool()) { theme_to = manager->settings->get(COLOR_KEY_AUTOMATIC_TO).toDouble(); theme_from = manager->settings->get(COLOR_KEY_AUTOMATIC_FROM).toDouble(); /* get the current hour of a day as a fraction */ frac_day = NightLightFracDayFromDt (dt_now); if (NightLightFracDayIsBetween (frac_day, theme_from, theme_to)) { manager->gtk_settings->set(GTK_THEME_KEY, "ukui-black"); manager->qt_settings->set(QT_THEME_KEY, "ukui-dark"); } else { manager->gtk_settings->set(GTK_THEME_KEY, "ukui-white"); manager->qt_settings->set(QT_THEME_KEY, "ukui-light"); } } if(!manager->settings->get(COLOR_KEY_ENABLED).toBool()){ manager->NightLightSetActive (false); return; } if(manager->settings->get(COLOR_KEY_ALLDAY).toBool()){ temperature = manager->settings->get(COLOR_KEY_TEMPERATURE).toUInt(); manager->NightLightSetTemperature (temperature); return; } /* calculate the position of the sun */ if (manager->settings->get(COLOR_KEY_AUTOMATIC).toBool()) { if (manager->cached_sunrise > 0.f && manager->cached_sunset > 0.f) { schedule_to = manager->cached_sunrise; schedule_from = manager->cached_sunset; manager->settings->set(COLOR_KEY_AUTOMATIC_FROM, schedule_from); manager->settings->set(COLOR_KEY_AUTOMATIC_TO, schedule_to); } else { schedule_from = manager->settings->get(COLOR_KEY_AUTOMATIC_FROM).toDouble(); schedule_to = manager->settings->get(COLOR_KEY_AUTOMATIC_TO).toDouble(); } } /* fall back to manual settings */ if (schedule_to < 0.f || schedule_from < 0.f) { schedule_from = manager->settings->get(COLOR_KEY_FROM).toDouble(); schedule_to = manager->settings->get(COLOR_KEY_TO).toDouble(); } /* get the current hour of a day as a fraction */ frac_day = NightLightFracDayFromDt (dt_now); // //qDebug("fractional day = %.3f, limits = %.3f->%.3f", // frac_day, schedule_from, schedule_to); /* disabled until tomorrow */ if (manager->disabled_until_tmw) { GTimeSpan time_span; bool reset = false; time_span = g_date_time_difference (dt_now, manager->disabled_until_tmw_dt); /* Reset if disabled until tomorrow is more than 24h ago. */ if (time_span > (GTimeSpan) 24 * 60 * 60 * 1000000) { //qDebug("night light disabled until tomorrow is older than 24h, resetting disabled until tomorrow"); reset = true; } else if (time_span > 0) { /* Or if a sunrise lies between the time it was disabled and now. */ gdouble frac_disabled; frac_disabled = NightLightFracDayFromDt (manager->disabled_until_tmw_dt); if (frac_disabled != frac_day && NightLightFracDayIsBetween (schedule_to, frac_disabled, frac_day)) { //qDebug("night light sun rise happened, resetting disabled until tomorrow"); reset = true; } } if (reset) { manager->disabled_until_tmw = false; g_clear_pointer(&manager->disabled_until_tmw_dt, g_date_time_unref); } else { USD_LOG(LOG_DEBUG,"night light still day-disabled, resetting"); manager->NightLightSetTemperature (USD_COLOR_TEMPERATURE_DEFAULT); return; } } /* lower smearing period to be smaller than the time between start/stop */ smear = MIN (smear, MIN (ABS (schedule_to - schedule_from), 24 - ABS (schedule_to - schedule_from))); if (!NightLightFracDayIsBetween (frac_day, schedule_from - smear, schedule_to)) { manager->NightLightSetActive (false); return; } /* smear the temperature for a short duration before the set limits * * |----------------------| = from->to * |-| = smear down * |-| = smear up * * \ / * \ / * \--------------------/ */ temperature = manager->settings->get(COLOR_KEY_TEMPERATURE).toUInt(); if (smear < 0.01) { /* Don't try to smear for extremely short or zero periods */ temp_smeared = temperature; } else if (NightLightFracDayIsBetween (frac_day, schedule_from - smear, schedule_from)) { double factor = 1.f - ((frac_day - (schedule_from - smear)) / smear); temp_smeared = LinearInterpolate (USD_COLOR_TEMPERATURE_DEFAULT, temperature, factor); USD_LOG(LOG_DEBUG,"val1:%d val2:%d factor:%f,frac_day:%f,schedule_from:%f",USD_COLOR_TEMPERATURE_DEFAULT, temperature, factor, frac_day,schedule_from); } else if (NightLightFracDayIsBetween (frac_day, schedule_to - smear, schedule_to)) { double factor = (frac_day - (schedule_to - smear)) / smear; temp_smeared = LinearInterpolate (USD_COLOR_TEMPERATURE_DEFAULT, temperature, factor); USD_LOG(LOG_DEBUG,"val1:%d val2:%d factor:%f,frac_day:%d,schedule_from:%d",USD_COLOR_TEMPERATURE_DEFAULT, temperature, factor, frac_day,schedule_from); } else { temp_smeared = temperature; } USD_LOG(LOG_DEBUG,"temp_smeared:%d ...%d", temp_smeared, USD_COLOR_TEMPERATURE_DEFAULT-temp_smeared); manager->NightLightSetActive (true); manager->NightLightSetTemperature (temp_smeared); } void ColorManager::OnLocationNotify(GClueSimple *simple, GParamSpec *pspec, gpointer user_data) { GClueLocation *location; gdouble latitude, longitude; ColorManager *manager = (ColorManager *)user_data; location = gclue_simple_get_location (simple); latitude = gclue_location_get_latitude (location); longitude = gclue_location_get_longitude (location); GSettings *setting = g_settings_new(PLUGIN_COLOR_SCHEMA); /* calculate the sunrise/sunset for the location */ g_settings_set_value (setting, COLOR_KEY_LAST_COORDINATES, g_variant_new ("(dd)", latitude, longitude)); g_clear_object(&setting); // //qDebug("got geoclue latitude %f, longitude %f", latitude, longitude); /* recheck the levels if the location changed significantly */ if (manager->UpdateCachedSunriseSunset ()) { manager->NightLightRecheck (manager); } // USD_LOG(LOG_DEBUG,"set latitude:%f longitude:%f,%f-%f", latitude, longitude,manager->cached_sunset,manager->cached_sunrise); //获取成功一次后停止服务。。 manager->stopService(); } void ColorManager::OnGeoclueSimpleReady(GObject *source_object, GAsyncResult *res, gpointer user_data) { GClueSimple *geoclue_simple; ColorManager *manager = (ColorManager *)user_data; g_autoptr(GError) error = NULL; geoclue_simple = gclue_simple_new_finish (res, &error); if (geoclue_simple == NULL) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) USD_LOG(LOG_DEBUG,"Failed to connect to GeoClue2 service: %s", error->message); return; } manager->geoclue_simple = geoclue_simple; manager->geoclue_client = gclue_simple_get_client (manager->geoclue_simple); g_object_set (G_OBJECT (manager->geoclue_client), "time-threshold", 60*60, NULL); /* 1 hour */ g_signal_connect (manager->geoclue_simple, "notify::location", G_CALLBACK (OnLocationNotify), user_data); OnLocationNotify (manager->geoclue_simple, NULL, user_data); } void ColorManager::StartGeoclue() { cancellable = g_cancellable_new (); gclue_simple_new (DESKTOP_ID, GCLUE_ACCURACY_LEVEL_CITY, cancellable, OnGeoclueSimpleReady, this); } void ColorManager::StopGeoclue() { g_cancellable_cancel (cancellable); g_clear_object (&cancellable); if (geoclue_client != NULL) { gclue_client_call_stop (geoclue_client, NULL, NULL, NULL); geoclue_client = NULL; } g_clear_object (&geoclue_simple); } void ColorManager::startService() { QDBusInterface iface("com.settings.daemon.qt.systemdbus", \ "/", \ "com.settings.daemon.interface", \ QDBusConnection::systemBus()); if (iface.isValid()) { iface.call("startColorService"); USD_LOG(LOG_DEBUG,"start geoclue"); } USD_LOG(LOG_DEBUG,"start ..."); QThread::msleep(200); if(mColorState ==nullptr) { mColorState = new ColorState(); } if (mColorProfiles == nullptr) { mColorProfiles = new ColorProfiles(); } StartGeoclue(); mColorProfiles->ColorProfilesStart(); mColorState->ColorStateStart(); NightLightRecheck(this); } void ColorManager::stopService() { m_stopServiceTimer->start(10000); } bool ColorManager::getNetworkState() { QDBusInterface iface("org.freedesktop.NetworkManager", \ "/org/freedesktop/NetworkManager", \ "org.freedesktop.NetworkManager", \ QDBusConnection::systemBus()); if (iface.isValid()) { USD_LOG(LOG_DEBUG,"network state:%d",iface.property("State").toInt()); } else { USD_LOG(LOG_DEBUG,"network state:xx!!"); } } void ColorManager::SettingsChangedCb(QString key) { bool darkMode = settings->get(COLOR_KEY_DARK_MODE).toBool(); bool ret; if (key.contains("-dm") || key == COLOR_KEY_REAL_TIME_TEMPERATURE) { return; } //外部修改,则直接退出夜间模式。 if (key == COLOR_KEY_ALLDAY || key == COLOR_KEY_ENABLED) { ret = settings->get(key).toBool(); if (darkMode && false == ret) { m_darkModeChangedBySelf = true; settings->set(COLOR_KEY_DARK_MODE,false); settings->apply(); } USD_LOG(LOG_DEBUG, "=============>key:%s:%d,dm:%d",key.toLatin1().data(),ret,darkMode); } else if (key == COLOR_KEY_AUTOMATIC) { ret = settings->get(key).toBool(); if (darkMode && true == ret) { m_darkModeChangedBySelf = true; settings->set(COLOR_KEY_DARK_MODE,false); settings->apply(); } USD_LOG(LOG_DEBUG, "=============>key:%s:%d,dm:%d",key.toLatin1().data(),ret,darkMode); } else if (key == COLOR_KEY_AUTO_THEME) { ret = settings->get(key).toBool(); if (darkMode && true == ret) { m_darkModeChangedBySelf = true; settings->set(COLOR_KEY_DARK_MODE,false); settings->apply(); } USD_LOG(LOG_DEBUG, "=============>key:%s:%d,dm:%d",key.toLatin1().data(),ret,darkMode); } if (key == COLOR_KEY_DARK_MODE) { if (m_darkModeChangedBySelf) { USD_LOG(LOG_DEBUG, "skip it...."); m_darkModeChangedBySelf = false; return; } if (settings->get(key).toBool()) {//进入夜间模式 settings->delay(); settings->set(COLOR_KEY_ALLDAY_DM, settings->get(COLOR_KEY_ALLDAY).toBool()); settings->set(COLOR_KEY_ENABLED_DM, settings->get(COLOR_KEY_ENABLED).toBool()); settings->set(COLOR_KEY_AUTOMATIC_DM, settings->get(COLOR_KEY_AUTOMATIC).toBool()); settings->set(COLOR_KEY_STYLE_NAME_DM, qt_settings->get(QT_THEME_KEY).toString()); settings->set(COLOR_KEY_AUTO_THEME_DM, settings->get(COLOR_KEY_AUTO_THEME).toString());//四个任意一个改变则退出夜间模式。 settings->set(COLOR_KEY_ALLDAY, true); settings->set(COLOR_KEY_ENABLED, true); settings->set(COLOR_KEY_AUTOMATIC, false); settings->set(COLOR_KEY_AUTO_THEME, false); qt_settings->set(QT_THEME_KEY, "ukui-dark"); gtk_settings->set(GTK_THEME_KEY, "ukui-black"); settings->apply(); USD_LOG(LOG_DEBUG, "enter dark mode"); } else {//退出夜间模式1 settings->delay(); settings->set(COLOR_KEY_ALLDAY, settings->get(COLOR_KEY_ALLDAY_DM).toBool()); settings->set(COLOR_KEY_ENABLED, settings->get(COLOR_KEY_ENABLED_DM).toBool()); settings->set(COLOR_KEY_AUTOMATIC, settings->get(COLOR_KEY_AUTOMATIC_DM).toBool()); settings->set(COLOR_KEY_AUTO_THEME, settings->get(COLOR_KEY_AUTO_THEME_DM).toBool()); if (false == settings->get(COLOR_KEY_AUTO_THEME).toBool()) { if (settings->get(COLOR_KEY_STYLE_NAME_DM).toString() == "ukui-default") { qt_settings->set(QT_THEME_KEY, "ukui-default"); gtk_settings->set(GTK_THEME_KEY, "ukui-white"); } else if(settings->get(COLOR_KEY_STYLE_NAME_DM).toString() == "ukui-light"){ qt_settings->set(QT_THEME_KEY, "ukui-light"); gtk_settings->set(GTK_THEME_KEY, "ukui-white"); } else { qt_settings->set(QT_THEME_KEY, "ukui-dark"); gtk_settings->set(GTK_THEME_KEY, "ukui-black"); } } else { } settings->apply(); USD_LOG(LOG_DEBUG, "exit dark mode"); } } if(key == COLOR_KEY_AUTOMATIC_FROM || key == COLOR_KEY_AUTOMATIC_TO){ USD_LOG(LOG_DEBUG,"KEY:%s",key.toLatin1().data()); NightLightRecheck(this); return; } USD_LOG(LOG_DEBUG,"KEY:%s",key.toLatin1().data()); if (key == COLOR_KEY_ACTIVE) { USD_LOG(LOG_DEBUG,"get active."); if (!settings->get(key).toBool()) { if (mColorState) { delete mColorState; mColorState = nullptr; } if (mColorProfiles) { delete mColorProfiles; mColorProfiles = nullptr; } USD_LOG(LOG_DEBUG,"."); stopService(); } return; } // USD_LOG(LOG_DEBUG,"KEY:%s",key.toLatin1().data()); NightLightRecheck(this); if (cached_temperature == USD_COLOR_TEMPERATURE_DEFAULT) { if (mColorState == nullptr) { startService(); QThread::msleep(300); } mColorState->ColorStateSetTemperature (cached_temperature); } else { if (mColorState == nullptr) { startService(); } mColorState->ColorStateSetTemperature (cached_temperature); } } void ColorManager::qtSetingsChangedCb(QString key) { if (key == QT_THEME_KEY) { if (qt_settings->get(key).toString() != "ukui-dark") { if (settings->get(COLOR_KEY_DARK_MODE).toBool()) { m_darkModeChangedBySelf = true; settings->set(COLOR_KEY_STYLE_NAME_DM, qt_settings->get(QT_THEME_KEY).toString()); settings->set(COLOR_KEY_DARK_MODE,false); settings->apply(); } } checkTempWarmAndTheme(); } } bool ColorManager::ColorManagerStart() { USD_LOG(LOG_DEBUG,"--Color manager start--"); int ms = 2000; if (UsdBaseClass::isEdu()) { if (!settings->get(HAD_SET_EDU).toBool()) { settings->set(COLOR_KEY_TEMPERATURE, 5150); settings->set(COLOR_KEY_ALLDAY, true); settings->set(COLOR_KEY_AUTOMATIC, false); settings->set(COLOR_KEY_TEMPERATURE, 5150); settings->set(HAD_SET_EDU,true); USD_LOG(LOG_DEBUG,"--edu first start--"); } ms = 100; USD_LOG(LOG_DEBUG,"--Color edu start--"); } if (!settings->get(HAD_READ_KWIN).toBool()){ if (false == ReadKwinColorTempConfig()) { ms = 100; } } QTimer::singleShot(ms, this, [=](){ connect(m_NightChecktimer, SIGNAL(timeout()), this, SLOT(checkTime())); m_NightChecktimer->start(USD_NIGHT_LIGHT_POLL_TIMEOUT*1000); connect(settings,SIGNAL(changed(QString)),this,SLOT(SettingsChangedCb(QString))); SettingsChangedCb(COLOR_KEY_ENABLED); m_pNetworkBus = new QDBusInterface("org.freedesktop.NetworkManager", \ "/org/freedesktop/NetworkManager", \ "org.freedesktop.NetworkManager", \ QDBusConnection::systemBus()); if (m_pNetworkBus->property("State").toInt() == 70) { USD_LOG(LOG_DEBUG,"network connect success"); startService(); StartGeoclue(); } else { connect(m_pNetworkBus, SIGNAL(StateChanged(uint)), this, SLOT(doNetworkStateCanged(uint))); } }); return true; } void ColorManager::checkTime() { NightLightRecheck (this); } void ColorManager::doStopServerTimer() { QDBusInterface iface("com.settings.daemon.qt.systemdbus", \ "/", \ "com.settings.daemon.interface", \ QDBusConnection::systemBus()); if (iface.isValid()) { iface.call("stopColorService"); USD_LOG(LOG_DEBUG,"stopService"); } QThread::msleep(200); if (mColorState) { delete mColorState; mColorState = nullptr; } if (mColorProfiles) { delete mColorProfiles; mColorProfiles = nullptr; } USD_LOG(LOG_DEBUG,"stop ..."); } void ColorManager::doNetworkStateCanged(uint state) { if (m_lastNetworkState != state && state == 70) { m_lastNetworkState = state; USD_LOG(LOG_DAEMON,"network had ready"); startService(); StartGeoclue(); } } void ColorManager::ColorManagerStop() { USD_LOG(LOG_DEBUG,"Color manager stop"); mColorProfiles->ColorProfilesStop(); mColorState->ColorStateStop(); StopGeoclue(); } ukui-settings-daemon/plugins/color/color-plugin.h0000664000175000017500000000242715167655063021161 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef COLORPLUGIN_H #define COLORPLUGIN_H #include "plugin-interface.h" #include "color-manager.h" class ColorPlugin : public PluginInterface { private: ColorPlugin(); ColorPlugin(ColorPlugin&)=delete; public: ~ColorPlugin(); static PluginInterface *getInstance(); virtual void activate(); virtual void deactivate(); private: ColorManager *mColorManager = nullptr; static PluginInterface *mInstance; }; extern "C" Q_DECL_EXPORT PluginInterface *createSettingsPlugin(); #endif // COLORPLUGIN_H ukui-settings-daemon/plugins/color/color-edid.cpp0000664000175000017500000002217115167655063021121 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include "color-edid.h" #define EDID_OFFSET_PNPID 0x08 #define EDID_OFFSET_SERIAL 0x0c #define EDID_OFFSET_SIZE 0x15 #define EDID_OFFSET_GAMMA 0x17 #define EDID_OFFSET_DATA_BLOCKS 0x36 #define EDID_OFFSET_LAST_BLOCK 0x6c #define EDID_OFFSET_EXTENSION_BLOCK_COUNT 0x7e #define DESCRIPTOR_DISPLAY_PRODUCT_NAME 0xfc #define DESCRIPTOR_DISPLAY_PRODUCT_SERIAL_NUMBER 0xff #define DESCRIPTOR_COLOR_MANAGEMENT_DATA 0xf9 #define DESCRIPTOR_ALPHANUMERIC_DATA_STRING 0xfe #define DESCRIPTOR_COLOR_POINT 0xfb ColorEdid::ColorEdid() { pnp_ids = gnome_pnp_ids_new (); pnp_id = g_new0 (gchar, 4); red = cd_color_yxy_new (); green = cd_color_yxy_new (); blue = cd_color_yxy_new (); white = cd_color_yxy_new (); } const gchar *ColorEdid::EdidGetMonitorName () { return monitor_name; } const gchar *ColorEdid::EdidGetVendorName () { if (vendor_name == NULL) vendor_name = gnome_pnp_ids_get_pnp_id (pnp_ids, pnp_id); return vendor_name; } const gchar *ColorEdid::EdidGetSerialNumber () { return serial_number; } const gchar *ColorEdid::EdidGetEisaId () { return eisa_id; } const gchar *ColorEdid::EdidGetChecksum () { return checksum; } const gchar *ColorEdid::EdidGetPnpId () { return pnp_id; } guint ColorEdid::EdidGetWidth () { return width; } guint ColorEdid::EdidGetHeight () { return height; } gfloat ColorEdid::EdidGetGamma () { return gamma; } const CdColorYxy *ColorEdid::EdidGetRed () { return red; } const CdColorYxy *ColorEdid::EdidGetGreen () { return green; } const CdColorYxy *ColorEdid::EdidGetBlue () { return blue; } const CdColorYxy *ColorEdid::EdidGetWhite () { return white; } void ColorEdid::EdidReset () { /* free old data */ /* g_free (monitor_name); g_free (vendor_name); g_free (serial_number); g_free (eisa_id); g_free (checksum); */ /* do not deallocate, just blank */ pnp_id[0] = '\0'; /* set to default values */ monitor_name = NULL; vendor_name = NULL; serial_number = NULL; eisa_id = NULL; checksum = NULL; width = 0; height = 0; gamma = 0.0f; } static gint EdidGetBit (gint in, gint bit) { return (in & (1 << bit)) >> bit; } /** * EdidGetBits: **/ static gint EdidGetBits (gint in, gint begin, gint end) { gint mask = (1 << (end - begin + 1)) - 1; return (in >> begin) & mask; } /** * edid_decode_fraction: **/ static gdouble EdidDecodeFraction (gint high, gint low) { gdouble result = 0.0; gint i; high = (high << 2) | low; for (i = 0; i < 10; ++i) result += EdidGetBit (high, i) * pow (2, i - 10); return result; } static gchar * EdidParseString (const guint8 *data) { gchar *text; guint i; guint replaced = 0; /* this is always 13 bytes, but we can't guarantee it's null * terminated or not junk. */ text = g_strndup ((const gchar *) data, 13); /* remove insane newline chars */ g_strdelimit (text, "\n\r", '\0'); /* remove spaces */ g_strchomp (text); /* nothing left? */ if (text[0] == '\0') { g_free (text); text = NULL; goto out; } /* ensure string is printable */ for (i = 0; text[i] != '\0'; i++) { if (!g_ascii_isprint (text[i])) { text[i] = '-'; replaced++; } } /* if the string is junk, ignore the string */ if (replaced > 4) { g_free (text); text = NULL; goto out; } out: return text; } gboolean ColorEdid::EdidParse (const guint8 *data, gsize length) { gboolean ret = TRUE; guint i; guint32 serial; gchar *tmp; /* check header */ if (length < 128) { USD_LOG(LOG_DEBUG,"EDID length is too small"); ret = FALSE; goto out; } if (data[0] != 0x00 || data[1] != 0xff) { USD_LOG(LOG_DEBUG,"Failed to parse EDID header"); ret = FALSE; goto out; } /* free old data */ EdidReset (); /* decode the PNP ID from three 5 bit words packed into 2 bytes * /--08--\/--09--\ * 7654321076543210 * |\---/\---/\---/ * R C1 C2 C3 */ pnp_id[0] = 'A' + ((data[EDID_OFFSET_PNPID+0] & 0x7c) / 4) - 1; pnp_id[1] = 'A' + ((data[EDID_OFFSET_PNPID+0] & 0x3) * 8) + ((data[EDID_OFFSET_PNPID+1] & 0xe0) / 32) - 1; pnp_id[2] = 'A' + (data[EDID_OFFSET_PNPID+1] & 0x1f) - 1; /* maybe there isn't a ASCII serial number descriptor, so use this instead */ serial = (guint32) data[EDID_OFFSET_SERIAL+0]; serial += (guint32) data[EDID_OFFSET_SERIAL+1] * 0x100; serial += (guint32) data[EDID_OFFSET_SERIAL+2] * 0x10000; serial += (guint32) data[EDID_OFFSET_SERIAL+3] * 0x1000000; if (serial > 0) serial_number = g_strdup_printf ("%" G_GUINT32_FORMAT, serial); /* get the size */ width = data[EDID_OFFSET_SIZE+0]; height = data[EDID_OFFSET_SIZE+1]; /* we don't care about aspect */ if (width == 0 || height == 0) { width = 0; height = 0; } /* get gamma */ if (data[EDID_OFFSET_GAMMA] == 0xff) { gamma = 1.0f; } else { gamma = ((gfloat) data[EDID_OFFSET_GAMMA] / 100) + 1; } /* get color red */ red->x = EdidDecodeFraction (data[0x1b], EdidGetBits (data[0x19], 6, 7)); red->y = EdidDecodeFraction (data[0x1c], EdidGetBits (data[0x19], 4, 5)); /* get color green */ green->x = EdidDecodeFraction (data[0x1d], EdidGetBits (data[0x19], 2, 3)); green->y = EdidDecodeFraction (data[0x1e], EdidGetBits (data[0x19], 0, 1)); /* get color blue */ blue->x = EdidDecodeFraction (data[0x1f], EdidGetBits (data[0x1a], 6, 7)); blue->y = EdidDecodeFraction (data[0x20], EdidGetBits (data[0x1a], 4, 5)); /* get color white */ white->x = EdidDecodeFraction (data[0x21], EdidGetBits (data[0x1a], 2, 3)); white->y = EdidDecodeFraction (data[0x22], EdidGetBits (data[0x1a], 0, 1)); /* parse EDID data */ for (i = EDID_OFFSET_DATA_BLOCKS; i <= EDID_OFFSET_LAST_BLOCK; i += 18) { /* ignore pixel clock data */ if (data[i] != 0) continue; if (data[i+2] != 0) continue; /* any useful blocks? */ if (data[i+3] == DESCRIPTOR_DISPLAY_PRODUCT_NAME) { tmp = EdidParseString (&data[i+5]); if (tmp != NULL) { g_free (monitor_name); monitor_name = tmp; } } else if (data[i+3] == DESCRIPTOR_DISPLAY_PRODUCT_SERIAL_NUMBER) { tmp = EdidParseString (&data[i+5]); if (tmp != NULL) { g_free (serial_number); serial_number = tmp; } } else if (data[i+3] == DESCRIPTOR_COLOR_MANAGEMENT_DATA) { g_warning ("failing to parse color management data"); } else if (data[i+3] == DESCRIPTOR_ALPHANUMERIC_DATA_STRING) { tmp = EdidParseString (&data[i+5]); if (tmp != NULL) { g_free (eisa_id); eisa_id = tmp; } } else if (data[i+3] == DESCRIPTOR_COLOR_POINT) { if (data[i+3+9] != 0xff) { /* extended EDID block(1) which contains * a better gamma value */ gamma = ((gfloat) data[i+3+9] / 100) + 1; } if (data[i+3+14] != 0xff) { /* extended EDID block(2) which contains * a better gamma value */ gamma = ((gfloat) data[i+3+9] / 100) + 1; } } } /* calculate checksum */ checksum = g_compute_checksum_for_data (G_CHECKSUM_MD5, data, length); out: return ret; } ukui-settings-daemon/plugins/color/color-profiles.h0000664000175000017500000000401615167655063021502 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef COLORPROFILES_H #define COLORPROFILES_H #include #include "config.h" #include #include #include extern "C"{ #include "clib-syslog.h" } class ColorProfiles : public QObject { Q_OBJECT public: ColorProfiles(); ColorProfiles(ColorProfiles&)=delete; ~ColorProfiles(); bool ColorProfilesStart(); void ColorProfilesStop(); public: static void SessionIccStoreAddedCb (CdIccStore *icc_store, CdIcc *icc, ColorProfiles *profiles); static void SessionIccStoreRemovedCb (CdIccStore *icc_store, CdIcc *icc, ColorProfiles *profiles); static void SessionFindProfileByFilenameCb (GObject *object, GAsyncResult *res, gpointer user_data); static void SessionClientConnectCb (GObject *source_object, GAsyncResult *res, gpointer user_data); private: GCancellable *cancellable; CdClient *client; CdIccStore *icc_store; }; #endif // COLORPROFILES_H ukui-settings-daemon/plugins/color/color-info.h0000664000175000017500000000262515167655063020616 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef COLORINFO_H #define COLORINFO_H #include #include #include #include struct ColorInfo { QString arg; QDBusVariant out; }; QDBusArgument &operator<<(QDBusArgument &argument, const ColorInfo &mystruct) { argument.beginStructure(); argument << mystruct.arg << mystruct.out; argument.endStructure(); return argument; } const QDBusArgument &operator>>(const QDBusArgument &argument, ColorInfo &mystruct) { argument.beginStructure(); argument >> mystruct.arg >> mystruct.out; argument.endStructure(); return argument; } Q_DECLARE_METATYPE(ColorInfo) #endif // COLORINFO_H ukui-settings-daemon/plugins/color/color-gtkconfig.h0000664000175000017500000000244315167655063021634 0ustar fengfeng/* -*- Mode: C; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef UKUIGTKCONFIG_H #define UKUIGTKCONFIG_H #include #include "QGSettings/qgsettings.h" class UkuiGtkConfig : public QObject { Q_OBJECT public: UkuiGtkConfig(); ~UkuiGtkConfig(); void getGsettingValue(); void addImportStatementsToGtkCssUserFile(); void modifyColorsCssFile(QString colorsDefinitions); QString converRGBToHex(QColor color); public Q_SLOTS: void doGsettingsChanged(QString key); private: QGSettings *m_colorGsettings; QGSettings *m_gtkThemeGsettings; }; #endif // UKUIGTKCONFIG_H ukui-settings-daemon/plugins/color/color.pro0000664000175000017500000000215315167655063020232 0ustar fengfeng#------------------------------------------------- # # Project created by QtCreator 2020-09-10T14:30:00 # #------------------------------------------------- QT += gui QT += core xml widgets x11extras TEMPLATE = lib DEFINES += COLOR_LIBRARY CONFIG += c++20 link_pkgconfig no_keywords plugin app_bundle DEFINES += QT_DEPRECATED_WARNINGS MODULE_NAME=\\\"color\\\" include($$PWD/../../common/common.pri) INCLUDEPATH += \ -I ukui-settings-daemon/ PKGCONFIG += \ glib-2.0 \ gtk+-3.0 \ colord \ libgeoclue-2.0 \ gobject-2.0 \ libnotify \ libcanberra \ libcanberra-gtk3 \ gio-2.0 \ mate-desktop-2.0 \ gnome-desktop-3.0 SOURCES += \ color-edid.cpp \ color-gtkconfig.cpp \ color-manager.cpp \ color-plugin.cpp \ color-profiles.cpp \ color-state.cpp HEADERS += \ color-edid.h \ color-gtkconfig.h \ color-info.h \ color-manager.h \ color-plugin.h \ color-profiles.h \ color-state.h color_lib.path = $${PLUGIN_INSTALL_DIRS} color_lib.files = $$OUT_PWD/libcolor.so INSTALLS += color_lib ukui-settings-daemon/plugins/color/color-profiles.cpp0000664000175000017500000001544715167655063022047 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include "color-profiles.h" static void SessionCreateProfileCb (GObject *object, GAsyncResult *res, gpointer user_data) { CdProfile *profile; GError *error = NULL; CdClient *client = CD_CLIENT (object); profile = cd_client_create_profile_finish (client, res, &error); if (profile == NULL) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) && !g_error_matches (error, CD_CLIENT_ERROR, CD_CLIENT_ERROR_ALREADY_EXISTS)) g_warning ("%s", error->message); g_error_free (error); return; } g_object_unref (profile); } static void SessionDeleteProfileCb (GObject *object, GAsyncResult *res, gpointer user_data) { gboolean ret; GError *error = NULL; CdClient *client = CD_CLIENT (object); ret = cd_client_delete_profile_finish (client, res, &error); if (!ret) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) g_warning ("%s", error->message); g_error_free (error); } } void ColorProfiles::SessionFindProfileByFilenameCb (GObject *object, GAsyncResult *res, gpointer user_data) { GError *error = NULL; CdProfile *profile; CdClient *client = CD_CLIENT (object); ColorProfiles *profiles = (ColorProfiles *)user_data; profile = cd_client_find_profile_by_filename_finish (client, res, &error); if (profile == NULL) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) g_warning ("%s", error->message); g_error_free (error); goto out; } /* remove it from colord */ cd_client_delete_profile (profiles->client, profile, profiles->cancellable, SessionDeleteProfileCb, profiles); out: if (profile != NULL) g_object_unref (profile); } void ColorProfiles::SessionIccStoreAddedCb (CdIccStore *icc_store, CdIcc *icc, ColorProfiles *profiles) { cd_client_create_profile_for_icc (profiles->client, icc, CD_OBJECT_SCOPE_TEMP, profiles->cancellable, SessionCreateProfileCb, profiles); } void ColorProfiles::SessionIccStoreRemovedCb (CdIccStore *icc_store, CdIcc *icc, ColorProfiles *profiles) { /* find the ID for the filename */ // qDebug ("filename %s removed", cd_icc_get_filename (icc)); cd_client_find_profile_by_filename (profiles->client, cd_icc_get_filename (icc), profiles->cancellable, SessionFindProfileByFilenameCb, profiles); } ColorProfiles::ColorProfiles() { cancellable = nullptr; client = cd_client_new (); icc_store = cd_icc_store_new (); cd_icc_store_set_load_flags (icc_store, CD_ICC_LOAD_FLAGS_FALLBACK_MD5); g_signal_connect (icc_store, "added", G_CALLBACK (SessionIccStoreAddedCb), this); g_signal_connect (icc_store, "removed", G_CALLBACK (SessionIccStoreRemovedCb), this); } ColorProfiles::~ColorProfiles() { g_cancellable_cancel (cancellable); g_clear_object (&cancellable); g_clear_object (&icc_store); g_clear_object (&client); } void ColorProfiles::SessionClientConnectCb (GObject *source_object, GAsyncResult *res, gpointer user_data) { gboolean ret; GError *error = NULL; CdClient *client = CD_CLIENT (source_object); ColorProfiles *profiles; /* connected */ ret = cd_client_connect_finish (client, res, &error); if (!ret) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { USD_LOG(LOG_DEBUG,"failed to connect to colord: %s", error->message); } g_error_free (error); return; } /* is there an available colord instance? */ profiles = (ColorProfiles *)user_data; ret = cd_client_get_has_server (profiles->client); if (!ret) { USD_LOG(LOG_DEBUG,"There is no colord server available"); return; } /* add profiles */ ret = cd_icc_store_search_kind (profiles->icc_store, CD_ICC_STORE_SEARCH_KIND_USER, CD_ICC_STORE_SEARCH_FLAGS_CREATE_LOCATION, profiles->cancellable, &error); if (!ret) { g_error_free (error); USD_LOG(LOG_DEBUG,"failed to add user icc: %s", error->message); } USD_LOG(LOG_DEBUG,"SessionClientConnectCb over.."); } bool ColorProfiles::ColorProfilesStart() { /* use a fresh cancellable for each start->stop operation */ g_cancellable_cancel (cancellable); g_clear_object (&cancellable); cancellable = g_cancellable_new (); cd_client_connect (client, cancellable, SessionClientConnectCb, this); return true; } void ColorProfiles::ColorProfilesStop() { g_cancellable_cancel (cancellable); } ukui-settings-daemon/plugins/color/color-edid.h0000664000175000017500000000512215167655063020563 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef COLOREDID_H #define COLOREDID_H #include #include extern "C"{ #include #include "clib-syslog.h" } #define USD_COLOR_TEMPERATURE_MIN 1000 /* Kelvin */ #define USD_COLOR_TEMPERATURE_DEFAULT 6500 /* Kelvin, is RGB [1.0,1.0,1.0] */ #define USD_COLOR_TEMPERATURE_MAX 10000 /* Kelvin */ class ColorEdid { public: ColorEdid(); void EdidReset (); gboolean EdidParse (const guint8 *data, gsize length); const gchar *EdidGetMonitorName (); const gchar *EdidGetVendorName (); const gchar *EdidGetSerialNumber (); const gchar *EdidGetEisaId (); const gchar *EdidGetChecksum (); const gchar *EdidGetPnpId (); guint EdidGetWidth (); guint EdidGetHeight (); gfloat EdidGetGamma (); const CdColorYxy *EdidGetRed (); const CdColorYxy *EdidGetGreen (); const CdColorYxy *EdidGetBlue (); const CdColorYxy *EdidGetWhite (); private: gchar *monitor_name; gchar *vendor_name; gchar *serial_number; gchar *eisa_id; gchar *checksum; gchar *pnp_id; guint width; guint height; gfloat gamma; CdColorYxy *red; CdColorYxy *green; CdColorYxy *blue; CdColorYxy *white; GnomePnpIds *pnp_ids; }; #endif // COLOREDID_H ukui-settings-daemon/plugins/color/color-state.cpp0000664000175000017500000013467315167655063021347 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "color-state.h" #include "config.h" #include typedef struct { guint32 red; guint32 green; guint32 blue; } MateRROutputClutItem; typedef struct { ColorState *state; CdProfile *profile; CdDevice *device; guint32 output_id; } SessionAsyncHelper; /* see http://www.oyranos.org/wiki/index.php?title=ICC_Profiles_in_X_Specification_0.3 */ #define USD_ICC_PROFILE_IN_X_VERSION_MAJOR 0 #define USD_ICC_PROFILE_IN_X_VERSION_MINOR 3 bool g_hadQuit = false; ColorState::ColorState() { #ifdef GDK_WINDOWING_X11 /* set the _ICC_PROFILE atoms on the root screen */ if (GDK_IS_X11_DISPLAY (gdk_display_get_default ())) gdk_window = gdk_screen_get_root_window (gdk_screen_get_default ()); #endif /* parsing the EDID is expensive */ edid_cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); /* we don't want to assign devices multiple times at startup */ device_assign_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); /* default color temperature */ color_temperature = USD_COLOR_TEMPERATURE_DEFAULT; client = cd_client_new (); cancellable = nullptr; g_hadQuit = false; } ColorState::~ColorState() { g_hadQuit = true; g_cancellable_cancel (cancellable); g_clear_object (&cancellable); g_clear_object (&client); //g_clear_pointer (&edid_cache, g_hash_table_destroy); g_clear_pointer (&device_assign_hash, g_hash_table_destroy); g_clear_object (&state_screen); } void ColorState::ColorStateSetTemperature(guint temperature) { if (color_temperature == temperature) { return; } if (g_hadQuit) { USD_LOG(LOG_DEBUG, "usd had quit can't set gamma..."); return; } if(temperature < USD_COLOR_TEMPERATURE_MIN) temperature = USD_COLOR_TEMPERATURE_MIN; if(temperature > USD_COLOR_TEMPERATURE_MAX) temperature = USD_COLOR_TEMPERATURE_MAX; color_temperature = temperature; SessionSetGammaForAllDevices (this); } ColorEdid *ColorState::SessionGetOutputEdid (ColorState *state, MateRROutput *output) { const guint8 *data; gsize size = 128; ColorEdid *edid = NULL; gboolean ret; /* can we find it in the cache */ edid = (ColorEdid *)g_hash_table_lookup (state->edid_cache, mate_rr_output_get_name (output)); if (edid != NULL) { return edid; } /* parse edid */ data = mate_rr_output_get_edid_data (output); if (data == nullptr) { // qDebug("unable to get EDID for output"); return nullptr; } edid = new ColorEdid (); ret = edid->EdidParse (data, size); if (!ret) { // delete edid; return nullptr; } /* add to cache */ g_hash_table_insert (state->edid_cache, g_strdup (mate_rr_output_get_name (output)), edid); return edid; } gchar *ColorState::SessionGetOutputId (ColorState *state, MateRROutput *output) { const gchar *name = nullptr; const gchar *serial = nullptr; const gchar *vendor = nullptr; ColorEdid *edid = NULL; GString *device_id; /* all output devices are prefixed with this */ device_id = g_string_new ("xrandr"); /* get the output EDID if possible */ edid = SessionGetOutputEdid (state, output); if (edid == NULL) { USD_LOG(LOG_ERR,"no edid for %s, falling back to connection name", mate_rr_output_get_name (output)); g_string_append_printf (device_id, "-%s", mate_rr_output_get_name (output)); goto out; } /* check EDID data is okay to use */ vendor = edid->EdidGetVendorName(); name = edid->EdidGetMonitorName(); serial = edid->EdidGetSerialNumber(); if (vendor == NULL && name == NULL && serial == NULL) { USD_LOG(LOG_ERR,"no edid for %s, falling back to connection name", mate_rr_output_get_name (output)); g_string_append_printf (device_id, "-%s", mate_rr_output_get_name (output)); goto out; } /* use EDID data */ if (vendor != NULL) g_string_append_printf (device_id, "-%s", vendor); if (name != NULL) g_string_append_printf (device_id, "-%s", name); if (serial != NULL) g_string_append_printf (device_id, "-%s", serial); out: if (edid != NULL) edid = nullptr; return g_string_free (device_id, FALSE); } static void SessionCreateDeviceCb (GObject *object, GAsyncResult *res, gpointer user_data) { CdDevice *device; GError *error = NULL; device = cd_client_create_device_finish (CD_CLIENT (object), res, &error); if (device == NULL) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) && !g_error_matches (error, CD_CLIENT_ERROR, CD_CLIENT_ERROR_ALREADY_EXISTS)) { USD_LOG(LOG_DEBUG,"failed to create device: %s", error->message); } g_error_free (error); return; } // fprintf(stderr, "success to create device\n"); g_object_unref (device); } void ColorState::SessionAddStateOutput (ColorState *state, MateRROutput *output) { const gchar *edid_checksum = NULL; const gchar *model = NULL; const gchar *output_name = NULL; const gchar *serial = NULL; const gchar *vendor = NULL; gboolean ret; gchar *device_id = NULL; ColorEdid *edid; GHashTable *device_props = NULL; /* VNC creates a fake device that cannot be color managed */ output_name = mate_rr_output_get_name (output); if (output_name != NULL && g_str_has_prefix (output_name, "VNC-")) { qDebug ("ignoring %s as fake VNC device detected", output_name); return; } /* try to get edid */ edid = SessionGetOutputEdid (state, output); if (edid == nullptr) { USD_LOG(LOG_DEBUG,"failed to get edid:"); } /* prefer DMI data for the internal output */ ret = mate_rr_output_is_laptop (output); if (ret) { model = cd_client_get_system_model (state->client); vendor = cd_client_get_system_vendor (state->client); } /* use EDID data if we have it */ if (edid != nullptr) { edid_checksum = edid->EdidGetChecksum(); if (model == NULL) model = edid->EdidGetMonitorName(); if (vendor == NULL) vendor = edid->EdidGetVendorName(); if (serial == NULL) serial = edid->EdidGetSerialNumber(); } /* ensure mandatory fields are set */ if (model == NULL) model = mate_rr_output_get_name (output); if (vendor == NULL) vendor = "unknown"; if (serial == NULL) serial = "unknown"; device_id = SessionGetOutputId (state, output); // qDebug ("output %s added", device_id); device_props = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL); g_hash_table_insert (device_props, (gpointer) CD_DEVICE_PROPERTY_KIND, (gpointer) cd_device_kind_to_string (CD_DEVICE_KIND_DISPLAY)); g_hash_table_insert (device_props, (gpointer) CD_DEVICE_PROPERTY_MODE, (gpointer) cd_device_mode_to_string (CD_DEVICE_MODE_PHYSICAL)); g_hash_table_insert (device_props, (gpointer) CD_DEVICE_PROPERTY_COLORSPACE, (gpointer) cd_colorspace_to_string (CD_COLORSPACE_RGB)); g_hash_table_insert (device_props, (gpointer) CD_DEVICE_PROPERTY_VENDOR, (gpointer) vendor); g_hash_table_insert (device_props, (gpointer) CD_DEVICE_PROPERTY_MODEL, (gpointer) model); g_hash_table_insert (device_props, (gpointer) CD_DEVICE_PROPERTY_SERIAL, (gpointer) serial); g_hash_table_insert (device_props, (gpointer) CD_DEVICE_METADATA_XRANDR_NAME, (gpointer) mate_rr_output_get_name (output)); g_hash_table_insert (device_props, (gpointer) CD_DEVICE_METADATA_OUTPUT_PRIORITY, mate_rr_output_get_is_primary (output) ? (gpointer) CD_DEVICE_METADATA_OUTPUT_PRIORITY_PRIMARY : (gpointer) CD_DEVICE_METADATA_OUTPUT_PRIORITY_SECONDARY); if (edid_checksum != NULL) { g_hash_table_insert (device_props, (gpointer) CD_DEVICE_METADATA_OUTPUT_EDID_MD5, (gpointer) edid_checksum); } /* set this so we can call the device a 'Laptop Screen' in the * control center main panel */ if (mate_rr_output_is_laptop (output)) { g_hash_table_insert (device_props, (gpointer) CD_DEVICE_PROPERTY_EMBEDDED, NULL); } cd_client_create_device (state->client, device_id, CD_OBJECT_SCOPE_TEMP, device_props, state->cancellable, SessionCreateDeviceCb, state); g_free (device_id); if (device_props != NULL) g_hash_table_unref (device_props); if (edid != nullptr) edid = nullptr; } static guint MateRrOutputGetGammaSize (MateRROutput *output) { MateRRCrtc *crtc; gint len = 0; crtc = mate_rr_output_get_crtc (output); if (crtc == NULL) return 0; mate_rr_crtc_get_gamma (crtc, &len, NULL, NULL, NULL); return (guint) len; } static void SessionAsyncHelperFree (SessionAsyncHelper *helper) { if (helper->state != NULL){ helper->state = NULL; } if (helper->profile != NULL) g_object_unref (helper->profile); /* * helper-device的引用计数一直是0,所以会报g_object_unref: assertion 'G_IS_OBJECT (object)' failed *if (helper->device != NULL) * g_object_unref (helper->device); */ g_free (helper); } static gboolean SessionOutputSetGamma (MateRROutput *output, GPtrArray *array) { gboolean ret = TRUE; guint16 *red = NULL; guint16 *green = NULL; guint16 *blue = NULL; guint i; MateRROutputClutItem *data; MateRRCrtc *crtc; /* no length? */ if (array->len == 0) { ret = FALSE; // qDebug("no data in the CLUT array"); goto out; } /* convert to a type X understands */ red = g_new (guint16, array->len); green = g_new (guint16, array->len); blue = g_new (guint16, array->len); for (i = 0; i < array->len; i++) { data = (MateRROutputClutItem *)g_ptr_array_index (array, i); red[i] = data->red; green[i] = data->green; blue[i] = data->blue; } /* send to LUT */ crtc = mate_rr_output_get_crtc (output); if (crtc == NULL) { ret = FALSE; // qDebug("failed to get ctrc for %s",mate_rr_output_get_name (output)); goto out; } mate_rr_crtc_set_gamma (crtc, array->len, red, green, blue); out: g_free (red); g_free (green); g_free (blue); return ret; } bool ColorState::SessionDeviceResetGamma(MateRROutput *output, guint color_temperature) { bool ret; guint i; guint size; guint32 value; GPtrArray *clut; MateRROutputClutItem *data; CdColorRGB temp; /* create a linear ramp */ // qDebug ("falling back to dummy ramp"); clut = g_ptr_array_new_with_free_func (g_free); size = MateRrOutputGetGammaSize (output); if (size == 0) { ret = true; goto out; } /* get the color temperature */ if (!cd_color_get_blackbody_rgb_full (color_temperature, &temp, CD_COLOR_BLACKBODY_FLAG_USE_PLANCKIAN)) { // USD_LOG(LOG_DEBUG,"failed to get blackbody for %uK", color_temperature); cd_color_rgb_set (&temp, 1.0, 1.0, 1.0); } for (i = 0; i < size; i++) { value = (i * 0xffff) / (size - 1); data = g_new0 (MateRROutputClutItem, 1); data->red = value * temp.R; data->green = value * temp.G; data->blue = value * temp.B; g_ptr_array_add (clut, data); } /* apply the vcgt to this output */ ret = SessionOutputSetGamma (output, clut); if (!ret) goto out; out: g_ptr_array_unref (clut); return ret; } /* * Check to see if the on-disk profile has the MAPPING_device_id * metadata, and if not, we should delete the profile and re-create it * so that it gets mapped by the daemon. */ gboolean ColorState::SessionCheckProfileDeviceMd (GFile *file) { const gchar *key_we_need = CD_PROFILE_METADATA_MAPPING_DEVICE_ID; CdIcc *icc = NULL; gboolean ret; icc = cd_icc_new (); ret = cd_icc_load_file (icc, file, CD_ICC_LOAD_FLAGS_METADATA, NULL, NULL); if (!ret) goto out; ret = cd_icc_get_metadata_item (icc, key_we_need) != NULL; if (!ret) { qDebug ("auto-edid profile is old, and contains no %s data", key_we_need); } out: if (icc != NULL) g_object_unref (icc); return ret; } MateRROutput *ColorState::SessionGetStateOutputById (ColorState *state, const gchar *device_id) { gchar *output_id; MateRROutput *output = NULL; MateRROutput **outputs = NULL; guint i; /* search all STATE outputs for the device id */ outputs = mate_rr_screen_list_outputs (state->state_screen); if (outputs == NULL) { // qDebug("Failed to get outputs"); goto out; } for (i = 0; outputs[i] != NULL && output == NULL; i++) { if (mate_rr_output_is_connected(outputs[i])) { output_id = SessionGetOutputId (state, outputs[i]); if (g_strcmp0 (output_id, device_id) == 0) output = outputs[i]; g_free (output_id); } } if (output == NULL) { USD_LOG(LOG_DEBUG,"Failed to find output %s", device_id); } out: return output; } bool ColorState::GetSystemIccProfile(ColorState *state, GFile *file) { const char efi_path[] = "/sys/firmware/efi/efivars/INTERNAL_PANEL_COLOR_INFO-01e1ada1-79f2-46b3-8d3e-71fc0996ca6b"; /* efi variables have a 4-byte header */ const int efi_var_header_length = 4; g_autoptr(GFile) efi_file = g_file_new_for_path (efi_path); gboolean ret; g_autofree char *data = NULL; gsize length; g_autoptr(GError) error = NULL; ret = g_file_query_exists (efi_file, NULL); if (!ret) return false; ret = g_file_load_contents (efi_file, NULL /* cancellable */, &data, &length, NULL /* etag_out */, &error); if (!ret) { USD_LOG(LOG_DEBUG,"failed to read EFI system color profile: %s", error->message); return false; } if (length <= efi_var_header_length) { USD_LOG(LOG_DEBUG,"EFI system color profile was too short"); return false; } ret = g_file_replace_contents (file, data + efi_var_header_length, length - efi_var_header_length, NULL /* etag */, FALSE /* make_backup */, G_FILE_CREATE_NONE, NULL /* new_etag */, NULL /* cancellable */, &error); if (!ret) { USD_LOG(LOG_DEBUG,"failed to write system color profile: %s", error->message); return false; } return true; } static gboolean UtilsMkdirForFilename (GFile *file) { gboolean ret = FALSE; GFile *parent_dir = NULL; /* get parent directory */ parent_dir = g_file_get_parent (file); if (parent_dir == NULL) { USD_LOG(LOG_DEBUG,"could not get parent dir"); goto out; } /* ensure desination does not already exist */ ret = g_file_query_exists (parent_dir, NULL); if (ret) goto out; ret = g_file_make_directory_with_parents (parent_dir, NULL, NULL); if (!ret) goto out; out: if (parent_dir != NULL) g_object_unref (parent_dir); return ret; } bool ColorState::ApplyCreateIccProfileForEdid (ColorState *state, CdDevice *device, ColorEdid *edid, GFile *file, GError **error) { CdIcc *icc = NULL; const gchar *data; bool ret = false; /* ensure the per-user directory exists */ ret = UtilsMkdirForFilename (file); if (!ret) goto out; /* create our generated profile */ icc = cd_icc_new (); ret = cd_icc_create_from_edid (icc, edid->EdidGetGamma(), edid->EdidGetRed(), edid->EdidGetGreen(), edid->EdidGetBlue(), edid->EdidGetWhite(), NULL); if (!ret) goto out; /* set copyright */ cd_icc_set_copyright (icc, NULL, /* deliberately not translated */ "This profile is free of known copyright restrictions."); /* set model and title */ data = edid->EdidGetMonitorName(); if (data == NULL) data = cd_client_get_system_model (state->client); if (data == NULL) data = "Unknown monitor"; cd_icc_set_model (icc, NULL, data); cd_icc_set_description (icc, NULL, data); /* get manufacturer */ data = edid->EdidGetVendorName(); if (data == NULL) data = cd_client_get_system_vendor (state->client); if (data == NULL) data = "Unknown vendor"; cd_icc_set_manufacturer (icc, NULL, data); /* set the framework creator metadata */ cd_icc_add_metadata (icc, CD_PROFILE_METADATA_CMF_PRODUCT, PACKAGE_NAME); cd_icc_add_metadata (icc, CD_PROFILE_METADATA_CMF_BINARY, PACKAGE_NAME); cd_icc_add_metadata (icc, CD_PROFILE_METADATA_CMF_VERSION, PACKAGE_VERSION); cd_icc_add_metadata (icc, CD_PROFILE_METADATA_MAPPING_DEVICE_ID, cd_device_get_id (device)); /* set 'ICC meta Tag for Monitor Profiles' data */ cd_icc_add_metadata (icc, CD_PROFILE_METADATA_EDID_MD5, edid->EdidGetChecksum()); data = edid->EdidGetMonitorName(); if (data != NULL) cd_icc_add_metadata (icc, CD_PROFILE_METADATA_EDID_MODEL, data); data = edid->EdidGetSerialNumber(); if (data != NULL) cd_icc_add_metadata (icc, CD_PROFILE_METADATA_EDID_SERIAL, data); data = edid->EdidGetPnpId(); if (data != NULL) cd_icc_add_metadata (icc, CD_PROFILE_METADATA_EDID_MNFT, data); data = edid->EdidGetVendorName(); if (data != NULL) cd_icc_add_metadata (icc, CD_PROFILE_METADATA_EDID_VENDOR, data); /* save */ ret = cd_icc_save_file (icc, file, CD_ICC_SAVE_FLAGS_NONE, NULL, error); if (!ret) goto out; out: if (icc != NULL) g_object_unref (icc); return ret; } /* this function is more complicated than it should be, due to the * fact that XOrg sometimes assigns no primary devices when using * "xrandr --auto" or when the version of RANDR is < 1.3 */ bool ColorState::SessionUseOutputProfileForScreen (ColorState *state, MateRROutput *output) { gboolean has_laptop = FALSE; gboolean has_primary = FALSE; MateRROutput **outputs; MateRROutput *connected = NULL; guint i; /* do we have any screens marked as primary */ outputs = mate_rr_screen_list_outputs (state->state_screen); if (outputs == NULL || outputs[0] == NULL) { // USD_LOG(LOG_DEBUG,"failed to get outputs"); return false; } for (i = 0; outputs[i] != NULL; i++) { if (connected == NULL) connected = outputs[i]; if (mate_rr_output_get_is_primary (outputs[i])) has_primary = TRUE; if (mate_rr_output_is_laptop (outputs[i])) has_laptop = TRUE; } /* we have an assigned primary device, are we that? */ if (has_primary) return mate_rr_output_get_is_primary (output); /* choosing the internal panel is probably sane */ if (has_laptop) return mate_rr_output_is_laptop (output); /* we have to choose one, so go for the first connected device */ if (connected != NULL) return mate_rr_output_get_id (connected) == mate_rr_output_get_id (output); return false; } bool ColorState::SessionScreenSetIccProfile (ColorState *state, const gchar *filename, GError **error) { gchar *data = NULL; gsize length; guint version_data; g_return_val_if_fail (filename != NULL, FALSE); /* wayland */ if (state->gdk_window == NULL) { qDebug ("not setting atom as running under wayland"); return true; } // qDebug ("setting root window ICC profile atom from %s", filename); /* get contents of file */ if (!g_file_get_contents (filename, &data, &length, error)) return false; /* set profile property */ gdk_property_change (state->gdk_window, gdk_atom_intern_static_string ("_ICC_PROFILE"), gdk_atom_intern_static_string ("CARDINAL"), 8, GDK_PROP_MODE_REPLACE, (const guchar *) data, length); /* set version property */ version_data = USD_ICC_PROFILE_IN_X_VERSION_MAJOR * 100 + USD_ICC_PROFILE_IN_X_VERSION_MINOR * 1; gdk_property_change (state->gdk_window, gdk_atom_intern_static_string ("_ICC_PROFILE_IN_X_VERSION"), gdk_atom_intern_static_string ("CARDINAL"), 8, GDK_PROP_MODE_REPLACE, (const guchar *) &version_data, 1); g_free (data); return true; } static GPtrArray * SessionGenerateVcgt (CdProfile *profile, guint color_temperature, guint size) { MateRROutputClutItem *tmp; GPtrArray *array = NULL; const cmsToneCurve **vcgt; cmsFloat32Number in; guint i; cmsHPROFILE lcms_profile; CdIcc *icc = NULL; CdColorRGB temp; /* invalid size */ if (size == 0) goto out; /* open file */ icc = cd_profile_load_icc (profile, CD_ICC_LOAD_FLAGS_NONE, NULL, NULL); if (icc == NULL) goto out; /* get tone curves from profile */ lcms_profile = cd_icc_get_handle (icc); vcgt = (const cmsToneCurve **)cmsReadTag (lcms_profile, cmsSigVcgtTag); if (vcgt == NULL || vcgt[0] == NULL) { // qDebug ("profile does not have any VCGT data"); goto out; } /* get the color temperature */ if (!cd_color_get_blackbody_rgb_full (color_temperature, &temp, CD_COLOR_BLACKBODY_FLAG_USE_PLANCKIAN)) { // USD_LOG(LOG_DEBUG,"failed to get blackbody for %uK", color_temperature); cd_color_rgb_set (&temp, 1.0, 1.0, 1.0); } else { qDebug ("using VCGT gamma of %uK = %.1f,%.1f,%.1f", color_temperature, temp.R, temp.G, temp.B); } /* create array */ array = g_ptr_array_new_with_free_func (g_free); for (i = 0; i < size; i++) { in = (gdouble) i / (gdouble) (size - 1); tmp = g_new0 (MateRROutputClutItem, 1); tmp->red = cmsEvalToneCurveFloat(vcgt[0], in) * temp.R * (gdouble) 0xffff; tmp->green = cmsEvalToneCurveFloat(vcgt[1], in) * temp.G * (gdouble) 0xffff; tmp->blue = cmsEvalToneCurveFloat(vcgt[2], in) * temp.B * (gdouble) 0xffff; g_ptr_array_add (array, tmp); } out: if (icc != NULL) g_object_unref (icc); return array; } static gboolean SessionDeviceSetGamma (MateRROutput *output, CdProfile *profile, guint color_temperature) { gboolean ret = FALSE; guint size; GPtrArray *clut = NULL; /* create a lookup table */ size = MateRrOutputGetGammaSize (output); if (size == 0) { ret = TRUE; goto out; } clut = SessionGenerateVcgt (profile, color_temperature, size); if (clut == NULL) { // qDebug("failed to generate vcgt"); goto out; } /* apply the vcgt to this output */ ret = SessionOutputSetGamma (output, clut); if (!ret) goto out; out: if (clut != NULL) g_ptr_array_unref (clut); return ret; } void ColorState::SessionDeviceAssignProfileConnectCb (GObject *object, GAsyncResult *res, gpointer user_data) { CdProfile *profile = CD_PROFILE (object); const gchar *filename; gboolean ret; GError *error = NULL; MateRROutput *output; SessionAsyncHelper *helper = (SessionAsyncHelper *) user_data; ColorState *state = (ColorState *) (helper->state); /* get properties */ ret = cd_profile_connect_finish (profile, res, &error); if (!ret) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { USD_LOG(LOG_DEBUG,"failed to connect to profile: %s", error->message); } g_error_free (error); goto out; } /* get the filename */ filename = cd_profile_get_filename (profile); g_assert (filename != NULL); /* get the output (can't save in helper as GnomeRROutput isn't * a GObject, just a pointer */ output = mate_rr_screen_get_output_by_id (state->state_screen, helper->output_id); if (output == NULL) goto out; /* set the _ICC_PROFILE atom */ ret = SessionUseOutputProfileForScreen (state, output); if (ret) { ret = SessionScreenSetIccProfile (state, filename, &error); if (!ret) { USD_LOG(LOG_DEBUG,"failed to set screen _ICC_PROFILE: %s", error->message); g_clear_error (&error); } } /* create a vcgt for this icc file */ ret = cd_profile_get_has_vcgt (profile); if (ret) { ret = SessionDeviceSetGamma (output, profile, state->color_temperature); if (!ret) { USD_LOG(LOG_DEBUG,"failed to set %s gamma tables", cd_device_get_id (helper->device)); goto out; } } else { ret = SessionDeviceResetGamma (output, state->color_temperature); if (!ret) { USD_LOG(LOG_DEBUG,"failed to reset %s gamma tables", cd_device_get_id (helper->device)); goto out; } } out: SessionAsyncHelperFree (helper); } void ColorState::SessionDeviceAssignConnectCb (GObject *object, GAsyncResult *res, gpointer user_data) { CdDeviceKind kind; CdProfile *profile = NULL; gboolean ret; gchar *autogen_filename = NULL; gchar *autogen_path = NULL; ColorEdid *edid = nullptr; MateRROutput *output = NULL; GError *error = NULL; GFile *file = NULL; const gchar *xrandr_id; SessionAsyncHelper *helper; CdDevice *device = CD_DEVICE (object); ColorState *state = (ColorState *)user_data; /* remove from assign array */ g_hash_table_remove (state->device_assign_hash, cd_device_get_object_path (device)); /* get properties */ ret = cd_device_connect_finish (device, res, &error); if (!ret) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { USD_LOG(LOG_DEBUG,"failed to connect to device: %s", error->message); } g_error_free (error); goto out; } /* check we care */ kind = cd_device_get_kind (device); if (kind != CD_DEVICE_KIND_DISPLAY) goto out; // qDebug ("need to assign display device %s", cd_device_get_id (device)); /* get the GnomeRROutput for the device id */ xrandr_id = cd_device_get_id (device); output = SessionGetStateOutputById (state, xrandr_id); if (output == NULL) { USD_LOG(LOG_DEBUG,"no %s device found", cd_device_get_id (device)); goto out; } /* create profile from device edid if it exists */ edid = SessionGetOutputEdid (state, output); if (edid == nullptr) { USD_LOG(LOG_DEBUG,"unable to get EDID for %s", cd_device_get_id (device)); } else { autogen_filename = g_strdup_printf ("edid-%s.icc", edid->EdidGetChecksum ()); autogen_path = g_build_filename (g_get_user_data_dir (), "icc", autogen_filename, NULL); /* check if auto-profile has up-to-date metadata */ file = g_file_new_for_path (autogen_path); // 新建~/.local/share/icc/edid-*.icc文件 if (SessionCheckProfileDeviceMd (file)) { // qDebug ("auto-profile edid %s exists with md", autogen_path); } else { qDebug ("auto-profile edid does not exist, creating as %s", autogen_path); /* check if the system has a built-in profile */ ret = mate_rr_output_is_laptop (output) && GetSystemIccProfile (state, file); /* try creating one from the EDID */ if (!ret) { ret = ApplyCreateIccProfileForEdid (state, device, edid, file, &error); } if (!ret) { if (error) { USD_LOG(LOG_DEBUG,"failed to create profile from EDID data: %s", error->message); g_clear_error (&error); } else { USD_LOG(LOG_DEBUG,"failed to create profile from EDID data: no reason"); } } } } /* get the default profile for the device */ profile = cd_device_get_default_profile (device); if (profile == NULL) { // qDebug ("%s has no default profile to set", cd_device_get_id (device)); /* the default output? */ if (mate_rr_output_get_is_primary (output) && state->gdk_window != NULL) { gdk_property_delete (state->gdk_window, gdk_atom_intern_static_string ("_ICC_PROFILE")); gdk_property_delete (state->gdk_window, gdk_atom_intern_static_string ("_ICC_PROFILE_IN_X_VERSION")); } /* reset, as we want linear profiles for profiling */ ret = SessionDeviceResetGamma (output, state->color_temperature); if (!ret) { USD_LOG(LOG_DEBUG,"failed to reset %s gamma tables", cd_device_get_id (device)); goto out; } goto out; } /* get properties */ helper = g_new0 (SessionAsyncHelper, 1); helper->output_id = mate_rr_output_get_id (output); // if(!helper->state) // helper->state = state; helper->state = state; helper->device = device; cd_profile_connect (profile, state->cancellable, SessionDeviceAssignProfileConnectCb, helper); out: g_free (autogen_filename); g_free (autogen_path); if (file != NULL) g_object_unref (file); if (edid != nullptr) edid = nullptr; if (profile != NULL) g_object_unref (profile); } void ColorState::SessionProfileGammaFindDeviceCb (GObject *object, GAsyncResult *res, gpointer user_data) { if (g_hadQuit) { USD_LOG(LOG_DEBUG, "usd had quit can't set gamma..."); return; } CdClient *client = CD_CLIENT (object); CdDevice *device = NULL; GError *error = NULL; ColorState *state = (ColorState *) user_data; device = cd_client_find_device_by_property_finish (client, res, &error); if (device == NULL) { USD_LOG(LOG_DEBUG,"error : %s",error->message); if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)){ USD_LOG(LOG_DEBUG,"."); } g_error_free (error); return; } /* get properties */ cd_device_connect (device, state->cancellable, SessionDeviceAssignConnectCb, state); if (device != NULL) g_object_unref (device); // USD_LOG(LOG_DEBUG,"set gamma over.."); } void ColorState::SessionSetGammaForAllDevices (ColorState *state) { MateRROutput **outputs; guint i; /* setting the temperature before we get the list of devices is fine, * as we use the temperature in the calculation */ if (state->state_screen == NULL) { USD_LOG(LOG_DEBUG,"state->state_screen is nullptr"); return; } /* get STATE outputs */ outputs = mate_rr_screen_list_outputs (state->state_screen); if (outputs == NULL) { USD_LOG(LOG_ERR,"failed to get outputs"); return; } for (i = 0; outputs[i] != NULL; i++) { // if (mate_rr_output_get_is_primary (outputs[i]) || mate_rr_output_is_laptop (outputs[i])){ /* * 目前需求是外显通过物理按键调节色温值,所以这里只是判断当前屏幕是否是笔记本的屏幕。 * 如果在台式机上就会无法调节色温 */ // if (mate_rr_output_is_laptop (outputs[i])) if (mate_rr_output_is_connected(outputs[i])){ /* get CdDevice for this output */ cd_client_find_device_by_property (state->client, CD_DEVICE_METADATA_XRANDR_NAME, mate_rr_output_get_name (outputs[i]), state->cancellable, SessionProfileGammaFindDeviceCb, state); } } } /* We have to reset the gamma tables each time as if the primary output * has changed then different crtcs are going to be used. * See https://bugzilla.gnome.org/show_bug.cgi?id=660164 for an example */ void ColorState::MateRrScreenOutputChangedCb (MateRRScreen *screen, ColorState *state) { //insert output list MateRROutput **outputs; /* get STATE outputs */ outputs = mate_rr_screen_list_outputs (state->state_screen); if (outputs == NULL) { USD_LOG(LOG_DEBUG,"failed to get outputs"); return; } for (int i = 0; outputs[i] != NULL; i++) { if (UsdBaseClass::isTablet()) { if (mate_rr_output_is_laptop (outputs[i])) { SessionAddStateOutput (state, outputs[i]); } } else { if (mate_rr_output_is_connected(outputs[i])) { SessionAddStateOutput (state, outputs[i]); } } } SessionSetGammaForAllDevices(state); } void ColorState::SessionDeviceAssign (ColorState *state, CdDevice *device) { const gchar *key; gpointer found; /* are we already assigning this device */ key = cd_device_get_object_path (device); found = g_hash_table_lookup (state->device_assign_hash, key); if (found != NULL) { qDebug ("assign for %s already in progress", key); return; } g_hash_table_insert (state->device_assign_hash, g_strdup (key), GINT_TO_POINTER (TRUE)); cd_device_connect (device, state->cancellable, SessionDeviceAssignConnectCb, state); } void ColorState::SessionDeviceAddedAssignCb (CdClient *client, CdDevice *device, ColorState *state) { SessionDeviceAssign (state, device); } void ColorState::SessionDeviceChangedAssignCb (CdClient *client, CdDevice *device, ColorState *state) { qDebug ("%s changed", cd_device_get_object_path (device)); SessionDeviceAssign (state, device); } void ColorState::SessionGetDevicesCb (GObject *object, GAsyncResult *res, gpointer user_data) { CdDevice *device; GError *error = NULL; GPtrArray *array; guint i; ColorState *state = (ColorState *)user_data; array = cd_client_get_devices_finish (CD_CLIENT (object), res, &error); if (array == NULL) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) USD_LOG(LOG_DEBUG,"failed to get devices: %s", error->message); g_error_free (error); return; } for (i = 0; i < array->len; i++) { device = (CdDevice *)g_ptr_array_index (array, i); SessionDeviceAssign (state, device); } if (array != NULL) g_ptr_array_unref (array); } void ColorState::SessionClientConnectCb (GObject *source_object, GAsyncResult *res, gpointer user_data) { gboolean ret; GError *error = NULL; MateRROutput **outputs; guint i; ColorState *state = (ColorState *)user_data; USD_LOG(LOG_DEBUG, "ready to connect to colord"); /* connected */ ret = cd_client_connect_finish (state->client, res, &error); USD_LOG(LOG_DEBUG, "connect to colord over!ret:%d",ret); if (!ret) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { USD_LOG(LOG_DEBUG,"failed to connect to colord: %s", error->message); } g_error_free (error); return; } USD_LOG(LOG_DEBUG, "success to connect to colord"); /* is there an available colord instance? */ ret = cd_client_get_has_server (state->client); if (!ret) { USD_LOG(LOG_DEBUG, "There is no colord server available"); return; } USD_LOG(LOG_DEBUG, "cd_client_get_has_server ok"); /* add screens */ mate_rr_screen_refresh (state->state_screen, &error); if (error != NULL) { USD_LOG(LOG_DEBUG,"failed to refresh: %s", error->message); g_error_free (error); return; } USD_LOG(LOG_DEBUG, "mate_rr_screen_refresh ok"); /* get STATE outputs */ outputs = mate_rr_screen_list_outputs (state->state_screen); if (outputs == NULL) { USD_LOG(LOG_DEBUG,"failed to get outputs"); return; } USD_LOG(LOG_DEBUG,"start add output.."); ret = false; for (i = 0; outputs[i] != NULL; i++) { if (UsdBaseClass::isTablet()) { if (mate_rr_output_is_laptop (outputs[i])) { SessionAddStateOutput (state, outputs[i]); ret = true; } } else { if (mate_rr_output_is_connected(outputs[i])) { SessionAddStateOutput (state, outputs[i]); USD_LOG(LOG_DEBUG,"find laptop screen :%s",mate_rr_output_get_name(outputs[i])); ret = true; } } } if (false == ret) { USD_LOG(LOG_DEBUG,"can't find laptop screen.."); } /* only connect when colord is awake */ g_signal_connect (state->state_screen, "changed", G_CALLBACK (MateRrScreenOutputChangedCb), state); g_signal_connect (state->client, "device-added", G_CALLBACK (SessionDeviceAddedAssignCb), state); g_signal_connect (state->client, "device-changed", G_CALLBACK (SessionDeviceChangedAssignCb), state); /* set for each device that already exist */ cd_client_get_devices (state->client, state->cancellable, SessionGetDevicesCb, state); } bool ColorState::ColorStateStart() { g_cancellable_cancel (cancellable); g_clear_object (&cancellable); cancellable = g_cancellable_new (); gdk_init(NULL,NULL); GError *error = NULL; state_screen = mate_rr_screen_new(gdk_screen_get_default (), &error); if (state_screen == NULL) { USD_LOG(LOG_DEBUG,"failed to get screens: %s", error->message); g_error_free (error); return false; } cd_client_connect (client, cancellable, SessionClientConnectCb, this); return true; } void ColorState::ColorStateStop() { g_cancellable_cancel (cancellable); } ukui-settings-daemon/plugins/a11y-keyboard/0000775000175000017500000000000015167655063017624 5ustar fengfengukui-settings-daemon/plugins/a11y-keyboard/a11y-preferences-dialog.h0000664000175000017500000000236315167655063024310 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef A11YPREFERENCESDIALOG_H #define A11YPREFERENCESDIALOG_H #include #include "clib-syslog.h" namespace Ui { class A11yPreferencesDialog; } class A11yPreferencesDialog : public QWidget { Q_OBJECT public: explicit A11yPreferencesDialog(QWidget *parent = nullptr); ~A11yPreferencesDialog(); Q_SIGNALS: void singalCloseWidget(); protected: void closeEvent(QCloseEvent *event); private: Ui::A11yPreferencesDialog *ui; }; #endif // A11YPREFERENCESDIALOG_H ukui-settings-daemon/plugins/a11y-keyboard/a11y-preferences-dialog.cpp0000664000175000017500000000230515167655063024637 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "a11y-preferences-dialog.h" #include "ui_a11y-preferences-dialog.h" A11yPreferencesDialog::A11yPreferencesDialog(QWidget *parent) : QWidget(parent), ui(new Ui::A11yPreferencesDialog) { ui->setupUi(this); } A11yPreferencesDialog::~A11yPreferencesDialog() { delete ui; } void A11yPreferencesDialog::closeEvent(QCloseEvent *event) { Q_UNUSED(event); USD_LOG(LOG_DEBUG,"dialog had close"); Q_EMIT singalCloseWidget(); } ukui-settings-daemon/plugins/a11y-keyboard/a11y-keyboard-manager.h0000664000175000017500000001257415167655063023767 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef A11YKEYBOARDMANAGER_H #define A11YKEYBOARDMANAGER_H #include #include #include #include #include #include #include "QGSettings/qgsettings.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "config.h" #include "a11y-preferences-dialog.h" #ifdef HAVE_LIBNOTIFY #include #endif /* HAVE_LIBNOTIFY */ class A11yKeyboardManager : public QObject { Q_OBJECT private: A11yKeyboardManager()=delete ; A11yKeyboardManager(A11yKeyboardManager&)=delete ; A11yKeyboardManager&operator=(const A11yKeyboardManager&)=delete ; A11yKeyboardManager(QObject *parent = nullptr); public: ~A11yKeyboardManager(); static A11yKeyboardManager *A11KeyboardManagerNew(); bool A11yKeyboardManagerStart(); void A11yKeyboardManagerStop(); public Q_SLOTS: void StartA11yKeyboardIdleCb(); void KeyboardCallback(QString); void OnPreferencesDialogResponse(); void ax_stickykeys_response(QAbstractButton *button); void ax_slowkeys_response (QAbstractButton *button); public: static XkbDescRec *GetXkbDescRec (); static void SetServerFromSettings (A11yKeyboardManager *manager); static void MaybeShowStatusIcon (A11yKeyboardManager *manager); static void A11yKeyboardManagerEnsureStatusIcon(A11yKeyboardManager *manager); static void OnStatusIconActivate (GtkStatusIcon *status_icon, A11yKeyboardManager *manager); static bool XkbEnabled (A11yKeyboardManager *manager); static void SetDevicepresenceHandler (A11yKeyboardManager *manager); static void SetSettingsFromServer (A11yKeyboardManager *manager); static void RestoreServerXkbConfig (A11yKeyboardManager *manager); static bool AxResponseCallback (A11yKeyboardManager *manager, QMessageBox *parent, int response_id, unsigned int revert_controls_mask, bool enabled); static void AxSlowkeysWarningPost (A11yKeyboardManager *manager, bool enabled); static void AxStickykeysWarningPost (A11yKeyboardManager *manager,bool enabled); static void AxStickykeysWarningPostDialog (A11yKeyboardManager *manager, bool enabled); static void AxSlowkeysWarningPostDialog (A11yKeyboardManager *manager, bool enabled); private: friend GdkFilterReturn CbXkbEventFilter (GdkXEvent *xevent, GdkEvent *ignored1, A11yKeyboardManager *manager); friend void OnNotificationClosed (NotifyNotification *notification, A11yKeyboardManager *manager); friend bool AxSlowkeysWarningPostDubble (A11yKeyboardManager *manager, bool enabled); friend void on_sticky_keys_action (NotifyNotification *notification, const char *action, A11yKeyboardManager *manager); friend void on_slow_keys_action (NotifyNotification *notification, const char *action, A11yKeyboardManager *manager); friend bool AxStickykeysWarningPostBubble (A11yKeyboardManager *manager, bool enabled); private: static A11yKeyboardManager *mA11yKeyboard; QTimer *time; int xkbEventBase; bool StickykeysShortcutVal; bool SlowkeysShortcutVal; QMessageBox *StickykeysAlert = nullptr; QMessageBox *SlowkeysAlert = nullptr; A11yPreferencesDialog *preferences_dialog=nullptr; //GtkStatusIcon *status_icon; XkbDescRec *OriginalXkbDesc; QGSettings *settings; #ifdef HAVE_LIBNOTIFY NotifyNotification *notification; #endif /* HAVE_LIBNOTIFY */ }; #endif // A11YKEYBOARDMANAGER_H ukui-settings-daemon/plugins/a11y-keyboard/a11y-preferences-dialog.ui0000664000175000017500000000631315167654733024500 0ustar fengfeng A11yPreferencesDialog 0 0 767 430 Form 121 0 371 401 Use on-screen _keyboard false false Use screen _reader Use screen _magnifier Enhance _contrast in colors Make _text larger and easier to read Press keyboard shortcuts one key at a time (Sticky Keys) Ignore duplicate keypresses (Bounce Keys) Press and _hold keys to accept them (Slow Keys) 560 200 80 26 close ukui-settings-daemon/plugins/a11y-keyboard/a11y-keyboard-plugin.cpp0000664000175000017500000000371015167655063024176 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "a11y-keyboard-plugin.h" #include "clib-syslog.h" PluginInterface *A11yKeyboardPlugin::mInstance = nullptr; A11yKeyboardManager *A11yKeyboardPlugin::UsdA11yManager= nullptr; A11yKeyboardPlugin::A11yKeyboardPlugin() { USD_LOG(LOG_DEBUG,"A11yKeyboardPlugin initializing "); if(nullptr == UsdA11yManager) UsdA11yManager = A11yKeyboardManager::A11KeyboardManagerNew(); } A11yKeyboardPlugin::~A11yKeyboardPlugin() { if(UsdA11yManager){ delete UsdA11yManager; UsdA11yManager = nullptr; } } void A11yKeyboardPlugin::activate() { bool res; USD_LOG (LOG_DEBUG, "Activating %s plugin compilation time:[%s] [%s]",MODULE_NAME,__DATE__,__TIME__); res = UsdA11yManager->A11yKeyboardManagerStart(); if(!res) USD_LOG(LOG_ERR,"Unable to start A11y-Keyboard manager"); } PluginInterface * A11yKeyboardPlugin::getInstance() { if(nullptr == mInstance) mInstance = new A11yKeyboardPlugin(); return mInstance; } void A11yKeyboardPlugin::deactivate() { USD_LOG(LOG_DEBUG,"Deactivating A11y-Keyboard plugin"); UsdA11yManager->A11yKeyboardManagerStop(); } PluginInterface *createSettingsPlugin() { return A11yKeyboardPlugin::getInstance(); } ukui-settings-daemon/plugins/a11y-keyboard/a11y-keyboard-manager.cpp0000664000175000017500000011311215167655063024310 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "a11y-keyboard-manager.h" #include "clib-syslog.h" #define CONFIG_SCHEMA "org.mate.accessibility-keyboard" #define NOTIFICATION_TIMEOUT 30 static GdkFilterReturn DevicepresenceFilter (GdkXEvent *xevent, GdkEvent *event,gpointer data); GdkFilterReturn CbXkbEventFilter (GdkXEvent *xevent, GdkEvent *ignored1, A11yKeyboardManager *manager); A11yKeyboardManager *A11yKeyboardManager::mA11yKeyboard=nullptr; //TODO:需要给出设置界面的呼出窗口(MaybeShowStatusIcon),并且需要针对功能进行完善 by Leon Sun 2021年07月24日15:17:44 A11yKeyboardManager::A11yKeyboardManager(QObject *parent) : QObject(parent) { time = new QTimer(this); settings = new QGSettings(CONFIG_SCHEMA); } A11yKeyboardManager::~A11yKeyboardManager() { settings->deleteLater(); time->deleteLater(); } A11yKeyboardManager * A11yKeyboardManager::A11KeyboardManagerNew() { if(nullptr == mA11yKeyboard) mA11yKeyboard = new A11yKeyboardManager(nullptr); return mA11yKeyboard; } bool A11yKeyboardManager::A11yKeyboardManagerStart() { USD_LOG(LOG_DEBUG," %s Manager Start compilation time:[%s] [%s]",MODULE_NAME,__DATE__,__TIME__); connect(time, &QTimer::timeout, this, &A11yKeyboardManager::StartA11yKeyboardIdleCb); time->start(); return true; } void A11yKeyboardManager::A11yKeyboardManagerStop() { USD_LOG(LOG_DEBUG,"Stopping A11y Keyboard manager"); gdk_window_remove_filter (NULL, DevicepresenceFilter, this); /*if (status_icon) gtk_status_icon_set_visible (status_icon, false); */ gdk_window_remove_filter (NULL, (GdkFilterFunc) CbXkbEventFilter, this); /* Disable all the AccessX bits */ RestoreServerXkbConfig (this); if (SlowkeysAlert != nullptr){ USD_LOG(LOG_DEBUG,"delete SlowkeysAlert"); SlowkeysAlert->deleteLater(); } if (StickykeysAlert != nullptr){ USD_LOG(LOG_DEBUG,"delete StickykeysAlert"); StickykeysAlert->deleteLater(); } SlowkeysShortcutVal = false; StickykeysShortcutVal = false; } static int GetInt (QGSettings *settings, char const *key) { int res = settings->get(key).toInt(); if (res <= 0) { res = 1; } return res; } static bool SetInt (QGSettings *settings, char const *key, int val) { int pre_val = settings->get(key).toInt(); settings->set(key,val); #ifdef DEBUG_ACCESSIBILITY if (val != pre_val) { g_warning ("%s changed", key); } #endif return val != pre_val; } static bool SetBool (QGSettings *settings, char const *key, int val) { bool bval = (val != 0); bool pre_val = settings->get(key).toBool(); settings->set(key,bval ? true : false); #ifdef DEBUG_ACCESSIBILITY if (bval != pre_val) { d ("%s changed", key); return true; } #endif return (bval != pre_val); } static unsigned long SetClear(bool flag, unsigned long value, unsigned long mask) { if(flag) return value | mask; return value & ~mask; } void A11yKeyboardManager::RestoreServerXkbConfig (A11yKeyboardManager *manager) { gdk_x11_display_error_trap_push (gdk_display_get_default()); XkbSetControls (GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), XkbSlowKeysMask | XkbBounceKeysMask | XkbStickyKeysMask | XkbMouseKeysMask | XkbMouseKeysAccelMask | XkbAccessXKeysMask | XkbAccessXTimeoutMask | XkbAccessXFeedbackMask | XkbControlsEnabledMask, manager->OriginalXkbDesc); XkbFreeKeyboard (manager->OriginalXkbDesc, XkbAllComponentsMask, True); XSync (GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), false); gdk_x11_display_error_trap_pop_ignored (gdk_display_get_default()); manager->OriginalXkbDesc = NULL; } XkbDescRec * A11yKeyboardManager::GetXkbDescRec() { XkbDescRec *desc = NULL; Status status = Success; gdk_x11_display_error_trap_push (gdk_display_get_default()); desc = XkbGetMap (GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), XkbAllMapComponentsMask, XkbUseCoreKbd); if (desc != NULL) { desc->ctrls = NULL; status = XkbGetControls (GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), XkbAllControlsMask, desc); } else { desc = NULL; gdk_x11_display_error_trap_pop_ignored (gdk_display_get_default()); return NULL; } gdk_x11_display_error_trap_pop_ignored (gdk_display_get_default()); g_return_val_if_fail (desc != NULL, NULL); g_return_val_if_fail (desc->ctrls != NULL, NULL); g_return_val_if_fail (status == Success, NULL); return desc; } static bool SetCtrlFromSettings (XkbDescRec *desc, QGSettings *settings, char const *key, unsigned long mask) { bool result = settings->get(key).toBool(); desc->ctrls->enabled_ctrls = SetClear(result, desc->ctrls->enabled_ctrls, mask); return result; } void A11yKeyboardManager::SetServerFromSettings(A11yKeyboardManager *manager) { XkbDescRec *desc; bool enable_accessX; desc = GetXkbDescRec (); if (!desc) { return; } /* general */ enable_accessX = manager->settings->get("enable").toBool(); desc->ctrls->enabled_ctrls = SetClear (enable_accessX, desc->ctrls->enabled_ctrls, XkbAccessXKeysMask); if (SetCtrlFromSettings (desc, manager->settings, "timeout-enable", XkbAccessXTimeoutMask)) { desc->ctrls->ax_timeout = GetInt (manager->settings, "timeout"); /* disable only the master flag via the server we will disable * the rest on the rebound without affecting gsettings state * don't change the option flags at all. */ desc->ctrls->axt_ctrls_mask = XkbAccessXKeysMask | XkbAccessXFeedbackMask; desc->ctrls->axt_ctrls_values = 0; desc->ctrls->axt_opts_mask = 0; } desc->ctrls->ax_options = SetClear (manager->settings->get("feature-state-change-beep").toBool(), desc->ctrls->ax_options, XkbAccessXFeedbackMask | XkbAX_FeatureFBMask | XkbAX_SlowWarnFBMask); /* bounce keys */ if (SetCtrlFromSettings (desc, manager->settings, "bouncekeys-enable", XkbBounceKeysMask)) { desc->ctrls->debounce_delay = GetInt (manager->settings, "bouncekeys-delay"); desc->ctrls->ax_options = SetClear (manager->settings->get("bouncekeys-beep-reject").toBool(), desc->ctrls->ax_options, XkbAccessXFeedbackMask | XkbAX_BKRejectFBMask); } /* mouse keys */ if (SetCtrlFromSettings (desc, manager->settings, "mousekeys-enable", XkbMouseKeysMask | XkbMouseKeysAccelMask)) { desc->ctrls->mk_interval = 100; /* msec between mousekey events */ desc->ctrls->mk_curve = 50; /* We store pixels / sec, XKB wants pixels / event */ desc->ctrls->mk_max_speed = GetInt (manager->settings, "mousekeys-max-speed") / (1000 / desc->ctrls->mk_interval); if (desc->ctrls->mk_max_speed <= 0) desc->ctrls->mk_max_speed = 1; desc->ctrls->mk_time_to_max = GetInt (manager->settings, /* events before max */ "mousekeys-accel-time") / desc->ctrls->mk_interval; if (desc->ctrls->mk_time_to_max <= 0) desc->ctrls->mk_time_to_max = 1; desc->ctrls->mk_delay = GetInt (manager->settings, /* ms before 1st event */ "mousekeys-init-delay"); } /* slow keys */ if (SetCtrlFromSettings (desc, manager->settings, "slowkeys-enable", XkbSlowKeysMask)) { desc->ctrls->ax_options = SetClear(manager->settings->get("slowkeys-beep-press").toBool(), desc->ctrls->ax_options, XkbAccessXFeedbackMask | XkbAX_SKPressFBMask); desc->ctrls->ax_options = SetClear(manager->settings->get("slowkeys-beep-accept").toBool(), desc->ctrls->ax_options, XkbAccessXFeedbackMask | XkbAX_SKAcceptFBMask); desc->ctrls->ax_options = SetClear(manager->settings->get("slowkeys-beep-reject").toBool(), desc->ctrls->ax_options, XkbAccessXFeedbackMask | XkbAX_SKRejectFBMask); desc->ctrls->slow_keys_delay = GetInt(manager->settings, "slowkeys-delay"); /* anything larger than 500 seems to loose all keyboard input */ if (desc->ctrls->slow_keys_delay > 500) desc->ctrls->slow_keys_delay = 500; } /* sticky keys */ if (SetCtrlFromSettings (desc, manager->settings, "stickykeys-enable", XkbStickyKeysMask)) { desc->ctrls->ax_options |= XkbAX_LatchToLockMask; desc->ctrls->ax_options = SetClear(manager->settings->get("stickykeys-two-key-off").toBool(), desc->ctrls->ax_options, XkbAccessXFeedbackMask | XkbAX_TwoKeysMask); desc->ctrls->ax_options = SetClear(manager->settings->get("stickykeys-modifier-beep").toBool(), desc->ctrls->ax_options, XkbAccessXFeedbackMask | XkbAX_StickyKeysFBMask); } /* toggle keys */ desc->ctrls->ax_options = SetClear(manager->settings->get("togglekeys-enable").toBool(), desc->ctrls->ax_options, XkbAccessXFeedbackMask | XkbAX_IndicatorFBMask); USD_LOG(LOG_DEBUG,"CHANGE to : 0x%x", desc->ctrls->enabled_ctrls); USD_LOG(LOG_DEBUG,"CHANGE to : 0x%x (2)", desc->ctrls->ax_options); gdk_x11_display_error_trap_push (gdk_display_get_default()); XkbSetControls (GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), XkbSlowKeysMask | XkbBounceKeysMask | XkbStickyKeysMask | XkbMouseKeysMask | XkbMouseKeysAccelMask | XkbAccessXKeysMask | XkbAccessXTimeoutMask | XkbAccessXFeedbackMask | XkbControlsEnabledMask, desc); XkbFreeKeyboard (desc, XkbAllComponentsMask, True); XSync (GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), false); gdk_x11_display_error_trap_pop_ignored (gdk_display_get_default()); } void A11yKeyboardManager::OnPreferencesDialogResponse() { USD_LOG(LOG_DEBUG,"get close dialog signal"); this->preferences_dialog->close(); preferences_dialog->deleteLater(); } void A11yKeyboardManager::OnStatusIconActivate(GtkStatusIcon *status_icon, A11yKeyboardManager *manager) { if (manager->preferences_dialog == NULL) { manager->preferences_dialog = new A11yPreferencesDialog(); // connect(manager->preferences_dialog,SIGNAL(response(A11yKeyboardManager)),manager,SLOT(OnPreferencesDialogResponse(A11yKeyboardManager))); connect(manager->preferences_dialog, &A11yPreferencesDialog::singalCloseWidget, manager, &A11yKeyboardManager::OnPreferencesDialogResponse); manager->preferences_dialog->show(); } else { manager->preferences_dialog->close(); delete manager->preferences_dialog; } } void A11yKeyboardManager::A11yKeyboardManagerEnsureStatusIcon(A11yKeyboardManager *manager) { /*if (!manager->status_icon) { manager->status_icon = gtk_status_icon_new_from_icon_name ("preferences-desktop-accessibility"); g_signal_connect (manager->status_icon, "activate", G_CALLBACK (OnStatusIconActivate), manager); }*/ } void A11yKeyboardManager::MaybeShowStatusIcon(A11yKeyboardManager *manager) { bool show; /* for now, show if accessx is enabled */ show = manager->settings->get("enable").toBool(); /* if (!show && manager->status_icon == NULL) return; */ A11yKeyboardManagerEnsureStatusIcon (manager); } void A11yKeyboardManager::KeyboardCallback(QString key) { SetServerFromSettings (this); } bool A11yKeyboardManager::XkbEnabled (A11yKeyboardManager *manager) { bool have_xkb; int opcode, errorBase, major, minor; have_xkb = XkbQueryExtension (gdk_x11_get_default_xdisplay(), &opcode, &manager->xkbEventBase, &errorBase, &major, &minor) && XkbUseExtension (gdk_x11_get_default_xdisplay(), &major, &minor); return have_xkb; } static bool SupportsXinputDevices (void) { int op_code, event, error; return XQueryExtension (gdk_x11_get_default_xdisplay(), "XInputExtension", &op_code, &event, &error); } static GdkFilterReturn DevicepresenceFilter (GdkXEvent *xevent, GdkEvent *event, gpointer data) { XEvent *xev = (XEvent *) xevent; XEventClass class_presence; int xi_presence; A11yKeyboardManager *manager = (A11yKeyboardManager *)data; DevicePresence (gdk_x11_get_default_xdisplay (), xi_presence, class_presence); if (xev->type == xi_presence) { XDevicePresenceNotifyEvent *dpn = (XDevicePresenceNotifyEvent *) xev; if (dpn->devchange == DeviceEnabled) { manager->SetServerFromSettings (manager); } } return GDK_FILTER_CONTINUE; } void A11yKeyboardManager::SetDevicepresenceHandler (A11yKeyboardManager *manager) { Display *display; XEventClass class_presence; int xi_presence; if (!SupportsXinputDevices ()) return; display = gdk_x11_get_default_xdisplay (); gdk_x11_display_error_trap_push(gdk_display_get_default()); DevicePresence (display, xi_presence, class_presence); /* FIXME: * Note that this might overwrite other events, see: * https://bugzilla.gnome.org/show_bug.cgi?id=610245#c2 **/ XSelectExtensionEvent (display, RootWindow (display, DefaultScreen (display)), &class_presence, 1); gdk_display_flush(gdk_display_get_default()); if (!gdk_x11_display_error_trap_pop(gdk_display_get_default())) gdk_window_add_filter (NULL, DevicepresenceFilter, manager); } GdkFilterReturn CbXkbEventFilter (GdkXEvent *xevent, GdkEvent *ignored1, A11yKeyboardManager *manager) { XEvent *xev = (XEvent *) xevent; XkbEvent *xkbEv = (XkbEvent *) xevent; if (xev->xany.type == (manager->xkbEventBase + XkbEventCode) && xkbEv->any.xkb_type == XkbControlsNotify) { qDebug ("XKB state changed"); manager->SetSettingsFromServer (manager); } else if (xev->xany.type == (manager->xkbEventBase + XkbEventCode) && xkbEv->any.xkb_type == XkbAccessXNotify) { if (xkbEv->accessx.detail == XkbAXN_AXKWarning) { qDebug ("About to turn on an AccessX feature from the keyboard!"); /* * TODO: when XkbAXN_AXKWarnings start working, we need to * invoke ax_keys_warning_dialog_run here instead of in * SetSettingsFromServer(). */ } } return GDK_FILTER_CONTINUE; } bool A11yKeyboardManager::AxResponseCallback(A11yKeyboardManager *manager, QMessageBox *parent, int response_id, unsigned int revert_controls_mask, bool enabled) { switch (response_id) { case GTK_RESPONSE_DELETE_EVENT: case GTK_RESPONSE_REJECT: case GTK_RESPONSE_CANCEL: /* we're reverting, so we invert sense of 'enabled' flag */ qDebug ("cancelling AccessX request"); if (revert_controls_mask == XkbStickyKeysMask) { manager->settings->set("stickykeys-enable", !enabled); } else if (revert_controls_mask == XkbSlowKeysMask) { manager->settings->set("slowkeys-enable",!enabled); } manager->SetServerFromSettings (manager); break; case GTK_RESPONSE_HELP: if(!parent->isActiveWindow()) { QMessageBox *error_dialog = new QMessageBox(); error_dialog->warning(nullptr,nullptr,tr("There was an error displaying help"),QMessageBox::Close); error_dialog->setResult(false); error_dialog->show(); } return FALSE; default: break; } return TRUE; } #ifdef HAVE_LIBNOTIFY void OnNotificationClosed (NotifyNotification *notification, A11yKeyboardManager *manager) { g_object_unref (manager->notification); manager->notification = NULL; } void on_sticky_keys_action (NotifyNotification *notification, const char *action, A11yKeyboardManager *manager) { bool res; int response_id; g_assert (action != NULL); if (strcmp (action, "accept") == 0) { response_id = GTK_RESPONSE_ACCEPT; } else if (strcmp (action, "reject") == 0) { response_id = GTK_RESPONSE_REJECT; } else { return; } res = manager->AxResponseCallback (manager, nullptr, response_id, XkbStickyKeysMask, manager->StickykeysShortcutVal); if (res) { notify_notification_close (manager->notification, NULL); } } void on_slow_keys_action (NotifyNotification *notification, const char *action, A11yKeyboardManager *manager) { bool res; int response_id; g_assert (action != NULL); if (strcmp (action, "accept") == 0) { response_id = GTK_RESPONSE_ACCEPT; } else if (strcmp (action, "reject") == 0) { response_id = GTK_RESPONSE_REJECT; } else { return; } res = manager->AxResponseCallback (manager, nullptr, response_id, XkbSlowKeysMask, manager->SlowkeysShortcutVal); if (res) { notify_notification_close (manager->notification, NULL); } } #endif /* HAVE_LIBNOTIFY */ bool AxSlowkeysWarningPostDubble (A11yKeyboardManager *manager, bool enabled) { #ifdef HAVE_LIBNOTIFY bool res; QString title; QString message; GError *error; title = enabled ? QObject::tr("Do you want to activate Slow Keys?") : QObject::tr("Do you want to deactivate Slow Keys?"); message = QObject::tr("You just held down the Shift key for 8 seconds. This is the shortcut " "for the Slow Keys feature, which affects the way your keyboard works."); /* if (manager->status_icon == NULL || ! gtk_status_icon_is_embedded (manager->status_icon)) { return FALSE; } */ if (manager->SlowkeysAlert != NULL) { manager->SlowkeysAlert->close(); delete manager->SlowkeysAlert; } if (manager->notification != NULL) { notify_notification_close (manager->notification, NULL); } manager->A11yKeyboardManagerEnsureStatusIcon (manager); manager->notification = notify_notification_new (title.toLatin1().data(), message.toLatin1().data(), "preferences-desktop-accessibility"); notify_notification_set_timeout (manager->notification, NOTIFICATION_TIMEOUT * 1000); notify_notification_add_action (manager->notification, "reject", enabled ? _("Don't activate") : _("Don't deactivate"), (NotifyActionCallback) on_slow_keys_action, manager, NULL); notify_notification_add_action (manager->notification, "accept", enabled ? _("Activate") : _("Deactivate"), (NotifyActionCallback) on_slow_keys_action, manager, NULL); g_signal_connect (manager->notification, "closed", G_CALLBACK (OnNotificationClosed), manager); error = NULL; res = notify_notification_show (manager->notification, &error); if (! res) { g_warning ("UsdA11yKeyboardManager: unable to show notification: %s", error->message); g_error_free (error); notify_notification_close (manager->notification, NULL); } return res; #else return false; #endif } void A11yKeyboardManager::ax_slowkeys_response (QAbstractButton *button) { int response_id = 0; if(button == (QAbstractButton *)QMessageBox::Help) response_id = GTK_RESPONSE_HELP; else if(button == (QAbstractButton *)QMessageBox::Cancel) response_id = GTK_RESPONSE_CANCEL; if (AxResponseCallback (this, StickykeysAlert, response_id, XkbSlowKeysMask, SlowkeysShortcutVal)) { StickykeysAlert->close(); } } void A11yKeyboardManager::AxSlowkeysWarningPostDialog (A11yKeyboardManager *manager, bool enabled) { QString title; QString message; title = enabled ? tr("Do you want to activate Slow Keys?") : tr("Do you want to deactivate Slow Keys?"); message = tr("You just held down the Shift key for 8 seconds. This is the shortcut " "for the Slow Keys feature, which affects the way your keyboard works."); if (manager->SlowkeysAlert != NULL) { manager->SlowkeysAlert->show(); return; } manager->SlowkeysAlert = new QMessageBox(); manager->SlowkeysAlert->warning(nullptr,tr("Slow Keys Alert"), title); manager->SlowkeysAlert->setText(message); manager->SlowkeysAlert->setStandardButtons(QMessageBox::Help); manager->SlowkeysAlert->setButtonText(QMessageBox::Rejected, enabled ? tr("Do_n't activate") : tr("Do_n't deactivate")); manager->SlowkeysAlert->setButtonText(QMessageBox::Accepted, enabled ? tr("_Activate") : tr("_Deactivate")); manager->SlowkeysAlert->setWindowIconText(tr("input-keyboard")); manager->SlowkeysAlert->setDefaultButton(QMessageBox::Default); QObject::connect(manager->SlowkeysAlert,SIGNAL(buttonClicked(QAbstractButton *button)), manager,SLOT(ax_slowkeys_response(QAbstractButton *button))); manager->SlowkeysAlert->show(); /*g_object_add_weak_pointer (G_OBJECT (manager->StickykeysAlert), (gpointer*) &manager->StickykeysAlert);*/ } void A11yKeyboardManager::AxSlowkeysWarningPost (A11yKeyboardManager *manager, bool enabled) { manager->SlowkeysShortcutVal = enabled; /* alway try to show something */ if (! AxSlowkeysWarningPostDubble (manager, enabled)) { AxSlowkeysWarningPostDialog (manager, enabled); } } bool AxStickykeysWarningPostBubble (A11yKeyboardManager *manager, bool enabled) { #ifdef HAVE_LIBNOTIFY bool res; QString title; QString message; GError *error; title = enabled ? QObject::tr("Do you want to activate Sticky Keys?") : QObject::tr("Do you want to deactivate Sticky Keys?"); message = enabled ? QObject::tr("You just pressed the Shift key 5 times in a row. This is the shortcut " "for the Sticky Keys feature, which affects the way your keyboard works.") : QObject::tr("You just pressed two keys at once, or pressed the Shift key 5 times in a row. " "This turns off the Sticky Keys feature, which affects the way your keyboard works."); if (manager->SlowkeysAlert != NULL) { manager->SlowkeysAlert->close(); delete manager->SlowkeysAlert; } if (manager->notification != NULL) { notify_notification_close (manager->notification, NULL); } //usd_a11y_keyboard_manager_ensure_status_icon (manager); manager->notification = notify_notification_new (title.toLatin1().data(), message.toLatin1().data(), "preferences-desktop-accessibility"); notify_notification_set_timeout (manager->notification, NOTIFICATION_TIMEOUT * 1000); notify_notification_add_action (manager->notification, "reject", enabled ? _("Don't activate") : _("Don't deactivate"), (NotifyActionCallback) on_sticky_keys_action, manager, NULL); notify_notification_add_action (manager->notification, "accept", enabled ? _("Activate") : _("Deactivate"), (NotifyActionCallback) on_sticky_keys_action, manager, NULL); g_signal_connect (manager->notification, "closed", G_CALLBACK (OnNotificationClosed), manager); error = NULL; res = notify_notification_show (manager->notification, &error); if (! res) { qWarning ("UsdA11yKeyboardManager: unable to show notification: %s", error->message); g_error_free (error); notify_notification_close (manager->notification, NULL); } return res; #else return FALSE; #endif /* HAVE_LIBNOTIFY */ } void A11yKeyboardManager::ax_stickykeys_response(QAbstractButton *button) { int response_id = 0; if(button == (QAbstractButton *)QMessageBox::Help) response_id = GTK_RESPONSE_HELP; else if(button == (QAbstractButton *)QMessageBox::Cancel) response_id = GTK_RESPONSE_CANCEL; if(AxResponseCallback(this,StickykeysAlert, response_id,XkbStickyKeysMask,StickykeysShortcutVal)) StickykeysAlert->close(); } void A11yKeyboardManager::AxStickykeysWarningPostDialog (A11yKeyboardManager *manager, bool enabled) { QString title; QString message; title = enabled ? tr("Do you want to activate Sticky Keys?") : tr("Do you want to deactivate Sticky Keys?"); message = enabled ? tr("You just pressed the Shift key 5 times in a row. This is the shortcut " "for the Sticky Keys feature, which affects the way your keyboard works.") : tr("You just pressed two keys at once, or pressed the Shift key 5 times in a row. " "This turns off the Sticky Keys feature, which affects the way your keyboard works."); if (manager->StickykeysAlert != NULL) { manager->StickykeysAlert->show(); return; } manager->StickykeysAlert = new QMessageBox(); manager->StickykeysAlert->warning(nullptr,tr("Sticky Keys Alert"), title); manager->StickykeysAlert->setText(message); manager->StickykeysAlert->setStandardButtons(QMessageBox::Help); manager->StickykeysAlert->setButtonText(QMessageBox::Rejected, enabled ? tr("Do_n't activate") : tr("Do_n't deactivate")); manager->StickykeysAlert->setButtonText(QMessageBox::Accepted, enabled ? tr("_Activate") : tr("_Deactivate")); manager->StickykeysAlert->setWindowIconText(tr("input-keyboard")); manager->StickykeysAlert->setDefaultButton(QMessageBox::Default); QObject::connect(manager->StickykeysAlert,SIGNAL(buttonClicked(QAbstractButton *button)), manager,SLOT(ax_stickykeys_response(QAbstractButton *button))); manager->StickykeysAlert->show(); /*g_object_add_weak_pointer (G_OBJECT (manager->stickykeys_alert), (gpointer*) &manager->stickykeys_alert);*/ } void A11yKeyboardManager::AxStickykeysWarningPost (A11yKeyboardManager *manager, bool enabled) { manager->StickykeysShortcutVal = enabled; /* alway try to show something */ if (! AxStickykeysWarningPostBubble (manager, enabled)) { AxStickykeysWarningPostDialog (manager, enabled); } } /* * */ void A11yKeyboardManager::SetSettingsFromServer(A11yKeyboardManager *manager) { QGSettings *settings; XkbDescRec *desc; bool changed = false; bool slowkeys_changed; bool stickykeys_changed; desc = GetXkbDescRec (); if (! desc) { return; } settings = new QGSettings(CONFIG_SCHEMA); settings->delay(); /* fprintf (stderr, "changed to : 0x%x\n", desc->ctrls->enabled_ctrls); fprintf (stderr, "changed to : 0x%x (2)\n", desc->ctrls->ax_options); */ changed |= SetBool (settings, "enable", desc->ctrls->enabled_ctrls & XkbAccessXKeysMask); changed |= SetBool (settings, "feature-state-change-beep", desc->ctrls->ax_options & (XkbAX_FeatureFBMask | XkbAX_SlowWarnFBMask)); changed |= SetBool (settings, "timeout-enable", desc->ctrls->enabled_ctrls & XkbAccessXTimeoutMask); changed |= SetInt (settings, "timeout", desc->ctrls->ax_timeout); changed |= SetBool (settings, "bouncekeys-enable", desc->ctrls->enabled_ctrls & XkbBounceKeysMask); changed |= SetInt (settings, "bouncekeys-delay", desc->ctrls->debounce_delay); changed |= SetBool (settings, "bouncekeys-beep-reject", desc->ctrls->ax_options & XkbAX_BKRejectFBMask); changed |= SetBool (settings, "mousekeys-enable", desc->ctrls->enabled_ctrls & XkbMouseKeysMask); changed |= SetInt (settings, "mousekeys-max-speed", desc->ctrls->mk_max_speed * (1000 / desc->ctrls->mk_interval)); /* NOTE : mk_time_to_max is measured in events not time */ changed |= SetInt (settings, "mousekeys-accel-time", desc->ctrls->mk_time_to_max * desc->ctrls->mk_interval); changed |= SetInt (settings, "mousekeys-init-delay", desc->ctrls->mk_delay); slowkeys_changed = SetBool (settings, "slowkeys-enable", desc->ctrls->enabled_ctrls & XkbSlowKeysMask); changed |= SetBool (settings, "slowkeys-beep-press", desc->ctrls->ax_options & XkbAX_SKPressFBMask); changed |= SetBool (settings, "slowkeys-beep-accept", desc->ctrls->ax_options & XkbAX_SKAcceptFBMask); changed |= SetBool (settings, "slowkeys-beep-reject", desc->ctrls->ax_options & XkbAX_SKRejectFBMask); changed |= SetInt (settings, "slowkeys-delay", desc->ctrls->slow_keys_delay); stickykeys_changed = SetBool (settings, "stickykeys-enable", desc->ctrls->enabled_ctrls & XkbStickyKeysMask); changed |= SetBool (settings, "stickykeys-two-key-off", desc->ctrls->ax_options & XkbAX_TwoKeysMask); changed |= SetBool (settings, "stickykeys-modifier-beep", desc->ctrls->ax_options & XkbAX_StickyKeysFBMask); changed |= SetBool (settings, "togglekeys-enable", desc->ctrls->ax_options & XkbAX_IndicatorFBMask); if (!changed && stickykeys_changed ^ slowkeys_changed) { /* * sticky or slowkeys has changed, singly, without our intervention. * 99% chance this is due to a keyboard shortcut being used. * we need to detect via this hack until we get * XkbAXN_AXKWarning notifications working (probable XKB bug), * at which time we can directly intercept such shortcuts instead. * See CbXkbEventFilter () below. */ /* sanity check: are keyboard shortcuts available? */ if (desc->ctrls->enabled_ctrls & XkbAccessXKeysMask) { if (slowkeys_changed) { AxSlowkeysWarningPost (manager, desc->ctrls->enabled_ctrls & XkbSlowKeysMask); } else { AxStickykeysWarningPost (manager, desc->ctrls->enabled_ctrls & XkbStickyKeysMask); } } } XkbFreeKeyboard (desc, XkbAllComponentsMask, True); changed |= (stickykeys_changed | slowkeys_changed); if (changed) { settings->apply(); } delete settings; } void A11yKeyboardManager::StartA11yKeyboardIdleCb() { unsigned int event_mask; USD_LOG(LOG_DEBUG, "Starting a11y_keyboard manager"); // OnStatusIconActivate(NULL,this); just for show config form. time->stop(); if (!XkbEnabled (this)) goto out; connect(settings, &QGSettings::changed, this, &A11yKeyboardManager::KeyboardCallback); SetDevicepresenceHandler (this); /* Save current xkb state so we can restore it on exit */ OriginalXkbDesc = GetXkbDescRec (); event_mask = XkbControlsNotifyMask; #ifdef DEBUG_ACCESSIBILITY event_mask |= XkbAccessXNotifyMask; /* make default when AXN_AXKWarning works */ #endif /* be sure to init before starting to monitor the server */ SetServerFromSettings (this); XkbSelectEvents (GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), XkbUseCoreKbd, event_mask, event_mask); gdk_window_add_filter (NULL, (GdkFilterFunc) CbXkbEventFilter, this); //MaybeShowStatusIcon (this); out: return; } ukui-settings-daemon/plugins/a11y-keyboard/a11y-keyboard.pro0000664000175000017500000000166615167655063022730 0ustar fengfeng#------------------------------------------------- # # Project created by QtCreator 2020-08-05T19:30:00 # #------------------------------------------------- QT += gui core widgets x11extras TARGET = a11y-keyboard TEMPLATE = lib DEFINES += A11YKEYBOARD_LIBRARY MODULE_NAME=\\\"a11y-keyboard\\\" CONFIG += c++20 no_keywords link_pkgconfig plugin debug CONFIG += app_bunale DEFINES += QT_DEPRECATED_WARNINGS include($$PWD/../../common/common.pri) PKGCONFIG += \ gtk+-3.0 \ glib-2.0 \ libnotify \ gsettings-qt \ xi SOURCES += \ a11y-keyboard-manager.cpp \ a11y-keyboard-plugin.cpp \ a11y-preferences-dialog.cpp HEADERS += \ a11y-keyboard-manager.h \ a11y-keyboard-plugin.h \ a11y-preferences-dialog.h a11y_keyboard_lib.path = $${PLUGIN_INSTALL_DIRS} a11y_keyboard_lib.files = $$OUT_PWD/liba11y-keyboard.so INSTALLS += a11y_keyboard_lib FORMS += \ a11y-preferences-dialog.ui ukui-settings-daemon/plugins/a11y-keyboard/a11y-keyboard-plugin.h0000664000175000017500000000252415167655063023645 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef A11YKEYBOARDPLUGIN_H #define A11YKEYBOARDPLUGIN_H #include "plugin-interface.h" #include "a11y-keyboard-manager.h" class A11yKeyboardPlugin : public PluginInterface { public: ~A11yKeyboardPlugin(); static PluginInterface * getInstance(); virtual void activate(); virtual void deactivate(); private: A11yKeyboardPlugin(); A11yKeyboardPlugin(A11yKeyboardPlugin&)=delete; static A11yKeyboardManager *UsdA11yManager; static PluginInterface *mInstance; }; extern "C" Q_DECL_EXPORT PluginInterface* createSettingsPlugin(); #endif // A11YKEYBOARDPLUGIN_H ukui-settings-daemon/plugins/kds/0000775000175000017500000000000015167655063016034 5ustar fengfengukui-settings-daemon/plugins/kds/widget.cpp0000664000175000017500000002743215167655063020033 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2023 KylinSoft Co., Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "widget.h" #include "ui_widget.h" #include #include #include #include #include #include #include #include #include #include #include "style_helper.h" #include "screen_switch.h" #include "usd_base_class.h" #include "ukuistylehelper/ukuistylehelper.h" #include "windowmanager/windowmanager.h" #include "clib-syslog.h" const static QVector> s_modeImages = { {UsdBaseClass::firstScreenMode, ":/img/main.png"}, {UsdBaseClass::secondScreenMode, ":/img/vice.png"}, {UsdBaseClass::cloneScreenMode, ":/img/clone.png"}, {UsdBaseClass::extendScreenMode, ":/img/extend.png"} }; Widget::Widget(QWidget *parent) : QWidget(parent) , ui(new Ui::Widget) { ui->setupUi(this); setAttribute(Qt::WA_TranslucentBackground, true); setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint); /* 不在任务栏显示图标 */ KX11Extras::setState(winId(), NET::SkipTaskbar | NET::SkipPager); this->setProperty("useStyleWindowManager", false); //初始化UI this->initUi(); //键盘快捷操作 this->addShortcutActions(); // connect(KX11Extras::self(), &KX11Extras::activeWindowChanged, this,[&](WId activeWindowId) { // //失焦退出 // if (activeWindowId != 0 && activeWindowId != this->winId()) { // this->close(); // } // }); connect(ScreenSwitch::instance(), &ScreenSwitch::sigScreenParamChanged, this, [=]{ //屏幕参数改变退出 USD_LOG(LOG_DEBUG, "close : due to screens param changed"); this->close(); }); } Button* Widget::createButton(const QString& text, const QString& img) { Button* button = new Button(text, img, this); button->setCheckable(true); button->setFixedSize(368, 64); return button; } void Widget::initTitleUi() { m_titleWidget = new QWidget(this); m_titleWidget->setFixedHeight(84); m_title = new QLabel(this); QFont font; font.setPointSizeF(StyleHelper::instance()->getFontSize() + 4); m_title->setFont(font); m_title->setText(tr("System Screen Projection")); m_title->adjustSize(); m_titleLayout = new QHBoxLayout(m_titleWidget); m_titleLayout->addWidget(m_title); m_titleLayout->setAlignment(Qt::AlignCenter); m_mainLayout->addWidget(m_titleWidget); } void Widget::initButtons() { m_btnsWidget = new QWidget(this); m_buttonGroup = new QButtonGroup(this); m_buttonGroup->setExclusive(true); m_btnsLayout = new QVBoxLayout(m_btnsWidget); m_btnsLayout->setContentsMargins(8, 8, 8, 8); m_btnsLayout->setSpacing(16); //获取屏幕列表 QStringList screens = ScreenSwitch::instance()->getScreenList(); int currentMode = ScreenSwitch::instance()->getScreenMode(); bool tabletMode = StyleHelper::instance()->isTabletMode(); if (screens.count() <= 1) { screens << tr("None"); } //屏幕数量三个以上只取前两个 if (screens.count() > 2) { screens = screens.mid(0, 2); } screens << tr("Clone Screen"); screens << tr("Extend Screen"); for (int i = 0; i < screens.count(); ++i) { const QString& image = s_modeImages[i].second; Button* btn = createButton(screens[i], image); btn->setMode(s_modeImages[i].first); m_btnsLayout->addWidget(btn); m_buttonGroup->addButton(btn, i); if (currentMode == btn->getMode()) { //选中状态 btn->setStatus(true); btn->setChecked(true); } //平板模式禁用选项 if (tabletMode) { btn->setEnabled(false); } } m_btnsWidget->adjustSize(); m_mainLayout->addWidget(m_btnsWidget); connect(m_buttonGroup, QOverload::of(&QButtonGroup::buttonClicked), [=](QAbstractButton *button){ Button * btn = dynamic_cast