Updated lib_ui sources to TDesktop version 2.3.2+d34eabd
This commit is contained in:
commit
58c35e9dcc
17 changed files with 602 additions and 169 deletions
|
|
@ -4,7 +4,7 @@
|
|||
# For license and copyright information please follow this link:
|
||||
# https://github.com/desktop-app/legal/blob/master/LEGAL
|
||||
|
||||
add_library(lib_ui OBJECT)
|
||||
add_library(lib_ui STATIC)
|
||||
add_library(desktop-app::lib_ui ALIAS lib_ui)
|
||||
init_target(lib_ui)
|
||||
|
||||
|
|
@ -84,6 +84,7 @@ PRIVATE
|
|||
ui/platform/win/ui_window_win.h
|
||||
ui/platform/win/ui_utility_win.cpp
|
||||
ui/platform/win/ui_utility_win.h
|
||||
ui/platform/ui_platform_window.cpp
|
||||
ui/platform/ui_platform_window.h
|
||||
ui/platform/ui_platform_utility.h
|
||||
ui/style/style_core.cpp
|
||||
|
|
|
|||
|
|
@ -536,20 +536,23 @@ mediaviewTransparentFg: #cccccc; // another transparent filling part
|
|||
notificationBg: windowBg; // custom notification window background
|
||||
|
||||
// calls
|
||||
callBg: #26282cf2; // phone call popup background
|
||||
callBg: #26282cf2; // old phone call popup background
|
||||
callBgOpaque: #1b1f23; // phone call popup background
|
||||
callBgButton: #1b1f237f; // phone call window control buttons bg
|
||||
callNameFg: #ffffff; // phone call popup name text
|
||||
callFingerprintBg: #00000066; // phone call popup emoji fingerprint background
|
||||
callStatusFg: #aaabac; // phone call popup status text
|
||||
callIconFg: #ffffff; // phone call popup answer, hangup and mute mic icon
|
||||
callIconBg: #ffffff1f; // phone call mute mic and camera button background
|
||||
callIconFg: #ffffff; // phone call popup answer, hangup, mute mic and camera icon
|
||||
callIconBgActive: #ffffffe5; // phone call line busy cancel, muted mic and camera button background
|
||||
callIconFgActive: #222222; // phone call line busy cancel, muted mic and camera icon
|
||||
callIconActiveRipple: #f1f1f1; // phone call line busy cancel, muted mic and camera ripple effect
|
||||
callAnswerBg: #64c15b; // phone call popup answer button background
|
||||
callAnswerRipple: #52b149; // phone call popup answer button ripple effect
|
||||
callAnswerBgOuter: #50eb4126; // phone call popup answer button outer ripple effect
|
||||
callHangupBg: #d75a5a; // phone call popup hangup button background
|
||||
callHangupRipple: #c04646; // phone call popup hangup button ripple effect
|
||||
callCancelBg: #ffffff; // phone call popup line busy cancel button background
|
||||
callCancelFg: #777777; // phone call popup line busy cancel button icon
|
||||
callCancelRipple: #f1f1f1; // phone call popup line busy cancel button ripple effect
|
||||
callMuteRipple: #ffffff12; // phone call popup mute mic ripple effect
|
||||
callMuteRipple: #ffffff12; // phone call popup mute mic and camera ripple effect
|
||||
|
||||
callBarBg: dialogsBgActive; // active phone call bar background
|
||||
callBarMuteRipple: dialogsRippleBgActive; // active phone call bar mute and hangup button ripple effect
|
||||
|
|
|
|||
|
|
@ -458,9 +458,9 @@ void prepareRound(
|
|||
}
|
||||
auto cornerWidth = cornerMasks[0].width();
|
||||
auto cornerHeight = cornerMasks[0].height();
|
||||
auto imageWidth = image.width();
|
||||
auto imageHeight = image.height();
|
||||
if (imageWidth < 2 * cornerWidth || imageHeight < 2 * cornerHeight) {
|
||||
auto targetWidth = target.width();
|
||||
auto targetHeight = target.height();
|
||||
if (targetWidth < 2 * cornerWidth || targetHeight < 2 * cornerHeight) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -475,9 +475,9 @@ void prepareRound(
|
|||
Assert(image.depth() == static_cast<int>((imageIntsPerPixel * sizeof(uint32)) << 3));
|
||||
Assert(image.bytesPerLine() == (imageIntsPerLine << 2));
|
||||
auto intsTopLeft = ints + target.x() + target.y() * imageIntsPerLine;
|
||||
auto intsTopRight = ints + target.x() + target.width() - cornerWidth + target.y() * imageIntsPerLine;
|
||||
auto intsBottomLeft = ints + target.x() + (target.y() + target.height() - cornerHeight) * imageIntsPerLine;
|
||||
auto intsBottomRight = ints + target.x() + target.width() - cornerWidth + (target.y() + target.height() - cornerHeight) * imageIntsPerLine;
|
||||
auto intsTopRight = ints + target.x() + targetWidth - cornerWidth + target.y() * imageIntsPerLine;
|
||||
auto intsBottomLeft = ints + target.x() + (target.y() + targetHeight - cornerHeight) * imageIntsPerLine;
|
||||
auto intsBottomRight = ints + target.x() + targetWidth - cornerWidth + (target.y() + targetHeight - cornerHeight) * imageIntsPerLine;
|
||||
auto maskCorner = [&](uint32 *imageInts, const QImage &mask) {
|
||||
auto maskWidth = mask.width();
|
||||
auto maskHeight = mask.height();
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
namespace Ui {
|
||||
namespace Platform {
|
||||
|
||||
std::unique_ptr<BasicWindowHelper> CreateWindowHelper(
|
||||
std::unique_ptr<BasicWindowHelper> CreateSpecialWindowHelper(
|
||||
not_null<RpWidget*> window) {
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,19 +24,29 @@ public:
|
|||
void setMinimumSize(QSize size) override;
|
||||
void setFixedSize(QSize size) override;
|
||||
void setGeometry(QRect rect) override;
|
||||
void close() override;
|
||||
|
||||
private:
|
||||
class Private;
|
||||
friend class Private;
|
||||
|
||||
void setupBodyTitleAreaEvents() override;
|
||||
|
||||
void init();
|
||||
void toggleCustomTitle(bool visible);
|
||||
|
||||
const not_null<RpWidget*> _window;
|
||||
const std::unique_ptr<Private> _private;
|
||||
const not_null<TitleWidget*> _title;
|
||||
const not_null<RpWidget*> _body;
|
||||
|
||||
#ifdef OS_OSX
|
||||
struct WindowDrag {
|
||||
QPoint windowStartPosition;
|
||||
QPoint dragStartPosition;
|
||||
};
|
||||
std::optional<WindowDrag> _drag;
|
||||
#endif // OS_OSX
|
||||
|
||||
};
|
||||
|
||||
} // namespace Platform
|
||||
|
|
|
|||
|
|
@ -7,10 +7,14 @@
|
|||
#include "ui/platform/mac/ui_window_mac.h"
|
||||
|
||||
#include "ui/platform/mac/ui_window_title_mac.h"
|
||||
#include "ui/widgets/window.h"
|
||||
#include "base/platform/base_platform_info.h"
|
||||
#include "styles/palette.h"
|
||||
|
||||
#include <QtCore/QCoreApplication>
|
||||
#include <QtCore/QAbstractNativeEventFilter>
|
||||
#include <QtGui/QWindow>
|
||||
#include <QtGui/QtEvents>
|
||||
#include <QtWidgets/QOpenGLWidget>
|
||||
#include <Cocoa/Cocoa.h>
|
||||
|
||||
|
|
@ -78,13 +82,42 @@ private:
|
|||
|
||||
};
|
||||
|
||||
class EventFilter : public QObject, public QAbstractNativeEventFilter {
|
||||
public:
|
||||
EventFilter(not_null<QObject*> parent, Fn<bool(void*)> checkPerformDrag)
|
||||
: QObject(parent)
|
||||
, _checkPerformDrag(std::move(checkPerformDrag)) {
|
||||
Expects(_checkPerformDrag != nullptr);
|
||||
}
|
||||
|
||||
bool nativeEventFilter(
|
||||
const QByteArray &eventType,
|
||||
void *message,
|
||||
long *result) {
|
||||
NSEvent *e = static_cast<NSEvent*>(message);
|
||||
return (e && [e type] == NSEventTypeLeftMouseDown)
|
||||
? _checkPerformDrag([e window])
|
||||
: false;
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
Fn<bool(void*)> _checkPerformDrag;
|
||||
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
class WindowHelper::Private final {
|
||||
public:
|
||||
explicit Private(not_null<WindowHelper*> owner);
|
||||
~Private();
|
||||
|
||||
[[nodiscard]] int customTitleHeight() const;
|
||||
[[nodiscard]] QRect controlsRect() const;
|
||||
[[nodiscard]] bool checkNativeMove(void *nswindow) const;
|
||||
void activateBeforeNativeMove();
|
||||
void close();
|
||||
|
||||
private:
|
||||
void init();
|
||||
|
|
@ -113,32 +146,87 @@ WindowHelper::Private::Private(not_null<WindowHelper*> owner)
|
|||
init();
|
||||
}
|
||||
|
||||
WindowHelper::Private::~Private() {
|
||||
[_observer release];
|
||||
}
|
||||
|
||||
int WindowHelper::Private::customTitleHeight() const {
|
||||
return _customTitleHeight;
|
||||
}
|
||||
|
||||
Fn<void(bool)> WindowHelper::Private::toggleCustomTitleCallback() {
|
||||
return [=](bool visible) {
|
||||
_owner->toggleCustomTitle(visible);
|
||||
QRect WindowHelper::Private::controlsRect() const {
|
||||
const auto button = [&](NSWindowButton type) {
|
||||
auto view = [_nativeWindow standardWindowButton:type];
|
||||
if (!view) {
|
||||
return QRect();
|
||||
}
|
||||
auto result = [view frame];
|
||||
for (auto parent = [view superview]; parent != nil; parent = [parent superview]) {
|
||||
const auto origin = [parent frame].origin;
|
||||
result.origin.x += origin.x;
|
||||
result.origin.y += origin.y;
|
||||
}
|
||||
return QRect(result.origin.x, result.origin.y, result.size.width, result.size.height);
|
||||
};
|
||||
auto result = QRect();
|
||||
const auto buttons = {
|
||||
NSWindowCloseButton,
|
||||
NSWindowMiniaturizeButton,
|
||||
NSWindowZoomButton,
|
||||
};
|
||||
for (const auto type : buttons) {
|
||||
result = result.united(button(type));
|
||||
}
|
||||
return QRect(
|
||||
result.x(),
|
||||
[_nativeWindow frame].size.height - result.y() - result.height(),
|
||||
result.width(),
|
||||
result.height());
|
||||
}
|
||||
|
||||
bool WindowHelper::Private::checkNativeMove(void *nswindow) const {
|
||||
if (_nativeWindow != nswindow
|
||||
|| ([_nativeWindow styleMask] & NSFullScreenWindowMask) == NSFullScreenWindowMask) {
|
||||
return false;
|
||||
}
|
||||
const auto cgReal = [NSEvent mouseLocation];
|
||||
const auto real = QPointF(cgReal.x, cgReal.y);
|
||||
const auto cgFrame = [_nativeWindow frame];
|
||||
const auto frame = QRectF(cgFrame.origin.x, cgFrame.origin.y, cgFrame.size.width, cgFrame.size.height);
|
||||
const auto border = QMarginsF{ 3., 3., 3., 3. };
|
||||
return frame.marginsRemoved(border).contains(real);
|
||||
}
|
||||
|
||||
void WindowHelper::Private::activateBeforeNativeMove() {
|
||||
[_nativeWindow makeKeyAndOrderFront:_nativeWindow];
|
||||
}
|
||||
|
||||
void WindowHelper::Private::close() {
|
||||
[_nativeWindow close];
|
||||
}
|
||||
|
||||
Fn<void(bool)> WindowHelper::Private::toggleCustomTitleCallback() {
|
||||
return crl::guard(_owner->window(), [=](bool visible) {
|
||||
_owner->toggleCustomTitle(visible);
|
||||
});
|
||||
}
|
||||
|
||||
Fn<void()> WindowHelper::Private::enforceStyleCallback() {
|
||||
return [=] {
|
||||
return crl::guard(_owner->window(), [=] {
|
||||
if (_nativeWindow && _customTitleHeight > 0) {
|
||||
[_nativeWindow setStyleMask:[_nativeWindow styleMask] | NSFullSizeContentViewWindowMask];
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
void WindowHelper::Private::initOpenGL() {
|
||||
auto forceOpenGL = std::make_unique<QOpenGLWidget>(_owner->_window);
|
||||
auto forceOpenGL = std::make_unique<QOpenGLWidget>(_owner->window());
|
||||
}
|
||||
|
||||
void WindowHelper::Private::resolveWeakPointers() {
|
||||
_owner->_window->createWinId();
|
||||
_owner->window()->createWinId();
|
||||
|
||||
_nativeView = reinterpret_cast<NSView*>(_owner->_window->winId());
|
||||
_nativeView = reinterpret_cast<NSView*>(_owner->window()->winId());
|
||||
_nativeWindow = _nativeView ? [_nativeView window] : nullptr;
|
||||
|
||||
Ensures(_nativeWindow != nullptr);
|
||||
|
|
@ -189,14 +277,17 @@ void WindowHelper::Private::init() {
|
|||
}
|
||||
|
||||
WindowHelper::WindowHelper(not_null<RpWidget*> window)
|
||||
: _window(window)
|
||||
: BasicWindowHelper(window)
|
||||
, _private(std::make_unique<Private>(this))
|
||||
, _title(_private->customTitleHeight()
|
||||
? Ui::CreateChild<TitleWidget>(
|
||||
_window.get(),
|
||||
window.get(),
|
||||
_private->customTitleHeight())
|
||||
: nullptr)
|
||||
, _body(Ui::CreateChild<RpWidget>(_window.get())) {
|
||||
, _body(Ui::CreateChild<RpWidget>(window.get())) {
|
||||
if (_title->shouldBeHidden()) {
|
||||
toggleCustomTitle(false);
|
||||
}
|
||||
init();
|
||||
}
|
||||
|
||||
|
|
@ -211,44 +302,92 @@ void WindowHelper::setTitle(const QString &title) {
|
|||
if (_title) {
|
||||
_title->setText(title);
|
||||
}
|
||||
_window->setWindowTitle(
|
||||
window()->setWindowTitle(
|
||||
(!_title || _title->isHidden()) ? title : QString());
|
||||
}
|
||||
|
||||
void WindowHelper::setTitleStyle(const style::WindowTitle &st) {
|
||||
if (_title) {
|
||||
_title->setStyle(st);
|
||||
if (_title->shouldBeHidden()) {
|
||||
toggleCustomTitle(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WindowHelper::toggleCustomTitle(bool visible) {
|
||||
if (_title->shouldBeHidden()) {
|
||||
visible = false;
|
||||
}
|
||||
if (!_title || _title->isHidden() != visible) {
|
||||
return;
|
||||
}
|
||||
_title->setVisible(visible);
|
||||
_window->setWindowTitle(visible ? QString() : _title->text());
|
||||
window()->setWindowTitle(visible ? QString() : _title->text());
|
||||
}
|
||||
|
||||
void WindowHelper::setMinimumSize(QSize size) {
|
||||
_window->setMinimumSize(
|
||||
window()->setMinimumSize(
|
||||
size.width(),
|
||||
(_title ? _title->height() : 0) + size.height());
|
||||
}
|
||||
|
||||
void WindowHelper::setFixedSize(QSize size) {
|
||||
_window->setFixedSize(
|
||||
window()->setFixedSize(
|
||||
size.width(),
|
||||
(_title ? _title->height() : 0) + size.height());
|
||||
}
|
||||
|
||||
void WindowHelper::setGeometry(QRect rect) {
|
||||
_window->setGeometry(
|
||||
window()->setGeometry(
|
||||
rect.marginsAdded({ 0, (_title ? _title->height() : 0), 0, 0 }));
|
||||
}
|
||||
|
||||
void WindowHelper::setupBodyTitleAreaEvents() {
|
||||
#ifndef OS_OSX
|
||||
const auto controls = _private->controlsRect();
|
||||
qApp->installNativeEventFilter(new EventFilter(window(), [=](void *nswindow) {
|
||||
const auto point = body()->mapFromGlobal(QCursor::pos());
|
||||
if (_private->checkNativeMove(nswindow)
|
||||
&& !controls.contains(point)
|
||||
&& (bodyTitleAreaHit(point) & WindowTitleHitTestFlag::Move)) {
|
||||
_private->activateBeforeNativeMove();
|
||||
window()->windowHandle()->startSystemMove();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}));
|
||||
#else // OS_OSX
|
||||
// OS X 10.10 doesn't have performWindowDragWithEvent yet.
|
||||
body()->events() | rpl::start_with_next([=](not_null<QEvent*> e) {
|
||||
const auto hitTest = [&] {
|
||||
return bodyTitleAreaHit(
|
||||
static_cast<QMouseEvent*>(e.get())->pos());
|
||||
};
|
||||
if (e->type() == QEvent::MouseButtonRelease
|
||||
&& (static_cast<QMouseEvent*>(e.get())->button()
|
||||
== Qt::LeftButton)) {
|
||||
_drag = std::nullopt;
|
||||
} else if (e->type() == QEvent::MouseButtonPress
|
||||
&& hitTest()
|
||||
&& (static_cast<QMouseEvent*>(e.get())->button()
|
||||
== Qt::LeftButton)) {
|
||||
_drag = { window()->pos(), static_cast<QMouseEvent*>(e.get())->globalPos() };
|
||||
} else if (e->type() == QEvent::MouseMove && _drag && !window()->isFullScreen()) {
|
||||
const auto delta = static_cast<QMouseEvent*>(e.get())->globalPos() - _drag->dragStartPosition;
|
||||
window()->move(_drag->windowStartPosition + delta);
|
||||
}
|
||||
}, body()->lifetime());
|
||||
#endif // OS_OSX
|
||||
}
|
||||
|
||||
void WindowHelper::close() {
|
||||
_private->close();
|
||||
}
|
||||
|
||||
void WindowHelper::init() {
|
||||
rpl::combine(
|
||||
_window->sizeValue(),
|
||||
window()->sizeValue(),
|
||||
_title->heightValue(),
|
||||
_title->shownValue()
|
||||
) | rpl::start_with_next([=](QSize size, int titleHeight, bool shown) {
|
||||
|
|
@ -263,7 +402,7 @@ void WindowHelper::init() {
|
|||
}, _body->lifetime());
|
||||
}
|
||||
|
||||
std::unique_ptr<BasicWindowHelper> CreateWindowHelper(
|
||||
std::unique_ptr<BasicWindowHelper> CreateSpecialWindowHelper(
|
||||
not_null<RpWidget*> window) {
|
||||
return std::make_unique<WindowHelper>(window);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ public:
|
|||
void setText(const QString &text);
|
||||
void setStyle(const style::WindowTitle &st);
|
||||
[[nodiscard]] QString text() const;
|
||||
[[nodiscard]] bool shouldBeHidden() const;
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
|
|
|
|||
|
|
@ -38,6 +38,10 @@ void TitleWidget::setStyle(const style::WindowTitle &st) {
|
|||
update();
|
||||
}
|
||||
|
||||
bool TitleWidget::shouldBeHidden() const {
|
||||
return !_st->height;
|
||||
}
|
||||
|
||||
QString TitleWidget::text() const {
|
||||
return _text;
|
||||
}
|
||||
|
|
|
|||
125
ui/platform/ui_platform_window.cpp
Normal file
125
ui/platform/ui_platform_window.cpp
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
// This file is part of Desktop App Toolkit,
|
||||
// a set of libraries for developing nice desktop applications.
|
||||
//
|
||||
// For license and copyright information please follow this link:
|
||||
// https://github.com/desktop-app/legal/blob/master/LEGAL
|
||||
//
|
||||
#include "ui/platform/ui_platform_window.h"
|
||||
|
||||
#include "ui/widgets/window.h"
|
||||
|
||||
#include <QtGui/QWindow>
|
||||
#include <QtGui/QtEvents>
|
||||
|
||||
namespace Ui {
|
||||
namespace Platform {
|
||||
|
||||
BasicWindowHelper::BasicWindowHelper(not_null<RpWidget*> window)
|
||||
: _window(window) {
|
||||
}
|
||||
|
||||
not_null<RpWidget*> BasicWindowHelper::body() {
|
||||
return _window;
|
||||
}
|
||||
|
||||
void BasicWindowHelper::setTitle(const QString &title) {
|
||||
_window->setWindowTitle(title);
|
||||
}
|
||||
|
||||
void BasicWindowHelper::setTitleStyle(const style::WindowTitle &st) {
|
||||
}
|
||||
|
||||
void BasicWindowHelper::setMinimumSize(QSize size) {
|
||||
_window->setMinimumSize(size);
|
||||
}
|
||||
|
||||
void BasicWindowHelper::setFixedSize(QSize size) {
|
||||
_window->setFixedSize(size);
|
||||
}
|
||||
|
||||
void BasicWindowHelper::setGeometry(QRect rect) {
|
||||
_window->setGeometry(rect);
|
||||
}
|
||||
|
||||
void BasicWindowHelper::showFullScreen() {
|
||||
_window->showFullScreen();
|
||||
}
|
||||
|
||||
void BasicWindowHelper::showNormal() {
|
||||
_window->showNormal();
|
||||
}
|
||||
|
||||
void BasicWindowHelper::close() {
|
||||
_window->close();
|
||||
}
|
||||
|
||||
void BasicWindowHelper::setBodyTitleArea(
|
||||
Fn<WindowTitleHitTestFlags(QPoint)> testMethod) {
|
||||
Expects(!_bodyTitleAreaTestMethod);
|
||||
|
||||
if (!testMethod) {
|
||||
return;
|
||||
}
|
||||
_bodyTitleAreaTestMethod = std::move(testMethod);
|
||||
setupBodyTitleAreaEvents();
|
||||
}
|
||||
|
||||
void BasicWindowHelper::setupBodyTitleAreaEvents() {
|
||||
// This is not done on macOS, because startSystemMove
|
||||
// doesn't work from event handler there.
|
||||
body()->events() | rpl::start_with_next([=](not_null<QEvent*> e) {
|
||||
const auto hitTest = [&] {
|
||||
return bodyTitleAreaHit(
|
||||
static_cast<QMouseEvent*>(e.get())->pos());
|
||||
};
|
||||
if (e->type() == QEvent::MouseButtonDblClick) {
|
||||
_mousePressed = false;
|
||||
const auto hit = hitTest();
|
||||
if (hit & WindowTitleHitTestFlag::Maximize) {
|
||||
const auto state = _window->windowState();
|
||||
if (state & Qt::WindowMaximized) {
|
||||
_window->setWindowState(state & ~Qt::WindowMaximized);
|
||||
} else {
|
||||
_window->setWindowState(state | Qt::WindowMaximized);
|
||||
}
|
||||
} else if (hit & WindowTitleHitTestFlag::FullScreen) {
|
||||
if (_window->isFullScreen()) {
|
||||
showNormal();
|
||||
} else {
|
||||
showFullScreen();
|
||||
}
|
||||
}
|
||||
} else if (e->type() == QEvent::MouseButtonRelease) {
|
||||
_mousePressed = false;
|
||||
} else if (e->type() == QEvent::MouseButtonPress
|
||||
&& (static_cast<QMouseEvent*>(e.get())->button()
|
||||
== Qt::LeftButton)) {
|
||||
_mousePressed = true;
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) || defined DESKTOP_APP_QT_PATCHED
|
||||
} else if (e->type() == QEvent::MouseMove) {
|
||||
const auto mouseEvent = static_cast<QMouseEvent*>(e.get());
|
||||
if (_mousePressed
|
||||
#ifndef Q_OS_WIN // We handle fullscreen startSystemMove() only on Windows.
|
||||
&& !_window->isFullScreen()
|
||||
#endif // !Q_OS_WIN
|
||||
&& (hitTest() & WindowTitleHitTestFlag::Move)) {
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
if (_window->isFullScreen()) {
|
||||
// On Windows we just jump out of fullscreen
|
||||
// like we do automatically for dragging a window
|
||||
// by title bar in a maximized state.
|
||||
showNormal();
|
||||
}
|
||||
#endif // Q_OS_WIN
|
||||
_mousePressed = false;
|
||||
_window->windowHandle()->startSystemMove();
|
||||
}
|
||||
#endif // Qt >= 5.15 || DESKTOP_APP_QT_PATCHED
|
||||
}
|
||||
}, body()->lifetime());
|
||||
}
|
||||
|
||||
} // namespace Platform
|
||||
} // namespace Ui
|
||||
|
|
@ -6,6 +6,8 @@
|
|||
//
|
||||
#pragma once
|
||||
|
||||
#include "base/flags.h"
|
||||
|
||||
namespace style {
|
||||
struct WindowTitle;
|
||||
} // namespace style
|
||||
|
|
@ -13,23 +15,58 @@ struct WindowTitle;
|
|||
namespace Ui {
|
||||
|
||||
class RpWidget;
|
||||
enum class WindowTitleHitTestFlag;
|
||||
using WindowTitleHitTestFlags = base::flags<WindowTitleHitTestFlag>;
|
||||
|
||||
namespace Platform {
|
||||
|
||||
class BasicWindowHelper {
|
||||
public:
|
||||
[[nodiscard]] virtual not_null<RpWidget*> body() = 0;
|
||||
virtual void setTitle(const QString &title) = 0;
|
||||
virtual void setTitleStyle(const style::WindowTitle &st) = 0;
|
||||
virtual void setMinimumSize(QSize size) = 0;
|
||||
virtual void setFixedSize(QSize size) = 0;
|
||||
virtual void setGeometry(QRect rect) = 0;
|
||||
explicit BasicWindowHelper(not_null<RpWidget*> window);
|
||||
virtual ~BasicWindowHelper() = default;
|
||||
|
||||
[[nodiscard]] virtual not_null<RpWidget*> body();
|
||||
virtual void setTitle(const QString &title);
|
||||
virtual void setTitleStyle(const style::WindowTitle &st);
|
||||
virtual void setMinimumSize(QSize size);
|
||||
virtual void setFixedSize(QSize size);
|
||||
virtual void setGeometry(QRect rect);
|
||||
virtual void showFullScreen();
|
||||
virtual void showNormal();
|
||||
virtual void close();
|
||||
|
||||
void setBodyTitleArea(Fn<WindowTitleHitTestFlags(QPoint)> testMethod);
|
||||
|
||||
protected:
|
||||
[[nodiscard]] not_null<RpWidget*> window() const {
|
||||
return _window;
|
||||
}
|
||||
[[nodiscard]] WindowTitleHitTestFlags bodyTitleAreaHit(
|
||||
QPoint point) const {
|
||||
return _bodyTitleAreaTestMethod
|
||||
? _bodyTitleAreaTestMethod(point)
|
||||
: WindowTitleHitTestFlag();
|
||||
}
|
||||
|
||||
private:
|
||||
virtual void setupBodyTitleAreaEvents();
|
||||
|
||||
const not_null<RpWidget*> _window;
|
||||
Fn<WindowTitleHitTestFlags(QPoint)> _bodyTitleAreaTestMethod;
|
||||
bool _mousePressed = false;
|
||||
|
||||
};
|
||||
|
||||
[[nodiscard]] std::unique_ptr<BasicWindowHelper> CreateWindowHelper(
|
||||
[[nodiscard]] std::unique_ptr<BasicWindowHelper> CreateSpecialWindowHelper(
|
||||
not_null<RpWidget*> window);
|
||||
|
||||
[[nodiscard]] inline std::unique_ptr<BasicWindowHelper> CreateWindowHelper(
|
||||
not_null<RpWidget*> window) {
|
||||
if (auto special = CreateSpecialWindowHelper(window)) {
|
||||
return special;
|
||||
}
|
||||
return std::make_unique<BasicWindowHelper>(window);
|
||||
}
|
||||
|
||||
} // namespace Platform
|
||||
} // namespace Ui
|
||||
|
|
|
|||
|
|
@ -19,39 +19,60 @@
|
|||
namespace Ui {
|
||||
namespace Platform {
|
||||
|
||||
TitleWidget::TitleWidget(not_null<RpWidget*> parent)
|
||||
: RpWidget(parent)
|
||||
, _st(&st::defaultWindowTitle)
|
||||
, _minimize(this, _st->minimize)
|
||||
, _maximizeRestore(this, _st->maximize)
|
||||
, _close(this, _st->close)
|
||||
, _shadow(this, st::titleShadow)
|
||||
, _maximizedState(parent->windowState() & Qt::WindowMaximized)
|
||||
TitleControls::TitleControls(
|
||||
not_null<RpWidget*> parent,
|
||||
const style::WindowTitle &st,
|
||||
Fn<void(bool maximized)> maximize)
|
||||
: _st(&st)
|
||||
, _minimize(parent, _st->minimize)
|
||||
, _maximizeRestore(parent, _st->maximize)
|
||||
, _close(parent, _st->close)
|
||||
, _maximizedState(parent->windowState()
|
||||
& (Qt::WindowMaximized | Qt::WindowFullScreen))
|
||||
, _activeState(parent->isActiveWindow()) {
|
||||
init();
|
||||
}
|
||||
init(std::move(maximize));
|
||||
|
||||
void TitleWidget::setText(const QString &text) {
|
||||
window()->setWindowTitle(text);
|
||||
}
|
||||
|
||||
void TitleWidget::setStyle(const style::WindowTitle &st) {
|
||||
_st = &st;
|
||||
setGeometry(0, 0, window()->width(), _st->height);
|
||||
_close->paintRequest(
|
||||
) | rpl::start_with_next([=] {
|
||||
const auto active = window()->isActiveWindow();
|
||||
if (_activeState != active) {
|
||||
_activeState = active;
|
||||
updateButtonsState();
|
||||
update();
|
||||
}
|
||||
}, _close->lifetime());
|
||||
}
|
||||
|
||||
not_null<RpWidget*> TitleWidget::window() const {
|
||||
return static_cast<RpWidget*>(parentWidget());
|
||||
void TitleControls::setStyle(const style::WindowTitle &st) {
|
||||
_st = &st;
|
||||
updateButtonsState();
|
||||
}
|
||||
|
||||
void TitleWidget::setResizeEnabled(bool enabled) {
|
||||
_resizeEnabled = enabled;
|
||||
updateControlsVisibility();
|
||||
not_null<const style::WindowTitle*> TitleControls::st() const {
|
||||
return _st;
|
||||
}
|
||||
|
||||
void TitleWidget::init() {
|
||||
QRect TitleControls::geometry() const {
|
||||
auto result = QRect();
|
||||
const auto add = [&](auto &&control) {
|
||||
if (!control->isHidden()) {
|
||||
result = result.united(control->geometry());
|
||||
}
|
||||
};
|
||||
add(_minimize);
|
||||
add(_maximizeRestore);
|
||||
add(_close);
|
||||
return result;
|
||||
}
|
||||
|
||||
not_null<RpWidget*> TitleControls::parent() const {
|
||||
return static_cast<RpWidget*>(_close->parentWidget());
|
||||
}
|
||||
|
||||
not_null<QWidget*> TitleControls::window() const {
|
||||
return _close->window();
|
||||
}
|
||||
|
||||
void TitleControls::init(Fn<void(bool maximized)> maximize) {
|
||||
_minimize->setClickedCallback([=] {
|
||||
window()->setWindowState(
|
||||
window()->windowState() | Qt::WindowMinimized);
|
||||
|
|
@ -59,9 +80,13 @@ void TitleWidget::init() {
|
|||
});
|
||||
_minimize->setPointerCursor(false);
|
||||
_maximizeRestore->setClickedCallback([=] {
|
||||
if (maximize) {
|
||||
maximize(!_maximizedState);
|
||||
} else {
|
||||
window()->setWindowState(_maximizedState
|
||||
? Qt::WindowNoState
|
||||
: Qt::WindowMaximized);
|
||||
}
|
||||
_maximizeRestore->clearState();
|
||||
});
|
||||
_maximizeRestore->setPointerCursor(false);
|
||||
|
|
@ -71,32 +96,32 @@ void TitleWidget::init() {
|
|||
});
|
||||
_close->setPointerCursor(false);
|
||||
|
||||
setAttribute(Qt::WA_OpaquePaintEvent);
|
||||
|
||||
window()->widthValue(
|
||||
parent()->widthValue(
|
||||
) | rpl::start_with_next([=](int width) {
|
||||
setGeometry(0, 0, width, _st->height);
|
||||
}, lifetime());
|
||||
updateControlsPosition();
|
||||
}, _close->lifetime());
|
||||
|
||||
window()->createWinId();
|
||||
connect(
|
||||
QObject::connect(
|
||||
window()->windowHandle(),
|
||||
&QWindow::windowStateChanged,
|
||||
[=](Qt::WindowState state) { handleWindowStateChanged(state); });
|
||||
_activeState = isActiveWindow();
|
||||
_activeState = parent()->isActiveWindow();
|
||||
updateButtonsState();
|
||||
}
|
||||
|
||||
void TitleWidget::paintEvent(QPaintEvent *e) {
|
||||
const auto active = isActiveWindow();
|
||||
if (_activeState != active) {
|
||||
_activeState = active;
|
||||
updateButtonsState();
|
||||
}
|
||||
QPainter(this).fillRect(e->rect(), active ? _st->bgActive : _st->bg);
|
||||
void TitleControls::setResizeEnabled(bool enabled) {
|
||||
_resizeEnabled = enabled;
|
||||
updateControlsVisibility();
|
||||
}
|
||||
|
||||
void TitleWidget::updateControlsPosition() {
|
||||
void TitleControls::raise() {
|
||||
_minimize->raise();
|
||||
_maximizeRestore->raise();
|
||||
_close->raise();
|
||||
}
|
||||
|
||||
void TitleControls::updateControlsPosition() {
|
||||
auto right = 0;
|
||||
_close->moveToRight(right, 0); right += _close->width();
|
||||
_maximizeRestore->moveToRight(right, 0);
|
||||
|
|
@ -106,28 +131,25 @@ void TitleWidget::updateControlsPosition() {
|
|||
_minimize->moveToRight(right, 0);
|
||||
}
|
||||
|
||||
void TitleWidget::resizeEvent(QResizeEvent *e) {
|
||||
updateControlsPosition();
|
||||
_shadow->setGeometry(0, height() - st::lineWidth, width(), st::lineWidth);
|
||||
}
|
||||
|
||||
void TitleWidget::updateControlsVisibility() {
|
||||
void TitleControls::updateControlsVisibility() {
|
||||
_maximizeRestore->setVisible(_resizeEnabled);
|
||||
updateControlsPosition();
|
||||
update();
|
||||
}
|
||||
|
||||
void TitleWidget::handleWindowStateChanged(Qt::WindowState state) {
|
||||
if (state == Qt::WindowMinimized) return;
|
||||
void TitleControls::handleWindowStateChanged(Qt::WindowState state) {
|
||||
if (state == Qt::WindowMinimized) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto maximized = (state == Qt::WindowMaximized);
|
||||
auto maximized = (state == Qt::WindowMaximized)
|
||||
|| (state == Qt::WindowFullScreen);
|
||||
if (_maximizedState != maximized) {
|
||||
_maximizedState = maximized;
|
||||
updateButtonsState();
|
||||
}
|
||||
}
|
||||
|
||||
void TitleWidget::updateButtonsState() {
|
||||
void TitleControls::updateButtonsState() {
|
||||
const auto minimize = _activeState
|
||||
? &_st->minimizeIconActive
|
||||
: &_st->minimize.icon;
|
||||
|
|
@ -161,12 +183,45 @@ void TitleWidget::updateButtonsState() {
|
|||
_close->setIconOverride(close, closeOver);
|
||||
}
|
||||
|
||||
TitleWidget::TitleWidget(not_null<RpWidget*> parent)
|
||||
: RpWidget(parent)
|
||||
, _controls(this, st::defaultWindowTitle)
|
||||
, _shadow(this, st::titleShadow) {
|
||||
setAttribute(Qt::WA_OpaquePaintEvent);
|
||||
|
||||
parent->widthValue(
|
||||
) | rpl::start_with_next([=](int width) {
|
||||
setGeometry(0, 0, width, _controls.st()->height);
|
||||
}, lifetime());
|
||||
}
|
||||
|
||||
void TitleWidget::setText(const QString &text) {
|
||||
window()->setWindowTitle(text);
|
||||
}
|
||||
|
||||
void TitleWidget::setStyle(const style::WindowTitle &st) {
|
||||
_controls.setStyle(st);
|
||||
setGeometry(0, 0, window()->width(), _controls.st()->height);
|
||||
update();
|
||||
}
|
||||
|
||||
void TitleWidget::setResizeEnabled(bool enabled) {
|
||||
_controls.setResizeEnabled(enabled);
|
||||
}
|
||||
|
||||
void TitleWidget::paintEvent(QPaintEvent *e) {
|
||||
const auto active = window()->isActiveWindow();
|
||||
QPainter(this).fillRect(
|
||||
e->rect(),
|
||||
active ? _controls.st()->bgActive : _controls.st()->bg);
|
||||
}
|
||||
|
||||
void TitleWidget::resizeEvent(QResizeEvent *e) {
|
||||
_shadow->setGeometry(0, height() - st::lineWidth, width(), st::lineWidth);
|
||||
}
|
||||
|
||||
HitTestResult TitleWidget::hitTest(QPoint point) const {
|
||||
if (false
|
||||
|| (_minimize->geometry().contains(point))
|
||||
|| (_maximizeRestore->geometry().contains(point))
|
||||
|| (_close->geometry().contains(point))
|
||||
) {
|
||||
if (_controls.geometry().contains(point)) {
|
||||
return HitTestResult::SysButton;
|
||||
} else if (rect().contains(point)) {
|
||||
return HitTestResult::Caption;
|
||||
|
|
|
|||
|
|
@ -38,6 +38,41 @@ enum class HitTestResult {
|
|||
TopLeft,
|
||||
};
|
||||
|
||||
class TitleControls final {
|
||||
public:
|
||||
TitleControls(
|
||||
not_null<RpWidget*> parent,
|
||||
const style::WindowTitle &st,
|
||||
Fn<void(bool maximized)> maximize = nullptr);
|
||||
|
||||
void setStyle(const style::WindowTitle &st);
|
||||
[[nodiscard]] not_null<const style::WindowTitle*> st() const;
|
||||
[[nodiscard]] QRect geometry() const;
|
||||
void setResizeEnabled(bool enabled);
|
||||
void raise();
|
||||
|
||||
private:
|
||||
[[nodiscard]] not_null<RpWidget*> parent() const;
|
||||
[[nodiscard]] not_null<QWidget*> window() const;
|
||||
|
||||
void init(Fn<void(bool maximized)> maximize);
|
||||
void updateControlsVisibility();
|
||||
void updateButtonsState();
|
||||
void updateControlsPosition();
|
||||
void handleWindowStateChanged(Qt::WindowState state = Qt::WindowNoState);
|
||||
|
||||
not_null<const style::WindowTitle*> _st;
|
||||
|
||||
object_ptr<Ui::IconButton> _minimize;
|
||||
object_ptr<Ui::IconButton> _maximizeRestore;
|
||||
object_ptr<Ui::IconButton> _close;
|
||||
|
||||
bool _maximizedState = false;
|
||||
bool _activeState = false;
|
||||
bool _resizeEnabled = true;
|
||||
|
||||
};
|
||||
|
||||
class TitleWidget : public RpWidget {
|
||||
public:
|
||||
explicit TitleWidget(not_null<RpWidget*> parent);
|
||||
|
|
@ -52,25 +87,9 @@ protected:
|
|||
void resizeEvent(QResizeEvent *e) override;
|
||||
|
||||
private:
|
||||
not_null<RpWidget*> window() const;
|
||||
|
||||
void init();
|
||||
void handleWindowStateChanged(Qt::WindowState state = Qt::WindowNoState);
|
||||
void updateControlsVisibility();
|
||||
void updateButtonsState();
|
||||
void updateControlsPosition();
|
||||
|
||||
not_null<const style::WindowTitle*> _st;
|
||||
|
||||
object_ptr<Ui::IconButton> _minimize;
|
||||
object_ptr<Ui::IconButton> _maximizeRestore;
|
||||
object_ptr<Ui::IconButton> _close;
|
||||
TitleControls _controls;
|
||||
object_ptr<Ui::PlainShadow> _shadow;
|
||||
|
||||
bool _maximizedState = false;
|
||||
bool _activeState = false;
|
||||
bool _resizeEnabled = true;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Platform
|
||||
|
|
|
|||
|
|
@ -93,11 +93,11 @@ bool WindowHelper::NativeFilter::nativeEventFilter(
|
|||
}
|
||||
|
||||
WindowHelper::WindowHelper(not_null<RpWidget*> window)
|
||||
: _window(window)
|
||||
, _handle(GetWindowHandle(_window))
|
||||
, _title(Ui::CreateChild<TitleWidget>(_window.get()))
|
||||
, _body(Ui::CreateChild<RpWidget>(_window.get()))
|
||||
, _shadow(_window, st::windowShadowFg->c) {
|
||||
: BasicWindowHelper(window)
|
||||
, _handle(GetWindowHandle(window))
|
||||
, _title(Ui::CreateChild<TitleWidget>(window.get()))
|
||||
, _body(Ui::CreateChild<RpWidget>(window.get()))
|
||||
, _shadow(window, st::windowShadowFg->c) {
|
||||
Expects(_handle != nullptr);
|
||||
|
||||
GetNativeFilter()->registerWindow(_handle, this);
|
||||
|
|
@ -114,7 +114,7 @@ not_null<RpWidget*> WindowHelper::body() {
|
|||
|
||||
void WindowHelper::setTitle(const QString &title) {
|
||||
_title->setText(title);
|
||||
_window->setWindowTitle(title);
|
||||
window()->setWindowTitle(title);
|
||||
}
|
||||
|
||||
void WindowHelper::setTitleStyle(const style::WindowTitle &st) {
|
||||
|
|
@ -122,27 +122,43 @@ void WindowHelper::setTitleStyle(const style::WindowTitle &st) {
|
|||
}
|
||||
|
||||
void WindowHelper::setMinimumSize(QSize size) {
|
||||
_window->setMinimumSize(size.width(), _title->height() + size.height());
|
||||
window()->setMinimumSize(size.width(), _title->height() + size.height());
|
||||
}
|
||||
|
||||
void WindowHelper::setFixedSize(QSize size) {
|
||||
_window->setFixedSize(size.width(), _title->height() + size.height());
|
||||
window()->setFixedSize(size.width(), _title->height() + size.height());
|
||||
_title->setResizeEnabled(false);
|
||||
_shadow.setResizeEnabled(false);
|
||||
}
|
||||
|
||||
void WindowHelper::setGeometry(QRect rect) {
|
||||
_window->setGeometry(rect.marginsAdded({ 0, _title->height(), 0, 0 }));
|
||||
window()->setGeometry(rect.marginsAdded({ 0, _title->height(), 0, 0 }));
|
||||
}
|
||||
|
||||
void WindowHelper::showFullScreen() {
|
||||
if (!_isFullScreen) {
|
||||
_isFullScreen = true;
|
||||
updateMargins();
|
||||
}
|
||||
window()->showFullScreen();
|
||||
}
|
||||
|
||||
void WindowHelper::showNormal() {
|
||||
window()->showNormal();
|
||||
if (_isFullScreen) {
|
||||
_isFullScreen = false;
|
||||
updateMargins();
|
||||
}
|
||||
}
|
||||
|
||||
void WindowHelper::init() {
|
||||
style::PaletteChanged(
|
||||
) | rpl::start_with_next([=] {
|
||||
_shadow.setColor(st::windowShadowFg->c);
|
||||
}, _window->lifetime());
|
||||
}, window()->lifetime());
|
||||
|
||||
rpl::combine(
|
||||
_window->sizeValue(),
|
||||
window()->sizeValue(),
|
||||
_title->heightValue()
|
||||
) | rpl::start_with_next([=](QSize size, int titleHeight) {
|
||||
_body->setGeometry(
|
||||
|
|
@ -165,14 +181,14 @@ void WindowHelper::init() {
|
|||
const auto handleStateChanged = [=](Qt::WindowState state) {
|
||||
updateSystemMenu(state);
|
||||
if (fixedSize() && (state & Qt::WindowMaximized)) {
|
||||
crl::on_main(_window.get(), [=] {
|
||||
_window->setWindowState(
|
||||
_window->windowState() & ~Qt::WindowMaximized);
|
||||
crl::on_main(window().get(), [=] {
|
||||
window()->setWindowState(
|
||||
window()->windowState() & ~Qt::WindowMaximized);
|
||||
});
|
||||
}
|
||||
};
|
||||
Ui::Connect(
|
||||
_window->windowHandle(),
|
||||
window()->windowHandle(),
|
||||
&QWindow::windowStateChanged,
|
||||
handleStateChanged);
|
||||
}
|
||||
|
|
@ -186,14 +202,14 @@ bool WindowHelper::handleNativeEvent(
|
|||
|
||||
case WM_ACTIVATE: {
|
||||
if (LOWORD(wParam) == WA_CLICKACTIVE) {
|
||||
Ui::MarkInactivePress(_window, true);
|
||||
Ui::MarkInactivePress(window(), true);
|
||||
}
|
||||
if (LOWORD(wParam) != WA_INACTIVE) {
|
||||
_shadow.update(WindowShadow::Change::Activate);
|
||||
} else {
|
||||
_shadow.update(WindowShadow::Change::Deactivate);
|
||||
}
|
||||
_window->update();
|
||||
window()->update();
|
||||
} return false;
|
||||
|
||||
case WM_NCPAINT: {
|
||||
|
|
@ -267,14 +283,14 @@ bool WindowHelper::handleNativeEvent(
|
|||
|| wParam == SIZE_RESTORED
|
||||
|| wParam == SIZE_MINIMIZED) {
|
||||
if (wParam != SIZE_RESTORED
|
||||
|| _window->windowState() != Qt::WindowNoState) {
|
||||
|| window()->windowState() != Qt::WindowNoState) {
|
||||
Qt::WindowState state = Qt::WindowNoState;
|
||||
if (wParam == SIZE_MAXIMIZED) {
|
||||
state = Qt::WindowMaximized;
|
||||
} else if (wParam == SIZE_MINIMIZED) {
|
||||
state = Qt::WindowMinimized;
|
||||
}
|
||||
emit _window->windowHandle()->windowStateChanged(state);
|
||||
emit window()->windowHandle()->windowStateChanged(state);
|
||||
}
|
||||
updateMargins();
|
||||
const auto changes = (wParam == SIZE_MINIMIZED
|
||||
|
|
@ -310,7 +326,7 @@ bool WindowHelper::handleNativeEvent(
|
|||
const auto mapped = QPoint(
|
||||
p.x - r.left + _marginsDelta.left(),
|
||||
p.y - r.top + _marginsDelta.top());
|
||||
if (!_window->rect().contains(mapped)) {
|
||||
if (!window()->rect().contains(mapped)) {
|
||||
*result = HTTRANSPARENT;
|
||||
} else if (!_title->geometry().contains(mapped)) {
|
||||
*result = HTCLIENT;
|
||||
|
|
@ -338,7 +354,7 @@ bool WindowHelper::handleNativeEvent(
|
|||
case WM_SYSCOMMAND: {
|
||||
if (wParam == SC_MOUSEMENU && !fixedSize()) {
|
||||
POINTS p = MAKEPOINTS(lParam);
|
||||
updateSystemMenu(_window->windowHandle()->windowState());
|
||||
updateSystemMenu(window()->windowHandle()->windowState());
|
||||
TrackPopupMenu(
|
||||
_menu,
|
||||
TPM_LEFTALIGN | TPM_TOPALIGN | TPM_LEFTBUTTON,
|
||||
|
|
@ -357,19 +373,19 @@ bool WindowHelper::handleNativeEvent(
|
|||
const auto command = LOWORD(wParam);
|
||||
switch (command) {
|
||||
case SC_CLOSE:
|
||||
_window->close();
|
||||
window()->close();
|
||||
return true;
|
||||
case SC_MINIMIZE:
|
||||
_window->setWindowState(
|
||||
_window->windowState() | Qt::WindowMinimized);
|
||||
window()->setWindowState(
|
||||
window()->windowState() | Qt::WindowMinimized);
|
||||
return true;
|
||||
case SC_MAXIMIZE:
|
||||
if (!fixedSize()) {
|
||||
_window->setWindowState(Qt::WindowMaximized);
|
||||
window()->setWindowState(Qt::WindowMaximized);
|
||||
}
|
||||
return true;
|
||||
case SC_RESTORE:
|
||||
_window->setWindowState(Qt::WindowNoState);
|
||||
window()->setWindowState(Qt::WindowNoState);
|
||||
return true;
|
||||
}
|
||||
} return true;
|
||||
|
|
@ -379,7 +395,7 @@ bool WindowHelper::handleNativeEvent(
|
|||
}
|
||||
|
||||
bool WindowHelper::fixedSize() const {
|
||||
return _window->minimumSize() == _window->maximumSize();
|
||||
return window()->minimumSize() == window()->maximumSize();
|
||||
}
|
||||
|
||||
void WindowHelper::updateMargins() {
|
||||
|
|
@ -442,16 +458,19 @@ void WindowHelper::updateMargins() {
|
|||
_marginsDelta = QMargins();
|
||||
}
|
||||
|
||||
if (_isFullScreen) {
|
||||
margins = QMargins();
|
||||
}
|
||||
if (const auto native = QGuiApplication::platformNativeInterface()) {
|
||||
native->setWindowProperty(
|
||||
_window->windowHandle()->handle(),
|
||||
window()->windowHandle()->handle(),
|
||||
"WindowsCustomMargins",
|
||||
QVariant::fromValue<QMargins>(margins));
|
||||
}
|
||||
}
|
||||
|
||||
void WindowHelper::updateSystemMenu() {
|
||||
updateSystemMenu(_window->windowHandle()->windowState());
|
||||
updateSystemMenu(window()->windowHandle()->windowState());
|
||||
}
|
||||
|
||||
void WindowHelper::updateSystemMenu(Qt::WindowState state) {
|
||||
|
|
@ -518,7 +537,7 @@ HWND GetWindowHandle(not_null<RpWidget*> widget) {
|
|||
window));
|
||||
}
|
||||
|
||||
std::unique_ptr<BasicWindowHelper> CreateWindowHelper(
|
||||
std::unique_ptr<BasicWindowHelper> CreateSpecialWindowHelper(
|
||||
not_null<RpWidget*> window) {
|
||||
return std::make_unique<WindowHelper>(window);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@ public:
|
|||
void setMinimumSize(QSize size) override;
|
||||
void setFixedSize(QSize size) override;
|
||||
void setGeometry(QRect rect) override;
|
||||
void showFullScreen() override;
|
||||
void showNormal() override;
|
||||
|
||||
private:
|
||||
class NativeFilter;
|
||||
|
|
@ -45,7 +47,6 @@ private:
|
|||
|
||||
static not_null<NativeFilter*> GetNativeFilter();
|
||||
|
||||
const not_null<RpWidget*> _window;
|
||||
const HWND _handle = nullptr;
|
||||
const not_null<TitleWidget*> _title;
|
||||
const not_null<RpWidget*> _body;
|
||||
|
|
@ -53,6 +54,7 @@ private:
|
|||
bool _updatingMargins = false;
|
||||
QMargins _marginsDelta;
|
||||
HMENU _menu = nullptr;
|
||||
bool _isFullScreen = false;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -382,6 +382,7 @@ CallButton {
|
|||
angle: double;
|
||||
outerRadius: pixels;
|
||||
outerBg: color;
|
||||
label: FlatLabel;
|
||||
}
|
||||
|
||||
Menu {
|
||||
|
|
|
|||
|
|
@ -13,55 +13,56 @@ namespace Ui {
|
|||
Window::Window(QWidget *parent)
|
||||
: RpWidget(parent)
|
||||
, _helper(Platform::CreateWindowHelper(this)) {
|
||||
Expects(_helper != nullptr);
|
||||
|
||||
hide();
|
||||
}
|
||||
|
||||
Window::~Window() = default;
|
||||
|
||||
not_null<RpWidget*> Window::body() {
|
||||
return _helper ? _helper->body() : this;
|
||||
return _helper->body();
|
||||
}
|
||||
|
||||
not_null<const RpWidget*> Window::body() const {
|
||||
return _helper ? _helper->body().get() : this;
|
||||
return _helper->body().get();
|
||||
}
|
||||
|
||||
void Window::setTitle(const QString &title) {
|
||||
if (_helper) {
|
||||
_helper->setTitle(title);
|
||||
} else {
|
||||
setWindowTitle(title);
|
||||
}
|
||||
}
|
||||
|
||||
void Window::setTitleStyle(const style::WindowTitle &st) {
|
||||
if (_helper) {
|
||||
_helper->setTitleStyle(st);
|
||||
}
|
||||
}
|
||||
|
||||
void Window::setMinimumSize(QSize size) {
|
||||
if (_helper) {
|
||||
_helper->setMinimumSize(size);
|
||||
} else {
|
||||
RpWidget::setMinimumSize(size);
|
||||
}
|
||||
}
|
||||
|
||||
void Window::setFixedSize(QSize size) {
|
||||
if (_helper) {
|
||||
_helper->setFixedSize(size);
|
||||
} else {
|
||||
RpWidget::setFixedSize(size);
|
||||
}
|
||||
}
|
||||
|
||||
void Window::setGeometry(QRect rect) {
|
||||
if (_helper) {
|
||||
_helper->setGeometry(rect);
|
||||
} else {
|
||||
RpWidget::setGeometry(rect);
|
||||
}
|
||||
|
||||
void Window::showFullScreen() {
|
||||
_helper->showFullScreen();
|
||||
}
|
||||
|
||||
void Window::showNormal() {
|
||||
_helper->showNormal();
|
||||
}
|
||||
|
||||
void Window::close() {
|
||||
_helper->close();
|
||||
}
|
||||
|
||||
void Window::setBodyTitleArea(
|
||||
Fn<WindowTitleHitTestFlags(QPoint)> testMethod) {
|
||||
_helper->setBodyTitleArea(std::move(testMethod));
|
||||
}
|
||||
|
||||
} // namespace Ui
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "ui/rp_widget.h"
|
||||
#include "base/flags.h"
|
||||
|
||||
namespace style {
|
||||
struct WindowTitle;
|
||||
|
|
@ -17,6 +18,17 @@ namespace Platform {
|
|||
class BasicWindowHelper;
|
||||
} // namespace Platform
|
||||
|
||||
enum class WindowTitleHitTestFlag {
|
||||
None = 0x00,
|
||||
Move = 0x01,
|
||||
Maximize = 0x02,
|
||||
FullScreen = 0x04,
|
||||
};
|
||||
inline constexpr bool is_flag_type(WindowTitleHitTestFlag) {
|
||||
return true;
|
||||
}
|
||||
using WindowTitleHitTestFlags = base::flags<WindowTitleHitTestFlag>;
|
||||
|
||||
class Window : public RpWidget {
|
||||
public:
|
||||
explicit Window(QWidget *parent = nullptr);
|
||||
|
|
@ -30,6 +42,10 @@ public:
|
|||
void setMinimumSize(QSize size);
|
||||
void setFixedSize(QSize size);
|
||||
void setGeometry(QRect rect);
|
||||
void showFullScreen();
|
||||
void showNormal();
|
||||
void close();
|
||||
void setBodyTitleArea(Fn<WindowTitleHitTestFlags(QPoint)> testMethod);
|
||||
|
||||
private:
|
||||
const std::unique_ptr<Platform::BasicWindowHelper> _helper;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue