mirror of
https://github.com/linuxdeepin/dde-dock.git
synced 2025-06-04 17:33:05 +00:00
Compare commits
174 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
a90f386ddc | ||
![]() |
13c4162b5e | ||
![]() |
32140ccf26 | ||
![]() |
697e678587 | ||
![]() |
b2da5add21 | ||
![]() |
a15d92c7eb | ||
![]() |
00d0f13c1a | ||
![]() |
32bd005492 | ||
![]() |
3eb95284a0 | ||
![]() |
1653473ecc | ||
![]() |
0f940b6579 | ||
![]() |
72f4286f49 | ||
![]() |
e8e0f3c96f | ||
![]() |
48cced00a9 | ||
![]() |
edea9b860d | ||
![]() |
710a9f562b | ||
![]() |
478f564631 | ||
![]() |
241e668ea2 | ||
![]() |
e6e8995e51 | ||
![]() |
2b81011b7e | ||
![]() |
2bb5e49cac | ||
![]() |
b4ec458dd5 | ||
![]() |
572c0c8aad | ||
![]() |
c0c909f9e8 | ||
![]() |
8b04a51b51 | ||
![]() |
d1f61330f3 | ||
![]() |
7097ae7f3c | ||
![]() |
3939ca9c12 | ||
![]() |
0300e28332 | ||
![]() |
13b1e661ea | ||
![]() |
b5399bd0ec | ||
![]() |
945bb03a27 | ||
![]() |
0f93647736 | ||
![]() |
ca4408c660 | ||
![]() |
ee030a6505 | ||
![]() |
326f510e4e | ||
![]() |
27e1493982 | ||
![]() |
3a5438b399 | ||
![]() |
e47a6dfb80 | ||
![]() |
b74544aa23 | ||
![]() |
3b567d096e | ||
![]() |
6b0fec0426 | ||
![]() |
f4a40f36b8 | ||
![]() |
556ea5acf8 | ||
![]() |
31e149d3d2 | ||
![]() |
a222173da6 | ||
![]() |
01e2377d86 | ||
![]() |
263e5a4358 | ||
![]() |
12d346a2c9 | ||
![]() |
bce2a49971 | ||
![]() |
2a5a1e0efb | ||
![]() |
4eecd92395 | ||
![]() |
cf909cd4d7 | ||
![]() |
107e7427d6 | ||
![]() |
79efd518a9 | ||
![]() |
6c492486a5 | ||
![]() |
a3499fcf34 | ||
![]() |
e0ac1f9562 | ||
![]() |
e02ff1ac53 | ||
![]() |
d765d60b22 | ||
![]() |
dab0083dcd | ||
![]() |
4e69cb7b68 | ||
![]() |
442a98cb70 | ||
![]() |
971cd92007 | ||
![]() |
c76dcb4361 | ||
![]() |
2459613b69 | ||
![]() |
d2e724b83e | ||
![]() |
3365365b56 | ||
![]() |
58547b091d | ||
![]() |
85deffe309 | ||
![]() |
919a2b5a49 | ||
![]() |
c2aedfe052 | ||
![]() |
70d73662ec | ||
![]() |
3573bb258b | ||
![]() |
afa0494067 | ||
![]() |
f771da5bdb | ||
![]() |
f6019f900d | ||
![]() |
7f148d257a | ||
![]() |
67df42b8a4 | ||
![]() |
7cd0cddf44 | ||
![]() |
f408bd89f4 | ||
![]() |
25194dbf13 | ||
![]() |
00369b053b | ||
![]() |
0f59177248 | ||
![]() |
f6b2044bea | ||
![]() |
111fb6c518 | ||
![]() |
38871e8b0d | ||
![]() |
d24429904c | ||
![]() |
914ddce850 | ||
![]() |
7ed222aadb | ||
![]() |
3cbb828863 | ||
![]() |
4b9b283e5c | ||
![]() |
e3c3dfe94d | ||
![]() |
75ebd8a0f2 | ||
![]() |
e14b877696 | ||
![]() |
406c5d8539 | ||
![]() |
5aa27ee40f | ||
![]() |
e78be366bc | ||
![]() |
2ccf74dd35 | ||
![]() |
41d27c5ad7 | ||
![]() |
bdb0dc3b86 | ||
![]() |
d1b37b045a | ||
![]() |
811fc172d7 | ||
![]() |
e4b9d8e695 | ||
![]() |
0e5aab95f5 | ||
![]() |
5d87a44ac4 | ||
![]() |
9f71814849 | ||
![]() |
e169dcf4de | ||
![]() |
265cbbec13 | ||
![]() |
dfe4514981 | ||
![]() |
7f554a1da5 | ||
![]() |
3da8943417 | ||
![]() |
e4dde7b5a1 | ||
![]() |
3a5f29ca28 | ||
![]() |
9011e4a125 | ||
![]() |
9f14b5f0a8 | ||
![]() |
1f2d150792 | ||
![]() |
cce27c4d0c | ||
![]() |
d2164e99ec | ||
![]() |
167a334142 | ||
![]() |
068f35e405 | ||
![]() |
e1a734e030 | ||
![]() |
8ca5259c1e | ||
![]() |
7c897e6c96 | ||
![]() |
668cea52fb | ||
![]() |
67b6fe41b8 | ||
![]() |
9de057e2cc | ||
![]() |
9e364902bf | ||
![]() |
5f6cacdf2a | ||
![]() |
eb33819302 | ||
![]() |
fae8e4436f | ||
![]() |
101dec15ca | ||
![]() |
fb3f888157 | ||
![]() |
42961e5092 | ||
![]() |
9f092c2d01 | ||
![]() |
78d5bdfb27 | ||
![]() |
e245821f93 | ||
![]() |
e5ce99533c | ||
![]() |
7a7b7d9235 | ||
![]() |
70683c4800 | ||
![]() |
32f8fe02bf | ||
![]() |
ec4637a430 | ||
![]() |
f48785876e | ||
![]() |
223a9df0d7 | ||
![]() |
c1aa1cf13c | ||
![]() |
7928cd6a2e | ||
![]() |
5894cc8a7d | ||
![]() |
ab58721930 | ||
![]() |
e5f7833b6a | ||
![]() |
6697f4e8c6 | ||
![]() |
fffda4d9ea | ||
![]() |
07b4efd267 | ||
![]() |
ccd2d3f586 | ||
![]() |
a36ee58753 | ||
![]() |
f0108d1c41 | ||
![]() |
83f264720c | ||
![]() |
79cab3fac8 | ||
![]() |
15e5a0fadb | ||
![]() |
0a103e62bd | ||
![]() |
48a580117a | ||
![]() |
579cf0afe9 | ||
![]() |
31958dfe1b | ||
![]() |
1be4bebe0a | ||
![]() |
24ff57eb70 | ||
![]() |
69cec726c3 | ||
![]() |
af35000028 | ||
![]() |
119d72b0ea | ||
![]() |
5908ee1605 | ||
![]() |
dc77b8904d | ||
![]() |
50bbc3cf01 | ||
![]() |
9bfcf4580e | ||
![]() |
cda8e2c746 | ||
![]() |
a1af30c814 | ||
![]() |
1b5f9554d1 |
6
.github/workflows/backup-to-gitlab.yml
vendored
6
.github/workflows/backup-to-gitlab.yml
vendored
@ -8,10 +8,8 @@ concurrency:
|
||||
jobs:
|
||||
backup-to-gitlabwh:
|
||||
uses: linuxdeepin/.github/.github/workflows/backup-to-gitlabwh.yml@master
|
||||
secrets:
|
||||
BRIDGETOKEN: ${{ secrets.BRIDGETOKEN }}
|
||||
secrets: inherit
|
||||
|
||||
backup-to-gitee:
|
||||
uses: linuxdeepin/.github/.github/workflows/backup-to-gitee.yml@master
|
||||
secrets:
|
||||
GITEE_SYNC_TOKEN: ${{ secrets.GITEE_SYNC_TOKEN }}
|
||||
secrets: inherit
|
||||
|
12
.github/workflows/call-api-check.yml
vendored
Normal file
12
.github/workflows/call-api-check.yml
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
name: apiCheck
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened, synchronize, reopened]
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
api-check:
|
||||
uses: linuxdeepin/.github/.github/workflows/api-check.yml@master
|
17
.github/workflows/call-build-deb.yml
vendored
17
.github/workflows/call-build-deb.yml
vendored
@ -1,17 +0,0 @@
|
||||
name: Call build-deb
|
||||
on:
|
||||
pull_request_target:
|
||||
paths-ignore:
|
||||
- ".github/workflows/**"
|
||||
types: [ opened, closed, synchronize ]
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-pull/${{ github.event.number }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
check_job:
|
||||
if: github.event.action != 'closed' || github.event.pull_request.merged
|
||||
uses: linuxdeepin/.github/.github/workflows/build-deb.yml@master
|
||||
secrets:
|
||||
BridgeToken: ${{ secrets.BridgeToken }}
|
@ -10,8 +10,4 @@ on:
|
||||
jobs:
|
||||
check_job:
|
||||
uses: linuxdeepin/.github/.github/workflows/build-distribution.yml@master
|
||||
secrets:
|
||||
BUILD_GPG_PRIVATE_KEY: ${{ secrets.BUILD_GPG_PRIVATE_KEY }}
|
||||
BUILD_SSH_PRIVATE_KEY: ${{ secrets.BUILD_SSH_PRIVATE_KEY }}
|
||||
WEBDAV_PASSWD: ${{ secrets.WEBDAV_PASSWD }}
|
||||
WEBDAV_USER: ${{ secrets.WEBDAV_USER }}
|
||||
secrets: inherit
|
||||
|
3
.github/workflows/call-chatOps.yml
vendored
3
.github/workflows/call-chatOps.yml
vendored
@ -6,5 +6,4 @@ on:
|
||||
jobs:
|
||||
chatopt:
|
||||
uses: linuxdeepin/.github/.github/workflows/chatOps.yml@master
|
||||
secrets:
|
||||
APP_PRIVATE_KEY: ${{ secrets.APP_PRIVATE_KEY }}
|
||||
secrets: inherit
|
||||
|
3
.github/workflows/call-clacheck.yml
vendored
3
.github/workflows/call-clacheck.yml
vendored
@ -12,5 +12,4 @@ concurrency:
|
||||
jobs:
|
||||
clacheck:
|
||||
uses: linuxdeepin/.github/.github/workflows/cla-check.yml@master
|
||||
secrets:
|
||||
APP_PRIVATE_KEY: ${{ secrets.APP_PRIVATE_KEY }}
|
||||
secrets: inherit
|
||||
|
20
.github/workflows/call-debian-check.yml
vendored
Normal file
20
.github/workflows/call-debian-check.yml
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
name: debianCheck
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened, synchronize, reopened]
|
||||
|
||||
permissions:
|
||||
pull-requests: write
|
||||
contents: read
|
||||
checks: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
debian-check:
|
||||
uses: linuxdeepin/.github/.github/workflows/debian-check.yml@master
|
||||
with:
|
||||
job_name: "debian-check"
|
||||
|
17
.github/workflows/call-static-check.yml
vendored
Normal file
17
.github/workflows/call-static-check.yml
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
name: staticCheck
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened, synchronize, reopened]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
checks: write
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
static-check:
|
||||
uses: linuxdeepin/.github/.github/workflows/static-check.yml@master
|
13
.github/workflows/call-tag-build.yml
vendored
13
.github/workflows/call-tag-build.yml
vendored
@ -1,13 +0,0 @@
|
||||
name: tag build
|
||||
on:
|
||||
push:
|
||||
tags: "*"
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
uses: linuxdeepin/.github/.github/workflows/tag-build.yml@master
|
||||
secrets: inherit
|
2
.github/workflows/cppcheck.yml
vendored
2
.github/workflows/cppcheck.yml
vendored
@ -14,7 +14,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: export
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
persist-credentials: false
|
||||
|
13
.gitignore
vendored
13
.gitignore
vendored
@ -13,6 +13,7 @@
|
||||
*.a
|
||||
|
||||
build*/
|
||||
obj-*-linux-gnu/
|
||||
*.pro.user*
|
||||
CMakeLists.txt.user*
|
||||
*.DS_Store
|
||||
@ -26,3 +27,15 @@ dde-dock
|
||||
*/dbusinterface/generation_dbus_interface/
|
||||
*/*/dbusinterface/generation_dbus_interface/
|
||||
.transifexrc
|
||||
.cache
|
||||
|
||||
# debain
|
||||
debian/.debhelper/
|
||||
debian/dde-dock/
|
||||
debian/dde-dock-dev/
|
||||
debian/dde-dock-onboard-plugin/
|
||||
debian/tmp/
|
||||
debian/*.log
|
||||
debian/*.substvars
|
||||
debian/debhelper-build-stamp
|
||||
debian/files
|
||||
|
@ -35,10 +35,9 @@ test_build:
|
||||
|
||||
tag_build:
|
||||
steps:
|
||||
- branch_package:
|
||||
source_project: deepin:Develop:dde
|
||||
source_package: %{SCM_REPOSITORY_NAME}
|
||||
target_project: deepin:Unstable:dde
|
||||
- trigger_services:
|
||||
project: deepin:Unstable:dde
|
||||
package: %{SCM_REPOSITORY_NAME}
|
||||
filters:
|
||||
event: tag_push
|
||||
|
||||
|
10
.reuse/dep5
10
.reuse/dep5
@ -24,7 +24,7 @@ Copyright: UnionTech Software Technology Co., Ltd.
|
||||
License: LGPL-3.0-or-later
|
||||
|
||||
# png svg
|
||||
Files: plugins/*.png plugins/*.svg frame/*.svg tests/*.png tests/*.svg
|
||||
Files: plugins/*.png plugins/*.svg frame/*.svg tests/*.png tests/*.svg plugins/*.dci
|
||||
Copyright: UnionTech Software Technology Co., Ltd.
|
||||
License: LGPL-3.0-or-later
|
||||
|
||||
@ -39,7 +39,8 @@ Copyright: None
|
||||
License: CC0-1.0
|
||||
|
||||
# xml toml json policy yaml
|
||||
Files: gschema/*.xml plugins/*.xml frame/*.xml .clog.toml plugins/*.json configs/*.json .packit.yaml .tx/config .tx/deepin.conf plugins/overlay-warning/com.deepin.dde.dock.overlay.policy plugins/dcc-dock-plugin/.tx/config
|
||||
Files: gschema/*.xml plugins/*.xml frame/*.xml .clog.toml plugins/*.json configs/*.json .packit.yaml .tx/config .tx/deepin.conf plugins/overlay-warning/com.deepin.dde.dock.overlay.policy plugins/dcc-dock-plugin/.tx/config
|
||||
frame/taskmanager/window_patterns.json
|
||||
Copyright: None
|
||||
License: CC0-1.0
|
||||
|
||||
@ -62,3 +63,8 @@ License: CC0-1.0
|
||||
Files: plugins/overlay-warning/org.deepin.dde.dock.overlay.policy
|
||||
Copyright: UnionTech Software Technology Co., Ltd.
|
||||
License: LGPL-3.0-or-later
|
||||
|
||||
Files: toolGenerate/**/*
|
||||
Copyright: None
|
||||
License: CC0-1.0
|
||||
|
||||
|
@ -1,11 +1,13 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
if (NOT DEFINED VERSION)
|
||||
set(VERSION 6.0.13)
|
||||
set(VERSION 6.0.37)
|
||||
endif()
|
||||
|
||||
project(dde-dock)
|
||||
|
||||
find_package(DtkTools REQUIRED)
|
||||
|
||||
set(CMAKE_THREAD_LIBS_INIT "-lpthread")
|
||||
set(CMAKE_HAVE_THREADS_LIBRARY 1)
|
||||
set(CMAKE_USE_PTHREADS_INIT 1)
|
||||
@ -31,6 +33,10 @@ endif()
|
||||
# generate a compile commands file as complete database for vim-YouCompleteMe or some other similar tools
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
|
||||
# Install settings
|
||||
if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
||||
set(CMAKE_INSTALL_PREFIX /usr)
|
||||
endif ()
|
||||
include(GNUInstallDirs)
|
||||
|
||||
if (NOT (${CMAKE_BUILD_TYPE} MATCHES "Debug"))
|
||||
@ -64,13 +70,13 @@ function(generation_dbus_interface xmldir outdir)
|
||||
string(REPLACE "." "_" classname ${classname})
|
||||
string(TOLOWER ${classname} filename)
|
||||
|
||||
execute_process(COMMAND qdbusxml2cpp-fix -c ${classname} -p ${outdir}/${filename} ${XMLFILE}
|
||||
execute_process(COMMAND ${DTK_XML2CPP} -c ${classname} -p ${outdir}/${filename} ${XMLFILE}
|
||||
WORKING_DIRECTORY ${outdir})
|
||||
endforeach()
|
||||
endfunction(generation_dbus_interface)
|
||||
|
||||
file(GLOB INTERFACES "interfaces/*.h")
|
||||
|
||||
add_definitions(-DCVERSION="${VERSION}")
|
||||
#因为单元测试需要直接测试源代码,而主程序代码中include的单元使用了相对路径
|
||||
#单元测试的CMakeLists和主程序的CMakeLists路径不同,编译单元测试时会提示找不到文件
|
||||
#因此设置搜索路径
|
||||
@ -130,11 +136,6 @@ add_subdirectory("frame")
|
||||
add_subdirectory("plugins")
|
||||
#add_subdirectory("tests")
|
||||
|
||||
# Install settings
|
||||
if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
||||
set(CMAKE_INSTALL_PREFIX /usr)
|
||||
endif ()
|
||||
|
||||
## qm files
|
||||
file(GLOB QM_FILES "translations/*.qm")
|
||||
install(FILES ${QM_FILES}
|
||||
|
232
LICENSES/GPL-3.0-or-later.txt
Normal file
232
LICENSES/GPL-3.0-or-later.txt
Normal file
@ -0,0 +1,232 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright © 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
“This License” refers to version 3 of the GNU General Public License.
|
||||
|
||||
“Copyright” also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.
|
||||
|
||||
“The Program” refers to any copyrightable work licensed under this License. Each licensee is addressed as “you”. “Licensees” and “recipients” may be individuals or organizations.
|
||||
|
||||
To “modify” a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a “modified version” of the earlier work or a work “based on” the earlier work.
|
||||
|
||||
A “covered work” means either the unmodified Program or a work based on the Program.
|
||||
|
||||
To “propagate” a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well.
|
||||
|
||||
To “convey” a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays “Appropriate Legal Notices” to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
The “source code” for a work means the preferred form of the work for making modifications to it. “Object code” means any non-source form of a work.
|
||||
|
||||
A “Standard Interface” means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language.
|
||||
|
||||
The “System Libraries” of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A “Major Component”, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The “Corresponding Source” for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to “keep intact all notices”.
|
||||
|
||||
c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an “aggregate” if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work.
|
||||
|
||||
A “User Product” is either (1) a “consumer product”, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, “normally used” refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product.
|
||||
|
||||
“Installation Information” for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
“Additional permissions” are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered “further restrictions” within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License.
|
||||
|
||||
An “entity transaction” is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
A “contributor” is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's “contributor version”.
|
||||
|
||||
A contributor's “essential patent claims” are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, “control” includes the right to grant patent sublicenses in a manner consistent with the requirements of this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a “patent license” is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To “grant” such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. “Knowingly relying” means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it.
|
||||
|
||||
A patent license is “discriminatory” if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
The Free Software Foundation may publish revised and/or new versions of the GNU 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 Program specifies that a certain numbered version of the GNU General Public License “or any later version” applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the “copyright” line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
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 (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, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an “about box”.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school, if any, to sign a “copyright disclaimer” for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read <https://www.gnu.org/philosophy/why-not-lgpl.html>.
|
@ -11,7 +11,7 @@ url="https://github.com/linuxdeepin/dde-dock"
|
||||
license=('LGPL-3.0-or-later')
|
||||
depends=('qt5-svg' 'deepin-daemon-git' 'deepin-qt5integration-git'
|
||||
'deepin-qt-dbus-factory-git' 'libdbusmenu-qt5' 'dtkcommon-git'
|
||||
'dtkcore-git' 'deepin-qt5integration-git' 'deepin-qt-dbus-factory'
|
||||
'dtkcore-git' 'deepin-qt5integration-git'
|
||||
'libdbusmenu-qt5' 'deepin-control-center-git' 'dwayland-git')
|
||||
makedepends=('git' 'cmake' 'ninja' 'qt5-tools' 'gtest' 'gmock' 'extra-cmake-modules')
|
||||
conflicts=('deepin-dock')
|
||||
|
@ -1,40 +0,0 @@
|
||||
{
|
||||
"magic":"dsg.config.meta",
|
||||
"version":"1.0",
|
||||
"contents":{
|
||||
"Dock_Show_Window_name":{
|
||||
"value":0,
|
||||
"serial":0,
|
||||
"flags":"",
|
||||
"name":"小窗口显示窗口名称",
|
||||
"name[zh_CN]":"小窗口显示窗口名称",
|
||||
"description[zh_CN]":"提供鼠标悬停小窗口标题显示配置,默认为悬停显示: \
|
||||
当配置为全部显示时,鼠标悬停在任务栏图标位置时所有预览窗口显示标题信息; \
|
||||
当配置为悬停显示时,鼠标仅在悬停在预览小窗口时在当前窗口显示标题信息; \
|
||||
当配置为不显示时,鼠标悬停应用位置和预览小窗口位置时都不显示标题信息;",
|
||||
"description":"0 Mouse over show;1 Always show; 2 Always hide",
|
||||
"permissions":"readwrite",
|
||||
"visibility":"public"
|
||||
},
|
||||
"Dock_Quick_Plugins": {
|
||||
"value": ["power", "network", "shutdown", "trash", "show-desktop", "multitasking"],
|
||||
"serial": 0,
|
||||
"flags": [],
|
||||
"name": "显示在任务栏上的快捷插件",
|
||||
"name[zh_CN]": "*****",
|
||||
"description": "记录哪些插件的图标在任务栏启动的时候显示在任务栏上",
|
||||
"permissions": "readwrite",
|
||||
"visibility": "private"
|
||||
},
|
||||
"Dock_Quick_Tray_Name": {
|
||||
"value": ["fcitx", "indicator:keybord_layout"],
|
||||
"serial": 0,
|
||||
"flags": [],
|
||||
"name": "显示在任务栏上的托盘图标",
|
||||
"name[zh_CN]": "任务栏上固定的托盘图标",
|
||||
"description": "记录哪些托盘的图标在任务栏启动的时候显示在任务栏上",
|
||||
"permissions": "readwrite",
|
||||
"visibility": "private"
|
||||
}
|
||||
}
|
||||
}
|
197
configs/com.deepin.dde.dock.json
Normal file
197
configs/com.deepin.dde.dock.json
Normal file
@ -0,0 +1,197 @@
|
||||
{
|
||||
"magic": "dsg.config.meta",
|
||||
"version": "1.0",
|
||||
"contents": {
|
||||
"Window_Size_Fashion": {
|
||||
"value": 48,
|
||||
"serial": 0,
|
||||
"flags": [],
|
||||
"name": "Window_Size_Fashion",
|
||||
"name[zh_CN]": "*****",
|
||||
"description": "",
|
||||
"permissions": "readwrite",
|
||||
"visibility": "private"
|
||||
},
|
||||
"Icon_Size": {
|
||||
"value": 36,
|
||||
"serial": 0,
|
||||
"flags": [],
|
||||
"name": "Icon_Size",
|
||||
"name[zh_CN]": "*****",
|
||||
"description": "",
|
||||
"permissions": "readwrite",
|
||||
"visibility": "private"
|
||||
},
|
||||
"Position": {
|
||||
"value": "bottom",
|
||||
"serial": 0,
|
||||
"flags": [],
|
||||
"name": "Position",
|
||||
"name[zh_CN]": "*****",
|
||||
"description": "",
|
||||
"permissions": "readwrite",
|
||||
"visibility": "private"
|
||||
},
|
||||
"Hide_Timeout": {
|
||||
"value": 0,
|
||||
"serial": 0,
|
||||
"flags": [],
|
||||
"name": "Hide_Timeout",
|
||||
"name[zh_CN]": "*****",
|
||||
"description": "",
|
||||
"permissions": "readwrite",
|
||||
"visibility": "private"
|
||||
},
|
||||
"Hide_Mode": {
|
||||
"value": "keep-showing",
|
||||
"serial": 0,
|
||||
"flags": [],
|
||||
"name": "Hide_Mode",
|
||||
"name[zh_CN]": "*****",
|
||||
"description": "The value will influence when the dock is shown or hidden.",
|
||||
"permissions": "readwrite",
|
||||
"visibility": "private"
|
||||
},
|
||||
"Show_Timeout": {
|
||||
"value": 100,
|
||||
"serial": 0,
|
||||
"flags": [],
|
||||
"name": "Show_Timeout",
|
||||
"name[zh_CN]": "*****",
|
||||
"description": "",
|
||||
"permissions": "readwrite",
|
||||
"visibility": "private"
|
||||
},
|
||||
"Window_Size_Efficient": {
|
||||
"value": 40,
|
||||
"serial": 0,
|
||||
"flags": [],
|
||||
"name": "Window_Size_Efficient",
|
||||
"name[zh_CN]": "*****",
|
||||
"description": "",
|
||||
"permissions": "readwrite",
|
||||
"visibility": "private"
|
||||
},
|
||||
"Plugin_Settings": {
|
||||
"value": "{}",
|
||||
"serial": 0,
|
||||
"flags": [],
|
||||
"name": "Plugin_Settings",
|
||||
"name[zh_CN]": "*****",
|
||||
"description": "",
|
||||
"permissions": "readwrite",
|
||||
"visibility": "private"
|
||||
},
|
||||
"Docked_Apps": {
|
||||
"value": ["/usr/share/applications/dde-file-manager", "/usr/share/applications/uos-browser", "/usr/share/applications/org.deepin.browser", "/usr/share/applications/deepin-appstore", "/usr/share/applications/deepin-app-store", "/usr/share/applications/com.deepin.store.intranet", "/usr/share/applications/deepin-album", "/usr/share/applications/deepin-music", "/usr/share/applications/deepin-contacts", "/usr/share/applications/dde-calendar", "/usr/share/applications/dde-control-center"],
|
||||
"serial": 0,
|
||||
"flags": [],
|
||||
"name": "Docked_Apps",
|
||||
"name[zh_CN]": "*****",
|
||||
"description": "The default apps which is docked when dock is started.",
|
||||
"permissions": "readwrite",
|
||||
"visibility": "private"
|
||||
},
|
||||
"Win_Icon_Preferred_Apps": {
|
||||
"value": ["apps.com.qq.im", "deepin.com.qq.im", "apps.com.qq.im.light", "apps.com.qq.b.eim", "apps.com.qq.rtxclient"],
|
||||
"serial": 0,
|
||||
"flags": [],
|
||||
"name": "Win_Icon_Preferred_Apps",
|
||||
"name[zh_CN]": "*****",
|
||||
"description": "",
|
||||
"permissions": "readwrite",
|
||||
"visibility": "private"
|
||||
},
|
||||
"Delay_Plugins_Time": {
|
||||
"value": 0,
|
||||
"serial": 0,
|
||||
"flags": [],
|
||||
"name": "Delay_Plugins_Time",
|
||||
"name[zh_CN]": "*****",
|
||||
"description": "",
|
||||
"permissions": "readwrite",
|
||||
"visibility": "private"
|
||||
},
|
||||
"Force_Quit_App": {
|
||||
"value": "enabled",
|
||||
"serial": 0,
|
||||
"flags": [],
|
||||
"name": "Force_Quit_App",
|
||||
"name[zh_CN]": "*****",
|
||||
"description": "",
|
||||
"permissions": "readwrite",
|
||||
"visibility": "private"
|
||||
},
|
||||
"Display_Mode": {
|
||||
"value": "fashion",
|
||||
"serial": 0,
|
||||
"flags": [],
|
||||
"name": "Display_Mode",
|
||||
"name[zh_CN]": "*****",
|
||||
"description": "The dock gets different display mode, for instance, dock looks like win7 taskbar on classic mode.",
|
||||
"permissions": "readwrite",
|
||||
"visibility": "private"
|
||||
},
|
||||
"Recent_App": {
|
||||
"value": [],
|
||||
"serial": 0,
|
||||
"flags": [],
|
||||
"name": "Recent_App",
|
||||
"name[zh_CN]": "*****",
|
||||
"description": "The apps which has been opened recently when dock is started",
|
||||
"permissions": "readwrite",
|
||||
"visibility": "private"
|
||||
},
|
||||
"Show_Recent": {
|
||||
"value": false,
|
||||
"serial": 0,
|
||||
"flags": [],
|
||||
"name": "Show_Recent",
|
||||
"name[zh_CN]": "*****",
|
||||
"description": "show or hide recent app in dock",
|
||||
"permissions": "readwrite",
|
||||
"visibility": "private"
|
||||
},
|
||||
"Show_MultiWindow": {
|
||||
"value": false,
|
||||
"serial": 0,
|
||||
"flags": [],
|
||||
"name": "Show_MultiWindow",
|
||||
"name[zh_CN]": "*****",
|
||||
"description": "show or hide Multi Window in dock when the Entry has subWindow",
|
||||
"permissions": "readwrite",
|
||||
"visibility": "private"
|
||||
},
|
||||
"Dock_Show_Window_name":{
|
||||
"value":0,
|
||||
"serial":0,
|
||||
"flags":"",
|
||||
"name":"小窗口显示窗口名称",
|
||||
"name[zh_CN]":"小窗口显示窗口名称",
|
||||
"description[zh_CN]": "提供鼠标悬停小窗口标题显示配置,默认为悬停显示: \n 当配置为全部显示时,鼠标悬停在任务栏图标位置时所有预览窗口显示标题信息; \n 当配置为悬停显示时,鼠标仅在悬停在预览小窗口时在当前窗口显示标题信息; \n当配置为不显示时,鼠标悬停应用位置和预览小窗口位置时都不显示标题信息;",
|
||||
"description":"0 Mouse over show;1 Always show; 2 Always hide",
|
||||
"permissions":"readwrite",
|
||||
"visibility":"public"
|
||||
},
|
||||
"Dock_Quick_Plugins": {
|
||||
"value": ["power", "network", "shutdown", "show-desktop", "multitasking", "notification", "uosai"],
|
||||
"serial": 0,
|
||||
"flags": [],
|
||||
"name": "Quick Plugins show on dock",
|
||||
"name[zh_CN]": "显示在任务栏上的快捷插件",
|
||||
"description": "记录哪些插件的图标在任务栏启动的时候显示在任务栏上",
|
||||
"permissions": "readwrite",
|
||||
"visibility": "private"
|
||||
},
|
||||
"Dock_Quick_Tray_Name": {
|
||||
"value": ["fcitx", "indicator:keybord_layout"],
|
||||
"serial": 0,
|
||||
"flags": [],
|
||||
"name": "Tray icons show on dock",
|
||||
"name[zh_CN]": "任务栏上固定的托盘图标",
|
||||
"description": "记录哪些托盘的图标在任务栏启动的时候显示在任务栏上",
|
||||
"permissions": "readwrite",
|
||||
"visibility": "private"
|
||||
}
|
||||
}
|
||||
}
|
224
debian/changelog
vendored
224
debian/changelog
vendored
@ -1,3 +1,227 @@
|
||||
dde-dock (6.0.37) unstable; urgency=medium
|
||||
|
||||
* release 6.0.37
|
||||
* fix linuxdeepin/developer-center#7612
|
||||
|
||||
-- Mike Chen <chenke@deepin.org> Wed, 03 Apr 2024 10:22:29 +0800
|
||||
|
||||
dde-dock (6.0.36) unstable; urgency=medium
|
||||
|
||||
* release 6.0.36
|
||||
* fix linuxdeepin/developer-center#7222
|
||||
* fix linuxdeepin/developer-center#7207
|
||||
* fix linuxdeepin/developer-center#6454
|
||||
|
||||
-- Mike Chen <chenke@deepin.org> Wed, 06 Mar 2024 16:50:36 +0800
|
||||
|
||||
dde-dock (6.0.35) unstable; urgency=medium
|
||||
|
||||
* feat: adjust dock ui
|
||||
|
||||
-- tsic404 <liuheng@deepin.org> Thu, 01 Feb 2024 10:58:27 +0800
|
||||
|
||||
dde-dock (6.0.34) unstable; urgency=medium
|
||||
|
||||
* fix: dock animation broken (https://github.com/linuxdeepin/developer-center/issues/7143)
|
||||
* fix: dock plugin calculated to an incorrect size (https://github.com/linuxdeepin/developer-center/issues/7127)
|
||||
* fix: dock will not auto hide after set size (https://github.com/linuxdeepin/developer-center/issues/7129)
|
||||
* fix: dock plugin unable to click when in keep hide (https://github.com/linuxdeepin/developer-center/issues/7132)
|
||||
* fix: dock item indicator not update (https://github.com/linuxdeepin/developer-center/issues/7097)
|
||||
|
||||
-- tsic404 <liuheng@deepin.org> Tue, 30 Jan 2024 16:17:59 +0800
|
||||
|
||||
dde-dock (6.0.33) unstable; urgency=medium
|
||||
|
||||
* fix: tmp block uosai in quickpanel
|
||||
|
||||
-- tsic404 <liuheng@deepin.org> Fri, 26 Jan 2024 14:38:06 +0800
|
||||
|
||||
dde-dock (6.0.32) unstable; urgency=medium
|
||||
|
||||
* fix: dock get max size when positionChanged and KeepHide mode (https://github.com/linuxdeepin/developer-center/issues/7040)
|
||||
* fix: dock not remove plugin when fcitx exit (https://github.com/linuxdeepin/developer-center/issues/7080)
|
||||
* fix: dock theme not follow system (https://github.com/linuxdeepin/developer-center/issues/7090)
|
||||
|
||||
-- tsic404 <liuheng@deepin.org> Thu, 25 Jan 2024 14:30:26 +0800
|
||||
|
||||
dde-dock (6.0.31) unstable; urgency=medium
|
||||
|
||||
* fix: error datetime tooltip (https://github.com/linuxdeepin/developer-center/issues/7056)
|
||||
* fix: unable get docked entriy by soft link path (https://github.com/linuxdeepin/developer-center/issues/7033)
|
||||
|
||||
-- tsic404 <liuheng@deepin.org> Tue, 23 Jan 2024 17:43:44 +0800
|
||||
|
||||
dde-dock (6.0.30) unstable; urgency=medium
|
||||
|
||||
* chore: remove Cooperation in display plugin (https://github.com/linuxdeepin/developer-center/issues/7023)
|
||||
|
||||
-- chenhongtao <chenhongtao@deepin.org> Mon, 22 Jan 2024 17:27:34 +0800
|
||||
|
||||
dde-dock (6.0.29) unstable; urgency=medium
|
||||
|
||||
* fix: when no timeformat, tooltip is empty
|
||||
|
||||
-- chenhongtao <chenhongtao@deepin.org> Mon, 22 Jan 2024 09:47:21 +0800
|
||||
|
||||
dde-dock (6.0.28) unstable; urgency=medium
|
||||
|
||||
* fix: the item that removed is exist yet (https://github.com/linuxdeepin/developer-center/issues/4631)
|
||||
* fix: dock wakeup area not changed (https://github.com/linuxdeepin/developer-center/issues/5831)
|
||||
* fix: onboard not to show on first click (https://github.com/linuxdeepin/developer-center/issues/6675)
|
||||
* fix: timedate tips show error (https://github.com/linuxdeepin/developer-center/issues/6674)
|
||||
* fix: quickpanel icon not follow theme (https://github.com/linuxdeepin/developer-center/issues/6263)
|
||||
* fix: disable resize of dock popup window (https://github.com/linuxdeepin/developer-center/issues/6264)
|
||||
* feat: add dbus property window margin
|
||||
|
||||
-- tsic404 <liuheng@deepin.org> Thu, 18 Jan 2024 09:57:27 +0800
|
||||
|
||||
dde-dock (6.0.27) unstable; urgency=medium
|
||||
|
||||
* fix: dock get stucked when launching (https://github.com/linuxdeepin/developer-center/issues/6657)
|
||||
* chore: make uosai default on dock (https://github.com/linuxdeepin/developer-center/issues/6486)
|
||||
* chore: open deepin-calendar instead of dde-widgets when click timedate (https://github.com/linuxdeepin/developer-center/issues/6696)
|
||||
* fix: item context menu not updated
|
||||
* feat: add plugin notification (https://github.com/linuxdeepin/developer-center/issues/6695)
|
||||
* fix: mainwindow hide when popup opens (https://github.com/linuxdeepin/developer-center/issues/4970)
|
||||
|
||||
-- tsic404 <liuheng@deepin.org> Tue, 09 Jan 2024 13:33:18 +0800
|
||||
|
||||
dde-dock (6.0.26) unstable; urgency=medium
|
||||
|
||||
* release 6.0.26
|
||||
* fix #6033 #5719 #5786 #4331
|
||||
|
||||
-- mike <chenke@deepin.org> Fri, 29 Dec 2023 11:27:59 +0800
|
||||
|
||||
dde-dock (6.0.25) unstable; urgency=medium
|
||||
|
||||
* chore: turn on bluetooth loading animation when not start
|
||||
* fix: fix again set dcc dock plugin icon pixelated
|
||||
|
||||
-- chenhongtao <chenhongtao@deepin.org> Wed, 13 Dec 2023 15:31:57 +0800
|
||||
|
||||
dde-dock (6.0.24) unstable; urgency=medium
|
||||
|
||||
* chore: use system icon first
|
||||
* fix: dcc dock plugin icon pixelated
|
||||
* fix some coredump issue
|
||||
* fix: brightness silder cannot sroll when is 28
|
||||
* tidy up some log
|
||||
|
||||
-- chenhongtao <chenhongtao@deepin.org> Tue, 28 Nov 2023 10:51:52 +0800
|
||||
|
||||
dde-dock (6.0.23) unstable; urgency=medium
|
||||
|
||||
* fix: displayplugin disappear when monitor count changed
|
||||
* fix: tray disappear when drag finished
|
||||
* fix: double tray show afeter drag into expandTray and drag back
|
||||
* chore: remove unused dbus
|
||||
* chore: Adapt time format feature(Issue: https://github.com/linuxdeepin/developer-center/issues/5902)
|
||||
|
||||
-- Deepin Packages Builder <packages@deepin.org> Thu, 26 Oct 2023 17:25:38 +0800
|
||||
|
||||
dde-dock (6.0.22) unstable; urgency=medium
|
||||
|
||||
* fix: a space on tray without trash show
|
||||
* fix: coredump empty tray when switch postion
|
||||
* fix: Can't hide when DockPopupWindow deactivate(Issue: https://github.com/linuxdeepin/developer-center/issues/5405)
|
||||
* fix: datetime size error
|
||||
* fix: tool appAreaWidget visible
|
||||
|
||||
-- tsic404 <liuheng@deepin.org> Mon, 11 Sep 2023 13:14:25 +0800
|
||||
|
||||
dde-dock (6.0.21) unstable; urgency=medium
|
||||
|
||||
* fix: add lost windowSizeChanged Signal
|
||||
* fix: brightness update, update main view slider
|
||||
* chore: make trash not display in default
|
||||
* fix: click preview container not active window
|
||||
* feat: Remove dock-hotspot-plugin by Conflicts
|
||||
* feat: use new am dbus interface
|
||||
* feat: when new am avaliable do not load custom desktopfile
|
||||
* fix: dock coredump when update recentApp invisible
|
||||
* feat: make unrecongnized application not dock on dde-dock
|
||||
* fix: datetime font size error
|
||||
|
||||
-- tsic404 <liuheng@deepin.org> Wed, 06 Sep 2023 14:20:11 +0800
|
||||
|
||||
dde-dock (6.0.20) unstable; urgency=medium
|
||||
|
||||
* fix: xebmbedtary click get no response in Efficient mode
|
||||
* fix: add hideModeChanged signal
|
||||
* fix: adjust the slider to set the sound multiple times
|
||||
* fix: dock autohide even trayGridWidget show
|
||||
|
||||
-- tsic404 <liuheng@deepin.org> Thu, 24 Aug 2023 15:30:37 +0800
|
||||
|
||||
dde-dock (6.0.19) unstable; urgency=medium
|
||||
|
||||
* fix: no positionModeChanged signal
|
||||
* fix: some app do not display
|
||||
* fix: plugin set show on dock more times, also need same times call unshow
|
||||
* fix: applicationpreview scale not keep aspectratio
|
||||
* fix: click always activate application in TrayGridWidget
|
||||
* fix: not show with launcher when hide
|
||||
* fix: coredump when open jetbrains-toolbox
|
||||
|
||||
-- Tsic404 <liuheng@deepin.org> Mon, 07 Aug 2023 17:08:30 +0800
|
||||
|
||||
dde-dock (6.0.18) unstable; urgency=medium
|
||||
|
||||
* fix: dock entries not update after displaymode changed
|
||||
* fix: official chrome unable to be identified
|
||||
|
||||
-- Deepin Packages Builder <liuheng@deepin.org> Mon, 24 Jul 2023 16:20:32 +0800
|
||||
|
||||
dde-dock (6.0.17) unstable; urgency=medium
|
||||
|
||||
* fix: dock position changed from left to bottom no date display
|
||||
* fix: DockPopupWindow losing active status(Issue: #172773)
|
||||
* fix: make keyboard layout plugin size fixed
|
||||
* fix: adjust tray icon size to 20
|
||||
* fix: incorrect trash status when deleting file in other partition
|
||||
* fix: imcomplete display when dock plugin's tips text is multi-line
|
||||
* fix: Fix the incomplete display of text when font 20 is scaled to 1.25(Influence: 电脑协同显示区域)
|
||||
* fix: text missing translation(Influence: 文本显示)
|
||||
* fix: 修复'Brightness' 文本裁切问题(Influence: 文本显示)
|
||||
* chore: chore: update translate
|
||||
* chore: update dependencies
|
||||
* fix: tips font size not follow system
|
||||
* fix: 任务栏声音面板中出现异常的悬浮提示 (#876)
|
||||
* fix: the name of sound device shouldn't be edited (#880)
|
||||
* refactor: rewrite encapsulation of the dconfig
|
||||
* refactor: Rewrite the calling method of dock settings
|
||||
* chore: update .gitignore add debian and build ignore
|
||||
* feat: add taskmanager from dde-application-manager
|
||||
* fix: dock size error when dock positon changed
|
||||
|
||||
-- Deepin Packages Builder <packages@deepin.org> Tue, 11 Jul 2023 09:50:13 +0800
|
||||
|
||||
dde-dock (6.0.16) unstable; urgency=medium
|
||||
|
||||
* fix: blank in the plugin area after recorder screen
|
||||
|
||||
-- tsic404 <liuheng@deepin.org> Thu, 11 May 2023 17:30:39 +0800
|
||||
|
||||
dde-dock (6.0.15) unstable; urgency=medium
|
||||
|
||||
* update translate
|
||||
* fix: timedate size is too full
|
||||
* fix: popupwindow is out of bounds at the edge of the screen
|
||||
|
||||
-- Tsic404 <liuheng@deepin.org> Thu, 11 May 2023 15:02:33 +0800
|
||||
|
||||
dde-dock (6.0.14) unstable; urgency=medium
|
||||
|
||||
* fix: trash do not display when dock hide and trash readded into dock
|
||||
* fix: popupwindow need click destkop twice to hide
|
||||
* fix: sound plugin style adjust
|
||||
* fix: window radius
|
||||
* fix: coredump after screen recorder finished, when drag something
|
||||
* fix: fcitx5 keyboard tray icon blur
|
||||
|
||||
-- Tsic404 <liuheng@deepin.org> Sat, 06 May 2023 16:59:15 +0800
|
||||
|
||||
dde-dock (6.0.13) unstable; urgency=medium
|
||||
|
||||
* fix appitem indicator wrong position
|
||||
|
79
debian/control
vendored
79
debian/control
vendored
@ -2,71 +2,80 @@ Source: dde-dock
|
||||
Section: x11
|
||||
Priority: optional
|
||||
Maintainer: Deepin Packages Builder <packages@deepin.com>
|
||||
Build-Depends: debhelper-compat (= 10),
|
||||
pkg-config,
|
||||
Build-Depends:
|
||||
cmake,
|
||||
qt5-qmake,
|
||||
libxcb-image0-dev,
|
||||
libxcb-composite0-dev,
|
||||
libxcb-ewmh-dev,
|
||||
libxtst-dev,
|
||||
qttools5-dev-tools,
|
||||
qtbase5-private-dev,
|
||||
libxcb-icccm4-dev,
|
||||
libqt5x11extras5-dev,
|
||||
libxcb-damage0-dev,
|
||||
libqt5svg5-dev,
|
||||
libdtkwidget-dev (>=5.4.19),
|
||||
debhelper-compat (= 10),
|
||||
extra-cmake-modules,
|
||||
libdbusmenu-qt5-dev,
|
||||
libdtkcore-dev (>=5.4.14),
|
||||
libdtkcore5-bin (>=5.4.14),
|
||||
libdtkgui-dev (>=5.4.13),
|
||||
libgsettings-qt-dev,
|
||||
libdbusmenu-qt5-dev,
|
||||
libgtest-dev,
|
||||
libgmock-dev,
|
||||
qttools5-dev,
|
||||
libxcursor-dev,
|
||||
libqt5waylandclient5-dev,
|
||||
qtwayland5-private-dev,
|
||||
libxdamage-dev,
|
||||
libdtkwidget-dev (>=5.4.19),
|
||||
libdwayland-dev,
|
||||
extra-cmake-modules
|
||||
libgmock-dev,
|
||||
libgsettings-qt-dev,
|
||||
libgtest-dev,
|
||||
libqt5svg5-dev,
|
||||
libqt5waylandclient5-dev,
|
||||
libqt5x11extras5-dev,
|
||||
libxcb-composite0-dev,
|
||||
libxcb-damage0-dev,
|
||||
libxcb-ewmh-dev,
|
||||
libxcb-icccm4-dev,
|
||||
libxcb-image0-dev,
|
||||
libxcursor-dev,
|
||||
libxdamage-dev,
|
||||
libxres-dev,
|
||||
libxtst-dev,
|
||||
pkg-config,
|
||||
qt5-qmake,
|
||||
qtbase5-private-dev,
|
||||
qttools5-dev,
|
||||
qttools5-dev-tools,
|
||||
qtwayland5-private-dev,
|
||||
Standards-Version: 3.9.8
|
||||
Homepage: http://www.deepin.org/
|
||||
|
||||
Package: dde-dock
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends},
|
||||
deepin-desktop-schemas (>=5.9.14),
|
||||
dde-qt5xcb-plugin (>=5.0.25),
|
||||
Depends:
|
||||
dbus-bin,
|
||||
dde-daemon (>=5.13.12),
|
||||
startdde (>=5.8.9),
|
||||
dde-qt5xcb-plugin (>=5.0.25),
|
||||
deepin-desktop-schemas (>=5.9.14),
|
||||
lastore-daemon (>=5.2.9),
|
||||
qtxdg-dev-tools,
|
||||
dbus-bin
|
||||
startdde (>=5.8.9),
|
||||
${misc:Depends},
|
||||
${shlibs:Depends},
|
||||
Recommends:
|
||||
dde-disk-mount-plugin,
|
||||
dde-dock-onboard-plugin,
|
||||
dde-network-dialog,
|
||||
dock-network-plugin,
|
||||
dde-network-dialog
|
||||
Conflicts:
|
||||
dde-workspace (<< 2.90.5),
|
||||
dde-dock-applets,
|
||||
dde-trash-plugin
|
||||
dde-trash-plugin,
|
||||
dde-workspace (<< 2.90.5),
|
||||
dock-hotspot-plugin,
|
||||
Replaces:
|
||||
dde-dock-applets,
|
||||
dde-trash-plugin
|
||||
dde-trash-plugin,
|
||||
Description: deepin desktop-environment - dock module
|
||||
Dock module of deepin desktop-environment
|
||||
|
||||
Package: dde-dock-dev
|
||||
Architecture: any
|
||||
Depends: ${misc:Depends}
|
||||
Depends:
|
||||
${misc:Depends},
|
||||
Description: deepin desktop-environment - dock module development files
|
||||
Dock module development files of deepin desktop-environment
|
||||
|
||||
Package: dde-dock-onboard-plugin
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}, onboard
|
||||
Depends:
|
||||
onboard,
|
||||
${misc:Depends},
|
||||
${shlibs:Depends},
|
||||
Description: deepin desktop-environment - dock plugin for onboard
|
||||
Dock plugin for onboard of deepin desktop-environment
|
||||
|
1
debian/dde-dock.install
vendored
1
debian/dde-dock.install
vendored
@ -9,4 +9,5 @@ usr/lib/dde-dock/plugins/quick-trays
|
||||
usr/lib/dde-dock/plugins/libmultitasking.so
|
||||
usr/lib/dde-dock/plugins/libshow-desktop.so
|
||||
usr/lib/dde-dock/plugins/libkeyboard-layout.so
|
||||
usr/lib/dde-dock/plugins/libnotification.so
|
||||
usr/share/dsg/configs/dde-dock/
|
||||
|
@ -34,8 +34,9 @@ find_package(DWayland REQUIRED)
|
||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
pkg_check_modules(XCB_EWMH REQUIRED IMPORTED_TARGET xcb-image xcb-ewmh xcb-composite xtst x11 dbusmenu-qt5 xext xcursor)
|
||||
pkg_check_modules(XCB_EWMH REQUIRED IMPORTED_TARGET x11 xcb xcb-icccm xcb-image xcb-ewmh xcb-composite xtst dbusmenu-qt5 xext xcursor xkbcommon xres)
|
||||
pkg_check_modules(QGSettings REQUIRED IMPORTED_TARGET gsettings-qt)
|
||||
pkg_check_modules(WAYLAND REQUIRED IMPORTED_TARGET wayland-client wayland-cursor wayland-egl)
|
||||
|
||||
# driver-manager
|
||||
add_executable(${BIN_NAME}
|
||||
@ -83,6 +84,7 @@ target_link_libraries(${BIN_NAME} PRIVATE
|
||||
${DtkWidget_LIBRARIES}
|
||||
PkgConfig::QGSettings
|
||||
PkgConfig::XCB_EWMH
|
||||
PkgConfig::WAYLAND
|
||||
Dtk::Gui
|
||||
Qt5::Widgets
|
||||
Qt5::Gui
|
||||
@ -111,3 +113,5 @@ endif()
|
||||
|
||||
# bin
|
||||
install(TARGETS ${BIN_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
# window_patterns
|
||||
install(FILES taskmanager/window_patterns.json DESTINATION ${CMAKE_INSTALL_DATADIR}/dde-dock/)
|
||||
|
@ -1,195 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
#include "accessibledefine.h"
|
||||
|
||||
#include "mainwindow.h"
|
||||
#include "mainpanelcontrol.h"
|
||||
#include "desktop_widget.h"
|
||||
#include "tipswidget.h"
|
||||
#include "dockpopupwindow.h"
|
||||
#include "dragwidget.h"
|
||||
|
||||
#include "launcheritem.h"
|
||||
#include "appitem.h"
|
||||
#include "components/previewcontainer.h"
|
||||
#include "pluginsitem.h"
|
||||
#include "traypluginitem.h"
|
||||
#include "placeholderitem.h"
|
||||
#include "components/appdragwidget.h"
|
||||
#include "components/appsnapshot.h"
|
||||
#include "components/floatingpreview.h"
|
||||
|
||||
#include "snitraywidget.h"
|
||||
#include "abstracttraywidget.h"
|
||||
#include "indicatortraywidget.h"
|
||||
#include "xembedtraywidget.h"
|
||||
#include "system-trays/systemtrayitem.h"
|
||||
#include "fashiontray/fashiontrayitem.h"
|
||||
#include "fashiontray/fashiontraywidgetwrapper.h"
|
||||
#include "fashiontray/fashiontraycontrolwidget.h"
|
||||
#include "fashiontray/containers/attentioncontainer.h"
|
||||
#include "fashiontray/containers/holdcontainer.h"
|
||||
#include "fashiontray/containers/normalcontainer.h"
|
||||
#include "fashiontray/containers/spliteranimated.h"
|
||||
|
||||
// 这部分由sound插件单独维护,这样做是因为在标记volumeslider这个类时,需要用到其setValue的实现,
|
||||
// 但插件的源文件dock这边并没有包含,不想引入复杂的包含关系,其实最好的做法就是像sound插件这样,谁维护谁的
|
||||
//#include "../plugins/sound/sounditem.h"
|
||||
//#include "../plugins/sound/soundapplet.h"
|
||||
//#include "../plugins/sound/sinkinputwidget.h"
|
||||
//#include "../plugins/sound/componments/volumeslider.h"
|
||||
//#include "../plugins/sound/componments/horizontalseparator.h"
|
||||
|
||||
#include "showdesktopwidget.h"
|
||||
#include "datetimewidget.h"
|
||||
#include "onboarditem.h"
|
||||
#include "trashwidget.h"
|
||||
#include "popupcontrolwidget.h"
|
||||
#include "shutdownwidget.h"
|
||||
#include "multitaskingwidget.h"
|
||||
#include "overlaywarningwidget.h"
|
||||
#include "horizontalseperator.h"
|
||||
|
||||
#include <DIconButton>
|
||||
#include <DSwitchButton>
|
||||
#include <DPushButton>
|
||||
#include <DListView>
|
||||
#include <DSwitchButton>
|
||||
#include <DSpinner>
|
||||
#include <dloadingindicator.h>
|
||||
|
||||
#include <QScrollBar>
|
||||
|
||||
DWIDGET_USE_NAMESPACE
|
||||
using namespace Dock;
|
||||
|
||||
// 添加accessible
|
||||
SET_FORM_ACCESSIBLE(MainWindow, "mainwindow")
|
||||
SET_BUTTON_ACCESSIBLE(MainPanelControl, "mainpanelcontrol")
|
||||
SET_LABEL_ACCESSIBLE(TipsWidget, "tips")
|
||||
SET_FORM_ACCESSIBLE(DockPopupWindow, "popupwindow")
|
||||
SET_BUTTON_ACCESSIBLE(LauncherItem, "launcheritem")
|
||||
SET_BUTTON_ACCESSIBLE(AppItem, "appitem")
|
||||
SET_BUTTON_ACCESSIBLE(PreviewContainer, "previewcontainer")
|
||||
SET_BUTTON_ACCESSIBLE(PluginsItem, m_w->pluginName())
|
||||
SET_BUTTON_ACCESSIBLE(TrayPluginItem, m_w->pluginName())
|
||||
SET_BUTTON_ACCESSIBLE(PlaceholderItem, "placeholderitem")
|
||||
SET_BUTTON_ACCESSIBLE(AppDragWidget, "appdragwidget")
|
||||
SET_BUTTON_ACCESSIBLE(AppSnapshot, "appsnapshot")
|
||||
SET_BUTTON_ACCESSIBLE(FloatingPreview, "floatingpreview")
|
||||
SET_BUTTON_ACCESSIBLE(XEmbedTrayWidget, m_w->itemKeyForConfig().replace("sni:", ""))
|
||||
SET_BUTTON_ACCESSIBLE(IndicatorTrayWidget, m_w->itemKeyForConfig().replace("sni:", ""))
|
||||
SET_BUTTON_ACCESSIBLE(SNITrayWidget, m_w->itemKeyForConfig().replace("sni:", ""))
|
||||
SET_BUTTON_ACCESSIBLE(AbstractTrayWidget, m_w->itemKeyForConfig().replace("sni:", ""))
|
||||
SET_BUTTON_ACCESSIBLE(SystemTrayItem, m_w->itemKeyForConfig().replace("sni:", ""))
|
||||
SET_FORM_ACCESSIBLE(FashionTrayItem, "fashiontrayitem")
|
||||
SET_FORM_ACCESSIBLE(FashionTrayWidgetWrapper, "fashiontraywrapper")
|
||||
SET_BUTTON_ACCESSIBLE(FashionTrayControlWidget, "fashiontraycontrolwidget")
|
||||
SET_FORM_ACCESSIBLE(AttentionContainer, "attentioncontainer")
|
||||
SET_FORM_ACCESSIBLE(HoldContainer, "holdcontainer")
|
||||
SET_FORM_ACCESSIBLE(NormalContainer, "normalcontainer")
|
||||
SET_FORM_ACCESSIBLE(SpliterAnimated, "spliteranimated")
|
||||
SET_FORM_ACCESSIBLE(DatetimeWidget, "plugin-datetime")
|
||||
SET_FORM_ACCESSIBLE(OnboardItem, "plugin-onboard")
|
||||
SET_FORM_ACCESSIBLE(TrashWidget, "plugin-trash")
|
||||
SET_BUTTON_ACCESSIBLE(PopupControlWidget, "popupcontrolwidget")
|
||||
SET_FORM_ACCESSIBLE(ShutdownWidget, "plugin-shutdown")
|
||||
SET_FORM_ACCESSIBLE(MultitaskingWidget, "plugin-multitasking")
|
||||
SET_FORM_ACCESSIBLE(ShowDesktopWidget, "plugin-showdesktop")
|
||||
SET_FORM_ACCESSIBLE(OverlayWarningWidget, "plugin-overlaywarningwidget")
|
||||
SET_FORM_ACCESSIBLE(QWidget, m_w->objectName().isEmpty() ? "widget" : m_w->objectName())
|
||||
SET_LABEL_ACCESSIBLE(QLabel, m_w->objectName() == "notifications" ? m_w->objectName() : m_w->text().isEmpty() ? m_w->objectName().isEmpty() ? "text" : m_w->objectName() : m_w->text())
|
||||
SET_BUTTON_ACCESSIBLE(DIconButton, m_w->objectName().isEmpty() ? "imagebutton" : m_w->objectName())
|
||||
SET_BUTTON_ACCESSIBLE(DSwitchButton, m_w->text().isEmpty() ? "switchbutton" : m_w->text())
|
||||
SET_BUTTON_ACCESSIBLE(DesktopWidget, "desktopWidget");
|
||||
SET_FORM_ACCESSIBLE(HorizontalSeperator, "HorizontalSeperator");
|
||||
// 几个没什么用的标记,但为了提醒大家不要遗漏标记控件,还是不要去掉
|
||||
SET_FORM_ACCESSIBLE(DBlurEffectWidget, "DBlurEffectWidget")
|
||||
SET_FORM_ACCESSIBLE(DListView, "DListView")
|
||||
SET_FORM_ACCESSIBLE(DLoadingIndicator, "DLoadingIndicator")
|
||||
SET_FORM_ACCESSIBLE(DSpinner, "DSpinner")
|
||||
SET_FORM_ACCESSIBLE(QMenu, "QMenu")
|
||||
SET_FORM_ACCESSIBLE(QPushButton, "QPushButton")
|
||||
SET_FORM_ACCESSIBLE(QSlider, "QSlider")
|
||||
SET_FORM_ACCESSIBLE(QScrollBar, "QScrollBar")
|
||||
SET_FORM_ACCESSIBLE(QScrollArea, "QScrollArea")
|
||||
SET_FORM_ACCESSIBLE(QFrame, "QFrame")
|
||||
SET_FORM_ACCESSIBLE(QGraphicsView, "QGraphicsView")
|
||||
SET_FORM_ACCESSIBLE(DragWidget, "DragWidget")
|
||||
|
||||
QAccessibleInterface *accessibleFactory(const QString &classname, QObject *object)
|
||||
{
|
||||
// 自动化标记确定不需要的控件,方可加入忽略列表
|
||||
const static QStringList ignoreLst = {"WirelessItem", "WiredItem", "SsidButton", "WirelessList", "AccessPointWidget"};
|
||||
|
||||
QAccessibleInterface *interface = nullptr;
|
||||
|
||||
USE_ACCESSIBLE(classname, MainWindow)
|
||||
ELSE_USE_ACCESSIBLE(classname, MainPanelControl)
|
||||
ELSE_USE_ACCESSIBLE(QString(classname).replace("Dock::", ""), TipsWidget)
|
||||
ELSE_USE_ACCESSIBLE(classname, DockPopupWindow)
|
||||
ELSE_USE_ACCESSIBLE(classname, LauncherItem)
|
||||
ELSE_USE_ACCESSIBLE(classname, AppItem)
|
||||
ELSE_USE_ACCESSIBLE(classname, PreviewContainer)
|
||||
ELSE_USE_ACCESSIBLE(classname, PluginsItem)
|
||||
ELSE_USE_ACCESSIBLE(classname, TrayPluginItem)
|
||||
ELSE_USE_ACCESSIBLE(classname, PlaceholderItem)
|
||||
ELSE_USE_ACCESSIBLE(classname, AppDragWidget)
|
||||
ELSE_USE_ACCESSIBLE(classname, AppSnapshot)
|
||||
ELSE_USE_ACCESSIBLE(classname, FloatingPreview)
|
||||
ELSE_USE_ACCESSIBLE(classname, SNITrayWidget)
|
||||
ELSE_USE_ACCESSIBLE(classname, AbstractTrayWidget)
|
||||
ELSE_USE_ACCESSIBLE(classname, SystemTrayItem)
|
||||
ELSE_USE_ACCESSIBLE(classname, FashionTrayItem)
|
||||
ELSE_USE_ACCESSIBLE(classname, FashionTrayWidgetWrapper)
|
||||
ELSE_USE_ACCESSIBLE(classname, FashionTrayControlWidget)
|
||||
ELSE_USE_ACCESSIBLE(classname, AttentionContainer)
|
||||
ELSE_USE_ACCESSIBLE(classname, HoldContainer)
|
||||
ELSE_USE_ACCESSIBLE(classname, NormalContainer)
|
||||
ELSE_USE_ACCESSIBLE(classname, SpliterAnimated)
|
||||
ELSE_USE_ACCESSIBLE(classname, IndicatorTrayWidget)
|
||||
ELSE_USE_ACCESSIBLE(classname, XEmbedTrayWidget)
|
||||
ELSE_USE_ACCESSIBLE(classname, DesktopWidget)
|
||||
ELSE_USE_ACCESSIBLE(classname, DatetimeWidget)
|
||||
ELSE_USE_ACCESSIBLE(classname, OnboardItem)
|
||||
ELSE_USE_ACCESSIBLE(classname, TrashWidget)
|
||||
ELSE_USE_ACCESSIBLE(classname, PopupControlWidget)
|
||||
ELSE_USE_ACCESSIBLE(classname, ShutdownWidget)
|
||||
ELSE_USE_ACCESSIBLE(classname, MultitaskingWidget)
|
||||
ELSE_USE_ACCESSIBLE(classname, ShowDesktopWidget)
|
||||
ELSE_USE_ACCESSIBLE(classname, OverlayWarningWidget)
|
||||
ELSE_USE_ACCESSIBLE(classname, QWidget)
|
||||
ELSE_USE_ACCESSIBLE_BY_OBJECTNAME(classname, QLabel, "spliter_fix")
|
||||
ELSE_USE_ACCESSIBLE_BY_OBJECTNAME(classname, QLabel, "spliter_app")
|
||||
ELSE_USE_ACCESSIBLE_BY_OBJECTNAME(classname, QLabel, "spliter_tray")
|
||||
ELSE_USE_ACCESSIBLE(classname, QLabel)
|
||||
ELSE_USE_ACCESSIBLE_BY_OBJECTNAME(QString(classname).replace("Dtk::Widget::", ""), DIconButton, "closebutton-2d")
|
||||
ELSE_USE_ACCESSIBLE_BY_OBJECTNAME(QString(classname).replace("Dtk::Widget::", ""), DIconButton, "closebutton-3d")
|
||||
ELSE_USE_ACCESSIBLE_BY_OBJECTNAME(QString(classname).replace("Dtk::Widget::", ""), DSwitchButton, "")
|
||||
ELSE_USE_ACCESSIBLE(QString(classname).replace("Dtk::Widget::", ""), DBlurEffectWidget)
|
||||
ELSE_USE_ACCESSIBLE(QString(classname).replace("Dtk::Widget::", ""), DListView)
|
||||
ELSE_USE_ACCESSIBLE(QString(classname).replace("Dtk::Widget::", ""), DLoadingIndicator)
|
||||
ELSE_USE_ACCESSIBLE(QString(classname).replace("Dtk::Widget::", ""), DSpinner)
|
||||
ELSE_USE_ACCESSIBLE(QString(classname).replace("Dtk::Widget::", ""), DSwitchButton)
|
||||
ELSE_USE_ACCESSIBLE(QString(classname).replace("Dtk::Widget::", ""), DIconButton)
|
||||
ELSE_USE_ACCESSIBLE(classname, QMenu)
|
||||
ELSE_USE_ACCESSIBLE(classname, QPushButton)
|
||||
ELSE_USE_ACCESSIBLE(classname, QSlider)
|
||||
ELSE_USE_ACCESSIBLE(classname, QScrollBar)
|
||||
ELSE_USE_ACCESSIBLE(classname, QScrollArea)
|
||||
ELSE_USE_ACCESSIBLE(classname, QFrame)
|
||||
ELSE_USE_ACCESSIBLE(classname, QGraphicsView)
|
||||
ELSE_USE_ACCESSIBLE(classname, DragWidget)
|
||||
ELSE_USE_ACCESSIBLE(classname, HorizontalSeperator);
|
||||
|
||||
if (!interface && object->inherits("QWidget") && !ignoreLst.contains(classname)) {
|
||||
QWidget *w = static_cast<QWidget *>(object);
|
||||
// 如果你看到这里的输出,说明代码中仍有控件未兼顾到accessible功能,请帮忙添加
|
||||
if (w->accessibleName().isEmpty())
|
||||
qWarning() << "accessibleFactory()" + QString("Class: " + classname + " cannot access");
|
||||
}
|
||||
|
||||
return interface;
|
||||
}
|
@ -1,405 +0,0 @@
|
||||
// Copyright (C) 2018 ~ 2020 Deepin Technology Co., Ltd.
|
||||
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
// 为了方便使用,把相关定义独立出来,如有需要,直接包含这个头文件,然后使用SET_*的宏去设置,USE_*宏开启即可
|
||||
// 注意:对项目中出现的所有的QWidget的派生类都要再启用一次accessiblity,包括qt的原生控件[qt未限制其标记名称为空的情况]
|
||||
// 注意:使用USE_ACCESSIBLE_BY_OBJECTNAME开启accessiblity的时候,一定要再对这个类用一下USE_ACCESSIBLE,否则标记可能会遗漏
|
||||
|
||||
#ifndef ACCESSIBLEINTERFACE_H
|
||||
#define ACCESSIBLEINTERFACE_H
|
||||
|
||||
#include <QAccessible>
|
||||
#include <QAccessibleWidget>
|
||||
#include <QEvent>
|
||||
#include <QMap>
|
||||
#include <QString>
|
||||
#include <QWidget>
|
||||
#include <QObject>
|
||||
#include <QMetaEnum>
|
||||
#include <QMouseEvent>
|
||||
#include <QApplication>
|
||||
|
||||
#define SEPARATOR "_"
|
||||
|
||||
inline QString getAccessibleName(QWidget *w, QAccessible::Role r, const QString &fallback)
|
||||
{
|
||||
const QString lowerFallback = fallback.toLower();
|
||||
// 避免重复生成
|
||||
static QMap< QObject *, QString > objnameMap;
|
||||
if (!objnameMap[w].isEmpty())
|
||||
return objnameMap[w];
|
||||
|
||||
static QMap< QAccessible::Role, QList< QString > > accessibleMap;
|
||||
QString oldAccessName = w->accessibleName().toLower();
|
||||
oldAccessName.replace(SEPARATOR, "");
|
||||
|
||||
// 按照类型添加固定前缀
|
||||
QMetaEnum metaEnum = QMetaEnum::fromType<QAccessible::Role>();
|
||||
QByteArray prefix = metaEnum.valueToKeys(r);
|
||||
switch (r) {
|
||||
case QAccessible::Button: prefix = "Btn"; break;
|
||||
case QAccessible::StaticText: prefix = "Label"; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
// 再加上标识
|
||||
QString accessibleName = QString::fromLatin1(prefix) + SEPARATOR;
|
||||
QString objectName = w->objectName().toLower();
|
||||
accessibleName += oldAccessName.isEmpty() ? (objectName.isEmpty() ?lowerFallback : objectName) : oldAccessName;
|
||||
// 检查名称是否唯一
|
||||
if (accessibleMap[r].contains(accessibleName)) {
|
||||
if (!objnameMap.key(accessibleName)) {
|
||||
objnameMap.remove(objnameMap.key(accessibleName));
|
||||
objnameMap.insert(w, accessibleName);
|
||||
return accessibleName;
|
||||
}
|
||||
// 获取编号,然后+1
|
||||
int pos = accessibleName.indexOf(SEPARATOR);
|
||||
int id = accessibleName.mid(pos + 1).toInt();
|
||||
|
||||
QString newAccessibleName;
|
||||
do {
|
||||
// 一直找到一个不重复的名字
|
||||
newAccessibleName = accessibleName + SEPARATOR + QString::number(++id);
|
||||
} while (accessibleMap[r].contains(newAccessibleName));
|
||||
|
||||
accessibleMap[r].append(newAccessibleName);
|
||||
objnameMap.insert(w, newAccessibleName);
|
||||
|
||||
// 对象销毁后移除占用名称
|
||||
QObject::connect(w, &QWidget::destroyed, [ = ] (QObject *obj) {
|
||||
objnameMap.remove(obj);
|
||||
accessibleMap[r].removeOne(newAccessibleName);
|
||||
});
|
||||
return newAccessibleName;
|
||||
} else {
|
||||
accessibleMap[r].append(accessibleName);
|
||||
objnameMap.insert(w, accessibleName);
|
||||
|
||||
// 对象销毁后移除占用名称
|
||||
QObject::connect(w, &QWidget::destroyed, [ = ] (QObject *obj) {
|
||||
objnameMap.remove(obj);
|
||||
accessibleMap[r].removeOne(accessibleName);
|
||||
});
|
||||
return accessibleName;
|
||||
}
|
||||
}
|
||||
|
||||
// 公共的功能
|
||||
#define FUNC_CREATE(classname,accessibletype,accessdescription) explicit Accessible##classname(classname *w) \
|
||||
: QAccessibleWidget(w,accessibletype,#classname)\
|
||||
, m_w(w)\
|
||||
, m_description(accessdescription)\
|
||||
{}\
|
||||
|
||||
#define FUNC_TEXT(classname,accessiblename) QString Accessible##classname::text(QAccessible::Text t) const{\
|
||||
switch (t) {\
|
||||
case QAccessible::Name:\
|
||||
return getAccessibleName(m_w, this->role(), accessiblename);\
|
||||
case QAccessible::Description:\
|
||||
return m_description;\
|
||||
default:\
|
||||
return QString();\
|
||||
}\
|
||||
}\
|
||||
|
||||
// button控件特有功能
|
||||
#define FUNC_ACTIONNAMES(classname) QStringList Accessible##classname::actionNames() const{\
|
||||
if(!m_w->isEnabled())\
|
||||
return QStringList();\
|
||||
return QStringList() << pressAction()<< showMenuAction();\
|
||||
}\
|
||||
|
||||
#define FUNC_DOACTION(classname) void Accessible##classname::doAction(const QString &actionName){\
|
||||
if(actionName == pressAction())\
|
||||
{\
|
||||
QPointF localPos = m_w->geometry().center();\
|
||||
QMouseEvent event(QEvent::MouseButtonPress,localPos,Qt::LeftButton,Qt::LeftButton,Qt::NoModifier);\
|
||||
qApp->sendEvent(m_w,&event);\
|
||||
}\
|
||||
else if(actionName == showMenuAction())\
|
||||
{\
|
||||
QPointF localPos = m_w->geometry().center();\
|
||||
QMouseEvent event(QEvent::MouseButtonPress,localPos,Qt::RightButton,Qt::RightButton,Qt::NoModifier);\
|
||||
qApp->sendEvent(m_w,&event);\
|
||||
}\
|
||||
}\
|
||||
|
||||
// Label控件特有功能
|
||||
#define FUNC_TEXT_(classname) QString Accessible##classname::text(int startOffset, int endOffset) const{\
|
||||
Q_UNUSED(startOffset)\
|
||||
Q_UNUSED(endOffset)\
|
||||
return m_w->text();\
|
||||
}\
|
||||
|
||||
// Slider控件特有功能
|
||||
#define FUNC_CURRENTVALUE(classname) QVariant Accessible##classname::currentValue() const{\
|
||||
return m_w->value();\
|
||||
}\
|
||||
|
||||
#define FUNC_SETCURRENTVALUE(classname) void Accessible##classname::setCurrentValue(const QVariant &value){\
|
||||
return m_w->setValue(value.toInt());\
|
||||
}\
|
||||
|
||||
#define FUNC_MAXMUMVALUE(classname) QVariant Accessible##classname::maximumValue() const{\
|
||||
return QVariant(m_w->maximum());\
|
||||
}\
|
||||
|
||||
#define FUNC_FUNC_MINIMUMVALUE(classname) QVariant Accessible##classname::minimumValue() const{\
|
||||
return QVariant(m_w->minimum());\
|
||||
}\
|
||||
|
||||
// DSlider控件特有功能函数
|
||||
#define FUNC_FUNC_MINIMUMSTEPSIZE(classname) QVariant Accessible##classname::minimumStepSize() const{\
|
||||
return QVariant(m_w->pageStep());\
|
||||
}\
|
||||
|
||||
#define SET_FORM_ACCESSIBLE_WITH_DESCRIPTION(classname,accessiblename,accessdescription) class Accessible##classname : public QAccessibleWidget\
|
||||
{\
|
||||
public:\
|
||||
FUNC_CREATE(classname,QAccessible::Form,accessdescription)\
|
||||
QString text(QAccessible::Text t) const override;\
|
||||
void *interface_cast(QAccessible::InterfaceType t) override{\
|
||||
switch (t) {\
|
||||
case QAccessible::ActionInterface:\
|
||||
return static_cast<QAccessibleActionInterface*>(this);\
|
||||
default:\
|
||||
return nullptr;\
|
||||
}\
|
||||
}\
|
||||
private:\
|
||||
classname *m_w;\
|
||||
QString m_description;\
|
||||
};\
|
||||
FUNC_TEXT(classname,accessiblename)\
|
||||
|
||||
#define SET_BUTTON_ACCESSIBLE_WITH_DESCRIPTION(classname,accessiblename,accessdescription) class Accessible##classname : public QAccessibleWidget\
|
||||
{\
|
||||
public:\
|
||||
FUNC_CREATE(classname,QAccessible::Button,accessdescription)\
|
||||
QString text(QAccessible::Text t) const override;\
|
||||
void *interface_cast(QAccessible::InterfaceType t) override{\
|
||||
switch (t) {\
|
||||
case QAccessible::ActionInterface:\
|
||||
return static_cast<QAccessibleActionInterface*>(this);\
|
||||
default:\
|
||||
return nullptr;\
|
||||
}\
|
||||
}\
|
||||
QStringList actionNames() const override;\
|
||||
void doAction(const QString &actionName) override;\
|
||||
private:\
|
||||
classname *m_w;\
|
||||
QString m_description;\
|
||||
};\
|
||||
FUNC_TEXT(classname,accessiblename)\
|
||||
FUNC_ACTIONNAMES(classname)\
|
||||
FUNC_DOACTION(classname)\
|
||||
|
||||
#define SET_LABEL_ACCESSIBLE_WITH_DESCRIPTION(classname,accessiblename,accessdescription) class Accessible##classname : public QAccessibleWidget, public QAccessibleTextInterface\
|
||||
{\
|
||||
public:\
|
||||
FUNC_CREATE(classname,QAccessible::StaticText,accessdescription)\
|
||||
QString text(QAccessible::Text t) const override;\
|
||||
void *interface_cast(QAccessible::InterfaceType t) override{\
|
||||
switch (t) {\
|
||||
case QAccessible::ActionInterface:\
|
||||
return static_cast<QAccessibleActionInterface*>(this);\
|
||||
case QAccessible::TextInterface:\
|
||||
return static_cast<QAccessibleTextInterface*>(this);\
|
||||
default:\
|
||||
return nullptr;\
|
||||
}\
|
||||
}\
|
||||
QString text(int startOffset, int endOffset) const override;\
|
||||
void selection(int selectionIndex, int *startOffset, int *endOffset) const override {\
|
||||
Q_UNUSED(selectionIndex)\
|
||||
Q_UNUSED(startOffset)\
|
||||
Q_UNUSED(endOffset)\
|
||||
}\
|
||||
int selectionCount() const override { return 0; }\
|
||||
void addSelection(int startOffset, int endOffset) override {\
|
||||
Q_UNUSED(startOffset)\
|
||||
Q_UNUSED(endOffset)\
|
||||
}\
|
||||
void removeSelection(int selectionIndex) override {\
|
||||
Q_UNUSED(selectionIndex)\
|
||||
}\
|
||||
void setSelection(int selectionIndex, int startOffset, int endOffset) override {\
|
||||
Q_UNUSED(selectionIndex)\
|
||||
Q_UNUSED(startOffset)\
|
||||
Q_UNUSED(endOffset)\
|
||||
}\
|
||||
int cursorPosition() const override { return 0; }\
|
||||
void setCursorPosition(int position) override {\
|
||||
Q_UNUSED(position)\
|
||||
}\
|
||||
int characterCount() const override { return 0; }\
|
||||
QRect characterRect(int offset) const override {\
|
||||
Q_UNUSED(offset)\
|
||||
return QRect();\
|
||||
}\
|
||||
int offsetAtPoint(const QPoint &point) const override {\
|
||||
Q_UNUSED(point)\
|
||||
return 0;\
|
||||
}\
|
||||
void scrollToSubstring(int startIndex, int endIndex) override {\
|
||||
Q_UNUSED(startIndex)\
|
||||
Q_UNUSED(endIndex)\
|
||||
}\
|
||||
QString attributes(int offset, int *startOffset, int *endOffset) const override {\
|
||||
Q_UNUSED(offset)\
|
||||
Q_UNUSED(startOffset)\
|
||||
Q_UNUSED(endOffset)\
|
||||
return QString();\
|
||||
}\
|
||||
private:\
|
||||
classname *m_w;\
|
||||
QString m_description;\
|
||||
};\
|
||||
FUNC_TEXT(classname,accessiblename)\
|
||||
FUNC_TEXT_(classname)\
|
||||
|
||||
#define SET_SLIDER_ACCESSIBLE_WITH_DESCRIPTION(classname,accessiblename,accessdescription) class Accessible##classname : public QAccessibleWidget, public QAccessibleValueInterface\
|
||||
{\
|
||||
public:\
|
||||
FUNC_CREATE(classname,QAccessible::Slider,accessdescription)\
|
||||
QString text(QAccessible::Text t) const override;\
|
||||
void *interface_cast(QAccessible::InterfaceType t) override{\
|
||||
switch (t) {\
|
||||
case QAccessible::ActionInterface:\
|
||||
return static_cast<QAccessibleActionInterface*>(this);\
|
||||
case QAccessible::ValueInterface:\
|
||||
return static_cast<QAccessibleValueInterface*>(this);\
|
||||
default:\
|
||||
return nullptr;\
|
||||
}\
|
||||
}\
|
||||
QVariant currentValue() const override;\
|
||||
void setCurrentValue(const QVariant &value) override;\
|
||||
QVariant maximumValue() const override;\
|
||||
QVariant minimumValue() const override;\
|
||||
QVariant minimumStepSize() const override;\
|
||||
private:\
|
||||
classname *m_w;\
|
||||
QString m_description;\
|
||||
};\
|
||||
FUNC_TEXT(classname,accessiblename)\
|
||||
FUNC_CURRENTVALUE(classname)\
|
||||
FUNC_SETCURRENTVALUE(classname)\
|
||||
FUNC_MAXMUMVALUE(classname)\
|
||||
FUNC_FUNC_MINIMUMVALUE(classname)\
|
||||
FUNC_FUNC_MINIMUMSTEPSIZE(classname)\
|
||||
|
||||
#define SET_EDITABLE_ACCESSIBLE_WITH_DESCRIPTION(classname,accessiblename,accessdescription) class Accessible##classname : public QAccessibleWidget, public QAccessibleEditableTextInterface, public QAccessibleTextInterface\
|
||||
{\
|
||||
public:\
|
||||
FUNC_CREATE(classname,QAccessible::EditableText,accessdescription)\
|
||||
QString text(QAccessible::Text t) const override;\
|
||||
QAccessibleInterface *child(int index) const override { Q_UNUSED(index); return nullptr; }\
|
||||
void *interface_cast(QAccessible::InterfaceType t) override{\
|
||||
switch (t) {\
|
||||
case QAccessible::ActionInterface:\
|
||||
return static_cast<QAccessibleActionInterface*>(this);\
|
||||
case QAccessible::TextInterface:\
|
||||
return static_cast<QAccessibleTextInterface*>(this);\
|
||||
case QAccessible::EditableTextInterface:\
|
||||
return static_cast<QAccessibleEditableTextInterface*>(this);\
|
||||
default:\
|
||||
return nullptr;\
|
||||
}\
|
||||
}\
|
||||
QString text(int startOffset, int endOffset) const override;\
|
||||
void selection(int selectionIndex, int *startOffset, int *endOffset) const override {\
|
||||
Q_UNUSED(selectionIndex)\
|
||||
Q_UNUSED(startOffset)\
|
||||
Q_UNUSED(endOffset)\
|
||||
}\
|
||||
int selectionCount() const override { return 0; }\
|
||||
void addSelection(int startOffset, int endOffset) override {\
|
||||
Q_UNUSED(startOffset)\
|
||||
Q_UNUSED(endOffset)\
|
||||
}\
|
||||
void removeSelection(int selectionIndex) override { Q_UNUSED(selectionIndex);}\
|
||||
void setSelection(int selectionIndex, int startOffset, int endOffset) override {\
|
||||
Q_UNUSED(selectionIndex)\
|
||||
Q_UNUSED(startOffset)\
|
||||
Q_UNUSED(endOffset)\
|
||||
}\
|
||||
int cursorPosition() const override { return 0; }\
|
||||
void setCursorPosition(int position) override {\
|
||||
Q_UNUSED(position)\
|
||||
}\
|
||||
int characterCount() const override { return 0; }\
|
||||
QRect characterRect(int offset) const override { \
|
||||
Q_UNUSED(offset)\
|
||||
return QRect(); }\
|
||||
int offsetAtPoint(const QPoint &point) const override {\
|
||||
Q_UNUSED(point)\
|
||||
return 0; }\
|
||||
void scrollToSubstring(int startIndex, int endIndex) override {\
|
||||
Q_UNUSED(startIndex)\
|
||||
Q_UNUSED(endIndex)\
|
||||
}\
|
||||
QString attributes(int offset, int *startOffset, int *endOffset) const override {\
|
||||
Q_UNUSED(offset)\
|
||||
Q_UNUSED(startOffset)\
|
||||
Q_UNUSED(endOffset)\
|
||||
return QString(); }\
|
||||
void insertText(int offset, const QString &text) override {\
|
||||
Q_UNUSED(offset)\
|
||||
Q_UNUSED(text)\
|
||||
}\
|
||||
void deleteText(int startOffset, int endOffset) override {\
|
||||
Q_UNUSED(startOffset)\
|
||||
Q_UNUSED(endOffset)\
|
||||
}\
|
||||
void replaceText(int startOffset, int endOffset, const QString &text) override {\
|
||||
Q_UNUSED(startOffset)\
|
||||
Q_UNUSED(endOffset)\
|
||||
Q_UNUSED(text)\
|
||||
}\
|
||||
private:\
|
||||
classname *m_w;\
|
||||
QString m_description;\
|
||||
};\
|
||||
FUNC_TEXT(classname,accessiblename)\
|
||||
FUNC_TEXT_(classname)\
|
||||
|
||||
#define USE_ACCESSIBLE(classnamestring,classname) if (classnamestring == QLatin1String(#classname) && object && object->isWidgetType())\
|
||||
{\
|
||||
interface = new Accessible##classname(static_cast<classname *>(object));\
|
||||
}\
|
||||
|
||||
#define ELSE_USE_ACCESSIBLE(classnamestring,classname) else if (classnamestring == QLatin1String(#classname) && object && object->isWidgetType())\
|
||||
{\
|
||||
interface = new Accessible##classname(static_cast<classname *>(object));\
|
||||
}\
|
||||
|
||||
|
||||
// [指定objectname]---适用同一个类,但objectname不同的情况
|
||||
#define USE_ACCESSIBLE_BY_OBJECTNAME(classnamestring,classname,objectname) if (classnamestring == QLatin1String(#classname) && object && (object->objectName() == objectname) && object->isWidgetType())\
|
||||
{\
|
||||
interface = new Accessible##classname(static_cast<classname *>(object));\
|
||||
}\
|
||||
|
||||
#define ELSE_USE_ACCESSIBLE_BY_OBJECTNAME(classnamestring,classname,objectname) else if (classnamestring == QLatin1String(#classname) && object && (object->objectName() == objectname) && object->isWidgetType())\
|
||||
{\
|
||||
interface = new Accessible##classname(static_cast<classname *>(object));\
|
||||
}\
|
||||
|
||||
/*******************************************简化使用*******************************************/
|
||||
#define SET_FORM_ACCESSIBLE(classname,accessiblename) SET_FORM_ACCESSIBLE_WITH_DESCRIPTION(classname,accessiblename,"")
|
||||
|
||||
#define SET_BUTTON_ACCESSIBLE(classname,accessiblename) SET_BUTTON_ACCESSIBLE_WITH_DESCRIPTION(classname,accessiblename,"")
|
||||
|
||||
#define SET_LABEL_ACCESSIBLE(classname,accessiblename) SET_LABEL_ACCESSIBLE_WITH_DESCRIPTION(classname,accessiblename,"")
|
||||
|
||||
#define SET_SLIDER_ACCESSIBLE(classname,accessiblename) SET_SLIDER_ACCESSIBLE_WITH_DESCRIPTION(classname,accessiblename,"")
|
||||
|
||||
#define SET_EDITABLE_ACCESSIBLE(classname,accessiblename) SET_EDITABLE_ACCESSIBLE_WITH_DESCRIPTION(classname,accessiblename,"")
|
||||
/************************************************************************************************/
|
||||
|
||||
#endif // ACCESSIBLEINTERFACE_H
|
@ -7,8 +7,12 @@
|
||||
#include "appitem.h"
|
||||
#include "launcheritem.h"
|
||||
#include "pluginsitem.h"
|
||||
#include "taskmanager/entry.h"
|
||||
#include "taskmanager/taskmanager.h"
|
||||
#include "taskmanager/windowinfobase.h"
|
||||
#include "traypluginitem.h"
|
||||
#include "utils.h"
|
||||
#include "docksettings.h"
|
||||
#include "appmultiitem.h"
|
||||
#include "quicksettingcontroller.h"
|
||||
|
||||
@ -24,24 +28,24 @@ const QGSettings *DockItemManager::m_dockedSettings = Utils::ModuleSettingsPtr("
|
||||
|
||||
DockItemManager::DockItemManager(QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_appInter(new DockInter(dockServiceName(), dockServicePath(), QDBusConnection::sessionBus(), this))
|
||||
, m_taskmanager(TaskManager::instance())
|
||||
, m_loadFinished(false)
|
||||
{
|
||||
//固定区域:启动器
|
||||
m_itemList.append(new LauncherItem);
|
||||
|
||||
// 应用区域
|
||||
for (auto entry : m_appInter->entries()) {
|
||||
AppItem *it = new AppItem(m_appInter, m_appSettings, m_activeSettings, m_dockedSettings, entry);
|
||||
for (auto entry : m_taskmanager->getEntries()) {
|
||||
AppItem *it = new AppItem(m_appSettings, m_activeSettings, m_dockedSettings, entry);
|
||||
manageItem(it);
|
||||
|
||||
connect(it, &AppItem::requestActivateWindow, m_appInter, &DockInter::ActivateWindow, Qt::QueuedConnection);
|
||||
connect(it, &AppItem::requestPreviewWindow, m_appInter, &DockInter::PreviewWindow);
|
||||
connect(it, &AppItem::requestCancelPreview, m_appInter, &DockInter::CancelPreviewWindow);
|
||||
connect(it, &AppItem::requestPreviewWindow, m_taskmanager, &TaskManager::previewWindow);
|
||||
connect(it, &AppItem::requestCancelPreview, m_taskmanager, &TaskManager::cancelPreviewWindow);
|
||||
connect(it, &AppItem::windowCountChanged, this, &DockItemManager::onAppWindowCountChanged);
|
||||
connect(this, &DockItemManager::requestUpdateDockItem, it, &AppItem::requestUpdateEntryGeometries);
|
||||
|
||||
m_itemList.append(it);
|
||||
m_appIDist.append(it->appId());
|
||||
updateMultiItems(it);
|
||||
}
|
||||
|
||||
@ -60,10 +64,10 @@ DockItemManager::DockItemManager(QObject *parent)
|
||||
connect(quickController, &QuickSettingController::pluginLoaderFinished, this, &DockItemManager::onPluginLoadFinished, Qt::QueuedConnection);
|
||||
|
||||
// 应用信号
|
||||
connect(m_appInter, &DockInter::EntryAdded, this, &DockItemManager::appItemAdded);
|
||||
connect(m_appInter, &DockInter::EntryRemoved, this, static_cast<void (DockItemManager::*)(const QString &)>(&DockItemManager::appItemRemoved), Qt::QueuedConnection);
|
||||
connect(m_appInter, &DockInter::ServiceRestarted, this, &DockItemManager::reloadAppItems);
|
||||
connect(m_appInter, &DockInter::ShowMultiWindowChanged, this, &DockItemManager::onShowMultiWindowChanged);
|
||||
connect(m_taskmanager, &TaskManager::entryAdded, this, &DockItemManager::appItemAdded, Qt::DirectConnection);
|
||||
connect(m_taskmanager, &TaskManager::entryRemoved, this, static_cast<void (DockItemManager::*)(const QString &)>(&DockItemManager::appItemRemoved), Qt::DirectConnection);
|
||||
connect(m_taskmanager, &TaskManager::serviceRestarted, this, &DockItemManager::reloadAppItems);
|
||||
connect(DockSettings::instance(), &DockSettings::showMultiWindowChanged, this, &DockItemManager::onShowMultiWindowChanged);
|
||||
|
||||
DApplication *app = qobject_cast<DApplication *>(qApp);
|
||||
if (app) {
|
||||
@ -80,7 +84,7 @@ DockItemManager::DockItemManager(QObject *parent)
|
||||
}
|
||||
|
||||
// 刷新图标
|
||||
QMetaObject::invokeMethod(this, "refreshItemsIcon", Qt::QueuedConnection);
|
||||
QMetaObject::invokeMethod(this, &DockItemManager::refreshItemsIcon, Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
DockItemManager *DockItemManager::instance(QObject *parent)
|
||||
@ -98,7 +102,7 @@ const QList<QPointer<DockItem>> DockItemManager::itemList() const
|
||||
|
||||
bool DockItemManager::appIsOnDock(const QString &appDesktop) const
|
||||
{
|
||||
return m_appInter->IsOnDock(appDesktop);
|
||||
return m_taskmanager->isOnDock(appDesktop);
|
||||
}
|
||||
|
||||
void DockItemManager::refreshItemsIcon()
|
||||
@ -166,15 +170,15 @@ void DockItemManager::itemMoved(DockItem *const sourceItem, DockItem *const targ
|
||||
|
||||
// for app move, index 0 is launcher item, need to pass it.
|
||||
if (moveType == DockItem::App && replaceType == DockItem::App)
|
||||
m_appInter->MoveEntry(moveIndex - 1, replaceIndex - 1);
|
||||
m_taskmanager->moveEntry(moveIndex - 1, replaceIndex - 1);
|
||||
}
|
||||
|
||||
void DockItemManager::itemAdded(const QString &appDesktop, int idx)
|
||||
{
|
||||
m_appInter->RequestDock(appDesktop, idx);
|
||||
m_taskmanager->requestDock(appDesktop, idx);
|
||||
}
|
||||
|
||||
void DockItemManager::appItemAdded(const QDBusObjectPath &path, const int index)
|
||||
void DockItemManager::appItemAdded(const Entry *entry, const int index)
|
||||
{
|
||||
// 第一个是启动器
|
||||
int insertIndex = 1;
|
||||
@ -188,18 +192,17 @@ void DockItemManager::appItemAdded(const QDBusObjectPath &path, const int index)
|
||||
++insertIndex;
|
||||
}
|
||||
|
||||
AppItem *item = new AppItem(m_appInter, m_appSettings, m_activeSettings, m_dockedSettings, path);
|
||||
AppItem *item = new AppItem(m_appSettings, m_activeSettings, m_dockedSettings, entry);
|
||||
|
||||
if (m_appIDist.contains(item->appId())) {
|
||||
delete item;
|
||||
item->deleteLater();
|
||||
return;
|
||||
}
|
||||
|
||||
manageItem(item);
|
||||
|
||||
connect(item, &AppItem::requestActivateWindow, m_appInter, &DockInter::ActivateWindow, Qt::QueuedConnection);
|
||||
connect(item, &AppItem::requestPreviewWindow, m_appInter, &DockInter::PreviewWindow);
|
||||
connect(item, &AppItem::requestCancelPreview, m_appInter, &DockInter::CancelPreviewWindow);
|
||||
connect(item, &AppItem::requestPreviewWindow, m_taskmanager, &TaskManager::previewWindow);
|
||||
connect(item, &AppItem::requestCancelPreview, m_taskmanager, &TaskManager::cancelPreviewWindow);
|
||||
connect(item, &AppItem::windowCountChanged, this, &DockItemManager::onAppWindowCountChanged);
|
||||
connect(this, &DockItemManager::requestUpdateDockItem, item, &AppItem::requestUpdateEntryGeometries);
|
||||
|
||||
@ -255,8 +258,8 @@ void DockItemManager::reloadAppItems()
|
||||
appItemRemoved(static_cast<AppItem *>(item.data()));
|
||||
|
||||
// append new item
|
||||
for (auto path : m_appInter->entries())
|
||||
appItemAdded(path, -1);
|
||||
for (Entry* entry : m_taskmanager->getEntries())
|
||||
appItemAdded(entry, -1);
|
||||
}
|
||||
|
||||
void DockItemManager::manageItem(DockItem *item)
|
||||
@ -365,11 +368,11 @@ void DockItemManager::onAppWindowCountChanged()
|
||||
void DockItemManager::updateMultiItems(AppItem *appItem, bool emitSignal)
|
||||
{
|
||||
// 如果系统设置不开启应用多窗口拆分,则无需之后的操作
|
||||
if (!m_appInter->showMultiWindow())
|
||||
if (!m_taskmanager->showMultiWindow())
|
||||
return;
|
||||
|
||||
// 如果开启了多窗口拆分,则同步窗口和多窗口应用的信息
|
||||
const WindowInfoMap &windowInfoMap = appItem->windowsMap();
|
||||
const WindowInfoMap &windowInfoMap = appItem->windowsInfos();
|
||||
QList<AppMultiItem *> removeItems;
|
||||
// 同步当前已经存在的多开窗口的列表,删除不存在的多开窗口
|
||||
for (int i = 0; i < m_itemList.size(); i++) {
|
||||
@ -430,7 +433,7 @@ bool DockItemManager::needRemoveMultiWindow(AppMultiItem *multiItem) const
|
||||
// 查找多分窗口对应的窗口在应用所有的打开的窗口中是否存在,只要它对应的窗口存在,就无需删除
|
||||
// 只要不存在,就需要删除
|
||||
AppItem *appItem = multiItem->appItem();
|
||||
const WindowInfoMap &windowInfoMap = appItem->windowsMap();
|
||||
const WindowInfoMap &windowInfoMap = appItem->windowsInfos();
|
||||
for (auto it = windowInfoMap.begin(); it != windowInfoMap.end(); it++) {
|
||||
if (it.key() == multiItem->winId())
|
||||
return false;
|
||||
@ -441,7 +444,7 @@ bool DockItemManager::needRemoveMultiWindow(AppMultiItem *multiItem) const
|
||||
|
||||
void DockItemManager::onShowMultiWindowChanged()
|
||||
{
|
||||
if (m_appInter->showMultiWindow()) {
|
||||
if (m_taskmanager->showMultiWindow()) {
|
||||
// 如果当前设置支持窗口多开,那么就依次对每个APPItem加载多开窗口
|
||||
for (int i = 0; i < m_itemList.size(); i++) {
|
||||
const QPointer<DockItem> &dockItem = m_itemList[i];
|
||||
|
@ -11,6 +11,8 @@
|
||||
#include "appitem.h"
|
||||
#include "placeholderitem.h"
|
||||
#include "dbusutil.h"
|
||||
#include "taskmanager/taskmanager.h"
|
||||
#include "taskmanager/windowinfobase.h"
|
||||
|
||||
#include <QObject>
|
||||
|
||||
@ -56,7 +58,7 @@ private Q_SLOTS:
|
||||
|
||||
private:
|
||||
explicit DockItemManager(QObject *parent = nullptr);
|
||||
void appItemAdded(const QDBusObjectPath &path, const int index);
|
||||
void appItemAdded(const Entry *entry, const int index);
|
||||
void appItemRemoved(const QString &appId);
|
||||
void appItemRemoved(AppItem *appItem);
|
||||
void updatePluginsItemOrderKey();
|
||||
@ -69,7 +71,7 @@ private:
|
||||
bool needRemoveMultiWindow(AppMultiItem *multiItem) const;
|
||||
|
||||
private:
|
||||
DockInter *m_appInter;
|
||||
TaskManager *m_taskmanager;
|
||||
|
||||
static DockItemManager *INSTANCE;
|
||||
|
||||
|
@ -36,9 +36,9 @@ bool QuickSettingController::eventFilter(QObject *watched, QEvent *event)
|
||||
void QuickSettingController::startLoader()
|
||||
{
|
||||
#ifdef QT_DEBUG
|
||||
AbstractPluginsController::startLoader(new PluginLoader(QString("%1/..%2").arg(qApp->applicationDirPath()).arg("/plugins/loader"), this));
|
||||
AbstractPluginsController::startLoader(new PluginLoader(QString("%1/..%2").arg(qApp->applicationDirPath()).arg("/plugins/loader"), this));
|
||||
#else
|
||||
AbstractPluginsController::startLoader(new PluginLoader("/usr/lib/dde-dock/plugins/loader", this));
|
||||
AbstractPluginsController::startLoader(new PluginLoader("/usr/lib/dde-dock/plugins/loader", this));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
#include "recentapphelper.h"
|
||||
#include "dockitemmanager.h"
|
||||
#include "appitem.h"
|
||||
|
||||
#include <QWidget>
|
||||
@ -12,14 +13,14 @@
|
||||
#define ENTRY_NORMAL 1
|
||||
#define ENTRY_RECENT 2
|
||||
|
||||
RecentAppHelper::RecentAppHelper(QWidget *appWidget, QWidget *recentWidget, DockInter *dockInter, QObject *parent)
|
||||
RecentAppHelper::RecentAppHelper(QWidget *appWidget, QWidget *recentWidget, QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_appWidget(appWidget)
|
||||
, m_recentWidget(recentWidget)
|
||||
, m_dockInter(dockInter)
|
||||
{
|
||||
m_appWidget->installEventFilter(this);
|
||||
m_recentWidget->installEventFilter(this);
|
||||
connect(this, &RecentAppHelper::requestUpdateRecentVisible, this, &RecentAppHelper::updateRecentVisible, Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void RecentAppHelper::setDisplayMode(Dock::DisplayMode displayMode)
|
||||
@ -71,11 +72,6 @@ bool RecentAppHelper::dockAppIsVisible() const
|
||||
|| m_appWidget->layout()->count() > 0);
|
||||
}
|
||||
|
||||
void RecentAppHelper::updateDockInter(DockInter *dockInter)
|
||||
{
|
||||
m_dockInter = dockInter;
|
||||
}
|
||||
|
||||
bool RecentAppHelper::eventFilter(QObject *watched, QEvent *event)
|
||||
{
|
||||
if (watched == m_appWidget || watched == m_recentWidget) {
|
||||
@ -175,7 +171,7 @@ void RecentAppHelper::removeRecentAreaItem(DockItem *wdg)
|
||||
{
|
||||
QBoxLayout *recentLayout = static_cast<QBoxLayout *>(m_recentWidget->layout());
|
||||
recentLayout->removeWidget(wdg);
|
||||
updateRecentVisible();
|
||||
Q_EMIT requestUpdateRecentVisible();
|
||||
}
|
||||
|
||||
void RecentAppHelper::removeAppAreaItem(DockItem *wdg)
|
||||
@ -193,7 +189,7 @@ int RecentAppHelper::getEntryIndex(DockItem *dockItem, QWidget *widget) const
|
||||
return -1;
|
||||
|
||||
// 查找当前的应用在所有的应用中的排序
|
||||
QStringList entryIds = m_dockInter->GetEntryIDs();
|
||||
QStringList entryIds = TaskManager::instance()->getEntryIDs();
|
||||
int index = entryIds.indexOf(appItem->appId());
|
||||
if (index < 0)
|
||||
return -1;
|
||||
|
@ -24,19 +24,19 @@ class RecentAppHelper : public QObject
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit RecentAppHelper(QWidget *appWidget, QWidget *recentWidget, DockInter *dockInter, QObject *parent = nullptr);
|
||||
explicit RecentAppHelper(QWidget *appWidget, QWidget *recentWidget, QObject *parent = nullptr);
|
||||
void setDisplayMode(Dock::DisplayMode displayMode);
|
||||
void resetAppInfo();
|
||||
void addAppItem(int index, DockItem *appItem);
|
||||
void removeAppItem(DockItem *dockItem);
|
||||
bool recentIsVisible() const;
|
||||
bool dockAppIsVisible() const;
|
||||
void updateDockInter(DockInter *dockInter);
|
||||
|
||||
Q_SIGNALS:
|
||||
void requestUpdate();
|
||||
void recentVisibleChanged(bool); // 最近区域是否可见发生变化的信号
|
||||
void dockAppVisibleChanged(bool); // 驻留应用区域是否可见发生变化的信号
|
||||
void requestUpdateRecentVisible();
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject *watched, QEvent *event) override;
|
||||
@ -45,7 +45,6 @@ private:
|
||||
bool appInRecent(DockItem *item) const;
|
||||
void addAppAreaItem(int index, DockItem *wdg);
|
||||
void addRecentAreaItem(int index, DockItem *wdg);
|
||||
void updateRecentVisible();
|
||||
void updateDockAppVisible(bool lastVisible);
|
||||
|
||||
void removeRecentAreaItem(DockItem *wdg);
|
||||
@ -57,12 +56,12 @@ private:
|
||||
|
||||
private Q_SLOTS:
|
||||
void onModeChanged(int mode);
|
||||
void updateRecentVisible();
|
||||
|
||||
private:
|
||||
QWidget *m_appWidget;
|
||||
QWidget *m_recentWidget;
|
||||
Dock::DisplayMode m_displayMode;
|
||||
DockInter *m_dockInter;
|
||||
};
|
||||
|
||||
#endif // RECENTAPPHELPER_H
|
||||
|
@ -45,6 +45,7 @@ void ToolAppHelper::setPosition(Position position)
|
||||
{
|
||||
m_toolAreaWidget->setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
|
||||
m_position = position;
|
||||
updateWidgetStatus();
|
||||
}
|
||||
|
||||
bool ToolAppHelper::toolIsVisible() const
|
||||
@ -60,8 +61,6 @@ void ToolAppHelper::appendToToolArea(int index, DockItem *dockItem)
|
||||
boxLayout->insertWidget(index, dockItem);
|
||||
else
|
||||
boxLayout->addWidget(dockItem);
|
||||
|
||||
Q_EMIT requestUpdate();
|
||||
}
|
||||
|
||||
bool ToolAppHelper::removeToolArea(PluginsItemInterface *itemInter)
|
||||
@ -142,7 +141,7 @@ void ToolAppHelper::updateWidgetStatus()
|
||||
m_toolAreaWidget->setVisible(false);
|
||||
} else {
|
||||
// 时尚模式
|
||||
m_toolAreaWidget->setVisible(m_toolAreaWidget->layout()->count() > 0);
|
||||
updateToolArea();
|
||||
}
|
||||
bool visible = toolIsVisible();
|
||||
if (oldVisible != visible)
|
||||
|
@ -25,7 +25,8 @@
|
||||
#include "windowmanager.h"
|
||||
#include "quicksettingcontroller.h"
|
||||
#include "pluginsitem.h"
|
||||
#include "settingconfig.h"
|
||||
#include "docksettings.h"
|
||||
#include "common.h"
|
||||
#include "customevent.h"
|
||||
|
||||
#include <DGuiApplicationHelper>
|
||||
@ -174,7 +175,7 @@ DockItemInfos DBusDockAdaptors::plugins()
|
||||
// 获取本地加载的插件
|
||||
QList<PluginsItemInterface *> allPlugin = localPlugins();
|
||||
DockItemInfos pluginInfos;
|
||||
QStringList quickSettingKeys = SETTINGCONFIG->value(DOCK_QUICK_PLUGINS).toStringList();
|
||||
QStringList quickSettingKeys = DockSettings::instance()->getQuickPlugins();
|
||||
for (PluginsItemInterface *plugin : allPlugin) {
|
||||
DockItemInfo info;
|
||||
info.name = plugin->pluginName();
|
||||
@ -271,13 +272,12 @@ void DBusDockAdaptors::setPluginVisible(const QString &pluginName, bool visible)
|
||||
|
||||
void DBusDockAdaptors::setItemOnDock(const QString settingKey, const QString &itemKey, bool visible)
|
||||
{
|
||||
QStringList settings = SETTINGCONFIG->value(settingKey).toStringList();
|
||||
if (visible && !settings.contains(itemKey))
|
||||
settings << itemKey;
|
||||
else if (!visible && settings.contains(itemKey))
|
||||
settings.removeOne(itemKey);
|
||||
|
||||
SETTINGCONFIG->setValue(settingKey, settings);
|
||||
DockSettings *settings = DockSettings::instance();
|
||||
if ( keyQuickTrayName == settingKey) {
|
||||
visible? settings->setTrayItemOnDock(itemKey) : settings->removeTrayItemOnDock(itemKey);
|
||||
} else if (keyQuickPlugins == settingKey) {
|
||||
visible? settings->setQuickPlugin(itemKey) : settings->removeQuickPlugin(itemKey);
|
||||
}
|
||||
}
|
||||
|
||||
QRect DBusDockAdaptors::geometry() const
|
||||
@ -326,7 +326,7 @@ QIcon DBusDockAdaptors::getSettingIcon(PluginsItemInterface *plugin, QSize &pixm
|
||||
{
|
||||
auto iconSize = [](const QIcon &icon) {
|
||||
QList<QSize> iconSizes = icon.availableSizes();
|
||||
if (iconSizes.size() > 0)
|
||||
if (iconSizes.size() > 0 && !iconSizes[0].isNull() )
|
||||
return iconSizes[0];
|
||||
|
||||
return defaultIconSize;
|
||||
@ -335,7 +335,14 @@ QIcon DBusDockAdaptors::getSettingIcon(PluginsItemInterface *plugin, QSize &pixm
|
||||
QIcon icon = plugin->icon(DockPart::DCCSetting, colorType);
|
||||
if (!icon.isNull()) {
|
||||
pixmapSize = iconSize(icon);
|
||||
return icon;
|
||||
|
||||
QColor c = colorType == DGuiApplicationHelper::LightType ? Qt::black :Qt::white;
|
||||
QPixmap pixmap = icon.pixmap(pixmapSize);
|
||||
QPainter pa(&pixmap);
|
||||
pa.setCompositionMode(QPainter::CompositionMode_SourceIn);
|
||||
pa.fillRect(pixmap.rect(), c);
|
||||
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
// 如果插件中没有设置图标,则根据插件的类型,获取其他的图标
|
||||
|
@ -1,47 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: sbw <sbw@sbw.so>
|
||||
*
|
||||
* Maintainer: sbw <sbw@sbw.so>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file was generated by qdbusxml2cpp version 0.8
|
||||
* Command line was: qdbusxml2cpp -c DBusMenu -p dbusmenu com.deepin.menu.Menu.xml
|
||||
*
|
||||
* qdbusxml2cpp is Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies).
|
||||
*
|
||||
* This is an auto-generated file.
|
||||
* This file may have been hand-edited. Look for HAND-EDIT comments
|
||||
* before re-generating it.
|
||||
*/
|
||||
|
||||
#include "dbusmenu.h"
|
||||
|
||||
/*
|
||||
* Implementation of interface class DBusMenu
|
||||
*/
|
||||
|
||||
DBusMenu::DBusMenu(const QString &path, QObject *parent)
|
||||
: QDBusAbstractInterface(staticServerPath(), path, staticInterfaceName(), QDBusConnection::sessionBus(), parent)
|
||||
{
|
||||
}
|
||||
|
||||
DBusMenu::~DBusMenu()
|
||||
{
|
||||
}
|
||||
|
@ -1,102 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: sbw <sbw@sbw.so>
|
||||
*
|
||||
* Maintainer: sbw <sbw@sbw.so>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file was generated by qdbusxml2cpp version 0.8
|
||||
* Command line was: qdbusxml2cpp -c DBusMenu -p dbusmenu com.deepin.menu.Menu.xml
|
||||
*
|
||||
* qdbusxml2cpp is Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies).
|
||||
*
|
||||
* This is an auto-generated file.
|
||||
* Do not edit! All changes made to it will be lost.
|
||||
*/
|
||||
|
||||
#ifndef DBUSMENU_H_1436158836
|
||||
#define DBUSMENU_H_1436158836
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QByteArray>
|
||||
#include <QtCore/QList>
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QStringList>
|
||||
#include <QtCore/QVariant>
|
||||
#include <QtDBus/QtDBus>
|
||||
|
||||
/*
|
||||
* Proxy class for interface com.deepin.menu.Menu
|
||||
*/
|
||||
class DBusMenu: public QDBusAbstractInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
static inline const char *staticServerPath()
|
||||
{ return "com.deepin.menu"; }
|
||||
static inline const char *staticInterfaceName()
|
||||
{ return "com.deepin.menu.Menu"; }
|
||||
|
||||
public:
|
||||
DBusMenu(const QString &path,QObject *parent = 0);
|
||||
|
||||
~DBusMenu();
|
||||
|
||||
public Q_SLOTS: // METHODS
|
||||
inline QDBusPendingReply<> SetItemActivity(const QString &itemId, bool isActive)
|
||||
{
|
||||
QList<QVariant> argumentList;
|
||||
argumentList << QVariant::fromValue(itemId) << QVariant::fromValue(isActive);
|
||||
return asyncCallWithArgumentList(QStringLiteral("SetItemActivity"), argumentList);
|
||||
}
|
||||
|
||||
inline QDBusPendingReply<> SetItemChecked(const QString &itemId, bool checked)
|
||||
{
|
||||
QList<QVariant> argumentList;
|
||||
argumentList << QVariant::fromValue(itemId) << QVariant::fromValue(checked);
|
||||
return asyncCallWithArgumentList(QStringLiteral("SetItemChecked"), argumentList);
|
||||
}
|
||||
|
||||
inline QDBusPendingReply<> SetItemText(const QString &itemId, const QString &text)
|
||||
{
|
||||
QList<QVariant> argumentList;
|
||||
argumentList << QVariant::fromValue(itemId) << QVariant::fromValue(text);
|
||||
return asyncCallWithArgumentList(QStringLiteral("SetItemText"), argumentList);
|
||||
}
|
||||
|
||||
inline QDBusPendingReply<> ShowMenu(const QString &menuJsonContent)
|
||||
{
|
||||
QList<QVariant> argumentList;
|
||||
argumentList << QVariant::fromValue(menuJsonContent);
|
||||
return asyncCallWithArgumentList(QStringLiteral("ShowMenu"), argumentList);
|
||||
}
|
||||
|
||||
Q_SIGNALS: // SIGNALS
|
||||
void ItemInvoked(const QString &itemId, bool checked);
|
||||
void MenuUnregistered();
|
||||
};
|
||||
|
||||
namespace com {
|
||||
namespace deepin {
|
||||
namespace menu {
|
||||
typedef ::DBusMenu Menu;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@ -1,47 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: sbw <sbw@sbw.so>
|
||||
*
|
||||
* Maintainer: sbw <sbw@sbw.so>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file was generated by qdbusxml2cpp version 0.8
|
||||
* Command line was: qdbusxml2cpp -c DBusMenuManager -p dbusmenumanager com.deepin.menu.Manager.xml
|
||||
*
|
||||
* qdbusxml2cpp is Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies).
|
||||
*
|
||||
* This is an auto-generated file.
|
||||
* This file may have been hand-edited. Look for HAND-EDIT comments
|
||||
* before re-generating it.
|
||||
*/
|
||||
|
||||
#include "dbusmenumanager.h"
|
||||
|
||||
/*
|
||||
* Implementation of interface class DBusMenuManager
|
||||
*/
|
||||
|
||||
DBusMenuManager::DBusMenuManager(QObject *parent)
|
||||
: QDBusAbstractInterface(staticServerPath(), staticInterfacePath(), staticInterfaceName(), QDBusConnection::sessionBus(), parent)
|
||||
{
|
||||
}
|
||||
|
||||
DBusMenuManager::~DBusMenuManager()
|
||||
{
|
||||
}
|
||||
|
@ -1,87 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 ~ 2018 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: sbw <sbw@sbw.so>
|
||||
*
|
||||
* Maintainer: sbw <sbw@sbw.so>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file was generated by qdbusxml2cpp version 0.8
|
||||
* Command line was: qdbusxml2cpp -c DBusMenuManager -p dbusmenumanager com.deepin.menu.Manager.xml
|
||||
*
|
||||
* qdbusxml2cpp is Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies).
|
||||
*
|
||||
* This is an auto-generated file.
|
||||
* Do not edit! All changes made to it will be lost.
|
||||
*/
|
||||
|
||||
#ifndef DBUSMENUMANAGER_H_1436158928
|
||||
#define DBUSMENUMANAGER_H_1436158928
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QByteArray>
|
||||
#include <QtCore/QList>
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QStringList>
|
||||
#include <QtCore/QVariant>
|
||||
#include <QtDBus/QtDBus>
|
||||
|
||||
/*
|
||||
* Proxy class for interface com.deepin.menu.Manager
|
||||
*/
|
||||
class DBusMenuManager: public QDBusAbstractInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
static inline const char *staticServerPath()
|
||||
{ return "com.deepin.menu"; }
|
||||
static inline const char *staticInterfacePath()
|
||||
{ return "/com/deepin/menu"; }
|
||||
static inline const char *staticInterfaceName()
|
||||
{ return "com.deepin.menu.Manager"; }
|
||||
|
||||
public:
|
||||
explicit DBusMenuManager(QObject *parent = 0);
|
||||
|
||||
~DBusMenuManager();
|
||||
|
||||
public Q_SLOTS: // METHODS
|
||||
inline QDBusPendingReply<QDBusObjectPath> RegisterMenu()
|
||||
{
|
||||
QList<QVariant> argumentList;
|
||||
return asyncCallWithArgumentList(QStringLiteral("RegisterMenu"), argumentList);
|
||||
}
|
||||
|
||||
inline QDBusPendingReply<> UnregisterMenu(const QString &menuObjectPath)
|
||||
{
|
||||
QList<QVariant> argumentList;
|
||||
argumentList << QVariant::fromValue(menuObjectPath);
|
||||
return asyncCallWithArgumentList(QStringLiteral("UnregisterMenu"), argumentList);
|
||||
}
|
||||
|
||||
Q_SIGNALS: // SIGNALS
|
||||
};
|
||||
|
||||
namespace com {
|
||||
namespace deepin {
|
||||
namespace menu {
|
||||
typedef ::DBusMenuManager Manager;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@ -1,16 +0,0 @@
|
||||
<interface name="dde.dock.ClientManager">
|
||||
<method name="ActivateWindow">
|
||||
<arg type="u" direction="in"></arg>
|
||||
<arg type="b" direction="out"></arg>
|
||||
</method>
|
||||
<method name="CloseWindow">
|
||||
<arg type="u" direction="in"></arg>
|
||||
<arg type="b" direction="out"></arg>
|
||||
</method>
|
||||
<method name="CurrentActiveWindow">
|
||||
<arg type="u" direction="out"></arg>
|
||||
</method>
|
||||
<signal name="ActiveWindowChanged">
|
||||
<arg type="u"></arg>
|
||||
</signal>
|
||||
</interface>
|
@ -1,13 +0,0 @@
|
||||
<interface name="dde.dock.Entry">
|
||||
<method name="Activate">
|
||||
</method>
|
||||
<signal name="DataChanged">
|
||||
<arg type="s"></arg>
|
||||
<arg type="s"></arg>
|
||||
</signal>
|
||||
<property name="Id" type="s" access="read"></property>
|
||||
<property name="Type" type="s" access="read"></property>
|
||||
<property name="Data" type="a{ss}" access="read">
|
||||
<annotation name="org.qtproject.QtDBus.QtTypeName" value="Dict"/>
|
||||
</property>
|
||||
</interface>
|
246
frame/dbus/dockdaemonadaptors.cpp
Normal file
246
frame/dbus/dockdaemonadaptors.cpp
Normal file
@ -0,0 +1,246 @@
|
||||
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "dockdaemonadaptors.h"
|
||||
#include "docksettings.h"
|
||||
#include "taskmanager/taskmanager.h"
|
||||
|
||||
DockDaemonDBusAdaptor::DockDaemonDBusAdaptor(QObject *parent)
|
||||
: QDBusAbstractAdaptor(parent)
|
||||
{
|
||||
// constructor
|
||||
setAutoRelaySignals(true);
|
||||
connect(TaskManager::instance(), &TaskManager::entryAdded, this, &DockDaemonDBusAdaptor::EntryAdded);
|
||||
connect(TaskManager::instance(), &TaskManager::entryRemoved, this, &DockDaemonDBusAdaptor::EntryRemoved);
|
||||
connect(TaskManager::instance(), &TaskManager::hideStateChanged, this, &DockDaemonDBusAdaptor::HideStateChanged);
|
||||
connect(TaskManager::instance(), &TaskManager::frontendWindowRectChanged, this, &DockDaemonDBusAdaptor::FrontendWindowRectChanged);
|
||||
connect(TaskManager::instance(), &TaskManager::showRecentChanged, this, &DockDaemonDBusAdaptor::showRecentChanged);
|
||||
connect(TaskManager::instance(), &TaskManager::showMultiWindowChanged, this, &DockDaemonDBusAdaptor::ShowMultiWindowChanged);
|
||||
connect(TaskManager::instance(), &TaskManager::windowMarginChanged, this, &DockDaemonDBusAdaptor::WindowMarginChanged);
|
||||
connect(DockSettings::instance(), &DockSettings::positionModeChanged, this, &DockDaemonDBusAdaptor::PositionChanged);
|
||||
connect(DockSettings::instance(), &DockSettings::hideModeChanged, this, &DockDaemonDBusAdaptor::HideModeChanged);
|
||||
connect(DockSettings::instance(), &DockSettings::displayModeChanged, this, &DockDaemonDBusAdaptor::DisplayModeChanged);
|
||||
connect(DockSettings::instance(), &DockSettings::windowSizeEfficientChanged, this, &DockDaemonDBusAdaptor::WindowSizeEfficientChanged);
|
||||
connect(DockSettings::instance(), &DockSettings::windowSizeFashionChanged, this, &DockDaemonDBusAdaptor::WindowSizeFashionChanged);
|
||||
}
|
||||
|
||||
DockDaemonDBusAdaptor::~DockDaemonDBusAdaptor()
|
||||
{
|
||||
// destructor
|
||||
}
|
||||
|
||||
int DockDaemonDBusAdaptor::displayMode() const
|
||||
{
|
||||
return TaskManager::instance()->getDisplayMode();
|
||||
}
|
||||
|
||||
void DockDaemonDBusAdaptor::setDisplayMode(int value)
|
||||
{
|
||||
if (displayMode() != value) {
|
||||
TaskManager::instance()->setDisplayMode(value);
|
||||
Q_EMIT DisplayModeChanged(value);
|
||||
}
|
||||
}
|
||||
|
||||
QStringList DockDaemonDBusAdaptor::dockedApps() const
|
||||
{
|
||||
return TaskManager::instance()->getDockedApps();
|
||||
}
|
||||
|
||||
int DockDaemonDBusAdaptor::hideMode() const
|
||||
{
|
||||
return TaskManager::instance()->getHideMode();
|
||||
}
|
||||
|
||||
void DockDaemonDBusAdaptor::setHideMode(int value)
|
||||
{
|
||||
if (hideMode() != value) {
|
||||
TaskManager::instance()->setHideMode(static_cast<HideMode>(value));
|
||||
Q_EMIT HideModeChanged(value);
|
||||
}
|
||||
}
|
||||
|
||||
int DockDaemonDBusAdaptor::hideState() const
|
||||
{
|
||||
return TaskManager::instance()->getHideState();
|
||||
}
|
||||
|
||||
uint DockDaemonDBusAdaptor::hideTimeout() const
|
||||
{
|
||||
return TaskManager::instance()->getHideTimeout();
|
||||
}
|
||||
|
||||
void DockDaemonDBusAdaptor::setHideTimeout(uint value)
|
||||
{
|
||||
if (hideTimeout() != value) {
|
||||
TaskManager::instance()->setHideTimeout(value);
|
||||
Q_EMIT HideTimeoutChanged(value);
|
||||
}
|
||||
}
|
||||
|
||||
uint DockDaemonDBusAdaptor::windowSizeEfficient() const
|
||||
{
|
||||
return TaskManager::instance()->getWindowSizeEfficient();
|
||||
}
|
||||
|
||||
void DockDaemonDBusAdaptor::setWindowSizeEfficient(uint value)
|
||||
{
|
||||
if (windowSizeEfficient() != value) {
|
||||
TaskManager::instance()->setWindowSizeEfficient(value);
|
||||
Q_EMIT WindowSizeEfficientChanged(value);
|
||||
}
|
||||
}
|
||||
|
||||
uint DockDaemonDBusAdaptor::windowSizeFashion() const
|
||||
{
|
||||
return TaskManager::instance()->getWindowSizeFashion();
|
||||
}
|
||||
|
||||
void DockDaemonDBusAdaptor::setWindowSizeFashion(uint value)
|
||||
{
|
||||
if (windowSizeFashion() != value) {
|
||||
TaskManager::instance()->setWindowSizeFashion(value);
|
||||
Q_EMIT WindowSizeFashionChanged(value);
|
||||
}
|
||||
}
|
||||
|
||||
uint DockDaemonDBusAdaptor::windowMargin() const
|
||||
{
|
||||
return TaskManager::instance()->windowMargin();
|
||||
}
|
||||
|
||||
QRect DockDaemonDBusAdaptor::frontendWindowRect() const
|
||||
{
|
||||
return TaskManager::instance()->getFrontendWindowRect();
|
||||
}
|
||||
|
||||
uint DockDaemonDBusAdaptor::iconSize() const
|
||||
{
|
||||
return TaskManager::instance()->getIconSize();
|
||||
}
|
||||
|
||||
void DockDaemonDBusAdaptor::setIconSize(uint value)
|
||||
{
|
||||
if (iconSize() != value) {
|
||||
TaskManager::instance()->setIconSize(value);
|
||||
Q_EMIT IconSizeChanged(value);
|
||||
}
|
||||
}
|
||||
|
||||
int DockDaemonDBusAdaptor::position() const
|
||||
{
|
||||
return TaskManager::instance()->getPosition();
|
||||
}
|
||||
|
||||
void DockDaemonDBusAdaptor::setPosition(int value)
|
||||
{
|
||||
if (position() != value) {
|
||||
TaskManager::instance()->setPosition(value);
|
||||
Q_EMIT PositionChanged(value);
|
||||
}
|
||||
}
|
||||
|
||||
uint DockDaemonDBusAdaptor::showTimeout() const
|
||||
{
|
||||
return TaskManager::instance()->getShowTimeout();
|
||||
}
|
||||
|
||||
void DockDaemonDBusAdaptor::setShowTimeout(uint value)
|
||||
{
|
||||
if (showTimeout() != value) {
|
||||
TaskManager::instance()->setShowTimeout(value);
|
||||
Q_EMIT ShowTimeoutChanged(value);
|
||||
}
|
||||
}
|
||||
|
||||
bool DockDaemonDBusAdaptor::showRecent() const
|
||||
{
|
||||
return DockSettings::instance()->showRecent();
|
||||
}
|
||||
|
||||
bool DockDaemonDBusAdaptor::showMultiWindow() const
|
||||
{
|
||||
return TaskManager::instance()->showMultiWindow();
|
||||
}
|
||||
|
||||
void DockDaemonDBusAdaptor::CloseWindow(uint win)
|
||||
{
|
||||
TaskManager::instance()->closeWindow(win);
|
||||
}
|
||||
|
||||
// for debug
|
||||
QStringList DockDaemonDBusAdaptor::GetEntryIDs()
|
||||
{
|
||||
return TaskManager::instance()->getEntryIDs();
|
||||
}
|
||||
|
||||
bool DockDaemonDBusAdaptor::IsDocked(const QString &desktopFile)
|
||||
{
|
||||
return TaskManager::instance()->isDocked(desktopFile);
|
||||
}
|
||||
|
||||
bool DockDaemonDBusAdaptor::IsOnDock(const QString &desktopFile)
|
||||
{
|
||||
return TaskManager::instance()->isOnDock(desktopFile);
|
||||
}
|
||||
|
||||
void DockDaemonDBusAdaptor::MoveEntry(int index, int newIndex)
|
||||
{
|
||||
TaskManager::instance()->moveEntry(index, newIndex);
|
||||
}
|
||||
|
||||
QString DockDaemonDBusAdaptor::QueryWindowIdentifyMethod(uint win)
|
||||
{
|
||||
return TaskManager::instance()->queryWindowIdentifyMethod(win);
|
||||
}
|
||||
|
||||
QStringList DockDaemonDBusAdaptor::GetDockedAppsDesktopFiles()
|
||||
{
|
||||
return TaskManager::instance()->getDockedAppsDesktopFiles();
|
||||
}
|
||||
|
||||
QString DockDaemonDBusAdaptor::GetPluginSettings()
|
||||
{
|
||||
return TaskManager::instance()->getPluginSettings();
|
||||
}
|
||||
|
||||
void DockDaemonDBusAdaptor::SetPluginSettings(QString jsonStr)
|
||||
{
|
||||
TaskManager::instance()->setPluginSettings(jsonStr);
|
||||
}
|
||||
|
||||
void DockDaemonDBusAdaptor::MergePluginSettings(QString jsonStr)
|
||||
{
|
||||
TaskManager::instance()->mergePluginSettings(jsonStr);
|
||||
}
|
||||
|
||||
void DockDaemonDBusAdaptor::RemovePluginSettings(QString key1, QStringList key2List)
|
||||
{
|
||||
TaskManager::instance()->removePluginSettings(key1, key2List);
|
||||
}
|
||||
|
||||
bool DockDaemonDBusAdaptor::RequestDock(const QString &desktopFile, int index)
|
||||
{
|
||||
return TaskManager::instance()->requestDock(desktopFile, index);
|
||||
}
|
||||
|
||||
bool DockDaemonDBusAdaptor::RequestUndock(const QString &desktopFile)
|
||||
{
|
||||
return TaskManager::instance()->requestUndock(desktopFile);
|
||||
}
|
||||
|
||||
void DockDaemonDBusAdaptor::SetShowRecent(bool visible)
|
||||
{
|
||||
DockSettings::instance()->setShowRecent(visible);
|
||||
}
|
||||
|
||||
void DockDaemonDBusAdaptor::SetShowMultiWindow(bool showMultiWindow)
|
||||
{
|
||||
TaskManager::instance()->setShowMultiWindow(showMultiWindow);
|
||||
}
|
||||
|
||||
void DockDaemonDBusAdaptor::SetFrontendWindowRect(int x, int y, uint width, uint height)
|
||||
{
|
||||
TaskManager::instance()->setFrontendWindowRect(x, y, width, height);
|
||||
}
|
208
frame/dbus/dockdaemonadaptors.h
Normal file
208
frame/dbus/dockdaemonadaptors.h
Normal file
@ -0,0 +1,208 @@
|
||||
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "taskmanager/entry.h"
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QMetaObject>
|
||||
#include <QtCore/QVariant>
|
||||
#include <QtDBus/QtDBus>
|
||||
#include <QtCore/QByteArray>
|
||||
#include <QtCore/QList>
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QStringList>
|
||||
#include <QtCore/QVariant>
|
||||
#include <QDBusObjectPath>
|
||||
#include <QRect>
|
||||
|
||||
/*
|
||||
* Adaptor class for interface org.deepin.dde.daemon.Dock1
|
||||
*/
|
||||
|
||||
class Entry;
|
||||
class DockDaemonDBusAdaptor: public QDBusAbstractAdaptor
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_CLASSINFO("D-Bus Interface", "org.deepin.dde.daemon.Dock1")
|
||||
Q_CLASSINFO("D-Bus Introspection", ""
|
||||
" <interface name=\"org.deepin.dde.daemon.Dock1\">\n"
|
||||
" <method name=\"CloseWindow\">\n"
|
||||
" <arg direction=\"in\" type=\"u\" name=\"win\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"GetEntryIDs\">\n"
|
||||
" <arg direction=\"out\" type=\"as\" name=\"list\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"IsDocked\">\n"
|
||||
" <arg direction=\"in\" type=\"s\" name=\"desktopFile\"/>\n"
|
||||
" <arg direction=\"out\" type=\"b\" name=\"value\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"IsOnDock\">\n"
|
||||
" <arg direction=\"in\" type=\"s\" name=\"desktopFile\"/>\n"
|
||||
" <arg direction=\"out\" type=\"b\" name=\"value\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"MoveEntry\">\n"
|
||||
" <arg direction=\"in\" type=\"i\" name=\"index\"/>\n"
|
||||
" <arg direction=\"in\" type=\"i\" name=\"newIndex\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"QueryWindowIdentifyMethod\">\n"
|
||||
" <arg direction=\"in\" type=\"u\" name=\"win\"/>\n"
|
||||
" <arg direction=\"out\" type=\"s\" name=\"identifyMethod\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"GetDockedAppsDesktopFiles\">\n"
|
||||
" <arg direction=\"out\" type=\"as\" name=\"desktopFiles\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"GetPluginSettings\">\n"
|
||||
" <arg direction=\"out\" type=\"s\" name=\"jsonStr\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"SetPluginSettings\">\n"
|
||||
" <arg direction=\"in\" type=\"s\" name=\"jsonStr\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"MergePluginSettings\">\n"
|
||||
" <arg direction=\"in\" type=\"s\" name=\"jsonStr\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"RemovePluginSettings\">\n"
|
||||
" <arg direction=\"in\" type=\"s\" name=\"key1\"/>\n"
|
||||
" <arg direction=\"in\" type=\"as\" name=\"key2List\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"RequestDock\">\n"
|
||||
" <arg direction=\"in\" type=\"s\" name=\"desktopFile\"/>\n"
|
||||
" <arg direction=\"in\" type=\"i\" name=\"index\"/>\n"
|
||||
" <arg direction=\"out\" type=\"b\" name=\"ok\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"RequestUndock\">\n"
|
||||
" <arg direction=\"in\" type=\"s\" name=\"desktopFile\"/>\n"
|
||||
" <arg direction=\"out\" type=\"b\" name=\"ok\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"SetShowRecent\">\n"
|
||||
" <arg direction=\"in\" type=\"b\" name=\"visible\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"SetShowMultiWindow\">\n"
|
||||
" <arg direction=\"in\" type=\"b\" name=\"visible\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"SetFrontendWindowRect\">\n"
|
||||
" <arg direction=\"in\" type=\"i\" name=\"x\"/>\n"
|
||||
" <arg direction=\"in\" type=\"i\" name=\"y\"/>\n"
|
||||
" <arg direction=\"in\" type=\"u\" name=\"width\"/>\n"
|
||||
" <arg direction=\"in\" type=\"u\" name=\"height\"/>\n"
|
||||
" </method>\n"
|
||||
" <signal name=\"ServiceRestarted\"/>\n"
|
||||
" <signal name=\"EntryAdded\">\n"
|
||||
" <arg type=\"o\" name=\"path\"/>\n"
|
||||
" <arg type=\"i\" name=\"index\"/>\n"
|
||||
" </signal>\n"
|
||||
" <signal name=\"EntryRemoved\">\n"
|
||||
" <arg type=\"s\" name=\"entryId\"/>\n"
|
||||
" </signal>\n"
|
||||
" <property access=\"readwrite\" type=\"u\" name=\"ShowTimeout\"/>\n"
|
||||
" <property access=\"readwrite\" type=\"u\" name=\"HideTimeout\"/>\n"
|
||||
" <property access=\"readwrite\" type=\"u\" name=\"WindowSizeEfficient\"/>\n"
|
||||
" <property access=\"readwrite\" type=\"u\" name=\"WindowSizeFashion\"/>\n"
|
||||
" <property access=\"read\" type=\"u\" name=\"WindowMargin\"/>\n"
|
||||
" <property access=\"read\" type=\"(iiii)\" name=\"FrontendWindowRect\"/>\n"
|
||||
" <property access=\"readwrite\" type=\"i\" name=\"HideMode\"/>\n"
|
||||
" <property access=\"readwrite\" type=\"i\" name=\"DisplayMode\"/>\n"
|
||||
" <property access=\"read\" type=\"i\" name=\"HideState\"/>\n"
|
||||
" <property access=\"readwrite\" type=\"i\" name=\"Position\"/>\n"
|
||||
" <property access=\"readwrite\" type=\"u\" name=\"IconSize\"/>\n"
|
||||
" <property access=\"read\" type=\"as\" name=\"DockedApps\"/>\n"
|
||||
" <property access=\"read\" type=\"b\" name=\"ShowRecent\"/>\n"
|
||||
" <property access=\"read\" type=\"b\" name=\"ShowMultiWindow\"/>\n"
|
||||
" </interface>\n"
|
||||
"")
|
||||
public:
|
||||
DockDaemonDBusAdaptor(QObject *parent);
|
||||
virtual ~DockDaemonDBusAdaptor();
|
||||
|
||||
public: // PROPERTIES
|
||||
Q_PROPERTY(int DisplayMode READ displayMode WRITE setDisplayMode NOTIFY DisplayModeChanged)
|
||||
int displayMode() const;
|
||||
void setDisplayMode(int value);
|
||||
|
||||
Q_PROPERTY(QStringList DockedApps READ dockedApps NOTIFY DockedAppsChanged)
|
||||
QStringList dockedApps() const;
|
||||
|
||||
Q_PROPERTY(int HideMode READ hideMode WRITE setHideMode NOTIFY HideModeChanged)
|
||||
int hideMode() const;
|
||||
void setHideMode(int value);
|
||||
|
||||
Q_PROPERTY(int HideState READ hideState NOTIFY HideStateChanged)
|
||||
int hideState() const;
|
||||
|
||||
Q_PROPERTY(uint HideTimeout READ hideTimeout WRITE setHideTimeout NOTIFY HideTimeoutChanged)
|
||||
uint hideTimeout() const;
|
||||
void setHideTimeout(uint value);
|
||||
|
||||
Q_PROPERTY(uint WindowSizeEfficient READ windowSizeEfficient WRITE setWindowSizeEfficient NOTIFY WindowSizeEfficientChanged)
|
||||
uint windowSizeEfficient() const;
|
||||
void setWindowSizeEfficient(uint value);
|
||||
|
||||
Q_PROPERTY(uint WindowSizeFashion READ windowSizeFashion WRITE setWindowSizeFashion NOTIFY WindowSizeFashionChanged)
|
||||
uint windowSizeFashion() const;
|
||||
void setWindowSizeFashion(uint value);
|
||||
|
||||
Q_PROPERTY(uint WindowMargin READ windowMargin NOTIFY WindowMarginChanged)
|
||||
uint windowMargin() const;
|
||||
|
||||
Q_PROPERTY(QRect FrontendWindowRect READ frontendWindowRect NOTIFY FrontendWindowRectChanged)
|
||||
QRect frontendWindowRect() const;
|
||||
|
||||
Q_PROPERTY(uint IconSize READ iconSize WRITE setIconSize NOTIFY IconSizeChanged)
|
||||
uint iconSize() const;
|
||||
void setIconSize(uint value);
|
||||
|
||||
Q_PROPERTY(int Position READ position WRITE setPosition NOTIFY PositionChanged)
|
||||
int position() const;
|
||||
void setPosition(int value);
|
||||
|
||||
Q_PROPERTY(uint ShowTimeout READ showTimeout WRITE setShowTimeout NOTIFY ShowTimeoutChanged)
|
||||
uint showTimeout() const;
|
||||
void setShowTimeout(uint value);
|
||||
|
||||
Q_PROPERTY(bool ShowRecent READ showRecent NOTIFY showRecentChanged)
|
||||
bool showRecent() const;
|
||||
|
||||
Q_PROPERTY(bool ShowMultiWindow READ showMultiWindow NOTIFY ShowMultiWindowChanged)
|
||||
bool showMultiWindow() const;
|
||||
|
||||
public Q_SLOTS: // METHODS
|
||||
void CloseWindow(uint win);
|
||||
QStringList GetEntryIDs();
|
||||
bool IsDocked(const QString &desktopFile);
|
||||
bool IsOnDock(const QString &desktopFile);
|
||||
void MoveEntry(int index, int newIndex);
|
||||
QString QueryWindowIdentifyMethod(uint win);
|
||||
QStringList GetDockedAppsDesktopFiles();
|
||||
QString GetPluginSettings();
|
||||
void SetPluginSettings(QString jsonStr);
|
||||
void MergePluginSettings(QString jsonStr);
|
||||
void RemovePluginSettings(QString key1, QStringList key2List);
|
||||
bool RequestDock(const QString &desktopFile, int index);
|
||||
bool RequestUndock(const QString &desktopFile);
|
||||
void SetShowRecent(bool visible);
|
||||
void SetShowMultiWindow(bool showMultiWindow);
|
||||
void SetFrontendWindowRect(int x, int y, uint width, uint height);
|
||||
|
||||
Q_SIGNALS: // SIGNALS
|
||||
void ServiceRestarted();
|
||||
void EntryAdded(const Entry *entry, int index);
|
||||
void EntryRemoved(const QString &entryId);
|
||||
|
||||
void DisplayModeChanged(int value) const;
|
||||
void DockedAppsChanged(const QStringList &value) const;
|
||||
void EntriesChanged(const QList<QDBusObjectPath> &value) const;
|
||||
void FrontendWindowRectChanged(const QRect &dockRect) const;
|
||||
void HideModeChanged(int value) const;
|
||||
void HideStateChanged(int value) const;
|
||||
void HideTimeoutChanged(uint value) const;
|
||||
void IconSizeChanged(uint value) const;
|
||||
void PositionChanged(int value) const;
|
||||
void ShowTimeoutChanged(uint value) const;
|
||||
void WindowSizeEfficientChanged(uint value) const;
|
||||
void WindowSizeFashionChanged(uint value) const;
|
||||
void WindowMarginChanged(uint value) const;
|
||||
void showRecentChanged(bool) const;
|
||||
void ShowMultiWindowChanged(bool) const;
|
||||
};
|
@ -1,339 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: donghualin <donghualin@uniontech.com>
|
||||
*
|
||||
* Maintainer: donghualin <donghualin@uniontech.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dockinterface.h"
|
||||
|
||||
#include "org_deepin_dde_daemon_dock1.h"
|
||||
|
||||
// 因为 types/dockrect.h 文件中定义了DockRect类,而在此处也定义了DockRect,
|
||||
// 所以在此处先加上DOCKRECT_H宏(types/dockrect.h文件中定义的宏)来禁止包含types/dockrect.h头文件
|
||||
// 否则会出现重复定义的错误
|
||||
#define DOCKRECT_H
|
||||
|
||||
/*
|
||||
* Implementation of interface class __Dock
|
||||
*/
|
||||
|
||||
class DockPrivate
|
||||
{
|
||||
public:
|
||||
DockPrivate() = default;
|
||||
|
||||
// begin member variables
|
||||
int DisplayMode;
|
||||
QStringList DockedApps;
|
||||
QList<QDBusObjectPath> Entries;
|
||||
DockRect FrontendWindowRect;
|
||||
int HideMode;
|
||||
int HideState;
|
||||
uint HideTimeout;
|
||||
uint IconSize;
|
||||
double Opacity;
|
||||
int Position;
|
||||
uint ShowTimeout;
|
||||
uint WindowSize;
|
||||
uint WindowSizeEfficient;
|
||||
uint WindowSizeFashion;
|
||||
|
||||
public:
|
||||
QMap<QString, QDBusPendingCallWatcher *> m_processingCalls;
|
||||
QMap<QString, QList<QVariant>> m_waittingCalls;
|
||||
};
|
||||
|
||||
// 窗管中提供的ActiveWindow接口,MinimizeWindow目前还在开发过程中,因此,关于这两个接口暂时使用v23的后端接口
|
||||
// 等窗管完成了这几个接口后,删除此处v20的接口,改成v23提供的新接口即可
|
||||
using DockInter = org::deepin::dde::daemon::Dock1;
|
||||
/**
|
||||
* @brief 任务栏的部分DBUS接口是通过窗管获取的,由于AM后端并未提供窗管的相关接口,因此,
|
||||
* 此处先将窗管的接口集成进来,作为私有类,只提供任务栏接口使用
|
||||
*/
|
||||
class WM : public QDBusAbstractInterface
|
||||
{
|
||||
public:
|
||||
static inline const char *staticInterfaceName()
|
||||
{ return "com.deepin.wm"; }
|
||||
|
||||
public:
|
||||
explicit WM(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = Q_NULLPTR);
|
||||
~WM();
|
||||
|
||||
public Q_SLOTS: // METHODS
|
||||
|
||||
inline QDBusPendingReply<> ActivateWindow(uint in0)
|
||||
{
|
||||
return m_dockInter->ActivateWindow(in0);
|
||||
}
|
||||
|
||||
QDBusPendingReply<> MinimizeWindow(uint in0)
|
||||
{
|
||||
return m_dockInter->MinimizeWindow(in0);
|
||||
}
|
||||
|
||||
inline QDBusPendingReply<> CancelPreviewWindow()
|
||||
{
|
||||
return asyncCallWithArgumentList(QStringLiteral("CancelPreviewWindow"), QList<QVariant>());
|
||||
}
|
||||
|
||||
inline QDBusPendingReply<> PreviewWindow(uint in0)
|
||||
{
|
||||
QList<QVariant> argumentList;
|
||||
argumentList << QVariant::fromValue(in0);
|
||||
return asyncCallWithArgumentList(QStringLiteral("PreviewWindow"), argumentList);
|
||||
}
|
||||
|
||||
private:
|
||||
DockInter *m_dockInter;
|
||||
};
|
||||
|
||||
WM::WM(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)
|
||||
: QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)
|
||||
, m_dockInter(new DockInter("org.deepin.dde.daemon.Dock1", "/org/deepin/dde/daemon/Dock1", QDBusConnection::sessionBus(), this))
|
||||
{
|
||||
}
|
||||
|
||||
WM::~WM()
|
||||
{
|
||||
}
|
||||
|
||||
Dde_Dock::Dde_Dock(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)
|
||||
: QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)
|
||||
, d_ptr(new DockPrivate)
|
||||
, m_wm(new WM("com.deepin.wm", "/com/deepin/wm", QDBusConnection::sessionBus(), this))
|
||||
{
|
||||
QDBusConnection::sessionBus().connect(this->service(), this->path(),
|
||||
"org.freedesktop.DBus.Properties",
|
||||
"PropertiesChanged","sa{sv}as",
|
||||
this,
|
||||
SLOT(onPropertyChanged(const QDBusMessage &)));
|
||||
|
||||
if (QMetaType::type("DockRect") == QMetaType::UnknownType)
|
||||
registerDockRectMetaType();
|
||||
}
|
||||
|
||||
Dde_Dock::~Dde_Dock()
|
||||
{
|
||||
qDeleteAll(d_ptr->m_processingCalls.values());
|
||||
delete d_ptr;
|
||||
}
|
||||
|
||||
void Dde_Dock::onPropertyChanged(const QDBusMessage& msg)
|
||||
{
|
||||
QList<QVariant> arguments = msg.arguments();
|
||||
if (3 != arguments.count())
|
||||
return;
|
||||
|
||||
QString interfaceName = msg.arguments().at(0).toString();
|
||||
if (interfaceName != staticInterfaceName())
|
||||
return;
|
||||
|
||||
QVariantMap changedProps = qdbus_cast<QVariantMap>(arguments.at(1).value<QDBusArgument>());
|
||||
QStringList keys = changedProps.keys();
|
||||
foreach(const QString &prop, keys) {
|
||||
const QMetaObject* self = metaObject();
|
||||
for (int i=self->propertyOffset(); i < self->propertyCount(); ++i) {
|
||||
QMetaProperty p = self->property(i);
|
||||
if (p.name() == prop)
|
||||
Q_EMIT p.notifySignal().invoke(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int Dde_Dock::displayMode()
|
||||
{
|
||||
return qvariant_cast<int>(property("DisplayMode"));
|
||||
}
|
||||
|
||||
void Dde_Dock::setDisplayMode(int value)
|
||||
{
|
||||
setProperty("DisplayMode", QVariant::fromValue(value));
|
||||
}
|
||||
|
||||
QStringList Dde_Dock::dockedApps()
|
||||
{
|
||||
return qvariant_cast<QStringList>(property("DockedApps"));
|
||||
}
|
||||
|
||||
QList<QDBusObjectPath> Dde_Dock::entries()
|
||||
{
|
||||
return qvariant_cast<QList<QDBusObjectPath>>(property("Entries"));
|
||||
}
|
||||
|
||||
DockRect Dde_Dock::frontendWindowRect()
|
||||
{
|
||||
return qvariant_cast<DockRect>(property("FrontendWindowRect"));
|
||||
}
|
||||
|
||||
int Dde_Dock::hideMode()
|
||||
{
|
||||
return qvariant_cast<int>(property("HideMode"));
|
||||
}
|
||||
|
||||
void Dde_Dock::setHideMode(int value)
|
||||
{
|
||||
internalPropSet("HideMode", QVariant::fromValue(value));
|
||||
}
|
||||
|
||||
int Dde_Dock::hideState()
|
||||
{
|
||||
return qvariant_cast<int>(property("HideState"));
|
||||
}
|
||||
|
||||
uint Dde_Dock::hideTimeout()
|
||||
{
|
||||
return qvariant_cast<uint>(property("HideTimeout"));
|
||||
}
|
||||
|
||||
void Dde_Dock::setHideTimeout(uint value)
|
||||
{
|
||||
setProperty("HideTimeout", QVariant::fromValue(value));
|
||||
}
|
||||
|
||||
uint Dde_Dock::iconSize()
|
||||
{
|
||||
return qvariant_cast<uint>(property("IconSize"));
|
||||
}
|
||||
|
||||
void Dde_Dock::setIconSize(uint value)
|
||||
{
|
||||
setProperty("IconSize", QVariant::fromValue(value));
|
||||
}
|
||||
|
||||
double Dde_Dock::opacity()
|
||||
{
|
||||
return qvariant_cast<double>(property("Opacity"));
|
||||
}
|
||||
|
||||
void Dde_Dock::setOpacity(double value)
|
||||
{
|
||||
setProperty("Opacity", QVariant::fromValue(value));
|
||||
}
|
||||
|
||||
int Dde_Dock::position()
|
||||
{
|
||||
return qvariant_cast<int>(property("Position"));
|
||||
}
|
||||
|
||||
void Dde_Dock::setPosition(int value)
|
||||
{
|
||||
setProperty("Position", QVariant::fromValue(value));
|
||||
}
|
||||
|
||||
uint Dde_Dock::showTimeout()
|
||||
{
|
||||
return qvariant_cast<uint>(property("ShowTimeout"));
|
||||
}
|
||||
|
||||
void Dde_Dock::setShowTimeout(uint value)
|
||||
{
|
||||
setProperty("ShowTimeout", QVariant::fromValue(value));
|
||||
}
|
||||
|
||||
uint Dde_Dock::windowSize()
|
||||
{
|
||||
return qvariant_cast<uint>(property("WindowSize"));
|
||||
}
|
||||
|
||||
void Dde_Dock::setWindowSize(uint value)
|
||||
{
|
||||
setProperty("WindowSize", QVariant::fromValue(value));
|
||||
}
|
||||
|
||||
uint Dde_Dock::windowSizeEfficient()
|
||||
{
|
||||
return qvariant_cast<uint>(property("WindowSizeEfficient"));
|
||||
}
|
||||
|
||||
void Dde_Dock::setWindowSizeEfficient(uint value)
|
||||
{
|
||||
setProperty("WindowSizeEfficient", QVariant::fromValue(value));
|
||||
}
|
||||
|
||||
uint Dde_Dock::windowSizeFashion()
|
||||
{
|
||||
return qvariant_cast<uint>(property("WindowSizeFashion"));
|
||||
}
|
||||
|
||||
void Dde_Dock::setWindowSizeFashion(uint value)
|
||||
{
|
||||
setProperty("WindowSizeFashion", QVariant::fromValue(value));
|
||||
}
|
||||
|
||||
bool Dde_Dock::showRecent() const
|
||||
{
|
||||
return qvariant_cast<bool>(property("ShowRecent"));
|
||||
}
|
||||
|
||||
bool Dde_Dock::showMultiWindow() const
|
||||
{
|
||||
return qvariant_cast<bool>(property("ShowMultiWindow"));
|
||||
}
|
||||
|
||||
QDBusPendingReply<> Dde_Dock::ActivateWindow(uint in0)
|
||||
{
|
||||
return m_wm->ActivateWindow(in0);
|
||||
}
|
||||
|
||||
QDBusPendingReply<> Dde_Dock::PreviewWindow(uint in0)
|
||||
{
|
||||
return m_wm->PreviewWindow(in0);
|
||||
}
|
||||
|
||||
QDBusPendingReply<> Dde_Dock::CancelPreviewWindow()
|
||||
{
|
||||
return m_wm->CancelPreviewWindow();
|
||||
}
|
||||
|
||||
QDBusPendingReply<> Dde_Dock::MinimizeWindow(uint in0)
|
||||
{
|
||||
return m_wm->MinimizeWindow(in0);
|
||||
}
|
||||
|
||||
void Dde_Dock::CallQueued(const QString &callName, const QList<QVariant> &args)
|
||||
{
|
||||
if (d_ptr->m_waittingCalls.contains(callName)) {
|
||||
d_ptr->m_waittingCalls[callName] = args;
|
||||
return;
|
||||
}
|
||||
|
||||
if (d_ptr->m_processingCalls.contains(callName)) {
|
||||
d_ptr->m_waittingCalls.insert(callName, args);
|
||||
} else {
|
||||
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(asyncCallWithArgumentList(callName, args));
|
||||
connect(watcher, &QDBusPendingCallWatcher::finished, this, &Dde_Dock::onPendingCallFinished);
|
||||
d_ptr->m_processingCalls.insert(callName, watcher);
|
||||
}
|
||||
}
|
||||
|
||||
void Dde_Dock::onPendingCallFinished(QDBusPendingCallWatcher *w)
|
||||
{
|
||||
w->deleteLater();
|
||||
const auto callName = d_ptr->m_processingCalls.key(w);
|
||||
Q_ASSERT(!callName.isEmpty());
|
||||
if (callName.isEmpty())
|
||||
return;
|
||||
|
||||
d_ptr->m_processingCalls.remove(callName);
|
||||
if (!d_ptr->m_waittingCalls.contains(callName))
|
||||
return;
|
||||
|
||||
const auto args = d_ptr->m_waittingCalls.take(callName);
|
||||
CallQueued(callName, args);
|
||||
}
|
@ -1,338 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: donghualin <donghualin@uniontech.com>
|
||||
*
|
||||
* Maintainer: donghualin <donghualin@uniontech.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef DOCK_INTERFACE
|
||||
#define DOCK_INTERFACE
|
||||
|
||||
#include "types/dockrect.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QByteArray>
|
||||
#include <QList>
|
||||
#include <QMap>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QVariant>
|
||||
#include <QtDBus>
|
||||
|
||||
/*
|
||||
* Proxy class for interface org.deepin.dde.daemon.Dock1
|
||||
*/
|
||||
class DockPrivate;
|
||||
class WM;
|
||||
|
||||
void registerDockRectMetaType();
|
||||
|
||||
class Dde_Dock : public QDBusAbstractInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static inline const char *staticInterfaceName()
|
||||
{ return "org.deepin.dde.daemon.Dock1"; }
|
||||
|
||||
public:
|
||||
explicit Dde_Dock(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);
|
||||
|
||||
~Dde_Dock();
|
||||
|
||||
Q_PROPERTY(int DisplayMode READ displayMode WRITE setDisplayMode NOTIFY DisplayModeChanged)
|
||||
int displayMode();
|
||||
void setDisplayMode(int value);
|
||||
|
||||
Q_PROPERTY(QStringList DockedApps READ dockedApps NOTIFY DockedAppsChanged)
|
||||
QStringList dockedApps();
|
||||
|
||||
Q_PROPERTY(QList<QDBusObjectPath> Entries READ entries NOTIFY EntriesChanged)
|
||||
QList<QDBusObjectPath> entries();
|
||||
|
||||
Q_PROPERTY(DockRect FrontendWindowRect READ frontendWindowRect NOTIFY FrontendWindowRectChanged)
|
||||
DockRect frontendWindowRect();
|
||||
|
||||
Q_PROPERTY(int HideMode READ hideMode WRITE setHideMode NOTIFY HideModeChanged)
|
||||
int hideMode();
|
||||
void setHideMode(int value);
|
||||
|
||||
Q_PROPERTY(int HideState READ hideState NOTIFY HideStateChanged)
|
||||
int hideState();
|
||||
|
||||
Q_PROPERTY(uint HideTimeout READ hideTimeout WRITE setHideTimeout NOTIFY HideTimeoutChanged)
|
||||
uint hideTimeout();
|
||||
void setHideTimeout(uint value);
|
||||
|
||||
Q_PROPERTY(uint IconSize READ iconSize WRITE setIconSize NOTIFY IconSizeChanged)
|
||||
uint iconSize();
|
||||
void setIconSize(uint value);
|
||||
|
||||
Q_PROPERTY(double Opacity READ opacity WRITE setOpacity NOTIFY OpacityChanged)
|
||||
double opacity();
|
||||
void setOpacity(double value);
|
||||
|
||||
Q_PROPERTY(int Position READ position WRITE setPosition NOTIFY PositionChanged)
|
||||
int position();
|
||||
void setPosition(int value);
|
||||
|
||||
Q_PROPERTY(uint ShowTimeout READ showTimeout WRITE setShowTimeout NOTIFY ShowTimeoutChanged)
|
||||
uint showTimeout();
|
||||
void setShowTimeout(uint value);
|
||||
|
||||
Q_PROPERTY(uint WindowSize READ windowSize WRITE setWindowSize NOTIFY WindowSizeChanged)
|
||||
uint windowSize();
|
||||
void setWindowSize(uint value);
|
||||
|
||||
Q_PROPERTY(uint WindowSizeEfficient READ windowSizeEfficient WRITE setWindowSizeEfficient NOTIFY WindowSizeEfficientChanged)
|
||||
uint windowSizeEfficient();
|
||||
void setWindowSizeEfficient(uint value);
|
||||
|
||||
Q_PROPERTY(uint WindowSizeFashion READ windowSizeFashion WRITE setWindowSizeFashion NOTIFY WindowSizeFashionChanged)
|
||||
uint windowSizeFashion();
|
||||
void setWindowSizeFashion(uint value);
|
||||
|
||||
Q_PROPERTY(bool ShowRecent READ showRecent NOTIFY showRecentChanged)
|
||||
bool showRecent() const;
|
||||
|
||||
Q_PROPERTY(bool ShowMultiWindow READ showMultiWindow NOTIFY ShowMultiWindowChanged)
|
||||
bool showMultiWindow() const;
|
||||
|
||||
public Q_SLOTS: // METHODS
|
||||
QDBusPendingReply<> ActivateWindow(uint in0);
|
||||
|
||||
QDBusPendingReply<> PreviewWindow(uint in0);
|
||||
|
||||
QDBusPendingReply<> CancelPreviewWindow();
|
||||
|
||||
QDBusPendingReply<> MinimizeWindow(uint in0);
|
||||
|
||||
inline void ActivateWindowQueued(uint in0)
|
||||
{
|
||||
QList<QVariant> argumentList;
|
||||
argumentList << QVariant::fromValue(in0);
|
||||
|
||||
CallQueued(QStringLiteral("ActivateWindow"), argumentList);
|
||||
}
|
||||
|
||||
inline QDBusPendingReply<> CloseWindow(uint in0)
|
||||
{
|
||||
QList<QVariant> argumentList;
|
||||
argumentList << QVariant::fromValue(in0);
|
||||
return asyncCallWithArgumentList(QStringLiteral("CloseWindow"), argumentList);
|
||||
}
|
||||
|
||||
inline void CloseWindowQueued(uint in0)
|
||||
{
|
||||
QList<QVariant> argumentList;
|
||||
argumentList << QVariant::fromValue(in0);
|
||||
|
||||
CallQueued(QStringLiteral("CloseWindow"), argumentList);
|
||||
}
|
||||
|
||||
inline QDBusPendingReply<QStringList> GetDockedAppsDesktopFiles()
|
||||
{
|
||||
QList<QVariant> argumentList;
|
||||
return asyncCallWithArgumentList(QStringLiteral("GetDockedAppsDesktopFiles"), argumentList);
|
||||
}
|
||||
|
||||
inline QDBusPendingReply<QStringList> GetEntryIDs()
|
||||
{
|
||||
QList<QVariant> argumentList;
|
||||
return asyncCallWithArgumentList(QStringLiteral("GetEntryIDs"), argumentList);
|
||||
}
|
||||
|
||||
inline QDBusPendingReply<QString> GetPluginSettings()
|
||||
{
|
||||
QList<QVariant> argumentList;
|
||||
return asyncCallWithArgumentList(QStringLiteral("GetPluginSettings"), argumentList);
|
||||
}
|
||||
|
||||
inline QDBusPendingReply<bool> IsDocked(const QString &in0)
|
||||
{
|
||||
QList<QVariant> argumentList;
|
||||
argumentList << QVariant::fromValue(in0);
|
||||
return asyncCallWithArgumentList(QStringLiteral("IsDocked"), argumentList);
|
||||
}
|
||||
|
||||
inline QDBusPendingReply<bool> IsOnDock(const QString &in0)
|
||||
{
|
||||
QList<QVariant> argumentList;
|
||||
argumentList << QVariant::fromValue(in0);
|
||||
return asyncCallWithArgumentList(QStringLiteral("IsOnDock"), argumentList);
|
||||
}
|
||||
|
||||
inline QDBusPendingReply<> MergePluginSettings(const QString &in0)
|
||||
{
|
||||
QList<QVariant> argumentList;
|
||||
argumentList << QVariant::fromValue(in0);
|
||||
return asyncCallWithArgumentList(QStringLiteral("MergePluginSettings"), argumentList);
|
||||
}
|
||||
|
||||
inline void MergePluginSettingsQueued(const QString &in0)
|
||||
{
|
||||
QList<QVariant> argumentList;
|
||||
argumentList << QVariant::fromValue(in0);
|
||||
|
||||
CallQueued(QStringLiteral("MergePluginSettings"), argumentList);
|
||||
}
|
||||
|
||||
inline QDBusPendingReply<> MoveEntry(int in0, int in1)
|
||||
{
|
||||
QList<QVariant> argumentList;
|
||||
argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1);
|
||||
return asyncCallWithArgumentList(QStringLiteral("MoveEntry"), argumentList);
|
||||
}
|
||||
|
||||
inline void MoveEntryQueued(int in0, int in1)
|
||||
{
|
||||
QList<QVariant> argumentList;
|
||||
argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1);
|
||||
|
||||
CallQueued(QStringLiteral("MoveEntry"), argumentList);
|
||||
}
|
||||
|
||||
inline void MoveWindowQueued(uint in0)
|
||||
{
|
||||
QList<QVariant> argumentList;
|
||||
argumentList << QVariant::fromValue(in0);
|
||||
|
||||
CallQueued(QStringLiteral("MoveWindow"), argumentList);
|
||||
}
|
||||
|
||||
inline QDBusPendingReply<QString> QueryWindowIdentifyMethod(uint in0)
|
||||
{
|
||||
QList<QVariant> argumentList;
|
||||
argumentList << QVariant::fromValue(in0);
|
||||
return asyncCallWithArgumentList(QStringLiteral("QueryWindowIdentifyMethod"), argumentList);
|
||||
}
|
||||
|
||||
inline QDBusPendingReply<> RemovePluginSettings(const QString &in0, const QStringList &in1)
|
||||
{
|
||||
QList<QVariant> argumentList;
|
||||
argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1);
|
||||
return asyncCallWithArgumentList(QStringLiteral("RemovePluginSettings"), argumentList);
|
||||
}
|
||||
|
||||
inline void RemovePluginSettingsQueued(const QString &in0, const QStringList &in1)
|
||||
{
|
||||
QList<QVariant> argumentList;
|
||||
argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1);
|
||||
|
||||
CallQueued(QStringLiteral("RemovePluginSettings"), argumentList);
|
||||
}
|
||||
|
||||
inline QDBusPendingReply<bool> RequestDock(const QString &in0, int in1)
|
||||
{
|
||||
QList<QVariant> argumentList;
|
||||
argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1);
|
||||
return asyncCallWithArgumentList(QStringLiteral("RequestDock"), argumentList);
|
||||
}
|
||||
|
||||
inline QDBusPendingReply<bool> RequestUndock(const QString &in0)
|
||||
{
|
||||
QList<QVariant> argumentList;
|
||||
argumentList << QVariant::fromValue(in0);
|
||||
return asyncCallWithArgumentList(QStringLiteral("RequestUndock"), argumentList);
|
||||
}
|
||||
|
||||
inline void SetShowRecent(bool in0)
|
||||
{
|
||||
QList<QVariant> argumentList;
|
||||
argumentList << QVariant::fromValue(in0);
|
||||
|
||||
CallQueued(QStringLiteral("SetShowRecent"), argumentList);
|
||||
}
|
||||
|
||||
inline QDBusPendingReply<> SetFrontendWindowRect(int in0, int in1, uint in2, uint in3)
|
||||
{
|
||||
QList<QVariant> argumentList;
|
||||
argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1) << QVariant::fromValue(in2) << QVariant::fromValue(in3);
|
||||
return asyncCallWithArgumentList(QStringLiteral("SetFrontendWindowRect"), argumentList);
|
||||
}
|
||||
|
||||
inline void SetFrontendWindowRectQueued(int in0, int in1, uint in2, uint in3)
|
||||
{
|
||||
QList<QVariant> argumentList;
|
||||
argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1) << QVariant::fromValue(in2) << QVariant::fromValue(in3);
|
||||
|
||||
CallQueued(QStringLiteral("SetFrontendWindowRect"), argumentList);
|
||||
}
|
||||
|
||||
inline QDBusPendingReply<> SetPluginSettings(const QString &in0)
|
||||
{
|
||||
QList<QVariant> argumentList;
|
||||
argumentList << QVariant::fromValue(in0);
|
||||
return asyncCallWithArgumentList(QStringLiteral("SetPluginSettings"), argumentList);
|
||||
}
|
||||
|
||||
inline void SetPluginSettingsQueued(const QString &in0)
|
||||
{
|
||||
QList<QVariant> argumentList;
|
||||
argumentList << QVariant::fromValue(in0);
|
||||
|
||||
CallQueued(QStringLiteral("SetPluginSettings"), argumentList);
|
||||
}
|
||||
|
||||
Q_SIGNALS: // SIGNALS
|
||||
void DockAppSettingsSynced();
|
||||
void EntryAdded(const QDBusObjectPath &in0, int in1);
|
||||
void EntryRemoved(const QString &in0);
|
||||
void PluginSettingsSynced();
|
||||
void ServiceRestarted();
|
||||
// begin property changed signals
|
||||
void DisplayModeChanged(int value) const;
|
||||
void DockedAppsChanged(const QStringList &value) const;
|
||||
void EntriesChanged(const QList<QDBusObjectPath> &value) const;
|
||||
void FrontendWindowRectChanged(DockRect value) const;
|
||||
void HideModeChanged(int value) const;
|
||||
void HideStateChanged(int value) const;
|
||||
void HideTimeoutChanged(uint value) const;
|
||||
void IconSizeChanged(uint value) const;
|
||||
void OpacityChanged(double value) const;
|
||||
void PositionChanged(int value) const;
|
||||
void ShowTimeoutChanged(uint value) const;
|
||||
void WindowSizeChanged(uint value) const;
|
||||
void WindowSizeEfficientChanged(uint value) const;
|
||||
void WindowSizeFashionChanged(uint value) const;
|
||||
void showRecentChanged(bool) const;
|
||||
void ShowMultiWindowChanged(bool) const;
|
||||
|
||||
public Q_SLOTS:
|
||||
void CallQueued(const QString &callName, const QList<QVariant> &args);
|
||||
|
||||
private Q_SLOTS:
|
||||
void onPendingCallFinished(QDBusPendingCallWatcher *w);
|
||||
void onPropertyChanged(const QDBusMessage& msg);
|
||||
|
||||
private:
|
||||
DockPrivate *d_ptr;
|
||||
WM *m_wm;
|
||||
};
|
||||
|
||||
namespace org {
|
||||
namespace deepin {
|
||||
namespace dde {
|
||||
namespace daemon {
|
||||
typedef ::Dde_Dock DdeDock;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif // DOCK_INTERFACE
|
@ -1,295 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: donghualin <donghualin@uniontech.com>
|
||||
*
|
||||
* Maintainer: donghualin <donghualin@uniontech.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "entryinterface.h"
|
||||
|
||||
/*
|
||||
* Implementation of interface class __Entry
|
||||
*/
|
||||
void registerWindowListMetaType()
|
||||
{
|
||||
qRegisterMetaType<WindowList>();
|
||||
qDBusRegisterMetaType<WindowList>();
|
||||
}
|
||||
|
||||
void registerWindowInfoMapMetaType()
|
||||
{
|
||||
registerWindowInfoMetaType();
|
||||
|
||||
qRegisterMetaType<WindowInfoMap>("WindowInfoMap");
|
||||
qDBusRegisterMetaType<WindowInfoMap>();
|
||||
}
|
||||
|
||||
void registerWindowInfoMetaType()
|
||||
{
|
||||
qRegisterMetaType<WindowInfo>("WindowInfo");
|
||||
qDBusRegisterMetaType<WindowInfo>();
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug argument, const WindowInfo &info)
|
||||
{
|
||||
argument << '(' << info.title << ',' << info.attention << info.uuid << ')';
|
||||
|
||||
return argument;
|
||||
}
|
||||
|
||||
QDBusArgument &operator<<(QDBusArgument &argument, const WindowInfo &info)
|
||||
{
|
||||
argument.beginStructure();
|
||||
argument << info.title << info.attention << info.uuid;
|
||||
argument.endStructure();
|
||||
|
||||
return argument;
|
||||
}
|
||||
|
||||
const QDBusArgument &operator>>(const QDBusArgument &argument, WindowInfo &info)
|
||||
{
|
||||
argument.beginStructure();
|
||||
argument >> info.title >> info.attention >> info.uuid;
|
||||
argument.endStructure();
|
||||
|
||||
return argument;
|
||||
}
|
||||
|
||||
bool WindowInfo::operator==(const WindowInfo &rhs) const
|
||||
{
|
||||
return (attention == rhs.attention &&
|
||||
title == rhs.title &&
|
||||
uuid == rhs.uuid);
|
||||
}
|
||||
|
||||
class EntryPrivate
|
||||
{
|
||||
public:
|
||||
EntryPrivate()
|
||||
: CurrentWindow(0)
|
||||
, IsActive(false)
|
||||
, IsDocked(false)
|
||||
, mode(0)
|
||||
{}
|
||||
|
||||
// begin member variables
|
||||
uint CurrentWindow;
|
||||
QString DesktopFile;
|
||||
QString Icon;
|
||||
QString Id;
|
||||
bool IsActive;
|
||||
bool IsDocked;
|
||||
QString Menu;
|
||||
QString Name;
|
||||
|
||||
WindowInfoMap WindowInfos;
|
||||
int mode;
|
||||
|
||||
public:
|
||||
QMap<QString, QDBusPendingCallWatcher *> m_processingCalls;
|
||||
QMap<QString, QList<QVariant>> m_waittingCalls;
|
||||
};
|
||||
|
||||
Dock_Entry::Dock_Entry(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)
|
||||
: QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)
|
||||
, d_ptr(new EntryPrivate)
|
||||
{
|
||||
QDBusConnection::sessionBus().connect(this->service(), this->path(),
|
||||
"org.freedesktop.DBus.Properties",
|
||||
"PropertiesChanged","sa{sv}as",
|
||||
this,
|
||||
SLOT(onPropertyChanged(const QDBusMessage &)));
|
||||
|
||||
if (QMetaType::type("WindowList") == QMetaType::UnknownType)
|
||||
registerWindowListMetaType();
|
||||
if (QMetaType::type("WindowInfoMap") == QMetaType::UnknownType)
|
||||
registerWindowInfoMapMetaType();
|
||||
}
|
||||
|
||||
Dock_Entry::~Dock_Entry()
|
||||
{
|
||||
qDeleteAll(d_ptr->m_processingCalls.values());
|
||||
delete d_ptr;
|
||||
}
|
||||
|
||||
void Dock_Entry::onPropertyChanged(const QString &propName, const QVariant &value)
|
||||
{
|
||||
if (propName == QStringLiteral("CurrentWindow")) {
|
||||
const uint &CurrentWindow = qvariant_cast<uint>(value);
|
||||
if (d_ptr->CurrentWindow != CurrentWindow) {
|
||||
d_ptr->CurrentWindow = CurrentWindow;
|
||||
Q_EMIT CurrentWindowChanged(d_ptr->CurrentWindow);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (propName == QStringLiteral("DesktopFile")) {
|
||||
const QString &DesktopFile = qvariant_cast<QString>(value);
|
||||
if (d_ptr->DesktopFile != DesktopFile) {
|
||||
d_ptr->DesktopFile = DesktopFile;
|
||||
Q_EMIT DesktopFileChanged(d_ptr->DesktopFile);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (propName == QStringLiteral("Icon")) {
|
||||
const QString &Icon = qvariant_cast<QString>(value);
|
||||
if (d_ptr->Icon != Icon)
|
||||
{
|
||||
d_ptr->Icon = Icon;
|
||||
Q_EMIT IconChanged(d_ptr->Icon);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (propName == QStringLiteral("IsActive")) {
|
||||
const bool &IsActive = qvariant_cast<bool>(value);
|
||||
if (d_ptr->IsActive != IsActive) {
|
||||
d_ptr->IsActive = IsActive;
|
||||
Q_EMIT IsActiveChanged(d_ptr->IsActive);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (propName == QStringLiteral("IsDocked")) {
|
||||
const bool &IsDocked = qvariant_cast<bool>(value);
|
||||
if (d_ptr->IsDocked != IsDocked) {
|
||||
d_ptr->IsDocked = IsDocked;
|
||||
Q_EMIT IsDockedChanged(d_ptr->IsDocked);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (propName == QStringLiteral("Menu")) {
|
||||
const QString &Menu = qvariant_cast<QString>(value);
|
||||
if (d_ptr->Menu != Menu) {
|
||||
d_ptr->Menu = Menu;
|
||||
Q_EMIT MenuChanged(d_ptr->Menu);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (propName == QStringLiteral("Name")) {
|
||||
const QString &Name = qvariant_cast<QString>(value);
|
||||
if (d_ptr->Name != Name) {
|
||||
d_ptr->Name = Name;
|
||||
Q_EMIT NameChanged(d_ptr->Name);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (propName == QStringLiteral("WindowInfos")) {
|
||||
const WindowInfoMap &WindowInfos = qvariant_cast<WindowInfoMap>(value);
|
||||
if (d_ptr->WindowInfos != WindowInfos) {
|
||||
d_ptr->WindowInfos = WindowInfos;
|
||||
Q_EMIT WindowInfosChanged(d_ptr->WindowInfos);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (propName == QStringLiteral("Mode")) {
|
||||
const int mode = qvariant_cast<int>(value);
|
||||
if (d_ptr->mode != mode) {
|
||||
d_ptr->mode = mode;
|
||||
Q_EMIT ModeChanged(d_ptr->mode);
|
||||
}
|
||||
}
|
||||
|
||||
qWarning() << "property not handle: " << propName;
|
||||
return;
|
||||
}
|
||||
|
||||
uint Dock_Entry::currentWindow()
|
||||
{
|
||||
return qvariant_cast<uint>(property("CurrentWindow"));
|
||||
}
|
||||
|
||||
QString Dock_Entry::desktopFile()
|
||||
{
|
||||
return qvariant_cast<QString>(property("DesktopFile"));
|
||||
}
|
||||
|
||||
QString Dock_Entry::icon()
|
||||
{
|
||||
return qvariant_cast<QString>(property("Icon"));
|
||||
}
|
||||
|
||||
QString Dock_Entry::id()
|
||||
{
|
||||
return qvariant_cast<QString>(property("Id"));
|
||||
}
|
||||
|
||||
bool Dock_Entry::isActive()
|
||||
{
|
||||
return qvariant_cast<bool>(property("IsActive"));
|
||||
}
|
||||
|
||||
bool Dock_Entry::isDocked()
|
||||
{
|
||||
return qvariant_cast<bool>(property("IsDocked"));
|
||||
}
|
||||
|
||||
int Dock_Entry::mode() const
|
||||
{
|
||||
return qvariant_cast<int>(property("Mode"));
|
||||
}
|
||||
|
||||
QString Dock_Entry::menu()
|
||||
{
|
||||
return qvariant_cast<QString>(property("Menu"));
|
||||
}
|
||||
|
||||
QString Dock_Entry::name()
|
||||
{
|
||||
return qvariant_cast<QString>(property("Name"));
|
||||
}
|
||||
|
||||
WindowInfoMap Dock_Entry::windowInfos()
|
||||
{
|
||||
return qvariant_cast<WindowInfoMap>(property("WindowInfos"));
|
||||
}
|
||||
|
||||
void Dock_Entry::CallQueued(const QString &callName, const QList<QVariant> &args)
|
||||
{
|
||||
if (d_ptr->m_waittingCalls.contains(callName)) {
|
||||
d_ptr->m_waittingCalls[callName] = args;
|
||||
return;
|
||||
}
|
||||
if (d_ptr->m_processingCalls.contains(callName)) {
|
||||
d_ptr->m_waittingCalls.insert(callName, args);
|
||||
} else {
|
||||
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(asyncCallWithArgumentList(callName, args));
|
||||
connect(watcher, &QDBusPendingCallWatcher::finished, this, &Dock_Entry::onPendingCallFinished);
|
||||
d_ptr->m_processingCalls.insert(callName, watcher);
|
||||
}
|
||||
}
|
||||
|
||||
void Dock_Entry::onPendingCallFinished(QDBusPendingCallWatcher *w)
|
||||
{
|
||||
w->deleteLater();
|
||||
const auto callName = d_ptr->m_processingCalls.key(w);
|
||||
Q_ASSERT(!callName.isEmpty());
|
||||
if (callName.isEmpty())
|
||||
return;
|
||||
|
||||
d_ptr->m_processingCalls.remove(callName);
|
||||
if (!d_ptr->m_waittingCalls.contains(callName))
|
||||
return;
|
||||
|
||||
const auto args = d_ptr->m_waittingCalls.take(callName);
|
||||
CallQueued(callName, args);
|
||||
}
|
@ -1,282 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd.
|
||||
*
|
||||
* Author: donghualin <donghualin@uniontech.com>
|
||||
*
|
||||
* Maintainer: donghualin <donghualin@uniontech.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef DOCK_ENTRY_H
|
||||
#define DOCK_ENTRY_H
|
||||
|
||||
#define WINDOWLIST_H
|
||||
#define WINDOWINFOLIST_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QByteArray>
|
||||
#include <QList>
|
||||
#include <QMap>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QVariant>
|
||||
#include <DDBusExtendedAbstractInterface>
|
||||
#include <QtDBus>
|
||||
|
||||
typedef QList<quint32> WindowList;
|
||||
|
||||
void registerWindowListMetaType();
|
||||
|
||||
class WindowInfo
|
||||
{
|
||||
public:
|
||||
friend QDebug operator<<(QDebug argument, const WindowInfo &info);
|
||||
friend QDBusArgument &operator<<(QDBusArgument &argument, const WindowInfo &info);
|
||||
friend const QDBusArgument &operator>>(const QDBusArgument &argument, WindowInfo &info);
|
||||
|
||||
bool operator==(const WindowInfo &rhs) const;
|
||||
|
||||
public:
|
||||
bool attention;
|
||||
QString title;
|
||||
QString uuid;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(WindowInfo)
|
||||
|
||||
typedef QMap<quint32, WindowInfo> WindowInfoMap;
|
||||
Q_DECLARE_METATYPE(WindowInfoMap)
|
||||
|
||||
void registerWindowInfoMetaType();
|
||||
void registerWindowInfoMapMetaType();
|
||||
|
||||
/*
|
||||
* Proxy class for interface org.deepin.dde.daemon.Dock1.Entry
|
||||
*/
|
||||
class EntryPrivate;
|
||||
|
||||
class Dock_Entry : public QDBusAbstractInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static inline const char *staticInterfaceName()
|
||||
{ return "org.deepin.dde.daemon.Dock1.Entry"; }
|
||||
|
||||
public:
|
||||
explicit Dock_Entry(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);
|
||||
|
||||
~Dock_Entry();
|
||||
|
||||
Q_PROPERTY(uint CurrentWindow READ currentWindow NOTIFY CurrentWindowChanged)
|
||||
uint currentWindow();
|
||||
|
||||
Q_PROPERTY(QString DesktopFile READ desktopFile NOTIFY DesktopFileChanged)
|
||||
QString desktopFile();
|
||||
|
||||
Q_PROPERTY(QString Icon READ icon NOTIFY IconChanged)
|
||||
QString icon();
|
||||
|
||||
Q_PROPERTY(QString Id READ id)
|
||||
QString id();
|
||||
|
||||
Q_PROPERTY(bool IsActive READ isActive NOTIFY IsActiveChanged)
|
||||
bool isActive();
|
||||
|
||||
Q_PROPERTY(bool IsDocked READ isDocked NOTIFY IsDockedChanged)
|
||||
bool isDocked();
|
||||
|
||||
Q_PROPERTY(QString Menu READ menu NOTIFY MenuChanged)
|
||||
QString menu();
|
||||
|
||||
Q_PROPERTY(QString Name READ name NOTIFY NameChanged)
|
||||
QString name();
|
||||
|
||||
Q_PROPERTY(WindowInfoMap WindowInfos READ windowInfos NOTIFY WindowInfosChanged)
|
||||
WindowInfoMap windowInfos();
|
||||
|
||||
Q_PROPERTY(int Mode READ mode NOTIFY ModeChanged)
|
||||
int mode() const;
|
||||
|
||||
public Q_SLOTS: // METHODS
|
||||
inline QDBusPendingReply<> Activate(uint in0)
|
||||
{
|
||||
QList<QVariant> argumentList;
|
||||
argumentList << QVariant::fromValue(in0);
|
||||
return asyncCallWithArgumentList(QStringLiteral("Activate"), argumentList);
|
||||
}
|
||||
|
||||
inline void ActivateQueued(uint in0)
|
||||
{
|
||||
QList<QVariant> argumentList;
|
||||
argumentList << QVariant::fromValue(in0);
|
||||
CallQueued(QStringLiteral("Activate"), argumentList);
|
||||
}
|
||||
|
||||
inline QDBusPendingReply<> Check()
|
||||
{
|
||||
QList<QVariant> argumentList;
|
||||
return asyncCallWithArgumentList(QStringLiteral("Check"), argumentList);
|
||||
}
|
||||
|
||||
inline void CheckQueued()
|
||||
{
|
||||
QList<QVariant> argumentList;
|
||||
CallQueued(QStringLiteral("Check"), argumentList);
|
||||
}
|
||||
|
||||
inline QDBusPendingReply<> ForceQuit()
|
||||
{
|
||||
QList<QVariant> argumentList;
|
||||
return asyncCallWithArgumentList(QStringLiteral("ForceQuit"), argumentList);
|
||||
}
|
||||
|
||||
inline QDBusPendingReply<> ActiveWindow(quint32 in0)
|
||||
{
|
||||
QList<QVariant> argumentList;
|
||||
argumentList << in0;
|
||||
return asyncCallWithArgumentList(QStringLiteral("ActiveWindow"), argumentList);
|
||||
}
|
||||
|
||||
inline void ForceQuitQueued()
|
||||
{
|
||||
QList<QVariant> argumentList;
|
||||
CallQueued(QStringLiteral("ForceQuit"), argumentList);
|
||||
}
|
||||
|
||||
inline QDBusPendingReply<WindowList> GetAllowedCloseWindows()
|
||||
{
|
||||
QList<QVariant> argumentList;
|
||||
return asyncCallWithArgumentList(QStringLiteral("GetAllowedCloseWindows"), argumentList);
|
||||
}
|
||||
|
||||
inline QDBusPendingReply<> HandleDragDrop(uint in0, const QStringList &in1)
|
||||
{
|
||||
QList<QVariant> argumentList;
|
||||
argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1);
|
||||
return asyncCallWithArgumentList(QStringLiteral("HandleDragDrop"), argumentList);
|
||||
}
|
||||
|
||||
inline void HandleDragDropQueued(uint in0, const QStringList &in1)
|
||||
{
|
||||
QList<QVariant> argumentList;
|
||||
argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1);
|
||||
CallQueued(QStringLiteral("HandleDragDrop"), argumentList);
|
||||
}
|
||||
|
||||
inline QDBusPendingReply<> HandleMenuItem(uint in0, const QString &in1)
|
||||
{
|
||||
QList<QVariant> argumentList;
|
||||
argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1);
|
||||
return asyncCallWithArgumentList(QStringLiteral("HandleMenuItem"), argumentList);
|
||||
}
|
||||
|
||||
inline void HandleMenuItemQueued(uint in0, const QString &in1)
|
||||
{
|
||||
QList<QVariant> argumentList;
|
||||
argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1);
|
||||
CallQueued(QStringLiteral("HandleMenuItem"), argumentList);
|
||||
}
|
||||
|
||||
inline QDBusPendingReply<> NewInstance(uint in0)
|
||||
{
|
||||
QList<QVariant> argumentList;
|
||||
argumentList << QVariant::fromValue(in0);
|
||||
return asyncCallWithArgumentList(QStringLiteral("NewInstance"), argumentList);
|
||||
}
|
||||
|
||||
inline void NewInstanceQueued(uint in0)
|
||||
{
|
||||
QList<QVariant> argumentList;
|
||||
argumentList << QVariant::fromValue(in0);
|
||||
CallQueued(QStringLiteral("NewInstance"), argumentList);
|
||||
}
|
||||
|
||||
inline QDBusPendingReply<> PresentWindows()
|
||||
{
|
||||
QList<QVariant> argumentList;
|
||||
return asyncCallWithArgumentList(QStringLiteral("PresentWindows"), argumentList);
|
||||
}
|
||||
|
||||
inline void PresentWindowsQueued()
|
||||
{
|
||||
QList<QVariant> argumentList;
|
||||
CallQueued(QStringLiteral("PresentWindows"), argumentList);
|
||||
}
|
||||
|
||||
inline QDBusPendingReply<> RequestDock()
|
||||
{
|
||||
QList<QVariant> argumentList;
|
||||
return asyncCallWithArgumentList(QStringLiteral("RequestDock"), argumentList);
|
||||
}
|
||||
|
||||
inline void RequestDockQueued()
|
||||
{
|
||||
QList<QVariant> argumentList;
|
||||
CallQueued(QStringLiteral("RequestDock"), argumentList);
|
||||
}
|
||||
|
||||
inline QDBusPendingReply<> RequestUndock()
|
||||
{
|
||||
QList<QVariant> argumentList;
|
||||
return asyncCallWithArgumentList(QStringLiteral("RequestUndock"), argumentList);
|
||||
}
|
||||
|
||||
inline void RequestUndockQueued()
|
||||
{
|
||||
QList<QVariant> argumentList;
|
||||
CallQueued(QStringLiteral("RequestUndock"), argumentList);
|
||||
}
|
||||
|
||||
Q_SIGNALS: // SIGNALS
|
||||
// begin property changed signals
|
||||
void IsActiveChanged(bool value) const;
|
||||
void IsDockedChanged(bool value) const;
|
||||
void MenuChanged(const QString &value) const;
|
||||
void IconChanged(const QString &value) const;
|
||||
void NameChanged(const QString &value) const;
|
||||
void DesktopFileChanged(const QString &value) const;
|
||||
void CurrentWindowChanged(uint32_t value) const;
|
||||
|
||||
void WindowInfosChanged(WindowInfoMap value) const;
|
||||
void ModeChanged(int value) const;
|
||||
|
||||
private:
|
||||
QVariant asyncProperty(const QString &propertyName);
|
||||
|
||||
public Q_SLOTS:
|
||||
void CallQueued(const QString &callName, const QList<QVariant> &args);
|
||||
|
||||
private Q_SLOTS:
|
||||
void onPendingCallFinished(QDBusPendingCallWatcher *w);
|
||||
void onPropertyChanged(const QString &propName, const QVariant &value);
|
||||
|
||||
private:
|
||||
EntryPrivate *d_ptr;
|
||||
};
|
||||
|
||||
namespace org {
|
||||
namespace deepin {
|
||||
namespace dde {
|
||||
namespace daemon {
|
||||
namespace dock {
|
||||
typedef ::Dock_Entry DockEntry;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // DOCK_ENTRY_H
|
@ -1,31 +0,0 @@
|
||||
<interface name="org.deepin.dde.daemon.Dock1">
|
||||
<method name="ActivateWindow">
|
||||
<arg type="u" direction="in"></arg>
|
||||
</method>
|
||||
<method name="CloseWindow">
|
||||
<arg type="u" direction="in"></arg>
|
||||
</method>
|
||||
<method name="GetEntryIDs">
|
||||
<arg type="as" direction="out"></arg>
|
||||
</method>
|
||||
<method name="ReorderEntries">
|
||||
<arg type="as" direction="in"></arg>
|
||||
</method>
|
||||
<method name="SetFrontendWindow">
|
||||
<arg type="u" direction="in"></arg>
|
||||
</method>
|
||||
<signal name="ServiceRestarted"></signal>
|
||||
<signal name="EntryAdded">
|
||||
<arg type="o"></arg>
|
||||
</signal>
|
||||
<signal name="EntryRemoved">
|
||||
<arg type="s"></arg>
|
||||
</signal>
|
||||
<property name="Entries" type="ao" access="read"></property>
|
||||
<property name="HideMode" type="i" access="readwrite"></property>
|
||||
<property name="DisplayMode" type="i" access="readwrite"></property>
|
||||
<property name="Position" type="i" access="readwrite"></property>
|
||||
<property name="ActiveWindow" type="u" access="read"></property>
|
||||
<property name="HideState" type="i" access="read"></property>
|
||||
</interface>
|
||||
|
@ -18,7 +18,6 @@ public:
|
||||
friend const QDBusArgument &operator>>(const QDBusArgument &arg, DockRect &rect);
|
||||
friend QDBusArgument &operator<<(QDBusArgument &arg, const DockRect &rect);
|
||||
|
||||
private:
|
||||
int x;
|
||||
int y;
|
||||
uint w;
|
||||
|
166
frame/dbusinterface/xml/com.deepin.wm.xml
Normal file
166
frame/dbusinterface/xml/com.deepin.wm.xml
Normal file
@ -0,0 +1,166 @@
|
||||
<interface name="com.deepin.wm">
|
||||
<property access="readwrite" type="b" name="compositingEnabled"/>
|
||||
<property access="read" type="b" name="compositingPossible"/>
|
||||
<property access="read" type="b" name="compositingAllowSwitch"/>
|
||||
<property access="readwrite" type="b" name="zoneEnabled"/>
|
||||
<property access="readwrite" type="s" name="cursorTheme"/>
|
||||
<property access="readwrite" type="i" name="cursorSize"/>
|
||||
<method name="SwitchApplication">
|
||||
<arg direction="in" type="b" name="backward"/>
|
||||
</method>
|
||||
<method name="TileActiveWindow">
|
||||
<arg direction="in" type="u" name="side"/>
|
||||
</method>
|
||||
<method name="BeginToMoveActiveWindow"/>
|
||||
<method name="ToggleActiveWindowMaximize"/>
|
||||
<method name="MinimizeActiveWindow"/>
|
||||
<method name="ShowWorkspace"/>
|
||||
<method name="ShowWindow"/>
|
||||
<method name="ShowAllWindow"/>
|
||||
<method name="PerformAction">
|
||||
<arg direction="in" type="i" name="type"/>
|
||||
</method>
|
||||
<method name="PreviewWindow">
|
||||
<arg direction="in" type="u" name="xid"/>
|
||||
</method>
|
||||
<method name="CancelPreviewWindow"/>
|
||||
<method name="GetCurrentWorkspaceBackground">
|
||||
<arg direction="out" type="s" name="result"/>
|
||||
</method>
|
||||
<method name="SetCurrentWorkspaceBackground">
|
||||
<arg direction="in" type="s" name="uri"/>
|
||||
</method>
|
||||
<method name="GetWorkspaceBackground">
|
||||
<arg direction="in" type="i" name="index"/>
|
||||
<arg direction="out" type="s" name="result"/>
|
||||
</method>
|
||||
<method name="SetWorkspaceBackground">
|
||||
<arg direction="in" type="i" name="index"/>
|
||||
<arg direction="in" type="s" name="uri"/>
|
||||
</method>
|
||||
<method name="SetTransientBackground">
|
||||
<arg direction="in" type="s"/>
|
||||
</method>
|
||||
<method name="GetCurrentWorkspaceBackgroundForMonitor">
|
||||
<arg direction="in" type="s" name="strMonitorName"/>
|
||||
<arg direction="out" type="s" name="result"/>
|
||||
</method>
|
||||
<method name="SetCurrentWorkspaceBackgroundForMonitor">
|
||||
<arg direction="in" type="s" name="uri"/>
|
||||
<arg direction="in" type="s" name="strMonitorName"/>
|
||||
</method>
|
||||
<method name="GetWorkspaceBackgroundForMonitor">
|
||||
<arg direction="in" type="i" name="index"/>
|
||||
<arg direction="in" type="s" name="strMonitorName"/>
|
||||
<arg direction="out" type="s" name="result"/>
|
||||
</method>
|
||||
<method name="SetWorkspaceBackgroundForMonitor">
|
||||
<arg direction="in" type="i" name="index"/>
|
||||
<arg direction="in" type="s" name="strMonitorName"/>
|
||||
<arg direction="in" type="s" name="uri"/>
|
||||
</method>
|
||||
<method name="SetTransientBackgroundForMonitor">
|
||||
<arg direction="in" type="s" name="uri"/>
|
||||
<arg direction="in" type="s" name="strMonitorName"/>
|
||||
</method>
|
||||
<method name="GetCurrentWorkspace">
|
||||
<arg direction="out" type="i" name="index"/>
|
||||
</method>
|
||||
<method name="WorkspaceCount">
|
||||
<arg direction="out" type="i" name="count"/>
|
||||
</method>
|
||||
<method name="SetCurrentWorkspace">
|
||||
<arg direction="in" type="i" name="index"/>
|
||||
</method>
|
||||
<method name="PreviousWorkspace"/>
|
||||
<method name="NextWorkspace"/>
|
||||
<method name="GetAllAccels">
|
||||
<arg direction="out" type="s" name="data"/>
|
||||
</method>
|
||||
<method name="GetAccel">
|
||||
<arg direction="in" type="s" name="id"/>
|
||||
<arg direction="out" type="as" name="data"/>
|
||||
</method>
|
||||
<method name="GetDefaultAccel">
|
||||
<arg direction="in" type="s" name="id"/>
|
||||
<arg direction="out" type="as" name="data"/>
|
||||
</method>
|
||||
<method name="SetAccel">
|
||||
<arg direction="in" type="s" name="data"/>
|
||||
<arg direction="out" type="b" name="result"/>
|
||||
</method>
|
||||
<method name="RemoveAccel">
|
||||
<arg direction="in" type="s" name="id"/>\
|
||||
</method>
|
||||
<method name="SetDecorationTheme">
|
||||
<arg direction="in" type="s" name="themeType"/>
|
||||
<arg direction="in" type="s" name="themeName"/>
|
||||
</method>
|
||||
<method name="SetDecorationDeepinTheme">
|
||||
<arg direction="in" type="s" name="deepinThemeName"/>
|
||||
</method>
|
||||
<signal name="WorkspaceBackgroundChanged">
|
||||
<arg type="i" name="index"/>
|
||||
<arg type="s" name="newUri"/>
|
||||
</signal>
|
||||
<signal name="WorkspaceBackgroundChangedForMonitor">
|
||||
<arg type="i" name="index"/>
|
||||
<arg type="s" name="strMonitorName"/>
|
||||
<arg type="s" name="uri"/>
|
||||
</signal>
|
||||
<signal name="compositingEnabledChanged">
|
||||
<arg type="b" name="enabled"/>
|
||||
</signal>
|
||||
<signal name="wmCompositingEnabledChanged">
|
||||
<arg type="b" name="enabled"/>
|
||||
</signal>
|
||||
<signal name="workspaceCountChanged">
|
||||
<arg type="i" name="count"/>
|
||||
</signal>
|
||||
<signal name="BeginToMoveActiveWindowChanged"/>
|
||||
<signal name="SwitchApplicationChanged">
|
||||
<arg type="b" name="backward"/>
|
||||
</signal>
|
||||
<signal name="TileActiveWindowChanged">
|
||||
<arg type="i" name="side"/>
|
||||
</signal>
|
||||
<signal name="ToggleActiveWindowMaximizeChanged"/>
|
||||
<signal name="ShowAllWindowChanged"/>
|
||||
<signal name="ShowWindowChanged"/>
|
||||
<signal name="ShowWorkspaceChanged"/>
|
||||
<signal name="ResumeCompositorChanged">
|
||||
<arg type="i" name="reason"/>
|
||||
</signal>
|
||||
<signal name="SuspendCompositorChanged">
|
||||
<arg type="i" name="reason"/>
|
||||
</signal>
|
||||
<method name="ChangeCurrentWorkspaceBackground">
|
||||
<arg direction="in" type="s" name="uri"/>
|
||||
</method>
|
||||
<method name="SwitchToWorkspace">
|
||||
<arg direction="in" type="b" name="backward"/>
|
||||
</method>
|
||||
<method name="PresentWindows">
|
||||
<arg direction="in" type="au" name="xids"/>
|
||||
<annotation value="QList<uint>" name="org.qtproject.QtDBus.QtTypeName.In0"/>
|
||||
</method>
|
||||
<method name="EnableZoneDetected">
|
||||
<arg direction="in" type="b" name="enabled"/>
|
||||
</method>
|
||||
<signal name="WorkspaceSwitched">
|
||||
<arg type="i" name="from"/>
|
||||
<arg type="i" name="to"/>
|
||||
</signal>
|
||||
<method name="GetMultiTaskingStatus">
|
||||
<arg direction="out" type="b" name="isActive"/>
|
||||
</method>
|
||||
<method name="SetMultiTaskingStatus">
|
||||
<arg direction="in" type="b" name="isActive"/>
|
||||
</method>
|
||||
<method name="GetIsShowDesktop">
|
||||
<arg direction="out" type="b" name="isShowDesktop"/>
|
||||
</method>
|
||||
<method name="SetShowDesktop">
|
||||
<arg direction="in" type="b" name="isShowDesktop"/>
|
||||
</method>
|
||||
</interface>
|
12
frame/dbusinterface/xml/org.deepin.dde.WMSwitcher1.xml
Normal file
12
frame/dbusinterface/xml/org.deepin.dde.WMSwitcher1.xml
Normal file
@ -0,0 +1,12 @@
|
||||
<interface name="org.deepin.dde.WMSwitcher1">
|
||||
<method name="AllowSwitch">
|
||||
<arg direction="out" type="b" name="outArg0"/>
|
||||
</method>
|
||||
<method name="CurrentWM">
|
||||
<arg direction="out" type="s" name="outArg0"/>
|
||||
</method>
|
||||
<method name="RequestSwitchWM"/>
|
||||
<signal name="WMChanged">
|
||||
<arg type="s" name="wmName"/>
|
||||
</signal>
|
||||
</interface>
|
@ -1,100 +0,0 @@
|
||||
<interface name="org.deepin.dde.daemon.Dock1">
|
||||
<method name="ActivateWindow">
|
||||
<arg type="u" direction="in"/>
|
||||
</method>
|
||||
<method name="CancelPreviewWindow"/>
|
||||
<method name="CloseWindow">
|
||||
<arg type="u" direction="in"/>
|
||||
</method>
|
||||
<method name="GetDockedAppsDesktopFiles">
|
||||
<arg type="as" direction="out"/>
|
||||
</method>
|
||||
<method name="GetEntryIDs">
|
||||
<arg type="as" direction="out"/>
|
||||
</method>
|
||||
<method name="GetPluginSettings">
|
||||
<arg type="s" direction="out"/>
|
||||
</method>
|
||||
<method name="IsDocked">
|
||||
<arg type="s" direction="in"/>
|
||||
<arg type="b" direction="out"/>
|
||||
</method>
|
||||
<method name="IsOnDock">
|
||||
<arg type="s" direction="in"/>
|
||||
<arg type="b" direction="out"/>
|
||||
</method>
|
||||
<method name="MakeWindowAbove">
|
||||
<arg type="u" direction="in"/>
|
||||
</method>
|
||||
<method name="MaximizeWindow">
|
||||
<arg type="u" direction="in"/>
|
||||
</method>
|
||||
<method name="MinimizeWindow">
|
||||
<arg type="u" direction="in"/>
|
||||
</method>
|
||||
<method name="MoveEntry">
|
||||
<arg type="i" direction="in"/>
|
||||
<arg type="i" direction="in"/>
|
||||
</method>
|
||||
<method name="MoveWindow">
|
||||
<arg type="u" direction="in"/>
|
||||
</method>
|
||||
<method name="PreviewWindow">
|
||||
<arg type="u" direction="in"/>
|
||||
</method>
|
||||
<method name="QueryWindowIdentifyMethod">
|
||||
<arg type="u" direction="in"/>
|
||||
<arg type="s" direction="out"/>
|
||||
</method>
|
||||
<method name="RemovePluginSettings">
|
||||
<arg type="s" direction="in"/>
|
||||
<arg type="as" direction="in"/>
|
||||
</method>
|
||||
<method name="RequestDock">
|
||||
<arg type="s" direction="in"/>
|
||||
<arg type="i" direction="in"/>
|
||||
<arg type="b" direction="out"/>
|
||||
</method>
|
||||
<method name="RequestUndock">
|
||||
<arg type="s" direction="in"/>
|
||||
<arg type="b" direction="out"/>
|
||||
</method>
|
||||
<method name="SetFrontendWindowRect">
|
||||
<arg type="i" direction="in"/>
|
||||
<arg type="i" direction="in"/>
|
||||
<arg type="u" direction="in"/>
|
||||
<arg type="u" direction="in"/>
|
||||
</method>
|
||||
<method name="SetPluginSettings">
|
||||
<arg type="s" direction="in"/>
|
||||
</method>
|
||||
<method name="MergePluginSettings">
|
||||
<arg type="s" direction="in"/>
|
||||
</method>
|
||||
<signal name="ServiceRestarted"/>
|
||||
<signal name="EntryAdded">
|
||||
<arg type="o"/>
|
||||
<arg type="i"/>
|
||||
</signal>
|
||||
<signal name="EntryRemoved">
|
||||
<arg type="s"/>
|
||||
</signal>
|
||||
<signal name="PluginSettingsSynced"/>
|
||||
<signal name="DockAppSettingsSynced"/>
|
||||
<property name="Entries" type="ao" access="read"/>
|
||||
<property name="HideMode" type="i" access="readwrite"/>
|
||||
<property name="DisplayMode" type="i" access="readwrite"/>
|
||||
<property name="Position" type="i" access="readwrite"/>
|
||||
<property name="IconSize" type="u" access="readwrite"/>
|
||||
<property name="WindowSize" type="u" access="readwrite"/>
|
||||
<property name="WindowSizeEfficient" type="u" access="readwrite"/>
|
||||
<property name="WindowSizeFashion" type="u" access="readwrite"/>
|
||||
<property name="ShowTimeout" type="u" access="readwrite"/>
|
||||
<property name="HideTimeout" type="u" access="readwrite"/>
|
||||
<property name="DockedApps" type="as" access="read"/>
|
||||
<property name="HideState" type="i" access="read"/>
|
||||
<property name="FrontendWindowRect" type="(iiuu)" access="read">
|
||||
<annotation name="org.qtproject.QtDBus.QtTypeName" value="DockRect"/>
|
||||
</property>
|
||||
<property name="Opacity" type="d" access="readwrite"/>
|
||||
</interface>
|
146
frame/dbusinterface/xml/org.deepin.dde.kwayland.PlasmaWindow.xml
Normal file
146
frame/dbusinterface/xml/org.deepin.dde.kwayland.PlasmaWindow.xml
Normal file
@ -0,0 +1,146 @@
|
||||
<interface name="org.deepin.dde.KWayland1.PlasmaWindow">
|
||||
<signal name="ActiveChanged"/>
|
||||
<signal name="AppIdChanged"/>
|
||||
<signal name="CloseableChanged"/>
|
||||
<signal name="DemandsAttentionChanged"/>
|
||||
<signal name="FullscreenableChanged"/>
|
||||
<signal name="FullscreenChanged"/>
|
||||
<signal name="GeometryChanged"/>
|
||||
<signal name="IconChanged"/>
|
||||
<signal name="KeepAboveChanged"/>
|
||||
<signal name="KeepBelowChanged"/>
|
||||
<signal name="MaximizeableChanged"/>
|
||||
<signal name="MaximizedChanged"/>
|
||||
<signal name="MinimizeableChanged"/>
|
||||
<signal name="MinimizedChanged"/>
|
||||
<signal name="MovableChanged"/>
|
||||
<signal name="OnAllDesktopsChanged"/>
|
||||
<signal name="ParentWindowChanged"/>
|
||||
<signal name="PlasmaVirtualDesktopEntered">
|
||||
<arg name="id" type="s" direction="out"/>
|
||||
</signal>
|
||||
<signal name="PlasmaVirtualDesktopLeft">
|
||||
<arg name="id" type="s" direction="out"/>
|
||||
</signal>
|
||||
<signal name="ResizableChanged"/>
|
||||
<signal name="ShadeableChanged"/>
|
||||
<signal name="ShadedChanged"/>
|
||||
<signal name="SkipSwitcherChanged"/>
|
||||
<signal name="SkipTaskbarChanged"/>
|
||||
<signal name="TitleChanged"/>
|
||||
<signal name="Unmapped"/>
|
||||
<signal name="VirtualDesktopChangeableChanged"/>
|
||||
<signal name="VirtualDesktopChanged"/>
|
||||
<method name="AppId">
|
||||
<arg type="s" direction="out"/>
|
||||
</method>
|
||||
<method name="Destroy"/>
|
||||
<method name="Geometry">
|
||||
<arg type="(iiii)" direction="out"/>
|
||||
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="DockRect"/>
|
||||
</method>
|
||||
<method name="Icon">
|
||||
<arg type="s" direction="out"/>
|
||||
</method>
|
||||
<method name="InternalId">
|
||||
<arg type="u" direction="out"/>
|
||||
</method>
|
||||
<method name="IsActive">
|
||||
<arg type="b" direction="out"/>
|
||||
</method>
|
||||
<method name="IsCloseable">
|
||||
<arg type="b" direction="out"/>
|
||||
</method>
|
||||
<method name="IsDemandingAttention">
|
||||
<arg type="b" direction="out"/>
|
||||
</method>
|
||||
<method name="IsFullscreen">
|
||||
<arg type="b" direction="out"/>
|
||||
</method>
|
||||
<method name="IsFullscreenable">
|
||||
<arg type="b" direction="out"/>
|
||||
</method>
|
||||
<method name="IsKeepAbove">
|
||||
<arg type="b" direction="out"/>
|
||||
</method>
|
||||
<method name="IsKeepBelow">
|
||||
<arg type="b" direction="out"/>
|
||||
</method>
|
||||
<method name="IsMaximizeable">
|
||||
<arg type="b" direction="out"/>
|
||||
</method>
|
||||
<method name="IsMaximized">
|
||||
<arg type="b" direction="out"/>
|
||||
</method>
|
||||
<method name="IsMinimizeable">
|
||||
<arg type="b" direction="out"/>
|
||||
</method>
|
||||
<method name="IsMinimized">
|
||||
<arg type="b" direction="out"/>
|
||||
</method>
|
||||
<method name="IsMovable">
|
||||
<arg type="b" direction="out"/>
|
||||
</method>
|
||||
<method name="IsOnAllDesktops">
|
||||
<arg type="b" direction="out"/>
|
||||
</method>
|
||||
<method name="IsResizable">
|
||||
<arg type="b" direction="out"/>
|
||||
</method>
|
||||
<method name="IsShadeable">
|
||||
<arg type="b" direction="out"/>
|
||||
</method>
|
||||
<method name="IsShaded">
|
||||
<arg type="b" direction="out"/>
|
||||
</method>
|
||||
<method name="IsValid">
|
||||
<arg type="b" direction="out"/>
|
||||
</method>
|
||||
<method name="IsVirtualDesktopChangeable">
|
||||
<arg type="b" direction="out"/>
|
||||
</method>
|
||||
<method name="Pid">
|
||||
<arg type="u" direction="out"/>
|
||||
</method>
|
||||
<method name="PlasmaVirtualDesktops">
|
||||
<arg type="as" direction="out"/>
|
||||
</method>
|
||||
<method name="Release"/>
|
||||
<method name="RequestActivate"/>
|
||||
<method name="RequestClose"/>
|
||||
<method name="RequestEnterNewVirtualDesktop"/>
|
||||
<method name="RequestEnterVirtualDesktop">
|
||||
<arg name="id" type="s" direction="in"/>
|
||||
</method>
|
||||
<method name="RequestLeaveVirtualDesktop">
|
||||
<arg name="id" type="s" direction="in"/>
|
||||
</method>
|
||||
<method name="RequestMove"/>
|
||||
<method name="RequestResize"/>
|
||||
<method name="RequestToggleKeepAbove"/>
|
||||
<method name="RequestToggleKeepBelow"/>
|
||||
<method name="RequestToggleMaximized"/>
|
||||
<method name="RequestToggleMinimized"/>
|
||||
<method name="RequestToggleShaded"/>
|
||||
<method name="RequestVirtualDesktop">
|
||||
<arg name="desktop" type="u" direction="in"/>
|
||||
</method>
|
||||
<method name="SkipSwitcher">
|
||||
<arg type="b" direction="out"/>
|
||||
</method>
|
||||
<method name="SkipTaskbar">
|
||||
<arg type="b" direction="out"/>
|
||||
</method>
|
||||
<method name="Title">
|
||||
<arg type="s" direction="out"/>
|
||||
</method>
|
||||
<method name="VirtualDesktop">
|
||||
<arg type="u" direction="out"/>
|
||||
</method>
|
||||
<method name="WindowId">
|
||||
<arg type="u" direction="out"/>
|
||||
</method>
|
||||
<method name="uuid">
|
||||
<arg type="ay" direction="out"/>
|
||||
</method>
|
||||
</interface>
|
@ -0,0 +1,31 @@
|
||||
<interface name="org.deepin.dde.KWayland1.WindowManager">
|
||||
<signal name="InterfaceAboutToBeReleased"/>
|
||||
<signal name="InterfaceAboutToBeDestroyed"/>
|
||||
<signal name="ShowingDesktopChanged">
|
||||
<arg type="b" direction="out"/>
|
||||
</signal>
|
||||
<signal name="WindowCreated">
|
||||
<arg name="dbus" type="s" direction="out"/>
|
||||
</signal>
|
||||
<signal name="WindowRemove">
|
||||
<arg name="dbus" type="s" direction="out"/>
|
||||
</signal>
|
||||
<signal name="ActiveWindowChanged"/>
|
||||
<method name="IsValid">
|
||||
<arg type="b" direction="out"/>
|
||||
</method>
|
||||
<method name="IsShowingDesktop">
|
||||
<arg type="b" direction="out"/>
|
||||
</method>
|
||||
<method name="SetShowingDesktop">
|
||||
<arg name="show" type="b" direction="in"/>
|
||||
</method>
|
||||
<method name="ShowDesktop"/>
|
||||
<method name="HideDesktop"/>
|
||||
<method name="Windows">
|
||||
<arg type="av" direction="out"/>
|
||||
</method>
|
||||
<method name="ActiveWindow">
|
||||
<arg type="u" direction="out"/>
|
||||
</method>
|
||||
</interface>
|
@ -4,6 +4,8 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
#include "appitem.h"
|
||||
#include "docksettings.h"
|
||||
#include "taskmanager/windowinfobase.h"
|
||||
#include "themeappicon.h"
|
||||
#include "xcb_misc.h"
|
||||
#include "appswingeffectbuilder.h"
|
||||
@ -27,6 +29,9 @@
|
||||
#include <DPlatformTheme>
|
||||
#include <DConfig>
|
||||
|
||||
#include <cstdint>
|
||||
#include <sys/types.h>
|
||||
|
||||
DGUI_USE_NAMESPACE
|
||||
DCORE_USE_NAMESPACE
|
||||
|
||||
@ -34,13 +39,13 @@ DCORE_USE_NAMESPACE
|
||||
|
||||
QPoint AppItem::MousePressPos;
|
||||
|
||||
AppItem::AppItem(DockInter *dockInter, const QGSettings *appSettings, const QGSettings *activeAppSettings, const QGSettings *dockedAppSettings, const QDBusObjectPath &entry, QWidget *parent)
|
||||
AppItem::AppItem(const QGSettings *appSettings, const QGSettings *activeAppSettings, const QGSettings *dockedAppSettings, const Entry *entry, QWidget *parent)
|
||||
: DockItem(parent)
|
||||
, m_appSettings(appSettings)
|
||||
, m_activeAppSettings(activeAppSettings)
|
||||
, m_dockedAppSettings(dockedAppSettings)
|
||||
, m_itemEntry(const_cast<Entry*>(entry))
|
||||
, m_appPreviewTips(nullptr)
|
||||
, m_itemEntryInter(new DockEntryInter(dockServiceName(), entry.path(), QDBusConnection::sessionBus(), this))
|
||||
, m_swingEffectView(nullptr)
|
||||
, m_itemAnimation(nullptr)
|
||||
, m_wmHelper(DWindowManagerHelper::instance())
|
||||
@ -48,6 +53,7 @@ AppItem::AppItem(DockInter *dockInter, const QGSettings *appSettings, const QGSe
|
||||
, m_retryTimes(0)
|
||||
, m_iconValid(true)
|
||||
, m_lastclickTimes(0)
|
||||
, m_showMultiWindow(DockSettings::instance()->showMultiWindow())
|
||||
, m_appIcon(QPixmap())
|
||||
, m_activeColor(DGuiApplicationHelper::instance()->systemTheme()->activeColor())
|
||||
, m_updateIconGeometryTimer(new QTimer(this))
|
||||
@ -55,19 +61,24 @@ AppItem::AppItem(DockInter *dockInter, const QGSettings *appSettings, const QGSe
|
||||
, m_refershIconTimer(new QTimer(this))
|
||||
, m_themeType(DGuiApplicationHelper::instance()->themeType())
|
||||
, m_createMSecs(QDateTime::currentMSecsSinceEpoch())
|
||||
, m_screenSpliter(ScreenSpliterFactory::createScreenSpliter(this, m_itemEntryInter))
|
||||
, m_dockInter(dockInter)
|
||||
, m_screenSpliter(ScreenSpliterFactory::createScreenSpliter(this))
|
||||
{
|
||||
QHBoxLayout *centralLayout = new QHBoxLayout;
|
||||
centralLayout->setMargin(0);
|
||||
centralLayout->setSpacing(0);
|
||||
|
||||
setObjectName(m_itemEntryInter->name());
|
||||
setAcceptDrops(true);
|
||||
setLayout(centralLayout);
|
||||
|
||||
m_id = m_itemEntryInter->id();
|
||||
m_active = m_itemEntryInter->isActive();
|
||||
m_id = m_itemEntry->getId();
|
||||
m_active = m_itemEntry->getIsActive();
|
||||
m_name = m_itemEntry->getName();
|
||||
m_icon = m_itemEntry->getIcon();
|
||||
m_mode = m_itemEntry->mode();
|
||||
m_isDocked = m_itemEntry->getIsDocked();
|
||||
m_menu = m_itemEntry->getMenu();
|
||||
|
||||
setObjectName(m_name);
|
||||
|
||||
m_updateIconGeometryTimer->setInterval(500);
|
||||
m_updateIconGeometryTimer->setSingleShot(true);
|
||||
@ -78,17 +89,32 @@ AppItem::AppItem(DockInter *dockInter, const QGSettings *appSettings, const QGSe
|
||||
m_refershIconTimer->setInterval(1000);
|
||||
m_refershIconTimer->setSingleShot(false);
|
||||
|
||||
connect(m_itemEntryInter, &DockEntryInter::IsActiveChanged, this, &AppItem::activeChanged);
|
||||
connect(m_itemEntryInter, &DockEntryInter::IsActiveChanged, this, static_cast<void (AppItem::*)()>(&AppItem::update));
|
||||
connect(m_itemEntryInter, &DockEntryInter::WindowInfosChanged, this, &AppItem::updateWindowInfos, Qt::QueuedConnection);
|
||||
connect(m_itemEntryInter, &DockEntryInter::IconChanged, this, &AppItem::refreshIcon);
|
||||
connect(m_itemEntryInter, &DockEntryInter::ModeChanged, this, &AppItem::modeChanged);
|
||||
connect(m_itemEntry, &Entry::isActiveChanged, this, &AppItem::activeChanged);
|
||||
connect(m_itemEntry, &Entry::isActiveChanged, this, static_cast<void (AppItem::*)()>(&AppItem::update));
|
||||
connect(m_itemEntry, &Entry::windowInfosChanged, this, &AppItem::updateWindowInfos, Qt::QueuedConnection);
|
||||
connect(m_itemEntry, &Entry::iconChanged, this, [=](QString icon) {
|
||||
if (!icon.isEmpty() && icon != m_icon)
|
||||
m_icon = icon;
|
||||
});
|
||||
connect(m_itemEntry, &Entry::iconChanged, this, &AppItem::refreshIcon);
|
||||
connect(m_itemEntry, &Entry::modeChanged, this, [=] (int32_t mode) { m_mode = mode; Q_EMIT modeChanged(m_mode);});
|
||||
connect(m_updateIconGeometryTimer, &QTimer::timeout, this, &AppItem::updateWindowIconGeometries, Qt::QueuedConnection);
|
||||
connect(m_retryObtainIconTimer, &QTimer::timeout, this, &AppItem::refreshIcon, Qt::QueuedConnection);
|
||||
connect(DockSettings::instance(), &DockSettings::showMultiWindowChanged, this, [=] (bool show) {
|
||||
m_showMultiWindow = show;
|
||||
});
|
||||
connect(m_itemEntry, &Entry::nameChanged, this, [=](const QString& name){ m_name = name; });
|
||||
connect(m_itemEntry, &Entry::desktopFileChanged, this, [=](const QString& desktopfile){ m_desktopfile = desktopfile; });
|
||||
connect(m_itemEntry, &Entry::isDockedChanged, this, [=](bool docked){ m_isDocked = docked; });
|
||||
connect(m_itemEntry, &Entry::menuChanged, this, [=](const QString& menu){ m_menu = menu; });
|
||||
connect(m_itemEntry, &Entry::currentWindowChanged, this, [=](uint32_t currentWindow){
|
||||
m_currentWindow = currentWindow;
|
||||
Q_EMIT onCurrentWindowChanged(m_currentWindow);
|
||||
});
|
||||
|
||||
connect(this, &AppItem::requestUpdateEntryGeometries, this, &AppItem::updateWindowIconGeometries);
|
||||
|
||||
updateWindowInfos(m_itemEntryInter->windowInfos());
|
||||
updateWindowInfos(m_itemEntry->getExportWindowInfos());
|
||||
|
||||
if (m_appSettings)
|
||||
connect(m_appSettings, &QGSettings::changed, this, &AppItem::onGSettingsChanged);
|
||||
@ -110,7 +136,7 @@ AppItem::AppItem(DockInter *dockInter, const QGSettings *appSettings, const QGSe
|
||||
*/
|
||||
void AppItem::checkEntry()
|
||||
{
|
||||
m_itemEntryInter->Check();
|
||||
m_itemEntry->check();
|
||||
}
|
||||
|
||||
const QString AppItem::appId() const
|
||||
@ -120,12 +146,12 @@ const QString AppItem::appId() const
|
||||
|
||||
QString AppItem::name() const
|
||||
{
|
||||
return m_itemEntryInter->name();
|
||||
return m_name;
|
||||
}
|
||||
|
||||
bool AppItem::isValid() const
|
||||
{
|
||||
return m_itemEntryInter->isValid() && !m_itemEntryInter->id().isEmpty();
|
||||
return m_itemEntry->isValid() && !m_id.isEmpty();
|
||||
}
|
||||
|
||||
// Update _NET_WM_ICON_GEOMETRY property for windows that every item
|
||||
@ -155,7 +181,7 @@ void AppItem::updateWindowIconGeometries()
|
||||
*/
|
||||
void AppItem::undock()
|
||||
{
|
||||
m_itemEntryInter->RequestUndock();
|
||||
m_itemEntry->requestUndock();
|
||||
}
|
||||
|
||||
QWidget *AppItem::appDragWidget()
|
||||
@ -201,28 +227,28 @@ bool AppItem::splitWindowOnScreen(ScreenSpliter::SplitDirection direction)
|
||||
|
||||
int AppItem::mode() const
|
||||
{
|
||||
return m_itemEntryInter->mode();
|
||||
return m_mode;
|
||||
}
|
||||
|
||||
|
||||
DockEntryInter *AppItem::itemEntryInter() const
|
||||
Entry *AppItem::itemEntry() const
|
||||
{
|
||||
return m_itemEntryInter;
|
||||
return m_itemEntry;
|
||||
}
|
||||
|
||||
QString AppItem::accessibleName()
|
||||
{
|
||||
return m_itemEntryInter->name();
|
||||
return m_name;
|
||||
}
|
||||
|
||||
void AppItem::requestDock()
|
||||
{
|
||||
m_itemEntryInter->RequestDock();
|
||||
m_itemEntry->requestDock();
|
||||
}
|
||||
|
||||
bool AppItem::isDocked() const
|
||||
{
|
||||
return m_itemEntryInter->isDocked();
|
||||
return m_isDocked;
|
||||
}
|
||||
|
||||
qint64 AppItem::appOpenMSecs() const
|
||||
@ -235,7 +261,7 @@ void AppItem::updateMSecs()
|
||||
m_createMSecs = QDateTime::currentMSecsSinceEpoch();
|
||||
}
|
||||
|
||||
const WindowInfoMap &AppItem::windowsMap() const
|
||||
const WindowInfoMap &AppItem::windowsInfos() const
|
||||
{
|
||||
return m_windowInfos;
|
||||
}
|
||||
@ -277,7 +303,7 @@ void AppItem::paintEvent(QPaintEvent *e)
|
||||
path.addRoundedRect(backgroundRect, 8, 8);
|
||||
|
||||
// 在没有开启窗口多开的情况下,显示背景色
|
||||
if (!m_dockInter->showMultiWindow()) {
|
||||
if (!m_showMultiWindow) {
|
||||
if (m_active) {
|
||||
QColor color = Qt::black;
|
||||
color.setAlpha(255 * 0.8);
|
||||
@ -371,7 +397,7 @@ void AppItem::mouseReleaseEvent(QMouseEvent *e)
|
||||
return;
|
||||
|
||||
if (e->button() == Qt::MiddleButton) {
|
||||
m_itemEntryInter->NewInstance(QX11Info::getTimestamp());
|
||||
m_itemEntry->newInstance(QX11Info::getTimestamp());
|
||||
|
||||
// play launch effect
|
||||
if (m_windowInfos.isEmpty())
|
||||
@ -383,15 +409,12 @@ void AppItem::mouseReleaseEvent(QMouseEvent *e)
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << "app item clicked, name:" << m_itemEntryInter->name()
|
||||
<< "id:" << m_itemEntryInter->id() << "my-id:" << m_id << "icon:" << m_itemEntryInter->icon();
|
||||
|
||||
if (m_dockInter->showMultiWindow()) {
|
||||
if (m_showMultiWindow) {
|
||||
// 如果开启了多窗口显示,则直接新建一个窗口
|
||||
m_itemEntryInter->NewInstance(QX11Info::getTimestamp());
|
||||
m_itemEntry->newInstance(QX11Info::getTimestamp());
|
||||
} else {
|
||||
// 如果没有开启新窗口显示,则
|
||||
m_itemEntryInter->Activate(QX11Info::getTimestamp());
|
||||
m_itemEntry->active(QX11Info::getTimestamp());
|
||||
// play launch effect
|
||||
if (m_windowInfos.isEmpty() && DGuiApplicationHelper::isSpecialEffectsEnvironment())
|
||||
playSwingEffect();
|
||||
@ -444,7 +467,7 @@ void AppItem::wheelEvent(QWheelEvent *e)
|
||||
QWidget::wheelEvent(e);
|
||||
|
||||
if (qAbs(e->angleDelta().y()) > 20) {
|
||||
m_itemEntryInter->PresentWindows();
|
||||
m_itemEntry->presentWindows();
|
||||
}
|
||||
}
|
||||
|
||||
@ -498,7 +521,7 @@ void AppItem::dropEvent(QDropEvent *e)
|
||||
}
|
||||
|
||||
qDebug() << "accept drop event with URIs: " << uriList;
|
||||
m_itemEntryInter->HandleDragDrop(QX11Info::getTimestamp(), uriList);
|
||||
m_itemEntry->handleDragDrop(QX11Info::getTimestamp(), uriList);
|
||||
}
|
||||
|
||||
void AppItem::leaveEvent(QEvent *e)
|
||||
@ -528,12 +551,12 @@ void AppItem::invokedMenuItem(const QString &itemId, const bool checked)
|
||||
{
|
||||
Q_UNUSED(checked);
|
||||
|
||||
m_itemEntryInter->HandleMenuItem(QX11Info::getTimestamp(), itemId);
|
||||
m_itemEntry->handleMenuItem(QX11Info::getTimestamp(), itemId);
|
||||
}
|
||||
|
||||
const QString AppItem::contextMenu() const
|
||||
{
|
||||
return m_itemEntryInter->menu();
|
||||
return m_menu;
|
||||
}
|
||||
|
||||
QWidget *AppItem::popupTips()
|
||||
@ -546,14 +569,14 @@ QWidget *AppItem::popupTips()
|
||||
|
||||
static TipsWidget appNameTips(topLevelWidget());
|
||||
appNameTips.setAccessibleName("tip");
|
||||
appNameTips.setObjectName(m_itemEntryInter->name());
|
||||
appNameTips.setObjectName(m_name);
|
||||
|
||||
if (!m_windowInfos.isEmpty()) {
|
||||
const quint32 currentWindow = m_itemEntryInter->currentWindow();
|
||||
const quint32 currentWindow = m_currentWindow;
|
||||
Q_ASSERT(m_windowInfos.contains(currentWindow));
|
||||
appNameTips.setText(m_windowInfos[currentWindow].title.simplified());
|
||||
} else {
|
||||
appNameTips.setText(m_itemEntryInter->name().simplified());
|
||||
appNameTips.setText(m_name.simplified());
|
||||
}
|
||||
|
||||
return &appNameTips;
|
||||
@ -638,7 +661,7 @@ void AppItem::updateWindowInfos(const WindowInfoMap &info)
|
||||
|
||||
m_windowInfos = info;
|
||||
if (m_appPreviewTips)
|
||||
m_appPreviewTips->setWindowInfos(m_windowInfos, m_itemEntryInter->GetAllowedCloseWindows().value());
|
||||
m_appPreviewTips->setWindowInfos(m_windowInfos, m_itemEntry->getAllowedClosedWindowIds().toList());
|
||||
m_updateIconGeometryTimer->start();
|
||||
|
||||
// process attention effect
|
||||
@ -660,22 +683,21 @@ void AppItem::refreshIcon()
|
||||
if (!isVisible())
|
||||
return;
|
||||
|
||||
const QString icon = m_itemEntryInter->icon();
|
||||
const int iconSize = qMin(width(), height());
|
||||
|
||||
if (DockDisplayMode == Efficient)
|
||||
m_iconValid = ThemeAppIcon::getIcon(m_appIcon, icon, iconSize * 0.7, !m_iconValid);
|
||||
m_iconValid = ThemeAppIcon::getIcon(m_appIcon, m_icon, iconSize * 0.7, !m_iconValid);
|
||||
else
|
||||
m_iconValid = ThemeAppIcon::getIcon(m_appIcon, icon, iconSize * 0.8, !m_iconValid);
|
||||
m_iconValid = ThemeAppIcon::getIcon(m_appIcon, m_icon, iconSize * 0.8, !m_iconValid);
|
||||
|
||||
if (!m_refershIconTimer->isActive() && m_itemEntryInter->icon() == "dde-calendar") {
|
||||
if (!m_refershIconTimer->isActive() && m_icon == "dde-calendar") {
|
||||
m_refershIconTimer->start();
|
||||
}
|
||||
|
||||
if (!m_iconValid) {
|
||||
if (m_retryTimes < 10) {
|
||||
m_retryTimes++;
|
||||
qDebug() << m_itemEntryInter->name() << "obtain app icon(" << icon << ")failed, retry times:" << m_retryTimes;
|
||||
qDebug() << m_name << "obtain app icon(" << m_icon << ")failed, retry times:" << m_retryTimes;
|
||||
// Maybe the icon was installed after we loaded the caches.
|
||||
// QIcon::setThemeSearchPaths will force Qt to re-check the gtk cache validity.
|
||||
QIcon::setThemeSearchPaths(QIcon::themeSearchPaths());
|
||||
@ -730,14 +752,14 @@ void AppItem::showPreview()
|
||||
return;
|
||||
|
||||
m_appPreviewTips = new PreviewContainer;
|
||||
m_appPreviewTips->setWindowInfos(m_windowInfos, m_itemEntryInter->GetAllowedCloseWindows().value());
|
||||
m_appPreviewTips->setWindowInfos(m_windowInfos, m_itemEntry->getAllowedClosedWindowIds().toList());
|
||||
m_appPreviewTips->updateLayoutDirection(DockPosition);
|
||||
|
||||
connect(m_appPreviewTips, &PreviewContainer::requestActivateWindow, this, &AppItem::requestActivateWindow, Qt::QueuedConnection);
|
||||
connect(m_appPreviewTips, &PreviewContainer::requestActivateWindow, this, &AppItem::activeWindow, Qt::QueuedConnection);
|
||||
connect(m_appPreviewTips, &PreviewContainer::requestPreviewWindow, this, &AppItem::requestPreviewWindow, Qt::QueuedConnection);
|
||||
connect(m_appPreviewTips, &PreviewContainer::requestCancelPreviewWindow, this, &AppItem::requestCancelPreview);
|
||||
connect(m_appPreviewTips, &PreviewContainer::requestHidePopup, this, &AppItem::hidePopup);
|
||||
connect(m_appPreviewTips, &PreviewContainer::requestCheckWindows, m_itemEntryInter, &DockEntryInter::Check);
|
||||
connect(m_appPreviewTips, &PreviewContainer::requestCheckWindows, m_itemEntry, &Entry::check);
|
||||
|
||||
connect(m_appPreviewTips, &PreviewContainer::requestActivateWindow, this, &AppItem::onResetPreview);
|
||||
connect(m_appPreviewTips, &PreviewContainer::requestCancelPreviewWindow, this, &AppItem::onResetPreview);
|
||||
@ -809,7 +831,7 @@ void AppItem::onGSettingsChanged(const QString &key)
|
||||
return;
|
||||
}
|
||||
|
||||
const QGSettings *setting = m_itemEntryInter->isDocked()
|
||||
const QGSettings *setting = m_isDocked
|
||||
? m_dockedAppSettings
|
||||
: m_activeAppSettings;
|
||||
|
||||
@ -821,7 +843,7 @@ void AppItem::onGSettingsChanged(const QString &key)
|
||||
|
||||
bool AppItem::checkGSettingsControl() const
|
||||
{
|
||||
const QGSettings *setting = m_itemEntryInter->isDocked()
|
||||
const QGSettings *setting = m_isDocked
|
||||
? m_dockedAppSettings
|
||||
: m_activeAppSettings;
|
||||
|
||||
@ -851,3 +873,8 @@ void AppItem::showEvent(QShowEvent *e)
|
||||
|
||||
refreshIcon();
|
||||
}
|
||||
|
||||
void AppItem::activeWindow(WId wid)
|
||||
{
|
||||
m_itemEntry->activeWindow(wid);
|
||||
}
|
||||
|
@ -11,12 +11,15 @@
|
||||
#include "appdrag.h"
|
||||
#include "../widgets/tipswidget.h"
|
||||
#include "dbusutil.h"
|
||||
#include "taskmanager/entry.h"
|
||||
|
||||
#include <QGraphicsView>
|
||||
#include <QGraphicsItem>
|
||||
#include <QGraphicsItemAnimation>
|
||||
#include <DGuiApplicationHelper>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
class QGSettings;
|
||||
class ScreenSpliter;
|
||||
|
||||
@ -25,7 +28,7 @@ class AppItem : public DockItem
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AppItem(DockInter *dockInter, const QGSettings *appSettings, const QGSettings *activeAppSettings, const QGSettings *dockedAppSettings, const QDBusObjectPath &entry, QWidget *parent = nullptr);
|
||||
explicit AppItem(const QGSettings *appSettings, const QGSettings *activeAppSettings, const QGSettings *dockedAppSettings, const Entry *entry, QWidget *parent = nullptr);
|
||||
~AppItem() override;
|
||||
|
||||
void checkEntry() override;
|
||||
@ -42,15 +45,17 @@ public:
|
||||
bool supportSplitWindow();
|
||||
bool splitWindowOnScreen(ScreenSpliter::SplitDirection direction);
|
||||
int mode() const;
|
||||
DockEntryInter *itemEntryInter() const;
|
||||
Entry *itemEntry() const;
|
||||
inline ItemType itemType() const override { return App; }
|
||||
QPixmap appIcon(){ return m_appIcon; }
|
||||
uint32_t currentWindow(){ return m_currentWindow; }
|
||||
virtual QString accessibleName() override;
|
||||
void requestDock();
|
||||
bool isDocked() const;
|
||||
qint64 appOpenMSecs() const;
|
||||
void updateMSecs();
|
||||
const WindowInfoMap &windowsMap() const;
|
||||
const WindowInfoMap &windowsInfos() const;
|
||||
void activeWindow(WId wid);
|
||||
|
||||
signals:
|
||||
void requestActivateWindow(const WId wid) const;
|
||||
@ -61,6 +66,7 @@ signals:
|
||||
void requestUpdateEntryGeometries() const;
|
||||
void windowCountChanged() const;
|
||||
void modeChanged(int) const;
|
||||
void onCurrentWindowChanged(uint32_t currentWindow);
|
||||
|
||||
private:
|
||||
void moveEvent(QMoveEvent *e) override;
|
||||
@ -104,9 +110,9 @@ private:
|
||||
const QGSettings *m_appSettings;
|
||||
const QGSettings *m_activeAppSettings;
|
||||
const QGSettings *m_dockedAppSettings;
|
||||
Entry *m_itemEntry;
|
||||
|
||||
PreviewContainer *m_appPreviewTips;
|
||||
DockEntryInter *m_itemEntryInter;
|
||||
|
||||
QGraphicsView *m_swingEffectView;
|
||||
QGraphicsItemAnimation *m_itemAnimation;
|
||||
@ -116,13 +122,24 @@ private:
|
||||
QPointer<AppDrag> m_drag;
|
||||
|
||||
bool m_active;
|
||||
bool m_isDocked;
|
||||
WindowInfoMap m_windowInfos;
|
||||
int32_t m_mode;
|
||||
QString m_desktopfile;
|
||||
QString m_icon;
|
||||
QString m_id;
|
||||
QString m_menu;
|
||||
QString m_name;
|
||||
uint32_t m_currentWindow;
|
||||
|
||||
int m_retryTimes;
|
||||
bool m_iconValid;
|
||||
quint64 m_lastclickTimes;
|
||||
bool m_showMultiWindow;
|
||||
|
||||
WindowInfoMap m_windowInfos;
|
||||
QString m_id;
|
||||
QPixmap m_appIcon;
|
||||
|
||||
// 统一样式?
|
||||
QPixmap m_horizontalIndicator;
|
||||
QPixmap m_verticalIndicator;
|
||||
QPixmap m_activeHorizontalIndicator;
|
||||
@ -141,7 +158,6 @@ private:
|
||||
static QPoint MousePressPos;
|
||||
|
||||
ScreenSpliter *m_screenSpliter;
|
||||
DockInter *m_dockInter;
|
||||
};
|
||||
|
||||
#endif // APPITEM_H
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "appitem.h"
|
||||
#include "appmultiitem.h"
|
||||
#include "imageutil.h"
|
||||
#include "screenspliter.h"
|
||||
#include "themeappicon.h"
|
||||
|
||||
#include <QBitmap>
|
||||
@ -23,7 +24,6 @@ AppMultiItem::AppMultiItem(AppItem *appItem, WId winId, const WindowInfo &window
|
||||
: DockItem(parent)
|
||||
, m_appItem(appItem)
|
||||
, m_windowInfo(windowInfo)
|
||||
, m_entryInter(appItem->itemEntryInter())
|
||||
, m_winId(winId)
|
||||
, m_menu(new QMenu(this))
|
||||
{
|
||||
@ -70,12 +70,12 @@ void AppMultiItem::initMenu()
|
||||
|
||||
void AppMultiItem::initConnection()
|
||||
{
|
||||
connect(m_entryInter, &DockEntryInter::CurrentWindowChanged, this, &AppMultiItem::onCurrentWindowChanged);
|
||||
connect(m_appItem, &AppItem::onCurrentWindowChanged, this, &AppMultiItem::onCurrentWindowChanged);
|
||||
}
|
||||
|
||||
void AppMultiItem::onOpen()
|
||||
{
|
||||
m_entryInter->ActiveWindow(m_winId);
|
||||
m_appItem->activeWindow(m_winId);
|
||||
}
|
||||
|
||||
void AppMultiItem::onCurrentWindowChanged(uint32_t value)
|
||||
@ -103,7 +103,7 @@ void AppMultiItem::paintEvent(QPaintEvent *)
|
||||
path.addRoundedRect(rect(), radius, radius);
|
||||
painter.fillPath(path, Qt::transparent);
|
||||
|
||||
if (m_entryInter->currentWindow() == m_winId) {
|
||||
if (m_appItem->currentWindow() == m_winId) {
|
||||
QColor backColor = Qt::black;
|
||||
backColor.setAlpha(255 * 0.8);
|
||||
painter.fillPath(path, backColor);
|
||||
@ -117,7 +117,7 @@ void AppMultiItem::paintEvent(QPaintEvent *)
|
||||
painter.drawPixmap(QRect(x, y, itemWidth, itemHeight), m_pixmap);
|
||||
|
||||
QPixmap pixmapAppIcon;
|
||||
ThemeAppIcon::getIcon(pixmapAppIcon, m_entryInter->icon(), qMin(width(), height()) * 0.8);
|
||||
ThemeAppIcon::getIcon(pixmapAppIcon, m_appItem->appId(), qMin(width(), height()) * 0.8);
|
||||
if (!pixmapAppIcon.isNull()) {
|
||||
// 绘制下方的图标,下方的小图标大约为应用图标的三分之一的大小
|
||||
//pixmap = pixmap.scaled(pixmap.width() * 0.3, pixmap.height() * 0.3);
|
||||
@ -135,7 +135,7 @@ void AppMultiItem::paintEvent(QPaintEvent *)
|
||||
void AppMultiItem::mouseReleaseEvent(QMouseEvent *event)
|
||||
{
|
||||
if (event->button() == Qt::LeftButton) {
|
||||
m_entryInter->ActiveWindow(m_winId);
|
||||
m_appItem->activeWindow(m_winId);
|
||||
} else {
|
||||
QPoint currentPoint = QCursor::pos();
|
||||
m_menu->exec(currentPoint);
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#include "dockitem.h"
|
||||
#include "dbusutil.h"
|
||||
#include "taskmanager/windowinfomap.h"
|
||||
|
||||
class AppItem;
|
||||
|
||||
@ -43,7 +44,6 @@ private Q_SLOTS:
|
||||
private:
|
||||
AppItem *m_appItem;
|
||||
WindowInfo m_windowInfo;
|
||||
DockEntryInter *m_entryInter;
|
||||
QPixmap m_pixmap;
|
||||
WId m_winId;
|
||||
QMenu *m_menu;
|
||||
|
@ -6,6 +6,8 @@
|
||||
#include "appsnapshot.h"
|
||||
#include "previewcontainer.h"
|
||||
#include "../widgets/tipswidget.h"
|
||||
#include "taskmanager/taskmanager.h"
|
||||
#include "taskmanager/xcbutils.h"
|
||||
#include "utils.h"
|
||||
#include "imageutil.h"
|
||||
|
||||
@ -23,6 +25,9 @@
|
||||
#include <QSizeF>
|
||||
#include <QTimer>
|
||||
#include <QPainterPath>
|
||||
#include <QDBusConnectionInterface>
|
||||
#include <QDBusInterface>
|
||||
#include <QDBusReply>
|
||||
|
||||
struct SHMInfo {
|
||||
long shmid;
|
||||
@ -51,7 +56,6 @@ AppSnapshot::AppSnapshot(const WId wid, QWidget *parent)
|
||||
, m_waitLeaveTimer(new QTimer(this))
|
||||
, m_closeBtn2D(new DIconButton(this))
|
||||
, m_wmHelper(DWindowManagerHelper::instance())
|
||||
, m_dockDaemonInter(new DockInter(dockServiceName(), dockServicePath(), QDBusConnection::sessionBus(), this))
|
||||
{
|
||||
m_closeBtn2D->setFixedSize(SNAP_CLOSE_BTN_WIDTH, SNAP_CLOSE_BTN_WIDTH);
|
||||
m_closeBtn2D->setIconSize(QSize(SNAP_CLOSE_BTN_WIDTH, SNAP_CLOSE_BTN_WIDTH));
|
||||
@ -79,7 +83,7 @@ AppSnapshot::AppSnapshot(const WId wid, QWidget *parent)
|
||||
void AppSnapshot::setWindowState()
|
||||
{
|
||||
if (m_isWidowHidden) {
|
||||
m_dockDaemonInter->MinimizeWindow(m_wid);
|
||||
TaskManager::instance()->MinimizeWindow(m_wid);
|
||||
}
|
||||
}
|
||||
|
||||
@ -130,7 +134,7 @@ void AppSnapshot::setTitleVisible(bool bVisible)
|
||||
void AppSnapshot::closeWindow() const
|
||||
{
|
||||
if (Utils::IS_WAYLAND_DISPLAY) {
|
||||
m_dockDaemonInter->CloseWindow(static_cast<uint>(m_wid));
|
||||
TaskManager::instance()->closeWindow(static_cast<uint>(m_wid));
|
||||
} else {
|
||||
const auto display = QX11Info::display();
|
||||
if (!display) {
|
||||
@ -293,7 +297,9 @@ void AppSnapshot::paintEvent(QPaintEvent *e)
|
||||
const int radius = dstyle.pixelMetric(DStyle::PM_FrameRadius);
|
||||
|
||||
painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
|
||||
QRect imageRect(8, 8, width() - 16, height() - 16);
|
||||
QSize size = m_pixmap.size().scaled(width() - 16, height() - 16, Qt::KeepAspectRatio);
|
||||
|
||||
QRect imageRect((width() - size.width()) / 2, (height() - size.height()) / 2, size.width(), size.height());
|
||||
painter.setPen(Qt::NoPen);
|
||||
QPainterPath path;
|
||||
path.addRoundedRect(imageRect, radius * ratio, radius * ratio);
|
||||
|
@ -7,6 +7,7 @@
|
||||
#define APPSNAPSHOT_H
|
||||
|
||||
#include "dbusutil.h"
|
||||
#include "taskmanager/windowinfomap.h"
|
||||
|
||||
#include <DIconButton>
|
||||
#include <DWindowManagerHelper>
|
||||
@ -99,7 +100,6 @@ private:
|
||||
QTimer *m_waitLeaveTimer;
|
||||
DIconButton *m_closeBtn2D;
|
||||
DWindowManagerHelper *m_wmHelper;
|
||||
DockInter *m_dockDaemonInter;
|
||||
};
|
||||
|
||||
#endif // APPSNAPSHOT_H
|
||||
|
@ -68,9 +68,7 @@ void PreviewContainer::setWindowInfos(const WindowInfoMap &infos, const WindowLi
|
||||
if (!m_snapshots.contains(key))
|
||||
appendSnapWidget(key);
|
||||
m_snapshots[key]->setWindowInfo(it.value());
|
||||
// FIXME: "GetAllowedCloseWindows" has remove form dde-daemon
|
||||
// 由于相关接口被移除,暂时无法正确设置 m_closeAble 属性,暂改为默认 true
|
||||
// m_snapshots[key]->setCloseAble(allowClose.contains(key));
|
||||
m_snapshots[key]->setCloseAble(allowClose.contains(key));
|
||||
}
|
||||
|
||||
if (m_snapshots.isEmpty()) {
|
||||
@ -257,7 +255,7 @@ void PreviewContainer::onSnapshotClicked(const WId wid)
|
||||
Q_EMIT requestActivateWindow(wid);
|
||||
m_needActivate = true;
|
||||
m_waitForShowPreviewTimer->stop();
|
||||
requestHidePopup();
|
||||
Q_EMIT requestHidePopup();
|
||||
}
|
||||
|
||||
void PreviewContainer::previewEntered(const WId wid)
|
||||
|
@ -17,7 +17,7 @@
|
||||
#include <DWindowManagerHelper>
|
||||
|
||||
DWIDGET_USE_NAMESPACE
|
||||
|
||||
typedef QList<quint32> WindowList;
|
||||
class PreviewContainer : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <QMouseEvent>
|
||||
#include <QApplication>
|
||||
#include <QGSettings>
|
||||
#include <QtConcurrent>
|
||||
#include <QDBusInterface>
|
||||
#include <QDBusPendingCall>
|
||||
#include <DDBusSender>
|
||||
@ -84,15 +85,17 @@ void LauncherItem::mouseReleaseEvent(QMouseEvent *e)
|
||||
|
||||
if (e->button() != Qt::LeftButton)
|
||||
return;
|
||||
|
||||
DDBusSender dbusSender = DDBusSender()
|
||||
|
||||
QtConcurrent::run([=] {
|
||||
DDBusSender dbusSender = DDBusSender()
|
||||
.service(launcherService)
|
||||
.path(launcherPath)
|
||||
.interface(launcherInterface);
|
||||
|
||||
QDBusPendingReply<bool> visibleReply = dbusSender.property("Visible").get();
|
||||
if (!visibleReply.value())
|
||||
dbusSender.method("Toggle").call();
|
||||
QDBusPendingReply<bool> visibleReply = dbusSender.property("Visible").get();
|
||||
if (!visibleReply.value())
|
||||
dbusSender.method("Toggle").call();
|
||||
});
|
||||
}
|
||||
|
||||
QWidget *LauncherItem::popupTips()
|
||||
|
@ -4,16 +4,14 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
#include "mainwindow.h"
|
||||
#include "accessible.h"
|
||||
#include "dbusdockadaptors.h"
|
||||
#include "dockdaemonadaptors.h"
|
||||
#include "utils.h"
|
||||
#include "themeappicon.h"
|
||||
#include "dockitemmanager.h"
|
||||
#include "dockapplication.h"
|
||||
#include "traymainwindow.h"
|
||||
#include "windowmanager.h"
|
||||
|
||||
#include <QAccessible>
|
||||
#include <QDir>
|
||||
#include <QStandardPaths>
|
||||
#include <QDateTime>
|
||||
@ -41,8 +39,6 @@ DUTIL_USE_NAMESPACE
|
||||
|
||||
const QString g_cfgPath = QStandardPaths::standardLocations(QStandardPaths::ConfigLocation)[0] + "/dde-cfg.ini";
|
||||
|
||||
using namespace std;
|
||||
|
||||
/**
|
||||
* @brief IsSaveMode
|
||||
* @return 判断当前是否应该进入安全模式(安全模式下不加载插件)
|
||||
@ -163,6 +159,10 @@ int main(int argc, char *argv[])
|
||||
DockApplication::setAttribute(Qt::AA_EnableHighDpiScaling, true);
|
||||
DockApplication app(argc, argv);
|
||||
|
||||
// NOTE: dde-shell load dde-dock plugins and mark loader program DS_APP_ID as dde-dock
|
||||
// so need reset DGuiApplication pallette to follow system
|
||||
DGuiApplicationHelper::instance()->setPaletteType(DGuiApplicationHelper::ColorType::UnknownType);
|
||||
|
||||
//崩溃信号
|
||||
signal(SIGSEGV, sig_crash);
|
||||
signal(SIGILL, sig_crash);
|
||||
@ -173,15 +173,12 @@ int main(int argc, char *argv[])
|
||||
app.setOrganizationName("deepin");
|
||||
app.setApplicationName("dde-dock");
|
||||
app.setApplicationDisplayName("DDE Dock");
|
||||
app.setApplicationVersion("2.0");
|
||||
app.setApplicationVersion(CVERSION);
|
||||
app.loadTranslator();
|
||||
app.setAttribute(Qt::AA_UseHighDpiPixmaps, true);
|
||||
|
||||
// 自动化标记由此开始
|
||||
QAccessible::installFactory(accessibleFactory);
|
||||
|
||||
// 设置日志输出到控制台以及文件
|
||||
DLogManager::setLogFormat("%{time}{yyyyMMdd.HH:mm:ss.zzz}[%{type:1}][%{function:-35} %{line:-4}] %{message}\n");
|
||||
DLogManager::setLogFormat("%{time}{yyMMdd.HH:mm:ss.zzz}[%{type:1}] [%{category}] [%{function:-25} %{line:-4}] %{message}");
|
||||
DLogManager::registerConsoleAppender();
|
||||
DLogManager::registerFileAppender();
|
||||
|
||||
@ -226,10 +223,15 @@ int main(int argc, char *argv[])
|
||||
|
||||
// 注册任务栏的DBus服务
|
||||
DBusDockAdaptors adaptor(&windowManager);
|
||||
DockDaemonDBusAdaptor daemonAdaptor(&windowManager);
|
||||
|
||||
QDBusConnection::sessionBus().registerService("org.deepin.dde.Dock1");
|
||||
QDBusConnection::sessionBus().registerObject("/org/deepin/dde/Dock1", "org.deepin.dde.Dock1", &windowManager);
|
||||
|
||||
//保证dock daemon接口兼容性,dde-desktop,dde-clipboard,deepin-system-monitor,dde-osd等在调用。
|
||||
QDBusConnection::sessionBus().registerService("org.deepin.dde.daemon.Dock1");
|
||||
QDBusConnection::sessionBus().registerObject("/org/deepin/dde/daemon/Dock1", "org.deepin.dde.daemon.Dock1", &windowManager);
|
||||
|
||||
// 当任务栏以-r参数启动时,设置CANSHOW未false,之后调用launch不显示任务栏
|
||||
qApp->setProperty("CANSHOW", !parser.isSet(runOption));
|
||||
|
||||
|
@ -14,10 +14,9 @@ bool ScreenSpliter::releaseSplit()
|
||||
return true;
|
||||
}
|
||||
|
||||
ScreenSpliter::ScreenSpliter(AppItem *appItem, DockEntryInter *entryInter, QObject *parent)
|
||||
ScreenSpliter::ScreenSpliter(AppItem *appItem, QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_appItem(appItem)
|
||||
, m_entryInter(entryInter)
|
||||
{
|
||||
}
|
||||
|
||||
@ -31,15 +30,10 @@ AppItem *ScreenSpliter::appItem() const
|
||||
return m_appItem;
|
||||
}
|
||||
|
||||
DockEntryInter *ScreenSpliter::entryInter() const
|
||||
{
|
||||
return m_entryInter;
|
||||
}
|
||||
|
||||
ScreenSpliter *ScreenSpliterFactory::createScreenSpliter(AppItem *appItem, DockEntryInter *entryInter)
|
||||
ScreenSpliter *ScreenSpliterFactory::createScreenSpliter(AppItem *appItem)
|
||||
{
|
||||
if (Utils::IS_WAYLAND_DISPLAY)
|
||||
return new ScreenSpliter_Wayland(appItem, entryInter, appItem);
|
||||
return new ScreenSpliter_Wayland(appItem, appItem);
|
||||
|
||||
return new ScreenSpliter_Xcb(appItem, entryInter, appItem);
|
||||
return new ScreenSpliter_Xcb(appItem, appItem);
|
||||
}
|
||||
|
@ -37,20 +37,18 @@ public:
|
||||
virtual bool releaseSplit(); // 释放分屏
|
||||
|
||||
protected:
|
||||
explicit ScreenSpliter(AppItem *appItem, DockEntryInter *entryInter, QObject *parent = nullptr);
|
||||
explicit ScreenSpliter(AppItem *appItem, QObject *parent = nullptr);
|
||||
virtual ~ScreenSpliter();
|
||||
AppItem *appItem() const;
|
||||
DockEntryInter *entryInter() const;
|
||||
|
||||
private:
|
||||
AppItem *m_appItem;
|
||||
DockEntryInter *m_entryInter;
|
||||
};
|
||||
|
||||
class ScreenSpliterFactory
|
||||
{
|
||||
public:
|
||||
static ScreenSpliter *createScreenSpliter(AppItem *appItem, DockEntryInter *entryInter);
|
||||
static ScreenSpliter *createScreenSpliter(AppItem *appItem);
|
||||
};
|
||||
|
||||
#endif // SCREENSPLITER_H
|
||||
|
@ -25,8 +25,8 @@ SplitWindowManager *ScreenSpliter_Wayland::m_splitManager = nullptr;
|
||||
* @brief ScreenSpliter_Wayland::ScreenSpliter_Wayland
|
||||
* @param parent
|
||||
*/
|
||||
ScreenSpliter_Wayland::ScreenSpliter_Wayland(AppItem *appItem, DockEntryInter *entryInter, QObject *parent)
|
||||
: ScreenSpliter(appItem, entryInter, parent)
|
||||
ScreenSpliter_Wayland::ScreenSpliter_Wayland(AppItem *appItem, QObject *parent)
|
||||
: ScreenSpliter(appItem, parent)
|
||||
{
|
||||
if (!m_splitManager)
|
||||
m_splitManager = new SplitWindowManager;
|
||||
@ -68,7 +68,7 @@ bool ScreenSpliter_Wayland::split(SplitDirection direction)
|
||||
if (!suportSplitScreen())
|
||||
return false;
|
||||
|
||||
WindowInfoMap windowInfos = entryInter()->windowInfos();
|
||||
WindowInfoMap windowInfos = appItem()->windowsInfos();
|
||||
m_splitManager->requestSplitWindow(windowInfos.first().uuid.toStdString().c_str(), direction);
|
||||
|
||||
return true;
|
||||
@ -82,7 +82,7 @@ bool ScreenSpliter_Wayland::windowSupportSplit(const QString &uuid) const
|
||||
bool ScreenSpliter_Wayland::suportSplitScreen()
|
||||
{
|
||||
// 判断所有打开的窗口列表,只要有一个窗口支持分屏,就认为它支持分屏
|
||||
const WindowInfoMap &windowsInfo = entryInter()->windowInfos();
|
||||
const WindowInfoMap &windowsInfo = appItem()->windowsInfos();
|
||||
for (const WindowInfo &windowInfo : windowsInfo) {
|
||||
if (windowSupportSplit(windowInfo.uuid))
|
||||
return true;
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "screenspliter.h"
|
||||
|
||||
#include <QWidget>
|
||||
#include <QMap>
|
||||
|
||||
namespace KWayland {
|
||||
namespace Client {
|
||||
@ -38,7 +39,7 @@ class ScreenSpliter_Wayland : public ScreenSpliter
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ScreenSpliter_Wayland(AppItem *appItem, DockEntryInter *entryInter, QObject *parent);
|
||||
explicit ScreenSpliter_Wayland(AppItem *appItem, QObject *parent);
|
||||
~ScreenSpliter_Wayland() override;
|
||||
|
||||
void startSplit(const QRect &rect) override;
|
||||
|
@ -61,8 +61,8 @@ static QByteArray windowProperty(quint32 WId, xcb_atom_t propAtom, xcb_atom_t ty
|
||||
return data;
|
||||
}
|
||||
|
||||
ScreenSpliter_Xcb::ScreenSpliter_Xcb(AppItem *appItem, DockEntryInter *entryInter, QObject *parent)
|
||||
: ScreenSpliter(appItem, entryInter, parent)
|
||||
ScreenSpliter_Xcb::ScreenSpliter_Xcb(AppItem *appItem, QObject *parent)
|
||||
: ScreenSpliter(appItem, parent)
|
||||
{
|
||||
}
|
||||
|
||||
@ -79,7 +79,7 @@ bool ScreenSpliter_Xcb::split(ScreenSpliter::SplitDirection direction)
|
||||
if (!suportSplitScreen())
|
||||
return false;
|
||||
|
||||
quint32 WId = entryInter()->windowInfos().keys().first();
|
||||
quint32 WId = appItem()->windowsInfos().keys().first();
|
||||
xcb_client_message_event_t xev;
|
||||
xev.response_type = XCB_CLIENT_MESSAGE;
|
||||
xev.type = internAtom("_DEEPIN_SPLIT_WINDOW", false);
|
||||
@ -116,7 +116,7 @@ void ScreenSpliter_Xcb::showSplitScreenEffect(const QRect &rect, bool visible)
|
||||
if (!suportSplitScreen())
|
||||
return;
|
||||
|
||||
quint32 WId = entryInter()->windowInfos().keys().first();
|
||||
quint32 WId = appItem()->windowsInfos().keys().first();
|
||||
// 触发分屏的效果
|
||||
xcb_client_message_event_t xev;
|
||||
xev.response_type = XCB_CLIENT_MESSAGE;
|
||||
@ -137,7 +137,7 @@ void ScreenSpliter_Xcb::showSplitScreenEffect(const QRect &rect, bool visible)
|
||||
bool ScreenSpliter_Xcb::suportSplitScreen()
|
||||
{
|
||||
// 判断所有的窗口,只要有一个窗口支持分屏,就认为它支持分屏
|
||||
QList<quint32> winIds = entryInter()->windowInfos().keys();
|
||||
QList<quint32> winIds = appItem()->windowsInfos().keys();
|
||||
for (const quint32 &winId : winIds) {
|
||||
if (windowSupportSplit(winId))
|
||||
return true;
|
||||
|
@ -16,7 +16,7 @@ typedef QMap<quint32, WindowInfo> WindowInfoMap;
|
||||
class ScreenSpliter_Xcb : public ScreenSpliter
|
||||
{
|
||||
public:
|
||||
explicit ScreenSpliter_Xcb(AppItem *appItem, DockEntryInter *entryInter, QObject *parent = nullptr);
|
||||
explicit ScreenSpliter_Xcb(AppItem *appItem, QObject *parent = nullptr);
|
||||
|
||||
void startSplit(const QRect &rect) override;
|
||||
bool split(ScreenSpliter::SplitDirection direction) override;
|
||||
|
60
frame/taskmanager/appinfo.cpp
Normal file
60
frame/taskmanager/appinfo.cpp
Normal file
@ -0,0 +1,60 @@
|
||||
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "appinfo.h"
|
||||
#include "common.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QString>
|
||||
#include <QCryptographicHash>
|
||||
|
||||
AppInfo::AppInfo(DesktopInfo &info)
|
||||
: m_installed(false)
|
||||
, m_isValid(true)
|
||||
{
|
||||
init(info);
|
||||
}
|
||||
|
||||
AppInfo::AppInfo(const QString &_fileName)
|
||||
: m_isValid(true)
|
||||
{
|
||||
DesktopInfo info(_fileName);
|
||||
init(info);
|
||||
}
|
||||
|
||||
void AppInfo::init(DesktopInfo &info)
|
||||
{
|
||||
if (!info.isValidDesktop()) {
|
||||
m_isValid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
QString xDeepinVendor = info.getDesktopFile()->value(MainSection + "/X-Deepin-Vendor").toString();
|
||||
if (xDeepinVendor == "deepin") {
|
||||
m_name = info.getGenericName();
|
||||
if (m_name.isEmpty()) {
|
||||
m_name = info.getName();
|
||||
}
|
||||
} else {
|
||||
m_name = info.getName();
|
||||
}
|
||||
|
||||
m_innerId = genInnerIdWithDesktopInfo(info);
|
||||
m_fileName = info.getDesktopFilePath();
|
||||
m_id = info.getId();
|
||||
m_icon = info.getIcon();
|
||||
m_installed = info.isInstalled();
|
||||
auto actions = info.getActions();
|
||||
std::copy(actions.begin(), actions.end(), std::back_inserter(m_actions));
|
||||
|
||||
}
|
||||
|
||||
QString AppInfo::genInnerIdWithDesktopInfo(DesktopInfo &info)
|
||||
{
|
||||
QString cmdline = info.getCommandLine();
|
||||
QByteArray encryText = QCryptographicHash::hash(QString(cmdline).toLatin1(), QCryptographicHash::Md5);
|
||||
QString innerId = desktopHashPrefix + encryText.toHex();
|
||||
qInfo() << "app: " << info.getId() << " generate innerId: " << innerId;
|
||||
return innerId;
|
||||
}
|
53
frame/taskmanager/appinfo.h
Normal file
53
frame/taskmanager/appinfo.h
Normal file
@ -0,0 +1,53 @@
|
||||
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#ifndef APPINFO_H
|
||||
#define APPINFO_H
|
||||
|
||||
#include "desktopinfo.h"
|
||||
|
||||
#include <QVector>
|
||||
|
||||
// 应用信息类
|
||||
class AppInfo
|
||||
{
|
||||
public:
|
||||
explicit AppInfo(DesktopInfo &info);
|
||||
explicit AppInfo(const QString &_fileName);
|
||||
|
||||
void init(DesktopInfo &info);
|
||||
void setIdentifyMethod(QString method) {m_identifyMethod = method;}
|
||||
|
||||
bool isValidApp() {return m_isValid;}
|
||||
bool isInstalled() {return m_installed;}
|
||||
|
||||
|
||||
QString getId() {return m_id;}
|
||||
QString getIcon() {return m_icon;}
|
||||
QString getName() {return m_name;}
|
||||
QString getInnerId() {return m_innerId;}
|
||||
QString getFileName() {return m_fileName;}
|
||||
QString getIdentifyMethod() {return m_identifyMethod;}
|
||||
|
||||
QVector<DesktopAction> getActions() {return m_actions;}
|
||||
|
||||
private:
|
||||
QString genInnerIdWithDesktopInfo(DesktopInfo &info);
|
||||
|
||||
private:
|
||||
|
||||
bool m_installed;
|
||||
bool m_isValid;
|
||||
|
||||
QString m_id;
|
||||
QString m_name;
|
||||
QString m_icon;
|
||||
QString m_innerId;
|
||||
QString m_fileName;
|
||||
QString m_identifyMethod;
|
||||
QVector<DesktopAction> m_actions;
|
||||
|
||||
};
|
||||
|
||||
#endif // APPINFO_H
|
80
frame/taskmanager/appmenu.cpp
Normal file
80
frame/taskmanager/appmenu.cpp
Normal file
@ -0,0 +1,80 @@
|
||||
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "appmenu.h"
|
||||
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
|
||||
AppMenu::AppMenu()
|
||||
: m_itemCount(0)
|
||||
, m_dirty(false)
|
||||
, m_checkableMenu(false)
|
||||
, m_singleCheck(false)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief AppMenu::appendItem 增加菜单选项
|
||||
* @param item
|
||||
*/
|
||||
void AppMenu::appendItem(AppMenuItem item)
|
||||
{
|
||||
if (!item.text.isEmpty()) {
|
||||
item.id = allocateId();
|
||||
m_items.push_back(item);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief AppMenu::handleAction 响应应用菜单项
|
||||
* @param timestamp
|
||||
* @param itemId
|
||||
*/
|
||||
void AppMenu::handleAction(uint32_t timestamp, QString itemId)
|
||||
{
|
||||
for (auto &item : m_items) {
|
||||
if (item.id == itemId) {
|
||||
item.action(timestamp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AppMenu::setDirtyStatus(bool isDirty)
|
||||
{
|
||||
m_dirty = isDirty;
|
||||
}
|
||||
|
||||
QString AppMenu::getMenuJsonStr()
|
||||
{
|
||||
QJsonObject obj;
|
||||
QJsonArray array;
|
||||
for (auto item : m_items) {
|
||||
QJsonObject objItem;
|
||||
objItem["itemId"] = item.id;
|
||||
objItem["itemText"] = item.text;
|
||||
objItem["isActive"] = item.isActive;
|
||||
objItem["isCheckable"] = item.isCheckable;
|
||||
objItem["checked"] = item.checked;
|
||||
objItem["itemIcon"] = item.icon;
|
||||
objItem["itemIconHover"] = item.iconHover;
|
||||
objItem["itemIconInactive"] = item.iconInactive;
|
||||
objItem["showCheckMark"] = item.showCheckMark;
|
||||
objItem["itemSubMenu"] = item.subMenu ? item.subMenu->getMenuJsonStr() : "";
|
||||
array.push_back(objItem);
|
||||
}
|
||||
obj["items"] = QJsonValue(array);
|
||||
obj["checkableMenu"] = m_checkableMenu;
|
||||
obj["singleCheck"] = m_singleCheck;
|
||||
|
||||
QString ret = QJsonDocument(obj).toJson();
|
||||
return ret;
|
||||
}
|
||||
|
||||
QString AppMenu::allocateId()
|
||||
{
|
||||
return QString::number(m_itemCount++);
|
||||
}
|
67
frame/taskmanager/appmenu.h
Normal file
67
frame/taskmanager/appmenu.h
Normal file
@ -0,0 +1,67 @@
|
||||
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#ifndef APPMENU_H
|
||||
#define APPMENU_H
|
||||
|
||||
#include <QString>
|
||||
#include <QJsonObject>
|
||||
#include <QVector>
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
|
||||
typedef std::function<void(uint32_t)> AppMenuAction;
|
||||
|
||||
class AppMenu;
|
||||
|
||||
// 应用菜单选项
|
||||
struct AppMenuItem
|
||||
{
|
||||
AppMenuItem()
|
||||
: isActive(true)
|
||||
, hint(0)
|
||||
{
|
||||
}
|
||||
|
||||
QString id;
|
||||
QString text;
|
||||
QString isCheckable;
|
||||
QString checked;
|
||||
QString icon;
|
||||
QString iconHover;
|
||||
QString iconInactive;
|
||||
QString showCheckMark;
|
||||
std::shared_ptr<AppMenu> subMenu;
|
||||
|
||||
bool isActive;
|
||||
int hint;
|
||||
AppMenuAction action;
|
||||
};
|
||||
|
||||
// 应用菜单类
|
||||
class AppMenu
|
||||
{
|
||||
public:
|
||||
AppMenu();
|
||||
|
||||
void appendItem(AppMenuItem item);
|
||||
void setDirtyStatus(bool isDirty);
|
||||
void handleAction(uint32_t timestamp, QString itemId);
|
||||
|
||||
QString getMenuJsonStr();
|
||||
|
||||
private:
|
||||
QString allocateId();
|
||||
|
||||
private:
|
||||
int m_itemCount;
|
||||
bool m_dirty;
|
||||
bool m_checkableMenu; // json:"checkableMenu"
|
||||
bool m_singleCheck; // json:"singleCheck"
|
||||
QVector<AppMenuItem> m_items; // json:"items"
|
||||
};
|
||||
|
||||
#endif // APPMENU_H
|
89
frame/taskmanager/bamfdesktop.cpp
Normal file
89
frame/taskmanager/bamfdesktop.cpp
Normal file
@ -0,0 +1,89 @@
|
||||
// SPDX-FileCopyrightText: 2022 ~ 2022 Deepin Technology Co., Ltd.
|
||||
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "bamfdesktop.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <qstandardpaths.h>
|
||||
|
||||
#define BAMF_INDEX_NAME "bamf-2.index"
|
||||
|
||||
BamfDesktop *BamfDesktop::instance()
|
||||
{
|
||||
static BamfDesktop instance;
|
||||
return &instance;
|
||||
}
|
||||
|
||||
QString BamfDesktop::fileName(const QString &instanceName) const
|
||||
{
|
||||
for (const BamfData &lineData: m_bamfLineData) {
|
||||
if (lineData.instanceName.toLower() == instanceName.toLower()) {
|
||||
QString name = lineData.lineData.split("\t").first();
|
||||
return QString("%1%2").arg(lineData.directory).arg(name);
|
||||
}
|
||||
}
|
||||
|
||||
// 如果根据instanceName没有找到,则根据空格来进行分隔
|
||||
for (const BamfData &lineData: m_bamfLineData) {
|
||||
QStringList lines = lineData.lineData.split("\t");
|
||||
if (lines.size() < 2)
|
||||
continue;
|
||||
|
||||
QStringList cmds = lines[2].split(" ");
|
||||
if (cmds.size() > 1 && cmds[1].toLower() == instanceName.toLower())
|
||||
return QString("%1%2").arg(lineData.directory).arg(lines.first());
|
||||
}
|
||||
|
||||
return instanceName;
|
||||
}
|
||||
|
||||
BamfDesktop::BamfDesktop()
|
||||
{
|
||||
loadDesktopFiles();
|
||||
}
|
||||
|
||||
BamfDesktop::~BamfDesktop()
|
||||
{
|
||||
}
|
||||
|
||||
QStringList BamfDesktop::applicationDirs() const
|
||||
{
|
||||
QStringList appDirs = QStandardPaths::standardLocations(QStandardPaths::ApplicationsLocation);
|
||||
QStringList directions;
|
||||
for (auto appDir : appDirs)
|
||||
directions << appDir;
|
||||
|
||||
return directions;
|
||||
}
|
||||
|
||||
void BamfDesktop::loadDesktopFiles()
|
||||
{
|
||||
QStringList directions = applicationDirs();
|
||||
for (const QString &direction : directions) {
|
||||
// 读取后缀名为
|
||||
QDir dir(direction);
|
||||
dir.setNameFilters(QStringList() << BAMF_INDEX_NAME);
|
||||
QFileInfoList fileList = dir.entryInfoList();
|
||||
if (fileList.size() == 0)
|
||||
continue;
|
||||
|
||||
QFileInfo fileInfo = fileList.at(0);
|
||||
QFile file(fileInfo.absoluteFilePath());
|
||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
|
||||
continue;
|
||||
|
||||
QList<QPair<QString, QString>> bamfLine;
|
||||
while (!file.atEnd()) {
|
||||
QString line = file.readLine();
|
||||
QStringList part = line.split("\t");
|
||||
BamfData bamf;
|
||||
bamf.directory = direction;
|
||||
if (part.size() > 2)
|
||||
bamf.instanceName = part[2].trimmed();
|
||||
bamf.lineData = line;
|
||||
m_bamfLineData << bamf;
|
||||
}
|
||||
}
|
||||
}
|
37
frame/taskmanager/bamfdesktop.h
Normal file
37
frame/taskmanager/bamfdesktop.h
Normal file
@ -0,0 +1,37 @@
|
||||
// SPDX-FileCopyrightText: 2022 ~ 2022 Deepin Technology Co., Ltd.
|
||||
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#ifndef BAMFDESKTOP_H
|
||||
#define BAMFDESKTOP_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QMap>
|
||||
|
||||
struct BamfData {
|
||||
QString directory;
|
||||
QString instanceName;
|
||||
QString lineData;
|
||||
};
|
||||
|
||||
class BamfDesktop
|
||||
{
|
||||
public:
|
||||
static BamfDesktop *instance();
|
||||
QString fileName(const QString &instanceName) const;
|
||||
|
||||
protected:
|
||||
BamfDesktop();
|
||||
~BamfDesktop();
|
||||
|
||||
private:
|
||||
QStringList applicationDirs() const;
|
||||
|
||||
void loadDesktopFiles();
|
||||
|
||||
private:
|
||||
QList<BamfData> m_bamfLineData;
|
||||
};
|
||||
|
||||
#endif // BAMFDESKTOP_H
|
89
frame/taskmanager/common.h
Normal file
89
frame/taskmanager/common.h
Normal file
@ -0,0 +1,89 @@
|
||||
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#ifndef COMMON_H
|
||||
#define COMMON_H
|
||||
|
||||
#include <QMap>
|
||||
#include <QDir>
|
||||
#include <QString>
|
||||
#include <QStandardPaths>
|
||||
|
||||
const QString configDock = "com.deepin.dde.dock";
|
||||
const QString configAppearance = "com.deepin.dde.appearance";
|
||||
|
||||
const QString keyOpacity = "Opacity";
|
||||
const QString keyPosition = "Position";
|
||||
const QString keyIconSize = "Icon_Size";
|
||||
const QString keyHideMode = "Hide_Mode";
|
||||
const QString keyRecentApp = "Recent_App";
|
||||
const QString keyShowRecent = "Show_Recent";
|
||||
const QString keyDockedApps = "Docked_Apps";
|
||||
const QString keyDisplayMode = "Display_Mode";
|
||||
const QString keyShowTimeout = "Show_Timeout";
|
||||
const QString keyHideTimeout = "Hide_Timeout";
|
||||
const QString keyForceQuitApp = "Force_Quit_App";
|
||||
const QString keyPluginSettings = "Plugin_Settings";
|
||||
const QString keyShowMultiWindow = "Show_MultiWindow";
|
||||
const QString keyWindowSizeFashion = "Window_Size_Fashion";
|
||||
const QString keyWindowSizeEfficient = "Window_Size_Efficient";
|
||||
const QString keyWinIconPreferredApps = "Win_Icon_Preferred_Apps";
|
||||
|
||||
constexpr auto DesktopFileActionKey = u8"Desktop Action ";
|
||||
constexpr auto DDEApplicationManager1ObjectPath = u8"/org/desktopspec/ApplicationManager1";
|
||||
constexpr auto ApplicationManager1DBusName= u8"org.desktopspec.ApplicationManager1";
|
||||
|
||||
static const QString scratchDir = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation).append("/deepin/dde-dock/scratch/");
|
||||
|
||||
const QString desktopHashPrefix = "d:";
|
||||
const QString windowHashPrefix = "w:";
|
||||
|
||||
// 驻留应用desktop file模板
|
||||
// 由于Icon存储的直接是icon base64压缩后的数据需要“”,防止被desktopfile当成stringlist,从而导致获取icon失败
|
||||
const QString dockedItemTemplate = R"([Desktop Entry]
|
||||
Name=%1
|
||||
Exec=%2
|
||||
Icon="%3"
|
||||
Type=Application
|
||||
Terminal=false
|
||||
StartupNotify=false
|
||||
)";
|
||||
|
||||
const QString frontendWindowWmClass = "dde-dock";
|
||||
const QString ddeLauncherWMClass = "dde-launcher";
|
||||
|
||||
const int smartHideTimerDelay = 400;
|
||||
const int configureNotifyDelay = 100;
|
||||
|
||||
const int bestIconSize = 48;
|
||||
const int menuItemHintShowAllWindows = 1;
|
||||
|
||||
const int MotifHintStatus = 8;
|
||||
const int MotifHintFunctions = 1;
|
||||
const int MotifHintInputMode = 4;
|
||||
const int MotifHintDecorations = 2;
|
||||
|
||||
const int MotifFunctionNone = 0;
|
||||
const int MotifFunctionAll = 1;
|
||||
const int MotifFunctionMove = 4;
|
||||
const int MotifFunctionClose = 32;
|
||||
const int MotifFunctionResize = 2;
|
||||
const int MotifFunctionMinimize = 8;
|
||||
const int MotifFunctionMaximize = 16;
|
||||
|
||||
|
||||
static inline QByteArray sessionType() {
|
||||
static QByteArray type = qgetenv("XDG_SESSION_TYPE");
|
||||
return type;
|
||||
}
|
||||
|
||||
static inline bool isWaylandSession() {
|
||||
return sessionType().compare("wayland") == 0;
|
||||
}
|
||||
|
||||
static inline bool isX11Session() {
|
||||
return sessionType().compare("x11") == 0;
|
||||
}
|
||||
|
||||
#endif // COMMON_H
|
343
frame/taskmanager/dbushandler.cpp
Normal file
343
frame/taskmanager/dbushandler.cpp
Normal file
@ -0,0 +1,343 @@
|
||||
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "dbushandler.h"
|
||||
#include "dbusutil.h"
|
||||
#include "taskmanager.h"
|
||||
#include "common.h"
|
||||
#include "entry.h"
|
||||
#include "windowinfok.h"
|
||||
|
||||
#include <DDBusSender>
|
||||
|
||||
#include <QtConcurrent>
|
||||
|
||||
DBusHandler::DBusHandler(TaskManager *taskmanager, QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_taskmanager(taskmanager)
|
||||
, m_wm(new com::deepin::wm("com.deepin.wm", "/com/deepin/wm", QDBusConnection::sessionBus(), this))
|
||||
, m_wmSwitcher(new org::deepin::dde::WMSwitcher1("org.deepin.dde.WMSwitcher1", "/org/deepin/dde/WMSwitcher1", QDBusConnection::sessionBus(), this))
|
||||
, m_kwaylandManager(nullptr)
|
||||
, m_xEventMonitor(nullptr)
|
||||
, m_launcher(new org::deepin::dde::Launcher1(launcherService, launcherPath, QDBusConnection::sessionBus(), this))
|
||||
{
|
||||
QDBusInterface *interAM = new QDBusInterface(ApplicationManager1DBusName, "/org/desktopspec/ApplicationManager1", "org.desktopspec.DBus.ObjectManager", QDBusConnection::sessionBus(), this);
|
||||
if (interAM->isValid()) {
|
||||
connect(interAM, SIGNAL(InterfacesRemoved(const QDBusObjectPath &, const QStringList &)), this, SIGNAL(appUninstalled(const QDBusObjectPath &, const QStringList &)));
|
||||
} else {
|
||||
qWarning() << "The interface of AM is invalid:" << interAM->lastError();
|
||||
}
|
||||
|
||||
connect(m_wmSwitcher, &org::deepin::dde::WMSwitcher1::WMChanged, this, [&](QString name) {m_taskmanager->setWMName(name);});
|
||||
if (!isWaylandSession()) {
|
||||
m_xEventMonitor = new org::deepin::dde::XEventMonitor1("org.deepin.dde.XEventMonitor1", "/org/deepin/dde/XEventMonitor1", QDBusConnection::sessionBus(), this);
|
||||
m_activeWindowMonitorKey = m_xEventMonitor->RegisterFullScreen();
|
||||
connect(m_xEventMonitor, &org::deepin::dde::XEventMonitor1::ButtonRelease, this, &DBusHandler::onActiveWindowButtonRelease);
|
||||
}
|
||||
|
||||
connect(m_launcher,static_cast<void (org::deepin::dde::Launcher1::*)(bool)>(&org::deepin::dde::Launcher1::VisibleChanged), this, [=] (const bool visible){
|
||||
m_taskmanager->setDdeLauncherVisible(visible);
|
||||
m_taskmanager->updateHideState(true);
|
||||
});
|
||||
|
||||
// try to active bamf in another thread
|
||||
QtConcurrent::run([ = ] {
|
||||
QDBusInterface bamfInterface(
|
||||
QStringLiteral("org.ayatana.bamf"),
|
||||
QStringLiteral("/org/ayatana/bamf/matcher"),
|
||||
QStringLiteral("org.ayatana.bamf.matcher"),
|
||||
QDBusConnection::sessionBus()
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
void DBusHandler::listenWaylandWMSignals()
|
||||
{
|
||||
m_kwaylandManager = new org::deepin::dde::kwayland1::WindowManager("org.deepin.dde.KWayland1", "/org/deepin/dde/KWayland1/WindowManager", QDBusConnection::sessionBus(), this);
|
||||
connect(m_kwaylandManager, &org::deepin::dde::kwayland1::WindowManager::ActiveWindowChanged, this, &DBusHandler::handleWlActiveWindowChange);
|
||||
connect(m_kwaylandManager, &org::deepin::dde::kwayland1::WindowManager::WindowCreated, this, [&] (const QString &ObjPath) {
|
||||
m_taskmanager->registerWindowWayland(ObjPath);
|
||||
});
|
||||
connect(m_kwaylandManager, &org::deepin::dde::kwayland1::WindowManager::WindowRemove, this, [&] (const QString &ObjPath) {
|
||||
m_taskmanager->unRegisterWindowWayland(ObjPath);
|
||||
});
|
||||
}
|
||||
|
||||
void DBusHandler::loadClientList()
|
||||
{
|
||||
if (!m_kwaylandManager)
|
||||
return;
|
||||
|
||||
QDBusPendingReply<QVariantList> windowList = m_kwaylandManager->Windows();
|
||||
QVariantList windows = windowList.value();
|
||||
for (QVariant windowPath : windows)
|
||||
m_taskmanager->registerWindowWayland(windowPath.toString());
|
||||
}
|
||||
|
||||
QString DBusHandler::getCurrentWM()
|
||||
{
|
||||
return m_wmSwitcher->CurrentWM().value();
|
||||
}
|
||||
|
||||
void DBusHandler::launchApp(QString desktopFile, uint32_t timestamp, QStringList files)
|
||||
{
|
||||
if (newStartManagerAvaliable()) {
|
||||
auto objPath = desktopEscapeToObjectPath(desktopFile);
|
||||
launchAppUsingApplicationManager1(QString{DDEApplicationManager1ObjectPath} + '/' + objPath, timestamp, files);
|
||||
} else {
|
||||
launchAppUsingApplication1Manager(desktopFile, timestamp, files);
|
||||
}
|
||||
}
|
||||
|
||||
void DBusHandler::launchAppAction(QString desktopFile, QString action, uint32_t timestamp)
|
||||
{
|
||||
if (newStartManagerAvaliable()) {
|
||||
auto objPath = desktopEscapeToObjectPath(desktopFile);
|
||||
launchAppActionUsingApplicationManager1(QString{DDEApplicationManager1ObjectPath} + '/' + objPath, action, timestamp);
|
||||
} else {
|
||||
launchAppActionUsingApplication1Manager(desktopFile, action, timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
void DBusHandler::launchAppUsingApplication1Manager(QString desktopFile, uint32_t timestamp, QStringList files)
|
||||
{
|
||||
QDBusInterface interface = QDBusInterface("org.deepin.dde.Application1.Manager", "/org/deepin/dde/Application1/Manager", "org.deepin.dde.Application1.Manager");
|
||||
interface.call("LaunchApp", desktopFile, timestamp, files);
|
||||
}
|
||||
|
||||
void DBusHandler::launchAppActionUsingApplication1Manager(QString desktopFile, QString action, uint32_t timestamp)
|
||||
{
|
||||
QDBusInterface interface = QDBusInterface("org.deepin.dde.Application1.Manager", "/org/deepin/dde/Application1/Manager", "org.deepin.dde.Application1.Manager");
|
||||
interface.call("LaunchAppAction", desktopFile, action, timestamp);
|
||||
}
|
||||
|
||||
// 新AM启动接口
|
||||
void DBusHandler::launchAppUsingApplicationManager1(QString dbusObjectPath, uint32_t timestamp, QStringList files)
|
||||
{
|
||||
QDBusInterface interface = QDBusInterface(ApplicationManager1DBusName, dbusObjectPath, "org.desktopspec.ApplicationManager1.Application");
|
||||
interface.call("Launch", "", QStringList(), QMap<QString, QVariant>());
|
||||
}
|
||||
|
||||
void DBusHandler::launchAppActionUsingApplicationManager1(QString dbusObjectPath, QString action, uint32_t timestamp)
|
||||
{
|
||||
action = action.right(action.size() - strlen(DesktopFileActionKey));
|
||||
QDBusInterface interface = QDBusInterface(ApplicationManager1DBusName, dbusObjectPath, "org.desktopspec.ApplicationManager1.Application");
|
||||
interface.call("Launch", action, QStringList(), QMap<QString, QVariant>());
|
||||
}
|
||||
|
||||
void DBusHandler::markAppLaunched(const QString &filePath)
|
||||
{
|
||||
QDBusInterface interface = QDBusInterface("org.deepin.dde.AlRecorder1", "/org/deepin/dde/AlRecorder1", "org.deepin.dde.AlRecorder1");
|
||||
interface.call("MarkLaunched", filePath);
|
||||
}
|
||||
|
||||
bool DBusHandler::wlShowingDesktop()
|
||||
{
|
||||
bool ret = false;
|
||||
if (m_kwaylandManager)
|
||||
ret = m_kwaylandManager->IsShowingDesktop().value();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint DBusHandler::wlActiveWindow()
|
||||
{
|
||||
uint ret = 0;
|
||||
if (m_kwaylandManager)
|
||||
ret = m_kwaylandManager->ActiveWindow().value();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void DBusHandler::handleWlActiveWindowChange()
|
||||
{
|
||||
uint activeWinInternalId = wlActiveWindow();
|
||||
if (activeWinInternalId == 0)
|
||||
return;
|
||||
|
||||
WindowInfoK *info = m_taskmanager->handleActiveWindowChangedK(activeWinInternalId);
|
||||
if (info && info->getXid() != 0) {
|
||||
m_taskmanager->handleActiveWindowChanged(info);
|
||||
} else {
|
||||
m_taskmanager->updateHideState(false);
|
||||
}
|
||||
}
|
||||
|
||||
void DBusHandler::onActiveWindowButtonRelease(int type, int x, int y, const QString &key)
|
||||
{
|
||||
// 当鼠标松开区域事件的时候,取消注册,同时调用激活窗口的方法来触发智能隐藏的相关信号
|
||||
if (key != m_activeWindowMonitorKey)
|
||||
return;
|
||||
|
||||
uint activeWinInternalId = wlActiveWindow();
|
||||
if (activeWinInternalId == 0)
|
||||
return;
|
||||
|
||||
WindowInfoK *info = m_taskmanager->handleActiveWindowChangedK(activeWinInternalId);
|
||||
if (!info)
|
||||
return;
|
||||
|
||||
// 如果是在当前激活窗口区域内释放的,则触发检测智能隐藏的方法
|
||||
DockRect dockRect = info->getGeometry();
|
||||
if (dockRect.x <= x && x <= int(dockRect.x + dockRect.w) && dockRect.y <= y && y <= int(dockRect.y + dockRect.h)) {
|
||||
// 取消智能隐藏
|
||||
m_taskmanager->updateHideState(false);
|
||||
}
|
||||
}
|
||||
|
||||
void DBusHandler::listenKWindowSignals(WindowInfoK *windowInfo)
|
||||
{
|
||||
PlasmaWindow *window = windowInfo->getPlasmaWindow();
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
connect(window, &PlasmaWindow::TitleChanged, this, [=] {
|
||||
windowInfo->updateTitle();
|
||||
auto entry = m_taskmanager->getEntryByWindowId(windowInfo->getXid());
|
||||
if (entry && entry->getCurrentWindowInfo() == windowInfo)
|
||||
entry->updateName();
|
||||
});
|
||||
connect(window, &PlasmaWindow::IconChanged, this, [=] {
|
||||
windowInfo->updateIcon();
|
||||
auto entry = m_taskmanager->getEntryByWindowId(windowInfo->getXid());
|
||||
if (!entry) return;
|
||||
|
||||
entry->updateIcon();
|
||||
});
|
||||
|
||||
// DemandingAttention changed
|
||||
connect(window, &PlasmaWindow::DemandsAttentionChanged, this, [=] {
|
||||
windowInfo->updateDemandingAttention();
|
||||
auto entry = m_taskmanager->getEntryByWindowId(windowInfo->getXid());
|
||||
if (!entry) return;
|
||||
|
||||
entry->updateExportWindowInfos();
|
||||
});
|
||||
|
||||
// Geometry changed
|
||||
connect(window, &PlasmaWindow::GeometryChanged, this, [=] {
|
||||
if (!windowInfo->updateGeometry()) return;
|
||||
|
||||
m_taskmanager->handleWindowGeometryChanged();
|
||||
});
|
||||
}
|
||||
|
||||
PlasmaWindow *DBusHandler::createPlasmaWindow(QString objPath)
|
||||
{
|
||||
return new PlasmaWindow("org.deepin.dde.KWayland1", objPath, QDBusConnection::sessionBus(), this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DBusHandler::removePlasmaWindowHandler 取消关联信号 TODO
|
||||
* @param window
|
||||
*/
|
||||
void DBusHandler::removePlasmaWindowHandler(PlasmaWindow *window)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void DBusHandler::presentWindows(QList<uint> windows)
|
||||
{
|
||||
m_wm->PresentWindows(windows);
|
||||
}
|
||||
|
||||
void DBusHandler::previewWindow(uint xid)
|
||||
{
|
||||
m_wm->PreviewWindow(xid);
|
||||
}
|
||||
|
||||
void DBusHandler::cancelPreviewWindow()
|
||||
{
|
||||
m_wm->CancelPreviewWindow();
|
||||
}
|
||||
|
||||
// TODO: 待优化点, 查看Bamf根据windowId获取对应应用desktopFile路径实现方式, 移除bamf依赖
|
||||
QString DBusHandler::getDesktopFromWindowByBamf(XWindow windowId)
|
||||
{
|
||||
QDBusInterface interface0 = QDBusInterface("org.ayatana.bamf", "/org/ayatana/bamf/matcher", "org.ayatana.bamf.matcher");
|
||||
QDBusReply<QString> replyApplication = interface0.call("ApplicationForXid", windowId);
|
||||
QString appObjPath = replyApplication.value();
|
||||
if (!replyApplication.isValid() || appObjPath.isEmpty())
|
||||
return "";
|
||||
|
||||
|
||||
QDBusInterface interface = QDBusInterface("org.ayatana.bamf", appObjPath, "org.ayatana.bamf.application");
|
||||
QDBusReply<QString> replyDesktopFile = interface.call("DesktopFile");
|
||||
|
||||
if (replyDesktopFile.isValid())
|
||||
return replyDesktopFile.value();
|
||||
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
// 新的AM调用
|
||||
QString DBusHandler::desktopEscapeToObjectPath(QString desktopFilePath)
|
||||
{
|
||||
// to desktop id
|
||||
QString objectPath;
|
||||
decltype(auto) desktopSuffix = ".desktop";
|
||||
auto tmp = desktopFilePath.chopped(sizeof(desktopSuffix) - 1);
|
||||
auto components = tmp.split(QDir::separator());
|
||||
auto it = std::find(components.cbegin(), components.cend(), "applications");
|
||||
if (it == components.cend()) return "_";
|
||||
QString FileId;
|
||||
++it;
|
||||
while (it != components.cend()) {
|
||||
FileId += (*(it++) + "-");
|
||||
}
|
||||
objectPath = FileId.chopped(1);
|
||||
|
||||
if (objectPath.isEmpty()) {
|
||||
return "_";
|
||||
}
|
||||
|
||||
// desktop id to objectPath
|
||||
QRegularExpression re{R"([^a-zA-Z0-9])"};
|
||||
auto matcher = re.globalMatch(objectPath);
|
||||
while (matcher.hasNext()) {
|
||||
auto replaceList = matcher.next().capturedTexts();
|
||||
replaceList.removeDuplicates();
|
||||
for (const auto &c : replaceList) {
|
||||
auto hexStr = QString::number(static_cast<uint>(c.front().toLatin1()), 16);
|
||||
objectPath.replace(c, QString{R"(_%1)"}.arg(hexStr));
|
||||
}
|
||||
}
|
||||
|
||||
return objectPath;
|
||||
}
|
||||
|
||||
bool DBusHandler::newStartManagerAvaliable()
|
||||
{
|
||||
static bool isAvaiable = false;
|
||||
std::call_once(m_isNewStartManagerAvaliableInited, [=](){
|
||||
auto services = QDBusConnection::sessionBus().interface()->registeredServiceNames().value();
|
||||
isAvaiable = std::any_of(services.begin(), services.end(), [=](const QString &name){
|
||||
return name == ApplicationManager1DBusName;
|
||||
});
|
||||
});
|
||||
|
||||
return isAvaiable;
|
||||
}
|
||||
|
||||
void DBusHandler::sendFailedDockNotification(const QString &appName)
|
||||
{
|
||||
QtConcurrent::run(QThreadPool::globalInstance(), [ = ] {
|
||||
DDBusSender()
|
||||
.service(notificationService)
|
||||
.path(notificationPath)
|
||||
.interface(notificationInterface)
|
||||
.method(QString("Notify"))
|
||||
.arg(QString("dde-control-center")) // appname
|
||||
.arg(static_cast<uint>(0)) // id
|
||||
.arg(QString("preferences-system")) // icon
|
||||
.arg(QString(tr("failed to dock ") + appName)) // summary
|
||||
.arg(QString(tr("Unrecognized application, unable to dock"))) // content
|
||||
.arg(QStringList()) // actions
|
||||
.arg(QVariantMap()) // hints
|
||||
.arg(5000) // timeout
|
||||
.call();
|
||||
});
|
||||
qInfo() << "unsupported app: " + appName;
|
||||
}
|
92
frame/taskmanager/dbushandler.h
Normal file
92
frame/taskmanager/dbushandler.h
Normal file
@ -0,0 +1,92 @@
|
||||
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#ifndef DBUSHANDLER_H
|
||||
#define DBUSHANDLER_H
|
||||
|
||||
#include "com_deepin_wm.h"
|
||||
#include "org_deepin_dde_launcher1.h"
|
||||
#include "org_deepin_dde_wmswitcher1.h"
|
||||
#include "org_deepin_dde_xeventmonitor1.h"
|
||||
#include "org_deepin_dde_kwayland_windowmanager.h"
|
||||
#include "org_deepin_dde_kwayland_plasmawindow.h"
|
||||
|
||||
#include "windowinfok.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QDBusConnection>
|
||||
#include <QDBusMessage>
|
||||
|
||||
class TaskManager;
|
||||
|
||||
// 处理DBus交互
|
||||
class DBusHandler : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DBusHandler(TaskManager *taskmanager, QObject *parent = nullptr);
|
||||
|
||||
/************************* KWayland/WindowManager ***************************/
|
||||
void listenWaylandWMSignals();
|
||||
void loadClientList();
|
||||
|
||||
bool wlShowingDesktop();
|
||||
uint wlActiveWindow();
|
||||
|
||||
/************************* WMSwitcher ***************************/
|
||||
QString getCurrentWM();
|
||||
|
||||
/************************* StartManager ***************************/
|
||||
void launchApp(QString desktopFile, uint32_t timestamp, QStringList files);
|
||||
void launchAppAction(QString desktopFile, QString action, uint32_t timestamp);
|
||||
void launchAppUsingApplication1Manager(QString desktopFile, uint32_t timestamp, QStringList files);
|
||||
void launchAppActionUsingApplication1Manager(QString desktopFile, QString action, uint32_t timestamp);
|
||||
void launchAppUsingApplicationManager1(QString desktopFile, uint32_t timestamp, QStringList files);
|
||||
void launchAppActionUsingApplicationManager1(QString desktopFile, QString action, uint32_t timestamp);
|
||||
|
||||
/************************* AlRecorder1 ***************************/
|
||||
void markAppLaunched(const QString &filePath);
|
||||
|
||||
/************************* KWayland.PlasmaWindow ***************************/
|
||||
void listenKWindowSignals(WindowInfoK *windowInfo);
|
||||
void removePlasmaWindowHandler(PlasmaWindow *window);
|
||||
|
||||
PlasmaWindow *createPlasmaWindow(QString objPath);
|
||||
|
||||
/************************* WM ***************************/
|
||||
void presentWindows(QList<uint> windows);
|
||||
void previewWindow(uint xid);
|
||||
void cancelPreviewWindow();
|
||||
|
||||
/************************* bamf ***************************/
|
||||
// XWindow -> desktopFile
|
||||
QString getDesktopFromWindowByBamf(XWindow windowId);
|
||||
|
||||
bool newStartManagerAvaliable();
|
||||
void sendFailedDockNotification(const QString &appName);
|
||||
|
||||
Q_SIGNALS:
|
||||
void appUninstalled(const QDBusObjectPath &objectPath, const QStringList &interfaces);
|
||||
|
||||
private Q_SLOTS:
|
||||
void handleWlActiveWindowChange();
|
||||
void onActiveWindowButtonRelease(int type, int x, int y, const QString &key);
|
||||
|
||||
private:
|
||||
QString desktopEscapeToObjectPath(QString desktopFilePath);
|
||||
|
||||
private:
|
||||
QString m_activeWindowMonitorKey;
|
||||
TaskManager *m_taskmanager;
|
||||
|
||||
com::deepin::wm *m_wm;
|
||||
org::deepin::dde::WMSwitcher1 *m_wmSwitcher;
|
||||
org::deepin::dde::kwayland1::WindowManager *m_kwaylandManager;
|
||||
org::deepin::dde::XEventMonitor1 *m_xEventMonitor;
|
||||
org::deepin::dde::Launcher1 *m_launcher;
|
||||
|
||||
std::once_flag m_isNewStartManagerAvaliableInited;
|
||||
};
|
||||
|
||||
#endif // DBUSHANDLER_H
|
256
frame/taskmanager/desktopinfo.cpp
Normal file
256
frame/taskmanager/desktopinfo.cpp
Normal file
@ -0,0 +1,256 @@
|
||||
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "desktopinfo.h"
|
||||
#include "locale.h"
|
||||
#include "taskmanager/common.h"
|
||||
#include "unistd.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include <algorithm>
|
||||
#include <QFileInfo>
|
||||
#include <QSettings>
|
||||
#include <QStandardPaths>
|
||||
#include <QVector>
|
||||
#include <QLocale>
|
||||
|
||||
QStringList DesktopInfo::currentDesktops;
|
||||
static QString desktopFileSuffix = ".desktop";
|
||||
|
||||
DesktopInfo::DesktopInfo(const QString &desktopfile)
|
||||
: m_isValid(true)
|
||||
, m_isInstalled(false)
|
||||
{
|
||||
QString desktopfilepath(desktopfile);
|
||||
QFileInfo desktopFileInfo(desktopfilepath);
|
||||
if (!(desktopfilepath.endsWith(desktopFileSuffix))) {
|
||||
desktopfilepath = desktopfilepath + desktopFileSuffix;
|
||||
desktopFileInfo.setFile(desktopfilepath);
|
||||
}
|
||||
|
||||
auto desktopFileName = desktopFileInfo.fileName();
|
||||
// 优先加载系统中的desktopfile,而不是用户传递过来的
|
||||
for (auto dir: QStandardPaths::standardLocations(QStandardPaths::ApplicationsLocation)) {
|
||||
QString path = dir.append("/").append(desktopFileName);
|
||||
if (QFile::exists(path)){
|
||||
desktopFileInfo.setFile(path);
|
||||
m_isInstalled = true;
|
||||
}
|
||||
}
|
||||
|
||||
m_desktopFilePath = desktopFileInfo.canonicalFilePath();
|
||||
m_isValid = desktopFileInfo.isAbsolute() && QFile::exists(desktopFileInfo.absoluteFilePath());
|
||||
m_desktopFile.reset(new QSettings(m_desktopFilePath, QSettings::IniFormat));
|
||||
m_desktopFile->setIniCodec("utf-8");
|
||||
// check DesktopInfo valid
|
||||
QStringList mainKeys = m_desktopFile->childGroups();
|
||||
if (mainKeys.size() == 0)
|
||||
m_isValid = false;
|
||||
|
||||
bool found = std::any_of(mainKeys.begin(), mainKeys.end(),
|
||||
[](const auto &key) {return key == MainSection;});
|
||||
|
||||
if (!found)
|
||||
m_isValid = false;
|
||||
|
||||
if (m_desktopFile->value(MainSection + '/' + KeyType).toString() != TypeApplication)
|
||||
m_isValid = false;
|
||||
|
||||
m_name = getLocaleStr(MainSection, KeyName);
|
||||
m_icon = m_desktopFile->value(MainSection + '/' + KeyIcon).toString();
|
||||
m_id = getId();
|
||||
}
|
||||
|
||||
DesktopInfo::~DesktopInfo()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QString DesktopInfo::getDesktopFilePath()
|
||||
{
|
||||
return m_desktopFilePath;
|
||||
}
|
||||
|
||||
bool DesktopInfo::isValidDesktop()
|
||||
{
|
||||
return m_isValid;
|
||||
}
|
||||
|
||||
bool DesktopInfo::isInstalled()
|
||||
{
|
||||
return m_isInstalled;
|
||||
}
|
||||
|
||||
/** if return true, item is shown
|
||||
* @brief DesktopInfo::shouldShow
|
||||
* @return
|
||||
*/
|
||||
bool DesktopInfo::shouldShow()
|
||||
{
|
||||
if (getNoDisplay() || getIsHidden()) {
|
||||
qDebug() << "hidden desktop file path: " << m_desktopFilePath;
|
||||
return false;
|
||||
}
|
||||
|
||||
QStringList desktopEnvs;
|
||||
return getShowIn(desktopEnvs);
|
||||
}
|
||||
|
||||
bool DesktopInfo::getNoDisplay()
|
||||
{
|
||||
return m_desktopFile->value(MainSection + '/' + KeyNoDisplay).toBool();
|
||||
}
|
||||
|
||||
bool DesktopInfo::getIsHidden()
|
||||
{
|
||||
return m_desktopFile->value(MainSection + '/' + KeyHidden).toBool();
|
||||
}
|
||||
|
||||
bool DesktopInfo::getShowIn(QStringList desktopEnvs)
|
||||
{
|
||||
#ifdef QT_DEBUG
|
||||
qDebug() << "desktop file path: " << m_desktopFilePath;
|
||||
#endif
|
||||
|
||||
if (desktopEnvs.size() == 0) {
|
||||
const QString env = getenv("XDG_CURRENT_DESKTOP");
|
||||
QVector<QString> desktops = env.split(":").toVector();
|
||||
currentDesktops.fromVector(desktops);
|
||||
desktopEnvs.fromVector(desktops);
|
||||
}
|
||||
|
||||
QStringList onlyShowIn = m_desktopFile->value(MainSection + '/' + KeyOnlyShowIn).toStringList();
|
||||
QStringList notShowIn = m_desktopFile->value(MainSection + '/' + KeyNotShowIn).toStringList();
|
||||
|
||||
#ifdef QT_DEBUG
|
||||
qDebug() << "onlyShowIn:" << onlyShowIn <<
|
||||
", notShowIn:" << notShowIn <<
|
||||
", desktopEnvs:" << desktopEnvs;
|
||||
#endif
|
||||
|
||||
for (const auto &desktop : desktopEnvs) {
|
||||
bool ret = std::any_of(onlyShowIn.begin(), onlyShowIn.end(),
|
||||
[&desktop](const auto &d) {return d == desktop;});
|
||||
#ifdef QT_DEBUG
|
||||
qInfo() << Q_FUNC_INFO << "onlyShowIn, result:" << ret;
|
||||
#endif
|
||||
if (ret)
|
||||
return true;
|
||||
|
||||
ret = std::any_of(notShowIn.begin(), notShowIn.end(),
|
||||
[&desktop](const auto &d) {return d == desktop;});
|
||||
#ifdef QT_DEBUG
|
||||
qInfo() << Q_FUNC_INFO << "notShowIn, result:" << ret;
|
||||
#endif
|
||||
if (ret)
|
||||
return false;
|
||||
}
|
||||
|
||||
return onlyShowIn.size() == 0;
|
||||
}
|
||||
|
||||
QString DesktopInfo::getExecutable()
|
||||
{
|
||||
return m_desktopFile->value(MainSection + '/' + KeyExec).toString();
|
||||
}
|
||||
|
||||
QList<DesktopAction> DesktopInfo::getActions()
|
||||
{
|
||||
QList<DesktopAction> actions;
|
||||
for (const auto &mainKey : m_desktopFile->childGroups()) {
|
||||
if (mainKey.startsWith(DesktopFileActionKey)) {
|
||||
DesktopAction action;
|
||||
action.name = getLocaleStr(mainKey, KeyName);
|
||||
action.exec = m_desktopFile->value(mainKey + '/' + KeyExec).toString();
|
||||
action.section = mainKey;
|
||||
actions.push_back(action);
|
||||
}
|
||||
}
|
||||
|
||||
return actions;
|
||||
}
|
||||
|
||||
// 使用appId获取DesktopInfo需检查有效性
|
||||
DesktopInfo DesktopInfo::getDesktopInfoById(const QString &appId)
|
||||
{
|
||||
QString desktopfile(appId);
|
||||
if (!desktopfile.endsWith(".desktop")) desktopfile.append(".desktop");
|
||||
for (const auto & dir : QStandardPaths::standardLocations(QStandardPaths::ApplicationsLocation)) {
|
||||
QString filePath = dir + desktopfile;
|
||||
//检测文件有效性
|
||||
if (QFile::exists(filePath)) {
|
||||
return DesktopInfo(filePath);
|
||||
}
|
||||
}
|
||||
|
||||
return DesktopInfo("");
|
||||
}
|
||||
|
||||
bool DesktopInfo::getTerminal()
|
||||
{
|
||||
return m_desktopFile->value(MainSection + '/' + KeyTerminal).toBool();
|
||||
}
|
||||
|
||||
// TryExec is Path to an executable file on disk used to determine if the program is actually installed
|
||||
QString DesktopInfo::getTryExec()
|
||||
{
|
||||
return m_desktopFile->value(MainSection + '/' + KeyTryExec).toString();
|
||||
}
|
||||
|
||||
// 按$PATH路径查找执行文件
|
||||
bool DesktopInfo::findExecutable(const QString &exec)
|
||||
{
|
||||
static const char *path = getenv("PATH");
|
||||
static QStringList paths = QString(path).split(':');
|
||||
return std::any_of(paths.begin(), paths.end(), [&exec](QString path) {return QFile::exists(path + '/' + exec);});
|
||||
}
|
||||
|
||||
QString DesktopInfo::getGenericName()
|
||||
{
|
||||
return getLocaleStr(MainSection, KeyGenericName);
|
||||
}
|
||||
|
||||
QString DesktopInfo::getName()
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
QString DesktopInfo::getIcon()
|
||||
{
|
||||
return m_icon;
|
||||
}
|
||||
|
||||
QString DesktopInfo::getCommandLine()
|
||||
{
|
||||
return m_desktopFile->value(MainSection + '/' + KeyExec).toString();
|
||||
}
|
||||
|
||||
QStringList DesktopInfo::getKeywords()
|
||||
{
|
||||
return m_desktopFile->value(MainSection + '/' + KeyKeywords).toStringList();
|
||||
}
|
||||
|
||||
QStringList DesktopInfo::getCategories()
|
||||
{
|
||||
return m_desktopFile->value(MainSection + '/' + KeyCategories).toStringList();
|
||||
}
|
||||
|
||||
QSettings *DesktopInfo::getDesktopFile()
|
||||
{
|
||||
return m_desktopFile.data();
|
||||
}
|
||||
|
||||
QString DesktopInfo::getId()
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
QString DesktopInfo::getLocaleStr(const QString §ion, const QString &key)
|
||||
{
|
||||
QString currentLanguageCode = QLocale::system().name();
|
||||
QString res = m_desktopFile->value(section + '/' + key + QString("[%1]").arg(currentLanguageCode)).toString();
|
||||
if (res.isEmpty()) res = m_desktopFile->value(section + '/' + key).toString();
|
||||
return res;
|
||||
}
|
109
frame/taskmanager/desktopinfo.h
Normal file
109
frame/taskmanager/desktopinfo.h
Normal file
@ -0,0 +1,109 @@
|
||||
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#ifndef DESKTOPINFO_H
|
||||
#define DESKTOPINFO_H
|
||||
|
||||
#include <QSettings>
|
||||
#include <qscopedpointer.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
const QString MainSection = "Desktop Entry";
|
||||
const QString KeyType = "Type";
|
||||
const QString KeyVersion = "Version";
|
||||
const QString KeyName = "Name";
|
||||
const QString KeyGenericName = "GenericName";
|
||||
const QString KeyNoDisplay = "NoDisplay";
|
||||
const QString KeyComment = "Comment";
|
||||
const QString KeyIcon = "Icon";
|
||||
const QString KeyHidden = "Hidden";
|
||||
const QString KeyOnlyShowIn = "OnlyShowIn";
|
||||
const QString KeyNotShowIn = "NotShowIn";
|
||||
const QString KeyTryExec = "TryExec";
|
||||
const QString KeyExec = "Exec";
|
||||
const QString KeyPath = "Path";
|
||||
const QString KeyTerminal = "Terminal";
|
||||
const QString KeyMimeType = "MimeType";
|
||||
const QString KeyCategories = "Categories";
|
||||
const QString KeyKeywords = "Keywords";
|
||||
const QString KeyStartupNotify = "StartupNotify";
|
||||
const QString KeyStartupWMClass = "StartupWMClass";
|
||||
const QString KeyURL = "URL";
|
||||
const QString KeyActions = "Actions";
|
||||
const QString KeyDBusActivatable = "DBusActivatable";
|
||||
|
||||
const QString TypeApplication = "Application";
|
||||
const QString TypeLink = "Link";
|
||||
const QString TypeDirectory = "Directory";
|
||||
|
||||
typedef struct DesktopAction
|
||||
{
|
||||
DesktopAction()
|
||||
: section("")
|
||||
, name("")
|
||||
, exec("")
|
||||
{
|
||||
}
|
||||
QString section;
|
||||
QString name;
|
||||
QString exec;
|
||||
} DesktopAction;
|
||||
|
||||
// 应用Desktop信息类
|
||||
class DesktopInfo {
|
||||
public:
|
||||
explicit DesktopInfo(const QString &desktopfile);
|
||||
~DesktopInfo();
|
||||
|
||||
static bool isDesktopAction(const QString &name);
|
||||
static DesktopInfo getDesktopInfoById(const QString &appId);
|
||||
|
||||
bool shouldShow();
|
||||
bool getIsHidden();
|
||||
bool isInstalled();
|
||||
bool getTerminal();
|
||||
bool getNoDisplay();
|
||||
bool isExecutableOk();
|
||||
bool isValidDesktop();
|
||||
bool getShowIn(QStringList desktopEnvs);
|
||||
|
||||
void setDesktopOverrideExec(const QString &execStr);
|
||||
|
||||
QString getId();
|
||||
QString getName();
|
||||
QString getIcon();
|
||||
QString getExecutable();
|
||||
QString getGenericName();
|
||||
QString getCommandLine();
|
||||
QString getDesktopFilePath();
|
||||
|
||||
QStringList getKeywords();
|
||||
QStringList getCategories();
|
||||
|
||||
QList<DesktopAction> getActions();
|
||||
|
||||
QSettings *getDesktopFile();
|
||||
|
||||
private:
|
||||
bool findExecutable(const QString &exec);
|
||||
QString getTryExec();
|
||||
QString getLocaleStr(const QString §ion, const QString &key);
|
||||
|
||||
private:
|
||||
static QStringList currentDesktops;
|
||||
|
||||
bool m_isValid;
|
||||
bool m_isInstalled;
|
||||
|
||||
QString m_id;
|
||||
QString m_name;
|
||||
QString m_icon;
|
||||
QString m_desktopFilePath;
|
||||
|
||||
// Desktopfile ini format
|
||||
QScopedPointer<QSettings> m_desktopFile;
|
||||
|
||||
};
|
||||
#endif // DESKTOPINFO_H
|
351
frame/taskmanager/entries.cpp
Normal file
351
frame/taskmanager/entries.cpp
Normal file
@ -0,0 +1,351 @@
|
||||
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "entries.h"
|
||||
#include "taskmanager.h"
|
||||
#include "docksettings.h"
|
||||
#include "taskmanager/windowinfobase.h"
|
||||
|
||||
#include <QList>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
||||
Entries::Entries(TaskManager *_taskmanager)
|
||||
: m_taskmanager(_taskmanager)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QVector<Entry *> Entries::filterDockedEntries()
|
||||
{
|
||||
QVector<Entry *> ret;
|
||||
for (auto entry : m_items) {
|
||||
if (entry->isValid() && entry->getIsDocked()) ret.push_back(entry);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
Entry *Entries::getByInnerId(QString innerId)
|
||||
{
|
||||
Entry *ret = nullptr;
|
||||
for (auto &entry : m_items) {
|
||||
if (entry->getInnerId() == innerId)
|
||||
ret = entry;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Entries::append(Entry *entry)
|
||||
{
|
||||
insert(entry, -1);
|
||||
}
|
||||
|
||||
void Entries::insert(Entry *entry, int index)
|
||||
{
|
||||
// 如果当前应用在列表中存在(通常是该应用为最近打开应用但是关闭了最近打开应用的接口或者当前为高效模式)
|
||||
if (m_items.contains(entry))
|
||||
m_items.removeOne(entry);
|
||||
|
||||
if (index < 0 || index >= m_items.size()) {
|
||||
// append
|
||||
index = m_items.size();
|
||||
m_items.push_back(entry);
|
||||
} else {
|
||||
// insert
|
||||
m_items.insert(index, entry);
|
||||
}
|
||||
|
||||
insertCb(entry, index);
|
||||
}
|
||||
|
||||
void Entries::remove(Entry *entry)
|
||||
{
|
||||
for (auto iter = m_items.begin(); iter != m_items.end();) {
|
||||
if ((*iter)->getId() == entry->getId()) {
|
||||
iter = m_items.erase(iter);
|
||||
} else {
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
|
||||
removeCb(entry);
|
||||
entry->deleteLater();
|
||||
}
|
||||
|
||||
void Entries::move(int oldIndex, int newIndex)
|
||||
{
|
||||
if (oldIndex == newIndex || oldIndex < 0 || newIndex < 0 || oldIndex >= m_items.size() || newIndex >= m_items.size())
|
||||
return;
|
||||
|
||||
m_items.swapItemsAt(oldIndex, newIndex);
|
||||
}
|
||||
|
||||
Entry *Entries::getByWindowPid(int pid)
|
||||
{
|
||||
Entry *ret = nullptr;
|
||||
for (auto &entry : m_items) {
|
||||
if (entry->getWindowInfoByPid(pid)) {
|
||||
ret = entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
QStringList Entries::getEntryIDs()
|
||||
{
|
||||
QStringList list;
|
||||
if (m_taskmanager->getDisplayMode() == DisplayMode::Fashion
|
||||
&& DockSettings::instance()->showRecent()) {
|
||||
for (Entry *item : m_items) list << item->getId();
|
||||
} else {
|
||||
// 如果是高效模式或者没有开启显示最近应用的功能,那么未驻留并且没有子窗口的就不显示
|
||||
// 换句话说,只显示已经驻留或者有子窗口的应用
|
||||
for (Entry *item : m_items) {
|
||||
if (item->getIsDocked() || item->hasWindow())
|
||||
list << item->getId();
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
Entry *Entries::getByWindowId(XWindow windowId)
|
||||
{
|
||||
Entry *ret = nullptr;
|
||||
for (auto &entry : m_items) {
|
||||
if (entry->getWindowInfoByWinId(windowId)) {
|
||||
ret = entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Entry *Entries::getByDesktopFilePath(const QString &filePath)
|
||||
{
|
||||
Entry *ret = nullptr;
|
||||
for (auto &entry : m_items) {
|
||||
qDebug() << entry->getName();
|
||||
if (entry->getFileName() == filePath) {
|
||||
ret = entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
QList<Entry*> Entries::getEntries()
|
||||
{
|
||||
QList<Entry*> list;
|
||||
if (static_cast<DisplayMode>(m_taskmanager->getDisplayMode()) == DisplayMode::Fashion
|
||||
&& DockSettings::instance()->showRecent()) {
|
||||
for (Entry *item : m_items)
|
||||
list << item;
|
||||
} else {
|
||||
// 如果是高效模式或者没有开启显示最近应用的功能,那么未驻留并且没有子窗口的就不显示
|
||||
// 换句话说,只显示已经驻留或者有子窗口的应用
|
||||
for (Entry *item : m_items) {
|
||||
if (!item->getIsDocked() && !item->hasWindow())
|
||||
continue;
|
||||
list << item;
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
Entry *Entries::getDockedEntryByDesktopFile(const QString &desktopFile)
|
||||
{
|
||||
QFileInfo desktopFileInfo(desktopFile);
|
||||
|
||||
Entry *ret = nullptr;
|
||||
for (auto entry : filterDockedEntries()) {
|
||||
if ((entry->isValid()) && desktopFileInfo.canonicalFilePath() == entry->getFileName()) {
|
||||
ret = entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
QString Entries::queryWindowIdentifyMethod(XWindow windowId)
|
||||
{
|
||||
QString ret;
|
||||
for (auto entry : m_items) {
|
||||
auto window = entry->getWindowInfoByWinId(windowId);
|
||||
if (window) {
|
||||
auto app = window->getAppInfo();
|
||||
ret = app ? app->getIdentifyMethod() : "Failed";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Entries::handleActiveWindowChanged(XWindow activeWindId)
|
||||
{
|
||||
for (auto entry : m_items) {
|
||||
auto windowInfo = entry->getWindowInfoByWinId(activeWindId);
|
||||
if (windowInfo) {
|
||||
entry->setPropIsActive(true);
|
||||
entry->setCurrentWindowInfo(windowInfo);
|
||||
entry->updateName();
|
||||
entry->updateIcon();
|
||||
} else {
|
||||
entry->setPropIsActive(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Entries::updateEntriesMenu()
|
||||
{
|
||||
for (auto entry : m_items) {
|
||||
entry->updateMenu();
|
||||
}
|
||||
}
|
||||
|
||||
const QList<Entry *> Entries::unDockedEntries() const
|
||||
{
|
||||
QList<Entry *> entrys;
|
||||
for (Entry *entry : m_items) {
|
||||
if (!entry->isValid() || entry->getIsDocked())
|
||||
continue;
|
||||
|
||||
entrys << entry;
|
||||
}
|
||||
|
||||
return entrys;
|
||||
}
|
||||
|
||||
void Entries::moveEntryToLast(Entry *entry)
|
||||
{
|
||||
if (m_items.contains(entry)) {
|
||||
m_items.removeOne(entry);
|
||||
m_items << entry;
|
||||
}
|
||||
}
|
||||
|
||||
void Entries::insertCb(Entry *entry, int index)
|
||||
{
|
||||
if (entry->getIsDocked() || entry->hasWindow() ||
|
||||
((m_taskmanager->getDisplayMode() == DisplayMode::Fashion) && DockSettings::instance()->showRecent())){
|
||||
Q_EMIT m_taskmanager->entryAdded(entry, index);
|
||||
}
|
||||
}
|
||||
|
||||
void Entries::removeCb(Entry *entry)
|
||||
{
|
||||
Q_EMIT m_taskmanager->entryRemoved(entry->getId());
|
||||
}
|
||||
|
||||
bool Entries::shouldInRecent()
|
||||
{
|
||||
// 如果当前移除的应用是未驻留应用,则判断未驻留应用的数量是否小于等于3,则让其始终显示
|
||||
QList<Entry *> unDocktrys;
|
||||
for (Entry *entry : m_items) {
|
||||
if (entry->isValid() && !entry->getIsDocked())
|
||||
unDocktrys << entry;
|
||||
}
|
||||
|
||||
// 如果当前未驻留应用的数量小于3个,则认为后续的应用应该显示到最近打开应用
|
||||
return (unDocktrys.size() <= MAX_UNOPEN_RECENT_COUNT);
|
||||
}
|
||||
|
||||
void Entries::removeLastRecent()
|
||||
{
|
||||
// 先查找最近使用的应用,删除没有使用的
|
||||
int unDockCount = 0;
|
||||
QList<Entry *> unDockEntrys;
|
||||
QList<Entry *> removeEntrys;
|
||||
|
||||
for (Entry *entry : m_items) {
|
||||
if (entry->getIsDocked())
|
||||
continue;
|
||||
|
||||
// 此处只移除没有子窗口的图标
|
||||
if (!entry->hasWindow()) {
|
||||
if (!entry->isValid())
|
||||
removeEntrys << entry; // 如果应用已经被卸载,那么需要删除
|
||||
else
|
||||
unDockEntrys << entry;
|
||||
}
|
||||
|
||||
unDockCount++;
|
||||
}
|
||||
if (unDockCount >= MAX_UNOPEN_RECENT_COUNT && unDockEntrys.size() > 0) {
|
||||
// 只有当最近使用区域的图标大于等于某个数值(3)的时候,并且存在没有子窗口的Entry,那么就移除该Entry
|
||||
Entry *entry = unDockEntrys[0];
|
||||
removeEntrys << entry;
|
||||
}
|
||||
for (Entry *entry : removeEntrys) {
|
||||
m_items.removeOne(entry);
|
||||
removeCb(entry);
|
||||
entry->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
void Entries::setDisplayMode(DisplayMode displayMode)
|
||||
{
|
||||
if (!DockSettings::instance()->showRecent())
|
||||
return;
|
||||
|
||||
// 如果从时尚模式变成高效模式,对列表中所有的没有打开窗口的应用发送移除信号
|
||||
if (displayMode == DisplayMode::Efficient) {
|
||||
for (Entry *entry : m_items) {
|
||||
entry->updateMode();
|
||||
if (!entry->getIsDocked() && !entry->hasWindow())
|
||||
Q_EMIT m_taskmanager->entryRemoved(entry->getId());
|
||||
}
|
||||
} else {
|
||||
// 如果从高效模式变成时尚模式,列表中所有的未驻留且不存在打开窗口的应用认为是最近打开应用,发送新增信号
|
||||
for (Entry *entry : m_items) {
|
||||
entry->updateMode();
|
||||
if (!entry->getIsDocked() && !entry->hasWindow()) {
|
||||
// QString objPath = entry->path();
|
||||
int index = m_items.indexOf(entry);
|
||||
Q_EMIT m_taskmanager->entryAdded(entry, index);
|
||||
qDebug() << entry->getName();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Entries::updateShowRecent()
|
||||
{
|
||||
// 高效模式无需做任何操作
|
||||
if (static_cast<DisplayMode>(m_taskmanager->getDisplayMode()) != DisplayMode::Fashion)
|
||||
return;
|
||||
|
||||
bool showRecent = DockSettings::instance()->showRecent();
|
||||
if (showRecent) {
|
||||
// 如果显示最近打开应用,则发送新增信号
|
||||
for (Entry *entry : m_items) {
|
||||
// 已经驻留的或者有子窗口的本来就在任务栏上面,无需发送信号
|
||||
entry->updateMode();
|
||||
if (entry->getIsDocked() || entry->hasWindow())
|
||||
continue;
|
||||
|
||||
// QString objPath = entry->path();
|
||||
int index = m_items.indexOf(entry);
|
||||
Q_EMIT m_taskmanager->entryAdded(entry, index);
|
||||
}
|
||||
} else {
|
||||
// 如果是隐藏最近打开的应用,则发送移除的信号
|
||||
for (Entry *entry : m_items) {
|
||||
// 已经驻留的或者有子窗口的本来就在任务栏上面,无需发送信号
|
||||
entry->updateMode();
|
||||
if (entry->getIsDocked() || entry->hasWindow())
|
||||
continue;
|
||||
|
||||
Q_EMIT m_taskmanager->entryRemoved(entry->getId());
|
||||
}
|
||||
}
|
||||
}
|
62
frame/taskmanager/entries.h
Normal file
62
frame/taskmanager/entries.h
Normal file
@ -0,0 +1,62 @@
|
||||
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#ifndef ENTRIES_H
|
||||
#define ENTRIES_H
|
||||
|
||||
#include "entry.h"
|
||||
#include "constants.h"
|
||||
#include "taskmanager/windowinfobase.h"
|
||||
|
||||
#include <QVector>
|
||||
#include <QWeakPointer>
|
||||
#include <qlist.h>
|
||||
|
||||
#define MAX_UNOPEN_RECENT_COUNT 3
|
||||
|
||||
class TaskManager;
|
||||
|
||||
// 所有应用管理类
|
||||
class Entries
|
||||
{
|
||||
public:
|
||||
Entries(TaskManager *_taskmanager);
|
||||
|
||||
const QList<Entry *> unDockedEntries() const;
|
||||
|
||||
bool shouldInRecent();
|
||||
|
||||
void removeLastRecent();
|
||||
void updateShowRecent();
|
||||
void updateEntriesMenu();
|
||||
void append(Entry *entry);
|
||||
void remove(Entry *entry);
|
||||
void moveEntryToLast(Entry *entry);
|
||||
void insert(Entry *entry, int index);
|
||||
void move(int oldIndex, int newIndex);
|
||||
void setDisplayMode(Dock::DisplayMode displayMode);
|
||||
void handleActiveWindowChanged(XWindow activeWindId);
|
||||
|
||||
QString queryWindowIdentifyMethod(XWindow windowId);
|
||||
QStringList getEntryIDs();
|
||||
|
||||
Entry *getByWindowPid(int pid);
|
||||
Entry *getByInnerId(QString innerId);
|
||||
Entry *getByWindowId(XWindow windowId);
|
||||
Entry *getByDesktopFilePath(const QString &filePath);
|
||||
Entry *getDockedEntryByDesktopFile(const QString &desktopFile);
|
||||
|
||||
QList<Entry*> getEntries();
|
||||
QVector<Entry *> filterDockedEntries();
|
||||
|
||||
private:
|
||||
void insertCb(Entry *entry, int index);
|
||||
void removeCb(Entry *entry);
|
||||
|
||||
private:
|
||||
QList<Entry *> m_items;
|
||||
TaskManager *m_taskmanager;
|
||||
};
|
||||
|
||||
#endif // ENTRIES_H
|
883
frame/taskmanager/entry.cpp
Normal file
883
frame/taskmanager/entry.cpp
Normal file
@ -0,0 +1,883 @@
|
||||
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "entry.h"
|
||||
#include "docksettings.h"
|
||||
#include "xcbutils.h"
|
||||
#include "taskmanager.h"
|
||||
#include "processinfo.h"
|
||||
#include "windowinfomap.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QDBusInterface>
|
||||
|
||||
#include <algorithm>
|
||||
#include <signal.h>
|
||||
|
||||
#define XCB XCBUtils::instance()
|
||||
|
||||
Entry::Entry(TaskManager *_taskmanager, AppInfo *_app, QString _innerId, QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_isActive(false)
|
||||
, m_isDocked(false)
|
||||
, m_winIconPreferred(false)
|
||||
, m_innerId(_innerId)
|
||||
, m_adapterEntry(nullptr)
|
||||
, m_taskmanager(_taskmanager)
|
||||
, m_current(nullptr)
|
||||
, m_currentWindow(0)
|
||||
{
|
||||
setAppInfo(_app);
|
||||
m_id = m_taskmanager->allocEntryId();
|
||||
m_mode = getCurrentMode();
|
||||
m_name = getName();
|
||||
m_icon = getIcon();
|
||||
}
|
||||
|
||||
Entry::~Entry()
|
||||
{
|
||||
for (auto winInfo : m_windowInfoMap) {
|
||||
if (winInfo) winInfo->deleteLater();
|
||||
}
|
||||
m_windowInfoMap.clear();
|
||||
|
||||
}
|
||||
|
||||
bool Entry::isValid()
|
||||
{
|
||||
// desktopfile 无效时且没有窗口时,该entry是无效的
|
||||
// 虽然也就是desktop是无效时,但是当前存在窗口,该entry也是有效的。
|
||||
return m_isValid || m_current;
|
||||
}
|
||||
|
||||
QString Entry::getId() const
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
QString Entry::getName()
|
||||
{
|
||||
QString ret = m_current ? m_current->getDisplayName() : QString();
|
||||
if (m_appInfo.isNull()) return ret;
|
||||
ret = m_appInfo->getName();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Entry::updateName()
|
||||
{
|
||||
setPropName(getName());
|
||||
}
|
||||
|
||||
QString Entry::getIcon()
|
||||
{
|
||||
QString ret;
|
||||
if (hasWindow()) {
|
||||
if (!m_current) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
// has window && current not nullptr
|
||||
if (m_winIconPreferred) {
|
||||
// try current window icon first
|
||||
ret = m_current->getIcon();
|
||||
if (ret.size() > 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_appInfo) {
|
||||
m_icon = m_appInfo->getIcon();
|
||||
if (m_icon.size() > 0) {
|
||||
return m_icon;
|
||||
}
|
||||
}
|
||||
|
||||
return m_current->getIcon();
|
||||
}
|
||||
|
||||
if (m_appInfo) {
|
||||
// no window
|
||||
return m_appInfo->getIcon();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
QString Entry::getInnerId()
|
||||
{
|
||||
return m_innerId;
|
||||
}
|
||||
|
||||
void Entry::setInnerId(QString _innerId)
|
||||
{
|
||||
qDebug() << "setting innerID from: " << m_innerId << " to: " << _innerId;
|
||||
m_innerId = _innerId;
|
||||
}
|
||||
|
||||
QString Entry::getFileName()
|
||||
{
|
||||
return m_appInfo.isNull() ? QString() : m_appInfo->getFileName();
|
||||
}
|
||||
|
||||
AppInfo *Entry::getAppInfo()
|
||||
{
|
||||
return m_appInfo.data();
|
||||
}
|
||||
|
||||
void Entry::setAppInfo(AppInfo *appinfo)
|
||||
{
|
||||
if (m_appInfo.data() == appinfo || appinfo == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_appInfo.reset(appinfo);
|
||||
m_isValid = appinfo->isValidApp();
|
||||
m_winIconPreferred = !appinfo;
|
||||
setPropDesktopFile(appinfo ? appinfo->getFileName(): "");
|
||||
if (!m_winIconPreferred) {
|
||||
QString id = m_appInfo->getId();
|
||||
auto perferredApps = m_taskmanager->getWinIconPreferredApps();
|
||||
if (perferredApps.contains(id)|| appinfo->getIcon().size() == 0) {
|
||||
m_winIconPreferred = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Entry::getIsDocked() const
|
||||
{
|
||||
return m_isDocked;
|
||||
}
|
||||
|
||||
void Entry::setIsDocked(bool value)
|
||||
{
|
||||
if (value != m_isDocked) {
|
||||
m_isDocked = value;
|
||||
Q_EMIT isDockedChanged(value);
|
||||
}
|
||||
}
|
||||
|
||||
void Entry::setMenu(AppMenu *_menu)
|
||||
{
|
||||
_menu->setDirtyStatus(true);
|
||||
m_appMenu.reset(_menu);
|
||||
Q_EMIT menuChanged(m_appMenu->getMenuJsonStr());
|
||||
}
|
||||
|
||||
void Entry::updateMenu()
|
||||
{
|
||||
qInfo() <<"Entry: updateMenu";
|
||||
AppMenu *appMenu = new AppMenu();
|
||||
appMenu->appendItem(getMenuItemLaunch());
|
||||
|
||||
for (auto &item :getMenuItemDesktopActions())
|
||||
appMenu->appendItem(item);
|
||||
|
||||
if (hasWindow())
|
||||
appMenu->appendItem(getMenuItemAllWindows());
|
||||
|
||||
// menu item dock or undock
|
||||
qInfo() << "entry " << m_id << " docked? " << m_isDocked;
|
||||
appMenu->appendItem(m_isDocked? getMenuItemUndock(): getMenuItemDock());
|
||||
|
||||
if (hasWindow()) {
|
||||
if (m_taskmanager->getForceQuitAppStatus() != ForceQuitAppMode::Disabled) {
|
||||
appMenu->appendItem(m_appInfo && m_appInfo->getIdentifyMethod() == "Andriod" ?
|
||||
getMenuItemForceQuitAndroid() : getMenuItemForceQuit());
|
||||
}
|
||||
|
||||
if (getAllowedCloseWindows().size() > 0)
|
||||
appMenu->appendItem(getMenuItemCloseAll());
|
||||
}
|
||||
|
||||
setMenu(appMenu);
|
||||
}
|
||||
|
||||
void Entry::updateIcon()
|
||||
{
|
||||
setPropIcon(getIcon());
|
||||
}
|
||||
|
||||
int Entry::getCurrentMode()
|
||||
{
|
||||
// 只要当前应用是已经驻留的应用,则让其显示为Normal
|
||||
if (getIsDocked())
|
||||
return ENTRY_NORMAL;
|
||||
|
||||
// 对于未驻留的应用则做如下处理
|
||||
if (m_taskmanager->getDisplayMode() == DisplayMode::Efficient) {
|
||||
// 高效模式下,只有存在子窗口的,则让其为nornal,没有子窗口的,一般不让其显示
|
||||
return hasWindow() ? ENTRY_NORMAL : ENTRY_NONE;
|
||||
}
|
||||
// 时尚模式下对未驻留应用做如下处理
|
||||
// 如果开启了最近打开应用的功能,则显示到最近打开区域(ENTRY_RECENT)
|
||||
if (DockSettings::instance()->showRecent())
|
||||
return ENTRY_RECENT;
|
||||
|
||||
// 未开启最近使用应用的功能,如果有子窗口,则显示成通用的(ENTRY_NORMAL),如果没有子窗口,则不显示(ENTRY_NONE)
|
||||
return hasWindow() ? ENTRY_NORMAL : ENTRY_NONE;
|
||||
}
|
||||
|
||||
void Entry::updateMode()
|
||||
{
|
||||
int currentMode = getCurrentMode();
|
||||
if (m_mode != currentMode) {
|
||||
m_mode = currentMode;
|
||||
Q_EMIT modeChanged(m_mode);
|
||||
}
|
||||
}
|
||||
|
||||
void Entry::forceUpdateIcon()
|
||||
{
|
||||
m_icon = getIcon();
|
||||
Q_EMIT iconChanged(m_icon);
|
||||
}
|
||||
|
||||
void Entry::updateIsActive()
|
||||
{
|
||||
bool isActive = false;
|
||||
auto activeWin = m_taskmanager->getActiveWindow();
|
||||
if (activeWin) {
|
||||
// 判断活跃窗口是否属于当前应用
|
||||
isActive = m_windowInfoMap.find(activeWin->getXid()) != m_windowInfoMap.end();
|
||||
}
|
||||
|
||||
setPropIsActive(isActive);
|
||||
}
|
||||
|
||||
WindowInfoBase *Entry::getWindowInfoByPid(int pid)
|
||||
{
|
||||
for (const auto &windowInfo : m_windowInfoMap) {
|
||||
if (windowInfo->getPid() == pid)
|
||||
return windowInfo;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
WindowInfoBase *Entry::getWindowInfoByWinId(XWindow windowId)
|
||||
{
|
||||
if (m_windowInfoMap.find(windowId) != m_windowInfoMap.end())
|
||||
return m_windowInfoMap[windowId];
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Entry::setPropIcon(QString value)
|
||||
{
|
||||
if (value != m_icon) {
|
||||
m_icon = value;
|
||||
Q_EMIT iconChanged(value);
|
||||
}
|
||||
}
|
||||
|
||||
void Entry::setPropName(QString value)
|
||||
{
|
||||
if (value != m_name) {
|
||||
m_name = value;
|
||||
Q_EMIT nameChanged(value);
|
||||
}
|
||||
}
|
||||
|
||||
void Entry::setPropIsActive(bool active)
|
||||
{
|
||||
if (m_isActive != active) {
|
||||
m_isActive = active;
|
||||
Q_EMIT isActiveChanged(active);
|
||||
}
|
||||
}
|
||||
|
||||
void Entry::setCurrentWindowInfo(WindowInfoBase *windowInfo)
|
||||
{
|
||||
m_current = windowInfo;
|
||||
setPropCurrentWindow(m_current ? m_current->getXid() : 0);
|
||||
}
|
||||
|
||||
void Entry::setPropCurrentWindow(XWindow value)
|
||||
{
|
||||
if (value != m_currentWindow) {
|
||||
m_currentWindow = value;
|
||||
Q_EMIT currentWindowChanged(value);
|
||||
}
|
||||
}
|
||||
|
||||
WindowInfoBase *Entry::getCurrentWindowInfo()
|
||||
{
|
||||
return m_current;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Entry::findNextLeader
|
||||
* @return
|
||||
*/
|
||||
WindowInfoBase *Entry::findNextLeader()
|
||||
{
|
||||
auto xids = m_windowInfoMap.keys();
|
||||
std::sort(xids.begin(), xids.end());
|
||||
XWindow curWinId = m_current->getXid();
|
||||
int index = xids.indexOf(curWinId);
|
||||
if (index < 0)
|
||||
return nullptr;
|
||||
|
||||
// 如果当前窗口是最大, 返回xids[0], 否则返回xids[index + 1]
|
||||
int nextIndex = 0;
|
||||
if (index < xids.size() - 1)
|
||||
nextIndex = index + 1;
|
||||
|
||||
return m_windowInfoMap[xids[nextIndex]];
|
||||
}
|
||||
|
||||
QString Entry::getExec()
|
||||
{
|
||||
if (!m_current)
|
||||
return "";
|
||||
|
||||
ProcessInfo *process = m_current->getProcess();
|
||||
return process->getExe();
|
||||
}
|
||||
|
||||
QString Entry::getCmdLine()
|
||||
{
|
||||
QString ret;
|
||||
if (!m_current) return ret;
|
||||
|
||||
ProcessInfo *process = m_current->getProcess();
|
||||
for (auto i : process->getCmdLine()) ret += i + " ";
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
bool Entry::hasWindow()
|
||||
{
|
||||
return m_windowInfoMap.size() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Entry::updateExportWindowInfos 同步更新导出窗口信息
|
||||
*/
|
||||
void Entry::updateExportWindowInfos()
|
||||
{
|
||||
WindowInfoMap infos;
|
||||
for (auto info : m_windowInfoMap) {
|
||||
WindowInfo winInfo;
|
||||
XWindow xid = info->getXid();
|
||||
winInfo.title = info->getTitle();
|
||||
winInfo.attention = info->isDemandingAttention();
|
||||
winInfo.uuid = info->uuid();
|
||||
infos[xid] = winInfo;
|
||||
}
|
||||
|
||||
bool changed = true;
|
||||
if (infos.size() == m_exportWindowInfos.size()) {
|
||||
changed = false;
|
||||
for (auto iter = infos.begin(); iter != infos.end(); iter++) {
|
||||
XWindow xid = iter.key();
|
||||
if (infos[xid].title != m_exportWindowInfos[xid].title ||
|
||||
infos[xid].attention != m_exportWindowInfos[xid].attention ||
|
||||
infos[xid].uuid != m_exportWindowInfos[xid].uuid) {
|
||||
changed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
Q_EMIT windowInfosChanged(infos);
|
||||
}
|
||||
|
||||
// 更新导出的窗口信息
|
||||
m_exportWindowInfos = infos;
|
||||
}
|
||||
|
||||
// 分离窗口, 返回是否需要从任务栏remove
|
||||
bool Entry::detachWindow(WindowInfoBase *info)
|
||||
{
|
||||
info->setEntry(nullptr);
|
||||
XWindow winId = info->getXid();
|
||||
if (m_windowInfoMap.contains(winId)) {
|
||||
m_windowInfoMap.remove(winId);
|
||||
info->deleteLater();
|
||||
}
|
||||
|
||||
if (m_windowInfoMap.isEmpty()) {
|
||||
if (!m_isDocked) {
|
||||
// 既无窗口也非驻留应用,并且不是最近打开,无需在任务栏显示
|
||||
return true;
|
||||
}
|
||||
|
||||
Q_EMIT windowInfosChanged(WindowInfoMap());
|
||||
setCurrentWindowInfo(nullptr);
|
||||
} else {
|
||||
for (auto window : m_windowInfoMap) {
|
||||
if (window) { // 选择第一个窗口作为当前窗口
|
||||
setCurrentWindowInfo(window);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateExportWindowInfos();
|
||||
updateIcon();
|
||||
updateMenu();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Entry::isShowOnDock() const
|
||||
{
|
||||
// 当前应用显示图标的条件是
|
||||
// 如果该图标已经固定在任务栏上,则始终显示
|
||||
if (getIsDocked())
|
||||
return true;
|
||||
|
||||
// 1.时尚模式下,如果开启了显示最近使用,则不管是否有子窗口,都在任务栏上显示
|
||||
// 如果没有开启显示最近使用,则只显示有子窗口的
|
||||
if (m_taskmanager->getDisplayMode() == DisplayMode::Fashion)
|
||||
return (DockSettings::instance()->showRecent() || m_exportWindowInfos.size() > 0);
|
||||
|
||||
// 2.高效模式下,只有该应用有打开窗口才显示
|
||||
return m_exportWindowInfos.size() > 0;
|
||||
}
|
||||
|
||||
bool Entry::attachWindow(WindowInfoBase *info)
|
||||
{
|
||||
XWindow winId = info->getXid();
|
||||
qInfo() << "attatchWindow: window id:" << winId;
|
||||
info->setEntry(this);
|
||||
|
||||
if (m_windowInfoMap.find(winId) != m_windowInfoMap.end()) {
|
||||
qInfo() << "attachWindow: window " << winId << " is already attached";
|
||||
return false;
|
||||
}
|
||||
|
||||
bool lastShowOnDock = isShowOnDock();
|
||||
m_windowInfoMap[winId] = info;
|
||||
updateExportWindowInfos();
|
||||
updateIsActive();
|
||||
|
||||
if (!m_current) {
|
||||
// from no window to has window
|
||||
setCurrentWindowInfo(info);
|
||||
}
|
||||
|
||||
updateIcon();
|
||||
updateMenu();
|
||||
|
||||
if (!lastShowOnDock && isShowOnDock()) {
|
||||
// 新打开的窗口始终显示到最后
|
||||
Q_EMIT m_taskmanager->entryAdded(this, -1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Entry::launchApp(uint32_t timestamp)
|
||||
{
|
||||
if (m_appInfo)
|
||||
m_taskmanager->launchApp(m_appInfo->getFileName(), timestamp, QStringList());
|
||||
}
|
||||
|
||||
bool Entry::containsWindow(XWindow xid)
|
||||
{
|
||||
return m_windowInfoMap.find(xid) != m_windowInfoMap.end();
|
||||
}
|
||||
|
||||
// 处理菜单项
|
||||
void Entry::handleMenuItem(uint32_t timestamp, QString itemId)
|
||||
{
|
||||
m_appMenu->handleAction(timestamp, itemId);
|
||||
}
|
||||
|
||||
// 处理拖拽事件
|
||||
void Entry::handleDragDrop(uint32_t timestamp, QStringList files)
|
||||
{
|
||||
m_taskmanager->launchApp(m_appInfo->getFileName(), timestamp, files);
|
||||
}
|
||||
|
||||
// 驻留
|
||||
void Entry::requestDock(bool dockToEnd)
|
||||
{
|
||||
if (m_taskmanager->dockEntry(this, dockToEnd)) {
|
||||
m_taskmanager->saveDockedApps();
|
||||
}
|
||||
}
|
||||
|
||||
// 取消驻留
|
||||
void Entry::requestUndock(bool dockToEnd)
|
||||
{
|
||||
m_taskmanager->undockEntry(this, dockToEnd);
|
||||
}
|
||||
|
||||
void Entry::newInstance(uint32_t timestamp)
|
||||
{
|
||||
QStringList files;
|
||||
m_taskmanager->launchApp(m_appInfo->getFileName(), timestamp, files);
|
||||
}
|
||||
|
||||
// 检查应用窗口分离、合并状态
|
||||
void Entry::check()
|
||||
{
|
||||
QList<WindowInfoBase *> windows = m_windowInfoMap.values();
|
||||
for (WindowInfoBase *window : windows) {
|
||||
m_taskmanager->attachOrDetachWindow(window);
|
||||
}
|
||||
}
|
||||
|
||||
// 强制退出
|
||||
void Entry::forceQuit()
|
||||
{
|
||||
QMap<int, QVector<WindowInfoBase*>> pidWinInfoMap;
|
||||
QList<WindowInfoBase *> windows = m_windowInfoMap.values();
|
||||
for (WindowInfoBase *window : windows) {
|
||||
int pid = window->getPid();
|
||||
if (pid != 0) {
|
||||
pidWinInfoMap[pid].push_back(window);
|
||||
} else {
|
||||
window->killClient();
|
||||
}
|
||||
}
|
||||
|
||||
for (auto iter = pidWinInfoMap.begin(); iter != pidWinInfoMap.end(); iter++) {
|
||||
if (!killProcess(iter.key())) { // kill pid
|
||||
for (auto &info : iter.value()) { // kill window
|
||||
info->killClient();
|
||||
}
|
||||
}
|
||||
}
|
||||
// 所有的窗口已经退出后,清空m_windowInfoMap内容
|
||||
m_windowInfoMap.clear();
|
||||
// 退出所有的进程后,及时更新当前剩余的窗口数量
|
||||
updateExportWindowInfos();
|
||||
m_taskmanager->removeEntryFromDock(this);
|
||||
}
|
||||
|
||||
void Entry::presentWindows()
|
||||
{
|
||||
QList<uint> windows = m_windowInfoMap.keys();
|
||||
m_taskmanager->presentWindows(windows);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Entry::active 激活窗口
|
||||
* @param timestamp
|
||||
*/
|
||||
void Entry::active(uint32_t timestamp)
|
||||
{
|
||||
if (m_taskmanager->getHideMode() == HideMode::SmartHide) {
|
||||
m_taskmanager->setPropHideState(HideState::Show);
|
||||
m_taskmanager->updateHideState(false);
|
||||
}
|
||||
|
||||
// 无窗口则直接启动
|
||||
if (!hasWindow()) {
|
||||
launchApp(timestamp);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_current) {
|
||||
qWarning() << "active: current window is nullptr";
|
||||
return;
|
||||
}
|
||||
|
||||
WindowInfoBase *winInfo = m_current;
|
||||
if (m_taskmanager->isWaylandEnv()) {
|
||||
// wayland环境
|
||||
if (!m_taskmanager->isActiveWindow(winInfo)) {
|
||||
winInfo->activate();
|
||||
} else {
|
||||
bool showing = m_taskmanager->isShowingDesktop();
|
||||
if (showing || winInfo->isMinimized()) {
|
||||
winInfo->activate();
|
||||
} else if (m_windowInfoMap.size() == 1) {
|
||||
winInfo->minimize();
|
||||
} else {
|
||||
WindowInfoBase *nextWin = findNextLeader();
|
||||
if (nextWin) {
|
||||
nextWin->activate();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// X11环境
|
||||
XWindow xid = winInfo->getXid();
|
||||
WindowInfoBase *activeWin = m_taskmanager->getActiveWindow();
|
||||
if (activeWin && xid != activeWin->getXid()) {
|
||||
m_taskmanager->doActiveWindow(xid);
|
||||
} else {
|
||||
bool found = false;
|
||||
XWindow hiddenAtom = XCB->getAtom("_NET_WM_STATE_HIDDEN");
|
||||
for (auto state : XCB->getWMState(xid)) {
|
||||
if (hiddenAtom == state) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
// 激活隐藏窗口
|
||||
m_taskmanager->doActiveWindow(xid);
|
||||
} else if (m_windowInfoMap.size() == 1) {
|
||||
// 窗口图标化
|
||||
XCB->minimizeWindow(xid);
|
||||
} else if (m_taskmanager->getActiveWindow() && m_taskmanager->getActiveWindow()->getXid() == xid) {
|
||||
WindowInfoBase *nextWin = findNextLeader();
|
||||
if (nextWin) {
|
||||
nextWin->activate();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Entry::activeWindow(quint32 winId)
|
||||
{
|
||||
if (m_taskmanager->isWaylandEnv()) {
|
||||
if (!m_windowInfoMap.contains(winId))
|
||||
return;
|
||||
|
||||
WindowInfoBase *winInfo = m_windowInfoMap[winId];
|
||||
if (m_taskmanager->isActiveWindow(winInfo)) {
|
||||
bool showing = m_taskmanager->isShowingDesktop();
|
||||
if (showing || winInfo->isMinimized()) {
|
||||
winInfo->activate();
|
||||
} else if (m_windowInfoMap.size() == 1) {
|
||||
winInfo->minimize();
|
||||
} else {
|
||||
WindowInfoBase *nextWin = findNextLeader();
|
||||
if (nextWin) {
|
||||
nextWin->activate();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
winInfo->activate();
|
||||
}
|
||||
} else {
|
||||
m_taskmanager->doActiveWindow(winId);
|
||||
}
|
||||
}
|
||||
|
||||
int Entry::mode()
|
||||
{
|
||||
return m_mode;
|
||||
}
|
||||
|
||||
XWindow Entry::getCurrentWindow()
|
||||
{
|
||||
return m_currentWindow;
|
||||
}
|
||||
|
||||
QString Entry::getDesktopFile()
|
||||
{
|
||||
return m_desktopFile;
|
||||
}
|
||||
|
||||
bool Entry::getIsActive() const
|
||||
{
|
||||
return m_isActive;
|
||||
}
|
||||
|
||||
QString Entry::getMenu() const
|
||||
{
|
||||
return m_appMenu->getMenuJsonStr();
|
||||
}
|
||||
|
||||
QVector<XWindow> Entry::getAllowedClosedWindowIds()
|
||||
{
|
||||
QVector<XWindow> ret;
|
||||
for (auto iter = m_windowInfoMap.begin(); iter != m_windowInfoMap.end(); iter++) {
|
||||
WindowInfoBase *info = iter.value();
|
||||
if (info && info->allowClose())
|
||||
ret.push_back(iter.key());
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
WindowInfoMap Entry::getExportWindowInfos()
|
||||
{
|
||||
return m_exportWindowInfos;
|
||||
}
|
||||
|
||||
QVector<WindowInfoBase *> Entry::getAllowedCloseWindows()
|
||||
{
|
||||
QVector<WindowInfoBase *> ret;
|
||||
for (auto iter = m_windowInfoMap.begin(); iter != m_windowInfoMap.end(); iter++) {
|
||||
WindowInfoBase *info = iter.value();
|
||||
if (info && info->allowClose()) {
|
||||
ret.push_back(info);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
QVector<AppMenuItem> Entry::getMenuItemDesktopActions()
|
||||
{
|
||||
QVector<AppMenuItem> ret;
|
||||
if (!m_appInfo) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (auto action : m_appInfo->getActions()) {
|
||||
AppMenuAction fn = [=](uint32_t timestamp) {
|
||||
qInfo() << "do MenuItem: " << action.name;
|
||||
m_taskmanager->launchAppAction(m_appInfo->getFileName(), action.section, timestamp);
|
||||
};
|
||||
|
||||
AppMenuItem item;
|
||||
item.text = action.name;
|
||||
item.action = fn;
|
||||
item.isActive = true;
|
||||
ret.push_back(item);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
AppMenuItem Entry::getMenuItemLaunch()
|
||||
{
|
||||
QString itemName;
|
||||
if (hasWindow()) {
|
||||
itemName = getName();
|
||||
} else {
|
||||
itemName = tr("Open");
|
||||
}
|
||||
|
||||
AppMenuAction fn = [this](uint32_t timestamp) {
|
||||
qInfo() << "do MenuItem: Open";
|
||||
this->launchApp(timestamp);
|
||||
};
|
||||
|
||||
AppMenuItem item;
|
||||
item.text = itemName;
|
||||
item.action = fn;
|
||||
item.isActive = true;
|
||||
return item;
|
||||
}
|
||||
|
||||
AppMenuItem Entry::getMenuItemCloseAll()
|
||||
{
|
||||
AppMenuAction fn = [this](uint32_t timestamp) {
|
||||
qInfo() << "do MenuItem: Close All";
|
||||
auto winInfos = getAllowedCloseWindows();
|
||||
|
||||
// 根据创建时间从大到小排序, 方便后续关闭窗口
|
||||
for (int i = 0; i < winInfos.size() - 1; i++) {
|
||||
for (int j = i + 1; j < winInfos.size(); j++) {
|
||||
if (winInfos[i]->getCreatedTime() < winInfos[j]->getCreatedTime()) {
|
||||
auto info = winInfos[i];
|
||||
winInfos[i] = winInfos[j];
|
||||
winInfos[j] = info;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto info : winInfos) {
|
||||
qInfo() << "close WindowId " << info->getXid();
|
||||
info->close(timestamp);
|
||||
}
|
||||
|
||||
// 关闭窗口后,主动刷新事件
|
||||
XCB->flush();
|
||||
};
|
||||
|
||||
AppMenuItem item;
|
||||
item.text = tr("Close All");
|
||||
item.action = fn;
|
||||
item.isActive = true;
|
||||
return item;
|
||||
}
|
||||
|
||||
AppMenuItem Entry::getMenuItemForceQuit()
|
||||
{
|
||||
bool active = m_taskmanager->getForceQuitAppStatus() != ForceQuitAppMode::Deactivated;
|
||||
AppMenuAction fn = [this](uint32_t) {
|
||||
qInfo() << "do MenuItem: Force Quit";
|
||||
forceQuit();
|
||||
};
|
||||
|
||||
AppMenuItem item;
|
||||
item.text = tr("Force Quit");
|
||||
item.action = fn;
|
||||
item.isActive = active;
|
||||
return item;
|
||||
}
|
||||
|
||||
//dock栏上Android程序的Force Quit功能
|
||||
AppMenuItem Entry::getMenuItemForceQuitAndroid()
|
||||
{
|
||||
bool active = m_taskmanager->getForceQuitAppStatus() != ForceQuitAppMode::Deactivated;
|
||||
auto allowedCloseWindows = getAllowedCloseWindows();
|
||||
AppMenuAction fn = [](uint32_t){};
|
||||
if (allowedCloseWindows.size() > 0) {
|
||||
qInfo() << "do MenuItem: Force Quit";
|
||||
AppMenuAction fn = [&](uint32_t timestamp) {
|
||||
for (auto info : allowedCloseWindows) {
|
||||
info->close(timestamp);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
AppMenuItem item;
|
||||
item.text = tr("Force Quit");
|
||||
item.action = fn;
|
||||
item.isActive = active;
|
||||
return item;
|
||||
}
|
||||
|
||||
AppMenuItem Entry::getMenuItemDock()
|
||||
{
|
||||
AppMenuItem item;
|
||||
item.text = tr("Dock");
|
||||
item.action = [this](uint32_t) {
|
||||
qInfo() << "do MenuItem: Dock";
|
||||
requestDock(true);
|
||||
};
|
||||
|
||||
item.isActive = true;
|
||||
return item;
|
||||
}
|
||||
|
||||
AppMenuItem Entry::getMenuItemUndock()
|
||||
{
|
||||
AppMenuItem item;
|
||||
item.text = tr("Undock");
|
||||
item.action = [this](uint32_t) {
|
||||
qInfo() << "do MenuItem: Undock";
|
||||
requestUndock(true);
|
||||
};
|
||||
|
||||
item.isActive = true;
|
||||
return item;
|
||||
}
|
||||
|
||||
AppMenuItem Entry::getMenuItemAllWindows()
|
||||
{
|
||||
AppMenuItem item;
|
||||
item.text = tr("All Windows");
|
||||
item.action = [this](uint32_t) {
|
||||
qInfo() << "do MenuItem: All Windows";
|
||||
presentWindows();
|
||||
};
|
||||
|
||||
item.isActive = true;
|
||||
item.hint = 1;
|
||||
return item;
|
||||
}
|
||||
|
||||
bool Entry::killProcess(int pid)
|
||||
{
|
||||
return !kill(pid, SIGTERM);
|
||||
}
|
||||
|
||||
bool Entry::setPropDesktopFile(QString value)
|
||||
{
|
||||
if (value != m_desktopFile) {
|
||||
m_desktopFile = value;
|
||||
Q_EMIT desktopFileChanged(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
156
frame/taskmanager/entry.h
Normal file
156
frame/taskmanager/entry.h
Normal file
@ -0,0 +1,156 @@
|
||||
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#ifndef ENTRY_H
|
||||
#define ENTRY_H
|
||||
|
||||
#include "appinfo.h"
|
||||
#include "appmenu.h"
|
||||
#include "windowinfomap.h"
|
||||
#include "windowinfobase.h"
|
||||
|
||||
#include <QMap>
|
||||
#include <QVector>
|
||||
#include <QObject>
|
||||
#include <qscopedpointer.h>
|
||||
|
||||
#define ENTRY_NONE 0
|
||||
#define ENTRY_NORMAL 1
|
||||
#define ENTRY_RECENT 2
|
||||
|
||||
// 单个应用类
|
||||
class TaskManager;
|
||||
class DBusAdaptorEntry;
|
||||
class WindowInfo;
|
||||
|
||||
typedef QMap<quint32, WindowInfo> WindowInfoMap;
|
||||
|
||||
class Entry: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
Entry(TaskManager *_taskmanager, AppInfo *_app, QString _innerId, QObject *parent = nullptr);
|
||||
~Entry();
|
||||
|
||||
void updateName();
|
||||
void updateMenu();
|
||||
void updateIcon();
|
||||
void updateMode();
|
||||
void updateIsActive();
|
||||
void forceUpdateIcon();
|
||||
void updateExportWindowInfos();
|
||||
void launchApp(uint32_t timestamp);
|
||||
|
||||
void setIsDocked(bool value);
|
||||
void setMenu(AppMenu *_menu);
|
||||
void setPropIcon(QString value);
|
||||
void setPropName(QString value);
|
||||
void setPropIsActive(bool active);
|
||||
void setInnerId(QString _innerId);
|
||||
void setAppInfo(AppInfo *appinfo);
|
||||
void setPropCurrentWindow(XWindow value);
|
||||
void setCurrentWindowInfo(WindowInfoBase *windowInfo);
|
||||
|
||||
void check();
|
||||
void forceQuit();
|
||||
void presentWindows();
|
||||
void active(uint32_t timestamp);
|
||||
void activeWindow(quint32 winId);
|
||||
void newInstance(uint32_t timestamp);
|
||||
void requestDock(bool dockToEnd = false);
|
||||
void requestUndock(bool dockToEnd = false);
|
||||
void handleMenuItem(uint32_t timestamp, QString itemId);
|
||||
void handleDragDrop(uint32_t timestamp, QStringList files);
|
||||
|
||||
bool containsWindow(XWindow xid);
|
||||
bool detachWindow(WindowInfoBase *info);
|
||||
bool attachWindow(WindowInfoBase *info);
|
||||
|
||||
bool getIsDocked() const;
|
||||
bool getIsActive() const;
|
||||
|
||||
QString getId() const;
|
||||
QString getMenu() const;
|
||||
|
||||
bool isValid();
|
||||
bool hasWindow();
|
||||
|
||||
int mode();
|
||||
|
||||
QString getName();
|
||||
QString getIcon();
|
||||
QString getInnerId();
|
||||
QString getFileName();
|
||||
QString getDesktopFile();
|
||||
QString getExec();
|
||||
QString getCmdLine();
|
||||
|
||||
XWindow getCurrentWindow();
|
||||
|
||||
AppInfo *getAppInfo();
|
||||
|
||||
WindowInfoBase *findNextLeader();
|
||||
WindowInfoBase *getCurrentWindowInfo();
|
||||
WindowInfoBase *getWindowInfoByPid(int pid);
|
||||
WindowInfoBase *getWindowInfoByWinId(XWindow windowId);
|
||||
|
||||
WindowInfoMap getExportWindowInfos();
|
||||
QVector<XWindow> getAllowedClosedWindowIds();
|
||||
|
||||
public Q_SLOTS:
|
||||
QVector<WindowInfoBase *> getAllowedCloseWindows();
|
||||
|
||||
Q_SIGNALS:
|
||||
void modeChanged(int);
|
||||
void isActiveChanged(bool);
|
||||
void isDockedChanged(bool);
|
||||
void menuChanged(QString);
|
||||
void iconChanged(QString);
|
||||
void nameChanged(QString);
|
||||
void desktopFileChanged(QString);
|
||||
void currentWindowChanged(uint32_t);
|
||||
void windowInfosChanged(const WindowInfoMap&);
|
||||
|
||||
private:
|
||||
// 右键菜单项
|
||||
bool killProcess(int pid);
|
||||
bool setPropDesktopFile(QString value);
|
||||
bool isShowOnDock() const;
|
||||
int getCurrentMode();
|
||||
|
||||
AppMenuItem getMenuItemLaunch();
|
||||
AppMenuItem getMenuItemCloseAll();
|
||||
AppMenuItem getMenuItemForceQuit();
|
||||
|
||||
AppMenuItem getMenuItemDock();
|
||||
AppMenuItem getMenuItemUndock();
|
||||
AppMenuItem getMenuItemAllWindows();
|
||||
AppMenuItem getMenuItemForceQuitAndroid();
|
||||
QVector<AppMenuItem> getMenuItemDesktopActions();
|
||||
|
||||
private:
|
||||
bool m_isActive;
|
||||
bool m_isValid;
|
||||
bool m_isDocked;
|
||||
bool m_winIconPreferred;
|
||||
int m_mode;
|
||||
|
||||
QString m_id;
|
||||
QString m_name;
|
||||
QString m_icon;
|
||||
QString m_innerId;
|
||||
QString m_desktopFile;
|
||||
|
||||
DBusAdaptorEntry *m_adapterEntry;
|
||||
TaskManager *m_taskmanager;
|
||||
WindowInfoMap m_exportWindowInfos; // 该应用导出的窗口属性
|
||||
WindowInfoBase *m_current; // 当前窗口
|
||||
XWindow m_currentWindow; //当前窗口Id
|
||||
|
||||
QScopedPointer<AppInfo> m_appInfo;
|
||||
QScopedPointer<AppMenu> m_appMenu;
|
||||
QMap<XWindow, WindowInfoBase *> m_windowInfoMap; // 该应用所有窗口
|
||||
};
|
||||
|
||||
#endif // ENTRY_H
|
214
frame/taskmanager/processinfo.cpp
Normal file
214
frame/taskmanager/processinfo.cpp
Normal file
@ -0,0 +1,214 @@
|
||||
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "processinfo.h"
|
||||
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <QDir>
|
||||
#include <QDebug>
|
||||
#include <QFileInfo>
|
||||
|
||||
ProcessInfo::ProcessInfo(int pid)
|
||||
: m_pid(pid)
|
||||
, m_ppid(0)
|
||||
|
||||
{
|
||||
if (pid == 0)
|
||||
return;
|
||||
m_exe = getExe();
|
||||
m_cwd = getCwd();
|
||||
m_cmdLine = getCmdLine();
|
||||
getStatus();
|
||||
// 部分root进程在/proc文件系统查找不到exe、cwd、cmdline信息
|
||||
if (m_exe.isEmpty() || m_cwd.isEmpty() || m_cmdLine.size() == 0) {
|
||||
m_isValid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// args
|
||||
qInfo() << "ProcessInfo: exe=" << m_exe << " cwd=" << m_cwd << " cmdLine=" << (m_cmdLine[0].isEmpty() ? " " : m_cmdLine[0]);
|
||||
auto verifyExe = [](QString exe, QString cwd, QString firstArg){
|
||||
if (firstArg.size() == 0) return false;
|
||||
|
||||
QFileInfo info(firstArg);
|
||||
if (info.completeBaseName() == firstArg) return true;
|
||||
|
||||
if (!QDir::isAbsolutePath(firstArg))
|
||||
firstArg = cwd + firstArg;
|
||||
|
||||
return exe == firstArg;
|
||||
};
|
||||
|
||||
if (!m_cmdLine[0].isEmpty()) {
|
||||
if (!verifyExe(m_exe, m_cwd, m_cmdLine[0])) {
|
||||
auto parts = m_cmdLine[0].split(' ');
|
||||
// try again
|
||||
if (verifyExe(m_exe, m_cwd, parts[0])) {
|
||||
m_args.append(parts.mid(1, parts.size() - 1));
|
||||
m_args.append(m_cmdLine.mid(1, m_cmdLine.size() - 1));
|
||||
}
|
||||
} else {
|
||||
m_args.append(m_cmdLine.mid(1, m_cmdLine.size() - 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ProcessInfo::ProcessInfo(QStringList cmd)
|
||||
: m_hasPid(false)
|
||||
, m_isValid(true)
|
||||
{
|
||||
if (cmd.size() == 0) {
|
||||
m_isValid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
m_cmdLine = cmd;
|
||||
m_exe = cmd[0];
|
||||
m_args.append(cmd.mid(1, cmd.size() - 1));
|
||||
}
|
||||
|
||||
ProcessInfo::~ProcessInfo()
|
||||
{
|
||||
}
|
||||
|
||||
QString ProcessInfo::getEnv(const QString &key)
|
||||
{
|
||||
if (m_environ.size() == 0) getEnviron();
|
||||
return m_environ[key];
|
||||
}
|
||||
|
||||
Status ProcessInfo::getStatus()
|
||||
{
|
||||
if (!m_status.empty()){
|
||||
return m_status;
|
||||
}
|
||||
|
||||
QString statusFile = getFile("status");
|
||||
|
||||
std::ifstream fs(statusFile.toStdString());
|
||||
if (!fs.is_open()) {
|
||||
return m_status;
|
||||
}
|
||||
|
||||
std::string tmp = "";
|
||||
while (std::getline(fs, tmp)) {
|
||||
auto pos = tmp.find_first_of(':');
|
||||
if (pos == std::string::npos) {
|
||||
continue;
|
||||
}
|
||||
|
||||
QString value;
|
||||
if (pos + 1 < tmp.length()) {
|
||||
value = QString::fromStdString(tmp.substr(pos + 1));
|
||||
}
|
||||
|
||||
m_status[QString::fromStdString(tmp.substr(0, pos))] = value;
|
||||
}
|
||||
|
||||
return m_status;
|
||||
}
|
||||
|
||||
QStringList ProcessInfo::getCmdLine()
|
||||
{
|
||||
if (m_cmdLine.size() == 0) {
|
||||
QString cmdlineFile = getFile("cmdline");
|
||||
m_cmdLine = readFile(cmdlineFile);
|
||||
}
|
||||
|
||||
return m_cmdLine;
|
||||
}
|
||||
|
||||
QStringList ProcessInfo::getArgs()
|
||||
{
|
||||
return m_args;
|
||||
}
|
||||
|
||||
int ProcessInfo::getPid()
|
||||
{
|
||||
|
||||
return m_pid;
|
||||
}
|
||||
|
||||
int ProcessInfo::getPpid()
|
||||
{
|
||||
if (m_ppid == 0) {
|
||||
if (m_status.find("PPid") != m_status.end()) {
|
||||
m_ppid = std::stoi(m_status["PPid"].toStdString());
|
||||
}
|
||||
}
|
||||
return m_ppid;
|
||||
}
|
||||
|
||||
bool ProcessInfo::initWithPid()
|
||||
{
|
||||
return m_hasPid;
|
||||
}
|
||||
|
||||
bool ProcessInfo::isValid()
|
||||
{
|
||||
return m_isValid;
|
||||
}
|
||||
|
||||
QString ProcessInfo::getExe()
|
||||
{
|
||||
if (m_exe.isEmpty()) {
|
||||
QString cmdLineFile = getFile("exe");
|
||||
QFileInfo path(cmdLineFile);
|
||||
m_exe = path.canonicalFilePath();
|
||||
}
|
||||
|
||||
return m_exe;
|
||||
}
|
||||
|
||||
bool ProcessInfo::isExist()
|
||||
{
|
||||
QString procDir = "/proc/" + QString(m_pid);
|
||||
return QFile::exists(procDir);
|
||||
}
|
||||
|
||||
QStringList ProcessInfo::readFile(const QString &filePath)
|
||||
{
|
||||
QStringList ret;
|
||||
std::ifstream fs(filePath.toStdString());
|
||||
if (!fs.is_open()) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string tmp;
|
||||
while (std::getline(fs, tmp, '\0')) {
|
||||
ret.append(QString::fromStdString(tmp));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
QString ProcessInfo::getFile(const QString &file)
|
||||
{
|
||||
return QString("/proc/").append(QString::number(m_pid).append('/').append(file));
|
||||
}
|
||||
|
||||
QString ProcessInfo::getCwd()
|
||||
{
|
||||
if (m_cwd.isEmpty()) {
|
||||
QString cwdFile = getFile("cwd");
|
||||
QFileInfo path(cwdFile);
|
||||
m_cwd = path.canonicalFilePath();
|
||||
}
|
||||
return m_cwd;
|
||||
}
|
||||
|
||||
QMap<QString, QString> ProcessInfo::getEnviron()
|
||||
{
|
||||
if (m_environ.size() == 0) {
|
||||
QString envFile = getFile("environ");
|
||||
QStringList contents = readFile(envFile);
|
||||
for (auto line : contents){
|
||||
int index = line.indexOf('=');
|
||||
m_environ.insert(line.left(index), line.right(line.size() - index - 1));
|
||||
}
|
||||
}
|
||||
return m_environ;
|
||||
}
|
59
frame/taskmanager/processinfo.h
Normal file
59
frame/taskmanager/processinfo.h
Normal file
@ -0,0 +1,59 @@
|
||||
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#ifndef PROCESSINFO_H
|
||||
#define PROCESSINFO_H
|
||||
|
||||
#include <QMap>
|
||||
#include <QVector>
|
||||
#include <QStringList>
|
||||
|
||||
typedef QMap<QString, QString> Status;
|
||||
|
||||
// 进程信息
|
||||
class ProcessInfo
|
||||
{
|
||||
public:
|
||||
explicit ProcessInfo(int pid);
|
||||
explicit ProcessInfo(QStringList cmd);
|
||||
virtual ~ProcessInfo();
|
||||
|
||||
bool isValid();
|
||||
bool initWithPid();
|
||||
|
||||
int getPid();
|
||||
int getPpid();
|
||||
|
||||
QString getExe();
|
||||
QString getCwd();
|
||||
Status getStatus();
|
||||
QString getEnv(const QString &key);
|
||||
|
||||
QStringList getArgs();
|
||||
QStringList getCmdLine();
|
||||
QMap<QString, QString> getEnviron();
|
||||
|
||||
private:
|
||||
bool isExist();
|
||||
QString getJoinedExeArgs();
|
||||
QString getFile(const QString &file);
|
||||
QStringList readFile(const QString &filePath);
|
||||
|
||||
private:
|
||||
|
||||
int m_pid;
|
||||
int m_ppid;
|
||||
bool m_hasPid;
|
||||
bool m_isValid;
|
||||
|
||||
Status m_status;
|
||||
QString m_exe;
|
||||
QString m_cwd;
|
||||
QStringList m_args;
|
||||
QStringList m_cmdLine;
|
||||
QVector<int> m_uids;
|
||||
QMap<QString, QString> m_environ;
|
||||
};
|
||||
|
||||
#endif // PROCESSINFO_H
|
1613
frame/taskmanager/taskmanager.cpp
Normal file
1613
frame/taskmanager/taskmanager.cpp
Normal file
File diff suppressed because it is too large
Load Diff
199
frame/taskmanager/taskmanager.h
Normal file
199
frame/taskmanager/taskmanager.h
Normal file
@ -0,0 +1,199 @@
|
||||
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#ifndef DOCK_H
|
||||
#define DOCK_H
|
||||
|
||||
#include "docksettings.h"
|
||||
#include "entries.h"
|
||||
#include "org_deepin_dde_kwayland_plasmawindow.h"
|
||||
|
||||
#include <QStringList>
|
||||
#include <QTimer>
|
||||
#include <QMutex>
|
||||
#include <QObject>
|
||||
|
||||
class WindowIdentify;
|
||||
class DBusHandler;
|
||||
class WaylandManager;
|
||||
class X11Manager;
|
||||
class WindowInfoK;
|
||||
class WindowInfoX;
|
||||
|
||||
using PlasmaWindow = org::deepin::dde::kwayland1::PlasmaWindow;
|
||||
|
||||
// 任务管理
|
||||
class TaskManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
static inline TaskManager *instance() {
|
||||
static TaskManager instance;
|
||||
return &instance;
|
||||
}
|
||||
|
||||
// 将Entry dock在任务栏上
|
||||
bool dockEntry(Entry *entry, bool moveToEnd = false);
|
||||
void undockEntry(Entry *entry, bool moveToEnd = false);
|
||||
|
||||
QString allocEntryId();
|
||||
bool shouldShowOnDock(WindowInfoBase *info);
|
||||
void setDdeLauncherVisible(bool visible);
|
||||
void setTrayGridWidgetVisible(bool visible);
|
||||
void setPopupVisible(bool visible);
|
||||
QString getWMName();
|
||||
void setWMName(QString name);
|
||||
void setPropHideState(HideState state);
|
||||
void attachWindow(WindowInfoBase *info);
|
||||
void detachWindow(WindowInfoBase *info);
|
||||
|
||||
void launchApp(const QString desktopFile, uint32_t timestamp, QStringList files);
|
||||
void launchAppAction(const QString desktopFile, QString action, uint32_t timestamp);
|
||||
|
||||
bool is3DWM();
|
||||
bool isWaylandEnv();
|
||||
WindowInfoK *handleActiveWindowChangedK(uint activeWin);
|
||||
void saveDockedApps();
|
||||
void removeAppEntry(Entry *entry);
|
||||
void handleWindowGeometryChanged();
|
||||
Entry *getEntryByWindowId(XWindow windowId);
|
||||
QString getDesktopFromWindowByBamf(XWindow windowId);
|
||||
|
||||
void registerWindowWayland(const QString &objPath);
|
||||
void unRegisterWindowWayland(const QString &objPath);
|
||||
bool isShowingDesktop();
|
||||
|
||||
AppInfo *identifyWindow(WindowInfoBase *winInfo, QString &innerId);
|
||||
void markAppLaunched(AppInfo *appInfo);
|
||||
|
||||
ForceQuitAppMode getForceQuitAppStatus();
|
||||
QVector<QString> getWinIconPreferredApps();
|
||||
void handleLauncherItemDeleted(QString itemPath);
|
||||
void handleLauncherItemUpdated(QString itemPath);
|
||||
|
||||
QRect getFrontendWindowRect();
|
||||
DisplayMode getDisplayMode();
|
||||
void setDisplayMode(int mode);
|
||||
QStringList getDockedApps();
|
||||
QList<Entry*> getEntries();
|
||||
HideMode getHideMode();
|
||||
void setHideMode(HideMode mode);
|
||||
HideState getHideState();
|
||||
void setHideState(HideState state);
|
||||
uint getHideTimeout();
|
||||
void setHideTimeout(uint timeout);
|
||||
uint getIconSize();
|
||||
void setIconSize(uint size);
|
||||
int getPosition();
|
||||
void setPosition(int position);
|
||||
uint windowMargin() const;
|
||||
uint getShowTimeout();
|
||||
void setShowTimeout(uint timeout);
|
||||
uint getWindowSizeEfficient();
|
||||
void setWindowSizeEfficient(uint size);
|
||||
uint getWindowSizeFashion();
|
||||
void setWindowSizeFashion(uint size);
|
||||
|
||||
/******************************** dbus handler ****************************/
|
||||
PlasmaWindow *createPlasmaWindow(QString objPath);
|
||||
void listenKWindowSignals(WindowInfoK *windowInfo);
|
||||
void removePlasmaWindowHandler(PlasmaWindow *window);
|
||||
void presentWindows(QList<uint> windows);
|
||||
|
||||
HideMode getDockHideMode();
|
||||
bool isActiveWindow(const WindowInfoBase *win);
|
||||
WindowInfoBase *getActiveWindow();
|
||||
void doActiveWindow(XWindow xid);
|
||||
QList<XWindow> getClientList();
|
||||
void setClientList(QList<XWindow> value);
|
||||
|
||||
void closeWindow(XWindow windowId);
|
||||
void MinimizeWindow(XWindow windowId);
|
||||
QStringList getEntryIDs();
|
||||
void setFrontendWindowRect(int32_t x, int32_t y, uint width, uint height);
|
||||
bool isDocked(const QString desktopFile);
|
||||
bool requestDock(QString desktopFile, int index);
|
||||
bool requestUndock(QString desktopFile);
|
||||
void setShowMultiWindow(bool visible);
|
||||
bool showMultiWindow() const;
|
||||
void moveEntry(int oldIndex, int newIndex);
|
||||
bool isOnDock(QString desktopFile);
|
||||
QString queryWindowIdentifyMethod(XWindow windowId);
|
||||
QStringList getDockedAppsDesktopFiles();
|
||||
QString getPluginSettings();
|
||||
void setPluginSettings(QString jsonStr);
|
||||
void mergePluginSettings(QString jsonStr);
|
||||
void removePluginSettings(QString pluginName, QStringList settingkeys);
|
||||
void removeEntryFromDock(Entry *entry);
|
||||
|
||||
void previewWindow(uint xid);
|
||||
void cancelPreviewWindow();
|
||||
bool preventDockAutoHide() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void serviceRestarted();
|
||||
void entryAdded(const Entry* entry, int index);
|
||||
void entryRemoved(QString id);
|
||||
void hideStateChanged(int);
|
||||
void frontendWindowRectChanged(const QRect &dockRect);
|
||||
void showRecentChanged(bool);
|
||||
void showMultiWindowChanged(bool);
|
||||
void windowMarginChanged(uint);
|
||||
|
||||
public Q_SLOTS:
|
||||
void updateHideState(bool delay);
|
||||
void handleActiveWindowChanged(WindowInfoBase *info);
|
||||
void smartHideModeTimerExpired();
|
||||
void attachOrDetachWindow(WindowInfoBase *info);
|
||||
|
||||
private:
|
||||
explicit TaskManager(QObject *parent = nullptr);
|
||||
~TaskManager();
|
||||
void initSettings();
|
||||
void initEntries();
|
||||
void loadAppInfos();
|
||||
void initClientList();
|
||||
WindowInfoX *findWindowByXidX(XWindow xid);
|
||||
WindowInfoK *findWindowByXidK(XWindow xid);
|
||||
bool isWindowDockOverlapX(XWindow xid);
|
||||
bool hasInterSectionX(const Geometry &windowRect, QRect dockRect);
|
||||
bool isWindowDockOverlapK(WindowInfoBase *info);
|
||||
bool hasInterSectionK(const DockRect &windowRect, QRect dockRect);
|
||||
Entry *getDockedEntryByDesktopFile(const QString &desktopFile);
|
||||
bool shouldHideOnSmartHideMode();
|
||||
QVector<XWindow> getActiveWinGroup(XWindow xid);
|
||||
void updateRecentApps();
|
||||
|
||||
private:
|
||||
void onShowRecentChanged(bool visible);
|
||||
void onShowMultiWindowChanged(bool visible);
|
||||
|
||||
private:
|
||||
bool m_isWayland; // 判断是否为wayland环境
|
||||
bool m_showRecent;
|
||||
bool m_showMultiWindow;
|
||||
int m_entriesSum; // 累计打开的应用数量
|
||||
|
||||
QString m_wmName; // 窗管名称
|
||||
HideState m_hideState; // 记录任务栏隐藏状态
|
||||
QRect m_frontendWindowRect; // 前端任务栏大小, 用于智能隐藏时判断窗口是否重合
|
||||
ForceQuitAppMode m_forceQuitAppStatus; // 强制退出应用状态
|
||||
bool m_ddeLauncherVisible;
|
||||
bool m_trayGridWidgetVisible;
|
||||
bool m_popupVisible;
|
||||
|
||||
Entries *m_entries; // 所有应用实例
|
||||
X11Manager *m_x11Manager; // X11窗口管理
|
||||
WaylandManager *m_waylandManager; // wayland窗口管理
|
||||
WindowIdentify *m_windowIdentify; // 窗口识别
|
||||
|
||||
QTimer *m_smartHideTimer; // 任务栏智能隐藏定时器
|
||||
DBusHandler *m_dbusHandler; // 处理dbus交互
|
||||
WindowInfoBase *m_activeWindow;// 记录当前活跃窗口信息
|
||||
WindowInfoBase *m_activeWindowOld;// 记录前一个活跃窗口信息
|
||||
|
||||
QList<XWindow> m_clientList; // 所有窗口
|
||||
};
|
||||
|
||||
#endif // TASKMANAGER_H
|
119
frame/taskmanager/waylandmanager.cpp
Normal file
119
frame/taskmanager/waylandmanager.cpp
Normal file
@ -0,0 +1,119 @@
|
||||
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "waylandmanager.h"
|
||||
#include "taskmanager.h"
|
||||
#include "taskmanager/entry.h"
|
||||
#include "xcbutils.h"
|
||||
|
||||
#define XCB XCBUtils::instance()
|
||||
|
||||
WaylandManager::WaylandManager(TaskManager *_taskmanager, QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_taskmanager(_taskmanager)
|
||||
, m_mutex(QMutex(QMutex::NonRecursive))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief WaylandManager::registerWindow 注册窗口
|
||||
* @param objPath
|
||||
*/
|
||||
void WaylandManager::registerWindow(const QString &objPath)
|
||||
{
|
||||
qInfo() << "registerWindow: " << objPath;
|
||||
if (findWindowByObjPath(objPath))
|
||||
return;
|
||||
|
||||
PlasmaWindow *plasmaWindow = m_taskmanager->createPlasmaWindow(objPath);
|
||||
if (!plasmaWindow) {
|
||||
qWarning() << "registerWindowWayland: createPlasmaWindow failed";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!plasmaWindow->IsValid() || !plasmaWindow->isValid()) {
|
||||
qWarning() << "PlasmaWindow is not valid:" << objPath;
|
||||
plasmaWindow->deleteLater();
|
||||
return;
|
||||
}
|
||||
|
||||
QString appId = plasmaWindow->AppId();
|
||||
QStringList list {"dde-dock", "dde-launcher", "dde-clipboard", "dde-osd", "dde-polkit-agent", "dde-simple-egl", "dmcs", "dde-lock"};
|
||||
if (list.indexOf(appId) >= 0 || appId.startsWith("No such object path")) {
|
||||
plasmaWindow->deleteLater();
|
||||
return;
|
||||
}
|
||||
|
||||
XWindow winId = XCB->allocId(); // XCB中未发现释放XID接口
|
||||
XWindow realId = plasmaWindow->WindowId();
|
||||
if (realId)
|
||||
winId = realId;
|
||||
|
||||
WindowInfoK *winInfo = new WindowInfoK(plasmaWindow, winId);
|
||||
m_taskmanager->listenKWindowSignals(winInfo);
|
||||
insertWindow(objPath, winInfo);
|
||||
m_taskmanager->attachOrDetachWindow(winInfo);
|
||||
if (winId) {
|
||||
m_windowInfoMap[winId] = winInfo;
|
||||
}
|
||||
}
|
||||
|
||||
// 取消注册窗口
|
||||
void WaylandManager::unRegisterWindow(const QString &objPath)
|
||||
{
|
||||
qInfo() << "unRegisterWindow: " << objPath;
|
||||
WindowInfoK *winInfo = findWindowByObjPath(objPath);
|
||||
if (!winInfo)
|
||||
return;
|
||||
|
||||
m_taskmanager->removePlasmaWindowHandler(winInfo->getPlasmaWindow());
|
||||
m_taskmanager->detachWindow(winInfo);
|
||||
deleteWindow(objPath);
|
||||
}
|
||||
|
||||
WindowInfoK *WaylandManager::findWindowById(uint activeWin)
|
||||
{
|
||||
QMutexLocker locker(&m_mutex);
|
||||
for (auto iter = m_kWinInfos.begin(); iter != m_kWinInfos.end(); iter++) {
|
||||
if (iter.value()->getInnerId() == QString::number(activeWin)) {
|
||||
return iter.value();
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
WindowInfoK *WaylandManager::findWindowByXid(XWindow xid)
|
||||
{
|
||||
WindowInfoK *winInfo = nullptr;
|
||||
for (auto iter = m_kWinInfos.begin(); iter != m_kWinInfos.end(); iter++) {
|
||||
if (iter.value()->getXid() == xid) {
|
||||
winInfo = iter.value();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return winInfo;
|
||||
}
|
||||
|
||||
WindowInfoK *WaylandManager::findWindowByObjPath(QString objPath)
|
||||
{
|
||||
if (m_kWinInfos.find(objPath) == m_kWinInfos.end())
|
||||
return nullptr;
|
||||
|
||||
return m_kWinInfos[objPath];
|
||||
}
|
||||
|
||||
void WaylandManager::insertWindow(QString objPath, WindowInfoK *windowInfo)
|
||||
{
|
||||
QMutexLocker locker(&m_mutex);
|
||||
m_kWinInfos[objPath] = windowInfo;
|
||||
}
|
||||
|
||||
void WaylandManager::deleteWindow(QString objPath)
|
||||
{
|
||||
m_kWinInfos.remove(objPath);
|
||||
}
|
40
frame/taskmanager/waylandmanager.h
Normal file
40
frame/taskmanager/waylandmanager.h
Normal file
@ -0,0 +1,40 @@
|
||||
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#ifndef WAYLANDMANAGER_H
|
||||
#define WAYLANDMANAGER_H
|
||||
|
||||
#include "taskmanager/entry.h"
|
||||
#include "windowinfok.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QMap>
|
||||
#include <QMutex>
|
||||
|
||||
class TaskManager;
|
||||
|
||||
// 管理wayland窗口
|
||||
class WaylandManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit WaylandManager(TaskManager *_taskmanager, QObject *parent = nullptr);
|
||||
|
||||
void registerWindow(const QString &objPath);
|
||||
void unRegisterWindow(const QString &objPath);
|
||||
|
||||
WindowInfoK *findWindowById(uint activeWin);
|
||||
WindowInfoK *findWindowByXid(XWindow xid);
|
||||
WindowInfoK *findWindowByObjPath(QString objPath);
|
||||
void insertWindow(QString objPath, WindowInfoK *windowInfo);
|
||||
void deleteWindow(QString objPath);
|
||||
|
||||
private:
|
||||
TaskManager *m_taskmanager;
|
||||
QMap<QString, WindowInfoK *> m_kWinInfos; // dbusObjectPath -> kwayland window Info
|
||||
QMap<XWindow, WindowInfoK *> m_windowInfoMap;
|
||||
QMutex m_mutex;
|
||||
};
|
||||
|
||||
#endif // WAYLANDMANAGER_H
|
246
frame/taskmanager/window_patterns.json
Normal file
246
frame/taskmanager/window_patterns.json
Normal file
@ -0,0 +1,246 @@
|
||||
[
|
||||
{
|
||||
"ret": "id=jftp",
|
||||
"rules": [
|
||||
[
|
||||
"exec",
|
||||
"=:java"
|
||||
],
|
||||
[
|
||||
"arg",
|
||||
"c:jftp.jar"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"ret": "env",
|
||||
"rules": [
|
||||
[
|
||||
"wmi",
|
||||
"=:dman"
|
||||
],
|
||||
[
|
||||
"wmc",
|
||||
"=:DManual"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"ret": "env",
|
||||
"rules": [
|
||||
[
|
||||
"wmi",
|
||||
"r:\\.exe$"
|
||||
],
|
||||
[
|
||||
"wmi",
|
||||
"=!iesetup.exe"
|
||||
],
|
||||
[
|
||||
"wmc",
|
||||
"=:Wine"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"ret": "id=netbeans",
|
||||
"rules": [
|
||||
[
|
||||
"wmc",
|
||||
"c:netbeans"
|
||||
],
|
||||
[
|
||||
"exec",
|
||||
"=:java"
|
||||
],
|
||||
[
|
||||
"arg",
|
||||
"c:netbeans"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"ret": "id=jabref",
|
||||
"rules": [
|
||||
[
|
||||
"wmc",
|
||||
"c:jabref"
|
||||
],
|
||||
[
|
||||
"exec",
|
||||
"=:java"
|
||||
],
|
||||
[
|
||||
"arg",
|
||||
"c:jabref"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"ret": "env",
|
||||
"rules": [
|
||||
[
|
||||
"wmi",
|
||||
"=:player"
|
||||
],
|
||||
[
|
||||
"wmc",
|
||||
"c:genymotion"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"ret": "id=xdemineur",
|
||||
"rules": [
|
||||
[
|
||||
"wmi",
|
||||
"c:xdemineur"
|
||||
],
|
||||
[
|
||||
"exec",
|
||||
"=:xdemineur"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"ret": "id=minecraft",
|
||||
"rules": [
|
||||
[
|
||||
"wmi",
|
||||
"c:minecraft"
|
||||
],
|
||||
[
|
||||
"wmc",
|
||||
"c:minecraft"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"ret": "id=steam",
|
||||
"rules": [
|
||||
[
|
||||
"hasPid",
|
||||
"=:f"
|
||||
],
|
||||
[
|
||||
"wmi",
|
||||
"=:"
|
||||
],
|
||||
[
|
||||
"wmc",
|
||||
"=:"
|
||||
],
|
||||
[
|
||||
"wmn",
|
||||
"e:steam"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"ret": "id=mintdrivers",
|
||||
"rules": [
|
||||
[
|
||||
"wmi",
|
||||
"e:mintdrivers.py"
|
||||
],
|
||||
[
|
||||
"wmc",
|
||||
"e:mintdrivers.py"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"ret": "id=google-earth",
|
||||
"rules": [
|
||||
[
|
||||
"wmi",
|
||||
"c:googleearth"
|
||||
],
|
||||
[
|
||||
"wmc",
|
||||
"c:googleearth"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"ret": "id=the-powder-toy",
|
||||
"rules": [
|
||||
[
|
||||
"wmi",
|
||||
"e:powder"
|
||||
],
|
||||
[
|
||||
"wmc",
|
||||
"e:powder"
|
||||
],
|
||||
[
|
||||
"hasPid",
|
||||
"=:t"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"ret": "id=cn.google.chrome",
|
||||
"rules": [
|
||||
[
|
||||
"wmi",
|
||||
"e:google-chrome"
|
||||
],
|
||||
[
|
||||
"wmc",
|
||||
"e:google-chrome"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"ret": "id=ganttproject",
|
||||
"rules": [
|
||||
[
|
||||
"wmi",
|
||||
"R:^sun-awt-X11"
|
||||
],
|
||||
[
|
||||
"exec",
|
||||
"=:java"
|
||||
],
|
||||
[
|
||||
"env.CLASSPATH",
|
||||
"c:ganttproject"
|
||||
],
|
||||
[
|
||||
"arg",
|
||||
"c:ganttproject"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"ret": "id=gdevelop",
|
||||
"rules": [
|
||||
[
|
||||
"wmi",
|
||||
"c:gdevelop"
|
||||
],
|
||||
[
|
||||
"wmc",
|
||||
"c:gdevelop"
|
||||
],
|
||||
[
|
||||
"exec",
|
||||
"=:gdevelop"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"ret": "id=apps.com.wechat.web",
|
||||
"rules": [
|
||||
[
|
||||
"wmi",
|
||||
"e:wx2.qq.com"
|
||||
],
|
||||
[
|
||||
"wmc",
|
||||
"e:google-chrome"
|
||||
]
|
||||
]
|
||||
}
|
||||
]
|
551
frame/taskmanager/windowidentify.cpp
Normal file
551
frame/taskmanager/windowidentify.cpp
Normal file
@ -0,0 +1,551 @@
|
||||
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "windowidentify.h"
|
||||
#include "common.h"
|
||||
#include "appinfo.h"
|
||||
#include "taskmanager.h"
|
||||
#include "processinfo.h"
|
||||
#include "taskmanager/desktopinfo.h"
|
||||
#include "xcbutils.h"
|
||||
#include "bamfdesktop.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QThread>
|
||||
#include <QDBusConnection>
|
||||
|
||||
#define XCB XCBUtils::instance()
|
||||
|
||||
static QMap<QString, QString> crxAppIdMap = {
|
||||
{"crx_onfalgmmmaighfmjgegnamdjmhpjpgpi", "apps.com.aiqiyi"},
|
||||
{"crx_gfhkopakpiiaeocgofdpcpjpdiglpkjl", "apps.cn.kugou.hd"},
|
||||
{"crx_gaoopbnflngfkoobibfgbhobdeiipcgh", "apps.cn.kuwo.kwmusic"},
|
||||
{"crx_jajaphleehpmpblokgighfjneejapnok", "apps.com.evernote"},
|
||||
{"crx_ebhffdbfjilfhahiinoijchmlceailfn", "apps.com.letv"},
|
||||
{"crx_almpoflgiciaanepplakjdkiaijmklld", "apps.com.tongyong.xxbox"},
|
||||
{"crx_heaphplipeblmpflpdcedfllmbehonfo", "apps.com.peashooter"},
|
||||
{"crx_dbngidmdhcooejaggjiochbafiaefndn", "apps.com.rovio.angrybirdsseasons"},
|
||||
{"crx_chfeacahlaknlmjhiagghobhkollfhip", "apps.com.sina.weibo"},
|
||||
{"crx_cpbmecbkmjjfemjiekledmejoakfkpec", "apps.com.openapp"},
|
||||
{"crx_lalomppgkdieklbppclocckjpibnlpjc", "apps.com.baidutieba"},
|
||||
{"crx_gejbkhjjmicgnhcdpgpggboldigfhgli", "apps.com.zhuishushenqi"},
|
||||
{"crx_gglenfcpioacendmikabbkecnfpanegk", "apps.com.duokan"},
|
||||
{"crx_nkmmgdfgabhefacpfdabadjfnpffhpio", "apps.com.zhihu.daily"},
|
||||
{"crx_ajkogonhhcighbinfgcgnjiadodpdicb", "apps.com.netease.newsreader"},
|
||||
{"crx_hgggjnaaklhemplabjhgpodlcnndhppo", "apps.com.baidu.music.pad"},
|
||||
{"crx_ebmgfebnlgilhandilnbmgadajhkkmob", "apps.cn.ibuka"},
|
||||
{"crx_nolebplcbgieabkblgiaacdpgehlopag", "apps.com.tianqitong"},
|
||||
{"crx_maghncnmccfbmkekccpmkjjfcmdnnlip", "apps.com.youjoy.strugglelandlord"},
|
||||
{"crx_heliimhfjgfabpgfecgdhackhelmocic", "apps.cn.emoney"},
|
||||
{"crx_jkgmneeafmgjillhgmjbaipnakfiidpm", "apps.com.instagram"},
|
||||
{"crx_cdbkhmfmikobpndfhiphdbkjklbmnakg", "apps.com.easymindmap"},
|
||||
{"crx_djflcciklfljleibeinjmjdnmenkciab", "apps.com.lgj.thunderbattle"},
|
||||
{"crx_ffdgbolnndgeflkapnmoefhjhkeilfff", "apps.com.qianlong"},
|
||||
{"crx_fmpniepgiofckbfgahajldgoelogdoap", "apps.com.windhd"},
|
||||
{"crx_dokjmallmkihbgefmladclcdcinjlnpj", "apps.com.youdao.hanyu"},
|
||||
{"crx_dicimeimfmbfcklbjdpnlmjgegcfilhm", "apps.com.ibookstar"},
|
||||
{"crx_cokkcjnpjfffianjbpjbcgjefningkjm", "apps.com.yidianzixun"},
|
||||
{"crx_ehflkacdpmeehailmcknlnkmjalehdah", "apps.com.xplane"},
|
||||
{"crx_iedokjbbjejfinokgifgecmboncmkbhb", "apps.com.wedevote"},
|
||||
{"crx_eaefcagiihjpndconigdpdmcbpcamaok", "apps.com.tongwei.blockbreaker"},
|
||||
{"crx_mkjjfibpccammnliaalefmlekiiikikj", "apps.com.dayima"},
|
||||
{"crx_gflkpppiigdigkemnjlonilmglokliol", "apps.com.cookpad"},
|
||||
{"crx_jfhpkchgedddadekfeganigbenbfaohe", "apps.com.issuu"},
|
||||
{"crx_ggkmfnbkldhmkehabgcbnmlccfbnoldo", "apps.bible.cbol"},
|
||||
{"crx_phlhkholfcljapmcidanddmhpcphlfng", "apps.com.kanjian.radio"},
|
||||
{"crx_bjgfcighhaahojkibojkdmpdihhcehfm", "apps.de.danoeh.antennapod"},
|
||||
{"crx_kldipknjommdfkifomkmcpbcnpmcnbfi", "apps.com.asoftmurmur"},
|
||||
{"crx_jfhlegimcipljdcionjbipealofoncmd", "apps.com.tencentnews"},
|
||||
{"crx_aikgmfkpmmclmpooohngmcdimgcocoaj", "apps.com.tonghuashun"},
|
||||
{"crx_ifimglalpdeoaffjmmihoofapmpflkad", "apps.com.letv.lecloud.disk"},
|
||||
{"crx_pllcekmbablpiogkinogefpdjkmgicbp", "apps.com.hwadzanebook"},
|
||||
{"crx_ohcknkkbjmgdfcejpbmhjbohnepcagkc", "apps.com.douban.radio"},
|
||||
};
|
||||
|
||||
WindowIdentify::WindowIdentify(TaskManager *_taskmanager, QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_taskmanager(_taskmanager)
|
||||
{
|
||||
m_identifyWindowFuns << qMakePair(QString("Android") , &identifyWindowAndroid);
|
||||
m_identifyWindowFuns << qMakePair(QString("PidEnv"), &identifyWindowByPidEnv);
|
||||
m_identifyWindowFuns << qMakePair(QString("CmdlineTurboBooster"), &identifyWindowByCmdlineTurboBooster);
|
||||
m_identifyWindowFuns << qMakePair(QString("Cmdline-XWalk"), &identifyWindowByCmdlineXWalk);
|
||||
m_identifyWindowFuns << qMakePair(QString("FlatpakAppID"), &identifyWindowByFlatpakAppID);
|
||||
m_identifyWindowFuns << qMakePair(QString("CrxId"), &identifyWindowByCrxId);
|
||||
m_identifyWindowFuns << qMakePair(QString("Rule"), &identifyWindowByRule);
|
||||
m_identifyWindowFuns << qMakePair(QString("Pid"), &identifyWindowByPid);
|
||||
m_identifyWindowFuns << qMakePair(QString("Scratch"), &identifyWindowByScratch);
|
||||
m_identifyWindowFuns << qMakePair(QString("GtkAppId"), &identifyWindowByGtkAppId);
|
||||
m_identifyWindowFuns << qMakePair(QString("WmClass"), &identifyWindowByWmClass);
|
||||
|
||||
// should remove bamf identify and turn to new AM
|
||||
auto *dbusWatcher = new QDBusServiceWatcher(QStringLiteral("org.ayatana.bamf"), QDBusConnection::sessionBus(),
|
||||
QDBusServiceWatcher::WatchForOwnerChange, this);
|
||||
|
||||
auto ifc = QDBusConnection::sessionBus().interface();
|
||||
|
||||
if (ifc->isServiceRegistered(QStringLiteral("org.ayatana.bamf"))) {
|
||||
m_identifyWindowFuns << qMakePair(QString("Bamf"), &identifyWindowByBamf);
|
||||
}
|
||||
|
||||
connect(dbusWatcher, &QDBusServiceWatcher::serviceRegistered, this, [this](){
|
||||
m_identifyWindowFuns << qMakePair(QString("Bamf"), &identifyWindowByBamf);
|
||||
});
|
||||
|
||||
connect(dbusWatcher, &QDBusServiceWatcher::serviceUnregistered, this, [this](){
|
||||
m_identifyWindowFuns.removeAll(qMakePair(QString("Bamf"), &identifyWindowByBamf));
|
||||
});
|
||||
}
|
||||
|
||||
AppInfo *WindowIdentify::identifyWindow(WindowInfoBase *winInfo, QString &innerId)
|
||||
{
|
||||
if (!winInfo)
|
||||
return nullptr;
|
||||
|
||||
qInfo() << "identifyWindow: window id " << winInfo->getXid() << " innerId " << winInfo->getInnerId();
|
||||
if (winInfo->getWindowType() == "X11")
|
||||
return identifyWindowX11(static_cast<WindowInfoX *>(winInfo), innerId);
|
||||
if (winInfo->getWindowType() == "Wayland")
|
||||
return identifyWindowWayland(static_cast<WindowInfoK *>(winInfo), innerId);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AppInfo *WindowIdentify::identifyWindowX11(WindowInfoX *winInfo, QString &innerId)
|
||||
{
|
||||
AppInfo *appInfo = nullptr;
|
||||
if (winInfo->getInnerId().isEmpty()) {
|
||||
qInfo() << "identifyWindowX11: window innerId is empty";
|
||||
return appInfo;
|
||||
}
|
||||
|
||||
for (auto iter = m_identifyWindowFuns.begin(); iter != m_identifyWindowFuns.end(); iter++) {
|
||||
QString name = iter->first;
|
||||
IdentifyFunc func = iter->second;
|
||||
qInfo() << "identifyWindowX11: try " << name;
|
||||
appInfo = func(m_taskmanager, winInfo, innerId);
|
||||
if (appInfo) { // TODO: if name == "Pid", appInfo may by nullptr
|
||||
// 识别成功
|
||||
qInfo() << "identify Window by " << name << " innerId " << appInfo->getInnerId() << " success!";
|
||||
AppInfo *fixedAppInfo = fixAutostartAppInfo(appInfo->getFileName());
|
||||
if (fixedAppInfo) {
|
||||
delete appInfo;
|
||||
appInfo = fixedAppInfo;
|
||||
appInfo->setIdentifyMethod(name + "+FixAutostart");
|
||||
innerId = appInfo->getInnerId();
|
||||
} else {
|
||||
appInfo->setIdentifyMethod(name);
|
||||
}
|
||||
return appInfo;
|
||||
}
|
||||
}
|
||||
|
||||
qInfo() << "identifyWindowX11: failed";
|
||||
// 如果识别窗口失败,则该app的entryInnerId使用当前窗口的innerId
|
||||
innerId = winInfo->getInnerId();
|
||||
return appInfo;
|
||||
}
|
||||
|
||||
AppInfo *WindowIdentify::identifyWindowWayland(WindowInfoK *winInfo, QString &innerId)
|
||||
{
|
||||
// TODO: 对桌面调起的文管应用做规避处理,需要在此处添加,因为初始化时appId和title为空
|
||||
if (winInfo->getAppId() == "dde-desktop" && m_taskmanager->shouldShowOnDock(winInfo)) {
|
||||
winInfo->setAppId("dde-file-manager");
|
||||
}
|
||||
|
||||
QString appId = winInfo->getAppId();
|
||||
if (appId.isEmpty()) {
|
||||
QString title = winInfo->getTitle();
|
||||
// TODO: 对于appId为空的情况,使用title过滤,此项修改针对浏览器下载窗口
|
||||
|
||||
}
|
||||
|
||||
// 先使用appId获取appInfo,如果不能成功获取再使用GIO_LAUNCHED_DESKTOP_FILE环境变量获取
|
||||
AppInfo *appInfo = new AppInfo(appId);
|
||||
if (!appInfo->isValidApp() && winInfo->getProcess()) {
|
||||
ProcessInfo *process = winInfo->getProcess();
|
||||
QString desktopFilePath = process->getEnv("GIO_LAUNCHED_DESKTOP_FILE");
|
||||
if ((desktopFilePath.endsWith(".desktop"))) {
|
||||
appInfo = new AppInfo(desktopFilePath);
|
||||
}
|
||||
}
|
||||
|
||||
// autoStart
|
||||
if (appInfo->isValidApp()) {
|
||||
AppInfo *fixedAppInfo = fixAutostartAppInfo(appInfo->getFileName());
|
||||
if (fixedAppInfo) {
|
||||
delete appInfo;
|
||||
appInfo = fixedAppInfo;
|
||||
appInfo->setIdentifyMethod("FixAutostart");
|
||||
}
|
||||
}
|
||||
|
||||
if (appInfo)
|
||||
innerId = appInfo->getInnerId();
|
||||
|
||||
return appInfo;
|
||||
}
|
||||
|
||||
AppInfo *WindowIdentify::identifyWindowAndroid(TaskManager *_taskmanager, WindowInfoX *winInfo, QString &innerId)
|
||||
{
|
||||
AppInfo *ret = nullptr;
|
||||
int32_t androidId = getAndroidUengineId(winInfo->getXid());
|
||||
QString androidName = getAndroidUengineName(winInfo->getXid());
|
||||
if (androidId != -1 && androidName != "") {
|
||||
QString desktopPath = "/usr/share/applications/uengine." + androidName + ".desktop";
|
||||
DesktopInfo desktopInfo(desktopPath);
|
||||
if (!desktopInfo.isValidDesktop()) {
|
||||
qInfo() << "identifyWindowAndroid: not exist DesktopFile " << desktopPath;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = new AppInfo(desktopInfo);
|
||||
ret->setIdentifyMethod("Android");
|
||||
innerId = ret->getInnerId();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
AppInfo *WindowIdentify::identifyWindowByPidEnv(TaskManager *_taskmanager, WindowInfoX *winInfo, QString &innerId)
|
||||
{
|
||||
AppInfo *ret = nullptr;
|
||||
int pid = winInfo->getPid();
|
||||
auto process = winInfo->getProcess();
|
||||
qInfo() << "identifyWindowByPidEnv: pid=" << pid << " WindowId=" << winInfo->getXid();
|
||||
|
||||
if (pid == 0 || !process) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
QString launchedDesktopFile = process->getEnv("GIO_LAUNCHED_DESKTOP_FILE");
|
||||
QString launchedDesktopFilePidStr = process->getEnv("GIO_LAUNCHED_DESKTOP_FILE_PID");
|
||||
int launchedDesktopFilePid = launchedDesktopFilePidStr.toInt();
|
||||
qInfo() << "launchedDesktopFilePid=" << launchedDesktopFilePid << " launchedDesktopFile=" << launchedDesktopFile;
|
||||
|
||||
if (launchedDesktopFile.isEmpty()) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto pidIsSh = [](int pid) -> bool {
|
||||
ProcessInfo parentProcess(pid);
|
||||
auto parentCmdLine = parentProcess.getCmdLine();
|
||||
if (parentCmdLine.size() <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
qInfo() << "ppid equal" << "parentCmdLine[0]:" << parentCmdLine[0];
|
||||
QString cmd0 = parentCmdLine[0];
|
||||
int pos = cmd0.lastIndexOf('/');
|
||||
if (pos > 0)
|
||||
cmd0 = cmd0.remove(0, pos + 1);
|
||||
|
||||
if (cmd0 == "sh" || cmd0 == "bash"){
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
auto processInLinglong = [](ProcessInfo* const process) -> bool {
|
||||
for (ProcessInfo p(process->getPpid()); p.getPid() != 0; p = ProcessInfo(p.getPpid())) {
|
||||
if (!p.getCmdLine().size()){
|
||||
qWarning() << "Failed to get command line of" << p.getPid() << " SKIP it.";
|
||||
continue;
|
||||
}
|
||||
if (p.getCmdLine()[0].indexOf("ll-box") != -1) {
|
||||
qDebug() << "process ID" << process->getPid() << "is in linglong container,"
|
||||
<<"ll-box PID" << p.getPid();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
// 以下几种情况下,才能信任环境变量 GIO_LAUNCHED_DESKTOP_FILE。
|
||||
if (pid == launchedDesktopFilePid || // 当窗口pid和launchedDesktopFilePid相同时
|
||||
( process->getPpid() &&
|
||||
process->getPpid() == launchedDesktopFilePid &&
|
||||
pidIsSh(process->getPpid())
|
||||
) || // 当窗口的进程的父进程id(即ppid)和launchedDesktopFilePid相同,并且该父进程是sh或bash时。
|
||||
processInLinglong(process) // 当窗口pid在玲珑容器中
|
||||
) {
|
||||
|
||||
ret = new AppInfo(launchedDesktopFile);
|
||||
innerId = ret->getInnerId();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
AppInfo *WindowIdentify::identifyWindowByCmdlineTurboBooster(TaskManager *_taskmanager, WindowInfoX *winInfo, QString &innerId)
|
||||
{
|
||||
AppInfo *ret = nullptr;
|
||||
int pid = winInfo->getPid();
|
||||
ProcessInfo *process = winInfo->getProcess();
|
||||
if (pid != 0 && process) {
|
||||
auto cmdline = process->getCmdLine();
|
||||
if (cmdline.size() > 0) {
|
||||
QString desktopFile;
|
||||
if (cmdline[0].startsWith(".desktop")) {
|
||||
desktopFile = cmdline[0];
|
||||
} else if (QString(cmdline[0]).contains("/applications/")) {
|
||||
QFileInfo fileInfo(cmdline[0]);
|
||||
QString path = fileInfo.path();
|
||||
QString base = fileInfo.completeBaseName();
|
||||
QDir dir(path);
|
||||
QStringList files = dir.entryList(QDir::Files);
|
||||
for (auto f : files) {
|
||||
if (f.contains(path + "/" + base + ".desktop")) {
|
||||
desktopFile = f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
qInfo() << "identifyWindowByCmdlineTurboBooster: desktopFile is " << desktopFile;
|
||||
if (!desktopFile.isEmpty()) {
|
||||
ret = new AppInfo(desktopFile);
|
||||
innerId = ret->getInnerId();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
AppInfo *WindowIdentify::identifyWindowByCmdlineXWalk(TaskManager *_taskmanager, WindowInfoX *winInfo, QString &innerId)
|
||||
{
|
||||
qInfo() << "identifyWindowByCmdlineXWalk: windowId=" << winInfo->getXid();
|
||||
AppInfo *ret = nullptr;
|
||||
do {
|
||||
auto process = winInfo->getProcess();
|
||||
if (!process || !winInfo->getPid())
|
||||
break;
|
||||
|
||||
QString exe = process->getExe();
|
||||
QFileInfo file(exe);
|
||||
QString exeBase = file.completeBaseName();
|
||||
auto args = process->getArgs();
|
||||
if (exe != "xwalk" || args.size() == 0)
|
||||
break;
|
||||
|
||||
QString lastArg = args[args.size() - 1];
|
||||
file.setFile(lastArg);
|
||||
if (file.completeBaseName() == "manifest.json") {
|
||||
auto strs = lastArg.split("/");
|
||||
if (strs.size() > 3 && strs[strs.size() - 2].size() > 0) { // appId为 strs倒数第二个字符串
|
||||
ret = new AppInfo(strs[strs.size() - 2]);
|
||||
innerId = ret->getInnerId();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
qInfo() << "identifyWindowByCmdlineXWalk: failed";
|
||||
} while (0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
AppInfo *WindowIdentify::identifyWindowByFlatpakAppID(TaskManager *_taskmanager, WindowInfoX *winInfo, QString &innerId)
|
||||
{
|
||||
AppInfo *ret = nullptr;
|
||||
QString flatpak = winInfo->getFlatpakAppId();
|
||||
qInfo() << "identifyWindowByFlatpakAppID: flatpak:" << flatpak;
|
||||
if (flatpak.startsWith("app/")) {
|
||||
auto parts = flatpak.split("/");
|
||||
if (parts.size() > 0) {
|
||||
QString appId = parts[1];
|
||||
ret = new AppInfo(appId);
|
||||
innerId = ret->getInnerId();
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
AppInfo *WindowIdentify::identifyWindowByCrxId(TaskManager *_taskmanager, WindowInfoX *winInfo, QString &innerId)
|
||||
{
|
||||
AppInfo *ret = nullptr;
|
||||
WMClass wmClass = XCB->getWMClass(winInfo->getXid());
|
||||
QString className, instanceName;
|
||||
className.append(wmClass.className.c_str());
|
||||
instanceName.append(wmClass.instanceName.c_str());
|
||||
|
||||
if (className.toLower() == "chromium-browser" && instanceName.toLower().startsWith("crx_")) {
|
||||
if (crxAppIdMap.find(instanceName.toLower()) != crxAppIdMap.end()) {
|
||||
QString appId = crxAppIdMap[instanceName.toLower()];
|
||||
qInfo() << "identifyWindowByCrxId: appId " << appId;
|
||||
ret = new AppInfo(appId);
|
||||
innerId = ret->getInnerId();
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
AppInfo *WindowIdentify::identifyWindowByRule(TaskManager *_taskmanager, WindowInfoX *winInfo, QString &innerId)
|
||||
{
|
||||
static WindowPatterns patterns;
|
||||
qInfo() << "identifyWindowByRule: windowId=" << winInfo->getXid();
|
||||
AppInfo *ret = nullptr;
|
||||
QString matchStr = patterns.match(winInfo);
|
||||
if (matchStr.isEmpty())
|
||||
return ret;
|
||||
|
||||
if (matchStr.size() > 4 && matchStr.startsWith("id=")) {
|
||||
matchStr.remove(0, 3);
|
||||
AppInfo* tmp = new AppInfo(matchStr);
|
||||
// 匹配到了,但是“无效规则“,匹配到程序未安装(优先匹配商店,但是实际程序是原生软件)
|
||||
if (tmp->isValidApp()) ret = tmp;
|
||||
else delete tmp;
|
||||
} else if (matchStr == "env") {
|
||||
auto process = winInfo->getProcess();
|
||||
if (process) {
|
||||
QString launchedDesktopFile = process->getEnv("GIO_LAUNCHED_DESKTOP_FILE");
|
||||
if (!launchedDesktopFile.isEmpty())
|
||||
ret = new AppInfo(launchedDesktopFile);
|
||||
}
|
||||
} else {
|
||||
qInfo() << "patterns match bad result";
|
||||
}
|
||||
|
||||
if (ret)
|
||||
innerId = ret->getInnerId();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
AppInfo *WindowIdentify::identifyWindowByBamf(TaskManager *_taskmanager, WindowInfoX *winInfo, QString &innerId)
|
||||
{
|
||||
if (_taskmanager->isWaylandEnv()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AppInfo *ret = nullptr;
|
||||
XWindow xid = winInfo->getXid();
|
||||
qInfo() << "identifyWindowByBamf: windowId=" << xid;
|
||||
QString desktopFile;
|
||||
// 重试 bamf 识别,部分的窗口经常要多次调用才能识别到。
|
||||
for (int i = 0; i < 3; i++) {
|
||||
desktopFile = _taskmanager->getDesktopFromWindowByBamf(xid);
|
||||
if (!desktopFile.isEmpty())
|
||||
break;
|
||||
}
|
||||
|
||||
if (!desktopFile.isEmpty()) {
|
||||
ret = new AppInfo(desktopFile);
|
||||
innerId = ret->getInnerId();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
AppInfo *WindowIdentify::identifyWindowByPid(TaskManager *_taskmanager, WindowInfoX *winInfo, QString &innerId)
|
||||
{
|
||||
AppInfo *ret = nullptr;
|
||||
if (winInfo->getPid() > 10) {
|
||||
auto entry = _taskmanager->getEntryByWindowId(winInfo->getPid());
|
||||
if (entry) {
|
||||
ret = entry->getAppInfo();
|
||||
innerId = ret->getInnerId();
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
AppInfo *WindowIdentify::identifyWindowByScratch(TaskManager *_taskmanager, WindowInfoX *winInfo, QString &innerId)
|
||||
{
|
||||
AppInfo *ret = nullptr;
|
||||
QString desktopFile = scratchDir + winInfo->getInnerId() + ".desktop";
|
||||
qInfo() << "identifyWindowByScratch: xid " << winInfo->getXid() << " desktopFile" << desktopFile;
|
||||
QFile file(desktopFile);
|
||||
|
||||
if (file.exists()) {
|
||||
ret = new AppInfo(desktopFile);
|
||||
innerId = ret->getInnerId();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
AppInfo *WindowIdentify::identifyWindowByGtkAppId(TaskManager *_taskmanager, WindowInfoX *winInfo, QString &innerId)
|
||||
{
|
||||
AppInfo *ret = nullptr;
|
||||
QString gtkAppId = winInfo->getGtkAppId();
|
||||
if (!gtkAppId.isEmpty()) {
|
||||
ret = new AppInfo(gtkAppId);
|
||||
innerId = ret->getInnerId();
|
||||
}
|
||||
|
||||
qInfo() << "identifyWindowByGtkAppId: gtkAppId:" << gtkAppId;
|
||||
return ret;
|
||||
}
|
||||
|
||||
AppInfo *WindowIdentify::identifyWindowByWmClass(TaskManager *_taskmanager, WindowInfoX *winInfo, QString &innerId)
|
||||
{
|
||||
WMClass wmClass = winInfo->getWMClass();
|
||||
if (wmClass.instanceName.size() > 0) {
|
||||
// example:
|
||||
// WM_CLASS(STRING) = "Brackets", "Brackets"
|
||||
// wm class instance is Brackets
|
||||
// try app id org.deepin.flatdeb.brackets
|
||||
//ret = new AppInfo("org.deepin.flatdeb." + QString(wmClass.instanceName.c_str()).toLower());
|
||||
if (DesktopInfo("org.deepin.flatdeb." + QString(wmClass.instanceName.c_str()).toLower()).isValidDesktop()) {
|
||||
AppInfo *appInfo = new AppInfo("org.deepin.flatdeb." + QString(wmClass.instanceName.c_str()).toLower());
|
||||
innerId = appInfo->getInnerId();
|
||||
return appInfo;
|
||||
}
|
||||
|
||||
if (DesktopInfo(QString::fromStdString(wmClass.instanceName)).isValidDesktop()) {
|
||||
AppInfo *appInfo = new AppInfo(wmClass.instanceName.c_str());
|
||||
innerId = appInfo->getInnerId();
|
||||
return appInfo;
|
||||
}
|
||||
}
|
||||
|
||||
if (wmClass.className.size() > 0) {
|
||||
QString filename = QString::fromStdString(wmClass.className);
|
||||
bool isValid = DesktopInfo(filename).isValidDesktop();
|
||||
if (!isValid) {
|
||||
filename = BamfDesktop::instance()->fileName(wmClass.instanceName.c_str());
|
||||
isValid = DesktopInfo(filename).isValidDesktop();
|
||||
}
|
||||
|
||||
if (isValid) {
|
||||
AppInfo *appInfo = new AppInfo(filename);
|
||||
innerId = appInfo->getInnerId();
|
||||
return appInfo;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AppInfo *WindowIdentify::fixAutostartAppInfo(QString fileName)
|
||||
{
|
||||
QFileInfo file(fileName);
|
||||
QString filePath = file.absolutePath();
|
||||
bool isAutoStart = false;
|
||||
for (auto dir : QStandardPaths::standardLocations(QStandardPaths::ConfigLocation)) {
|
||||
if (dir.contains(filePath)) {
|
||||
isAutoStart = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return isAutoStart ? new AppInfo(file.completeBaseName()) : nullptr;
|
||||
}
|
||||
|
||||
int32_t WindowIdentify::getAndroidUengineId(XWindow winId)
|
||||
{
|
||||
// TODO 获取AndroidUengineId
|
||||
return 0;
|
||||
}
|
||||
|
||||
QString WindowIdentify::getAndroidUengineName(XWindow winId)
|
||||
{
|
||||
// TODO 获取AndroidUengineName
|
||||
return "";
|
||||
}
|
57
frame/taskmanager/windowidentify.h
Normal file
57
frame/taskmanager/windowidentify.h
Normal file
@ -0,0 +1,57 @@
|
||||
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#ifndef WINDOWIDENTIFY_H
|
||||
#define WINDOWIDENTIFY_H
|
||||
|
||||
#include "taskmanager/entry.h"
|
||||
#include "windowpatterns.h"
|
||||
#include "windowinfok.h"
|
||||
#include "windowinfox.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QVector>
|
||||
#include <QMap>
|
||||
|
||||
class AppInfo;
|
||||
class TaskManager;
|
||||
|
||||
typedef AppInfo *(*IdentifyFunc)(TaskManager *, WindowInfoX*, QString &innerId);
|
||||
|
||||
// 应用窗口识别类
|
||||
class WindowIdentify : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit WindowIdentify(TaskManager *_taskmanager, QObject *parent = nullptr);
|
||||
|
||||
AppInfo *identifyWindow(WindowInfoBase *winInfo, QString &innerId);
|
||||
AppInfo *identifyWindowX11(WindowInfoX *winInfo, QString &innerId);
|
||||
AppInfo *identifyWindowWayland(WindowInfoK *winInfo, QString &innerId);
|
||||
|
||||
static AppInfo *identifyWindowAndroid(TaskManager *_dock, WindowInfoX *winInfo, QString &innerId);
|
||||
static AppInfo *identifyWindowByPidEnv(TaskManager *_dock, WindowInfoX *winInfo, QString &innerId);
|
||||
static AppInfo *identifyWindowByCmdlineTurboBooster(TaskManager *_dock, WindowInfoX *winInfo, QString &innerId);
|
||||
static AppInfo *identifyWindowByCmdlineXWalk(TaskManager *_dock, WindowInfoX *winInfo, QString &innerId);
|
||||
static AppInfo *identifyWindowByFlatpakAppID(TaskManager *_dock, WindowInfoX *winInfo, QString &innerId);
|
||||
static AppInfo *identifyWindowByCrxId(TaskManager *_dock, WindowInfoX *winInfo, QString &innerId);
|
||||
static AppInfo *identifyWindowByRule(TaskManager *_dock, WindowInfoX *winInfo, QString &innerId);
|
||||
static AppInfo *identifyWindowByBamf(TaskManager *_dock, WindowInfoX *winInfo, QString &innerId);
|
||||
static AppInfo *identifyWindowByPid(TaskManager *_dock, WindowInfoX *winInfo, QString &innerId);
|
||||
static AppInfo *identifyWindowByScratch(TaskManager *_dock, WindowInfoX *winInfo, QString &innerId);
|
||||
static AppInfo *identifyWindowByGtkAppId(TaskManager *_dock, WindowInfoX *winInfo, QString &innerId);
|
||||
static AppInfo *identifyWindowByWmClass(TaskManager *_dock, WindowInfoX *winInfo, QString &innerId);
|
||||
|
||||
private:
|
||||
AppInfo *fixAutostartAppInfo(QString fileName);
|
||||
static int32_t getAndroidUengineId(XWindow winId);
|
||||
static QString getAndroidUengineName(XWindow winId);
|
||||
|
||||
private:
|
||||
TaskManager *m_taskmanager;
|
||||
QList<QPair<QString, IdentifyFunc>> m_identifyWindowFuns;
|
||||
};
|
||||
|
||||
#endif // IDENTIFYWINDOW_H
|
68
frame/taskmanager/windowinfobase.h
Normal file
68
frame/taskmanager/windowinfobase.h
Normal file
@ -0,0 +1,68 @@
|
||||
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#ifndef WINDOWINFOBASE_H
|
||||
#define WINDOWINFOBASE_H
|
||||
|
||||
#include "processinfo.h"
|
||||
#include "xcbutils.h"
|
||||
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
#include <qobject.h>
|
||||
#include <qobjectdefs.h>
|
||||
#include <qscopedpointer.h>
|
||||
|
||||
class Entry;
|
||||
class AppInfo;
|
||||
|
||||
class WindowInfoBase : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
WindowInfoBase(QObject *parent = nullptr) : QObject(parent), entry(nullptr), app(nullptr), m_processInfo(nullptr) {}
|
||||
virtual ~WindowInfoBase() {};
|
||||
|
||||
virtual bool shouldSkip() = 0;
|
||||
virtual QString getIcon() = 0;
|
||||
virtual QString getTitle() = 0;
|
||||
virtual bool isDemandingAttention() = 0;
|
||||
virtual void close(uint32_t timestamp) = 0;
|
||||
virtual void activate() = 0;
|
||||
virtual void minimize() = 0;
|
||||
virtual bool isMinimized() = 0;
|
||||
virtual int64_t getCreatedTime() = 0;
|
||||
virtual QString getWindowType() = 0;
|
||||
virtual QString getDisplayName() = 0;
|
||||
virtual bool allowClose() = 0;
|
||||
virtual void update() = 0;
|
||||
virtual void killClient() = 0;
|
||||
virtual QString uuid() = 0;
|
||||
virtual QString getInnerId() { return innerId; }
|
||||
|
||||
XWindow getXid() {return xid;}
|
||||
void setEntry(Entry *value) { entry = value; }
|
||||
Entry *getEntry() { return entry; }
|
||||
QString getEntryInnerId() { return entryInnerId; }
|
||||
void setEntryInnerId(QString value) { entryInnerId = value; }
|
||||
AppInfo *getAppInfo() { return app; }
|
||||
void setAppInfo(AppInfo *value) { app = value; }
|
||||
int getPid() { return pid; }
|
||||
ProcessInfo *getProcess() { return m_processInfo.data(); }
|
||||
bool containAtom(QVector<XCBAtom> supports, XCBAtom ty) {return supports.indexOf(ty) != -1;}
|
||||
|
||||
protected:
|
||||
XWindow xid; // 窗口id
|
||||
QString title; // 窗口标题
|
||||
QString icon; // 窗口图标
|
||||
int pid; // 窗口所属应用进程
|
||||
QString entryInnerId; // 窗口所属应用对应的innerId
|
||||
QString innerId; // 窗口对应的innerId
|
||||
Entry *entry; // 窗口所属应用
|
||||
AppInfo *app; // 窗口所属应用对应的desktopFile信息
|
||||
int64_t m_createdTime; // 创建时间
|
||||
QScopedPointer<ProcessInfo> m_processInfo; // 窗口所属应用的进程信息
|
||||
};
|
||||
|
||||
#endif // WINDOWINFOBASE_H
|
210
frame/taskmanager/windowinfok.cpp
Normal file
210
frame/taskmanager/windowinfok.cpp
Normal file
@ -0,0 +1,210 @@
|
||||
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "windowinfok.h"
|
||||
#include "entry.h"
|
||||
#include "processinfo.h"
|
||||
#include "appinfo.h"
|
||||
|
||||
#include <chrono>
|
||||
#include <qobject.h>
|
||||
|
||||
WindowInfoK::WindowInfoK(PlasmaWindow *window, XWindow _xid, QObject *parent)
|
||||
: WindowInfoBase (parent)
|
||||
, m_updateCalled(false)
|
||||
, m_internalId(0)
|
||||
, m_demaningAttention(false)
|
||||
, m_closeable(true)
|
||||
, m_plasmaWindow(window)
|
||||
{
|
||||
xid = _xid;
|
||||
m_createdTime = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch()).count(); // 获取当前时间,精确到纳秒
|
||||
}
|
||||
|
||||
WindowInfoK::~WindowInfoK()
|
||||
{
|
||||
}
|
||||
|
||||
bool WindowInfoK::shouldSkip()
|
||||
{
|
||||
if (!m_updateCalled) {
|
||||
update();
|
||||
m_updateCalled = true;
|
||||
}
|
||||
|
||||
bool skip = m_plasmaWindow->SkipTaskbar();
|
||||
|
||||
// 添加窗口能否最小化判断, 如果窗口不能最小化则隐藏任务栏图标
|
||||
bool canMinimize = false;
|
||||
canMinimize = m_plasmaWindow->IsMinimizeable();
|
||||
if (!canMinimize)
|
||||
skip = true;
|
||||
|
||||
if (skip) {
|
||||
// 白名单, 过滤类似“欢迎应用”, 没有最小化窗口但是需要在任务栏显示图标
|
||||
QStringList list { "dde-introduction"};
|
||||
if (list.indexOf(m_appId) != -1)
|
||||
skip = false;
|
||||
}
|
||||
|
||||
return skip;
|
||||
}
|
||||
|
||||
QString WindowInfoK::getIcon()
|
||||
{
|
||||
return icon;
|
||||
}
|
||||
|
||||
QString WindowInfoK::getTitle()
|
||||
{
|
||||
return title;
|
||||
}
|
||||
|
||||
bool WindowInfoK::isDemandingAttention()
|
||||
{
|
||||
return m_demaningAttention;
|
||||
}
|
||||
|
||||
bool WindowInfoK::allowClose()
|
||||
{
|
||||
return m_closeable;
|
||||
}
|
||||
|
||||
void WindowInfoK::close(uint32_t timestamp)
|
||||
{
|
||||
m_plasmaWindow->RequestClose();
|
||||
}
|
||||
|
||||
QString WindowInfoK::getAppId()
|
||||
{
|
||||
return m_appId;
|
||||
}
|
||||
|
||||
void WindowInfoK::setAppId(QString _appId)
|
||||
{
|
||||
m_appId = _appId;
|
||||
}
|
||||
|
||||
void WindowInfoK::activate()
|
||||
{
|
||||
m_plasmaWindow->RequestActivate();
|
||||
}
|
||||
|
||||
void WindowInfoK::minimize()
|
||||
{
|
||||
m_plasmaWindow->RequestToggleMinimized();
|
||||
}
|
||||
|
||||
bool WindowInfoK::isMinimized()
|
||||
{
|
||||
return m_plasmaWindow->IsMinimized();
|
||||
}
|
||||
|
||||
bool WindowInfoK::changeXid(XWindow _xid)
|
||||
{
|
||||
xid = _xid;
|
||||
return true;
|
||||
}
|
||||
|
||||
PlasmaWindow *WindowInfoK::getPlasmaWindow()
|
||||
{
|
||||
return m_plasmaWindow.data();
|
||||
}
|
||||
|
||||
bool WindowInfoK::updateGeometry()
|
||||
{
|
||||
DockRect rect = m_plasmaWindow->Geometry();
|
||||
if (m_geometry == rect)
|
||||
return false;
|
||||
|
||||
m_geometry = rect;
|
||||
return true;
|
||||
}
|
||||
|
||||
void WindowInfoK::updateTitle()
|
||||
{
|
||||
title = m_plasmaWindow->Title();
|
||||
}
|
||||
|
||||
void WindowInfoK::updateDemandingAttention()
|
||||
{
|
||||
m_demaningAttention = m_plasmaWindow->IsDemandingAttention();
|
||||
}
|
||||
|
||||
void WindowInfoK::updateIcon()
|
||||
{
|
||||
icon = m_plasmaWindow->Icon();
|
||||
}
|
||||
|
||||
void WindowInfoK::updateAppId()
|
||||
{
|
||||
m_appId = m_plasmaWindow->AppId();
|
||||
}
|
||||
|
||||
void WindowInfoK::updateInternalId()
|
||||
{
|
||||
m_internalId = m_plasmaWindow->InternalId();
|
||||
}
|
||||
|
||||
void WindowInfoK::updateCloseable()
|
||||
{
|
||||
m_closeable = m_plasmaWindow->IsCloseable();
|
||||
}
|
||||
|
||||
void WindowInfoK::updateProcessInfo()
|
||||
{
|
||||
pid = m_plasmaWindow->Pid();
|
||||
m_processInfo.reset(new ProcessInfo(pid));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief WindowInfoK::getGeometry 获取窗口大小
|
||||
* @return
|
||||
*/
|
||||
DockRect WindowInfoK::getGeometry()
|
||||
{
|
||||
return m_geometry;
|
||||
}
|
||||
|
||||
int64_t WindowInfoK::getCreatedTime()
|
||||
{
|
||||
return m_createdTime;
|
||||
}
|
||||
|
||||
// 主要是为兼容X11
|
||||
QString WindowInfoK::getDisplayName()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
QString WindowInfoK::getWindowType()
|
||||
{
|
||||
return "Wayland";
|
||||
}
|
||||
|
||||
void WindowInfoK::update()
|
||||
{
|
||||
updateInternalId();
|
||||
updateAppId();
|
||||
updateIcon();
|
||||
updateTitle();
|
||||
updateGeometry();
|
||||
updateDemandingAttention();
|
||||
updateCloseable();
|
||||
updateProcessInfo();
|
||||
}
|
||||
|
||||
void WindowInfoK::killClient()
|
||||
{
|
||||
}
|
||||
|
||||
QString WindowInfoK::uuid()
|
||||
{
|
||||
return QString(m_plasmaWindow->uuid());
|
||||
}
|
||||
|
||||
QString WindowInfoK::getInnerId()
|
||||
{
|
||||
return QString::number(m_internalId);
|
||||
}
|
68
frame/taskmanager/windowinfok.h
Normal file
68
frame/taskmanager/windowinfok.h
Normal file
@ -0,0 +1,68 @@
|
||||
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#ifndef WINDOWINFOK_H
|
||||
#define WINDOWINFOK_H
|
||||
|
||||
#include "windowinfobase.h"
|
||||
#include "org_deepin_dde_kwayland_plasmawindow.h"
|
||||
|
||||
#include <QString>
|
||||
#include <qobject.h>
|
||||
#include <qscopedpointer.h>
|
||||
|
||||
using PlasmaWindow = org::deepin::dde::kwayland1::PlasmaWindow;
|
||||
|
||||
class Entry;
|
||||
class ProcessInfo;
|
||||
|
||||
// wayland下窗口信息
|
||||
class WindowInfoK: public WindowInfoBase
|
||||
{
|
||||
public:
|
||||
explicit WindowInfoK(PlasmaWindow *window, XWindow _xid = 0, QObject *parent = nullptr);
|
||||
virtual ~WindowInfoK() override;
|
||||
|
||||
virtual bool shouldSkip() override;
|
||||
virtual QString getIcon() override;
|
||||
virtual QString getTitle() override;
|
||||
virtual bool isDemandingAttention() override;
|
||||
virtual bool allowClose() override;
|
||||
virtual void close(uint32_t timestamp) override;
|
||||
virtual void activate() override;
|
||||
virtual void minimize() override;
|
||||
virtual bool isMinimized() override;
|
||||
virtual int64_t getCreatedTime() override;
|
||||
virtual QString getDisplayName() override;
|
||||
virtual QString getWindowType() override;
|
||||
virtual void update() override;
|
||||
virtual void killClient() override;
|
||||
virtual QString uuid() override;
|
||||
QString getInnerId() override;
|
||||
|
||||
QString getAppId();
|
||||
void setAppId(QString _appId);
|
||||
bool changeXid(XWindow _xid);
|
||||
PlasmaWindow *getPlasmaWindow();
|
||||
bool updateGeometry();
|
||||
void updateTitle();
|
||||
void updateDemandingAttention();
|
||||
void updateIcon();
|
||||
void updateAppId();
|
||||
void updateInternalId();
|
||||
void updateCloseable();
|
||||
void updateProcessInfo();
|
||||
DockRect getGeometry();
|
||||
|
||||
private:
|
||||
bool m_updateCalled;
|
||||
QString m_appId;
|
||||
uint32_t m_internalId;
|
||||
bool m_demaningAttention;
|
||||
bool m_closeable;
|
||||
DockRect m_geometry;
|
||||
QScopedPointer<PlasmaWindow> m_plasmaWindow;
|
||||
};
|
||||
|
||||
#endif // WINDOWINFOK_H
|
37
frame/taskmanager/windowinfomap.cpp
Normal file
37
frame/taskmanager/windowinfomap.cpp
Normal file
@ -0,0 +1,37 @@
|
||||
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "windowinfomap.h"
|
||||
|
||||
QDebug operator<<(QDebug argument, const WindowInfo &info)
|
||||
{
|
||||
argument << '(' << info.title << ',' << info.attention << info.uuid << ')';
|
||||
|
||||
return argument;
|
||||
}
|
||||
|
||||
QDBusArgument &operator<<(QDBusArgument &argument, const WindowInfo &info)
|
||||
{
|
||||
argument.beginStructure();
|
||||
argument << info.title << info.attention << info.uuid;
|
||||
argument.endStructure();
|
||||
|
||||
return argument;
|
||||
}
|
||||
|
||||
const QDBusArgument &operator>>(const QDBusArgument &argument, WindowInfo &info)
|
||||
{
|
||||
argument.beginStructure();
|
||||
argument >> info.title >> info.attention >> info.uuid;
|
||||
argument.endStructure();
|
||||
|
||||
return argument;
|
||||
}
|
||||
|
||||
bool WindowInfo::operator==(const WindowInfo &rhs) const
|
||||
{
|
||||
return attention == rhs.attention &&
|
||||
title == rhs.title &&
|
||||
uuid == rhs.uuid;
|
||||
}
|
28
frame/taskmanager/windowinfomap.h
Normal file
28
frame/taskmanager/windowinfomap.h
Normal file
@ -0,0 +1,28 @@
|
||||
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#ifndef WINDOWINFOLIST_H
|
||||
#define WINDOWINFOLIST_H
|
||||
|
||||
#include <QDebug>
|
||||
#include <QList>
|
||||
#include <QDBusArgument>
|
||||
|
||||
class WindowInfo
|
||||
{
|
||||
public:
|
||||
friend QDebug operator<<(QDebug argument, const WindowInfo &info);
|
||||
friend QDBusArgument &operator<<(QDBusArgument &argument, const WindowInfo &info);
|
||||
friend const QDBusArgument &operator>>(const QDBusArgument &argument, WindowInfo &info);
|
||||
|
||||
bool operator==(const WindowInfo &rhs) const;
|
||||
|
||||
public:
|
||||
bool attention;
|
||||
QString title;
|
||||
QString uuid;
|
||||
};
|
||||
typedef QMap<quint32, WindowInfo> WindowInfoMap;
|
||||
|
||||
#endif // WINDOWINFOLIST_H
|
470
frame/taskmanager/windowinfox.cpp
Normal file
470
frame/taskmanager/windowinfox.cpp
Normal file
@ -0,0 +1,470 @@
|
||||
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "windowinfox.h"
|
||||
#include "appinfo.h"
|
||||
#include "xcbutils.h"
|
||||
#include "common.h"
|
||||
#include "processinfo.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QCryptographicHash>
|
||||
#include <QTimer>
|
||||
#include <QImage>
|
||||
#include <QIcon>
|
||||
#include <QBuffer>
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <algorithm>
|
||||
#include <qobject.h>
|
||||
#include <string>
|
||||
|
||||
#define XCB XCBUtils::instance()
|
||||
|
||||
WindowInfoX::WindowInfoX(XWindow _xid, QObject *parent)
|
||||
: WindowInfoBase (parent)
|
||||
, m_x(0)
|
||||
, m_y(0)
|
||||
, m_width(0)
|
||||
, m_height(0)
|
||||
, m_hasWMTransientFor(false)
|
||||
, m_hasXEmbedInfo(false)
|
||||
, m_updateCalled(false)
|
||||
{
|
||||
xid = _xid;
|
||||
m_createdTime = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch()).count(); // 获取当前时间,精确到纳秒
|
||||
}
|
||||
|
||||
WindowInfoX::~WindowInfoX()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool WindowInfoX::shouldSkip()
|
||||
{
|
||||
qInfo() << "window " << xid << " shouldSkip?";
|
||||
if (!m_updateCalled) {
|
||||
update();
|
||||
m_updateCalled = true;
|
||||
}
|
||||
|
||||
if (hasWmStateSkipTaskBar() || isValidModal() || shouldSkipWithWMClass())
|
||||
return true;
|
||||
|
||||
for (auto atom : m_wmWindowType) {
|
||||
if (atom == XCB->getAtom("_NET_WM_WINDOW_TYPE_DIALOG") && !isActionMinimizeAllowed())
|
||||
return true;
|
||||
|
||||
if (atom == XCB->getAtom("_NET_WM_WINDOW_TYPE_UTILITY")
|
||||
|| atom == XCB->getAtom("_NET_WM_WINDOW_TYPE_COMBO")
|
||||
|| atom == XCB->getAtom("_NET_WM_WINDOW_TYPE_DESKTOP") // 桌面属性窗口
|
||||
|| atom == XCB->getAtom("_NET_WM_WINDOW_TYPE_DND")
|
||||
|| atom == XCB->getAtom("_NET_WM_WINDOW_TYPE_DOCK") // 任务栏属性窗口
|
||||
|| atom == XCB->getAtom("_NET_WM_WINDOW_TYPE_DROPDOWN_MENU")
|
||||
|| atom == XCB->getAtom("_NET_WM_WINDOW_TYPE_MENU")
|
||||
|| atom == XCB->getAtom("_NET_WM_WINDOW_TYPE_NOTIFICATION")
|
||||
|| atom == XCB->getAtom("_NET_WM_WINDOW_TYPE_POPUP_MENU")
|
||||
|| atom == XCB->getAtom("_NET_WM_WINDOW_TYPE_SPLASH")
|
||||
|| atom == XCB->getAtom("_NET_WM_WINDOW_TYPE_TOOLBAR")
|
||||
|| atom == XCB->getAtom("_NET_WM_WINDOW_TYPE_TOOLTIP"))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
QString WindowInfoX::getIcon()
|
||||
{
|
||||
if (icon.isEmpty())
|
||||
icon = getIconFromWindow();
|
||||
|
||||
return icon;
|
||||
}
|
||||
|
||||
void WindowInfoX::activate()
|
||||
{
|
||||
XCB->changeActiveWindow(xid);
|
||||
QTimer::singleShot(50, [&] {
|
||||
XCB->restackWindow(xid);
|
||||
});
|
||||
}
|
||||
|
||||
void WindowInfoX::minimize()
|
||||
{
|
||||
XCB->minimizeWindow(xid);
|
||||
}
|
||||
|
||||
bool WindowInfoX::isMinimized()
|
||||
{
|
||||
return containAtom(m_wmState, XCB->getAtom("_NET_WM_STATE_HIDDEN"));
|
||||
}
|
||||
|
||||
int64_t WindowInfoX::getCreatedTime()
|
||||
{
|
||||
return m_createdTime;
|
||||
}
|
||||
|
||||
QString WindowInfoX::getWindowType()
|
||||
{
|
||||
return "X11";
|
||||
}
|
||||
|
||||
bool WindowInfoX::allowClose()
|
||||
{
|
||||
// 允许关闭的条件:
|
||||
// 1. 不设置 functions 字段,即MotifHintFunctions 标志位;
|
||||
// 2. 或者设置了 functions 字段并且 设置了 MotifFunctionAll 标志位;
|
||||
// 3. 或者设置了 functions 字段并且 设置了 MotifFunctionClose 标志位。
|
||||
// 相关定义在 motif-2.3.8/lib/Xm/MwmUtil.h 。
|
||||
if ((m_motifWmHints.flags & MotifHintFunctions) == 0
|
||||
|| (m_motifWmHints.functions & MotifFunctionAll) != 0
|
||||
|| (m_motifWmHints.functions & MotifFunctionClose) != 0)
|
||||
return true;
|
||||
|
||||
for (auto action : m_wmAllowedActions) {
|
||||
if (action == XCB->getAtom("_NET_WM_ACTION_CLOSE")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
QString WindowInfoX::getDisplayName()
|
||||
{
|
||||
XWindow winId = xid;
|
||||
//QString role = wmRole;
|
||||
QString className(m_wmClass.className.c_str());
|
||||
QString instance;
|
||||
if (m_wmClass.instanceName.size() > 0) {
|
||||
int pos = QString(m_wmClass.instanceName.c_str()).lastIndexOf('/');
|
||||
if (pos != -1)
|
||||
instance.remove(0, pos + 1);
|
||||
}
|
||||
qInfo() << "getDisplayName class:" << className << " ,instance:" << instance;
|
||||
|
||||
//if (!role.isEmpty() && !className.isEmpty())
|
||||
// return className + " " + role;
|
||||
|
||||
if (!className.isEmpty())
|
||||
return className;
|
||||
|
||||
if (!instance.isEmpty())
|
||||
return instance;
|
||||
|
||||
|
||||
QString _wmName = m_wmName;
|
||||
if (!_wmName.isEmpty()) {
|
||||
int pos = _wmName.lastIndexOf('-');
|
||||
if (pos != -1 && !_wmName.startsWith("-")) {
|
||||
_wmName.truncate(pos);
|
||||
return _wmName;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_processInfo) {
|
||||
QString exe {m_processInfo->getEnv("exe")};
|
||||
if (!exe.isEmpty())
|
||||
return exe;
|
||||
}
|
||||
|
||||
return QString("window:%1").arg(winId);
|
||||
}
|
||||
|
||||
void WindowInfoX::killClient()
|
||||
{
|
||||
XCB->killClientChecked(xid);
|
||||
}
|
||||
|
||||
QString WindowInfoX::uuid()
|
||||
{
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString WindowInfoX::getGtkAppId()
|
||||
{
|
||||
return m_gtkAppId;
|
||||
}
|
||||
|
||||
QString WindowInfoX::getFlatpakAppId()
|
||||
{
|
||||
return m_flatpakAppId;
|
||||
}
|
||||
|
||||
QString WindowInfoX::getWmRole()
|
||||
{
|
||||
return m_wmRole;
|
||||
}
|
||||
|
||||
WMClass WindowInfoX::getWMClass()
|
||||
{
|
||||
return m_wmClass;
|
||||
}
|
||||
|
||||
QString WindowInfoX::getWMName()
|
||||
{
|
||||
return m_wmName;
|
||||
}
|
||||
|
||||
ConfigureEvent *WindowInfoX::getLastConfigureEvent()
|
||||
{
|
||||
return m_lastConfigureNotifyEvent;
|
||||
}
|
||||
|
||||
void WindowInfoX::setLastConfigureEvent(ConfigureEvent *event)
|
||||
{
|
||||
m_lastConfigureNotifyEvent = event;
|
||||
}
|
||||
|
||||
bool WindowInfoX::isGeometryChanged(int _x, int _y, int _width, int _height)
|
||||
{
|
||||
return !(_x == m_x && _y == m_y && _width == m_width && _height == m_height);
|
||||
}
|
||||
|
||||
void WindowInfoX::setGtkAppId(QString _gtkAppId)
|
||||
{
|
||||
m_gtkAppId = _gtkAppId;
|
||||
}
|
||||
|
||||
void WindowInfoX::updateMotifWmHints()
|
||||
{
|
||||
// get from XCB
|
||||
m_motifWmHints = XCB->getWindowMotifWMHints(xid);
|
||||
}
|
||||
|
||||
// XEmbed info
|
||||
// 一般 tray icon 会带有 _XEMBED_INFO 属性
|
||||
void WindowInfoX::updateHasXEmbedInfo()
|
||||
{
|
||||
m_hasXEmbedInfo = XCB->hasXEmbedInfo(xid);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief WindowInfoX::genInnerId 生成innerId
|
||||
* @param winInfo
|
||||
* @return
|
||||
*/
|
||||
QString WindowInfoX::genInnerId(WindowInfoX *winInfo)
|
||||
{
|
||||
XWindow winId = winInfo->getXid();
|
||||
QString wmClassName, wmInstance;
|
||||
WMClass wmClass = winInfo->getWMClass();
|
||||
if (wmClass.className.size() > 0)
|
||||
wmClassName = wmClass.className.c_str();
|
||||
|
||||
if (wmClass.instanceName.size() > 0) {
|
||||
QString instanceName(wmClass.instanceName.c_str());
|
||||
instanceName.remove(0, instanceName.lastIndexOf('/') + 1);
|
||||
wmInstance = instanceName;
|
||||
}
|
||||
|
||||
QString exe, args;
|
||||
if (winInfo->getProcess()) {
|
||||
exe = winInfo->getProcess()->getExe();
|
||||
for (auto arg : winInfo->getProcess()->getArgs()) {
|
||||
if (arg.contains("/") || arg == "." || arg == "..") {
|
||||
args += "%F ";
|
||||
} else {
|
||||
args += arg + " ";
|
||||
}
|
||||
}
|
||||
|
||||
if (args.size() > 0)
|
||||
args.remove(args.size() - 2, 1);
|
||||
}
|
||||
|
||||
bool hasPid = winInfo->getPid() != 0;
|
||||
QString str;
|
||||
// NOTE: 不要使用 wmRole,有些程序总会改变这个值比如 GVim
|
||||
if (wmInstance.isEmpty() && wmClassName.isEmpty() && exe.isEmpty() && winInfo->getGtkAppId().isEmpty()) {
|
||||
if (!winInfo->getWMName().isEmpty())
|
||||
str = QString("wmName:%1").arg(winInfo->getWMName());
|
||||
else
|
||||
str = QString("windowId:%1").arg(winInfo->getXid());
|
||||
} else {
|
||||
str = QString("wmInstance:%1,wmClass:%2,exe:%3,args:%4,hasPid:%5,gtkAppId:%6").arg(wmInstance).arg(wmClassName).arg(exe).arg(args).arg(hasPid).arg(winInfo->getGtkAppId());
|
||||
}
|
||||
|
||||
QByteArray encryText = QCryptographicHash::hash(str.toLatin1(), QCryptographicHash::Md5);
|
||||
QString innerId = windowHashPrefix + encryText.toHex();
|
||||
qInfo() << "genInnerId window " << winId << " innerId :" << innerId;
|
||||
return innerId;
|
||||
}
|
||||
|
||||
// 更新窗口类型
|
||||
void WindowInfoX::updateWmWindowType()
|
||||
{
|
||||
m_wmWindowType.clear();
|
||||
for (auto ty : XCB->getWMWindoType(xid)) {
|
||||
m_wmWindowType.push_back(ty);
|
||||
}
|
||||
}
|
||||
|
||||
// 更新窗口许可动作
|
||||
void WindowInfoX::updateWmAllowedActions()
|
||||
{
|
||||
m_wmAllowedActions.clear();
|
||||
for (auto action : XCB->getWMAllowedActions(xid)) {
|
||||
m_wmAllowedActions.push_back(action);
|
||||
}
|
||||
}
|
||||
|
||||
void WindowInfoX::updateWmState()
|
||||
{
|
||||
m_wmState.clear();
|
||||
for (auto a : XCB->getWMState(xid)) {
|
||||
m_wmState.push_back(a);
|
||||
}
|
||||
}
|
||||
|
||||
void WindowInfoX::updateWmClass()
|
||||
{
|
||||
m_wmClass = XCB->getWMClass(xid);
|
||||
}
|
||||
|
||||
void WindowInfoX::updateWmName()
|
||||
{
|
||||
auto name = XCB->getWMName(xid);
|
||||
if (!name.empty())
|
||||
m_wmName = name.c_str();
|
||||
|
||||
title = getTitle();
|
||||
}
|
||||
|
||||
void WindowInfoX::updateIcon()
|
||||
{
|
||||
icon = getIconFromWindow();
|
||||
}
|
||||
|
||||
void WindowInfoX::updateHasWmTransientFor()
|
||||
{
|
||||
if (XCB->getWMTransientFor(xid) == 1)
|
||||
m_hasWMTransientFor = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief WindowInfoX::update 更新窗口信息(在识别窗口时执行一次)
|
||||
*/
|
||||
void WindowInfoX::update()
|
||||
{
|
||||
updateWmClass();
|
||||
updateWmState();
|
||||
updateWmWindowType();
|
||||
updateWmAllowedActions();
|
||||
updateHasWmTransientFor();
|
||||
updateProcessInfo();
|
||||
updateWmName();
|
||||
innerId = genInnerId(this);
|
||||
}
|
||||
|
||||
QString WindowInfoX::getIconFromWindow()
|
||||
{
|
||||
WMIcon icon = XCB->getWMIcon(xid);
|
||||
|
||||
// invalid icon
|
||||
if (icon.width == 0) {
|
||||
return QString();
|
||||
}
|
||||
|
||||
QImage img = QImage((uchar *)icon.data.data(), icon.width, icon.width, QImage::Format_ARGB32);
|
||||
QBuffer buffer;
|
||||
buffer.open(QIODevice::WriteOnly);
|
||||
img.scaled(48, 48, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
img.save(&buffer, "PNG");
|
||||
|
||||
// convert to base64
|
||||
QString encode = buffer.data().toBase64();
|
||||
QString iconPath = QString("%1,%2").arg("data:image/png:base64").arg(encode);
|
||||
buffer.close();
|
||||
|
||||
return iconPath;
|
||||
}
|
||||
|
||||
bool WindowInfoX::isActionMinimizeAllowed()
|
||||
{
|
||||
return containAtom(m_wmAllowedActions, XCB->getAtom("_NET_WM_ACTION_MINIMIZE"));
|
||||
}
|
||||
|
||||
bool WindowInfoX::hasWmStateDemandsAttention()
|
||||
{
|
||||
return containAtom(m_wmState, XCB->getAtom("_NET_WM_STATE_DEMANDS_ATTENTION"));
|
||||
}
|
||||
|
||||
bool WindowInfoX::hasWmStateSkipTaskBar()
|
||||
{
|
||||
return containAtom(m_wmState, XCB->getAtom("_NET_WM_STATE_SKIP_TASKBAR"));
|
||||
}
|
||||
|
||||
bool WindowInfoX::hasWmStateModal()
|
||||
{
|
||||
return containAtom(m_wmState, XCB->getAtom("_NET_WM_STATE_MODAL"));
|
||||
}
|
||||
|
||||
bool WindowInfoX::isValidModal()
|
||||
{
|
||||
return hasWmStateModal() && hasWmStateModal();
|
||||
}
|
||||
|
||||
// 通过WMClass判断是否需要隐藏此窗口
|
||||
bool WindowInfoX::shouldSkipWithWMClass()
|
||||
{
|
||||
bool ret = false;
|
||||
if (m_wmClass.instanceName == "explorer.exe" && m_wmClass.className == "Wine")
|
||||
ret = true;
|
||||
else if (m_wmClass.className == "dde-launcher" ||
|
||||
m_wmClass.className == "dde-dock" ||
|
||||
m_wmClass.className == "dde-lock") {
|
||||
ret = true;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void WindowInfoX::updateProcessInfo()
|
||||
{
|
||||
XWindow winId = xid;
|
||||
pid = XCB->getWMPid(winId);
|
||||
qInfo() << "updateProcessInfo: pid=" << pid;
|
||||
m_processInfo.reset(new ProcessInfo(pid));
|
||||
if (!m_processInfo->isValid()) {
|
||||
// try WM_COMMAND
|
||||
auto wmComand = XCB->getWMCommand(winId);
|
||||
if (wmComand.size() > 0) {
|
||||
QStringList cmds;
|
||||
std::transform(wmComand.begin(), wmComand.end(), std::back_inserter(cmds), [=] (std::string cmd){ return QString::fromStdString(cmd);});
|
||||
m_processInfo.reset(new ProcessInfo(cmds));
|
||||
}
|
||||
}
|
||||
|
||||
qInfo() << "updateProcessInfo: pid is " << pid;
|
||||
}
|
||||
|
||||
bool WindowInfoX::getUpdateCalled()
|
||||
{
|
||||
return m_updateCalled;
|
||||
}
|
||||
|
||||
void WindowInfoX::setInnerId(QString _innerId)
|
||||
{
|
||||
innerId = _innerId;
|
||||
}
|
||||
|
||||
QString WindowInfoX::getTitle()
|
||||
{
|
||||
QString name = m_wmName;
|
||||
if (name.isEmpty())
|
||||
name = getDisplayName();
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
bool WindowInfoX::isDemandingAttention()
|
||||
{
|
||||
return hasWmStateDemandsAttention();
|
||||
}
|
||||
|
||||
void WindowInfoX::close(uint32_t timestamp)
|
||||
{
|
||||
XCB->requestCloseWindow(xid, timestamp);
|
||||
}
|
98
frame/taskmanager/windowinfox.h
Normal file
98
frame/taskmanager/windowinfox.h
Normal file
@ -0,0 +1,98 @@
|
||||
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#ifndef WINDOWINFOX_H
|
||||
#define WINDOWINFOX_H
|
||||
|
||||
#include "windowinfobase.h"
|
||||
#include "xcbutils.h"
|
||||
|
||||
#include <QVector>
|
||||
#include <qobject.h>
|
||||
#include <qobjectdefs.h>
|
||||
|
||||
class AppInfo;
|
||||
|
||||
// X11下窗口信息 在明确X11环境下使用
|
||||
class WindowInfoX: public WindowInfoBase
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
WindowInfoX(XWindow _xid = 0, QObject *parent = nullptr);
|
||||
virtual ~WindowInfoX() override;
|
||||
|
||||
virtual bool shouldSkip() override;
|
||||
virtual QString getIcon() override;
|
||||
virtual QString getTitle() override;
|
||||
virtual bool isDemandingAttention() override;
|
||||
virtual void close(uint32_t timestamp) override;
|
||||
virtual void activate() override;
|
||||
virtual void minimize() override;
|
||||
virtual bool isMinimized() override;
|
||||
virtual int64_t getCreatedTime() override;
|
||||
virtual QString getDisplayName() override;
|
||||
virtual QString getWindowType() override;
|
||||
virtual bool allowClose() override;
|
||||
virtual void update() override;
|
||||
virtual void killClient() override;
|
||||
virtual QString uuid() override;
|
||||
|
||||
QString genInnerId(WindowInfoX *winInfo);
|
||||
QString getGtkAppId();
|
||||
QString getFlatpakAppId();
|
||||
QString getWmRole();
|
||||
WMClass getWMClass();
|
||||
QString getWMName();
|
||||
void updateProcessInfo();
|
||||
bool getUpdateCalled();
|
||||
void setInnerId(QString _innerId);
|
||||
ConfigureEvent *getLastConfigureEvent();
|
||||
void setLastConfigureEvent(ConfigureEvent *event);
|
||||
bool isGeometryChanged(int _x, int _y, int _width, int _height);
|
||||
void setGtkAppId(QString _gtkAppId);
|
||||
|
||||
/************************更新XCB窗口属性*********************/
|
||||
void updateWmWindowType();
|
||||
void updateWmAllowedActions();
|
||||
void updateWmState();
|
||||
void updateWmClass();
|
||||
void updateMotifWmHints();
|
||||
void updateWmName();
|
||||
void updateIcon();
|
||||
void updateHasXEmbedInfo();
|
||||
void updateHasWmTransientFor();
|
||||
|
||||
private:
|
||||
QString getIconFromWindow();
|
||||
bool isActionMinimizeAllowed();
|
||||
bool hasWmStateDemandsAttention();
|
||||
bool hasWmStateSkipTaskBar();
|
||||
bool hasWmStateModal();
|
||||
bool isValidModal();
|
||||
bool shouldSkipWithWMClass();
|
||||
|
||||
private:
|
||||
int16_t m_x;
|
||||
int16_t m_y;
|
||||
uint16_t m_width;
|
||||
uint16_t m_height;
|
||||
QVector<XCBAtom> m_wmState;
|
||||
QVector<XCBAtom> m_wmWindowType;
|
||||
QVector<XCBAtom> m_wmAllowedActions;
|
||||
bool m_hasWMTransientFor;
|
||||
WMClass m_wmClass;
|
||||
QString m_wmName;
|
||||
bool m_hasXEmbedInfo;
|
||||
|
||||
// 自定义atom属性
|
||||
QString m_gtkAppId;
|
||||
QString m_flatpakAppId;
|
||||
QString m_wmRole;
|
||||
MotifWMHints m_motifWmHints;
|
||||
|
||||
bool m_updateCalled;
|
||||
ConfigureEvent *m_lastConfigureNotifyEvent;
|
||||
};
|
||||
|
||||
#endif // WINDOWINFOX_H
|
299
frame/taskmanager/windowpatterns.cpp
Normal file
299
frame/taskmanager/windowpatterns.cpp
Normal file
@ -0,0 +1,299 @@
|
||||
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "windowpatterns.h"
|
||||
#include "processinfo.h"
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QStandardPaths>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonValue>
|
||||
#include <QJsonArray>
|
||||
#include <QVariant>
|
||||
#include <QVariantMap>
|
||||
#include <QDebug>
|
||||
#include <QRegExp>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
|
||||
const int parsedFlagNegative = 0x001;
|
||||
const int parsedFlagIgnoreCase = 0x010;
|
||||
|
||||
const QString getWindowPatternsFile(){
|
||||
for (auto dataLocation : QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation)) {
|
||||
QString targetFilePath = dataLocation.append("/dde-dock/window_patterns.json");
|
||||
if (QFile::exists(targetFilePath)) return targetFilePath;
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
bool contains(QString key, QString value) {
|
||||
return key.contains(value);
|
||||
}
|
||||
|
||||
bool containsIgnoreCase(QString key, QString value) {
|
||||
QString _key = key.toLower();
|
||||
QString _value = value.toLower();
|
||||
return _key.contains(_value);
|
||||
}
|
||||
|
||||
bool equal(QString key, QString value) {
|
||||
return key == value;
|
||||
}
|
||||
|
||||
bool equalIgnoreCase(QString key, QString value) {
|
||||
return key.toLower() == value.toLower();
|
||||
}
|
||||
|
||||
bool regexMatch(QString key, QString value) {
|
||||
QRegExp ruleRegex(value);
|
||||
bool ret = ruleRegex.exactMatch(key);
|
||||
|
||||
// 配置中\.exe$ 在V20中go代码可以匹配以.exe结尾的字符串, Qt中使用\.*exe$匹配以.exe结尾字符串失败,暂时做兼容处理
|
||||
if (!ret && value == "\\.exe$") {
|
||||
ret = key.endsWith(".exe");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool regexMatchIgnoreCase(QString key, QString value) {
|
||||
QRegExp ruleRegex(value, Qt::CaseInsensitive);
|
||||
bool ret = ruleRegex.exactMatch(key);
|
||||
|
||||
// 配置中\.exe$ 在V20中go代码可以匹配以.exe结尾的字符串, Qt中使用\.*exe$匹配以.exe结尾字符串失败,暂时做兼容处理
|
||||
if (!ret && value == "\\.exe$") {
|
||||
QString _key = key.toLower();
|
||||
ret = _key.endsWith(".exe");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
RuleValueParse::RuleValueParse()
|
||||
: negative(false)
|
||||
, type(0)
|
||||
, flags(0)
|
||||
{
|
||||
}
|
||||
|
||||
bool RuleValueParse::match(const WindowInfoX *winInfo)
|
||||
{
|
||||
QString parsedKey = parseRuleKey(const_cast<WindowInfoX *>(winInfo), key);
|
||||
if (!fn)
|
||||
return false;
|
||||
|
||||
bool ret = fn(parsedKey, value);
|
||||
return negative ? !ret : ret;
|
||||
}
|
||||
|
||||
QString RuleValueParse::parseRuleKey(WindowInfoX *winInfo, const QString &ruleKey)
|
||||
{
|
||||
ProcessInfo * process = winInfo->getProcess();
|
||||
if (ruleKey == "hasPid") {
|
||||
if (process && process->initWithPid()) {
|
||||
return "t";
|
||||
}
|
||||
return "f";
|
||||
} else if (ruleKey == "exec") {
|
||||
if (process) {
|
||||
// 返回执行文件baseName
|
||||
auto baseName = QFileInfo(process->getExe()).completeBaseName();
|
||||
return baseName.isEmpty() ? "" : baseName;
|
||||
}
|
||||
} else if (ruleKey == "arg") {
|
||||
if (process) {
|
||||
// 返回命令行参数
|
||||
auto ret = process->getArgs().join("");
|
||||
return ret.isEmpty() ? "" : ret;
|
||||
}
|
||||
} else if (ruleKey == "wmi") {
|
||||
// 窗口实例
|
||||
auto wmClass = winInfo->getWMClass();
|
||||
if (!wmClass.instanceName.empty())
|
||||
return wmClass.instanceName.c_str();
|
||||
} else if (ruleKey == "wmc") {
|
||||
// 窗口类型
|
||||
auto wmClass = winInfo->getWMClass();
|
||||
if (!wmClass.className.empty())
|
||||
return wmClass.className.c_str();
|
||||
} else if (ruleKey == "wmn") {
|
||||
// 窗口名称
|
||||
return winInfo->getWMName();
|
||||
} else if (ruleKey == "wmrole") {
|
||||
// 窗口角色
|
||||
return winInfo->getWmRole();
|
||||
} else {
|
||||
const QString envPrefix = "env.";
|
||||
if (ruleKey.startsWith(envPrefix)) {
|
||||
QString envName = ruleKey.mid(envPrefix.size());
|
||||
if (winInfo->getProcess()) {
|
||||
auto ret = process->getEnv(envName);
|
||||
return ret.isEmpty() ? "" : ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
WindowPatterns::WindowPatterns()
|
||||
{
|
||||
loadWindowPatterns();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief WindowPatterns::match 匹配窗口类型
|
||||
* @param winInfo
|
||||
* @return
|
||||
*/
|
||||
QString WindowPatterns::match(WindowInfoX *winInfo)
|
||||
{
|
||||
for (auto pattern : m_patterns) {
|
||||
bool patternOk = true;
|
||||
for (auto rule : pattern.parseRules) {
|
||||
if (!rule.match(winInfo)) {
|
||||
patternOk = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (patternOk) {
|
||||
// 匹配成功
|
||||
return pattern.result;
|
||||
}
|
||||
}
|
||||
|
||||
// 匹配失败
|
||||
return "";
|
||||
}
|
||||
|
||||
void WindowPatterns::loadWindowPatterns()
|
||||
{
|
||||
qInfo() << "---loadWindowPatterns";
|
||||
QFile file(getWindowPatternsFile());
|
||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
|
||||
return;
|
||||
|
||||
QJsonDocument doc = QJsonDocument::fromJson(file.readAll());
|
||||
file.close();
|
||||
if (!doc.isArray())
|
||||
return;
|
||||
|
||||
QJsonArray arr = doc.array();
|
||||
if (arr.size() == 0)
|
||||
return;
|
||||
|
||||
m_patterns.clear();
|
||||
for (auto iterp = arr.begin(); iterp != arr.end(); iterp++) {
|
||||
// 过滤非Object
|
||||
if (!(*iterp).isObject())
|
||||
continue;
|
||||
|
||||
QJsonObject patternObj = (*iterp).toObject();
|
||||
QVariantMap patternMap = patternObj.toVariantMap();
|
||||
WindowPattern pattern;
|
||||
for (auto infoIter = patternMap.begin(); infoIter != patternMap.end(); infoIter++) {
|
||||
QString ret = infoIter.key();
|
||||
QVariant value = infoIter.value();
|
||||
|
||||
if (ret == "ret") {
|
||||
pattern.result = value.toString();
|
||||
} else if (ret == "rules") {
|
||||
for (auto &item : value.toList()) {
|
||||
if (!item.isValid())
|
||||
continue;
|
||||
|
||||
if (item.toList().size() != 2)
|
||||
continue;
|
||||
|
||||
pattern.rules.push_back({item.toList()[0].toString(), item.toList()[1].toString()});
|
||||
}
|
||||
}
|
||||
}
|
||||
qInfo() << pattern.result;
|
||||
for (const auto &item : pattern.rules) {
|
||||
qInfo() << item[0] << " " << item[1];
|
||||
}
|
||||
m_patterns.push_back(pattern);
|
||||
}
|
||||
|
||||
// 解析patterns
|
||||
for (auto &pattern : m_patterns) {
|
||||
for (int i=0; i < pattern.rules.size(); i++) {
|
||||
RuleValueParse ruleValue = parseRule(pattern.rules[i]);
|
||||
pattern.parseRules.push_back(ruleValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// "=:XXX" equal XXX
|
||||
// "=!XXX" not equal XXX
|
||||
|
||||
// "c:XXX" contains XXX
|
||||
// "c!XXX" not contains XXX
|
||||
|
||||
// "r:XXX" match regexp XXX
|
||||
// "r!XXX" not match regexp XXX
|
||||
|
||||
// e c r ignore case
|
||||
// = E C R not ignore case
|
||||
// 解析窗口类型规则
|
||||
RuleValueParse WindowPatterns::parseRule(QVector<QString> rule)
|
||||
{
|
||||
RuleValueParse ret;
|
||||
ret.key = rule[0];
|
||||
ret.original = rule[1];
|
||||
if (rule[1].size() < 2)
|
||||
return ret;
|
||||
|
||||
int len = ret.original.size() + 1;
|
||||
char *orig = static_cast<char *>(calloc(1, size_t(len)));
|
||||
if (!orig)
|
||||
return ret;
|
||||
|
||||
strncpy(orig, ret.original.toStdString().c_str(), size_t(len));
|
||||
switch (orig[1]) {
|
||||
case ':':
|
||||
break;
|
||||
case '!':
|
||||
ret.flags |= parsedFlagNegative;
|
||||
ret.negative = true;
|
||||
break;
|
||||
default:
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret.value = QString(&orig[2]);
|
||||
ret.type = uint8_t(orig[0]);
|
||||
switch (orig[0]) {
|
||||
case 'C':
|
||||
ret.fn = contains;
|
||||
break;
|
||||
case 'c':
|
||||
ret.flags |= parsedFlagIgnoreCase;
|
||||
ret.fn = containsIgnoreCase;
|
||||
break;
|
||||
case '=':
|
||||
case 'E':
|
||||
ret.fn = equal;
|
||||
break;
|
||||
case 'e':
|
||||
ret.flags |= parsedFlagIgnoreCase;
|
||||
ret.fn = equalIgnoreCase;
|
||||
break;
|
||||
case 'R':
|
||||
ret.fn = regexMatch;
|
||||
break;
|
||||
case 'r':
|
||||
ret.flags |= parsedFlagIgnoreCase;
|
||||
ret.fn = regexMatchIgnoreCase;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
free(orig);
|
||||
return ret;
|
||||
}
|
50
frame/taskmanager/windowpatterns.h
Normal file
50
frame/taskmanager/windowpatterns.h
Normal file
@ -0,0 +1,50 @@
|
||||
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#ifndef WINDOWPATTERNS_H
|
||||
#define WINDOWPATTERNS_H
|
||||
|
||||
#include "windowinfox.h"
|
||||
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
|
||||
|
||||
struct RuleValueParse {
|
||||
RuleValueParse();
|
||||
bool match(const WindowInfoX *winInfo);
|
||||
static QString parseRuleKey(WindowInfoX *winInfo, const QString &ruleKey);
|
||||
QString key;
|
||||
bool negative;
|
||||
bool (*fn)(QString, QString);
|
||||
uint8_t type;
|
||||
uint flags;
|
||||
QString original;
|
||||
QString value;
|
||||
};
|
||||
|
||||
class WindowPatterns
|
||||
{
|
||||
// 窗口类型匹配
|
||||
struct WindowPattern {
|
||||
QVector<QVector<QString>> rules; // rules
|
||||
QString result; // ret
|
||||
QVector<RuleValueParse> parseRules;
|
||||
};
|
||||
|
||||
public:
|
||||
WindowPatterns();
|
||||
|
||||
QString match(WindowInfoX *winInfo);
|
||||
|
||||
private:
|
||||
void loadWindowPatterns();
|
||||
RuleValueParse parseRule(QVector<QString> rule);
|
||||
|
||||
private:
|
||||
QVector<WindowPattern> m_patterns;
|
||||
|
||||
};
|
||||
|
||||
#endif // WINDOWPATTERNS_H
|
455
frame/taskmanager/x11manager.cpp
Normal file
455
frame/taskmanager/x11manager.cpp
Normal file
@ -0,0 +1,455 @@
|
||||
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "x11manager.h"
|
||||
#include "taskmanager.h"
|
||||
#include "common.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QTimer>
|
||||
|
||||
/*
|
||||
* 使用Xlib监听X Events
|
||||
* 使用XCB接口与X进行交互
|
||||
* */
|
||||
|
||||
#include <ctype.h>
|
||||
#include <X11/Xos.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/Xproto.h>
|
||||
|
||||
#define XCB XCBUtils::instance()
|
||||
|
||||
X11Manager::X11Manager(TaskManager *_taskmanager, QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_taskmanager(_taskmanager)
|
||||
, m_mutex(QMutex(QMutex::NonRecursive))
|
||||
, m_listenXEvent(true)
|
||||
{
|
||||
m_rootWindow = XCB->getRootWindow();
|
||||
}
|
||||
|
||||
void X11Manager::listenXEventUseXlib()
|
||||
{
|
||||
|
||||
Display *dpy;
|
||||
int screen;
|
||||
char *displayname = nullptr;
|
||||
Window w;
|
||||
XSetWindowAttributes attr;
|
||||
XWindowAttributes wattr;
|
||||
|
||||
dpy = XOpenDisplay (displayname);
|
||||
if (!dpy) {
|
||||
exit (1);
|
||||
}
|
||||
|
||||
screen = DefaultScreen (dpy);
|
||||
w = RootWindow(dpy, screen);
|
||||
|
||||
const struct {
|
||||
const char *name;
|
||||
long mask;
|
||||
} events[] = {
|
||||
{ "keyboard", KeyPressMask | KeyReleaseMask | KeymapStateMask },
|
||||
{ "mouse", ButtonPressMask | ButtonReleaseMask | EnterWindowMask |
|
||||
LeaveWindowMask | PointerMotionMask | Button1MotionMask |
|
||||
Button2MotionMask | Button3MotionMask | Button4MotionMask |
|
||||
Button5MotionMask | ButtonMotionMask },
|
||||
{ "button", ButtonPressMask | ButtonReleaseMask },
|
||||
{ "expose", ExposureMask },
|
||||
{ "visibility", VisibilityChangeMask },
|
||||
{ "structure", StructureNotifyMask },
|
||||
{ "substructure", SubstructureNotifyMask | SubstructureRedirectMask },
|
||||
{ "focus", FocusChangeMask },
|
||||
{ "property", PropertyChangeMask },
|
||||
{ "colormap", ColormapChangeMask },
|
||||
{ "owner_grab_button", OwnerGrabButtonMask },
|
||||
{ nullptr, 0 }
|
||||
};
|
||||
|
||||
long mask = 0;
|
||||
for (int i = 0; events[i].name; i++)
|
||||
mask |= events[i].mask;
|
||||
|
||||
attr.event_mask = mask;
|
||||
|
||||
XGetWindowAttributes(dpy, w, &wattr);
|
||||
|
||||
attr.event_mask &= ~SubstructureRedirectMask;
|
||||
XSelectInput(dpy, w, attr.event_mask);
|
||||
|
||||
while (m_listenXEvent) {
|
||||
XEvent event;
|
||||
XNextEvent (dpy, &event);
|
||||
|
||||
switch (event.type) {
|
||||
case DestroyNotify: {
|
||||
XDestroyWindowEvent *eD = (XDestroyWindowEvent *)(&event);
|
||||
// qDebug() << "DestroyNotify windowId=" << eD->window;
|
||||
|
||||
handleDestroyNotifyEvent(XWindow(eD->window));
|
||||
break;
|
||||
}
|
||||
case MapNotify: {
|
||||
XMapEvent *eM = (XMapEvent *)(&event);
|
||||
// qDebug() << "MapNotify windowId=" << eM->window;
|
||||
|
||||
handleMapNotifyEvent(XWindow(eM->window));
|
||||
break;
|
||||
}
|
||||
case ConfigureNotify: {
|
||||
XConfigureEvent *eC = (XConfigureEvent *)(&event);
|
||||
// qDebug() << "ConfigureNotify windowId=" << eC->window;
|
||||
|
||||
handleConfigureNotifyEvent(XWindow(eC->window), eC->x, eC->y, eC->width, eC->height);
|
||||
break;
|
||||
}
|
||||
case PropertyNotify: {
|
||||
XPropertyEvent *eP = (XPropertyEvent *)(&event);
|
||||
// qDebug() << "PropertyNotify windowId=" << eP->window;
|
||||
|
||||
handlePropertyNotifyEvent(XWindow(eP->window), XCBAtom(eP->atom));
|
||||
break;
|
||||
}
|
||||
case UnmapNotify: {
|
||||
// 当松开鼠标的时候会触发该事件,在松开鼠标的时候,需要检测当前窗口是否符合智能隐藏的条件,因此在此处加上该功能
|
||||
// 如果不加上该处理,那么就会出现将窗口从任务栏下方移动到屏幕中央的时候,任务栏不隐藏
|
||||
handleActiveWindowChangedX();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
//qDebug() << "unused event type " << event.type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
XCloseDisplay (dpy);
|
||||
}
|
||||
|
||||
void X11Manager::listenXEventUseXCB()
|
||||
{
|
||||
/*
|
||||
xcb_get_window_attributes_cookie_t cookie = xcb_get_window_attributes(XCB->getConnect(), XCB->getRootWindow());
|
||||
xcb_get_window_attributes_reply_t *reply = xcb_get_window_attributes_reply(XCB->getConnect(), cookie, NULL);
|
||||
if (reply) {
|
||||
uint32_t valueMask = reply->your_event_mask;
|
||||
valueMask &= ~XCB_CW_OVERRIDE_REDIRECT;
|
||||
uint32_t mask[2] = {0};
|
||||
mask[0] = valueMask;
|
||||
//xcb_change_window_attributes(XCB->getConnect(), XCB->getRootWindow(), valueMask, mask);
|
||||
|
||||
free(reply);
|
||||
}
|
||||
|
||||
xcb_generic_event_t *event;
|
||||
while ( (event = xcb_wait_for_event (XCB->getConnect())) ) {
|
||||
eventHandler(event->response_type & ~0x80, event);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief X11Manager::registerWindow 注册X11窗口
|
||||
* @param xid
|
||||
* @return
|
||||
*/
|
||||
WindowInfoX *X11Manager::registerWindow(XWindow xid)
|
||||
{
|
||||
qInfo() << "registWindow: windowId=" << xid;
|
||||
WindowInfoX *ret = nullptr;
|
||||
do {
|
||||
if (m_windowInfoMap.find(xid) != m_windowInfoMap.end()) {
|
||||
ret = m_windowInfoMap[xid];
|
||||
break;
|
||||
}
|
||||
|
||||
WindowInfoX *winInfo = new WindowInfoX(xid);
|
||||
if (!winInfo)
|
||||
break;
|
||||
|
||||
listenWindowXEvent(winInfo);
|
||||
m_windowInfoMap[xid] = winInfo;
|
||||
ret = winInfo;
|
||||
} while (0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// 取消注册X11窗口
|
||||
void X11Manager::unregisterWindow(XWindow xid)
|
||||
{
|
||||
qInfo() << "unregisterWindow: windowId=" << xid;
|
||||
if (m_windowInfoMap.find(xid) != m_windowInfoMap.end()) {
|
||||
m_windowInfoMap.remove(xid);
|
||||
}
|
||||
}
|
||||
|
||||
WindowInfoX *X11Manager::findWindowByXid(XWindow xid)
|
||||
{
|
||||
WindowInfoX *ret = nullptr;
|
||||
if (m_windowInfoMap.find(xid) != m_windowInfoMap.end())
|
||||
ret = m_windowInfoMap[xid];
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void X11Manager::handleClientListChanged()
|
||||
{
|
||||
QSet<XWindow> newClientList, oldClientList, addClientList, rmClientList;
|
||||
for (auto atom : XCB->getClientList())
|
||||
newClientList.insert(atom);
|
||||
|
||||
for (auto atom : m_taskmanager->getClientList())
|
||||
oldClientList.insert(atom);
|
||||
|
||||
addClientList = newClientList - oldClientList;
|
||||
rmClientList = oldClientList - newClientList;
|
||||
m_taskmanager->setClientList(newClientList.values());
|
||||
|
||||
// 处理新增窗口
|
||||
for (auto xid : addClientList) {
|
||||
WindowInfoX *info = registerWindow(xid);
|
||||
if (!XCB->isGoodWindow(xid))
|
||||
continue;
|
||||
|
||||
uint32_t pid = XCB->getWMPid(xid);
|
||||
WMClass wmClass = XCB->getWMClass(xid);
|
||||
QString wmName(XCB->getWMName(xid).c_str());
|
||||
if (pid != 0 || (wmClass.className.size() > 0 && wmClass.instanceName.size() > 0)
|
||||
|| wmName.size() > 0 || XCB->getWMCommand(xid).size() > 0) {
|
||||
|
||||
if (info) {
|
||||
Q_EMIT requestAttachOrDetachWindow(info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 处理需要移除的窗口
|
||||
for (auto xid : rmClientList) {
|
||||
WindowInfoX *info = m_windowInfoMap[xid];
|
||||
if (info) {
|
||||
m_taskmanager->detachWindow(info);
|
||||
unregisterWindow(xid);
|
||||
} else {
|
||||
// no window
|
||||
auto entry = m_taskmanager->getEntryByWindowId(xid);
|
||||
if (entry && !m_taskmanager->isDocked(entry->getFileName())) {
|
||||
m_taskmanager->removeAppEntry(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void X11Manager::handleActiveWindowChangedX()
|
||||
{
|
||||
XWindow active = XCB->getActiveWindow();
|
||||
WindowInfoX *info = findWindowByXid(active);
|
||||
if (info) {
|
||||
Q_EMIT requestHandleActiveWindowChange(info);
|
||||
}
|
||||
}
|
||||
|
||||
void X11Manager::listenRootWindowXEvent()
|
||||
{
|
||||
uint32_t eventMask = EventMask::XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY;
|
||||
XCB->registerEvents(m_rootWindow, eventMask);
|
||||
handleActiveWindowChangedX();
|
||||
handleClientListChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief X11Manager::listenWindowXEvent 监听窗口事件
|
||||
* @param winInfo
|
||||
*/
|
||||
void X11Manager::listenWindowXEvent(WindowInfoX *winInfo)
|
||||
{
|
||||
uint32_t eventMask = EventMask::XCB_EVENT_MASK_PROPERTY_CHANGE | EventMask::XCB_EVENT_MASK_STRUCTURE_NOTIFY | EventMask::XCB_EVENT_MASK_VISIBILITY_CHANGE;
|
||||
XCB->registerEvents(winInfo->getXid(), eventMask);
|
||||
}
|
||||
|
||||
void X11Manager::handleRootWindowPropertyNotifyEvent(XCBAtom atom)
|
||||
{
|
||||
if (atom == XCB->getAtom("_NET_CLIENT_LIST")) {
|
||||
// 窗口列表改变
|
||||
handleClientListChanged();
|
||||
} else if (atom == XCB->getAtom("_NET_ACTIVE_WINDOW")) {
|
||||
// 活动窗口改变
|
||||
handleActiveWindowChangedX();
|
||||
} else if (atom == XCB->getAtom("_NET_SHOWING_DESKTOP")) {
|
||||
// 更新任务栏隐藏状态
|
||||
Q_EMIT requestUpdateHideState(false);
|
||||
}
|
||||
}
|
||||
|
||||
// destory event
|
||||
void X11Manager::handleDestroyNotifyEvent(XWindow xid)
|
||||
{
|
||||
WindowInfoX *winInfo = findWindowByXid(xid);
|
||||
if (!winInfo)
|
||||
return;
|
||||
|
||||
m_taskmanager->detachWindow(winInfo);
|
||||
unregisterWindow(xid);
|
||||
}
|
||||
|
||||
// map event
|
||||
void X11Manager::handleMapNotifyEvent(XWindow xid)
|
||||
{
|
||||
WindowInfoX *winInfo = registerWindow(xid);
|
||||
if (!winInfo)
|
||||
return;
|
||||
|
||||
// TODO QTimer不能在非主线程执行,使用单独线程开发定时器处理非主线程类似定时任务
|
||||
//QTimer::singleShot(2 * 1000, this, [=] {
|
||||
qInfo() << "handleMapNotifyEvent: pass 2s, now call idnetifyWindow, windowId=" << winInfo->getXid();
|
||||
QString innerId;
|
||||
AppInfo *appInfo = m_taskmanager->identifyWindow(winInfo, innerId);
|
||||
m_taskmanager->markAppLaunched(appInfo);
|
||||
//});
|
||||
}
|
||||
|
||||
// config changed event 检测窗口大小调整和重绘应用,触发智能隐藏更新
|
||||
void X11Manager::handleConfigureNotifyEvent(XWindow xid, int x, int y, int width, int height)
|
||||
{
|
||||
WindowInfoX *winInfo = findWindowByXid(xid);
|
||||
if (!winInfo || m_taskmanager->getDockHideMode() != HideMode::SmartHide)
|
||||
return;
|
||||
|
||||
WMClass wmClass = winInfo->getWMClass();
|
||||
if (wmClass.className.c_str() == frontendWindowWmClass)
|
||||
return; // ignore frontend window ConfigureNotify event
|
||||
|
||||
Q_EMIT requestUpdateHideState(winInfo->isGeometryChanged(x, y, width, height));
|
||||
}
|
||||
|
||||
// property changed event
|
||||
void X11Manager::handlePropertyNotifyEvent(XWindow xid, XCBAtom atom)
|
||||
{
|
||||
if (xid == m_rootWindow) {
|
||||
handleRootWindowPropertyNotifyEvent(atom);
|
||||
return;
|
||||
}
|
||||
|
||||
WindowInfoX *winInfo = findWindowByXid(xid);
|
||||
if (!winInfo)
|
||||
return;
|
||||
|
||||
QString newInnerId;
|
||||
bool needAttachOrDetach = false;
|
||||
if (atom == XCB->getAtom("_NET_WM_STATE")) {
|
||||
winInfo->updateWmState();
|
||||
needAttachOrDetach = true;
|
||||
} else if (atom == XCB->getAtom("_GTK_APPLICATION_ID")) {
|
||||
QString gtkAppId;
|
||||
winInfo->setGtkAppId(gtkAppId);
|
||||
newInnerId = winInfo->genInnerId(winInfo);
|
||||
} else if (atom == XCB->getAtom("_NET_WM_PID")) {
|
||||
winInfo->updateProcessInfo();
|
||||
newInnerId = winInfo->genInnerId(winInfo);
|
||||
} else if (atom == XCB->getAtom("_NET_WM_NAME")) {
|
||||
winInfo->updateWmName();
|
||||
newInnerId = winInfo->genInnerId(winInfo);
|
||||
} else if (atom == XCB->getAtom("_NET_WM_ICON")) {
|
||||
winInfo->updateIcon();
|
||||
} else if (atom == XCB->getAtom("_NET_WM_ALLOWED_ACTIONS")) {
|
||||
winInfo->updateWmAllowedActions();
|
||||
} else if (atom == XCB->getAtom("_MOTIF_WM_HINTS")) {
|
||||
winInfo->updateMotifWmHints();
|
||||
} else if (atom == XCB_ATOM_WM_CLASS) {
|
||||
winInfo->updateWmClass();
|
||||
newInnerId = winInfo->genInnerId(winInfo);
|
||||
needAttachOrDetach = true;
|
||||
} else if (atom == XCB->getAtom("_XEMBED_INFO")) {
|
||||
winInfo->updateHasXEmbedInfo();
|
||||
needAttachOrDetach = true;
|
||||
} else if (atom == XCB->getAtom("_NET_WM_WINDOW_TYPE")) {
|
||||
winInfo->updateWmWindowType();
|
||||
needAttachOrDetach = true;
|
||||
} else if (atom == XCB_ATOM_WM_TRANSIENT_FOR) {
|
||||
winInfo->updateHasWmTransientFor();
|
||||
needAttachOrDetach = true;
|
||||
}
|
||||
|
||||
if (!newInnerId.isEmpty() && winInfo->getUpdateCalled() && winInfo->getInnerId() != newInnerId) {
|
||||
// winInfo.innerId changed
|
||||
m_taskmanager->detachWindow(winInfo);
|
||||
winInfo->setInnerId(newInnerId);
|
||||
needAttachOrDetach = true;
|
||||
}
|
||||
|
||||
if (needAttachOrDetach && winInfo) {
|
||||
Q_EMIT requestAttachOrDetachWindow(winInfo);
|
||||
}
|
||||
|
||||
Entry *entry = m_taskmanager->getEntryByWindowId(xid);
|
||||
if (!entry)
|
||||
return;
|
||||
|
||||
if (atom == XCB->getAtom("_NET_WM_STATE")) {
|
||||
// entry->updateExportWindowInfos();
|
||||
} else if (atom == XCB->getAtom("_NET_WM_ICON")) {
|
||||
if (entry->getCurrentWindowInfo() == winInfo) {
|
||||
entry->updateIcon();
|
||||
}
|
||||
} else if (atom == XCB->getAtom("_NET_WM_NAME")) {
|
||||
if (entry->getCurrentWindowInfo() == winInfo) {
|
||||
entry->updateName();
|
||||
}
|
||||
// entry->updateExportWindowInfos();
|
||||
} else if (atom == XCB->getAtom("_NET_WM_ALLOWED_ACTIONS")) {
|
||||
entry->updateMenu();
|
||||
}
|
||||
}
|
||||
|
||||
void X11Manager::eventHandler(uint8_t type, void *event)
|
||||
{
|
||||
qInfo() << "eventHandler" << "type = " << type;
|
||||
switch (type) {
|
||||
case XCB_MAP_NOTIFY: // 17 注册新窗口
|
||||
qInfo() << "eventHandler: XCB_MAP_NOTIFY";
|
||||
break;
|
||||
case XCB_DESTROY_NOTIFY: // 19 销毁窗口
|
||||
qInfo() << "eventHandler: XCB_DESTROY_NOTIFY";
|
||||
break;
|
||||
case XCB_CONFIGURE_NOTIFY: // 22 窗口变化
|
||||
qInfo() << "eventHandler: XCB_CONFIGURE_NOTIFY";
|
||||
break;
|
||||
case XCB_PROPERTY_NOTIFY: // 28 窗口属性改变
|
||||
qInfo() << "eventHandler: XCB_PROPERTY_NOTIFY";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void X11Manager::addWindowLastConfigureEvent(XWindow xid, ConfigureEvent *event)
|
||||
{
|
||||
delWindowLastConfigureEvent(xid);
|
||||
|
||||
QMutexLocker locker(&m_mutex);
|
||||
QTimer *timer = new QTimer();
|
||||
timer->setInterval(configureNotifyDelay);
|
||||
m_windowLastConfigureEventMap[xid] = QPair(event, timer);
|
||||
}
|
||||
|
||||
QPair<ConfigureEvent *, QTimer *> X11Manager::getWindowLastConfigureEvent(XWindow xid)
|
||||
{
|
||||
QPair<ConfigureEvent *, QTimer *> ret;
|
||||
QMutexLocker locker(&m_mutex);
|
||||
if (m_windowLastConfigureEventMap.find(xid) != m_windowLastConfigureEventMap.end())
|
||||
ret = m_windowLastConfigureEventMap[xid];
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void X11Manager::delWindowLastConfigureEvent(XWindow xid)
|
||||
{
|
||||
QMutexLocker locker(&m_mutex);
|
||||
if (m_windowLastConfigureEventMap.find(xid) != m_windowLastConfigureEventMap.end()) {
|
||||
QPair<ConfigureEvent*, QTimer*> item = m_windowLastConfigureEventMap[xid];
|
||||
m_windowLastConfigureEventMap.remove(xid);
|
||||
delete item.first;
|
||||
item.second->deleteLater();
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user