1
0
mirror of https://github.com/KDE/latte-dock.git synced 2025-03-29 10:50:33 +03:00

Compare commits

...

492 Commits

Author SHA1 Message Date
l10n daemon script
6aa19750e5 GIT_SILENT Sync po/docbooks with svn 2025-03-14 02:32:19 +00:00
l10n daemon script
e8e8229465 GIT_SILENT Sync po/docbooks with svn 2025-03-05 02:58:15 +00:00
l10n daemon script
db20896762 GIT_SILENT made messages (after extraction) 2025-03-01 02:09:51 +00:00
l10n daemon script
3eb57736fb GIT_SILENT Sync po/docbooks with svn 2025-02-16 02:28:12 +00:00
l10n daemon script
7de7ed150c GIT_SILENT Sync po/docbooks with svn 2025-02-15 02:46:21 +00:00
l10n daemon script
60bc8ee65b GIT_SILENT Sync po/docbooks with svn 2025-01-27 02:29:33 +00:00
l10n daemon script
6acb37bc5a GIT_SILENT Sync po/docbooks with svn 2025-01-21 02:21:52 +00:00
l10n daemon script
a53f381352 GIT_SILENT Sync po/docbooks with svn 2025-01-12 02:31:15 +00:00
l10n daemon script
67bc5c9801 GIT_SILENT Sync po/docbooks with svn 2025-01-05 02:24:40 +00:00
l10n daemon script
824feedbe2 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2025-01-05 02:19:33 +00:00
l10n daemon script
1ac1a76b53 GIT_SILENT made messages (after extraction) 2025-01-05 01:55:31 +00:00
l10n daemon script
f79594dd01 GIT_SILENT Sync po/docbooks with svn 2024-12-18 02:28:45 +00:00
l10n daemon script
6e21efcd2b GIT_SILENT Sync po/docbooks with svn 2024-12-14 03:11:22 +00:00
l10n daemon script
56a0b8d34f GIT_SILENT Sync po/docbooks with svn 2024-12-02 03:11:20 +00:00
l10n daemon script
fecbc680a6 GIT_SILENT Sync po/docbooks with svn 2024-10-27 02:29:23 +00:00
l10n daemon script
86731f1566 GIT_SILENT Sync po/docbooks with svn 2024-09-17 02:26:18 +00:00
l10n daemon script
5c241eed78 GIT_SILENT Sync po/docbooks with svn 2024-09-06 02:44:11 +00:00
l10n daemon script
9b6f42d888 GIT_SILENT Sync po/docbooks with svn 2024-09-01 02:20:21 +00:00
l10n daemon script
62febcef54 GIT_SILENT made messages (after extraction) 2024-09-01 01:46:58 +00:00
l10n daemon script
3f43a2ec5e SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2024-08-28 02:28:22 +00:00
l10n daemon script
9e3f53321c GIT_SILENT Sync po/docbooks with svn 2024-08-22 02:32:18 +00:00
l10n daemon script
e1bd2c02ec GIT_SILENT Sync po/docbooks with svn 2024-08-21 02:32:35 +00:00
l10n daemon script
a46fe062cf SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2024-08-21 02:25:59 +00:00
Edgar Schneikart
31a6135fd9 fix: Set Arch link to AUR 2024-07-07 23:29:21 +02:00
l10n daemon script
4f1c08054b GIT_SILENT Sync po/docbooks with svn 2024-07-01 02:22:53 +00:00
l10n daemon script
6858dcdeb8 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2024-06-28 02:26:30 +00:00
l10n daemon script
30b3d4c761 GIT_SILENT Sync po/docbooks with svn 2024-06-19 02:21:15 +00:00
l10n daemon script
fd459df480 GIT_SILENT Sync po/docbooks with svn 2024-06-05 02:49:26 +00:00
l10n daemon script
6d286ea440 GIT_SILENT Sync po/docbooks with svn 2024-05-31 02:36:19 +00:00
l10n daemon script
f6ff829371 GIT_SILENT Sync po/docbooks with svn 2024-05-29 02:54:55 +00:00
l10n daemon script
a9ce43f133 GIT_SILENT Sync po/docbooks with svn 2024-05-25 02:25:51 +00:00
l10n daemon script
d1d57b7d01 GIT_SILENT Sync po/docbooks with svn 2024-05-20 02:20:20 +00:00
l10n daemon script
10be08a794 GIT_SILENT Sync po/docbooks with svn 2024-05-12 02:39:56 +00:00
l10n daemon script
78d0bc8a0f GIT_SILENT Sync po/docbooks with svn 2024-05-09 02:30:07 +00:00
l10n daemon script
ae7854c16a GIT_SILENT Sync po/docbooks with svn 2024-05-06 02:33:00 +00:00
l10n daemon script
23b9e9ea36 GIT_SILENT Sync po/docbooks with svn 2024-04-24 02:42:41 +00:00
l10n daemon script
a815969fa4 GIT_SILENT Sync po/docbooks with svn 2024-04-22 02:44:29 +00:00
l10n daemon script
4c504a318a GIT_SILENT Sync po/docbooks with svn 2024-04-21 02:30:08 +00:00
l10n daemon script
b784da8d1c GIT_SILENT Sync po/docbooks with svn 2024-04-20 02:32:04 +00:00
l10n daemon script
1398747bb8 GIT_SILENT Sync po/docbooks with svn 2024-04-17 02:33:39 +00:00
l10n daemon script
3365b2c400 GIT_SILENT Sync po/docbooks with svn 2024-04-15 02:23:57 +00:00
l10n daemon script
f5df4ae3d1 GIT_SILENT Sync po/docbooks with svn 2024-04-14 02:24:59 +00:00
l10n daemon script
5c48f63afb GIT_SILENT Sync po/docbooks with svn 2024-04-13 02:31:09 +00:00
l10n daemon script
6f1834d6da GIT_SILENT Sync po/docbooks with svn 2024-04-12 02:29:19 +00:00
l10n daemon script
1a2a1dcbe6 GIT_SILENT Sync po/docbooks with svn 2024-04-11 02:30:08 +00:00
l10n daemon script
fccdb88630 GIT_SILENT Sync po/docbooks with svn 2024-04-10 02:32:25 +00:00
l10n daemon script
a2860999eb GIT_SILENT Sync po/docbooks with svn 2024-04-09 02:31:22 +00:00
l10n daemon script
c7bd1bfdff GIT_SILENT Sync po/docbooks with svn 2024-04-08 02:30:46 +00:00
l10n daemon script
1fc935038a GIT_SILENT Sync po/docbooks with svn 2024-04-07 02:31:12 +00:00
l10n daemon script
9c09448ddd GIT_SILENT Sync po/docbooks with svn 2024-04-05 02:28:38 +00:00
l10n daemon script
6160c679c6 GIT_SILENT Sync po/docbooks with svn 2024-04-04 02:33:04 +00:00
l10n daemon script
b4b16f61f1 GIT_SILENT Sync po/docbooks with svn 2024-03-25 02:40:04 +00:00
pa aa
cc737af39f Fixed minor typos 2024-03-19 09:36:16 +00:00
l10n daemon script
4d7595469d GIT_SILENT Sync po/docbooks with svn 2024-03-18 02:50:50 +00:00
l10n daemon script
71f3112a08 GIT_SILENT Sync po/docbooks with svn 2024-03-17 02:49:16 +00:00
l10n daemon script
7184d79c95 GIT_SILENT Sync po/docbooks with svn 2024-03-16 02:56:28 +00:00
l10n daemon script
93b55677ef GIT_SILENT Sync po/docbooks with svn 2024-03-15 02:49:18 +00:00
l10n daemon script
eeab393c55 GIT_SILENT Sync po/docbooks with svn 2024-03-14 02:50:31 +00:00
l10n daemon script
4c7fbeb1e0 GIT_SILENT Sync po/docbooks with svn 2024-03-10 02:48:37 +00:00
l10n daemon script
6d9f516581 GIT_SILENT Sync po/docbooks with svn 2024-03-01 02:50:57 +00:00
l10n daemon script
d185475c3e GIT_SILENT Sync po/docbooks with svn 2024-02-29 02:16:59 +00:00
l10n daemon script
fe12d95454 GIT_SILENT Sync po/docbooks with svn 2024-02-27 02:17:52 +00:00
l10n daemon script
d3cc4aad00 GIT_SILENT Sync po/docbooks with svn 2024-02-21 02:13:52 +00:00
l10n daemon script
8328f9a686 GIT_SILENT Sync po/docbooks with svn 2024-02-10 02:36:41 +00:00
l10n daemon script
0c95dd84aa GIT_SILENT Sync po/docbooks with svn 2024-02-06 02:52:37 +00:00
l10n daemon script
5e0872c396 GIT_SILENT Sync po/docbooks with svn 2024-02-05 02:43:02 +00:00
l10n daemon script
131ee4d39c GIT_SILENT Sync po/docbooks with svn 2024-01-31 02:26:43 +00:00
l10n daemon script
6356c472fe GIT_SILENT Sync po/docbooks with svn 2024-01-29 02:17:49 +00:00
l10n daemon script
b1ea81662c SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2024-01-29 02:08:07 +00:00
l10n daemon script
358acbf1f6 GIT_SILENT Sync po/docbooks with svn 2024-01-22 02:51:41 +00:00
l10n daemon script
ca6af59420 GIT_SILENT Sync po/docbooks with svn 2024-01-14 02:52:31 +00:00
l10n daemon script
110adba6c2 GIT_SILENT Sync po/docbooks with svn 2024-01-13 02:26:08 +00:00
l10n daemon script
df36844edd GIT_SILENT Sync po/docbooks with svn 2024-01-07 01:37:09 +00:00
l10n daemon script
8d64858029 GIT_SILENT Sync po/docbooks with svn 2023-12-31 01:37:09 +00:00
l10n daemon script
7c9c8f1f01 GIT_SILENT Sync po/docbooks with svn 2023-12-30 01:25:28 +00:00
l10n daemon script
8ae05c72df GIT_SILENT Sync po/docbooks with svn 2023-12-24 01:40:11 +00:00
l10n daemon script
afab5529df GIT_SILENT Sync po/docbooks with svn 2023-12-21 01:41:39 +00:00
l10n daemon script
6ef3ebf245 GIT_SILENT Sync po/docbooks with svn 2023-12-18 01:40:55 +00:00
l10n daemon script
3d26e09efd GIT_SILENT Sync po/docbooks with svn 2023-12-10 01:40:19 +00:00
Marius P
c250bd7413 templates remove ktp-contactlist.desktop
ktp-contactlist.desktop is ktp-contactlist=telepathy|contactlist
is https://invent.kde.org/network/ktp-contact-list and is an
archived KDE project.
2023-12-01 05:26:57 +02:00
l10n daemon script
99b6b9475a GIT_SILENT Sync po/docbooks with svn 2023-11-26 01:41:45 +00:00
Nicolas Fella
6b2741d1f4 Adapt CI to renamed plasma-framework and kactivities 2023-11-25 15:29:56 +01:00
l10n daemon script
5fef17739b GIT_SILENT Sync po/docbooks with svn 2023-11-20 01:41:27 +00:00
l10n daemon script
6fcf67aa73 GIT_SILENT Sync po/docbooks with svn 2023-11-19 01:36:15 +00:00
Hannibal Lecter
c6882e79c4 docs: add dependencies for openSUSE 2023-11-16 17:56:50 +00:00
l10n daemon script
4a6be0a96b GIT_SILENT Sync po/docbooks with svn 2023-11-16 01:32:14 +00:00
l10n daemon script
755676d752 GIT_SILENT Sync po/docbooks with svn 2023-11-11 01:31:47 +00:00
l10n daemon script
de6c48cdbc GIT_SILENT Sync po/docbooks with svn 2023-11-09 01:26:41 +00:00
Nicolas Fella
0a960689e4 Adjust to KWayland moving to Plasma 2023-11-07 16:25:54 +01:00
l10n daemon script
6c29aaabeb GIT_SILENT Sync po/docbooks with svn 2023-11-07 02:31:45 +00:00
l10n daemon script
ea822c7c01 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2023-11-07 02:15:55 +00:00
l10n daemon script
304f8c2aea GIT_SILENT made messages (after extraction) 2023-11-07 01:22:14 +00:00
Nicolas Fella
fd67338d16 Adapt to plasma-framework moving to Plasma 2023-11-05 15:02:16 +01:00
l10n daemon script
a9880aa8d7 GIT_SILENT Sync po/docbooks with svn 2023-11-05 13:47:45 +00:00
l10n daemon script
06b3c89a01 GIT_SILENT made messages (after extraction) 2023-11-05 12:36:09 +00:00
Ben Cooksley
d3d043d2e1 Reflect move of KActivities out of Frameworks to Plasma
Ref T16978
2023-11-05 15:30:29 +13:00
l10n daemon script
1d7b8519d9 GIT_SILENT Sync po/docbooks with svn 2023-11-04 16:41:26 +00:00
l10n daemon script
237ec8c4bf SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2023-11-04 11:56:25 +00:00
l10n daemon script
05e4885ef3 GIT_SILENT Sync po/docbooks with svn 2023-11-03 01:28:29 +00:00
l10n daemon script
6aae3646e8 GIT_SILENT Sync po/docbooks with svn 2023-11-02 01:28:30 +00:00
l10n daemon script
32ce630b51 GIT_SILENT Sync po/docbooks with svn 2023-11-01 01:30:01 +00:00
l10n daemon script
b6884636b1 GIT_SILENT Sync po/docbooks with svn 2023-10-31 01:28:27 +00:00
l10n daemon script
054c9e5c94 GIT_SILENT Sync po/docbooks with svn 2023-10-30 01:30:17 +00:00
Lana Black
f9727cdac5 Add default.nix for fun and profit. 2023-10-29 22:42:13 +00:00
Lana Black
66e52716b4 Allow maximising panel conditionally.
Add code that maximises panel length when maximised windows are present on the same screen.
2023-10-29 22:28:04 +00:00
l10n daemon script
7b210a9970 GIT_SILENT Sync po/docbooks with svn 2023-10-22 01:46:41 +00:00
Carl Schwan
8ea7f3e066
Fix ci
Use stable version from plasma workspace
2023-10-19 03:52:30 -04:00
l10n daemon script
620c7fa986 GIT_SILENT Sync po/docbooks with svn 2023-10-14 01:36:07 +00:00
l10n daemon script
bf320e2d15 GIT_SILENT Sync po/docbooks with svn 2023-10-11 01:48:03 +00:00
l10n daemon script
98d25c1427 GIT_SILENT Sync po/docbooks with svn 2023-10-10 01:33:57 +00:00
l10n daemon script
7524c210b9 GIT_SILENT Sync po/docbooks with svn 2023-10-01 01:39:40 +00:00
l10n daemon script
cb44b6f84d SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2023-10-01 01:22:04 +00:00
l10n daemon script
71e0243709 GIT_SILENT Sync po/docbooks with svn 2023-09-27 01:30:53 +00:00
l10n daemon script
65b6761237 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2023-09-27 01:23:50 +00:00
l10n daemon script
902092f2a8 GIT_SILENT Sync po/docbooks with svn 2023-09-17 02:10:38 +00:00
l10n daemon script
5dc506b49f GIT_SILENT Sync po/docbooks with svn 2023-09-13 01:54:27 +00:00
l10n daemon script
0423fd4259 GIT_SILENT Sync po/docbooks with svn 2023-09-04 01:50:41 +00:00
l10n daemon script
427b6ba690 GIT_SILENT Sync po/docbooks with svn 2023-09-03 02:16:32 +00:00
l10n daemon script
853a7735a4 GIT_SILENT Sync po/docbooks with svn 2023-08-28 02:17:27 +00:00
l10n daemon script
4f7f4c2395 GIT_SILENT Sync po/docbooks with svn 2023-08-23 01:49:27 +00:00
l10n daemon script
3b67d2112d GIT_SILENT Sync po/docbooks with svn 2023-08-08 01:53:42 +00:00
l10n daemon script
1aa9d9f825 GIT_SILENT Sync po/docbooks with svn 2023-08-07 02:11:43 +00:00
l10n daemon script
81ea60df72 GIT_SILENT made messages (after extraction) 2023-08-07 00:50:53 +00:00
l10n daemon script
61fa1b0e23 GIT_SILENT Sync po/docbooks with svn 2023-08-06 01:53:30 +00:00
l10n daemon script
720fc92d14 GIT_SILENT made messages (after extraction) 2023-08-05 00:47:56 +00:00
l10n daemon script
2d7c1642fc GIT_SILENT Sync po/docbooks with svn 2023-08-03 02:18:03 +00:00
l10n daemon script
5956db83ec GIT_SILENT Sync po/docbooks with svn 2023-08-02 01:58:00 +00:00
l10n daemon script
a0ff6e7817 GIT_SILENT Sync po/docbooks with svn 2023-07-31 02:18:45 +00:00
l10n daemon script
edb8a258a2 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2023-07-28 01:43:04 +00:00
l10n daemon script
ea8c4b9714 GIT_SILENT Sync po/docbooks with svn 2023-07-24 09:13:26 +00:00
l10n daemon script
459f0d54ff GIT_SILENT Sync po/docbooks with svn 2023-07-19 02:54:04 +00:00
l10n daemon script
a0e6eae9c8 GIT_SILENT Sync po/docbooks with svn 2023-07-11 01:52:47 +00:00
l10n daemon script
892ac7868b GIT_SILENT made messages (after extraction) 2023-07-11 00:48:35 +00:00
l10n daemon script
67591cf616 GIT_SILENT Sync po/docbooks with svn 2023-07-04 02:49:20 +00:00
l10n daemon script
a91a1ef227 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2023-06-25 01:53:34 +00:00
l10n daemon script
6532af166f GIT_SILENT Sync po/docbooks with svn 2023-06-23 02:03:57 +00:00
l10n daemon script
5c2158b969 GIT_SILENT Sync po/docbooks with svn 2023-06-22 01:56:49 +00:00
l10n daemon script
b58cdd7882 GIT_SILENT Sync po/docbooks with svn 2023-06-20 02:38:42 +00:00
l10n daemon script
4cc612284d GIT_SILENT Sync po/docbooks with svn 2023-06-19 02:08:26 +00:00
l10n daemon script
1193856d40 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2023-06-19 01:50:44 +00:00
l10n daemon script
5e5c352421 GIT_SILENT Sync po/docbooks with svn 2023-06-18 02:57:31 +00:00
l10n daemon script
515238b4b9 GIT_SILENT Sync po/docbooks with svn 2023-06-04 02:02:06 +00:00
l10n daemon script
6263a65606 GIT_SILENT Sync po/docbooks with svn 2023-05-31 02:41:34 +00:00
l10n daemon script
e295e8a782 GIT_SILENT Sync po/docbooks with svn 2023-05-30 02:21:37 +00:00
l10n daemon script
819720a9e6 GIT_SILENT Sync po/docbooks with svn 2023-05-23 02:44:11 +00:00
l10n daemon script
93fcab6217 GIT_SILENT Sync po/docbooks with svn 2023-05-14 02:13:45 +00:00
l10n daemon script
657e243951 GIT_SILENT Sync po/docbooks with svn 2023-04-30 03:02:25 +00:00
l10n daemon script
70eef99173 GIT_SILENT Sync po/docbooks with svn 2023-04-27 02:00:45 +00:00
l10n daemon script
a2339ed3e3 GIT_SILENT Sync po/docbooks with svn 2023-04-24 02:19:00 +00:00
l10n daemon script
de353395dc GIT_SILENT Sync po/docbooks with svn 2023-04-23 02:56:53 +00:00
l10n daemon script
e1e8c47aec GIT_SILENT Sync po/docbooks with svn 2023-04-17 02:55:30 +00:00
l10n daemon script
79033efbcc GIT_SILENT Sync po/docbooks with svn 2023-04-11 02:30:32 +00:00
l10n daemon script
6a78c351d9 GIT_SILENT Sync po/docbooks with svn 2023-04-07 01:51:50 +00:00
Aroun Olorin
4f93251d8c fix: read plasmashell version more reliably
In some cases, `plasmashell -v` crashes, which makes `readAllStandardOutput`
fail, although the version is printed out by the process before crashing.
See https://bugs.kde.org/show_bug.cgi?id=467696 and
https://bugreports.qt.io/browse/QTBUG-112258 for the details of the crash.

Instead, read the libtaskmanager version from CMake, which is much more
reliable.
2023-03-31 15:30:03 +00:00
l10n daemon script
06fbe1fd4d GIT_SILENT Sync po/docbooks with svn 2023-03-28 02:31:18 +00:00
l10n daemon script
0db62d6bdc GIT_SILENT Sync po/docbooks with svn 2023-03-27 02:55:36 +00:00
l10n daemon script
a0a4911a69 GIT_SILENT Sync po/docbooks with svn 2023-03-12 03:35:44 +00:00
l10n daemon script
98ac3dc225 GIT_SILENT Sync po/docbooks with svn 2023-03-02 02:55:00 +00:00
l10n daemon script
491a5b0f49 GIT_SILENT Sync po/docbooks with svn 2023-02-25 03:27:04 +00:00
l10n daemon script
f37c8531a8 GIT_SILENT Sync po/docbooks with svn 2023-02-24 02:26:45 +00:00
l10n daemon script
a7e875e567 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2023-02-24 02:04:42 +00:00
l10n daemon script
a111d8153a GIT_SILENT Sync po/docbooks with svn 2023-02-23 02:30:18 +00:00
l10n daemon script
7564e0ee52 GIT_SILENT Sync po/docbooks with svn 2023-02-16 03:32:10 +00:00
l10n daemon script
c73d03b2b3 GIT_SILENT made messages (after extraction) 2023-02-16 01:01:05 +00:00
Mathias Tillman
76302ee78a Fix an issue that caused panels and docks with the Visiblity set to Always Visible to behave the same way as Windows Go Below due to the workspace not being resized properly. 2023-02-12 11:39:13 +00:00
l10n daemon script
906fdf796a GIT_SILENT Sync po/docbooks with svn 2023-02-12 02:18:52 +00:00
l10n daemon script
63043c0b34 GIT_SILENT Sync po/docbooks with svn 2023-02-09 02:42:04 +00:00
l10n daemon script
911bc0bd7e GIT_SILENT Sync po/docbooks with svn 2023-02-08 03:30:06 +00:00
l10n daemon script
9fbafbfbb4 GIT_SILENT Sync po/docbooks with svn 2023-02-04 02:48:23 +00:00
l10n daemon script
159496edc0 GIT_SILENT Sync po/docbooks with svn 2023-01-26 02:12:43 +00:00
Fushan Wen
aa04303c63
plasmoid: remove deprecated DragHelper
It's removed in Plasma 6.

CCBUG: 464528
2023-01-26 09:27:36 +08:00
l10n daemon script
30def9c505 GIT_SILENT Sync po/docbooks with svn 2023-01-25 02:30:09 +00:00
l10n daemon script
6c2b5f4971 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2023-01-25 02:03:41 +00:00
l10n daemon script
f7088bf0ba GIT_SILENT Sync po/docbooks with svn 2023-01-24 02:25:30 +00:00
Fushan Wen
e9269e5151
plasmoid: use generateMimeData in Backend
CCBUG: 464528
2023-01-23 12:56:07 +08:00
Fushan Wen
218ff83986
plasmoid: port away from custom drag handler
BUG: 464528
CCBUG: 402376
2023-01-23 10:47:21 +08:00
l10n daemon script
57c6148dc4 GIT_SILENT Sync po/docbooks with svn 2023-01-20 02:22:33 +00:00
l10n daemon script
daa1e6b066 GIT_SILENT Sync po/docbooks with svn 2023-01-17 02:41:36 +00:00
l10n daemon script
957fece0ca GIT_SILENT Sync po/docbooks with svn 2023-01-15 02:12:54 +00:00
l10n daemon script
6a677d7b95 GIT_SILENT Sync po/docbooks with svn 2023-01-13 03:12:52 +00:00
l10n daemon script
c04bda6d92 GIT_SILENT Sync po/docbooks with svn 2023-01-07 03:04:54 +00:00
l10n daemon script
29ae2aa698 GIT_SILENT Sync po/docbooks with svn 2023-01-04 03:01:53 +00:00
l10n daemon script
af28885b81 GIT_SILENT Sync po/docbooks with svn 2023-01-03 03:22:44 +00:00
l10n daemon script
531d2bce80 GIT_SILENT Sync po/docbooks with svn 2023-01-02 03:05:57 +00:00
l10n daemon script
d882578f6f GIT_SILENT Sync po/docbooks with svn 2023-01-01 03:04:40 +00:00
Nicolas Fella
a3467a975d Remove waylandcpp from install instructions
We don't need the cpp lib, only the official C lib

BUG: 463466
2022-12-27 13:56:32 +01:00
l10n daemon script
93c50a7e8f GIT_SILENT Sync po/docbooks with svn 2022-12-25 03:02:46 +00:00
l10n daemon script
7d8a939f81 GIT_SILENT Sync po/docbooks with svn 2022-12-21 02:12:41 +00:00
l10n daemon script
f8afad52fb GIT_SILENT Sync po/docbooks with svn 2022-12-18 02:44:24 +00:00
l10n daemon script
60826a13c9 GIT_SILENT Sync po/docbooks with svn 2022-12-14 03:01:24 +00:00
l10n daemon script
8783d07542 GIT_SILENT Sync po/docbooks with svn 2022-12-02 03:11:58 +00:00
l10n daemon script
4ec72572f2 GIT_SILENT Sync po/docbooks with svn 2022-11-22 02:20:20 +00:00
l10n daemon script
42fedafc02 GIT_SILENT Sync po/docbooks with svn 2022-11-20 02:51:05 +00:00
l10n daemon script
45d4ccc6d3 GIT_SILENT Sync po/docbooks with svn 2022-11-19 02:11:07 +00:00
l10n daemon script
61b1441f5b GIT_SILENT Sync po/docbooks with svn 2022-11-17 02:06:08 +00:00
David Redondo
1d468a94e9 Opt out of fixed window positions on Wayland
Latte dock is using PlasmaQuick::Dialog and can load applets that use
PlasmaQuick::Dialog, which uses QWindow::position to cache the position
where the window is requested to be, so we need to opt out of this
Qt behavior.
BUG=461856
2022-11-16 10:19:07 +01:00
l10n daemon script
8588614fbf GIT_SILENT Sync po/docbooks with svn 2022-11-15 02:19:16 +00:00
l10n daemon script
8b60c00cf1 GIT_SILENT Sync po/docbooks with svn 2022-11-13 02:09:23 +00:00
l10n daemon script
bf7bee9b20 GIT_SILENT Sync po/docbooks with svn 2022-11-07 02:51:51 +00:00
l10n daemon script
051aad2661 GIT_SILENT Sync po/docbooks with svn 2022-11-04 02:06:10 +00:00
l10n daemon script
f9c1854438 GIT_SILENT Sync po/docbooks with svn 2022-11-03 02:11:28 +00:00
l10n daemon script
d170d540b4 GIT_SILENT Sync po/docbooks with svn 2022-11-02 02:23:23 +00:00
l10n daemon script
e433d1c7f0 GIT_SILENT Sync po/docbooks with svn 2022-10-31 03:00:48 +00:00
l10n daemon script
c755c7f534 GIT_SILENT Sync po/docbooks with svn 2022-10-28 02:19:38 +00:00
l10n daemon script
27fbdff59d GIT_SILENT Sync po/docbooks with svn 2022-10-26 02:13:52 +00:00
l10n daemon script
b55a7b24fa GIT_SILENT Sync po/docbooks with svn 2022-10-25 02:13:15 +00:00
l10n daemon script
e6e50d712f GIT_SILENT Sync po/docbooks with svn 2022-10-22 11:42:26 +00:00
l10n daemon script
b7797307e7 GIT_SILENT Sync po/docbooks with svn 2022-10-20 03:16:17 +00:00
l10n daemon script
db47394e33 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2022-10-20 02:05:25 +00:00
l10n daemon script
d7e9fbe772 GIT_SILENT made messages (after extraction) 2022-10-20 00:51:21 +00:00
l10n daemon script
0acb003769 GIT_SILENT Sync po/docbooks with svn 2022-10-09 02:14:02 +00:00
l10n daemon script
24776aa572 GIT_SILENT Sync po/docbooks with svn 2022-10-07 02:24:20 +00:00
l10n daemon script
53fce38f9e SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2022-10-07 01:51:20 +00:00
l10n daemon script
1b01e945b9 GIT_SILENT made messages (after extraction) 2022-10-07 00:47:52 +00:00
l10n daemon script
cff02dcc30 GIT_SILENT Sync po/docbooks with svn 2022-10-06 02:13:59 +00:00
l10n daemon script
5f0a553ec3 GIT_SILENT Sync po/docbooks with svn 2022-10-03 03:01:44 +00:00
l10n daemon script
6d74ebb2d9 GIT_SILENT Sync po/docbooks with svn 2022-10-02 03:16:37 +00:00
Friedrich W. H. Kossebau
cd36798a61 Remove explicit use of ECM_KDE_MODULE_DIR, is part of ECM_MODULE_PATH
GIT_SILENT
2022-09-06 17:39:14 +00:00
Nicolas Fella
5971fca696 Add Gitlab CI 2022-08-27 19:08:24 +02:00
l10n daemon script
a9d8687073 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2022-08-08 01:49:51 +00:00
l10n daemon script
c459397db7 GIT_SILENT made messages (after extraction) 2022-08-08 00:47:03 +00:00
l10n daemon script
55caf75ab4 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2022-08-07 01:49:36 +00:00
Nicolas Fella
bbb155c6bb Remove arcconfig
We are not using Phabricator anymore
2022-08-05 01:20:23 +02:00
l10n daemon script
ff511ccc1d SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2022-08-04 01:46:35 +00:00
l10n daemon script
7c4ab40769 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2022-07-23 01:47:49 +00:00
l10n daemon script
d404ca5219 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2022-07-15 01:48:37 +00:00
l10n daemon script
b0885a1711 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2022-07-14 01:51:45 +00:00
Michail Vourlakos
960186b147 blur:do not make calculations for HIDDENMASK 2022-07-13 12:25:46 +03:00
Michail Vourlakos
a3bdc89a0f wayland:support PipeWire for Plasma 5.24,5.25,5.26 2022-07-13 12:08:28 +03:00
Michail Vourlakos
2e252b5420 update KDE Neon installation command 2022-07-08 13:30:43 +03:00
Nick Girga
777d16b3d3 Add dependency to build instructions for Fedora 36
When I first tried to build using the included instructions (on Fedora 36), CMake failed, complaining about a missing `I18n`. So, I just looked for packages with similar names that have fitting descriptions. `kf5-ki18n-devel` was the first one that I tried because the description seemed really promising. CMake immediately was able to continue and Latte Dock finished building and installing successfully. It also functions exactly as expected now.

This small addition to the dependency installation command should reduce the speed bumps for Fedora users.
2022-07-08 10:29:01 +00:00
l10n daemon script
24b1e8faae SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2022-07-04 01:48:39 +00:00
Michail Vourlakos
0cc73324c3 settings:fix options form layout alignment 2022-06-30 10:46:33 +03:00
Michail Vourlakos
899c0155c7 plasmatheme:define max background opacity to 1%
BUG:443366
2022-06-27 12:41:22 +03:00
Michail Vourlakos
54ccf51cda view:respect plasma theme default opacity value
--when background contrast effect is enabled and the
user has chosen DEFAULT opacity for its background then
plasma theme preferred contrast effect values should be
used.

BUG:443366
2022-06-26 09:36:08 +03:00
Michail Vourlakos
c758a694e0 plasma_indicator:rename task background file 2022-06-26 09:19:46 +03:00
Michail Vourlakos
46f343aa5c plasma_indicator:respect plasma theme svgs
--use plasma implementation for plasma applets and tasks
at all cases... all workarounds must be removed and respect
plasma themes even when they are broken on their
implementation.

BUG:455925
2022-06-26 09:15:07 +03:00
Michail Vourlakos
bdf92099bb plasmatheme:for defaults settings use real mask
--follow the new panel background way to access its mask
and use it also for both the blur area and mask area when
they are really needed. Such a case in only when the user
has requested for plasma theme default settings

BUG:455567
2022-06-25 10:00:13 +03:00
Michail Vourlakos
cbf9088f60 [wm/tasktools] update to plasma 5.24.5 codebase 2022-06-22 09:18:04 +03:00
Michail Vourlakos
d5bbdf57dc highlight only grouped windows when hovered
BUG:455656
2022-06-22 09:01:19 +03:00
Michail Vourlakos
80931bd3d5 support plasma 5.25 windows accent autocoloring 2022-06-21 19:43:11 +03:00
l10n daemon script
4ae96e718c SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2022-06-20 01:54:41 +00:00
Michail Vourlakos
ec51d21eae support json files from indicators
--when an indicator provides only a json file for
its metadata latte now is able to indentify it
properly.

BUG:455603
2022-06-19 18:35:01 +03:00
Michail Vourlakos
81e0f90f43 taks:provide single json metadata file
--this way make installation happy without warnings
2022-06-19 18:00:18 +03:00
Michail Vourlakos
3c155198a1 replace deprecated cmake library 2022-06-19 14:01:44 +03:00
Michail Vourlakos
48a60c6268 tasks:fix dolphin context menu with plasma 5.25
--update context menu code in order to be relevant with
plasma 5.25
2022-06-19 10:47:54 +03:00
l10n daemon script
bef155238a SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2022-06-19 01:43:12 +00:00
Michail Vourlakos
6009db6163 tasks:support plasma 5.25 present windows
BUG:454296
2022-06-16 16:16:48 +03:00
l10n daemon script
73abdf7a13 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2022-06-16 01:55:13 +00:00
l10n daemon script
2157c0d455 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2022-06-13 02:36:06 +00:00
l10n daemon script
a014f386fb GIT_SILENT made messages (after extraction) 2022-06-13 01:09:04 +00:00
Michail Vourlakos
5a691197e8 rename "size" to thickness for some properties 2022-06-11 09:21:53 +03:00
Michail Vourlakos
3c3b5c6d11 tasks:support plasma 5.25 window view effect
--support window view effect from plasma 5.25 when
the user tries to activate a grouped task

BUG:454296
2022-06-06 22:02:14 +03:00
Michail Vourlakos
771f059e63 remove no needed if statement 2022-06-05 18:11:04 +03:00
l10n daemon script
220b8b98da SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2022-06-01 01:57:59 +00:00
l10n daemon script
ac3505b076 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2022-05-29 01:45:51 +00:00
l10n daemon script
917e928dbd SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2022-05-28 02:21:24 +00:00
l10n daemon script
420cb4198a GIT_SILENT made messages (after extraction) 2022-05-28 01:01:58 +00:00
Lucas Rafael
0a0110f534 Docs: add missing Fedora deps.
Added some dependencies that were missing to build Latte in Fedora 36. Without these, `install.sh` fails.
2022-05-27 15:22:06 +00:00
l10n daemon script
c4abc2eaf5 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2022-05-27 01:42:54 +00:00
l10n daemon script
66a1713b40 GIT_SILENT made messages (after extraction) 2022-05-27 00:46:06 +00:00
l10n daemon script
4e1fdc4466 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2022-05-25 01:46:56 +00:00
Michail Vourlakos
8c26f50fa4 contextmenu:fix broken binder 2022-05-23 21:39:31 +03:00
Michail Vourlakos
abe7c19547 drop per dock/panel inConfigureAppletsMode
--we now support a global value that can be used
in order to provide inConfigureAppletsMode for
all docks and panels at the same time.
2022-05-23 21:35:02 +03:00
l10n daemon script
9c1728cd25 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2022-05-23 01:45:01 +00:00
Michail Vourlakos
d3538eeec3 view:remove viewpart contextmenu class 2022-05-22 20:30:14 +03:00
Michail Vourlakos
cbd30a8c22 contextmenu:remove systray deprecated code 2022-05-22 20:25:24 +03:00
Michail Vourlakos
b7c7e9ebd4 wayland workaround:respect popupmargin 2022-05-22 18:38:54 +03:00
Michail Vourlakos
625b852ba7 view:remove mousePressed slot 2022-05-22 18:06:47 +03:00
Michail Vourlakos
d208698143 more fixes for context menu 2022-05-22 17:44:28 +03:00
Michail Vourlakos
18b47b607f protect from nullptr crashes 2022-05-22 17:24:40 +03:00
Michail Vourlakos
02d3c37f93 view:drop contextmenu class
--use ContextMenuLayer internal quickitem
that is responsible for applets and containments
context menus from now on.
2022-05-22 17:20:19 +03:00
Michail Vourlakos
90e4ea28c4 introduce ContextMenuLayerQuickItem
--use plasma approach in order to show context menus
for applets by introducing a new QuickItem that will
be responsible for this at the bottom of applets and
containment layers
2022-05-22 17:12:42 +03:00
Michail Vourlakos
dd8756ad79 view:simplify main context menu code 2022-05-22 16:09:01 +03:00
Michail Vourlakos
b4b6979ea7 contextmenu:remove deprecated tasks workaround 2022-05-22 12:54:02 +03:00
Michail Vourlakos
4f7812338e plasmoid:add virtualdesktops binder 2022-05-22 11:59:38 +03:00
Michail Vourlakos
f9b264e053 plasmoid:remove plasma deprecated code from menu 2022-05-22 11:59:38 +03:00
l10n daemon script
f94e5bc843 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2022-05-19 01:42:43 +00:00
l10n daemon script
163720adef SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2022-05-18 01:43:49 +00:00
l10n daemon script
1c9ec6ef73 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2022-05-17 01:45:57 +00:00
l10n daemon script
866fc3eb16 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2022-05-16 01:48:57 +00:00
Tamim Khan
e1ad706481 Update INSTALLATION.md with missing arch dependancy.
`plasma-wayland-protocols` was missing from the pacman command. Installation fails otherwise. Added it to the file.
2022-05-15 17:02:07 +00:00
Alexander Lohnau
a2fb837ea1 Configure metadata for plasmoid, remove versions where not needed 2022-05-15 09:14:46 +00:00
Alexander Lohnau
cb32286a8f Remove author data, name and description from package metadata files
Task: https://phabricator.kde.org/T15452
2022-05-15 09:14:46 +00:00
Alexander Lohnau
3f9fdf996b Convert desktop files of applets to json
Task: https://phabricator.kde.org/T14564
2022-05-15 09:14:46 +00:00
Alexander Lohnau
44287ff696 containmentactions/contextmenu: Install plugin in specific namespace
Otherwise, we use KServiceTypeTrader at runtime
2022-05-15 09:14:46 +00:00
Alexander Lohnau
4e6dca0879 Remove configure_file method calls for KPackage metadata.desktop files
We already have the configured desktop files in-source. Also, the author information is nothing which is subject to change.
2022-05-15 09:14:46 +00:00
Alexander Lohnau
8c21550f18 Indicator packageplugin: Clean up a bit of unneeded code 2022-05-15 09:14:46 +00:00
Alexander Lohnau
f1f1668394 Slightly bump KF5 requirements, fix ECM_FIND_VERSION checks, move basic ECM includes to top
Now we need to explicitly set the KDE_COMPILERSETTINGS_LEVEL variable.
2022-05-15 09:14:46 +00:00
Alexander Lohnau
1cb7e1c8b0 Convert desktop files of plugins to json
Task: https://phabricator.kde.org/T14564
2022-05-15 09:14:46 +00:00
Alexander Lohnau
0d461b1cad Port away from deprecated Plasma plugin macros 2022-05-15 09:14:46 +00:00
l10n daemon script
7cda1c66e1 GIT_SILENT made messages (after extraction) 2022-05-15 00:51:20 +00:00
Michail Vourlakos
a11b9a8d62 update panelshadows code to plasma 5.24 2022-05-11 21:10:38 +03:00
Michail Vourlakos
4374dace17 indicators:switch to QtQuick NewStuff dialog 2022-05-11 20:48:41 +03:00
Michail Vourlakos
3ea1e904a2 add bullet points in readme 2022-05-11 20:15:45 +03:00
Michail Vourlakos
8f48f4ea9b wrong type 2022-05-11 20:14:04 +03:00
Michail Vourlakos
83d4da52e6 add missing new lines 2022-05-11 20:12:26 +03:00
Michail Vourlakos
3b480d42d9 upgrade widgets explorer code to plasma 5.24
BUG:451743
2022-05-10 19:06:47 +03:00
Ömer Fadıl Usta
e49404db7c Remove oldcode to sync with new KF5_MIN_VERSION ( 5.82 )
Now we based on 5.82 as KF5_MIN_VERSION so time to make a spring cleaning
2022-05-10 09:29:40 +00:00
Michail Vourlakos
be9799b342 wayland:views now switch properly between screens 2022-05-09 20:39:23 +03:00
Michail Vourlakos
b1d57051c2 wayland:support Plasma primaryscreen protocol
--use ScreenPool as reference for primary screen.
The new code uses PrimaryOutputWatcher class from
Plasma Shell in order to keep track of primary
screen at all cases.

BUG:448418
FIXED-IN:0.11.0
2022-05-09 20:35:45 +03:00
Michail Vourlakos
4401fdbb0f tasks:always finish bouncing animation
--more specific when a new window is added or
when the in attention bouncing animation is not
needed any more
2022-04-17 21:30:06 +03:00
Michail Vourlakos
5100deee38 startup:track background brightness correctly
--plasma is doing some funny stuff in multi-screen
environments by changing screen ids and back and forth
when primary screen is changed. We now take into account
this and when screen plasma pools updates its ids in
any case the wallpapers tracking follows instantly.
2022-04-17 17:22:31 +03:00
Michail Vourlakos
6750f02d6f cmd:define log file for debug output 2022-04-17 16:07:28 +03:00
Michail Vourlakos
6bce84c68b tasks:return bounce on start when destructed 2022-04-17 09:24:05 +03:00
l10n daemon script
bd6ae904b9 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2022-04-01 02:01:29 +00:00
l10n daemon script
ec5b56031a GIT_SILENT made messages (after extraction) 2022-04-01 00:54:17 +00:00
Amy Rose
538dba0a02 refactor LayoutManager::save() to remove code repetition
Hey, first KDE contribution here. I was digging through code trying to fix [bug 427530](https://bugs.kde.org/show_bug.cgi?id=427530) when I found this copied-and-pasted block in LayoutManager::save(). This MR moves the block into a lambda to remove code repetition.

I am not a C++ programmer and although nothing changed that I could notice, it would be smart to sanity check and/or test this before merging.
2022-03-31 14:40:35 +00:00
l10n daemon script
d43f3d5ac4 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2022-03-29 02:16:19 +00:00
l10n daemon script
45619c7248 GIT_SILENT made messages (after extraction) 2022-03-29 00:53:23 +00:00
l10n daemon script
a42bc6788c SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2022-03-23 02:09:30 +00:00
Michail Vourlakos
3f90a49b55 applet:use last mouse event after dock slide-in
--this way the parabolic effect works nicely after
the dock slides-in. In the past there was a chance
that even though mouse was hovering an parabolicable applet
the parabolic effect was not started because parabolic
event was rejected because the dock was not fully shown
yet
2022-03-06 11:56:25 +02:00
Michail Vourlakos
21d8728498 tasks:fix launchers behavior in different applets
BUG:450986
2022-03-05 11:10:40 +02:00
Ömer Fadıl Usta
ac021a38b7 Fix Typo in header guard of floatinggapwindow 2022-03-02 19:42:57 +00:00
Ömer Fadıl Usta
bf7a87a81b Fix Typo in header guard of colorsmodel 2022-03-02 19:37:39 +00:00
Ömer Fadıl Usta
8476a796d2 Spring cleaning with Qt5.15.x
Because of we increased min qt version to 5.15.x, we dont need these checks anymore
2022-03-01 04:47:12 +00:00
Michail Vourlakos
fe63a63efc clones:fix parabolic behavior on alignment changes
--more specificaly before this patch when the host
dock was changing from justify to center alignment
clones parabolic effect did not work as intended
2022-02-28 22:51:22 +02:00
Michail Vourlakos
0f3c2b8468 change appletcontainer length to float value 2022-02-27 18:05:50 +02:00
Michail Vourlakos
dea478f16e fix trembling at parabolic edges 2022-02-27 17:39:26 +02:00
Michail Vourlakos
59b422448b fix #100,introduce parabolic edge spacers for main
--new introduced external spacers of main layout are
used from parabolic effect in order to keep the contents
of main layout in balance. That produces a much better
visual result for the user because when the user hovers
an item, that item is zoomed and the mouse is still
present at first hovered position.
2022-02-27 17:24:48 +02:00
Michail Vourlakos
d841e1e443 provide Default option for Background opacity
--the user can now move the background opacity slider
to the farest left side and is such case it will get
the plasma theme default opacity. This is the same
way that background radius and shadows size can return
to default settings

BUG:443366
2022-02-25 18:34:42 +02:00
Michail Vourlakos
f1472db653 parabolic:simplify linear code
--define the mathematical approach more appropriately
in order to be extended and understood much easier
2022-02-21 16:28:45 +02:00
Michail Vourlakos
48ecda9723 accept background radius 0% 2022-02-18 19:10:46 +02:00
Michail Vourlakos
6e1c45d087 increase max zoom factor to 125%
--when user is using no thickness margin influence
for parabolic effect it nice to have a little bigger
zoom factor in order for parabolic zoom to
look nicer
2022-02-12 22:09:19 +02:00
Michail Vourlakos
40b4851dac introduce thickness margin influence option 2022-02-12 22:06:05 +02:00
Michail Vourlakos
b6a38e3830 improve autocalculationss for mask/blur regions
--this fix provides more accurate roundness masks
based on user preference
2022-02-05 17:28:57 +02:00
Michail Vourlakos
4d1fbfd584 simplify how dock window thickness is calculated
--provide a minimum window thickness for docks at 384px.
and afterwards use maxiconsize, maxmargin etc calculations
in order to use greater window thicknesses
2022-01-30 21:50:51 +02:00
Michail Vourlakos
11f42978fa specify input mask when parabolic effect applied
--trying to handle this way all jumpiness from parabolic
effect when dock is at the bottom edge and the user moves its
mouse at the top edge of the parabolized item. When the mouse
slightly exits the item ParabolicMouseArea and gets a mouseEntered
signal even though, it should not and immediately gets also
a mouseExited signal to correct things. This happens exactly
after the Paraboli.sglClearZoom() signal has been triggered.
2022-01-30 20:29:20 +02:00
Michail Vourlakos
8a2e2581ef head thickness margin take into account background 2022-01-30 13:28:30 +02:00
Michail Vourlakos
097ceed7d2 split thickness margins to tail and head
--make head thickness margin and tail thickness
margin totally independent
--ability item: reanchor it based on the screen edge
like applets are already doing
--adjust tasks animations in order to take into
account the anchoring
--parabolic effect adjust calculations to use
new thickness margins
2022-01-30 13:25:51 +02:00
Michail Vourlakos
f0ad7b23c7 update Changelog to v0.10.8 2022-01-25 10:52:17 +02:00
Michail Vourlakos
c7bb46b217 introduce new MultipleLayouts mechanism
--the new approach does not load/unload layouts
during startup/exit. When the user loads layouts
in multiple layouts mode the layouts are inserted
and when exit they still remain in the hidden
multiple layouts file. These layouts present in the
multiple layouts file from now are called preloaded
layouts.
--the new approach fixes also the wayland exit
issue and in general the message for Latte not
closed properly has been totally dropped.

BUG:448702
BUG:446205
2022-01-25 09:58:44 +02:00
Michail Vourlakos
219e901e87 zoom:improve response on first and last items
--improve zoom behavior for first and last items when
the user hovers them before any other item is hovered
and zoomed
2022-01-23 00:28:43 +02:00
Vlad Zahorodnii
e326dddbd6 Unset global shortcut for settings
Meta+W will be used by Plasma in 5.24.

In general, settings are not frequently accessed so they don't need a
global shortcut assigned by default.
2022-01-18 16:03:23 +00:00
Rodrigo Pedra Brum
2b039e1275 Add const declarations on implementation files which use them as references
When trying to compile the new Multiple Screens feature released yesterday I got this error on KDE neon:

```bash
[ 83%] Building CXX object app/CMakeFiles/latte-dock.dir/lattedockadaptor.cpp.o
[ 84%] Linking CXX executable ../bin/latte-dock
/usr/bin/ld: CMakeFiles/latte-dock.dir/view/clonedview.cpp.o: in function `Latte::ClonedView::translateToClonesOrder(QList<int> const&)':
clonedview.cpp:(.text+0x1aaa): undefined reference to `Latte::ClonedView::ERRORAPPLETID'
collect2: error: ld returned 1 exit status
make[2]: *** [app/CMakeFiles/latte-dock.dir/build.make:2270: bin/latte-dock] Error 1
make[1]: *** [CMakeFiles/Makefile2:1806: app/CMakeFiles/latte-dock.dir/all] Error 2
make: *** [Makefile:146: all] Error 2
```

After some research I found this StackOverflow answer:

https://stackoverflow.com/a/3026148

Which referenced this FAQ by Bjarne Stroustrup:

https://www.stroustrup.com/bs_faq2.html#in-class

In summary, if a `static const` is initialized in a class, and later is used as a reference in an implementation file, it should also be declared inside the implementation file. The initialization can live only inside the class.

Maybe the compiler used by @mvourlakos has an optimization to overcome such construct.

In my case by adding these two lines I could compile it on KDE neon (after fixing the first error, compilation failed on a second spot).
2022-01-17 15:41:44 +00:00
Michail Vourlakos
ee307a0759 update to v0.10.76 2022-01-16 22:09:49 +02:00
Michail Vourlakos
84fe31c318 panels:fix switch to explicit screens and back
--some improvements introduced to 0.10.7 broke the
screen switching codepath for panels. With this
fix users can again move panels around for their
screens

BUG:448569
FIXED-IN:0.10.8
2022-01-16 22:00:18 +02:00
Michail Vourlakos
60095bba3b fix #96,FEATURE:AllScreens and AllSecondaryScreens
--This is a HUGE FEATURE and so important for multi-screens
users. It is introduced as one single commit because it
reimplements plenty of infrastructure changes and it will
be easier to identify newly introduced bugs.
--Users can now choose for their docks and panels to belong
at various screen groups. The first two screen groups introduced
are AllScreens and AllSecondayScreens. In the future it might
be possible to provide CustomScreensGroup that the user will
be able to define specific screens in which a dock or panel
should be always present.
--Current solution specifies an Original dock or panel and clones/copies
itself automatically to other screens. So docks and panels in other screens
are just real docks and panels that reference themselves to original
docks and panels.
--Clones are destroyed during layout startup and are automaticaly
recreated. It is suggested to export your layouts through the
official Layouts Editor in order to share them because in that case
clones are not included in the new generated layout file. If in any
case you do not this and you share your layout with any previous
versions then your clones will just appear as separate docks and
panels that belong to specific screens.
--Automatic syncing was introduced in order to keep up-to-date
the configuration of Original docks and panels with their referenced
Clones.
--Automatic syncing currently works for all docks and panels settings,
for all normal applets configurations and for all subcontaiments
configuration such as systrays.
--Automatic syncing does not work for applets inside subcontainments
such as Group Plasmoid. In such case it is suggested to configure
your applets inside your Group Plasmoid in the original dock or panel
and afterwards to trigger a recreation for the relevant clones
--Manual recreation of clones is easily possible by just choosing
the dock or panel to be OnPrimary or OnSpecificScreen and rechoosing
afterwards the AllScreensGroup or AllSecondaryScreensGroup
2022-01-16 13:38:13 +02:00
Michail Vourlakos
8a0f18326e fix for vertical panels identifying top borders
--use also floating screen edge margin in order to identify
if the top or bottom borders of a vertical dock or panel
should be drawn
2022-01-16 03:42:23 +02:00
Michail Vourlakos
fa4db13e81 fix position of custombackground on screen corners
BUG:448519
FIXED-IN:0.10.8
2022-01-16 03:12:35 +02:00
Michail Vourlakos
6fa1d1cc87 fix vertical docks/panels positioning
--identify correctly for vertical panels in right edge
when they need to draw or not their top and bottom borders.
This is enough in order to position properly these docks.

BUG:448519
FIXED-IN:0.10.8
2022-01-16 02:32:24 +02:00
Michail Vourlakos
ec62b36018 position kwinedgehelper properly after startup
BUG:448433
FIXED-IN:0.10.8
2022-01-16 02:32:24 +02:00
Michail Vourlakos
0657ca1e4e x11:center applet config window on screen 2022-01-14 20:58:25 +02:00
Michail Vourlakos
6187f4d997 do not shrink vertical docks/panels on startup 2022-01-14 20:21:20 +02:00
Michail Vourlakos
c4afa37465 view:unblock events when user undo removal
--this way when a dock or panel is scheduled for
removal but the user undo that removal all
events for main dock/panel window are forwarded
correctly. As  a side fix parabolic effect works
just fine now is such scenario.
2022-01-14 20:05:29 +02:00
Michail Vourlakos
837f0a81e7 update Changelog to v0.10.7 2022-01-10 15:54:41 +02:00
Ömer Fadıl Usta
3c5b474a97 Make spring cleaning to match our KF5_MIN_VERSION
Since we already require 5.71.0 as min version of KF , it is meaning less to keep old checks for lower versions in code, this will make code more and more cleaner

Since all plasma using cpp17 and we recently switch to cpp14 think that it may be better to keep it more up-to-date and match with plasma
2022-01-09 12:21:55 +00:00
Michail Vourlakos
aa57d21515 kwinedge:calculations improvements 2022-01-08 21:17:39 +02:00
Michail Vourlakos
20e3f3cbb3 kwinedges:fix calculations and positioning 2022-01-08 21:01:09 +02:00
Michail Vourlakos
a12565ab1f windowsgobelow:show properly on startup
BUG:448099
2022-01-08 21:01:09 +02:00
Ömer Fadıl Usta
d0f4bcfa33 Freebsd compile fix
(try#1)
2022-01-08 02:20:00 +00:00
Michail Vourlakos
98f39e17e3 parabolic:fix applets clearing issue 2022-01-07 14:32:38 +02:00
Michail Vourlakos
b1c3594367 provide ParabolicEffect spread option
--this way the user can choose to use a much
greater parabolic effect that will influence five
or seven of its neighbours instead of just three.
The new option can be found at Latte Global Preferences.
2022-01-07 10:17:36 +02:00
Michail Vourlakos
78b124e8f4 align properly thintooltips on vertical edges 2022-01-04 15:01:39 +02:00
Michail Vourlakos
7d180f8dd6 ignore layout/view extensions properly
--remove them manually and do not use baseName()
because it might take into account dots that are
part of the name.
2022-01-04 10:15:02 +02:00
Michail Vourlakos
4de51de221 dragging:respect placeholder in length fill calcs
--reduce glitches when dragging applets around and there
are also fillLength applets in Justify alignment
2022-01-04 01:31:17 +02:00
Michail Vourlakos
c9aa147b7b justify:update centered offset always 2022-01-04 00:56:44 +02:00
Michail Vourlakos
c6ea796f00 fill one pixel gap of justify splitters 2022-01-04 00:12:15 +02:00
Michail Vourlakos
02d7e2a7d8 drag applet:remove no needed reparenting
--no reason to reparent placeholder out of layouts
order while dragging an applet. This way internal
view splitters are always calculated correctly.
2022-01-04 00:12:15 +02:00
Michail Vourlakos
850937ca22 justify:offset centered applets if overlap 2022-01-03 22:57:33 +02:00
Michail Vourlakos
4c1c65e353 scrgeometries:public empty QRegion() correctly 2022-01-03 20:46:00 +02:00
Michail Vourlakos
765aa45c72 view:enable OnAllDesktops during creation
--try to avoid corner cases that wm ignores OnAllDesktops
flag for specific views during startup. This patch should
protect these corner cases.

BUG:447689
FIXED-IN:0.10.7
2022-01-01 21:06:27 +02:00
l10n daemon script
1e841db497 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2022-01-01 01:44:03 +00:00
Michail Vourlakos
1a12bce8af update application name in desktop file
--help external applications to locate the
proper desktop file. This helps also kglobalaccel
to discover which desktop file is linked to
Latte Dock. As a side improvement now latte
dock gains its icon in Plasma Systemsettings
Shortcuts.
2021-12-31 17:23:00 +02:00
Michail Vourlakos
fc8c439787 anchor tooltip for all latte specific applets 2021-12-31 12:30:22 +02:00
Michail Vourlakos
ce15e4e511 hide thin tooltip properly
--update current visual parent for thin tooltip
even when this tooltip showing is blocked. Such
a case is when a different applet popup is triggered.

BUG:443645
FIXED-IN:0.10.7
2021-12-30 03:31:49 +02:00
Michail Vourlakos
9351277cd7 anchor thin tooltips on their visual parents
BUG:447631
2021-12-30 03:12:18 +02:00
Michail Vourlakos
8bd168a5a5 always trust KWin for setting struts
--when kwin is running then we should always
trust it in order to provide correct struts.
That applies also under x11 where other wms
might fail.

BUG:447595
FIXEX-IN:0.10.7
2021-12-29 18:52:57 +02:00
Michail Vourlakos
5ecb8ab767 window belongs in a screen whenever touching it
--whenever a window geometry is touching a screen geometry
is now considered that this window belongs to that screen.
This way a window could look active to more that one screens.
This way all last active window considerations now work
properly even when the window center is out of screen.
2021-12-27 23:31:08 +02:00
Michail Vourlakos
cd2ec88274 enable regions broadcasting
--it doesnt make any difference with Plasma
2021-12-27 23:30:55 +02:00
Michail Vourlakos
c98f6679b8 fix plasma available geometry broadcasting
--ignore docks and panels for availableScreenRect(s) etc.
when they are in startup and they are painted offscreen
--plasma is not ready to accept availableScreenRegion(s) because
after startup moves desktop widgets to the left even though
it should not
--fix availableScreenRegion calculations for Centered and Justified
docks and panels
2021-12-27 23:30:11 +02:00
Michail Vourlakos
7304025bc3 remove doubled debug message 2021-12-24 13:45:04 +02:00
Michail Vourlakos
3b8c4392c1 remove no needed qt checks 2021-12-20 23:07:50 +02:00
Pino Toscano
362b21ee08 Merge remote-tracking branch 'origin/v0.10' 2021-12-19 08:23:18 +01:00
Michail Vourlakos
346381370b update Changelog to 0.10.6 2021-12-18 10:42:26 +02:00
Michail Vourlakos
74626f7bdf Revert "find Qt5 minor version"
This reverts commit 51f166bf514fc0e4f2f1d158ef7022a0eff42d7f.
2021-12-17 12:07:03 +02:00
Michail Vourlakos
4e28392c3e fix broken initialization of windows tracking
--some improvements of 0.10.5 broke the windows tracking
initialization. This is a fix in order for windows tracking
to be enabled/disabled properly per dock/panel during
startup phase.
2021-12-17 11:59:05 +02:00
Michail Vourlakos
51f166bf51 find Qt5 minor version 2021-12-17 11:23:03 +02:00
Michail Vourlakos
74d5b567ed update qt minimum to 5.15 2021-12-17 10:49:03 +02:00
Michail Vourlakos
055e92b0d6 update Changelog to 0.10.5 2021-12-16 17:22:13 +02:00
Michail Vourlakos
a033a20062 more startup improvements
--visibility: simplify and improve code
for restoring and saving values
--enable visibility mode early on the startup
sequence
--enable windows tracking after startup phase
has ended
--windows tracking respect also view geometry
changes and not only window changes from the
desktop environment
2021-12-15 21:32:23 +02:00
l10n daemon script
7a7af88e99 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2021-12-15 01:55:46 +00:00
Michail Vourlakos
c317d3257a fix 30bit color depth that makes dock invisible
--previous approach did not work correctly on 24bit
systems. The new approach should handle properly all
cases.
2021-12-14 20:14:51 +02:00
Michail Vourlakos
c15a97bacf Revert "[x11] - fix 30bit color depth that makes dock invisible with broken transparency"
This reverts commit 6497da4a4d6beede0cd1650d4b9e02efb88d3d24.
2021-12-14 20:03:09 +02:00
Michail Vourlakos
45db72b5db tasks: fix typo 2021-12-14 20:03:09 +02:00
Michail Vourlakos
720a9ca5b0 tasks:identify vivaldi properly
--update PulseAudio qml code inside the
latte taskmanager in order to identify properly
through pid applications that are playing
audio but they use a different parent pid
to do so. This is the Vivaldi case that
appears as Chromium in pulseaudio streams.

BUG:446828
FIXED-IN:0.10.5
2021-12-14 19:45:22 +02:00
Jonas Latza
ccbf079113 [x11] - fix 30bit color depth that makes dock invisible with broken transparency 2021-12-14 17:35:21 +00:00
Michail Vourlakos
de61ff48ad enable strtus fro all alternative DEs 2021-12-14 17:20:57 +02:00
Michail Vourlakos
fb4cfaa399 view:copy properly screen edge margin
Consider -1 as screen edge margin default value
and not zero. This way when duplicating a default
dock AllBorders are not enabled in the new dock.

BUG:446903
FIXED-IN:0.10.5
2021-12-13 23:50:25 +02:00
Michail Vourlakos
24fc1e8709 singlelayout:fix borderless activation/deactivation 2021-12-13 23:16:46 +02:00
Michail Vourlakos
5e0feef0f6 do not allow struts when view is offscreen 2021-12-13 23:16:46 +02:00
Michail Vourlakos
62ed63daf1 option:rename screen edge to floating gap 2021-12-12 19:12:05 +02:00
Michail Vourlakos
ca83433ce0 multiscreen:disable struts under x11 when overlap
--when multiple screens placement have edges that overlap
with each other, at that edges struts must be disabled
to provide much better windows behavior. For example when
dragging a window between such screens and there is
an AlwaysVisible panel or dock between them.

BUG:445595
FIXED-IN:0.10.5
2021-12-12 14:39:46 +02:00
Michail Vourlakos
bce0d74e5f multiple:do not update borderless when no needed
--when activating activities under multiple layouts
the currentActivityChanged() signal is sent from
KActivities before the runningActivitiesChanged() and
as such we can end in considering borderless maximized
window flag before all appropriate layouts have been enabled.
The patch adds a timer and delays borderlessMaximized consideration
when currentActivityChanged signal is received.
2021-12-12 14:39:35 +02:00
Michail Vourlakos
c2b20852ea recreateview:fix launchers group assignment
--after recreating a view, launchers group is now
assigned again correctly. As it appears the problem
was that Host.MyView ability was sending an isReady
signal that was not accurate enough.
2021-12-12 14:39:27 +02:00
Michail Vourlakos
aeb934d0fb improve smoothness of animations during startup
--This new approach paints all docks and panels during
starup offscreen. This way especially under x11 not a lot of
visual glitches are appearing all over the place.
After startup time has ended docks and panels are
moved at their original and valid placement and slide in
animations are triggered.
2021-12-12 14:39:18 +02:00
Michail Vourlakos
6a66dd0000 add missing signal 2021-12-12 04:41:11 +02:00
Michail Vourlakos
3287a293b9 canvas ruler:decrease view maxlength properly
--whem view minlength and maxlength are equals
the Canvas Ruler should decrease and increase
both of them when the user mouse scrolls the ruler
2021-12-11 19:57:12 +02:00
Michail Vourlakos
a553f7403f position vertical docks/panels more accurately
--send more availableRect/Region changed signals
for more cases and as such all views update
their positioning properly.
--for example when a horizontal view updates its
offset or max length independent of its visibility mode
the neighbour vertical views need to update
and validate their position.
2021-12-11 19:32:58 +02:00
Michail Vourlakos
7258920d70 Merge branch 'v0.10' into master 2021-12-10 17:14:15 +02:00
Michail Vourlakos
ea19ff18ad improve responsiveness for DynamicStruts Scenario
--add a timer blocker in order to reduce struts calls
at window manager. This way the entire desktop experience
becomes more stable and fluent.
2021-12-10 17:08:58 +02:00
Michail Vourlakos
11a8c3fee7 fix binding loop when moving int.splitters 2021-12-10 17:08:43 +02:00
Michail Vourlakos
321a50627d plenty of fixes when dragging/moving applets 2021-12-10 17:08:32 +02:00
Michail Vourlakos
434f3b16e6 cmd:close after disabling autostart 2021-12-08 18:24:58 +02:00
Michail Vourlakos
229f92b2c8 ignore window states when kwin is showing desktop
--this way every dock/panel and also applets that
are using the LastActiveWindow API behave like there
is no shown window
2021-12-07 20:58:26 +02:00
Michail Vourlakos
1365b9f24f cmd:print all available templates 2021-12-07 20:24:34 +02:00
Michail Vourlakos
e88aaf27a9 cmd:support "add-dock" through command line
-- "add-dock" option now works even when application
is not running and the user is executing it through
command line.

BUG: 446526
FIXED-IN: 0.10.5
2021-12-07 20:11:29 +02:00
l10n daemon script
b4da839df4 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2021-12-03 01:46:34 +00:00
Michail Vourlakos
3067b6d51c autostart: do not overwrite startup file 2021-12-02 20:55:22 +02:00
Michail Vourlakos
05e588c333 update .knsrc file
--update knsrc file in new way of handling
online latte indicators and in this way
support at the same time latte indicators
to be installed from Plasma LookNFeel packages.
--because of previous change the new required
kde frameworks version is 5.71
2021-12-01 17:48:01 +02:00
Michail Vourlakos
e0bfff4c48 get ready for Plasma LookNFeel packages
--introduce enable/disableAutostart from command line
--accept import-layout from command line when latte is already running
--introduce --suggested-layout-name to be used with
  import-layout in order to provide a preferred layout name
  e.g. latte-dock --import-layout /blah/blah/mywhat.layout.latte
       --suggested-layout-name MyAwesomeLayout
--dbus:introduce "setAutostart" function
--dbus:introduce "importLayoutFile" function

BUG:446249
FIXED-IN:0.10.5
2021-11-30 21:29:06 +02:00
l10n daemon script
127f24bb24 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2021-11-29 01:38:54 +00:00
l10n daemon script
fae5fcffb7 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2021-11-28 01:33:07 +00:00
Michail Vourlakos
eb6ae017fe ignore maxlength=0 for fill lenght applets
--fix mediacontroller_plus applet scenario
by ignoring maximum width = 0 that qt is
already doing for Layouts that fill length.

BUG:445869
2021-11-21 20:35:24 +02:00
Michail Vourlakos
518563a8c1 update changelog to v0.10.4 2021-11-17 13:20:12 +02:00
Michail Vourlakos
5dc6cea1f8 remove QDBusInterface usage 2021-11-14 19:14:24 +02:00
Michail Vourlakos
0c1e29bf4e plasmageometry:remove workarounds for activities
--remove workarounds for plasma desktop not respecting
geometries sent from Latte for activities that are not
the current one
2021-11-14 14:08:41 +02:00
Michail Vourlakos
b3efb73aef plasmadesk:fix startup freezes from QDbusInterface
--as it appears plasma applets were not the main faulter
to blame for startup freezes. The bug was that Latte
was trying to communicate with Plasma DBus interface
to inform it about docks/panels geometries. For some
reason during startup other applets could also were
trying the same and for that reason Qt provides a 25sec
forced delay in case there are too many such calls.
The new approach does not block the startup code at all
and it should work at all cases.

BUG:444739
FIXED-IN:0.10.4
2021-11-14 13:44:20 +02:00
l10n daemon script
23ec03a9fd SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2021-11-13 01:27:36 +00:00
Michail Vourlakos
27062087ea startup:avoid kwin reconfiguring with no reason
--during startup borderless maximized windows should not be
enabled or not as long as kwin has already been configured
in the proper way. This way we make Latte startup lighter
because KWin is not reconfiguring when not needed.
2021-11-11 18:42:17 +02:00
Michail Vourlakos
c4964d0b1f modernize dbus noblock calls 2021-11-11 18:42:08 +02:00
Michail Vourlakos
199effaf2b wayland:hide centered black line for alwaysvisible
--drop RasterWindow for always visible ghost windows and
use a fully transparent QQuickView

BUG:444419
FIXED-IN:0.10.4
2021-11-11 14:00:48 +02:00
Michail Vourlakos
55e893b43b update inputgeometry when sliding in/out
--this way mouse clicks correspond much better
in how they should behave. For example right
clicks do not forward always the events to the
desktop during sliding.
2021-11-06 10:38:56 +02:00
Michail Vourlakos
90405fef8a update lastactivewindow based on changed signal 2021-10-31 19:11:47 +02:00
Michail Vourlakos
e642087e31 Indicators API:Extend animations capabilities
extend indicator.level.requested signals with:
  --taskLauncherActivated
  --taskGroupWindowAdded
  --taskGroupWindowRemoved

extend indicator.level.requested properties with:
  --isIndicatorTaskLauncherAnimationRunning

extend indicator info with:
  --providesInAttentionAnimation
  --providesTaskLauncherAnimation
  --providesGroupedWindowAddedAnimation
  --providesGroupedWindowRemovedAnimation

adjust Latte Tasks in order to support properly
animations implemented through indicators.
2021-10-30 14:37:02 +03:00
Michail Vourlakos
956b589764 wm:init vdswraparound value properly
BUG:444572
2021-10-29 22:50:30 +03:00
Michail Vourlakos
eda019016d Indicators:expose more options for Icons
--the following options are exposed to indicators
in order to use them to their preference:
----iconTransformOrigin
----iconOpacity
----iconRotation
----iconScale
2021-10-28 12:33:29 +03:00
Michail Vourlakos
6f30380802 decouple task realremanimation from launcheranim 2021-10-28 10:07:44 +03:00
Michail Vourlakos
7e1b0bc2ee fix binding loops in Indexer client ability 2021-10-28 10:05:03 +03:00
Michail Vourlakos
9ce7c5b72d respect applet maximumLength==0
--if the applet has set maximum length to
zero then the applet should not be shown
2021-10-27 21:21:31 +03:00
Michail Vourlakos
81c298114b update Changelog to 0.10.3 2021-10-25 16:50:00 +03:00
Michail Vourlakos
61d4ff64d8 support X11::GlobalScaling properly
--as it appears many users are using Plasma GlobalScaling
in conjuction with PLASMA_USE_QT_SCALING. This commit
provides plenty of fixes for that scenario in order to
make things workable.
--adjust X11::InputMask based on devicePixelRatio()
--adjust X11::GtkFrameExtents based on devicePixelRatio()
--adjust View::absoluteGeometry() based on devicePixelRatio()
--adjust WM::Tracker based on devicePixelRatio()
--adjust WM::AbstractInterface based on devicePixelRatio()

BUG:444222
FIXED-IN:0.10.3
2021-10-24 16:37:04 +03:00
Michail Vourlakos
36af1f27e8 latte indicator:show border always on second point 2021-10-24 13:29:55 +03:00
Michail Vourlakos
e2b98892e5 simplify latte indicator implementation
--fix also the line animation in order to be always
played correctly
2021-10-24 12:03:26 +03:00
Michail Vourlakos
ea500a8ec0 indicators:expose iconOffsetX/Y to applets
--expose iconed applets indicator iconOffsetX/Y setting
and this way animate applet icons if the indicator
would like to do so
2021-10-24 00:36:44 +03:00
Michail Vourlakos
04929b0138 do not clip applets at all cases
--this way cases that applets painting such as
shadows, blur etc. is out of the applets contents
they are still painted
2021-10-23 20:35:00 +03:00
Michail Vourlakos
33428af95b default roundToIconSize for applets in panels 2021-10-23 20:34:51 +03:00
Michail Vourlakos
1aeae6d256 restore indicator iconOffset when changing styles 2021-10-23 13:02:18 +03:00
Michail Vourlakos
e822062668 disable "CanBeAboveFullscreen" properly
--fix how CanBeAboveFullscreen windows option can be
enabled/disabled properly and work correctly
--fix how Blur is handled for docks and panels that
can be AboveFullScreenWindows under X11. Blur is now
working correctly for them but of course GtkFrameExtents
do not work at all because they are intended to work
based on KWin implementation.

BUG:443536
2021-10-22 21:34:21 +03:00
Michail Vourlakos
cbbfc55861 disable frame_extents for X11::ByPassWM()
--fix blur positioning for docks panels that
have chosen to ByPassWM() under X11 environment
2021-10-22 20:43:25 +03:00
Michail Vourlakos
63a54b40db unblock Meta event properly for all launchers 2021-10-22 20:05:53 +03:00
Michail Vourlakos
3769cef501 identify kickofflegacy applet properly 2021-10-22 19:31:55 +03:00
l10n daemon script
dacf4d71a8 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2021-10-21 01:16:23 +00:00
Michail Vourlakos
c9515a0353 activate through mouse wheel more applets
--when an applet is not identified as expandable
but on the other hand has activated the flag
activationTogglesExpanded then for those
applets the mouse wheel option should also
trigger an activation event
2021-10-15 01:41:13 +03:00
Michail Vourlakos
59360176ee dont block visibility function after Meta trigger
--Menu11 and SimpleMenu applets are using a custom
plasmoid approach in order to be able to position their
popups differently on the screen. This patch considers
this in a more generic way and does not use the default
codepath to show popups from these applets. More
importantly the Needs/RequiresAttention status is used
in order to determine the panel/dock visibility for
these applets.

BUG:441053
2021-10-15 01:16:05 +03:00
Michail Vourlakos
d354cc4513 fix focus behavior when notes applet is used
BUG:443236
2021-10-07 18:09:01 +03:00
Michail Vourlakos
4ca17600c6 fix popup positioning for plasma-style popups
--consider the panel background roundness and position
positions only related to that roundness. This way the
plasma style popups that feel part of the panel background
are positioned properly always and they do not touch
in empty areas.
2021-10-04 23:10:15 +03:00
Michail Vourlakos
c24cd92c98 latte indicator set backcorner step to 1 2021-10-04 17:54:23 +03:00
Michail Vourlakos
c86878f6c7 [indicators api] - new background corner margin
--introducing in Indicators API a new option to
specify the indicator preference for the distance
between the indicator and panel background roundness.
By altering the option the indicator can get into
the panel background roundness.

BUG:442675
2021-10-03 09:23:50 +03:00
Michail Vourlakos
fc4dc6dacc prevent session manager from restoring application
--disable session manager restoring and keep only the
autostart desktop file way in order to start Latte
2021-10-02 09:29:37 +03:00
Michail Vourlakos
58c7093be9 fix #85,respect kwin vds navigation wrapping around
--respect and track KWin option for Virtual Desktops
navigation wrapping around setting
2021-09-28 22:05:17 +03:00
Michail Vourlakos
53674a65e1 provide translations for dock panel templates
BUG:442435
2021-09-14 21:05:59 +03:00
Michail Vourlakos
ad3f97d6df add v0.10.2 to Changelog 2021-09-11 21:43:41 +03:00
Michail Vourlakos
a2813a1c43 fix Fitt's Law for parabolic effect items
--fix Fitt's law for items touching the screen
edge and at the same time using parabolic
effect
2021-09-11 14:06:38 +03:00
Michail Vourlakos
a80c71981a fix Fitt's Law for justify vertical panels 2021-09-11 13:12:29 +03:00
l10n daemon script
d47f01a499 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2021-08-31 01:29:24 +00:00
Michail Vourlakos
596a184fa1 context:store properly no actions at all case
--make sure that if the user has disable all context
menu actions then this is preserved after during
startups
2021-08-27 08:54:10 +03:00
Michail Vourlakos
5e55abbff5 context:use restore() provided function
containment() is not accessible during the containment
actions constructor. We now use the provided ::restore()
function in order to load the actions

BUG:441448
2021-08-27 08:32:15 +03:00
Michail Vourlakos
5c9dc950d7 viewsdialog:add missing translations
CCBUG:441357
2021-08-26 15:55:01 +03:00
l10n daemon script
bcae47a3f9 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2021-08-26 01:18:26 +00:00
l10n daemon script
463437d8d0 GIT_SILENT made messages (after extraction) 2021-08-26 00:18:36 +00:00
Michail Vourlakos
a192b66a16 update Changelog for v0.10.1 2021-08-25 11:46:21 +03:00
l10n daemon script
eb95f2ef13 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2021-08-22 01:17:47 +00:00
l10n daemon script
25e05070bb GIT_SILENT made messages (after extraction) 2021-08-20 00:22:30 +00:00
Rafael Brandmaier
27b90bb89c add missing Fedora dependencies 2021-08-16 17:02:00 +00:00
l10n daemon script
9f89d13c7b SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2021-08-13 01:18:37 +00:00
Michail Vourlakos
66ddda956b fix build with Fedora requirements
--simplify warnings and add formalt security checks

BUG:440759
2021-08-12 08:08:00 +03:00
Nicolas Fella
38455ea76a Raise minimum CMake version to 3.16
As discussed in https://mail.kde.org/pipermail/plasma-devel/2021-February/119329.html

GIT_SILENT
2021-08-10 05:35:03 +00:00
Michail Vourlakos
df9117d010 specify KAboutData::productName()
--this way KCrash should now be able to identify
latte-dock bug address properly
2021-08-09 17:23:12 +03:00
Michail Vourlakos
949e9c5c5e Merge branch 'v0.10' into master 2021-08-09 16:26:51 +03:00
Michail Vourlakos
f7032f7f19 crash:dont show settings dialog in early startup
--showing settings dialog too early before layout(s)
are loaded can possible create crashes. Settings dialog
is considering that everything is in place and ready
to be used.

BUG:440731
2021-08-08 14:28:48 +03:00
Alexander Lohnau
2f6808b626
Define new KPackageStructure property in kpackage structures
The pluginId field is kept for compatibility.

Task: https://phabricator.kde.org/T14563
2021-08-01 20:33:50 +02:00
Alexander Lohnau
c02e4b6a7e
Consistently name kpackage structures
This will allow kpackage to load the structures by their path.

Task: https://phabricator.kde.org/T14757
Conceptually the same direction as https://phabricator.kde.org/T14499.
2021-08-01 20:26:35 +02:00
Michail Vourlakos
71f9e89157 disable inattention blocked slide-in when no needed
--when the task is no more inattention then dock should
slide-out when the visibility mode requests it even
when the inattention timer has not finished yet

BUG:439497
2021-07-27 14:13:16 +03:00
Michail Vourlakos
47702a59be respect indicators iconOffsetX/Y values properly
BUG:440283
2021-07-26 09:55:42 +03:00
Michail Vourlakos
f2c401b02f always show/hide applets popups properly 2021-07-25 08:47:19 +03:00
Michail Vourlakos
d84e50a594 restack applets internal ClickEffect
--internal click effect is now moved to CompactApplet
which is much better place to be. This way fullrepresentation
applets do not use it at all
2021-07-24 15:36:20 +03:00
l10n daemon script
27c6225b1a SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2021-07-24 01:14:07 +00:00
l10n daemon script
d600bbeb63 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2021-07-21 01:14:48 +00:00
Michail Vourlakos
834f71d266 major:update LastActiveWindow implementation
--new implementation keeps a more consistent history.
Each LastActiveWindow(LAW) now keeps track of all windows
that are related to its view even when these windows are not
currently shown. This way inactive windows history is
consistent and can be used from applets/visibility modes
more appropriately. VDs/Activities that are not
the current one(s) do not delete records from history
any more. Their respected windows are recorded and
flagged as NOT SHOWN, waiting this way to be valid
again after Activities/VDs changes.
2021-07-17 21:02:58 +03:00
Michail Vourlakos
72ff76033b fix "favorite" icon name typo
--this way favorite icon is always used
properly because it is shown from Breeze icon
theme if current icon theme does not
provide it
2021-07-17 15:28:55 +03:00
Michail Vourlakos
e0e3f19f7a pref option to disable geometries broadcasting
--the user can choose to disable available desktop geometry
broadcasting to Plasma in order to avoid any desktop widgets
moving at all cases
2021-07-16 18:57:30 +03:00
Michail Vourlakos
19defa08cd drop WinTracker::availableScreenGeometry calcs
--Views WindowsTracker in using screen geometry only to
identify which windows are in the same view screen has nothing
to do with availablescreengeometry. This is why it is
dropped and replaced by View::screenGeometry() value
2021-07-11 11:39:38 +03:00
Michail Vourlakos
bb713e1092 calculate scrolling length in (int) values
--calculations for tasks length exceed must be done
always in same arthmetic world either int or float for
all values. It is chosen the int case because latte
is providing applets length in int values

BUG:439540
2021-07-10 08:54:33 +03:00
Michail Vourlakos
750785b5e5 fix notifications placement for sidebars
--Corona::availableScreenRe.. functions now ignore
visibility modes from views that are almost always hidden
such as SideBars and AutoHide panels/docks
2021-07-09 10:23:22 +03:00
l10n daemon script
92aec503f5 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2021-07-03 01:21:02 +00:00
Michail Vourlakos
fd5b4e53ec fix Debug Window layout
--it was broken because of all new View::Name
property
2021-06-29 18:58:00 +03:00
Michail Vourlakos
30de674870 cmdline:add dock/panel through --add-dock 2021-06-28 17:14:54 +03:00
Michail Vourlakos
8ec97ed6c4 cmd:provide option for add-dock 2021-06-27 20:53:39 +03:00
Michail Vourlakos
469a5e48cc update to version 0.10.75 2021-06-27 08:58:01 +03:00
Michail Vourlakos
ce9fd0132d update Changelog to v0.10.0 2021-06-27 08:48:33 +03:00
l10n daemon script
d699e144ce SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2021-06-26 01:23:25 +00:00
450 changed files with 207120 additions and 4844 deletions

View File

@ -1,3 +0,0 @@
{
"phabricator.uri" : "https://phabricator.kde.org/"
}

1
.gitignore vendored
View File

@ -1,5 +1,4 @@
*~
.*
!.arcconfig
!.gitignore

6
.gitlab-ci.yml Normal file
View File

@ -0,0 +1,6 @@
# SPDX-FileCopyrightText: None
# SPDX-License-Identifier: CC0-1.0
include:
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/linux.yml
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/freebsd.yml

29
.kde-ci.yml Normal file
View File

@ -0,0 +1,29 @@
# SPDX-FileCopyrightText: None
# SPDX-License-Identifier: CC0-1.0
Dependencies:
- 'on': ['@all']
'require':
'frameworks/extra-cmake-modules': '@latest'
'frameworks/kdoctools': '@latest'
'frameworks/kio': '@latest'
'frameworks/ki18n': '@latest'
'frameworks/kwidgetsaddons': '@latest'
'frameworks/karchive': '@latest'
'frameworks/kcoreaddons': '@latest'
'frameworks/kguiaddons': '@latest'
'frameworks/kdbusaddons': '@latest'
'frameworks/kcrash': '@latest'
'frameworks/kdeclarative': '@latest'
'frameworks/kglobalaccel': '@latest'
'frameworks/kirigami': '@latest'
'frameworks/ki18n': '@latest'
'frameworks/kiconthemes': '@latest'
'frameworks/knewstuff': '@latest'
'frameworks/knotifications': '@latest'
'frameworks/kwindowsystem': '@latest'
'frameworks/kxmlgui': '@latest'
'plasma/kwayland': '@latest'
'plasma/libplasma': '@latest'
'plasma/plasma-workspace': '@stable'
'plasma/plasma-activities': '@latest'

View File

@ -1,5 +1,31 @@
#**CHANGELOG**#
#### Version 0.10.X (current development build)
* optionally maximise panel size in presence of maximised windows (https://invent.kde.org/plasma/latte-dock/-/merge_requests/46)
#### Version 0.10.8
* multi-screen: fix docks/panels screen repositioning when the user specifies different screen for dock or panel
* fix borders identification for autopositioning vertical docks/panels
* fix vertical docks/panels autopositioning which is relevant to top and bottom panels
* position kwin edges helper window properly on startup after offscreen positioning
* x11: center applets config window on screen
* do not shrink vertical docks/panels on startup after switching from offscreen to onscreen
* make dock and panel work properly when they undo their removal
#### Version 0.10.7
* multi-screen: always trust KWin under X11 in order to set correct struts for panels and docks
* automatically offset centered applets when the left or right widgets overlap the centered one
* windowsgobelow: show properly during startup
* kwinedges: calculate accurately their size and position
* improve applets dragging during rearrange and configure widgets mode
* hide thin tooltips properly at some cases that were stack
* fill one pixel gap of justify splitters during rearrange and configure widgets mode
* fix, windows belong to screen whenever they are touching it. This way a window could belong in more than one screens and be taken into account for visibility modes and active window tracking
* remove file extensions for layouts and templates properly in order to identify the layout or template name
* fix build for Freebsd
* x11: force OnAllDesktops for all docks and panels during creation
* fix empty availableScreenRegion broadcast to Plasma
#### Version 0.10.6
* fix build with Qt 5.12
* initialize windows tracking properly

View File

@ -1,27 +1,43 @@
project(lattedock)
cmake_minimum_required(VERSION 3.0 FATAL_ERROR)
cmake_minimum_required(VERSION 3.16 FATAL_ERROR)
set(CMAKE_CXX_STANDARD 14)
set(VERSION 0.10.6)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(VERSION 0.10.77)
set(AUTHOR "Michail Vourlakos, Smith Ar")
set(EMAIL "mvourlakos@gmail.com, audoban@openmailbox.org")
set(WEBSITE "https://userbase.kde.org/LatteDock")
set(BUG_ADDRESS "https://bugs.kde.org/enter_bug.cgi?product=lattedock")
set(FAQS "https://userbase.kde.org/LatteDock/FAQ")
set(QT_MIN_VERSION "5.9.0")
set(KF5_MIN_VERSION "5.48.0")
set(QT_MIN_VERSION "5.15.0")
set(KF5_MIN_VERSION "5.88.0")
set(KDE_COMPILERSETTINGS_LEVEL "5.84.0")
set(KF5_LOCALE_PREFIX "")
find_package(ECM ${KF5_MIN_VER} REQUIRED NO_MODULE)
set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR})
find_package(ECM ${KF5_MIN_VERSION} REQUIRED NO_MODULE)
set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH})
include(KDEInstallDirs)
include(CheckIncludeFiles)
include(CMakePackageConfigHelpers)
include(ECMOptionalAddSubdirectory)
include(ECMQtDeclareLoggingCategory)
include(KDECMakeSettings)
include(KDECompilerSettings NO_POLICY_SCOPE)
include(KDEPackageAppTemplates)
include(WriteBasicConfigVersionFile)
find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED NO_MODULE COMPONENTS DBus Gui Qml Quick)
find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS
Activities Archive CoreAddons GuiAddons Crash DBusAddons Declarative GlobalAccel Kirigami2
I18n IconThemes KIO NewStuff Notifications Plasma PlasmaQuick Wayland WindowSystem XmlGui)
find_package(LibTaskManager REQUIRED)
add_definitions(-DPLASMA_WORKSPACE_VERSION="${LibTaskManager_VERSION}")
find_package(X11 REQUIRED)
set_package_properties(X11 PROPERTIES DESCRIPTION "X11 libraries"
@ -45,17 +61,20 @@ if(X11_FOUND AND XCB_XCB_FOUND)
set(HAVE_X11 ON)
endif()
find_package(QtWaylandScanner REQUIRED)
find_package(Qt${QT_MAJOR_VERSION}WaylandClient)
find_package(PlasmaWaylandProtocols 1.6 REQUIRED)
find_package(Wayland REQUIRED COMPONENTS Client)
string(REGEX MATCH "\\.([^]]+)\\." KF5_VERSION_MINOR ${KF5_VERSION})
string(REGEX REPLACE "\\." "" KF5_VERSION_MINOR ${KF5_VERSION_MINOR})
message(STATUS "KF5 VERSION : ${KF5_VERSION}")
message(STATUS "KF5 VERSION MINOR : ${KF5_VERSION_MINOR}")
if(${KF5_VERSION_MINOR} LESS "62")
find_package(KF5 REQUIRED COMPONENTS SysGuard)
endif()
include(ECMQMLModules)
include(ECMFindQmlModule)
ecm_find_qmlmodule(QtQuick 2.7)
ecm_find_qmlmodule(QtQuick.Layouts 1.3)
ecm_find_qmlmodule(QtQuick.Controls 1.4)
@ -65,17 +84,8 @@ ecm_find_qmlmodule(org.kde.kquickcontrolsaddons 2.0)
ecm_find_qmlmodule(org.kde.plasma.core 2.0)
ecm_find_qmlmodule(org.kde.plasma.components 2.0)
include(CheckIncludeFiles)
include(CMakePackageConfigHelpers)
include(ECMOptionalAddSubdirectory)
include(ECMQtDeclareLoggingCategory)
include(KDECMakeSettings)
include(KDECompilerSettings NO_POLICY_SCOPE)
include(KDEInstallDirs)
include(KDEPackageAppTemplates)
include(WriteBasicConfigVersionFile)
include(Definitions.cmake)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/app/config-latte.h.cmake
${CMAKE_CURRENT_BINARY_DIR}/app/config-latte.h)
#hide warnings
string(REPLACE "-Wall" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})

View File

@ -1,2 +0,0 @@
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/app/config-latte.h.cmake
${CMAKE_CURRENT_BINARY_DIR}/app/config-latte.h)

View File

@ -17,22 +17,26 @@ sudo apt dist-upgrade
### Kubuntu and KDE Neon
```
sudo apt install cmake extra-cmake-modules qtdeclarative5-dev libqt5x11extras5-dev libkf5iconthemes-dev libkf5plasma-dev libkf5windowsystem-dev libkf5declarative-dev libkf5xmlgui-dev libkf5activities-dev build-essential libxcb-util-dev libkf5wayland-dev git gettext libkf5archive-dev libkf5notifications-dev libxcb-util0-dev libsm-dev libkf5crash-dev libkf5newstuff-dev libxcb-shape0-dev libxcb-randr0-dev libx11-dev libx11-xcb-dev kirigami2-dev
sudo apt install cmake extra-cmake-modules qtdeclarative5-dev libqt5x11extras5-dev libkf5iconthemes-dev libkf5plasma-dev libkf5windowsystem-dev libkf5declarative-dev libkf5xmlgui-dev libkf5activities-dev build-essential libxcb-util-dev libkf5wayland-dev git gettext libkf5archive-dev libkf5notifications-dev libxcb-util0-dev libsm-dev libkf5crash-dev libkf5newstuff-dev libxcb-shape0-dev libxcb-randr0-dev libx11-dev libx11-xcb-dev kirigami2-dev libwayland-dev libwayland-client0 plasma-wayland-protocols libqt5waylandclient5-dev qtwayland5-dev-tools
```
### Arch Linux
```
sudo pacman -Syu
sudo pacman -S cmake extra-cmake-modules python plasma-framework plasma-desktop
sudo pacman -S cmake extra-cmake-modules python plasma-framework plasma-desktop plasma-wayland-protocols
```
### Fedora/RHEL
```
sudo dnf install cmake extra-cmake-modules qt5-qtdeclarative-devel qt5-qtx11extras-devel kf5-kiconthemes-devel kf5-plasma-devel kf5-kwindowsystem-devel kf5-kdeclarative-devel kf5-kxmlgui-devel kf5-kactivities-devel gcc-c++ gcc xcb-util-devel kf5-kwayland-devel git gettext kf5-karchive-devel kf5-knotifications-devel libSM-devel kf5-kcrash-devel kf5-knewstuff-devel kf5-kdbusaddons-devel kf5-kxmlgui-devel kf5-kglobalaccel-devel kf5-kio-devel kf5-kguiaddons-devel kf5-kirigami2-devel kf5-kirigami-devel
sudo dnf install cmake extra-cmake-modules qt5-qtdeclarative-devel qt5-qtx11extras-devel kf5-kiconthemes-devel kf5-plasma-devel kf5-kwindowsystem-devel kf5-kdeclarative-devel kf5-kxmlgui-devel kf5-kactivities-devel gcc-c++ gcc xcb-util-devel kf5-kwayland-devel git gettext kf5-karchive-devel kf5-knotifications-devel libSM-devel kf5-kcrash-devel kf5-knewstuff-devel kf5-kdbusaddons-devel kf5-kxmlgui-devel kf5-kglobalaccel-devel kf5-kio-devel kf5-kguiaddons-devel kf5-kirigami2-devel kf5-kirigami-devel kf5-ki18n-devel qt5-qtwayland-devel plasma-wayland-protocols-devel wayland-devel
```
### openSUSE
```
sudo zypper install cmake extra-cmake-modules gcc-c++ gcc xcb-util-devel git gettext libSM-devel wayland-devel libQt5DBus-devel libQt5Gui-devel qtdeclarative-imports-provides-qt5 libqt5-qtdeclarative-devel knotifications-devel kactivities5-devel karchive-devel kcoreaddons-devel kcoreaddons-devel kguiaddons-devel kcrash-devel kdbusaddons-devel kdeclarative-devel kglobalaccel-devel kirigami2-devel ki18n-devel kiconthemes-devel kio-devel knewstuff-devel plasma-framework-devel kwayland-devel plasma5-workspace-devel kitemmodels-devel libqt5-qtx11extras-devel plasma-wayland-protocols libqt5-qtwayland
```
### Building and Installing
**Now you can run the installation script.**

121
LICENSES/CC0-1.0.txt Normal file
View File

@ -0,0 +1,121 @@
Creative Commons Legal Code
CC0 1.0 Universal
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
HEREUNDER.
Statement of Purpose
The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator
and subsequent owner(s) (each and all, an "owner") of an original work of
authorship and/or a database (each, a "Work").
Certain owners wish to permanently relinquish those rights to a Work for
the purpose of contributing to a commons of creative, cultural and
scientific works ("Commons") that the public can reliably and without fear
of later claims of infringement build upon, modify, incorporate in other
works, reuse and redistribute as freely as possible in any form whatsoever
and for any purposes, including without limitation commercial purposes.
These owners may contribute to the Commons to promote the ideal of a free
culture and the further production of creative, cultural and scientific
works, or to gain reputation or greater distribution for their Work in
part through the use and efforts of others.
For these and/or other purposes and motivations, and without any
expectation of additional consideration or compensation, the person
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
is an owner of Copyright and Related Rights in the Work, voluntarily
elects to apply CC0 to the Work and publicly distribute the Work under its
terms, with knowledge of his or her Copyright and Related Rights in the
Work and the meaning and intended legal effect of CC0 on those rights.
1. Copyright and Related Rights. A Work made available under CC0 may be
protected by copyright and related or neighboring rights ("Copyright and
Related Rights"). Copyright and Related Rights include, but are not
limited to, the following:
i. the right to reproduce, adapt, distribute, perform, display,
communicate, and translate a Work;
ii. moral rights retained by the original author(s) and/or performer(s);
iii. publicity and privacy rights pertaining to a person's image or
likeness depicted in a Work;
iv. rights protecting against unfair competition in regards to a Work,
subject to the limitations in paragraph 4(a), below;
v. rights protecting the extraction, dissemination, use and reuse of data
in a Work;
vi. database rights (such as those arising under Directive 96/9/EC of the
European Parliament and of the Council of 11 March 1996 on the legal
protection of databases, and under any national implementation
thereof, including any amended or successor version of such
directive); and
vii. other similar, equivalent or corresponding rights throughout the
world based on applicable law or treaty, and any national
implementations thereof.
2. Waiver. To the greatest extent permitted by, but not in contravention
of, applicable law, Affirmer hereby overtly, fully, permanently,
irrevocably and unconditionally waives, abandons, and surrenders all of
Affirmer's Copyright and Related Rights and associated claims and causes
of action, whether now known or unknown (including existing as well as
future claims and causes of action), in the Work (i) in all territories
worldwide, (ii) for the maximum duration provided by applicable law or
treaty (including future time extensions), (iii) in any current or future
medium and for any number of copies, and (iv) for any purpose whatsoever,
including without limitation commercial, advertising or promotional
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
member of the public at large and to the detriment of Affirmer's heirs and
successors, fully intending that such Waiver shall not be subject to
revocation, rescission, cancellation, termination, or any other legal or
equitable action to disrupt the quiet enjoyment of the Work by the public
as contemplated by Affirmer's express Statement of Purpose.
3. Public License Fallback. Should any part of the Waiver for any reason
be judged legally invalid or ineffective under applicable law, then the
Waiver shall be preserved to the maximum extent permitted taking into
account Affirmer's express Statement of Purpose. In addition, to the
extent the Waiver is so judged Affirmer hereby grants to each affected
person a royalty-free, non transferable, non sublicensable, non exclusive,
irrevocable and unconditional license to exercise Affirmer's Copyright and
Related Rights in the Work (i) in all territories worldwide, (ii) for the
maximum duration provided by applicable law or treaty (including future
time extensions), (iii) in any current or future medium and for any number
of copies, and (iv) for any purpose whatsoever, including without
limitation commercial, advertising or promotional purposes (the
"License"). The License shall be deemed effective as of the date CC0 was
applied by Affirmer to the Work. Should any part of the License for any
reason be judged legally invalid or ineffective under applicable law, such
partial invalidity or ineffectiveness shall not invalidate the remainder
of the License, and in such case Affirmer hereby affirms that he or she
will not (i) exercise any of his or her remaining Copyright and Related
Rights in the Work or (ii) assert any associated claims and causes of
action with respect to the Work, in either case contrary to Affirmer's
express Statement of Purpose.
4. Limitations and Disclaimers.
a. No trademark or patent rights held by Affirmer are waived, abandoned,
surrendered, licensed or otherwise affected by this document.
b. Affirmer offers the Work as-is and makes no representations or
warranties of any kind concerning the Work, express, implied,
statutory or otherwise, including without limitation warranties of
title, merchantability, fitness for a particular purpose, non
infringement, or the absence of latent or other defects, accuracy, or
the present or absence of errors, whether or not discoverable, all to
the greatest extent permissible under applicable law.
c. Affirmer disclaims responsibility for clearing rights of other persons
that may apply to the Work or any use thereof, including without
limitation any person's Copyright and Related Rights in the Work.
Further, Affirmer disclaims responsibility for obtaining any necessary
consents, permissions or other rights required for any use of the
Work.
d. Affirmer understands and acknowledges that Creative Commons is not a
party to this document and has no duty or obligation with respect to
this CC0 or use of the Work.

View File

@ -1,6 +1,6 @@
About
=====
Latte is a dock based on plasma frameworks that provides an elegant and intuitive experience for your tasks and plasmoids. It animates its contents by using parabolic zoom effect and trys to be there only when it is needed.
Latte is a dock based on plasma frameworks that provides an elegant and intuitive experience for your tasks and plasmoids. It animates its contents by using parabolic zoom effect and tries to be there only when it is needed.
**"Art in Coffee"**
@ -15,7 +15,7 @@ Development
============
- Official KDE repo in which you can also send your MRs is located at: https://invent.kde.org/plasma/latte-dock
- Bug reports can be send at: https://bugs.kde.org/enter_bug.cgi?product=lattedock
- Bug reports can be sent at: https://bugs.kde.org/enter_bug.cgi?product=lattedock
Installation
@ -23,10 +23,11 @@ Installation
## Requirements
We recommend to use at least:
**Plasma >= 5.15.0**
**Qt >= 5.12**
We need to use at least:
- **Plasma >= 5.24.0**
- **PlasmaWaylandProtocols >= 1.6.0**
- **Qt >= 5.15**
Minimum requirements:
@ -37,34 +38,32 @@ Minimum requirements:
**development packages for:**
```
Qt5Core >= 5.12.0
Qt5Gui >= 5.12.0
Qt5Dbus >= 5.12.0
Qt5Core >= 5.15.0
Qt5Gui >= 5.15.0
Qt5Dbus >= 5.15.0
KF5Plasma >= 5.48.0
KF5PlasmaQuick >= 5.48.0
KF5Activities >= 5.48.0
KF5CoreAddons >= 5.48.0
KF5GuiAddons >= 5.48.0
KF5DBusAddons >= 5.48.0
KF5Declarative >= 5.48.0
KF5Kirigami2 >= 5.48.0
KF5Wayland >= 5.48.0
KF5Package >= 5.48.0
KF5XmlGui >= 5.48.0
KF5IconThemes >= 5.48.0
KF5KIO >= 5.48.0
KF5I18n >= 5.48.0
KF5Notifications >= 5.48.0
KF5NewStuff >= 5.48.0
KF5Archive >= 5.48.0
KF5GlobalAccel >= 5.48.0
KF5Crash >= 5.48.0
KF5Plasma >= 5.82.0
KF5PlasmaQuick >= 5.82.0
KF5Activities >= 5.82.0
KF5CoreAddons >= 5.82.0
KF5GuiAddons >= 5.82.0
KF5DBusAddons >= 5.82.0
KF5Declarative >= 5.82.0
KF5Kirigami2 >= 5.82.0
KF5Wayland >= 5.82.0
KF5Package >= 5.82.0
KF5XmlGui >= 5.82.0
KF5IconThemes >= 5.82.0
KF5KIO >= 5.82.0
KF5I18n >= 5.82.0
KF5Notifications >= 5.82.0
KF5NewStuff >= 5.82.0
KF5Archive >= 5.82.0
KF5GlobalAccel >= 5.82.0
KF5Crash >= 5.82.0
KSysGuard [reguired only for kf5<=5.61]
For X11 support:
KF5WindowSystem >= 5.48.0
For X11 support:
KF5WindowSystem >= 5.82.0
Qt5X11Extras >= 5.7.0
libxcb
libxcb-randr
@ -89,7 +88,7 @@ Minimum requirements:
### Arch Linux
- [Arch Linux](https://www.archlinux.org/packages/?sort=&q=latte-dock)
- [Arch Linux](https://aur.archlinux.org/packages/latte-dock)
### Gentoo
@ -106,7 +105,7 @@ Minimum requirements:
### FreeBSD
- [FreeBSD Port](https://www.freshports.org/deskutils/latte-dock/)
See the [installation instruction](./INSTALLATION.md) for others Linux distribution or development build
See the [installation instructions](./INSTALLATION.md) for other Linux distributions or development builds
## Run Latte-Dock
@ -115,7 +114,7 @@ Latte is now ready to be used by executing
latte-dock
```
or activating **Latte Dock** from applications menu.
or activating **Latte Dock** from the applications menu.
Contributors

View File

@ -4,7 +4,8 @@ set(lattedock-app_SRCS
infoview.cpp
lattecorona.cpp
screenpool.cpp
main.cpp
primaryoutputwatcher.cpp
main.cpp
coretypes.h
)
@ -49,61 +50,40 @@ ki18n_wrap_ui(lattedock-app_SRCS settings/screensdialog/screensdialog.ui)
ki18n_wrap_ui(lattedock-app_SRCS settings/settingsdialog/settingsdialog.ui)
ki18n_wrap_ui(lattedock-app_SRCS settings/viewsdialog/viewsdialog.ui)
ecm_add_qtwayland_client_protocol(lattedock-app_SRCS
PROTOCOL ${PLASMA_WAYLAND_PROTOCOLS_DIR}/kde-primary-output-v1.xml
BASENAME kde-primary-output-v1
)
add_executable(latte-dock ${lattedock-app_SRCS})
include(FakeTarget.cmake)
if(${KF5_VERSION_MINOR} LESS "62")
target_link_libraries(latte-dock
Qt5::DBus
Qt5::Quick
Qt5::Qml
KF5::Activities
KF5::Archive
KF5::CoreAddons
KF5::Crash
KF5::DBusAddons
KF5::Declarative
KF5::GuiAddons
KF5::GlobalAccel
KF5::I18n
KF5::IconThemes
KF5::KIOWidgets
KF5::Notifications
KF5::NewStuff
KF5::QuickAddons
KF5::Plasma
KF5::PlasmaQuick
KF5::ProcessCore
KF5::WaylandClient
KF5::XmlGui
)
else()
target_link_libraries(latte-dock
Qt5::DBus
Qt5::Quick
Qt5::Qml
KF5::Activities
KF5::Archive
KF5::CoreAddons
KF5::Crash
KF5::DBusAddons
KF5::Declarative
KF5::GuiAddons
KF5::GlobalAccel
KF5::I18n
KF5::IconThemes
KF5::KIOWidgets
KF5::Notifications
KF5::NewStuff
KF5::QuickAddons
KF5::Plasma
KF5::PlasmaQuick
KF5::WaylandClient
KF5::XmlGui
)
target_link_libraries(latte-dock
Qt5::DBus
Qt5::Quick
Qt5::Qml
KF5::Activities
KF5::Archive
KF5::CoreAddons
KF5::Crash
KF5::DBusAddons
KF5::Declarative
KF5::GuiAddons
KF5::GlobalAccel
KF5::I18n
KF5::IconThemes
KF5::KIOWidgets
KF5::Notifications
KF5::NewStuff
KF5::QuickAddons
KF5::Plasma
KF5::PlasmaQuick
KF5::WaylandClient
KF5::XmlGui
Wayland::Client
)
endif()
if(HAVE_X11)
target_link_libraries(latte-dock
@ -122,13 +102,8 @@ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/org.kde.latte-dock.desktop DESTINATION
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/org.kde.latte-dock.appdata.xml DESTINATION ${KDE_INSTALL_METAINFODIR})
install(FILES dbus/org.kde.LatteDock.xml DESTINATION ${KDE_INSTALL_DBUSINTERFACEDIR})
install(FILES lattedock.notifyrc DESTINATION ${KNOTIFYRC_INSTALL_DIR})
install(FILES latte-layouts.knsrc DESTINATION ${KDE_INSTALL_KNSRCDIR})
install(FILES latte-indicators.knsrc DESTINATION ${KDE_INSTALL_KNSRCDIR})
if(${KF5_VERSION_MINOR} LESS "57")
install(FILES latte-layouts.knsrc DESTINATION ${CONFIG_INSTALL_DIR})
install(FILES latte-indicators.knsrc DESTINATION ${CONFIG_INSTALL_DIR})
else()
install(FILES latte-layouts.knsrc DESTINATION ${KDE_INSTALL_KNSRCDIR})
install(FILES latte-indicators.knsrc DESTINATION ${KDE_INSTALL_KNSRCDIR})
endif()
add_subdirectory(packageplugins)

View File

@ -40,6 +40,19 @@ enum LayoutsMemory
}
}
namespace Latte {
namespace MultipleLayouts {
enum Status
{
Uninitialized = -1,
Paused,
Running
};
}
}
//! These are LatteApp::Types that will be used from Latte App c++ implementation AND
//! Latte containment qml. Such types are irrelevant and not used from plasma applets.

View File

@ -15,7 +15,9 @@ const bool Preferences::BORDERLESSMAXIMIZED;
const bool Preferences::ISAVAILABLEGEOMETRYBROADCASTEDTOPLASMA;
const bool Preferences::METAPRESSFORAPPLAUNCHER;
const bool Preferences::METAHOLDFORBADGES;
const int Preferences::PARABOLICSPREAD;
const int Preferences::SCREENSDELAY;
const float Preferences::THICKNESSMARGININFLUENCE = 1.0f;
const Settings::MouseSensitivity Preferences::MOUSESENSITIVITY;
Preferences::Preferences()
@ -32,6 +34,8 @@ Preferences::Preferences(Preferences &&o)
metaPressForAppLauncher(o.metaPressForAppLauncher),
metaHoldForBadges(o.metaHoldForBadges),
mouseSensitivity(o.mouseSensitivity),
parabolicSpread(o.parabolicSpread),
thicknessMarginInfluence(o.thicknessMarginInfluence),
screensDelay(o.screensDelay)
{
}
@ -46,6 +50,8 @@ Preferences::Preferences(const Preferences &o)
metaPressForAppLauncher(o.metaPressForAppLauncher),
metaHoldForBadges(o.metaHoldForBadges),
mouseSensitivity(o.mouseSensitivity),
parabolicSpread(o.parabolicSpread),
thicknessMarginInfluence(o.thicknessMarginInfluence),
screensDelay(o.screensDelay)
{
}
@ -61,6 +67,8 @@ Preferences &Preferences::operator=(const Preferences &rhs)
metaPressForAppLauncher = rhs.metaPressForAppLauncher;
metaHoldForBadges = rhs.metaHoldForBadges;
mouseSensitivity = rhs.mouseSensitivity;
parabolicSpread = rhs.parabolicSpread;
thicknessMarginInfluence = rhs.thicknessMarginInfluence;
screensDelay = rhs.screensDelay;
return (*this);
@ -77,6 +85,8 @@ Preferences &Preferences::operator=(Preferences &&rhs)
metaPressForAppLauncher = rhs.metaPressForAppLauncher;
metaHoldForBadges = rhs.metaHoldForBadges;
mouseSensitivity = rhs.mouseSensitivity;
parabolicSpread = rhs.parabolicSpread;
thicknessMarginInfluence = rhs.thicknessMarginInfluence;
screensDelay = rhs.screensDelay;
return (*this);
@ -93,6 +103,8 @@ bool Preferences::operator==(const Preferences &rhs) const
&& (metaPressForAppLauncher == rhs.metaPressForAppLauncher)
&& (metaHoldForBadges == rhs.metaHoldForBadges)
&& (mouseSensitivity == rhs.mouseSensitivity)
&& (parabolicSpread == rhs.parabolicSpread)
&& (thicknessMarginInfluence == rhs.thicknessMarginInfluence)
&& (screensDelay == rhs.screensDelay);
}
@ -112,6 +124,8 @@ bool Preferences::inDefaultValues() const
&& (metaPressForAppLauncher == METAPRESSFORAPPLAUNCHER)
&& (metaHoldForBadges == METAHOLDFORBADGES)
&& (mouseSensitivity == MOUSESENSITIVITY)
&& (parabolicSpread == PARABOLICSPREAD)
&& (thicknessMarginInfluence == THICKNESSMARGININFLUENCE)
&& (screensDelay == SCREENSDELAY);
}
@ -126,6 +140,8 @@ void Preferences::setToDefaults()
metaPressForAppLauncher = METAPRESSFORAPPLAUNCHER;
metaHoldForBadges = METAHOLDFORBADGES;
mouseSensitivity = MOUSESENSITIVITY;
parabolicSpread = PARABOLICSPREAD;
thicknessMarginInfluence = THICKNESSMARGININFLUENCE;
screensDelay = SCREENSDELAY;
}

View File

@ -26,7 +26,9 @@ public:
static const bool ISAVAILABLEGEOMETRYBROADCASTEDTOPLASMA = true;
static const bool METAPRESSFORAPPLAUNCHER = false;
static const bool METAHOLDFORBADGES = true;
static const int PARABOLICSPREAD = 3;
static const int SCREENSDELAY = 2500;
static const float THICKNESSMARGININFLUENCE;
static const Settings::MouseSensitivity MOUSESENSITIVITY = Settings::HighMouseSensitivity;
Preferences();
@ -41,7 +43,9 @@ public:
bool isAvailableGeometryBroadcastedToPlasma{ISAVAILABLEGEOMETRYBROADCASTEDTOPLASMA};
bool metaPressForAppLauncher{METAPRESSFORAPPLAUNCHER};
bool metaHoldForBadges{METAHOLDFORBADGES};
int parabolicSpread{PARABOLICSPREAD};
int screensDelay{SCREENSDELAY};
float thicknessMarginInfluence{THICKNESSMARGININFLUENCE};
QStringList contextMenuAlwaysActions{Data::ContextMenu::ACTIONSALWAYSVISIBLE};
Settings::MouseSensitivity mouseSensitivity{MOUSESENSITIVITY};

View File

@ -103,6 +103,12 @@ void Screen::init(const QString &screenId, const QString &serialized)
}
}
bool Screen::isScreensGroup() const
{
int sid = id.toInt();
return ((sid == ONALLSCREENSID) || (sid == ONALLSECONDARYSCREENSID));
}
QString Screen::serialize() const
{
QStringList result;

View File

@ -23,7 +23,11 @@ class Screen : public Generic
public:
static constexpr const char* SERIALIZESPLITTER = ":::";
static const int ONPRIMARYID = 0;
static const int ONALLSCREENSID = -100;
static const int ONALLSECONDARYSCREENSID = -101;
static constexpr const char* ONPRIMARYNAME = "{primary-screen}";
static constexpr const char* ONALLSCREENSNAME = "{all-screens}";
static constexpr const char* ONALLSECONDARYSCREENSNAME = "{all-secondary-screens}";
Screen();
Screen(Screen &&o);
@ -43,6 +47,8 @@ public:
bool operator==(const Screen &rhs) const;
bool operator!=(const Screen &rhs) const;
bool isScreensGroup() const;
void init(const QString &screenId, const QString &serialized);
QString serialize() const;

View File

@ -8,6 +8,8 @@
namespace Latte {
namespace Data {
const int View::ISCLONEDNULL = -1;
View::View()
: Generic()
{
@ -19,8 +21,10 @@ View::View(View &&o)
isMoveOrigin(o.isMoveOrigin),
isMoveDestination(o.isMoveDestination),
onPrimary(o.onPrimary),
isClonedFrom(o.isClonedFrom),
screen(o.screen),
screenEdgeMargin(o.screenEdgeMargin),
screensGroup(o.screensGroup),
maxLength(o.maxLength),
edge(o.edge),
alignment(o.alignment),
@ -40,8 +44,10 @@ View::View(const View &o)
isMoveOrigin(o.isMoveOrigin),
isMoveDestination(o.isMoveDestination),
onPrimary(o.onPrimary),
isClonedFrom(o.isClonedFrom),
screen(o.screen),
screenEdgeMargin(o.screenEdgeMargin),
screensGroup(o.screensGroup),
maxLength(o.maxLength),
edge(o.edge),
alignment(o.alignment),
@ -68,8 +74,10 @@ View &View::operator=(const View &rhs)
isMoveOrigin = rhs.isMoveOrigin;
isMoveDestination = rhs.isMoveDestination;
onPrimary = rhs.onPrimary;
isClonedFrom = rhs.isClonedFrom;
screen = rhs.screen;
screenEdgeMargin = rhs.screenEdgeMargin,
screenEdgeMargin = rhs.screenEdgeMargin;
screensGroup = rhs.screensGroup;
maxLength = rhs.maxLength;
edge = rhs.edge;
alignment = rhs.alignment;
@ -93,8 +101,10 @@ View &View::operator=(View &&rhs)
isMoveOrigin = rhs.isMoveOrigin;
isMoveDestination = rhs.isMoveDestination;
onPrimary = rhs.onPrimary;
isClonedFrom = rhs.isClonedFrom;
screen = rhs.screen;
screenEdgeMargin = rhs.screenEdgeMargin,
screenEdgeMargin = rhs.screenEdgeMargin;
screensGroup = rhs.screensGroup;
maxLength = rhs.maxLength;
edge = rhs.edge;
alignment = rhs.alignment;
@ -118,8 +128,10 @@ bool View::operator==(const View &rhs) const
//&& (isMoveOrigin == rhs.isMoveOrigin) /*Disabled because this is not needed in order to track view changes for saving*/
//&& (isMoveDestination == rhs.isMoveDestination) /*Disabled because this is not needed in order to track view changes for saving*/
&& (onPrimary == rhs.onPrimary)
&& (isClonedFrom == rhs.isClonedFrom)
&& (screen == rhs.screen)
&& (screenEdgeMargin == rhs.screenEdgeMargin)
&& (screensGroup == rhs.screensGroup)
&& (maxLength == rhs.maxLength)
&& (edge == rhs.edge)
&& (alignment == rhs.alignment)
@ -168,6 +180,21 @@ View::operator QString() const
}
result += " : ";
if (isCloned()) {
result += ("Cloned from:"+ isClonedFrom);
} else {
result += "Original";
}
result += " : ";
if (screensGroup == Latte::Types::SingleScreenGroup) {
result += onPrimary ? "Primary" : "Explicit";
} else if (screensGroup == Latte::Types::AllScreensGroup) {
result += "All Screens";
} else if (screensGroup == Latte::Types::AllSecondaryScreensGroup) {
result += "All Secondary Screens";
}
result += onPrimary ? "Primary" : "Explicit";
result += " : ";
result += QString::number(screen);
@ -212,6 +239,16 @@ bool View::isCreated() const
return m_state == IsCreated;
}
bool View::isOriginal() const
{
return !isCloned();
}
bool View::isCloned() const
{
return isClonedFrom != ISCLONEDNULL;
}
bool View::isValid() const
{
return m_state != IsInvalid;

View File

@ -32,6 +32,8 @@ public:
OriginFromLayout /*used from duplicate, copy, move view functions*/
};
static const int ISCLONEDNULL;
View();
View(View &&o);
View(const View &o);
@ -40,11 +42,13 @@ public:
//! View data
bool isActive{false};
bool onPrimary{true};
int isClonedFrom{ISCLONEDNULL};
int screen{Latte::ScreenPool::FIRSTSCREENID};
int screenEdgeMargin{0};
float maxLength{1.0};
Plasma::Types::Location edge{Plasma::Types::BottomEdge};
Latte::Types::Alignment alignment{Latte::Types::Center};
Latte::Types::ScreensGroup screensGroup{Latte::Types::SingleScreenGroup};
GenericTable<Data::Generic> subcontainments;
int errors{0};
@ -56,6 +60,8 @@ public:
bool isValid() const;
bool isCreated() const;
bool isOriginal() const;
bool isCloned() const;
bool hasViewTemplateOrigin() const;
bool hasLayoutOrigin() const;
bool hasSubContainment(const QString &subId) const;

View File

@ -90,6 +90,19 @@ ViewsTable ViewsTable::subtracted(const ViewsTable &rhs) const
return subtract;
}
ViewsTable ViewsTable::onlyOriginals() const
{
ViewsTable originals;
for(int i=0; i<m_list.count(); ++i) {
if (m_list[i].isOriginal()) {
originals << m_list[i];
}
}
return originals;
}
void ViewsTable::appendTemporaryView(const Data::View &view)
{
int maxTempId = 0;

View File

@ -38,6 +38,7 @@ public:
bool operator==(const ViewsTable &rhs) const;
bool operator!=(const ViewsTable &rhs) const;
ViewsTable subtracted(const ViewsTable &rhs) const;
ViewsTable onlyOriginals() const;
};
}

View File

@ -1,5 +1,6 @@
set(lattedock-app_SRCS
${lattedock-app_SRCS}
${CMAKE_CURRENT_SOURCE_DIR}/contextmenulayerquickitem.cpp
${CMAKE_CURRENT_SOURCE_DIR}/interfaces.cpp
PARENT_SCOPE
)

View File

@ -0,0 +1,515 @@
/*
SPDX-FileCopyrightText: 2022 Michail Vourlakos <mvourlakos@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "contextmenulayerquickitem.h"
// local
#include "../lattecorona.h"
#include "../layouts/storage.h"
#include "../view/view.h"
// Qt
#include <QMouseEvent>
#include <QVersionNumber>
#include <QLatin1String>
// KDE
#include <KAcceleratorManager>
#include <KActionCollection>
#include <KAuthorized>
#include <KLocalizedString>
// Plasma
#include <Plasma/Applet>
#include <Plasma/Containment>
#include <Plasma/ContainmentActions>
#include <Plasma/Corona>
#include <PlasmaQuick/AppletQuickItem>
namespace Latte {
ContextMenuLayerQuickItem::ContextMenuLayerQuickItem(QQuickItem *parent) :
QQuickItem(parent)
{
setAcceptedMouseButtons(Qt::AllButtons);
}
ContextMenuLayerQuickItem::~ContextMenuLayerQuickItem()
{
}
bool ContextMenuLayerQuickItem::menuIsShown() const
{
return m_contextMenu != nullptr;
}
QObject *ContextMenuLayerQuickItem::view() const
{
return m_latteView;
}
void ContextMenuLayerQuickItem::setView(QObject *view)
{
if (m_latteView == view) {
return;
}
m_latteView = qobject_cast<Latte::View *>(view);
emit viewChanged();
}
void ContextMenuLayerQuickItem::onMenuAboutToHide()
{
if (!m_latteView) {
return;
}
m_latteView->containment()->setStatus(m_lastContainmentStatus);
m_contextMenu = nullptr;
emit menuChanged();
}
QPoint ContextMenuLayerQuickItem::popUpRelevantToParent(const QRect &parentItem, const QRect popUpRect)
{
QPoint resultPoint;
if (!m_latteView) {
return resultPoint;
}
if (m_latteView->location() == Plasma::Types::TopEdge) {
resultPoint.setX(parentItem.left());
resultPoint.setY(parentItem.bottom());
} else if (m_latteView->location() == Plasma::Types::BottomEdge) {
resultPoint.setX(parentItem.left());
resultPoint.setY(parentItem.top() - popUpRect.height() - 1);
} else if (m_latteView->location() == Plasma::Types::LeftEdge) {
resultPoint.setX(parentItem.right());
resultPoint.setY(parentItem.top());
} else if (m_latteView->location() == Plasma::Types::RightEdge) {
resultPoint.setX(parentItem.left() - popUpRect.width());
resultPoint.setY(parentItem.top());
}
return resultPoint;
}
QPoint ContextMenuLayerQuickItem::popUpRelevantToGlobalPoint(const QRect &parentItem, const QRect popUpRect)
{
QPoint resultPoint;
if (!m_latteView) {
return resultPoint;
}
if (m_latteView->location() == Plasma::Types::TopEdge) {
resultPoint.setX(popUpRect.x());
resultPoint.setY(popUpRect.y() + 1);
} else if (m_latteView->location() == Plasma::Types::BottomEdge) {
resultPoint.setX(popUpRect.x());
resultPoint.setY(popUpRect.y() - popUpRect.height() - 1);
} else if (m_latteView->location() == Plasma::Types::LeftEdge) {
resultPoint.setX(popUpRect.x() + 1);
resultPoint.setY(popUpRect.y());
} else if (m_latteView->location() == Plasma::Types::RightEdge) {
resultPoint.setX(popUpRect.x() - popUpRect.width() - 1);
resultPoint.setY(popUpRect.y());
}
return resultPoint;
}
QPoint ContextMenuLayerQuickItem::popUpTopLeft(Plasma::Applet *applet, const QRect popUpRect)
{
PlasmaQuick::AppletQuickItem *ai = applet->property("_plasma_graphicObject").value<PlasmaQuick::AppletQuickItem *>();
QRect globalItemRect = m_latteView->absoluteGeometry();
if (ai && applet != m_latteView->containment()) {
QPointF appletGlobalTopLeft = ai->mapToGlobal(QPointF(ai->x(), ai->y()));
globalItemRect = QRect(appletGlobalTopLeft.x(), appletGlobalTopLeft.y(), ai->width(), ai->height());
}
int itemLength = (m_latteView->formFactor() == Plasma::Types::Horizontal ? globalItemRect.width() : globalItemRect.height());
int menuLength = (m_latteView->formFactor() == Plasma::Types::Horizontal ? popUpRect.width() : popUpRect.height());
if ((itemLength > menuLength)
|| (applet == m_latteView->containment())
|| (m_latteView && Layouts::Storage::self()->isSubContainment(m_latteView->corona(), applet)) ) {
return popUpRelevantToGlobalPoint(globalItemRect, popUpRect);
} else {
return popUpRelevantToParent(globalItemRect, popUpRect);
}
}
void ContextMenuLayerQuickItem::mouseReleaseEvent(QMouseEvent *event)
{
if (!event || !m_latteView) {
return;
}
event->setAccepted(m_latteView->containment()->containmentActions().contains(Plasma::ContainmentActions::eventToString(event)));
emit menuChanged();
}
void ContextMenuLayerQuickItem::mousePressEvent(QMouseEvent *event)
{
//qDebug() << "Step -1 ...";
if (!event || !m_latteView || !m_latteView->containment()) {
return;
}
//qDebug() << "Step 0...";
//even if the menu is executed synchronously, other events may be processed
//by the qml incubator when plasma is loading, so we need to guard there
if (m_contextMenu) {
//qDebug() << "Step 0.5 ...";
m_contextMenu->close();
m_contextMenu = nullptr;
return;
}
//qDebug() << "1 ...";
const QString trigger = Plasma::ContainmentActions::eventToString(event);
Plasma::ContainmentActions *plugin = m_latteView->containment()->containmentActions().value(trigger);
if (!plugin || plugin->contextualActions().isEmpty()) {
event->setAccepted(false);
return;
}
// the plugin can be a single action or a context menu
// Don't have an action list? execute as single action
// and set the event position as action data
if (plugin->contextualActions().length() == 1) {
QAction *action = plugin->contextualActions().at(0);
action->setData(event->pos());
action->trigger();
event->accept();
return;
}
//qDebug() << "2 ...";
//the plugin can be a single action or a context menu
//Don't have an action list? execute as single action
//and set the event position as action data
/*if (plugin->contextualActions().length() == 1) {
QAction *action = plugin->contextualActions().at(0);
action->setData(event->pos());
action->trigger();
event->accept();
return;
}*/
//FIXME: very inefficient appletAt() implementation
Plasma::Applet *applet = 0;
//! initialize the appletContainsMethod on the first right click
if (!m_appletContainsMethod.isValid()) {
updateAppletContainsMethod();
}
for (const Plasma::Applet *appletTemp : m_latteView->containment()->applets()) {
PlasmaQuick::AppletQuickItem *ai = appletTemp->property("_plasma_graphicObject").value<PlasmaQuick::AppletQuickItem *>();
bool appletContainsMouse = false;
if (m_appletContainsMethod.isValid()) {
QVariant retVal;
m_appletContainsMethod.invoke(m_appletContainsMethodItem, Qt::DirectConnection, Q_RETURN_ARG(QVariant, retVal)
, Q_ARG(QVariant, appletTemp->id()), Q_ARG(QVariant, event->pos()));
appletContainsMouse = retVal.toBool();
} else {
appletContainsMouse = ai->contains(ai->mapFromItem(this, event->pos()));
}
if (ai && ai->isVisible() && appletContainsMouse) {
applet = ai->applet();
break;
}
}
if (!applet) {
applet = m_latteView->containment();
}
//qDebug() << "3 ...";
QMenu *desktopMenu = new QMenu;
//this is a workaround where Qt now creates the menu widget
//in .exec before oxygen can polish it and set the following attribute
desktopMenu->setAttribute(Qt::WA_TranslucentBackground);
//end workaround
if (desktopMenu->winId()) {
desktopMenu->windowHandle()->setTransientParent(window());
}
desktopMenu->setAttribute(Qt::WA_DeleteOnClose);
m_contextMenu = desktopMenu;
emit menuChanged();
//end workaround
//!end of plasma official code(workaround)
//qDebug() << "5 ...";
emit m_latteView->containment()->contextualActionsAboutToShow();
if (applet && applet != m_latteView->containment()) {
//qDebug() << "5.3 ...";
emit applet->contextualActionsAboutToShow();
addAppletActions(desktopMenu, applet, event);
} else {
//qDebug() << "5.6 ...";
addContainmentActions(desktopMenu, event);
}
//!plasma official code
//this is a workaround where Qt will fail to realize a mouse has been released
// this happens if a window which does not accept focus spawns a new window that takes focus and X grab
// whilst the mouse is depressed
// https://bugreports.qt.io/browse/QTBUG-59044
// this causes the next click to go missing
//by releasing manually we avoid that situation
auto ungrabMouseHack = [this]() {
if (window() && window()->mouseGrabberItem()) {
window()->mouseGrabberItem()->ungrabMouse();
}
};
//post 5.8.0 QQuickWindow code is sendEvent(item, mouseEvent); item->grabMouse()
QTimer::singleShot(0, this, ungrabMouseHack);
//this is a workaround where Qt now creates the menu widget
//in .exec before oxygen can polish it and set the following attribute
desktopMenu->setAttribute(Qt::WA_TranslucentBackground);
//end workaround
QPoint globalPos = event->globalPos();
desktopMenu->adjustSize();
QRect popUpRect(globalPos.x(), globalPos.y(), desktopMenu->width(), desktopMenu->height());
if (applet) {
globalPos = popUpTopLeft(applet, popUpRect);
} else {
globalPos = popUpRelevantToGlobalPoint(QRect(0,0,0,0), popUpRect);
}
//qDebug() << "7...";
if (desktopMenu->isEmpty()) {
//qDebug() << "7.5 ...";
delete desktopMenu;
event->accept();
return;
}
// Bug 344205 keep panel visible while menu is open
m_lastContainmentStatus = m_latteView->containment()->status();
m_latteView->containment()->setStatus(Plasma::Types::RequiresAttentionStatus);
connect(desktopMenu, SIGNAL(aboutToHide()), this, SLOT(onMenuAboutToHide()));
KAcceleratorManager::manage(desktopMenu);
for (auto action : desktopMenu->actions()) {
if (action->menu()) {
connect(action->menu(), &QMenu::aboutToShow, desktopMenu, [action, desktopMenu] {
if (action->menu()->windowHandle()) {
// Need to add the transient parent otherwise Qt will create a new toplevel
action->menu()->windowHandle()->setTransientParent(desktopMenu->windowHandle());
}
});
}
}
//qDebug() << "8 ...";
desktopMenu->popup(globalPos);
event->setAccepted(true);
}
//! update the appletContainsPos method from Panel view
void ContextMenuLayerQuickItem::updateAppletContainsMethod()
{
if (!m_latteView) {
return;
}
for (QQuickItem *item : m_latteView->contentItem()->childItems()) {
if (auto *metaObject = item->metaObject()) {
// not using QMetaObject::invokeMethod to avoid warnings when calling
// this on applets that don't have it or other child items since this
// is pretty much trial and error.
// Also, "var" arguments are treated as QVariant in QMetaObject
int methodIndex = metaObject->indexOfMethod("appletContainsPos(QVariant,QVariant)");
if (methodIndex == -1) {
continue;
}
m_appletContainsMethod = metaObject->method(methodIndex);
m_appletContainsMethodItem = item;
}
}
}
void ContextMenuLayerQuickItem::addAppletActions(QMenu *desktopMenu, Plasma::Applet *applet, QEvent *event)
{
if (!m_latteView || !m_latteView->containment()) {
return;
}
desktopMenu->addSection(applet->pluginMetaData().name());
for (QAction *action : applet->contextualActions()) {
if (action) {
desktopMenu->addAction(action);
}
}
if (!applet->failedToLaunch()) {
QAction *runAssociatedApplication = applet->actions()->action(QStringLiteral("run associated application"));
if (runAssociatedApplication && runAssociatedApplication->isEnabled()) {
desktopMenu->addAction(runAssociatedApplication);
}
QAction *configureApplet = applet->actions()->action(QStringLiteral("configure"));
if (configureApplet && configureApplet->isEnabled()) {
desktopMenu->addAction(configureApplet);
}
QAction *appletAlternatives = applet->actions()->action(QStringLiteral("alternatives"));
if (appletAlternatives && appletAlternatives->isEnabled() && m_latteView->containment()->isUserConfiguring()) {
desktopMenu->addAction(appletAlternatives);
}
}
QAction *containmentAction = desktopMenu->menuAction();
containmentAction->setText(i18nc("%1 is the name of the containment", "%1 Options", m_latteView->containment()->title()));
if (desktopMenu->actions().count()>1) { /*take into account the Applet Name Section*/
addContainmentActions(containmentAction->menu(), event);
}
if (!containmentAction->menu()->isEmpty()) {
int enabled = 0;
//count number of real actions
QListIterator<QAction *> actionsIt(containmentAction->menu()->actions());
while (enabled < 3 && actionsIt.hasNext()) {
QAction *action = actionsIt.next();
if (action->isVisible() && !action->isSeparator()) {
++enabled;
}
}
desktopMenu->addSeparator();
if (enabled) {
//if there is only one, don't create a submenu
// if (enabled < 2) {
for (QAction *action : containmentAction->menu()->actions()) {
if (action && action->isVisible()) {
desktopMenu->addAction(action);
}
}
// } else {
// desktopMenu->addMenu(containmentMenu);
// }
}
}
if (m_latteView->containment()->immutability() == Plasma::Types::Mutable &&
(m_latteView->containment()->containmentType() != Plasma::Types::PanelContainment || m_latteView->containment()->isUserConfiguring())) {
QAction *closeApplet = applet->actions()->action(QStringLiteral("remove"));
//qDebug() << "checking for removal" << closeApplet;
if (closeApplet) {
if (!desktopMenu->isEmpty()) {
desktopMenu->addSeparator();
}
//qDebug() << "adding close action" << closeApplet->isEnabled() << closeApplet->isVisible();
desktopMenu->addAction(closeApplet);
}
}
}
void ContextMenuLayerQuickItem::addContainmentActions(QMenu *desktopMenu, QEvent *event)
{
if (!m_latteView || !m_latteView->containment()) {
return;
}
if (m_latteView->containment()->corona()->immutability() != Plasma::Types::Mutable &&
!KAuthorized::authorizeAction(QStringLiteral("plasma/containment_actions"))) {
//qDebug() << "immutability";
return;
}
//this is what ContainmentPrivate::prepareContainmentActions was
const QString trigger = Plasma::ContainmentActions::eventToString(event);
//"RightButton;NoModifier"
Plasma::ContainmentActions *plugin = m_latteView->containment()->containmentActions().value(trigger);
if (!plugin) {
return;
}
if (plugin->containment() != m_latteView->containment()) {
plugin->setContainment(m_latteView->containment());
// now configure it
KConfigGroup cfg(m_latteView->containment()->corona()->config(), "ActionPlugins");
cfg = KConfigGroup(&cfg, QString::number(m_latteView->containment()->containmentType()));
KConfigGroup pluginConfig = KConfigGroup(&cfg, trigger);
plugin->restore(pluginConfig);
}
QList<QAction *> actions = plugin->contextualActions();
/* for (const QAction *act : actions) {
if (act->menu()) {
//this is a workaround where Qt now creates the menu widget
//in .exec before oxygen can polish it and set the following attribute
act->menu()->setAttribute(Qt::WA_TranslucentBackground);
//end workaround
if (act->menu()->winId()) {
act->menu()->windowHandle()->setTransientParent(m_latteView);
}
}
}*/
desktopMenu->addActions(actions);
}
Plasma::Containment *ContextMenuLayerQuickItem::containmentById(uint id)
{
if (!m_latteView) {
return nullptr;
}
for (const auto containment : m_latteView->corona()->containments()) {
if (id == containment->id()) {
return containment;
}
}
return nullptr;
}
}

View File

@ -1,10 +1,10 @@
/*
SPDX-FileCopyrightText: 2018 Michail Vourlakos <mvourlakos@gmail.com>
SPDX-FileCopyrightText: 2022 Michail Vourlakos <mvourlakos@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef CONTEXTMENU_H
#define CONTEXTMENU_H
#ifndef CONTEXTMENULAYERQUICKITEM_H
#define CONTEXTMENULAYERQUICKITEM_H
// Qt
#include <QEvent>
@ -16,9 +16,13 @@
#include <QMouseEvent>
#include <QObject>
// Plasma
#include <Plasma>
namespace Plasma {
class Applet;
class Containment;
class Types;
}
namespace Latte {
@ -26,26 +30,32 @@ class View;
}
namespace Latte {
namespace ViewPart {
class ContextMenu : public QObject
class ContextMenuLayerQuickItem : public QQuickItem
{
Q_OBJECT
Q_PROPERTY(bool menuIsShown READ menuIsShown NOTIFY menuChanged)
Q_PROPERTY(QObject *view READ view WRITE setView NOTIFY viewChanged)
public:
ContextMenu(Latte::View *view);
~ContextMenu() override;
ContextMenuLayerQuickItem(QQuickItem *parent = nullptr);
~ContextMenuLayerQuickItem() override;
QMenu *menu();
QObject *view() const;
void setView(QObject *view);
bool mousePressEvent(QMouseEvent *event);
bool mousePressEventForContainmentMenu(QQuickView *view, QMouseEvent *event);
bool menuIsShown() const;
signals:
void menuChanged();
void viewChanged();
protected:
void mousePressEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
private slots:
void menuAboutToHide();
void onMenuAboutToHide();
private:
void addAppletActions(QMenu *desktopMenu, Plasma::Applet *applet, QEvent *event);
@ -61,16 +71,17 @@ private:
private:
Plasma::Types::ItemStatus m_lastContainmentStatus;
QPointer<QMenu> m_contextMenu;
QMetaMethod m_appletContainsMethod;
QQuickItem *m_appletContainsMethodItem{nullptr};
Latte::View *m_latteView;
Latte::View *m_latteView{nullptr};
friend class Latte::View;
};
}
}
#endif // DOCKMENUMANAGER_H

View File

@ -29,7 +29,7 @@
#include <KArchive/KZip>
#include <KArchive/KArchiveEntry>
#include <KArchive/KArchiveDirectory>
#include <KNewStuff3/KNS3/DownloadDialog>
#include <KNewStuff3/KNS3/QtQuickDialogWrapper>
namespace Latte {
namespace Indicator {
@ -115,10 +115,10 @@ void Factory::reload(const QString &indicatorPath)
QString pluginChangedId;
if (!indicatorPath.isEmpty() && indicatorPath != "." && indicatorPath != "..") {
QString metadataFile = indicatorPath + "/metadata.desktop";
QString metadataFile = metadataFileAbsolutePath(indicatorPath);
if(QFileInfo(metadataFile).exists()) {
KPluginMetaData metadata = KPluginMetaData::fromDesktopFile(metadataFile);
KPluginMetaData metadata = KPluginMetaData(metadataFile);
if (metadataAreValid(metadata)) {
pluginChangedId = metadata.pluginId();
@ -244,7 +244,7 @@ bool Factory::metadataAreValid(KPluginMetaData &metadata)
bool Factory::metadataAreValid(QString &file)
{
if (QFileInfo(file).exists()) {
KPluginMetaData metadata = KPluginMetaData::fromDesktopFile(file);
KPluginMetaData metadata(file);
return metadata.isValid();
}
@ -260,6 +260,23 @@ QString Factory::uiPath(QString pluginName) const
return m_pluginUiPaths[pluginName];
}
QString Factory::metadataFileAbsolutePath(const QString &directoryPath)
{
QString metadataFile = directoryPath + "/metadata.json";
if(QFileInfo(metadataFile).exists()) {
return metadataFile;
}
metadataFile = directoryPath + "/metadata.desktop";
if(QFileInfo(metadataFile).exists()) {
return metadataFile;
}
return QString();
}
Latte::ImportExport::State Factory::importIndicatorFile(QString compressedFile)
{
auto showNotificationError = []() {
@ -303,7 +320,7 @@ Latte::ImportExport::State Factory::importIndicatorFile(QString compressedFile)
//metadata file
QString packagePath = archiveTempDir.path();
QString metadataFile = archiveTempDir.path() + "/metadata.desktop";
QString metadataFile = metadataFileAbsolutePath(archiveTempDir.path());
if (!QFileInfo(metadataFile).exists()){
QDirIterator iter(archiveTempDir.path(), QDir::Dirs | QDir::NoDotAndDotDot);
@ -311,7 +328,7 @@ Latte::ImportExport::State Factory::importIndicatorFile(QString compressedFile)
while(iter.hasNext() ) {
QString currentPath = iter.next();
QString tempMetadata = currentPath + "/metadata.desktop";
QString tempMetadata = metadataFileAbsolutePath(currentPath);
if (QFileInfo(tempMetadata).exists()) {
metadataFile = tempMetadata;
@ -320,7 +337,7 @@ Latte::ImportExport::State Factory::importIndicatorFile(QString compressedFile)
}
}
KPluginMetaData metadata = KPluginMetaData::fromDesktopFile(metadataFile);
KPluginMetaData metadata = KPluginMetaData(metadataFile);
if (metadataAreValid(metadata)) {
QStringList standardPaths = Latte::Layouts::Importer::standardPaths();
@ -387,8 +404,7 @@ void Factory::removeIndicator(QString id)
void Factory::downloadIndicator()
{
KNS3::DownloadDialog dialog(QStringLiteral("latte-indicators.knsrc"), m_parentWidget);
KNS3::QtQuickDialogWrapper dialog(QStringLiteral("latte-indicators.knsrc"), m_parentWidget);
dialog.exec();
}

View File

@ -42,6 +42,8 @@ public:
QString uiPath(QString pluginName) const;
static QString metadataFileAbsolutePath(const QString &directoryPath);
//! metadata record
static bool metadataAreValid(KPluginMetaData &metadata);
//! metadata file

View File

@ -80,12 +80,8 @@ void InfoView::init()
KDeclarative::KDeclarative kdeclarative;
kdeclarative.setDeclarativeEngine(engine());
kdeclarative.setTranslationDomain(QStringLiteral("latte-dock"));
#if KF5_VERSION_MINOR >= 45
kdeclarative.setupContext();
kdeclarative.setupEngine(engine());
#else
kdeclarative.setupBindings();
#endif
auto source = QUrl::fromLocalFile(m_corona->kPackage().filePath("infoviewui"));
setSource(source);

View File

@ -32,7 +32,7 @@ class InfoView : public QQuickView
Q_PROPERTY(Plasma::FrameSvg::EnabledBorders enabledBorders READ enabledBorders NOTIFY enabledBordersChanged)
public:
InfoView(Latte::Corona *corona, QString message, QScreen *screen = qGuiApp->primaryScreen(), QWindow *parent = nullptr);
InfoView(Latte::Corona *corona, QString message, QScreen *screen, QWindow *parent = nullptr);
~InfoView() override;
QString validTitle() const;

View File

@ -1,11 +1,13 @@
[KNewStuff3]
Name=Latte Indicators
Name[ar]=مؤشرات لاتيه
Name[az]=Latte İndikatorları
Name[ca]=Indicadors del Latte
Name[ca@valencia]=Indicadors del Latte
Name[ca@valencia]=Indicadors de Latte
Name[cs]=Ukazatele Latte
Name[el]=Δείκτες Latte
Name[en_GB]=Latte Indicators
Name[eo]=Latte Indikiloj
Name[es]=Indicadores de Latte
Name[et]=Latte indikaatorid
Name[eu]=Latte adierazleak
@ -15,6 +17,8 @@ Name[gl]=Indicadores de Latte
Name[hsb]=Latte pokazowaki
Name[id]=Indikator Latte
Name[it]=Indicatori Latte
Name[ja]=Latte インジケータ
Name[ka]=Latte -ის ინდიკატორები
Name[ko]=Latte 표시기
Name[lt]=Latte indikatoriai
Name[nl]=Indicatoren van Latte
@ -26,6 +30,7 @@ Name[ru]=Индикаторы Latte
Name[sk]=Indikátory Latte
Name[sl]=Kazalniki Latte
Name[sv]=Latte indikatorer
Name[tr]=Latte Göstergeleri
Name[uk]=Індикатори Латте
Name[x-test]=xxLatte Indicatorsxx
Name[zh_CN]=Latte 指示器
@ -34,5 +39,5 @@ Name[zh_TW]=Latte 指示器
ProvidersUrl=https://autoconfig.kde.org/ocs/providers.xml
Categories=Latte Indicators
StandardResource=tmp
InstallationCommand=kpackagetool5 --install %f --type Latte/Indicator
UninstallCommand=kpackagetool5 --remove %f --type Latte/Indicator
Uncompress=kpackage
KPackageType=Latte/Indicator

View File

@ -3,11 +3,12 @@ Name=Latte Layouts
Name[ar]=مخطّطات لاتيه
Name[az]=Latte Maketləri
Name[ca]=Disposicions del Latte
Name[ca@valencia]=Disposicions del Latte
Name[cs]=Rozložení Latte
Name[ca@valencia]=Disposicions de Latte
Name[cs]=Rozvržení Latte
Name[de]=Latte-Profile
Name[el]=Προφίλ Latte
Name[en_GB]=Latte Layouts
Name[eo]=Latteaj Aranĝoj
Name[es]=Distribuciones de Latte
Name[et]=Latte paigutused
Name[eu]=Latte antolamenduak
@ -17,6 +18,8 @@ Name[gl]=Disposicións de Latte
Name[hsb]=Latte layouty
Name[id]=Tataletak Latte
Name[it]=Disposizioni di Latte
Name[ja]=Latte レイアウト
Name[ka]=Latte -ის განლაგებები
Name[ko]=Latte 레이아웃
Name[lt]=Latte išdėstymai
Name[nl]=Latte-indelingen
@ -28,10 +31,11 @@ Name[ru]=Макеты Latte
Name[sk]=Rozloženia Latte
Name[sl]=Postavitve Latte
Name[sv]=Latte layouter
Name[tr]=Latte Yerleşimleri
Name[uk]=Компонування Латте
Name[x-test]=xxLatte Layoutsxx
Name[zh_CN]=Latte 布局
Name[zh_TW]=Latte 版面
Name[zh_TW]=Latte 佈局
ProvidersUrl=https://autoconfig.kde.org/ocs/providers.xml
Categories=Latte Layouts

View File

@ -16,6 +16,7 @@
#include "data/generictable.h"
#include "data/layouticondata.h"
#include "declarativeimports/interfaces.h"
#include "declarativeimports/contextmenulayerquickitem.h"
#include "indicator/factory.h"
#include "layout/abstractlayout.h"
#include "layout/centrallayout.h"
@ -32,6 +33,7 @@
#include "plasma/extended/theme.h"
#include "settings/universalsettings.h"
#include "templates/templatesmanager.h"
#include "view/originalview.h"
#include "view/view.h"
#include "view/settings/viewsettingsfactory.h"
#include "view/windowstracker/windowstracker.h"
@ -206,6 +208,10 @@ void Corona::onAboutToQuit()
cleanConfig();
}
if (m_layoutsManager->memoryUsage() == Latte::MemoryUsage::MultipleLayouts) {
m_layoutsManager->importer()->setMultipleLayoutsStatus(Latte::MultipleLayouts::Paused);
}
qDebug() << "Latte Corona - unload: containments ...";
m_layoutsManager->unload();
}
@ -220,10 +226,9 @@ void Corona::load()
m_templatesManager->init();
m_layoutsManager->init();
connect(this, &Corona::availableScreenRectChangedFrom, this, &Plasma::Corona::availableScreenRectChanged);
connect(this, &Corona::availableScreenRegionChangedFrom, this, &Plasma::Corona::availableScreenRegionChanged);
connect(qGuiApp, &QGuiApplication::primaryScreenChanged, this, &Corona::primaryOutputChanged, Qt::UniqueConnection);
connect(m_screenPool, &ScreenPool::primaryPoolChanged, this, &Corona::screenCountChanged);
connect(this, &Corona::availableScreenRectChangedFrom, this, &Plasma::Corona::availableScreenRectChanged, Qt::UniqueConnection);
connect(this, &Corona::availableScreenRegionChangedFrom, this, &Plasma::Corona::availableScreenRegionChanged, Qt::UniqueConnection);
connect(m_screenPool, &ScreenPool::primaryScreenChanged, this, &Corona::onScreenCountChanged, Qt::UniqueConnection);
QString loadLayoutName = "";
@ -265,7 +270,7 @@ void Corona::load()
//! load screens signals such screenGeometryChanged in order to support
//! plasmoid.screenGeometry properly
for (QScreen *screen : qGuiApp->screens()) {
addOutput(screen);
onScreenAdded(screen);
}
connect(m_layoutsManager->synchronizer(), &Layouts::Synchronizer::initializationFinished, [this]() {
@ -279,8 +284,8 @@ void Corona::load()
m_inStartup = false;
connect(qGuiApp, &QGuiApplication::screenAdded, this, &Corona::addOutput, Qt::UniqueConnection);
connect(qGuiApp, &QGuiApplication::screenRemoved, this, &Corona::screenRemoved, Qt::UniqueConnection);
connect(qGuiApp, &QGuiApplication::screenAdded, this, &Corona::onScreenAdded, Qt::UniqueConnection);
connect(qGuiApp, &QGuiApplication::screenRemoved, this, &Corona::onScreenRemoved, Qt::UniqueConnection);
}
}
@ -328,7 +333,7 @@ void Corona::setupWaylandIntegration()
}
});
#if KF5_VERSION_MINOR >= 52
QObject::connect(registry, &KWayland::Client::Registry::plasmaVirtualDesktopManagementAnnounced,
[this, registry] (quint32 name, quint32 version) {
KWayland::Client::PlasmaVirtualDesktopManagement *vdm = registry->createPlasmaVirtualDesktopManagement(name, version, this);
@ -339,7 +344,7 @@ void Corona::setupWaylandIntegration()
wI->initVirtualDesktopManagement(vdm);
}
});
#endif
registry->setup();
connection->roundtrip();
@ -489,7 +494,7 @@ int Corona::numScreens() const
QRect Corona::screenGeometry(int id) const
{
const auto screens = qGuiApp->screens();
const QScreen *screen{qGuiApp->primaryScreen()};
const QScreen *screen{m_screenPool->primaryScreen()};
QString screenName;
@ -583,7 +588,9 @@ QRegion Corona::availableScreenRegionWithCriteria(int id,
bool allEdges = ignoreEdges.isEmpty();
for (const auto *view : views) {
if (view && view->containment() && view->screen() == screen
bool inDesktopOffScreenStartup = desktopUse && view && view->positioner() && view->positioner()->isOffScreen();
if (view && view->containment() && view->screen() == screen && !inDesktopOffScreenStartup
&& ((allEdges || !ignoreEdges.contains(view->location()))
&& (view->visibility() && !ignoreModes.contains(view->visibility()->mode())))) {
int realThickness = view->normalThickness();
@ -606,11 +613,11 @@ QRegion Corona::availableScreenRegionWithCriteria(int id,
case Latte::Types::Center:
case Latte::Types::Justify:
x = (view->geometry().center().x() - w/2) + offsetW;
x = (view->geometry().center().x() - w/2) + 1 + offsetW;
break;
case Latte::Types::Right:
x = view->geometry().right() - w - offsetW;
x = view->geometry().right() + 1 - w - offsetW;
break;
}
}
@ -630,7 +637,7 @@ QRegion Corona::availableScreenRegionWithCriteria(int id,
case Latte::Types::Center:
case Latte::Types::Justify:
y = (view->geometry().center().y() - h/2) + offsetH;
y = (view->geometry().center().y() - h/2) + 1 + offsetH;
break;
case Latte::Types::Bottom:
@ -785,7 +792,9 @@ QRect Corona::availableScreenRectWithCriteria(int id,
bool allEdges = ignoreEdges.isEmpty();
for (const auto *view : views) {
if (view && view->containment() && view->screen() == screen
bool inDesktopOffScreenStartup = desktopUse && view && view->positioner() && view->positioner()->isOffScreen();
if (view && view->containment() && view->screen() == screen && !inDesktopOffScreenStartup
&& ((allEdges || !ignoreEdges.contains(view->location()))
&& (view->visibility() && !ignoreModes.contains(view->visibility()->mode())))) {
@ -842,7 +851,7 @@ QRect Corona::availableScreenRectWithCriteria(int id,
return available;
}
void Corona::addOutput(QScreen *screen)
void Corona::onScreenAdded(QScreen *screen)
{
Q_ASSERT(screen);
@ -852,35 +861,42 @@ void Corona::addOutput(QScreen *screen)
m_screenPool->insertScreenMapping(screen->name());
}
connect(screen, &QScreen::geometryChanged, this, [ = ]() {
const int id = m_screenPool->id(screen->name());
if (id >= 0) {
emit screenGeometryChanged(id);
emit availableScreenRegionChanged();
emit availableScreenRectChanged();
}
});
connect(screen, &QScreen::geometryChanged, this, &Corona::onScreenGeometryChanged);
emit availableScreenRectChanged();
emit screenAdded(m_screenPool->id(screen->name()));
screenCountChanged();
onScreenCountChanged();
}
void Corona::primaryOutputChanged()
void Corona::onScreenRemoved(QScreen *screen)
{
disconnect(screen, &QScreen::geometryChanged, this, &Corona::onScreenGeometryChanged);
onScreenCountChanged();
}
void Corona::onScreenCountChanged()
{
m_viewsScreenSyncTimer.start();
}
void Corona::screenRemoved(QScreen *screen)
void Corona::onScreenGeometryChanged(const QRect &geometry)
{
screenCountChanged();
}
Q_UNUSED(geometry);
void Corona::screenCountChanged()
{
m_viewsScreenSyncTimer.start();
QScreen *screen = qobject_cast<QScreen *>(sender());
if (!screen) {
return;
}
const int id = m_screenPool->id(screen->name());
if (id >= 0) {
emit screenGeometryChanged(id);
emit availableScreenRegionChanged();
emit availableScreenRectChanged();
}
}
//! the central functions that updates loading/unloading latteviews
@ -892,7 +908,7 @@ void Corona::syncLatteViewsToScreens()
int Corona::primaryScreenId() const
{
return m_screenPool->id(qGuiApp->primaryScreen()->name());
return m_screenPool->primaryScreenId();
}
void Corona::quitApplication()
@ -1188,9 +1204,25 @@ QStringList Corona::contextMenuData(const uint &containmentId)
}
data << layoutsmenu.join(";;");
data << QString::number((int)viewType); //Selected View type
data << (view ? view->layout()->name() : QString()); //Selected View layout*/
QStringList viewtype;
viewtype << QString::number((int)viewType); //Selected View type
if (view && view->isOriginal()) { /*View*/
auto originalview = qobject_cast<Latte::OriginalView *>(view);
viewtype << "0"; //original view
viewtype << QString::number(originalview->clonesCount());
} else if (view && view->isCloned()) {
viewtype << "1"; //cloned view
viewtype << "0"; //has no clones
} else {
viewtype << "0"; //original view
viewtype << "0"; //has no clones
}
data << viewtype.join(";;");
return data;
}
@ -1243,7 +1275,14 @@ void Corona::moveViewToLayout(const uint &containmentId, const QString &layoutNa
{
auto view = m_layoutsManager->synchronizer()->viewForContainment((int)containmentId);
if (view && !layoutName.isEmpty() && view->layout()->name() != layoutName) {
view->positioner()->setNextLocation(layoutName, "", Plasma::Types::Floating, Latte::Types::NoneAlignment);
Latte::Types::ScreensGroup screensgroup{Latte::Types::SingleScreenGroup};
if (view->isOriginal()) {
auto originalview = qobject_cast<Latte::OriginalView *>(view);
screensgroup = originalview->screensGroup();
}
view->positioner()->setNextLocation(layoutName, screensgroup, "", Plasma::Types::Floating, Latte::Types::NoneAlignment);
}
}
@ -1300,18 +1339,7 @@ inline void Corona::qmlRegisterTypes() const
qmlRegisterType<Latte::BackgroundTracker>("org.kde.latte.private.app", 0, 1, "BackgroundTracker");
qmlRegisterType<Latte::Interfaces>("org.kde.latte.private.app", 0, 1, "Interfaces");
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
qmlRegisterType<QScreen>();
qmlRegisterType<Latte::View>();
qmlRegisterType<Latte::ViewPart::WindowsTracker>();
qmlRegisterType<Latte::ViewPart::TrackerPart::CurrentScreenTracker>();
qmlRegisterType<Latte::ViewPart::TrackerPart::AllScreensTracker>();
qmlRegisterType<Latte::WindowSystem::SchemeColors>();
qmlRegisterType<Latte::WindowSystem::Tracker::LastActiveWindow>();
qmlRegisterType<Latte::Types>();
#else
qmlRegisterType<Latte::ContextMenuLayerQuickItem>("org.kde.latte.private.app", 0, 1, "ContextMenuLayer");
qmlRegisterAnonymousType<QScreen>("latte-dock", 1);
qmlRegisterAnonymousType<Latte::View>("latte-dock", 1);
qmlRegisterAnonymousType<Latte::ViewPart::WindowsTracker>("latte-dock", 1);
@ -1320,7 +1348,7 @@ inline void Corona::qmlRegisterTypes() const
qmlRegisterAnonymousType<Latte::WindowSystem::SchemeColors>("latte-dock", 1);
qmlRegisterAnonymousType<Latte::WindowSystem::Tracker::LastActiveWindow>("latte-dock", 1);
qmlRegisterAnonymousType<Latte::Types>("latte-dock", 1);
#endif
}
}

View File

@ -189,10 +189,10 @@ private slots:
void onAboutToQuit();
void addOutput(QScreen *screen);
void primaryOutputChanged();
void screenRemoved(QScreen *screen);
void screenCountChanged();
void onScreenAdded(QScreen *screen);
void onScreenRemoved(QScreen *screen);
void onScreenCountChanged();
void onScreenGeometryChanged(const QRect &geometry);
void syncLatteViewsToScreens();
private:

View File

@ -9,6 +9,7 @@ Name[da]=Latte-dok
Name[de]=Latte-Dock
Name[el]=Latte Dock
Name[en_GB]=Latte Dock
Name[eo]=Latte Doko
Name[es]=Latte Dock
Name[et]=Latte dokk
Name[eu]=Latte Dock
@ -29,6 +30,7 @@ Name[ru]=Latte Dock
Name[sk]=Dok Latte
Name[sl]=Latte Dock
Name[sv]=Latte dockningsfönster
Name[tr]=Latte Rıhtım
Name[uk]=Панель Латте
Name[x-test]=xxLatte Dockxx
Name[zh_CN]=Latte 停靠栏
@ -43,6 +45,7 @@ Comment[da]=Latte-dok
Comment[de]=Latte-Dock
Comment[el]=Διαχειριστής εργασιών Latte
Comment[en_GB]=Latte Dock
Comment[eo]=Latte Doko
Comment[es]=Latte Dock
Comment[et]=Latte dokk
Comment[eu]=Latte Dock
@ -63,6 +66,7 @@ Comment[ru]=Latte Dock
Comment[sk]=Dok Latte
Comment[sl]=Latte Dock
Comment[sv]=Latte dockningsfönster
Comment[tr]=Latte Rıhtım
Comment[uk]=Панель Латте
Comment[x-test]=xxLatte Dockxx
Comment[zh_CN]=Latte 停靠栏
@ -71,6 +75,7 @@ IconName=latte-dock
[Event/import-done]
Name=Imported successfully
Name[ar]=استوردتُ بنجاح
Name[az]=Müvəffəqiyyətlə İdxal Olundu
Name[ca]=S'ha importat amb èxit
Name[ca@valencia]=S'ha importat amb èxit
@ -78,6 +83,7 @@ Name[cs]=Importováno úspěšně
Name[de]=Erfolgreich importiert
Name[el]=Επιτυχής εισαγωγή
Name[en_GB]=Imported successfully
Name[eo]=Importita sukcese
Name[es]=Importada exitosamente
Name[et]=Imporditi edukalt
Name[eu]=Inportatze arrakastatsua
@ -87,6 +93,8 @@ Name[gl]=Importouse correctamente
Name[hsb]=Wuspěšnje importował
Name[id]=Berhasil diimpor
Name[it]=Importata con successo
Name[ja]=インポートに成功しました
Name[ka]=შემოტანა წარმატებულია
Name[ko]=성공적으로 가져왔습니다
Name[lt]=Sėkmingai importuota
Name[nl]=Met succes geïmporteerd
@ -107,22 +115,26 @@ Action=Popup
[Event/import-fail]
Name=Failed to import
Name[ar]=فشل استيراد
Name[az]=İdxal baş tutmadı
Name[ca]=Ha fallat en importar
Name[ca@valencia]=Ha fallat en importar
Name[ca@valencia]=No s'ha pogut importar
Name[cs]=Nepodařilo se importovat
Name[de]=Importieren fehlgeschlagen
Name[el]=Αποτυχία εισαγωγής
Name[en_GB]=Failed to import
Name[eo]=Malsukcesis importi
Name[es]=Error al importar
Name[et]=Importimine nurjus
Name[eu]=Huts egin du inportatzea
Name[fi]=Tuonti epäonnistui
Name[fr]=Échec de l'importation
Name[gl]=Non se puido importar
Name[gl]=Non foi posíbel importar
Name[hsb]=Njemóžach importować
Name[id]=Gagal mengimpor
Name[it]=Impossibile importare
Name[ja]=インポートに失敗しました
Name[ka]=შემოტანის შეცდომა
Name[ko]=가져오지 못했습니다
Name[lt]=Nepavyko importuoti
Name[nl]=Importeren is mislukt
@ -143,6 +155,7 @@ Action=Popup
[Event/export-done]
Name=Exported successfully
Name[ar]=صدّرتُ بنجاح
Name[az]=Müvəffəqiyyətlə ixrac olundu
Name[ca]=S'ha exportat amb èxit
Name[ca@valencia]=S'ha exportat amb èxit
@ -150,6 +163,7 @@ Name[cs]=Exportováno úspěšně
Name[de]=Erfolgreich exportiert
Name[el]=Επιτυχής εξαγωγή
Name[en_GB]=Exported successfully
Name[eo]=Sukcese eksportita
Name[es]=Exportada exitosamente
Name[et]=Eksporditi edukalt
Name[eu]=Esportatze arrakastatsua
@ -159,6 +173,8 @@ Name[gl]=Exportouse correctamente
Name[hsb]=Wuspěšnje eksportował
Name[id]=Berhasil diekspor
Name[it]=Esportata correttamente
Name[ja]=エクスポートに成功しました
Name[ka]=გატანა წარმატებულია
Name[ko]=성공적으로 내보냈습니다
Name[lt]=Sėkmingai eksportuota
Name[nl]=Met succes geëxporteerd
@ -179,22 +195,27 @@ Action=Popup
[Event/export-fail]
Name=Failed to export
Name[ar]=فشل تصدير
Name[az]=İxrac baş tutmadı
Name[ca]=Ha fallat en exportar
Name[ca@valencia]=Ha fallat en exportar
Name[ca@valencia]=No s'ha pogut exportar
Name[cs]=Export selhal
Name[de]=Exportieren fehlgeschlagen
Name[el]=Αποτυχία εξαγωγής
Name[en_GB]=Failed to export
Name[eo]=Malsukcesis eksporti
Name[es]=Error al exportar
Name[et]=Eksportimine nurjus
Name[eu]=Huts egin du esportatzea
Name[fi]=Vienti epäonnistui
Name[fr]=Exportation impossible
Name[gl]=Non se puido exportar
Name[gl]=Non foi posíbel exportar
Name[hsb]=Njemóžach eksportować
Name[ia]=Falleva a exportar
Name[id]=Gagal mengekspor
Name[it]=Impossibile esportare
Name[ja]=エクスポートに失敗しました
Name[ka]=გატანის შეცდომა
Name[ko]=내보내지 못했습니다
Name[lt]=Nepavyko eksportuoti
Name[nl]=Exporteren is mislukt
@ -215,6 +236,7 @@ Action=Popup
[Event/remove-done]
Name=Removed successfully
Name[ar]=استوردتُ بنجاح
Name[az]=Müvəffəqiyyətlə silindi
Name[ca]=S'ha eliminat amb èxit
Name[ca@valencia]=S'ha eliminat amb èxit
@ -222,6 +244,7 @@ Name[cs]=Úspěšně odstraněno
Name[de]=Erfolgreich entfernt
Name[el]=Επιτυχής αφαίρεση
Name[en_GB]=Removed successfully
Name[eo]=Forigita sukcese
Name[es]=Eliminada exitosamente
Name[et]=Eemaldati edukalt
Name[eu]=Ezabatze arrakastatsua
@ -231,6 +254,8 @@ Name[gl]=Retirouse correctamente
Name[hsb]=Wuspěšnje wumazał
Name[id]=Berhasil dihapus
Name[it]=Rimossa con successo
Name[ja]=削除に成功しました
Name[ka]=წაშლა წარმატებულია
Name[ko]=성공적으로 삭제했습니다
Name[lt]=Sėkmingai pašalinta
Name[nl]=Met succes verwijderd
@ -251,23 +276,27 @@ Action=Popup
[Event/remove-fail]
Name=Failed to remove
Name[ar]=فشلت إزالة
Name[az]=Silinmə alınmadı
Name[ca]=Ha fallat en eliminar
Name[ca@valencia]=Ha fallat en eliminar
Name[ca@valencia]=No s'ha pogut eliminar
Name[cs]=Selhalo odstranění
Name[de]=Entfernen fehlgeschlagen
Name[el]=Αποτυχία αφαίρεσης
Name[en_GB]=Failed to remove
Name[eo]=Malsukcesis forigi
Name[es]=Error al eliminar
Name[et]=Eemaldamine nurjus
Name[eu]=Huts egin du ezabatzea
Name[fi]=Poistaminen epäonnistui
Name[fr]=Échec de la suppression
Name[gl]=Non se puido retirar
Name[gl]=Non foi posíbel retirar
Name[hsb]=Njemóžach wumazać
Name[ia]=Il falleva a remover
Name[id]=Gagal menghapus
Name[it]=Impossibile rimuovere
Name[ja]=削除に失敗しました
Name[ka]=წაშლის შეცდომა
Name[ko]=삭제하지 못했습니다
Name[lt]=Nepavyko pašalinti
Name[nl]=Verwijderen is mislukt
@ -288,14 +317,16 @@ Action=Popup
[Event/switch-layout]
Name=Switch to layout
Name[ar]=بدل إلى تخطيط
Name[az]=Maketi Keçmək
Name[ca]=Commuta a la disposició
Name[ca@valencia]=Commuta a la disposició
Name[cs]=Přepnout na rozložení
Name[ca@valencia]=Canvia a la disposició
Name[cs]=Přepnout na rozvržení
Name[da]=Skift til layout
Name[de]=Wechsel zu Profil
Name[el]=Εναλλαγή στο προφίλ
Name[en_GB]=Switch to layout
Name[eo]=Ŝaltu al aranĝo
Name[es]=Cambiar a distribución
Name[et]=Paigutusele lülitumine
Name[eu]=Aldatu antolamendura
@ -305,6 +336,8 @@ Name[gl]=Cambiar á disposición
Name[hsb]=Layout přešaltować
Name[id]=Beralih ke tataletak
Name[it]=Passa alla disposizione
Name[ja]=レイアウトの切り替え
Name[ka]=განლაგებაზე გადართვა
Name[ko]=레이아웃으로 전환
Name[lt]=Perjungti į išdėstymą
Name[nl]=Naar indeling omschakelen
@ -316,6 +349,7 @@ Name[ru]=Использовать макет
Name[sk]=Prepnúť na rozloženie
Name[sl]=Preklop na postavitev
Name[sv]=Byt till layout
Name[tr]=Yerleşime geç
Name[uk]=Перемкнутися на компонування
Name[x-test]=xxSwitch to layoutxx
Name[zh_CN]=切换布局

View File

@ -46,9 +46,9 @@ void CentralLayout::init()
connect(this, &CentralLayout::showInMenuChanged, this, &CentralLayout::saveConfig);
}
void CentralLayout::initToCorona(Latte::Corona *corona)
bool CentralLayout::initCorona()
{
if (GenericLayout::initToCorona(corona)) {
if (GenericLayout::initCorona()) {
onSchemeFileChanged();
connect(this, &CentralLayout::disableBordersForMaximizedWindowsChanged,
@ -56,7 +56,10 @@ void CentralLayout::initToCorona(Latte::Corona *corona)
connect(this, &Layout::AbstractLayout::schemeFileChanged, this, &CentralLayout::onSchemeFileChanged);
connect(m_corona->wm()->schemesTracker(), &WindowSystem::Tracker::Schemes::defaultSchemeChanged, this, &CentralLayout::onSchemeFileChanged);
return true;
}
return false;
}
bool CentralLayout::disableBordersForMaximizedWindows() const

View File

@ -41,7 +41,7 @@ public:
CentralLayout(QObject *parent, QString layoutFile, QString layoutName = QString());
~CentralLayout() override;
void initToCorona(Latte::Corona *corona);
bool initCorona() override;
bool disableBordersForMaximizedWindows() const;
void setDisableBordersForMaximizedWindows(bool disable);

View File

@ -17,8 +17,10 @@
#include "../layouts/synchronizer.h"
#include "../shortcuts/shortcutstracker.h"
#include "../templates/templatesmanager.h"
#include "../view/view.h"
#include "../view/clonedview.h"
#include "../view/originalview.h"
#include "../view/positioner.h"
#include "../view/view.h"
// Qt
#include <QDebug>
@ -143,7 +145,7 @@ void GenericLayout::setBlockAutomaticLatteViewCreation(bool block)
bool GenericLayout::isActive() const
{
return m_corona && (m_corona->layoutsManager()->synchronizer()->layout(m_layoutName) != nullptr);
return m_corona && m_hasInitializedContainments && (m_corona->layoutsManager()->synchronizer()->layout(m_layoutName) != nullptr);
}
bool GenericLayout::isCurrent()
@ -155,6 +157,16 @@ bool GenericLayout::isCurrent()
return m_corona->layoutsManager()->currentLayoutsNames().contains(name());
}
bool GenericLayout::hasCorona() const
{
return (m_corona!=nullptr);
}
void GenericLayout::setCorona(Latte::Corona *corona)
{
m_corona = corona;
}
QString GenericLayout::background() const
{
QString colorsPath = m_corona->kPackage().path() + "../../shells/org.kde.latte.shell/contents/images/canvas/";
@ -368,6 +380,12 @@ Latte::View *GenericLayout::viewForContainment(uint id) const
}
}
for(auto view : m_waitingLatteViews) {
if (view && view->containment()->id() == id) {
return view;
}
}
return nullptr;
}
@ -449,12 +467,26 @@ QList<Latte::View *> GenericLayout::latteViews()
return m_latteViews.values();
}
QList<Latte::View *> GenericLayout::sortedLatteViews()
QList<Latte::View *> GenericLayout::onlyOriginalViews()
{
return sortedLatteViews(latteViews());
QList<Latte::View *> viewslist;
for (const auto v : m_latteViews) {
if (v->isOriginal()) {
viewslist << v;
}
}
return viewslist;
}
QList<Latte::View *> GenericLayout::sortedLatteViews(QList<Latte::View *> views)
QList<Latte::View *> GenericLayout::sortedLatteViews()
{
QScreen *primaryScreen = (m_corona ? m_corona->screenPool()->primaryScreen() : nullptr);
return sortedLatteViews(latteViews(), primaryScreen);
}
QList<Latte::View *> GenericLayout::sortedLatteViews(QList<Latte::View *> views, QScreen *primaryScreen)
{
QList<Latte::View *> sortedViews = views;
@ -470,7 +502,7 @@ QList<Latte::View *> GenericLayout::sortedLatteViews(QList<Latte::View *> views)
//! Bottom,Left,Top,Right
for (int i = 0; i < sortedViews.size(); ++i) {
for (int j = 0; j < sortedViews.size() - i - 1; ++j) {
if (viewAtLowerScreenPriority(sortedViews[j], sortedViews[j + 1])
if (viewAtLowerScreenPriority(sortedViews[j], sortedViews[j + 1], primaryScreen)
|| (sortedViews[j]->screen() == sortedViews[j + 1]->screen()
&& viewAtLowerEdgePriority(sortedViews[j], sortedViews[j + 1]))) {
Latte::View *temp = sortedViews[j + 1];
@ -503,7 +535,7 @@ QList<Latte::View *> GenericLayout::sortedLatteViews(QList<Latte::View *> views)
return sortedViews;
}
bool GenericLayout::viewAtLowerScreenPriority(Latte::View *test, Latte::View *base)
bool GenericLayout::viewAtLowerScreenPriority(Latte::View *test, Latte::View *base, QScreen *primaryScreen)
{
if (!base || ! test) {
return true;
@ -511,9 +543,9 @@ bool GenericLayout::viewAtLowerScreenPriority(Latte::View *test, Latte::View *ba
if (base->screen() == test->screen()) {
return false;
} else if (base->screen() != qGuiApp->primaryScreen() && test->screen() == qGuiApp->primaryScreen()) {
} else if (base->screen() != primaryScreen && test->screen() == primaryScreen) {
return false;
} else if (base->screen() == qGuiApp->primaryScreen() && test->screen() != qGuiApp->primaryScreen()) {
} else if (base->screen() == primaryScreen && test->screen() != primaryScreen) {
return true;
} else {
int basePriority = -1;
@ -819,109 +851,55 @@ void GenericLayout::renameLayout(QString newName)
}
}
void GenericLayout::addView(Plasma::Containment *containment, bool forceOnPrimary, int explicitScreen, Layout::ViewsMap *occupied)
void GenericLayout::addView(Plasma::Containment *containment)
{
qDebug() << "Layout :::: " << m_layoutName << " ::: addView was called... m_containments :: " << m_containments.size();
qDebug().noquote() << "Adding View: Called for layout:" << m_layoutName << "with m_containments.size() ::" << m_containments.size();
if (!containment || !m_corona || !containment->kPackage().isValid()) {
qWarning() << "the requested containment plugin can not be located or loaded";
qWarning() << "Adding View: The requested containment plugin can not be located or loaded";
return;
}
qDebug() << "step 1...";
qDebug() << "Adding View:" << containment->id() << "- Step 1...";
if (!Layouts::Storage::self()->isLatteContainment(containment)) {
return;
}
qDebug() << "step 2...";
qDebug() << "Adding View:" << containment->id() << "- Step 2...";
for (auto *dock : m_latteViews) {
if (dock->containment() == containment)
return;
}
qDebug() << "step 3...";
QScreen *nextScreen{qGuiApp->primaryScreen()};
bool onPrimary = containment->config().readEntry("onPrimary", true);
int id = containment->screen();
if (!Layouts::Storage::isValid(id) && !Layouts::Storage::isValid(explicitScreen)) {
id = containment->lastScreen();
}
if (onPrimary) {
id = m_corona->screenPool()->primaryScreenId();
} else if (Layouts::Storage::isValid(explicitScreen)) {
id = explicitScreen;
}
Plasma::Types::Location edge = containment->location();
QString connector = m_corona->screenPool()->hasScreenId(id) ? m_corona->screenPool()->connector(id) : "";
qDebug() << "Adding view - containment id:" << containment->id() << " ,screen :" << id << " - " << connector
<< " ,onprimary:" << onPrimary << " - " << " edge:" << edge << " ,screenName:" << qGuiApp->primaryScreen()->name() << " ,forceOnPrimary:" << forceOnPrimary;
if (occupied && m_corona->screenPool()->hasScreenId(id) && (*occupied).contains(connector) && (*occupied)[connector].contains(edge)) {
qDebug() << "Rejected : adding view because the edge is already occupied by a higher priority view ! : " << (*occupied)[connector][edge];
if (hasLatteView(containment)) {
return;
}
if (Layouts::Storage::isValid(id) && !onPrimary && !forceOnPrimary) {
qDebug() << "Add view - connector : " << connector;
bool found{false};
qDebug() << "Adding View:" << containment->id() << "- Step 3...";
if (m_corona->screenPool()->hasScreenId(id)) {
for (const auto scr : qGuiApp->screens()) {
if (scr && scr->name() == connector) {
found = true;
nextScreen = scr;
break;
}
}
QScreen *nextScreen{m_corona->screenPool()->primaryScreen()};
Data::View viewdata = Layouts::Storage::self()->view(this, containment);
viewdata.screen = Layouts::Storage::self()->expectedViewScreenId(m_corona, viewdata);
QString nextScreenName = m_corona->screenPool()->hasScreenId(viewdata.screen) ? m_corona->screenPool()->connector(viewdata.screen) : "";
qDebug().noquote() << "Adding View:" << viewdata.id << "-"
<< "IsClonedFrom:" << viewdata.isClonedFrom
<< ", NextScreen:" << viewdata.screen << "-" << nextScreenName
<< ", OnPrimary:" << viewdata.onPrimary
<< ", Edge:" << viewdata.edge;
if (!viewdata.onPrimary && Layouts::Storage::isValid(viewdata.screen)) {
bool foundNextExplicitScreen{false};
if (m_corona->screenPool()->isScreenActive(viewdata.screen)) {
foundNextExplicitScreen = true;
nextScreen = m_corona->screenPool()->screenForId(viewdata.screen);
}
if (!found) {
qDebug() << "Rejected : adding explicit view, screen not available ! : " << connector;
if (!foundNextExplicitScreen) {
qDebug().noquote() << "Adding View:" << viewdata.id << "- Rejected because Screen is not available :: " << nextScreenName;
return;
}
//! explicit dock can not be added at explicit screen when that screen is the same with
//! primary screen and that edge is already occupied by a primary dock
//! CAN BE REMOVED because we now accept primary and explicit views on ACTIVE SCREENS at ALL CASES
//if (nextScreen == qGuiApp->primaryScreen() && primaryDockOccupyEdge(containment->location())) {
// qDebug() << "Rejected : adding explicit view, primary dock occupies edge at screen ! : " << connector;
// return;
// }
}
if (Layouts::Storage::isValid(id) && onPrimary) {
qDebug() << "add dock - connector : " << connector;
for (const Plasma::Containment *testContainment : m_latteViews.keys()) {
int testScreenId = testContainment->screen();
if (!Layouts::Storage::isValid(testScreenId)) {
testScreenId = testContainment->lastScreen();
}
bool testOnPrimary = testContainment->config().readEntry("onPrimary", true);
Plasma::Types::Location testLocation = static_cast<Plasma::Types::Location>((int)testContainment->config().readEntry("location", (int)Plasma::Types::BottomEdge));
if (!testOnPrimary && m_corona->screenPool()->primaryScreenId() == testScreenId && testLocation == containment->location()) {
qDebug() << "Rejected explicit latteView and removing it in order add an onPrimary with higher priority at screen: " << connector;
auto viewToDelete = m_latteViews.take(testContainment);
viewToDelete->disconnectSensitiveSignals();
viewToDelete->deleteLater();
}
}
}
qDebug() << "Adding view passed ALL checks" << " ,onPrimary:" << onPrimary << " ,screen:" << nextScreen->name() << " !!!";
//! it is used to set the correct flag during the creation
//! of the window... This of course is also used during
//! recreations of the window between different visibility modes
@ -937,21 +915,29 @@ void GenericLayout::addView(Plasma::Containment *containment, bool forceOnPrimar
byPassWM = containment->config().readEntry("byPassWM", false);
}
auto latteView = new Latte::View(m_corona, nextScreen, byPassWM);
Latte::View *latteView;
if (!viewdata.isCloned()) {
latteView = new Latte::OriginalView(m_corona, nextScreen, byPassWM);
} else {
auto view = viewForContainment((uint)viewdata.isClonedFrom);
if (!containsView(viewdata.isClonedFrom) || !view) {
qDebug().noquote() << "Adding View:" << viewdata.id << "- Clone did not find OriginalView and as such was stopped!!!";
return;
}
auto originalview = qobject_cast<Latte::OriginalView *>(view);
latteView = new Latte::ClonedView(m_corona, originalview, nextScreen, byPassWM);
}
qDebug().noquote() << "Adding View:" << viewdata.id << "- Passed ALL checks !!!";
m_latteViews[containment] = latteView;
latteView->init(containment);
latteView->setContainment(containment);
//! force this special dock case to become primary
//! even though it isnt
if (forceOnPrimary) {
qDebug() << "Enforcing onPrimary:true as requested for LatteView...";
latteView->setOnPrimary(true);
}
latteView->setLayout(this);
//! Qt 5.9 creates a crash for this in wayland, that is why the check is used
//! but on the other hand we need this for copy to work correctly and show
//! the copied dock under X11
@ -959,8 +945,6 @@ void GenericLayout::addView(Plasma::Containment *containment, bool forceOnPrimar
latteView->show();
//}
m_latteViews[containment] = latteView;
emit viewsCountChanged();
}
@ -970,7 +954,7 @@ void GenericLayout::toggleHiddenState(QString viewName, QString screenName, Plas
return;
}
QString validScreenName = qGuiApp->primaryScreen()->name();
QString validScreenName = m_corona->screenPool()->primaryScreen()->name();
if (!screenName.isEmpty()) {
validScreenName = screenName;
}
@ -996,27 +980,13 @@ void GenericLayout::toggleHiddenState(QString viewName, QString screenName, Plas
}
}
bool GenericLayout::initToCorona(Latte::Corona *corona)
bool GenericLayout::initCorona()
{
if (m_corona) {
if (!m_corona) {
return false;
}
m_corona = corona;
for (const auto containment : m_corona->containments()) {
if (m_corona->layoutsManager()->memoryUsage() == MemoryUsage::SingleLayout) {
addContainment(containment);
} else if (m_corona->layoutsManager()->memoryUsage() == MemoryUsage::MultipleLayouts) {
QString layoutId = containment->config().readEntry("layoutId", QString());
if (!layoutId.isEmpty() && (layoutId == m_layoutName)) {
addContainment(containment);
}
}
}
qDebug() << "Layout ::::: " << name() << " added containments ::: " << m_containments.size();
connect(m_corona, &Plasma::Corona::containmentAdded, this, &GenericLayout::addContainment);
updateLastUsedActivity();
@ -1025,8 +995,6 @@ bool GenericLayout::initToCorona(Latte::Corona *corona)
connect(m_corona->activitiesConsumer(), &KActivities::Consumer::currentActivityChanged, this, &GenericLayout::updateLastUsedActivity);
connect(m_corona->activitiesConsumer(), &KActivities::Consumer::runningActivitiesChanged, this, &GenericLayout::updateLastUsedActivity);
connect(m_corona, &Plasma::Corona::containmentAdded, this, &GenericLayout::addContainment);
connect(this, &GenericLayout::lastConfigViewForChanged, m_corona->layoutsManager(), &Layouts::Manager::lastConfigViewChangedFrom);
connect(m_corona->layoutsManager(), &Layouts::Manager::lastConfigViewChangedFrom, this, &GenericLayout::onLastConfigViewChangedFrom);
@ -1034,8 +1002,41 @@ bool GenericLayout::initToCorona(Latte::Corona *corona)
connect(this, &GenericLayout::viewsCountChanged, m_corona, &Plasma::Corona::availableScreenRectChanged);
connect(this, &GenericLayout::viewsCountChanged, m_corona, &Plasma::Corona::availableScreenRegionChanged);
emit viewsCountChanged();
return true;
}
bool GenericLayout::initContainments()
{
if (!m_corona || m_hasInitializedContainments) {
return false;
}
qDebug() << "Layout ::::: " << name() << " added containments ::: " << m_containments.size();
for(int pass=1; pass<=2; ++pass) {
for (const auto containment : m_corona->containments()) {
//! in first pass we load subcontainments
//! in second pass we load main dock and panel containments
//! this way subcontainments will be always available to find when the layout is activating
//! for example during startup that clones must be created and subcontainments should be taken into account
if ((pass==1 && Layouts::Storage::self()->isLatteContainment(containment)
|| (pass==2 && !Layouts::Storage::self()->isLatteContainment(containment)))) {
continue;
}
if (m_corona->layoutsManager()->memoryUsage() == MemoryUsage::SingleLayout) {
addContainment(containment);
} else if (m_corona->layoutsManager()->memoryUsage() == MemoryUsage::MultipleLayouts) {
QString layoutId = containment->config().readEntry("layoutId", QString());
if (!layoutId.isEmpty() && (layoutId == m_layoutName)) {
addContainment(containment);
}
}
}
}
m_hasInitializedContainments = true;
emit viewsCountChanged();
return true;
}
@ -1163,7 +1164,7 @@ void GenericLayout::recreateView(Plasma::Containment *containment, bool delayed)
}
bool GenericLayout::latteViewExists(Plasma::Containment *containment)
bool GenericLayout::hasLatteView(Plasma::Containment *containment)
{
if (!m_corona) {
return false;
@ -1254,119 +1255,55 @@ bool GenericLayout::mapContainsId(const Layout::ViewsMap *map, uint viewId) cons
return false;
}
//! screen name, location, containmentId
Layout::ViewsMap GenericLayout::validViewsMap(Layout::ViewsMap *occupiedMap)
QString GenericLayout::mapScreenName(const ViewsMap *map, uint viewId) const
{
for(const auto &scr : map->keys()) {
for(const auto &edge : (*map)[scr].keys()) {
if ((*map)[scr][edge].contains(viewId)) {
return scr;
}
}
}
return QString::number(Latte::ScreenPool::NOSCREENID);
}
//! screen name, location, containmentId
Layout::ViewsMap GenericLayout::validViewsMap()
{
//! Shared Views occupy the screen edge first
//! Primary Views occupy the screen edge if Shared Views do not exist already on that screen edge
//! Explicity Views occypy the screen edge if Shared Views and Primary Views do not exist already on that screen edge
Layout::ViewsMap map;
if (!m_corona) {
return map;
}
if (occupiedMap != nullptr) {
map = (*occupiedMap);
}
QString prmScreenName = m_corona->screenPool()->primaryScreen()->name();
QString prmScreenName = qGuiApp->primaryScreen()->name();
//! first step: primary docks must be placed in primary screen free edges
for (const auto containment : m_containments) {
if (Layouts::Storage::self()->isLatteContainment(containment)) {
int screenId{Layouts::Storage::IDNULL};
if (Layouts::Storage::self()->isLatteContainment(containment)
&& !Layouts::Storage::self()->isClonedView(containment)) {
Data::View view = hasLatteView(containment) ? m_latteViews[containment]->data() : Latte::Layouts::Storage::self()->view(this, containment);
view.screen = Layouts::Storage::self()->expectedViewScreenId(m_corona, view);
//! valid screen id
if (latteViewExists(containment)) {
screenId = m_latteViews[containment]->positioner()->currentScreenId();
if (view.onPrimary) {
map[prmScreenName][view.edge] << containment->id();
} else {
screenId = containment->screen();
QString expScreenName = m_corona->screenPool()->connector(view.screen);
if (!Layouts::Storage::isValid(screenId)) {
screenId = containment->lastScreen();
}
}
bool onPrimary{true};
//! valid onPrimary flag
if (latteViewExists(containment)) {
onPrimary = m_latteViews[containment]->onPrimary();
} else {
onPrimary = containment->config().readEntry("onPrimary", true);
}
//! valid location
Plasma::Types::Location location = containment->location();
if (onPrimary) {
map[prmScreenName][location] << containment->id();
} else {
QString expScreenName = m_corona->screenPool()->connector(screenId);
if (m_corona->screenPool()->isScreenActive(screenId)) {
map[expScreenName][location] << containment->id();
if (m_corona->screenPool()->isScreenActive(view.screen)) {
map[expScreenName][view.edge] << containment->id();
}
}
}
}
/*
//! CAN BE REMOVED because we now accept primary and explicit views on ACTIVE SCREENS at ALL CASES
Layout::ViewsMap explicitMap;
//! second step: explicit docks must be placed in their screens if the screen edge is free
for (const auto containment : m_containments) {
if (Layouts::Storage::self()->isLatteContainment(containment)) {
int screenId{Layouts::Storage::IDNULL};
//! valid screen id
if (latteViewExists(containment)) {
screenId = m_latteViews[containment]->positioner()->currentScreenId();
} else {
screenId = containment->screen();
if (!Layouts::Storage::isValid(screenId)) {
screenId = containment->lastScreen();
}
}
bool onPrimary{true};
//! valid onPrimary flag
if (latteViewExists(containment)) {
onPrimary = m_latteViews[containment]->onPrimary();
} else {
onPrimary = containment->config().readEntry("onPrimary", true);
}
//! valid location
Plasma::Types::Location location = containment->location();
if (!onPrimary) {
QString expScreenName = m_corona->screenPool()->connector(screenId);
if (m_corona->screenPool()->isScreenActive(screenId) && !map[expScreenName].contains(location)) {
explicitMap[expScreenName][location] << containment->id();
}
}
}
}
for(const QString &expScreenName : explicitMap.keys()) {
for(const Plasma::Types::Location &expLocation : explicitMap[expScreenName].keys()) {
map[expScreenName][expLocation] << explicitMap[expScreenName][expLocation];
}
}*/
return map;
}
//! the central functions that updates loading/unloading latteviews
//! concerning screen changed (for multi-screen setups mainly)
void GenericLayout::syncLatteViewsToScreens(Layout::ViewsMap *occupiedMap)
void GenericLayout::syncLatteViewsToScreens()
{
if (!m_corona) {
return;
@ -1400,27 +1337,17 @@ void GenericLayout::syncLatteViewsToScreens(Layout::ViewsMap *occupiedMap)
}
//! use valid views map based on active screens
Layout::ViewsMap viewsMap = validViewsMap(occupiedMap);
Layout::ViewsMap viewsMap = validViewsMap();
if (occupiedMap != nullptr) {
qDebug() << "Occupied map used :: " << *occupiedMap;
}
QString prmScreenName = qGuiApp->primaryScreen()->name();
QString prmScreenName = m_corona->screenPool()->primaryScreen()->name();
qDebug() << "PRIMARY SCREEN :: " << prmScreenName;
qDebug() << "LATTEVIEWS MAP :: " << viewsMap;
//! add views
for (const auto containment : m_containments) {
int screenId = containment->screen();
if (!Layouts::Storage::isValid(screenId)) {
screenId = containment->lastScreen();
}
if (!latteViewExists(containment) && mapContainsId(&viewsMap, containment->id())) {
qDebug() << "syncLatteViewsToScreens: view must be added... for containment:" << containment->id() << " at screen:" << m_corona->screenPool()->connector(screenId);
if (!hasLatteView(containment) && mapContainsId(&viewsMap, containment->id())) {
qDebug() << "syncLatteViewsToScreens: view must be added... for containment:" << containment->id() << " at screen:" << mapScreenName(&viewsMap, containment->id());
addView(containment);
}
}
@ -1430,7 +1357,7 @@ void GenericLayout::syncLatteViewsToScreens(Layout::ViewsMap *occupiedMap)
for (auto view : m_latteViews) {
auto containment = view->containment();
if (containment && !mapContainsId(&viewsMap, containment->id())) {
if (containment && view->isOriginal() && !mapContainsId(&viewsMap, containment->id())) {
viewsToDelete << containment;
}
}
@ -1445,7 +1372,7 @@ void GenericLayout::syncLatteViewsToScreens(Layout::ViewsMap *occupiedMap)
//! reconsider views
for (const auto view : m_latteViews) {
if (view->containment() && mapContainsId(&viewsMap, view->containment()->id())) {
if (view->containment() && view->isOriginal() && mapContainsId(&viewsMap, view->containment()->id())) {
//! if the dock will not be deleted its a very good point to reconsider
//! if the screen in which is running is the correct one
qDebug() << "syncLatteViewsToScreens: view must consider its screen... for containment:" << view->containment()->id() << " at screen:" << view->positioner()->currentScreenName();
@ -1607,7 +1534,7 @@ void GenericLayout::updateView(const Latte::Data::View &viewData)
}
view->setName(viewData.name);
view->positioner()->setNextLocation(nextactivelayoutname, scrName, viewData.edge, viewData.alignment);
view->positioner()->setNextLocation(nextactivelayoutname, viewData.screensGroup, scrName, viewData.edge, viewData.alignment);
return;
} else {
//! viewMustBeDeleted

View File

@ -55,12 +55,15 @@ public:
virtual const QStringList appliedActivities() = 0; // to move at an interface
virtual bool initCorona();
void importToCorona();
bool initToCorona(Latte::Corona *corona);
bool initContainments();
void setCorona(Latte::Corona *corona);
bool isActive() const; //! is loaded and running
virtual bool isCurrent();
bool isWritable() const;
bool hasCorona() const;
virtual int viewsCount(int screen) const;
virtual int viewsCount(QScreen *screen) const;
@ -85,15 +88,16 @@ public:
Plasma::Containment *containmentForId(uint id) const;
QList<Plasma::Containment *> subContainmentsOf(uint id) const;
static bool viewAtLowerScreenPriority(Latte::View *test, Latte::View *base);
static bool viewAtLowerScreenPriority(Latte::View *test, Latte::View *base, QScreen *primaryScreen);
static bool viewAtLowerEdgePriority(Latte::View *test, Latte::View *base);
static QList<Latte::View *> sortedLatteViews(QList<Latte::View *> views);
static QList<Latte::View *> sortedLatteViews(QList<Latte::View *> views, QScreen *primaryScreen);
QList<Latte::View *> sortedLatteViews();
virtual QList<Latte::View *> viewsWithPlasmaShortcuts();
virtual QList<Latte::View *> latteViews();
ViewsMap validViewsMap(ViewsMap *occupiedMap = nullptr);
virtual void syncLatteViewsToScreens(Layout::ViewsMap *occupiedMap = nullptr);
virtual QList<Latte::View *> onlyOriginalViews();
ViewsMap validViewsMap();
virtual void syncLatteViewsToScreens();
void syncToLayoutFile(bool removeLayoutId = false);
@ -106,10 +110,10 @@ public:
virtual void setLastConfigViewFor(Latte::View *view);
virtual Latte::View *lastConfigViewFor();
//! this function needs the layout to have first set the corona through initToCorona() function
virtual void addView(Plasma::Containment *containment, bool forceOnPrimary = false, int explicitScreen = -1, Layout::ViewsMap *occupied = nullptr);
//! this function needs the layout to have first set the corona through setCorona() function
virtual void addView(Plasma::Containment *containment);
void recreateView(Plasma::Containment *containment, bool delayed = true);
bool latteViewExists(Plasma::Containment *containment);
bool hasLatteView(Plasma::Containment *containment);
bool newView(const QString &templateName);
Data::View newView(const Latte::Data::View &nextViewData);
@ -190,6 +194,7 @@ private:
bool viewDataAtLowerStatePriority(const Latte::Data::View &test, const Latte::Data::View &base) const;
bool mapContainsId(const ViewsMap *map, uint viewId) const;
QString mapScreenName(const ViewsMap *map, uint viewId) const;
QList<int> subContainmentsOf(Plasma::Containment *containment) const;
@ -199,7 +204,7 @@ private:
private:
bool m_blockAutomaticLatteViewCreation{false};
bool m_hasInitializedContainments{false};
QPointer<Latte::View> m_lastConfigViewFor;
QStringList m_unloadedContainmentsIds;

View File

@ -758,6 +758,38 @@ QString Importer::uniqueLayoutName(QString name)
return name;
}
Latte::MultipleLayouts::Status Importer::multipleLayoutsStatus()
{
QString linkedFilePath = layoutUserFilePath(Layout::MULTIPLELAYOUTSHIDDENNAME);
if (!QFileInfo(linkedFilePath).exists()) {
return Latte::MultipleLayouts::Uninitialized;
}
KSharedConfigPtr filePtr = KSharedConfig::openConfig(linkedFilePath);
KConfigGroup multipleSettings = KConfigGroup(filePtr, "MultipleLayoutsSettings");
return static_cast<Latte::MultipleLayouts::Status>(multipleSettings.readEntry("status", (int)Latte::MultipleLayouts::Uninitialized));
}
void Importer::setMultipleLayoutsStatus(const Latte::MultipleLayouts::Status &status)
{
QString linkedFilePath = layoutUserFilePath(Layout::MULTIPLELAYOUTSHIDDENNAME);
if (!QFileInfo(linkedFilePath).exists()) {
return;
}
if (multipleLayoutsStatus() == status) {
return;
}
qDebug() << " MULTIPLE LAYOUTS changed status:" << status;
KSharedConfigPtr filePtr = KSharedConfig::openConfig(linkedFilePath);
KConfigGroup multipleSettings = KConfigGroup(filePtr, "MultipleLayoutsSettings");
multipleSettings.writeEntry("status", (int)(status));
multipleSettings.sync();
}
QStringList Importer::checkRepairMultipleLayoutsLinkedFile()
{
QString linkedFilePath = layoutUserFilePath(Layout::MULTIPLELAYOUTSHIDDENNAME);

View File

@ -8,6 +8,9 @@
#ifndef IMPORTER_H
#define IMPORTER_H
// local
#include "../apptypes.h"
// Qt
#include <QObject>
#include <QTemporaryDir>
@ -107,6 +110,9 @@ public:
//! close correctly, e.g. there was a crash.
static QStringList checkRepairMultipleLayoutsLinkedFile();
static Latte::MultipleLayouts::Status multipleLayoutsStatus();
static void setMultipleLayoutsStatus(const Latte::MultipleLayouts::Status &status);
signals:
void newLayoutAdded(const QString &path);

View File

@ -16,6 +16,7 @@
#include "../data/generictable.h"
#include "../layout/abstractlayout.h"
#include "../layout/centrallayout.h"
#include "../layouts/storage.h"
#include "../settings/universalsettings.h"
#include "../templates/templatesmanager.h"
#include "../tools/commontools.h"
@ -51,6 +52,10 @@ Manager::Manager(QObject *parent)
Manager::~Manager()
{
if (memoryUsage() == Latte::MemoryUsage::MultipleLayouts) {
m_importer->setMultipleLayoutsStatus(Latte::MultipleLayouts::Paused);
}
m_importer->deleteLater();
m_syncedLaunchers->deleteLater();
@ -230,7 +235,7 @@ bool Manager::switchToLayout(QString layoutName, MemoryUsage::LayoutsMemory new
void Manager::loadLayoutOnStartup(QString layoutName)
{
QStringList layouts = m_importer->checkRepairMultipleLayoutsLinkedFile();
/* QStringList layouts = m_importer->checkRepairMultipleLayoutsLinkedFile();
//! Latte didn't close correctly, maybe a crash
if (layouts.size() > 0) {
@ -254,7 +259,7 @@ void Manager::loadLayoutOnStartup(QString layoutName)
KMessageBox::NoExec,
QString());
dialog->show();
}
}*/
m_synchronizer->switchToLayout(layoutName);
}
@ -332,6 +337,8 @@ void Manager::setOnActivities(QString layoutName, QStringList activities)
void Manager::cleanupOnStartup(QString path)
{
Layouts::Storage::self()->removeAllClonedViews(path);
KSharedConfigPtr filePtr = KSharedConfig::openConfig(path);
KConfigGroup actionGroups = KConfigGroup(filePtr, "ActionPlugins");

View File

@ -12,6 +12,7 @@
#include "../lattecorona.h"
#include "../screenpool.h"
#include "../data/errordata.h"
#include "../data/viewdata.h"
#include "../layout/abstractlayout.h"
#include "../view/view.h"
@ -99,13 +100,13 @@ bool Storage::isLatteContainment(const KConfigGroup &group) const
return pluginId == QLatin1String("org.kde.latte.containment");
}
bool Storage::isSubContainment(const Layout::GenericLayout *layout, const Plasma::Applet *applet) const
bool Storage::isSubContainment(const Plasma::Corona *corona, const Plasma::Applet *applet) const
{
if (!layout || !applet) {
if (!corona || !applet) {
return false;
}
for (const auto containment : *layout->containments()) {
for (const auto containment : corona->containments()) {
Plasma::Applet *parentApplet = qobject_cast<Plasma::Applet *>(containment->parent());
if (parentApplet && parentApplet == applet) {
return true;
@ -178,14 +179,14 @@ int Storage::subIdentityIndex(const KConfigGroup &appletGroup) const
return IDNULL;
}
Plasma::Containment *Storage::subContainmentOf(const Layout::GenericLayout *layout, const Plasma::Applet *applet)
Plasma::Containment *Storage::subContainmentOf(const Plasma::Corona *corona, const Plasma::Applet *applet)
{
if (!layout || !applet) {
if (!corona || !applet) {
return nullptr;
}
if (isSubContainment(layout, applet)) {
for (const auto containment : *layout->containments()) {
if (isSubContainment(corona, applet)) {
for (const auto containment : corona->containments()) {
Plasma::Applet *parentApplet = qobject_cast<Plasma::Applet *>(containment->parent());
if (parentApplet && parentApplet == applet) {
return containment;
@ -224,6 +225,8 @@ void Storage::importToCorona(const Layout::GenericLayout *layout)
//! Setting mutable for create a containment
layout->corona()->setImmutability(Plasma::Types::Mutable);
removeAllClonedViews(layout->file());
QString temp1FilePath = m_storageTmpDir.path() + "/" + layout->name() + ".multiple.views";
//! we need to copy first the layout file because the kde cache
//! may not have yet been updated (KSharedConfigPtr)
@ -240,8 +243,9 @@ void Storage::importToCorona(const Layout::GenericLayout *layout)
tempLayoutFile.remove();
}
if (copyFile.exists())
if (copyFile.exists()) {
copyFile.remove();
}
layoutOriginalFile.copy(tempLayoutFilePath);
@ -329,7 +333,7 @@ QString Storage::newUniqueIdsFile(QString originFile, const Layout::GenericLayou
QString currentdestinationname = destinationLayout->name();
QString currentdestinationfile = "";
if (!destinationLayout->isActive()) {
if (!destinationLayout->hasCorona()) {
currentdestinationfile = destinationLayout->file();
}
@ -344,7 +348,7 @@ QString Storage::newUniqueIdsFile(QString originFile, const Layout::GenericLayou
//! BEGIN updating the ids in the temp file
QStringList allIds;
if (destinationLayout->isActive()) {
if (destinationLayout->hasCorona()) {
allIds << destinationLayout->corona()->containmentsIds();
allIds << destinationLayout->corona()->appletsIds();
} else {
@ -475,7 +479,7 @@ QString Storage::newUniqueIdsFile(QString originFile, const Layout::GenericLayou
}
}
if (destinationLayout->isActive() && destinationLayout->corona()->layoutsManager()->memoryUsage() == MemoryUsage::MultipleLayouts) {
if (destinationLayout->hasCorona() && destinationLayout->corona()->layoutsManager()->memoryUsage() == MemoryUsage::MultipleLayouts) {
//! will be added in main corona multiple layouts file
investigate_conts.group(cId).writeEntry("layoutId", destinationLayout->name());
} else {
@ -560,6 +564,45 @@ void Storage::syncToLayoutFile(const Layout::GenericLayout *layout, bool removeL
}
filePtr->reparseConfiguration();
removeAllClonedViews(layout->file());
}
void Storage::moveToLayoutFile(const QString &layoutName)
{
if (layoutName.isEmpty()) {
return;
}
QString linkedFilePath = Importer::layoutUserFilePath(Layout::MULTIPLELAYOUTSHIDDENNAME);
QString layoutFilePath = Importer::layoutUserFilePath(layoutName);
if (linkedFilePath.isEmpty() || layoutFilePath.isEmpty() || !QFileInfo(linkedFilePath).exists() || !QFileInfo(layoutFilePath).exists()) {
return;
}
KSharedConfigPtr layoutFilePtr = KSharedConfig::openConfig(layoutFilePath);
KConfigGroup singleContainments = KConfigGroup(layoutFilePtr, "Containments");
singleContainments.deleteGroup();
KSharedConfigPtr multiFilePtr = KSharedConfig::openConfig(linkedFilePath);
KConfigGroup multiContainments = KConfigGroup(multiFilePtr, "Containments");
for(const auto &cId : multiContainments.groupList()) {
QString cname = multiContainments.group(cId).readEntry("layoutId", QString());
if (!cname.isEmpty() && cname == layoutName) {
multiContainments.group(cId).writeEntry("layoutId", "");
KConfigGroup singleGroup = singleContainments.group(cId);
multiContainments.group(cId).copyTo(&singleGroup);
singleGroup.writeEntry("layoutId", "");
singleGroup.sync();
multiContainments.group(cId).deleteGroup();
}
}
layoutFilePtr->reparseConfiguration();
removeAllClonedViews(layoutFilePath);
}
QList<Plasma::Containment *> Storage::importLayoutFile(const Layout::GenericLayout *layout, QString file)
@ -567,13 +610,10 @@ QList<Plasma::Containment *> Storage::importLayoutFile(const Layout::GenericLayo
KSharedConfigPtr filePtr = KSharedConfig::openConfig(file);
auto newContainments = layout->corona()->importLayout(KConfigGroup(filePtr, ""));
qDebug() << " imported containments ::: " << newContainments.length();
QList<Plasma::Containment *> importedViews;
for (const auto containment : newContainments) {
if (isLatteContainment(containment)) {
qDebug() << "new latte containment id: " << containment->id();
importedViews << containment;
}
}
@ -609,7 +649,7 @@ Data::View Storage::newView(const Layout::GenericLayout *destinationLayout, cons
qDebug() << "new view for layout";
if (destinationLayout->isActive()) {
if (destinationLayout->hasCorona()) {
//! Setting mutable for create a containment
destinationLayout->corona()->setImmutability(Plasma::Types::Mutable);
}
@ -650,7 +690,7 @@ Data::View Storage::newView(const Layout::GenericLayout *destinationLayout, cons
return Data::View();
}
if (destinationLayout->isActive()) {
if (destinationLayout->hasCorona()) {
//! import views for active layout
QList<Plasma::Containment *> importedViews = importLayoutFile(destinationLayout, temp2File);
@ -732,6 +772,7 @@ bool Storage::exportTemplate(const QString &originFile, const QString &destinati
KConfigGroup layoutSettingsGrp(destFilePtr, "LayoutSettings");
clearExportedLayoutSettings(layoutSettingsGrp);
destFilePtr->reparseConfiguration();
removeAllClonedViews(destinationFile);
return true;
}
@ -828,6 +869,7 @@ bool Storage::exportTemplate(const Layout::GenericLayout *layout, Plasma::Contai
KConfigGroup layoutSettingsGrp(destFilePtr, "LayoutSettings");
clearExportedLayoutSettings(layoutSettingsGrp);
destFilePtr->reparseConfiguration();
removeAllClonedViews(destinationFile);
return true;
}
@ -1271,7 +1313,7 @@ Data::AppletsTable Storage::plugins(const Layout::GenericLayout *layout, const i
}
for (auto applet : containment->applets()) {
if (isSubContainment(layout, applet)) {
if (isSubContainment(layout->corona(), applet)) {
validcontainmentids << subContainmentId(applet->config());
}
}
@ -1426,6 +1468,51 @@ bool Storage::hasContainment(const Layout::GenericLayout *layout, const int &id)
return false;
}
bool Storage::isClonedView(const Plasma::Containment *containment) const
{
if (!containment) {
return false;
}
return isClonedView(containment->config());
}
bool Storage::isClonedView(const KConfigGroup &containmentGroup) const
{
if (!isLatteContainment(containmentGroup)) {
return false;
}
int isClonedFrom = containmentGroup.readEntry("isClonedFrom", Data::View::ISCLONEDNULL);
return (isClonedFrom != IDNULL);
}
void Storage::removeAllClonedViews(const QString &filepath)
{
KSharedConfigPtr lFile = KSharedConfig::openConfig(filepath);
KConfigGroup containmentGroups = KConfigGroup(lFile, "Containments");
QList<Data::View> clones;
for (const auto &contId : containmentGroups.groupList()) {
if (isClonedView(containmentGroups.group(contId))) {
clones << view(containmentGroups.group(contId));
}
}
if (clones.size() <= 0) {
return;
}
if (clones.count()>0) {
qDebug() << "org.kde.layout :: Removing clones from file: " << filepath;
}
for (const auto &clonedata : clones) {
qDebug() << "org.kde.layout :: Removing clone:" << clonedata.id << " and its subcontainments:" << clonedata.subcontainments;
removeView(filepath, clonedata);
}
}
Data::GenericTable<Data::Generic> Storage::subcontainments(const Layout::GenericLayout *layout, const Plasma::Containment *lattecontainment) const
{
@ -1505,8 +1592,10 @@ Data::View Storage::view(const KConfigGroup &containmentGroup)
vdata.id = containmentGroup.name();
vdata.name = containmentGroup.readEntry("name", QString());
vdata.isActive = false;
vdata.screensGroup = static_cast<Latte::Types::ScreensGroup>(containmentGroup.readEntry("screensGroup", (int)Latte::Types::SingleScreenGroup));
vdata.onPrimary = containmentGroup.readEntry("onPrimary", true);
vdata.screen = containmentGroup.readEntry("lastScreen", IDNULL);
vdata.isClonedFrom = containmentGroup.readEntry("isClonedFrom", Data::View::ISCLONEDNULL);
vdata.screenEdgeMargin = containmentGroup.group("General").readEntry("screenEdgeMargin", (int)-1);
int location = containmentGroup.readEntry("location", (int)Plasma::Types::BottomEdge);
@ -1530,7 +1619,9 @@ void Storage::updateView(KConfigGroup viewGroup, const Data::View &viewData)
}
viewGroup.writeEntry("name", viewData.name);
viewGroup.writeEntry("screensGroup", (int)viewData.screensGroup);
viewGroup.writeEntry("onPrimary", viewData.onPrimary);
viewGroup.writeEntry("isClonedFrom", viewData.isClonedFrom);
viewGroup.writeEntry("lastScreen", viewData.screen);
viewGroup.group("General").writeEntry("screenEdgeMargin", viewData.screenEdgeMargin);
viewGroup.writeEntry("location", (int)viewData.edge);
@ -1602,6 +1693,30 @@ void Storage::removeContainment(const QString &filepath, const QString &containm
lFile->reparseConfiguration();
}
QStringList Storage::storedLayoutsInMultipleFile()
{
QStringList layouts;
QString linkedFilePath = Importer::layoutUserFilePath(Layout::MULTIPLELAYOUTSHIDDENNAME);
if (linkedFilePath.isEmpty() || !QFileInfo(linkedFilePath).exists()) {
return layouts;
}
KSharedConfigPtr filePtr = KSharedConfig::openConfig(linkedFilePath);
KConfigGroup linkedContainments = KConfigGroup(filePtr, "Containments");
for(const auto &cId : linkedContainments.groupList()) {
QString layoutName = linkedContainments.group(cId).readEntry("layoutId", QString());
if (!layoutName.isEmpty() && !layouts.contains(layoutName)) {
layouts << layoutName;
}
}
return layouts;
}
QString Storage::storedView(const Layout::GenericLayout *layout, const int &containmentId)
{
//! make sure that layout and containmentId are valid
@ -1677,6 +1792,38 @@ QString Storage::storedView(const Layout::GenericLayout *layout, const int &cont
return nextTmpStoredViewAbsolutePath;
}
int Storage::expectedViewScreenId(const Latte::Corona *corona, const KConfigGroup &containmentGroup) const
{
return expectedViewScreenId(corona, self()->view(containmentGroup));
}
int Storage::expectedViewScreenId(const Layout::GenericLayout *layout, const Plasma::Containment *lattecontainment) const
{
if (!layout || !layout->corona()) {
return Latte::ScreenPool::NOSCREENID;
}
return expectedViewScreenId(layout->corona(), self()->view(layout, lattecontainment));
}
int Storage::expectedViewScreenId(const Latte::Corona *corona, const Data::View &view) const
{
if (!corona || !view.isValid()) {
return Latte::ScreenPool::NOSCREENID;
}
if (view.screensGroup == Latte::Types::SingleScreenGroup || view.isCloned()) {
return view.onPrimary ? corona->screenPool()->primaryScreenId() : view.screen;
} else if (view.screensGroup == Latte::Types::AllScreensGroup) {
return corona->screenPool()->primaryScreenId();
} else if (view.screensGroup == Latte::Types::AllSecondaryScreensGroup) {
QList<int> secondaryscreens = corona->screenPool()->secondaryScreenIds();
return secondaryscreens.contains(view.screen) || secondaryscreens.isEmpty() ? view.screen : secondaryscreens[0];
}
return Latte::ScreenPool::NOSCREENID;
}
Data::ViewsTable Storage::views(const Layout::GenericLayout *layout)
{
Data::ViewsTable vtable;

View File

@ -24,6 +24,7 @@
#include <Plasma/Containment>
namespace Latte {
class Corona;
namespace Layout {
class GenericLayout;
}
@ -51,14 +52,18 @@ public:
bool isWritable(const Layout::GenericLayout *layout) const;
bool isLatteContainment(const Plasma::Containment *containment) const;
bool isLatteContainment(const KConfigGroup &group) const;
bool isSubContainment(const Layout::GenericLayout *layout, const Plasma::Applet *applet) const;
bool isSubContainment(const Plasma::Corona *corona, const Plasma::Applet *applet) const;
bool hasContainment(const Layout::GenericLayout *layout, const int &id);
bool containsView(const QString &filepath, const int &viewId);
bool isClonedView(const Plasma::Containment *containment) const;
bool isClonedView(const KConfigGroup &containmentGroup) const;
void removeAllClonedViews(const QString &filepath);
int subContainmentId(const KConfigGroup &appletGroup) const;
Plasma::Containment *subContainmentOf(const Layout::GenericLayout *layout, const Plasma::Applet *applet);
Plasma::Containment *subContainmentOf(const Plasma::Corona *corona, const Plasma::Applet *applet);
void lock(const Layout::GenericLayout *layout); //! make it only read-only
void unlock(const Layout::GenericLayout *layout); //! make it writable which it should be the default
@ -72,17 +77,23 @@ public:
void updateView(KConfigGroup viewGroup, const Data::View &viewData);
QString storedView(const Layout::GenericLayout *layout, const int &containmentId); //returns temp filepath containing all view data
void moveToLayoutFile(const QString &layoutName);
QStringList storedLayoutsInMultipleFile();
void removeContainment(const QString &filepath, const QString &containmentId);
bool exportTemplate(const QString &originFile, const QString &destinationFile, const Data::AppletsTable &approvedApplets);
bool exportTemplate(const Layout::GenericLayout *layout, Plasma::Containment *containment, const QString &destinationFile, const Data::AppletsTable &approvedApplets);
int expectedViewScreenId(const Latte::Corona *corona, const Data::View &view) const;
int expectedViewScreenId(const Latte::Corona *corona, const KConfigGroup &containmentGroup) const;
int expectedViewScreenId(const Layout::GenericLayout *layout, const Plasma::Containment *lattecontainment) const;
/// STATIC
//! Check if an applet config group is valid or belongs to removed applet
static bool appletGroupIsValid(const KConfigGroup &appletGroup);
static bool isValid(const int &id);
//! AppletsData Information
Data::Applet metadata(const QString &pluginId);
Data::AppletsTable plugins(const Layout::GenericLayout *layout, const int containmentid = IDNULL);

View File

@ -6,7 +6,6 @@
#include "syncedlaunchers.h"
// local
#include <coretypes.h>
#include "../lattecorona.h"
#include "../layout/centrallayout.h"
#include "../layouts/manager.h"
@ -63,36 +62,61 @@ void SyncedLaunchers::removeClientObject(QObject *obj)
}
}
QList<QQuickItem *> SyncedLaunchers::clients(QString layoutName)
QQuickItem *SyncedLaunchers::client(const int &id)
{
if (id <= 0) {
return nullptr;
}
for(const auto client: m_clients) {
int clientid = client->property("clientId").toInt();
if (clientid == id) {
return client;
}
}
return nullptr;
}
QList<QQuickItem *> SyncedLaunchers::clients(QString layoutName, QString groupId)
{
QList<QQuickItem *> items;
if (!layoutName.isEmpty()) {
for(const auto client: m_clients) {
QString cLayoutName = client->property("layoutName").toString();
if (cLayoutName == layoutName) {
items << client;
}
for(const auto client: m_clients) {
QString cLayoutName = layoutName.isEmpty() ? QString() : client->property("layoutName").toString();
QString gid = client->property("syncedGroupId").toString();
if (cLayoutName == layoutName && gid == groupId) {
items << client;
}
} else {
items = m_clients;
}
return items;
}
void SyncedLaunchers::addLauncher(QString layoutName, int launcherGroup, QString launcher)
QList<QQuickItem *> SyncedLaunchers::clients(QString layoutName, uint senderId, Latte::Types::LaunchersGroup launcherGroup, QString launcherGroupId)
{
Types::LaunchersGroup group = static_cast<Types::LaunchersGroup>(launcherGroup);
QList<QQuickItem *> temclients;
if ((Types::LaunchersGroup)group == Types::UniqueLaunchers) {
return;
if (launcherGroup == Types::UniqueLaunchers && launcherGroupId.isEmpty()) {
//! on its own, single taskmanager
auto c = client(senderId);
if (c) {
temclients << client(senderId);
}
} else {
temclients << clients(layoutName, launcherGroupId);
}
return temclients;
}
void SyncedLaunchers::addLauncher(QString layoutName, uint senderId, int launcherGroup, QString launcherGroupId, QString launcher)
{
Types::LaunchersGroup group = static_cast<Types::LaunchersGroup>(launcherGroup);
QString lName = (group == Types::LayoutLaunchers) ? layoutName : "";
for(const auto client : clients(lName)) {
if (auto *metaObject = client->metaObject()) {
for(const auto c : clients(lName, senderId, group, launcherGroupId)) {
if (auto *metaObject = c->metaObject()) {
int methodIndex = metaObject->indexOfMethod("addSyncedLauncher(QVariant,QVariant)");
if (methodIndex == -1) {
@ -101,23 +125,18 @@ void SyncedLaunchers::addLauncher(QString layoutName, int launcherGroup, QString
}
QMetaMethod method = metaObject->method(methodIndex);
method.invoke(client, Q_ARG(QVariant, launcherGroup), Q_ARG(QVariant, launcher));
method.invoke(c, Q_ARG(QVariant, launcherGroup), Q_ARG(QVariant, launcher));
}
}
}
void SyncedLaunchers::removeLauncher(QString layoutName, int launcherGroup, QString launcher)
void SyncedLaunchers::removeLauncher(QString layoutName, uint senderId, int launcherGroup, QString launcherGroupId, QString launcher)
{
Types::LaunchersGroup group = static_cast<Types::LaunchersGroup>(launcherGroup);
if ((Types::LaunchersGroup)group == Types::UniqueLaunchers) {
return;
}
QString lName = (group == Types::LayoutLaunchers) ? layoutName : "";
for(const auto client : clients(lName)) {
if (auto *metaObject = client->metaObject()) {
for(const auto c : clients(lName, senderId, group, launcherGroupId)) {
if (auto *metaObject = c->metaObject()) {
int methodIndex = metaObject->indexOfMethod("removeSyncedLauncher(QVariant,QVariant)");
if (methodIndex == -1) {
@ -126,23 +145,18 @@ void SyncedLaunchers::removeLauncher(QString layoutName, int launcherGroup, QStr
}
QMetaMethod method = metaObject->method(methodIndex);
method.invoke(client, Q_ARG(QVariant, launcherGroup), Q_ARG(QVariant, launcher));
method.invoke(c, Q_ARG(QVariant, launcherGroup), Q_ARG(QVariant, launcher));
}
}
}
void SyncedLaunchers::addLauncherToActivity(QString layoutName, int launcherGroup, QString launcher, QString activity)
void SyncedLaunchers::addLauncherToActivity(QString layoutName, uint senderId, int launcherGroup, QString launcherGroupId, QString launcher, QString activity)
{
Types::LaunchersGroup group = static_cast<Types::LaunchersGroup>(launcherGroup);
if ((Types::LaunchersGroup)group == Types::UniqueLaunchers) {
return;
}
QString lName = (group == Types::LayoutLaunchers) ? layoutName : "";
for(const auto client : clients(lName)) {
if (auto *metaObject = client->metaObject()) {
for(const auto c : clients(lName, senderId, group, launcherGroupId)) {
if (auto *metaObject = c->metaObject()) {
int methodIndex = metaObject->indexOfMethod("addSyncedLauncherToActivity(QVariant,QVariant,QVariant)");
if (methodIndex == -1) {
@ -151,23 +165,18 @@ void SyncedLaunchers::addLauncherToActivity(QString layoutName, int launcherGrou
}
QMetaMethod method = metaObject->method(methodIndex);
method.invoke(client, Q_ARG(QVariant, launcherGroup), Q_ARG(QVariant, launcher), Q_ARG(QVariant, activity));
method.invoke(c, Q_ARG(QVariant, launcherGroup), Q_ARG(QVariant, launcher), Q_ARG(QVariant, activity));
}
}
}
void SyncedLaunchers::removeLauncherFromActivity(QString layoutName, int launcherGroup, QString launcher, QString activity)
void SyncedLaunchers::removeLauncherFromActivity(QString layoutName, uint senderId, int launcherGroup, QString launcherGroupId, QString launcher, QString activity)
{
Types::LaunchersGroup group = static_cast<Types::LaunchersGroup>(launcherGroup);
if ((Types::LaunchersGroup)group == Types::UniqueLaunchers) {
return;
}
QString lName = (group == Types::LayoutLaunchers) ? layoutName : "";
for(const auto client : clients(lName)) {
if (auto *metaObject = client->metaObject()) {
for(const auto c : clients(lName, senderId, group, launcherGroupId)) {
if (auto *metaObject = c->metaObject()) {
int methodIndex = metaObject->indexOfMethod("removeSyncedLauncherFromActivity(QVariant,QVariant,QVariant)");
if (methodIndex == -1) {
@ -176,23 +185,18 @@ void SyncedLaunchers::removeLauncherFromActivity(QString layoutName, int launche
}
QMetaMethod method = metaObject->method(methodIndex);
method.invoke(client, Q_ARG(QVariant, launcherGroup), Q_ARG(QVariant, launcher), Q_ARG(QVariant, activity));
method.invoke(c, Q_ARG(QVariant, launcherGroup), Q_ARG(QVariant, launcher), Q_ARG(QVariant, activity));
}
}
}
void SyncedLaunchers::urlsDropped(QString layoutName, int launcherGroup, QStringList urls)
void SyncedLaunchers::urlsDropped(QString layoutName, uint senderId, int launcherGroup, QString launcherGroupId, QStringList urls)
{
Types::LaunchersGroup group = static_cast<Types::LaunchersGroup>(launcherGroup);
if ((Types::LaunchersGroup)group == Types::UniqueLaunchers) {
return;
}
QString lName = (group == Types::LayoutLaunchers) ? layoutName : "";
for(const auto client : clients(lName)) {
if (auto *metaObject = client->metaObject()) {
for(const auto c : clients(lName, senderId, group, launcherGroupId)) {
if (auto *metaObject = c->metaObject()) {
int methodIndex = metaObject->indexOfMethod("dropSyncedUrls(QVariant,QVariant)");
if (methodIndex == -1) {
@ -201,26 +205,21 @@ void SyncedLaunchers::urlsDropped(QString layoutName, int launcherGroup, QString
}
QMetaMethod method = metaObject->method(methodIndex);
method.invoke(client, Q_ARG(QVariant, launcherGroup), Q_ARG(QVariant, urls));
method.invoke(c, Q_ARG(QVariant, launcherGroup), Q_ARG(QVariant, urls));
}
}
}
void SyncedLaunchers::validateLaunchersOrder(QString layoutName, uint senderId, int launcherGroup, QStringList launchers)
void SyncedLaunchers::validateLaunchersOrder(QString layoutName, uint senderId, int launcherGroup, QString launcherGroupId, QStringList launchers)
{
Types::LaunchersGroup group = static_cast<Types::LaunchersGroup>(launcherGroup);
if ((Types::LaunchersGroup)group == Types::UniqueLaunchers) {
return;
}
QString lName = (group == Types::LayoutLaunchers) ? layoutName : "";
for(const auto client : clients(lName)) {
uint clientId = client->property("clientId").toUInt();
for(const auto c : clients(lName, senderId, group, launcherGroupId)) {
auto tc = client(senderId);
if (clientId != senderId) {
if (auto *metaObject = client->metaObject()) {
if (c != tc) {
if (auto *metaObject = c->metaObject()) {
int methodIndex = metaObject->indexOfMethod("validateSyncedLaunchersOrder(QVariant,QVariant)");
if (methodIndex == -1) {
@ -229,7 +228,7 @@ void SyncedLaunchers::validateLaunchersOrder(QString layoutName, uint senderId,
}
QMetaMethod method = metaObject->method(methodIndex);
method.invoke(client, Q_ARG(QVariant, launcherGroup), Q_ARG(QVariant, launchers));
method.invoke(c, Q_ARG(QVariant, launcherGroup), Q_ARG(QVariant, launchers));
}
}
}

View File

@ -6,6 +6,9 @@
#ifndef SYNCEDLAUNCHERS_H
#define SYNCEDLAUNCHERS_H
// local
#include <coretypes.h>
// Qt
#include <QList>
#include <QObject>
@ -42,15 +45,17 @@ public slots:
Q_INVOKABLE void addAbilityClient(QQuickItem *client);
Q_INVOKABLE void removeAbilityClient(QQuickItem *client);
Q_INVOKABLE void addLauncher(QString layoutName, int launcherGroup, QString launcher);
Q_INVOKABLE void removeLauncher(QString layoutName, int launcherGroup, QString launcher);
Q_INVOKABLE void addLauncherToActivity(QString layoutName, int launcherGroup, QString launcher, QString activity);
Q_INVOKABLE void removeLauncherFromActivity(QString layoutName, int launcherGroup, QString launcher, QString activity);
Q_INVOKABLE void urlsDropped(QString layoutName, int launcherGroup, QStringList urls);
Q_INVOKABLE void validateLaunchersOrder(QString layoutName, uint senderId, int launcherGroup, QStringList launchers);
Q_INVOKABLE void addLauncher(QString layoutName, uint senderId, int launcherGroup, QString launcherGroupId, QString launcher);
Q_INVOKABLE void removeLauncher(QString layoutName, uint senderId, int launcherGroup, QString launcherGroupId, QString launcher);
Q_INVOKABLE void addLauncherToActivity(QString layoutName, uint senderId, int launcherGroup,QString launcherGroupId, QString launcher, QString activity);
Q_INVOKABLE void removeLauncherFromActivity(QString layoutName, uint senderId, int launcherGroup, QString launcherGroupId, QString launcher, QString activity);
Q_INVOKABLE void urlsDropped(QString layoutName, uint senderId, int launcherGroup, QString launcherGroupId, QStringList urls);
Q_INVOKABLE void validateLaunchersOrder(QString layoutName, uint senderId, int launcherGroup, QString launcherGroupId, QStringList launchers);
private:
QList<QQuickItem *> clients(QString layoutName = QString());
QList<QQuickItem *> clients(QString layoutName, QString groupId);
QList<QQuickItem *> clients(QString layoutName, uint senderId, Latte::Types::LaunchersGroup launcherGroup, QString launcherGroupId);
QQuickItem *client(const int &id);
private slots:
void removeClientObject(QObject *obj);

View File

@ -10,6 +10,7 @@
#include "importer.h"
#include "manager.h"
#include "../apptypes.h"
#include "../screenpool.h"
#include "../data/layoutdata.h"
#include "../lattecorona.h"
#include "../layout/centrallayout.h"
@ -191,7 +192,9 @@ QStringList Synchronizer::centralLayoutsNames()
QStringList names;
if (m_manager->memoryUsage() == MemoryUsage::SingleLayout) {
names << m_centralLayouts.at(0)->name();
if (m_centralLayouts.count() > 0) {
names << m_centralLayouts.at(0)->name();
}
} else {
for (int i = 0; i < m_centralLayouts.size(); ++i) {
CentralLayout *layout = m_centralLayouts.at(i);
@ -357,6 +360,17 @@ QList<Latte::View *> Synchronizer::currentViews() const
return views;
}
QList<Latte::View *> Synchronizer::currentOriginalViews() const
{
QList<Latte::View *> views;
for(auto layout : currentLayouts()) {
views << layout->onlyOriginalViews();
}
return views;
}
QList<Latte::View *> Synchronizer::currentViewsWithPlasmaShortcuts() const
{
QList<Latte::View *> views;
@ -370,9 +384,12 @@ QList<Latte::View *> Synchronizer::currentViewsWithPlasmaShortcuts() const
QList<Latte::View *> Synchronizer::sortedCurrentViews() const
{
QList<Latte::View *> views = currentViews();
return Layout::GenericLayout::sortedLatteViews(currentViews(), m_manager->corona()->screenPool()->primaryScreen());
}
return Layout::GenericLayout::sortedLatteViews(views);
QList<Latte::View *> Synchronizer::sortedCurrentOriginalViews() const
{
return Layout::GenericLayout::sortedLatteViews(currentOriginalViews(), m_manager->corona()->screenPool()->primaryScreen());
}
QList<Latte::View *> Synchronizer::viewsBasedOnActivityId(const QString &id) const
@ -436,7 +453,6 @@ void Synchronizer::addLayout(CentralLayout *layout)
{
if (!m_centralLayouts.contains(layout)) {
m_centralLayouts.append(layout);
layout->initToCorona(m_manager->corona());
}
}
@ -540,14 +556,14 @@ void Synchronizer::unloadCentralLayout(CentralLayout *layout)
if (pos>=0) {
CentralLayout *central = m_centralLayouts.takeAt(pos);
if (m_multipleModeInitialized) {
if (m_multipleModeInitialized && !m_manager->corona()->inQuit()) {
central->syncToLayoutFile(true);
}
central->unloadLatteViews();
central->unloadContainments();
if (m_multipleModeInitialized) {
if (m_multipleModeInitialized && !m_manager->corona()->inQuit()) {
m_manager->clearUnloadedContainmentsFromLinkedFile(central->unloadedContainmentsIds(), true);
}
@ -619,6 +635,24 @@ void Synchronizer::unloadLayouts()
m_multipleModeInitialized = false;
}
void Synchronizer::unloadPreloadedLayouts()
{
QStringList currentnames;
QStringList preloadednames = Layouts::Storage::self()->storedLayoutsInMultipleFile();
for(auto l : m_centralLayouts) {
if (l) {
currentnames << l->name();
}
}
for(auto lname : preloadednames) {
if (!currentnames.contains(lname)) {
Layouts::Storage::self()->moveToLayoutFile(lname);
}
}
}
bool Synchronizer::memoryInitialized() const
{
return ((m_manager->memoryUsage() == MemoryUsage::SingleLayout && m_centralLayouts.size()>0)
@ -642,13 +676,23 @@ bool Synchronizer::initSingleMode(QString layoutName)
//! Tasks plasmoid case that triggers layouts switching through its context menu
QTimer::singleShot(LAYOUTSINITINTERVAL, [this, layoutName, layoutpath]() {
qDebug() << " ... initializing layout in single mode : " << layoutName << " - " << layoutpath;
unloadPreloadedLayouts();
unloadLayouts();
//! load the main layout/corona file
//! load the main single layout/corona file
CentralLayout *newLayout = new CentralLayout(this, layoutpath, layoutName);
addLayout(newLayout);
m_manager->loadLatteLayout(layoutpath);
//! Order of initialization steps is very important and guarantees correct startup initialization
//! Step1: corona is set for the layout
//! Step2: containments from file are loaded into main corona
//! Step3: layout connects to corona signals and slots
//! Step4: layout is added in manager and is accesible for others to find
//! Step5: layout is attaching its initial containmens and is now considered ACTIVE
newLayout->setCorona(m_manager->corona()); //step1
m_manager->loadLatteLayout(layoutpath); //step2
newLayout->initCorona(); //step3
addLayout(newLayout); //step4
newLayout->initContainments(); //step5
emit centralLayoutsChanged();
@ -664,7 +708,7 @@ bool Synchronizer::initSingleMode(QString layoutName)
}
m_manager->corona()->universalSettings()->setSingleModeLayoutName(layoutName);
m_manager->importer()->setMultipleLayoutsStatus(Latte::MultipleLayouts::Uninitialized);
emit initializationFinished();
});
@ -687,6 +731,9 @@ bool Synchronizer::initMultipleMode(QString layoutName)
qDebug() << " ... initializing layout in multiple mode : " << layoutName ;
unloadLayouts();
QStringList layoutsinmultiplestorage = Layouts::Storage::self()->storedLayoutsInMultipleFile();
qDebug() << "Preloaded Multiple Layouts in Storage :: " << layoutsinmultiplestorage;
m_manager->loadLatteLayout(layoutPath(QString(Layout::MULTIPLELAYOUTSHIDDENNAME)));
m_multipleModeInitialized = true;
@ -697,8 +744,8 @@ bool Synchronizer::initMultipleMode(QString layoutName)
switchToLayoutInMultipleModeBasedOnActivities(layoutName);
}
syncMultipleLayoutsToActivities();
syncMultipleLayoutsToActivities(layoutsinmultiplestorage);
m_manager->importer()->setMultipleLayoutsStatus(Latte::MultipleLayouts::Running);
emit initializationFinished();
});
@ -878,7 +925,7 @@ bool Synchronizer::switchToLayout(QString layoutName, MemoryUsage::LayoutsMemory
}
}
void Synchronizer::syncMultipleLayoutsToActivities()
void Synchronizer::syncMultipleLayoutsToActivities(QStringList preloadedLayouts)
{
qDebug() << " ---- --------- ------ syncMultipleLayoutsToActivities ------- ";
qDebug() << " ---- --------- ------ ------------------------------- ------- ";
@ -899,14 +946,6 @@ void Synchronizer::syncMultipleLayoutsToActivities()
//! discover layouts assigned to explicit activities based on running activities
for (const auto &activity : runningActivities()) {
#if KF5_VERSION_MINOR < 81
if (KWindowSystem::isPlatformWayland() && (m_activitiesController->currentActivity() != activity)){
//! Wayland Protection: Plasma wayland does not support Activities for windows before kde frameworks 5.81
//! In that scenario we can load the layouts that belong OnAllActivities + (ForFreeActivities OR SpecificActivity)
continue;
}
#endif
if (m_assignedLayouts.contains(activity)) {
layoutNamesToLoad << m_assignedLayouts[activity];
}
@ -919,6 +958,12 @@ void Synchronizer::syncMultipleLayoutsToActivities()
}
}
for (const auto lname : preloadedLayouts) {
if (!layoutNamesToLoad.contains(lname)) {
layoutNamesToUnload << lname;
}
}
QString defaultForcedLayout;
//! Safety
@ -939,8 +984,20 @@ void Synchronizer::syncMultipleLayoutsToActivities()
if (newLayout) {
qDebug() << "ACTIVATING LAYOUT ::::: " << layoutname;
addLayout(newLayout);
newLayout->importToCorona();
//! Order of initialization steps is very important and guarantees correct startup initialization
//! Step1: corona is set for the layout
//! Step2: containments from the layout file are adjusted and are imported into main corona
//! Step3: layout connects to corona signals and slots
//! Step4: layout is added in manager and is accesible for others to find
//! Step5: layout is attaching its initial containmens and is now considered ACTIVE
newLayout->setCorona(m_manager->corona()); //step1
if (!preloadedLayouts.contains(layoutname)) {
newLayout->importToCorona(); //step2
}
newLayout->initCorona(); //step3
addLayout(newLayout); //step4
newLayout->initContainments(); //step5
if (!defaultForcedLayout.isEmpty() && defaultForcedLayout == layoutname) {
emit newLayoutAdded(newLayout->data());
@ -967,8 +1024,8 @@ void Synchronizer::syncMultipleLayoutsToActivities()
emit currentLayoutIsSwitching(layoutname);
}
QTimer::singleShot(LAYOUTSINITINTERVAL, [this, layoutNamesToUnload]() {
unloadLayouts(layoutNamesToUnload);
QTimer::singleShot(LAYOUTSINITINTERVAL, [this, layoutNamesToUnload, preloadedLayouts]() {
unloadLayouts(layoutNamesToUnload, preloadedLayouts);
});
}
@ -980,7 +1037,7 @@ void Synchronizer::syncMultipleLayoutsToActivities()
}
}
void Synchronizer::unloadLayouts(const QStringList &layoutNames)
void Synchronizer::unloadLayouts(const QStringList &layoutNames, const QStringList &preloadedLayouts)
{
if (layoutNames.isEmpty()) {
return;
@ -995,11 +1052,19 @@ void Synchronizer::unloadLayouts(const QStringList &layoutNames)
qDebug() << "REMOVING LAYOUT ::::: " << layoutname;
m_centralLayouts.removeAt(posLayout);
layout->syncToLayoutFile(true);
if (!m_manager->corona()->inQuit()) {
layout->syncToLayoutFile(true);
}
layout->unloadContainments();
layout->unloadLatteViews();
m_manager->clearUnloadedContainmentsFromLinkedFile(layout->unloadedContainmentsIds());
if (!m_manager->corona()->inQuit()) {
m_manager->clearUnloadedContainmentsFromLinkedFile(layout->unloadedContainmentsIds());
}
delete layout;
} else if (preloadedLayouts.contains(layoutname)) {
Layouts::Storage::self()->moveToLayoutFile(layoutname);
//! just make sure that
}
}
@ -1017,7 +1082,7 @@ void Synchronizer::updateKWinDisabledBorders()
if (!m_manager->corona()->universalSettings()->canDisableBorders()) {
m_manager->corona()->universalSettings()->kwin_setDisabledMaximizedBorders(false);
} else {
if (m_manager->corona()->layoutsManager()->memoryUsage() == MemoryUsage::SingleLayout) {
if (m_manager->corona()->layoutsManager()->memoryUsage() == MemoryUsage::SingleLayout && m_centralLayouts.size() > 0) {
m_manager->corona()->universalSettings()->kwin_setDisabledMaximizedBorders(m_centralLayouts.at(0)->disableBordersForMaximizedWindows());
} else if (m_manager->corona()->layoutsManager()->memoryUsage() == MemoryUsage::MultipleLayouts) {
QList<CentralLayout *> centrals = centralLayoutsForActivity(m_manager->corona()->activitiesConsumer()->currentActivity());

View File

@ -15,6 +15,7 @@
#include <QObject>
#include <QHash>
#include <QTimer>
#include <QStringList>
namespace Latte {
@ -65,7 +66,7 @@ public:
void pauseLayout(QString layoutName);
void syncActiveLayoutsToOriginalFiles();
void syncLatteViewsToScreens();
void syncMultipleLayoutsToActivities();
void syncMultipleLayoutsToActivities(QStringList preloadedLayouts = QStringList());
//! In that case single layout file must be removed after loading the new layout
void setIsSingleLayoutInDeprecatedRenaming(const bool &enabled);
@ -95,7 +96,9 @@ public:
QList<CentralLayout *> currentLayouts() const;
QList<Latte::View *> currentViews() const;
QList<Latte::View *> currentViewsWithPlasmaShortcuts() const;
QList<Latte::View *> currentOriginalViews() const;
QList<Latte::View *> sortedCurrentViews() const;
QList<Latte::View *> sortedCurrentOriginalViews() const;
QList<Latte::View *> viewsBasedOnActivityId(const QString &id) const;
CentralLayout *centralLayout(QString layoutname) const;
@ -130,13 +133,14 @@ private slots:
void onActivityRemoved(const QString &activityid);
void onLayoutAdded(const QString &layoutpath);
void unloadPreloadedLayouts();
void reloadAssignedLayouts();
void updateBorderlessMaximizedAfterTimer();
private:
void addLayout(CentralLayout *layout);
void unloadCentralLayout(CentralLayout *layout);
void unloadLayouts(const QStringList &layoutNames);
void unloadLayouts(const QStringList &layoutNames, const QStringList &preloadedLayouts);
bool initSingleMode(QString layoutName);
bool initMultipleMode(QString layoutName);

View File

@ -25,9 +25,11 @@
#include <QDBusConnection>
#include <QDBusInterface>
#include <QDir>
#include <QFile>
#include <QLockFile>
#include <QSessionManager>
#include <QSharedMemory>
#include <QTextStream>
// KDE
#include <KCrash>
@ -50,6 +52,7 @@ inline void detectPlatform(int argc, char **argv);
inline void filterDebugMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg);
QString filterDebugMessageText;
QString filterDebugLogFile;
int main(int argc, char **argv)
{
@ -70,9 +73,11 @@ int main(int argc, char **argv)
QQuickWindow::setDefaultAlphaBuffer(true);
qputenv("QT_WAYLAND_DISABLE_FIXED_POSITIONS", {});
const bool qpaVariable = qEnvironmentVariableIsSet("QT_QPA_PLATFORM");
detectPlatform(argc, argv);
QApplication app(argc, argv);
qunsetenv("QT_WAYLAND_DISABLE_FIXED_POSITIONS");
if (!qpaVariable) {
// don't leak the env variable to processes we start
@ -171,6 +176,12 @@ int main(int argc, char **argv)
filterDebugEventSinkMask.setDescription(QStringLiteral("Show visual indicators for areas of EventsSink."));
filterDebugEventSinkMask.setFlags(QCommandLineOption::HiddenFromHelp);
parser.addOption(filterDebugEventSinkMask);
QCommandLineOption filterDebugLogCmd(QStringList() << QStringLiteral("log-file"));
filterDebugLogCmd.setDescription(QStringLiteral("Forward debug output in a log text file."));
filterDebugLogCmd.setFlags(QCommandLineOption::HiddenFromHelp);
filterDebugLogCmd.setValueName(i18nc("command line: log-filepath", "filter_log_filepath"));
parser.addOption(filterDebugLogCmd);
//! END: Hidden options
parser.process(app);
@ -398,6 +409,11 @@ int main(int argc, char **argv)
filterDebugMessageText = parser.value(QStringLiteral("debug-text"));
}
//! log file for debug output
if (parser.isSet(QStringLiteral("log-file")) && !parser.value(QStringLiteral("log-file")).isEmpty()) {
filterDebugLogFile = parser.value(QStringLiteral("log-file"));
}
//! debug/mask options
if (parser.isSet(QStringLiteral("debug")) || parser.isSet(QStringLiteral("mask")) || parser.isSet(QStringLiteral("debug-text"))) {
qInstallMessageHandler(filterDebugMessageOutput);
@ -406,7 +422,6 @@ int main(int argc, char **argv)
qInstallMessageHandler(noMessageOutput);
}
auto signal_handler = [](int) {
qGuiApp->exit();
};
@ -467,14 +482,21 @@ inline void filterDebugMessageOutput(QtMsgType type, const QMessageLogContext &c
TypeColor = CRED;
} else {
TypeColor = CIGREEN;
}
qDebug().nospace() << TypeColor << "[" << typeStr.toStdString().c_str() << " : " << CGREEN << QTime::currentTime().toString("h:mm:ss.zz").toStdString().c_str() << TypeColor << "]" << CNORMAL
#ifndef QT_NO_DEBUG
<< CIRED << " [" << CCYAN << function << CIRED << ":" << CCYAN << context.line << CIRED << "]"
#endif
<< CICYAN << " - " << CNORMAL << msg;
if (filterDebugLogFile.isEmpty()) {
qDebug().nospace() << TypeColor << "[" << typeStr.toStdString().c_str() << " : " << CGREEN << QTime::currentTime().toString("h:mm:ss.zz").toStdString().c_str() << TypeColor << "]" << CNORMAL
#ifndef QT_NO_DEBUG
<< CIRED << " [" << CCYAN << function << CIRED << ":" << CCYAN << context.line << CIRED << "]"
#endif
<< CICYAN << " - " << CNORMAL << msg;
} else {
QFile logfile(filterDebugLogFile);
logfile.open(QIODevice::WriteOnly | QIODevice::Append);
QTextStream logts(&logfile);
logts << "[" << typeStr.toStdString().c_str() << " : " << QTime::currentTime().toString("h:mm:ss.zz").toStdString().c_str() << "]"
<< " - " << msg << Qt::endl;
}
}
inline void configureAboutData()

View File

@ -4,7 +4,6 @@
<extends>org.kde.plasmashell</extends>
<name>Latte</name>
<name xml:lang="ar">لاتيه</name>
<name xml:lang="ast">Latte</name>
<name xml:lang="az">Latte</name>
<name xml:lang="ca">Latte</name>
<name xml:lang="ca-valencia">Latte</name>
@ -13,6 +12,7 @@
<name xml:lang="de">Latte</name>
<name xml:lang="el">Latte</name>
<name xml:lang="en-GB">Latte</name>
<name xml:lang="eo">Latte</name>
<name xml:lang="es">Latte</name>
<name xml:lang="et">Latte</name>
<name xml:lang="eu">Latte</name>
@ -22,6 +22,7 @@
<name xml:lang="ia">Latte</name>
<name xml:lang="id">Latte</name>
<name xml:lang="it">Latte</name>
<name xml:lang="ka">Latte</name>
<name xml:lang="ko">Latte</name>
<name xml:lang="lt">Latte</name>
<name xml:lang="nl">Latte</name>
@ -40,7 +41,6 @@
<name xml:lang="zh-TW">Latte</name>
<summary>Dock for the masses</summary>
<summary xml:lang="ar">رصيف للأمور الكبيرة</summary>
<summary xml:lang="ast">Árees d'anclaxe pa les mases</summary>
<summary xml:lang="az">Hər kəs üçün Dok panel</summary>
<summary xml:lang="ca">Acoblador per a les masses</summary>
<summary xml:lang="ca-valencia">Acoblador per a les masses</summary>
@ -49,6 +49,7 @@
<summary xml:lang="de">Dock für die Massen</summary>
<summary xml:lang="el">Πίνακες εφαρμογών για όλον τον κόσμο</summary>
<summary xml:lang="en-GB">Dock for the masses</summary>
<summary xml:lang="eo">Doko por la amasoj</summary>
<summary xml:lang="es">Un dock para las masas</summary>
<summary xml:lang="et">Dokk massidele</summary>
<summary xml:lang="eu">Jendartearen kaia</summary>
@ -68,33 +69,33 @@
<summary xml:lang="sk">Dok pre masy</summary>
<summary xml:lang="sl">Dok za množice</summary>
<summary xml:lang="sv">Dockningsfönster för alla</summary>
<summary xml:lang="tr">Kitleler için kilitleme</summary>
<summary xml:lang="tr">Kitleler için rıhtım</summary>
<summary xml:lang="uk">Панель для усіх</summary>
<summary xml:lang="x-test">xxDock for the massesxx</summary>
<summary xml:lang="zh-CN">使</summary>
<summary xml:lang="zh-CN">使</summary>
<summary xml:lang="zh-TW">使 Dock</summary>
<description>
<p>Latte is a dock based on plasma frameworks that provides an elegant and intuitive experience for your tasks and plasmoids. It animates its contents by using parabolic zoom effect and tries to be there only when it is needed.</p>
<p xml:lang="ar">«لاتيه» هو رصيف مبنيّ على أُطر عمل «بلازما» حيث يقدّم تجربة أنيقة وبدهيّة لمهامك والبلازمويد لديك. يعمل الرّصيف على إنشاء حركة للمحتويات باستخدام تأثير تقريب القطع المكافئ، ويحاول أن يكون بمتناول يديك عند حاجتك إليه فقط.</p>
<p xml:lang="ast">Latte ye un área d'anclaxe basáu nos frameworks de Plasma qu'apurren una esperiencia elegante ya intuitiva pa xeres y plasmoides. Anima'l so conteníu usando l'efeutu de zoom parabólicu y tenta d'amosase namás cuando se precisa.</p>
<p xml:lang="az">Latte, plasma iş çərçivələrinə əsaslanan, tapşırıq və plasmoid'ləriniz üçün rahat istifadə oluna bilən, zərif və intiutiv bir Dok Panelidir. O tərkibində yerləşən nişanları parabolik böyütmə effekti ilə canlandırır və yalnız lazım olduqda görünməyə çalışır.</p>
<p xml:lang="ca">El Latte és un acoblador basat en els Frameworks del Plasma que proporciona una experiència elegant i intuïtiva per a les vostres tasques i els plasmoides. Anima els seus continguts usant un efecte de zoom parabòlic i intenta mostrar-se només quan cal.</p>
<p xml:lang="ca-valencia">El Latte és un acoblador basat en els Frameworks del Plasma que proporciona una experiència elegant i intuïtiva per a les vostres tasques i els plasmoides. Anima els seus continguts usant un efecte de zoom parabòlic i intenta mostrar-se només quan cal.</p>
<p xml:lang="ca-valencia">Latte és un acoblador basat en els Frameworks de Plasma que proporciona una experiència elegant i intuïtiva per a les vostres tasques i els plasmoides. Anima els seus continguts utilitzant un efecte de zoom parabòlic i intenta mostrar-se només quan cal.</p>
<p xml:lang="da">Latte er en dok som er baseret på plasma-frameworks som giver en elegant og intuitiv oplevelse til dine opgaver og plasmoids. Den animerer dens indhold med parabolsk zoom og prøver på kun at være der når der er brug for det.</p>
<p xml:lang="de">Latte-Dock ist ein auf Plasma-Framework-Technologie basierendes Dock für Anwendungen und Plasmoide, das ein elegantes und intuitives Nutzererlebnis bietet.Seine Inhalte werden mithilfe parabolischer Zoom-Effekte animiert. Latte versucht, immer zur Stelle zu sein, wenn es benötigt wird.</p>
<p xml:lang="el">Το Latte είναι ένας πίνακας εφαρμογών βασισμένος στις βιβλιοθήκες plasma που εστιάζει στην καλαισθησία και παρέχει ένα όμορφο περιβάλλον για τις εργασίες και τα γραφικά συστατικά σας. Χρησιμοποιεί το παραβολικό εφέ έτσι ώστε να απεικονίσει τα περιεχόμενα του και προσπαθεί να είναι εκεί μόνο όταν το χρειάζεστε.</p>
<p xml:lang="en-GB">Latte is a dock based on plasma frameworks that provides an elegant and intuitive experience for your tasks and plasmoids. It animates its contents by using parabolic zoom effect and tries to be there only when it is needed.</p>
<p xml:lang="eo">Latte estas doko bazita sur plasma-frameworks kiu provizas elegantan kaj intuician sperton por viaj taskoj kaj plasmoidoj. Ĝi animas sian enhavon uzante parabolan zomefikon kaj provas esti tie nur kiam ĝi estas bezonata.</p>
<p xml:lang="es">Latte es un dock basado en la infraestructura plasma que proporciona una experiencia intuitiva y elegante para sus tareas y plasmoides. Anima sus contenidos usando un efecto de zoom parabólico e intenta estar presente solo cuando se le necesita.</p>
<p xml:lang="et">Latte on Plasma raamistikul põhinev dokk, mis pakub elegantset ja loomupärast kogemust ülesannete ja plasmoididega majandamisel. Sisu animeeritakse paraboolse suurenduse efekti abil ning dokk püüab olla alati sinu käsutuses, kui sa seda vajad.</p>
<p xml:lang="eu">Plasma frameworks-en oinarritutako kaia da Latte, bizipen eder eta intuitiboa hornitzen duena zure ataza eta aplikaziotxoentzat. Honek bere edukiak animatzen ditu zoom parabolikoaren efektua erabiliz eta bertan behar denean bakarrik egoten saiatzen da.</p>
<p xml:lang="fi">Latte on Plasma Frameworksiin perustuva telakka, joka tarjoaa tyylikkään ja intuitiivisen tehtävä- ja sovelmakäyttöliittymän. Se animoi sisältönsä parabolisella lähennystehosteella ja yrittää pysyä poissa, kunnes sitä tarvitaan.</p>
<p xml:lang="fr">Latte est une barre des tâches conçue à partir de l'environnement de développement de Plasma. Il propose une expérience élégante et intuitive pour vos tâches et pour vos composants graphiques. Son contenu est animé grâce à l'utilisation d'un effet de zoom parabolique. Il n'essaie d'être là que lorsque cela est nécessaire.</p>
<p xml:lang="gl">Latte é unha doca construída coas infraestruturas de Plasma que fornece unha experiencia elegante e intuitiva para as súas tarefas e plasmoides. Anima o seu contido usando o efecto de ampliación parabólico e intenta estar aí só cando se necesita.</p>
<p xml:lang="gl">Latte é unha doca construída coas infraestruturas de Plasma que fornece unha experiencia elegante e intuitiva para as súas tarefas e trebellos. Anima o seu contido usando o efecto de ampliación parabólico e intenta estar aí só cando se necesita.</p>
<p xml:lang="id">Latte adalah dock berdasarkan kerangka kerja plasma yang memberikan pengalaman yang elegan dan intuitif untuk tugas dan plasmoid kamu. Ini menganimasikan konten dengan menggunakan efek zoom parabola dan mencoba untuk berada di sana hanya ketika diperlukan.</p>
<p xml:lang="it">Latte è un'area di aggancio basata su plasma frameworks. Offre ai tuoi processi e ai tuoi plasmoidi un'esperienza elegante ed intuitiva, animando il loro contenuto con un effetto zoom parabolico e facendosi trovare solo quando necessario.</p>
<p xml:lang="ko">Latte plasmoids . / .</p>
<p xml:lang="lt">Latte yra Plasma karkasu pagrįstas dokas, kuris teikia elegantišką ir intuityvų jūsų užduočių ir Plasma įskiepių patyrimą. Jis animuoja savo turinį naudodamas parabolinį mastelio efektą ir stengiasi pasirodyti tik tuomet, kai jo reikia.</p>
<p xml:lang="nl">Latte is een dock gebaseerd op plasma frameworks die een elegante en intuïtieve ervaring voor uw taken en plasmoids is. Het animeert zijn inhoud door een parabolisch zoomeffect te gebruiken en probeert er alleen te zijn wanneer nodig.</p>
<p xml:lang="nl">Latte voorziet uw desktop van Docks of Panelen met behulp waarvan u uw taken en widgets op een elegante en eenvoudige manier kunt beheren. Latte animeert de inhoud m.b.v. parabolische effecten in macOS-stijl en probeert er alleen te zijn wanneer dat nodig is. </p>
<p xml:lang="nn">Latte er ei dokk basert på Plasma-rammeverket og som gjev elegant og intuitiv tilgang til program/oppgåver og skjerm­element. Innhaldet vert animerte med parabolske forstørrings­effektar og programmet prøver å ikkje vera i vegen når det ikkje trengst.</p>
<p xml:lang="pl">Latte jest dokiem opartym na szkieletach plazmy, który zapewnia przyjemne i intuicyjne odczucia w pracy z zadaniami i plazmoidami. Animuje swoją zawartośc przy użyciu efektu przybliżenia parabolicznego i próbuje być widocznym tylko wtedy, gdy jest potrzebny.</p>
<p xml:lang="pt">O Latte é uma área acoplável baseada nas plataformas do Plasma que oferece uma experiência elegante e intuitiva para as suas tarefas e plasmóides. Ele anima o seu conteúdo, usando um efeito de ampliação parabólico e tenta estar apenas onde for necessário.</p>
@ -103,14 +104,13 @@
<p xml:lang="sk">Latte je dok založený na frameworkoch plasma, ktorý poskytuje elegantné a intuitívne rozhranie pre vaše úlohy a plazmoidy. Animuje svoj obsah použitím parabolického efektu priblíženia a snaží sa by tam len vtedy, keď je to treba.</p>
<p xml:lang="sl">Latte je dok, ki temelji v okolju Plasma Frameworka, ki zagotavlja elegantno in intuitivno izkušnjo za vaše naloge in plazmoide. Svojo vsebino animiraz uporabo učinka paraboličnega povečevanja in poskuša biti tam le, kadar je to potrebno.</p>
<p xml:lang="sv">Latte är ett dockningsfönster baserat på Plasma ramverk som erbjuder en elegant och intuitiv upplevelse för aktiviteter och Plasmoider. Det animerar innehållet genom att använda en paraboleffekt för zoomning, och försöker bara vara där när det behövs.</p>
<p xml:lang="tr">Latte, görevleriniz ve plasmoidleriniz için zarif ve sezgisel bir deneyim sağlayan plazma çerçevelerine dayalı bir yuvadır. İçeriğini parabolik yakınlaştırma efekti kullanarak canlandırır ve sadece ihtiyaç duyulduğunda orada olmaya çalışır.</p>
<p xml:lang="tr">Latte, görevleriniz ve Plasmoid'leriniz için zarif ve sezgisel bir deneyim sağlayan Plasma kod kitaplıklarını kullanan bir rıhtımdır. İçeriğini parabolik yakınlaştırma efekti kullanarak canlandırır ve yalnızca gereksinim duyulduğunda orada olmaya çalışır.</p>
<p xml:lang="uk">Латте панель на основі бібліотек Плазми, яка забезпечує елегантний і інтуїтивно зрозумілий доступ до ваших завдань та плазмоїдів. Вміст панелі анімується за допомогою ефекту параболічного збільшення і показується лише тоді, коли це потрібно.</p>
<p xml:lang="x-test">xxLatte is a dock based on plasma frameworks that provides an elegant and intuitive experience for your tasks and plasmoids. It animates its contents by using parabolic zoom effect and tries to be there only when it is needed.xx</p>
<p xml:lang="zh-CN">Latte plasma plasmoid 线</p>
<p xml:lang="zh-CN">Latte Plasma Plasma 使线</p>
<p xml:lang="zh-TW">Latte Plasma plasmoid dock使</p>
<p> "Art In Coffee" </p>
<p xml:lang="ar">الفنّ في القهوة</p>
<p xml:lang="ast">«Arte nel café»</p>
<p xml:lang="az">"Qəhvədə İncəsənət"</p>
<p xml:lang="ca">«Art al cafè»</p>
<p xml:lang="ca-valencia">«Art al cafè»</p>
@ -119,6 +119,7 @@
<p xml:lang="de">Art In Coffee</p>
<p xml:lang="el">"Τέχνη στον Καφέ"</p>
<p xml:lang="en-GB">"Art In Coffee"</p>
<p xml:lang="eo">"Arto En Kafo"</p>
<p xml:lang="es">"El arte en el café"</p>
<p xml:lang="et">"Kohvikunst"</p>
<p xml:lang="eu">"Artea kafean"</p>
@ -127,6 +128,7 @@
<p xml:lang="gl">«Arte en café».</p>
<p xml:lang="id">"Art In Coffee"</p>
<p xml:lang="it">«Art In Coffee»</p>
<p xml:lang="ka">" "</p>
<p xml:lang="ko">" "</p>
<p xml:lang="lt">"Menas kavoje"</p>
<p xml:lang="nl">"Kunst in koffie"</p>
@ -152,7 +154,7 @@
<url type="bugtracker">@BUG_ADDRESS@</url>
<url type="faq">@FAQS@</url>
<developer_name>Michail Vourlakos, Johan Smith Agudelo Rodriguez</developer_name>
<developer_name xml:lang="ast">Michail Vourlakos y Johan Smith Agudelo Rodriguez</developer_name>
<developer_name xml:lang="ar">ميخائيل فورلاكوس، يوهان سميث أجوديلو رودريجيز</developer_name>
<developer_name xml:lang="az">Michail Vourlakos, Johan Smith Agudelo Rodriguez</developer_name>
<developer_name xml:lang="ca">Michail Vourlakos, Johan Smith Agudelo Rodriguez</developer_name>
<developer_name xml:lang="ca-valencia">Michail Vourlakos, Johan Smith Agudelo Rodriguez</developer_name>
@ -160,6 +162,7 @@
<developer_name xml:lang="de">Michail Vourlakos, Johan Smith Agudelo Rodriguez</developer_name>
<developer_name xml:lang="el">Michail Vourlakos, Johan Smith Agudelo Rodriguez</developer_name>
<developer_name xml:lang="en-GB">Michail Vourlakos, Johan Smith Agudelo Rodriguez</developer_name>
<developer_name xml:lang="eo">Michail Vourlakos, Johan Smith Agudelo Rodriguez</developer_name>
<developer_name xml:lang="es">Michail Vourlakos, Johan Smith Agudelo Rodriguez</developer_name>
<developer_name xml:lang="et">Michail Vourlakos, Johan Smith Agudelo Rodriguez</developer_name>
<developer_name xml:lang="eu">Michail Vourlakos, Johan Smith Agudelo Rodriguez</developer_name>
@ -169,6 +172,7 @@
<developer_name xml:lang="ia">Michail Vourlakos, Johan Smith Agudelo Rodriguez</developer_name>
<developer_name xml:lang="id">Michail Vourlakos, Johan Smith Agudelo Rodriguez</developer_name>
<developer_name xml:lang="it">Michail Vourlakos, Johan Smith Agudelo Rodriguez</developer_name>
<developer_name xml:lang="ka">Michail Vourlakos, Johan Smith Agudelo Rodriguez</developer_name>
<developer_name xml:lang="ko">Michail Vourlakos, Johan Smith Agudelo Rodriguez</developer_name>
<developer_name xml:lang="lt">Michail Vourlakos, Johan Smith Agudelo Rodriguez</developer_name>
<developer_name xml:lang="nl">Michail Vourlakos, Johan Smith Agudelo Rodriguez</developer_name>

View File

@ -1,39 +1,42 @@
[Desktop Entry]
Name=Latte
Name[ast]=Latte
Name[az]=Latte
Name[ca]=Latte
Name[ca@valencia]=Latte
Name[cs]=Latte
Name[da]=Latte
Name[de]=Latte
Name[el]=Latte
Name[en_GB]=Latte
Name[es]=Latte
Name[et]=Latte
Name[eu]=Latte
Name[fi]=Latte
Name[fr]=Latte
Name[gl]=Latte
Name[hsb]=Latte
Name[id]=Latte
Name[it]=Latte
Name[ko]=Latte
Name[lt]=Latte
Name[nl]=Latte
Name[nn]=Latte
Name[pl]=Latte
Name[pt]=Latte
Name[pt_BR]=Latte
Name[ru]=Latte
Name[sk]=Latte
Name[sl]=Latte
Name[sv]=Latte
Name[uk]=Латте
Name[x-test]=xxLattexx
Name[zh_CN]=Latte
Name[zh_TW]=Latte
Name=Latte Dock
Name[ar]=رصيف لاتيه
Name[az]=Latte Dok Paneli
Name[ca]=Acoblador Latte
Name[ca@valencia]=Acoblador Latte
Name[cs]=Dok Latte
Name[da]=Latte-dok
Name[de]=Latte-Dock
Name[el]=Latte Dock
Name[en_GB]=Latte Dock
Name[eo]=Latte Doko
Name[es]=Latte Dock
Name[et]=Latte dokk
Name[eu]=Latte Dock
Name[fi]=Latte-telakka
Name[fr]=Barre des tâches de Latte
Name[gl]=Doca Latte
Name[hsb]=Latte pas
Name[id]=Dock Latte
Name[it]=Latte Dock
Name[ko]=Latte
Name[lt]=Latte dokas
Name[nl]=Latte Dock
Name[nn]=Latte-dokk
Name[pl]=Dok Latte
Name[pt]=Área Acoplável do Latte
Name[pt_BR]=Latte Dock
Name[ru]=Latte Dock
Name[sk]=Dok Latte
Name[sl]=Latte Dock
Name[sv]=Latte dockningsfönster
Name[tr]=Latte Rıhtım
Name[uk]=Панель Латте
Name[x-test]=xxLatte Dockxx
Name[zh_CN]=Latte
Name[zh_TW]=Latte Dock
Comment=Dock for the masses
Comment[ar]=رصيف للأمور الكبيرة
Comment[az]=Hər kəs üçün Dok panel
Comment[ca]=Acoblador per a les masses
Comment[ca@valencia]=Acoblador per a les masses
@ -42,6 +45,7 @@ Comment[da]=Dok til masserene
Comment[de]=Dock für die Massen
Comment[el]=Διαχειριστής εργασιών για όλον τον κόσμο
Comment[en_GB]=Dock for the masses
Comment[eo]=Doko por la masoj
Comment[es]=Un dock para las masas
Comment[et]=Dokk massidele
Comment[eu]=Jendartearen kaia
@ -51,6 +55,7 @@ Comment[gl]=Doca para as masas.
Comment[hsb]=Pas za wšěch
Comment[id]=Dock untuk mengumpulkan
Comment[it]=Area di aggancio per le masse
Comment[ja]=
Comment[ko]=
Comment[lt]=Dokas masėms
Comment[nl]=Dock voor de massa
@ -62,11 +67,13 @@ Comment[ru]=Док для всех
Comment[sk]=Dok pre davy ľudí
Comment[sl]=Dok za množice
Comment[sv]=Dockningsfönster för alla
Comment[tr]=Kitleler için rıhtım
Comment[uk]=Панель для усіх
Comment[x-test]=xxDock for the massesxx
Comment[zh_CN]=使
Comment[zh_TW]=使 Dock
GenericName=Dock
GenericName[ar]=مرسى
GenericName[az]=Dok
GenericName[ca]=Acobla
GenericName[ca@valencia]=Acobla
@ -75,6 +82,7 @@ GenericName[da]=Dok
GenericName[de]=Dock
GenericName[el]=Dock
GenericName[en_GB]=Dock
GenericName[eo]=Doko
GenericName[es]=Dock
GenericName[et]=Dokk
GenericName[eu]=Kaia
@ -85,6 +93,8 @@ GenericName[hsb]=Pas
GenericName[ia]=Bassino
GenericName[id]=Dok
GenericName[it]=Aggancio
GenericName[ja]=
GenericName[ka]=
GenericName[ko]=
GenericName[lt]=Dokas
GenericName[nl]=Dock
@ -96,6 +106,7 @@ GenericName[ru]=Док
GenericName[sk]=Dok
GenericName[sl]=Dok
GenericName[sv]=Dockningsfönster
GenericName[tr]=Rıhtım
GenericName[uk]=Панель
GenericName[x-test]=xxDockxx
GenericName[zh_CN]=

View File

@ -1,8 +1,5 @@
set(indicator_SRCS
indicatorpackage.cpp
)
add_library(latte_packagestructure_indicator MODULE ${indicator_SRCS})
kcoreaddons_add_plugin(latte_packagestructure_indicator SOURCES indicatorpackage.cpp INSTALL_NAMESPACE kpackage/packagestructure)
set_target_properties(latte_packagestructure_indicator PROPERTIES OUTPUT_NAME latte_indicator)
target_link_libraries(latte_packagestructure_indicator
KF5::Declarative
@ -10,7 +7,4 @@ target_link_libraries(latte_packagestructure_indicator
KF5::Package
)
kcoreaddons_desktop_to_json(latte_packagestructure_indicator latte-packagestructure-indicator.desktop)
install(TARGETS latte_packagestructure_indicator DESTINATION ${KDE_INSTALL_PLUGINDIR}/kpackage/packagestructure)
install(FILES latte-indicator.desktop DESTINATION ${KDE_INSTALL_KSERVICETYPES5DIR})

View File

@ -19,10 +19,6 @@ IndicatorPackage::IndicatorPackage(QObject *parent, const QVariantList &args)
{
}
IndicatorPackage::~IndicatorPackage()
{
}
void IndicatorPackage::initPackage(KPackage::Package *package)
{
package->setDefaultPackageRoot(QStringLiteral("latte/indicators"));
@ -36,6 +32,6 @@ void IndicatorPackage::initPackage(KPackage::Package *package)
}
K_EXPORT_KPACKAGE_PACKAGE_WITH_JSON(Latte::IndicatorPackage, "latte-packagestructure-indicator.json")
K_PLUGIN_CLASS_WITH_JSON(Latte::IndicatorPackage, "latte-packagestructure-indicator.json")
#include "indicatorpackage.moc"

View File

@ -19,11 +19,9 @@ class IndicatorPackage : public KPackage::PackageStructure
Q_OBJECT
public:
explicit IndicatorPackage(QObject *parent = 0, const QVariantList &args = QVariantList());
~IndicatorPackage() override;
explicit IndicatorPackage(QObject *parent, const QVariantList &args );
void initPackage(KPackage::Package *package) override;
//void pathChanged(KPackage::Package *package) override;
};
}

View File

@ -3,21 +3,24 @@ Type=ServiceType
X-KDE-ServiceType=Latte/Indicator
Comment=Latte indicator
Comment[ar]=مؤشرات لاتيه
Comment[az]=Latte İndikatoru
Comment[ca]=Indicador del Latte
Comment[ca@valencia]=Indicador del Latte
Comment[ca@valencia]=Indicador de Latte
Comment[cs]=Ukazatel Latte
Comment[el]=Δείκτης Latte
Comment[en_GB]=Latte indicator
Comment[eo]=Latte indikilo
Comment[es]=Indicador Latte
Comment[et]=Latte indikaator
Comment[eu]=Latte adierazlea
Comment[fi]=Latte-ilmaisin
Comment[fr]=Indicateur de Latte
Comment[gl]=Indicador de Latte
Comment[gl]=Indicador de Latte.
Comment[hsb]=Latte pokazowak
Comment[id]=Indikator latte
Comment[it]=Indicatore Latte
Comment[ja]=Latte
Comment[ko]=Latte
Comment[lt]=Latte indikatorius
Comment[nl]=Indicator van Latte
@ -29,6 +32,7 @@ Comment[ru]=Индикатор Latte
Comment[sk]=Latte indicator
Comment[sl]=Kazalnik Latte
Comment[sv]=Latte indikator
Comment[tr]=Latte göstergesi
Comment[uk]=Індикатор Латте
Comment[x-test]=xxLatte indicatorxx
Comment[zh_CN]=Latte

View File

@ -1,40 +0,0 @@
[Desktop Entry]
Name=Indicator
Name[az]=İndikator
Name[ca]=Indicador
Name[ca@valencia]=Indicador
Name[cs]=Ukazatel
Name[el]=Δείκτης
Name[en_GB]=Indicator
Name[es]=Indicador
Name[et]=Indikaator
Name[eu]=Adierazlea
Name[fi]=Ilmaisin
Name[fr]=Indicateur
Name[gl]=Indicador
Name[hsb]=Pokazowak
Name[id]=Indikator
Name[it]=Indicatore
Name[ko]=
Name[lt]=Indikatorius
Name[nl]=Indicator
Name[nn]=Markør
Name[pl]=Wskaźnik
Name[pt]=Indicador
Name[pt_BR]=Indicador
Name[ru]=Индикатор
Name[sk]=Indikátor
Name[sl]=Kazalnik
Name[sv]=Indikator
Name[uk]=Індикатор
Name[x-test]=xxIndicatorxx
Name[zh_CN]=
Name[zh_TW]=
Type=Service
X-KDE-ServiceTypes=KPackage/PackageStructure
X-KDE-Library=latte_packagestructure_indicator
X-KDE-PluginInfo-Author=Michail Vourlakos
X-KDE-PluginInfo-Email=mvourlakos@gmail.com
X-KDE-PluginInfo-Name=Latte/Indicator
X-KDE-PluginInfo-Version=1
X-KDE-ParentApp=org.kde.latte-dock

View File

@ -0,0 +1,4 @@
{
"KPackageStructure": "Latte/Indicator",
"X-KDE-ParentApp": "org.kde.latte-dock"
}

View File

@ -52,6 +52,7 @@ BackgroundCache::BackgroundCache(QObject *parent)
if (!m_pool) {
m_pool = new ScreenPool(this);
connect(m_pool, &ScreenPool::idsChanged, this, &BackgroundCache::reload);
}
reload();

View File

@ -122,11 +122,7 @@ void PanelBackground::updateMaxOpacity(Plasma::Svg *svg)
QImage center = svg->image(QSize(CENTERWIDTH, CENTERHEIGHT), element(svg, "center"));
if (center.format() != QImage::Format_ARGB32_Premultiplied) {
#if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
center.convertTo(QImage::Format_ARGB32_Premultiplied);
#else
center = center.convertToFormat(QImage::Format_ARGB32_Premultiplied);
#endif
}
float alphasum{0};
@ -144,6 +140,12 @@ void PanelBackground::updateMaxOpacity(Plasma::Svg *svg)
m_maxOpacity = alphasum / (float)(2 * CENTERWIDTH);
//! minimum acceptable panel background opacity is 1%. Such is a case is when
//! panel background is fully transparent but it provides a border. In such case
//! previous approach was identifying as background max opacity 0% and in such case
//! all the upcoming calculations where returning a fully transparent plasma svg to the user
m_maxOpacity = qMax(0.01f, m_maxOpacity);
emit maxOpacityChanged();
}
@ -173,11 +175,7 @@ void PanelBackground::updateRoundnessFromMask(Plasma::Svg *svg)
QImage corner = svg->image(svg->elementSize(cornerId), cornerId);
if (corner.format() != QImage::Format_ARGB32_Premultiplied) {
#if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
corner.convertTo(QImage::Format_ARGB32_Premultiplied);
#else
corner = corner.convertToFormat(QImage::Format_ARGB32_Premultiplied);
#endif
}
int baseRow = (topLeftCorner ? corner.height()-1 : 0);
@ -345,11 +343,7 @@ void PanelBackground::updateRoundnessFromShadows(Plasma::Svg *svg)
QImage corner = svg->image(svg->elementSize(cornerId), cornerId);
if (corner.format() != QImage::Format_ARGB32_Premultiplied) {
#if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
corner.convertTo(QImage::Format_ARGB32_Premultiplied);
#else
corner = corner.convertToFormat(QImage::Format_ARGB32_Premultiplied);
#endif
}
int baseRow = (topLeftCorner ? corner.height()-1 : 0);
@ -510,11 +504,7 @@ void PanelBackground::updateRoundnessFallback(Plasma::Svg *svg)
QImage corner = svg->image(svg->elementSize(cornerId), cornerId);
if (corner.format() != QImage::Format_ARGB32_Premultiplied) {
#if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
corner.convertTo(QImage::Format_ARGB32_Premultiplied);
#else
corner = corner.convertToFormat(QImage::Format_ARGB32_Premultiplied);
#endif
}
int discovRow = (m_location == Plasma::Types::LeftEdge ? corner.height()-1 : 0);
@ -586,11 +576,7 @@ void PanelBackground::updateShadow(Plasma::Svg *svg)
QImage border = svg->image(svg->elementSize(borderId), borderId);
if (border.format() != QImage::Format_ARGB32_Premultiplied) {
#if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
border.convertTo(QImage::Format_ARGB32_Premultiplied);
#else
border = border.convertToFormat(QImage::Format_ARGB32_Premultiplied);
#endif
}
//! find shadow size through, plasma theme

View File

@ -139,15 +139,16 @@ void ScreenGeometries::setPlasmaAvailableScreenRegion(const QString &screenName,
QVariant regionvariant;
QList<QRect> rects;
if (!region.isNull()) {
//! transorm QRegion to QList<QRect> in order to be sent through dbus
QList<QRect> rects;
foreach (const QRect &rect, region) {
rects << rect;
}
regionvariant = QVariant::fromValue(rects);
} else {
rects << QRect();
}
regionvariant = QVariant::fromValue(rects);
QVariantList args;
@ -189,6 +190,8 @@ void ScreenGeometries::updateGeometries()
qDebug() << " PLASMA SCREEN GEOMETRIES, LAST AVAILABLE SCREEN RECTS :: " << m_lastAvailableRect;
QStringList clearedScreenNames;
//! check for available geometries changes
for (QScreen *screen : qGuiApp->screens()) {
QString scrName = screen->name();
@ -211,17 +214,23 @@ void ScreenGeometries::updateGeometries()
true,
true);
//! Disable checks because of the workaround concerning plasma desktop behavior
if (!m_lastAvailableRect.contains(scrName) || m_lastAvailableRect[scrName] != availableRect) {
m_lastAvailableRect[scrName] = availableRect;
setPlasmaAvailableScreenRect(scrName, availableRect);
qDebug() << " PLASMA SCREEN GEOMETRIES, AVAILABLE RECT :: " << screen->name() << " : " << availableRect;
}
bool clearedScreen = (availableRect == screen->geometry());
if (!m_lastAvailableRegion.contains(scrName) || m_lastAvailableRegion[scrName] != availableRegion) {
m_lastAvailableRegion[scrName] = availableRegion;
setPlasmaAvailableScreenRegion(scrName, availableRegion);
qDebug() << " PLASMA SCREEN GEOMETRIES, AVAILABLE REGION :: " << screen->name() << " : " << availableRegion;
if (!clearedScreen) {
//! Disable checks because of the workaround concerning plasma desktop behavior
if (!m_lastAvailableRect.contains(scrName) || m_lastAvailableRect[scrName] != availableRect) {
m_lastAvailableRect[scrName] = availableRect;
setPlasmaAvailableScreenRect(scrName, availableRect);
qDebug() << " PLASMA SCREEN GEOMETRIES, AVAILABLE RECT :: " << screen->name() << " : " << availableRect;
}
if (!m_lastAvailableRegion.contains(scrName) || m_lastAvailableRegion[scrName] != availableRegion) {
m_lastAvailableRegion[scrName] = availableRegion;
setPlasmaAvailableScreenRegion(scrName, availableRegion);
qDebug() << " PLASMA SCREEN GEOMETRIES, AVAILABLE REGION :: " << screen->name() << " : " << availableRegion;
}
} else {
clearedScreenNames << scrName;
}
}
@ -230,14 +239,21 @@ void ScreenGeometries::updateGeometries()
//! check for inactive screens that were published previously
for (QString &lastScrName : m_lastScreenNames) {
if (!screenIsActive(lastScrName)) {
bool scractive = screenIsActive(lastScrName);
if (!scractive || clearedScreenNames.contains(lastScrName)) {
//! screen became inactive and its geometries could be unpublished
setPlasmaAvailableScreenRect(lastScrName, QRect());
setPlasmaAvailableScreenRegion(lastScrName, QRegion());
m_lastAvailableRect.remove(lastScrName);
m_lastAvailableRegion.remove(lastScrName);
}
if (!scractive) {
qDebug() << " PLASMA SCREEN GEOMETRIES, INACTIVE SCREEN :: " << lastScrName;
} else if (clearedScreenNames.contains(lastScrName)) {
qDebug() << " PLASMA SCREEN GEOMETRIES, CLEARED SCREEN :: " << lastScrName;
}
}

View File

@ -6,6 +6,7 @@
#include "screenpool.h"
// local
#include "../../primaryoutputwatcher.h"
#include "../../tools/commontools.h"
// Qt
@ -25,10 +26,11 @@ namespace Latte {
namespace PlasmaExtended {
ScreenPool::ScreenPool(QObject *parent)
: QObject(parent)
: QObject(parent),
m_primaryWatcher(new PrimaryOutputWatcher(this))
{
KSharedConfigPtr plasmaPtr = KSharedConfig::openConfig(PLASMARC);
m_screensGroup = KConfigGroup(plasmaPtr, "ScreenConnectors");
m_plasmarcConfig = KSharedConfig::openConfig(PLASMARC);
m_screensGroup = KConfigGroup(m_plasmarcConfig, "ScreenConnectors");
load();
@ -62,12 +64,14 @@ void ScreenPool::load()
m_connectorForId.clear();
m_idForConnector.clear();
m_plasmarcConfig->reparseConfiguration();
bool updated{false};
for (const auto &screenId : m_screensGroup.keyList()) {
QString screenName = m_screensGroup.readEntry(screenId, QString());
if (screenId != 0) {
int scrId = screenId.toInt();
int scrId = screenId.toInt();
if (scrId != 0) {
insertScreenMapping(scrId, screenName);
if (!connectorForId.contains(scrId) || connectorForId[scrId] != m_connectorForId[scrId]) {
@ -106,7 +110,7 @@ int ScreenPool::id(const QString &connector) const
{
if (!m_idForConnector.contains(connector)) {
//! return 0 for primary screen, -1 for not found
return qGuiApp->primaryScreen()->name() == connector ? 0 : -1;
return m_primaryWatcher->primaryScreen()->name() == connector ? 0 : -1;
}
return m_idForConnector.value(connector);

View File

@ -13,6 +13,9 @@
// KDE
#include <KConfigGroup>
#include <KSharedConfig>
class PrimaryOutputWatcher;
namespace Latte {
namespace PlasmaExtended {
@ -42,7 +45,10 @@ private:
QMap<int, QString> m_connectorForId;
QHash<QString, int> m_idForConnector;
KSharedConfig::Ptr m_plasmarcConfig;
KConfigGroup m_screensGroup;
PrimaryOutputWatcher *m_primaryWatcher;
};
}

View File

@ -433,8 +433,8 @@ const CornerRegions &Theme::cornersMask(const int &radius)
int axis = (2 * radius) + 2;
QImage cornerimage(axis, axis, QImage::Format_ARGB32);
QPainter painter(&cornerimage);
//!does not provide valid masks
//painter.setRenderHints(QPainter::Antialiasing);
//!does not provide valid masks ?
painter.setRenderHints(QPainter::Antialiasing);
QPen pen(Qt::black);
pen.setStyle(Qt::SolidLine);
@ -454,7 +454,7 @@ const CornerRegions &Theme::cornersMask(const int &radius)
for(int x=0; x<radius; ++x) {
QRgb point = line[x];
if (QColor(point) == Qt::black) {
if (QColor(point) != Qt::white) {
bits = bits + "1 ";
width = qMax(0, x);
break;
@ -541,13 +541,8 @@ void Theme::saveConfig()
void Theme::qmlRegisterTypes()
{
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
qmlRegisterType<Latte::PlasmaExtended::Theme>();
qmlRegisterType<Latte::PlasmaExtended::PanelBackground>();
#else
qmlRegisterAnonymousType<Latte::PlasmaExtended::Theme>("latte-dock", 1);
qmlRegisterAnonymousType<Latte::PlasmaExtended::PanelBackground>("latte-dock", 1);
#endif
}
}

View File

@ -0,0 +1,166 @@
/*
SPDX-FileCopyrightText: 2013 Marco Martin <mart@kde.org>
SPDX-FileCopyrightText: 2021 Aleix Pol Gonzalez <aleixpol@kde.org>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "primaryoutputwatcher.h"
#include <KWindowSystem>
#include <QDebug>
#include <QGuiApplication>
#include <QScreen>
#include "qwayland-kde-primary-output-v1.h"
#include <KWayland/Client/connection_thread.h>
#include <KWayland/Client/registry.h>
#include <config-latte.h>
#if HAVE_X11
#include <QTimer> //Used only in x11 case
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
#include <private/qtx11extras_p.h>
#else
#include <QX11Info>
#endif
#include <xcb/randr.h>
#include <xcb/xcb.h>
#include <xcb/xcb_event.h>
#endif
class WaylandPrimaryOutput : public QObject, public QtWayland::kde_primary_output_v1
{
Q_OBJECT
public:
WaylandPrimaryOutput(struct ::wl_registry *registry, int id, int version, QObject *parent)
: QObject(parent)
, QtWayland::kde_primary_output_v1(registry, id, version)
{
}
void kde_primary_output_v1_primary_output(const QString &outputName) override
{
Q_EMIT primaryOutputChanged(outputName);
}
Q_SIGNALS:
void primaryOutputChanged(const QString &outputName);
};
PrimaryOutputWatcher::PrimaryOutputWatcher(QObject *parent)
: QObject(parent)
{
#if HAVE_X11
if (KWindowSystem::isPlatformX11()) {
m_primaryOutputName = qGuiApp->primaryScreen()->name();
qGuiApp->installNativeEventFilter(this);
const xcb_query_extension_reply_t *reply = xcb_get_extension_data(QX11Info::connection(), &xcb_randr_id);
m_xrandrExtensionOffset = reply->first_event;
setPrimaryOutputName(qGuiApp->primaryScreen()->name());
connect(qGuiApp, &QGuiApplication::primaryScreenChanged, this, [this](QScreen *newPrimary) {
setPrimaryOutputName(newPrimary->name());
});
}
#endif
if (KWindowSystem::isPlatformWayland()) {
setupRegistry();
}
}
void PrimaryOutputWatcher::setPrimaryOutputName(const QString &newOutputName)
{
if (newOutputName != m_primaryOutputName) {
const QString oldOutputName = m_primaryOutputName;
m_primaryOutputName = newOutputName;
Q_EMIT primaryOutputNameChanged(oldOutputName, newOutputName);
}
}
void PrimaryOutputWatcher::setupRegistry()
{
auto m_connection = KWayland::Client::ConnectionThread::fromApplication(this);
if (!m_connection) {
return;
}
// Asking for primaryOutputName() before this happened, will return qGuiApp->primaryScreen()->name() anyways, so set it so the primaryOutputNameChange will
// have parameters that are coherent
m_primaryOutputName = qGuiApp->primaryScreen()->name();
m_registry = new KWayland::Client::Registry(this);
connect(m_registry, &KWayland::Client::Registry::interfaceAnnounced, this, [this](const QByteArray &interface, quint32 name, quint32 version) {
if (interface == WaylandPrimaryOutput::interface()->name) {
auto m_outputManagement = new WaylandPrimaryOutput(m_registry->registry(), name, version, this);
connect(m_outputManagement, &WaylandPrimaryOutput::primaryOutputChanged, this, [this](const QString &outputName) {
m_primaryOutputWayland = outputName;
// Only set the outputName when there's a QScreen attached to it
if (screenForName(outputName)) {
setPrimaryOutputName(outputName);
}
});
}
});
// In case the outputName was received before Qt reported the screen
connect(qGuiApp, &QGuiApplication::screenAdded, this, [this](QScreen *screen) {
if (screen->name() == m_primaryOutputWayland) {
setPrimaryOutputName(m_primaryOutputWayland);
}
});
m_registry->create(m_connection);
m_registry->setup();
}
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
bool PrimaryOutputWatcher::nativeEventFilter(const QByteArray &eventType, void *message, long int *result)
#else
bool PrimaryOutputWatcher::nativeEventFilter(const QByteArray &eventType, void *message, qintptr *result)
#endif
{
Q_UNUSED(result);
#if HAVE_X11
// a particular edge case: when we switch the only enabled screen
// we don't have any signal about it, the primary screen changes but we have the same old QScreen* getting recycled
// see https://bugs.kde.org/show_bug.cgi?id=373880
// if this slot will be invoked many times, their//second time on will do nothing as name and primaryOutputName will be the same by then
if (eventType[0] != 'x') {
return false;
}
xcb_generic_event_t *ev = static_cast<xcb_generic_event_t *>(message);
const auto responseType = XCB_EVENT_RESPONSE_TYPE(ev);
if (responseType == m_xrandrExtensionOffset + XCB_RANDR_SCREEN_CHANGE_NOTIFY) {
QTimer::singleShot(0, this, [this]() {
setPrimaryOutputName(qGuiApp->primaryScreen()->name());
});
}
#endif
return false;
}
QScreen *PrimaryOutputWatcher::screenForName(const QString &outputName) const
{
const auto screens = qGuiApp->screens();
for (auto screen : screens) {
if (screen->name() == outputName) {
return screen;
}
}
return nullptr;
}
QScreen *PrimaryOutputWatcher::primaryScreen() const
{
auto screen = screenForName(m_primaryOutputName);
if (!screen) {
qDebug() << "PrimaryOutputWatcher: Could not find primary screen:" << m_primaryOutputName;
return qGuiApp->primaryScreen();
}
return screen;
}
#include "primaryoutputwatcher.moc"

View File

@ -0,0 +1,58 @@
/*
SPDX-FileCopyrightText: 2021 Aleix Pol Gonzalez <aleixpol@kde.org>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#ifndef PRIMARYOUTPUTWATCHER_H
#define PRIMARYOUTPUTWATCHER_H
#include <QAbstractNativeEventFilter>
#include <QObject>
namespace KWayland
{
namespace Client
{
class Registry;
class ConnectionThread;
}
}
class QScreen;
class PrimaryOutputWatcher : public QObject, public QAbstractNativeEventFilter
{
Q_OBJECT
public:
PrimaryOutputWatcher(QObject *parent);
QScreen *primaryScreen() const;
QScreen *screenForName(const QString &outputName) const;
Q_SIGNALS:
void primaryOutputNameChanged(const QString &oldOutputName, const QString &newOutputName);
protected:
friend class WaylandOutputDevice;
void setPrimaryOutputName(const QString &outputName);
private:
void setupRegistry();
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) override;
#else
bool nativeEventFilter(const QByteArray &eventType, void *message, qintptr *result) override;
#endif
// All
QString m_primaryOutputName;
// Wayland
KWayland::Client::Registry *m_registry = nullptr;
QString m_primaryOutputWayland;
// Xrandr
int m_xrandrExtensionOffset;
};
#endif // PRIMARYOUTPUTWATCHER_H

View File

@ -8,6 +8,7 @@
// local
#include <config-latte.h>
#include "primaryoutputwatcher.h"
// Qt
#include <QDebug>
@ -17,6 +18,7 @@
// KDE
#include <KLocalizedString>
#include <KWindowSystem>
// X11
#if HAVE_X11
@ -32,10 +34,9 @@ const int ScreenPool::FIRSTSCREENID;
ScreenPool::ScreenPool(KSharedConfig::Ptr config, QObject *parent)
: QObject(parent),
m_configGroup(KConfigGroup(config, QStringLiteral("ScreenConnectors")))
m_configGroup(KConfigGroup(config, QStringLiteral("ScreenConnectors"))),
m_primaryWatcher(new PrimaryOutputWatcher(this))
{
qApp->installNativeEventFilter(this);
m_configSaveTimer.setSingleShot(true);
connect(&m_configSaveTimer, &QTimer::timeout, this, [this]() {
m_configGroup.sync();
@ -52,15 +53,8 @@ ScreenPool::~ScreenPool()
void ScreenPool::load()
{
m_lastPrimaryConnector = QString();
m_screensTable.clear();
QScreen *primary = qGuiApp->primaryScreen();
if (primary) {
m_lastPrimaryConnector = primary->name();
}
//restore the known ids to connector mappings
for (const QString &key : m_configGroup.keyList()) {
if (key.toInt() <= 0) {
@ -94,6 +88,20 @@ void ScreenPool::load()
onScreenAdded(screen);
}
if (KWindowSystem::isPlatformX11()) {
connect(qGuiApp, &QGuiApplication::primaryScreenChanged, this, &ScreenPool::primaryScreenChanged, Qt::UniqueConnection);
}
connect(m_primaryWatcher, &PrimaryOutputWatcher::primaryOutputNameChanged, this, &ScreenPool::onPrimaryOutputNameChanged, Qt::UniqueConnection);
}
void ScreenPool::onPrimaryOutputNameChanged(const QString &oldOutputName, const QString &newOutputName)
{
Q_UNUSED(oldOutputName);
Q_UNUSED(newOutputName);
emit primaryScreenChanged(m_primaryWatcher->primaryScreen());
}
void ScreenPool::onScreenAdded(const QScreen *screen)
@ -165,7 +173,24 @@ void ScreenPool::removeScreens(const Latte::Data::ScreensTable &obsoleteScreens)
int ScreenPool::primaryScreenId() const
{
return id(qGuiApp->primaryScreen()->name());
return id(primaryScreen()->name());
}
QList<int> ScreenPool::secondaryScreenIds() const
{
QList<int> secondaryscreens;
QScreen *primary{primaryScreen()};
for (const auto scr : qGuiApp->screens()) {
if (scr == primary) {
continue;
}
secondaryscreens << id(scr->name());
}
return secondaryscreens;
}
void ScreenPool::save()
@ -214,7 +239,7 @@ void ScreenPool::insertScreenMapping(const QString &connector)
int ScreenPool::id(const QString &connector) const
{
QString screenId = m_screensTable.idForName(connector);
return screenId.isEmpty() ? -1 : screenId.toInt();
return screenId.isEmpty() ? NOSCREENID : screenId.toInt();
}
QString ScreenPool::connector(int id) const
@ -259,10 +284,15 @@ bool ScreenPool::isScreenActive(int screenId) const
return false;
}
QScreen *ScreenPool::primaryScreen() const
{
return m_primaryWatcher->primaryScreen();
}
QScreen *ScreenPool::screenForId(int id)
{
const auto screens = qGuiApp->screens();
QScreen *screen{qGuiApp->primaryScreen()};
QScreen *screen{primaryScreen()};
if (hasScreenId(id)) {
QString scrName = connector(id);
@ -277,41 +307,4 @@ QScreen *ScreenPool::screenForId(int id)
return screen;
}
bool ScreenPool::nativeEventFilter(const QByteArray &eventType, void *message, long int *result)
{
Q_UNUSED(result);
#if HAVE_X11
// a particular edge case: when we switch the only enabled screen
// we don't have any signal about it, the primary screen changes but we have the same old QScreen* getting recycled
// see https://bugs.kde.org/show_bug.cgi?id=373880
// if this slot will be invoked many times, their//second time on will do nothing as name and primaryconnector will be the same by then
if (eventType != "xcb_generic_event_t") {
return false;
}
xcb_generic_event_t *ev = static_cast<xcb_generic_event_t *>(message);
const auto responseType = XCB_EVENT_RESPONSE_TYPE(ev);
const xcb_query_extension_reply_t *reply = xcb_get_extension_data(QX11Info::connection(), &xcb_randr_id);
if (responseType == reply->first_event + XCB_RANDR_SCREEN_CHANGE_NOTIFY) {
if (qGuiApp->primaryScreen()->name() != m_lastPrimaryConnector) {
//new screen?
if (id(qGuiApp->primaryScreen()->name()) < 0) {
insertScreenMapping(qGuiApp->primaryScreen()->name());
}
m_lastPrimaryConnector = qGuiApp->primaryScreen()->name();
emit primaryPoolChanged();
}
}
#endif
return false;
}
}
#include "moc_screenpool.cpp"

View File

@ -16,28 +16,32 @@
#include <QScreen>
#include <QString>
#include <QTimer>
#include <QAbstractNativeEventFilter>
// KDE
#include <KConfigGroup>
#include <KSharedConfig>
class PrimaryOutputWatcher;
namespace Latte {
class ScreenPool : public QObject, public QAbstractNativeEventFilter
class ScreenPool : public QObject
{
Q_OBJECT
public:
static const int FIRSTSCREENID = 10;
static const int NOSCREENID = -1;
ScreenPool(KSharedConfig::Ptr config, QObject *parent = nullptr);
void load();
~ScreenPool() override;
void load();
bool hasScreenId(int screenId) const;
bool isScreenActive(int screenId) const;
int primaryScreenId() const;
QList<int> secondaryScreenIds() const;
void insertScreenMapping(const QString &connector);
void reload(QString path);
@ -48,20 +52,20 @@ public:
QString connector(int id) const;
QScreen *screenForId(int id);
QScreen *primaryScreen() const;
Latte::Data::ScreensTable screensTable();
signals:
void primaryPoolChanged();
void primaryScreenChanged(QScreen *screen);
void screenGeometryChanged();
protected:
bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) Q_DECL_OVERRIDE;
int firstAvailableId() const;
private slots:
void updateScreenGeometry(const QScreen *screen);
void onPrimaryOutputNameChanged(const QString &oldOutputName, const QString &newOutputName);
void onScreenAdded(const QScreen *screen);
void onScreenRemoved(const QScreen *screen);
@ -73,10 +77,10 @@ private:
Latte::Data::ScreensTable m_screensTable;
KConfigGroup m_configGroup;
//! used to workaround a bug under X11 when primary screen changes and no screenChanged signal is emitted
QString m_lastPrimaryConnector;
QTimer m_configSaveTimer;
PrimaryOutputWatcher *m_primaryWatcher;
};
}

View File

@ -4,7 +4,7 @@
*/
#ifndef COLORSMODEL_H
#define COLROSMODEL_H
#define COLORSMODEL_H
// local
#include "../../lattecorona.h"

View File

@ -193,7 +193,7 @@ void ExportTemplateHandler::chooseFileDialog()
});
chooseFileDlg->open();
chooseFileDlg->selectFile(currentFile.baseName());
chooseFileDlg->selectFile(currentFile.fileName());
}
void ExportTemplateHandler::onExport()

View File

@ -502,7 +502,7 @@ int screenMaxLength(const QStyleOption &option, const int &maxIconSize)
return scr_maxlength;
}
QRect remainedFromScreenDrawing(const QStyleOption &option, const int &maxIconSize)
QRect remainedFromScreenDrawing(const QStyleOption &option, bool drawMultipleScreens, const int &maxIconSize)
{
int total_length = screenMaxLength(option, maxIconSize) + MARGIN * 2 + 1;
@ -512,7 +512,7 @@ QRect remainedFromScreenDrawing(const QStyleOption &option, const int &maxIconSi
return optionRemainedRect;
}
QRect drawScreen(QPainter *painter, const QStyleOption &option, QRect screenGeometry, const int &maxIconSize, const float brushOpacity)
QRect drawScreen(QPainter *painter, const QStyleOption &option, bool drawMultipleScreens, QRect screenGeometry, const int &maxIconSize, const float brushOpacity)
{
float scr_ratio = (float)screenGeometry.width() / (float)screenGeometry.height();
bool isVertical = (scr_ratio < 1.0);
@ -565,13 +565,24 @@ QRect drawScreen(QPainter *painter, const QStyleOption &option, QRect screenGeom
painter->setPen(pen);
painter->drawRect(screenRect);
//! draw screen base
pen.setWidth(1);
painter->setPen(pen);
painter->setRenderHint(QPainter::Antialiasing, false);
//! draw multiple
if (drawMultipleScreens) {
int multiplemargin = 3;
int curx = screenRect.x()-multiplemargin;
painter->drawLine(screenRect.x() - multiplemargin, screenRect.y() - multiplemargin,
screenRect.x() - multiplemargin, screenRect.y() - multiplemargin + screenRect.height());
painter->drawLine(screenRect.x() - multiplemargin, screenRect.y() - multiplemargin,
screenRect.x() - multiplemargin + screenRect.width(), screenRect.y() - multiplemargin);
}
int basex = screenRect.x() + (screenRect.width()/2) - 4;
int basey = screenRect.y() + screenRect.height() + 2;
painter->setRenderHint(QPainter::Antialiasing, false);
painter->drawLine(basex , basey, basex + 8, basey);
// debug screen maximum available rect

View File

@ -60,8 +60,8 @@ QRect remainedFromCheckBox(const QStyleOptionButton &option, Qt::AlignmentFlag a
void drawCheckBox(QPainter *painter, const QStyleOptionButton &option, Qt::AlignmentFlag alignment = Qt::AlignLeft, const QWidget *widget = nullptr);
//! screen icon
QRect remainedFromScreenDrawing(const QStyleOption &option, const int &maxIconSize = -1);
QRect drawScreen(QPainter *painter, const QStyleOption &option, QRect screenGeometry, const int &maxIconSize = -1, const float brushOpacity = 1.0); // returns screen available rect
QRect remainedFromScreenDrawing(const QStyleOption &option, bool drawMultipleScreens, const int &maxIconSize = -1);
QRect drawScreen(QPainter *painter, const QStyleOption &option, bool drawMultipleScreens, QRect screenGeometry, const int &maxIconSize = -1, const float brushOpacity = 1.0); // returns screen available rect
int screenMaxLength(const QStyleOption &option, const int &maxIconSize = -1);

View File

@ -111,8 +111,8 @@ void CheckBox::paint(QPainter *painter, const QStyleOptionViewItem &option, cons
//! screen
int maxiconsize = -1; //disabled
remainedrect = Latte::remainedFromScreenDrawing(adjustedOption, maxiconsize);
Latte::drawScreen(painter, adjustedOption, screen.geometry, maxiconsize);
remainedrect = Latte::remainedFromScreenDrawing(adjustedOption, false, maxiconsize);
Latte::drawScreen(painter, adjustedOption, false, screen.geometry, maxiconsize);
adjustedOption.rect = remainedrect;
//! screen id

View File

@ -236,7 +236,7 @@ const Latte::Data::ViewsTable Layouts::selectedLayoutViews()
central = new CentralLayout(this, selectedCurrentData.id);
}
selectedCurrentData.views = central->viewsTable();
selectedCurrentData.views = central->viewsTable().onlyOriginals();
selectedCurrentData.views.isInitialized = true;
if (!islayoutactive) {

File diff suppressed because it is too large Load Diff

View File

@ -21,6 +21,7 @@
#include "../../layout/centrallayout.h"
#include "../../layouts/importer.h"
#include "../../layouts/manager.h"
#include "../../layouts/storage.h"
#include "../../templates/templatesmanager.h"
#include "../../tools/commontools.h"
@ -513,8 +514,6 @@ void TabLayouts::removeLayout()
return;
}
qDebug() << Q_FUNC_INFO;
m_layoutsController->removeSelected();
}
@ -660,6 +659,9 @@ void TabLayouts::exportLayoutForBackup()
QFile(file).setPermissions(QFileDevice::ReadUser | QFileDevice::WriteUser | QFileDevice::ReadGroup | QFileDevice::ReadOther);
}
// cleanup clones from exported file
Latte::Layouts::Storage::self()->removeAllClonedViews(file);
CentralLayout layoutS(this, file);
layoutS.setActivities(QStringList());
layoutS.clearLastUsedActivity();
@ -714,7 +716,7 @@ void TabLayouts::exportLayoutForBackup()
});
exportFileDialog->open();
exportFileDialog->selectFile(selectedLayout.name);
exportFileDialog->selectFile(selectedLayout.name + ".layout.latte");
}
void TabLayouts::showDetailsDialog()

View File

@ -33,21 +33,39 @@ TabPreferences::TabPreferences(Latte::Settings::Dialog::SettingsDialog *parent)
void TabPreferences::initUi()
{
//! exclusive group
m_mouseSensitivityButtons = new QButtonGroup(this);
m_mouseSensitivityButtons->addButton(m_ui->lowSensitivityBtn, Latte::Settings::LowMouseSensitivity);
m_mouseSensitivityButtons->addButton(m_ui->mediumSensitivityBtn, Latte::Settings::MediumMouseSensitivity);
m_mouseSensitivityButtons->addButton(m_ui->highSensitivityBtn, Latte::Settings::HighMouseSensitivity);
m_mouseSensitivityButtons->setExclusive(true);
//! exclusive groups
m_parabolicSpreadButtons = new QButtonGroup(this);
m_parabolicSpreadButtons->addButton(m_ui->smallParabolicBtn, Data::Preferences::PARABOLICSPREAD);
m_parabolicSpreadButtons->addButton(m_ui->mediumParabolicBtn, 5);
m_parabolicSpreadButtons->addButton(m_ui->largeParabolicBtn, 7);
m_parabolicSpreadButtons->setExclusive(true);
m_thicknessMarginInfluenceButtons = new QButtonGroup(this);
m_thicknessMarginInfluenceButtons->addButton(m_ui->noMarginInfluenceBtn, 0); // 0%
m_thicknessMarginInfluenceButtons->addButton(m_ui->halfMarginInfluenceBtn, 50); // 50%
m_thicknessMarginInfluenceButtons->addButton(m_ui->fullMarginInfluenceBtn, 100); // 100%
m_thicknessMarginInfluenceButtons->setExclusive(true);
m_ui->noMarginInfluenceBtn->setText(i18nc("number in percentage, e.g. 85%","%1%").arg(0));
m_ui->halfMarginInfluenceBtn->setText(i18nc("number in percentage, e.g. 85%","%1%").arg(50));
m_ui->fullMarginInfluenceBtn->setText(i18nc("number in percentage, e.g. 85%","%1%").arg(100));
//! Buttons
connect(m_ui->contextMenuActionsBtn, &QPushButton::clicked, this, &TabPreferences::onActionsBtnPressed);
//! signals
connect(m_mouseSensitivityButtons, static_cast<void(QButtonGroup::*)(int, bool)>(&QButtonGroup::buttonToggled),
connect(m_parabolicSpreadButtons, static_cast<void(QButtonGroup::*)(int, bool)>(&QButtonGroup::buttonToggled),
[ = ](int id, bool checked) {
if (checked) {
m_preferences.mouseSensitivity = static_cast<Latte::Settings::MouseSensitivity>(id);
m_preferences.parabolicSpread = id;
emit dataChanged();
}
});
connect(m_thicknessMarginInfluenceButtons, static_cast<void(QButtonGroup::*)(int, bool)>(&QButtonGroup::buttonToggled),
[ = ](int id, bool checked) {
if (checked) {
m_preferences.thicknessMarginInfluence = (id / 100.0f);
emit dataChanged();
}
});
@ -110,7 +128,8 @@ void TabPreferences::initSettings()
o_preferences.metaPressForAppLauncher = m_corona->universalSettings()->kwin_metaForwardedToLatte();
o_preferences.metaHoldForBadges = m_corona->universalSettings()->metaPressAndHoldEnabled();
o_preferences.borderlessMaximized = m_corona->universalSettings()->canDisableBorders();
o_preferences.mouseSensitivity = m_corona->universalSettings()->sensitivity();
o_preferences.parabolicSpread = m_corona->universalSettings()->parabolicSpread();
o_preferences.thicknessMarginInfluence = m_corona->universalSettings()->thicknessMarginInfluence();
o_preferences.screensDelay = m_corona->universalSettings()->screenTrackerInterval();
m_preferences = o_preferences;
@ -145,12 +164,20 @@ void TabPreferences::updateUi()
m_ui->noBordersForMaximizedChkBox->setChecked(m_preferences.borderlessMaximized);
m_ui->screenTrackerSpinBox->setValue(m_preferences.screensDelay);
if (m_preferences.mouseSensitivity == Settings::LowMouseSensitivity) {
m_ui->lowSensitivityBtn->setChecked(true);
} else if (m_preferences.mouseSensitivity == Settings::MediumMouseSensitivity) {
m_ui->mediumSensitivityBtn->setChecked(true);
} else if (m_preferences.mouseSensitivity == Settings::HighMouseSensitivity) {
m_ui->highSensitivityBtn->setChecked(true);
if (m_preferences.parabolicSpread == Data::Preferences::PARABOLICSPREAD) {
m_ui->smallParabolicBtn->setChecked(true);
} else if (m_preferences.parabolicSpread == 5) {
m_ui->mediumParabolicBtn->setChecked(true);
} else if (m_preferences.parabolicSpread == 7) {
m_ui->largeParabolicBtn->setChecked(true);
}
if (m_preferences.thicknessMarginInfluence == 0.0f) {
m_ui->noMarginInfluenceBtn->setChecked(true);
} else if (m_preferences.thicknessMarginInfluence == 0.5f) {
m_ui->halfMarginInfluenceBtn->setChecked(true);
} else if (m_preferences.thicknessMarginInfluence == Data::Preferences::THICKNESSMARGININFLUENCE) {
m_ui->fullMarginInfluenceBtn->setChecked(true);
}
emit dataChanged();
@ -186,7 +213,6 @@ void TabPreferences::resetDefaults()
void TabPreferences::save()
{
m_corona->universalSettings()->setSensitivity(m_preferences.mouseSensitivity);
m_corona->universalSettings()->setAutostart(m_preferences.autostart);
m_corona->universalSettings()->setBadges3DStyle(m_preferences.badgeStyle3D);
m_corona->universalSettings()->setContextMenuActionsAlwaysShown(m_preferences.contextMenuAlwaysActions);
@ -195,6 +221,8 @@ void TabPreferences::save()
m_corona->universalSettings()->setMetaPressAndHoldEnabled(m_preferences.metaHoldForBadges);
m_corona->universalSettings()->setShowInfoWindow(m_preferences.layoutsInformationWindow);
m_corona->universalSettings()->setCanDisableBorders(m_preferences.borderlessMaximized);
m_corona->universalSettings()->setParabolicSpread(m_preferences.parabolicSpread);
m_corona->universalSettings()->setThicknessMarginInfluence(m_preferences.thicknessMarginInfluence);
m_corona->universalSettings()->setScreenTrackerInterval(m_preferences.screensDelay);
o_preferences = m_preferences;

View File

@ -69,7 +69,8 @@ private:
Ui::SettingsDialog *m_ui{nullptr};
Latte::Corona *m_corona{nullptr};
QButtonGroup *m_mouseSensitivityButtons;
QButtonGroup *m_parabolicSpreadButtons;
QButtonGroup *m_thicknessMarginInfluenceButtons;
//! current data
Data::Preferences m_preferences;

View File

@ -46,14 +46,17 @@ UniversalSettings::UniversalSettings(KSharedConfig::Ptr config, QObject *parent)
connect(this, &UniversalSettings::badges3DStyleChanged, this, &UniversalSettings::saveConfig);
connect(this, &UniversalSettings::canDisableBordersChanged, this, &UniversalSettings::saveConfig);
connect(this, &UniversalSettings::inAdvancedModeForEditSettingsChanged, this, &UniversalSettings::saveConfig);
connect(this, &UniversalSettings::inConfigureAppletsModeChanged, this, &UniversalSettings::saveConfig);
connect(this, &UniversalSettings::isAvailableGeometryBroadcastedToPlasmaChanged, this, &UniversalSettings::saveConfig);
connect(this, &UniversalSettings::launchersChanged, this, &UniversalSettings::saveConfig);
connect(this, &UniversalSettings::layoutsMemoryUsageChanged, this, &UniversalSettings::saveConfig);
connect(this, &UniversalSettings::metaPressAndHoldEnabledChanged, this, &UniversalSettings::saveConfig);
connect(this, &UniversalSettings::parabolicSpreadChanged, this, &UniversalSettings::saveConfig);
connect(this, &UniversalSettings::sensitivityChanged, this, &UniversalSettings::saveConfig);
connect(this, &UniversalSettings::screenTrackerIntervalChanged, this, &UniversalSettings::saveConfig);
connect(this, &UniversalSettings::showInfoWindowChanged, this, &UniversalSettings::saveConfig);
connect(this, &UniversalSettings::singleModeLayoutNameChanged, this, &UniversalSettings::saveConfig);
connect(this, &UniversalSettings::thicknessMarginInfluenceChanged, this, &UniversalSettings::saveConfig);
connect(this, &UniversalSettings::versionChanged, this, &UniversalSettings::saveConfig);
connect(this, &UniversalSettings::screenScalesChanged, this, &UniversalSettings::saveScalesConfig);
@ -131,6 +134,21 @@ void UniversalSettings::setInAdvancedModeForEditSettings(const bool &inAdvanced)
emit inAdvancedModeForEditSettingsChanged();
}
bool UniversalSettings::inConfigureAppletsMode() const
{
return m_inConfigureAppletsMode;
}
void UniversalSettings::setInConfigureAppletsMode(const bool enabled)
{
if (m_inConfigureAppletsMode == enabled) {
return;
}
m_inConfigureAppletsMode = enabled;
emit inConfigureAppletsModeChanged();
}
bool UniversalSettings::isAvailableGeometryBroadcastedToPlasma() const
{
return m_isAvailableGeometryBroadcastedToPlasma;
@ -193,6 +211,36 @@ void UniversalSettings::setScreenTrackerInterval(int duration)
emit screenTrackerIntervalChanged();
}
int UniversalSettings::parabolicSpread() const
{
return m_parabolicSpread;
}
void UniversalSettings::setParabolicSpread(const int &spread)
{
if (m_parabolicSpread == spread) {
return;
}
m_parabolicSpread = spread;
emit parabolicSpreadChanged();
}
float UniversalSettings::thicknessMarginInfluence() const
{
return m_thicknessMarginInfluence;
}
void UniversalSettings::setThicknessMarginInfluence(const float &influence)
{
if (m_thicknessMarginInfluence == influence) {
return;
}
m_thicknessMarginInfluence = influence;
emit thicknessMarginInfluenceChanged();
}
QString UniversalSettings::singleModeLayoutName() const
{
return m_singleModeLayoutName;
@ -434,7 +482,9 @@ void UniversalSettings::setLayoutsMemoryUsage(MemoryUsage::LayoutsMemory layouts
Settings::MouseSensitivity UniversalSettings::sensitivity()
{
return m_sensitivity;
//! return always default option as the users have not shown any interest in that option
return Latte::Settings::HighMouseSensitivity;
// return m_sensitivity;
}
void UniversalSettings::setSensitivity(Settings::MouseSensitivity sense)
@ -444,7 +494,7 @@ void UniversalSettings::setSensitivity(Settings::MouseSensitivity sense)
}
m_sensitivity = sense;
emit sensitivityChanged();
// emit sensitivityChanged();
}
float UniversalSettings::screenWidthScale(QString screenName) const
@ -521,14 +571,17 @@ void UniversalSettings::loadConfig()
m_canDisableBorders = m_universalGroup.readEntry("canDisableBorders", false);
m_contextMenuActionsAlwaysShown = m_universalGroup.readEntry("contextMenuActionsAlwaysShown", Latte::Data::ContextMenu::ACTIONSALWAYSVISIBLE);
m_inAdvancedModeForEditSettings = m_universalGroup.readEntry("inAdvancedModeForEditSettings", false);
m_inConfigureAppletsMode = m_universalGroup.readEntry("inConfigureAppletsMode", false);
m_isAvailableGeometryBroadcastedToPlasma = m_universalGroup.readEntry("isAvailableGeometryBroadcastedToPlasma", true);
m_launchers = m_universalGroup.readEntry("launchers", QStringList());
m_metaPressAndHoldEnabled = m_universalGroup.readEntry("metaPressAndHoldEnabled", true);
m_screenTrackerInterval = m_universalGroup.readEntry("screenTrackerInterval", 2500);
m_showInfoWindow = m_universalGroup.readEntry("showInfoWindow", true);
m_singleModeLayoutName = m_universalGroup.readEntry("singleModeLayoutName", QString());
m_parabolicSpread = m_universalGroup.readEntry("parabolicSpread", Data::Preferences::PARABOLICSPREAD);
m_thicknessMarginInfluence = m_universalGroup.readEntry("parabolicThicknessMarginInfluence", Data::Preferences::THICKNESSMARGININFLUENCE);
m_memoryUsage = static_cast<MemoryUsage::LayoutsMemory>(m_universalGroup.readEntry("memoryUsage", (int)MemoryUsage::SingleLayout));
m_sensitivity = static_cast<Settings::MouseSensitivity>(m_universalGroup.readEntry("mouseSensitivity", (int)Settings::HighMouseSensitivity));
//m_sensitivity = static_cast<Settings::MouseSensitivity>(m_universalGroup.readEntry("mouseSensitivity", (int)Settings::HighMouseSensitivity));
loadScalesConfig();
@ -544,14 +597,17 @@ void UniversalSettings::saveConfig()
m_universalGroup.writeEntry("canDisableBorders", m_canDisableBorders);
m_universalGroup.writeEntry("contextMenuActionsAlwaysShown", m_contextMenuActionsAlwaysShown);
m_universalGroup.writeEntry("inAdvancedModeForEditSettings", m_inAdvancedModeForEditSettings);
m_universalGroup.writeEntry("inConfigureAppletsMode", m_inConfigureAppletsMode);
m_universalGroup.writeEntry("isAvailableGeometryBroadcastedToPlasma", m_isAvailableGeometryBroadcastedToPlasma);
m_universalGroup.writeEntry("launchers", m_launchers);
m_universalGroup.writeEntry("metaPressAndHoldEnabled", m_metaPressAndHoldEnabled);
m_universalGroup.writeEntry("screenTrackerInterval", m_screenTrackerInterval);
m_universalGroup.writeEntry("showInfoWindow", m_showInfoWindow);
m_universalGroup.writeEntry("singleModeLayoutName", m_singleModeLayoutName);
m_universalGroup.writeEntry("parabolicSpread", m_parabolicSpread);
m_universalGroup.writeEntry("parabolicThicknessMarginInfluence", m_thicknessMarginInfluence);
m_universalGroup.writeEntry("memoryUsage", (int)m_memoryUsage);
m_universalGroup.writeEntry("mouseSensitivity", (int)m_sensitivity);
//m_universalGroup.writeEntry("mouseSensitivity", (int)m_sensitivity);
syncSettings();
}

View File

@ -12,6 +12,7 @@
#include <coretypes.h>
#include "../apptypes.h"
#include "../lattecorona.h"
#include "../data/preferencesdata.h"
// Qt
#include <QObject>
@ -44,9 +45,13 @@ class UniversalSettings : public QObject
Q_PROPERTY(bool autostart READ autostart WRITE setAutostart NOTIFY autostartChanged)
Q_PROPERTY(bool badges3DStyle READ badges3DStyle WRITE setBadges3DStyle NOTIFY badges3DStyleChanged)
Q_PROPERTY(bool inAdvancedModeForEditSettings READ inAdvancedModeForEditSettings WRITE setInAdvancedModeForEditSettings NOTIFY inAdvancedModeForEditSettingsChanged)
Q_PROPERTY(bool inConfigureAppletsMode READ inConfigureAppletsMode WRITE setInConfigureAppletsMode NOTIFY inConfigureAppletsModeChanged)
Q_PROPERTY(bool colorsScriptIsPresent READ colorsScriptIsPresent NOTIFY colorsScriptIsPresentChanged)
Q_PROPERTY(bool showInfoWindow READ showInfoWindow WRITE setShowInfoWindow NOTIFY showInfoWindowChanged)
Q_PROPERTY(int parabolicSpread READ parabolicSpread WRITE setParabolicSpread NOTIFY parabolicSpreadChanged)
Q_PROPERTY(float thicknessMarginInfluence READ thicknessMarginInfluence WRITE setThicknessMarginInfluence NOTIFY thicknessMarginInfluenceChanged)
Q_PROPERTY(QString singleModeLayoutName READ singleModeLayoutName WRITE setSingleModeLayoutName NOTIFY singleModeLayoutNameChanged)
Q_PROPERTY(QStringList launchers READ launchers WRITE setLaunchers NOTIFY launchersChanged)
@ -76,6 +81,9 @@ public:
bool inAdvancedModeForEditSettings() const;
void setInAdvancedModeForEditSettings(const bool &inAdvanced);
bool inConfigureAppletsMode() const;
void setInConfigureAppletsMode(const bool enabled);
bool isAvailableGeometryBroadcastedToPlasma() const;
void setIsAvailableGeometryBroadcastedToPlasma(const bool &isBroadcasted);
@ -91,12 +99,18 @@ public:
bool showInfoWindow() const;
void setShowInfoWindow(bool show);
int parabolicSpread() const;
void setParabolicSpread(const int &spread);
int version() const;
void setVersion(int ver);
int screenTrackerInterval() const;
void setScreenTrackerInterval(int duration);
float thicknessMarginInfluence() const;
void setThicknessMarginInfluence(const float &influence);
QString singleModeLayoutName() const;
void setSingleModeLayoutName(QString layoutName);
@ -132,18 +146,21 @@ signals:
void colorsScriptIsPresentChanged();
void downloadWindowSizeChanged();
void inAdvancedModeForEditSettingsChanged();
void inConfigureAppletsModeChanged();
void layoutsColumnWidthsChanged();
void layoutsWindowSizeChanged();
void launchersChanged();
void layoutsMemoryUsageChanged();
void isAvailableGeometryBroadcastedToPlasmaChanged();
void metaPressAndHoldEnabledChanged();
void parabolicSpreadChanged();
void sensitivityChanged();
void screensCountChanged();
void screenScalesChanged();
void screenTrackerIntervalChanged();
void showInfoWindowChanged();
void singleModeLayoutNameChanged();
void thicknessMarginInfluenceChanged();
void versionChanged();
private slots:
@ -170,6 +187,7 @@ private:
bool m_canDisableBorders{false};
bool m_colorsScriptIsPresent{false};
bool m_inAdvancedModeForEditSettings{false};
bool m_inConfigureAppletsMode{false};
bool m_isAvailableGeometryBroadcastedToPlasma{true};
bool m_metaPressAndHoldEnabled{true};
bool m_showInfoWindow{true};
@ -182,6 +200,8 @@ private:
int m_version{1};
int m_screenTrackerInterval{2500};
int m_parabolicSpread{Data::Preferences::PARABOLICSPREAD};
float m_thicknessMarginInfluence{Data::Preferences::THICKNESSMARGININFLUENCE};
QString m_singleModeLayoutName;

View File

@ -89,8 +89,8 @@ void CustomMenuItemWidget::paintEvent(QPaintEvent* e)
if (!m_screen.id.isEmpty()) {
int maxiconsize = 26;
remained = Latte::remainedFromScreenDrawing(opt, maxiconsize);
QRect availableScreenRect = Latte::drawScreen(&painter, opt, m_screen.geometry, maxiconsize);
remained = Latte::remainedFromScreenDrawing(opt, m_screen.isScreensGroup(), maxiconsize);
QRect availableScreenRect = Latte::drawScreen(&painter, opt, m_screen.isScreensGroup(), m_screen.geometry, maxiconsize);
if (!m_view.id.isEmpty()) {
Latte::drawView(&painter, opt, m_view, availableScreenRect);

View File

@ -27,7 +27,7 @@ NameDelegate::NameDelegate(QObject *parent)
void NameDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
editor->setGeometry(Latte::remainedFromScreenDrawing(option));
editor->setGeometry(Latte::remainedFromScreenDrawing(option, false));
}
void NameDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
@ -90,8 +90,8 @@ void NameDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
// draw screen icon
int maxiconsize = -1; //disabled
remainedrect = Latte::remainedFromScreenDrawing(myOptions, maxiconsize);
QRect availableScreenRect = Latte::drawScreen(painter, myOptions, screen.geometry, maxiconsize, textopacity);
remainedrect = Latte::remainedFromScreenDrawing(myOptions, screen.isScreensGroup(), maxiconsize);
QRect availableScreenRect = Latte::drawScreen(painter, myOptions, screen.isScreensGroup(), screen.geometry, maxiconsize, textopacity);
Latte::drawView(painter, myOptions, view, availableScreenRect, textopacity);
myOptions.rect = remainedrect;

View File

@ -31,12 +31,8 @@
// KDE
#include <KMessageWidget>
#include <KSharedConfig>
#if KF5_VERSION_MINOR >= 71
#include <KIO/OpenUrlJob>
#else
#include <KRun>
#endif
namespace Latte {
namespace Settings {
@ -604,12 +600,8 @@ void Views::showDefaultPersistentErrorWarningInlineMessage(const QString &messag
QString file = openlayoutaction->data().toString();
if (!file.isEmpty()) {
#if KF5_VERSION_MINOR >= 71
auto job = new KIO::OpenUrlJob(QUrl::fromLocalFile(file), QStringLiteral("text/plain"), this);
job->start();
#else
KRun::runUrl(QUrl::fromLocalFile(file), QStringLiteral("text/plain"), m_view);
#endif
showDefaultInlineMessageValidator();
}
});

View File

@ -424,16 +424,26 @@ Latte::Data::Screen Views::screenData(const QString &viewId) const
return Latte::Data::Screen();
}
QString primaryid = QString::number(m_corona->screenPool()->primaryScreenId());
// QString primaryid = QString::number(m_corona->screenPool()->primaryScreenId());
QString explicitid = QString::number(m_viewsTable[row].screen);
if (m_viewsTable[row].onPrimary && s_screens.containsId(primaryid)) {
return s_screens[primaryid];
Data::Screen scrData = s_screens[0]; //default
if (m_viewsTable[row].onPrimary || (m_viewsTable[row].screensGroup == Latte::Types::AllScreensGroup)) {
scrData = s_screens[0]; //primary, allscreens
} else if (m_viewsTable[row].screensGroup == Latte::Types::AllSecondaryScreensGroup) {
scrData = s_screens[2]; //allsecondaryscreens
} else if (!m_viewsTable[row].onPrimary && s_screens.containsId(explicitid)) {
return s_screens[explicitid];
scrData = s_screens[explicitid]; //explicit
}
return Latte::Data::Screen();
if (m_viewsTable[row].screensGroup == Latte::Types::AllScreensGroup) {
scrData.id = QString::number(Data::Screen::ONALLSCREENSID);
} else if (m_viewsTable[row].screensGroup == Latte::Types::AllSecondaryScreensGroup) {
scrData.id = QString::number(Data::Screen::ONALLSECONDARYSCREENSID);
}
return scrData;
}
Latte::Data::ViewsTable Views::alteredViews() const
@ -486,14 +496,21 @@ void Views::clearErrorsAndWarnings()
void Views::populateScreens()
{
s_screens.clear();
Data::Screen primary(QString::number(Data::Screen::ONPRIMARYID),
i18nc("primary screen", " - Follow Primary Screen - "));
Data::Screen primary(QString::number(Data::Screen::ONPRIMARYID), i18n(" - On Primary Screen - "));
Data::Screen allscreens(QString::number(Data::Screen::ONALLSCREENSID), i18n(" - On All Screens - "));
Data::Screen allsecscreens(QString::number(Data::Screen::ONALLSECONDARYSCREENSID), i18n(" - On All Secondary Screens - "));
primary.isActive = true;
allscreens.isActive = true;
allsecscreens.isActive = (m_corona->screenPool()->secondaryScreenIds().count() > 0);
primary.isActive = true;
s_screens << primary;
s_screens << allscreens;
s_screens << allsecscreens;
int defcount = s_screens.rowCount();
s_screens << m_corona->screenPool()->screensTable();
for (int i=1; i<s_screens.rowCount(); ++i) {
for (int i=defcount; i<s_screens.rowCount(); ++i) {
s_screens[i].isActive = m_corona->screenPool()->isScreenActive(s_screens[i].id.toInt());
}
}
@ -662,22 +679,30 @@ bool Views::setData(const QModelIndex &index, const QVariant &value, int role)
if (role == Qt::UserRole) {
int screen = value.toString().toInt();
bool onprimary = (screen == Latte::Data::Screen::ONPRIMARYID);
if ((m_viewsTable[row].onPrimary == onprimary) && (m_viewsTable[row].screen == screen)) {
return false;
}
bool onallscreens = (screen == Latte::Data::Screen::ONALLSCREENSID);
bool onallsecscreens = (screen == Latte::Data::Screen::ONALLSECONDARYSCREENSID);
if (onprimary) {
m_viewsTable[row].onPrimary = true;
m_viewsTable[row].screensGroup = Latte::Types::SingleScreenGroup;
} else if (onallscreens) {
m_viewsTable[row].onPrimary = true;
m_viewsTable[row].screensGroup = Latte::Types::AllScreensGroup;
} else if (onallsecscreens) {
m_viewsTable[row].onPrimary = false;
m_viewsTable[row].screensGroup = Latte::Types::AllSecondaryScreensGroup;
} else {
m_viewsTable[row].onPrimary = false;
m_viewsTable[row].screensGroup = Latte::Types::SingleScreenGroup;
m_viewsTable[row].screen = screen;
}
if (onprimary || onallscreens || onallsecscreens) {
if (o_viewsTable.containsId(m_viewsTable[row].id)) {
//! we need to update screen also in order to not show that there are changes even though
//! they are not any
m_viewsTable[row].screen = o_viewsTable[m_viewsTable[row].id].screen;
}
} else {
m_viewsTable[row].onPrimary = false;
m_viewsTable[row].screen = screen;
}
emit dataChanged(this->index(row, NAMECOLUMN), this->index(row, ALIGNMENTCOLUMN), roles);
@ -759,7 +784,7 @@ QVariant Views::data(const QModelIndex &index, int role) const
if (!m_viewsTable[row].onPrimary && !currentScreens.containsId(QString::number(m_viewsTable[row].screen))) {
Data::Screen explicitScr(QString::number(m_viewsTable[row].screen),
i18nc("unknown screen", "Unknown : [%1]", explicitScr.id));
i18nc("unknown screen", "Unknown: [%1]", explicitScr.id));
currentScreens.insertBasedOnId(explicitScr);
}
@ -838,18 +863,30 @@ QVariant Views::data(const QModelIndex &index, int role) const
break;
case SCREENCOLUMN:
if (role == Qt::DisplayRole){
if (m_viewsTable[row].onPrimary) {
if (m_viewsTable[row].screensGroup == Latte::Types::SingleScreenGroup && m_viewsTable[row].onPrimary) {
return i18nc("primary screen", "Primary");
} else if (m_viewsTable[row].screensGroup == Latte::Types::AllScreensGroup) {
return i18n("All Screens");
} else if (m_viewsTable[row].screensGroup == Latte::Types::AllSecondaryScreensGroup) {
return i18n("Secondary Screens");
} else {
QString scrId = QString::number(m_viewsTable[row].screen);
if (s_screens.containsId(scrId)) {
return s_screens[scrId].name;
} else {
return i18nc("unknown screen", "Unknown : [%1]", scrId);
return i18nc("unknown screen", "Unknown: [%1]", scrId);
}
}
} else if (role == Qt::UserRole) {
return m_viewsTable[row].onPrimary ? QString::number(Data::Screen::ONPRIMARYID) : QString::number(m_viewsTable[row].screen);
if (m_viewsTable[row].screensGroup == Latte::Types::SingleScreenGroup && m_viewsTable[row].onPrimary) {
return QString::number(Data::Screen::ONPRIMARYID);
} else if (m_viewsTable[row].screensGroup == Latte::Types::AllScreensGroup) {
return QString::number(Data::Screen::ONALLSCREENSID);
} else if (m_viewsTable[row].screensGroup == Latte::Types::AllSecondaryScreensGroup) {
return QString::number(Data::Screen::ONALLSECONDARYSCREENSID);
} else {
return QString::number(m_viewsTable[row].screen);
}
} else if (role == ISCHANGEDROLE) {
return (isNewView
|| (m_viewsTable[row].onPrimary != o_viewsTable[origviewid].onPrimary)

View File

@ -103,8 +103,8 @@ void GlobalShortcuts::init()
//show the layouts editor
QAction *layoutsAction = generalActions->addAction(QStringLiteral("show latte global settings"));
layoutsAction->setText(i18n("Show Latte Global Settings"));
layoutsAction->setShortcut(QKeySequence(Qt::META + Qt::Key_W));
KGlobalAccel::setGlobalShortcut(layoutsAction, QKeySequence(Qt::META + Qt::Key_W));
layoutsAction->setShortcut(QKeySequence());
KGlobalAccel::setGlobalShortcut(layoutsAction, QKeySequence());
connect(layoutsAction, &QAction::triggered, this, [this]() {
m_modifierTracker->cancelMetaPressed();
m_corona->layoutsManager()->showLatteSettingsDialog(Settings::Dialog::PreferencesPage, true);
@ -487,7 +487,7 @@ bool GlobalShortcuts::viewsToHideAreValid()
void GlobalShortcuts::showSettings()
{
QList<Latte::View *> sortedViews = m_corona->layoutsManager()->synchronizer()->sortedCurrentViews();
QList<Latte::View *> sortedViews = m_corona->layoutsManager()->synchronizer()->sortedCurrentOriginalViews();
//! find which is the next view to show its settings
if (sortedViews.count() > 0) {

View File

@ -214,10 +214,10 @@ QString Manager::proposedTemplateAbsolutePath(QString templateFilename)
QString tempfilename = templateFilename;
if (tempfilename.endsWith(".layout.latte")) {
QString clearedname = QFileInfo(tempfilename).baseName();
QString clearedname = tempfilename.chopped(QString(".layout.latte").size());
tempfilename = uniqueLayoutTemplateName(clearedname) + ".layout.latte";
} else if (tempfilename.endsWith(".view.latte")) {
QString clearedname = QFileInfo(tempfilename).baseName();
QString clearedname = tempfilename.chopped(QString(".view.latte").size());
tempfilename = uniqueViewTemplateName(clearedname) + ".view.latte";
}

View File

@ -1,7 +1,7 @@
set(lattedock-app_SRCS
${lattedock-app_SRCS}
${lattedock-app_SRCS}
${CMAKE_CURRENT_SOURCE_DIR}/clonedview.cpp
${CMAKE_CURRENT_SOURCE_DIR}/containmentinterface.cpp
${CMAKE_CURRENT_SOURCE_DIR}/contextmenu.cpp
${CMAKE_CURRENT_SOURCE_DIR}/effects.cpp
${CMAKE_CURRENT_SOURCE_DIR}/eventssink.cpp
${CMAKE_CURRENT_SOURCE_DIR}/panelshadows.cpp
@ -9,6 +9,7 @@ set(lattedock-app_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/positioner.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tasksmodel.cpp
${CMAKE_CURRENT_SOURCE_DIR}/view.cpp
${CMAKE_CURRENT_SOURCE_DIR}/originalview.cpp
${CMAKE_CURRENT_SOURCE_DIR}/visibilitymanager.cpp
PARENT_SCOPE
)

357
app/view/clonedview.cpp Normal file
View File

@ -0,0 +1,357 @@
/*
SPDX-FileCopyrightText: 2021 Michail Vourlakos <mvourlakos@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "clonedview.h"
#include "containmentinterface.h"
#include "visibilitymanager.h"
#include "../data/viewdata.h"
#include "../layouts/storage.h"
namespace Latte {
const int ClonedView::ERRORAPPLETID;
QStringList ClonedView::CONTAINMENTMANUALSYNCEDPROPERTIES = QStringList()
<< QString("appletOrder")
<< QString("lockedZoomApplets")
<< QString("userBlocksColorizingApplets");
ClonedView::ClonedView(Plasma::Corona *corona, Latte::OriginalView *originalView, QScreen *targetScreen, bool byPassX11WM)
: View(corona, targetScreen, byPassX11WM),
m_originalView(originalView)
{
m_originalView->addClone(this);
initSync();
}
ClonedView::~ClonedView()
{
}
void ClonedView::initSync()
{
connect(m_originalView, &View::containmentChanged, this, &View::groupIdChanged);
//! Update Visibility From Original
connect(m_originalView->visibility(), &Latte::ViewPart::VisibilityManager::modeChanged, this, [&]() {
visibility()->setMode(m_originalView->visibility()->mode());
});
connect(m_originalView->visibility(), &Latte::ViewPart::VisibilityManager::raiseOnDesktopChanged, this, [&]() {
visibility()->setRaiseOnDesktop(m_originalView->visibility()->raiseOnDesktop());
});
connect(m_originalView->visibility(), &Latte::ViewPart::VisibilityManager::raiseOnActivityChanged, this, [&]() {
visibility()->setRaiseOnActivity(m_originalView->visibility()->raiseOnActivity());
});
connect(m_originalView->visibility(), &Latte::ViewPart::VisibilityManager::enableKWinEdgesChanged, this, [&]() {
visibility()->setEnableKWinEdges(m_originalView->visibility()->enableKWinEdges());
});
connect(m_originalView->visibility(), &Latte::ViewPart::VisibilityManager::timerShowChanged, this, [&]() {
visibility()->setTimerShow(m_originalView->visibility()->timerShow());
});
connect(m_originalView->visibility(), &Latte::ViewPart::VisibilityManager::timerHideChanged, this, [&]() {
visibility()->setTimerHide(m_originalView->visibility()->timerHide());
});
//! Update Applets from Clone -> OriginalView
connect(extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletConfigPropertyChanged, this, &ClonedView::updateOriginalAppletConfigProperty);
connect(extendedInterface(), &Latte::ViewPart::ContainmentInterface::initializationCompleted, this, &ClonedView::updateAppletIdsHash);
connect(extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletsOrderChanged, this, &ClonedView::updateAppletIdsHash);
connect(extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletDataCreated, this, &ClonedView::updateAppletIdsHash);
connect(extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletCreated, this, [&](const QString &pluginId) {
m_originalView->addApplet(pluginId, containment()->id());
});
connect(extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletDropped, this, [&](QObject *data, int x, int y) {
m_originalView->addApplet(data, x, y, containment()->id());
});
//! Update Applets and Containment from OrigalView -> Clone
connect(m_originalView->extendedInterface(), &Latte::ViewPart::ContainmentInterface::containmentConfigPropertyChanged, this, &ClonedView::updateContainmentConfigProperty);
connect(m_originalView->extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletConfigPropertyChanged, this, &ClonedView::onOriginalAppletConfigPropertyChanged);
connect(m_originalView->extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletInScheduledDestructionChanged, this, &ClonedView::onOriginalAppletInScheduledDestructionChanged);
connect(m_originalView->extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletRemoved, this, &ClonedView::onOriginalAppletRemoved);
connect(m_originalView->extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletsOrderChanged, this, &ClonedView::onOriginalAppletsOrderChanged);
connect(m_originalView->extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletsInLockedZoomChanged, this, &ClonedView::onOriginalAppletsInLockedZoomChanged);
connect(m_originalView->extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletsDisabledColoringChanged, this, &ClonedView::onOriginalAppletsDisabledColoringChanged);
connect(m_originalView->extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletDataCreated, this, &ClonedView::updateAppletIdsHash);
connect(m_originalView->extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletCreated, this->extendedInterface(), [&](const QString &pluginId) {
extendedInterface()->addApplet(pluginId);
});
connect(m_originalView->extendedInterface(), &Latte::ViewPart::ContainmentInterface::appletDropped, this->extendedInterface(), [&](QObject *data, int x, int y) {
extendedInterface()->addApplet(data, x, y);
});
//! Indicator
connect(m_originalView, &Latte::View::indicatorChanged, this, &ClonedView::indicatorChanged);
}
bool ClonedView::isSingle() const
{
return false;
}
bool ClonedView::isOriginal() const
{
return false;
}
bool ClonedView::isCloned() const
{
return true;
}
bool ClonedView::isPreferredForShortcuts() const
{
return false;
}
int ClonedView::groupId() const
{
if (!m_originalView->containment()) {
return -1;
}
return m_originalView->containment()->id();
}
Latte::Types::ScreensGroup ClonedView::screensGroup() const
{
return Latte::Types::SingleScreenGroup;
}
ViewPart::Indicator *ClonedView::indicator() const
{
return m_originalView->indicator();
}
bool ClonedView::hasOriginalAppletId(const int &clonedid)
{
if (clonedid < 0) {
return false;
}
QHash<int, int>::const_iterator i = m_currentAppletIds.constBegin();
while (i != m_currentAppletIds.constEnd()) {
if (i.value() == clonedid) {
return true;
}
++i;
}
return false;
}
int ClonedView::originalAppletId(const int &clonedid)
{
if (clonedid < 0) {
return -1;
}
QHash<int, int>::const_iterator i = m_currentAppletIds.constBegin();
while (i != m_currentAppletIds.constEnd()) {
if (i.value() == clonedid) {
return i.key();
}
++i;
}
return -1;
}
bool ClonedView::isTranslatableToClonesOrder(const QList<int> &originalOrder)
{
for(int i=0; i<originalOrder.count(); ++i) {
int oid = originalOrder[i];
if (oid < 0 ) {
continue;
}
if (!m_currentAppletIds.contains(oid)) {
return false;
}
}
return true;
}
Latte::Data::View ClonedView::data() const
{
Latte::Data::View vdata = View::data();
vdata.isClonedFrom = m_originalView->containment()->id();
return vdata;
}
void ClonedView::updateAppletIdsHash()
{
QList<int> originalids = m_originalView->extendedInterface()->appletsOrder();
QList<int> clonedids = extendedInterface()->appletsOrder();
for (int i=0; i<originalids.count(); ++i) {
int oid = originalids[i];
if (oid < 0 || (m_currentAppletIds.contains(oid) && m_currentAppletIds[oid] > 0)) {
continue;
}
int oindex = m_originalView->extendedInterface()->indexOfApplet(oid);
ViewPart::AppletInterfaceData originalapplet = m_originalView->extendedInterface()->appletDataForId(oid);
ViewPart::AppletInterfaceData clonedapplet = extendedInterface()->appletDataAtIndex(oindex);
bool registeredclonedid = (originalAppletId(clonedapplet.id) > 0);
if (originalapplet.id>0 && clonedapplet.id>0 && originalapplet.plugin == clonedapplet.plugin && !registeredclonedid) {
m_currentAppletIds[originalapplet.id] = clonedapplet.id;
}
}
}
QList<int> ClonedView::translateToClonesOrder(const QList<int> &originalIds)
{
QList<int> ids;
for (int i=0; i<originalIds.count(); ++i) {
int originalid = originalIds[i];
if (originalid < 0 ) {
ids << originalid;
continue;
}
if (m_currentAppletIds.contains(originalid)) {
ids << m_currentAppletIds[originalid];
} else {
ids << ERRORAPPLETID; //error
}
}
return ids;
}
void ClonedView::showConfigurationInterface(Plasma::Applet *applet)
{
Plasma::Containment *c = qobject_cast<Plasma::Containment *>(applet);
if (Layouts::Storage::self()->isLatteContainment(c)) {
m_originalView->showSettingsWindow();
} else {
View::showConfigurationInterface(applet);
}
}
void ClonedView::onOriginalAppletRemoved(const int &id)
{
if (!m_currentAppletIds.contains(id)) {
return;
}
extendedInterface()->removeApplet(m_currentAppletIds[id]);
m_currentAppletIds.remove(id);
}
void ClonedView::onOriginalAppletConfigPropertyChanged(const int &id, const QString &key, const QVariant &value)
{
if (!m_currentAppletIds.contains(id)) {
return;
}
extendedInterface()->updateAppletConfigProperty(m_currentAppletIds[id], key, value);
}
void ClonedView::onOriginalAppletInScheduledDestructionChanged(const int &id, const bool &enabled)
{
if (!m_currentAppletIds.contains(id)) {
return;
}
extendedInterface()->setAppletInScheduledDestruction(m_currentAppletIds[id], enabled);
}
void ClonedView::updateContainmentConfigProperty(const QString &key, const QVariant &value)
{
if (!CONTAINMENTMANUALSYNCEDPROPERTIES.contains(key)) {
extendedInterface()->updateContainmentConfigProperty(key, value);
} else {
//qDebug() << "org.kde.sync :: containment config value syncing blocked :: " << key;
}
}
void ClonedView::updateOriginalAppletConfigProperty(const int &clonedid, const QString &key, const QVariant &value)
{
if (!hasOriginalAppletId(clonedid)) {
return;
}
m_originalView->extendedInterface()->updateAppletConfigProperty(originalAppletId(clonedid), key, value);
}
void ClonedView::onOriginalAppletsOrderChanged()
{
updateAppletIdsHash();
QList<int> originalorder = m_originalView->extendedInterface()->appletsOrder();
if (originalorder.count() != extendedInterface()->appletsOrder().count()) {
//probably an applet was removed or added and clone has not been updated yet
return;
}
if (!isTranslatableToClonesOrder(originalorder)) {
qDebug() << "org.kde.sync ::: original applets order changed but unfortunately original order can not be translated to cloned ids...";
return;
}
QList<int> newclonesorder = translateToClonesOrder(originalorder);
if (newclonesorder.contains(ERRORAPPLETID)) {
qDebug() << "org.kde.sync ::: original applets order changed but unfortunately original and clones order map can not be generated...";
return;
}
extendedInterface()->setAppletsOrder(newclonesorder);
}
void ClonedView::onOriginalAppletsInLockedZoomChanged(const QList<int> &originalapplets)
{
if (!isTranslatableToClonesOrder(originalapplets)) {
qDebug() << "org.kde.sync ::: original applets order changed but unfortunately original order can not be translated to cloned ids...";
return;
}
QList<int> newclonesorder = translateToClonesOrder(originalapplets);
if (newclonesorder.contains(ERRORAPPLETID)) {
qDebug() << "org.kde.sync ::: original applets order changed but unfortunately original and clones order map can not be generated...";
return;
}
extendedInterface()->setAppletsInLockedZoom(newclonesorder);
}
void ClonedView::onOriginalAppletsDisabledColoringChanged(const QList<int> &originalapplets)
{
if (!isTranslatableToClonesOrder(originalapplets)) {
qDebug() << "org.kde.sync ::: original applets order changed but unfortunately original order can not be translated to cloned ids...";
return;
}
QList<int> newclonesorder = translateToClonesOrder(originalapplets);
if (newclonesorder.contains(ERRORAPPLETID)) {
qDebug() << "org.kde.sync ::: original applets order changed but unfortunately original and clones order map can not be generated...";
return;
}
extendedInterface()->setAppletsDisabledColoring(newclonesorder);
}
}

72
app/view/clonedview.h Normal file
View File

@ -0,0 +1,72 @@
/*
SPDX-FileCopyrightText: 2021 Michail Vourlakos <mvourlakos@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef CLONEDVIEW_H
#define CLONEDVIEW_H
// local
#include <coretypes.h>
#include "originalview.h"
#include "indicator/indicator.h"
#include "view.h"
namespace Latte {
class ClonedView : public View
{
Q_OBJECT
public:
static const int ERRORAPPLETID = -999;
ClonedView(Plasma::Corona *corona, Latte::OriginalView *originalView, QScreen *targetScreen = nullptr, bool byPassX11WM = false);
~ClonedView();
bool isOriginal() const override;
bool isCloned() const override;
bool isSingle() const override;
bool isPreferredForShortcuts() const override;
int groupId() const override;
Latte::Types::ScreensGroup screensGroup() const override;
ViewPart::Indicator *indicator() const override;
Latte::Data::View data() const override;
protected:
void showConfigurationInterface(Plasma::Applet *applet) override;
private slots:
void initSync();
void onOriginalAppletConfigPropertyChanged(const int &id, const QString &key, const QVariant &value);
void onOriginalAppletInScheduledDestructionChanged(const int &id, const bool &enabled);
void onOriginalAppletRemoved(const int &id);
void onOriginalAppletsOrderChanged();
void onOriginalAppletsInLockedZoomChanged(const QList<int> &originalapplets);
void onOriginalAppletsDisabledColoringChanged(const QList<int> &originalapplets);
void updateContainmentConfigProperty(const QString &key, const QVariant &value);
void updateOriginalAppletConfigProperty(const int &clonedid, const QString &key, const QVariant &value);
void updateAppletIdsHash();
private:
bool isTranslatableToClonesOrder(const QList<int> &originalOrder);
bool hasOriginalAppletId(const int &clonedid);
int originalAppletId(const int &clonedid);
QList<int> translateToClonesOrder(const QList<int> &originalIds);
private:
static QStringList CONTAINMENTMANUALSYNCEDPROPERTIES;
QPointer<Latte::OriginalView> m_originalView;
QHash<int, int> m_currentAppletIds;
};
}
#endif

View File

@ -9,11 +9,13 @@
#include "view.h"
#include "../lattecorona.h"
#include "../layout/genericlayout.h"
#include "../layouts/importer.h"
#include "../layouts/storage.h"
#include "../settings/universalsettings.h"
// Qt
#include <QDebug>
#include <QDir>
#include <QLatin1String>
// Plasma
@ -25,6 +27,7 @@
#include <KDesktopFile>
#include <KLocalizedString>
#include <KPluginMetaData>
#include <KDeclarative/ConfigPropertyMap>
namespace Latte {
namespace ViewPart {
@ -41,13 +44,16 @@ ContainmentInterface::ContainmentInterface(Latte::View *parent)
m_appletsExpandedConnectionsTimer.setInterval(2000);
m_appletsExpandedConnectionsTimer.setSingleShot(true);
m_appletDelayedConfigurationTimer.setInterval(1000);
m_appletDelayedConfigurationTimer.setSingleShot(true);
connect(&m_appletDelayedConfigurationTimer, &QTimer::timeout, this, &ContainmentInterface::updateAppletDelayedConfiguration);
connect(&m_appletsExpandedConnectionsTimer, &QTimer::timeout, this, &ContainmentInterface::updateAppletsTracking);
connect(m_view, &View::containmentChanged
, this, [&]() {
if (m_view->containment()) {
connect(m_view->containment(), &Plasma::Containment::appletAdded, this, &ContainmentInterface::onAppletAdded);
m_appletsExpandedConnectionsTimer.start();
}
});
@ -423,7 +429,7 @@ bool ContainmentInterface::appletIsExpandable(const int id) const
for (const auto applet : m_view->containment()->applets()) {
if (applet && applet->id() == (uint)id) {
if (Layouts::Storage::self()->isSubContainment(m_view->layout(), applet)) {
if (Layouts::Storage::self()->isSubContainment(m_view->corona(), applet)) {
return true;
}
@ -446,7 +452,7 @@ bool ContainmentInterface::appletIsExpandable(PlasmaQuick::AppletQuickItem *appl
return ((appletQuickItem->fullRepresentation() != nullptr
&& appletQuickItem->preferredRepresentation() != appletQuickItem->fullRepresentation())
|| Latte::Layouts::Storage::self()->isSubContainment(m_view->layout(), appletQuickItem->applet()));
|| Latte::Layouts::Storage::self()->isSubContainment(m_view->corona(), appletQuickItem->applet()));
}
bool ContainmentInterface::appletIsActivationTogglesExpanded(const int id) const
@ -457,7 +463,7 @@ bool ContainmentInterface::appletIsActivationTogglesExpanded(const int id) const
for (const auto applet : m_view->containment()->applets()) {
if (applet && applet->id() == (uint)id) {
if (Layouts::Storage::self()->isSubContainment(m_view->layout(), applet)) {
if (Layouts::Storage::self()->isSubContainment(m_view->corona(), applet)) {
return true;
}
@ -487,6 +493,148 @@ bool ContainmentInterface::hasPlasmaTasks() const
return (m_plasmaTasksModel->count() > 0);
}
int ContainmentInterface::indexOfApplet(const int &id)
{
if (m_appletOrder.contains(id)) {
return m_appletOrder.indexOf(id);
} else if (m_appletData.contains(id)) {
return m_appletData[id].lastValidIndex;
}
return -1;
}
ViewPart::AppletInterfaceData ContainmentInterface::appletDataAtIndex(const int &index)
{
ViewPart::AppletInterfaceData data;
if (index<0 || (index > (m_appletOrder.count()-1))) {
return data;
}
return m_appletData[m_appletOrder[index]];
}
ViewPart::AppletInterfaceData ContainmentInterface::appletDataForId(const int &id)
{
ViewPart::AppletInterfaceData data;
if (!m_appletData.contains(id)) {
return data;
}
return m_appletData[id];
}
QObject *ContainmentInterface::plasmoid() const
{
return m_plasmoid;
}
void ContainmentInterface::setPlasmoid(QObject *plasmoid)
{
if (m_plasmoid == plasmoid) {
return;
}
m_plasmoid = plasmoid;
if (m_plasmoid) {
m_configuration = qobject_cast<KDeclarative::ConfigPropertyMap *>(m_plasmoid->property("configuration").value<QObject *>());
if (m_configuration) {
connect(m_configuration, &QQmlPropertyMap::valueChanged, this, &ContainmentInterface::containmentConfigPropertyChanged);
}
}
emit plasmoidChanged();
}
QObject *ContainmentInterface::layoutManager() const
{
return m_layoutManager;
}
void ContainmentInterface::setLayoutManager(QObject *manager)
{
if (m_layoutManager == manager) {
return;
}
m_layoutManager = manager;
// applets order
int metaorderindex = m_layoutManager->metaObject()->indexOfProperty("order");
if (metaorderindex >= 0) {
QMetaProperty metaorder = m_layoutManager->metaObject()->property(metaorderindex);
if (metaorder.hasNotifySignal()) {
QMetaMethod metaorderchanged = metaorder.notifySignal();
QMetaMethod metaupdateappletorder = this->metaObject()->method(this->metaObject()->indexOfSlot("updateAppletsOrder()"));
connect(m_layoutManager, metaorderchanged, this, metaupdateappletorder);
updateAppletsOrder();
}
}
// applets in locked zoom
metaorderindex = m_layoutManager->metaObject()->indexOfProperty("lockedZoomApplets");
if (metaorderindex >= 0) {
QMetaProperty metaorder = m_layoutManager->metaObject()->property(metaorderindex);
if (metaorder.hasNotifySignal()) {
QMetaMethod metaorderchanged = metaorder.notifySignal();
QMetaMethod metaupdateapplets = this->metaObject()->method(this->metaObject()->indexOfSlot("updateAppletsInLockedZoom()"));
connect(m_layoutManager, metaorderchanged, this, metaupdateapplets);
updateAppletsInLockedZoom();
}
}
// applets disabled their autocoloring
metaorderindex = m_layoutManager->metaObject()->indexOfProperty("userBlocksColorizingApplets");
if (metaorderindex >= 0) {
QMetaProperty metaorder = m_layoutManager->metaObject()->property(metaorderindex);
if (metaorder.hasNotifySignal()) {
QMetaMethod metaorderchanged = metaorder.notifySignal();
QMetaMethod metaupdateapplets = this->metaObject()->method(this->metaObject()->indexOfSlot("updateAppletsDisabledColoring()"));
connect(m_layoutManager, metaorderchanged, this, metaupdateapplets);
updateAppletsDisabledColoring();
}
}
emit layoutManagerChanged();
}
void ContainmentInterface::addApplet(const QString &pluginId)
{
if (pluginId.isEmpty()) {
return;
}
QStringList paths = Latte::Layouts::Importer::standardPaths();
QString pluginpath;
for(int i=0; i<paths.count(); ++i) {
QString cpath = paths[i] + "/plasma/plasmoids/" + pluginId;
if (QDir(cpath).exists()) {
pluginpath = cpath;
break;
}
}
if (!pluginpath.isEmpty()) {
m_view->containment()->createApplet(pluginId);
}
}
void ContainmentInterface::addApplet(QObject *metadata, int x, int y)
{
int processmimedataindex = m_plasmoid->metaObject()->indexOfMethod("processMimeData(QObject*,int,int)");
QMetaMethod processmethod = m_plasmoid->metaObject()->method(processmimedataindex);
processmethod.invoke(m_plasmoid,
Q_ARG(QObject *, metadata),
Q_ARG(int, x),
Q_ARG(int, y));
}
void ContainmentInterface::addExpandedApplet(PlasmaQuick::AppletQuickItem * appletQuickItem)
{
if (appletQuickItem && m_expandedAppletIds.contains(appletQuickItem) && appletIsExpandable(appletQuickItem)) {
@ -555,6 +703,68 @@ void ContainmentInterface::onAppletExpandedChanged()
}
}
QList<int> ContainmentInterface::appletsOrder() const
{
return m_appletOrder;
}
void ContainmentInterface::updateAppletsOrder()
{
if (!m_layoutManager) {
return;
}
QList<int> neworder = m_layoutManager->property("order").value<QList<int>>();
if (m_appletOrder == neworder) {
return;
}
m_appletOrder = neworder;
//! update applets last recorded index, this is needed for example when an applet is removed
//! to know in which index was located before the removal
for(const auto &id: m_appletOrder) {
if (m_appletData.contains(id)) {
m_appletData[id].lastValidIndex = m_appletOrder.indexOf(id);
}
}
emit appletsOrderChanged();
}
void ContainmentInterface::updateAppletsInLockedZoom()
{
if (!m_layoutManager) {
return;
}
QList<int> appletslockedzoom = m_layoutManager->property("lockedZoomApplets").value<QList<int>>();
if (m_appletsInLockedZoom == appletslockedzoom) {
return;
}
m_appletsInLockedZoom = appletslockedzoom;
emit appletsInLockedZoomChanged(m_appletsInLockedZoom);
}
void ContainmentInterface::updateAppletsDisabledColoring()
{
if (!m_layoutManager) {
return;
}
QList<int> appletsdisabledcoloring = m_layoutManager->property("userBlocksColorizingApplets").value<QList<int>>();
if (m_appletsDisabledColoring == appletsdisabledcoloring) {
return;
}
m_appletsDisabledColoring = appletsdisabledcoloring;
emit appletsDisabledColoringChanged(appletsdisabledcoloring);
}
void ContainmentInterface::onLatteTasksCountChanged()
{
if ((m_hasLatteTasks && m_latteTasksModel->count()>0)
@ -589,7 +799,7 @@ void ContainmentInterface::toggleAppletExpanded(const int id)
}
for (const auto applet : m_view->containment()->applets()) {
if (applet->id() == (uint)id && !Layouts::Storage::self()->isSubContainment(m_view->layout(), applet)/*block for sub-containments*/) {
if (applet->id() == (uint)id && !Layouts::Storage::self()->isSubContainment(m_view->corona(), applet)/*block for sub-containments*/) {
PlasmaQuick::AppletQuickItem *ai = applet->property("_plasma_graphicObject").value<PlasmaQuick::AppletQuickItem *>();
if (ai) {
@ -599,6 +809,78 @@ void ContainmentInterface::toggleAppletExpanded(const int id)
}
}
void ContainmentInterface::removeApplet(const int &id)
{
if (!m_appletData.contains(id)) {
return;
}
auto applet = m_appletData[id].applet;
emit applet->appletDeleted(applet); //! this signal should be part of Plasma Frameworks AppletPrivate::destroy() function...
applet->destroy();
}
void ContainmentInterface::setAppletsOrder(const QList<int> &order)
{
QMetaObject::invokeMethod(m_layoutManager,
"requestAppletsOrder",
Qt::DirectConnection,
Q_ARG(QList<int>, order));
}
void ContainmentInterface::setAppletsInLockedZoom(const QList<int> &applets)
{
QMetaObject::invokeMethod(m_layoutManager,
"requestAppletsInLockedZoom",
Qt::DirectConnection,
Q_ARG(QList<int>, applets));
}
void ContainmentInterface::setAppletsDisabledColoring(const QList<int> &applets)
{
QMetaObject::invokeMethod(m_layoutManager,
"requestAppletsDisabledColoring",
Qt::DirectConnection,
Q_ARG(QList<int>, applets));
}
void ContainmentInterface::setAppletInScheduledDestruction(const int &id, const bool &enabled)
{
QMetaObject::invokeMethod(m_layoutManager,
"setAppletInScheduledDestruction",
Qt::DirectConnection,
Q_ARG(int, id),
Q_ARG(bool, enabled));
}
void ContainmentInterface::updateContainmentConfigProperty(const QString &key, const QVariant &value)
{
if (!m_configuration || !m_configuration->keys().contains(key)) {
}
if (m_configuration->keys().contains(key)
&& (*m_configuration)[key] != value) {
m_configuration->insert(key, value);
emit m_configuration->valueChanged(key, value);
}
}
void ContainmentInterface::updateAppletConfigProperty(const int &id, const QString &key, const QVariant &value)
{
if (!m_appletData.contains(id) || !m_appletData[id].configuration || !m_appletData[id].configuration->keys().contains(key)) {
return;
}
if (m_appletData[id].configuration->keys().contains(key)
&& (*m_appletData[id].configuration)[key] != value) {
m_appletData[id].configuration->insert(key, value);
emit m_appletData[id].configuration->valueChanged(key, value);
}
}
void ContainmentInterface::updateAppletsTracking()
{
if (!m_view->containment()) {
@ -608,6 +890,69 @@ void ContainmentInterface::updateAppletsTracking()
for (const auto applet : m_view->containment()->applets()) {
onAppletAdded(applet);
}
emit initializationCompleted();
}
void ContainmentInterface::updateAppletDelayedConfiguration()
{
for (const auto id : m_appletData.keys()) {
if (!m_appletData[id].configuration) {
m_appletData[id].configuration = appletConfiguration(m_appletData[id].applet);
if (m_appletData[id].configuration) {
qDebug() << "org.kde.sync delayed applet configuration was successful for : " << id;
initAppletConfigurationSignals(id, m_appletData[id].configuration);
}
}
}
}
void ContainmentInterface::initAppletConfigurationSignals(const int &id, KDeclarative::ConfigPropertyMap *configuration)
{
if (!configuration) {
return;
}
connect(configuration, &QQmlPropertyMap::valueChanged,
this, [&, id](const QString &key, const QVariant &value) {
//qDebug() << "org.kde.sync applet property changed : " << currentAppletId << " __ " << m_appletData[currentAppletId].plugin << " __ " << key << " __ " << value;
emit appletConfigPropertyChanged(id, key, value);
});
}
KDeclarative::ConfigPropertyMap *ContainmentInterface::appletConfiguration(const Plasma::Applet *applet)
{
if (!m_view->containment() || !applet) {
return nullptr;
}
PlasmaQuick::AppletQuickItem *ai = applet->property("_plasma_graphicObject").value<PlasmaQuick::AppletQuickItem *>();
bool isSubContainment = Layouts::Storage::self()->isSubContainment(m_view->corona(), applet); //we use corona() to make sure that returns true even when it is first created from user
int currentAppletId = applet->id();
KDeclarative::ConfigPropertyMap *configuration{nullptr};
//! set configuration object properly for applets and subcontainments
if (!isSubContainment) {
int metaconfigindex = ai->metaObject()->indexOfProperty("configuration");
if (metaconfigindex >=0 ){
configuration = qobject_cast<KDeclarative::ConfigPropertyMap *>((ai->property("configuration")).value<QObject *>());
}
} else {
Plasma::Containment *subcontainment = Layouts::Storage::self()->subContainmentOf(m_view->corona(), applet);
if (subcontainment) {
PlasmaQuick::AppletQuickItem *subcai = subcontainment->property("_plasma_graphicObject").value<PlasmaQuick::AppletQuickItem *>();
if (subcai) {
int metaconfigindex = subcai->metaObject()->indexOfProperty("configuration");
if (metaconfigindex >=0 ){
configuration = qobject_cast<KDeclarative::ConfigPropertyMap *>((subcai->property("configuration")).value<QObject *>());
}
}
}
}
return configuration;
}
void ContainmentInterface::onAppletAdded(Plasma::Applet *applet)
@ -616,10 +961,15 @@ void ContainmentInterface::onAppletAdded(Plasma::Applet *applet)
return;
}
if (Layouts::Storage::self()->isSubContainment(m_view->layout(), applet)) {
PlasmaQuick::AppletQuickItem *ai = applet->property("_plasma_graphicObject").value<PlasmaQuick::AppletQuickItem *>();
bool isSubContainment = Layouts::Storage::self()->isSubContainment(m_view->corona(), applet); //we use corona() to make sure that returns true even when it is first created from user
int currentAppletId = applet->id();
//! Track expanded/able applets and Tasks applets
if (isSubContainment) {
//! internal containment case
Plasma::Containment *subContainment = Layouts::Storage::self()->subContainmentOf(m_view->layout(), applet);
PlasmaQuick::AppletQuickItem *contAi = applet->property("_plasma_graphicObject").value<PlasmaQuick::AppletQuickItem *>();
Plasma::Containment *subContainment = Layouts::Storage::self()->subContainmentOf(m_view->corona(), applet);
PlasmaQuick::AppletQuickItem *contAi = ai;
if (contAi && !m_appletsExpandedConnections.contains(contAi)) {
m_appletsExpandedConnections[contAi] = connect(contAi, &PlasmaQuick::AppletQuickItem::expandedChanged, this, &ContainmentInterface::onAppletExpandedChanged);
@ -642,13 +992,7 @@ void ContainmentInterface::onAppletAdded(Plasma::Applet *applet)
});
}
}
} else {
PlasmaQuick::AppletQuickItem *ai = applet->property("_plasma_graphicObject").value<PlasmaQuick::AppletQuickItem *>();
if (!ai) {
return;
}
} else if (ai) {
KPluginMetaData meta = applet->kPackage().metadata();
const auto &provides = KPluginMetaData::readStringList(meta.rawData(), QStringLiteral("X-Plasma-Provides"));
@ -668,6 +1012,56 @@ void ContainmentInterface::onAppletAdded(Plasma::Applet *applet)
}
}
//! Track All Applets, for example to support syncing between different docks and panels
if (ai) {
bool initializing{!m_appletData.contains(currentAppletId)};
KPluginMetaData meta = applet->kPackage().metadata();
ViewPart::AppletInterfaceData data;
data.id = currentAppletId;
data.plugin = meta.pluginId();
data.applet = applet;
data.plasmoid = ai;
data.lastValidIndex = m_appletOrder.indexOf(data.id);
//! set configuration object properly for applets and subcontainments
data.configuration = appletConfiguration(applet);
//! track property changes in applets
if (data.configuration) {
initAppletConfigurationSignals(data.id, data.configuration);
} else {
qDebug() << "org.kde.sync Unfortunately configuration syncing for :: " << currentAppletId << " was not established, configuration object was missing!";
m_appletDelayedConfigurationTimer.start();
}
if (initializing) {
//! track applet destroyed flag
connect(applet, &Plasma::Applet::destroyedChanged, this, [&, currentAppletId](bool destroyed) {
emit appletInScheduledDestructionChanged(currentAppletId, destroyed);
});
//! remove on applet destruction
connect(applet, &QObject::destroyed, this, [&, data](){
emit appletRemoved(data.id);
//qDebug() << "org.kde.sync: removing applet ::: " << data.id << " __ " << data.plugin << " remained : " << m_appletData.keys();
m_appletData.remove(data.id);
});
}
m_appletData[data.id] = data;
emit appletDataCreated(data.id);
}
}
QList<int> ContainmentInterface::toIntList(const QVariantList &list)
{
QList<int> converted;
for(const QVariant &item: list) {
converted << item.toInt();
}
return converted;
}
}

View File

@ -10,8 +10,8 @@
#include "tasksmodel.h"
// Qt
#include <QMetaMethod>
#include <QHash>
#include <QMetaMethod>
#include <QObject>
#include <QPointer>
#include <QQuickItem>
@ -26,6 +26,10 @@ namespace PlasmaQuick {
class AppletQuickItem;
}
namespace KDeclarative {
class ConfigPropertyMap;
}
namespace Latte {
class Corona;
class View;
@ -34,6 +38,16 @@ class View;
namespace Latte {
namespace ViewPart {
struct AppletInterfaceData
{
int id{-1};
QString plugin;
int lastValidIndex{-1};
Plasma::Applet *applet{nullptr};
PlasmaQuick::AppletQuickItem *plasmoid{nullptr};
KDeclarative::ConfigPropertyMap *configuration{nullptr};
};
class ContainmentInterface: public QObject
{
Q_OBJECT
@ -41,9 +55,14 @@ class ContainmentInterface: public QObject
Q_PROPERTY(bool hasLatteTasks READ hasLatteTasks NOTIFY hasLatteTasksChanged)
Q_PROPERTY(bool hasPlasmaTasks READ hasPlasmaTasks NOTIFY hasPlasmaTasksChanged)
Q_PROPERTY(QObject *plasmoid READ plasmoid() WRITE setPlasmoid NOTIFY plasmoidChanged)
Q_PROPERTY(QAbstractListModel *latteTasksModel READ latteTasksModel() NOTIFY latteTasksModelChanged)
Q_PROPERTY(QAbstractListModel *plasmaTasksModel READ plasmaTasksModel() NOTIFY plasmaTasksModelChanged)
//! specified from containment qml side
Q_PROPERTY(QObject* layoutManager READ layoutManager WRITE setLayoutManager NOTIFY layoutManagerChanged)
public:
ContainmentInterface(Latte::View *parent);
virtual ~ContainmentInterface();
@ -73,6 +92,17 @@ public:
int applicationLauncherId() const;
int appletIdForVisualIndex(const int index);
int indexOfApplet(const int &id);
QList<int> appletsOrder() const;
ViewPart::AppletInterfaceData appletDataAtIndex(const int &index);
ViewPart::AppletInterfaceData appletDataForId(const int &id);
QObject *plasmoid() const;
void setPlasmoid(QObject *plasmoid);
QObject *layoutManager() const;
void setLayoutManager(QObject *manager);
QAbstractListModel *latteTasksModel() const;
QAbstractListModel *plasmaTasksModel() const;
@ -86,13 +116,39 @@ public slots:
Q_INVOKABLE bool isApplication(const QUrl &url) const;
void addApplet(const QString &pluginId);
void addApplet(QObject *metadata, int x, int y);
void removeApplet(const int &id);
void setAppletsOrder(const QList<int> &order);
void setAppletsInLockedZoom(const QList<int> &applets);
void setAppletsDisabledColoring(const QList<int> &applets);
void setAppletInScheduledDestruction(const int &id, const bool &enabled);
void updateContainmentConfigProperty(const QString &key, const QVariant &value);
void updateAppletConfigProperty(const int &id, const QString &key, const QVariant &value);
signals:
void expandedAppletStateChanged();
void hasExpandedAppletChanged();
void hasLatteTasksChanged();
void hasPlasmaTasksChanged();
void initializationCompleted();
void latteTasksModelChanged();
void layoutManagerChanged();
void plasmaTasksModelChanged();
void plasmoidChanged();
//! syncing signals
void appletRemoved(const int &id);
void appletConfigPropertyChanged(const int &id, const QString &key, const QVariant &value);
void appletCreated(const QString &pluginId);
void appletDataCreated(const int &id);
void appletDropped(QObject *data, int x, int y);
void containmentConfigPropertyChanged(const QString &key, const QVariant &value);
void appletsOrderChanged();
void appletsInLockedZoomChanged(const QList<int> &applets);
void appletsDisabledColoringChanged(const QList<int> &applets);
void appletInScheduledDestructionChanged(const int &id, const bool &enabled);
void appletRequestedVisualIndicator(const int &plasmoidId);
@ -100,7 +156,12 @@ private slots:
void identifyShortcutsHost();
void identifyMethods();
void updateAppletsOrder();
void updateAppletsInLockedZoom();
void updateAppletsDisabledColoring();
void updateAppletsTracking();
void updateAppletDelayedConfiguration();
void onAppletAdded(Plasma::Applet *applet);
void onAppletExpandedChanged();
void onLatteTasksCountChanged();
@ -109,9 +170,14 @@ private slots:
private:
void addExpandedApplet(PlasmaQuick::AppletQuickItem * appletQuickItem);
void removeExpandedApplet(PlasmaQuick::AppletQuickItem *appletQuickItem);
void initAppletConfigurationSignals(const int &id, KDeclarative::ConfigPropertyMap *configuration);
bool appletIsExpandable(PlasmaQuick::AppletQuickItem *appletQuickItem) const;
KDeclarative::ConfigPropertyMap *appletConfiguration(const Plasma::Applet *applet);
QList<int> toIntList(const QVariantList &list);
private:
bool m_hasLatteTasks{false};
bool m_hasPlasmaTasks{false};
@ -132,9 +198,21 @@ private:
TasksModel *m_latteTasksModel;
TasksModel *m_plasmaTasksModel;
//!follow containment plasmoid
QPointer<QObject> m_plasmoid;
QPointer<QObject> m_layoutManager;
QPointer<KDeclarative::ConfigPropertyMap> m_configuration;
//!keep record of applet ids and avoid crashes when trying to access ids for already destroyed applets
QHash<PlasmaQuick::AppletQuickItem *, int> m_expandedAppletIds;
QHash<PlasmaQuick::AppletQuickItem *, QMetaObject::Connection> m_appletsExpandedConnections;
//!all applet data
QList<int> m_appletOrder; //includes justify splitters
QList<int> m_appletsInLockedZoom;
QList<int> m_appletsDisabledColoring;
QHash<int, ViewPart::AppletInterfaceData> m_appletData;
QTimer m_appletDelayedConfigurationTimer;
};
}

View File

@ -1,584 +0,0 @@
/*
SPDX-FileCopyrightText: 2018 Michail Vourlakos <mvourlakos@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "contextmenu.h"
// local
#include "view.h"
#include "visibilitymanager.h"
#include "../lattecorona.h"
#include "../layouts/storage.h"
// Qt
#include <QMouseEvent>
#include <QVersionNumber>
#include <QLatin1String>
// KDE
#include <KActionCollection>
#include <KAuthorized>
#include <KLocalizedString>
// Plasma
#include <Plasma/Applet>
#include <Plasma/Containment>
#include <Plasma/ContainmentActions>
#include <Plasma/Corona>
#include <PlasmaQuick/AppletQuickItem>
#define BLOCKHIDINGTYPE "View::contextMenu()"
namespace Latte {
namespace ViewPart {
ContextMenu::ContextMenu(Latte::View *view) :
QObject(view),
m_latteView(view)
{
}
ContextMenu::~ContextMenu()
{
}
QMenu *ContextMenu::menu()
{
return m_contextMenu;
}
void ContextMenu::menuAboutToHide()
{
if (!m_latteView) {
return;
}
m_contextMenu = 0;
emit menuChanged();
}
QPoint ContextMenu::popUpRelevantToParent(const QRect &parentItem, const QRect popUpRect)
{
QPoint resultPoint;
if (m_latteView->location() == Plasma::Types::TopEdge) {
resultPoint.setX(parentItem.left());
resultPoint.setY(parentItem.bottom());
} else if (m_latteView->location() == Plasma::Types::BottomEdge) {
resultPoint.setX(parentItem.left());
resultPoint.setY(parentItem.top() - popUpRect.height() - 1);
} else if (m_latteView->location() == Plasma::Types::LeftEdge) {
resultPoint.setX(parentItem.right());
resultPoint.setY(parentItem.top());
} else if (m_latteView->location() == Plasma::Types::RightEdge) {
resultPoint.setX(parentItem.left() - popUpRect.width());
resultPoint.setY(parentItem.top());
}
return resultPoint;
}
QPoint ContextMenu::popUpRelevantToGlobalPoint(const QRect &parentItem, const QRect popUpRect)
{
QPoint resultPoint;
if (m_latteView->location() == Plasma::Types::TopEdge) {
resultPoint.setX(popUpRect.x());
resultPoint.setY(popUpRect.y() + 1);
} else if (m_latteView->location() == Plasma::Types::BottomEdge) {
resultPoint.setX(popUpRect.x());
resultPoint.setY(popUpRect.y() - popUpRect.height() - 1);
} else if (m_latteView->location() == Plasma::Types::LeftEdge) {
resultPoint.setX(popUpRect.x() + 1);
resultPoint.setY(popUpRect.y());
} else if (m_latteView->location() == Plasma::Types::RightEdge) {
resultPoint.setX(popUpRect.x() - popUpRect.width() - 1);
resultPoint.setY(popUpRect.y());
}
return resultPoint;
}
QPoint ContextMenu::popUpTopLeft(Plasma::Applet *applet, const QRect popUpRect)
{
PlasmaQuick::AppletQuickItem *ai = applet->property("_plasma_graphicObject").value<PlasmaQuick::AppletQuickItem *>();
QRect globalItemRect = m_latteView->absoluteGeometry();
if (ai && applet != m_latteView->containment()) {
QPointF appletGlobalTopLeft = ai->mapToGlobal(QPointF(ai->x(), ai->y()));
globalItemRect = QRect(appletGlobalTopLeft.x(), appletGlobalTopLeft.y(), ai->width(), ai->height());
}
int itemLength = (m_latteView->formFactor() == Plasma::Types::Horizontal ? globalItemRect.width() : globalItemRect.height());
int menuLength = (m_latteView->formFactor() == Plasma::Types::Horizontal ? popUpRect.width() : popUpRect.height());
if ((itemLength > menuLength)
|| (applet == m_latteView->containment())
|| (m_latteView && Layouts::Storage::self()->isSubContainment(m_latteView->layout(), applet)) ) {
return popUpRelevantToGlobalPoint(globalItemRect, popUpRect);
} else {
return popUpRelevantToParent(globalItemRect, popUpRect);
}
}
bool ContextMenu::mousePressEventForContainmentMenu(QQuickView *view, QMouseEvent *event)
{
if (!event || !view || !m_latteView->containment()) {
return false;
}
if (m_contextMenu) {
m_contextMenu->close();
m_contextMenu = 0;
return false;
}
QString trigger = Plasma::ContainmentActions::eventToString(event);
if (trigger == QLatin1String("RightButton;NoModifier")) {
Plasma::ContainmentActions *plugin = m_latteView->containment()->containmentActions().value(trigger);
if (!plugin || plugin->contextualActions().isEmpty()) {
event->setAccepted(false);
return false;
}
if (m_latteView->containment()) {
QMenu *desktopMenu = new QMenu;
desktopMenu->setAttribute(Qt::WA_TranslucentBackground);
if (desktopMenu->winId()) {
desktopMenu->windowHandle()->setTransientParent(m_latteView);
}
desktopMenu->setAttribute(Qt::WA_DeleteOnClose);
m_contextMenu = desktopMenu;
emit menuChanged();
auto ungrabMouseHack = [this]() {
if (m_latteView->mouseGrabberItem()) {
m_latteView->mouseGrabberItem()->ungrabMouse();
}
};
if (QVersionNumber::fromString(qVersion()) > QVersionNumber(5, 8, 0)) {
QTimer::singleShot(0, this, ungrabMouseHack);
} else {
ungrabMouseHack();
}
emit m_latteView->containment()->contextualActionsAboutToShow();
addContainmentActions(desktopMenu, event);
desktopMenu->setAttribute(Qt::WA_TranslucentBackground);
QPoint globalPos = event->globalPos();
desktopMenu->adjustSize();
QRect popUpRect(globalPos.x(), globalPos.y(), desktopMenu->width(), desktopMenu->height());
globalPos = popUpRelevantToGlobalPoint(QRect(0,0,0,0), popUpRect);
if (desktopMenu->isEmpty()) {
delete desktopMenu;
event->accept();
return false;
}
connect(desktopMenu, SIGNAL(aboutToHide()), this, SLOT(menuAboutToHide()));
desktopMenu->popup(globalPos);
event->setAccepted(true);
return false;
}
}
return true;
}
bool ContextMenu::mousePressEvent(QMouseEvent *event)
{
//qDebug() << "Step -1 ...";
if (!event || !m_latteView->containment()) {
return false;
}
//qDebug() << "Step 0...";
//even if the menu is executed synchronously, other events may be processed
//by the qml incubator when plasma is loading, so we need to guard there
if (m_contextMenu) {
//qDebug() << "Step 0.5 ...";
m_contextMenu->close();
m_contextMenu = 0;
return false;
}
//qDebug() << "1 ...";
QString trigger = Plasma::ContainmentActions::eventToString(event);
if (trigger == QLatin1String("RightButton;NoModifier")) {
Plasma::ContainmentActions *plugin = m_latteView->containment()->containmentActions().value(trigger);
if (!plugin || plugin->contextualActions().isEmpty()) {
event->setAccepted(false);
return false;
}
//qDebug() << "2 ...";
//the plugin can be a single action or a context menu
//Don't have an action list? execute as single action
//and set the event position as action data
/*if (plugin->contextualActions().length() == 1) {
QAction *action = plugin->contextualActions().at(0);
action->setData(event->pos());
action->trigger();
event->accept();
return;
}*/
//FIXME: very inefficient appletAt() implementation
Plasma::Applet *applet = 0;
bool inSystray = false;
//! initialize the appletContainsMethod on the first right click
if (!m_appletContainsMethod.isValid()) {
updateAppletContainsMethod();
}
for (const Plasma::Applet *appletTemp : m_latteView->containment()->applets()) {
PlasmaQuick::AppletQuickItem *ai = appletTemp->property("_plasma_graphicObject").value<PlasmaQuick::AppletQuickItem *>();
bool appletContainsMouse = false;
if (m_appletContainsMethod.isValid()) {
QVariant retVal;
m_appletContainsMethod.invoke(m_appletContainsMethodItem, Qt::DirectConnection, Q_RETURN_ARG(QVariant, retVal)
, Q_ARG(QVariant, appletTemp->id()), Q_ARG(QVariant, event->pos()));
appletContainsMouse = retVal.toBool();
} else {
appletContainsMouse = ai->contains(ai->mapFromItem(m_latteView->contentItem(), event->pos()));
}
if (ai && ai->isVisible() && appletContainsMouse) {
applet = ai->applet();
if (m_latteView && Layouts::Storage::self()->isSubContainment(m_latteView->layout(), applet)) {
Plasma::Containment *subContainment = Layouts::Storage::self()->subContainmentOf(m_latteView->layout(), applet);
if (subContainment) {
Plasma::Applet *internalApplet{nullptr};
for (const Plasma::Applet *appletCont : subContainment->applets()) {
PlasmaQuick::AppletQuickItem *ai2 = appletCont->property("_plasma_graphicObject").value<PlasmaQuick::AppletQuickItem *>();
if (ai2 && ai2->isVisible() && ai2->contains(ai2->mapFromItem(m_latteView->contentItem(), event->pos()))) {
internalApplet = ai2->applet();
break;
}
}
if (!internalApplet) {
return true;
} else {
applet = internalApplet;
}
}
break;
} else {
ai = 0;
}
}
}
if (!applet && !inSystray) {
applet = m_latteView->containment();
}
//qDebug() << "3 ...";
if (applet) {
const auto &provides = KPluginMetaData::readStringList(applet->pluginMetaData().rawData(), QStringLiteral("X-Plasma-Provides"));
//qDebug() << "3.5 ...";
if (!provides.contains(QLatin1String("org.kde.plasma.multitasking"))) {
//qDebug() << "4...";
QMenu *desktopMenu = new QMenu;
//this is a workaround where Qt now creates the menu widget
//in .exec before oxygen can polish it and set the following attribute
desktopMenu->setAttribute(Qt::WA_TranslucentBackground);
//end workaround
if (desktopMenu->winId()) {
desktopMenu->windowHandle()->setTransientParent(m_latteView);
}
desktopMenu->setAttribute(Qt::WA_DeleteOnClose);
m_contextMenu = desktopMenu;
emit menuChanged();
//! deprecated old code that can be removed if the following plasma approach doesn't
//! create any issues with context menu creation in Latte
/*if (m_latteView->mouseGrabberItem()) {
//workaround, this fixes for me most of the right click menu behavior
m_latteView->mouseGrabberItem()->ungrabMouse();
return;
}*/
//!plasma official code
//this is a workaround where Qt will fail to realize a mouse has been released
// this happens if a window which does not accept focus spawns a new window that takes focus and X grab
// whilst the mouse is depressed
// https://bugreports.qt.io/browse/QTBUG-59044
// this causes the next click to go missing
//by releasing manually we avoid that situation
auto ungrabMouseHack = [this]() {
if (m_latteView->mouseGrabberItem()) {
m_latteView->mouseGrabberItem()->ungrabMouse();
}
};
//pre 5.8.0 QQuickWindow code is "item->grabMouse(); sendEvent(item, mouseEvent)"
//post 5.8.0 QQuickWindow code is sendEvent(item, mouseEvent); item->grabMouse()
if (QVersionNumber::fromString(qVersion()) > QVersionNumber(5, 8, 0)) {
QTimer::singleShot(0, this, ungrabMouseHack);
} else {
ungrabMouseHack();
}
//end workaround
//!end of plasma official code(workaround)
//qDebug() << "5 ...";
if (applet && applet != m_latteView->containment()) {
//qDebug() << "5.3 ...";
emit applet->contextualActionsAboutToShow();
addAppletActions(desktopMenu, applet, event);
} else {
//qDebug() << "5.6 ...";
emit m_latteView->containment()->contextualActionsAboutToShow();
addContainmentActions(desktopMenu, event);
}
//this is a workaround where Qt now creates the menu widget
//in .exec before oxygen can polish it and set the following attribute
desktopMenu->setAttribute(Qt::WA_TranslucentBackground);
//end workaround
QPoint globalPos = event->globalPos();
desktopMenu->adjustSize();
QRect popUpRect(globalPos.x(), globalPos.y(), desktopMenu->width(), desktopMenu->height());
if (applet) {
globalPos = popUpTopLeft(applet, popUpRect);
} else {
globalPos = popUpRelevantToGlobalPoint(QRect(0,0,0,0), popUpRect);
}
//qDebug() << "7...";
if (desktopMenu->isEmpty()) {
//qDebug() << "7.5 ...";
delete desktopMenu;
event->accept();
return false;
}
connect(desktopMenu, SIGNAL(aboutToHide()), this, SLOT(menuAboutToHide()));
desktopMenu->popup(globalPos);
event->setAccepted(true);
return false;
}
//qDebug() << "8 ...";
}
//qDebug() << "9 ...";
}
//qDebug() << "10 ...";
return true;
// PlasmaQuick::ContainmentView::mousePressEvent(event);
}
//! update the appletContainsPos method from Panel view
void ContextMenu::updateAppletContainsMethod()
{
for (QQuickItem *item : m_latteView->contentItem()->childItems()) {
if (auto *metaObject = item->metaObject()) {
// not using QMetaObject::invokeMethod to avoid warnings when calling
// this on applets that don't have it or other child items since this
// is pretty much trial and error.
// Also, "var" arguments are treated as QVariant in QMetaObject
int methodIndex = metaObject->indexOfMethod("appletContainsPos(QVariant,QVariant)");
if (methodIndex == -1) {
continue;
}
m_appletContainsMethod = metaObject->method(methodIndex);
m_appletContainsMethodItem = item;
}
}
}
void ContextMenu::addAppletActions(QMenu *desktopMenu, Plasma::Applet *applet, QEvent *event)
{
if (!m_latteView->containment()) {
return;
}
desktopMenu->addSection(applet->pluginMetaData().name());
for (QAction *action : applet->contextualActions()) {
if (action) {
desktopMenu->addAction(action);
}
}
if (!applet->failedToLaunch()) {
QAction *runAssociatedApplication = applet->actions()->action(QStringLiteral("run associated application"));
if (runAssociatedApplication && runAssociatedApplication->isEnabled()) {
desktopMenu->addAction(runAssociatedApplication);
}
QAction *configureApplet = applet->actions()->action(QStringLiteral("configure"));
if (configureApplet && configureApplet->isEnabled()) {
desktopMenu->addAction(configureApplet);
}
QAction *appletAlternatives = applet->actions()->action(QStringLiteral("alternatives"));
if (appletAlternatives && appletAlternatives->isEnabled() && m_latteView->containment()->isUserConfiguring()) {
desktopMenu->addAction(appletAlternatives);
}
}
QAction *containmentAction = desktopMenu->menuAction();
containmentAction->setText(i18nc("%1 is the name of the containment", "%1 Options", m_latteView->containment()->title()));
addContainmentActions(containmentAction->menu(), event);
if (!containmentAction->menu()->isEmpty()) {
int enabled = 0;
//count number of real actions
QListIterator<QAction *> actionsIt(containmentAction->menu()->actions());
while (enabled < 3 && actionsIt.hasNext()) {
QAction *action = actionsIt.next();
if (action->isVisible() && !action->isSeparator()) {
++enabled;
}
}
desktopMenu->addSeparator();
if (enabled) {
//if there is only one, don't create a submenu
// if (enabled < 2) {
for (QAction *action : containmentAction->menu()->actions()) {
if (action && action->isVisible()) {
desktopMenu->addAction(action);
}
}
// } else {
// desktopMenu->addMenu(containmentMenu);
// }
}
}
if (m_latteView->containment()->immutability() == Plasma::Types::Mutable &&
(m_latteView->containment()->containmentType() != Plasma::Types::PanelContainment || m_latteView->containment()->isUserConfiguring())) {
QAction *closeApplet = applet->actions()->action(QStringLiteral("remove"));
//qDebug() << "checking for removal" << closeApplet;
if (closeApplet) {
if (!desktopMenu->isEmpty()) {
desktopMenu->addSeparator();
}
//qDebug() << "adding close action" << closeApplet->isEnabled() << closeApplet->isVisible();
desktopMenu->addAction(closeApplet);
}
}
}
void ContextMenu::addContainmentActions(QMenu *desktopMenu, QEvent *event)
{
if (!m_latteView->containment()) {
return;
}
if (m_latteView->containment()->corona()->immutability() != Plasma::Types::Mutable &&
!KAuthorized::authorizeAction(QStringLiteral("plasma/containment_actions"))) {
//qDebug() << "immutability";
return;
}
//this is what ContainmentPrivate::prepareContainmentActions was
const QString trigger = Plasma::ContainmentActions::eventToString(event);
//"RightButton;NoModifier"
Plasma::ContainmentActions *plugin = m_latteView->containment()->containmentActions().value(trigger);
if (!plugin) {
return;
}
if (plugin->containment() != m_latteView->containment()) {
plugin->setContainment(m_latteView->containment());
// now configure it
KConfigGroup cfg(m_latteView->containment()->corona()->config(), "ActionPlugins");
cfg = KConfigGroup(&cfg, QString::number(m_latteView->containment()->containmentType()));
KConfigGroup pluginConfig = KConfigGroup(&cfg, trigger);
plugin->restore(pluginConfig);
}
QList<QAction *> actions = plugin->contextualActions();
for (const QAction *act : actions) {
if (act->menu()) {
//this is a workaround where Qt now creates the menu widget
//in .exec before oxygen can polish it and set the following attribute
act->menu()->setAttribute(Qt::WA_TranslucentBackground);
//end workaround
if (act->menu()->winId()) {
act->menu()->windowHandle()->setTransientParent(m_latteView);
}
}
}
desktopMenu->addActions(actions);
return;
}
Plasma::Containment *ContextMenu::containmentById(uint id)
{
for (const auto containment : m_latteView->corona()->containments()) {
if (id == containment->id()) {
return containment;
}
}
return 0;
}
}
}

View File

@ -40,6 +40,7 @@ Effects::~Effects()
void Effects::init()
{
connect(this, &Effects::backgroundOpacityChanged, this, &Effects::updateEffects);
connect(this, &Effects::backgroundOpacityChanged, this, &Effects::updateBackgroundContrastValues);
connect(this, &Effects::backgroundCornersMaskChanged, this, &Effects::updateEffects);
connect(this, &Effects::backgroundRadiusEnabledChanged, this, &Effects::updateEffects);
connect(this, &Effects::drawEffectsChanged, this, &Effects::updateEffects);
@ -91,17 +92,6 @@ void Effects::init()
connect(m_view, &Latte::View::layoutChanged, this, &Effects::onPopUpMarginChanged);
connect(&m_theme, &Plasma::Theme::themeChanged, this, [&]() {
auto background = m_background;
m_background = new Plasma::FrameSvg(this);
if (background) {
background->deleteLater();
}
if (m_background->imagePath() != "widgets/panel-background") {
m_background->setImagePath(QStringLiteral("widgets/panel-background"));
}
updateBackgroundContrastValues();
updateEffects();
});
@ -353,6 +343,21 @@ void Effects::setAppletsLayoutGeometry(const QRect &geom)
emit appletsLayoutGeometryChanged();
}
QQuickItem *Effects::panelBackgroundSvg() const
{
return m_panelBackgroundSvg;
}
void Effects::setPanelBackgroundSvg(QQuickItem *quickitem)
{
if (m_panelBackgroundSvg == quickitem) {
return;
}
m_panelBackgroundSvg = quickitem;
emit panelBackgroundSvgChanged();
}
void Effects::onPopUpMarginChanged()
{
m_view->setProperty("_applets_popup_margin", QVariant(popUpMargin()));
@ -360,14 +365,6 @@ void Effects::onPopUpMarginChanged()
void Effects::forceMaskRedraw()
{
if (m_background) {
delete m_background;
}
m_background = new Plasma::FrameSvg(this);
m_background->setImagePath(QStringLiteral("widgets/panel-background"));
m_background->setEnabledBorders(m_enabledBorders);
updateMask();
}
@ -461,7 +458,7 @@ QRegion Effects::maskCombinedRegion()
void Effects::updateBackgroundCorners()
{
if (m_backgroundRadius<=0) {
if (m_backgroundRadius<0) {
return;
}
@ -499,21 +496,14 @@ void Effects::updateMask()
//! rounded corners to be shown correctly
//! the enabledBorders check was added because there was cases
//! that the mask region wasn't calculated correctly after location changes
if (!m_background) {
if (m_background && m_background->enabledBorders() != m_enabledBorders) {
delete m_background;
}
m_background = new Plasma::FrameSvg(this);
if (!m_panelBackgroundSvg) {
return;
}
if (m_background->imagePath() != "widgets/panel-background") {
m_background->setImagePath(QStringLiteral("widgets/panel-background"));
const QVariant maskProperty = m_panelBackgroundSvg->property("mask");
if (static_cast<QMetaType::Type>(maskProperty.type()) == QMetaType::QRegion) {
fixedMask = maskProperty.value<QRegion>();
}
m_background->setEnabledBorders(m_enabledBorders);
m_background->resizeFrame(maskRect.size());
fixedMask = m_background->mask();
}
fixedMask.translate(maskRect.x(), maskRect.y());
@ -553,7 +543,7 @@ void Effects::updateEffects()
if (m_drawEffects) {
if (!m_view->behaveAsPlasmaPanel()) {
if (!m_rect.isNull() && !m_rect.isEmpty()) {
if (!m_rect.isNull() && !m_rect.isEmpty() && m_rect != VisibilityManager::ISHIDDENMASK) {
QRegion backMask;
if (m_backgroundRadiusEnabled) {
@ -564,25 +554,23 @@ void Effects::updateEffects()
//! this is used when compositing is disabled and provides
//! the correct way for the mask to be painted in order for
//! rounded corners to be shown correctly
if (!m_background) {
m_background = new Plasma::FrameSvg(this);
if (!m_panelBackgroundSvg) {
return;
}
if (m_background->imagePath() != "widgets/panel-background") {
m_background->setImagePath(QStringLiteral("widgets/panel-background"));
if (m_rect == VisibilityManager::ISHIDDENMASK) {
clearEffects = true;
} else {
const QVariant maskProperty = m_panelBackgroundSvg->property("mask");
if (static_cast<QMetaType::Type>(maskProperty.type()) == QMetaType::QRegion) {
backMask = maskProperty.value<QRegion>();
}
}
m_background->setEnabledBorders(m_enabledBorders);
m_background->resizeFrame(m_rect.size());
backMask = m_background->mask();
}
//! adjust mask coordinates based on local coordinates
int fX = m_rect.x(); int fY = m_rect.y();
#if KF5_VERSION_MINOR >= 65
//! Latte is now using GtkFrameExtents so Effects geometries must be adjusted
//! windows that use GtkFrameExtents and apply Effects on them they take GtkFrameExtents
//! as granted
@ -593,7 +581,6 @@ void Effects::updateEffects()
fX = qMax(0, fX - m_view->headThicknessGap());
}
}
#endif
//! There are cases that mask is NULL even though it should not
//! Example: SidebarOnDemand from v0.10 that BEHAVEASPLASMAPANEL in EditMode
@ -666,15 +653,21 @@ qreal Effects::currentMidValue(const qreal &max, const qreal &factor, const qrea
void Effects::updateBackgroundContrastValues()
{
if (!m_theme.backgroundContrastEnabled()) {
m_backEffectContrast = 1;
m_backEffectIntesity = 1;
m_backEffectSaturation = 1;
m_backEffectContrast = 1.0;
m_backEffectIntesity = 1.0;
m_backEffectSaturation = 1.0;
return;
}
m_backEffectContrast = currentMidValue(m_theme.backgroundContrast(), m_backgroundOpacity, 1);
m_backEffectIntesity = currentMidValue(m_theme.backgroundIntensity(), m_backgroundOpacity, 1);
m_backEffectSaturation = currentMidValue(m_theme.backgroundSaturation(), m_backgroundOpacity, 1);
if (m_backgroundOpacity == -1 /*Default plasma opacity option*/) {
m_backEffectContrast = m_theme.backgroundContrast();
m_backEffectIntesity = m_theme.backgroundIntensity();
m_backEffectSaturation = m_theme.backgroundSaturation();
} else {
m_backEffectContrast = currentMidValue(m_theme.backgroundContrast(), m_backgroundOpacity, 1);
m_backEffectIntesity = currentMidValue(m_theme.backgroundIntensity(), m_backgroundOpacity, 1);
m_backEffectSaturation = currentMidValue(m_theme.backgroundSaturation(), m_backgroundOpacity, 1);
}
}
void Effects::updateEnabledBorders()

View File

@ -52,6 +52,8 @@ class Effects: public QObject
Q_PROPERTY(Plasma::FrameSvg::EnabledBorders enabledBorders READ enabledBorders NOTIFY enabledBordersChanged)
Q_PROPERTY(QQuickItem *panelBackgroundSvg READ panelBackgroundSvg WRITE setPanelBackgroundSvg NOTIFY panelBackgroundSvgChanged)
public:
Effects(Latte::View *parent);
virtual ~Effects();
@ -102,6 +104,9 @@ public:
Plasma::FrameSvg::EnabledBorders enabledBorders() const;
QQuickItem *panelBackgroundSvg() const;
void setPanelBackgroundSvg(QQuickItem *quickitem);
public slots:
Q_INVOKABLE void forceMaskRedraw();
Q_INVOKABLE void setSubtractedMaskRegion(const QString &regionid, const QRegion &region);
@ -130,6 +135,7 @@ signals:
void maskChanged();
void innerShadowChanged();
void inputMaskChanged();
void panelBackgroundSvgChanged();
void popUpMarginChanged();
void rectChanged();
@ -185,12 +191,13 @@ private:
PlasmaExtended::CornerRegions m_cornersMaskRegion;
Plasma::Theme m_theme;
//only for the mask on disabled compositing, not to actually paint
Plasma::FrameSvg *m_background{nullptr};
//only for the mask, not to actually paint
Plasma::FrameSvg::EnabledBorders m_enabledBorders{Plasma::FrameSvg::AllBorders};
//assigned from qml side in order to access the official panel background svg
QQuickItem *m_panelBackgroundSvg{nullptr};
//! Subtracted and United Mask regions
QHash<QString, QRegion> m_subtractedMaskRegions;
QHash<QString, QRegion> m_unitedMaskRegions;

View File

@ -184,12 +184,7 @@ QEvent *EventsSink::onEvent(QEvent *e)
case QEvent::Wheel:
if (auto we = dynamic_cast<QWheelEvent *>(e)) {
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
QPoint pos = QPoint(we->x(), we->y());
#else
QPoint pos = we->position().toPoint();
#endif
if (originSinksContain(pos)) {
auto positionadjusted = positionAdjustedForDestination(pos);
auto we2 = new QWheelEvent(positionadjusted,

View File

@ -4,7 +4,7 @@
*/
#ifndef FLOATINGGAPWINDOW_H
#define FLOATINGWINDOW_H
#define FLOATINGGAPWINDOW_H
// local
#include "subwindow.h"

View File

@ -7,6 +7,7 @@
// local
#include "../view.h"
#include "../positioner.h"
// Qt
#include <QDebug>
@ -41,6 +42,8 @@ ScreenEdgeGhostWindow::ScreenEdgeGhostWindow(Latte::View *view) :
setColor(m_showColor);
connect(m_latteView->positioner(), &Latte::ViewPart::Positioner::slideOffsetChanged, this, &ScreenEdgeGhostWindow::updateGeometry);
//! this timer is used in order to avoid fast enter/exit signals during first
//! appearing after edge activation
m_delayedMouseTimer.setSingleShot(true);
@ -72,7 +75,7 @@ void ScreenEdgeGhostWindow::updateGeometry()
return;
}
QRect newGeometry;
QRect newGeometry = m_latteView->absoluteGeometry();
if (KWindowSystem::compositingActive()) {
m_thickness = 6;
@ -86,41 +89,42 @@ void ScreenEdgeGhostWindow::updateGeometry()
if (m_latteView->formFactor() == Plasma::Types::Horizontal) {
//! set minimum length to be 25% of screen width
length = qMax(m_latteView->screenGeometry().width()/4,qMin(m_latteView->absoluteGeometry().width(), m_latteView->screenGeometry().width() - 1));
lengthDifference = qMax(0,length - m_latteView->absoluteGeometry().width());
lengthDifference = qMax(0,length - m_latteView->absoluteGeometry().width()) / 2;
} else {
//! set minimum length to be 25% of screen height
length = qMax(m_latteView->screenGeometry().height()/4,qMin(m_latteView->absoluteGeometry().height(), m_latteView->screenGeometry().height() - 1));
lengthDifference = qMax(0,length - m_latteView->absoluteGeometry().height());
}
if (m_latteView->location() == Plasma::Types::BottomEdge) {
int xF = qMax(m_latteView->screenGeometry().left(), m_latteView->absoluteGeometry().left() - lengthDifference);
newGeometry.moveLeft(xF);
newGeometry.moveTop(m_latteView->screenGeometry().bottom() - m_thickness);
} else if (m_latteView->location() == Plasma::Types::TopEdge) {
int xF = qMax(m_latteView->screenGeometry().left(), m_latteView->absoluteGeometry().left() - lengthDifference);
newGeometry.moveLeft(xF);
newGeometry.moveTop(m_latteView->screenGeometry().top());
} else if (m_latteView->location() == Plasma::Types::LeftEdge) {
int yF = qMax(m_latteView->screenGeometry().top(), m_latteView->absoluteGeometry().top() - lengthDifference);
newGeometry.moveLeft(m_latteView->screenGeometry().left());
newGeometry.moveTop(yF);
} else if (m_latteView->location() == Plasma::Types::RightEdge) {
int yF = qMax(m_latteView->screenGeometry().top(), m_latteView->absoluteGeometry().top() - lengthDifference);
newGeometry.moveLeft(m_latteView->screenGeometry().right() - m_thickness);
newGeometry.moveTop(yF);
lengthDifference = qMax(0,length - m_latteView->absoluteGeometry().height()) / 2;
}
if (m_latteView->formFactor() == Plasma::Types::Horizontal) {
int leftF = qMax(m_latteView->screenGeometry().left(), m_latteView->absoluteGeometry().left() - lengthDifference);
int rightF = qMax(m_latteView->screenGeometry().left(), qMin(m_latteView->screenGeometry().right(), m_latteView->absoluteGeometry().right() + lengthDifference));
newGeometry.setLeft(leftF);
newGeometry.setRight(rightF);
} else {
int topF = qMax(m_latteView->screenGeometry().top(), m_latteView->absoluteGeometry().top() - lengthDifference);
int bottomF = qMax(m_latteView->screenGeometry().top(), qMin(m_latteView->screenGeometry().bottom(), m_latteView->absoluteGeometry().bottom() + lengthDifference));
newGeometry.setTop(topF);
newGeometry.setBottom(bottomF);
}
if (m_latteView->location() == Plasma::Types::BottomEdge) {
newGeometry.moveTop(m_latteView->screenGeometry().bottom() - m_thickness);
} else if (m_latteView->location() == Plasma::Types::TopEdge) {
newGeometry.moveTop(m_latteView->screenGeometry().top());
} else if (m_latteView->location() == Plasma::Types::LeftEdge) {
newGeometry.moveLeft(m_latteView->screenGeometry().left());
} else if (m_latteView->location() == Plasma::Types::RightEdge) {
newGeometry.moveLeft(m_latteView->screenGeometry().right() - m_thickness);
}
if (m_latteView->formFactor() == Plasma::Types::Horizontal) {
newGeometry.setWidth(length);
newGeometry.setHeight(m_thickness + 1);
} else {
newGeometry.setWidth(m_thickness + 1);
newGeometry.setHeight(length);
}
m_calculatedGeometry = newGeometry;
emit calculatedGeometryChanged();
}

View File

@ -15,6 +15,7 @@
// Qt
#include <QFileDialog>
#include <QFileInfo>
#include <QLatin1String>
// KDE
@ -243,9 +244,7 @@ void Indicator::load(QString type)
m_metadata = metadata;
m_type = type;
QString path = m_metadata.fileName();
m_pluginPath = path.remove("metadata.desktop");
m_pluginPath = QFileInfo(m_metadata.fileName()).absolutePath();
if (m_corona && m_corona->indicatorFactory()->isCustomType(type)) {
setCustomType(type);
@ -271,7 +270,7 @@ void Indicator::updateComponent()
QString uiPath = m_metadata.value("X-Latte-MainScript");
if (!uiPath.isEmpty()) {
uiPath = m_pluginPath + "package/" + uiPath;
uiPath = m_pluginPath + "/package/" + uiPath;
m_component = new QQmlComponent(m_view->engine(), uiPath);
}
@ -288,10 +287,7 @@ void Indicator::loadPlasmaComponent()
QString uiPath = metadata.value("X-Latte-MainScript");
if (!uiPath.isEmpty()) {
QString path = metadata.fileName();
path = path.remove("metadata.desktop");
uiPath = path + "package/" + uiPath;
uiPath = QFileInfo(metadata.fileName()).absolutePath() + "/package/" + uiPath;
m_plasmaComponent = new QQmlComponent(m_view->engine(), uiPath);
}
@ -315,7 +311,7 @@ void Indicator::updateScheme()
QString xmlPath = m_metadata.value("X-Latte-ConfigXml");
if (!xmlPath.isEmpty()) {
QFile file(m_pluginPath + "package/" + xmlPath);
QFile file(m_pluginPath + "/package/" + xmlPath);
m_configLoader = new KConfigLoader(m_view->containment()->config().group("Indicator").group(m_metadata.pluginId()), &file);
m_configuration = new KDeclarative::ConfigPropertyMap(m_configLoader, this);
} else {

282
app/view/originalview.cpp Normal file
View File

@ -0,0 +1,282 @@
/*
SPDX-FileCopyrightText: 2021 Michail Vourlakos <mvourlakos@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "originalview.h"
#include "clonedview.h"
#include "positioner.h"
#include "../lattecorona.h"
#include "../screenpool.h"
#include "../layouts/storage.h"
// KDE
#include <KLocalizedString>
namespace Latte {
OriginalView::OriginalView(Plasma::Corona *corona, QScreen *targetScreen, bool byPassX11WM)
: View(corona, targetScreen, byPassX11WM)
{
connect(this, &View::containmentChanged, this, [&]() {
if (!this->containment()) {
return;
}
connect(containment(), &Plasma::Applet::destroyedChanged, this, &OriginalView::syncClonesToScreens);
restoreConfig();
});
connect(this, &View::layoutChanged, this, &OriginalView::syncClonesToScreens);
connect(this, &OriginalView::screensGroupChanged, this, &OriginalView::syncClonesToScreens);
connect(this, &OriginalView::screensGroupChanged, this, &OriginalView::saveConfig);
}
OriginalView::~OriginalView()
{
cleanClones();
}
bool OriginalView::isSingle() const
{
return m_screensGroup == Latte::Types::SingleScreenGroup;
}
bool OriginalView::isOriginal() const
{
return true;
}
bool OriginalView::isCloned() const
{
return !isOriginal();
}
int OriginalView::clonesCount() const
{
return m_clones.count();
}
int OriginalView::expectedScreenIdFromScreenGroup(const Latte::Types::ScreensGroup &nextScreensGroup) const
{
Data::View view = data();
view.screensGroup = nextScreensGroup;
return Latte::Layouts::Storage::self()->expectedViewScreenId(m_corona, view);
}
Latte::Types::ScreensGroup OriginalView::screensGroup() const
{
return m_screensGroup;
}
void OriginalView::setScreensGroup(const Latte::Types::ScreensGroup &group)
{
if (m_screensGroup == group) {
return;
}
m_screensGroup = group;
emit screensGroupChanged();
}
void OriginalView::addClone(Latte::ClonedView *view)
{
if (m_clones.contains(view)) {
return;
}
m_clones << view;
m_waitingCreation.removeAll(view->positioner()->currentScreenId());
}
void OriginalView::removeClone(Latte::ClonedView *view)
{
if (!m_clones.contains(view)) {
return;
}
int idx = m_clones.indexOf(view);
auto cloned = m_clones.takeAt(idx);
if (!cloned->layout()) {
return;
}
cloned->positioner()->slideOutDuringExit();
cloned->layout()->removeView(cloned->data());
}
void OriginalView::createClone(int screenId)
{
if (!layout() || !containment()) {
return;
}
QString templateFile = layout()->storedView(containment()->id());
if (templateFile.isEmpty()) {
return;
}
Data::ViewsTable templateviews = Layouts::Storage::self()->views(templateFile);
if (templateviews.rowCount() <= 0) {
return;
}
Data::View nextdata = templateviews[0];
nextdata.name = i18nc("clone of original dock panel, name","Clone of %1", name());
nextdata.onPrimary = false;
nextdata.screensGroup = Latte::Types::SingleScreenGroup;
nextdata.isClonedFrom = containment()->id();
nextdata.screen = screenId;
nextdata.setState(Data::View::OriginFromViewTemplate, templateFile);
if (!m_waitingCreation.contains(screenId)) {
m_waitingCreation << screenId;
layout()->newView(nextdata);
}
}
void OriginalView::cleanClones()
{
if (m_clones.count()==0) {
return;
}
while(!m_clones.isEmpty()) {
removeClone(m_clones[0]);
}
}
void OriginalView::reconsiderScreen()
{
View::reconsiderScreen();
syncClonesToScreens();
}
void OriginalView::setNextLocationForClones(const QString layoutName, int edge, int alignment)
{
if (m_clones.count()==0) {
return;
}
for (const auto clone : m_clones) {
clone->positioner()->setNextLocation(layoutName, Latte::Types::SingleScreenGroup, "", edge, alignment);
}
}
void OriginalView::addApplet(const QString &pluginId, const int &excludecloneid)
{
if (m_clones.count() == 0) {
return;
}
// add applet in original view
extendedInterface()->addApplet(pluginId);
// add applet in clones and exclude the one that probably produced this triggering
for(const auto clone: m_clones) {
if (clone->containment()->id() == excludecloneid) {
// this way we make sure that an applet will not be double added
continue;
}
clone->extendedInterface()->addApplet(pluginId);
}
}
void OriginalView::addApplet(QObject *mimedata, const int &x, const int &y, const int &excludecloneid)
{
if (m_clones.count() == 0) {
return;
}
// add applet in original view
extendedInterface()->addApplet(mimedata, x, y);
// add applet in clones and exclude the one that probably produced this triggering
for(const auto clone: m_clones) {
if (clone->containment()->id() == excludecloneid) {
// this way we make sure that an applet will not be double added
continue;
}
clone->extendedInterface()->addApplet(mimedata, x, y);
}
}
void OriginalView::syncClonesToScreens()
{
if (isSingle() || (containment() && containment()->destroyed())) {
cleanClones();
return;
}
QList<int> secondaryscreens = m_corona->screenPool()->secondaryScreenIds();
for (const auto scrid : secondaryscreens) {
if (m_waitingCreation.contains(scrid)) {
secondaryscreens.removeAll(scrid);
}
}
if (m_screensGroup == Latte::Types::AllSecondaryScreensGroup) {
//! occuped screen from original view in "allsecondaryscreensgroup" must be ignored
secondaryscreens.removeAll(expectedScreenIdFromScreenGroup(m_screensGroup));
}
QList<Latte::ClonedView *> removable;
for (const auto clone : m_clones) {
if (secondaryscreens.contains(clone->positioner()->currentScreenId())) {
// do nothing valid clone
secondaryscreens.removeAll(clone->positioner()->currentScreenId());
} else {
// must be removed the screen is not active
removable << clone;
}
}
for (const auto scrid : secondaryscreens) {
if (removable.count() > 0) {
//! move deprecated and available clone to valid secondary screen
auto clone = removable.takeFirst();
clone->positioner()->setScreenToFollow(m_corona->screenPool()->screenForId(scrid));
} else {
//! create a new clone
createClone(scrid);
}
}
for (auto removableclone : removable) {
//! remove deprecated clones
removeClone(removableclone);
}
}
void OriginalView::saveConfig()
{
if (!this->containment()) {
return;
}
auto config = this->containment()->config();
config.writeEntry("screensGroup", (int)m_screensGroup);
}
void OriginalView::restoreConfig()
{
if (!this->containment()) {
return;
}
auto config = this->containment()->config();
m_screensGroup = static_cast<Latte::Types::ScreensGroup>(config.readEntry("screensGroup", (int)Latte::Types::SingleScreenGroup));
//! Send changed signals at the end in order to be sure that saveConfig
//! wont rewrite default/invalid values
emit screensGroupChanged();
}
}

72
app/view/originalview.h Normal file
View File

@ -0,0 +1,72 @@
/*
SPDX-FileCopyrightText: 2021 Michail Vourlakos <mvourlakos@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef ORIGINALVIEW_H
#define ORIGINALVIEW_H
// local
#include <coretypes.h>
#include "view.h"
// Qt
#include <QList>
namespace Latte {
class ClonedView;
class OriginalView : public View
{
Q_OBJECT
Q_PROPERTY(Latte::Types::ScreensGroup screensGroup READ screensGroup NOTIFY screensGroupChanged)
public:
OriginalView(Plasma::Corona *corona, QScreen *targetScreen = nullptr, bool byPassX11WM = false);
~OriginalView();
bool isOriginal() const override;
bool isCloned() const override;
bool isSingle() const override;
int clonesCount() const;
int expectedScreenIdFromScreenGroup(const Latte::Types::ScreensGroup &nextScreensGroup) const;
Latte::Types::ScreensGroup screensGroup() const override;
void setScreensGroup(const Latte::Types::ScreensGroup &group);
void addClone(Latte::ClonedView *view);
void setNextLocationForClones(const QString layoutName, int edge, int alignment);
void addApplet(const QString &pluginId, const int &excludecloneid);
void addApplet(QObject *mimedata, const int &x, const int &y, const int &excludecloneid);
void reconsiderScreen() override;
public slots:
void cleanClones();
signals:
void screensGroupChanged();
private slots:
void syncClonesToScreens();
void restoreConfig();
void saveConfig();
private:
void createClone(int screenId);
void removeClone(Latte::ClonedView *view);
private:
Latte::Types::ScreensGroup m_screensGroup{Latte::Types::SingleScreenGroup};
QList<Latte::ClonedView *> m_clones;
QList<int> m_waitingCreation;
};
}
#endif

View File

@ -6,98 +6,34 @@
#include "panelshadows_p.h"
#include <QWindow>
#include <QPainter>
#include <config-latte.h>
#include <KWindowSystem>
#if HAVE_X11
#include <QX11Info>
#include <X11/Xatom.h>
#include <X11/Xlib.h>
#include <X11/Xlib-xcb.h>
#include <fixx11h.h>
#endif
#include <KWayland/Client/connection_thread.h>
#include <KWayland/Client/registry.h>
#include <KWayland/Client/shadow.h>
#include <KWayland/Client/shm_pool.h>
#include <KWayland/Client/surface.h>
#include <qdebug.h>
#include <QDebug>
#include <KWindowShadow>
class PanelShadows::Private
{
public:
Private(PanelShadows *shadows)
: q(shadows)
#if HAVE_X11
,_connection( nullptr ),
_gc( 0x0 )
, m_isX11(KWindowSystem::isPlatformX11())
#endif
{
setupWaylandIntegration();
}
~Private()
{
// Do not call clearPixmaps() from here: it creates new QPixmap(),
// which causes a crash when application is stopping.
freeX11Pixmaps();
}
void freeX11Pixmaps();
void freeWaylandBuffers();
void clearPixmaps();
void setupPixmaps();
Qt::HANDLE createPixmap(const QPixmap& source);
void initPixmap(const QString &element);
QPixmap initEmptyPixmap(const QSize &size);
void updateShadow(const QWindow *window, Plasma::FrameSvg::EnabledBorders);
void updateShadowX11(const QWindow *window, Plasma::FrameSvg::EnabledBorders);
void updateShadowWayland(const QWindow *window, Plasma::FrameSvg::EnabledBorders);
void clearShadow(const QWindow *window);
void clearShadowX11(const QWindow *window);
void clearShadowWayland(const QWindow *window);
void clearTiles();
void setupTiles();
void initTile(const QString &element);
void updateShadow(QWindow *window, Plasma::FrameSvg::EnabledBorders);
void clearShadow(QWindow *window);
void updateShadows();
void setupData(Plasma::FrameSvg::EnabledBorders enabledBorders);
bool hasShadows() const;
void setupWaylandIntegration();
PanelShadows *q;
QList<QPixmap> m_shadowPixmaps;
QPixmap m_emptyCornerPix;
QPixmap m_emptyCornerLeftPix;
QPixmap m_emptyCornerTopPix;
QPixmap m_emptyCornerRightPix;
QPixmap m_emptyCornerBottomPix;
QPixmap m_emptyVerticalPix;
QPixmap m_emptyHorizontalPix;
#if HAVE_X11
//! xcb connection
xcb_connection_t* _connection;
//! graphical context
xcb_gcontext_t _gc;
bool m_isX11;
#endif
struct Wayland {
KWayland::Client::ShadowManager *manager = nullptr;
KWayland::Client::ShmPool *shmPool = nullptr;
QList<KWayland::Client::Buffer::Ptr> shadowBuffers;
};
Wayland m_wayland;
QHash<Plasma::FrameSvg::EnabledBorders, QVector<unsigned long> > data;
QHash<const QWindow *, Plasma::FrameSvg::EnabledBorders> m_windows;
QHash<QWindow *, Plasma::FrameSvg::EnabledBorders> m_windows;
QHash<QWindow *, KWindowShadow *> m_shadows;
QVector<KWindowShadowTile::Ptr> m_tiles;
};
class PanelShadowsSingleton
@ -107,14 +43,14 @@ public:
{
}
PanelShadows self;
PanelShadows self;
};
Q_GLOBAL_STATIC(PanelShadowsSingleton, privatePanelShadowsSelf)
PanelShadows::PanelShadows(QObject *parent, const QString &prefix)
: Plasma::Svg(parent),
d(new Private(this))
: Plasma::Svg(parent)
, d(new Private(this))
{
setImagePath(prefix);
connect(this, &Plasma::Svg::repaintNeeded, this, [this]() {
@ -132,7 +68,7 @@ PanelShadows *PanelShadows::self()
return &privatePanelShadowsSelf->self;
}
void PanelShadows::addWindow(const QWindow *window, Plasma::FrameSvg::EnabledBorders enabledBorders)
void PanelShadows::addWindow(QWindow *window, Plasma::FrameSvg::EnabledBorders enabledBorders)
{
if (!window) {
return;
@ -142,13 +78,14 @@ void PanelShadows::addWindow(const QWindow *window, Plasma::FrameSvg::EnabledBor
d->updateShadow(window, enabledBorders);
connect(window, &QObject::destroyed, this, [this, window]() {
d->m_windows.remove(window);
d->clearShadow(window);
if (d->m_windows.isEmpty()) {
d->clearPixmaps();
d->clearTiles();
}
});
}
void PanelShadows::removeWindow(const QWindow *window)
void PanelShadows::removeWindow(QWindow *window)
{
if (!d->m_windows.contains(window)) {
return;
@ -159,16 +96,11 @@ void PanelShadows::removeWindow(const QWindow *window)
d->clearShadow(window);
if (d->m_windows.isEmpty()) {
d->clearPixmaps();
d->clearTiles();
}
}
bool PanelShadows::hasShadows() const
{
return hasElement(QStringLiteral("shadow-left"));
}
void PanelShadows::setEnabledBorders(const QWindow *window, Plasma::FrameSvg::EnabledBorders enabledBorders)
void PanelShadows::setEnabledBorders(QWindow *window, Plasma::FrameSvg::EnabledBorders enabledBorders)
{
if (!window || !d->m_windows.contains(window)) {
return;
@ -180,12 +112,12 @@ void PanelShadows::setEnabledBorders(const QWindow *window, Plasma::FrameSvg::En
void PanelShadows::Private::updateShadows()
{
const bool hadShadowsBefore = !m_shadowPixmaps.isEmpty();
const bool hadShadowsBefore = !m_tiles.isEmpty();
// has shadows now?
if (hasShadows()) {
if (hadShadowsBefore) {
clearPixmaps();
clearTiles();
}
for (auto i = m_windows.constBegin(); i != m_windows.constEnd(); ++i) {
updateShadow(i.key(), i.value());
@ -195,524 +127,162 @@ void PanelShadows::Private::updateShadows()
for (auto i = m_windows.constBegin(); i != m_windows.constEnd(); ++i) {
clearShadow(i.key());
}
clearPixmaps();
clearTiles();
}
}
}
Qt::HANDLE PanelShadows::Private::createPixmap(const QPixmap& source)
void PanelShadows::Private::initTile(const QString &element)
{
const QImage image = q->pixmap(element).toImage();
// do nothing for invalid pixmaps
if( source.isNull() ) return nullptr;
/*
in some cases, pixmap handle is invalid. This is the case notably
when Qt uses to RasterEngine. In this case, we create an X11 Pixmap
explicitly and draw the source pixmap on it.
*/
#if HAVE_X11
if (!m_isX11) {
return nullptr;
}
// check connection
if( !_connection ) _connection = QX11Info::connection();
const int width( source.width() );
const int height( source.height() );
// create X11 pixmap
Pixmap pixmap = XCreatePixmap( QX11Info::display(), QX11Info::appRootWindow(), width, height, 32 );
// check gc
if( !_gc )
{
_gc = xcb_generate_id( _connection );
xcb_create_gc( _connection, _gc, pixmap, 0, nullptr );
}
// // create explicitly shared QPixmap from it
// QPixmap dest( QPixmap::fromX11Pixmap( pixmap, QPixmap::ExplicitlyShared ) );
//
// // create surface for pixmap
// {
// QPainter painter( &dest );
// painter.setCompositionMode( QPainter::CompositionMode_Source );
// painter.drawPixmap( 0, 0, source );
// }
//
//
// return pixmap;
QImage image( source.toImage() );
xcb_put_image(
_connection, XCB_IMAGE_FORMAT_Z_PIXMAP, pixmap, _gc,
image.width(), image.height(), 0, 0,
0, 32,
image.byteCount(), image.constBits());
return (Qt::HANDLE)pixmap;
#else
return 0;
#endif
KWindowShadowTile::Ptr tile = KWindowShadowTile::Ptr::create();
tile->setImage(image);
m_tiles << tile;
}
void PanelShadows::Private::initPixmap(const QString &element)
void PanelShadows::Private::setupTiles()
{
m_shadowPixmaps << q->pixmap(element);
clearTiles();
initTile(QStringLiteral("shadow-top"));
initTile(QStringLiteral("shadow-topright"));
initTile(QStringLiteral("shadow-right"));
initTile(QStringLiteral("shadow-bottomright"));
initTile(QStringLiteral("shadow-bottom"));
initTile(QStringLiteral("shadow-bottomleft"));
initTile(QStringLiteral("shadow-left"));
initTile(QStringLiteral("shadow-topleft"));
}
QPixmap PanelShadows::Private::initEmptyPixmap(const QSize &size)
void PanelShadows::Private::clearTiles()
{
#if HAVE_X11
if (!m_isX11) {
return QPixmap();
}
QPixmap tempEmptyPix(size);
if (!size.isEmpty()) {
tempEmptyPix.fill(Qt::transparent);
}
return tempEmptyPix;
#else
Q_UNUSED(size)
return QPixmap();
#endif
m_tiles.clear();
}
void PanelShadows::Private::setupPixmaps()
{
clearPixmaps();
initPixmap(QStringLiteral("shadow-top"));
initPixmap(QStringLiteral("shadow-topright"));
initPixmap(QStringLiteral("shadow-right"));
initPixmap(QStringLiteral("shadow-bottomright"));
initPixmap(QStringLiteral("shadow-bottom"));
initPixmap(QStringLiteral("shadow-bottomleft"));
initPixmap(QStringLiteral("shadow-left"));
initPixmap(QStringLiteral("shadow-topleft"));
m_emptyCornerPix = initEmptyPixmap(QSize(1,1));
m_emptyCornerLeftPix = initEmptyPixmap(QSize(q->elementSize(QStringLiteral("shadow-topleft")).width(), 1));
m_emptyCornerTopPix = initEmptyPixmap(QSize(1, q->elementSize(QStringLiteral("shadow-topleft")).height()));
m_emptyCornerRightPix = initEmptyPixmap(QSize(q->elementSize(QStringLiteral("shadow-bottomright")).width(), 1));
m_emptyCornerBottomPix = initEmptyPixmap(QSize(1, q->elementSize(QStringLiteral("shadow-bottomright")).height()));
m_emptyVerticalPix = initEmptyPixmap(QSize(1, q->elementSize(QStringLiteral("shadow-left")).height()));
m_emptyHorizontalPix = initEmptyPixmap(QSize(q->elementSize(QStringLiteral("shadow-top")).width(), 1));
if (m_wayland.shmPool) {
for (auto it = m_shadowPixmaps.constBegin(); it != m_shadowPixmaps.constEnd(); ++it) {
m_wayland.shadowBuffers << m_wayland.shmPool->createBuffer(it->toImage());
}
}
}
void PanelShadows::Private::setupData(Plasma::FrameSvg::EnabledBorders enabledBorders)
{
#if HAVE_X11
if (!m_isX11) {
return;
}
//shadow-top
if (enabledBorders & Plasma::FrameSvg::TopBorder) {
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_shadowPixmaps[0]));
} else {
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyHorizontalPix));
}
//shadow-topright
if (enabledBorders & Plasma::FrameSvg::TopBorder &&
enabledBorders & Plasma::FrameSvg::RightBorder) {
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_shadowPixmaps[1]));
} else if (enabledBorders & Plasma::FrameSvg::TopBorder) {
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerTopPix));
} else if (enabledBorders & Plasma::FrameSvg::RightBorder) {
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerRightPix));
} else {
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerPix));
}
//shadow-right
if (enabledBorders & Plasma::FrameSvg::RightBorder) {
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_shadowPixmaps[2]));
} else {
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyVerticalPix));
}
//shadow-bottomright
if (enabledBorders & Plasma::FrameSvg::BottomBorder &&
enabledBorders & Plasma::FrameSvg::RightBorder) {
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_shadowPixmaps[3]));
} else if (enabledBorders & Plasma::FrameSvg::BottomBorder) {
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerBottomPix));
} else if (enabledBorders & Plasma::FrameSvg::RightBorder) {
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerRightPix));
} else {
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerPix));
}
//shadow-bottom
if (enabledBorders & Plasma::FrameSvg::BottomBorder) {
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_shadowPixmaps[4]));
} else {
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyHorizontalPix));
}
//shadow-bottomleft
if (enabledBorders & Plasma::FrameSvg::BottomBorder &&
enabledBorders & Plasma::FrameSvg::LeftBorder) {
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_shadowPixmaps[5]));
} else if (enabledBorders & Plasma::FrameSvg::BottomBorder) {
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerBottomPix));
} else if (enabledBorders & Plasma::FrameSvg::LeftBorder) {
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerLeftPix));
} else {
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerPix));
}
//shadow-left
if (enabledBorders & Plasma::FrameSvg::LeftBorder) {
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_shadowPixmaps[6]));
} else {
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyVerticalPix));
}
//shadow-topleft
if (enabledBorders & Plasma::FrameSvg::TopBorder &&
enabledBorders & Plasma::FrameSvg::LeftBorder) {
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_shadowPixmaps[7]));
} else if (enabledBorders & Plasma::FrameSvg::TopBorder) {
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerTopPix));
} else if (enabledBorders & Plasma::FrameSvg::LeftBorder) {
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerLeftPix));
} else {
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerPix));
}
#endif
int left, top, right, bottom = 0;
QSize marginHint;
if (enabledBorders & Plasma::FrameSvg::TopBorder) {
marginHint = q->elementSize(QStringLiteral("shadow-hint-top-margin"));
if (marginHint.isValid()) {
top = marginHint.height();
} else {
top = m_shadowPixmaps[0].height(); // top
}
} else {
top = 1;
}
if (enabledBorders & Plasma::FrameSvg::RightBorder) {
marginHint = q->elementSize(QStringLiteral("shadow-hint-right-margin"));
if (marginHint.isValid()) {
right = marginHint.width();
} else {
right = m_shadowPixmaps[2].width(); // right
}
} else {
right = 1;
}
if (enabledBorders & Plasma::FrameSvg::BottomBorder) {
marginHint = q->elementSize(QStringLiteral("shadow-hint-bottom-margin"));
if (marginHint.isValid()) {
bottom = marginHint.height();
} else {
bottom = m_shadowPixmaps[4].height(); // bottom
}
} else {
bottom = 1;
}
if (enabledBorders & Plasma::FrameSvg::LeftBorder) {
marginHint = q->elementSize(QStringLiteral("shadow-hint-left-margin"));
if (marginHint.isValid()) {
left = marginHint.width();
} else {
left = m_shadowPixmaps[6].width(); // left
}
} else {
left = 1;
}
data[enabledBorders] << top << right << bottom << left;
}
void PanelShadows::Private::freeX11Pixmaps()
{
#if HAVE_X11
if (!m_isX11) {
return;
}
auto *display = QX11Info::display();
if (!display) {
return;
}
foreach (const QPixmap &pixmap, m_shadowPixmaps) {
if (!pixmap.isNull()) {
XFreePixmap(display, reinterpret_cast<unsigned long>(createPixmap(pixmap)));
}
}
if (!m_emptyCornerPix.isNull()) {
XFreePixmap(display, reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerPix)));
}
if (!m_emptyCornerBottomPix.isNull()) {
XFreePixmap(display, reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerBottomPix)));
}
if (!m_emptyCornerLeftPix.isNull()) {
XFreePixmap(display, reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerLeftPix)));
}
if (!m_emptyCornerRightPix.isNull()) {
XFreePixmap(display, reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerRightPix)));
}
if (!m_emptyCornerTopPix.isNull()) {
XFreePixmap(display, reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerTopPix)));
}
if (!m_emptyVerticalPix.isNull()) {
XFreePixmap(display, reinterpret_cast<unsigned long>(createPixmap(m_emptyVerticalPix)));
}
if (!m_emptyHorizontalPix.isNull()) {
XFreePixmap(display, reinterpret_cast<unsigned long>(createPixmap(m_emptyHorizontalPix)));
}
#endif
}
void PanelShadows::Private::clearPixmaps()
{
#if HAVE_X11
freeX11Pixmaps();
m_emptyCornerPix = QPixmap();
m_emptyCornerBottomPix = QPixmap();
m_emptyCornerLeftPix = QPixmap();
m_emptyCornerRightPix = QPixmap();
m_emptyCornerTopPix = QPixmap();
m_emptyVerticalPix = QPixmap();
m_emptyHorizontalPix = QPixmap();
#endif
freeWaylandBuffers();
m_shadowPixmaps.clear();
data.clear();
}
void PanelShadows::Private::freeWaylandBuffers()
{
m_wayland.shadowBuffers.clear();
}
void PanelShadows::Private::updateShadow(const QWindow *window, Plasma::FrameSvg::EnabledBorders enabledBorders)
void PanelShadows::Private::updateShadow(QWindow *window, Plasma::FrameSvg::EnabledBorders enabledBorders)
{
if (!hasShadows()) {
return;
}
#if HAVE_X11
if (m_isX11) {
updateShadowX11(window, enabledBorders);
}
#endif
if (m_wayland.manager) {
updateShadowWayland(window, enabledBorders);
}
}
void PanelShadows::Private::updateShadowX11(const QWindow *window, Plasma::FrameSvg::EnabledBorders enabledBorders)
{
#if HAVE_X11
if (m_shadowPixmaps.isEmpty()) {
setupPixmaps();
if (m_tiles.isEmpty()) {
setupTiles();
}
if (!data.contains(enabledBorders)) {
setupData(enabledBorders);
KWindowShadow *&shadow = m_shadows[window];
if (!shadow) {
shadow = new KWindowShadow(q);
}
Display *dpy = QX11Info::display();
Atom atom = XInternAtom(dpy, "_KDE_NET_WM_SHADOW", False);
// qDebug() << "going to set the shadow of" << window->winId() << "to" << data;
XChangeProperty(dpy, window->winId(), atom, XA_CARDINAL, 32, PropModeReplace,
reinterpret_cast<const unsigned char *>(data[enabledBorders].constData()), data[enabledBorders].size());
#endif
}
void PanelShadows::Private::updateShadowWayland(const QWindow *window, Plasma::FrameSvg::EnabledBorders enabledBorders)
{
if (!m_wayland.shmPool) {
return;
if (shadow->isCreated()) {
shadow->destroy();
}
if (m_wayland.shadowBuffers.isEmpty()) {
setupPixmaps();
}
// TODO: check whether the surface already has a shadow
KWayland::Client::Surface *surface = KWayland::Client::Surface::fromWindow(const_cast<QWindow*>(window));
if (!surface) {
return;
}
auto shadow = m_wayland.manager->createShadow(surface, surface);
//shadow-top
if (enabledBorders & Plasma::FrameSvg::TopBorder) {
shadow->attachTop(m_wayland.shadowBuffers.at(0));
shadow->setTopTile(m_tiles.at(0));
} else {
shadow->setTopTile(nullptr);
}
//shadow-topright
if (enabledBorders & Plasma::FrameSvg::TopBorder &&
enabledBorders & Plasma::FrameSvg::RightBorder) {
shadow->attachTopRight(m_wayland.shadowBuffers.at(1));
if (enabledBorders & Plasma::FrameSvg::TopBorder && enabledBorders & Plasma::FrameSvg::RightBorder) {
shadow->setTopRightTile(m_tiles.at(1));
} else {
shadow->setTopRightTile(nullptr);
}
//shadow-right
if (enabledBorders & Plasma::FrameSvg::RightBorder) {
shadow->attachRight(m_wayland.shadowBuffers.at(2));
shadow->setRightTile(m_tiles.at(2));
} else {
shadow->setRightTile(nullptr);
}
//shadow-bottomright
if (enabledBorders & Plasma::FrameSvg::BottomBorder &&
enabledBorders & Plasma::FrameSvg::RightBorder) {
shadow->attachBottomRight(m_wayland.shadowBuffers.at(3));
if (enabledBorders & Plasma::FrameSvg::BottomBorder && enabledBorders & Plasma::FrameSvg::RightBorder) {
shadow->setBottomRightTile(m_tiles.at(3));
} else {
shadow->setBottomRightTile(nullptr);
}
//shadow-bottom
if (enabledBorders & Plasma::FrameSvg::BottomBorder) {
shadow->attachBottom(m_wayland.shadowBuffers.at(4));
shadow->setBottomTile(m_tiles.at(4));
} else {
shadow->setBottomTile(nullptr);
}
//shadow-bottomleft
if (enabledBorders & Plasma::FrameSvg::BottomBorder &&
enabledBorders & Plasma::FrameSvg::LeftBorder) {
shadow->attachBottomLeft(m_wayland.shadowBuffers.at(5));
if (enabledBorders & Plasma::FrameSvg::BottomBorder && enabledBorders & Plasma::FrameSvg::LeftBorder) {
shadow->setBottomLeftTile(m_tiles.at(5));
} else {
shadow->setBottomLeftTile(nullptr);
}
//shadow-left
if (enabledBorders & Plasma::FrameSvg::LeftBorder) {
shadow->attachLeft(m_wayland.shadowBuffers.at(6));
shadow->setLeftTile(m_tiles.at(6));
} else {
shadow->setLeftTile(nullptr);
}
//shadow-topleft
if (enabledBorders & Plasma::FrameSvg::TopBorder &&
enabledBorders & Plasma::FrameSvg::LeftBorder) {
shadow->attachTopLeft(m_wayland.shadowBuffers.at(7));
if (enabledBorders & Plasma::FrameSvg::TopBorder && enabledBorders & Plasma::FrameSvg::LeftBorder) {
shadow->setTopLeftTile(m_tiles.at(7));
} else {
shadow->setTopLeftTile(nullptr);
}
QSize marginHint;
QMarginsF margins;
QMargins padding;
if (enabledBorders & Plasma::FrameSvg::TopBorder) {
marginHint = q->elementSize(QStringLiteral("shadow-hint-top-margin"));
const QSize marginHint = q->elementSize(QStringLiteral("shadow-hint-top-margin"));
if (marginHint.isValid()) {
margins.setTop(marginHint.height());
padding.setTop(marginHint.height());
} else {
margins.setTop(m_shadowPixmaps[0].height());
padding.setTop(m_tiles[0]->image().height());
}
}
if (enabledBorders & Plasma::FrameSvg::RightBorder) {
marginHint = q->elementSize(QStringLiteral("shadow-hint-right-margin"));
const QSize marginHint = q->elementSize(QStringLiteral("shadow-hint-right-margin"));
if (marginHint.isValid()) {
margins.setRight(marginHint.width());
padding.setRight(marginHint.width());
} else {
margins.setRight(m_shadowPixmaps[2].width());
padding.setRight(m_tiles[2]->image().width());
}
}
if (enabledBorders & Plasma::FrameSvg::BottomBorder) {
marginHint = q->elementSize(QStringLiteral("shadow-hint-bottom-margin"));
const QSize marginHint = q->elementSize(QStringLiteral("shadow-hint-bottom-margin"));
if (marginHint.isValid()) {
margins.setBottom(marginHint.height());
padding.setBottom(marginHint.height());
} else {
margins.setBottom(m_shadowPixmaps[4].height());
padding.setBottom(m_tiles[4]->image().height());
}
}
if (enabledBorders & Plasma::FrameSvg::LeftBorder) {
marginHint = q->elementSize(QStringLiteral("shadow-hint-left-margin"));
const QSize marginHint = q->elementSize(QStringLiteral("shadow-hint-left-margin"));
if (marginHint.isValid()) {
margins.setLeft(marginHint.width());
padding.setLeft(marginHint.width());
} else {
margins.setLeft(m_shadowPixmaps[6].width());
padding.setLeft(m_tiles[6]->image().width());
}
}
shadow->setOffsets(margins);
shadow->commit();
surface->commit(KWayland::Client::Surface::CommitFlag::None);
}
shadow->setPadding(padding);
shadow->setWindow(window);
void PanelShadows::Private::clearShadow(const QWindow *window)
{
if (!static_cast<const QSurface*>(window)->surfaceHandle()) {
qWarning() << "Cannot clear shadow from window without native surface!";
return;
}
#if HAVE_X11
if (m_isX11) {
clearShadowX11(window);
}
#endif
if (m_wayland.manager) {
clearShadowWayland(window);
if (!shadow->create()) {
qDebug() << "Couldn't create KWindowShadow for" << window;
}
}
void PanelShadows::Private::clearShadowX11(const QWindow* window)
void PanelShadows::Private::clearShadow(QWindow *window)
{
#if HAVE_X11
Display *dpy = QX11Info::display();
Atom atom = XInternAtom(dpy, "_KDE_NET_WM_SHADOW", False);
XDeleteProperty(dpy, window->winId(), atom);
#endif
}
void PanelShadows::Private::clearShadowWayland(const QWindow *window)
{
KWayland::Client::Surface *surface = KWayland::Client::Surface::fromWindow(const_cast<QWindow*>(window));
if (!surface) {
return;
}
m_wayland.manager->removeShadow(surface);
surface->commit(KWayland::Client::Surface::CommitFlag::None);
delete m_shadows.take(window);
}
bool PanelShadows::Private::hasShadows() const
{
return q->hasShadows();
}
void PanelShadows::Private::setupWaylandIntegration()
{
if (!KWindowSystem::isPlatformWayland()) {
return;
}
using namespace KWayland::Client;
ConnectionThread *connection = ConnectionThread::fromApplication(q);
if (!connection) {
return;
}
Registry *registry = new Registry(q);
registry->create(connection);
connect(registry, &Registry::shadowAnnounced, q,
[this, registry] (quint32 name, quint32 version) {
m_wayland.manager = registry->createShadowManager(name, version, q);
updateShadows();
}, Qt::QueuedConnection
);
connect(registry, &Registry::shmAnnounced, q,
[this, registry] (quint32 name, quint32 version) {
m_wayland.shmPool = registry->createShmPool(name, version, q);
updateShadows();
}, Qt::QueuedConnection
);
registry->setup();
connection->roundtrip();
return q->hasElement(QStringLiteral("shadow-left"));
}
#include "moc_panelshadows_p.cpp"

View File

@ -4,15 +4,13 @@
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#ifndef PANELSHADOWS_P_H
#define PANELSHADOWS_P_H
#pragma once
#include <QSet>
#include "plasma/framesvg.h"
#include "plasma/svg.h"
class PanelShadows : public Plasma::Svg
{
Q_OBJECT
@ -23,17 +21,12 @@ public:
static PanelShadows *self();
void addWindow(const QWindow *window, Plasma::FrameSvg::EnabledBorders enabledBorders = Plasma::FrameSvg::AllBorders);
void removeWindow(const QWindow *window);
void addWindow(QWindow *window, Plasma::FrameSvg::EnabledBorders enabledBorders = Plasma::FrameSvg::AllBorders);
void removeWindow(QWindow *window);
void setEnabledBorders(const QWindow *window, Plasma::FrameSvg::EnabledBorders enabledBorders = Plasma::FrameSvg::AllBorders);
bool hasShadows() const;
void setEnabledBorders(QWindow *window, Plasma::FrameSvg::EnabledBorders enabledBorders = Plasma::FrameSvg::AllBorders);
private:
class Private;
Private * const d;
Private *const d;
};
#endif

View File

@ -8,6 +8,7 @@
// local
#include <coretypes.h>
#include "effects.h"
#include "originalview.h"
#include "view.h"
#include "visibilitymanager.h"
#include "../lattecorona.h"
@ -208,7 +209,7 @@ void Positioner::init()
});
connect(qGuiApp, &QGuiApplication::screenAdded, this, &Positioner::onScreenChanged);
connect(qGuiApp, &QGuiApplication::primaryScreenChanged, this, &Positioner::onScreenChanged);
connect(m_corona->screenPool(), &ScreenPool::primaryScreenChanged, this, &Positioner::onScreenChanged);
connect(m_view, &Latte::View::visibilityChanged, this, &Positioner::initDelayedSignals);
@ -268,7 +269,7 @@ void Positioner::setInRelocationShowing(bool active)
bool Positioner::isOffScreen() const
{
return (m_validGeometry.x()<-500 || m_validGeometry.y()<-500);
return (m_view->absoluteGeometry().x()<-500 || m_view->absoluteGeometry().y()<-500);
}
int Positioner::currentScreenId() const
@ -347,6 +348,7 @@ void Positioner::onStartupFinished()
if (m_inStartup) {
m_inStartup = false;
syncGeometry();
emit isOffScreenChanged();
}
}
@ -433,11 +435,12 @@ void Positioner::reconsiderScreen()
}
bool screenExists{false};
QScreen *primaryScreen{m_corona->screenPool()->primaryScreen()};
//!check if the associated screen is running
for (const auto scr : qGuiApp->screens()) {
if (m_screenNameToFollow == scr->name()
|| (m_view->onPrimary() && scr == qGuiApp->primaryScreen())) {
|| (m_view->onPrimary() && scr == primaryScreen)) {
screenExists = true;
}
}
@ -445,12 +448,12 @@ void Positioner::reconsiderScreen()
qDebug() << "dock screen exists ::: " << screenExists;
//! 1.a primary dock must be always on the primary screen
if (m_view->onPrimary() && (m_screenNameToFollow != qGuiApp->primaryScreen()->name()
|| m_screenToFollow != qGuiApp->primaryScreen()
|| m_view->screen() != qGuiApp->primaryScreen())) {
if (m_view->onPrimary() && (m_screenNameToFollow != primaryScreen->name()
|| m_screenToFollow != primaryScreen
|| m_view->screen() != primaryScreen)) {
//! case 1
qDebug() << "reached case 1: of updating dock primary screen...";
setScreenToFollow(qGuiApp->primaryScreen());
setScreenToFollow(primaryScreen);
} else if (!m_view->onPrimary()) {
//! 2.an explicit dock must be always on the correct associated screen
//! there are cases that window manager misplaces the dock, this function
@ -564,7 +567,10 @@ void Positioner::immediateSyncGeometry()
freeRegion = latteCorona->availableScreenRegionWithCriteria(fixedScreen, activityid, ignoreModes, ignoreEdges);
}
maximumRect = maximumNormalGeometry();
//! On startup when offscreen use offscreen screen geometry.
//! This way vertical docks and panels are not showing are shrinked that
//! need to be expanded after sliding-in in startup
maximumRect = maximumNormalGeometry(m_inStartup ? availableScreenRect : QRect());
QRegion availableRegion = freeRegion.intersected(maximumRect);
availableScreenRect = freeRegion.intersected(maximumRect).boundingRect();
@ -584,7 +590,6 @@ void Positioner::immediateSyncGeometry()
}
validateTopBottomBorders(availableScreenRect, freeRegion);
m_lastAvailableScreenRegion = freeRegion;
} else {
m_view->effects()->setForceTopBorder(false);
@ -634,23 +639,25 @@ void Positioner::setCanvasGeometry(const QRect &geometry)
//! this is used mainly from vertical panels in order to
//! to get the maximum geometry that can be used from the dock
//! based on their alignment type and the location dock
QRect Positioner::maximumNormalGeometry()
QRect Positioner::maximumNormalGeometry(QRect screenGeometry)
{
QRect currentScrGeometry = screenGeometry.isEmpty() ? m_view->screen()->geometry() : screenGeometry;
int xPos = 0;
int yPos = m_view->screen()->geometry().y();;
int maxHeight = m_view->screen()->geometry().height();
int yPos = currentScrGeometry.y();;
int maxHeight = currentScrGeometry.height();
int maxWidth = m_view->maxNormalThickness();
QRect maxGeometry;
maxGeometry.setRect(0, 0, maxWidth, maxHeight);
switch (m_view->location()) {
case Plasma::Types::LeftEdge:
xPos = m_view->screen()->geometry().x();
xPos = currentScrGeometry.x();
maxGeometry.setRect(xPos, yPos, maxWidth, maxHeight);
break;
case Plasma::Types::RightEdge:
xPos = m_view->screen()->geometry().right() - maxWidth + 1;
xPos = currentScrGeometry.right() - maxWidth + 1;
maxGeometry.setRect(xPos, yPos, maxWidth, maxHeight);
break;
@ -669,7 +676,8 @@ void Positioner::validateTopBottomBorders(QRect availableScreenRect, QRegion ava
if (availableScreenRect.top() != m_view->screenGeometry().top()) {
//! check top border
QRegion fitInRegion = QRect(m_view->screenGeometry().x(), availableScreenRect.y()-1, edgeMargin, 1);
int x = m_view->location() == Plasma::Types::LeftEdge ? m_view->screenGeometry().x() : m_view->screenGeometry().right() - edgeMargin + 1;
QRegion fitInRegion = QRect(x, availableScreenRect.y()-1, edgeMargin, 1);
QRegion subtracted = fitInRegion.subtracted(availableScreenRegion);
if (subtracted.isNull()) {
@ -685,7 +693,8 @@ void Positioner::validateTopBottomBorders(QRect availableScreenRect, QRegion ava
if (availableScreenRect.bottom() != m_view->screenGeometry().bottom()) {
//! check top border
QRegion fitInRegion = QRect(m_view->screenGeometry().x(), availableScreenRect.bottom()+1, edgeMargin, 1);
int x = m_view->location() == Plasma::Types::LeftEdge ? m_view->screenGeometry().x() : m_view->screenGeometry().right() - edgeMargin + 1;
QRegion fitInRegion = QRect(x, availableScreenRect.bottom()+1, edgeMargin, 1);
QRegion subtracted = fitInRegion.subtracted(availableScreenRegion);
if (subtracted.isNull()) {
@ -966,10 +975,18 @@ void Positioner::initSignalingForLocationChangeSliding()
//! SCREEN
connect(m_view, &QQuickView::screenChanged, this, [&]() {
if (!m_view || !m_nextScreen) {
return;
}
//[1] if panels are not excluded from confirmed geometry check then they are stuck in sliding out end
//and they do not switch to new screen geometry
//[2] under wayland view geometry may be delayed to be updated even though the screen has been updated correctly
bool confirmedgeometry = KWindowSystem::isPlatformWayland() || m_view->behaveAsPlasmaPanel() || (!m_view->behaveAsPlasmaPanel() && m_nextScreen->geometry().contains(m_view->geometry().center()));
if (m_nextScreen
&& m_nextScreen == m_view->screen()
&& m_nextScreen->geometry().contains(m_view->geometry().center())) {
&& confirmedgeometry) {
bool isrelocationlastevent = isLastHidingRelocationEvent();
m_nextScreen = nullptr;
m_nextScreenName = "";
@ -1014,7 +1031,7 @@ void Positioner::initSignalingForLocationChangeSliding()
//! SCREEN
if (!m_nextScreenName.isEmpty()) {
bool nextonprimary = (m_nextScreenName == Latte::Data::Screen::ONPRIMARYNAME);
m_nextScreen = qGuiApp->primaryScreen();
m_nextScreen = m_corona->screenPool()->primaryScreen();
if (!nextonprimary) {
for (const auto scr : qGuiApp->screens()) {
@ -1039,6 +1056,12 @@ void Positioner::initSignalingForLocationChangeSliding()
m_view->setAlignment(m_nextAlignment);
m_nextAlignment = Latte::Types::NoneAlignment;
}
//! SCREENSGROUP
if (m_view->isOriginal()) {
auto originalview = qobject_cast<Latte::OriginalView *>(m_view);
originalview->setScreensGroup(m_nextScreensGroup);
}
});
}
@ -1133,7 +1156,7 @@ bool Positioner::isLastHidingRelocationEvent() const
return (events <= 1);
}
void Positioner::setNextLocation(const QString layoutName, const QString screenName, int edge, int alignment)
void Positioner::setNextLocation(const QString layoutName, const int screensGroup, QString screenName, int edge, int alignment)
{
bool isanimated{false};
bool haschanges{false};
@ -1158,6 +1181,30 @@ void Positioner::setNextLocation(const QString layoutName, const QString screenN
}
}
//! SCREENSGROUP
if (m_view->isOriginal()) {
auto originalview = qobject_cast<Latte::OriginalView *>(m_view);
//!initialize screens group
m_nextScreensGroup = originalview->screensGroup();
if (m_nextScreensGroup != screensGroup) {
haschanges = true;
m_nextScreensGroup = static_cast<Latte::Types::ScreensGroup>(screensGroup);
if (m_nextScreensGroup == Latte::Types::AllScreensGroup) {
screenName = Latte::Data::Screen::ONPRIMARYNAME;
} else if (m_nextScreensGroup == Latte::Types::AllSecondaryScreensGroup) {
int scrid = originalview->expectedScreenIdFromScreenGroup(m_nextScreensGroup);
if (scrid != Latte::ScreenPool::NOSCREENID) {
screenName = m_corona->screenPool()->connector(scrid);
}
}
}
} else {
m_nextScreensGroup = Latte::Types::SingleScreenGroup;
}
//! SCREEN
if (!screenName.isEmpty()) {
bool nextonprimary = (screenName == Latte::Data::Screen::ONPRIMARYNAME);
@ -1166,7 +1213,7 @@ void Positioner::setNextLocation(const QString layoutName, const QString screenN
|| (!m_view->onPrimary() && nextonprimary) /*explicit -> primary*/
|| (!m_view->onPrimary() && !nextonprimary && screenName != currentScreenName()) ) { /*explicit -> new_explicit*/
QString nextscreenname = nextonprimary ? qGuiApp->primaryScreen()->name() : screenName;
QString nextscreenname = nextonprimary ? m_corona->screenPool()->primaryScreen()->name() : screenName;
if (currentScreenName() == nextscreenname) {
m_view->setOnPrimary(nextonprimary);
@ -1194,6 +1241,11 @@ void Positioner::setNextLocation(const QString layoutName, const QString screenN
haschanges = true;
}
if (haschanges && m_view->isOriginal()) {
auto originalview = qobject_cast<Latte::OriginalView *>(m_view);
originalview->setNextLocationForClones(layoutName, edge, alignment);
}
m_repositionIsAnimated = isanimated;
m_repositionFromViewSettingsWindow = m_view->settingsWindowIsShown();

View File

@ -40,6 +40,7 @@ class Positioner: public QObject
Q_PROPERTY(bool inRelocationShowing READ inRelocationShowing WRITE setInRelocationShowing NOTIFY inRelocationShowingChanged)
Q_PROPERTY(bool inSlideAnimation READ inSlideAnimation WRITE setInSlideAnimation NOTIFY inSlideAnimationChanged)
Q_PROPERTY(bool isOffScreen READ isOffScreen NOTIFY isOffScreenChanged)
Q_PROPERTY(bool isStickedOnTopEdge READ isStickedOnTopEdge WRITE setIsStickedOnTopEdge NOTIFY isStickedOnTopEdgeChanged)
Q_PROPERTY(bool isStickedOnBottomEdge READ isStickedOnBottomEdge WRITE setIsStickedOnBottomEdge NOTIFY isStickedOnBottomEdgeChanged)
@ -90,7 +91,7 @@ public:
Latte::WindowSystem::WindowId trackedWindowId();
public slots:
Q_INVOKABLE void setNextLocation(const QString layoutName, const QString screenId, int edge, int alignment);
Q_INVOKABLE void setNextLocation(const QString layoutName, const int screensGroup, QString screenName, int edge, int alignment);
Q_INVOKABLE void slideInDuringStartup();
void syncGeometry();
@ -126,6 +127,7 @@ signals:
void inRelocationAnimationChanged();
void inRelocationShowingChanged();
void inSlideAnimationChanged();
void isOffScreenChanged();
void isStickedOnTopEdgeChanged();
void isStickedOnBottomEdgeChanged();
@ -155,7 +157,7 @@ private:
bool isLastHidingRelocationEvent() const;
QRect maximumNormalGeometry();
QRect maximumNormalGeometry(QRect screenGeometry = QRect());
WindowSystem::AbstractWindowInterface::Slide slideLocation(Plasma::Types::Location location);
@ -193,6 +195,7 @@ private:
bool m_repositionIsAnimated{false};
QString m_nextLayoutName;
Latte::Types::ScreensGroup m_nextScreensGroup{Latte::Types::SingleScreenGroup};
QString m_nextScreenName;
QScreen *m_nextScreen{nullptr};
Plasma::Types::Location m_nextScreenEdge{Plasma::Types::Floating};

Some files were not shown because too many files have changed in this diff Show More