Compare commits

..

588 Commits

Author SHA1 Message Date
zhuzichu 10580baf54
Bug fixed. 2023-07-08 19:11:21 +08:00
Mentalflow e72257bb34
Use mirror submodule. 2023-07-08 19:11:20 +08:00
Dylan Liu 43f632f261
Fix the bug of unregistered datatype QuickGlobal::SystemTheme in Qt 5. (#240) 2023-07-06 11:50:05 +08:00
Yuhang Zhao 9dce992112 cmake: update submodule 2023-07-04 15:14:49 +08:00
Yuhang Zhao d1b4aadb76 mica material: use separate thread to do time-consuming task 2023-07-02 13:48:38 +08:00
Yuhang Zhao 6b09aa9e91 bump version to 2.4.0 2023-07-02 11:56:21 +08:00
Yuhang Zhao 617a015b97 mica material: minor fixes of previous implementation 2023-07-02 11:44:54 +08:00
Yuhang Zhao 7c0d8c4b11 mica material: support reading very large image files 2023-07-01 18:16:57 +08:00
Yuhang Zhao fa5389a0fc ci: try fix ci 2023-06-30 17:31:01 +08:00
Yuhang Zhao 2a49e9fcaf cmake: support ninja multi-config
Fixes: #231
2023-06-30 16:55:26 +08:00
Yuhang Zhao 6ccb25db0a cmake: update submodule 2023-06-29 14:52:42 +08:00
Yuhang Zhao 8f321e2e54 cmake: allow produce same binary
Task-number: #238
2023-06-29 10:59:39 +08:00
Yuhang Zhao f15412cf5b cmake: update submodule 2023-06-26 13:24:56 +08:00
Yuhang Zhao a5ec49d0a2 cmake: update submodule 2023-06-26 11:16:45 +08:00
Yuhang Zhao 86a9b85d04 cmake: fix cmake error on Apple 2023-06-20 11:07:38 +08:00
Yuhang Zhao b7556d467e cmake: update 2023-06-19 18:04:04 +08:00
Yuhang Zhao 074664afc2 cmake: update submodule 2023-06-19 17:48:40 +08:00
Yuhang Zhao 6229a0db3c README: fix wrong function name 2023-06-19 17:14:31 +08:00
Yuhang Zhao 6c27125d69 win: guard some code with proper version check 2023-06-19 16:07:43 +08:00
Yuhang Zhao fdd6640d5c cmake: fix wrong compilation flags 2023-06-19 15:29:14 +08:00
Yuhang Zhao 10b661f541 cmake: update submodule 2023-06-17 12:41:55 +08:00
Yuhang Zhao c1370c4897 cmake: minor change 2023-06-17 12:34:30 +08:00
Dylan Liu af200adf63
Remove unused function in NSWindowProxy. (#236) 2023-06-15 18:48:21 +08:00
Yuhang Zhao 85be988760 ci: fix macos ci 2023-06-10 20:54:07 +08:00
Yuhang Zhao 273e3e204c update submodule 2023-06-10 20:41:46 +08:00
Yuhang Zhao 00b67ead0e win: remove unnecessary code & add some comments
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-06-04 13:28:14 +08:00
Yuhang Zhao 907fdeae67 fix ci: remove unused functions
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-06-03 15:24:04 +08:00
Yuhang Zhao 5a344f3e23 minor fixes & some refactorings
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-06-03 15:13:50 +08:00
Yuhang Zhao b28b6e8d27 update submodule
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-06-03 13:35:02 +08:00
Yuhang Zhao 1e754c1612 minor fixes 2023-06-02 14:51:12 +08:00
Yuhang Zhao f7f8fc3dd0 core: fix wrong override condition
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-05-28 13:55:44 +08:00
Yuhang Zhao e1cf95f208 cmake: fix link with mingw
Signed-off-by: Yuhang Zhao <zhaoyuhang@rankyee.com>
2023-05-26 11:08:08 +08:00
Yuhang Zhao 9778582d9b update README
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-05-25 19:35:29 +08:00
Yuhang Zhao 0424d0ee1b README: add more info
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-05-25 19:30:12 +08:00
Yuhang Zhao 13e93cfed5 cmake: code simplify
Signed-off-by: Yuhang Zhao <zhaoyuhang@rankyee.com>
2023-05-24 15:41:11 +08:00
zhuzichu 9376e4d6e7
fix mingw dont work (#229) 2023-05-24 15:38:51 +08:00
Yuhang Zhao 59fb61d981 cmake: fix old mingw toolchain
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-05-22 19:27:26 +08:00
zhuzichu e090359d9a
fix setOverrideTheme render multiple times (#228)
* fix setOverrideTheme render multiple times

* fix setOverrideTheme render multiple times

* fix encoding utf8

* fix setOverrideTheme render multiple times

---------

Co-authored-by: 朱子楚\zhuzi <zhuzichu520@outlook.com>
2023-05-22 19:15:51 +08:00
Yuhang Zhao e7da37d06a deprecated unused function & other minor tweaks
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-05-21 12:04:57 +08:00
Dylan Liu 3a18f36d3f
Fix the native titlebar buttons don't show below Qt 6.2.4. (#226) 2023-05-20 21:01:23 +08:00
Yuhang Zhao 9df1e9d7b5 mac: add a comment
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-05-20 20:07:43 +08:00
Dylan Liu e48fc7e01f
Fix the native titlebar buttons don't show in Qt 6.0.0 - Qt 6.2.4. (#225) 2023-05-20 19:57:00 +08:00
Yuhang Zhao 2b1623fbd6 cmake: hide detailed info if the user don't want it
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-05-20 15:32:48 +08:00
Yuhang Zhao e67a91d668 refactor: remove all mutexes
They are currently not used and slow down the general performance.
2023-05-19 13:31:20 +08:00
Dylan Liu ec93740bd7
Add manual control of darkmode for Quick. (#220)
Add the function of manual control of dark mode in Quick module.
2023-05-19 13:12:25 +08:00
Yuhang Zhao e4fdb9c260 refactor 2023-05-19 11:58:32 +08:00
Yuhang Zhao de2cad679b update submodule 2023-05-19 11:56:14 +08:00
Yuhang Zhao 1ba9c9c918 refactor 2023-05-19 11:55:41 +08:00
Yuhang Zhao 721f46307b fix cmake syntax error
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-05-18 20:40:46 +08:00
Yuhang Zhao 32b055a7ab cmake: dump more info
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-05-18 20:38:05 +08:00
Yuhang Zhao 8b7ee7a24d cmake: don't touch AppleClang flags
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-05-18 19:58:42 +08:00
Dylan Liu 951dd5f931
Add version check for universal build. (#219) 2023-05-18 19:54:50 +08:00
Yuhang Zhao 2c1164b834 fix win ci warning 2023-05-18 16:49:07 +08:00
Yuhang Zhao 0be45565dc update ci 2023-05-18 16:41:44 +08:00
Yuhang Zhao 2fa3140b0f update submodule 2023-05-18 16:13:48 +08:00
Yuhang Zhao 8d5ea49d52 allow user override system theme
Task-number: #216
2023-05-18 16:08:33 +08:00
Yuhang Zhao 66c2c60a09 DPI change event improve 2023-05-18 14:40:28 +08:00
Yuhang Zhao 82e29f37bb try fix macOS ci 2023-05-18 09:47:30 +08:00
Dylan Liu 84745db4d9
Add Universal build for macOS and compile error fixed. (#217)
* Add Universal build for macOS.

* Fix compile error in example quick.

* Use cmake_dependent_option instead of option.
2023-05-17 20:19:31 +08:00
Yuhang Zhao 84a9a76021 try fix ci 2023-05-17 20:05:06 +08:00
Yuhang Zhao 901aaee7e3 try fix ci 2023-05-17 19:50:11 +08:00
Yuhang Zhao a9ee1c5fff fix ci 2023-05-17 19:31:26 +08:00
Yuhang Zhao 76453b123e fix ci: 6.5.1 has not been released yet 2023-05-17 18:06:00 +08:00
Yuhang Zhao cfcf9f4178 fix ci 2023-05-17 18:04:19 +08:00
Yuhang Zhao 8ece315390 update submodule 2023-05-17 17:51:37 +08:00
Yuhang Zhao 92d850c2a9 add support for Qt 6.6's DPR change event 2023-05-17 13:22:42 +08:00
Yuhang Zhao 224302500d cmake: quick: fix build with version below 6.3
Fixes: #215
2023-05-17 09:20:53 +08:00
Yuhang Zhao cf568b6e7a cmake: use Qt's official function to get the quick plugin info 2023-05-16 18:01:06 +08:00
Yuhang Zhao a3cfa59d1d improve dpi change experience
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-05-13 11:30:54 +08:00
Yuhang Zhao 250aff0faf cmake: fix build on arm64 platforms 2023-05-04 17:37:43 +08:00
Yuhang Zhao b039a9130a win: minor refactor 2023-04-28 09:14:06 +08:00
Yuhang Zhao 4d063369fa mica material: add fallback color and fix the qtquick one
I don't understand why I didn't make QuickMicaMaterial configurable.
2023-04-27 10:36:47 +08:00
Yuhang Zhao 41e91bb39a win: fix wrong restore geometry when after DPI changes 2023-04-25 15:19:31 +08:00
Yuhang Zhao 30d2261baf bump version to 2.3.7 2023-04-24 15:43:17 +08:00
Yuhang Zhao fe724271da unix: fix wrong system menu position 2023-04-24 13:18:57 +08:00
Yuhang Zhao b2561c16ba minor refactor 2023-04-23 13:42:27 +08:00
Yuhang Zhao a203e2c3ca win32: fix restore geometry bug
The upstream fix has not been merged yet, however, it will be in 6.5.1 for sure.

Fixes: #20

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-04-22 15:21:49 +08:00
Yuhang Zhao 8930ea128f minor tweaks
Signed-off-by: Yuhang Zhao <zhaoyuhang@rankyee.com>
2023-04-17 11:16:50 +08:00
Yuhang Zhao 3b8571401f minor refactor 2023-04-11 17:09:58 +08:00
Yuhang Zhao 99417bf916 fix coordinate calculation in multi-monitor scenarios 2023-04-11 15:12:33 +08:00
Yuhang Zhao b9dcaac87d remove unused tool
Signed-off-by: Yuhang Zhao <zhaoyuhang@rankyee.com>
2023-04-07 17:22:39 +08:00
Yuhang Zhao 9dd57367a7 bump version to 2.3.6
Signed-off-by: Yuhang Zhao <zhaoyuhang@rankyee.com>
2023-04-07 17:22:16 +08:00
Yuhang Zhao b4a27c059b fix system menu wrong position
Signed-off-by: Yuhang Zhao <zhaoyuhang@rankyee.com>
2023-04-07 16:56:58 +08:00
Yuhang Zhao b597d2c91a update submodule 2023-04-07 16:42:11 +08:00
Yuhang Zhao 632a708c8a fix white-line issue for QWidget applications
Fixes: #204

Signed-off-by: Yuhang Zhao <zhaoyuhang@rankyee.com>
2023-04-07 16:41:39 +08:00
Yuhang Zhao d49c3be147 fix runtime error
Signed-off-by: Yuhang Zhao <zhaoyuhang@rankyee.com>
2023-04-04 16:47:03 +08:00
Yuhang Zhao 55ecb4f5dd fix invalid parameter for msvc
Signed-off-by: Yuhang Zhao <zhaoyuhang@rankyee.com>
2023-04-04 10:52:54 +08:00
Yuhang Zhao 48a3270356 update submodule
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-04-01 20:15:25 +08:00
Yuhang Zhao 1effb497ce update cmake scripts, fix clang-cl build
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-04-01 14:00:10 +08:00
Yuhang Zhao b5c9f85f62 allow user force use system blur
Signed-off-by: Yuhang Zhao <zhaoyuhang@rankyee.com>
2023-03-30 14:16:34 +08:00
Yuhang Zhao 9e208bb77c fix build on qt5
Task-number: #210

Signed-off-by: Yuhang Zhao <zhaoyuhang@rankyee.com>
2023-03-30 11:47:34 +08:00
Yuhang Zhao 5ade3cfb74 fix hidpi position calculation
Task-number: #210

Signed-off-by: Yuhang Zhao <zhaoyuhang@rankyee.com>
2023-03-30 11:39:05 +08:00
Yuhang Zhao 2a6b8e6ebe fix compilation error
Fixes: #211
2023-03-30 10:28:31 +08:00
Yuhang Zhao b864e39894 cmake: update submodule
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-03-10 20:09:19 +08:00
Yuhang Zhao 0b0da5f4b1 cmake: update
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-03-04 16:44:23 +08:00
Yuhang Zhao b9cd887dbc msbuild: install & tweaks
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-03-04 16:21:49 +08:00
Yuhang Zhao c4a29df155 Add MSBuild support
Thanks to @MouriNaruto !

Co-authored-by: MouriNaruto <Mouri_Naruto@Outlook.com>
2023-02-26 10:00:27 +08:00
Yuhang Zhao a0c825930e win: allow user disable specific system menu items
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-02-24 15:40:08 +08:00
Yuhang Zhao 598de50290 add synchronize api to wait for the ready signal
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-02-24 13:13:01 +08:00
Yuhang Zhao e2652fc2a9 cmake: minor tweaks
Fixes: #205

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-02-24 10:03:10 +08:00
Yuhang Zhao 45c1c005fe cmake: update submodule
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-02-23 13:17:06 +08:00
Yuhang Zhao c197653efe examples: improve cmake script
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-02-21 09:34:44 +08:00
Yuhang Zhao b6af9f58f6 fix x86 build
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-02-20 13:13:04 +08:00
Yuhang Zhao c944655e63 cmake: fix wrong syntax
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-02-19 17:32:28 +08:00
Yuhang Zhao 5bd4db212e ci: fix
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-02-19 17:20:37 +08:00
Yuhang Zhao 1fb3b282ed ci: temporarily unblock ci
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-02-19 17:08:46 +08:00
Yuhang Zhao fa5a21f7ca cmake: minor tweaks
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-02-19 17:01:56 +08:00
Yuhang Zhao 9e341e4e40 examples: update cmake project
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-02-19 16:31:24 +08:00
Yuhang Zhao cf2bc7c1b9 update submodule
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-02-19 13:17:25 +08:00
Yuhang Zhao b5bbb341a4 cmake: minor improvement
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-02-19 13:14:45 +08:00
Yuhang Zhao f6383c5832 ci: fix ci
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-02-19 13:00:11 +08:00
Yuhang Zhao 9a81cf1503 cmake: improve the package code
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-02-19 12:36:41 +08:00
Yuhang Zhao a375bc6748 sysapiloader: minor improvements of previous refactor
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-02-17 09:59:41 +08:00
Yuhang Zhao fa8ca1ae2f cmake: let user be able to change the namespace
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-02-17 09:21:52 +08:00
Yuhang Zhao 4929707806 fix header search path
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-02-17 09:17:15 +08:00
Yuhang Zhao 02f70d1ade sysapiloader: minor improvements
And some other minor refactors.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-02-16 14:55:26 +08:00
Yuhang Zhao 7fb9b312b1 ci: try fix
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-02-15 17:14:28 +08:00
Yuhang Zhao 11c85a9229 ci: try fix
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-02-15 17:12:13 +08:00
Yuhang Zhao 4e01917b35 ci: try fix
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-02-15 17:05:03 +08:00
Yuhang Zhao 75fc33325b ci: try fix
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-02-15 16:56:39 +08:00
Yuhang Zhao 0034927378 ci: try fix
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-02-15 16:51:01 +08:00
Yuhang Zhao 36c691e239 ci: try fix
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-02-15 16:44:44 +08:00
Yuhang Zhao d43551e6e4 ci: try fix
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-02-15 15:50:41 +08:00
Yuhang Zhao a246b25019 ci: try fix
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-02-15 15:28:14 +08:00
Yuhang Zhao 5566a0cbc4 ci: try fix ci
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-02-15 15:14:56 +08:00
Yuhang Zhao 3523ea67ea cmake: update submodule
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-02-15 14:53:29 +08:00
Yuhang Zhao 9bf6361171 qt: adapt to latest qt dev code
It was decided to rename the property from Appearance to ColorScheme.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-02-15 11:22:52 +08:00
Yuhang Zhao 8bd2a777d1 cmake: update submodule
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-02-14 11:50:06 +08:00
Yuhang Zhao 2b9d810002 cmake: minor tweaks
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-02-10 14:10:46 +08:00
Yuhang Zhao 16c10d7569 linux: fix typo in code memo
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-02-08 13:44:15 +08:00
Yuhang Zhao 6048349e52 cmake: allow turn off cmake summary
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-02-08 13:19:23 +08:00
Yuhang Zhao c461a1cf51 linux: add some code memo
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-02-08 10:02:20 +08:00
Yuhang Zhao e7e6426dca linux: another attempt to fix the segfault
Related: #202

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-02-07 14:38:18 +08:00
Yuhang Zhao 91239fca90 update macos screenshots
Fixes: #203

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-02-07 13:32:16 +08:00
Yuhang Zhao 4d43296e28 update readme
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-02-07 11:15:54 +08:00
Yuhang Zhao dc848b3da2 update screenshot for macos
Related issue: #203

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-02-07 11:11:48 +08:00
Yuhang Zhao c56aa7b594 linux: try fix segfault further
Related reports: #201 #202

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-02-06 15:12:12 +08:00
Yuhang Zhao 8b6dd746eb refactor
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-02-06 15:08:19 +08:00
Yuhang Zhao 4cb9c9c60d linux: fix segfault on some distros
Task-number: #201
Task-number: #202

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-02-06 13:40:12 +08:00
Yuhang Zhao a0125df8cd fix macos build
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-02-06 09:13:40 +08:00
Yuhang Zhao fc92783af9 misc modifications
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-02-05 18:54:34 +08:00
Yuhang Zhao e9a2abf663 fix macos build
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-02-05 14:12:01 +08:00
Yuhang Zhao 9cadad625a fix linux build
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-02-05 14:06:33 +08:00
Yuhang Zhao 14ccc990cf general refactor, remove useless code
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-02-05 14:01:46 +08:00
Yuhang Zhao 3d37d87c81 win: tweak some enum values
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-02-03 11:18:08 +08:00
Yuhang Zhao 2040e7c747 try fix ci
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-02-02 13:24:46 +08:00
Yuhang Zhao 544d3b898b minor cmake tweaks
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-02-02 13:07:09 +08:00
Yuhang Zhao 0a85d47390 update README
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-01-31 17:45:09 +08:00
Yuhang Zhao c69ede0fca update submodule
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-01-30 17:35:44 +08:00
Yuhang Zhao 0b5df78866 update submodule
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-01-28 15:16:22 +08:00
Yuhang Zhao ed75e2f3e8 adapt to latest Qt code style
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-01-27 18:16:32 +08:00
Yuhang Zhao f16fb95cba try fix ci
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-01-27 17:31:46 +08:00
Yuhang Zhao 6063a962eb simplify cmake scripts
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-01-27 16:27:16 +08:00
Yuhang Zhao 5cd386a419 qmake: adapt latest cmake changes
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-01-25 13:49:06 +08:00
Yuhang Zhao 69ef2a6ca1 linux: fix potential segment faults
Fixes: #199

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-01-24 16:57:44 +08:00
Yuhang Zhao a23438b02b win: add one more safe guard
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-01-18 18:01:10 +08:00
Yuhang Zhao 7534a4631c migrate to the <module/file> include pattern
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-01-18 14:27:10 +08:00
Yuhang Zhao 378aa7db12 fix nested frameless windows & other minor tweaks
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-01-18 13:43:51 +08:00
Yuhang Zhao 4896869123 use better name
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-01-18 10:00:18 +08:00
Yuhang Zhao 139d5a41df quick demo: a little improvement
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-01-15 14:34:14 +08:00
Yuhang Zhao 5e7ddb1864 quick: adapt macos updates
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-01-15 14:11:52 +08:00
Yuhang Zhao d25666b0e6 titlebar: fix calculation error of previous commit
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-01-14 20:54:29 +08:00
Yuhang Zhao 819ffb79fb macOS: widgets: preserve the native title bar elements
Quick part to be done.
2023-01-14 18:32:47 +08:00
Yuhang Zhao 9e975e02e0 cmake: fix export error
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-01-14 12:59:18 +08:00
Yuhang Zhao d1f17eb239 cmake: add option to disable install
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-01-14 12:23:04 +08:00
Yuhang Zhao eb6fc55006 quick: remove unneeded enums, fix warning
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-01-13 17:47:37 +08:00
Yuhang Zhao 6e79ba3f33 minor tweaks
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-01-13 13:39:21 +08:00
Yuhang Zhao 653fa1d6f1 quick demo: fix for latest qt
The onClosing signal was removed in latest qt.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-01-12 09:11:29 +08:00
Yuhang Zhao 814d2ad12d cmake: detect qt library type
Fixes: #200

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-01-05 15:07:38 +08:00
Yuhang Zhao 16479be799 quick demo: minor tweaks
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-01-03 13:38:00 +08:00
Yuhang Zhao 3a97e712fb fixes repaint issue on macos
fixes:  #197

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2023-01-01 14:19:14 +08:00
Yuhang Zhao f651116fda msvc: allow disable permissive checks
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-12-30 11:01:43 +08:00
micpub 32457c5538
fix qmake linux build, and fix the "Quick" example (#194)
* fix: qmake linux build

* little fix for the "Quick" example

Window.qml / ApplicationWindow.qml: fix: "FramelessApplicationWindow.onClosing" is not available in org.wangwenx190.FramelessHelper 1.0.

* remove xcb - as requested
2022-12-30 10:35:20 +08:00
Yuhang Zhao 4a903a5805 linux: improve configure log
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-12-28 11:33:24 +08:00
Yuhang Zhao a5586604e9 quick: fix build error
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-12-28 11:22:40 +08:00
Yuhang Zhao d4c087f627 linux: comment out some code that doesn't work
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-12-25 13:36:18 +08:00
Yuhang Zhao 7327179d77 linux: add temporary solution to get theme color
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-12-25 13:33:34 +08:00
Yuhang Zhao 8a1dcfb808 minor refactor
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-12-23 10:11:59 +08:00
Yuhang Zhao 0924aeb51f linux: finalize x11 function tweaks
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-12-21 11:43:37 +08:00
Yuhang Zhao ea6a070766 linux: fix the regression caused by previous refactoring
Sadly we have to bring back the GTK dependency at compile time.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-12-20 16:39:20 +08:00
Yuhang Zhao ba709ec598 fix linux ci
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-12-20 13:06:13 +08:00
Yuhang Zhao 62527f4f88 minor code tidies
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-12-20 11:59:25 +08:00
Yuhang Zhao 16501e9bd7 fix linux ci, finally
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-12-19 17:59:34 +08:00
Yuhang Zhao 55f67ac707 fix linux ci
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-12-19 17:53:28 +08:00
Yuhang Zhao 4e46ba4fb5 linux: fix build on Qt5
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-12-19 17:49:00 +08:00
Yuhang Zhao 768ab6da4b win: fix the border color, take 2
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-12-19 17:39:36 +08:00
Yuhang Zhao a381836ef7 linux: further improvements
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-12-19 16:37:48 +08:00
Yuhang Zhao 840cf3060d general fixes
fixed some minor issues

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-12-19 11:35:05 +08:00
Yuhang Zhao c3fa2f6920 minor fixes of previous commit 2022-12-16 10:48:38 +08:00
Yuhang Zhao 5b36fe8a81 linux: add missing file
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-12-15 15:56:42 +08:00
Yuhang Zhao 34ba90376b linux: remove the build-time dependency of libxcb and libgtk
We can load them dynamically at run-time.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-12-15 15:48:56 +08:00
Yuhang Zhao 8683a14a3c fix compilation error
fixes: #191

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-12-15 13:09:51 +08:00
1bbb 4844257fc8 支持嵌套无边框组件 2022-12-15 11:32:57 +08:00
Yuhang Zhao d5d1edd690 win: add ms license header
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-12-14 16:23:27 +08:00
Yuhang Zhao 493663a787 win: minor tweaks
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-12-14 16:17:07 +08:00
Yuhang Zhao 45225d11d8 remove needless terminate character
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-12-13 16:31:00 +08:00
Yuhang Zhao b420e67fad cmake: fix warning from Qt 6.5
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-12-13 15:58:49 +08:00
Yuhang Zhao d4293e0a55 win: refactor
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-12-13 11:36:41 +08:00
Yuhang Zhao c849217d43 fix build on linux and macos
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-12-12 14:55:17 +08:00
Yuhang Zhao d04eaabde7 minor tweaks
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-12-12 13:42:18 +08:00
Yuhang Zhao f00adba67c replace QScopedPointer with std::unique_ptr
QScopedPointer is being deprecated in latest qtbase code.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-12-12 11:59:53 +08:00
Yuhang Zhao ed3771c949 replace qRound with std::round
It's better to do so.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-12-12 09:34:46 +08:00
Yuhang Zhao b1f52837d2 replace qAsConst with std::as_const
qAsConst is being deprecated in latest qtbase code.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-12-12 09:30:16 +08:00
Yuhang Zhao e77341d128 win: adjust one version condition
It's decided that the fix will not be cherry-picked to the 6.2 branch.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-12-08 15:36:27 +08:00
Yuhang Zhao 61eb467f94 remove license header from qrc files
They may break compilation.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-12-08 11:37:21 +08:00
Yuhang Zhao 8003f79e17 icon: replace Micon with our own custom one
Because Micon has some license issues.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-12-06 16:53:37 +08:00
Yuhang Zhao 64ef4b25ca fix MSVC warning found by /W4
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-12-06 16:06:13 +08:00
Yuhang Zhao 1e429b363b cmake: minor tweaks
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-12-06 14:35:04 +08:00
Yuhang Zhao 87953f1382 cmake: minor tweaks
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-12-06 11:43:05 +08:00
Yuhang Zhao 3df052de81 cmake: minor tweaks
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-12-06 11:18:34 +08:00
Yuhang Zhao f956c1c002 cmake: minor tweaks
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-12-05 17:12:17 +08:00
Yuhang Zhao cb88b602fe minor tweaks
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-12-05 14:33:38 +08:00
Yuhang Zhao 7e6b629396 ci: minor tweaks
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-12-04 14:53:21 +08:00
Yuhang Zhao 7daa1facc7 fix build on Qt version < 6.2.1
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-12-04 14:49:16 +08:00
Yuhang Zhao 48a1106fc0 Allow build with no private Qt modules
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-12-04 14:25:09 +08:00
Yuhang Zhao d14a0e62d9 bump version
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-11-29 19:51:33 +08:00
Yuhang Zhao 40058a1e79 cmake: allow disable resource bundle
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-11-26 16:44:41 +08:00
Yuhang Zhao 9c08c69a4d bump version to 2.3.4
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-11-24 13:47:29 +08:00
Yuhang Zhao 1cf5a53ecb fix build error
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-11-24 10:47:55 +08:00
Yuhang Zhao a26df61c33 win: fix multi-monitor bug, take 3
#141
#184

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-11-24 10:38:21 +08:00
Yuhang Zhao ff5b171566 win: final fix of the multi-monitor bug
#141
#184

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-11-23 14:54:46 +08:00
Yuhang Zhao ebd3d6573f win: fix the multi monitor window expand issue
#141
#184

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-11-22 15:03:11 +08:00
Yuhang Zhao 3961ecb505 quick: fix a regression
Looks like we can't use overloads in QML documents.

Should fix #183

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-11-21 17:12:33 +08:00
Yuhang Zhao 648876b6b0 win: add a little delay to some operations
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-11-20 12:56:36 +08:00
Yuhang Zhao 04f254556d minor tweaks
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-11-17 10:24:45 +08:00
Yuhang Zhao 3791802d3b win: add support for mica alt and other tweaks
Add some more comments to the windows header.
Remove the usages of UseRoundWindowCorner.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-11-16 14:10:49 +08:00
Yuhang Zhao b09acecac6 try re-trigger ci
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-11-13 13:29:41 +08:00
Yuhang Zhao 2c93d7fe38 some minor tweaks
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-11-13 13:24:30 +08:00
Yuhang Zhao 524f65cc9b win: some minor improvements
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-11-11 15:25:39 +08:00
Yuhang Zhao 766c1e148e linux & macos: add missing code
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-11-11 11:46:44 +08:00
Yuhang Zhao 027780429d win: add more safe guards to dpi hacks
And some other minor improvements.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-11-11 11:38:06 +08:00
Yuhang Zhao ddb2dcc7f7 win: fix some rare bugs, add more comments
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-11-10 16:53:25 +08:00
Yuhang Zhao 70a71822da use better solution to disable logging
Thank very much to @SineStriker !

Fixes: #181

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-11-10 14:15:05 +08:00
Yuhang Zhao b8a3ff604f win: minor tweaks
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-11-10 11:17:29 +08:00
Yuhang Zhao 3842f4e353 win: fix typo
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-11-09 14:43:44 +08:00
Yuhang Zhao c86a3fe35e win: reshuffle code a bit
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-11-09 14:40:03 +08:00
Yuhang Zhao 8c35eb9b70 win: add more dpi hacks & fix some bugs
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-11-09 13:22:58 +08:00
Yuhang Zhao b88ac1591d minor tweak of the logo message
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-11-08 09:36:29 +08:00
Yuhang Zhao 9dc2e0086a fix build, take 3
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-11-06 19:40:23 +08:00
Yuhang Zhao 4463a61834 fix build, take 2
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-11-06 19:37:10 +08:00
Yuhang Zhao e83c00f0cb fix build with qt5
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-11-06 19:33:48 +08:00
Yuhang Zhao 07bd39d1aa win: minor improvement
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-11-06 19:28:25 +08:00
Yuhang Zhao 378f59f462 win: fix a rare bug
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-11-06 16:35:30 +08:00
Yuhang Zhao 32d29e39f6 win: use same code style
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-11-06 16:04:34 +08:00
Yuhang Zhao 2a24f72cea bump version to v2.3.1
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-11-06 15:54:25 +08:00
Yuhang Zhao ac6a2c11a7 win: minor improvement
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-11-06 15:52:25 +08:00
Yuhang Zhao 9715bd9d4b minor tweaks
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-11-03 13:52:57 +08:00
Yuhang Zhao c75712d3f1 Add option to suppress debug messages
Fixes: #177

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-11-02 15:13:47 +08:00
trbogdanov 78638a3e23
call gtk_init() before gtk_settings_get_default() to avoid Q_ASSERT triggering (#173)
As stated in GTK documentation about gtk_init():

* "Call this function before using any other GTK+ functions in your GUI
applications. It will initialize everything needed to operate the toolkit
and parses some standard command line options."

* "It is possible to pass NULL if argv is not available or commandline
handling is not required."

Fixes: #170
2022-10-31 09:39:43 +08:00
Yuhang Zhao 4c88bc5ab2 Fix build error on macOS
Fixes: #174

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-10-29 18:52:39 +08:00
trbogdanov 31849d1c12
gcc and qt-5.12.0 compilation error fix (#171)
Compililation with gcc (any version) and Qt 5.12.0 (important) fails with error:
```
Core/private/sysapiloader_p.h:59:26: error: no matching function for call to ‘QMutex::QMutex()’
     static inline QMutex m_mutex;
                          ^~~~~~~
include/QtCore/qmutex.h:165:5: note: candidate: ‘QMutex::QMutex(const QMutex&)’ <deleted>
     Q_DISABLE_COPY(QMutex)
     ^~~~~~~~~~~~~~
```

`QMutex` in Qt 5.12.0 has explicit (!) one-parameter constructor with a
default value: `QMutex(QMutex::RecursionMode mode = NonRecursive)` and no
default constructor. In this case declaring static inline member without
initializer causes the above error.
2022-10-26 17:13:53 +08:00
Yuhang Zhao 90116239cf win: minor tweaks
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-10-21 09:41:35 +08:00
Yuhang Zhao 53bf6016df win: simplify code a little
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-10-20 17:26:55 +08:00
Yuhang Zhao af6d3c7380 win: minor tweaks
1. Avoid name collision of original Win SDK
2. Enable non-client area DPI scaling when building with Qt < 5.9.0

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-10-20 14:15:11 +08:00
Yuhang Zhao fe6fb8ef5f win: add new win10 subver
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-10-19 17:15:23 +08:00
Yuhang Zhao 3c50ab7714 win: some minor tweaks of the manifest file
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-10-19 16:38:04 +08:00
Yuhang Zhao 439a5d569b fix issues found by ci
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-10-18 17:03:28 +08:00
Yuhang Zhao eb43a60094 cmake: use more strict qt
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-10-18 16:50:29 +08:00
Yuhang Zhao cb7eebcda0 try to fix ci
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-10-18 10:58:25 +08:00
Yuhang Zhao c29e6de2e1 try to fix ci
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-10-18 10:52:04 +08:00
Yuhang Zhao 5ec3eaf88e ci: use ninja, try fix ci
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-10-18 10:28:01 +08:00
Yuhang Zhao fe81fb80bd cmake: fix install error
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-10-18 10:08:43 +08:00
Yuhang Zhao 85366ba667 Revert "misc: use better code style"
This reverts commit 3889e49583.

Reason for revert: breaks CI, and no siginificant improvement.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-10-18 09:22:00 +08:00
Yuhang Zhao 3889e49583 misc: use better code style
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-10-17 18:01:41 +08:00
Yuhang Zhao 6d524d2db7 ci: add more test
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-10-17 16:02:05 +08:00
Yuhang Zhao 1ae0bd8fd6 examples: reuse common code
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-10-17 13:43:38 +08:00
Yuhang Zhao e2f7c76c88 win: minor tweaks
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-10-16 13:41:41 +08:00
Yuhang Zhao ca8e9f555d quick: remove now useless workaround
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-10-14 10:24:46 +08:00
Yuhang Zhao b84b47302e fix mingw build error
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-10-14 09:53:11 +08:00
Yuhang Zhao 6fa183c586 more improvements to ci
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-10-13 19:48:52 +08:00
Yuhang Zhao dacc1e8bf3 more ci improvement
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-10-13 18:02:31 +08:00
Yuhang Zhao 9b45580cb1 ci: also test static builds
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-10-13 16:40:54 +08:00
Yuhang Zhao a25078bc21 add a ci status badge to readme
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-10-13 13:32:10 +08:00
Yuhang Zhao fb863088bc try to fix win ci
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-10-13 13:07:16 +08:00
Yuhang Zhao 8097a30a68 fix macos build
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-10-13 11:55:06 +08:00
Yuhang Zhao 4538e80038 fix msvc ci
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-10-13 11:46:44 +08:00
Yuhang Zhao 2dc7951f7a fix unix build, issue found by ci
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-10-13 11:38:20 +08:00
Yuhang Zhao c3824ecef0 try to fix ci, take 3
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-10-13 11:29:19 +08:00
Yuhang Zhao 8cd57ccc78 fix CI, take 2
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-10-13 11:13:09 +08:00
Yuhang Zhao 5132b7080c fix ci
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-10-13 11:10:35 +08:00
Yuhang Zhao 67ff0b211c add ci
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-10-13 11:00:13 +08:00
Yuhang Zhao 87da6cb5da move static_assert to cpp source files
To speed up compilation time.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-10-13 09:44:50 +08:00
Yuhang Zhao f15ca8daf0 fix various issues
1. Fix mica material doesn't work normally when used on multiple windows.
2. Fix build on Qt5.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-10-12 14:08:58 +08:00
Yuhang Zhao 994b02ad6c quick: add FramelessApplicationWindow element
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-10-12 10:47:41 +08:00
Yuhang Zhao f11a329c1d update readme
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-10-11 20:11:37 +08:00
Yuhang Zhao 15490cae5f update screenshots
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-10-11 19:55:24 +08:00
Yuhang Zhao b9f5cf79c0 win32: add support for dark theme menu
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-10-11 16:17:04 +08:00
Yuhang Zhao fcf51d6d73 refactor
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-10-11 11:52:49 +08:00
Yuhang Zhao 1e43ba2e81 improve windowborder element
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-10-10 22:12:01 +08:00
Yuhang Zhao 1fc23e1c6a cmake: minor tweaks
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-10-10 15:13:18 +08:00
Yuhang Zhao 55be173c31 minor tweaks
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-10-10 13:59:00 +08:00
Yuhang Zhao 92415fb61c Add WindowBorderPainter and WindowBorder
1. Added WindowBorderPainter for QtWidgets
2. Added WindowBorder for QtQuick (uses WindowBorderPainter internally)
3. Adjust some header includes
4. Limit a Linux workaround to the appropriate Qt versions

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-10-10 13:35:37 +08:00
Yuhang Zhao 9f17c8afdd demo: disable lazy initialization for mica material
we need it anyway.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-10-09 10:15:48 +08:00
Yuhang Zhao b50a2dcd72 fix Qt5 compilation error
And change to lazy initialization for Mica Material.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-10-09 10:08:49 +08:00
Yuhang Zhao f6e9bd895c Commit missing file
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-10-08 16:15:23 +08:00
Yuhang Zhao d483c39b9a add way to disable window maximization
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-10-08 15:25:22 +08:00
Yuhang Zhao e77a2db663 Revert "fix multiple issues found by user"
This reverts commit c0ce7b0f48.

Reason for revert: the fix is totally wrong, as it's trying
to fix a bug which never exists, what's worse, the wrong fix
itself is also causing critical regressions. so revert it immediately.

But the QMake modifications are correct and necessary, so don't
revert that part.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-10-04 08:55:25 +08:00
Yuhang Zhao c0ce7b0f48 fix multiple issues found by user
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-10-02 20:17:52 +08:00
Yuhang Zhao ac9a05209e quick: fix misleading and annoying warning
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-09-30 12:58:13 +08:00
Yuhang Zhao cb107b127a win: add one more workaround of Qt bug
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-09-29 15:01:59 +08:00
Yuhang Zhao d1a410b498 cmake: avoid possible issue
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-09-28 11:28:54 +08:00
Yuhang Zhao 57a4d8875c cmake: improve the build scripts
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-09-27 21:13:46 +08:00
Yuhang Zhao 07101273bd win: refactor & simplify
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-09-26 11:18:13 +08:00
Yuhang Zhao f97f000cc7 avoid potential deadlocks
And some other minor tweaks.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-09-25 10:35:00 +08:00
Yuhang Zhao c914992aa4 adapt to latest qtbase
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-09-24 17:57:38 +08:00
Yuhang Zhao 95449f140f tool: update code
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-09-23 14:24:55 +08:00
Yuhang Zhao 684ebc3fa3 minor improvement
Code simplification & adapt to latest Qt code.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-09-23 14:04:47 +08:00
Yuhang Zhao eeda750a61 finalize api update
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-09-21 13:22:03 +08:00
Yuhang Zhao ee2a9e6b19 update readme
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-09-20 17:49:15 +08:00
Yuhang Zhao 81ec19d2aa remove unsafe compile params
Not sure whether MinGW supports it or not.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-09-20 17:39:24 +08:00
Yuhang Zhao 47bf4da5ae allow user to remove a window from the frameless window list
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-09-20 15:56:59 +08:00
Yuhang Zhao 3d3607af7b refactor
and maybe avoid potential bugs.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-09-16 17:38:13 +08:00
Yuhang Zhao 91bb8273b8 routine code quality improvement
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-09-15 18:24:34 +08:00
Yuhang Zhao 31eed109a0 update readme
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-09-14 17:19:20 +08:00
Yuhang Zhao 47dcb8f032 quick: emulate Windows behavior more, just like widget
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-09-14 17:07:06 +08:00
Yuhang Zhao 1b36587f14 widgets: emulate Windows behavior more
On Windows, when you left click the window icon in the title bar, the system menu will be triggered.
And when you double click it, the window will be closed.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-09-14 13:30:08 +08:00
Yuhang Zhao 8667d1996e cmake: add some experimental flags, but commented out
Uncomment out if they are verified to work well.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-09-13 20:02:02 +08:00
Yuhang Zhao 0ceb0e85c1 win: remove one confusing assert
It works well for msvc but it also confuses a lot of people, so let's remove it.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-09-13 17:46:23 +08:00
Yuhang Zhao 221f1c12aa fix button size can't be changed
widget: fix the bug
quick: add the interface to change size

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-09-13 17:38:10 +08:00
Yuhang Zhao 119d10930b win: minor tweaks
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-09-13 11:02:53 +08:00
Yuhang Zhao 55fe04000e add more comments
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-09-11 10:43:48 +08:00
Jan Kowalewicz 6a46844853
win: Qt version check for #155 (#157) 2022-09-11 10:23:01 +08:00
Yuhang Zhao 9cf8ba959d mac: fix build 2022-09-10 17:56:39 +08:00
Jan Kowalewicz f2affbca85
win: fix build with Qt 5.14 and MinGW (#155) 2022-09-10 16:38:40 +08:00
Yuhang Zhao 33c3eaa05a win: add missing definitions for mingw
Fixes: #153
Fixes: #154

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-09-10 16:04:17 +08:00
Yuhang Zhao 34596db939 fix various issues found by user
Issue list:

1. MinGW lacks some definitions so there's compilation errors
2. The chrome buttons' foreground color is incorrect when the window is inactive.
3. Adapt to new macros from Qt dev branch.
4. Remove unneeded parameter from setApplicationOSThemeAware().

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-09-10 13:11:55 +08:00
Yuhang Zhao 6fe35a667e cmake: fix build error
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-09-07 13:44:08 +08:00
Yuhang Zhao 5d494453bc update readme
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-09-06 13:48:52 +08:00
Yuhang Zhao 7dda58deaf free all resources during destruction
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-09-06 13:40:16 +08:00
Yuhang Zhao fb13ff1c1b improve macos experience [2/2]
Add support for old Qt version and old macOS version.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-09-06 11:31:07 +08:00
Yuhang Zhao 2411343f42 update readme
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-09-05 17:35:02 +08:00
Yuhang Zhao f2a6d35908 improve macos code [1/2]
1. Simplify code a little
2. Use Qt functionalities as many as possible.
3. Prepare for adding old Qt support.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-09-05 16:55:55 +08:00
Yuhang Zhao b9f65aa783 add frameless dialog & demo
And some other minor fixes.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-09-05 15:00:02 +08:00
Yuhang Zhao 5018d9ea82 widget: add support for changing title font
Not needed for Qt Quick, because you can easily to change it:

```qml
StandardTitleBar {
    titleLabel {
        font {
            family: "Arial"
            pointSize: 10
            italic: true
        }
    }
}
```

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-09-02 10:39:45 +08:00
Yuhang Zhao f052a087de bump version to v2.2.1
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-09-01 16:47:49 +08:00
Yuhang Zhao ba343fbbd4 win: fix bug when using Qt 5.14 and below
Fixes: #152

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-09-01 16:45:32 +08:00
Yuhang Zhao 6b1a37a82a win: fix null pointer access in some rare cases
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-09-01 10:51:50 +08:00
Yuhang Zhao 012721d9a0 demo: add missing definition
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-08-31 16:47:40 +08:00
Yuhang Zhao 7a35b09a74 add limited qmake support
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-08-31 16:34:30 +08:00
Yuhang Zhao abf4b29dca minor fixes of the last commit
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-08-31 10:45:26 +08:00
Yuhang Zhao 463ac0a999 add window icon support
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-08-31 10:21:24 +08:00
Yuhang Zhao e55afa2fe3 simplify a function
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-08-28 20:08:44 +08:00
Yuhang Zhao ce78c037b1 add some helper functionalities
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-08-28 19:25:22 +08:00
Yuhang Zhao 5195a27022 linux: adapt to latest qtbase changes
The X11 QPA has gained the ability to detect runtime theme changes in Qt 6.4.0

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-08-27 13:07:01 +08:00
Yuhang Zhao c3338cd9b7 win: don't use round corner when fullscreen on win11
Fixes: #149

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-08-26 15:54:56 +08:00
Yuhang Zhao 406c801383 Remove unneeded function
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-08-25 11:16:50 +08:00
Yuhang Zhao de3d5440db simplify code a little
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-08-22 18:02:03 +08:00
Yuhang Zhao f484209b94 win: fix round error on some systems
Fixes: #146

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-08-22 13:57:21 +08:00
Yuhang Zhao 6ddf79ba9c demo: fix build on qt5
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-08-22 13:00:33 +08:00
Yuhang Zhao 6c060b3946 demo: add shortcut to switch between fullscreen state
Can also help use better debugging the old style window frame
issue on Windows.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-08-21 15:38:43 +08:00
Yuhang Zhao 1bce57445b win: use qt own functions more
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-08-19 10:53:46 +08:00
Yuhang Zhao a49756ee45 registrykey: rename
RegistryKey is a better name than Registry.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-08-17 10:42:48 +08:00
Yuhang Zhao 0535276f55 win: use Qt functionalities as much as possible
If Qt provides the functionalities we need, use it
instead of reinventing the wheel.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-08-16 15:24:14 +08:00
Yuhang Zhao 3dbeb2721a minor tweaks
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-08-06 12:01:12 +08:00
Yuhang Zhao 08a38f1d73 update ignore list
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-08-04 14:32:45 +08:00
Yuhang Zhao beb16bfdc2 linux: minor improvement
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-08-04 10:32:32 +08:00
Yuhang Zhao 2f872732b5 tool: minor tweaks
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-08-03 17:53:17 +08:00
Yuhang Zhao 9343c7a088 macos: remove needless version check
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-08-03 09:41:29 +08:00
Yuhang Zhao f4f56498c2 win32: minor improvement
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-07-30 17:26:27 +08:00
Yuhang Zhao 775b1a2aab minor tweaks
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-07-30 11:34:14 +08:00
Yuhang Zhao cf83b050d2 common: minor tweaks
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-07-29 15:36:28 +08:00
Yuhang Zhao 4fe67c9313 cmake: minor improvements
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-07-27 09:36:28 +08:00
Yuhang Zhao 14a3440bbf win32: fix typo
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-07-25 09:35:02 +08:00
Yuhang Zhao 1264fe8341 minor tweaks
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-07-24 14:54:55 +08:00
Yuhang Zhao b2f443a592 cmake: minor tweaks of msvc flags
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-07-21 13:57:13 +08:00
Yuhang Zhao 0aea6c3658 tool: update the dpitester tool
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-07-19 14:23:41 +08:00
Yuhang Zhao 2fb842e4a9 minor tweaks of the dpitester tool
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-07-18 18:02:15 +08:00
Yuhang Zhao 56499c7028 fix the widget demo
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-07-18 15:16:06 +08:00
Yuhang Zhao dd4acb6686 add the dpitester tool, msvc only
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-07-18 14:20:42 +08:00
Yuhang Zhao 7616161699 Implement homemade Mica material & other improvements
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-07-16 15:25:15 +08:00
Yuhang Zhao 7f9f2c8543 adapt to latest qt change
And install some missing files

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-07-13 10:40:29 +08:00
Yuhang Zhao 5e863ee661 cmake: fix include dir for package
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-07-12 14:58:20 +08:00
Yuhang Zhao b9d187d5f1 icon font: logic minor improvement
No need to bundle the Segoe icon font file,
the OS will always have them installed.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-07-12 14:00:49 +08:00
Yuhang Zhao b8fee2e732 support use different icon font based on current platform
And some other minor tweaks

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-07-11 10:55:05 +08:00
Yuhang Zhao 4f8106a009 minor tweaks
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-07-10 14:26:01 +08:00
Yuhang Zhao 2f36d1f73e blur behind window: add macos implementation
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-07-09 14:59:47 +08:00
Yuhang Zhao 7e3a735a7d minor tweaks and improvements
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-07-09 12:10:41 +08:00
Yuhang Zhao 2a113ee8ab Allow build as a CMake package, support the install command
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-07-08 13:47:50 +08:00
Yuhang Zhao 9a93475f2b fix typo: snap layouts --> snap layout
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-07-07 17:00:15 +08:00
Yuhang Zhao 011b4a85f5 fix Qt5 build
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-07-07 16:22:34 +08:00
Yuhang Zhao 389c8ad6d6 examples: add convenient script to deploy qt libraries
Currently only functional on Windows. macOS and Linux to do.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-07-07 15:34:31 +08:00
Yuhang Zhao 2806cc811b code simplification, minor re-structure
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-07-07 13:43:09 +08:00
VerySimple b413d0b1e6
修改了几个地方 (#139)
* merge 3 commits

modify a few lines

Update framelesshelper_windows.h

* improve syntax
2022-07-07 10:26:14 +08:00
Yuhang Zhao 01828e086f quick blur demo: fix typo
And minor improvements to the win32 utils code.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-07-06 18:01:24 +08:00
Yuhang Zhao 464e2af515 finish the chrome palette implementation
And with some other minor tweaks that improve user experience.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-07-06 14:24:41 +08:00
Yuhang Zhao e8dcb6e6fe add api to set title bar and chrome button color
TODO:
1. Special handling for the close button
2. Move QuickChromePalette class to own files
3. More testing

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-07-05 17:58:04 +08:00
Yuhang Zhao aed1673855 win32: remove the limit to the manifest file
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-07-05 10:36:34 +08:00
Yuhang Zhao df5ff50c7f win32: minor improvement
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-07-04 18:05:04 +08:00
Yuhang Zhao 3737b4d6fe update README.md
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-07-04 13:27:42 +08:00
Yuhang Zhao cbf34ea0ec win32: try to fix bug
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-07-04 13:03:23 +08:00
Yuhang Zhao 71f8a5aab1 add blurBehindWindowEnabled property
Current only implements for Windows,
macOS will be implemented later,
Linux won't be supported in the near future.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-07-03 16:01:19 +08:00
Yuhang Zhao f90b49538a add support for qmltc tool
Also remove one useless enum.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-07-01 15:52:28 +08:00
Yuhang Zhao 5b852b3d6c update README.md
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-06-30 11:24:48 +08:00
Yuhang Zhao 66250dbb6e cmake: minor tweaks
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-06-27 14:15:34 +08:00
Yuhang Zhao 6683a183d7 cmake: a little simplification
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-06-27 10:00:23 +08:00
Yuhang Zhao 7b769a71a0 minor tweaks
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-06-26 14:57:18 +08:00
Yuhang Zhao a89f19af96 2.1.7 release
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-06-25 19:38:41 +08:00
Yuhang Zhao 75f19218c6 minor tweaks
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-06-24 21:38:26 +08:00
Yuhang Zhao ffa9bc912b update README.md
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-06-24 20:39:09 +08:00
Yuhang Zhao 888f9d0aca standardsystembutton: use icon font instead of svg images
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-06-24 18:04:49 +08:00
Yuhang Zhao bfc7b27900 macos: minor improvements
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-06-23 16:43:22 +08:00
Yuhang Zhao 7a65ce04ee win32: remove ATL dependency
Fixes: #136

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-06-20 17:14:16 +08:00
Yuhang Zhao 9cbfe495b7 win32: fix crash in rare cases
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-06-07 10:43:26 +08:00
Yuhang Zhao a04fd53a38 general improvements
1. replace raw char array with QByteArray
2. Register QWindow for Quick module
3. Account for hidden and disable state when hovering controls
4. fix quick title bar label alignment

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-06-01 11:16:34 +08:00
Yuhang Zhao 0cff5ff48e add "hideWhenClose" property
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-05-23 21:09:09 +08:00
Yuhang Zhao 093040ec93 make windowFixedSize a Qt property
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-05-23 15:17:34 +08:00
Yuhang Zhao 6fe3dd1088 cmake: minor tweaks
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-05-23 14:46:20 +08:00
Yuhang Zhao ca1c33ac23 win32 demos: minor tweaks
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-05-23 09:58:39 +08:00
Yuhang Zhao 5754f2ec20 common: improve robustness
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-05-20 17:36:44 +08:00
Yuhang Zhao 44b3730056 quick: remove not used code
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-05-19 10:23:18 +08:00
Yuhang Zhao 6731007e35 quick: make sure top border stays on top
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-05-18 18:00:56 +08:00
Yuhang Zhao 06653433d7 win32: a little fix
Amends commit 8f31e67dae

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-05-18 09:34:00 +08:00
Yuhang Zhao 8f31e67dae win32: remove useless error checking
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-05-18 09:24:25 +08:00
Yuhang Zhao e162345c62 update readme
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-05-17 13:50:00 +08:00
Yuhang Zhao 7313ed0f99 update readme
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-05-17 13:41:32 +08:00
Yuhang Zhao ff1605ee7b win32: fix crash caused by "isWindowFixedSize()"
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-05-16 10:09:23 +08:00
Yuhang Zhao 45be647baf win32: fix another issue related to hit test
This issue was hidden due to it's actually not executed.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-05-15 15:51:09 +08:00
Yuhang Zhao c2c6ef1976 win32: fix controls in the title bar area can't be hovered
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-05-15 14:29:21 +08:00
Yuhang Zhao 3a0e6f081f titlebar: allow use alternative background
Set this property to true if you want to use your own background color/pixmap
instead of system's current accent color.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-05-15 11:46:27 +08:00
Yuhang Zhao 1cd39fd7b2 quick: a little code simplification
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-05-14 10:02:42 +08:00
Yuhang Zhao 45b3657d7e minor tweaks
Doesn't seem to affect the final appearance

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-05-13 20:51:03 +08:00
Yuhang Zhao d13d74783f quick: simplify implementation
1. Merge the three system buttons into one class.
2. Fixed some color calculation errors of system button.
3. Removed some not used bundled resources.
4. Added function to retrieve runtime version of FramelessHelper.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-05-13 17:33:01 +08:00
Yuhang Zhao 8042a78b8f various fixes and improvements
1. Make all demo applications be able to record and restore the previous window geometry.
2. Improve the robustness of the widgets and quick implementation.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-05-13 14:19:50 +08:00
Julien 915e775d94
FIX: crash in isFixedSize when calling destructors (#131)
Fixes: #130

Co-authored-by: Julien Maille <julien.maille@data-pixel.com>
2022-05-13 11:05:11 +08:00
Yuhang Zhao 1a3d1c82a1 update readme
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-05-12 17:50:38 +08:00
Yuhang Zhao 1db02751d7 update readme
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-05-12 17:39:53 +08:00
Yuhang Zhao 5c3b8b70df general: fix the system button background color in various cases
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-05-12 17:25:10 +08:00
Yuhang Zhao 8cb24c61b3 general improvements
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-05-12 15:07:57 +08:00
Yuhang Zhao bebd20f01e win32: finish the fixed size fix
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-05-11 21:18:25 +08:00
Yuhang Zhao ab20f3433b remove useless code
And that also fixes the bug for Qt Quick applications

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-05-11 20:24:29 +08:00
Yuhang Zhao a1acc3e06f common: minor tweaks
Code simplification, format changes, etc ...

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-05-11 17:32:14 +08:00
Yuhang Zhao aad6957a52 win32: fix fixed size behavior
The code was from 2.0 and due to we changed solution in 2.1,
it needs to be tweaked accordingly but was forgotten.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-05-11 11:04:03 +08:00
Yuhang Zhao 059013a338 update readme
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-05-09 14:32:21 +08:00
Yuhang Zhao ecef5bb9fd fix wrong discord link
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-05-09 11:51:09 +08:00
Yuhang Zhao 54496f9fe0 lower warning level for msvc
Bug reports from users indicate that /W4 causes many
warnings for MSVC 2019 and the warnings come from
private Qt headers so no way to fix them in FramelessHelper.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-05-09 11:39:15 +08:00
Yuhang Zhao 66d77112ed win32: fix possible crash in some very rare cases
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-05-08 21:50:08 +08:00
Yuhang Zhao a10ac4e32d demos: simplify some code
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-05-08 18:24:09 +08:00
Yuhang Zhao c853cc63c6 re-fix wrong parameter for xcb
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-05-08 16:42:55 +08:00
Yuhang Zhao 053d6b104e centralize how we handle global options
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-05-08 16:09:00 +08:00
Yuhang Zhao 286811c9df expose private headers, someone may need
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-05-07 18:02:44 +08:00
Yuhang Zhao c936a7da80 minor tweaks
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-05-06 21:00:07 +08:00
Yuhang Zhao 2135d2f15f update docs
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-05-06 17:59:53 +08:00
Yuhang Zhao 196aeb1ce1 linux: minor fixes of the xcb usage
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-05-06 16:32:59 +08:00
Yuhang Zhao 4b136295a8 update docs
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-05-06 10:36:35 +08:00
Yuhang Zhao e7f434c5a4 demo: center window on first show
Looks better than before.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-05-05 20:23:35 +08:00
Yuhang Zhao 1c6e02d81b code tidies, prepare for the 2.1 release
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-05-05 18:02:38 +08:00
Yuhang Zhao cfb0842726 win: make sure we can still compile this project using some old windows sdks
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-05-04 17:09:30 +08:00
Yuhang Zhao 9d71baffd1 remove the last piece of Qt internal classes
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-05-04 16:08:47 +08:00
Yuhang Zhao a97b1782ae redesign the title bar interface
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-05-04 14:50:11 +08:00
Yuhang Zhao 8ccbe2cf94 file rename, step 2
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-05-03 19:06:30 +08:00
Yuhang Zhao 6977db1e02 file rename, step 1
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-05-03 19:05:53 +08:00
Yuhang Zhao 81e736570f refactor widgets interface
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-05-03 19:02:39 +08:00
Yuhang Zhao 306ebfc717 Refactor the Quick implementation, interface is now simpler
Now we use attached properties instead, it make things simpler.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-05-02 12:26:57 +08:00
Yuhang Zhao d6fa6a163e quick: fix build on Qt5
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-04-30 13:30:30 +08:00
Yuhang Zhao ff8252aaf4 Add initial snap layout implementation
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-04-30 12:47:51 +08:00
Yuhang Zhao fbe241f29e internal refactor
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-04-29 18:03:39 +08:00
Yuhang Zhao 16b7841bac update roadmap
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-04-29 10:36:50 +08:00
Yuhang Zhao 2f629a9e5b Quick: make the titleBarItem become a property
By making it a Q_PROPERTY we can use it more conveniently.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-04-25 14:50:41 +08:00
Yuhang Zhao fd2b3f5e84 Linux: fix mouse release event not being sent due to wrong parameter
Also simplifies a little Windows implementation.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-04-25 13:48:19 +08:00
Yuhang Zhao 3d7576e062 macOS: remove the system buttons, fix implementation
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-04-24 21:03:46 +08:00
Yuhang Zhao 3c0209c979 Linux: fix the mouse grab issue, for real
Port previous workaround from 1.x to 2.0

And some minor tweaks.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-04-24 13:37:10 +08:00
Yuhang Zhao 2915d1f33a Widgets: move FramelessWidgetsHelper to source directory
It's pure implementation detail, so should not be publicly visible

Also fixed the crash of the QOpenGLWidget demo application.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-04-24 11:33:05 +08:00
Yuhang Zhao a0a9b8d108 Final code of version 2.0.0!
Some minor issues are known to exist and they'll get fixed before 2.1 is officially released.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-04-23 14:59:27 +08:00
Yuhang Zhao 8460995d7f quick module: minor improvements
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-04-22 15:49:00 +08:00
Yuhang Zhao 201f54e7a5 widgets module: fix two issues
1. The top border has a one pixel gap under some circumstances, fixed
2. The zoomed property didn't get notified correctly sometimes, fixed

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-04-22 12:57:00 +08:00
Yuhang Zhao 3f17626c64 misc: minor tweaks
1. Finish the simple title bar of the QOpenGLWidget demo
2. Minor improvements of the Quick implementation

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-04-22 12:04:38 +08:00
Yuhang Zhao 130d174dc2 misc: improve old Qt version support
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-04-21 21:13:16 +08:00
Yuhang Zhao 701d8d0927 fix build on 5.12 & add initial opengl demo
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-04-21 15:10:16 +08:00
Yuhang Zhao cf4e4c331b macos: verify functionality
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-04-20 16:31:30 +08:00
Yuhang Zhao f2faf5dac3 linux: minor improvements
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-04-20 15:26:25 +08:00
Yuhang Zhao b5eebada2c minor general improvement
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-04-20 13:09:11 +08:00
Yuhang Zhao b6e86f90e6 macos: fix build
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-04-19 17:13:07 +08:00
Yuhang Zhao d86e9144a2 general improvement
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-04-19 17:01:07 +08:00
Yuhang Zhao 68296cc1ae linux: update the implementation based on previous commit
When implementing macOS functionalities, some functions changed signature, update accordingly.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-04-18 19:11:23 +08:00
Yuhang Zhao 976b2463d7 win32: update changes from previous commit
Some functions changed signature, update accordingly.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-04-18 17:33:41 +08:00
Yuhang Zhao 5173fb51af macos: add initial implementation
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-04-18 16:56:58 +08:00
Yuhang Zhao dee635c0b9 misc: minor improvements
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-04-17 21:09:24 +08:00
Yuhang Zhao bb42c69d36 linux: minor improvements
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-04-17 18:30:16 +08:00
Yuhang Zhao 45ebbee471 misc: minor format changes
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-04-17 17:29:22 +08:00
Yuhang Zhao 079c8ff6b6 misc: minor tweaks
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-04-17 09:03:11 +08:00
Yuhang Zhao 537b65e592 update roadmap
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-04-16 16:57:03 +08:00
Yuhang Zhao 2c0ec868ab finish the linux implementation
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-04-16 16:55:51 +08:00
Yuhang Zhao 859912ae25 misc: minor tweaks
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-04-16 10:09:51 +08:00
Yuhang Zhao cd05b6ecdf quick: finish qml -> cpp migrating
Convert all qml files to pure c++ implementation.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-04-16 09:52:38 +08:00
Yuhang Zhao 4f5044a58c wip: quick: start migrating to modern usage
Still wip, but doesn't left much.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-04-14 17:33:09 +08:00
Yuhang Zhao d353c81c5e misc: minor tweaks
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-04-14 10:22:57 +08:00
Yuhang Zhao a57011bd11 win32: half implementation of max btn docking
Now the problem is how to send mouse click events to our system buttons

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-04-09 12:53:55 +08:00
Yuhang Zhao c940bd5ce7 try to enable the win11 docking feature, but failed
It's really a headache. Maybe need to try another solution.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-04-07 15:51:58 +08:00
Yuhang Zhao 1839c968db finish the implementation of StandardSystemButton
Convenient button widget to emulate the standard system button

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-04-07 10:17:16 +08:00
Yuhang Zhao 4eac2b2970 implement TransparentWindowBackground option
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-04-06 13:15:29 +08:00
Yuhang Zhao e19dad5b82 some wip code
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-04-05 19:54:43 +08:00
Yuhang Zhao b5d2ae5888 quick: improve the standard titlebar's appearance
And some minor tweaks to the initialize() function.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-04-02 17:56:45 +08:00
Yuhang Zhao f0846596ff minor tweaks of readme
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-04-02 13:13:40 +08:00
Yuhang Zhao d4bacdcab6 quick: fix running on qt5
Previously Qt5 can't recognize the Anchor enum, it's fixed now.
Also rename framelesshelper_quick to framelessquickhelper, the
former name was to avoid conflict with an already removed class.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-04-02 13:07:26 +08:00
Yuhang Zhao 3a466492c2 win32: fix 32bit compilation failure, for real
I misunderstands the 32bit build failure in the previous
commit. The fix in the last commit didn't fix anything
but break the compilation on 32bit platforms.

Fixes: #109

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-04-02 09:56:32 +08:00
Yuhang Zhao eb1c6f4a62 win32: minor improvements
1. Fix build on 32bit platforms: the "Ptr" suffixed APIs not available on 32bit platforms
2. Reduce the confusion caused by the original "UseStandardWindowLayout" option
3. Minor tweaks of the quick implementation

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-04-01 20:06:48 +08:00
Yuhang Zhao be09197784 win32: fix the d2d crash on win7
The function signature was wrong so it crashed.
Now it won't crash anymore.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-04-01 15:46:52 +08:00
Yuhang Zhao 5c7434ea35 misc: refactor, take 2
add byte array literals handling

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-04-01 15:18:44 +08:00
Yuhang Zhao bde9c85cd9 cmake: add license headers
add some more license headers

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-04-01 14:36:36 +08:00
Yuhang Zhao 8bc08ab32f quick example: add some comments
explain some more

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-04-01 14:22:45 +08:00
Yuhang Zhao 6166422e37 misc: internal refactor
centralize how we handle string literals.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-04-01 14:09:14 +08:00
Yuhang Zhao 3525dfee58 win32: nitpck: don't highlight the first entry of the system menu if brought by mouse
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-31 15:59:49 +08:00
Yuhang Zhao 92ab78e281 win32: nitpick
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-31 10:59:26 +08:00
Yuhang Zhao f13238312b win32: fix dark mode detection
global dark mode was first introduced in Win10 1607, not 1809
1809 was the first version that file explorer supported dark mode
really sorry for the wrong information

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-30 14:15:12 +08:00
Yuhang Zhao 3104fd07d2 update roadmap
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-30 13:31:59 +08:00
Yuhang Zhao 90ad8d281a little simplify
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-30 13:16:19 +08:00
Julien 4af48d84b9
Fix "out of boundaries" line drawing (#106)
drawLine on [0, w-1]
2022-03-30 09:32:19 +08:00
Julien 06c23aaba5
FIX #92 do not call startSystemMove2 in MousePressEvent (#105)
* FIX #92 do not call startSystemMove2 in MousePressEvent

* Add same fix for QtQuick

Co-authored-by: Julien Maille <julien.maille@data-pixel.com>
2022-03-29 15:38:20 +08:00
Yuhang Zhao c49b971983 internal refactoring
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-29 13:34:05 +08:00
Yuhang Zhao d4e711d679 win implementation is mostly settled now
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-26 15:31:16 +08:00
Yuhang Zhao 389a342a81 update readme
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-25 16:16:03 +08:00
Yuhang Zhao 533bbeac82 wip - QtQuick impl on win mostly done
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-25 15:44:59 +08:00
Yuhang Zhao fd3b815924 wip
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-24 16:37:37 +08:00
Yuhang Zhao 6ffc894213 wip
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-23 16:38:14 +08:00
Yuhang Zhao 059b8d7982 wip
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-23 10:59:24 +08:00
Yuhang Zhao d94f8221d3 wip
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-23 10:48:22 +08:00
Yuhang Zhao d3157699ef wip
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-22 17:14:03 +08:00
Yuhang Zhao 5ecc06df2f wip
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-22 15:03:22 +08:00
Yuhang Zhao 6a43ef39f8 wip
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-22 11:56:05 +08:00
Yuhang Zhao f30d7a0f57 wip
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-22 10:50:47 +08:00
Yuhang Zhao a2622616a2 wip
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-21 16:58:56 +08:00
Yuhang Zhao 1ed6e2fb01 wip
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-21 16:53:18 +08:00
Yuhang Zhao 0e75f12089 wip
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-21 15:18:42 +08:00
Yuhang Zhao 2191d9ad77 wip
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-21 15:03:06 +08:00
Yuhang Zhao 56f2638363 adjust the project structure again
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-21 14:28:52 +08:00
Yuhang Zhao ebd69353a0 wip
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-21 13:52:10 +08:00
Yuhang Zhao 6676a3c1f9 wip
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-21 13:08:27 +08:00
Yuhang Zhao 12988f2ddf add the Options feature to control some details
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-20 15:51:05 +08:00
Yuhang Zhao 09acbfaf02 adjust the project file architecture
to make it more like a modern library project

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-20 12:30:00 +08:00
Yuhang Zhao 8ccd39ac9b fix build with qt5
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-19 15:35:23 +08:00
Yuhang Zhao b1f0e38fc8 wip
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-19 15:23:18 +08:00
Yuhang Zhao 79ea80ea74 wip
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-19 13:38:11 +08:00
Yuhang Zhao 4d277a5eac wip
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-18 18:09:20 +08:00
Yuhang Zhao ebc20e23b6 wip
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-17 18:05:03 +08:00
Yuhang Zhao f700b07e5c wip
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-17 16:48:57 +08:00
Yuhang Zhao 7d22263df0 wip
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-17 11:58:19 +08:00
Yuhang Zhao b9b6f25dea wip
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-16 18:05:53 +08:00
Yuhang Zhao 1aa92e3db4 wip
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-16 16:19:24 +08:00
Yuhang Zhao 2180568efc wip
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-16 10:32:53 +08:00
Yuhang Zhao d6fe3fd8bd wip
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-16 10:12:12 +08:00
Yuhang Zhao 7694a10e87 wip
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-15 18:04:05 +08:00
Yuhang Zhao 6bbbc0a145 wip
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-15 17:41:16 +08:00
Yuhang Zhao 942fd02b66 wip
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-15 17:29:00 +08:00
Yuhang Zhao fde00ab7ea wip
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-15 16:57:16 +08:00
Yuhang Zhao 578458f35d wip
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-15 14:21:15 +08:00
Yuhang Zhao d46ec0c1b6 wip
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-15 13:02:59 +08:00
Yuhang Zhao f68665298b wip
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-14 20:59:38 +08:00
Yuhang Zhao 2dbdca2999 wip
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-14 18:05:02 +08:00
Yuhang Zhao a06b4b82b8 wip
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-14 17:33:05 +08:00
Yuhang Zhao c0b403f7b3 wip
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-14 16:38:19 +08:00
Yuhang Zhao b9cb70b3ac wip
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-14 15:36:12 +08:00
Yuhang Zhao bb8d174c56 wip
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-14 15:26:49 +08:00
Yuhang Zhao efb56c712c wip
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-13 15:48:07 +08:00
Yuhang Zhao 3216defd59 wip
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-13 15:36:18 +08:00
Yuhang Zhao 2073cb9fd2 wip
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-13 15:17:27 +08:00
Yuhang Zhao 556741cfb1 wip
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-13 12:14:08 +08:00
Yuhang Zhao d0e19a2b1e wip
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-12 16:58:58 +08:00
Yuhang Zhao 2881874d7a wip
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-12 15:53:50 +08:00
Yuhang Zhao 01ad24aae1 wip
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-11 21:57:24 +08:00
Yuhang Zhao 0ce352ff22 wip
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-11 17:59:53 +08:00
Yuhang Zhao ae65733b2d wip
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-11 17:23:31 +08:00
Yuhang Zhao 0e4f95fe2c wip
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-11 16:23:12 +08:00
Yuhang Zhao 8e69a57039 wip
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-11 09:33:27 +08:00
Yuhang Zhao 3b171b3ea9 fix build on unix platforms
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-11 09:22:44 +08:00
Yuhang Zhao affba58e25 win32: add more comments
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-10 18:07:35 +08:00
Yuhang Zhao bbd20b6476 win32: minor improvements
1. Adds some more comments
2. Fixed a typo in QMainWindow example
3. Commented out a block of code that may cause issues
4. Return WVR_REDRAW by default in WM_NCCALCSIZE
5. Other minor tweaks

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-09 10:21:52 +08:00
Yuhang Zhao 39ec7efcf3 win32: minor refactor
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-07 11:45:54 +08:00
Yuhang Zhao 04f31f7b42 Win32: update the internal margin when DPI changes
Make the internal margin sync with the latest DPI.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-03-07 10:26:16 +08:00
Yuhang Zhao 824b0746c1 Win32: remove unnecessary code
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-02-21 11:05:00 +08:00
Yuhang Zhao a9256ba4b3 QtQuick demo: work-around a QtQuick bug
See https://bugreports.qt.io/browse/QTBUG-69711
Also some minor tweaks of the constexpr variables.

Fixes: #35

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-02-10 10:14:54 +08:00
Yuhang Zhao ebe7da1a9f Win32: use Win32 APIs instead of Qt APIs
Our native event filter happens before QPA's internal
handling, so the window state won't change if we query
for them in the native event filter. To fix this, use
Win32 API instead.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-01-20 13:16:45 +08:00
Yuhang Zhao e0c00bce35 Example improvements
Try to fix the frame border issue on high dpi monitors.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-01-10 10:07:26 +08:00
Yuhang Zhao 485d9665ea Fix build on Qt versions below 5.14
QStringView introduced in Qt 5.10.0
qExchange() introduced in Qt 5.14.0
qSwap() is deprecated, use std::swap() instead

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-01-07 13:15:46 +08:00
Yuhang Zhao e85e3f891e Example: special case for Win11
1. On Win11 we don't need to paint the frame border, the OS will always draw one for us.
2. Fix the wrong coordinate of the right and bottom frame border of the widget example.
3. Improve the Qt Quick example.
4. Correctly detect the OS version when building against Qt below 5.9.
5. Other minor tweaks.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-01-07 11:10:28 +08:00
Yuhang Zhao 7ddde978e8 Fix compilation on sdks lack "timeapi.h"
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-01-06 17:40:58 +08:00
Yuhang Zhao e3adb917a6 Fix build on Qt before 5.14
1. The QWinRegistryKey class was introduced in 5.14.0. The implementation is quite clean, so just copy the sources files from Qt repo in case the user is linking against a version older than 5.14.
2. Fixes the rounding error of the self-painted frame border of the examples.
3. Other minor tweaks.

Fixes: #95
Task-number: #94

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-01-06 11:18:33 +08:00
Yuhang Zhao fc307c83bf Simplify code a bit
Amends commit 17601f386f

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-01-05 11:10:58 +08:00
Yuhang Zhao 17601f386f Code refactor
1. Load dwmapi.dll and winmm.dll dynamically at runtime, to remove the dependency on those dlls
2. Use QSystemLibrary to load dlls, it can make the loading of system dlls safer, and avoid duplicating the code
3. Use QWinRegistryKey to access registry, no need to use QSettings in such scenarios
4. Adapt to new code when building against Qt 6.3 and newer.
5. Other minor tweaks.

Fixes: #94
2022-01-05 11:00:31 +08:00
Yuhang Zhao c3c5ef0d5d The DWM workaround is not needed when DWM composition is disabled
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2022-01-03 11:03:24 +08:00
Yuhang Zhao 9904a5077a Fix top part be cut-off for some pixels when maximized
Root cause: forgot to change the passed parameter after the function signature changed

Fixes: #77

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2021-12-20 10:51:36 +08:00
Julien 76c13cf9bf
FIX for #92 return HTCAPTION only when mouse is pressed (#93) 2021-12-18 08:20:50 +08:00
Yuhang Zhao fb8f061091 Win32: Add workaround for DWM flicker
And some other minor tweaks.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2021-12-01 14:59:29 +08:00
Yuhang Zhao 6068944657 Win32: always return 0 in WM_NCCALCSIZE
Otherwise will cause bugs.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2021-11-28 20:22:08 +08:00
Yuhang Zhao 2fafa7a433 Fix the border width of the examples
Amends commit 3aba956d66

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2021-11-19 14:29:44 +08:00
Yuhang Zhao 3aba956d66 Minor improvements
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2021-11-19 14:11:55 +08:00
Yuhang Zhao 5be463436c Minor tweaks
The "wParam == FALSE" case is very rare, but it may be needed.
Adding special handling for it doesn't bring any harm anyway.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2021-11-18 14:16:20 +08:00
Yuhang Zhao bb7ab2ea2b Fix build error on Win11
Fixes: #88
2021-11-18 14:02:08 +08:00
Yuhang Zhao 330669e34a Quality improvements
1. Use native frame color in the MainWindow example, just like the Widget example. Fixes #87
2. Rename setHitTestVisibleInChrome() to setHitTestVisible(): This name was taken from Microsoft's WindowChrome class in WPF. Now they removed the legacy "Chrome" suffix in their new products, so we removed it as well.
3. Fix build with Qt older than 5.15: Q_NAMESPACE_EXPORT was introduced in Qt 5.14
4. Removed code that supports native frame: they are just leftovers of the previous refactoring.
4. Correctly detect SetWindowLongPtrW() and GetWindowLongPtrW() 's operation result: they won't modify the Last Error state on success, so we have to set Last Error state to ERROR_SUCCESS before calling them to make sure we get the correct error code.
5. Remove implicitly conversions, use explicit casts where possible
6. Fixed FormatMessage() usage, correctly retrieve the error message: According to MSDN, we should pass the address of a LPWSTR, not the LPWSTR itself.
7. Removed the special handing of WM_SIZE: It turns out that this handling is not needed at all and it's causing new issues, so just remove it.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
2021-10-08 15:43:33 +08:00
296 changed files with 28408 additions and 6697 deletions

85
.github/workflows/ci.yml vendored Normal file
View File

@ -0,0 +1,85 @@
name: "CI: Build Test"
on:
push:
branches:
- main
paths-ignore:
- "**.md"
- "**.png"
- "**.jpg"
- "**.jpeg"
- ".gitignore"
workflow_dispatch:
pull_request:
jobs:
build:
name: Build
strategy:
matrix:
qt-version: [5.15.2, 6.5.1]
library-type: [shared, static]
platform: [windows-latest, ubuntu-latest, macos-latest]
include:
- platform: windows-latest
CC: cl
CXX: cl
LD: link
EXTRA_FLAGS: -DFRAMELESSHELPER_ENABLE_SPECTRE=ON -DFRAMELESSHELPER_ENABLE_EHCONTGUARD=ON -DFRAMELESSHELPER_ENABLE_INTELCET=ON -DFRAMELESSHELPER_ENABLE_CFGUARD=ON
- platform: ubuntu-latest
CC: gcc
CXX: g++
LD: ld
EXTRA_FLAGS: -DFRAMELESSHELPER_ENABLE_SPECTRE=ON -DFRAMELESSHELPER_ENABLE_INTELCET=ON -DFRAMELESSHELPER_ENABLE_CFGUARD=ON
- platform: macos-latest
CC: /usr/local/opt/llvm/bin/clang
CXX: /usr/local/opt/llvm/bin/clang++
LD: /usr/local/opt/llvm/bin/ld64.lld
EXTRA_FLAGS: -DFRAMELESSHELPER_ENABLE_UNIVERSAL_BUILD=OFF
- library-type: shared
lib_type_flag: -DFRAMELESSHELPER_BUILD_STATIC=OFF
- library-type: static
lib_type_flag: -DFRAMELESSHELPER_BUILD_STATIC=ON
runs-on: ${{ matrix.platform }}
steps:
- name: Check out repository
uses: actions/checkout@v3
with:
submodules: recursive
- name: Install Qt SDK
uses: jurplel/install-qt-action@v3
with:
version: ${{ matrix.qt-version }}
cache: true
- name: Set up Ninja
uses: seanmiddleditch/gha-setup-ninja@v3
with:
version: 1.11.1 # Current latest version.
- name: Set up MSVC environment
if: ${{ matrix.platform == 'windows-latest' }}
uses: ilammy/msvc-dev-cmd@v1
- name: Install Linux dependencies
if: ${{ matrix.platform == 'ubuntu-latest' }}
run: |
sudo apt install -y libgl1-mesa-dev libxcb1-dev libgtk-3-dev
- name: Install macOS dependencies
if: ${{ matrix.platform == 'macos-latest' }}
run: |
brew install llvm
export PATH="/usr/local/opt/llvm/bin:$PATH"
- name: Build library with CMake
run: |
mkdir ci
cd ci
cmake -DCMAKE_MESSAGE_LOG_LEVEL=STATUS -DCMAKE_C_COMPILER=${{ matrix.CC }} -DCMAKE_CXX_COMPILER=${{ matrix.CXX }} -DCMAKE_LINKER=${{ matrix.LD }} -DCMAKE_INSTALL_PREFIX=../../install -DCMAKE_BUILD_TYPE=Release -DFRAMELESSHELPER_BUILD_EXAMPLES=ON -DFRAMELESSHELPER_NO_SUMMARY=OFF ${{ matrix.lib_type_flag }} ${{ matrix.EXTRA_FLAGS }} -GNinja ..
cmake --build . --target all --config Release --parallel
cmake --install . --config Release --strip

15
.gitignore vendored
View File

@ -6,6 +6,7 @@
*.la
*.lai
*.so
*.so.*
*.dll
*.dylib
@ -28,6 +29,8 @@ ui_*.h
*.jsc
Makefile*
*build-*
*.qm
*.prl
# Qt unit tests
target_wrapper.*
@ -42,6 +45,12 @@ target_wrapper.*
# QtCreator CMake
CMakeLists.txt.user*
# QtCreator 4.8< compilation database
compile_commands.json
# QtCreator local machine specific files for imported projects
*creator.user*
# My
[Bb]in/
[Bb]in64/
@ -65,11 +74,11 @@ user.conf
[Dd]ocs/
Thumbs.db
*.rc
*.qm
*.bin
*.run
.qmake.conf
*.res
.DS_Store
.vscode/
*/.DS_Store
.vs/
.cmake.conf

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "cmake"]
path = cmake
url = https://git.ourdocs.cn/github_mirror/cmake-utils.git

View File

@ -1,31 +1,238 @@
cmake_minimum_required(VERSION 3.5)
#[[
MIT License
project(FramelessHelper LANGUAGES CXX)
Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
option(BUILD_EXAMPLES "Build examples." ON)
option(TEST_UNIX "Test UNIX version (from Win32)." OFF)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
set(BUILD_SHARED_LIBS OFF)
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
]]
set(CMAKE_INCLUDE_CURRENT_DIR ON)
cmake_minimum_required(VERSION 3.20)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
project(FramelessHelper
VERSION "2.4.0"
DESCRIPTION "Cross-platform window customization framework for Qt Widgets and Qt Quick."
HOMEPAGE_URL "https://github.com/wangwenx190/framelesshelper/"
)
find_package(QT NAMES Qt6 Qt5 COMPONENTS Gui REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Gui REQUIRED)
find_package(QT NAMES Qt6 Qt5 COMPONENTS Widgets)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Widgets)
find_package(QT NAMES Qt6 Qt5 COMPONENTS Quick)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Quick)
include(CMakeDependentOption)
add_subdirectory(src)
# TODO: Use add_feature_info() for every option below? Is it worth doing?
option(FRAMELESSHELPER_BUILD_STATIC "Build FramelessHelper as a static library." OFF)
option(FRAMELESSHELPER_BUILD_WIDGETS "Build FramelessHelper's Widgets module." ON)
option(FRAMELESSHELPER_BUILD_QUICK "Build FramelessHelper's Quick module." ON)
option(FRAMELESSHELPER_BUILD_EXAMPLES "Build FramelessHelper demo applications." OFF)
option(FRAMELESSHELPER_EXAMPLES_DEPLOYQT "Deploy the Qt framework after building the demo projects." OFF)
option(FRAMELESSHELPER_NO_DEBUG_OUTPUT "Suppress the debug messages from FramelessHelper." OFF)
option(FRAMELESSHELPER_NO_BUNDLE_RESOURCE "Do not bundle any resources within FramelessHelper." OFF)
option(FRAMELESSHELPER_NO_PRIVATE "Do not use any private functionalities from Qt." OFF)
option(FRAMELESSHELPER_ENABLE_VCLTL "MSVC only: link to the system MSVCRT/UCRT and get rid of API sets." OFF)
option(FRAMELESSHELPER_ENABLE_YYTHUNKS "MSVC only: dynamic load most Win32 APIs to give better compatibility for old Windows versions." OFF)
option(FRAMELESSHELPER_NO_PERMISSIVE_CHECKS "MSVC only: disable the additional permissive checks." OFF)
option(FRAMELESSHELPER_NO_INSTALL "Don't install any files." OFF)
option(FRAMELESSHELPER_NO_SUMMARY "Don't show CMake configure summary." OFF)
option(FRAMELESSHELPER_ENABLE_SPECTRE "Mitigate Spectre security vulnerabilities." OFF)
option(FRAMELESSHELPER_ENABLE_EHCONTGUARD "MSVC only: Enable EH Continuation (EHCONT) Metadata." OFF)
option(FRAMELESSHELPER_ENABLE_INTELCET "Enable Intel CET." OFF)
option(FRAMELESSHELPER_ENABLE_INTELJCC "Enable Intel JCC." OFF)
option(FRAMELESSHELPER_ENABLE_CFGUARD "Enable Control Flow Guard (CFG)." OFF)
option(FRAMELESSHELPER_EXAMPLES_STANDALONE "Build the demo projects as standalone CMake projects." OFF)
cmake_dependent_option(FRAMELESSHELPER_ENABLE_UNIVERSAL_BUILD "macOS only: build universal library/example for Mac." ON APPLE OFF)
option(FRAMELESSHELPER_FORCE_LTO "Force enable LTO/LTCG even when building static libraries." OFF)
option(FRAMELESSHELPER_REPRODUCIBLE_OUTPUT "Don't update the build commit and date dynamically." OFF)
if(BUILD_EXAMPLES)
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core Gui)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Gui)
find_package(QT NAMES Qt6 Qt5 QUIET COMPONENTS Widgets Quick)
find_package(Qt${QT_VERSION_MAJOR} QUIET COMPONENTS Widgets Quick)
include(cmake/utils.cmake)
if(NOT APPLE AND FRAMELESSHELPER_ENABLE_UNIVERSAL_BUILD)
message(WARNING "Current OS is not macOS, universal build will be disabled.")
set(FRAMELESSHELPER_ENABLE_UNIVERSAL_BUILD OFF)
elseif(APPLE AND ((QT_VERSION VERSION_LESS "6.2" AND QT_VERSION VERSION_GREATER_EQUAL "6.0") OR (QT_VERSION VERSION_LESS "5.15.9")))
message(WARNING "Your Qt version ${QT_VERSION} doesn't support universal build, it will be disabled.")
set(FRAMELESSHELPER_ENABLE_UNIVERSAL_BUILD OFF)
endif()
if(FRAMELESSHELPER_NO_BUNDLE_RESOURCE)
message(WARNING "Nothing will be embeded into the FramelessHelper library, the chrome buttons will have no icon.")
endif()
if(FRAMELESSHELPER_ENABLE_VCLTL AND NOT MSVC)
message(WARNING "VC-LTL is only available for the MSVC toolchain.")
endif()
set(__extra_flags)
if(NOT FRAMELESSHELPER_BUILD_STATIC)
list(APPEND __extra_flags ENABLE_LTO)
endif()
setup_project(
QT_PROJECT
QML_IMPORT_DIR "${PROJECT_BINARY_DIR}/imports"
LANGUAGES CXX RC
MAX_WARNING
RTTI
EXCEPTIONS
${__extra_flags}
)
unset(__extra_flags)
set(PROJECT_VERSION_COMMIT "UNKNOWN")
set(PROJECT_COMPILE_DATETIME "UNKNOWN")
if(NOT FRAMELESSHELPER_REPRODUCIBLE_OUTPUT)
get_commit_hash(RESULT PROJECT_VERSION_COMMIT)
string(TIMESTAMP PROJECT_COMPILE_DATETIME UTC)
endif()
if(MINGW AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(FRAMELESSHELPER_ENABLE_SPECTRE OFF)
set(FRAMELESSHELPER_ENABLE_EHCONTGUARD OFF)
set(FRAMELESSHELPER_ENABLE_INTELCET OFF)
set(FRAMELESSHELPER_ENABLE_INTELJCC OFF)
set(FRAMELESSHELPER_ENABLE_CFGUARD OFF)
endif()
if(MSVC)
if(FRAMELESSHELPER_ENABLE_VCLTL)
include(cmake/VC-LTL.cmake)
if("x${SupportLTL}" STREQUAL "xtrue")
# Make sure we will always overwrite the previous settings.
unset(CMAKE_MSVC_RUNTIME_LIBRARY)
unset(CMAKE_MSVC_RUNTIME_LIBRARY CACHE)
#unset(CMAKE_MSVC_RUNTIME_LIBRARY PARENT_SCOPE)
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>" CACHE STRING "" FORCE)
endif()
endif()
if(FRAMELESSHELPER_ENABLE_YYTHUNKS)
unset(YYTHUNKS_TARGET_OS)
unset(YYTHUNKS_TARGET_OS CACHE)
#unset(YYTHUNKS_TARGET_OS PARENT_SCOPE)
set(YYTHUNKS_TARGET_OS "WinXP" CACHE STRING "" FORCE)
include(cmake/YY-Thunks.cmake)
endif()
endif()
set(__extra_flags)
if(FRAMELESSHELPER_NO_INSTALL)
list(APPEND __extra_flags NO_INSTALL)
endif()
prepare_package_export(
PACKAGE_NAME "${PROJECT_NAME}"
PACKAGE_VERSION "${PROJECT_VERSION}"
${__extra_flags}
)
unset(__extra_flags)
if(FRAMELESSHELPER_BUILD_QUICK AND NOT TARGET Qt${QT_VERSION_MAJOR}::Quick)
message(WARNING "Can't find the QtQuick module. FramelessHelper's QtQuick implementation and the QtQuick demo won't be built.")
set(FRAMELESSHELPER_BUILD_QUICK OFF)
endif()
if(TARGET Qt${QT_VERSION_MAJOR}::Core AND TARGET Qt${QT_VERSION_MAJOR}::Gui)
add_subdirectory(src)
else()
message(WARNING "Can't find the QtCore and QtGui module. Nothing will be built.")
set(FRAMELESSHELPER_BUILD_WIDGETS OFF)
set(FRAMELESSHELPER_BUILD_EXAMPLES OFF)
endif()
if(FRAMELESSHELPER_BUILD_EXAMPLES)
add_subdirectory(examples)
endif()
endif()
if(NOT FRAMELESSHELPER_NO_INSTALL)
install(FILES "msbuild/FramelessHelper.props" DESTINATION ".")
endif()
if(NOT FRAMELESSHELPER_NO_SUMMARY)
message("--------------------------- Toolchain ----------------------------")
message("CMake version: ${CMAKE_VERSION} (${CMAKE_COMMAND})")
message("Host system: ${CMAKE_HOST_SYSTEM}")
message("Host processor: ${CMAKE_HOST_SYSTEM_PROCESSOR}")
#[[message("C compiler: ${CMAKE_C_COMPILER_ID} (${CMAKE_C_COMPILER})") # Currently we are not using any C compilers.
message("C compiler version: ${CMAKE_C_COMPILER_VERSION}")
message("C common flags: ${CMAKE_C_FLAGS}")
message("C debug flags: ${CMAKE_C_FLAGS_DEBUG}")
message("C release flags: ${CMAKE_C_FLAGS_RELEASE}")
message("C minsizerel flags: ${CMAKE_C_FLAGS_MINSIZEREL}")
message("C relwithdebinfo flags: ${CMAKE_C_FLAGS_RELWITHDEBINFO}")]]
message("C++ compiler: ${CMAKE_CXX_COMPILER_ID} (${CMAKE_CXX_COMPILER})")
message("C++ compiler version: ${CMAKE_CXX_COMPILER_VERSION}")
message("C++ common flags: ${CMAKE_CXX_FLAGS}")
message("C++ debug flags: ${CMAKE_CXX_FLAGS_DEBUG}")
message("C++ release flags: ${CMAKE_CXX_FLAGS_RELEASE}")
message("C++ minsizerel flags: ${CMAKE_CXX_FLAGS_MINSIZEREL}")
message("C++ relwithdebinfo flags: ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
message("Linker: ${CMAKE_LINKER}")
message("Linker exe common flags: ${CMAKE_EXE_LINKER_FLAGS}")
message("Linker exe debug flags: ${CMAKE_EXE_LINKER_FLAGS_DEBUG}")
message("Linker exe release flags: ${CMAKE_EXE_LINKER_FLAGS_RELEASE}")
message("Linker exe minsizerel flags: ${CMAKE_EXE_LINKER_FLAGS_MINSIZEREL}")
message("Linker exe relwithdebinfo flags: ${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO}")
message("Linker dll common flags: ${CMAKE_SHARED_LINKER_FLAGS}")
message("Linker dll debug flags: ${CMAKE_SHARED_LINKER_FLAGS_DEBUG}")
message("Linker dll release flags: ${CMAKE_SHARED_LINKER_FLAGS_RELEASE}")
message("Linker dll minsizerel flags: ${CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL}")
message("Linker dll relwithdebinfo flags: ${CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO}")
message("Make program: ${CMAKE_MAKE_PROGRAM}")
message("Generator: ${CMAKE_GENERATOR}")
message("Build type: ${CMAKE_BUILD_TYPE}")
message("Configuration types: ${CMAKE_CONFIGURATION_TYPES}")
message("Install prefix: ${CMAKE_INSTALL_PREFIX}")
message("Prefix paths: ${CMAKE_PREFIX_PATH}")
message("Toolchain file: ${CMAKE_TOOLCHAIN_FILE}")
message("------------------------------ Qt -------------------------------")
query_qt_paths(SDK_DIR __qt_inst_dir)
query_qt_library_info(STATIC __qt_static_lib)
message("Qt SDK installation directory: ${__qt_inst_dir}")
message("Qt SDK version: ${QT_VERSION}")
if(__qt_static_lib)
message("Qt SDK library type: static")
else()
message("Qt SDK library type: shared")
endif()
message("------------------------ FramelessHelper ------------------------")
message("FramelessHelper version: ${PROJECT_VERSION}")
message("FramelessHelper commit hash: ${PROJECT_VERSION_COMMIT}")
message("FramelessHelper configure date and time: ${PROJECT_COMPILE_DATETIME} (UTC)")
message("Build the static version of FramelessHelper: ${FRAMELESSHELPER_BUILD_STATIC}")
message("Build the FramelessHelper::Widgets module: ${FRAMELESSHELPER_BUILD_WIDGETS}")
message("Build the FramelessHelper::Quick module: ${FRAMELESSHELPER_BUILD_QUICK}")
message("Build the FramelessHelper demo applications: ${FRAMELESSHELPER_BUILD_EXAMPLES}")
message("Deploy Qt libraries after compilation: ${FRAMELESSHELPER_EXAMPLES_DEPLOYQT}")
message("Suppress debug messages from FramelessHelper: ${FRAMELESSHELPER_NO_DEBUG_OUTPUT}")
message("Do not bundle any resources within FramelessHelper: ${FRAMELESSHELPER_NO_BUNDLE_RESOURCE}")
message("Do not use any private functionalities from Qt: ${FRAMELESSHELPER_NO_PRIVATE}")
message("[MSVC] Link to system C runtime library: ${FRAMELESSHELPER_ENABLE_VCLTL}")
message("[MSVC] Thunk system APIs for old system: ${FRAMELESSHELPER_ENABLE_YYTHUNKS}")
message("[MSVC] Disable permissive checks: ${FRAMELESSHELPER_NO_PERMISSIVE_CHECKS}")
message("Do not install anything for CMake install: ${FRAMELESSHELPER_NO_INSTALL}")
message("Mitigate Spectre security vulnerabilities: ${FRAMELESSHELPER_ENABLE_SPECTRE}")
message("[MSVC] Enable EH Continuation (EHCONT) Metadata: ${FRAMELESSHELPER_ENABLE_EHCONTGUARD}")
message("Enable Intel CET: ${FRAMELESSHELPER_ENABLE_INTELCET}")
message("Enable Intel JCC: ${FRAMELESSHELPER_ENABLE_INTELJCC}")
message("Enable Control Flow Guard (CFG): ${FRAMELESSHELPER_ENABLE_CFGUARD}")
message("Build standalone demo projects: ${FRAMELESSHELPER_EXAMPLES_STANDALONE}")
message("[macOS]: Build universal library/example: ${FRAMELESSHELPER_ENABLE_UNIVERSAL_BUILD}")
message("Force enable LTO: ${FRAMELESSHELPER_FORCE_LTO}")
message("Make output reproducible: ${FRAMELESSHELPER_REPRODUCIBLE_OUTPUT}")
message("-----------------------------------------------------------------")
endif()

View File

@ -0,0 +1,55 @@
#[[
MIT License
Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
]]
@PACKAGE_INIT@
set(_@PROJECT_NAME@_supported_components Core Widgets Quick)
foreach(_comp ${@PROJECT_NAME@_FIND_COMPONENTS})
if(_comp IN_LIST _@PROJECT_NAME@_supported_components)
include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@${_comp}Config.cmake")
else()
set(@PROJECT_NAME@_FOUND FALSE)
set(@PROJECT_NAME@_NOT_FOUND_MESSAGE "Unsupported component: ${_comp}")
endif()
endforeach()
if(NOT DEFINED @PROJECT_NAME@_FOUND)
set(@PROJECT_NAME@_FOUND TRUE)
set(@PROJECT_NAME@_VERSION "@PROJECT_VERSION@")
set(@PROJECT_NAME@_VERSION_MAJOR "@PROJECT_VERSION_MAJOR@")
set(@PROJECT_NAME@_VERSION_MINOR "@PROJECT_VERSION_MINOR@")
set(@PROJECT_NAME@_VERSION_PATCH "@PROJECT_VERSION_PATCH@")
#set(@PROJECT_NAME@_VERSION_TWEAK "@PROJECT_VERSION_TWEAK@")
set(@PROJECT_NAME@_DESCRIPTION "@PROJECT_DESCRIPTION@")
set(@PROJECT_NAME@_HOMEPAGE_URL "@PROJECT_HOMEPAGE_URL@")
set(@PROJECT_NAME@_COMMIT "@PROJECT_VERSION_COMMIT@")
set(@PROJECT_NAME@_COMPILE_DATETIME "@PROJECT_COMPILE_DATETIME@")
endif()
include(FeatureSummary)
set_package_properties(@PROJECT_NAME@ PROPERTIES
DESCRIPTION "@PROJECT_DESCRIPTION@"
URL "@PROJECT_HOMEPAGE_URL@"
)

View File

@ -1,6 +1,6 @@
MIT License
Copyright (C) 2020 by wangwenx190 (Yuhang Zhao)
Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

461
README.md
View File

@ -1,110 +1,427 @@
# FramelessHelper
# FramelessHelper 2.x
If you are using part of or all the code from this repository in your own projects, it's my pleasure and I'm happy that it can help you. But I hope you can tell me the URL of the homepage or repository of your projects, whether your projects are close-sourced or commercial products do not matter. I'll link to your homepage or repository in this README file. It would be much better if you can provide me some screenshots of your software for demonstration.
[![CI: Build Test](https://github.com/wangwenx190/framelesshelper/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/wangwenx190/framelesshelper/actions/workflows/ci.yml)
如果您正在使用此项目的部分或全部代码,这是我的荣幸,我很高兴能帮到您,但我同时也希望,您能将您项目的首页或仓库的网址告诉我(闭源或收费都没关系),我将在这个自述文件中链接到您所提供的网址,以供展示。如果您能一并提供一些软件运行时的截图,那就更好了。
Cross-platform window customization framework for Qt Widgets and Qt Quick. Supports Windows, Linux and macOS.
## Join with Us :triangular_flag_on_post:
You can join our [Discord channel](https://discord.gg/grrM4Tmesy) to communicate with us. You can share your findings, thoughts and ideas on improving / implementing FramelessHelper functionalities on more platforms and apps!
## HELP WANTED!
1. The current CMake package code is not complete and still has some small issues. Need some experienced CMake developers to help me improve it!
2. The current Linux/X11 implementation is not stable enough and still has some bugs. Need some experienced Linux developers to help me improve it!
3. The current macOS implementation is not stable enough and still has some bugs. Need some experienced macOS developers to help me improve it!
## Roadmap
- Common: Add cross-platform customizable system menu for both Qt Widgets and Qt Quick. Also supports both light and dark theme.
- Examples: Add QtWebEngine based demo projects for both Qt Widgets and Qt Quick. The whole user interface will be written in HTML instead of C++/QML.
- Examples: Add demo projects that emulate the classic appearance of UWP applications. They will have a backward button on the left side of the title bar and a search box in the middle of the title bar. And maybe a side bar on the left side to switch between different pages.
- Examples: Add demo projects that the main window is not resizable.
- Examples: Add demo projects that have transparent background and doesn't have rectangular window frame.
- Feature requests are welcome!
## Highlights v2.4
- Widgets: Nested frameless windows are supported now!
- Linux: There have been many improvements to the Linux/X11 implementation! Most of them won't be directly visible to the user, but the code quality has been greatly improved.
- macOS: The frameless windows will now use native window frame and buttons, only the title bar itself is hidden, which also means the window will have round corners as all other native windows on macOS.
- Mica Material: It is now possible to load wallpaper images with very large file size or resolution, for example, 4K pictures. However, if the images have larger resolution than 1920x1080, they will be shrinked to reduce memory usage, and this process will also lower the image quality and break the aspect ratio of them.
- Mica Material: FramelessHelper will now use a seperate thread to load and apply special effects to the wallpaper image, to speed up application startup performance and avoid such process block the main thread.
- Window management: It is now possible to close the window (the dtor is executed) and show it again without breaking the frameless functionalities.
- Theme: It is now possible to force a desired theme instead of always respecting the system theme.
- Build system: The [**Ninja Multi-Config**](https://cmake.org/cmake/help/latest/generator/Ninja%20Multi-Config.html) generator is fully supported now, finally!
- Routine bug fixes and internal refactorings.
## Highlights v2.3
- Widgets & Quick: When you clicks the window icon, the system menu will now popup, and when you double clicks it, the window will be closed. This emulates the traditional window behavior on Windows.
- Widgets & Quick: The StandardSystemButton's icon size can't be changed due to I forgot to implement such funtionality, it's implemented now.
- Widgets: Added `FramelessDialog` class. You can use it in case a `QDialog` is preferred over a general `QWidget`.
- Widgets: The StandardSystemButton's size can't be changed due to a FramelessHelper bug, it's fixed now.
- Widgets: Added public interface to change the title label font (family, point size, style, etc...).
- Widgets: The window borders are now drawn by the newly introduced `WindowBorderPainter` class, and it's also exposed publicly, so you'll be able to change how we draw the window border easily.
- Quick: Added `WindowBorder` element. It's a cross-platform window border decorator, and can work without the `FramelessHelper` element.
- Quick: Added `FramelessApplicationWindow` element. It's a simple wrapper of the standard `ApplicationWindow` element, just removes the title bar and adds the window border.
- Windows: Added support for dark theme system menu. The system menu triggered by right-clicking on the title bar will now use the same theme with the current system theme, and will switch between light and dark theme automatically.
- macOS: Added support for old macOS versions and old Qt versions, in theory.
- Common: Internal code improvements & bug fixes.
## Highlights v2.2
- Common: Added blur behind window feature for Windows (7\~11), Linux and macOS. On Windows 11 and macOS, FramelessHelper will make use of the blur effect provided by the OS to get the best appearance and performance, while on Windows 7\~10 and Linux, FramelessHelper will use a homemade blur effect to provide as much consistent experience as possible.
- Common: Added window icon support. It's now possible to set the window icon's image, size and visibility for the standard title bar control.
- Windows: If you are using Qt 6.4+, your Qt Widgets applications will now automatically switch to light/dark theme if the OS theme changes. It requires you are using the default palette provided by Qt. Qt Quick applications will not be affected.
- Linux: FramelessHelper is now theme-aware. If you change your OS theme, FramelessHelper will now emit the theme change signal and refresh it's internal palette.
- Build system: Implemented CMake package support. It's now possible to use `find_package` to find FramelessHelper.
- Build system: Implemented limited QMake support. FramelessHelper doesn't provide complete QMake project, to decrease the maintainance burden, but you can use the .pri files to directly embed FramelessHelper into your own application.
- Examples: Enabled blur behind window and round window corner by default.
- Common: Migrated to categorized logging output. You can now enable or disable some specific debug messages using QLoggingCategory.
- Common: Internal code improvements & bug fixes.
## Highlights v2.1
- Windows: Added support for the snap layout feature introduced in Windows 11.
- Widgets: Redesigned the public interface, the use of FramelessHelper is now more elegant.
- Quick: Redesigned the public interface, the use of FramelessHelper is now more elegant.
- Common: Redesigned the standard title bar interface, it's now possible to customize it from outside. Previously there's no standard title bar in the widgets module, it's now added and exported.
- Doc: Add initial simple documentation to show how to use this library for both Qt Widgets and Qt Quick.
- Misc: Removed bundled Qt internal classes that are licensed under Commercial/GPL/LGPL. This library is now pure MIT licensed.
- Misc: Bug fixes and internal refactorings.
## Highlights v2.0
- Windows: Gained the ability to only remove the title bar but preserve the window frame at the same time.
- Windows: The flicker and jitter during window resizing is completely gone.
- Windows: The system menu will be opened if you right-click on your custom title bar.
- Windows: Replaced Qt's original system menu with FramelessHelper's homemade one, which looks a lot better than the original one.
- Linux: Removed the limitation of the Qt version. The minimum supported version is lowered to Qt 5.6 now (previously was 5.15).
- macOS: Removed the limitation of the Qt version. The minimum supported version is lowered to Qt 5.6 now (previously was 5.15).
- macOS: The frameless window now supports native resizing.
- Common: Almost completely rewritten of the whole library, it's now a lot more easier to setup your own custom title bar than before.
- Common: Added many more helper functions to allow creating your own custom window easier.
- Misc: Reorganized the project structure to be more like a modern library, it's now a lot more friendly to the library users.
- Misc: Many bugs from the 1.x times are fixed (they were not fixable in 1.x due to technical reasons).
## Screenshots
![Quick_Acrylic_Win7](/screenshots/quick_acrylic_win7.png)
### Windows
## Features
![Light](./doc/win_light.png)
- Support Windows, X11, Wayland and macOS.
- Frameless but have frame shadow.
- Draggable and resizable.
- Automatically high DPI scaling.
- Multi-monitor support (different resolution and DPI).
- Have animations when minimizing, maximizing and restoring.
- Support tiled and stack windows by DWM (Win32 only).
- Won't cover the task bar when maximized (Win32 only).
- Won't block the auto-hide task bar when maximized (Win32 only).
![Dark](./doc/win_dark.png)
## Usage
### Linux
```cpp
#include "framelesswindowsmanager.h"
#include <QWidget>
![Light](./doc/linux_light.png)
int main(int argc, char *argv[]) {
QWidget widget;
// Qt's internal function. Make sure it's a top level window.
widget.createWinId();
// Do this before the widget is shown.
FramelessWindowsManager::addWindow(widget.windowHandle());
widget.show();
}
```
![Dark](./doc/linux_dark.png)
Please refer to [the QWidget example](/examples/widget/) for more detailed information.
### macOS
### Some details
![Light](./doc/mac_light.png)
```cpp
// Only **TOP LEVEL** QWidgets and QWindows are supported.
QMainWindow *mainWindow = new QMainWindow;
// Qt's internal function. Make sure it's a top level window.
mainWindow->createWinId();
QWindow *win = mainWindow->windowHandle();
// Disable resizing of the given window. Resizing is enabled by default.
FramelessWindowsManager::setResizable(win, false);
// All the following values should not be DPI-aware, just use the
// original numbers, assuming the scale factor is 1.0, don't scale
// them yourself, this code will do the scaling according to DPI
// internally and automatically.
// Maximum window size
win->setMaximumSize(1280, 720);
// Minimum window size
win->setMinimumSize(800, 540);
// The **POINTER** of a QWidget or QQuickItem
FramelessWindowsManager::setHitTestVisibleInChrome(win, ui->pushButton_minimize, true);
```
![Dark](./doc/mac_dark.png)
## IMPORTANT NOTES
## Use Cases
- For [QDockWidget](https://doc.qt.io/qt-6/qdockwidget.html), it supports set a custom title bar widget officially, no need to use this library, and this library is known to be not working well for QDockWidgets. Please refer to <https://doc.qt.io/qt-6/qdockwidget.html#setTitleBarWidget> for more details.
- Only top level windows ([QWindow](https://doc.qt.io/qt-6/qwindow.html) and [QWidget](https://doc.qt.io/qt-6/qwidget.html)) are supported.
- Win32: There are some known issues when DWM composition is disabled. This is unsupported and not tested and will not be fixed. However, PRs are always welcome.
- Win32: High DPI scaling must be enabled for your application otherwise some Win32 APIs may return wrong value and thus it may result in unexpected behavior.
### QVogenClient
![QVogenClient](./doc/QVogenClient.png)
Vogen editor using **QSynthesis** framework. Repository URL: <https://gitee.com/functioner/qvogenclient>.
## Requiredments
- Compiler: a modern compiler which supports C++17 at least. Tested on MSVC 2022 (Windows), GCC 11 (Linux) and Clang 13 (macOS).
- Qt version: using the latest stable version of Qt is highly recommended, the minimum supported version is Qt 5.6. However, if you are using some old Qt versions (such as older than 5.12), some features may not be available. Only Qt 5.15 and Qt 6 are actively tested.
- Qt modules: QtCore and QtGui for the core module; QtWidgets for the widgets module; QtQuick, QtQuickControls2 and QtQuickTemplates2 for the quick module.
- CMake & ninja: the newer, the better. Other build systems are not tested.
## Supported Platforms
### Win32
- Windows: Windows Vista \~ 11 (only actively tested on Windows 10 & 11)
- Linux: any modern Linux distros should work, but only tested on Ubuntu 20.04 and Ubuntu 22.04
- macOS: only tested on macOS 12 & 13 due to lack of Apple devices
Windows 7 ~ 10, 32 bit & 64 bit.
There are some additional restrictions for each platform, please refer to the _Platform notes_ section below.
The code itself should be able to work on Windows Vista in theory, but Qt5 has dropped Vista support long time ago. And Qt6 will only support Win10.
## Build
### UNIX
```bash
git clone --recursive https://github.com/wangwenx190/framelesshelper.git # "--recursive" is necessary to clone the submodules.
mkdir build # Please change to your own build directory!
cd build
cmake -DCMAKE_PREFIX_PATH=<YOUR_QT_SDK_DIR_PATH> -DCMAKE_INSTALL_PREFIX=<WHERE_YOU_WANT_TO_INSTALL> -DCMAKE_BUILD_TYPE=Release -GNinja <PATH_TO_THE_REPOSITORY>
cmake --build . --config Release --target all --parallel
cmake --install . --config Release --strip # Don't add "--strip" for MSVC/Clang-CL/Intel-CL toolchains!
# YOUR_QT_SDK_DIR_PATH: the Qt SDK directory, something like "C:/Qt/6.5.1/msvc2019_64" or "/opt/Qt/6.5.1/gcc_64". Please change to your own path!
# WHERE_YOU_WANT_TO_INSTALL: the install directory of FramelessHelper, something like "../install". You can ignore this setting if you don't need to install the CMake package. Please change to your own path!
# PATH_TO_THE_REPOSITORY: the source code directory of FramelessHelper, something like "../framelesshelper". Please change to your own path!
```
A not too old version of Linux and macOS, 32 bit & 64 bit.
You can also use `Qt6_DIR` or `Qt5_DIR` to replace `CMAKE_PREFIX_PATH`:
## Requirements
```bash
cmake -DQt6_DIR=C:/Qt/6.5.1/msvc2019_64/lib/cmake/Qt6 [other parameters ...]
# Or
cmake -DQt5_DIR=C:/Qt/5.15.2/msvc2019_64/lib/cmake/Qt5 [other parameters ...]
```
### Win32
If there are any errors when cloning the submodules, try run `git submodule update --init --recursive --remote` in the project directory, that command will download & update all the submodules. If it fails again, try execute it multiple times until it finally succeeds.
| Component | Requirement | Additional Information |
| --- | --- | --- |
| Qt | >= 5.6 | Only the `core` and `gui` modules are required |
| Compiler | >= C++11 | MSVC, MinGW, Clang-CL, Intel-CL or cross compile from Linux/macOS are all supported |
Once the compilation and installation is done, you will be able to use the `find_package(FramelessHelper REQUIRED COMPONENTS Core Widgets Quick)` command to find and link to the FramelessHelper library. But before doing that, please make sure CMake knows where to find FramelessHelper, by passing the `CMAKE_PREFIX_PATH` or `FramelessHelper_DIR` variable to it. For example: `-DCMAKE_PREFIX_PATH=C:/my-cmake-packages;C:/my-toolchain;etc...` or `-DFramelessHelper_DIR=C:/Projects/FramelessHelper/lib64/cmake/FramelessHelper`. Build FramelessHelper as a sub-directory of your CMake project is of course also supported. The supported FramelessHelper target names are `FramelessHelper::Core`, `FramelessHelper::Widgets` and `FramelessHelper::Quick`. Example code:
### UNIX
```cmake
# Find Qt:
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets)
# Find FramelessHelper:
find_package(FramelessHelper REQUIRED COMPONENTS Core Widgets)
# Create your target:
add_executable(demo)
# Add your source code:
target_sources(demo PRIVATE main.cpp)
# Link to Qt and FramelessHelper:
target_link_libraries(demo PRIVATE
Qt${QT_VERSION_MAJOR}::Widgets
FramelessHelper::Core
FramelessHelper::Widgets
)
```
| Component | Requirement | Additional Information |
| --- | --- | --- |
| Qt | >= 5.15 | This code uses two functions, [`startSystemMove`](https://doc.qt.io/qt-5/qwindow.html#startSystemMove) and [`startSystemResize`](https://doc.qt.io/qt-5/qwindow.html#startSystemResize), which are introduced in Qt 5.15 |
| Compiler | >= C++11 | MSVC, MinGW, Clang-CL, Intel-CL / GCC, Clang, ICC are all supported |
If you need the syntax highlighting of FramelessHelper's Quick module, please set up the `QML_IMPORT_PATH` variable. Example code:
## Known Bugs
```cmake
# This is the path where you want FramelessHelper's Quick plugin (it only contains the QML meta
# info and an optional dummy library, for QtCreator's QML tooling purpose, it's not the Quick
# module) to place. Please change to your own path!
# If you are using add_subdirectory() to include FramelessHelper directly, you can change it to
# "${PROJECT_BINARY_DIR}/imports" instead of the install location.
set(FRAMELESSHELPER_IMPORT_DIR "C:/packages/FramelessHelper/qml")
list(APPEND QML_IMPORT_PATH "${FRAMELESSHELPER_IMPORT_DIR}")
list(REMOVE_DUPLICATES QML_IMPORT_PATH)
# Force cache refresh:
set(QML_IMPORT_PATH ${QML_IMPORT_PATH} CACHE STRING "Qt Creator extra QML import paths" FORCE)
```
Please refer to <https://github.com/wangwenx190/framelesshelper/issues> for more information.
## Use
### Qt Widgets
To customize the window frame of a QWidget, you need to instantiate a `FramelessWidgetsHelper` object and then attach it to the widget's top level widget, and then `FramelessWidgetsHelper` will do all the rest work for you: the window frame will be removed automatically once it has been attached to the top level widget successfully. In theory you can instantiate multiple `FramelessWidgetsHelper` objects for a same widget, in this case there will be only one object that keeps functional, all other objects will become a wrapper of that one. But to make sure everything goes smoothly and normally, you should not do that in any case. The simplest way to instantiate a `FramelessWidgetsHelper`
object is to call the static method `FramelessWidgetsHelper *FramelessWidgetsHelper::get(QObject *)`. It will return the handle of the previously instantiated object if any, or it will instantiate a new object if it can't find one. It's safe to call this method multiple times for a same widget, it won't instantiate any new objects if there is one already. It also does not matter when and where you call that function as long as the top level widget is the same. The internally created objects will always be parented to the top level widget. Once you get the handle of the `FramelessWidgetsHelper` object, you can call `void FramelessWidgetsHelper::extendsContentIntoTitleBar()` to let it hide the default title bar provided by the operating system. In order to make sure `FramelessWidgetsHelper` can find the correct top level widget, you should call the `FramelessWidgetsHelper *FramelessWidgetsHelper::get(QObject *)` function on a widget which has a complete parent-chain whose root parent is the top level widget. To make the frameless window draggable, you should provide a homemade title bar widget yourself, the title bar widget doesn't need to be in rectangular shape, it also doesn't need to be placed on the first row of the window. Call `void FramelessWidgetsHelper::setTitleBarWidget(QWidget *)` to let `FramelessHelper` know what's your title bar widget. By default, all the widgets in the title bar area won't be responsible to any mouse and keyboard events due to they have been intercepted by FramelessHelper. To make them recover the responsible state, you should make them visible to hit test. Call `void FramelessWidgetsHelper::setHitTestVisible(QWidget* )` to do that. You can of course call it on a widget that is not inside the title bar at all, it won't have any effect though. Due to Qt's own limitations, you need to make sure your widget has a complete parent-chain whose root parent is the top level widget. Do not ever try to delete the `FramelessWidgetsHelper` object, it may still be monitoring and controlling your widget, and Qt will delete it for you automatically. No need to worry about memory leaks.
There are also two classes called `FramelessWidget` and `FramelessMainWindow`, they are only simple wrappers of `FramelessWidgetsHelper`, which just saves the call of the `void FramelessWidgetsHelper::extendsContentIntoTitleBar()` function for you. You can absolutely use plain `QWidget` instead.
#### Code Snippet
First of all, call `void FramelessHelper::Widgets::initialize()` in your `main` function in a very early stage (**MUST** before the construction of any `Q(Gui|Core)Application` objects):
```cpp
int main(int, char **)
{
FramelessHelper::Widgets::initialize();
// ...
}
```
Then hide the standard title bar provided by the OS:
```cpp
MyWidget::MyWidget(QWidget *parent) : QWidget(parent)
{
// You should do this early enough.
FramelessWidgetsHelper::get(this)->extendsContentIntoTitleBar();
// ...
}
```
Then let `FramelessHelper` know what should be the title bar:
```cpp
void MyWidget::myFunction()
{
// ...
FramelessWidgetsHelper::get(this)->setTitleBarWidget(m_myTitleBarWidget);
// ...
}
```
Then make some widgets inside your title bar visible to hit test:
```cpp
void MyWidget::myFunction2()
{
// ...
FramelessWidgetsHelper::get(this)->setHitTestVisible(m_someSearchBox);
FramelessWidgetsHelper::get(this)->setHitTestVisible(m_someButton);
FramelessWidgetsHelper::get(this)->setHitTestVisible(m_someMenuItem);
// ...
}
```
**IMPORTANT NOTE for Qt Widgets applications**: Some functionalities may only be available when `FramelessHelper` has finished the window customization process, such as changing window geometry/flags/state. In this case you can connect to the public `void ready()` signal of `FramelessHelper` to get the accurate time point and do your rest initialization process afterwards.
### Qt Quick
#### Code Snippet
First of all, you should call `void FramelessHelper::Quick::initialize()` in your `main` function in a very early stage (**MUST** before the construction of any `Q(Gui|Core)Application` objects):
```cpp
int main(int, char **)
{
FramelessHelper::Quick::initialize();
// ...
}
```
Then you need to register the custom types provided by `FramelessHelper` by calling `void FramelessHelper::Quick::registerTypes(QQmlEngine *)`, before the QML engine loads any QML documents:
```cpp
int main(int, char **)
{
// ...
QQmlApplicationEngine engine;
FramelessHelper::Quick::registerTypes(&engine);
// ...
}
```
Now you can write your QML documents. You should import `FramelessHelper` from the URI `org.wangwenx190.FramelessHelper`. You should specify a version number right after it if you are using Qt5:
```qml
import org.wangwenx190.FramelessHelper 1.0 // You can use "auto" or omit the version number in Qt6.
```
And then you can use the attached properties from the QML type `FramelessHelper`:
```qml
Window {
Item {
id: myTitleBar
Item { id: someControl1 }
Item { id: someControl2 }
Item { id: someControl3 }
Component.onCompleted: {
// Don't access FramelessHelper too early, otherwise it may not be able to find the root window!
FramelessHelper.titleBarItem = myTitleBar;
FramelessHelper.setHitTestVisible(someControl1);
FramelessHelper.setHitTestVisible(someControl2);
FramelessHelper.setHitTestVisible(someControl3);
}
}
}
```
It's the same with the `FramelessWidgetsHelper` interface, the QML type `FramelessHelper` will be instantiated only once for each `Window`, no matter when and where you use attached properties from it. However, due to the special design of the `FramelessHelper` type, you can also use it just like a normal QML type:
```qml
Window {
Item {
id: myTitleBar
Item { id: someControl1 }
Item { id: someControl2 }
Item { id: someControl3 }
Component.onCompleted: {
framelessHelper.setHitTestVisible(someControl1);
framelessHelper.setHitTestVisible(someControl2);
framelessHelper.setHitTestVisible(someControl3);
}
}
FramelessHelper {
id: framelessHelper
titleBarItem: myTitleBar
}
}
```
In theory it's possible to instantiate multiple `FramelessHelper` objects for a same `Window`, in this case only one of them will keep functional, all other objects will become a wrapper of it, but doing so is not recommended and may cause unexpected behavior or bugs, so please avoid trying to do that in any case.
If you find any of `FramelessHelper` functions have no effect after calling, the most possible reason is by the time you call the function/change the property of `FramelessHelper`, the root window has not finished its initialization process and thus `FramelessHelper` can't get the handle of it, so any action from the user will be ignored until the root window finished initialization.
There's also a QML type called `FramelessWindow`, it's only a simple wrapper of `FramelessHelper`, you can absolutely use plain `Window` instead.
**IMPORTANT NOTE for Qt Quick applications**: Some functionalities may only be available when `FramelessHelper` has finished the window customization process, such as changing window geometry/flags/state. In this case you can connect to the public `void ready()` signal of `FramelessHelper` to get the accurate time point and do your rest initialization process afterwards:
```qml
Window {
FramelessHelper.onReady: {
// do something here ...
}
}
```
```qml
Window {
FramelessHelper {
onReady: {
// do something here ...
}
}
}
```
**IMPORTANT NOTE for all applications**: Once you called `QWidget::close()` or `Q(Quick)Window::close()`, Qt will release all the resources of the corresponding widget/window, and thus FramelessHelper's custom event handler will also be removed from them at the same time. However, this will make the title bar become unresponsible if you re-open the widget/window. The current workaround for this issue is to hide the widget/window instead of closing it, if you are going to show it again later. But if you have no plan to show the widget/window again after it has been closed, you don't need to do anything to workaround this issue.
### More
Please refer to the demo projects to see more detailed usages: [examples](./examples/)
### Title Bar Design Guidance
- Microsoft: <https://docs.microsoft.com/en-us/windows/apps/design/basics/titlebar-design>
- KDE: <https://develop.kde.org/hig/>
- GNOME: <https://developer.gnome.org/hig/patterns/containers/header-bars.html>
- Apple: <https://developer.apple.com/design/human-interface-guidelines/macos/windows-and-views/window-anatomy/>
## Platform Notes
### Windows
- If DWM composition is disabled in some very rare cases (only possible on Windows 7), the top-left corner and top-right corner will appear in round shape. The round corners can be restored to square if you re-enable DWM composition.
- There's an OpenGL driver bug which will cause some frameless windows have a strange black bar right on top of your homemade title bar, and it also makes the controls in your windows shifted to the bottom-right corner for some pixels. It's a bug of your graphics card driver, specifically, your OpenGL driver, not FramelessHelper. There are some solutions provided by our users but some of them may not work in all conditions, you can pick one from them:
Solution | Principle
-------- | ---------
Upgrade the graphics driver | Try to use a newer driver which may ship with the fix
Change the system theme to "Basic" (in contrary to "Windows Aero") | Let Windows use pure software rendering
If there are multiple graphics cards, use another one instead | Try to use a different driver which may don't have such bug at all
Upgrade the system to at least Windows 11 | Windows 11 redesigned the windowing system so the bug can no longer be triggered
Remove the `WS_THICKFRAME` and `WS_OVERLAPPED` styles from the window, and maybe also add the `WS_POPUP` style at the same time, and don't do anything inside the `WM_NCCALCSIZE` block (just return `false` directly or remove/comment out the whole block) | Try to mirror Qt's `FramelessWindowHint`'s behavior
Use `Qt::FramelessWindowHint` instead of doing the `WM_NCCALCSIZE` trick | Qt's rendering code path is totally different between these two solutions
Force Qt to use the ANGLE backend instead of the Desktop OpenGL | ANGLE will translate OpenGL directives into D3D ones
Force Qt to use pure software rendering instead of rendering through OpenGL | Qt is not using OpenGL at all
Force Qt to use the Mesa 3D libraries instead of normal OpenGL | Try to use a different OpenGL implementation
Use Direct3D/Vulkan/Metal instead of OpenGL | Just don't use the buggy OpenGL
If you are lucky enough, one of them may fix the issue for you. If not, you may try to use multiple solutions together. **But I can't guarantee the issue can 100% be fixed.**
- Due to there are many sub-versions of Windows 10, it's highly recommended to use the latest version of Windows 10, at least **no older than Windows 10 1809**. If you try to use this framework on some very old Windows 10 versions such as 1507 or 1607, there may be some compatibility issues. Using this framework on Windows 7 is also supported but not recommended. To get the most stable behavior and the best appearance, you should use it on the latest version of Windows 10 or Windows 11.
- To make the snap layout work as expected, there are some additional rules for your homemade system buttons to follow:
- **Add a manifest file to your application. In the manifest file, you need to claim your application supports Windows 11 explicitly. This step is VERY VERY IMPORTANT. Without this step, the snap layout feature can't be enabled.**
- Make sure there are two public invokable functions (slot functions are always invokable): `void setHovered(bool)` and `void setPressed(bool)`. These two functions will be invoked by FramelessHelper when the button is being hovered or pressed. You should change the button's visual state inside these functions. If you need to show tooltips, you'll have to do it manually in these functions.
- Make sure there's a public signal: `void clicked()`. When the button is being clicked, that signal will be triggered by FramelessHelper. You should connect your event handler to that signal.
- For Qt Quick applications, for the C++ side, you need to inherit your button from the `QQuickAbstractButton` class, for the QML side, you need to inherit your button from the `Button` type (from the `QtQuick.Controls.Basic` module). They have all the invokable functions and signals we need, so no more extra work is needed.
- Don't forget to call `setSystemButton()` for each button to let FramelessHelper know which is the minimize/maximize/close button.
- System buttons will not be able to receive any actual mouse and keyboard events so there's no need to handle these events inside these buttons. That's also why we need to set the button's visual state manually.
- I know this is making everything complicated but unfortunately we can't avoid this mess if we need to support the snap layout feature. Snap layout is really only designed for the original standard window frame, so if we want to forcely support it without a standard window frame, many black magic will be needed.
### Linux
- FramelessHelper will force your application to use the _XCB_ platform plugin when running on Wayland.
- The resize area is inside of the window.
### macOS
- Some users reported that the window is not resizable on some old macOS versions.
## FAQs
### `When running on Win10, it seems the top border is missing? But the demo applications still have it?`
`FramelessHelper` hides the system title bar by removing the whole top part of the window frame, including the top border. There's no way to only remove the system title bar but still preserve the top border at the same time, even Microsoft themself can't do that either. The exact reason is unknown to non-Microsoft developers, and I have no interest in digging into all the magic behind it. So you'll have to draw one manually yourself to pretend the top border is still there. You can retrieve it's height and color through official DWM APIs. Please refer to the documentation of [`DwmGetWindowAttribute()`](https://docs.microsoft.com/en-us/windows/win32/api/dwmapi/nf-dwmapi-dwmgetwindowattribute) and [`DwmGetColorizationColor()`](https://docs.microsoft.com/en-us/windows/win32/api/dwmapi/nf-dwmapi-dwmgetcolorizationcolor). The demo applications still have the top border because their main windows all inherit from `FramelessWidget` or `FramelessMainWindow`, which will draw the top border for you internally. As for Qt Quick, the QML type `FramelessWindow` will also draw the top border.
### `When running on Wayland, dragging the title bar causes crash?`
You need to force Qt to use the **XCB** QPA when running on Wayland. Try setting the environment variable `QT_QPA_PLATFORM` (case sensitive) to `xcb` (case sensitive) before instantiating any `Q(Gui)Application` instances. Or just call `void FramelessHelper::Widgets/Quick::initialize()` in your `main` function, this function will take care of it for you.
### `I can see the black background during window resizing?`
First of all, it's a Qt issue, not caused by FramelessHelper. And it should not be possible for Qt Widgets applications. It's a common issue for Qt Quick applications. Most of the time it's caused by D3D11/Vulkan/Metal because they are not good at dealing with texture resizing operations. If you really want to fix this issue, you can try to change Qt's RHI backend to **OpenGL** (be careful of the bug of your graphics card driver) or **Software** (if you don't care about performance). And please keep in mind that this issue is not fixable from outside of Qt.
### `Can I preserve the window frame border even on Win7? How does Google Chrome/Microsoft Edge's installer achieve that?`
Short answer: it's impossible. Full explaination: of course we can use the same technique we use on Win10 to remove the whole top part of the window and preserve the other three frame borders at the same time, but on Win10 we can bring the top border back, either by doing some black magic in the `WM_PAINT` handler or draw a thin frame border manually ourself, however, it's impossible to do this on Win7. I've tried it on Win7 already and sadly the result is the `WM_PAINT` trick won't work on Win7, and we also can't draw a frame border which looks very similar to the original one (a semi-transparent rectangle, blended with system's accent color and the visual content behind the window, also with some blur effect applied). But it seems Google Chrome/Microsoft Edge's installer have achieved what we wanted to do, how? Well, their installer is open source and I've read it's code already. They achieve that by overlapping two windows, one normal window on the bottom, another border-less window on the top to cover the bottom window's title bar. They draw their homemade title bar on the border-less window and use it to emulate the standard title bar's behavior. The original title bar provided by the system is still there, but it can't be seen by anyone just because it's covered by another window. I admit it's a good solution in such cases but for our library it's not appropriate because the code complexity will blow up.
## License
```text
MIT License
Copyright (C) 2021 by wangwenx190 (Yuhang Zhao)
Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,74 +0,0 @@
# FramelessHelper (UNIX version)
## Screenshots
TODO
## Features
- Frameless (of course!).
- Draggable.
- Resizable.
- Cross-platform: Windows, X11, Wayland, macOS (however, it doesn't look good on Windows, so you may want to try [`FramelessHelperWin`](/framelesshelper_win32.h) instead).
As for the frame shadow and other window features, they mainly depend on your window manager.
## Usage
```cpp
QWidget widget;
FramelessHelper helper;
helper.removeWindowFrame(&widget);
widget.show();
```
### Some details
```cpp
helper.setHitTestVisibleInChrome(window, widget, true);
```
## IMPORTANT NOTES
- For [QDockWidget](https://doc.qt.io/qt-6/qdockwidget.html), it supports set a custom title bar widget officially, no need to use this library, and this library is known to be not working well for QDockWidgets. Please refer to <https://doc.qt.io/qt-6/qdockwidget.html#setTitleBarWidget> for more details.
- Only top level windows ([QWindow](https://doc.qt.io/qt-6/qwindow.html) and [QWidget](https://doc.qt.io/qt-6/qwidget.html)) are supported.
## Requirements
| Component | Requirement | Additional Information |
| --- | --- | --- |
| Qt | >= 5.15 | This code uses two functions, [`startSystemMove`](https://doc.qt.io/qt-5/qwindow.html#startSystemMove) and [`startSystemResize`](https://doc.qt.io/qt-5/qwindow.html#startSystemResize), which are introduced in Qt 5.15 |
| Compiler | >= C++11 | MSVC, MinGW, Clang-CL, Intel-CL / GCC, Clang, ICC are all supported |
## References for developers
- <https://doc.qt.io/qt-5/qobject.html#installEventFilter>
- <https://doc.qt.io/qt-5/qobject.html#removeEventFilter>
- <https://doc.qt.io/qt-5/qwindow.html#startSystemMove>
- <https://doc.qt.io/qt-5/qwindow.html#startSystemResize>
## License
```text
MIT License
Copyright (C) 2021 by wangwenx190 (Yuhang Zhao)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```

View File

@ -1,182 +0,0 @@
# FramelessHelper (Win32 version)
## Screenshots
![Quick_Acrylic_Win7](/screenshots/quick_acrylic_win7.png)
## Features
- Frameless but have frame shadow.
- Draggable and resizable.
- Automatically high DPI scaling.
- Multi-monitor support (different resolution and DPI).
- Have animations when minimizing, maximizing and restoring.
- Support tiled and stack windows by DWM.
- Won't cover the task bar when maximized.
- Won't block the auto-hide task bar when maximized.
## Usage
```cpp
QWidget widget;
// Qt's internal function. Make sure it's a top level window.
widget.createWinId();
// Do this before the widget is shown.
WinNativeEventFilter::addFramelessWindow(widget.windowHandle());
widget.show();
```
Please refer to [the QWidget example](/examples/widget/) for more detailed information.
### Some details
```cpp
QWindow *win = widget.windowHandle();
// All the following values should not be DPI-aware, just use the
// original numbers, assuming the scale factor is 1.0, don't scale
// them yourself, this code will do the scaling according to DPI
// internally and automatically.
// Maximum window size
win->setMaximumSize(1280, 720);
// Minimum window size
win->setMinimumSize(800, 540);
// The **POINTER** of a QWidget or QQuickItem
WinNativeEventFilter::setHitTestVisibleInChrome(win, ui->minimizeBtn, true);
// The frameless window is resizable by default.
win->setFlag(Qt::MSWindowsFixedSizeDialogHint);
```
## IMPORTANT NOTES
- For [QDockWidget](https://doc.qt.io/qt-6/qdockwidget.html), it supports set a custom title bar widget officially, no need to use this library, and this library is known to be not working well for QDockWidgets. Please refer to <https://doc.qt.io/qt-6/qdockwidget.html#setTitleBarWidget> for more details.
- Only top level windows ([QWindow](https://doc.qt.io/qt-6/qwindow.html) and [QWidget](https://doc.qt.io/qt-6/qwidget.html)) are supported.
- There are some known issues when DWM composition is disabled. This is unsupported and not tested and will not be fixed. However, PRs are always welcome.
- High DPI scaling must be enabled for your application otherwise some Win32 APIs may return wrong value and thus it may result in unexpected behavior.
## Supported Platforms
Windows 7 ~ 10, 32 bit & 64 bit.
The code itself should be able to work on Windows Vista in theory, but Qt5 has dropped Vista support long time ago. And Qt6 will only support Win10.
## Requirements
| Component | Requirement | Additional Information |
| --- | --- | --- |
| Qt | >= 5.6 | Only the `core` and `gui` modules are required |
| Compiler | >= C++11 | MSVC, MinGW, Clang-CL, Intel-CL or cross compile from Linux are all supported |
## Known Bugs
Please refer to <https://github.com/wangwenx190/framelesshelper/issues> for more information.
## Notes for developers
- As you may have found, if you use this code, the resize areas will be inside the frameless window, however, a normal Win32 window can be resized outside of it. Here is the reason: the `WS_THICKFRAME` window style will cause a window has three transparent areas beside the window's left, right and bottom edge. Their width/height is 8px if the window is not scaled. In most cases, they are totally invisible. It's DWM's responsibility to draw and control them. They exist to let the user resize the window, visually outside of it. They are in the window area, but not the client area, so they are in the non-client area actually. But we have turned the whole window area into client area in `WM_NCCALCSIZE`, so the three transparent resize areas also become a part of the client area and thus they become visible. When we resize the window, it looks like we are resizing inside of it, however, that's because the transparent resize areas are visible now, we ARE resizing outside of the window actually. But I don't know how to make them become transparent again without breaking the frame shadow drawn by DWM. If you really want to solve it, you can try to embed your window into a larger transparent window and draw the frame shadow yourself. [See the discussions here](https://github.com/wangwenx190/framelesshelper/issues/3) for more detailed information.
- All traditional Win32 APIs are replaced by their DPI-aware ones, if there is one.
- Starting from Windows 10, normal windows usually have a one pixel width border line. After many times of trying, I still can't preserve it if I want to remove the window frame. I don't know how to solve this currently. If you really need it, you have to draw one manually by yourself. [See the discussions here](https://github.com/wangwenx190/framelesshelper/issues/3) for more detailed information.
- The frame shadow will get lost if the window is totally transparent. It can't be solved unless you draw the frame shadow manually.
- On Windows 7, if you disabled the Windows Aero, the frame shadow will be disabled as well because it's DWM's resposibility to draw the frame shadow.
- The border width (8px if not scaled), border height (8px if not scaled) and titlebar height (31px if not scaled) are acquired by Win32 APIs and are the same with other standard windows, and thus you should not modify them. Only modify them when you really have a good reason to do so.
- You can also copy all the code to `QWidget::nativeEvent()` or `QWindow::nativeEvent()`, it's the same with install a native event filter to the application.
## References for developers
### System Metrics
![System Metrics for DPI](/screenshots/SystemMetricsForDPI.png)
### Microsoft Docs
- <https://docs.microsoft.com/en-us/windows/win32/winmsg/wm-nccalcsize>
- <https://docs.microsoft.com/en-us/windows/win32/inputdev/wm-nchittest>
- <https://docs.microsoft.com/en-us/windows/win32/winmsg/wm-ncactivate>
- <https://docs.microsoft.com/en-us/windows/win32/winmsg/wm-erasebkgnd>
- <https://docs.microsoft.com/en-us/windows/win32/winmsg/wm-getminmaxinfo>
- <https://docs.microsoft.com/en-us/windows/win32/dwm/customframe>
- <https://docs.microsoft.com/en-us/windows/win32/hidpi/high-dpi-desktop-application-development-on-windows>
### Windows Presentation Foundation (WPF)
- <https://github.com/dotnet/wpf/blob/master/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Shell/WindowChromeWorker.cs>
### Chromium
- <https://github.com/chromium/chromium/blob/master/ui/base/win/hwnd_metrics.cc>
- <https://github.com/chromium/chromium/blob/master/ui/display/win/screen_win.cc>
- <https://github.com/chromium/chromium/blob/master/ui/views/win/hwnd_message_handler.cc>
- <https://github.com/chromium/chromium/blob/master/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc>
- <https://github.com/chromium/chromium/blob/master/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc>
- <https://github.com/chromium/chromium/blob/master/ui/views/widget/native_widget_aura.cc>
- <https://github.com/chromium/chromium/blob/master/ui/views/widget/widget.cc>
### Mozilla Firefox
- <https://github.com/mozilla/gecko-dev/blob/master/widget/windows/nsWindow.cpp>
### Microsoft Terminal
- <https://github.com/microsoft/terminal/blob/main/src/cascadia/WindowsTerminal/IslandWindow.cpp>
- <https://github.com/microsoft/terminal/blob/main/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp>
### GitHub
- <https://github.com/rossy/borderless-window>
- <https://github.com/Bringer-of-Light/Qt-Nice-Frameless-Window>
- <https://github.com/dfct/TrueFramelessWindow>
- <https://github.com/qtdevs/FramelessHelper>
### Qt
- <https://doc.qt.io/qt-5/qcoreapplication.html#installNativeEventFilter>
- <https://doc.qt.io/qt-5/qcoreapplication.html#removeNativeEventFilter>
- <https://doc.qt.io/qt-5/qobject.html#installEventFilter>
- <https://doc.qt.io/qt-5/qobject.html#removeEventFilter>
- <https://doc.qt.io/qt-5/qwindow.html#startSystemMove>
- <https://doc.qt.io/qt-5/qwindow.html#startSystemResize>
### 窗口样式的作用
`WS_OVERLAPPEDWINDOW` = `WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX`
`WS_OVERLAPPEDWINDOW`代表了一个正常的Win32窗口也就是说它就是正常窗口默认的窗口样式`Window style`)。
`WS_OVERLAPPED`:窗口有标题栏和边界(功能性,并不是真的要有可视化的东西);`WS_CAPTION`窗口有标题栏功能并不是真的要有个可视化的标题栏而是拥有和DWM交互的能力`WS_SYSMENU`窗口可以弹出系统菜单ALT+空格);`WS_THICKFRAME`窗口有三个不可视的拖拽区域前提是非客户区存在并且拥有DWM绘制的边框阴影没有这个样式DWM一定不会绘制边框阴影只要有就一定是自绘的`WS_MINIMIZEBOX`:窗口支持最小化(与`WS_THICKFRAME`一起使用时最小化有动画);`WS_MAXIMIZEBOX`:窗口支持最大化(与`WS_THICKFRAME`一起使用时最大化有动画)。
这些窗口样式,只有`WS_SYSMENU`是可以没有的虽然这样会导致窗口无法弹出系统菜单但如果非要做也是能用其他API模拟的比如火狐和Chrome浏览器的做法如果缺少其他窗口样式会导致窗口的正常功能产生残缺比如最大化最小化时的动画丢失缺少窗口阴影等。
参考资料:<https://docs.microsoft.com/en-us/windows/win32/winmsg/window-styles>
## Special Thanks
Thanks **Lucas** for testing this code in many various conditions.
Thanks [**Shujaat Ali Khan**](https://github.com/shujaatak) for searching so many useful articles and repositories for me.
Thanks [**Julien Maille**](https://github.com/JulienMaille) for adding the `QMainWindow` example.
## License
```text
MIT License
Copyright (C) 2021 by wangwenx190 (Yuhang Zhao)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```

1
cmake Submodule

@ -0,0 +1 @@
Subproject commit 4b4b901807771eda16fb07f36a5cb40505f64087

BIN
doc/QVogenClient.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

BIN
doc/linux_dark.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 303 KiB

BIN
doc/linux_light.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 294 KiB

BIN
doc/mac_dark.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

BIN
doc/mac_light.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

BIN
doc/win_dark.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

BIN
doc/win_light.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

View File

@ -1,14 +1,34 @@
find_package(QT NAMES Qt6 Qt5 COMPONENTS Widgets)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Widgets)
#[[
MIT License
include_directories(../src)
Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
if(TARGET Qt${QT_VERSION_MAJOR}::Widgets)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
]]
if(FRAMELESSHELPER_BUILD_WIDGETS AND TARGET Qt${QT_VERSION_MAJOR}::Widgets)
add_subdirectory(widget)
add_subdirectory(mainwindow)
add_subdirectory(minimal)
#add_subdirectory(openglwidget) # Currently not functional.
add_subdirectory(dialog)
endif()
if(TARGET Qt${QT_VERSION_MAJOR}::Quick)
if(FRAMELESSHELPER_BUILD_QUICK AND TARGET Qt${QT_VERSION_MAJOR}::Quick AND (QT_VERSION_MAJOR GREATER_EQUAL 6) AND (NOT FRAMELESSHELPER_NO_PRIVATE))
add_subdirectory(quick)
endif()

View File

@ -1,22 +0,0 @@
DESTDIR = $$OUT_PWD/../../bin
CONFIG += c++17 strict_c++ utf8_source warn_on
DEFINES += \
QT_NO_CAST_FROM_ASCII \
QT_NO_CAST_TO_ASCII \
QT_NO_KEYWORDS \
QT_DEPRECATED_WARNINGS \
QT_DISABLE_DEPRECATED_BEFORE=0x060100
RESOURCES += $$PWD/images.qrc
win32 {
CONFIG += windeployqt
CONFIG -= embed_manifest_exe
LIBS += -luser32 -lshell32 -ldwmapi
RC_FILE = $$PWD/example.rc
OTHER_FILES += $$PWD/example.manifest
}
win32 {
CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../../debug -lFramelessHelperd
else: CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../../release -lFramelessHelper
} else: unix {
LIBS += -L$$OUT_PWD/../../bin -lFramelessHelper
}

View File

@ -0,0 +1,110 @@
#[[
MIT License
Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
]]
set(DEMO_NAME FramelessHelperDemo-Dialog)
if(FRAMELESSHELPER_ENABLE_UNIVERSAL_BUILD)
set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64" CACHE STRING "" FORCE)
endif()
if(FRAMELESSHELPER_EXAMPLES_STANDALONE)
cmake_minimum_required(VERSION 3.20)
project(${DEMO_NAME} VERSION 1.0)
include(../../cmake/utils.cmake)
setup_project(
QT_PROJECT
LANGUAGES CXX RC
NO_WARNING
ENABLE_LTO
)
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets)
find_package(FramelessHelper REQUIRED COMPONENTS Core Widgets)
endif()
add_executable(${DEMO_NAME})
target_sources(${DEMO_NAME} PRIVATE
../shared/log.h
../shared/log.cpp
../shared/settings.h
../shared/settings.cpp
dialog.h
dialog.cpp
main.cpp
)
if(WIN32)
set(__rc_path "${PROJECT_BINARY_DIR}/${DEMO_NAME}.rc")
generate_win32_rc_file(
PATH "${__rc_path}"
VERSION "${PROJECT_VERSION}"
COMPANY "wangwenx190"
DESCRIPTION "FramelessHelper Demo Application: Dialog"
COPYRIGHT "MIT License"
PRODUCT "FramelessHelper Demo"
ICONS "../shared/example.ico"
)
set(__manifest_path "${PROJECT_BINARY_DIR}/${DEMO_NAME}.manifest")
generate_win32_manifest_file(
PATH "${__manifest_path}"
ID "org.wangwenx190.demo.Dialog"
VERSION "${PROJECT_VERSION}"
VISTA_COMPAT
WIN7_COMPAT
WIN8_COMPAT
WIN8_1_COMPAT
WIN10_COMPAT
WIN11_COMPAT
XAML_ISLANDS_COMPAT
UTF8_CODEPAGE
)
target_sources(${DEMO_NAME} PRIVATE
"${__rc_path}"
"${__manifest_path}"
)
endif()
target_link_libraries(${DEMO_NAME} PRIVATE
Qt${QT_VERSION_MAJOR}::Widgets
FramelessHelper::Core
FramelessHelper::Widgets
)
setup_gui_app(
TARGETS ${DEMO_NAME}
BUNDLE_ID "org.wangwenx190.demo.Dialog"
BUNDLE_VERSION "1.0.0"
BUNDLE_VERSION_SHORT "1.0"
)
if(FRAMELESSHELPER_EXAMPLES_DEPLOYQT)
set(__extra_flags)
if(FRAMELESSHELPER_NO_INSTALL)
set(__extra_flags NO_INSTALL)
endif()
deploy_qt_runtime(TARGET ${DEMO_NAME} ${__extra_flags})
endif()
#dump_target_info(TARGETS ${DEMO_NAME})

163
examples/dialog/dialog.cpp Normal file
View File

@ -0,0 +1,163 @@
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "dialog.h"
#include <QtWidgets/qlabel.h>
#include <QtWidgets/qlineedit.h>
#include <QtWidgets/qcheckbox.h>
#include <QtWidgets/qdialogbuttonbox.h>
#include <QtWidgets/qpushbutton.h>
#include <QtWidgets/qboxlayout.h>
#include <QtWidgets/qfileiconprovider.h>
#include <QtWidgets/qmessagebox.h>
#include <FramelessHelper/Widgets/standardtitlebar.h>
#include <FramelessHelper/Widgets/framelesswidgetshelper.h>
#include <FramelessHelper/Widgets/standardsystembutton.h>
#include <FramelessHelper/Widgets/private/framelesswidgetshelper_p.h>
#include "../shared/settings.h"
extern template void Settings::set<QRect>(const QString &, const QString &, const QRect &);
extern template void Settings::set<qreal>(const QString &, const QString &, const qreal &);
extern template QRect Settings::get<QRect>(const QString &, const QString &);
extern template qreal Settings::get<qreal>(const QString &, const QString &);
FRAMELESSHELPER_USE_NAMESPACE
using namespace Global;
FRAMELESSHELPER_STRING_CONSTANT(Geometry)
FRAMELESSHELPER_STRING_CONSTANT(DevicePixelRatio)
Dialog::Dialog(QWidget *parent) : FramelessDialog(parent)
{
setupUi();
}
Dialog::~Dialog() = default;
void Dialog::closeEvent(QCloseEvent *event)
{
if (!parent()) {
const QString id = objectName();
Settings::set(id, kGeometry, geometry());
Settings::set(id, kDevicePixelRatio, devicePixelRatioF());
}
FramelessDialog::closeEvent(event);
}
void Dialog::setupUi()
{
setWindowTitle(tr("FramelessHelper demo application - QDialog"));
setWindowIcon(QFileIconProvider().icon(QFileIconProvider::Computer));
connect(this, &Dialog::objectNameChanged, this, [this](const QString &name){
if (name.isEmpty()) {
return;
}
setWindowTitle(windowTitle() + FRAMELESSHELPER_STRING_LITERAL(" [%1]").arg(name));
});
titleBar = new StandardTitleBar(this);
titleBar->setWindowIconVisible(true);
#ifndef Q_OS_MACOS
titleBar->maximizeButton()->hide();
#endif // Q_OS_MACOS
label = new QLabel(tr("Find &what:"));
lineEdit = new QLineEdit;
label->setBuddy(lineEdit);
caseCheckBox = new QCheckBox(tr("Match &case"));
fromStartCheckBox = new QCheckBox(tr("Search from &start"));
fromStartCheckBox->setChecked(true);
findButton = new QPushButton(tr("&Find"));
findButton->setDefault(true);
connect(findButton, &QPushButton::clicked, this, [this](){
const QString text = lineEdit->text();
if (text.isEmpty()) {
QMessageBox::warning(this, tr("Warning"), tr("You didn't enter anything in the search box."));
} else {
QMessageBox::information(this, tr("Result"), tr("You wanted to find: \"%1\".").arg(text));
}
});
moreButton = new QPushButton(tr("&More"));
moreButton->setCheckable(true);
moreButton->setAutoDefault(false);
extension = new QWidget;
wholeWordsCheckBox = new QCheckBox(tr("&Whole words"));
backwardCheckBox = new QCheckBox(tr("Search &backward"));
searchSelectionCheckBox = new QCheckBox(tr("Search se&lection"));
buttonBox = new QDialogButtonBox(Qt::Vertical);
buttonBox->addButton(findButton, QDialogButtonBox::ActionRole);
buttonBox->addButton(moreButton, QDialogButtonBox::ActionRole);
connect(moreButton, &QPushButton::toggled, extension, &QWidget::setVisible);
QVBoxLayout *extensionLayout = new QVBoxLayout;
extensionLayout->setContentsMargins(0, 0, 0, 0);
extensionLayout->addWidget(wholeWordsCheckBox);
extensionLayout->addWidget(backwardCheckBox);
extensionLayout->addWidget(searchSelectionCheckBox);
extension->setLayout(extensionLayout);
QHBoxLayout *topLeftLayout = new QHBoxLayout;
topLeftLayout->addWidget(label);
topLeftLayout->addWidget(lineEdit);
QVBoxLayout *leftLayout = new QVBoxLayout;
leftLayout->addLayout(topLeftLayout);
leftLayout->addWidget(caseCheckBox);
leftLayout->addWidget(fromStartCheckBox);
QGridLayout *controlsLayout = new QGridLayout;
controlsLayout->setContentsMargins(11, 11, 11, 11);
controlsLayout->addLayout(leftLayout, 0, 0);
controlsLayout->addWidget(buttonBox, 0, 1);
controlsLayout->addWidget(extension, 1, 0, 1, 2);
controlsLayout->setRowStretch(2, 1);
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->setContentsMargins(0, 0, 0, 0);
mainLayout->setSizeConstraint(QLayout::SetFixedSize);
mainLayout->addWidget(titleBar);
mainLayout->addLayout(controlsLayout);
setLayout(mainLayout);
extension->hide();
FramelessWidgetsHelper *helper = FramelessWidgetsHelper::get(this);
helper->setTitleBarWidget(titleBar);
#ifndef Q_OS_MACOS
helper->setSystemButton(titleBar->minimizeButton(), SystemButtonType::Minimize);
helper->setSystemButton(titleBar->maximizeButton(), SystemButtonType::Maximize);
helper->setSystemButton(titleBar->closeButton(), SystemButtonType::Close);
#endif // Q_OS_MACOS
// Special hack to disable the overriding of the mouse cursor, it's totally different
// with making the window un-resizable: we still want the window be able to resize
// programatically, but we also want the user not able to resize the window manually.
// So apparently we can't use QWidget::setFixedWidth/Height/Size() here.
FramelessWidgetsHelperPrivate::get(helper)->setProperty(kDontOverrideCursorVar, true);
}
void Dialog::waitReady()
{
FramelessWidgetsHelper *helper = FramelessWidgetsHelper::get(this);
helper->waitForReady();
const QString id = objectName();
const auto savedGeometry = Settings::get<QRect>(id, kGeometry);
if (savedGeometry.isValid() && !parent()) {
const auto savedDpr = Settings::get<qreal>(id, kDevicePixelRatio);
// Qt doesn't support dpr < 1.
const qreal oldDpr = std::max(savedDpr, qreal(1));
const qreal scale = (devicePixelRatioF() / oldDpr);
setGeometry({savedGeometry.topLeft() * scale, savedGeometry.size() * scale});
} else {
helper->moveWindowToDesktopCenter();
}
}

51
examples/dialog/dialog.h Normal file
View File

@ -0,0 +1,51 @@
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#pragma once
#include <FramelessHelper/Widgets/framelessdialog.h>
QT_BEGIN_NAMESPACE
class QCheckBox;
class QDialogButtonBox;
class QGroupBox;
class QLabel;
class QLineEdit;
class QPushButton;
QT_END_NAMESPACE
FRAMELESSHELPER_BEGIN_NAMESPACE
class StandardTitleBar;
FRAMELESSHELPER_END_NAMESPACE
class Dialog : public FRAMELESSHELPER_PREPEND_NAMESPACE(FramelessDialog)
{
Q_OBJECT
Q_DISABLE_COPY_MOVE(Dialog)
public:
explicit Dialog(QWidget *parent = nullptr);
~Dialog() override;
void waitReady();
protected:
void closeEvent(QCloseEvent *event) override;
private:
void setupUi();
private:
FRAMELESSHELPER_PREPEND_NAMESPACE(StandardTitleBar) *titleBar = nullptr;
QLabel *label = nullptr;
QLineEdit *lineEdit = nullptr;
QCheckBox *caseCheckBox = nullptr;
QCheckBox *fromStartCheckBox = nullptr;
QCheckBox *wholeWordsCheckBox = nullptr;
QCheckBox *searchSelectionCheckBox = nullptr;
QCheckBox *backwardCheckBox = nullptr;
QDialogButtonBox *buttonBox = nullptr;
QPushButton *findButton = nullptr;
QPushButton *moreButton = nullptr;
QWidget *extension = nullptr;
};

67
examples/dialog/main.cpp Normal file
View File

@ -0,0 +1,67 @@
/*
* MIT License
*
* Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <QtWidgets/qapplication.h>
#include <FramelessHelper/Core/private/framelessconfig_p.h>
#include "dialog.h"
#include "../shared/log.h"
FRAMELESSHELPER_USE_NAMESPACE
#define CREATE_WINDOW(Name) \
const auto Name = std::make_unique<Dialog>(); \
Name->setObjectName(FRAMELESSHELPER_STRING_LITERAL(#Name)); \
Name->waitReady(); \
Name->show();
int main(int argc, char *argv[])
{
Log::setup(FRAMELESSHELPER_STRING_LITERAL("dialog"));
// Not necessary, but better call this function, before the construction
// of any Q(Core|Gui)Application instances.
FramelessHelper::Widgets::initialize();
#if 0
if (!qEnvironmentVariableIsSet("QT_WIDGETS_RHI")) {
qputenv("QT_WIDGETS_RHI", FRAMELESSHELPER_BYTEARRAY_LITERAL("1"));
}
#endif
const auto application = std::make_unique<QApplication>(argc, argv);
// Must be called after QGuiApplication has been constructed, we are using
// some private functions from QPA which won't be available until there's
// a QGuiApplication instance.
FramelessHelper::Core::setApplicationOSThemeAware();
FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow);
//FramelessConfig::instance()->set(Global::Option::DisableLazyInitializationForMicaMaterial);
CREATE_WINDOW(dialog1)
CREATE_WINDOW(dialog2)
CREATE_WINDOW(dialog3)
return QCoreApplication::exec();
}

View File

@ -1,34 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity type="win32" name="org.wangwenx190.framelesshelper.demo" version="1.0.0.0"/>
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/>
</dependentAssembly>
</dependency>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="asInvoker" uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- Windows 7 and Windows Server 2008 R2 -->
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
<!-- Windows 8 and Windows Server 2012 -->
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
<!-- Windows 8.1 and Windows Server 2012 R2 -->
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
<!-- Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
</application>
</compatibility>
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">True/PM</dpiAware>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2, PerMonitor</dpiAwareness>
</windowsSettings>
</application>
</assembly>

View File

@ -1,4 +0,0 @@
TEMPLATE = subdirs
CONFIG -= ordered
qtHaveModule(widgets): SUBDIRS += widget mainwindow
qtHaveModule(quick): SUBDIRS += quick

View File

@ -1,12 +0,0 @@
<RCC>
<qresource prefix="/">
<file>images/button_minimize_black.svg</file>
<file>images/button_minimize_white.svg</file>
<file>images/button_maximize_black.svg</file>
<file>images/button_maximize_white.svg</file>
<file>images/button_restore_black.svg</file>
<file>images/button_restore_white.svg</file>
<file>images/button_close_black.svg</file>
<file>images/button_close_white.svg</file>
</qresource>
</RCC>

View File

@ -1,5 +0,0 @@
All the SVG images in this folder are created by me, using Inkscape. No images are downloaded from the Internet, not even one pixel.
Since I copied the screenshot (when the scale factor is 1.0) pixel by pixel, they should be exactly the same with the real system buttons, in theory.
Anyone can use them freely.

View File

@ -1,6 +0,0 @@
<svg width="45pt" height="30pt" version="1.1" viewBox="0 0 15.875 10.583" xmlns="http://www.w3.org/2000/svg">
<g fill="none" stroke="#000" stroke-width=".17639">
<path d="m6.1295 3.6601 3.2632 3.2632z"/>
<path d="m9.3927 3.6601-3.2632 3.2632z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 264 B

View File

@ -1,6 +0,0 @@
<svg width="45pt" height="30pt" version="1.1" viewBox="0 0 15.875 10.583" xmlns="http://www.w3.org/2000/svg">
<g fill="none" stroke="#fff" stroke-width=".17639">
<path d="m6.1295 3.6601 3.2632 3.2632z"/>
<path d="m9.3927 3.6601-3.2632 3.2632z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 264 B

View File

@ -1,3 +0,0 @@
<svg width="45pt" height="30pt" version="1.1" viewBox="0 0 15.875 10.583" xmlns="http://www.w3.org/2000/svg">
<rect x="6.1736" y="3.7042" width="3.175" height="3.175" fill="none" stroke="#000" stroke-width=".35278"/>
</svg>

Before

Width:  |  Height:  |  Size: 225 B

View File

@ -1,3 +0,0 @@
<svg width="45pt" height="30pt" version="1.1" viewBox="0 0 15.875 10.583" xmlns="http://www.w3.org/2000/svg">
<rect x="6.1736" y="3.7042" width="3.175" height="3.175" fill="none" stroke="#fff" stroke-width=".35278"/>
</svg>

Before

Width:  |  Height:  |  Size: 225 B

View File

@ -1,3 +0,0 @@
<svg width="45pt" height="30pt" version="1.1" viewBox="0 0 15.875 10.583" xmlns="http://www.w3.org/2000/svg">
<path d="m6.35 5.4681h3.5278z" fill="none" stroke="#000" stroke-width=".35278"/>
</svg>

Before

Width:  |  Height:  |  Size: 199 B

View File

@ -1,3 +0,0 @@
<svg width="45pt" height="30pt" version="1.1" viewBox="0 0 15.875 10.583" xmlns="http://www.w3.org/2000/svg">
<path d="m6.35 5.4681h3.5278z" fill="none" stroke="#fff" stroke-width=".35278"/>
</svg>

Before

Width:  |  Height:  |  Size: 199 B

View File

@ -1,11 +0,0 @@
<svg width="45pt" height="30pt" version="1.1" viewBox="0 0 15.875 10.583" xmlns="http://www.w3.org/2000/svg">
<g fill="none" stroke="#000">
<rect x="6.1736" y="4.4097" width="2.4694" height="2.4694" stroke-width=".35278"/>
<g stroke-width=".35278">
<path d="m6.8792 4.2333v-0.70556z"/>
<path d="m7.0556 3.7042h2.4694z"/>
<path d="m9.3486 3.8806v2.4694z"/>
<path d="m9.1722 6.1736h-0.35278z"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 430 B

View File

@ -1,11 +0,0 @@
<svg width="45pt" height="30pt" version="1.1" viewBox="0 0 15.875 10.583" xmlns="http://www.w3.org/2000/svg">
<g fill="none" stroke="#fff">
<rect x="6.1736" y="4.4097" width="2.4694" height="2.4694" stroke-width=".35278"/>
<g stroke-width=".35278">
<path d="m6.8792 4.2333v-0.70556z"/>
<path d="m7.0556 3.7042h2.4694z"/>
<path d="m9.3486 3.8806v2.4694z"/>
<path d="m9.1722 6.1736h-0.35278z"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 430 B

View File

@ -1,41 +1,115 @@
set(CMAKE_INCLUDE_CURRENT_DIR ON)
#[[
MIT License
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
find_package(QT NAMES Qt6 Qt5 COMPONENTS Widgets REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Widgets REQUIRED)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
set(SOURCES
../images.qrc
TitleBar.ui
MainWindow.ui
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
]]
set(DEMO_NAME FramelessHelperDemo-MainWindow)
if(FRAMELESSHELPER_ENABLE_UNIVERSAL_BUILD)
set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64" CACHE STRING "" FORCE)
endif()
if(FRAMELESSHELPER_EXAMPLES_STANDALONE)
cmake_minimum_required(VERSION 3.20)
project(${DEMO_NAME} VERSION 1.0)
include(../../cmake/utils.cmake)
setup_project(
QT_PROJECT
LANGUAGES CXX RC
NO_WARNING
ENABLE_LTO
)
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets)
find_package(FramelessHelper REQUIRED COMPONENTS Core Widgets)
endif()
add_executable(${DEMO_NAME})
target_sources(${DEMO_NAME} PRIVATE
../shared/log.h
../shared/log.cpp
../shared/settings.h
../shared/settings.cpp
../dialog/dialog.h
../dialog/dialog.cpp
../widget/widget.h
../widget/widget.cpp
mainwindow.ui
mainwindow.h
mainwindow.cpp
main.cpp
)
if(WIN32)
enable_language(RC)
list(APPEND SOURCES ../example.rc ../example.manifest)
set(__rc_path "${PROJECT_BINARY_DIR}/${DEMO_NAME}.rc")
generate_win32_rc_file(
PATH "${__rc_path}"
VERSION "${PROJECT_VERSION}"
COMPANY "wangwenx190"
DESCRIPTION "FramelessHelper Demo Application: MainWindow"
COPYRIGHT "MIT License"
PRODUCT "FramelessHelper Demo"
ICONS "../shared/example.ico"
)
set(__manifest_path "${PROJECT_BINARY_DIR}/${DEMO_NAME}.manifest")
generate_win32_manifest_file(
PATH "${__manifest_path}"
ID "org.wangwenx190.demo.MainWindow"
VERSION "${PROJECT_VERSION}"
VISTA_COMPAT
WIN7_COMPAT
WIN8_COMPAT
WIN8_1_COMPAT
WIN10_COMPAT
WIN11_COMPAT
XAML_ISLANDS_COMPAT
UTF8_CODEPAGE
)
target_sources(${DEMO_NAME} PRIVATE
"${__rc_path}"
"${__manifest_path}"
)
endif()
add_executable(MainWindow WIN32 ${SOURCES})
target_link_libraries(MainWindow PRIVATE
target_link_libraries(${DEMO_NAME} PRIVATE
Qt${QT_VERSION_MAJOR}::Widgets
wangwenx190::FramelessHelper
FramelessHelper::Core
FramelessHelper::Widgets
)
target_compile_definitions(MainWindow PRIVATE
QT_NO_CAST_FROM_ASCII
QT_NO_CAST_TO_ASCII
QT_NO_KEYWORDS
QT_DEPRECATED_WARNINGS
QT_DISABLE_DEPRECATED_BEFORE=0x060100
setup_gui_app(
TARGETS ${DEMO_NAME}
BUNDLE_ID "org.wangwenx190.demo.MainWindow"
BUNDLE_VERSION "1.0.0"
BUNDLE_VERSION_SHORT "1.0"
)
if(WIN32)
target_link_libraries(MainWindow PRIVATE dwmapi)
if(FRAMELESSHELPER_EXAMPLES_DEPLOYQT)
set(__extra_flags)
if(FRAMELESSHELPER_NO_INSTALL)
set(__extra_flags NO_INSTALL)
endif()
deploy_qt_runtime(TARGET ${DEMO_NAME} ${__extra_flags})
endif()
#dump_target_info(TARGETS ${DEMO_NAME})

View File

@ -1,290 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TitleBar</class>
<widget class="QWidget" name="TitleBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>552</width>
<height>31</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>31</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>31</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">QMenuBar {
background-color: transparent;
height: 23px;
}
#iconButton, #minimizeButton, #maximizeButton, #closeButton {
border-style: none;
background-color: transparent;
}
#minimizeButton:hover, #maximizeButton:hover {
background-color: #80c7c7c7;
}
#minimizeButton:pressed, #maximizeButton:pressed {
background-color: #80808080;
}
#closeButton:hover {
background-color: #e81123;
icon: url(:/images/button_close_white.svg);
}
#closeButton:pressed {
background-color: #8c0a15;
}</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QPushButton" name="iconButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>30</width>
<height>30</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>30</width>
<height>30</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="titleLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<family>Arial</family>
<pointsize>9</pointsize>
</font>
</property>
<property name="text">
<string>Window Title</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="minimizeButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>45</width>
<height>30</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>45</width>
<height>30</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="contextMenuPolicy">
<enum>Qt::NoContextMenu</enum>
</property>
<property name="toolTip">
<string>Minimize</string>
</property>
<property name="icon">
<iconset resource="../images.qrc">
<normaloff>:/images/button_minimize_black.svg</normaloff>:/images/button_minimize_black.svg</iconset>
</property>
<property name="iconSize">
<size>
<width>45</width>
<height>30</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="maximizeButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>45</width>
<height>30</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>45</width>
<height>30</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="contextMenuPolicy">
<enum>Qt::NoContextMenu</enum>
</property>
<property name="toolTip">
<string>Maximize</string>
</property>
<property name="icon">
<iconset resource="../images.qrc">
<normaloff>:/images/button_maximize_black.svg</normaloff>
<normalon>:/images/button_restore_black.svg</normalon>:/images/button_maximize_black.svg</iconset>
</property>
<property name="iconSize">
<size>
<width>45</width>
<height>30</height>
</size>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="closeButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>45</width>
<height>30</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>45</width>
<height>30</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="contextMenuPolicy">
<enum>Qt::NoContextMenu</enum>
</property>
<property name="toolTip">
<string>Close</string>
</property>
<property name="icon">
<iconset resource="../images.qrc">
<normaloff>:/images/button_close_black.svg</normaloff>:/images/button_close_black.svg</iconset>
</property>
<property name="iconSize">
<size>
<width>45</width>
<height>30</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources>
<include location="../images.qrc"/>
<include location="../images.qrc"/>
<include location="../images.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -1,7 +1,7 @@
/*
* MIT License
*
* Copyright (C) 2021 by wangwenx190 (Yuhang Zhao)
* Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@ -23,23 +23,45 @@
*/
#include <QtWidgets/qapplication.h>
#include <FramelessHelper/Core/private/framelessconfig_p.h>
#include "mainwindow.h"
#include "../shared/log.h"
FRAMELESSHELPER_USE_NAMESPACE
#define CREATE_WINDOW(Name) \
const auto Name = std::make_unique<MainWindow>(); \
Name->setObjectName(FRAMELESSHELPER_STRING_LITERAL(#Name)); \
Name->waitReady(); \
Name->show();
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
#endif
Log::setup(FRAMELESSHELPER_STRING_LITERAL("mainwindow"));
// Not necessary, but better call this function, before the construction
// of any Q(Core|Gui)Application instances.
FramelessHelper::Widgets::initialize();
#if 0
if (!qEnvironmentVariableIsSet("QT_WIDGETS_RHI")) {
qputenv("QT_WIDGETS_RHI", FRAMELESSHELPER_BYTEARRAY_LITERAL("1"));
}
#endif
QApplication application(argc, argv);
const auto application = std::make_unique<QApplication>(argc, argv);
MainWindow mainWindow;
mainWindow.show();
// Must be called after QGuiApplication has been constructed, we are using
// some private functions from QPA which won't be available until there's
// a QGuiApplication instance.
FramelessHelper::Core::setApplicationOSThemeAware();
return QApplication::exec();
FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow);
//FramelessConfig::instance()->set(Global::Option::DisableLazyInitializationForMicaMaterial);
CREATE_WINDOW(mainWindow1)
CREATE_WINDOW(mainWindow2)
CREATE_WINDOW(mainWindow3)
return QCoreApplication::exec();
}

View File

@ -1,7 +1,7 @@
/*
* MIT License
*
* Copyright (C) 2021 by wangwenx190 (Yuhang Zhao)
* Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@ -23,158 +23,131 @@
*/
#include "mainwindow.h"
#include <QtGui/qpainter.h>
#include "core/utilities.h"
#include "ui_mainwindow.h"
#include <QtWidgets/qboxlayout.h>
#include <QtWidgets/qfileiconprovider.h>
#include <FramelessHelper/Core/utils.h>
#include <FramelessHelper/Widgets/standardtitlebar.h>
#include <FramelessHelper/Widgets/standardsystembutton.h>
#include <FramelessHelper/Widgets/framelesswidgetshelper.h>
#include "../shared/settings.h"
#include "../widget/widget.h"
#include "../dialog/dialog.h"
extern template void Settings::set<QRect>(const QString &, const QString &, const QRect &);
extern template void Settings::set<qreal>(const QString &, const QString &, const qreal &);
extern template void Settings::set<QByteArray>(const QString &, const QString &, const QByteArray &);
extern template QRect Settings::get<QRect>(const QString &, const QString &);
extern template qreal Settings::get<qreal>(const QString &, const QString &);
extern template QByteArray Settings::get<QByteArray>(const QString &, const QString &);
FRAMELESSHELPER_USE_NAMESPACE
MainWindow::MainWindow(QWidget *parent, Qt::WindowFlags flags) : QMainWindow(parent, flags)
using namespace Global;
FRAMELESSHELPER_STRING_CONSTANT(Geometry)
FRAMELESSHELPER_STRING_CONSTANT(State)
FRAMELESSHELPER_STRING_CONSTANT(DevicePixelRatio)
MainWindow::MainWindow(QWidget *parent, const Qt::WindowFlags flags) : FramelessMainWindow(parent, flags)
{
setAttribute(Qt::WA_DontCreateNativeAncestors);
createWinId();
initialize();
}
resize(800, 600);
MainWindow::~MainWindow() = default;
appMainWindow = new Ui::MainWindow;
appMainWindow->setupUi(this);
void MainWindow::closeEvent(QCloseEvent *event)
{
if (!parent()) {
const QString id = objectName();
Settings::set(id, kGeometry, geometry());
Settings::set(id, kState, saveState());
Settings::set(id, kDevicePixelRatio, devicePixelRatioF());
}
FramelessMainWindow::closeEvent(event);
}
m_titleBar = new QWidget(this);
titleBarWidget = new Ui::TitleBar;
titleBarWidget->setupUi(m_titleBar);
void MainWindow::initialize()
{
m_titleBar = new StandardTitleBar(this);
m_titleBar->setTitleLabelAlignment(Qt::AlignCenter);
m_mainWindow = new Ui::MainWindow;
m_mainWindow->setupUi(this);
QMenuBar *mb = menuBar();
titleBarWidget->horizontalLayout->insertWidget(1, mb);
QMenuBar * const mb = menuBar();
mb->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred);
mb->setStyleSheet(FRAMELESSHELPER_STRING_LITERAL(R"(
QMenuBar {
background-color: transparent;
}
QMenuBar::item {
background: transparent;
}
QMenuBar::item:selected {
background: #a8a8a8;
}
QMenuBar::item:pressed {
background: #888888;
}
)"));
const auto titleBarLayout = static_cast<QHBoxLayout *>(m_titleBar->layout());
titleBarLayout->insertWidget(0, mb);
// setMenuWidget(): make the menu widget become the first row of the window.
setMenuWidget(m_titleBar);
connect(this, &MainWindow::windowIconChanged, titleBarWidget->iconButton, &QPushButton::setIcon);
connect(this, &MainWindow::windowTitleChanged, titleBarWidget->titleLabel, &QLabel::setText);
connect(titleBarWidget->closeButton, &QPushButton::clicked, this, &MainWindow::close);
connect(titleBarWidget->minimizeButton, &QPushButton::clicked, this, &MainWindow::showMinimized);
connect(titleBarWidget->maximizeButton, &QPushButton::clicked, [this](){
if (isMaximized() || isFullScreen()) {
showNormal();
} else {
showMaximized();
FramelessWidgetsHelper *helper = FramelessWidgetsHelper::get(this);
helper->setTitleBarWidget(m_titleBar);
#ifndef Q_OS_MACOS
helper->setSystemButton(m_titleBar->minimizeButton(), SystemButtonType::Minimize);
helper->setSystemButton(m_titleBar->maximizeButton(), SystemButtonType::Maximize);
helper->setSystemButton(m_titleBar->closeButton(), SystemButtonType::Close);
#endif // Q_OS_MACOS
helper->setHitTestVisible(mb); // IMPORTANT!
setWindowTitle(tr("FramelessHelper demo application - QMainWindow"));
setWindowIcon(QFileIconProvider().icon(QFileIconProvider::Computer));
connect(this, &MainWindow::objectNameChanged, this, [this](const QString &name){
if (name.isEmpty()) {
return;
}
setWindowTitle(windowTitle() + FRAMELESSHELPER_STRING_LITERAL(" [%1]").arg(name));
});
connect(this, &MainWindow::windowStateChanged, [this](){
titleBarWidget->maximizeButton->setChecked(isMaximized());
titleBarWidget->maximizeButton->setToolTip(isMaximized() ? tr("Restore") : tr("Maximize"));
connect(m_mainWindow->pushButton, &QPushButton::clicked, this, [this]{
const auto dialog = new Dialog(this);
dialog->waitReady();
dialog->setAttribute(Qt::WA_DeleteOnClose);
dialog->exec();
});
connect(appMainWindow->uninstallBtn, &QPushButton::clicked, [this]() {
this->m_helper->uninstall();
connect(m_mainWindow->pushButton_2, &QPushButton::clicked, this, [this]{
const auto widget = new Widget(this);
widget->waitReady();
widget->setAttribute(Qt::WA_DeleteOnClose);
widget->show();
});
connect(appMainWindow->installBtn, &QPushButton::clicked, [this]() {
this->m_helper->install();
});
setWindowTitle(tr("Hello, World!"));
}
MainWindow::~MainWindow()
void MainWindow::waitReady()
{
if (titleBarWidget) {
delete titleBarWidget;
titleBarWidget = nullptr;
FramelessWidgetsHelper *helper = FramelessWidgetsHelper::get(this);
helper->waitForReady();
const QString id = objectName();
const auto savedGeometry = Settings::get<QRect>(id, kGeometry);
if (savedGeometry.isValid() && !parent()) {
const auto savedDpr = Settings::get<qreal>(id, kDevicePixelRatio);
// Qt doesn't support dpr < 1.
const qreal oldDpr = std::max(savedDpr, qreal(1));
const qreal scale = (devicePixelRatioF() / oldDpr);
setGeometry({savedGeometry.topLeft() * scale, savedGeometry.size() * scale});
} else {
helper->moveWindowToDesktopCenter();
}
if (appMainWindow) {
delete appMainWindow;
appMainWindow = nullptr;
const QByteArray savedState = Settings::get<QByteArray>(id, kState);
if (!savedState.isEmpty() && !parent()) {
restoreState(savedState);
}
}
void MainWindow::showEvent(QShowEvent *event)
{
QMainWindow::showEvent(event);
static bool inited = false;
if (!inited) {
const auto win = windowHandle();
if (win) {
m_helper = new FramelessHelper(win);
m_helper->setHitTestVisible(titleBarWidget->iconButton);
m_helper->setHitTestVisible(titleBarWidget->minimizeButton);
m_helper->setHitTestVisible(titleBarWidget->maximizeButton);
m_helper->setHitTestVisible(titleBarWidget->closeButton);
m_helper->setHitTestVisible(appMainWindow->menubar);
m_helper->setTitleBarHeight(m_titleBar->height());
m_helper->setResizeBorderThickness(4);
m_helper->install();
#ifndef Q_OS_MAC
setContentsMargins(1, 1, 1, 1);
#else // Q_OS_MAC
titleBarWidget->minimizeButton->hide();
titleBarWidget->maximizeButton->hide();
titleBarWidget->closeButton->hide();
Utilities::setStandardWindowButtonsVisibility(windowHandle(), true);
#endif // Q_OS_MAC
inited = true;
}
}
}
#ifdef Q_OS_WIN
bool MainWindow::nativeEvent(const QByteArray &eventType, void *message, long *result)
{
if (!m_helper)
return QWidget::nativeEvent(eventType, message, result);
if (m_helper->handleNativeEvent(this->windowHandle(), eventType, message, result))
return true;
else
return QWidget::nativeEvent(eventType, message, result);
}
#endif // Q_OS_WIN
#ifndef Q_OS_MAC
void MainWindow::changeEvent(QEvent *event)
{
QWidget::changeEvent(event);
bool shouldUpdate = false;
if (event->type() == QEvent::WindowStateChange) {
if (isMaximized() || isFullScreen()) {
setContentsMargins(0, 0, 0, 0);
} else if (!isMinimized()) {
setContentsMargins(1, 1, 1, 1);
}
shouldUpdate = true;
Q_EMIT windowStateChanged();
} else if (event->type() == QEvent::ActivationChange) {
shouldUpdate = true;
}
if (shouldUpdate) {
update();
}
}
void MainWindow::paintEvent(QPaintEvent *event)
{
QMainWindow::paintEvent(event);
if (windowState() == Qt::WindowNoState) {
QPainter painter(this);
const int w = width();
const int h = height();
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
using BorderLines = QList<QLine>;
#else
using BorderLines = QVector<QLine>;
#endif
const BorderLines lines = {
{0, 0, w, 0},
{w - 1, 0, w - 1, h},
{w, h - 1, 0, h - 1},
{0, h, 0, 0}
};
painter.save();
const ColorizationArea area = Utilities::getColorizationArea();
const bool colorizedBorder = ((area == ColorizationArea::TitleBar_WindowBorder)
|| (area == ColorizationArea::AllArea));
const QColor borderColor = (isActiveWindow() ? (colorizedBorder ? Utilities::getColorizationColor() : Qt::black) : Qt::darkGray);
const auto borderThickness = static_cast<qreal>(Utilities::getWindowVisibleFrameBorderThickness(winId()));
painter.setPen({borderColor, qMax(borderThickness, devicePixelRatioF())});
painter.drawLines(lines);
painter.restore();
}
}
#endif // Q_OS_MAC

View File

@ -1,7 +1,7 @@
/*
* MIT License
*
* Copyright (C) 2021 by wangwenx190 (Yuhang Zhao)
* Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@ -24,37 +24,35 @@
#pragma once
#include <QtWidgets/qmainwindow.h>
#include "ui_MainWindow.h"
#include "ui_TitleBar.h"
#include "core/framelesshelper.h"
#include <FramelessHelper/Widgets/framelessmainwindow.h>
class MainWindow : public QMainWindow
FRAMELESSHELPER_BEGIN_NAMESPACE
class StandardTitleBar;
FRAMELESSHELPER_END_NAMESPACE
namespace Ui
{
class MainWindow;
}
class MainWindow : public FRAMELESSHELPER_PREPEND_NAMESPACE(FramelessMainWindow)
{
Q_OBJECT
Q_DISABLE_COPY_MOVE(MainWindow)
public:
explicit MainWindow(QWidget *parent = nullptr, Qt::WindowFlags flags = {});
explicit MainWindow(QWidget *parent = nullptr, const Qt::WindowFlags flags = {});
~MainWindow() override;
void waitReady();
protected:
void showEvent(QShowEvent *event) override;
#ifndef Q_OS_MAC
void paintEvent(QPaintEvent *event) override;
void changeEvent(QEvent *event) override;
#endif // Q_OS_MAC
#ifdef Q_OS_WIN
bool nativeEvent(const QByteArray &eventType, void *message, long *result) override;
#endif // Q_OS_WIN
Q_SIGNALS:
void windowStateChanged();
void closeEvent(QCloseEvent *event) override;
private:
__flh_ns::FramelessHelper *m_helper = nullptr;
QWidget *m_titleBar = nullptr;
Ui::TitleBar *titleBarWidget = nullptr;
Ui::MainWindow *appMainWindow = nullptr;
void initialize();
private:
FRAMELESSHELPER_PREPEND_NAMESPACE(StandardTitleBar) *m_titleBar = nullptr;
Ui::MainWindow *m_mainWindow = nullptr;
};

View File

@ -1,7 +0,0 @@
TARGET = MainWindow
TEMPLATE = app
QT += widgets
HEADERS += mainwindow.h
SOURCES += mainwindow.cpp main.cpp
FORMS += TitleBar.ui MainWindow.ui
include($$PWD/../common.pri)

View File

@ -6,30 +6,19 @@
<rect>
<x>0</x>
<y>0</y>
<width>518</width>
<height>383</height>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<property name="windowIcon">
<iconset>
<normaloff>../windows.ico</normaloff>../windows.ico</iconset>
<string>Hello, World!</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QPushButton" name="uninstallBtn">
<widget class="QPushButton" name="pushButton_3">
<property name="text">
<string>Uninstall Frameless Window</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="installBtn">
<property name="text">
<string>Install Frameless Window</string>
<string>PushButton</string>
</property>
</widget>
</item>
@ -129,15 +118,6 @@
<height>25</height>
</size>
</property>
<property name="mouseTracking">
<bool>true</bool>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="nativeMenuBar">
<bool>true</bool>
</property>
<widget class="QMenu" name="menuItem_1">
<property name="title">
<string>Menu 1</string>

View File

@ -1,33 +0,0 @@
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
find_package(QT NAMES Qt6 Qt5 COMPONENTS Widgets REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Widgets REQUIRED)
set(SOURCES
main.cpp
flwindow.h
flwindow.cpp
)
add_executable(minimal ${SOURCES})
target_link_libraries(minimal PRIVATE
Qt${QT_VERSION_MAJOR}::Widgets
wangwenx190::FramelessHelper
)
target_compile_definitions(minimal PRIVATE
QT_NO_CAST_FROM_ASCII
QT_NO_CAST_TO_ASCII
QT_NO_KEYWORDS
QT_DEPRECATED_WARNINGS
QT_DISABLE_DEPRECATED_BEFORE=0x060100
)
if(WIN32)
target_link_libraries(minimal PRIVATE dwmapi)
endif()

View File

@ -1,77 +0,0 @@
#include "flwindow.h"
#include "core/framelesshelper.h"
#include "core/utilities.h"
#include <QScreen>
#include <QVBoxLayout>
#include <QPushButton>
FRAMELESSHELPER_USE_NAMESPACE
FLWindow::FLWindow(QWidget *parent) : FramelessWindow<QWidget>(parent)
{
setWindowFlags(Qt::FramelessWindowHint);
setupUi();
move(screen()->geometry().center() - frameGeometry().center());
}
FLWindow::~FLWindow()
{
}
void FLWindow::setupUi()
{
resize(800, 600);
m_titleBarWidget = new QWidget(this);
m_titleBarWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
m_titleBarWidget->setFixedHeight(40);
m_titleBarWidget->setStyleSheet(QString::fromLatin1("background:grey"));
m_minimizeButton = new QPushButton(m_titleBarWidget);
m_minimizeButton->setText(QStringLiteral("Min"));
m_minimizeButton->setObjectName(QStringLiteral("MinimizeButton"));
connect(m_minimizeButton, &QPushButton::clicked, this, &QWidget::showMinimized);
m_maximizeButton = new QPushButton(m_titleBarWidget);
m_maximizeButton->setText(QStringLiteral("Max"));
m_maximizeButton->setObjectName(QStringLiteral("MaximizeButton"));
connect(m_maximizeButton, &QPushButton::clicked, this, [this](){
if (isMaximized() || isFullScreen()) {
showNormal();
} else {
showMaximized();
}
});
m_closeButton = new QPushButton(m_titleBarWidget);
m_closeButton->setText(QStringLiteral("Close"));
m_closeButton->setObjectName(QStringLiteral("CloseButton"));
connect(m_closeButton, &QPushButton::clicked, this, &QWidget::close);
const auto titleBarLayout = new QHBoxLayout(m_titleBarWidget);
titleBarLayout->setContentsMargins(0, 0, 0, 0);
titleBarLayout->setSpacing(10);
titleBarLayout->addStretch();
titleBarLayout->addWidget(m_minimizeButton);
titleBarLayout->addWidget(m_maximizeButton);
titleBarLayout->addWidget(m_closeButton);
titleBarLayout->addStretch();
m_titleBarWidget->setLayout(titleBarLayout);
const auto mainLayout = new QVBoxLayout(this);
mainLayout->setContentsMargins(0, 0, 0, 0);
mainLayout->setSpacing(0);
mainLayout->addWidget(m_titleBarWidget);
mainLayout->addStretch();
setLayout(mainLayout);
setResizeBorderThickness(4);
setTitleBarHeight(m_titleBarWidget->height());
setResizable(true);
setHitTestVisible(m_minimizeButton);
setHitTestVisible(m_maximizeButton);
setHitTestVisible(m_closeButton);
}

View File

@ -1,23 +0,0 @@
#pragma once
#include <QWidget>
#include "widget/framelesswindow.h"
class QPushButton;
class FLWindow : public __flh_ns::FramelessWindow<QWidget>
{
Q_OBJECT
public:
explicit FLWindow(QWidget *parent = nullptr);
~FLWindow() override;
private:
void setupUi();
private:
QWidget *m_titleBarWidget = nullptr;
QPushButton *m_minimizeButton = nullptr;
QPushButton *m_maximizeButton = nullptr;
QPushButton *m_closeButton = nullptr;
};

View File

@ -1,25 +0,0 @@
#include <QtWidgets/qapplication.h>
#include "flwindow.h"
#include <QStyleFactory>
int main(int argc, char *argv[])
{
#if 1
QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
#endif
#endif
#endif
QApplication application(argc, argv);
application.setStyle(QStyleFactory::create(QStringLiteral("fusion")));
FLWindow win;
win.show();
return QApplication::exec();
}

View File

@ -0,0 +1,125 @@
#[[
MIT License
Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
]]
set(DEMO_NAME FramelessHelperDemo-OpenGLWidget)
if(FRAMELESSHELPER_ENABLE_UNIVERSAL_BUILD)
set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64" CACHE STRING "" FORCE)
endif()
if(FRAMELESSHELPER_EXAMPLES_STANDALONE)
cmake_minimum_required(VERSION 3.20)
project(${DEMO_NAME} VERSION 1.0)
include(../../cmake/utils.cmake)
setup_project(
QT_PROJECT
LANGUAGES CXX RC
NO_WARNING
ENABLE_LTO
)
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets OpenGL)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets OpenGL)
if(QT_VERSION_MAJOR GREATER_EQUAL 6)
find_package(Qt6 REQUIRED COMPONENTS OpenGLWidgets)
endif()
find_package(FramelessHelper REQUIRED COMPONENTS Core Widgets)
endif()
add_executable(${DEMO_NAME})
target_sources(${DEMO_NAME} PRIVATE
../shared/log.h
../shared/log.cpp
../shared/settings.h
../shared/settings.cpp
images.qrc
logo.h
logo.cpp
glwidget.h
glwidget.cpp
mainwindow.h
mainwindow.cpp
main.cpp
)
if(WIN32)
set(__rc_path "${PROJECT_BINARY_DIR}/${DEMO_NAME}.rc")
generate_win32_rc_file(
PATH "${__rc_path}"
VERSION "${PROJECT_VERSION}"
COMPANY "wangwenx190"
DESCRIPTION "FramelessHelper Demo Application: OpenGLWidget"
COPYRIGHT "MIT License"
PRODUCT "FramelessHelper Demo"
ICONS "../shared/example.ico"
)
set(__manifest_path "${PROJECT_BINARY_DIR}/${DEMO_NAME}.manifest")
generate_win32_manifest_file(
PATH "${__manifest_path}"
ID "org.wangwenx190.demo.OpenGLWidget"
VERSION "${PROJECT_VERSION}"
VISTA_COMPAT
WIN7_COMPAT
WIN8_COMPAT
WIN8_1_COMPAT
WIN10_COMPAT
WIN11_COMPAT
XAML_ISLANDS_COMPAT
UTF8_CODEPAGE
)
target_sources(${DEMO_NAME} PRIVATE
"${__rc_path}"
"${__manifest_path}"
)
endif()
target_link_libraries(${DEMO_NAME} PRIVATE
Qt${QT_VERSION_MAJOR}::Widgets
Qt${QT_VERSION_MAJOR}::OpenGL
FramelessHelper::Core
FramelessHelper::Widgets
)
if(TARGET Qt6::OpenGLWidgets)
target_link_libraries(${DEMO_NAME} PRIVATE
Qt6::OpenGLWidgets
)
endif()
setup_gui_app(
TARGETS ${DEMO_NAME}
BUNDLE_ID "org.wangwenx190.demo.OpenGLWidget"
BUNDLE_VERSION "1.0.0"
BUNDLE_VERSION_SHORT "1.0"
)
if(FRAMELESSHELPER_EXAMPLES_DEPLOYQT)
set(__extra_flags)
if(FRAMELESSHELPER_NO_INSTALL)
set(__extra_flags NO_INSTALL)
endif()
deploy_qt_runtime(TARGET ${DEMO_NAME} ${__extra_flags})
endif()
#dump_target_info(TARGETS ${DEMO_NAME})

View File

@ -0,0 +1,276 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "glwidget.h"
#include <QImage>
#include <QOpenGLTexture>
#include <QOpenGLShaderProgram>
#include <QOpenGLBuffer>
#include <QOpenGLContext>
#include <QOpenGLVertexArrayObject>
#include <QOpenGLExtraFunctions>
#include <QPropertyAnimation>
#include <QSequentialAnimationGroup>
#include <QTimer>
GLWidget::GLWidget(QWidget *parent, Qt::WindowFlags f) : QOpenGLWidget(parent, f)
{
m_world.setToIdentity();
m_world.translate(0, 0, -1);
m_world.rotate(180, 1, 0, 0);
QSequentialAnimationGroup *animGroup = new QSequentialAnimationGroup(this);
animGroup->setLoopCount(-1);
QPropertyAnimation *zAnim0 = new QPropertyAnimation(this, QByteArrayLiteral("z"));
zAnim0->setStartValue(1.5f);
zAnim0->setEndValue(10.0f);
zAnim0->setDuration(2000);
animGroup->addAnimation(zAnim0);
QPropertyAnimation *zAnim1 = new QPropertyAnimation(this, QByteArrayLiteral("z"));
zAnim1->setStartValue(10.0f);
zAnim1->setEndValue(50.0f);
zAnim1->setDuration(4000);
zAnim1->setEasingCurve(QEasingCurve::OutElastic);
animGroup->addAnimation(zAnim1);
QPropertyAnimation *zAnim2 = new QPropertyAnimation(this, QByteArrayLiteral("z"));
zAnim2->setStartValue(50.0f);
zAnim2->setEndValue(1.5f);
zAnim2->setDuration(2000);
animGroup->addAnimation(zAnim2);
animGroup->start();
QPropertyAnimation* rAnim = new QPropertyAnimation(this, QByteArrayLiteral("r"));
rAnim->setStartValue(0.0f);
rAnim->setEndValue(360.0f);
rAnim->setDuration(2000);
rAnim->setLoopCount(-1);
rAnim->start();
QTimer::singleShot(4000, this, &GLWidget::startSecondStage);
}
GLWidget::~GLWidget()
{
makeCurrent();
delete m_texture;
delete m_program;
delete m_vbo;
delete m_vao;
}
void GLWidget::startSecondStage()
{
QPropertyAnimation* r2Anim = new QPropertyAnimation(this, QByteArrayLiteral("r2"));
r2Anim->setStartValue(0.0f);
r2Anim->setEndValue(360.0f);
r2Anim->setDuration(20000);
r2Anim->setLoopCount(-1);
r2Anim->start();
}
void GLWidget::setZ(float v)
{
m_eye.setZ(v);
m_uniformsDirty = true;
update();
Q_EMIT zChanged();
}
void GLWidget::setR(float v)
{
m_r = v;
m_uniformsDirty = true;
update();
Q_EMIT rChanged();
}
void GLWidget::setR2(float v)
{
m_r2 = v;
m_uniformsDirty = true;
update();
Q_EMIT r2Changed();
}
static constexpr const char vertexShaderSource[] =
"layout(location = 0) in vec4 vertex;\n"
"layout(location = 1) in vec3 normal;\n"
"out vec3 vert;\n"
"out vec3 vertNormal;\n"
"out vec3 color;\n"
"uniform mat4 projMatrix;\n"
"uniform mat4 camMatrix;\n"
"uniform mat4 worldMatrix;\n"
"uniform mat4 myMatrix;\n"
"uniform sampler2D sampler;\n"
"void main() {\n"
" ivec2 pos = ivec2(gl_InstanceID % 32, gl_InstanceID / 32);\n"
" vec2 t = vec2(float(-16 + pos.x) * 0.8, float(-18 + pos.y) * 0.6);\n"
" float val = 2.0 * length(texelFetch(sampler, pos, 0).rgb);\n"
" mat4 wm = myMatrix * mat4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, t.x, t.y, val, 1) * worldMatrix;\n"
" color = texelFetch(sampler, pos, 0).rgb * vec3(0.4, 1.0, 0.0);\n"
" vert = vec3(wm * vertex);\n"
" vertNormal = mat3(transpose(inverse(wm))) * normal;\n"
" gl_Position = projMatrix * camMatrix * wm * vertex;\n"
"}\n";
static constexpr const char fragmentShaderSource[] =
"in highp vec3 vert;\n"
"in highp vec3 vertNormal;\n"
"in highp vec3 color;\n"
"out highp vec4 fragColor;\n"
"uniform highp vec3 lightPos;\n"
"void main() {\n"
" highp vec3 L = normalize(lightPos - vert);\n"
" highp float NL = max(dot(normalize(vertNormal), L), 0.0);\n"
" highp vec3 col = clamp(color * 0.2 + color * 0.8 * NL, 0.0, 1.0);\n"
" fragColor = vec4(col, 1.0);\n"
"}\n";
QByteArray versionedShaderCode(const char *src)
{
QByteArray versionedSrc;
if (QOpenGLContext::currentContext()->isOpenGLES())
versionedSrc.append(QByteArrayLiteral("#version 300 es\n"));
else
versionedSrc.append(QByteArrayLiteral("#version 330\n"));
versionedSrc.append(src);
return versionedSrc;
}
void GLWidget::initializeGL()
{
QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
QImage img(QStringLiteral(":/images/qtlogo.png"));
Q_ASSERT(!img.isNull());
delete m_texture;
m_texture = new QOpenGLTexture(img.scaled(32, 36).mirrored());
delete m_program;
m_program = new QOpenGLShaderProgram;
// Prepend the correct version directive to the sources. The rest is the
// same, thanks to the common GLSL syntax.
m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, versionedShaderCode(vertexShaderSource));
m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, versionedShaderCode(fragmentShaderSource));
m_program->link();
m_projMatrixLoc = m_program->uniformLocation("projMatrix");
m_camMatrixLoc = m_program->uniformLocation("camMatrix");
m_worldMatrixLoc = m_program->uniformLocation("worldMatrix");
m_myMatrixLoc = m_program->uniformLocation("myMatrix");
m_lightPosLoc = m_program->uniformLocation("lightPos");
// Create a VAO. Not strictly required for ES 3, but it is for plain OpenGL.
delete m_vao;
m_vao = new QOpenGLVertexArrayObject;
if (m_vao->create())
m_vao->bind();
m_program->bind();
delete m_vbo;
m_vbo = new QOpenGLBuffer;
m_vbo->create();
m_vbo->bind();
m_vbo->allocate(m_logo.constData(), m_logo.count() * sizeof(GLfloat));
f->glEnableVertexAttribArray(0);
f->glEnableVertexAttribArray(1);
f->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat),
nullptr);
f->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat),
reinterpret_cast<void *>(3 * sizeof(GLfloat)));
m_vbo->release();
f->glEnable(GL_DEPTH_TEST);
f->glEnable(GL_CULL_FACE);
}
void GLWidget::resizeGL(int w, int h)
{
m_proj.setToIdentity();
m_proj.perspective(45.0f, GLfloat(w) / h, 0.01f, 100.0f);
m_uniformsDirty = true;
}
void GLWidget::paintGL()
{
// Now use QOpenGLExtraFunctions instead of QOpenGLFunctions as we want to
// do more than what GL(ES) 2.0 offers.
QOpenGLExtraFunctions *f = QOpenGLContext::currentContext()->extraFunctions();
static constexpr const auto rgb = 240.0f / 255.0f;
f->glClearColor(rgb, rgb, rgb, 1);
f->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
m_program->bind();
m_texture->bind();
if (m_uniformsDirty) {
m_uniformsDirty = false;
QMatrix4x4 camera;
camera.lookAt(m_eye, m_eye + m_target, QVector3D(0, 1, 0));
m_program->setUniformValue(m_projMatrixLoc, m_proj);
m_program->setUniformValue(m_camMatrixLoc, camera);
QMatrix4x4 wm = m_world;
wm.rotate(m_r, 1, 1, 0);
m_program->setUniformValue(m_worldMatrixLoc, wm);
QMatrix4x4 mm;
mm.setToIdentity();
mm.rotate(-m_r2, 1, 0, 0);
m_program->setUniformValue(m_myMatrixLoc, mm);
m_program->setUniformValue(m_lightPosLoc, QVector3D(0, 0, 70));
}
// Now call a function introduced in OpenGL 3.1 / OpenGL ES 3.0. We
// requested a 3.3 or ES 3.0 context, so we know this will work.
f->glDrawArraysInstanced(GL_TRIANGLES, 0, m_logo.vertexCount(), 32 * 36);
}

View File

@ -0,0 +1,117 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#pragma once
#include <QOpenGLWidget>
#include <QMatrix4x4>
#include <QVector3D>
#include "logo.h"
QT_BEGIN_NAMESPACE
class QOpenGLTexture;
class QOpenGLShaderProgram;
class QOpenGLBuffer;
class QOpenGLVertexArrayObject;
QT_END_NAMESPACE
class GLWidget : public QOpenGLWidget
{
Q_OBJECT
Q_PROPERTY(float z READ z WRITE setZ NOTIFY zChanged FINAL)
Q_PROPERTY(float r READ r WRITE setR NOTIFY rChanged FINAL)
Q_PROPERTY(float r2 READ r2 WRITE setR2 NOTIFY r2Changed FINAL)
public:
explicit GLWidget(QWidget *parent = nullptr, Qt::WindowFlags f = {});
~GLWidget() override;
void initializeGL() override;
void resizeGL(int w, int h) override;
void paintGL() override;
float z() const { return m_eye.z(); }
void setZ(float v);
float r() const { return m_r; }
void setR(float v);
float r2() const { return m_r2; }
void setR2(float v);
private Q_SLOTS:
void startSecondStage();
Q_SIGNALS:
void zChanged();
void rChanged();
void r2Changed();
private:
QOpenGLTexture *m_texture = nullptr;
QOpenGLShaderProgram *m_program = nullptr;
QOpenGLBuffer *m_vbo = nullptr;
QOpenGLVertexArrayObject *m_vao = nullptr;
Logo m_logo;
int m_projMatrixLoc = 0;
int m_camMatrixLoc = 0;
int m_worldMatrixLoc = 0;
int m_myMatrixLoc = 0;
int m_lightPosLoc = 0;
QMatrix4x4 m_proj;
QMatrix4x4 m_world;
QVector3D m_eye;
QVector3D m_target = {0, 0, -1};
bool m_uniformsDirty = true;
float m_r = 0;
float m_r2 = 0;
};

View File

@ -0,0 +1,5 @@
<RCC>
<qresource prefix="/">
<file>images/qtlogo.png</file>
</qresource>
</RCC>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -0,0 +1,150 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "logo.h"
#include <qmath.h>
Logo::Logo()
{
m_data.resize(2500 * 6);
const GLfloat x1 = +0.06f;
const GLfloat y1 = -0.14f;
const GLfloat x2 = +0.14f;
const GLfloat y2 = -0.06f;
const GLfloat x3 = +0.08f;
const GLfloat y3 = +0.00f;
const GLfloat x4 = +0.30f;
const GLfloat y4 = +0.22f;
quad(x1, y1, x2, y2, y2, x2, y1, x1);
quad(x3, y3, x4, y4, y4, x4, y3, x3);
extrude(x1, y1, x2, y2);
extrude(x2, y2, y2, x2);
extrude(y2, x2, y1, x1);
extrude(y1, x1, x1, y1);
extrude(x3, y3, x4, y4);
extrude(x4, y4, y4, x4);
extrude(y4, x4, y3, x3);
const int NumSectors = 100;
for (int i = 0; i < NumSectors; ++i) {
GLfloat angle = (i * 2 * M_PI) / NumSectors;
GLfloat angleSin = qSin(angle);
GLfloat angleCos = qCos(angle);
const GLfloat x5 = 0.30f * angleSin;
const GLfloat y5 = 0.30f * angleCos;
const GLfloat x6 = 0.20f * angleSin;
const GLfloat y6 = 0.20f * angleCos;
angle = ((i + 1) * 2 * M_PI) / NumSectors;
angleSin = qSin(angle);
angleCos = qCos(angle);
const GLfloat x7 = 0.20f * angleSin;
const GLfloat y7 = 0.20f * angleCos;
const GLfloat x8 = 0.30f * angleSin;
const GLfloat y8 = 0.30f * angleCos;
quad(x5, y5, x6, y6, x7, y7, x8, y8);
extrude(x6, y6, x7, y7);
extrude(x8, y8, x5, y5);
}
}
void Logo::add(const QVector3D &v, const QVector3D &n)
{
GLfloat *p = m_data.data() + m_count;
*p++ = v.x();
*p++ = v.y();
*p++ = v.z();
*p++ = n.x();
*p++ = n.y();
*p++ = n.z();
m_count += 6;
}
void Logo::quad(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2, GLfloat x3, GLfloat y3, GLfloat x4, GLfloat y4)
{
QVector3D n = QVector3D::normal(QVector3D(x4 - x1, y4 - y1, 0.0f), QVector3D(x2 - x1, y2 - y1, 0.0f));
add(QVector3D(x1, y1, -0.05f), n);
add(QVector3D(x4, y4, -0.05f), n);
add(QVector3D(x2, y2, -0.05f), n);
add(QVector3D(x3, y3, -0.05f), n);
add(QVector3D(x2, y2, -0.05f), n);
add(QVector3D(x4, y4, -0.05f), n);
n = QVector3D::normal(QVector3D(x1 - x4, y1 - y4, 0.0f), QVector3D(x2 - x4, y2 - y4, 0.0f));
add(QVector3D(x4, y4, 0.05f), n);
add(QVector3D(x1, y1, 0.05f), n);
add(QVector3D(x2, y2, 0.05f), n);
add(QVector3D(x2, y2, 0.05f), n);
add(QVector3D(x3, y3, 0.05f), n);
add(QVector3D(x4, y4, 0.05f), n);
}
void Logo::extrude(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2)
{
QVector3D n = QVector3D::normal(QVector3D(0.0f, 0.0f, -0.1f), QVector3D(x2 - x1, y2 - y1, 0.0f));
add(QVector3D(x1, y1, +0.05f), n);
add(QVector3D(x1, y1, -0.05f), n);
add(QVector3D(x2, y2, +0.05f), n);
add(QVector3D(x2, y2, -0.05f), n);
add(QVector3D(x2, y2, +0.05f), n);
add(QVector3D(x1, y1, -0.05f), n);
}

View File

@ -0,0 +1,72 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#pragma once
#include <qopengl.h>
#include <QVector>
#include <QVector3D>
class Logo
{
public:
Logo();
const GLfloat *constData() const { return m_data.constData(); }
int count() const { return m_count; }
int vertexCount() const { return m_count / 6; }
private:
void quad(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2, GLfloat x3, GLfloat y3, GLfloat x4, GLfloat y4);
void extrude(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2);
void add(const QVector3D &v, const QVector3D &n);
QVector<GLfloat> m_data;
int m_count = 0;
};

View File

@ -0,0 +1,110 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QDebug>
#include <QApplication>
#include <QSurfaceFormat>
#include <QOpenGLContext>
#include <FramelessHelper/Core/private/framelessconfig_p.h>
#include <clocale>
#include "mainwindow.h"
#include "../shared/log.h"
// This example demonstrates easy, cross-platform usage of OpenGL ES 3.0 functions via
// QOpenGLExtraFunctions in an application that works identically on desktop platforms
// with OpenGL 3.3 and mobile/embedded devices with OpenGL ES 3.0.
// The code is always the same, with the exception of two places: (1) the OpenGL context
// creation has to have a sufficiently high version number for the features that are in
// use, and (2) the shader code's version directive is different.
FRAMELESSHELPER_USE_NAMESPACE
int main(int argc, char *argv[])
{
std::setlocale(LC_ALL, "en_US.UTF-8");
Log::setup(FRAMELESSHELPER_STRING_LITERAL("openglwidget"));
// Not necessary, but better call this function, before the construction
// of any Q(Core|Gui)Application instances.
FramelessHelper::Widgets::initialize();
const auto application = std::make_unique<QApplication>(argc, argv);
// Must be called after QGuiApplication has been constructed, we are using
// some private functions from QPA which won't be available until there's
// a QGuiApplication instance.
FramelessHelper::Core::setApplicationOSThemeAware();
FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow);
FramelessConfig::instance()->set(Global::Option::DisableLazyInitializationForMicaMaterial);
QSurfaceFormat fmt = {};
fmt.setDepthBufferSize(24);
// Request OpenGL 3.3 core or OpenGL ES 3.0.
if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) {
qDebug() << "Requesting OpenGL 3.3 core context ...";
fmt.setVersion(3, 3);
fmt.setProfile(QSurfaceFormat::CoreProfile);
} else {
qDebug() << "Requesting OpenGL ES 3.0 context ...";
fmt.setVersion(3, 0);
}
QSurfaceFormat::setDefaultFormat(fmt);
const auto mainWindow = std::make_unique<MainWindow>();
mainWindow->waitReady();
mainWindow->show();
return QCoreApplication::exec();
}

View File

@ -0,0 +1,101 @@
/*
* MIT License
*
* Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "mainwindow.h"
#include "glwidget.h"
#include <QtWidgets/qboxlayout.h>
#include <QtWidgets/qfileiconprovider.h>
#include <FramelessHelper/Widgets/framelesswidgetshelper.h>
#include <FramelessHelper/Widgets/standardtitlebar.h>
#include <FramelessHelper/Widgets/standardsystembutton.h>
#include "../shared/settings.h"
extern template void Settings::set<QRect>(const QString &, const QString &, const QRect &);
extern template void Settings::set<qreal>(const QString &, const QString &, const qreal &);
extern template QRect Settings::get<QRect>(const QString &, const QString &);
extern template qreal Settings::get<qreal>(const QString &, const QString &);
FRAMELESSHELPER_USE_NAMESPACE
using namespace Global;
FRAMELESSHELPER_STRING_CONSTANT(Geometry)
FRAMELESSHELPER_STRING_CONSTANT(DevicePixelRatio)
MainWindow::MainWindow(QWidget *parent) : FramelessWidget(parent)
{
initialize();
}
MainWindow::~MainWindow() = default;
void MainWindow::closeEvent(QCloseEvent *event)
{
if (!parent()) {
Settings::set({}, kGeometry, geometry());
Settings::set({}, kDevicePixelRatio, devicePixelRatioF());
}
FramelessWidget::closeEvent(event);
}
void MainWindow::initialize()
{
setWindowTitle(tr("FramelessHelper demo application - QOpenGLWidget"));
setWindowIcon(QFileIconProvider().icon(QFileIconProvider::Computer));
resize(800, 600);
m_titleBar = new StandardTitleBar(this);
m_titleBar->setWindowIconVisible(true);
m_glWidget = new GLWidget(this);
const auto mainLayout = new QVBoxLayout(this);
mainLayout->setSpacing(0);
mainLayout->setContentsMargins(0, 0, 0, 0);
mainLayout->addWidget(m_titleBar);
mainLayout->addWidget(m_glWidget);
setLayout(mainLayout);
FramelessWidgetsHelper *helper = FramelessWidgetsHelper::get(this);
helper->setTitleBarWidget(m_titleBar);
#ifndef Q_OS_MACOS
helper->setSystemButton(m_titleBar->minimizeButton(), SystemButtonType::Minimize);
helper->setSystemButton(m_titleBar->maximizeButton(), SystemButtonType::Maximize);
helper->setSystemButton(m_titleBar->closeButton(), SystemButtonType::Close);
#endif // Q_OS_MACOS
}
void MainWindow::waitReady()
{
FramelessWidgetsHelper *helper = FramelessWidgetsHelper::get(this);
helper->waitForReady();
const auto savedGeometry = Settings::get<QRect>({}, kGeometry);
if (savedGeometry.isValid() && !parent()) {
const auto savedDpr = Settings::get<qreal>({}, kDevicePixelRatio);
// Qt doesn't support dpr < 1.
const qreal oldDpr = std::max(savedDpr, qreal(1));
const qreal scale = (devicePixelRatioF() / oldDpr);
setGeometry({savedGeometry.topLeft() * scale, savedGeometry.size() * scale});
} else {
helper->moveWindowToDesktopCenter();
}
}

View File

@ -1,7 +1,7 @@
/*
* MIT License
*
* Copyright (C) 2021 by wangwenx190 (Yuhang Zhao)
* Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@ -22,28 +22,34 @@
* SOFTWARE.
*/
import QtQuick 2.0
import QtQuick.Controls 2.0
#pragma once
Button {
id: button
#include <FramelessHelper/Widgets/framelesswidget.h>
implicitWidth: 45
implicitHeight: 30
FRAMELESSHELPER_BEGIN_NAMESPACE
class StandardTitleBar;
FRAMELESSHELPER_END_NAMESPACE
property bool maximized: false
class GLWidget;
ToolTip.visible: hovered && !down
ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval
ToolTip.text: maximized ? qsTr("Restore") : qsTr("Maximize")
class MainWindow : public FRAMELESSHELPER_PREPEND_NAMESPACE(FramelessWidget)
{
Q_OBJECT
Q_DISABLE_COPY_MOVE(MainWindow)
contentItem: Image {
anchors.fill: parent
source: maximized ? "qrc:/images/button_restore_black.svg" : "qrc:/images/button_maximize_black.svg"
}
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow() override;
background: Rectangle {
visible: button.down || button.hovered
color: button.down ? "#808080" : (button.hovered ? "#c7c7c7" : "transparent")
}
}
void waitReady();
protected:
void closeEvent(QCloseEvent *event) override;
private:
void initialize();
private:
FRAMELESSHELPER_PREPEND_NAMESPACE(StandardTitleBar) *m_titleBar = nullptr;
GLWidget *m_glWidget = nullptr;
};

View File

@ -1,39 +1,146 @@
set(CMAKE_INCLUDE_CURRENT_DIR ON)
#[[
MIT License
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
find_package(QT NAMES Qt6 Qt5 COMPONENTS Quick QuickControls2 REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Quick QuickControls2 REQUIRED)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
set(SOURCES
../images.qrc
qml.qrc
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
]]
set(DEMO_NAME FramelessHelperDemo-Quick)
if(FRAMELESSHELPER_ENABLE_UNIVERSAL_BUILD)
set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64" CACHE STRING "" FORCE)
endif()
if(FRAMELESSHELPER_EXAMPLES_STANDALONE)
cmake_minimum_required(VERSION 3.20)
project(${DEMO_NAME} VERSION 1.0)
include(../../cmake/utils.cmake)
setup_project(
QT_PROJECT
LANGUAGES CXX RC
NO_WARNING
ENABLE_LTO
)
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Quick)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Quick)
find_package(FramelessHelper REQUIRED COMPONENTS Core Quick)
endif()
add_executable(${DEMO_NAME})
target_sources(${DEMO_NAME} PRIVATE
../shared/log.h
../shared/log.cpp
../shared/settings.h
../shared/settings.cpp
main.cpp
quicksettings.h
quicksettings.cpp
)
if(WIN32)
enable_language(RC)
list(APPEND SOURCES ../example.rc ../example.manifest)
set(__rc_path "${PROJECT_BINARY_DIR}/${DEMO_NAME}.rc")
generate_win32_rc_file(
PATH "${__rc_path}"
VERSION "${PROJECT_VERSION}"
COMPANY "wangwenx190"
DESCRIPTION "FramelessHelper Demo Application: Quick"
COPYRIGHT "MIT License"
PRODUCT "FramelessHelper Demo"
ICONS "../shared/example.ico"
)
set(__manifest_path "${PROJECT_BINARY_DIR}/${DEMO_NAME}.manifest")
generate_win32_manifest_file(
PATH "${__manifest_path}"
ID "org.wangwenx190.demo.Quick"
VERSION "${PROJECT_VERSION}"
VISTA_COMPAT
WIN7_COMPAT
WIN8_COMPAT
WIN8_1_COMPAT
WIN10_COMPAT
WIN11_COMPAT
XAML_ISLANDS_COMPAT
UTF8_CODEPAGE
)
target_sources(${DEMO_NAME} PRIVATE
"${__rc_path}"
"${__manifest_path}"
)
endif()
add_executable(Quick WIN32 ${SOURCES})
if(QT_VERSION VERSION_GREATER_EQUAL "6.2")
set(QML_SOURCES
"qml/Window.qml"
"qml/ApplicationWindow.qml"
"qml/HomePage.qml"
)
set_source_files_properties(${QML_SOURCES}
PROPERTIES QT_DISCARD_FILE_CONTENTS TRUE
)
qt_add_qml_module(${DEMO_NAME}
URI Demo
VERSION 1.0
RESOURCE_PREFIX "/"
NO_RESOURCE_TARGET_PATH
IMPORTS
QtQuick/auto
DEPENDENCIES
org.wangwenx190.FramelessHelper/auto
QML_FILES ${QML_SOURCES}
#ENABLE_TYPE_COMPILER
)
qt_add_resources(${DEMO_NAME} resources
PREFIX
"/"
FILES
"images/microsoft.svg"
)
else()
target_sources(${DEMO_NAME} PRIVATE resources.qrc)
endif()
target_link_libraries(Quick PRIVATE
target_link_libraries(${DEMO_NAME} PRIVATE
Qt${QT_VERSION_MAJOR}::Quick
Qt${QT_VERSION_MAJOR}::QuickControls2
wangwenx190::FramelessHelper
Qt${QT_VERSION_MAJOR}::QuickPrivate
FramelessHelper::Core
FramelessHelper::Quick
)
target_compile_definitions(Quick PRIVATE
QT_NO_CAST_FROM_ASCII
QT_NO_CAST_TO_ASCII
QT_NO_KEYWORDS
QT_DEPRECATED_WARNINGS
QT_DISABLE_DEPRECATED_BEFORE=0x060100
setup_gui_app(
TARGETS ${DEMO_NAME}
BUNDLE_ID "org.wangwenx190.demo.Quick"
BUNDLE_VERSION "1.0.0"
BUNDLE_VERSION_SHORT "1.0"
)
if(WIN32)
target_link_libraries(Quick PRIVATE dwmapi)
if(FRAMELESSHELPER_EXAMPLES_DEPLOYQT)
set(__extra_flags)
if(FRAMELESSHELPER_NO_INSTALL)
set(__extra_flags NO_INSTALL)
endif()
deploy_qt_runtime(
TARGET ${DEMO_NAME}
QML_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/qml"
${__extra_flags}
)
endif()
#dump_target_info(TARGETS ${DEMO_NAME})

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg t="1661848097607" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3344" width="512" height="512" xmlns:xlink="http://www.w3.org/1999/xlink">
<path d="M0 0h486.592v486.592H0z" fill="#F25022" p-id="3345"/>
<path d="M537.408 0H1024v486.592H537.408z" fill="#7FBA00" p-id="3346"/>
<path d="M0 537.408h486.592V1024H0z" fill="#00A4EF" p-id="3347"/>
<path d="M537.408 537.408H1024V1024H537.408z" fill="#FFB900" p-id="3348"/>
</svg>

After

Width:  |  Height:  |  Size: 636 B

View File

@ -1,7 +1,7 @@
/*
* MIT License
*
* Copyright (C) 2021 by wangwenx190 (Yuhang Zhao)
* Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@ -22,52 +22,141 @@
* SOFTWARE.
*/
#include "quick/framelessquickhelper.h"
#ifndef QMLTC_ENABLED
# define QMLTC_ENABLED 0
#endif
#include <QtGui/qguiapplication.h>
#include <QtQml/qqmlapplicationengine.h>
#include <QtQuickControls2/qquickstyle.h>
#include <QtQml/qqmlcontext.h>
#include <QtQuick/qquickwindow.h>
#include <FramelessHelper/Quick/framelessquickmodule.h>
#include <FramelessHelper/Core/private/framelessconfig_p.h>
#include "quicksettings.h"
#if QMLTC_ENABLED
# include <homepage.h>
#endif
#include "../shared/log.h"
FRAMELESSHELPER_USE_NAMESPACE
static constexpr const bool IS_MACOS_HOST =
#ifdef Q_OS_MACOS
true
#else // !Q_OS_MACOS
false
#endif // Q_OS_MACOS
;
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
#endif
#endif
Log::setup(FRAMELESSHELPER_STRING_LITERAL("quick"));
QGuiApplication application(argc, argv);
// Not necessary, but better call this function, before the construction
// of any Q(Core|Gui)Application instances.
FramelessHelper::Quick::initialize();
QQmlApplicationEngine engine;
const auto application = std::make_unique<QGuiApplication>(argc, argv);
// Must be called after QGuiApplication has been constructed, we are using
// some private functions from QPA which won't be available until there's
// a QGuiApplication instance.
FramelessHelper::Core::setApplicationOSThemeAware();
FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow);
//FramelessConfig::instance()->set(Global::Option::DisableLazyInitializationForMicaMaterial);
// Enable QtRHI debug output if not explicitly requested by the user.
if (!qEnvironmentVariableIsSet("QSG_INFO")) {
qputenv("QSG_INFO", FRAMELESSHELPER_BYTEARRAY_LITERAL("1"));
}
// Allow testing other RHI backends through environment variable.
if (!qEnvironmentVariableIsSet("QSG_RHI_BACKEND")) {
// This line is not relevant to FramelessHelper, we change
// the default RHI backend to "software" just because it's
// stable enough and have exactly the same behavior on all
// supported platforms. Other backends may behave differently
// on different platforms and graphics cards, so I think they
// are not suitable for our demonstration.
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
QQuickStyle::setStyle(QStringLiteral("Basic"));
QQuickWindow::setGraphicsApi(QSGRendererInterface::Software);
#elif (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
QQuickWindow::setSceneGraphBackend(QSGRendererInterface::Software);
#endif
}
if (!qEnvironmentVariableIsSet("QT_QUICK_CONTROLS_STYLE")) {
// This line is not relevant to FramelessHelper, we change the default
// Qt Quick Controls theme to "Basic" (Qt6) or "Default" (Qt5) just
// because other themes will make our homemade system buttons look
// not good. This line has nothing to do with FramelessHelper itself.
qputenv("QT_QUICK_CONTROLS_STYLE", []() -> QByteArray {
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
return FRAMELESSHELPER_BYTEARRAY_LITERAL("Basic");
#else
QQuickStyle::setStyle(QStringLiteral("Default"));
return FRAMELESSHELPER_BYTEARRAY_LITERAL("Default");
#endif
}());
}
#if 0
// Enable some helpful debugging messages.
if (!qEnvironmentVariableIsSet("QML_IMPORT_TRACE")) {
qputenv("QML_IMPORT_TRACE", FRAMELESSHELPER_BYTEARRAY_LITERAL("1"));
}
#endif
qmlRegisterType<FRAMELESSHELPER_PREPEND_NAMESPACE(FramelessQuickHelper)>("wangwenx190.Utils", 1, 0, "FramelessHelper");
const auto engine = std::make_unique<QQmlApplicationEngine>();
const QUrl mainQmlUrl(QStringLiteral("qrc:///qml/main.qml"));
engine->rootContext()->setContextProperty(
FRAMELESSHELPER_STRING_LITERAL("$isMacOSHost"), QVariant(IS_MACOS_HOST));
#if (((QT_VERSION < QT_VERSION_CHECK(6, 2, 0)) || defined(QUICK_USE_QMAKE)) && !QMLTC_ENABLED)
// Don't forget to register our own custom QML types!
FramelessHelper::Quick::registerTypes(engine.get());
qmlRegisterSingletonType<QuickSettings>("Demo", 1, 0, "Settings",
[](QQmlEngine *engine, QJSEngine *scriptEngine) -> QObject * {
Q_UNUSED(engine);
Q_UNUSED(scriptEngine);
return new QuickSettings;
});
#endif
#if !QMLTC_ENABLED
const QUrl mainUrl(FRAMELESSHELPER_STRING_LITERAL("qrc:///qml/HomePage.qml"));
#endif
#if (QT_VERSION >= QT_VERSION_CHECK(6, 4, 0))
QObject::connect(engine.get(), &QQmlApplicationEngine::objectCreationFailed, application.get(),
[](const QUrl &url){
qCritical() << "The QML engine failed to create component:" << url;
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
#elif !QMLTC_ENABLED
const QMetaObject::Connection connection = QObject::connect(
&engine,
&QQmlApplicationEngine::objectCreated,
&application,
[&mainQmlUrl, &connection](QObject *object, const QUrl &url) {
if (url != mainQmlUrl) {
engine.get(), &QQmlApplicationEngine::objectCreated, application.get(),
[&mainUrl, &connection](QObject *object, const QUrl &url) {
if (url != mainUrl) {
return;
}
if (!object) {
QGuiApplication::exit(-1);
} else {
if (object) {
QObject::disconnect(connection);
} else {
QCoreApplication::exit(-1);
}
},
Qt::QueuedConnection);
}, Qt::QueuedConnection);
#endif
engine.load(mainQmlUrl);
#if !QMLTC_ENABLED
engine->load(mainUrl);
#endif
return QGuiApplication::exec();
#if QMLTC_ENABLED
const auto homePage = std::make_unique<HomePage>(engine.get());
homePage->show();
#endif
return QCoreApplication::exec();
}

View File

@ -1,8 +0,0 @@
<RCC>
<qresource prefix="/">
<file>qml/main.qml</file>
<file>qml/MinimizeButton.qml</file>
<file>qml/MaximizeButton.qml</file>
<file>qml/CloseButton.qml</file>
</qresource>
</RCC>

View File

@ -0,0 +1,111 @@
/*
* MIT License
*
* Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
import QtQuick
import QtQuick.Controls.Basic
import org.wangwenx190.FramelessHelper
import Demo
FramelessApplicationWindow {
id: window
objectName: "applicationWindow"
visible: false // Hide the window before we sets up it's correct size and position.
width: 800
height: 600
title: qsTr("FramelessHelper demo application - Qt Quick [") + objectName + ']'
color: {
if (FramelessHelper.blurBehindWindowEnabled) {
return "transparent";
}
if (FramelessUtils.systemTheme === FramelessHelperConstants.Dark) {
return FramelessUtils.defaultSystemDarkColor;
}
return FramelessUtils.defaultSystemLightColor;
}
Component.onDestruction: Settings.saveGeometry(window)
FramelessHelper.onReady: {
// Let FramelessHelper know what's our homemade title bar, otherwise
// our window won't be draggable.
FramelessHelper.titleBarItem = titleBar;
if (!$isMacOSHost) {
// Make our own items visible to the hit test and on Windows, enable
// the snap layout feature (available since Windows 11).
FramelessHelper.setSystemButton(titleBar.minimizeButton, FramelessHelperConstants.Minimize);
FramelessHelper.setSystemButton(titleBar.maximizeButton, FramelessHelperConstants.Maximize);
FramelessHelper.setSystemButton(titleBar.closeButton, FramelessHelperConstants.Close);
}
if (!Settings.restoreGeometry(window)) {
FramelessHelper.moveWindowToDesktopCenter();
}
// Finally, show the window after everything is setted.
window.visible = true;
}
Shortcut {
sequences: [ StandardKey.Cancel, StandardKey.Close, StandardKey.Quit ]
onActivated: {
if (window.visibility === Window.FullScreen) {
window.toggleFullScreen();
} else {
window.close();
}
}
}
Shortcut {
sequences: [ StandardKey.FullScreen, "ALT+RETURN" ]
onActivated: window.toggleFullScreen()
}
Timer {
interval: 500
running: true
repeat: true
onTriggered: timeLabel.text = Qt.formatTime(new Date(), "hh:mm:ss")
}
Label {
id: timeLabel
anchors.centerIn: parent
font {
pointSize: 70
bold: true
}
color: (FramelessUtils.systemTheme === FramelessHelperConstants.Dark) ? Qt.color("white") : Qt.color("black")
}
StandardTitleBar {
id: titleBar
anchors {
top: parent.top
topMargin: window.visibility === Window.Windowed ? 1 : 0
left: parent.left
right: parent.right
}
windowIcon: "qrc:///images/microsoft.svg"
windowIconVisible: true
}
}

View File

@ -1,7 +1,7 @@
/*
* MIT License
*
* Copyright (C) 2021 by wangwenx190 (Yuhang Zhao)
* Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@ -22,26 +22,14 @@
* SOFTWARE.
*/
import QtQuick 2.0
import QtQuick.Controls 2.0
import QtQml
Button {
id: button
QtObject {
property Window window: Window{}
property ApplicationWindow applicationWindow: ApplicationWindow{}
implicitWidth: 45
implicitHeight: 30
ToolTip.visible: hovered && !down
ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval
ToolTip.text: qsTr("Minimize")
contentItem: Image {
anchors.fill: parent
source: "qrc:/images/button_minimize_black.svg"
}
background: Rectangle {
visible: button.down || button.hovered
color: button.down ? "#808080" : (button.hovered ? "#c7c7c7" : "transparent")
Component.onCompleted: {
window.show();
applicationWindow.show();
}
}

View File

@ -0,0 +1,111 @@
/*
* MIT License
*
* Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
import QtQuick
import QtQuick.Controls.Basic
import org.wangwenx190.FramelessHelper
import Demo
FramelessWindow {
id: window
objectName: "window"
visible: false // Hide the window before we sets up it's correct size and position.
width: 800
height: 600
title: qsTr("FramelessHelper demo application - Qt Quick [") + objectName +']'
color: {
if (FramelessHelper.blurBehindWindowEnabled) {
return "transparent";
}
if (FramelessUtils.systemTheme === FramelessHelperConstants.Dark) {
return FramelessUtils.defaultSystemDarkColor;
}
return FramelessUtils.defaultSystemLightColor;
}
Component.onDestruction: Settings.saveGeometry(window)
FramelessHelper.onReady: {
// Let FramelessHelper know what's our homemade title bar, otherwise
// our window won't be draggable.
FramelessHelper.titleBarItem = titleBar;
if (!$isMacOSHost) {
// Make our own items visible to the hit test and on Windows, enable
// the snap layout feature (available since Windows 11).
FramelessHelper.setSystemButton(titleBar.minimizeButton, FramelessHelperConstants.Minimize);
FramelessHelper.setSystemButton(titleBar.maximizeButton, FramelessHelperConstants.Maximize);
FramelessHelper.setSystemButton(titleBar.closeButton, FramelessHelperConstants.Close);
}
if (!Settings.restoreGeometry(window)) {
FramelessHelper.moveWindowToDesktopCenter();
}
// Finally, show the window after everything is setted.
window.visible = true;
}
Shortcut {
sequences: [ StandardKey.Cancel, StandardKey.Close, StandardKey.Quit ]
onActivated: {
if (window.visibility === Window.FullScreen) {
window.toggleFullScreen();
} else {
window.close();
}
}
}
Shortcut {
sequences: [ StandardKey.FullScreen, "ALT+RETURN" ]
onActivated: window.toggleFullScreen()
}
Timer {
interval: 500
running: true
repeat: true
onTriggered: timeLabel.text = Qt.formatTime(new Date(), "hh:mm:ss")
}
Label {
id: timeLabel
anchors.centerIn: parent
font {
pointSize: 70
bold: true
}
color: (FramelessUtils.systemTheme === FramelessHelperConstants.Dark) ? Qt.color("white") : Qt.color("black")
}
StandardTitleBar {
id: titleBar
anchors {
top: parent.top
topMargin: window.visibility === Window.Windowed ? 1 : 0
left: parent.left
right: parent.right
}
windowIcon: "qrc:///images/microsoft.svg"
windowIconVisible: true
}
}

View File

@ -1,156 +0,0 @@
/*
* MIT License
*
* Copyright (C) 2021 by wangwenx190 (Yuhang Zhao)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
import QtQuick 2.0
import QtQuick.Window 2.0
import QtQuick.Controls 2.0
import wangwenx190.Utils 1.0
Window {
id: window
visible: true
width: 800
height: 600
title: qsTr("Hello, World!")
color: "#f0f0f0"
property real _flh_margin: ((window.visibility === Window.Maximized)
|| (window.visibility
=== Window.FullScreen)) ? 0.0 : (1.0 / Screen.devicePixelRatio)
property var _win_prev_state: null
FramelessHelper {
id: framelessHelper
}
Timer {
id: timer
interval: 500
running: true
repeat: true
onTriggered: label.text = Qt.formatTime(new Date(), "hh:mm:ss")
}
Rectangle {
id: titleBar
height: framelessHelper.titleBarHeight
color: "transparent"
anchors {
top: parent.top
topMargin: window._flh_margin
left: parent.left
leftMargin: window._flh_margin
right: parent.right
rightMargin: window._flh_margin
}
Text {
id: titleBarText
text: window.title
font.pointSize: 13
color: window.active ? "black" : "gray"
anchors.left: parent.left
anchors.leftMargin: 15
anchors.verticalCenter: parent.verticalCenter
}
Row {
anchors.top: parent.top
anchors.right: parent.right
MinimizeButton {
id: minimizeButton
onClicked: window.showMinimized()
Component.onCompleted: framelessHelper.setHitTestVisibleInChrome(
minimizeButton, true)
}
MaximizeButton {
id: maximizeButton
maximized: ((window.visibility === Window.Maximized)
|| (window.visibility === Window.FullScreen))
onClicked: {
if (maximized) {
window.showNormal()
} else {
window.showMaximized()
}
}
Component.onCompleted: framelessHelper.setHitTestVisibleInChrome(
maximizeButton, true)
}
CloseButton {
id: closeButton
onClicked: window.close()
Component.onCompleted: framelessHelper.setHitTestVisibleInChrome(
closeButton, true)
}
}
}
Label {
id: label
anchors.centerIn: parent
font {
pointSize: 70
bold: true
}
}
Button {
anchors {
horizontalCenter: parent.horizontalCenter
top: label.bottom
topMargin: 15
}
property bool _full: window.visibility === Window.FullScreen
text: _full ? qsTr("Exit FullScreen") : qsTr("Enter FullScreen")
onClicked: {
if (_full) {
if (_win_prev_state == Window.Maximized) {
window.showMaximized()
} else if (_win_prev_state == Window.Windowed) {
window.showNormal()
}
} else {
_win_prev_state = window.visibility
window.showFullScreen()
}
}
}
Rectangle {
id: windowFrame
anchors.fill: parent
color: "transparent"
border {
color: window.active ? "black" : "darkGray"
width: window._flh_margin
}
}
Component.onCompleted: framelessHelper.removeWindowFrame()
}

View File

@ -1,7 +1,16 @@
TARGET = Quick
TEMPLATE = app
QT += quick quickcontrols2
CONFIG(release, debug|release): CONFIG += qtquickcompiler
SOURCES += main.cpp
RESOURCES += qml.qrc
include($$PWD/../common.pri)
TARGET = FramelessHelperDemo-Quick
QT += qml quick quickcontrols2
DEFINES += QUICK_USE_QMAKE
HEADERS += \
../shared/log.h \
../shared/settings.h \
quicksettings.h
SOURCES += \
../shared/log.cpp \
../shared/settings.cpp \
quicksettings.cpp \
main.cpp
RESOURCES += resources.qrc
include(../../qmake/core.pri)
include(../../qmake/quick.pri)

View File

@ -0,0 +1,71 @@
/*
* MIT License
*
* Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "quicksettings.h"
#include "../shared/settings.h"
FRAMELESSHELPER_STRING_CONSTANT(Geometry)
FRAMELESSHELPER_STRING_CONSTANT(DevicePixelRatio)
extern template void Settings::set<QRect>(const QString &, const QString &, const QRect &);
extern template void Settings::set<qreal>(const QString &, const QString &, const qreal &);
extern template QRect Settings::get<QRect>(const QString &, const QString &);
extern template qreal Settings::get<qreal>(const QString &, const QString &);
QuickSettings::QuickSettings(QObject *parent) : QObject(parent)
{
}
QuickSettings::~QuickSettings() = default;
void QuickSettings::saveGeometry(QWindow *window)
{
Q_ASSERT(window);
if (!window) {
return;
}
const QString objName = window->objectName();
Settings::set(objName, kGeometry, window->geometry());
Settings::set(objName, kDevicePixelRatio, window->devicePixelRatio());
}
bool QuickSettings::restoreGeometry(QWindow *window)
{
Q_ASSERT(window);
if (!window) {
return false;
}
const QString objName = window->objectName();
const auto savedGeometry = Settings::get<QRect>(objName, kGeometry);
if (!savedGeometry.isValid()) {
return false;
}
const auto savedDpr = Settings::get<qreal>(objName, kDevicePixelRatio);
// Qt doesn't support dpr < 1.
const qreal oldDpr = std::max(savedDpr, qreal(1));
const qreal scale = (window->devicePixelRatio() / oldDpr);
window->setGeometry({savedGeometry.topLeft() * scale, savedGeometry.size() * scale});
return true;
}

View File

@ -0,0 +1,48 @@
/*
* MIT License
*
* Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#pragma once
#include <QtGui/qwindow.h>
#include <FramelessHelper/Quick/framelesshelperquick_global.h>
class QuickSettings : public QObject
{
Q_OBJECT
#ifdef QML_NAMED_ELEMENT
QML_NAMED_ELEMENT(Settings)
#endif
#ifdef QML_SINGLETON
QML_SINGLETON
#endif
Q_DISABLE_COPY_MOVE(QuickSettings)
public:
explicit QuickSettings(QObject *parent = nullptr);
~QuickSettings() override;
public Q_SLOTS:
void saveGeometry(QWindow *window);
Q_NODISCARD bool restoreGeometry(QWindow *window);
};

View File

@ -0,0 +1,8 @@
<RCC>
<qresource prefix="/">
<file>images/microsoft.svg</file>
<file>qml/Window.qml</file>
<file>qml/ApplicationWindow.qml</file>
<file>qml/HomePage.qml</file>
</qresource>
</RCC>

View File

@ -0,0 +1,28 @@
:: MIT License
::
:: Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
::
:: Permission is hereby granted, free of charge, to any person obtaining a copy
:: of this software and associated documentation files (the "Software"), to deal
:: in the Software without restriction, including without limitation the rights
:: to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
:: copies of the Software, and to permit persons to whom the Software is
:: furnished to do so, subject to the following conditions:
::
:: The above copyright notice and this permission notice shall be included in
:: all copies or substantial portions of the Software.
::
:: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
:: IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
:: FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
:: AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
:: LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
:: OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
:: SOFTWARE.
@echo off
setlocal
set QSG_RHI_BACKEND=d3d11
"%~dp0FramelessHelperDemo-Quick.exe"
endlocal
exit /b 0

View File

@ -0,0 +1,28 @@
:: MIT License
::
:: Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
::
:: Permission is hereby granted, free of charge, to any person obtaining a copy
:: of this software and associated documentation files (the "Software"), to deal
:: in the Software without restriction, including without limitation the rights
:: to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
:: copies of the Software, and to permit persons to whom the Software is
:: furnished to do so, subject to the following conditions:
::
:: The above copyright notice and this permission notice shall be included in
:: all copies or substantial portions of the Software.
::
:: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
:: IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
:: FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
:: AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
:: LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
:: OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
:: SOFTWARE.
@echo off
setlocal
set QSG_RHI_BACKEND=d3d12
"%~dp0FramelessHelperDemo-Quick.exe"
endlocal
exit /b 0

View File

@ -0,0 +1,28 @@
:: MIT License
::
:: Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
::
:: Permission is hereby granted, free of charge, to any person obtaining a copy
:: of this software and associated documentation files (the "Software"), to deal
:: in the Software without restriction, including without limitation the rights
:: to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
:: copies of the Software, and to permit persons to whom the Software is
:: furnished to do so, subject to the following conditions:
::
:: The above copyright notice and this permission notice shall be included in
:: all copies or substantial portions of the Software.
::
:: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
:: IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
:: FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
:: AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
:: LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
:: OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
:: SOFTWARE.
@echo off
setlocal
set QSG_RHI_BACKEND=opengl
"%~dp0FramelessHelperDemo-Quick.exe"
endlocal
exit /b 0

View File

@ -0,0 +1,28 @@
:: MIT License
::
:: Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
::
:: Permission is hereby granted, free of charge, to any person obtaining a copy
:: of this software and associated documentation files (the "Software"), to deal
:: in the Software without restriction, including without limitation the rights
:: to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
:: copies of the Software, and to permit persons to whom the Software is
:: furnished to do so, subject to the following conditions:
::
:: The above copyright notice and this permission notice shall be included in
:: all copies or substantial portions of the Software.
::
:: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
:: IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
:: FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
:: AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
:: LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
:: OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
:: SOFTWARE.
@echo off
setlocal
set QSG_RHI_BACKEND=vulkan
"%~dp0FramelessHelperDemo-Quick.exe"
endlocal
exit /b 0

View File

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 45 KiB

94
examples/shared/log.cpp Normal file
View File

@ -0,0 +1,94 @@
/*
* MIT License
*
* Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "log.h"
#include <QtCore/qdebug.h>
#include <QtCore/qfile.h>
#include <QtCore/qtextstream.h>
#include <iostream>
#include <framelesshelpercore_global.h>
#ifndef QT_ENDL
# if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
# define QT_ENDL Qt::endl
# else
# define QT_ENDL endl
# endif
#endif
static QString g_app = {};
static bool g_logError = false;
static std::unique_ptr<QFile> g_logFile = nullptr;
static std::unique_ptr<QTextStream> g_logStream = nullptr;
static inline void myMessageHandler(const QtMsgType type, const QMessageLogContext &context, const QString &message)
{
if (message.isEmpty()) {
return;
}
const QString finalMessage = qFormatLogMessage(type, context, message).trimmed();
if ((type == QtInfoMsg) || (type == QtDebugMsg)) {
std::cout << qUtf8Printable(finalMessage) << std::endl;
} else {
std::cerr << qUtf8Printable(finalMessage) << std::endl;
}
if (g_logError) {
return;
}
if (!g_logFile) {
g_logFile = std::make_unique<QFile>();
g_logFile->setFileName(FRAMELESSHELPER_STRING_LITERAL("debug-%1.log").arg(g_app));
if (!g_logFile->open(QFile::WriteOnly | QFile::Text | QFile::Append)) {
std::cerr << "Can't open file to write: " << qUtf8Printable(g_logFile->errorString()) << std::endl;
g_logFile.reset();
g_logError = true;
return;
}
}
if (!g_logStream) {
g_logStream = std::make_unique<QTextStream>();
g_logStream->setDevice(g_logFile.get());
}
(*g_logStream) << finalMessage << QT_ENDL;
}
void Log::setup(const QString &app)
{
Q_ASSERT(!app.isEmpty());
if (app.isEmpty()) {
return;
}
static bool once = false;
if (once) {
return;
}
once = true;
g_app = app;
qSetMessagePattern(FRAMELESSHELPER_STRING_LITERAL(
"[%{time yyyy/MM/dd hh:mm:ss.zzz}] <%{if-info}INFO%{endif}%{if-debug}DEBUG"
"%{endif}%{if-warning}WARNING%{endif}%{if-critical}CRITICAL%{endif}%{if-fatal}"
"FATAL%{endif}> %{if-category}%{category}: %{endif}%{message}"));
qInstallMessageHandler(myMessageHandler);
}

32
examples/shared/log.h Normal file
View File

@ -0,0 +1,32 @@
/*
* MIT License
*
* Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#pragma once
#include <QtCore/qstring.h>
namespace Log
{
void setup(const QString &app);
} // namespace Log

View File

@ -0,0 +1,83 @@
/*
* MIT License
*
* Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "settings.h"
#include <QtCore/qsettings.h>
#include <QtCore/qcoreapplication.h>
#include <QtCore/qfileinfo.h>
#include <QtCore/qrect.h>
#include <framelesshelpercore_global.h>
static std::unique_ptr<QSettings> g_settings = nullptr;
[[nodiscard]] static inline QSettings *appConfigFile()
{
const QFileInfo fileInfo(QCoreApplication::applicationFilePath());
const QString iniFileName = fileInfo.completeBaseName() + FRAMELESSHELPER_STRING_LITERAL(".ini");
const QString iniFilePath = fileInfo.canonicalPath() + u'/' + iniFileName;
return new QSettings(iniFilePath, QSettings::IniFormat);
}
[[nodiscard]] static inline QString appKey(const QString &id, const QString &key)
{
Q_ASSERT(!key.isEmpty());
if (key.isEmpty()) {
return {};
}
return (id.isEmpty() ? key : (id + u'/' + key));
}
template<typename T>
void Settings::set(const QString &id, const QString &key, const T &data)
{
Q_ASSERT(!key.isEmpty());
if (key.isEmpty()) {
return;
}
if (!g_settings) {
g_settings.reset(appConfigFile());
}
g_settings->setValue(appKey(id, key), data);
}
template<typename T>
T Settings::get(const QString &id, const QString &key)
{
Q_ASSERT(!key.isEmpty());
if (key.isEmpty()) {
return T{};
}
if (!g_settings) {
g_settings.reset(appConfigFile());
}
return qvariant_cast<T>(g_settings->value(appKey(id, key)));
}
template void Settings::set<QRect>(const QString &, const QString &, const QRect &);
template void Settings::set<qreal>(const QString &, const QString &, const qreal &);
template void Settings::set<QByteArray>(const QString &, const QString &, const QByteArray &);
template QRect Settings::get<QRect>(const QString &, const QString &);
template qreal Settings::get<qreal>(const QString &, const QString &);
template QByteArray Settings::get<QByteArray>(const QString &, const QString &);

View File

@ -0,0 +1,36 @@
/*
* MIT License
*
* Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#pragma once
#include <QtCore/qstring.h>
namespace Settings
{
template<typename T>
void set(const QString &id, const QString &key, const T &data);
template<typename T>
[[nodiscard]] T get(const QString &id, const QString &key);
} // namespace Settings

View File

@ -1,39 +1,110 @@
set(CMAKE_INCLUDE_CURRENT_DIR ON)
#[[
MIT License
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
find_package(QT NAMES Qt6 Qt5 COMPONENTS Widgets REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Widgets REQUIRED)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
set(SOURCES
../images.qrc
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
]]
set(DEMO_NAME FramelessHelperDemo-Widget)
if(FRAMELESSHELPER_ENABLE_UNIVERSAL_BUILD)
set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64" CACHE STRING "" FORCE)
endif()
if(FRAMELESSHELPER_EXAMPLES_STANDALONE)
cmake_minimum_required(VERSION 3.20)
project(${DEMO_NAME} VERSION 1.0)
include(../../cmake/utils.cmake)
setup_project(
QT_PROJECT
LANGUAGES CXX RC
NO_WARNING
ENABLE_LTO
)
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets)
find_package(FramelessHelper REQUIRED COMPONENTS Core Widgets)
endif()
add_executable(${DEMO_NAME})
target_sources(${DEMO_NAME} PRIVATE
../shared/log.h
../shared/log.cpp
../shared/settings.h
../shared/settings.cpp
widget.h
widget.cpp
main.cpp
)
if(WIN32)
enable_language(RC)
list(APPEND SOURCES ../example.rc ../example.manifest)
set(__rc_path "${PROJECT_BINARY_DIR}/${DEMO_NAME}.rc")
generate_win32_rc_file(
PATH "${__rc_path}"
VERSION "${PROJECT_VERSION}"
COMPANY "wangwenx190"
DESCRIPTION "FramelessHelper Demo Application: Widget"
COPYRIGHT "MIT License"
PRODUCT "FramelessHelper Demo"
ICONS "../shared/example.ico"
)
set(__manifest_path "${PROJECT_BINARY_DIR}/${DEMO_NAME}.manifest")
generate_win32_manifest_file(
PATH "${__manifest_path}"
ID "org.wangwenx190.demo.Widget"
VERSION "${PROJECT_VERSION}"
VISTA_COMPAT
WIN7_COMPAT
WIN8_COMPAT
WIN8_1_COMPAT
WIN10_COMPAT
WIN11_COMPAT
XAML_ISLANDS_COMPAT
UTF8_CODEPAGE
)
target_sources(${DEMO_NAME} PRIVATE
"${__rc_path}"
"${__manifest_path}"
)
endif()
add_executable(Widget WIN32 ${SOURCES})
target_link_libraries(Widget PRIVATE
target_link_libraries(${DEMO_NAME} PRIVATE
Qt${QT_VERSION_MAJOR}::Widgets
wangwenx190::FramelessHelper
FramelessHelper::Core
FramelessHelper::Widgets
)
target_compile_definitions(Widget PRIVATE
QT_NO_CAST_FROM_ASCII
QT_NO_CAST_TO_ASCII
QT_NO_KEYWORDS
QT_DEPRECATED_WARNINGS
QT_DISABLE_DEPRECATED_BEFORE=0x060100
setup_gui_app(
TARGETS ${DEMO_NAME}
BUNDLE_ID "org.wangwenx190.demo.Widget"
BUNDLE_VERSION "1.0.0"
BUNDLE_VERSION_SHORT "1.0"
)
if(WIN32)
target_link_libraries(Widget PRIVATE dwmapi)
if(FRAMELESSHELPER_EXAMPLES_DEPLOYQT)
set(__extra_flags)
if(FRAMELESSHELPER_NO_INSTALL)
set(__extra_flags NO_INSTALL)
endif()
deploy_qt_runtime(TARGET ${DEMO_NAME} ${__extra_flags})
endif()
#dump_target_info(TARGETS ${DEMO_NAME})

View File

@ -1,7 +1,7 @@
/*
* MIT License
*
* Copyright (C) 2021 by wangwenx190 (Yuhang Zhao)
* Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@ -23,23 +23,45 @@
*/
#include <QtWidgets/qapplication.h>
#include <FramelessHelper/Core/private/framelessconfig_p.h>
#include "widget.h"
#include "../shared/log.h"
FRAMELESSHELPER_USE_NAMESPACE
#define CREATE_WINDOW(Name) \
const auto Name = std::make_unique<Widget>(); \
Name->setObjectName(FRAMELESSHELPER_STRING_LITERAL(#Name)); \
Name->waitReady(); \
Name->show();
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
#endif
Log::setup(FRAMELESSHELPER_STRING_LITERAL("widget"));
// Not necessary, but better call this function, before the construction
// of any Q(Core|Gui)Application instances.
FramelessHelper::Widgets::initialize();
#if 0
if (!qEnvironmentVariableIsSet("QT_WIDGETS_RHI")) {
qputenv("QT_WIDGETS_RHI", FRAMELESSHELPER_BYTEARRAY_LITERAL("1"));
}
#endif
QApplication application(argc, argv);
const auto application = std::make_unique<QApplication>(argc, argv);
Widget widget;
widget.show();
// Must be called after QGuiApplication has been constructed, we are using
// some private functions from QPA which won't be available until there's
// a QGuiApplication instance.
FramelessHelper::Core::setApplicationOSThemeAware();
return QApplication::exec();
FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow);
//FramelessConfig::instance()->set(Global::Option::DisableLazyInitializationForMicaMaterial);
CREATE_WINDOW(widget1)
CREATE_WINDOW(widget2)
CREATE_WINDOW(widget3)
return QCoreApplication::exec();
}

View File

@ -1,7 +1,7 @@
/*
* MIT License
*
* Copyright (C) 2021 by wangwenx190 (Yuhang Zhao)
* Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@ -23,351 +23,152 @@
*/
#include "widget.h"
#include <QtCore/qdebug.h>
#include <QtCore/qdatetime.h>
#include <QtGui/qpainter.h>
#include <QtWidgets/qboxlayout.h>
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
# include <QtGui/qshortcut.h>
#else
# include <QtWidgets/qshortcut.h>
#endif
#include <QtWidgets/qlabel.h>
#include <QtWidgets/qpushbutton.h>
#include "core/utilities.h"
#include "core/framelesshelper.h"
#include <QtWidgets/qboxlayout.h>
#include <QtWidgets/qfileiconprovider.h>
#include <FramelessHelper/Core/framelessmanager.h>
#include <FramelessHelper/Widgets/framelesswidgetshelper.h>
#include <FramelessHelper/Widgets/standardtitlebar.h>
#include <FramelessHelper/Widgets/standardsystembutton.h>
#include "../shared/settings.h"
extern template void Settings::set<QRect>(const QString &, const QString &, const QRect &);
extern template void Settings::set<qreal>(const QString &, const QString &, const qreal &);
extern template QRect Settings::get<QRect>(const QString &, const QString &);
extern template qreal Settings::get<qreal>(const QString &, const QString &);
FRAMELESSHELPER_USE_NAMESPACE
static const QColor systemLightColor = QStringLiteral("#f0f0f0");
static const QColor systemDarkColor = QColor::fromRgb(32, 32, 32);
using namespace Global;
static constexpr char mainStyleSheet[] = R"(
#MainWidget {
background-color: %1;
}
FRAMELESSHELPER_STRING_CONSTANT(Geometry)
FRAMELESSHELPER_STRING_CONSTANT(DevicePixelRatio)
#TitleBarWidget {
background-color: %2;
}
#WindowTitleLabel {
color: %3;
}
#MinimizeButton, #MaximizeButton, #CloseButton {
border-style: none;
background-color: transparent;
}
#MinimizeButton:hover, #MaximizeButton:hover {
background-color: #c7c7c7;
}
#MinimizeButton:pressed, #MaximizeButton:pressed {
background-color: #808080;
}
#CloseButton:hover {
background-color: #e81123;
}
#CloseButton:pressed {
background-color: #8c0a15;
}
#ClockLabel {
color: %4;
}
)";
Widget::Widget(QWidget *parent) : QWidget(parent)
Widget::Widget(QWidget *parent) : FramelessWidget(parent)
{
setAttribute(Qt::WA_DontCreateNativeAncestors);
createWinId();
setupUi();
initialize();
startTimer(500);
connect(FramelessManager::instance(), &FramelessManager::systemThemeChanged, this, &Widget::updateStyleSheet);
}
Widget::~Widget() = default;
void Widget::showEvent(QShowEvent *event)
{
QWidget::showEvent(event);
static bool inited = false;
if (!inited) {
inited = true;
QWindow *win = windowHandle();
Q_ASSERT(win);
if (!win) {
qFatal("Failed to retrieve the window handle.");
return;
}
m_helper = new FramelessHelper(win);
m_helper->setHitTestVisible(m_minimizeButton);
m_helper->setHitTestVisible(m_maximizeButton);
m_helper->setHitTestVisible(m_closeButton);
m_helper->setResizeBorderThickness(4);
m_helper->setTitleBarHeight(m_titleBarWidget->height());
m_helper->install();
#ifndef Q_OS_MAC
const int margin = Utilities::getWindowVisibleFrameBorderThickness(winId());
setContentsMargins(margin, margin, margin, margin);
#else // Q_OS_MAC
m_minimizeButton->hide();
m_maximizeButton->hide();
m_closeButton->hide();
Utilities::setStandardWindowButtonsVisibility(windowHandle(), true);
#endif // Q_OS_MAC
}
}
void Widget::timerEvent(QTimerEvent *event)
{
QWidget::timerEvent(event);
FramelessWidget::timerEvent(event);
if (m_clockLabel) {
m_clockLabel->setText(QTime::currentTime().toString(QStringLiteral("hh:mm:ss")));
m_clockLabel->setText(QTime::currentTime().toString(FRAMELESSHELPER_STRING_LITERAL("hh:mm:ss")));
}
}
#ifndef Q_OS_MAC
void Widget::changeEvent(QEvent *event)
void Widget::closeEvent(QCloseEvent *event)
{
QWidget::changeEvent(event);
bool shouldUpdate = false;
if (event->type() == QEvent::WindowStateChange) {
const int margin = ((isMaximized() || isFullScreen()) ? 0 : Utilities::getWindowVisibleFrameBorderThickness(winId()));
setContentsMargins(margin, margin, margin, margin);
updateSystemButtonIcons();
shouldUpdate = true;
} else if (event->type() == QEvent::ActivationChange) {
shouldUpdate = true;
}
if (shouldUpdate) {
updateStyleSheet();
if (!parent()) {
const QString objName = objectName();
Settings::set(objName, kGeometry, geometry());
Settings::set(objName, kDevicePixelRatio, devicePixelRatioF());
}
FramelessWidget::closeEvent(event);
}
void Widget::paintEvent(QPaintEvent *event)
void Widget::initialize()
{
QWidget::paintEvent(event);
if (!isMaximized() && !isFullScreen()) {
QPainter painter(this);
painter.save();
painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform);
const auto w = static_cast<qreal>(width());
const auto h = static_cast<qreal>(height());
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
using BorderLines = QList<QLineF>;
#else
using BorderLines = QVector<QLineF>;
#endif
const BorderLines lines = {
{0, 0, w, 0},
{w, 0, w , h},
{w, h, 0, h},
{0, h, 0, 0}
};
const ColorizationArea area = Utilities::getColorizationArea();
const bool colorizedBorder = ((area == ColorizationArea::TitleBar_WindowBorder)
|| (area == ColorizationArea::AllArea));
const QColor borderColor = (isActiveWindow() ? (colorizedBorder ? Utilities::getColorizationColor() : Qt::black) : Qt::darkGray);
const auto borderThickness = static_cast<qreal>(Utilities::getWindowVisibleFrameBorderThickness(winId()));
painter.setPen({borderColor, qMax(borderThickness, devicePixelRatioF())});
painter.drawLines(lines);
painter.restore();
}
}
#endif // Q_OS_MAC
void Widget::setupUi()
{
setObjectName(QStringLiteral("MainWidget"));
setWindowTitle(tr("Hello, World!"));
setWindowTitle(tr("FramelessHelper demo application - QWidget"));
setWindowIcon(QFileIconProvider().icon(QFileIconProvider::Computer));
resize(800, 600);
m_titleBarWidget = new QWidget(this);
m_titleBarWidget->setObjectName(QStringLiteral("TitleBarWidget"));
m_titleBarWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
m_titleBarWidget->setFixedHeight(28);
const QSize systemButtonSize = {45, 30};
m_windowTitleLabel = new QLabel(m_titleBarWidget);
m_windowTitleLabel->setObjectName(QStringLiteral("WindowTitleLabel"));
m_windowTitleLabel->setFrameShape(QFrame::NoFrame);
QFont titleFont = font();
titleFont.setPointSize(11);
m_windowTitleLabel->setFont(titleFont);
m_windowTitleLabel->setText(windowTitle());
connect(this, &Widget::windowTitleChanged, m_windowTitleLabel, &QLabel::setText);
m_minimizeButton = new QPushButton(m_titleBarWidget);
m_minimizeButton->setObjectName(QStringLiteral("MinimizeButton"));
m_minimizeButton->setFixedSize(systemButtonSize);
m_minimizeButton->setIconSize(systemButtonSize);
connect(m_minimizeButton, &QPushButton::clicked, this, &Widget::showMinimized);
m_maximizeButton = new QPushButton(m_titleBarWidget);
m_maximizeButton->setObjectName(QStringLiteral("MaximizeButton"));
m_maximizeButton->setFixedSize(systemButtonSize);
m_maximizeButton->setIconSize(systemButtonSize);
connect(m_maximizeButton, &QPushButton::clicked, this, [this](){
if (isMaximized() || isFullScreen()) {
showNormal();
} else {
showMaximized();
}
updateSystemButtonIcons();
});
m_closeButton = new QPushButton(m_titleBarWidget);
m_closeButton->setObjectName(QStringLiteral("CloseButton"));
m_closeButton->setFixedSize(systemButtonSize);
m_closeButton->setIconSize(systemButtonSize);
connect(m_closeButton, &QPushButton::clicked, this, &Widget::close);
updateSystemButtonIcons();
const auto titleBarLayout = new QHBoxLayout(m_titleBarWidget);
titleBarLayout->setContentsMargins(0, 0, 0, 0);
titleBarLayout->setSpacing(0);
titleBarLayout->addSpacerItem(new QSpacerItem(10, 10));
#ifdef Q_OS_MAC
titleBarLayout->addStretch();
#endif // Q_OS_MAC
titleBarLayout->addWidget(m_windowTitleLabel);
titleBarLayout->addStretch();
titleBarLayout->addWidget(m_minimizeButton);
titleBarLayout->addWidget(m_maximizeButton);
titleBarLayout->addWidget(m_closeButton);
m_titleBarWidget->setLayout(titleBarLayout);
m_titleBar = new StandardTitleBar(this);
m_titleBar->setWindowIconVisible(true);
m_clockLabel = new QLabel(this);
m_clockLabel->setObjectName(QStringLiteral("ClockLabel"));
m_clockLabel->setFrameShape(QFrame::NoFrame);
QFont clockFont = font();
clockFont.setBold(true);
clockFont.setPointSize(70);
m_clockLabel->setFont(clockFont);
const auto contentLayout = new QHBoxLayout;
contentLayout->setContentsMargins(0, 0, 0, 0);
contentLayout->setSpacing(0);
contentLayout->addStretch();
contentLayout->addWidget(m_clockLabel);
contentLayout->addStretch();
const auto mainLayout = new QVBoxLayout(this);
mainLayout->setContentsMargins(0, 0, 0, 0);
mainLayout->setSpacing(0);
mainLayout->addWidget(m_titleBarWidget);
mainLayout->addStretch();
mainLayout->setContentsMargins(0, 0, 0, 0);
mainLayout->addWidget(m_titleBar);
mainLayout->addLayout(contentLayout);
mainLayout->addStretch();
setLayout(mainLayout);
updateStyleSheet();
m_cancelShortcut = new QShortcut(this);
m_cancelShortcut->setKey(FRAMELESSHELPER_STRING_LITERAL("ESC"));
connect(m_cancelShortcut, &QShortcut::activated, this, [this](){
if (isFullScreen()) {
Q_EMIT m_fullScreenShortcut->activated();
} else {
close();
}
});
m_fullScreenShortcut = new QShortcut(this);
m_fullScreenShortcut->setKey(FRAMELESSHELPER_STRING_LITERAL("ALT+RETURN"));
connect(m_fullScreenShortcut, &QShortcut::activated, this, [this](){
if (isFullScreen()) {
setWindowState(windowState() & ~Qt::WindowFullScreen);
} else {
showFullScreen();
}
});
connect(this, &Widget::objectNameChanged, this, [this](const QString &name){
if (name.isEmpty()) {
return;
}
setWindowTitle(windowTitle() + FRAMELESSHELPER_STRING_LITERAL(" [%1]").arg(name));
});
FramelessWidgetsHelper *helper = FramelessWidgetsHelper::get(this);
helper->setTitleBarWidget(m_titleBar);
#ifndef Q_OS_MACOS
helper->setSystemButton(m_titleBar->minimizeButton(), SystemButtonType::Minimize);
helper->setSystemButton(m_titleBar->maximizeButton(), SystemButtonType::Maximize);
helper->setSystemButton(m_titleBar->closeButton(), SystemButtonType::Close);
#endif // Q_OS_MACOS
}
void Widget::updateStyleSheet()
{
const bool active = isActiveWindow();
const bool dark = Utilities::shouldAppsUseDarkMode();
const ColorizationArea area = Utilities::getColorizationArea();
const bool colorizedTitleBar = ((area == ColorizationArea::TitleBar_WindowBorder)
|| (area == ColorizationArea::AllArea));
const QColor colorizationColor = Utilities::getColorizationColor();
const QColor mainWidgetBackgroundColor = (dark ? systemDarkColor : systemLightColor);
const QColor titleBarWidgetBackgroundColor = [active, colorizedTitleBar, &colorizationColor, dark]{
if (active) {
if (colorizedTitleBar) {
return colorizationColor;
} else {
if (dark) {
return QColor(Qt::black);
} else {
return QColor(Qt::white);
}
}
} else {
if (dark) {
return systemDarkColor;
} else {
return QColor(Qt::white);
}
}
}();
const QColor windowTitleLabelTextColor = (active ? (dark ? Qt::white : Qt::black) : Qt::darkGray);
const QColor clockLabelTextColor = (dark ? Qt::white : Qt::black);
setStyleSheet(QString::fromUtf8(mainStyleSheet)
.arg(mainWidgetBackgroundColor.name(),
titleBarWidgetBackgroundColor.name(),
windowTitleLabelTextColor.name(),
clockLabelTextColor.name()));
const bool dark = (FramelessManager::instance()->systemTheme() == SystemTheme::Dark);
const QColor clockLabelTextColor = (dark ? kDefaultWhiteColor : kDefaultBlackColor);
m_clockLabel->setStyleSheet(FRAMELESSHELPER_STRING_LITERAL("background-color: transparent; color: %1;")
.arg(clockLabelTextColor.name()));
if (FramelessWidgetsHelper::get(this)->isBlurBehindWindowEnabled()) {
setStyleSheet(FRAMELESSHELPER_STRING_LITERAL("background-color: transparent;"));
} else {
const QColor windowBackgroundColor = (dark ? kDefaultSystemDarkColor : kDefaultSystemLightColor);
setStyleSheet(FRAMELESSHELPER_STRING_LITERAL("background-color: %1;").arg(windowBackgroundColor.name()));
}
update();
}
void Widget::updateTitleBarSize()
void Widget::waitReady()
{
const QWindow *win = windowHandle();
Q_ASSERT(win);
if (!win) {
return;
}
const int titleBarHeight = Utilities::getSystemMetric(win, SystemMetric::TitleBarHeight, false);
const QSize systemButtonSize = {qRound(static_cast<qreal>(titleBarHeight) * 1.5), titleBarHeight};
m_minimizeButton->setFixedSize(systemButtonSize);
m_minimizeButton->setIconSize(systemButtonSize);
m_maximizeButton->setFixedSize(systemButtonSize);
m_maximizeButton->setIconSize(systemButtonSize);
m_closeButton->setFixedSize(systemButtonSize);
m_closeButton->setIconSize(systemButtonSize);
m_titleBarWidget->setFixedHeight(titleBarHeight);
}
void Widget::updateSystemButtonIcons()
{
Q_ASSERT(m_minimizeButton);
Q_ASSERT(m_maximizeButton);
Q_ASSERT(m_closeButton);
if (!m_minimizeButton || !m_maximizeButton || !m_closeButton) {
return;
}
const QString suffix = (Utilities::shouldAppsUseDarkMode() ? QStringLiteral("white") : QStringLiteral("black"));
m_minimizeButton->setIcon(QIcon(QStringLiteral(":/images/button_minimize_%1.svg").arg(suffix)));
if (isMaximized() || isFullScreen()) {
m_maximizeButton->setIcon(QIcon(QStringLiteral(":/images/button_restore_%1.svg").arg(suffix)));
FramelessWidgetsHelper *helper = FramelessWidgetsHelper::get(this);
helper->waitForReady();
const QString objName = objectName();
const auto savedGeometry = Settings::get<QRect>(objName, kGeometry);
if (savedGeometry.isValid() && !parent()) {
const auto savedDpr = Settings::get<qreal>(objName, kDevicePixelRatio);
// Qt doesn't support dpr < 1.
const qreal oldDpr = std::max(savedDpr, qreal(1));
const qreal scale = (devicePixelRatioF() / oldDpr);
setGeometry({savedGeometry.topLeft() * scale, savedGeometry.size() * scale});
} else {
m_maximizeButton->setIcon(QIcon(QStringLiteral(":/images/button_maximize_%1.svg").arg(suffix)));
helper->moveWindowToDesktopCenter();
}
m_closeButton->setIcon(QIcon(QStringLiteral(":/images/button_close_%1.svg").arg(suffix)));
}
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
bool Widget::nativeEvent(const QByteArray &eventType, void *message, qintptr *result)
#else
bool Widget::nativeEvent(const QByteArray &eventType, void *message, long *result)
#endif
{
#ifdef Q_OS_WIN
if (m_helper) {
if (m_helper->handleNativeEvent(this->windowHandle(), eventType, message, result))
return true;
else
return QWidget::nativeEvent(eventType, message, result);
}
#endif
if (message) {
if (Utilities::isThemeChanged(message)) {
updateStyleSheet();
updateSystemButtonIcons();
return true;
}
QPointF pos = {};
if (Utilities::isSystemMenuRequested(message, &pos)) {
if (Utilities::showSystemMenu(winId(), pos)) {
return true;
} else {
qWarning() << "Failed to display the system menu.";
}
}
}
return QWidget::nativeEvent(eventType, message, result);
}

View File

@ -1,7 +1,7 @@
/*
* MIT License
*
* Copyright (C) 2021 by wangwenx190 (Yuhang Zhao)
* Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@ -24,49 +24,41 @@
#pragma once
#include <QtWidgets/qwidget.h>
#include "core/framelesshelper.h"
#include <FramelessHelper/Widgets/framelesswidget.h>
QT_BEGIN_NAMESPACE
QT_FORWARD_DECLARE_CLASS(QLabel)
QT_FORWARD_DECLARE_CLASS(QPushButton)
class QLabel;
class QShortcut;
QT_END_NAMESPACE
class Widget : public QWidget
FRAMELESSHELPER_BEGIN_NAMESPACE
class StandardTitleBar;
FRAMELESSHELPER_END_NAMESPACE
class Widget : public FRAMELESSHELPER_PREPEND_NAMESPACE(FramelessWidget)
{
Q_OBJECT
Q_DISABLE_COPY_MOVE(Widget)
public:
explicit Widget(QWidget *parent = nullptr);
~Widget() override;
void waitReady();
protected:
void showEvent(QShowEvent *event) override;
void timerEvent(QTimerEvent *event) override;
#ifndef Q_OS_MAC
void changeEvent(QEvent *event) override;
void paintEvent(QPaintEvent *event) override;
#endif // Q_OS_MAC
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
bool nativeEvent(const QByteArray &eventType, void *message, qintptr *result) override;
#else
bool nativeEvent(const QByteArray &eventType, void *message, long *result) override;
#endif
void closeEvent(QCloseEvent *event) override;
private:
void setupUi();
void initialize();
private Q_SLOTS:
void updateStyleSheet();
void updateTitleBarSize();
void updateSystemButtonIcons();
private:
__flh_ns::FramelessHelper *m_helper = nullptr;
QWidget *m_titleBarWidget = nullptr;
QLabel *m_windowTitleLabel = nullptr;
QPushButton *m_minimizeButton = nullptr;
QPushButton *m_maximizeButton = nullptr;
QPushButton *m_closeButton = nullptr;
QLabel *m_clockLabel = nullptr;
FRAMELESSHELPER_PREPEND_NAMESPACE(StandardTitleBar) *m_titleBar = nullptr;
QShortcut *m_fullScreenShortcut = nullptr;
QShortcut *m_cancelShortcut = nullptr;
};

View File

@ -1,6 +1,14 @@
TARGET = Widget
TEMPLATE = app
TARGET = FramelessHelperDemo-Widget
QT += widgets
HEADERS += widget.h
SOURCES += widget.cpp main.cpp
include($$PWD/../common.pri)
HEADERS += \
../shared/log.h \
../shared/settings.h \
widget.h
SOURCES += \
../shared/log.cpp \
../shared/settings.cpp \
widget.cpp \
main.cpp
include(../../qmake/core.pri)
include(../../qmake/widgets.pri)

View File

@ -0,0 +1 @@
#include "chromepalette.h"

View File

@ -0,0 +1 @@
#include "framelesshelper_linux.h"

View File

@ -0,0 +1 @@
#include "framelesshelper_qt.h"

View File

@ -0,0 +1 @@
#include "framelesshelper_win.h"

View File

@ -0,0 +1 @@
#include "framelesshelper_windows.h"

View File

@ -0,0 +1 @@
#include "framelessmanager.h"

View File

@ -0,0 +1 @@
#include "framelesshelpercore_global.h"

View File

@ -0,0 +1 @@
#include "micamaterial.h"

View File

@ -0,0 +1 @@
#include "utils.h"

View File

@ -0,0 +1 @@
#include "windowborderpainter.h"

View File

@ -0,0 +1,125 @@
/*
* MIT License
*
* Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#pragma once
#include <FramelessHelper/Core/framelesshelpercore_global.h>
FRAMELESSHELPER_BEGIN_NAMESPACE
class ChromePalettePrivate;
class FRAMELESSHELPER_CORE_API ChromePalette : public QObject
{
Q_OBJECT
Q_DECLARE_PRIVATE(ChromePalette)
Q_DISABLE_COPY_MOVE(ChromePalette)
Q_PROPERTY(QColor titleBarActiveBackgroundColor READ titleBarActiveBackgroundColor
WRITE setTitleBarActiveBackgroundColor RESET resetTitleBarActiveBackgroundColor
NOTIFY titleBarActiveBackgroundColorChanged FINAL)
Q_PROPERTY(QColor titleBarInactiveBackgroundColor READ titleBarInactiveBackgroundColor
WRITE setTitleBarInactiveBackgroundColor RESET resetTitleBarInactiveBackgroundColor
NOTIFY titleBarInactiveBackgroundColorChanged FINAL)
Q_PROPERTY(QColor titleBarActiveForegroundColor READ titleBarActiveForegroundColor
WRITE setTitleBarActiveForegroundColor RESET resetTitleBarActiveForegroundColor
NOTIFY titleBarActiveForegroundColorChanged FINAL)
Q_PROPERTY(QColor titleBarInactiveForegroundColor READ titleBarInactiveForegroundColor
WRITE setTitleBarInactiveForegroundColor RESET resetTitleBarInactiveForegroundColor
NOTIFY titleBarInactiveForegroundColorChanged FINAL)
Q_PROPERTY(QColor chromeButtonNormalColor READ chromeButtonNormalColor
WRITE setChromeButtonNormalColor RESET resetChromeButtonNormalColor
NOTIFY chromeButtonNormalColorChanged FINAL)
Q_PROPERTY(QColor chromeButtonHoverColor READ chromeButtonHoverColor
WRITE setChromeButtonHoverColor RESET resetChromeButtonHoverColor
NOTIFY chromeButtonHoverColorChanged FINAL)
Q_PROPERTY(QColor chromeButtonPressColor READ chromeButtonPressColor
WRITE setChromeButtonPressColor RESET resetChromeButtonPressColor
NOTIFY chromeButtonPressColorChanged FINAL)
Q_PROPERTY(QColor closeButtonNormalColor READ closeButtonNormalColor
WRITE setCloseButtonNormalColor RESET resetCloseButtonNormalColor
NOTIFY closeButtonNormalColorChanged FINAL)
Q_PROPERTY(QColor closeButtonHoverColor READ closeButtonHoverColor
WRITE setCloseButtonHoverColor RESET resetCloseButtonHoverColor
NOTIFY closeButtonHoverColorChanged FINAL)
Q_PROPERTY(QColor closeButtonPressColor READ closeButtonPressColor
WRITE setCloseButtonPressColor RESET resetCloseButtonPressColor
NOTIFY closeButtonPressColorChanged FINAL)
public:
explicit ChromePalette(QObject *parent = nullptr);
~ChromePalette() override;
Q_NODISCARD QColor titleBarActiveBackgroundColor() const;
Q_NODISCARD QColor titleBarInactiveBackgroundColor() const;
Q_NODISCARD QColor titleBarActiveForegroundColor() const;
Q_NODISCARD QColor titleBarInactiveForegroundColor() const;
Q_NODISCARD QColor chromeButtonNormalColor() const;
Q_NODISCARD QColor chromeButtonHoverColor() const;
Q_NODISCARD QColor chromeButtonPressColor() const;
Q_NODISCARD QColor closeButtonNormalColor() const;
Q_NODISCARD QColor closeButtonHoverColor() const;
Q_NODISCARD QColor closeButtonPressColor() const;
public Q_SLOTS:
void setTitleBarActiveBackgroundColor(const QColor &value);
void resetTitleBarActiveBackgroundColor();
void setTitleBarInactiveBackgroundColor(const QColor &value);
void resetTitleBarInactiveBackgroundColor();
void setTitleBarActiveForegroundColor(const QColor &value);
void resetTitleBarActiveForegroundColor();
void setTitleBarInactiveForegroundColor(const QColor &value);
void resetTitleBarInactiveForegroundColor();
void setChromeButtonNormalColor(const QColor &value);
void resetChromeButtonNormalColor();
void setChromeButtonHoverColor(const QColor &value);
void resetChromeButtonHoverColor();
void setChromeButtonPressColor(const QColor &value);
void resetChromeButtonPressColor();
void setCloseButtonNormalColor(const QColor &value);
void resetCloseButtonNormalColor();
void setCloseButtonHoverColor(const QColor &value);
void resetCloseButtonHoverColor();
void setCloseButtonPressColor(const QColor &value);
void resetCloseButtonPressColor();
Q_SIGNALS:
void titleBarActiveBackgroundColorChanged();
void titleBarInactiveBackgroundColorChanged();
void titleBarActiveForegroundColorChanged();
void titleBarInactiveForegroundColorChanged();
void chromeButtonNormalColorChanged();
void chromeButtonHoverColorChanged();
void chromeButtonPressColorChanged();
void closeButtonNormalColorChanged();
void closeButtonHoverColorChanged();
void closeButtonPressColorChanged();
void titleBarColorChanged();
void chromeButtonColorChanged();
private:
QScopedPointer<ChromePalettePrivate> d_ptr;
};
FRAMELESSHELPER_END_NAMESPACE

View File

@ -0,0 +1,526 @@
/*
* MIT License
*
* Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#pragma once
#include <FramelessHelper/Core/framelesshelpercore_global.h>
/*
* Copyright (C) 2001-2006 Bart Massey, Jamey Sharp, and Josh Triplett.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the names of the authors or their
* institutions shall not be used in advertising or otherwise to promote the
* sale, use or other dealings in this Software without prior written
* authorization from the authors.
*/
// This one is not included in any public headers.
using Display = struct _XDisplay;
#if 0 // Causes segfault
#ifndef FRAMELESSHELPER_HAS_XLIB
extern "C"
{
FRAMELESSHELPER_CORE_API int
XInitThreads(
void
);
} // extern "C"
#endif // FRAMELESSHELPER_HAS_XLIB
#endif
#if __has_include(<xcb/xcb.h>)
# include <xcb/xcb.h>
# define FRAMELESSHELPER_HAS_XCB
#else // !__has_include(<xcb/xcb.h>)
using xcb_connection_t = struct xcb_connection_t;
using xcb_button_t = uint8_t;
using xcb_window_t = uint32_t;
using xcb_timestamp_t = uint32_t;
using xcb_atom_t = uint32_t;
using xcb_generic_error_t = struct xcb_generic_error_t
{
uint8_t response_type;
uint8_t error_code;
uint16_t sequence;
uint32_t resource_id;
uint16_t minor_code;
uint8_t major_code;
uint8_t pad0;
uint32_t pad[5];
uint32_t full_sequence;
};
using xcb_client_message_data_t = union xcb_client_message_data_t
{
uint8_t data8[20];
uint16_t data16[10];
uint32_t data32[5];
};
using xcb_button_press_event_t = struct xcb_button_press_event_t
{
uint8_t response_type;
xcb_button_t detail;
uint16_t sequence;
xcb_timestamp_t time;
xcb_window_t root;
xcb_window_t event;
xcb_window_t child;
int16_t root_x;
int16_t root_y;
int16_t event_x;
int16_t event_y;
uint16_t state;
uint8_t same_screen;
uint8_t pad0;
};
using xcb_button_release_event_t = xcb_button_press_event_t;
using xcb_void_cookie_t = struct xcb_void_cookie_t
{
unsigned int sequence;
};
using xcb_intern_atom_cookie_t = struct xcb_intern_atom_cookie_t
{
unsigned int sequence;
};
using xcb_intern_atom_reply_t = struct xcb_intern_atom_reply_t
{
uint8_t response_type;
uint8_t pad0;
uint16_t sequence;
uint32_t length;
xcb_atom_t atom;
};
using xcb_client_message_event_t = struct xcb_client_message_event_t
{
uint8_t response_type;
uint8_t format;
uint16_t sequence;
xcb_window_t window;
xcb_atom_t type;
xcb_client_message_data_t data;
};
using xcb_get_property_reply_t = struct xcb_get_property_reply_t
{
uint8_t response_type;
uint8_t format;
uint16_t sequence;
uint32_t length;
xcb_atom_t type;
uint32_t bytes_after;
uint32_t value_len;
uint8_t pad0[12];
};
using xcb_get_property_cookie_t = struct xcb_get_property_cookie_t
{
unsigned int sequence;
};
using xcb_list_properties_cookie_t = struct xcb_list_properties_cookie_t
{
unsigned int sequence;
};
using xcb_list_properties_reply_t = struct xcb_list_properties_reply_t
{
uint8_t response_type;
uint8_t pad0;
uint16_t sequence;
uint32_t length;
uint16_t atoms_len;
uint8_t pad1[22];
};
[[maybe_unused]] inline constexpr const auto XCB_NONE = 0;
[[maybe_unused]] inline constexpr const auto XCB_WINDOW_NONE = 0;
[[maybe_unused]] inline constexpr const auto XCB_CURRENT_TIME = 0;
[[maybe_unused]] inline constexpr const auto XCB_PROP_MODE_REPLACE = 0;
[[maybe_unused]] inline constexpr const auto XCB_ATOM_ATOM = 4;
[[maybe_unused]] inline constexpr const auto XCB_ATOM_CARDINAL = 6;
[[maybe_unused]] inline constexpr const auto XCB_ATOM_WINDOW = 33;
[[maybe_unused]] inline constexpr const auto XCB_BUTTON_INDEX_ANY = 0;
[[maybe_unused]] inline constexpr const auto XCB_BUTTON_INDEX_1 = 1;
[[maybe_unused]] inline constexpr const auto XCB_BUTTON_INDEX_2 = 2;
[[maybe_unused]] inline constexpr const auto XCB_BUTTON_INDEX_3 = 3;
[[maybe_unused]] inline constexpr const auto XCB_BUTTON_RELEASE = 5;
[[maybe_unused]] inline constexpr const auto XCB_CLIENT_MESSAGE = 33;
[[maybe_unused]] inline constexpr const auto XCB_EVENT_MASK_STRUCTURE_NOTIFY = 131072;
[[maybe_unused]] inline constexpr const auto XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT = 1048576;
[[maybe_unused]] inline constexpr const auto XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY = 524288;
#endif // __has_include(<xcb/xcb.h>)
[[maybe_unused]] inline constexpr const auto _NET_WM_MOVERESIZE_SIZE_TOPLEFT = 0;
[[maybe_unused]] inline constexpr const auto _NET_WM_MOVERESIZE_SIZE_TOP = 1;
[[maybe_unused]] inline constexpr const auto _NET_WM_MOVERESIZE_SIZE_TOPRIGHT = 2;
[[maybe_unused]] inline constexpr const auto _NET_WM_MOVERESIZE_SIZE_RIGHT = 3;
[[maybe_unused]] inline constexpr const auto _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT = 4;
[[maybe_unused]] inline constexpr const auto _NET_WM_MOVERESIZE_SIZE_BOTTOM = 5;
[[maybe_unused]] inline constexpr const auto _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT = 6;
[[maybe_unused]] inline constexpr const auto _NET_WM_MOVERESIZE_SIZE_LEFT = 7;
[[maybe_unused]] inline constexpr const auto _NET_WM_MOVERESIZE_MOVE = 8;
[[maybe_unused]] inline constexpr const auto _NET_WM_MOVERESIZE_SIZE_KEYBOARD = 9;
[[maybe_unused]] inline constexpr const auto _NET_WM_MOVERESIZE_MOVE_KEYBOARD = 10;
[[maybe_unused]] inline constexpr const auto _NET_WM_MOVERESIZE_CANCEL = 11;
[[maybe_unused]] inline constexpr const char ATOM_NET_SUPPORTED[] = "_NET_SUPPORTED";
[[maybe_unused]] inline constexpr const char ATOM_NET_WM_NAME[] = "_NET_WM_NAME";
[[maybe_unused]] inline constexpr const char ATOM_NET_WM_MOVERESIZE[] = "_NET_WM_MOVERESIZE";
[[maybe_unused]] inline constexpr const char ATOM_NET_SUPPORTING_WM_CHECK[] = "_NET_SUPPORTING_WM_CHECK";
[[maybe_unused]] inline constexpr const char ATOM_NET_KDE_COMPOSITE_TOGGLING[] = "_NET_KDE_COMPOSITE_TOGGLING";
[[maybe_unused]] inline constexpr const char ATOM_KDE_NET_WM_BLUR_BEHIND_REGION[] = "_KDE_NET_WM_BLUR_BEHIND_REGION";
[[maybe_unused]] inline constexpr const char ATOM_GTK_SHOW_WINDOW_MENU[] = "_GTK_SHOW_WINDOW_MENU";
[[maybe_unused]] inline constexpr const char ATOM_DEEPIN_NO_TITLEBAR[] = "_DEEPIN_NO_TITLEBAR";
[[maybe_unused]] inline constexpr const char ATOM_DEEPIN_FORCE_DECORATE[] = "_DEEPIN_FORCE_DECORATE";
[[maybe_unused]] inline constexpr const char ATOM_NET_WM_DEEPIN_BLUR_REGION_MASK[] = "_NET_WM_DEEPIN_BLUR_REGION_MASK";
[[maybe_unused]] inline constexpr const char ATOM_NET_WM_DEEPIN_BLUR_REGION_ROUNDED[] = "_NET_WM_DEEPIN_BLUR_REGION_ROUNDED";
[[maybe_unused]] inline constexpr const char ATOM_UTF8_STRING[] = "UTF8_STRING";
#ifndef FRAMELESSHELPER_HAS_XCB
extern "C"
{
FRAMELESSHELPER_CORE_API xcb_void_cookie_t
xcb_send_event(
xcb_connection_t *connection,
uint8_t propagate,
xcb_window_t destination,
uint32_t event_mask,
const char *event
);
FRAMELESSHELPER_CORE_API int
xcb_flush(
xcb_connection_t *connection
);
FRAMELESSHELPER_CORE_API xcb_intern_atom_cookie_t
xcb_intern_atom(
xcb_connection_t *connection,
uint8_t only_if_exists,
uint16_t name_len,
const char *name
);
FRAMELESSHELPER_CORE_API xcb_intern_atom_reply_t *
xcb_intern_atom_reply(
xcb_connection_t *connection,
xcb_intern_atom_cookie_t cookie,
xcb_generic_error_t **error
);
FRAMELESSHELPER_CORE_API xcb_void_cookie_t
xcb_ungrab_pointer(
xcb_connection_t *connection,
xcb_timestamp_t time
);
FRAMELESSHELPER_CORE_API xcb_void_cookie_t
xcb_change_property(
xcb_connection_t *connection,
uint8_t mode,
xcb_window_t window,
xcb_atom_t property,
xcb_atom_t type,
uint8_t format,
uint32_t data_len,
const void *data
);
FRAMELESSHELPER_CORE_API xcb_void_cookie_t
xcb_delete_property_checked(
xcb_connection_t *connection,
xcb_window_t window,
xcb_atom_t property
);
FRAMELESSHELPER_CORE_API xcb_get_property_cookie_t
xcb_get_property(
xcb_connection_t *connection,
uint8_t _delete,
xcb_window_t window,
xcb_atom_t property,
xcb_atom_t type,
uint32_t long_offset,
uint32_t long_length
);
FRAMELESSHELPER_CORE_API xcb_get_property_reply_t *
xcb_get_property_reply(
xcb_connection_t *connection,
xcb_get_property_cookie_t cookie,
xcb_generic_error_t **error
);
FRAMELESSHELPER_CORE_API void *
xcb_get_property_value(
const xcb_get_property_reply_t *reply
);
FRAMELESSHELPER_CORE_API int
xcb_get_property_value_length(
const xcb_get_property_reply_t *reply
);
FRAMELESSHELPER_CORE_API xcb_list_properties_cookie_t
xcb_list_properties(
xcb_connection_t *connection,
xcb_window_t window
);
FRAMELESSHELPER_CORE_API xcb_list_properties_reply_t *
xcb_list_properties_reply(
xcb_connection_t *connection,
xcb_list_properties_cookie_t cookie,
xcb_generic_error_t **error
);
FRAMELESSHELPER_CORE_API int
xcb_list_properties_atoms_length(
const xcb_list_properties_reply_t *atom
);
FRAMELESSHELPER_CORE_API xcb_atom_t *
xcb_list_properties_atoms(
const xcb_list_properties_reply_t *atom
);
FRAMELESSHELPER_CORE_API xcb_get_property_cookie_t
xcb_get_property_unchecked(
xcb_connection_t *connection,
uint8_t _delete,
xcb_window_t window,
xcb_atom_t property,
xcb_atom_t type,
uint32_t long_offset,
uint32_t long_length
);
} // extern "C"
#endif // FRAMELESSHELPER_HAS_XCB
/* GTK - The GIMP Toolkit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GTK+ Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
#if __has_include(<gtk/gtk.h>)
# undef signals // Workaround a compilation issue caused by GTK.
# include <gtk/gtk.h>
# define FRAMELESSHELPER_HAS_GTK
#else // !__has_include(<gtk/gtk.h>)
#define G_VALUE_INIT { 0, { { 0 } } }
#define g_signal_connect(instance, detailed_signal, c_handler, data) \
g_signal_connect_data((instance), (detailed_signal), (c_handler), (data), nullptr, G_CONNECT_DEFAULT)
using gint = int;
using glong = long;
using gshort = short;
using gboolean = int;
using gushort = unsigned short;
using guint = unsigned int;
using gulong = unsigned long;
using gfloat = float;
using gdouble = double;
using gchar = char;
using guchar = unsigned char;
using gchararray = char *;
using gpointer = void *;
using gint64 = signed long;
using guint64 = unsigned long;
using gsize = unsigned int;
using GType = unsigned long; // TODO: or unsigned int?
using GValue = struct _GValue;
using GObject = struct _GObject;
using GClosure = struct _GClosure;
using GtkSettings = struct _GtkSettings;
using GConnectFlags = enum GConnectFlags
{
G_CONNECT_DEFAULT = 0,
G_CONNECT_AFTER = 1 << 0,
G_CONNECT_SWAPPED = 1 << 1
};
using GCallback = void(*)(void);
using GClosureNotify = void(*)(gpointer data, GClosure *closure);
struct _GValue
{
GType g_type;
union
{
gint v_int;
guint v_uint;
glong v_long;
gulong v_ulong;
gint64 v_int64;
guint64 v_uint64;
gfloat v_float;
gdouble v_double;
gpointer v_pointer;
} data[2];
};
#endif // __has_include(<gtk/gtk.h>)
[[maybe_unused]] inline constexpr const char GTK_THEME_NAME_ENV_VAR[] = "GTK_THEME";
[[maybe_unused]] inline constexpr const char GTK_THEME_NAME_PROP[] = "gtk-theme-name";
[[maybe_unused]] inline constexpr const char GTK_THEME_PREFER_DARK_PROP[] = "gtk-application-prefer-dark-theme";
#ifndef FRAMELESSHELPER_HAS_GTK
extern "C"
{
FRAMELESSHELPER_CORE_API void
gtk_init(
int *argc,
char ***argv
);
FRAMELESSHELPER_CORE_API GValue *
g_value_init(
GValue *value,
GType g_type
);
FRAMELESSHELPER_CORE_API GValue *
g_value_reset(
GValue *value
);
FRAMELESSHELPER_CORE_API void
g_value_unset(
GValue *value
);
FRAMELESSHELPER_CORE_API gboolean
g_value_get_boolean(
const GValue *value
);
FRAMELESSHELPER_CORE_API const gchar *
g_value_get_string(
const GValue *value
);
FRAMELESSHELPER_CORE_API GtkSettings *
gtk_settings_get_default(
void
);
FRAMELESSHELPER_CORE_API void
g_object_get_property(
GObject *object,
const gchar *property_name,
GValue *value
);
FRAMELESSHELPER_CORE_API gulong
g_signal_connect_data(
gpointer instance,
const gchar *detailed_signal,
GCallback c_handler,
gpointer data,
GClosureNotify destroy_data,
GConnectFlags connect_flags
);
FRAMELESSHELPER_CORE_API void
g_free(
gpointer mem
);
FRAMELESSHELPER_CORE_API void
g_object_unref(
GObject *object
);
FRAMELESSHELPER_CORE_API void
g_clear_object(
GObject **object_ptr
);
} // extern "C"
#endif // FRAMELESSHELPER_HAS_GTK
FRAMELESSHELPER_BEGIN_NAMESPACE
template<typename T>
[[nodiscard]] T gtkSettings(const gchar *property);
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
using x11_return_type = quint32;
#else // (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
using x11_return_type = unsigned long;
#endif // (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
FRAMELESSHELPER_END_NAMESPACE

View File

@ -0,0 +1,49 @@
/*
* MIT License
*
* Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#pragma once
#include <FramelessHelper/Core/framelesshelpercore_global.h>
FRAMELESSHELPER_BEGIN_NAMESPACE
struct SystemParameters;
class FRAMELESSHELPER_CORE_API FramelessHelperQt : public QObject
{
Q_OBJECT
Q_DISABLE_COPY_MOVE(FramelessHelperQt)
public:
explicit FramelessHelperQt(QObject *parent = nullptr);
~FramelessHelperQt() override;
static void addWindow(const SystemParameters *params);
static void removeWindow(const WId windowId);
protected:
Q_NODISCARD bool eventFilter(QObject *object, QEvent *event) override;
};
FRAMELESSHELPER_END_NAMESPACE

View File

@ -1,7 +1,7 @@
/*
* MIT License
*
* Copyright (C) 2021 by wangwenx190 (Yuhang Zhao)
* Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@ -24,17 +24,14 @@
#pragma once
#include "framelesshelper_global.h"
#include <FramelessHelper/Core/framelesshelpercore_global.h>
#include <QtCore/qabstractnativeeventfilter.h>
#include <QtCore/qobject.h>
QT_BEGIN_NAMESPACE
QT_FORWARD_DECLARE_CLASS(QWindow)
QT_END_NAMESPACE
FRAMELESSHELPER_BEGIN_NAMESPACE
class FRAMELESSHELPER_API FramelessHelperWin : public QAbstractNativeEventFilter
struct SystemParameters;
class FRAMELESSHELPER_CORE_API FramelessHelperWin : public QAbstractNativeEventFilter
{
Q_DISABLE_COPY_MOVE(FramelessHelperWin)
@ -42,14 +39,10 @@ public:
explicit FramelessHelperWin();
~FramelessHelperWin() override;
static void addFramelessWindow(QWindow *window);
static void removeFramelessWindow(QWindow *window);
static void addWindow(const SystemParameters *params);
static void removeWindow(const WId windowId);
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
bool nativeEventFilter(const QByteArray &eventType, void *message, qintptr *result) override;
#else
bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) override;
#endif
Q_NODISCARD bool nativeEventFilter(const QByteArray &eventType, void *message, QT_NATIVE_EVENT_RESULT_TYPE *result) override;
};
FRAMELESSHELPER_END_NAMESPACE

View File

@ -0,0 +1,734 @@
/*
* MIT License
*
* Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
// Copyright (C) Microsoft Corporation.
// Licensed under the MIT license.
#pragma once
#ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
#endif
#ifndef WINRT_LEAN_AND_MEAN
# define WINRT_LEAN_AND_MEAN
#endif
#ifndef UNICODE
# define UNICODE
#endif
#ifndef _UNICODE
# define _UNICODE
#endif
#ifndef _CRT_NON_CONFORMING_SWPRINTFS
# define _CRT_NON_CONFORMING_SWPRINTFS
#endif
#ifndef _CRT_SECURE_NO_WARNINGS
# define _CRT_SECURE_NO_WARNINGS
#endif
#ifndef NOMINMAX
# define NOMINMAX
#endif
#if __has_include(<sdkddkver.h>)
# include <sdkddkver.h>
#endif
#ifndef _WIN32_WINNT_WIN10
# define _WIN32_WINNT_WIN10 0x0A00
#endif
#ifndef NTDDI_WIN10_NI
# define NTDDI_WIN10_NI 0x0A00000C
#endif
#ifndef WINVER
# define WINVER _WIN32_WINNT_WIN10
#endif
#ifndef _WIN32_WINNT
# define _WIN32_WINNT _WIN32_WINNT_WIN10
#endif
#ifndef NTDDI_VERSION
# define NTDDI_VERSION NTDDI_WIN10_NI
#endif
#include <windows.h>
#include <uxtheme.h>
#include <shellapi.h>
#include <dwmapi.h>
#include <FramelessHelper/Core/framelesshelpercore_global.h>
#ifndef WM_NCUAHDRAWCAPTION
# define WM_NCUAHDRAWCAPTION (0x00AE)
#endif
#ifndef WM_NCUAHDRAWFRAME
# define WM_NCUAHDRAWFRAME (0x00AF)
#endif
#ifndef WM_DWMCOMPOSITIONCHANGED
# define WM_DWMCOMPOSITIONCHANGED (0x031E)
#endif
#ifndef WM_DWMCOLORIZATIONCOLORCHANGED
# define WM_DWMCOLORIZATIONCOLORCHANGED (0x0320)
#endif
#ifndef WM_DPICHANGED
# define WM_DPICHANGED (0x02E0)
#endif
#ifndef WM_GETDPISCALEDSIZE
# define WM_GETDPISCALEDSIZE (0x02E4)
#endif
#ifndef SM_CXPADDEDBORDER
# define SM_CXPADDEDBORDER (92)
#endif
#ifndef SM_CYPADDEDBORDER
# define SM_CYPADDEDBORDER SM_CXPADDEDBORDER
#endif
#ifndef ABM_GETAUTOHIDEBAREX
# define ABM_GETAUTOHIDEBAREX (0x0000000b)
#endif
#ifndef GET_X_LPARAM
# define GET_X_LPARAM(lp) (static_cast<int>(static_cast<short>(LOWORD(lp))))
#endif
#ifndef GET_Y_LPARAM
# define GET_Y_LPARAM(lp) (static_cast<int>(static_cast<short>(HIWORD(lp))))
#endif
#ifndef IsMinimized
# define IsMinimized(hwnd) (IsIconic(hwnd) != FALSE)
#endif
#ifndef IsMaximized
# define IsMaximized(hwnd) (IsZoomed(hwnd) != FALSE)
#endif
#ifndef RECT_WIDTH
# define RECT_WIDTH(rect) ((rect).right - (rect).left)
#endif
#ifndef RECT_HEIGHT
# define RECT_HEIGHT(rect) ((rect).bottom - (rect).top)
#endif
#ifndef MMSYSERR_NOERROR
# define MMSYSERR_NOERROR (0)
#endif
#ifndef TIMERR_NOERROR
# define TIMERR_NOERROR (0)
#endif
#ifndef WS_EX_NOREDIRECTIONBITMAP
# define WS_EX_NOREDIRECTIONBITMAP (0x00200000L)
#endif
#ifndef USER_DEFAULT_SCREEN_DPI
# define USER_DEFAULT_SCREEN_DPI (96)
#endif
DECLARE_HANDLE(_DPI_AWARENESS_CONTEXT);
#ifndef _DPI_AWARENESS_CONTEXT_UNAWARE
# define _DPI_AWARENESS_CONTEXT_UNAWARE (reinterpret_cast<_DPI_AWARENESS_CONTEXT>(-1))
#endif
#ifndef _DPI_AWARENESS_CONTEXT_SYSTEM_AWARE
# define _DPI_AWARENESS_CONTEXT_SYSTEM_AWARE (reinterpret_cast<_DPI_AWARENESS_CONTEXT>(-2))
#endif
#ifndef _DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE
# define _DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE (reinterpret_cast<_DPI_AWARENESS_CONTEXT>(-3))
#endif
#ifndef _DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2
# define _DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 (reinterpret_cast<_DPI_AWARENESS_CONTEXT>(-4))
#endif
#ifndef _DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED
# define _DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED (reinterpret_cast<_DPI_AWARENESS_CONTEXT>(-5))
#endif
#ifndef HKEY_CLASSES_ROOT
# define HKEY_CLASSES_ROOT (reinterpret_cast<HKEY>(static_cast<ULONG_PTR>(static_cast<LONG>(0x80000000))))
#endif
#ifndef HKEY_CURRENT_USER
# define HKEY_CURRENT_USER (reinterpret_cast<HKEY>(static_cast<ULONG_PTR>(static_cast<LONG>(0x80000001))))
#endif
#ifndef HKEY_LOCAL_MACHINE
# define HKEY_LOCAL_MACHINE (reinterpret_cast<HKEY>(static_cast<ULONG_PTR>(static_cast<LONG>(0x80000002))))
#endif
#ifndef HKEY_USERS
# define HKEY_USERS (reinterpret_cast<HKEY>(static_cast<ULONG_PTR>(static_cast<LONG>(0x80000003))))
#endif
#ifndef HKEY_PERFORMANCE_DATA
# define HKEY_PERFORMANCE_DATA (reinterpret_cast<HKEY>(static_cast<ULONG_PTR>(static_cast<LONG>(0x80000004))))
#endif
#ifndef HKEY_CURRENT_CONFIG
# define HKEY_CURRENT_CONFIG (reinterpret_cast<HKEY>(static_cast<ULONG_PTR>(static_cast<LONG>(0x80000005))))
#endif
#ifndef HKEY_DYN_DATA
# define HKEY_DYN_DATA (reinterpret_cast<HKEY>(static_cast<ULONG_PTR>(static_cast<LONG>(0x80000006))))
#endif
#ifndef HKEY_CURRENT_USER_LOCAL_SETTINGS
# define HKEY_CURRENT_USER_LOCAL_SETTINGS (reinterpret_cast<HKEY>(static_cast<ULONG_PTR>(static_cast<LONG>(0x80000007))))
#endif
#ifndef HKEY_PERFORMANCE_TEXT
# define HKEY_PERFORMANCE_TEXT (reinterpret_cast<HKEY>(static_cast<ULONG_PTR>(static_cast<LONG>(0x80000050))))
#endif
#ifndef HKEY_PERFORMANCE_NLSTEXT
# define HKEY_PERFORMANCE_NLSTEXT (reinterpret_cast<HKEY>(static_cast<ULONG_PTR>(static_cast<LONG>(0x80000060))))
#endif
#ifndef _STATUS_SUCCESS
# define _STATUS_SUCCESS (static_cast<_NTSTATUS>(0x00000000L))
#endif
#ifndef WTNCA_NODRAWCAPTION
# define WTNCA_NODRAWCAPTION (0x00000001) // don't draw the window caption
#endif
#ifndef WTNCA_NODRAWICON
# define WTNCA_NODRAWICON (0x00000002) // don't draw the system icon
#endif
#ifndef WTNCA_NOSYSMENU
# define WTNCA_NOSYSMENU (0x00000004) // don't expose the system menu icon functionality
#endif
#ifndef WTNCA_NOMIRRORHELP
# define WTNCA_NOMIRRORHELP (0x00000008) // don't mirror the question mark, even in RTL layout
#endif
#ifndef WTNCA_VALIDBITS
# define WTNCA_VALIDBITS (WTNCA_NODRAWCAPTION | WTNCA_NODRAWICON | WTNCA_NOSYSMENU | WTNCA_NOMIRRORHELP)
#endif
#ifndef EXTERN_C
# define EXTERN_C extern "C"
#endif
#ifndef EXTERN_C_START
# define EXTERN_C_START EXTERN_C {
#endif
#ifndef EXTERN_C_END
# define EXTERN_C_END }
#endif
using _NTSTATUS = LONG;
using _MMRESULT = UINT;
using _TIMECAPS = struct _TIMECAPS
{
UINT wPeriodMin; // minimum period supported
UINT wPeriodMax; // maximum period supported
};
using _PTIMECAPS = _TIMECAPS *;
using _PROCESS_DPI_AWARENESS = enum _PROCESS_DPI_AWARENESS
{
_PROCESS_DPI_UNAWARE = 0,
_PROCESS_SYSTEM_DPI_AWARE = 1,
_PROCESS_PER_MONITOR_DPI_AWARE = 2,
_PROCESS_PER_MONITOR_V2_DPI_AWARE = 3,
_PROCESS_DPI_UNAWARE_GDISCALED = 4
};
using _MONITOR_DPI_TYPE = enum _MONITOR_DPI_TYPE
{
_MDT_EFFECTIVE_DPI = 0,
_MDT_ANGULAR_DPI = 1,
_MDT_RAW_DPI = 2,
_MDT_DEFAULT = _MDT_EFFECTIVE_DPI
};
using _DEVICE_SCALE_FACTOR = enum _DEVICE_SCALE_FACTOR
{
_DEVICE_SCALE_FACTOR_INVALID = 0,
_SCALE_100_PERCENT = 100,
_SCALE_120_PERCENT = 120,
_SCALE_125_PERCENT = 125,
_SCALE_140_PERCENT = 140,
_SCALE_150_PERCENT = 150,
_SCALE_160_PERCENT = 160,
_SCALE_175_PERCENT = 175,
_SCALE_180_PERCENT = 180,
_SCALE_200_PERCENT = 200,
_SCALE_225_PERCENT = 225,
_SCALE_250_PERCENT = 250,
_SCALE_300_PERCENT = 300,
_SCALE_350_PERCENT = 350,
_SCALE_400_PERCENT = 400,
_SCALE_450_PERCENT = 450,
_SCALE_500_PERCENT = 500
};
using _DPI_AWARENESS = enum _DPI_AWARENESS
{
_DPI_AWARENESS_INVALID = -1,
_DPI_AWARENESS_UNAWARE = 0,
_DPI_AWARENESS_SYSTEM_AWARE = 1,
_DPI_AWARENESS_PER_MONITOR_AWARE = 2,
_DPI_AWARENESS_PER_MONITOR_V2_AWARE = 3,
_DPI_AWARENESS_UNAWARE_GDISCALED = 4
};
using _DWMWINDOWATTRIBUTE = enum _DWMWINDOWATTRIBUTE
{
_DWMWA_USE_HOSTBACKDROPBRUSH = 17, // [set] BOOL, Allows the use of host backdrop brushes for the window.
_DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1 = 19, // Undocumented, the same with DWMWA_USE_IMMERSIVE_DARK_MODE, but available on systems before Win10 20H1.
_DWMWA_USE_IMMERSIVE_DARK_MODE = 20, // [set] BOOL, Allows a window to either use the accent color, or dark, according to the user Color Mode preferences.
_DWMWA_WINDOW_CORNER_PREFERENCE = 33, // [set] WINDOW_CORNER_PREFERENCE, Controls the policy that rounds top-level window corners
_DWMWA_VISIBLE_FRAME_BORDER_THICKNESS = 37, // [get] UINT, width of the visible border around a thick frame window
_DWMWA_SYSTEMBACKDROP_TYPE = 38, // [get, set] SYSTEMBACKDROP_TYPE, Controls the system-drawn backdrop material of a window, including behind the non-client area.
_DWMWA_MICA_EFFECT = 1029 // Undocumented, use this value to enable Mica material on Win11 21H2. You should use DWMWA_SYSTEMBACKDROP_TYPE instead on Win11 22H2 and newer.
};
using _DWM_WINDOW_CORNER_PREFERENCE = enum _DWM_WINDOW_CORNER_PREFERENCE
{
_DWMWCP_DEFAULT = 0, // Let the system decide whether or not to round window corners
_DWMWCP_DONOTROUND = 1, // Never round window corners
_DWMWCP_ROUND = 2, // Round the corners if appropriate
_DWMWCP_ROUNDSMALL = 3 // Round the corners if appropriate, with a small radius
};
using _DWM_SYSTEMBACKDROP_TYPE = enum _DWM_SYSTEMBACKDROP_TYPE
{
_DWMSBT_AUTO = 0, // [Default] Let DWM automatically decide the system-drawn backdrop for this window.
_DWMSBT_NONE = 1, // Do not draw any system backdrop.
_DWMSBT_MAINWINDOW = 2, /* Mica */ // Draw the backdrop material effect corresponding to a long-lived window.
_DWMSBT_TRANSIENTWINDOW = 3, /* Acrylic */ // Draw the backdrop material effect corresponding to a transient window.
_DWMSBT_TABBEDWINDOW = 4 /* Mica Alt */ // Draw the backdrop material effect corresponding to a window with a tabbed title bar.
};
using WINDOWCOMPOSITIONATTRIB = enum WINDOWCOMPOSITIONATTRIB
{
WCA_UNDEFINED = 0,
WCA_NCRENDERING_ENABLED = 1,
WCA_NCRENDERING_POLICY = 2,
WCA_TRANSITIONS_FORCEDISABLED = 3,
WCA_ALLOW_NCPAINT = 4,
WCA_CAPTION_BUTTON_BOUNDS = 5,
WCA_NONCLIENT_RTL_LAYOUT = 6,
WCA_FORCE_ICONIC_REPRESENTATION = 7,
WCA_EXTENDED_FRAME_BOUNDS = 8,
WCA_HAS_ICONIC_BITMAP = 9,
WCA_THEME_ATTRIBUTES = 10,
WCA_NCRENDERING_EXILED = 11,
WCA_NCADORNMENTINFO = 12,
WCA_EXCLUDED_FROM_LIVEPREVIEW = 13,
WCA_VIDEO_OVERLAY_ACTIVE = 14,
WCA_FORCE_ACTIVEWINDOW_APPEARANCE = 15,
WCA_DISALLOW_PEEK = 16,
WCA_CLOAK = 17,
WCA_CLOAKED = 18,
WCA_ACCENT_POLICY = 19,
WCA_FREEZE_REPRESENTATION = 20,
WCA_EVER_UNCLOAKED = 21,
WCA_VISUAL_OWNER = 22,
WCA_HOLOGRAPHIC = 23,
WCA_EXCLUDED_FROM_DDA = 24,
WCA_PASSIVEUPDATEMODE = 25,
WCA_USEDARKMODECOLORS = 26,
WCA_CORNER_STYLE = 27,
WCA_PART_COLOR = 28,
WCA_DISABLE_MOVESIZE_FEEDBACK = 29,
WCA_LAST = 30
};
using ACCENT_STATE = enum ACCENT_STATE
{
ACCENT_DISABLED = 0,
ACCENT_ENABLE_GRADIENT = 1,
ACCENT_ENABLE_TRANSPARENTGRADIENT = 2,
ACCENT_ENABLE_BLURBEHIND = 3, // Traditional DWM blur
ACCENT_ENABLE_ACRYLICBLURBEHIND = 4, // RS4 1803
ACCENT_ENABLE_HOST_BACKDROP = 5, // RS5 1809
ACCENT_INVALID_STATE = 6 // Using this value will remove the window background
};
using ACCENT_FLAG = enum ACCENT_FLAG
{
ACCENT_NONE = 0,
ACCENT_ENABLE_LUMINOSITY = 1 << 1,
ACCENT_ENABLE_BORDER_LEFT = 1 << 5,
ACCENT_ENABLE_BORDER_TOP = 1 << 6,
ACCENT_ENABLE_BORDER_RIGHT = 1 << 7,
ACCENT_ENABLE_BORDER_BOTTOM = 1 << 8,
ACCENT_ENABLE_BORDER = ACCENT_ENABLE_BORDER_LEFT | ACCENT_ENABLE_BORDER_TOP | ACCENT_ENABLE_BORDER_RIGHT | ACCENT_ENABLE_BORDER_BOTTOM,
ACCENT_ENABLE_ALL = ACCENT_ENABLE_BORDER
};
using ACCENT_POLICY = struct ACCENT_POLICY
{
ACCENT_STATE AccentState;
ACCENT_FLAG AccentFlags;
DWORD dwGradientColor; // #AABBGGRR
DWORD dwAnimationId;
};
using PACCENT_POLICY = ACCENT_POLICY *;
using WINDOWCOMPOSITIONATTRIBDATA = struct WINDOWCOMPOSITIONATTRIBDATA
{
WINDOWCOMPOSITIONATTRIB Attrib;
PVOID pvData;
SIZE_T cbData;
};
using PWINDOWCOMPOSITIONATTRIBDATA = WINDOWCOMPOSITIONATTRIBDATA *;
using _WINDOWTHEMEATTRIBUTETYPE = enum _WINDOWTHEMEATTRIBUTETYPE
{
_WTA_NONCLIENT = 1
};
using WTA_OPTIONS2 = struct WTA_OPTIONS2
{
DWORD dwFlags; // Values for each style option specified in the bitmask.
DWORD dwMask; // Bitmask for flags that are changing.
};
using PWTA_OPTIONS2 = WTA_OPTIONS2 *;
using IMMERSIVE_HC_CACHE_MODE = enum IMMERSIVE_HC_CACHE_MODE
{
IHCM_USE_CACHED_VALUE = 0,
IHCM_REFRESH = 1
};
using PREFERRED_APP_MODE = enum PREFERRED_APP_MODE
{
PAM_DEFAULT = 0, // Default behavior on systems before Win10 1809. It indicates the application doesn't support dark mode at all.
PAM_AUTO = 1, // Available since Win10 1809, let system decide whether to enable dark mode or not.
PAM_DARK = 2, // Available since Win10 1903, force dark mode regardless of the system theme.
PAM_LIGHT = 3, // Available since Win10 1903, force light mode regardless of the system theme.
PAM_MAX = 4
};
using GetWindowCompositionAttributePtr = BOOL(WINAPI *)(HWND, PWINDOWCOMPOSITIONATTRIBDATA);
using SetWindowCompositionAttributePtr = BOOL(WINAPI *)(HWND, PWINDOWCOMPOSITIONATTRIBDATA);
// Win10 1809 (10.0.17763)
using ShouldAppsUseDarkModePtr = BOOL(WINAPI *)(VOID); // Ordinal 132
using AllowDarkModeForWindowPtr = BOOL(WINAPI *)(HWND, BOOL); // Ordinal 133
using AllowDarkModeForAppPtr = BOOL(WINAPI *)(BOOL); // Ordinal 135
using FlushMenuThemesPtr = VOID(WINAPI *)(VOID); // Ordinal 136
using RefreshImmersiveColorPolicyStatePtr = VOID(WINAPI *)(VOID); // Ordinal 104
using IsDarkModeAllowedForWindowPtr = BOOL(WINAPI *)(HWND); // Ordinal 137
using GetIsImmersiveColorUsingHighContrastPtr = BOOL(WINAPI *)(IMMERSIVE_HC_CACHE_MODE); // Ordinal 106
using OpenNcThemeDataPtr = HTHEME(WINAPI *)(HWND, LPCWSTR); // Ordinal 49
// Win10 1903 (10.0.18362)
using ShouldSystemUseDarkModePtr = BOOL(WINAPI *)(VOID); // Ordinal 138
using SetPreferredAppModePtr = PREFERRED_APP_MODE(WINAPI *)(PREFERRED_APP_MODE); // Ordinal 135
using IsDarkModeAllowedForAppPtr = BOOL(WINAPI *)(VOID); // Ordinal 139
EXTERN_C_START
///////////////////////////////////////////////
// Function prototypes
_MMRESULT WINAPI
_timeGetDevCaps(
_PTIMECAPS ptc,
UINT cbtc
);
_MMRESULT WINAPI
_timeBeginPeriod(
UINT uPeriod
);
_MMRESULT WINAPI
_timeEndPeriod(
UINT uPeriod
);
HRESULT WINAPI
_SetProcessDpiAwareness(
_PROCESS_DPI_AWARENESS value
);
HRESULT WINAPI
_GetProcessDpiAwareness(
HANDLE hProcess,
_PROCESS_DPI_AWARENESS *value
);
HRESULT WINAPI
_GetDpiForMonitor(
HMONITOR hMonitor,
_MONITOR_DPI_TYPE dpiType,
UINT *dpiX,
UINT *dpiY
);
int WINAPI
_GetSystemMetricsForDpi(
int nIndex,
UINT dpi
);
UINT WINAPI
_GetWindowDPI(
HWND hWnd
);
UINT WINAPI
_GetDpiForWindow(
HWND hWnd
);
UINT WINAPI
_GetDpiForSystem(
VOID
);
UINT WINAPI
_GetSystemDpiForProcess(
HANDLE hProcess
);
BOOL WINAPI
_SetProcessDpiAwarenessContext(
_DPI_AWARENESS_CONTEXT value
);
BOOL WINAPI
_SetProcessDPIAware(
VOID
);
HRESULT WINAPI
_GetScaleFactorForMonitor(
HMONITOR hMon,
_DEVICE_SCALE_FACTOR *pScale
);
BOOL WINAPI
_EnableNonClientDpiScaling(
HWND hWnd
);
_DPI_AWARENESS_CONTEXT WINAPI
_GetThreadDpiAwarenessContext(
VOID
);
_DPI_AWARENESS_CONTEXT WINAPI
_GetWindowDpiAwarenessContext(
HWND hWnd
);
_DPI_AWARENESS WINAPI
_GetAwarenessFromDpiAwarenessContext(
_DPI_AWARENESS_CONTEXT value
);
_DPI_AWARENESS_CONTEXT WINAPI
_GetDpiAwarenessContextForProcess(
HANDLE hProcess
);
BOOL WINAPI
_AreDpiAwarenessContextsEqual(
_DPI_AWARENESS_CONTEXT dpiContextA,
_DPI_AWARENESS_CONTEXT dpiContextB
);
BOOL WINAPI
_EnableChildWindowDpiMessage(
HWND hWnd,
BOOL fEnable
);
BOOL WINAPI
_EnablePerMonitorDialogScaling(
VOID
);
int WINAPI
_GetDpiMetrics(
int nIndex,
UINT dpi
);
BOOL WINAPI
_AdjustWindowRectExForDpi(
LPRECT lpRect,
DWORD dwStyle,
BOOL bMenu,
DWORD dwExStyle,
UINT dpi
);
///////////////////////////////////////////////
// API thunks
FRAMELESSHELPER_CORE_API BOOL WINAPI
_GetWindowCompositionAttribute(
const HWND hWnd,
PWINDOWCOMPOSITIONATTRIBDATA pvData
);
FRAMELESSHELPER_CORE_API BOOL WINAPI
_SetWindowCompositionAttribute(
const HWND hWnd,
PWINDOWCOMPOSITIONATTRIBDATA pvData
);
FRAMELESSHELPER_CORE_API HRESULT WINAPI
_SetWindowThemeAttribute(
const HWND hWnd,
const _WINDOWTHEMEATTRIBUTETYPE attrib,
PVOID pvData,
const DWORD cbData
);
FRAMELESSHELPER_CORE_API HRESULT WINAPI
_SetWindowThemeNonClientAttributes(
const HWND hWnd,
const DWORD dwMask,
const DWORD dwAttributes
);
FRAMELESSHELPER_CORE_API BOOL WINAPI
_ShouldAppsUseDarkMode(
VOID
);
FRAMELESSHELPER_CORE_API BOOL WINAPI
_AllowDarkModeForWindow(
const HWND hWnd,
const BOOL bAllow
);
FRAMELESSHELPER_CORE_API BOOL WINAPI
_AllowDarkModeForApp(
const BOOL bAllow
);
FRAMELESSHELPER_CORE_API VOID WINAPI
_FlushMenuThemes(
VOID
);
FRAMELESSHELPER_CORE_API VOID WINAPI
_RefreshImmersiveColorPolicyState(
VOID
);
FRAMELESSHELPER_CORE_API BOOL WINAPI
_IsDarkModeAllowedForWindow(
const HWND hWnd
);
FRAMELESSHELPER_CORE_API BOOL WINAPI
_GetIsImmersiveColorUsingHighContrast(
const IMMERSIVE_HC_CACHE_MODE mode
);
FRAMELESSHELPER_CORE_API HTHEME WINAPI
_OpenNcThemeData(
const HWND hWnd,
LPCWSTR pszClassList
);
FRAMELESSHELPER_CORE_API BOOL WINAPI
_ShouldSystemUseDarkMode(
VOID
);
FRAMELESSHELPER_CORE_API PREFERRED_APP_MODE WINAPI
_SetPreferredAppMode(
const PREFERRED_APP_MODE mode
);
FRAMELESSHELPER_CORE_API BOOL WINAPI
_IsDarkModeAllowedForApp(
VOID
);
FRAMELESSHELPER_CORE_API BOOL WINAPI
_EnableChildWindowDpiMessage2(
const HWND hWnd,
const BOOL fEnable
);
FRAMELESSHELPER_CORE_API BOOL WINAPI
_EnablePerMonitorDialogScaling2(
VOID
);
FRAMELESSHELPER_CORE_API UINT WINAPI
_GetDpiForWindow2(
const HWND hWnd
);
FRAMELESSHELPER_CORE_API int WINAPI
_GetSystemMetricsForDpi2(
const int nIndex,
const UINT dpi
);
FRAMELESSHELPER_CORE_API BOOL WINAPI
_AdjustWindowRectExForDpi2(
LPRECT lpRect,
const DWORD dwStyle,
const BOOL bMenu,
const DWORD dwExStyle,
const UINT dpi
);
EXTERN_C_END
[[maybe_unused]] inline constexpr const int kAutoHideTaskBarThickness = 2; // The thickness of an auto-hide taskbar in pixels.
[[maybe_unused]] inline constexpr const wchar_t kDwmRegistryKey[] = LR"(Software\Microsoft\Windows\DWM)";
[[maybe_unused]] inline constexpr const wchar_t kPersonalizeRegistryKey[] = LR"(Software\Microsoft\Windows\CurrentVersion\Themes\Personalize)";
[[maybe_unused]] inline constexpr const wchar_t kThemeSettingChangeEventName[] = L"ImmersiveColorSet";
[[maybe_unused]] inline constexpr const wchar_t kDwmColorKeyName[] = L"ColorPrevalence";
[[maybe_unused]] inline constexpr const wchar_t kSystemDarkThemeResourceName[] = L"DarkMode_Explorer";
[[maybe_unused]] inline constexpr const wchar_t kSystemLightThemeResourceName[] = L"Explorer";
[[maybe_unused]] inline constexpr const wchar_t kDesktopRegistryKey[] = LR"(Control Panel\Desktop)";
[[maybe_unused]] inline constexpr const wchar_t kDarkModePropertyName[] = L"UseImmersiveDarkModeColors";

View File

@ -0,0 +1,475 @@
/*
* MIT License
*
* Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#pragma once
#include <QtCore/qglobal.h>
#include <QtCore/qmath.h>
#include <QtCore/qpoint.h>
#include <QtCore/qsize.h>
#include <QtCore/qobject.h>
#include <QtCore/qpointer.h>
#include <QtGui/qcolor.h>
#include <QtGui/qwindowdefs.h>
#include <functional>
#include <optional>
#include <memory>
QT_BEGIN_NAMESPACE
class QEvent;
class QEnterEvent;
QT_END_NAMESPACE
#ifndef FRAMELESSHELPER_CORE_API
# ifdef FRAMELESSHELPER_CORE_STATIC
# define FRAMELESSHELPER_CORE_API
# else // !FRAMELESSHELPER_CORE_STATIC
# ifdef FRAMELESSHELPER_CORE_LIBRARY
# define FRAMELESSHELPER_CORE_API Q_DECL_EXPORT
# else // !FRAMELESSHELPER_CORE_LIBRARY
# define FRAMELESSHELPER_CORE_API Q_DECL_IMPORT
# endif // FRAMELESSHELPER_CORE_LIBRARY
# endif // FRAMELESSHELPER_CORE_STATIC
#endif // FRAMELESSHELPER_CORE_API
#if (defined(Q_OS_WIN) && !defined(Q_OS_WINDOWS))
# define Q_OS_WINDOWS // Since 5.14
#endif
#ifndef Q_DISABLE_COPY_MOVE // Since 5.13
# define Q_DISABLE_COPY_MOVE(Class) \
Q_DISABLE_COPY(Class) \
Class(Class &&) = delete; \
Class &operator=(Class &&) = delete;
#endif
#if (QT_VERSION < QT_VERSION_CHECK(5, 10, 0))
using QStringView = const QString &;
#endif
#if (QT_VERSION < QT_VERSION_CHECK(5, 14, 0))
# define qExchange(a, b) std::exchange(a, b)
#endif
#ifndef Q_NAMESPACE_EXPORT // Since 5.14
# define Q_NAMESPACE_EXPORT(...) Q_NAMESPACE
#endif
// QColor can't be constexpr before 5.14
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
# define Q_COLOR_CONSTEXPR constexpr
#else
# define Q_COLOR_CONSTEXPR
#endif
// MOC can't handle C++ attributes before 5.15.
#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
# define Q_NODISCARD [[nodiscard]]
# define Q_MAYBE_UNUSED [[maybe_unused]]
#else
# define Q_NODISCARD
# define Q_MAYBE_UNUSED
#endif
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
using QT_NATIVE_EVENT_RESULT_TYPE = qintptr;
using QT_ENTER_EVENT_TYPE = QEnterEvent;
#else
using QT_NATIVE_EVENT_RESULT_TYPE = long;
using QT_ENTER_EVENT_TYPE = QEvent;
#endif
#ifndef QUtf8String
# define QUtf8String(str) QString::fromUtf8(str)
#endif
#ifndef Q_GADGET_EXPORT // Since 6.3
# define Q_GADGET_EXPORT(...) Q_GADGET
#endif
#if (QT_VERSION >= QT_VERSION_CHECK(6, 4, 0))
using namespace Qt::Literals::StringLiterals;
#endif
#ifndef FRAMELESSHELPER_BYTEARRAY_LITERAL
# if (QT_VERSION >= QT_VERSION_CHECK(6, 4, 0))
# define FRAMELESSHELPER_BYTEARRAY_LITERAL(ba) ba##_ba
# elif (QT_VERSION >= QT_VERSION_CHECK(6, 2, 0))
# define FRAMELESSHELPER_BYTEARRAY_LITERAL(ba) ba##_qba
# else
# define FRAMELESSHELPER_BYTEARRAY_LITERAL(ba) QByteArrayLiteral(ba)
# endif
#endif
#ifndef FRAMELESSHELPER_STRING_LITERAL
# if (QT_VERSION >= QT_VERSION_CHECK(6, 4, 0))
# define FRAMELESSHELPER_STRING_LITERAL(str) u##str##_s
# elif (QT_VERSION >= QT_VERSION_CHECK(6, 2, 0))
# define FRAMELESSHELPER_STRING_LITERAL(str) u##str##_qs
# else
# define FRAMELESSHELPER_STRING_LITERAL(str) QStringLiteral(str)
# endif
#endif
#ifndef Q_UNREACHABLE_RETURN // Since 6.5
# define Q_UNREACHABLE_RETURN(...) \
do { \
Q_UNREACHABLE(); \
return __VA_ARGS__; \
} while (false)
#endif
#ifndef FRAMELESSHELPER_BYTEARRAY_CONSTANT2
# define FRAMELESSHELPER_BYTEARRAY_CONSTANT2(name, ba) \
[[maybe_unused]] static const auto k##name = FRAMELESSHELPER_BYTEARRAY_LITERAL(ba);
#endif
#ifndef FRAMELESSHELPER_STRING_CONSTANT2
# define FRAMELESSHELPER_STRING_CONSTANT2(name, str) \
[[maybe_unused]] static const auto k##name = FRAMELESSHELPER_STRING_LITERAL(str);
#endif
#ifndef FRAMELESSHELPER_BYTEARRAY_CONSTANT
# define FRAMELESSHELPER_BYTEARRAY_CONSTANT(ba) FRAMELESSHELPER_BYTEARRAY_CONSTANT2(ba, #ba)
#endif
#ifndef FRAMELESSHELPER_STRING_CONSTANT
# define FRAMELESSHELPER_STRING_CONSTANT(str) FRAMELESSHELPER_STRING_CONSTANT2(str, #str)
#endif
#ifndef FRAMELESSHELPER_NAMESPACE
# define FRAMELESSHELPER_NAMESPACE wangwenx190::FramelessHelper
#endif
#ifndef FRAMELESSHELPER_BEGIN_NAMESPACE
# define FRAMELESSHELPER_BEGIN_NAMESPACE namespace FRAMELESSHELPER_NAMESPACE {
#endif
#ifndef FRAMELESSHELPER_END_NAMESPACE
# define FRAMELESSHELPER_END_NAMESPACE }
#endif
#ifndef FRAMELESSHELPER_USE_NAMESPACE
# define FRAMELESSHELPER_USE_NAMESPACE using namespace FRAMELESSHELPER_NAMESPACE;
#endif
#ifndef FRAMELESSHELPER_PREPEND_NAMESPACE
# define FRAMELESSHELPER_PREPEND_NAMESPACE(X) ::FRAMELESSHELPER_NAMESPACE::X
#endif
#ifndef FRAMELESSHELPER_MAKE_VERSION
# define FRAMELESSHELPER_MAKE_VERSION(Major, Minor, Patch) \
((((Major) & 0xff) << 24) | (((Minor) & 0xff) << 16) | (((Patch) & 0xff) << 8))
#endif
#ifndef FRAMELESSHELPER_EXTRACT_VERSION
# define FRAMELESSHELPER_EXTRACT_VERSION(Version, Major, Minor, Patch) \
{ \
(Major) = (((Version) & 0xff) >> 24); \
(Minor) = (((Version) & 0xff) >> 16); \
(Patch) = (((Version) & 0xff) >> 8); \
}
#endif
#ifndef FRAMELESSHELPER_CORE_NO_BUNDLE_RESOURCE
// Call this function in your main() function if you are using FramelessHelper as a static library,
// it can make sure the resources bundled in the static library are correctly initialized.
// NOTE: This function is intentionally not inside any namespaces.
FRAMELESSHELPER_CORE_API void framelesshelpercore_initResource();
#endif // FRAMELESSHELPER_CORE_NO_BUNDLE_RESOURCE
FRAMELESSHELPER_BEGIN_NAMESPACE
#include "framelesshelper.version"
[[maybe_unused]] inline constexpr const int FRAMELESSHELPER_VERSION =
FRAMELESSHELPER_MAKE_VERSION(
FRAMELESSHELPER_VERSION_MAJOR,
FRAMELESSHELPER_VERSION_MINOR,
FRAMELESSHELPER_VERSION_PATCH);
namespace Global
{
Q_NAMESPACE_EXPORT(FRAMELESSHELPER_CORE_API)
[[maybe_unused]] inline constexpr const int kDefaultResizeBorderThickness = 8;
[[maybe_unused]] inline constexpr const int kDefaultCaptionHeight = 23;
[[maybe_unused]] inline constexpr const int kDefaultTitleBarHeight = 32;
[[maybe_unused]] inline constexpr const int kDefaultExtendedTitleBarHeight = 48;
[[maybe_unused]] inline constexpr const int kDefaultWindowFrameBorderThickness = 1;
[[maybe_unused]] inline constexpr const int kDefaultTitleBarFontPointSize = 11;
[[maybe_unused]] inline constexpr const int kDefaultTitleBarContentsMargin = 10;
[[maybe_unused]] inline constexpr const int kMacOSChromeButtonAreaWidth = 60;
[[maybe_unused]] inline constexpr const QSize kDefaultWindowIconSize = {16, 16};
// We have to use "qRound()" here because "std::round()" is not constexpr, yet.
[[maybe_unused]] inline constexpr const QSize kDefaultSystemButtonSize = {qRound(qreal(kDefaultTitleBarHeight) * 1.5), kDefaultTitleBarHeight};
[[maybe_unused]] inline constexpr const QSize kDefaultSystemButtonIconSize = kDefaultWindowIconSize;
[[maybe_unused]] inline constexpr const QSize kDefaultWindowSize = {160, 160}; // Value taken from Windows QPA.
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
# define kDefaultBlackColor QColorConstants::Black
# define kDefaultWhiteColor QColorConstants::White
# define kDefaultTransparentColor QColorConstants::Transparent
# define kDefaultDarkGrayColor QColorConstants::DarkGray
#else // (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
[[maybe_unused]] inline Q_COLOR_CONSTEXPR const QColor kDefaultBlackColor = {0, 0, 0}; // #000000
[[maybe_unused]] inline Q_COLOR_CONSTEXPR const QColor kDefaultWhiteColor = {255, 255, 255}; // #FFFFFF
[[maybe_unused]] inline Q_COLOR_CONSTEXPR const QColor kDefaultTransparentColor = {0, 0, 0, 0};
[[maybe_unused]] inline Q_COLOR_CONSTEXPR const QColor kDefaultDarkGrayColor = {169, 169, 169}; // #A9A9A9
#endif // (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
[[maybe_unused]] inline Q_COLOR_CONSTEXPR const QColor kDefaultSystemLightColor = {240, 240, 240}; // #F0F0F0
[[maybe_unused]] inline Q_COLOR_CONSTEXPR const QColor kDefaultSystemDarkColor = {32, 32, 32}; // #202020
[[maybe_unused]] inline Q_COLOR_CONSTEXPR const QColor kDefaultFrameBorderActiveColor = {77, 77, 77}; // #4D4D4D
[[maybe_unused]] inline Q_COLOR_CONSTEXPR const QColor kDefaultFrameBorderInactiveColorDark = {87, 89, 89}; // #575959
[[maybe_unused]] inline Q_COLOR_CONSTEXPR const QColor kDefaultFrameBorderInactiveColorLight = {166, 166, 166}; // #A6A6A6
[[maybe_unused]] inline Q_COLOR_CONSTEXPR const QColor kDefaultSystemButtonBackgroundColor = {204, 204, 204}; // #CCCCCC
[[maybe_unused]] inline Q_COLOR_CONSTEXPR const QColor kDefaultSystemCloseButtonBackgroundColor = {232, 17, 35}; // #E81123
[[maybe_unused]] inline const QByteArray kDontOverrideCursorVar
= FRAMELESSHELPER_BYTEARRAY_LITERAL("FRAMELESSHELPER_DONT_OVERRIDE_CURSOR");
[[maybe_unused]] inline const QByteArray kDontToggleMaximizeVar
= FRAMELESSHELPER_BYTEARRAY_LITERAL("FRAMELESSHELPER_DONT_TOGGLE_MAXIMIZE");
[[maybe_unused]] inline const QByteArray kSysMenuDisableMinimizeVar
= FRAMELESSHELPER_BYTEARRAY_LITERAL("FRAMELESSHELPER_SYSTEM_MENU_DISABLE_MINIMIZE");
[[maybe_unused]] inline const QByteArray kSysMenuDisableMaximizeVar
= FRAMELESSHELPER_BYTEARRAY_LITERAL("FRAMELESSHELPER_SYSTEM_MENU_DISABLE_MAXIMIZE");
[[maybe_unused]] inline const QByteArray kSysMenuDisableRestoreVar
= FRAMELESSHELPER_BYTEARRAY_LITERAL("FRAMELESSHELPER_SYSTEM_MENU_DISABLE_RESTORE");
enum class Option : quint8
{
UseCrossPlatformQtImplementation,
ForceHideWindowFrameBorder,
ForceShowWindowFrameBorder,
DisableWindowsSnapLayout,
WindowUseRoundCorners,
CenterWindowBeforeShow,
EnableBlurBehindWindow,
ForceNonNativeBackgroundBlur,
DisableLazyInitializationForMicaMaterial,
ForceNativeBackgroundBlur
};
Q_ENUM_NS(Option)
enum class SystemTheme : quint8
{
Unknown,
Light,
Dark,
HighContrast
};
Q_ENUM_NS(SystemTheme)
enum class SystemButtonType : quint8
{
Unknown,
WindowIcon,
Help,
Minimize,
Maximize,
Restore,
Close
};
Q_ENUM_NS(SystemButtonType)
#ifdef Q_OS_WINDOWS
enum class DwmColorizationArea : quint8
{
None,
StartMenu_TaskBar_ActionCenter,
TitleBar_WindowBorder,
All
};
Q_ENUM_NS(DwmColorizationArea)
#endif // Q_OS_WINDOWS
enum class ButtonState : quint8
{
Normal,
Hovered,
Pressed,
Released
};
Q_ENUM_NS(ButtonState)
#ifdef Q_OS_WINDOWS
enum class WindowsVersion : quint8
{
_2000,
_XP,
_XP_64,
_Vista,
_Vista_SP1,
_Vista_SP2,
_7,
_7_SP1,
_8,
_8_1,
_8_1_Update1,
_10_1507,
_10_1511,
_10_1607,
_10_1703,
_10_1709,
_10_1803,
_10_1809,
_10_1903,
_10_1909,
_10_2004,
_10_20H2,
_10_21H1,
_10_21H2,
_10_22H2,
_11_21H2,
_11_22H2,
_WS_03 = _XP_64, // Windows Server 2003
_10 = _10_1507,
_11 = _11_21H2,
Latest = _11_22H2
};
Q_ENUM_NS(WindowsVersion)
#endif // Q_OS_WINDOWS
enum class BlurMode : quint8
{
Disable, // Do not enable blur behind window
Default, // Use platform default blur mode
Windows_Aero, // Windows only, use the traditional DWM blur
Windows_Acrylic, // Windows only, use the Acrylic blur
Windows_Mica, // Windows only, use the Mica material
Windows_MicaAlt // Windows only, use the Mica Alt material
};
Q_ENUM_NS(BlurMode)
enum class WallpaperAspectStyle : quint8
{
Fill, // Keep aspect ratio to fill, expand/crop if necessary.
Fit, // Keep aspect ratio to fill, but don't expand/crop.
Stretch, // Ignore aspect ratio to fill.
Tile,
Center,
Span // ???
};
Q_ENUM_NS(WallpaperAspectStyle)
#ifdef Q_OS_WINDOWS
enum class RegistryRootKey : quint8
{
ClassesRoot,
CurrentUser,
LocalMachine,
Users,
PerformanceData,
CurrentConfig,
DynData,
CurrentUserLocalSettings,
PerformanceText,
PerformanceNlsText
};
Q_ENUM_NS(RegistryRootKey)
#endif // Q_OS_WINDOWS
enum class WindowEdge : quint8
{
Left = 1 << 0,
Top = 1 << 1,
Right = 1 << 2,
Bottom = 1 << 3
};
Q_ENUM_NS(WindowEdge)
Q_DECLARE_FLAGS(WindowEdges, WindowEdge)
Q_FLAG_NS(WindowEdges)
Q_DECLARE_OPERATORS_FOR_FLAGS(WindowEdges)
#ifdef Q_OS_WINDOWS
enum class DpiAwareness : quint8
{
Unknown,
Unaware,
System,
PerMonitor,
PerMonitorVersion2,
Unaware_GdiScaled
};
Q_ENUM_NS(DpiAwareness)
#endif // Q_OS_WINDOWS
enum class WindowCornerStyle : quint8
{
Default,
Square,
Round
};
Q_ENUM_NS(WindowCornerStyle)
struct VersionInfo
{
int version = 0;
const char *version_str = nullptr;
const char *commit = nullptr;
const char *compileDateTime = nullptr;
const char *compiler = nullptr;
bool isDebug = false;
bool isStatic = false;
};
struct Dpi
{
quint32 x = 0;
quint32 y = 0;
[[nodiscard]] friend constexpr bool operator==(const Dpi &lhs, const Dpi &rhs) noexcept
{
return ((lhs.x == rhs.x) && (lhs.y == rhs.y));
}
[[nodiscard]] friend constexpr bool operator!=(const Dpi &lhs, const Dpi &rhs) noexcept
{
return !operator==(lhs, rhs);
}
};
} // namespace Global
namespace FramelessHelper::Core
{
FRAMELESSHELPER_CORE_API void initialize();
FRAMELESSHELPER_CORE_API void uninitialize();
[[nodiscard]] FRAMELESSHELPER_CORE_API Global::VersionInfo version();
FRAMELESSHELPER_CORE_API void setApplicationOSThemeAware();
FRAMELESSHELPER_CORE_API void outputLogo();
} // namespace FramelessHelper::Core
FRAMELESSHELPER_END_NAMESPACE
#ifndef QT_NO_DEBUG_STREAM
QT_BEGIN_NAMESPACE
FRAMELESSHELPER_CORE_API QDebug operator<<(QDebug, const FRAMELESSHELPER_PREPEND_NAMESPACE(Global)::VersionInfo &);
FRAMELESSHELPER_CORE_API QDebug operator<<(QDebug, const FRAMELESSHELPER_PREPEND_NAMESPACE(Global)::Dpi &);
QT_END_NAMESPACE
#endif // QT_NO_DEBUG_STREAM

View File

@ -0,0 +1,68 @@
/*
* MIT License
*
* Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#pragma once
#include <FramelessHelper/Core/framelesshelpercore_global.h>
FRAMELESSHELPER_BEGIN_NAMESPACE
struct SystemParameters;
class FramelessManagerPrivate;
class FRAMELESSHELPER_CORE_API FramelessManager : public QObject
{
Q_OBJECT
Q_DECLARE_PRIVATE(FramelessManager)
Q_DISABLE_COPY_MOVE(FramelessManager)
Q_PROPERTY(Global::SystemTheme systemTheme READ systemTheme WRITE setOverrideTheme NOTIFY systemThemeChanged FINAL)
Q_PROPERTY(QColor systemAccentColor READ systemAccentColor NOTIFY systemThemeChanged FINAL)
Q_PROPERTY(QString wallpaper READ wallpaper NOTIFY wallpaperChanged FINAL)
Q_PROPERTY(Global::WallpaperAspectStyle wallpaperAspectStyle READ wallpaperAspectStyle NOTIFY wallpaperChanged FINAL)
public:
explicit FramelessManager(QObject *parent = nullptr);
~FramelessManager() override;
Q_NODISCARD static FramelessManager *instance();
Q_NODISCARD Global::SystemTheme systemTheme() const;
Q_NODISCARD QColor systemAccentColor() const;
Q_NODISCARD QString wallpaper() const;
Q_NODISCARD Global::WallpaperAspectStyle wallpaperAspectStyle() const;
public Q_SLOTS:
void addWindow(const SystemParameters *params);
void removeWindow(const WId windowId);
void setOverrideTheme(const Global::SystemTheme theme);
Q_SIGNALS:
void systemThemeChanged();
void wallpaperChanged();
private:
QScopedPointer<FramelessManagerPrivate> d_ptr;
};
FRAMELESSHELPER_END_NAMESPACE

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