forked from github_mirror/framelesshelper
add frameless dialog & demo
And some other minor fixes. Signed-off-by: Yuhang Zhao <2546789017@qq.com>
This commit is contained in:
parent
5018d9ea82
commit
b9f65aa783
|
@ -26,6 +26,7 @@ if(FRAMELESSHELPER_BUILD_WIDGETS AND TARGET Qt${QT_VERSION_MAJOR}::Widgets)
|
|||
add_subdirectory(widget)
|
||||
add_subdirectory(mainwindow)
|
||||
add_subdirectory(openglwidget)
|
||||
add_subdirectory(dialog)
|
||||
endif()
|
||||
|
||||
if(FRAMELESSHELPER_BUILD_QUICK AND TARGET Qt${QT_VERSION_MAJOR}::Quick AND ${QT_VERSION_MAJOR} GREATER_EQUAL 6)
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
#[[
|
||||
MIT License
|
||||
|
||||
Copyright (C) 2022 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(SOURCES
|
||||
dialog.h
|
||||
dialog.cpp
|
||||
main.cpp
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
enable_language(RC)
|
||||
list(APPEND SOURCES ../example.rc ../example.manifest)
|
||||
endif()
|
||||
|
||||
add_executable(Dialog ${SOURCES})
|
||||
|
||||
target_link_libraries(Dialog PRIVATE
|
||||
Qt${QT_VERSION_MAJOR}::Widgets
|
||||
FramelessHelper::Widgets
|
||||
)
|
||||
|
||||
target_compile_definitions(Dialog PRIVATE
|
||||
QT_NO_KEYWORDS
|
||||
)
|
||||
|
||||
include(../../src/core/cmakehelper.cmake)
|
||||
setup_gui_app(Dialog)
|
||||
setup_compile_params(Dialog)
|
||||
if(FRAMELESSHELPER_EXAMPLES_DEPLOYQT)
|
||||
deploy_qt_runtime(Dialog)
|
||||
endif()
|
|
@ -0,0 +1,103 @@
|
|||
// 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 <StandardTitleBar>
|
||||
#include <FramelessWidgetsHelper>
|
||||
#include <StandardSystemButton>
|
||||
#include <private/framelesswidgetshelper_p.h>
|
||||
|
||||
FRAMELESSHELPER_USE_NAMESPACE
|
||||
|
||||
using namespace Global;
|
||||
|
||||
Dialog::Dialog(QWidget *parent) : FramelessDialog(parent)
|
||||
{
|
||||
setupUi();
|
||||
}
|
||||
|
||||
Dialog::~Dialog() = default;
|
||||
|
||||
void Dialog::setupUi()
|
||||
{
|
||||
setWindowTitle(tr("Qt Dialog demo"));
|
||||
setWindowIcon(QFileIconProvider().icon(QFileIconProvider::Computer));
|
||||
|
||||
titleBar = new StandardTitleBar(this);
|
||||
titleBar->setWindowIconVisible(true);
|
||||
titleBar->maximizeButton()->hide();
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
helper->setSystemButton(titleBar->minimizeButton(), SystemButtonType::Minimize);
|
||||
helper->setSystemButton(titleBar->maximizeButton(), SystemButtonType::Maximize);
|
||||
helper->setSystemButton(titleBar->closeButton(), SystemButtonType::Close);
|
||||
FramelessWidgetsHelperPrivate::get(helper)->setProperty(FRAMELESSHELPER_BYTEARRAY_LITERAL("FRAMELESSHELPER_DONT_OVERRIDE_CURSOR"), true);
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
// Copyright (C) 2022 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <FramelessDialog>
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
};
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (C) 2022 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 <framelessconfig_p.h>
|
||||
#include <clocale>
|
||||
#include "dialog.h"
|
||||
|
||||
FRAMELESSHELPER_USE_NAMESPACE
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
std::setlocale(LC_ALL, "en_US.UTF-8");
|
||||
|
||||
// Not necessary, but better call this function, before the construction
|
||||
// of any Q(Core|Gui)Application instances.
|
||||
FramelessHelper::Widgets::initialize();
|
||||
|
||||
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(true, false);
|
||||
|
||||
FramelessConfig::instance()->set(Global::Option::WindowUseRoundCorners);
|
||||
FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow);
|
||||
|
||||
Dialog dialog;
|
||||
dialog.show();
|
||||
|
||||
const int exec = QCoreApplication::exec();
|
||||
|
||||
FramelessHelper::Widgets::uninitialize();
|
||||
|
||||
return exec;
|
||||
}
|
|
@ -452,6 +452,10 @@ using GetWindowIdCallback = std::function<WId()>;
|
|||
using ShouldIgnoreMouseEventsCallback = std::function<bool(const QPoint &)>;
|
||||
using ShowSystemMenuCallback = std::function<void(const QPoint &)>;
|
||||
using GetCurrentApplicationTypeCallback = std::function<ApplicationType()>;
|
||||
using SetPropertyCallback = std::function<void(const QByteArray &, const QVariant &)>;
|
||||
using GetPropertyCallback = std::function<QVariant(const QByteArray &, const QVariant &)>;
|
||||
using SetCursorCallback = std::function<void(const QCursor &)>;
|
||||
using UnsetCursorCallback = std::function<void()>;
|
||||
|
||||
struct SystemParameters
|
||||
{
|
||||
|
@ -477,6 +481,10 @@ struct SystemParameters
|
|||
ShouldIgnoreMouseEventsCallback shouldIgnoreMouseEvents = nullptr;
|
||||
ShowSystemMenuCallback showSystemMenu = nullptr;
|
||||
GetCurrentApplicationTypeCallback getCurrentApplicationType = nullptr;
|
||||
SetPropertyCallback setProperty = nullptr;
|
||||
GetPropertyCallback getProperty = nullptr;
|
||||
SetCursorCallback setCursor = nullptr;
|
||||
UnsetCursorCallback unsetCursor = nullptr;
|
||||
|
||||
[[nodiscard]] inline bool isValid() const
|
||||
{
|
||||
|
@ -502,6 +510,10 @@ struct SystemParameters
|
|||
Q_ASSERT(shouldIgnoreMouseEvents);
|
||||
Q_ASSERT(showSystemMenu);
|
||||
Q_ASSERT(getCurrentApplicationType);
|
||||
Q_ASSERT(setProperty);
|
||||
Q_ASSERT(getProperty);
|
||||
Q_ASSERT(setCursor);
|
||||
Q_ASSERT(unsetCursor);
|
||||
return (getWindowFlags && setWindowFlags && getWindowSize
|
||||
&& setWindowSize && getWindowPosition && setWindowPosition
|
||||
&& getWindowScreen && isWindowFixedSize && setWindowFixedSize
|
||||
|
@ -509,7 +521,8 @@ struct SystemParameters
|
|||
&& windowToScreen && screenToWindow && isInsideSystemButtons
|
||||
&& isInsideTitleBarDraggableArea && getWindowDevicePixelRatio
|
||||
&& setSystemButtonState && getWindowId && shouldIgnoreMouseEvents
|
||||
&& showSystemMenu && getCurrentApplicationType);
|
||||
&& showSystemMenu && getCurrentApplicationType && setProperty
|
||||
&& getProperty && setCursor && unsetCursor);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -71,6 +71,9 @@ public:
|
|||
Q_NODISCARD bool isBlurBehindWindowEnabled() const;
|
||||
void setBlurBehindWindowEnabled(const bool value, const QColor &color);
|
||||
|
||||
void setProperty(const QByteArray &name, const QVariant &value);
|
||||
Q_NODISCARD QVariant getProperty(const QByteArray &name, const QVariant &defaultValue = {});
|
||||
|
||||
protected:
|
||||
Q_NODISCARD bool eventFilter(QObject *object, QEvent *event) override;
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
#include <framelessdialog.h>
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (C) 2022 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 "framelesshelperwidgets_global.h"
|
||||
#include <QtCore/qloggingcategory.h>
|
||||
#include <QtWidgets/qdialog.h>
|
||||
|
||||
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||
|
||||
Q_DECLARE_LOGGING_CATEGORY(lcFramelessDialog)
|
||||
|
||||
class FramelessDialogPrivate;
|
||||
|
||||
class FRAMELESSHELPER_WIDGETS_API FramelessDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DECLARE_PRIVATE(FramelessDialog)
|
||||
Q_DISABLE_COPY_MOVE(FramelessDialog)
|
||||
|
||||
public:
|
||||
explicit FramelessDialog(QWidget *parent = nullptr);
|
||||
~FramelessDialog() override;
|
||||
|
||||
private:
|
||||
QScopedPointer<FramelessDialogPrivate> d_ptr;
|
||||
};
|
||||
|
||||
FRAMELESSHELPER_END_NAMESPACE
|
||||
|
||||
Q_DECLARE_METATYPE2(FRAMELESSHELPER_PREPEND_NAMESPACE(FramelessDialog))
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (C) 2022 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 "framelesshelperwidgets_global.h"
|
||||
#include "framelessdialog.h"
|
||||
#include <QtCore/qobject.h>
|
||||
#include <QtCore/qpointer.h>
|
||||
|
||||
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||
|
||||
class WidgetsSharedHelper;
|
||||
|
||||
class FRAMELESSHELPER_WIDGETS_API FramelessDialogPrivate : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DECLARE_PUBLIC(FramelessDialog)
|
||||
Q_DISABLE_COPY_MOVE(FramelessDialogPrivate)
|
||||
|
||||
public:
|
||||
explicit FramelessDialogPrivate(FramelessDialog *q);
|
||||
~FramelessDialogPrivate() override;
|
||||
|
||||
Q_NODISCARD static FramelessDialogPrivate *get(FramelessDialog *pub);
|
||||
Q_NODISCARD static const FramelessDialogPrivate *get(const FramelessDialog *pub);
|
||||
|
||||
Q_NODISCARD WidgetsSharedHelper *widgetsSharedHelper() const;
|
||||
|
||||
private:
|
||||
void initialize();
|
||||
|
||||
private:
|
||||
QPointer<FramelessDialog> q_ptr = nullptr;
|
||||
QScopedPointer<WidgetsSharedHelper> m_helper;
|
||||
};
|
||||
|
||||
FRAMELESSHELPER_END_NAMESPACE
|
||||
|
||||
Q_DECLARE_METATYPE2(FRAMELESSHELPER_PREPEND_NAMESPACE(FramelessDialogPrivate))
|
|
@ -67,6 +67,9 @@ public:
|
|||
Q_NODISCARD bool isBlurBehindWindowEnabled() const;
|
||||
void setBlurBehindWindowEnabled(const bool enable, const QColor &color);
|
||||
|
||||
void setProperty(const QByteArray &name, const QVariant &value);
|
||||
Q_NODISCARD QVariant getProperty(const QByteArray &name, const QVariant &defaultValue = {});
|
||||
|
||||
private:
|
||||
Q_NODISCARD QRect mapWidgetGeometryToScene(const QWidget * const widget) const;
|
||||
Q_NODISCARD bool isInSystemButtons(const QPoint &pos, Global::SystemButtonType *button) const;
|
||||
|
|
|
@ -22,12 +22,14 @@ HEADERS += \
|
|||
$$WIDGETS_PUB_INC_DIR/standardsystembutton.h \
|
||||
$$WIDGETS_PUB_INC_DIR/framelesswidgetshelper.h \
|
||||
$$WIDGETS_PUB_INC_DIR/standardtitlebar.h \
|
||||
$$WIDGETS_PUB_INC_DIR/framelessdialog.h \
|
||||
$$WIDGETS_PRIV_INC_DIR/framelesswidgetshelper_p.h \
|
||||
$$WIDGETS_PRIV_INC_DIR/standardsystembutton_p.h \
|
||||
$$WIDGETS_PRIV_INC_DIR/standardtitlebar_p.h \
|
||||
$$WIDGETS_PRIV_INC_DIR/framelesswidget_p.h \
|
||||
$$WIDGETS_PRIV_INC_DIR/framelessmainwindow_p.h \
|
||||
$$WIDGETS_PRIV_INC_DIR/widgetssharedhelper_p.h
|
||||
$$WIDGETS_PRIV_INC_DIR/widgetssharedhelper_p.h \
|
||||
$$WIDGETS_PRIV_INC_DIR/framelessdialog_p.h
|
||||
|
||||
SOURCES += \
|
||||
$$WIDGETS_SRC_DIR/framelessmainwindow.cpp \
|
||||
|
@ -36,4 +38,5 @@ SOURCES += \
|
|||
$$WIDGETS_SRC_DIR/standardsystembutton.cpp \
|
||||
$$WIDGETS_SRC_DIR/standardtitlebar.cpp \
|
||||
$$WIDGETS_SRC_DIR/widgetssharedhelper.cpp \
|
||||
$$WIDGETS_SRC_DIR/framelesshelperwidgets_global.cpp
|
||||
$$WIDGETS_SRC_DIR/framelesshelperwidgets_global.cpp \
|
||||
$$WIDGETS_SRC_DIR/framelessdialog.cpp
|
||||
|
|
|
@ -41,6 +41,8 @@ Q_LOGGING_CATEGORY(lcFramelessHelperQt, "wangwenx190.framelesshelper.core.impl.q
|
|||
|
||||
using namespace Global;
|
||||
|
||||
FRAMELESSHELPER_BYTEARRAY_CONSTANT2(DontOverrideCursor, "FRAMELESSHELPER_DONT_OVERRIDE_CURSOR")
|
||||
|
||||
struct QtHelperData
|
||||
{
|
||||
SystemParameters params = {};
|
||||
|
@ -151,6 +153,7 @@ bool FramelessHelperQt::eventFilter(QObject *object, QEvent *event)
|
|||
const bool windowFixedSize = data.params.isWindowFixedSize();
|
||||
const bool ignoreThisEvent = data.params.shouldIgnoreMouseEvents(scenePos);
|
||||
const bool insideTitleBar = data.params.isInsideTitleBarDraggableArea(scenePos);
|
||||
const bool dontOverrideCursor = data.params.getProperty(kDontOverrideCursor, false).toBool();
|
||||
switch (type) {
|
||||
case QEvent::MouseButtonPress: {
|
||||
if (button == Qt::LeftButton) {
|
||||
|
@ -188,16 +191,16 @@ bool FramelessHelperQt::eventFilter(QObject *object, QEvent *event)
|
|||
}
|
||||
} break;
|
||||
case QEvent::MouseMove: {
|
||||
if (!windowFixedSize) {
|
||||
if (!windowFixedSize && !dontOverrideCursor) {
|
||||
const Qt::CursorShape cs = Utils::calculateCursorShape(window, scenePos);
|
||||
if (cs == Qt::ArrowCursor) {
|
||||
if (data.cursorShapeChanged) {
|
||||
window->unsetCursor();
|
||||
data.params.unsetCursor();
|
||||
const QMutexLocker locker(&g_qtHelper()->mutex);
|
||||
g_qtHelper()->data[windowId].cursorShapeChanged = false;
|
||||
}
|
||||
} else {
|
||||
window->setCursor(cs);
|
||||
data.params.setCursor(cs);
|
||||
const QMutexLocker locker(&g_qtHelper()->mutex);
|
||||
g_qtHelper()->data[windowId].cursorShapeChanged = true;
|
||||
}
|
||||
|
|
|
@ -73,6 +73,7 @@ FRAMELESSHELPER_STRING_CONSTANT(SetWindowPos)
|
|||
FRAMELESSHELPER_STRING_CONSTANT(TrackMouseEvent)
|
||||
FRAMELESSHELPER_STRING_CONSTANT(FindWindowW)
|
||||
FRAMELESSHELPER_STRING_CONSTANT(UnregisterClassW)
|
||||
FRAMELESSHELPER_BYTEARRAY_CONSTANT2(DontOverrideCursor, "FRAMELESSHELPER_DONT_OVERRIDE_CURSOR")
|
||||
|
||||
struct Win32HelperData
|
||||
{
|
||||
|
@ -652,35 +653,46 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
|
|||
// preserve the four window borders.
|
||||
|
||||
// If `wParam` is `FALSE`, `lParam` points to a `RECT` that contains
|
||||
// the proposed window rectangle for our window. During our
|
||||
// the proposed window rectangle for our window. During our
|
||||
// processing of the `WM_NCCALCSIZE` message, we are expected to
|
||||
// modify the `RECT` that `lParam` points to, so that its value upon
|
||||
// our return is the new client area. We must return 0 if `wParam`
|
||||
// our return is the new client area. We must return 0 if `wParam`
|
||||
// is `FALSE`.
|
||||
//
|
||||
// If `wParam` is `TRUE`, `lParam` points to a `NCCALCSIZE_PARAMS`
|
||||
// struct. This struct contains an array of 3 `RECT`s, the first of
|
||||
// struct. This struct contains an array of 3 `RECT`s, the first of
|
||||
// which has the exact same meaning as the `RECT` that is pointed to
|
||||
// by `lParam` when `wParam` is `FALSE`. The remaining `RECT`s, in
|
||||
// by `lParam` when `wParam` is `FALSE`. The remaining `RECT`s, in
|
||||
// conjunction with our return value, can
|
||||
// be used to specify portions of the source and destination window
|
||||
// rectangles that are valid and should be preserved. We opt not to
|
||||
// rectangles that are valid and should be preserved. We opt not to
|
||||
// implement an elaborate client-area preservation technique, and
|
||||
// simply return 0, which means "preserve the entire old client area
|
||||
// and align it with the upper-left corner of our new client area".
|
||||
const auto clientRect = ((static_cast<BOOL>(wParam) == FALSE)
|
||||
? reinterpret_cast<LPRECT>(lParam)
|
||||
: &(reinterpret_cast<LPNCCALCSIZE_PARAMS>(lParam))->rgrc[0]);
|
||||
const auto clientRect = ((static_cast<BOOL>(wParam) == FALSE) ?
|
||||
reinterpret_cast<LPRECT>(lParam) : &(reinterpret_cast<LPNCCALCSIZE_PARAMS>(lParam))->rgrc[0]);
|
||||
if (frameBorderVisible) {
|
||||
// Store the original top before the default window proc applies the default frame.
|
||||
// Store the original top margin before the default window procedure applies the default frame.
|
||||
const LONG originalTop = clientRect->top;
|
||||
// Apply the default frame.
|
||||
// Apply the default frame because we don't want to remove the whole window frame,
|
||||
// we still need the standard window frame (the resizable frame border and the frame
|
||||
// shadow) for the left, bottom and right edges.
|
||||
// If we return 0 here directly, the whole window frame will be removed (which means
|
||||
// there will be no resizable frame border and the frame shadow will also disappear),
|
||||
// and that's also how most applications customize their title bars on Windows. It's
|
||||
// totally OK but since we want to preserve as much original frame as possible, we
|
||||
// can't use that solution.
|
||||
const LRESULT ret = DefWindowProcW(hWnd, WM_NCCALCSIZE, wParam, lParam);
|
||||
if (ret != 0) {
|
||||
*result = ret;
|
||||
return true;
|
||||
}
|
||||
// Re-apply the original top from before the size of the default frame was applied.
|
||||
// Re-apply the original top from before the size of the default frame was applied,
|
||||
// and the whole top frame (the title bar and the top border) is gone now.
|
||||
// For the top frame, we only has 2 choices: (1) remove the top frame entirely, or
|
||||
// (2) don't touch it at all. We can't preserve the top border by adjusting the top
|
||||
// margin here. If we try to modify the top margin, the original title bar will
|
||||
// always be painted by DWM regardless what margin we set, so here we can only remove
|
||||
// the top frame entirely and use some special technique to bring the top border back.
|
||||
clientRect->top = originalTop;
|
||||
}
|
||||
const bool max = IsMaximized(hWnd);
|
||||
|
@ -915,12 +927,13 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
|
|||
(GetAsyncKeyState(VK_RBUTTON) < 0) : (GetAsyncKeyState(VK_LBUTTON) < 0));
|
||||
const bool isTitleBar = (data.params.isInsideTitleBarDraggableArea(qtScenePos) && leftButtonPressed);
|
||||
const bool isFixedSize = data.params.isWindowFixedSize();
|
||||
const bool dontOverrideCursor = data.params.getProperty(kDontOverrideCursor, false).toBool();
|
||||
if (frameBorderVisible) {
|
||||
// This will handle the left, right and bottom parts of the frame
|
||||
// because we didn't change them.
|
||||
const LRESULT originalRet = DefWindowProcW(hWnd, WM_NCHITTEST, 0, lParam);
|
||||
if (originalRet != HTCLIENT) {
|
||||
*result = originalRet;
|
||||
*result = (dontOverrideCursor ? HTBORDER : originalRet);
|
||||
return true;
|
||||
}
|
||||
if (full) {
|
||||
|
@ -937,7 +950,10 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
|
|||
// the little border at the top which the user can use to move or
|
||||
// resize the window.
|
||||
if (isTop && !isFixedSize) {
|
||||
*result = HTTOP;
|
||||
// Return HTCLIENT instead of HTBORDER here, because the mouse is
|
||||
// inside our homemade title bar now, return HTCLIENT to let our
|
||||
// title bar can still capture mouse events.
|
||||
*result = (dontOverrideCursor ? HTCLIENT : HTTOP);
|
||||
return true;
|
||||
}
|
||||
if (isTitleBar) {
|
||||
|
@ -970,6 +986,13 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
|
|||
const int scaledFrameSizeX = qRound(qreal(frameSizeX) * scaleFactor);
|
||||
const bool isLeft = (nativeLocalPos.x < scaledFrameSizeX);
|
||||
const bool isRight = (nativeLocalPos.x >= (width - scaledFrameSizeX));
|
||||
if (dontOverrideCursor && (isTop || isBottom || isLeft || isRight)) {
|
||||
// Return HTCLIENT instead of HTBORDER here, because the mouse is
|
||||
// inside the window now, return HTCLIENT to let the controls
|
||||
// inside our window can still capture mouse events.
|
||||
*result = HTCLIENT;
|
||||
return true;
|
||||
}
|
||||
if (isTop) {
|
||||
if (isLeft) {
|
||||
*result = HTTOPLEFT;
|
||||
|
|
|
@ -384,9 +384,9 @@ static inline void expblur(QImage &img, qreal radius, const bool improvedQuality
|
|||
|
||||
if (p) {
|
||||
p->save();
|
||||
p->setRenderHints(QPainter::Antialiasing |
|
||||
QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform);
|
||||
p->scale(scale, scale);
|
||||
p->setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing
|
||||
| QPainter::SmoothPixmapTransform, quality);
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 2, 0))
|
||||
const QSize imageSize = blurImage.deviceIndependentSize().toSize();
|
||||
#else
|
||||
|
@ -527,15 +527,20 @@ void MicaMaterialPrivate::maybeGenerateBlurredWallpaper(const bool force)
|
|||
const QRect desktopRect = {desktopOriginPoint, size};
|
||||
if (aspectStyle == WallpaperAspectStyle::Tile) {
|
||||
QPainter bufferPainter(&buffer);
|
||||
const QBrush brush(image);
|
||||
bufferPainter.fillRect(desktopRect, brush);
|
||||
bufferPainter.setRenderHints(QPainter::Antialiasing |
|
||||
QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform);
|
||||
bufferPainter.fillRect(desktopRect, QBrush(image));
|
||||
} else {
|
||||
QPainter bufferPainter(&buffer);
|
||||
bufferPainter.setRenderHints(QPainter::Antialiasing |
|
||||
QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform);
|
||||
const QRect rect = alignedRect(Qt::LeftToRight, Qt::AlignCenter, image.size(), desktopRect);
|
||||
bufferPainter.drawImage(rect.topLeft(), image);
|
||||
}
|
||||
g_micaMaterialData()->mutex.lock();
|
||||
QPainter painter(&g_micaMaterialData()->blurredWallpaper);
|
||||
painter.setRenderHints(QPainter::Antialiasing |
|
||||
QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform);
|
||||
#if 1
|
||||
qt_blurImage(&painter, buffer, kDefaultBlurRadius, true, false);
|
||||
#else
|
||||
|
@ -555,6 +560,8 @@ void MicaMaterialPrivate::updateMaterialBrush()
|
|||
fillColor.setAlphaF(0.9f);
|
||||
micaTexture.fill(fillColor);
|
||||
QPainter painter(&micaTexture);
|
||||
painter.setRenderHints(QPainter::Antialiasing |
|
||||
QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform);
|
||||
painter.setOpacity(tintOpacity);
|
||||
const QRect rect = {QPoint(0, 0), micaTexture.size()};
|
||||
painter.fillRect(rect, tintColor);
|
||||
|
@ -573,6 +580,8 @@ void MicaMaterialPrivate::paint(QPainter *painter, const QSize &size, const QPoi
|
|||
}
|
||||
static constexpr const QPoint originPoint = {0, 0};
|
||||
painter->save();
|
||||
painter->setRenderHints(QPainter::Antialiasing |
|
||||
QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform);
|
||||
g_micaMaterialData()->mutex.lock();
|
||||
painter->drawPixmap(originPoint, g_micaMaterialData()->blurredWallpaper, QRect(pos, size));
|
||||
g_micaMaterialData()->mutex.unlock();
|
||||
|
|
|
@ -761,7 +761,7 @@ void Utils::showSystemMenu(const WId windowId, const QPoint &pos, const bool sel
|
|||
// Tweak the menu items according to the current window status.
|
||||
const bool maxOrFull = (IsMaximized(hWnd) || isFullScreen(windowId));
|
||||
const bool fixedSize = isWindowFixedSize();
|
||||
EnableMenuItem(hMenu, SC_RESTORE, (MF_BYCOMMAND | ((maxOrFull && !fixedSize) ? MFS_ENABLED : MFS_DISABLED)));
|
||||
EnableMenuItem(hMenu, SC_RESTORE, (MF_BYCOMMAND | ((maxOrFull && !fixedSize) ? MFS_ENABLED : MFS_GRAYED)));
|
||||
// The first menu item should be selected by default if the menu is brought
|
||||
// up by keyboard. I don't know how to pre-select a menu item but it seems
|
||||
// highlight can do the job. However, there's an annoying issue if we do
|
||||
|
@ -772,10 +772,10 @@ void Utils::showSystemMenu(const WId windowId, const QPoint &pos, const bool sel
|
|||
// highlight bar to indicate the current selected menu item, which will make
|
||||
// the menu look kind of weird. Currently I don't know how to fix this issue.
|
||||
HiliteMenuItem(hWnd, hMenu, SC_RESTORE, (MF_BYCOMMAND | (selectFirstEntry ? MFS_HILITE : MFS_UNHILITE)));
|
||||
EnableMenuItem(hMenu, SC_MOVE, (MF_BYCOMMAND | (!maxOrFull ? MFS_ENABLED : MFS_DISABLED)));
|
||||
EnableMenuItem(hMenu, SC_SIZE, (MF_BYCOMMAND | ((!maxOrFull && !fixedSize) ? MFS_ENABLED : MFS_DISABLED)));
|
||||
EnableMenuItem(hMenu, SC_MOVE, (MF_BYCOMMAND | (!maxOrFull ? MFS_ENABLED : MFS_GRAYED)));
|
||||
EnableMenuItem(hMenu, SC_SIZE, (MF_BYCOMMAND | ((!maxOrFull && !fixedSize) ? MFS_ENABLED : MFS_GRAYED)));
|
||||
EnableMenuItem(hMenu, SC_MINIMIZE, (MF_BYCOMMAND | MFS_ENABLED));
|
||||
EnableMenuItem(hMenu, SC_MAXIMIZE, (MF_BYCOMMAND | ((!maxOrFull && !fixedSize) ? MFS_ENABLED : MFS_DISABLED)));
|
||||
EnableMenuItem(hMenu, SC_MAXIMIZE, (MF_BYCOMMAND | ((!maxOrFull && !fixedSize) ? MFS_ENABLED : MFS_GRAYED)));
|
||||
EnableMenuItem(hMenu, SC_CLOSE, (MF_BYCOMMAND | MFS_ENABLED));
|
||||
|
||||
// The default menu item will appear in bold font. There can only be one default
|
||||
|
|
|
@ -196,6 +196,10 @@ void FramelessQuickHelperPrivate::attachToWindow()
|
|||
params.shouldIgnoreMouseEvents = [this](const QPoint &pos) -> bool { return shouldIgnoreMouseEvents(pos); };
|
||||
params.showSystemMenu = [this](const QPoint &pos) -> void { showSystemMenu(pos); };
|
||||
params.getCurrentApplicationType = []() -> ApplicationType { return ApplicationType::Quick; };
|
||||
params.setProperty = [this](const QByteArray &name, const QVariant &value) -> void { setProperty(name, value); };
|
||||
params.getProperty = [this](const QByteArray &name, const QVariant &defaultValue) -> QVariant { return getProperty(name, defaultValue); };
|
||||
params.setCursor = [window](const QCursor &cursor) -> void { window->setCursor(cursor); };
|
||||
params.unsetCursor = [window]() -> void { window->unsetCursor(); };
|
||||
|
||||
g_quickHelper()->mutex.lock();
|
||||
data->params = params;
|
||||
|
@ -454,6 +458,36 @@ void FramelessQuickHelperPrivate::setBlurBehindWindowEnabled(const bool value, c
|
|||
}
|
||||
}
|
||||
|
||||
void FramelessQuickHelperPrivate::setProperty(const QByteArray &name, const QVariant &value)
|
||||
{
|
||||
Q_ASSERT(!name.isEmpty());
|
||||
Q_ASSERT(value.isValid());
|
||||
if (name.isEmpty() || !value.isValid()) {
|
||||
return;
|
||||
}
|
||||
Q_Q(FramelessQuickHelper);
|
||||
QQuickWindow * const window = q->window();
|
||||
if (!window) {
|
||||
return;
|
||||
}
|
||||
window->setProperty(name.constData(), value);
|
||||
}
|
||||
|
||||
QVariant FramelessQuickHelperPrivate::getProperty(const QByteArray &name, const QVariant &defaultValue)
|
||||
{
|
||||
Q_ASSERT(!name.isEmpty());
|
||||
if (name.isEmpty()) {
|
||||
return {};
|
||||
}
|
||||
Q_Q(FramelessQuickHelper);
|
||||
const QQuickWindow * const window = q->window();
|
||||
if (!window) {
|
||||
return {};
|
||||
}
|
||||
const QVariant value = window->property(name.constData());
|
||||
return (value.isValid() ? value : defaultValue);
|
||||
}
|
||||
|
||||
bool FramelessQuickHelperPrivate::eventFilter(QObject *object, QEvent *event)
|
||||
{
|
||||
Q_ASSERT(object);
|
||||
|
|
|
@ -85,8 +85,8 @@ void QuickImageItemPrivate::paint(QPainter *painter) const
|
|||
return;
|
||||
}
|
||||
painter->save();
|
||||
painter->setRenderHints(QPainter::Antialiasing
|
||||
| QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform);
|
||||
painter->setRenderHints(QPainter::Antialiasing |
|
||||
QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform);
|
||||
switch (m_source.userType()) {
|
||||
case QMetaType::QUrl:
|
||||
fromUrl(m_source.toUrl(), painter);
|
||||
|
|
|
@ -35,6 +35,7 @@ set(PUBLIC_HEADERS
|
|||
${INCLUDE_PREFIX}/standardsystembutton.h
|
||||
${INCLUDE_PREFIX}/framelesswidgetshelper.h
|
||||
${INCLUDE_PREFIX}/standardtitlebar.h
|
||||
${INCLUDE_PREFIX}/framelessdialog.h
|
||||
)
|
||||
|
||||
set(PUBLIC_HEADERS_ALIAS
|
||||
|
@ -44,6 +45,7 @@ set(PUBLIC_HEADERS_ALIAS
|
|||
${INCLUDE_PREFIX}/StandardSystemButton
|
||||
${INCLUDE_PREFIX}/FramelessWidgetsHelper
|
||||
${INCLUDE_PREFIX}/StandardTitleBar
|
||||
${INCLUDE_PREFIX}/FramelessDialog
|
||||
)
|
||||
|
||||
set(PRIVATE_HEADERS
|
||||
|
@ -53,6 +55,7 @@ set(PRIVATE_HEADERS
|
|||
${INCLUDE_PREFIX}/private/framelesswidget_p.h
|
||||
${INCLUDE_PREFIX}/private/framelessmainwindow_p.h
|
||||
${INCLUDE_PREFIX}/private/widgetssharedhelper_p.h
|
||||
${INCLUDE_PREFIX}/private/framelessdialog_p.h
|
||||
)
|
||||
|
||||
set(SOURCES
|
||||
|
@ -63,6 +66,7 @@ set(SOURCES
|
|||
standardtitlebar.cpp
|
||||
widgetssharedhelper.cpp
|
||||
framelesshelperwidgets_global.cpp
|
||||
framelessdialog.cpp
|
||||
)
|
||||
|
||||
if(WIN32 AND NOT FRAMELESSHELPER_BUILD_STATIC)
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (C) 2022 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 "framelessdialog.h"
|
||||
#include "framelessdialog_p.h"
|
||||
#include "framelesswidgetshelper.h"
|
||||
#include "widgetssharedhelper_p.h"
|
||||
#include <utils.h>
|
||||
|
||||
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||
|
||||
Q_LOGGING_CATEGORY(lcFramelessDialog, "wangwenx190.framelesshelper.widgets.framelessdialog")
|
||||
#define INFO qCInfo(lcFramelessDialog)
|
||||
#define DEBUG qCDebug(lcFramelessDialog)
|
||||
#define WARNING qCWarning(lcFramelessDialog)
|
||||
#define CRITICAL qCCritical(lcFramelessDialog)
|
||||
|
||||
using namespace Global;
|
||||
|
||||
FramelessDialogPrivate::FramelessDialogPrivate(FramelessDialog *q) : QObject(q)
|
||||
{
|
||||
Q_ASSERT(q);
|
||||
if (!q) {
|
||||
return;
|
||||
}
|
||||
q_ptr = q;
|
||||
initialize();
|
||||
}
|
||||
|
||||
FramelessDialogPrivate::~FramelessDialogPrivate() = default;
|
||||
|
||||
FramelessDialogPrivate *FramelessDialogPrivate::get(FramelessDialog *pub)
|
||||
{
|
||||
Q_ASSERT(pub);
|
||||
if (!pub) {
|
||||
return nullptr;
|
||||
}
|
||||
return pub->d_func();
|
||||
}
|
||||
|
||||
const FramelessDialogPrivate *FramelessDialogPrivate::get(const FramelessDialog *pub)
|
||||
{
|
||||
Q_ASSERT(pub);
|
||||
if (!pub) {
|
||||
return nullptr;
|
||||
}
|
||||
return pub->d_func();
|
||||
}
|
||||
|
||||
void FramelessDialogPrivate::initialize()
|
||||
{
|
||||
Q_Q(FramelessDialog);
|
||||
FramelessWidgetsHelper::get(q)->extendsContentIntoTitleBar();
|
||||
m_helper.reset(new WidgetsSharedHelper(this));
|
||||
m_helper->setup(q);
|
||||
}
|
||||
|
||||
WidgetsSharedHelper *FramelessDialogPrivate::widgetsSharedHelper() const
|
||||
{
|
||||
return (m_helper.isNull() ? nullptr : m_helper.data());
|
||||
}
|
||||
|
||||
FramelessDialog::FramelessDialog(QWidget *parent)
|
||||
: QDialog(parent), d_ptr(new FramelessDialogPrivate(this))
|
||||
{
|
||||
}
|
||||
|
||||
FramelessDialog::~FramelessDialog() = default;
|
||||
|
||||
FRAMELESSHELPER_END_NAMESPACE
|
|
@ -0,0 +1 @@
|
|||
#include "../../include/FramelessHelper/Widgets/framelessdialog.h"
|
|
@ -0,0 +1 @@
|
|||
#include "../../include/FramelessHelper/Widgets/private/framelessdialog_p.h"
|
|
@ -28,6 +28,8 @@
|
|||
#include "framelesswidget_p.h"
|
||||
#include "framelessmainwindow.h"
|
||||
#include "framelessmainwindow_p.h"
|
||||
#include "framelessdialog.h"
|
||||
#include "framelessdialog_p.h"
|
||||
#include "widgetssharedhelper_p.h"
|
||||
#include <QtCore/qmutex.h>
|
||||
#include <QtCore/qhash.h>
|
||||
|
@ -87,6 +89,11 @@ Q_GLOBAL_STATIC(WidgetsHelper, g_widgetsHelper)
|
|||
return mainWindowPriv->widgetsSharedHelper();
|
||||
}
|
||||
}
|
||||
if (const auto dialog = qobject_cast<FramelessDialog *>(window)) {
|
||||
if (const auto dialogPriv = FramelessDialogPrivate::get(dialog)) {
|
||||
return dialogPriv->widgetsSharedHelper();
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -230,6 +237,36 @@ void FramelessWidgetsHelperPrivate::setBlurBehindWindowEnabled(const bool enable
|
|||
}
|
||||
}
|
||||
|
||||
void FramelessWidgetsHelperPrivate::setProperty(const QByteArray &name, const QVariant &value)
|
||||
{
|
||||
Q_ASSERT(!name.isEmpty());
|
||||
Q_ASSERT(value.isValid());
|
||||
if (name.isEmpty() || !value.isValid()) {
|
||||
return;
|
||||
}
|
||||
QWidget * const window = getWindow();
|
||||
Q_ASSERT(window);
|
||||
if (!window) {
|
||||
return;
|
||||
}
|
||||
window->setProperty(name.constData(), value);
|
||||
}
|
||||
|
||||
QVariant FramelessWidgetsHelperPrivate::getProperty(const QByteArray &name, const QVariant &defaultValue)
|
||||
{
|
||||
Q_ASSERT(!name.isEmpty());
|
||||
if (name.isEmpty()) {
|
||||
return {};
|
||||
}
|
||||
const QWidget * const window = getWindow();
|
||||
Q_ASSERT(window);
|
||||
if (!window) {
|
||||
return {};
|
||||
}
|
||||
const QVariant value = window->property(name.constData());
|
||||
return (value.isValid() ? value : defaultValue);
|
||||
}
|
||||
|
||||
void FramelessWidgetsHelperPrivate::setTitleBarWidget(QWidget *widget)
|
||||
{
|
||||
Q_ASSERT(widget);
|
||||
|
@ -332,6 +369,10 @@ void FramelessWidgetsHelperPrivate::attachToWindow()
|
|||
params.shouldIgnoreMouseEvents = [this](const QPoint &pos) -> bool { return shouldIgnoreMouseEvents(pos); };
|
||||
params.showSystemMenu = [this](const QPoint &pos) -> void { showSystemMenu(pos); };
|
||||
params.getCurrentApplicationType = []() -> ApplicationType { return ApplicationType::Widgets; };
|
||||
params.setProperty = [this](const QByteArray &name, const QVariant &value) -> void { setProperty(name, value); };
|
||||
params.getProperty = [this](const QByteArray &name, const QVariant &defaultValue) -> QVariant { return getProperty(name, defaultValue); };
|
||||
params.setCursor = [window](const QCursor &cursor) -> void { window->setCursor(cursor); };
|
||||
params.unsetCursor = [window]() -> void { window->unsetCursor(); };
|
||||
|
||||
g_widgetsHelper()->mutex.lock();
|
||||
data->params = params;
|
||||
|
|
|
@ -146,9 +146,17 @@ void WidgetsSharedHelper::changeEventHandler(QEvent *event)
|
|||
return;
|
||||
}
|
||||
updateContentsMargins();
|
||||
QMetaObject::invokeMethod(m_targetWidget, "hiddenChanged");
|
||||
QMetaObject::invokeMethod(m_targetWidget, "normalChanged");
|
||||
QMetaObject::invokeMethod(m_targetWidget, "zoomedChanged");
|
||||
if (const auto mo = m_targetWidget->metaObject()) {
|
||||
if (const int idx = mo->indexOfSignal(QMetaObject::normalizedSignature("hiddenChanged()").constData()); idx >= 0) {
|
||||
QMetaObject::invokeMethod(m_targetWidget, "hiddenChanged");
|
||||
}
|
||||
if (const int idx = mo->indexOfSignal(QMetaObject::normalizedSignature("normalChanged()").constData()); idx >= 0) {
|
||||
QMetaObject::invokeMethod(m_targetWidget, "normalChanged");
|
||||
}
|
||||
if (const int idx = mo->indexOfSignal(QMetaObject::normalizedSignature("zoomedChanged()").constData()); idx >= 0) {
|
||||
QMetaObject::invokeMethod(m_targetWidget, "zoomedChanged");
|
||||
}
|
||||
}
|
||||
#ifdef Q_OS_WINDOWS
|
||||
const WId windowId = m_targetWidget->winId();
|
||||
static const bool isWin11OrGreater = Utils::isWindowsVersionOrGreater(WindowsVersion::_11_21H2);
|
||||
|
@ -181,6 +189,10 @@ void WidgetsSharedHelper::paintEventHandler(QPaintEvent *event)
|
|||
if (shouldDrawFrameBorder()) {
|
||||
QPainter painter(m_targetWidget);
|
||||
painter.save();
|
||||
painter.setRenderHints(QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform);
|
||||
// We can't enable antialiasing here, because the border is only 1px height,
|
||||
// it's too thin and antialiasing will break it's painting.
|
||||
painter.setRenderHint(QPainter::Antialiasing, false);
|
||||
QPen pen = {};
|
||||
pen.setColor(Utils::getFrameBorderColor(m_targetWidget->isActiveWindow()));
|
||||
pen.setWidth(kDefaultWindowFrameBorderThickness);
|
||||
|
|
Loading…
Reference in New Issue