Compare commits
42 Commits
main
...
altairwei/
Author | SHA1 | Date |
---|---|---|
|
f4d20e5f06 | |
|
997ef5c508 | |
|
1ebead3148 | |
|
7b82375543 | |
|
57610634d6 | |
|
7d29ee5b95 | |
|
dd0aa92035 | |
|
dcb5fb1da4 | |
|
92681dc9d9 | |
|
18912d5710 | |
|
fdf38d4c80 | |
|
c8cfefb3ca | |
|
50dafa0c5e | |
|
d8c137d11f | |
|
1f1de5deb6 | |
|
0e63a053de | |
|
420d942762 | |
|
d680ad87b1 | |
|
af797125f8 | |
|
cefae7950d | |
|
183aa9a730 | |
|
5e96c3fec6 | |
|
c684d3c0ac | |
|
de1d6abaf0 | |
|
ce69d1a4c5 | |
|
6a0dc5052c | |
|
6a6fea8ac9 | |
|
989de57f33 | |
|
3a3e39c0c0 | |
|
9b2dc893b6 | |
|
5f58937588 | |
|
5ab2024f54 | |
|
0964483b20 | |
|
96f49ded2f | |
|
1aed38e882 | |
|
501ff149cf | |
|
a365499455 | |
|
93ac6f6ee3 | |
|
678f903f5c | |
|
da342753a2 | |
|
3784ef0e7f | |
|
1e2598398d |
|
@ -1,85 +0,0 @@
|
|||
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
|
|
@ -6,7 +6,6 @@
|
|||
*.la
|
||||
*.lai
|
||||
*.so
|
||||
*.so.*
|
||||
*.dll
|
||||
*.dylib
|
||||
|
||||
|
@ -29,8 +28,6 @@ ui_*.h
|
|||
*.jsc
|
||||
Makefile*
|
||||
*build-*
|
||||
*.qm
|
||||
*.prl
|
||||
|
||||
# Qt unit tests
|
||||
target_wrapper.*
|
||||
|
@ -45,12 +42,6 @@ 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/
|
||||
|
@ -74,11 +65,11 @@ user.conf
|
|||
[Dd]ocs/
|
||||
Thumbs.db
|
||||
*.rc
|
||||
*.qm
|
||||
*.bin
|
||||
*.run
|
||||
.qmake.conf
|
||||
*.res
|
||||
.DS_Store
|
||||
|
||||
.vscode/
|
||||
.vs/
|
||||
.cmake.conf
|
||||
*/.DS_Store
|
|
@ -1,3 +0,0 @@
|
|||
[submodule "cmake"]
|
||||
path = cmake
|
||||
url = https://git.ourdocs.cn/github_mirror/cmake-utils.git
|
249
CMakeLists.txt
|
@ -1,238 +1,31 @@
|
|||
#[[
|
||||
MIT License
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
|
||||
project(FramelessHelper LANGUAGES CXX)
|
||||
|
||||
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:
|
||||
option(BUILD_EXAMPLES "Build examples." ON)
|
||||
option(TEST_UNIX "Test UNIX version (from Win32)." OFF)
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
set(BUILD_SHARED_LIBS 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_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
cmake_minimum_required(VERSION 3.20)
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR 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/"
|
||||
)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
|
||||
include(CMakeDependentOption)
|
||||
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)
|
||||
|
||||
# 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)
|
||||
add_subdirectory(src)
|
||||
|
||||
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)
|
||||
if(BUILD_EXAMPLES)
|
||||
add_subdirectory(examples)
|
||||
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()
|
||||
endif()
|
|
@ -1,55 +0,0 @@
|
|||
#[[
|
||||
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@"
|
||||
)
|
2
LICENSE
|
@ -1,6 +1,6 @@
|
|||
MIT License
|
||||
|
||||
Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
|
||||
Copyright (C) 2020 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
|
@ -1,427 +1,110 @@
|
|||
# FramelessHelper 2.x
|
||||
# FramelessHelper
|
||||
|
||||
[](https://github.com/wangwenx190/framelesshelper/actions/workflows/ci.yml)
|
||||
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.
|
||||
|
||||
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
|
||||
|
||||
### Windows
|
||||

|
||||
|
||||

|
||||
## Features
|
||||
|
||||

|
||||
- 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).
|
||||
|
||||
### Linux
|
||||
## Usage
|
||||
|
||||

|
||||
```cpp
|
||||
#include "framelesswindowsmanager.h"
|
||||
#include <QWidget>
|
||||
|
||||

|
||||
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();
|
||||
}
|
||||
```
|
||||
|
||||
### macOS
|
||||
Please refer to [the QWidget example](/examples/widget/) for more detailed information.
|
||||
|
||||

|
||||
### Some details
|
||||
|
||||

|
||||
```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);
|
||||
```
|
||||
|
||||
## Use Cases
|
||||
## IMPORTANT NOTES
|
||||
|
||||
### QVogenClient
|
||||
|
||||

|
||||
|
||||
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.
|
||||
- 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.
|
||||
|
||||
## Supported Platforms
|
||||
|
||||
- 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
|
||||
### Win32
|
||||
|
||||
There are some additional restrictions for each platform, please refer to the _Platform notes_ section below.
|
||||
Windows 7 ~ 10, 32 bit & 64 bit.
|
||||
|
||||
## Build
|
||||
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.
|
||||
|
||||
```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!
|
||||
```
|
||||
### UNIX
|
||||
|
||||
You can also use `Qt6_DIR` or `Qt5_DIR` to replace `CMAKE_PREFIX_PATH`:
|
||||
A not too old version of Linux and macOS, 32 bit & 64 bit.
|
||||
|
||||
```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 ...]
|
||||
```
|
||||
## Requirements
|
||||
|
||||
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.
|
||||
### Win32
|
||||
|
||||
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:
|
||||
| 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 |
|
||||
|
||||
```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
|
||||
)
|
||||
```
|
||||
### UNIX
|
||||
|
||||
If you need the syntax highlighting of FramelessHelper's Quick module, please set up the `QML_IMPORT_PATH` variable. Example code:
|
||||
| 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 |
|
||||
|
||||
```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)
|
||||
```
|
||||
## Known Bugs
|
||||
|
||||
## 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.
|
||||
Please refer to <https://github.com/wangwenx190/framelesshelper/issues> for more information.
|
||||
|
||||
## License
|
||||
|
||||
```text
|
||||
MIT License
|
||||
|
||||
Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
|
||||
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
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
# 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.
|
||||
```
|
|
@ -0,0 +1,182 @@
|
|||
# FramelessHelper (Win32 version)
|
||||
|
||||
## Screenshots
|
||||
|
||||

|
||||
|
||||
## 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
|
||||
|
||||

|
||||
|
||||
### 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
|
@ -1 +0,0 @@
|
|||
Subproject commit 4b4b901807771eda16fb07f36a5cb40505f64087
|
Before Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 303 KiB |
Before Width: | Height: | Size: 294 KiB |
BIN
doc/mac_dark.png
Before Width: | Height: | Size: 61 KiB |
Before Width: | Height: | Size: 68 KiB |
BIN
doc/win_dark.png
Before Width: | Height: | Size: 116 KiB |
Before Width: | Height: | Size: 117 KiB |
|
@ -1,34 +1,14 @@
|
|||
#[[
|
||||
MIT License
|
||||
find_package(QT NAMES Qt6 Qt5 COMPONENTS Widgets)
|
||||
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Widgets)
|
||||
|
||||
Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
|
||||
include_directories(../src)
|
||||
|
||||
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)
|
||||
if(TARGET Qt${QT_VERSION_MAJOR}::Widgets)
|
||||
add_subdirectory(widget)
|
||||
add_subdirectory(mainwindow)
|
||||
#add_subdirectory(openglwidget) # Currently not functional.
|
||||
add_subdirectory(dialog)
|
||||
add_subdirectory(minimal)
|
||||
endif()
|
||||
|
||||
if(FRAMELESSHELPER_BUILD_QUICK AND TARGET Qt${QT_VERSION_MAJOR}::Quick AND (QT_VERSION_MAJOR GREATER_EQUAL 6) AND (NOT FRAMELESSHELPER_NO_PRIVATE))
|
||||
if(TARGET Qt${QT_VERSION_MAJOR}::Quick)
|
||||
add_subdirectory(quick)
|
||||
endif()
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
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
|
||||
}
|
|
@ -1,110 +0,0 @@
|
|||
#[[
|
||||
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})
|
|
@ -1,163 +0,0 @@
|
|||
// 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();
|
||||
}
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
// 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;
|
||||
};
|
|
@ -1,67 +0,0 @@
|
|||
/*
|
||||
* 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();
|
||||
}
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB |
|
@ -0,0 +1,34 @@
|
|||
<?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>
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
|
||||
* 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
|
||||
|
@ -22,37 +22,39 @@
|
|||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "quickchromepalette.h"
|
||||
#include <QtCore/qloggingcategory.h>
|
||||
#include <windows.h>
|
||||
|
||||
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||
IDI_ICON1 ICON "example.ico"
|
||||
|
||||
[[maybe_unused]] static Q_LOGGING_CATEGORY(lcQuickChromePalette, "wangwenx190.framelesshelper.quick.quickchromepalette")
|
||||
//CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "example.manifest"
|
||||
|
||||
#ifdef FRAMELESSHELPER_QUICK_NO_DEBUG_OUTPUT
|
||||
# define INFO QT_NO_QDEBUG_MACRO()
|
||||
# define DEBUG QT_NO_QDEBUG_MACRO()
|
||||
# define WARNING QT_NO_QDEBUG_MACRO()
|
||||
# define CRITICAL QT_NO_QDEBUG_MACRO()
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,0,0,0
|
||||
PRODUCTVERSION 1,0,0,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS VS_FF_DEBUG
|
||||
#else
|
||||
# define INFO qCInfo(lcQuickChromePalette)
|
||||
# define DEBUG qCDebug(lcQuickChromePalette)
|
||||
# define WARNING qCWarning(lcQuickChromePalette)
|
||||
# define CRITICAL qCCritical(lcQuickChromePalette)
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
|
||||
QuickChromePalette::QuickChromePalette(QObject *parent) : ChromePalette(parent)
|
||||
{
|
||||
}
|
||||
|
||||
QuickChromePalette::~QuickChromePalette() = default;
|
||||
|
||||
void QuickChromePalette::classBegin()
|
||||
{
|
||||
}
|
||||
|
||||
void QuickChromePalette::componentComplete()
|
||||
{
|
||||
}
|
||||
|
||||
FRAMELESSHELPER_END_NAMESPACE
|
||||
FILEOS VOS_NT_WINDOWS32
|
||||
FILETYPE VFT_APP
|
||||
FILESUBTYPE VFT2_UNKNOWN
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "wangwenx190"
|
||||
VALUE "FileDescription", "FramelessHelper Demo Application"
|
||||
VALUE "FileVersion", "1.0.0.0"
|
||||
VALUE "LegalCopyright", "MIT License"
|
||||
VALUE "ProductName", "Demo"
|
||||
VALUE "ProductVersion", "1.0.0.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
|
@ -0,0 +1,4 @@
|
|||
TEMPLATE = subdirs
|
||||
CONFIG -= ordered
|
||||
qtHaveModule(widgets): SUBDIRS += widget mainwindow
|
||||
qtHaveModule(quick): SUBDIRS += quick
|
|
@ -0,0 +1,12 @@
|
|||
<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>
|
|
@ -0,0 +1,5 @@
|
|||
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.
|
|
@ -0,0 +1,6 @@
|
|||
<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>
|
After Width: | Height: | Size: 264 B |
|
@ -0,0 +1,6 @@
|
|||
<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>
|
After Width: | Height: | Size: 264 B |
|
@ -0,0 +1,3 @@
|
|||
<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>
|
After Width: | Height: | Size: 225 B |
|
@ -0,0 +1,3 @@
|
|||
<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>
|
After Width: | Height: | Size: 225 B |
|
@ -0,0 +1,3 @@
|
|||
<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>
|
After Width: | Height: | Size: 199 B |
|
@ -0,0 +1,3 @@
|
|||
<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>
|
After Width: | Height: | Size: 199 B |
|
@ -0,0 +1,11 @@
|
|||
<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>
|
After Width: | Height: | Size: 430 B |
|
@ -0,0 +1,11 @@
|
|||
<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>
|
After Width: | Height: | Size: 430 B |
|
@ -1,115 +1,41 @@
|
|||
#[[
|
||||
MIT License
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
|
||||
Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
|
||||
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:
|
||||
find_package(QT NAMES Qt6 Qt5 COMPONENTS Widgets REQUIRED)
|
||||
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Widgets REQUIRED)
|
||||
|
||||
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
|
||||
set(SOURCES
|
||||
../images.qrc
|
||||
TitleBar.ui
|
||||
MainWindow.ui
|
||||
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: 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}"
|
||||
)
|
||||
enable_language(RC)
|
||||
list(APPEND SOURCES ../example.rc ../example.manifest)
|
||||
endif()
|
||||
|
||||
target_link_libraries(${DEMO_NAME} PRIVATE
|
||||
add_executable(MainWindow WIN32 ${SOURCES})
|
||||
|
||||
target_link_libraries(MainWindow PRIVATE
|
||||
Qt${QT_VERSION_MAJOR}::Widgets
|
||||
FramelessHelper::Core
|
||||
FramelessHelper::Widgets
|
||||
wangwenx190::FramelessHelper
|
||||
)
|
||||
|
||||
setup_gui_app(
|
||||
TARGETS ${DEMO_NAME}
|
||||
BUNDLE_ID "org.wangwenx190.demo.MainWindow"
|
||||
BUNDLE_VERSION "1.0.0"
|
||||
BUNDLE_VERSION_SHORT "1.0"
|
||||
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
|
||||
)
|
||||
|
||||
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})
|
||||
if(WIN32)
|
||||
target_link_libraries(MainWindow PRIVATE dwmapi)
|
||||
endif()
|
||||
|
||||
#dump_target_info(TARGETS ${DEMO_NAME})
|
||||
|
|
|
@ -6,19 +6,30 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>800</width>
|
||||
<height>600</height>
|
||||
<width>518</width>
|
||||
<height>383</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Hello, World!</string>
|
||||
<string>MainWindow</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset>
|
||||
<normaloff>../windows.ico</normaloff>../windows.ico</iconset>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_3">
|
||||
<widget class="QPushButton" name="uninstallBtn">
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
<string>Uninstall Frameless Window</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="installBtn">
|
||||
<property name="text">
|
||||
<string>Install Frameless Window</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -118,6 +129,15 @@
|
|||
<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>
|
|
@ -0,0 +1,290 @@
|
|||
<?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>
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
|
||||
* 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
|
||||
|
@ -23,45 +23,23 @@
|
|||
*/
|
||||
|
||||
#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[])
|
||||
{
|
||||
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"));
|
||||
}
|
||||
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
|
||||
|
||||
const auto application = std::make_unique<QApplication>(argc, argv);
|
||||
QApplication application(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();
|
||||
MainWindow mainWindow;
|
||||
mainWindow.show();
|
||||
|
||||
FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow);
|
||||
//FramelessConfig::instance()->set(Global::Option::DisableLazyInitializationForMicaMaterial);
|
||||
|
||||
CREATE_WINDOW(mainWindow1)
|
||||
CREATE_WINDOW(mainWindow2)
|
||||
CREATE_WINDOW(mainWindow3)
|
||||
|
||||
return QCoreApplication::exec();
|
||||
return QApplication::exec();
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
|
||||
* 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
|
||||
|
@ -23,131 +23,158 @@
|
|||
*/
|
||||
|
||||
#include "mainwindow.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 &);
|
||||
#include <QtGui/qpainter.h>
|
||||
#include "core/utilities.h"
|
||||
|
||||
FRAMELESSHELPER_USE_NAMESPACE
|
||||
|
||||
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)
|
||||
MainWindow::MainWindow(QWidget *parent, Qt::WindowFlags flags) : QMainWindow(parent, flags)
|
||||
{
|
||||
initialize();
|
||||
}
|
||||
setAttribute(Qt::WA_DontCreateNativeAncestors);
|
||||
createWinId();
|
||||
|
||||
MainWindow::~MainWindow() = default;
|
||||
resize(800, 600);
|
||||
|
||||
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);
|
||||
}
|
||||
appMainWindow = new Ui::MainWindow;
|
||||
appMainWindow->setupUi(this);
|
||||
|
||||
void MainWindow::initialize()
|
||||
{
|
||||
m_titleBar = new StandardTitleBar(this);
|
||||
m_titleBar->setTitleLabelAlignment(Qt::AlignCenter);
|
||||
m_mainWindow = new Ui::MainWindow;
|
||||
m_mainWindow->setupUi(this);
|
||||
m_titleBar = new QWidget(this);
|
||||
titleBarWidget = new Ui::TitleBar;
|
||||
titleBarWidget->setupUi(m_titleBar);
|
||||
|
||||
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.
|
||||
QMenuBar *mb = menuBar();
|
||||
titleBarWidget->horizontalLayout->insertWidget(1, mb);
|
||||
setMenuWidget(m_titleBar);
|
||||
|
||||
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;
|
||||
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();
|
||||
}
|
||||
setWindowTitle(windowTitle() + FRAMELESSHELPER_STRING_LITERAL(" [%1]").arg(name));
|
||||
});
|
||||
connect(m_mainWindow->pushButton, &QPushButton::clicked, this, [this]{
|
||||
const auto dialog = new Dialog(this);
|
||||
dialog->waitReady();
|
||||
dialog->setAttribute(Qt::WA_DeleteOnClose);
|
||||
dialog->exec();
|
||||
connect(this, &MainWindow::windowStateChanged, [this](){
|
||||
titleBarWidget->maximizeButton->setChecked(isMaximized());
|
||||
titleBarWidget->maximizeButton->setToolTip(isMaximized() ? tr("Restore") : tr("Maximize"));
|
||||
});
|
||||
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->uninstallBtn, &QPushButton::clicked, [this]() {
|
||||
this->m_helper->uninstall();
|
||||
});
|
||||
connect(appMainWindow->installBtn, &QPushButton::clicked, [this]() {
|
||||
this->m_helper->install();
|
||||
});
|
||||
|
||||
setWindowTitle(tr("Hello, World!"));
|
||||
}
|
||||
|
||||
void MainWindow::waitReady()
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
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 (titleBarWidget) {
|
||||
delete titleBarWidget;
|
||||
titleBarWidget = nullptr;
|
||||
}
|
||||
const QByteArray savedState = Settings::get<QByteArray>(id, kState);
|
||||
if (!savedState.isEmpty() && !parent()) {
|
||||
restoreState(savedState);
|
||||
if (appMainWindow) {
|
||||
delete appMainWindow;
|
||||
appMainWindow = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
|
||||
* 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
|
||||
|
@ -24,35 +24,37 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <FramelessHelper/Widgets/framelessmainwindow.h>
|
||||
#include <QtWidgets/qmainwindow.h>
|
||||
#include "ui_MainWindow.h"
|
||||
#include "ui_TitleBar.h"
|
||||
#include "core/framelesshelper.h"
|
||||
|
||||
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||
class StandardTitleBar;
|
||||
FRAMELESSHELPER_END_NAMESPACE
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class MainWindow;
|
||||
}
|
||||
|
||||
class MainWindow : public FRAMELESSHELPER_PREPEND_NAMESPACE(FramelessMainWindow)
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY_MOVE(MainWindow)
|
||||
|
||||
public:
|
||||
explicit MainWindow(QWidget *parent = nullptr, const Qt::WindowFlags flags = {});
|
||||
explicit MainWindow(QWidget *parent = nullptr, Qt::WindowFlags flags = {});
|
||||
~MainWindow() override;
|
||||
|
||||
void waitReady();
|
||||
|
||||
protected:
|
||||
void closeEvent(QCloseEvent *event) override;
|
||||
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();
|
||||
|
||||
private:
|
||||
void initialize();
|
||||
|
||||
private:
|
||||
FRAMELESSHELPER_PREPEND_NAMESPACE(StandardTitleBar) *m_titleBar = nullptr;
|
||||
Ui::MainWindow *m_mainWindow = nullptr;
|
||||
__flh_ns::FramelessHelper *m_helper = nullptr;
|
||||
QWidget *m_titleBar = nullptr;
|
||||
Ui::TitleBar *titleBarWidget = nullptr;
|
||||
Ui::MainWindow *appMainWindow = nullptr;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
TARGET = MainWindow
|
||||
TEMPLATE = app
|
||||
QT += widgets
|
||||
HEADERS += mainwindow.h
|
||||
SOURCES += mainwindow.cpp main.cpp
|
||||
FORMS += TitleBar.ui MainWindow.ui
|
||||
include($$PWD/../common.pri)
|
|
@ -0,0 +1,33 @@
|
|||
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()
|
|
@ -0,0 +1,77 @@
|
|||
#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);
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
#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;
|
||||
};
|
|
@ -0,0 +1,25 @@
|
|||
#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();
|
||||
}
|
|
@ -1,125 +0,0 @@
|
|||
#[[
|
||||
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})
|
|
@ -1,276 +0,0 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** 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);
|
||||
}
|
|
@ -1,117 +0,0 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** 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;
|
||||
};
|
|
@ -1,5 +0,0 @@
|
|||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>images/qtlogo.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
Before Width: | Height: | Size: 2.3 KiB |
|
@ -1,150 +0,0 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** 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);
|
||||
}
|
|
@ -1,72 +0,0 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** 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;
|
||||
};
|
|
@ -1,110 +0,0 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** 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();
|
||||
}
|
|
@ -1,101 +0,0 @@
|
|||
/*
|
||||
* 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();
|
||||
}
|
||||
}
|
|
@ -1,146 +1,39 @@
|
|||
#[[
|
||||
MIT License
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
|
||||
Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
|
||||
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:
|
||||
find_package(QT NAMES Qt6 Qt5 COMPONENTS Quick QuickControls2 REQUIRED)
|
||||
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Quick QuickControls2 REQUIRED)
|
||||
|
||||
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
|
||||
set(SOURCES
|
||||
../images.qrc
|
||||
qml.qrc
|
||||
main.cpp
|
||||
quicksettings.h
|
||||
quicksettings.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: 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}"
|
||||
)
|
||||
enable_language(RC)
|
||||
list(APPEND SOURCES ../example.rc ../example.manifest)
|
||||
endif()
|
||||
|
||||
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()
|
||||
add_executable(Quick WIN32 ${SOURCES})
|
||||
|
||||
target_link_libraries(${DEMO_NAME} PRIVATE
|
||||
target_link_libraries(Quick PRIVATE
|
||||
Qt${QT_VERSION_MAJOR}::Quick
|
||||
Qt${QT_VERSION_MAJOR}::QuickPrivate
|
||||
FramelessHelper::Core
|
||||
FramelessHelper::Quick
|
||||
Qt${QT_VERSION_MAJOR}::QuickControls2
|
||||
wangwenx190::FramelessHelper
|
||||
)
|
||||
|
||||
setup_gui_app(
|
||||
TARGETS ${DEMO_NAME}
|
||||
BUNDLE_ID "org.wangwenx190.demo.Quick"
|
||||
BUNDLE_VERSION "1.0.0"
|
||||
BUNDLE_VERSION_SHORT "1.0"
|
||||
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
|
||||
)
|
||||
|
||||
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}
|
||||
)
|
||||
if(WIN32)
|
||||
target_link_libraries(Quick PRIVATE dwmapi)
|
||||
endif()
|
||||
|
||||
#dump_target_info(TARGETS ${DEMO_NAME})
|
||||
|
|
Before Width: | Height: | Size: 8.4 KiB |
|
@ -1,8 +0,0 @@
|
|||
<?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>
|
Before Width: | Height: | Size: 636 B |
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
|
||||
* 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
|
||||
|
@ -22,141 +22,52 @@
|
|||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef QMLTC_ENABLED
|
||||
# define QMLTC_ENABLED 0
|
||||
#endif
|
||||
|
||||
#include "quick/framelessquickhelper.h"
|
||||
#include <QtGui/qguiapplication.h>
|
||||
#include <QtQml/qqmlapplicationengine.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
|
||||
;
|
||||
#include <QtQuickControls2/qquickstyle.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
Log::setup(FRAMELESSHELPER_STRING_LITERAL("quick"));
|
||||
|
||||
// Not necessary, but better call this function, before the construction
|
||||
// of any Q(Core|Gui)Application instances.
|
||||
FramelessHelper::Quick::initialize();
|
||||
|
||||
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))
|
||||
QQuickWindow::setGraphicsApi(QSGRendererInterface::Software);
|
||||
#elif (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
||||
QQuickWindow::setSceneGraphBackend(QSGRendererInterface::Software);
|
||||
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
|
||||
}
|
||||
|
||||
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 {
|
||||
QGuiApplication application(argc, argv);
|
||||
|
||||
QQmlApplicationEngine engine;
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
return FRAMELESSHELPER_BYTEARRAY_LITERAL("Basic");
|
||||
QQuickStyle::setStyle(QStringLiteral("Basic"));
|
||||
#else
|
||||
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"));
|
||||
}
|
||||
QQuickStyle::setStyle(QStringLiteral("Default"));
|
||||
#endif
|
||||
|
||||
const auto engine = std::make_unique<QQmlApplicationEngine>();
|
||||
qmlRegisterType<FRAMELESSHELPER_PREPEND_NAMESPACE(FramelessQuickHelper)>("wangwenx190.Utils", 1, 0, "FramelessHelper");
|
||||
|
||||
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 QUrl mainQmlUrl(QStringLiteral("qrc:///qml/main.qml"));
|
||||
const QMetaObject::Connection connection = QObject::connect(
|
||||
engine.get(), &QQmlApplicationEngine::objectCreated, application.get(),
|
||||
[&mainUrl, &connection](QObject *object, const QUrl &url) {
|
||||
if (url != mainUrl) {
|
||||
&engine,
|
||||
&QQmlApplicationEngine::objectCreated,
|
||||
&application,
|
||||
[&mainQmlUrl, &connection](QObject *object, const QUrl &url) {
|
||||
if (url != mainQmlUrl) {
|
||||
return;
|
||||
}
|
||||
if (object) {
|
||||
QObject::disconnect(connection);
|
||||
if (!object) {
|
||||
QGuiApplication::exit(-1);
|
||||
} else {
|
||||
QCoreApplication::exit(-1);
|
||||
QObject::disconnect(connection);
|
||||
}
|
||||
}, Qt::QueuedConnection);
|
||||
#endif
|
||||
},
|
||||
Qt::QueuedConnection);
|
||||
|
||||
#if !QMLTC_ENABLED
|
||||
engine->load(mainUrl);
|
||||
#endif
|
||||
engine.load(mainQmlUrl);
|
||||
|
||||
#if QMLTC_ENABLED
|
||||
const auto homePage = std::make_unique<HomePage>(engine.get());
|
||||
homePage->show();
|
||||
#endif
|
||||
|
||||
return QCoreApplication::exec();
|
||||
return QGuiApplication::exec();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
<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>
|
|
@ -1,111 +0,0 @@
|
|||
/*
|
||||
* 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
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
|
||||
* 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
|
||||
|
@ -22,19 +22,27 @@
|
|||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
import QtQuick 2.0
|
||||
import QtQuick.Controls 2.0
|
||||
|
||||
#include <FramelessHelper/Quick/framelesshelperquick_global.h>
|
||||
Button {
|
||||
id: button
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QQmlEngine;
|
||||
QT_END_NAMESPACE
|
||||
implicitWidth: 45
|
||||
implicitHeight: 30
|
||||
|
||||
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||
ToolTip.visible: hovered && !down
|
||||
ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval
|
||||
ToolTip.text: qsTr("Close")
|
||||
|
||||
namespace FramelessHelper::Quick
|
||||
{
|
||||
FRAMELESSHELPER_QUICK_API void registerTypes(QQmlEngine *engine);
|
||||
} // namespace FramelessHelper::Quick
|
||||
contentItem: Image {
|
||||
anchors.fill: parent
|
||||
source: button.down
|
||||
|| button.hovered ? "qrc:/images/button_close_white.svg" : "qrc:/images/button_close_black.svg"
|
||||
}
|
||||
|
||||
FRAMELESSHELPER_END_NAMESPACE
|
||||
background: Rectangle {
|
||||
visible: button.down || button.hovered
|
||||
color: button.down ? "#8c0a15" : (button.hovered ? "#e81123" : "transparent")
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
|
||||
* 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
|
||||
|
@ -22,34 +22,28 @@
|
|||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
import QtQuick 2.0
|
||||
import QtQuick.Controls 2.0
|
||||
|
||||
#include <FramelessHelper/Widgets/framelesswidget.h>
|
||||
Button {
|
||||
id: button
|
||||
|
||||
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||
class StandardTitleBar;
|
||||
FRAMELESSHELPER_END_NAMESPACE
|
||||
implicitWidth: 45
|
||||
implicitHeight: 30
|
||||
|
||||
class GLWidget;
|
||||
property bool maximized: false
|
||||
|
||||
class MainWindow : public FRAMELESSHELPER_PREPEND_NAMESPACE(FramelessWidget)
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY_MOVE(MainWindow)
|
||||
ToolTip.visible: hovered && !down
|
||||
ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval
|
||||
ToolTip.text: maximized ? qsTr("Restore") : qsTr("Maximize")
|
||||
|
||||
public:
|
||||
explicit MainWindow(QWidget *parent = nullptr);
|
||||
~MainWindow() override;
|
||||
contentItem: Image {
|
||||
anchors.fill: parent
|
||||
source: maximized ? "qrc:/images/button_restore_black.svg" : "qrc:/images/button_maximize_black.svg"
|
||||
}
|
||||
|
||||
void waitReady();
|
||||
|
||||
protected:
|
||||
void closeEvent(QCloseEvent *event) override;
|
||||
|
||||
private:
|
||||
void initialize();
|
||||
|
||||
private:
|
||||
FRAMELESSHELPER_PREPEND_NAMESPACE(StandardTitleBar) *m_titleBar = nullptr;
|
||||
GLWidget *m_glWidget = nullptr;
|
||||
};
|
||||
background: Rectangle {
|
||||
visible: button.down || button.hovered
|
||||
color: button.down ? "#808080" : (button.hovered ? "#c7c7c7" : "transparent")
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
|
||||
* 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
|
||||
|
@ -22,14 +22,26 @@
|
|||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
import QtQml
|
||||
import QtQuick 2.0
|
||||
import QtQuick.Controls 2.0
|
||||
|
||||
QtObject {
|
||||
property Window window: Window{}
|
||||
property ApplicationWindow applicationWindow: ApplicationWindow{}
|
||||
Button {
|
||||
id: button
|
||||
|
||||
Component.onCompleted: {
|
||||
window.show();
|
||||
applicationWindow.show();
|
||||
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")
|
||||
}
|
||||
}
|
|
@ -1,111 +0,0 @@
|
|||
/*
|
||||
* 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
|
||||
}
|
||||
}
|
|
@ -0,0 +1,156 @@
|
|||
|
||||
|
||||
/*
|
||||
* 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()
|
||||
}
|
|
@ -1,16 +1,7 @@
|
|||
TARGET = Quick
|
||||
TEMPLATE = app
|
||||
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)
|
||||
QT += quick quickcontrols2
|
||||
CONFIG(release, debug|release): CONFIG += qtquickcompiler
|
||||
SOURCES += main.cpp
|
||||
RESOURCES += qml.qrc
|
||||
include($$PWD/../common.pri)
|
||||
|
|
|
@ -1,71 +0,0 @@
|
|||
/*
|
||||
* 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;
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
/*
|
||||
* 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);
|
||||
};
|
|
@ -1,8 +0,0 @@
|
|||
<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>
|
|
@ -1,28 +0,0 @@
|
|||
:: 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
|
|
@ -1,28 +0,0 @@
|
|||
:: 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
|
|
@ -1,28 +0,0 @@
|
|||
:: 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
|
|
@ -1,28 +0,0 @@
|
|||
:: 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
|
|
@ -1,94 +0,0 @@
|
|||
/*
|
||||
* 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);
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
/*
|
||||
* 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
|
|
@ -1,83 +0,0 @@
|
|||
/*
|
||||
* 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 &);
|
|
@ -1,36 +0,0 @@
|
|||
/*
|
||||
* 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
|
|
@ -1,110 +1,39 @@
|
|||
#[[
|
||||
MIT License
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
|
||||
Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
|
||||
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:
|
||||
find_package(QT NAMES Qt6 Qt5 COMPONENTS Widgets REQUIRED)
|
||||
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Widgets REQUIRED)
|
||||
|
||||
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
|
||||
set(SOURCES
|
||||
../images.qrc
|
||||
widget.h
|
||||
widget.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: 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}"
|
||||
)
|
||||
enable_language(RC)
|
||||
list(APPEND SOURCES ../example.rc ../example.manifest)
|
||||
endif()
|
||||
|
||||
target_link_libraries(${DEMO_NAME} PRIVATE
|
||||
add_executable(Widget WIN32 ${SOURCES})
|
||||
|
||||
target_link_libraries(Widget PRIVATE
|
||||
Qt${QT_VERSION_MAJOR}::Widgets
|
||||
FramelessHelper::Core
|
||||
FramelessHelper::Widgets
|
||||
wangwenx190::FramelessHelper
|
||||
)
|
||||
|
||||
setup_gui_app(
|
||||
TARGETS ${DEMO_NAME}
|
||||
BUNDLE_ID "org.wangwenx190.demo.Widget"
|
||||
BUNDLE_VERSION "1.0.0"
|
||||
BUNDLE_VERSION_SHORT "1.0"
|
||||
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
|
||||
)
|
||||
|
||||
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})
|
||||
if(WIN32)
|
||||
target_link_libraries(Widget PRIVATE dwmapi)
|
||||
endif()
|
||||
|
||||
#dump_target_info(TARGETS ${DEMO_NAME})
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
|
||||
* 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
|
||||
|
@ -23,45 +23,23 @@
|
|||
*/
|
||||
|
||||
#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[])
|
||||
{
|
||||
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"));
|
||||
}
|
||||
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
|
||||
|
||||
const auto application = std::make_unique<QApplication>(argc, argv);
|
||||
QApplication application(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();
|
||||
Widget widget;
|
||||
widget.show();
|
||||
|
||||
FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow);
|
||||
//FramelessConfig::instance()->set(Global::Option::DisableLazyInitializationForMicaMaterial);
|
||||
|
||||
CREATE_WINDOW(widget1)
|
||||
CREATE_WINDOW(widget2)
|
||||
CREATE_WINDOW(widget3)
|
||||
|
||||
return QCoreApplication::exec();
|
||||
return QApplication::exec();
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
|
||||
* 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
|
||||
|
@ -23,152 +23,351 @@
|
|||
*/
|
||||
|
||||
#include "widget.h"
|
||||
#include <QtCore/qdebug.h>
|
||||
#include <QtCore/qdatetime.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 <QtGui/qpainter.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 &);
|
||||
#include <QtWidgets/qlabel.h>
|
||||
#include <QtWidgets/qpushbutton.h>
|
||||
#include "core/utilities.h"
|
||||
#include "core/framelesshelper.h"
|
||||
|
||||
FRAMELESSHELPER_USE_NAMESPACE
|
||||
|
||||
using namespace Global;
|
||||
static const QColor systemLightColor = QStringLiteral("#f0f0f0");
|
||||
static const QColor systemDarkColor = QColor::fromRgb(32, 32, 32);
|
||||
|
||||
FRAMELESSHELPER_STRING_CONSTANT(Geometry)
|
||||
FRAMELESSHELPER_STRING_CONSTANT(DevicePixelRatio)
|
||||
static constexpr char mainStyleSheet[] = R"(
|
||||
#MainWidget {
|
||||
background-color: %1;
|
||||
}
|
||||
|
||||
Widget::Widget(QWidget *parent) : FramelessWidget(parent)
|
||||
#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)
|
||||
{
|
||||
initialize();
|
||||
setAttribute(Qt::WA_DontCreateNativeAncestors);
|
||||
createWinId();
|
||||
setupUi();
|
||||
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)
|
||||
{
|
||||
FramelessWidget::timerEvent(event);
|
||||
QWidget::timerEvent(event);
|
||||
if (m_clockLabel) {
|
||||
m_clockLabel->setText(QTime::currentTime().toString(FRAMELESSHELPER_STRING_LITERAL("hh:mm:ss")));
|
||||
m_clockLabel->setText(QTime::currentTime().toString(QStringLiteral("hh:mm:ss")));
|
||||
}
|
||||
}
|
||||
|
||||
void Widget::closeEvent(QCloseEvent *event)
|
||||
#ifndef Q_OS_MAC
|
||||
void Widget::changeEvent(QEvent *event)
|
||||
{
|
||||
if (!parent()) {
|
||||
const QString objName = objectName();
|
||||
Settings::set(objName, kGeometry, geometry());
|
||||
Settings::set(objName, kDevicePixelRatio, devicePixelRatioF());
|
||||
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();
|
||||
}
|
||||
FramelessWidget::closeEvent(event);
|
||||
}
|
||||
|
||||
void Widget::initialize()
|
||||
void Widget::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
setWindowTitle(tr("FramelessHelper demo application - QWidget"));
|
||||
setWindowIcon(QFileIconProvider().icon(QFileIconProvider::Computer));
|
||||
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!"));
|
||||
resize(800, 600);
|
||||
m_titleBar = new StandardTitleBar(this);
|
||||
m_titleBar->setWindowIconVisible(true);
|
||||
|
||||
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_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->setSpacing(0);
|
||||
mainLayout->setContentsMargins(0, 0, 0, 0);
|
||||
mainLayout->addWidget(m_titleBar);
|
||||
mainLayout->setSpacing(0);
|
||||
mainLayout->addWidget(m_titleBarWidget);
|
||||
mainLayout->addStretch();
|
||||
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 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()));
|
||||
}
|
||||
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()));
|
||||
update();
|
||||
}
|
||||
|
||||
void Widget::waitReady()
|
||||
void Widget::updateTitleBarSize()
|
||||
{
|
||||
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 {
|
||||
helper->moveWindowToDesktopCenter();
|
||||
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)));
|
||||
} else {
|
||||
m_maximizeButton->setIcon(QIcon(QStringLiteral(":/images/button_maximize_%1.svg").arg(suffix)));
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao)
|
||||
* 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
|
||||
|
@ -24,41 +24,49 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <FramelessHelper/Widgets/framelesswidget.h>
|
||||
#include <QtWidgets/qwidget.h>
|
||||
#include "core/framelesshelper.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QLabel;
|
||||
class QShortcut;
|
||||
QT_FORWARD_DECLARE_CLASS(QLabel)
|
||||
QT_FORWARD_DECLARE_CLASS(QPushButton)
|
||||
QT_END_NAMESPACE
|
||||
|
||||
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||
class StandardTitleBar;
|
||||
FRAMELESSHELPER_END_NAMESPACE
|
||||
|
||||
class Widget : public FRAMELESSHELPER_PREPEND_NAMESPACE(FramelessWidget)
|
||||
class Widget : public QWidget
|
||||
{
|
||||
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;
|
||||
void closeEvent(QCloseEvent *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
|
||||
|
||||
private:
|
||||
void initialize();
|
||||
|
||||
private Q_SLOTS:
|
||||
void setupUi();
|
||||
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;
|
||||
};
|
||||
|
|
|
@ -1,14 +1,6 @@
|
|||
TARGET = Widget
|
||||
TEMPLATE = app
|
||||
TARGET = FramelessHelperDemo-Widget
|
||||
QT += widgets
|
||||
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)
|
||||
HEADERS += widget.h
|
||||
SOURCES += widget.cpp main.cpp
|
||||
include($$PWD/../common.pri)
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
#include "chromepalette.h"
|
|
@ -1 +0,0 @@
|
|||
#include "framelesshelper_linux.h"
|
|
@ -1 +0,0 @@
|
|||
#include "framelesshelper_qt.h"
|
|
@ -1 +0,0 @@
|
|||
#include "framelesshelper_win.h"
|
|
@ -1 +0,0 @@
|
|||
#include "framelesshelper_windows.h"
|
|
@ -1 +0,0 @@
|
|||
#include "framelessmanager.h"
|
|
@ -1 +0,0 @@
|
|||
#include "framelesshelpercore_global.h"
|
|
@ -1 +0,0 @@
|
|||
#include "micamaterial.h"
|
|
@ -1 +0,0 @@
|
|||
#include "utils.h"
|
|
@ -1 +0,0 @@
|
|||
#include "windowborderpainter.h"
|
|
@ -1,125 +0,0 @@
|
|||
/*
|
||||
* 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
|
|
@ -1,526 +0,0 @@
|
|||
/*
|
||||
* 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
|
|
@ -1,49 +0,0 @@
|
|||
/*
|
||||
* 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
|
|
@ -1,734 +0,0 @@
|
|||
/*
|
||||
* 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";
|
|
@ -1,475 +0,0 @@
|
|||
/*
|
||||
* 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
|