mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-17 22:57:11 +02:00
Switch MainWindow to Ui::RpWindow
This commit is contained in:
parent
4ef2d3b957
commit
1ebf27bfa1
29 changed files with 116 additions and 1933 deletions
|
@ -873,7 +873,6 @@ PRIVATE
|
|||
platform/linux/notifications_manager_linux.h
|
||||
platform/linux/specific_linux.cpp
|
||||
platform/linux/specific_linux.h
|
||||
platform/linux/window_title_linux.h
|
||||
platform/mac/file_utilities_mac.mm
|
||||
platform/mac/file_utilities_mac.h
|
||||
platform/mac/launcher_mac.mm
|
||||
|
@ -888,7 +887,6 @@ PRIVATE
|
|||
platform/mac/specific_mac_p.mm
|
||||
platform/mac/specific_mac_p.h
|
||||
platform/mac/window_title_mac.mm
|
||||
platform/mac/window_title_mac.h
|
||||
platform/mac/touchbar/items/mac_formatter_item.h
|
||||
platform/mac/touchbar/items/mac_formatter_item.mm
|
||||
platform/mac/touchbar/items/mac_pinned_chats_item.h
|
||||
|
@ -919,8 +917,6 @@ PRIVATE
|
|||
platform/win/notifications_manager_win.h
|
||||
platform/win/specific_win.cpp
|
||||
platform/win/specific_win.h
|
||||
platform/win/window_title_win.cpp
|
||||
platform/win/window_title_win.h
|
||||
platform/win/windows_app_user_model_id.cpp
|
||||
platform/win/windows_app_user_model_id.h
|
||||
platform/win/windows_dlls.cpp
|
||||
|
@ -1099,9 +1095,6 @@ PRIVATE
|
|||
window/window_session_controller.h
|
||||
window/window_slide_animation.cpp
|
||||
window/window_slide_animation.h
|
||||
window/window_title_qt.cpp
|
||||
window/window_title_qt.h
|
||||
window/window_title.h
|
||||
window/window_top_bar_wrap.h
|
||||
window/themes/window_theme.cpp
|
||||
window/themes/window_theme.h
|
||||
|
@ -1140,13 +1133,6 @@ PRIVATE
|
|||
stdafx.h
|
||||
)
|
||||
|
||||
if (NOT LINUX)
|
||||
remove_target_sources(Telegram ${src_loc}
|
||||
window/window_title_qt.cpp
|
||||
window/window_title_qt.h
|
||||
)
|
||||
endif()
|
||||
|
||||
if (DESKTOP_APP_DISABLE_DBUS_INTEGRATION)
|
||||
remove_target_sources(Telegram ${src_loc}
|
||||
platform/linux/linux_xdp_file_dialog.cpp
|
||||
|
|
|
@ -269,7 +269,7 @@ void Application::run() {
|
|||
|
||||
const auto currentGeometry = _window->widget()->geometry();
|
||||
_mediaView = std::make_unique<Media::View::OverlayWidget>();
|
||||
_window->widget()->setGeometry(currentGeometry);
|
||||
_window->widget()->Ui::RpWidget::setGeometry(currentGeometry);
|
||||
|
||||
DEBUG_LOG(("Application Info: showing."));
|
||||
_window->finishFirstShow();
|
||||
|
|
|
@ -41,7 +41,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "settings/settings_intro.h"
|
||||
#include "platform/platform_notifications_manager.h"
|
||||
#include "base/platform/base_platform_info.h"
|
||||
#include "ui/platform/ui_platform_utility.h"
|
||||
#include "base/call_delayed.h"
|
||||
#include "base/variant.h"
|
||||
#include "window/notifications_manager.h"
|
||||
|
@ -115,12 +114,7 @@ MainWindow::MainWindow(not_null<Window::Controller*> controller)
|
|||
}, lifetime());
|
||||
|
||||
setAttribute(Qt::WA_NoSystemBackground);
|
||||
|
||||
if (Ui::Platform::WindowExtentsSupported()) {
|
||||
setAttribute(Qt::WA_TranslucentBackground);
|
||||
} else {
|
||||
setAttribute(Qt::WA_OpaquePaintEvent);
|
||||
}
|
||||
setAttribute(Qt::WA_OpaquePaintEvent);
|
||||
}
|
||||
|
||||
void MainWindow::initHook() {
|
||||
|
@ -226,10 +220,8 @@ void MainWindow::applyInitialWorkMode() {
|
|||
|
||||
void MainWindow::finishFirstShow() {
|
||||
createTrayIconMenu();
|
||||
initShadows();
|
||||
applyInitialWorkMode();
|
||||
createGlobalMenu();
|
||||
firstShadowsUpdate();
|
||||
|
||||
windowDeactivateEvents(
|
||||
) | rpl::start_with_next([=] {
|
||||
|
@ -419,7 +411,7 @@ void MainWindow::showMainMenu() {
|
|||
|
||||
ensureLayerCreated();
|
||||
_layer->showMainMenu(
|
||||
object_ptr<Window::MainMenu>(this, sessionController()),
|
||||
object_ptr<Window::MainMenu>(body(), sessionController()),
|
||||
anim::type::normal);
|
||||
}
|
||||
|
||||
|
|
|
@ -21,128 +21,73 @@ using namespace KWayland::Client;
|
|||
namespace Platform {
|
||||
namespace internal {
|
||||
|
||||
class WaylandIntegration::Private : public QObject {
|
||||
public:
|
||||
Private();
|
||||
|
||||
[[nodiscard]] Registry ®istry() {
|
||||
return _registry;
|
||||
}
|
||||
|
||||
[[nodiscard]] XdgExporter *xdgExporter() {
|
||||
return _xdgExporter.get();
|
||||
}
|
||||
|
||||
[[nodiscard]] PlasmaShell *plasmaShell() {
|
||||
return _plasmaShell.get();
|
||||
}
|
||||
|
||||
[[nodiscard]] AppMenuManager *appMenuManager() {
|
||||
return _appMenuManager.get();
|
||||
}
|
||||
|
||||
[[nodiscard]] QEventLoop &interfacesLoop() {
|
||||
return _interfacesLoop;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool interfacesAnnounced() const {
|
||||
return _interfacesAnnounced;
|
||||
}
|
||||
|
||||
private:
|
||||
ConnectionThread _connection;
|
||||
ConnectionThread *_applicationConnection = nullptr;
|
||||
Registry _registry;
|
||||
Registry _applicationRegistry;
|
||||
std::unique_ptr<XdgExporter> _xdgExporter;
|
||||
std::unique_ptr<PlasmaShell> _plasmaShell;
|
||||
std::unique_ptr<AppMenuManager> _appMenuManager;
|
||||
QEventLoop _interfacesLoop;
|
||||
bool _interfacesAnnounced = false;
|
||||
struct WaylandIntegration::Private {
|
||||
std::unique_ptr<ConnectionThread> connection;
|
||||
Registry registry;
|
||||
std::unique_ptr<XdgExporter> xdgExporter;
|
||||
std::unique_ptr<PlasmaShell> plasmaShell;
|
||||
std::unique_ptr<AppMenuManager> appMenuManager;
|
||||
};
|
||||
|
||||
WaylandIntegration::Private::Private()
|
||||
: _applicationConnection(ConnectionThread::fromApplication(this)) {
|
||||
_applicationRegistry.create(_applicationConnection);
|
||||
_applicationRegistry.setup();
|
||||
|
||||
connect(
|
||||
_applicationConnection,
|
||||
&ConnectionThread::connectionDied,
|
||||
&_applicationRegistry,
|
||||
&Registry::destroy);
|
||||
|
||||
connect(&_connection, &ConnectionThread::connected, [=] {
|
||||
LOG(("Successfully connected to Wayland server at socket: %1")
|
||||
.arg(_connection.socketName()));
|
||||
|
||||
_registry.create(&_connection);
|
||||
_registry.setup();
|
||||
});
|
||||
|
||||
connect(
|
||||
&_connection,
|
||||
&ConnectionThread::connectionDied,
|
||||
&_registry,
|
||||
&Registry::destroy);
|
||||
|
||||
connect(&_registry, &Registry::interfacesAnnounced, [=] {
|
||||
_interfacesAnnounced = true;
|
||||
if (_interfacesLoop.isRunning()) {
|
||||
_interfacesLoop.quit();
|
||||
}
|
||||
});
|
||||
|
||||
connect(
|
||||
&_applicationRegistry,
|
||||
&Registry::exporterUnstableV2Announced,
|
||||
[=](uint name, uint version) {
|
||||
_xdgExporter = std::unique_ptr<XdgExporter>{
|
||||
_applicationRegistry.createXdgExporter(name, version),
|
||||
};
|
||||
|
||||
connect(
|
||||
_applicationConnection,
|
||||
&ConnectionThread::connectionDied,
|
||||
_xdgExporter.get(),
|
||||
&XdgExporter::destroy);
|
||||
});
|
||||
|
||||
connect(
|
||||
&_applicationRegistry,
|
||||
&Registry::plasmaShellAnnounced,
|
||||
[=](uint name, uint version) {
|
||||
_plasmaShell = std::unique_ptr<PlasmaShell>{
|
||||
_applicationRegistry.createPlasmaShell(name, version),
|
||||
};
|
||||
|
||||
connect(
|
||||
_applicationConnection,
|
||||
&ConnectionThread::connectionDied,
|
||||
_plasmaShell.get(),
|
||||
&PlasmaShell::destroy);
|
||||
});
|
||||
|
||||
connect(
|
||||
&_applicationRegistry,
|
||||
&Registry::appMenuAnnounced,
|
||||
[=](uint name, uint version) {
|
||||
_appMenuManager = std::unique_ptr<AppMenuManager>{
|
||||
_applicationRegistry.createAppMenuManager(name, version),
|
||||
};
|
||||
|
||||
connect(
|
||||
_applicationConnection,
|
||||
&ConnectionThread::connectionDied,
|
||||
_appMenuManager.get(),
|
||||
&AppMenuManager::destroy);
|
||||
});
|
||||
|
||||
_connection.initConnection();
|
||||
}
|
||||
|
||||
WaylandIntegration::WaylandIntegration()
|
||||
: _private(std::make_unique<Private>()) {
|
||||
_private->connection = std::unique_ptr<ConnectionThread>{
|
||||
ConnectionThread::fromApplication(),
|
||||
};
|
||||
|
||||
_private->registry.create(_private->connection.get());
|
||||
_private->registry.setup();
|
||||
|
||||
QObject::connect(
|
||||
_private->connection.get(),
|
||||
&ConnectionThread::connectionDied,
|
||||
&_private->registry,
|
||||
&Registry::destroy);
|
||||
|
||||
QObject::connect(
|
||||
&_private->registry,
|
||||
&Registry::exporterUnstableV2Announced,
|
||||
[=](uint name, uint version) {
|
||||
_private->xdgExporter = std::unique_ptr<XdgExporter>{
|
||||
_private->registry.createXdgExporter(name, version),
|
||||
};
|
||||
|
||||
QObject::connect(
|
||||
_private->connection.get(),
|
||||
&ConnectionThread::connectionDied,
|
||||
_private->xdgExporter.get(),
|
||||
&XdgExporter::destroy);
|
||||
});
|
||||
|
||||
QObject::connect(
|
||||
&_private->registry,
|
||||
&Registry::plasmaShellAnnounced,
|
||||
[=](uint name, uint version) {
|
||||
_private->plasmaShell = std::unique_ptr<PlasmaShell>{
|
||||
_private->registry.createPlasmaShell(name, version),
|
||||
};
|
||||
|
||||
QObject::connect(
|
||||
_private->connection.get(),
|
||||
&ConnectionThread::connectionDied,
|
||||
_private->plasmaShell.get(),
|
||||
&PlasmaShell::destroy);
|
||||
});
|
||||
|
||||
QObject::connect(
|
||||
&_private->registry,
|
||||
&Registry::appMenuAnnounced,
|
||||
[=](uint name, uint version) {
|
||||
_private->appMenuManager = std::unique_ptr<AppMenuManager>{
|
||||
_private->registry.createAppMenuManager(name, version),
|
||||
};
|
||||
|
||||
QObject::connect(
|
||||
_private->connection.get(),
|
||||
&ConnectionThread::connectionDied,
|
||||
_private->appMenuManager.get(),
|
||||
&AppMenuManager::destroy);
|
||||
});
|
||||
}
|
||||
|
||||
WaylandIntegration::~WaylandIntegration() = default;
|
||||
|
@ -153,20 +98,8 @@ WaylandIntegration *WaylandIntegration::Instance() {
|
|||
return &instance;
|
||||
}
|
||||
|
||||
void WaylandIntegration::waitForInterfaceAnnounce() {
|
||||
Expects(!_private->interfacesLoop().isRunning());
|
||||
if (!_private->interfacesAnnounced()) {
|
||||
_private->interfacesLoop().exec();
|
||||
}
|
||||
}
|
||||
|
||||
bool WaylandIntegration::supportsXdgDecoration() {
|
||||
return _private->registry().hasInterface(
|
||||
Registry::Interface::XdgDecorationUnstableV1);
|
||||
}
|
||||
|
||||
QString WaylandIntegration::nativeHandle(QWindow *window) {
|
||||
if (const auto exporter = _private->xdgExporter()) {
|
||||
if (const auto exporter = _private->xdgExporter.get()) {
|
||||
if (const auto surface = Surface::fromWindow(window)) {
|
||||
if (const auto exported = exporter->exportTopLevel(
|
||||
surface,
|
||||
|
@ -186,11 +119,11 @@ QString WaylandIntegration::nativeHandle(QWindow *window) {
|
|||
}
|
||||
|
||||
bool WaylandIntegration::skipTaskbarSupported() {
|
||||
return _private->plasmaShell();
|
||||
return _private->plasmaShell != nullptr;
|
||||
}
|
||||
|
||||
void WaylandIntegration::skipTaskbar(QWindow *window, bool skip) {
|
||||
const auto shell = _private->plasmaShell();
|
||||
const auto shell = _private->plasmaShell.get();
|
||||
if (!shell) {
|
||||
return;
|
||||
}
|
||||
|
@ -212,7 +145,7 @@ void WaylandIntegration::registerAppMenu(
|
|||
QWindow *window,
|
||||
const QString &serviceName,
|
||||
const QString &objectPath) {
|
||||
const auto manager = _private->appMenuManager();
|
||||
const auto manager = _private->appMenuManager.get();
|
||||
if (!manager) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -13,8 +13,7 @@ namespace internal {
|
|||
class WaylandIntegration {
|
||||
public:
|
||||
[[nodiscard]] static WaylandIntegration *Instance();
|
||||
void waitForInterfaceAnnounce();
|
||||
[[nodiscard]] bool supportsXdgDecoration();
|
||||
|
||||
[[nodiscard]] QString nativeHandle(QWindow *window);
|
||||
[[nodiscard]] bool skipTaskbarSupported();
|
||||
void skipTaskbar(QWindow *window, bool skip);
|
||||
|
@ -27,7 +26,7 @@ private:
|
|||
WaylandIntegration();
|
||||
~WaylandIntegration();
|
||||
|
||||
class Private;
|
||||
struct Private;
|
||||
const std::unique_ptr<Private> _private;
|
||||
};
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
namespace Platform {
|
||||
namespace internal {
|
||||
|
||||
class WaylandIntegration::Private {
|
||||
struct WaylandIntegration::Private {
|
||||
};
|
||||
|
||||
WaylandIntegration::WaylandIntegration() {
|
||||
|
@ -26,13 +26,6 @@ WaylandIntegration *WaylandIntegration::Instance() {
|
|||
return &instance;
|
||||
}
|
||||
|
||||
void WaylandIntegration::waitForInterfaceAnnounce() {
|
||||
}
|
||||
|
||||
bool WaylandIntegration::supportsXdgDecoration() {
|
||||
return false;
|
||||
}
|
||||
|
||||
QString WaylandIntegration::nativeHandle(QWindow *window) {
|
||||
return {};
|
||||
}
|
||||
|
|
|
@ -971,7 +971,6 @@ void MainWindow::workmodeUpdated(Core::Settings::WorkMode mode) {
|
|||
}
|
||||
|
||||
void MainWindow::unreadCounterChangedHook() {
|
||||
setWindowTitle(titleText());
|
||||
updateIconCounters();
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "base/platform/base_platform_info.h"
|
||||
#include "base/platform/linux/base_linux_glibmm_helper.h"
|
||||
#include "base/platform/linux/base_linux_gtk_integration.h"
|
||||
#include "ui/platform/linux/ui_linux_wayland_integration.h"
|
||||
#include "platform/linux/linux_desktop_environment.h"
|
||||
#include "platform/linux/linux_gtk_integration.h"
|
||||
#include "platform/linux/linux_wayland_integration.h"
|
||||
|
@ -60,6 +61,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
using namespace Platform;
|
||||
using BaseGtkIntegration = base::Platform::GtkIntegration;
|
||||
using UiWaylandIntegration = Ui::Platform::WaylandIntegration;
|
||||
using Platform::internal::WaylandIntegration;
|
||||
using Platform::internal::GtkIntegration;
|
||||
|
||||
|
@ -799,7 +801,7 @@ void start() {
|
|||
}
|
||||
|
||||
// wait for interface announce to know if native window frame is supported
|
||||
if (const auto integration = WaylandIntegration::Instance()) {
|
||||
if (const auto integration = UiWaylandIntegration::Instance()) {
|
||||
integration->waitForInterfaceAnnounce();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,47 +0,0 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "platform/platform_window_title.h"
|
||||
#include "platform/linux/linux_wayland_integration.h"
|
||||
#include "base/object_ptr.h"
|
||||
|
||||
namespace Window {
|
||||
namespace Theme {
|
||||
|
||||
int DefaultPreviewTitleHeight();
|
||||
void DefaultPreviewWindowFramePaint(QImage &preview, const style::palette &palette, QRect body, int outerWidth);
|
||||
|
||||
} // namespace Theme
|
||||
} // namespace Window
|
||||
|
||||
namespace Platform {
|
||||
|
||||
inline bool AllowNativeWindowFrameToggle() {
|
||||
const auto waylandIntegration = internal::WaylandIntegration::Instance();
|
||||
return !waylandIntegration
|
||||
|| waylandIntegration->supportsXdgDecoration();
|
||||
}
|
||||
|
||||
inline object_ptr<Window::TitleWidget> CreateTitleWidget(QWidget *parent) {
|
||||
return object_ptr<Window::TitleWidgetQt>(parent);
|
||||
}
|
||||
|
||||
inline bool NativeTitleRequiresShadow() {
|
||||
return false;
|
||||
}
|
||||
|
||||
inline int PreviewTitleHeight() {
|
||||
return Window::Theme::DefaultPreviewTitleHeight();
|
||||
}
|
||||
|
||||
inline void PreviewWindowFramePaint(QImage &preview, const style::palette &palette, QRect body, int outerWidth) {
|
||||
return Window::Theme::DefaultPreviewWindowFramePaint(preview, palette, body, outerWidth);
|
||||
}
|
||||
|
||||
} // namespace Platform
|
|
@ -62,7 +62,6 @@ protected:
|
|||
void handleActiveChangedHook() override;
|
||||
void stateChangedHook(Qt::WindowState state) override;
|
||||
void initHook() override;
|
||||
void titleVisibilityChangedHook() override;
|
||||
void unreadCounterChangedHook() override;
|
||||
|
||||
bool hasTrayIcon() const override {
|
||||
|
@ -80,9 +79,6 @@ protected:
|
|||
void psSetupTrayIcon();
|
||||
virtual void placeSmallCounter(QImage &img, int size, int count, style::color bg, const QPoint &shift, style::color color) = 0;
|
||||
|
||||
QTimer psUpdatedPositionTimer;
|
||||
|
||||
void initShadows() override;
|
||||
void closeWithoutDestroy() override;
|
||||
void createGlobalMenu() override;
|
||||
|
||||
|
@ -90,7 +86,6 @@ private:
|
|||
friend class Private;
|
||||
|
||||
void hideAndDeactivate();
|
||||
void updateTitleCounter();
|
||||
void updateIconCounters();
|
||||
[[nodiscard]] QIcon generateIconForTray(int counter, bool muted) const;
|
||||
|
||||
|
|
|
@ -53,9 +53,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
- (void) darkModeChanged:(NSNotification *)aNotification;
|
||||
- (void) screenIsLocked:(NSNotification *)aNotification;
|
||||
- (void) screenIsUnlocked:(NSNotification *)aNotification;
|
||||
- (void) windowWillEnterFullScreen:(NSNotification *)aNotification;
|
||||
- (void) windowWillExitFullScreen:(NSNotification *)aNotification;
|
||||
- (void) windowDidExitFullScreen:(NSNotification *)aNotification;
|
||||
|
||||
@end // @interface MainWindowObserver
|
||||
|
||||
|
@ -67,43 +64,6 @@ namespace {
|
|||
// fullscreen mode, after that we'll hide the window no matter what.
|
||||
constexpr auto kHideAfterFullscreenTimeoutMs = 3000;
|
||||
|
||||
id FindClassInSubviews(NSView *parent, NSString *className) {
|
||||
for (NSView *child in [parent subviews]) {
|
||||
if ([child isKindOfClass:NSClassFromString(className)]) {
|
||||
return child;
|
||||
} else if (id inchild = FindClassInSubviews(child, className)) {
|
||||
return inchild;
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
#ifndef OS_MAC_OLD
|
||||
|
||||
class LayerCreationChecker : public QObject {
|
||||
public:
|
||||
LayerCreationChecker(NSView * __weak view, Fn<void()> callback)
|
||||
: _weakView(view)
|
||||
, _callback(std::move(callback)) {
|
||||
QCoreApplication::instance()->installEventFilter(this);
|
||||
}
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject *object, QEvent *event) override {
|
||||
if (!_weakView || [_weakView layer] != nullptr) {
|
||||
_callback();
|
||||
}
|
||||
return QObject::eventFilter(object, event);
|
||||
}
|
||||
|
||||
private:
|
||||
NSView * __weak _weakView = nil;
|
||||
Fn<void()> _callback;
|
||||
|
||||
};
|
||||
|
||||
#endif // OS_MAC_OLD
|
||||
|
||||
[[nodiscard]] QImage TrayIconBack(bool darkMode) {
|
||||
static const auto WithColor = [](QColor color) {
|
||||
return st::macTrayIcon.instance(color, 100);
|
||||
|
@ -127,38 +87,16 @@ public:
|
|||
not_null<Window::Controller*> controller,
|
||||
rpl::producer<bool> canApplyMarkdown);
|
||||
void setWindowBadge(const QString &str);
|
||||
void setWindowTitle(const QString &str);
|
||||
void updateNativeTitle();
|
||||
|
||||
void enableShadow(WId winId);
|
||||
|
||||
void willEnterFullScreen();
|
||||
void willExitFullScreen();
|
||||
void didExitFullScreen();
|
||||
|
||||
bool clipboardHasText();
|
||||
~Private();
|
||||
|
||||
private:
|
||||
void initCustomTitle();
|
||||
void refreshWeakTitleReferences();
|
||||
void enforceCorrectStyleMask();
|
||||
|
||||
not_null<MainWindow*> _public;
|
||||
friend class MainWindow;
|
||||
|
||||
#ifdef OS_MAC_OLD
|
||||
NSWindow *_nativeWindow = nil;
|
||||
NSView *_nativeView = nil;
|
||||
#else // OS_MAC_OLD
|
||||
NSWindow * __weak _nativeWindow = nil;
|
||||
NSView * __weak _nativeView = nil;
|
||||
id __weak _nativeTitleWrapWeak = nil;
|
||||
id __weak _nativeTitleWeak = nil;
|
||||
std::unique_ptr<LayerCreationChecker> _layerCreationChecker;
|
||||
#endif // !OS_MAC_OLD
|
||||
bool _useNativeTitle = false;
|
||||
bool _inFullScreen = false;
|
||||
|
||||
MainWindowObserver *_observer = nullptr;
|
||||
NSPasteboard *_generalPasteboard = nullptr;
|
||||
|
@ -198,18 +136,6 @@ private:
|
|||
Core::App().setScreenIsLocked(false);
|
||||
}
|
||||
|
||||
- (void) windowWillEnterFullScreen:(NSNotification *)aNotification {
|
||||
_private->willEnterFullScreen();
|
||||
}
|
||||
|
||||
- (void) windowWillExitFullScreen:(NSNotification *)aNotification {
|
||||
_private->willExitFullScreen();
|
||||
}
|
||||
|
||||
- (void) windowDidExitFullScreen:(NSNotification *)aNotification {
|
||||
_private->didExitFullScreen();
|
||||
}
|
||||
|
||||
@end // @implementation MainWindowObserver
|
||||
|
||||
namespace Platform {
|
||||
|
@ -256,15 +182,12 @@ void MainWindow::Private::setWindowBadge(const QString &str) {
|
|||
}
|
||||
}
|
||||
|
||||
void MainWindow::Private::setWindowTitle(const QString &str) {
|
||||
_public->setWindowTitle(str);
|
||||
updateNativeTitle();
|
||||
}
|
||||
|
||||
void MainWindow::Private::setNativeWindow(NSWindow *window, NSView *view) {
|
||||
_nativeWindow = window;
|
||||
_nativeView = view;
|
||||
initCustomTitle();
|
||||
auto inner = [_nativeWindow contentLayoutRect];
|
||||
auto full = [_nativeView frame];
|
||||
_public->_customTitleHeight = qMax(qRound(full.size.height - inner.size.height), 0);
|
||||
}
|
||||
|
||||
void MainWindow::Private::initTouchBar(
|
||||
|
@ -288,119 +211,6 @@ void MainWindow::Private::initTouchBar(
|
|||
#endif
|
||||
}
|
||||
|
||||
void MainWindow::Private::initCustomTitle() {
|
||||
#ifndef OS_MAC_OLD
|
||||
if (![_nativeWindow respondsToSelector:@selector(contentLayoutRect)]
|
||||
|| ![_nativeWindow respondsToSelector:@selector(setTitlebarAppearsTransparent:)]) {
|
||||
return;
|
||||
}
|
||||
[_nativeWindow setTitlebarAppearsTransparent:YES];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:_observer selector:@selector(windowWillEnterFullScreen:) name:NSWindowWillEnterFullScreenNotification object:_nativeWindow];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:_observer selector:@selector(windowWillExitFullScreen:) name:NSWindowWillExitFullScreenNotification object:_nativeWindow];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:_observer selector:@selector(windowDidExitFullScreen:) name:NSWindowDidExitFullScreenNotification object:_nativeWindow];
|
||||
|
||||
// Qt has bug with layer-backed widgets containing QOpenGLWidgets.
|
||||
// See https://bugreports.qt.io/browse/QTBUG-64494
|
||||
// Emulate custom title instead (code below).
|
||||
//
|
||||
// Tried to backport a fix, testing.
|
||||
[_nativeWindow setStyleMask:[_nativeWindow styleMask] | NSFullSizeContentViewWindowMask];
|
||||
auto inner = [_nativeWindow contentLayoutRect];
|
||||
auto full = [_nativeView frame];
|
||||
_public->_customTitleHeight = qMax(qRound(full.size.height - inner.size.height), 0);
|
||||
|
||||
// Qt still has some bug with layer-backed widgets containing QOpenGLWidgets.
|
||||
// See https://github.com/telegramdesktop/tdesktop/issues/4150
|
||||
// Tried to workaround it by catching the first moment we have CALayer created
|
||||
// and explicitly setting contentsScale to window->backingScaleFactor there.
|
||||
_layerCreationChecker = std::make_unique<LayerCreationChecker>(_nativeView, [=] {
|
||||
if (_nativeView && _nativeWindow) {
|
||||
if (CALayer *layer = [_nativeView layer]) {
|
||||
LOG(("Window Info: Setting layer scale factor to: %1").arg([_nativeWindow backingScaleFactor]));
|
||||
[layer setContentsScale: [_nativeWindow backingScaleFactor]];
|
||||
_layerCreationChecker = nullptr;
|
||||
}
|
||||
} else {
|
||||
_layerCreationChecker = nullptr;
|
||||
}
|
||||
});
|
||||
|
||||
// Disabled for now.
|
||||
//_useNativeTitle = true;
|
||||
//setWindowTitle(qsl("Telegram"));
|
||||
#endif // !OS_MAC_OLD
|
||||
}
|
||||
|
||||
void MainWindow::Private::refreshWeakTitleReferences() {
|
||||
if (!_nativeWindow) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef OS_MAC_OLD
|
||||
@autoreleasepool {
|
||||
|
||||
if (NSView *parent = [[_nativeWindow contentView] superview]) {
|
||||
if (id titleWrap = FindClassInSubviews(parent, Q2NSString(strTitleWrapClass()))) {
|
||||
if ([titleWrap respondsToSelector:@selector(setBackgroundColor:)]) {
|
||||
if (id title = FindClassInSubviews(titleWrap, Q2NSString(strTitleClass()))) {
|
||||
if ([title respondsToSelector:@selector(setAttributedStringValue:)]) {
|
||||
_nativeTitleWrapWeak = titleWrap;
|
||||
_nativeTitleWeak = title;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#endif // !OS_MAC_OLD
|
||||
}
|
||||
|
||||
void MainWindow::Private::updateNativeTitle() {
|
||||
if (!_useNativeTitle) {
|
||||
return;
|
||||
}
|
||||
#ifndef OS_MAC_OLD
|
||||
if (!_nativeTitleWrapWeak || !_nativeTitleWeak) {
|
||||
refreshWeakTitleReferences();
|
||||
}
|
||||
if (_nativeTitleWrapWeak && _nativeTitleWeak) {
|
||||
@autoreleasepool {
|
||||
|
||||
auto convertColor = [](QColor color) {
|
||||
return [NSColor colorWithDeviceRed:color.redF() green:color.greenF() blue:color.blueF() alpha:color.alphaF()];
|
||||
};
|
||||
auto adjustFg = [](const style::color &st) {
|
||||
// Weird thing with NSTextField taking NSAttributedString with
|
||||
// NSForegroundColorAttributeName set to colorWithDeviceRed:green:blue
|
||||
// with components all equal to 128 - it ignores it and prints black text!
|
||||
auto color = st->c;
|
||||
return (color.red() == 128 && color.green() == 128 && color.blue() == 128)
|
||||
? QColor(129, 129, 129, color.alpha())
|
||||
: color;
|
||||
};
|
||||
|
||||
auto active = _public->isActiveWindow();
|
||||
auto bgColor = (active ? st::titleBgActive : st::titleBg)->c;
|
||||
auto fgColor = adjustFg(active ? st::titleFgActive : st::titleFg);
|
||||
|
||||
auto bgConverted = convertColor(bgColor);
|
||||
auto fgConverted = convertColor(fgColor);
|
||||
[_nativeTitleWrapWeak setBackgroundColor:bgConverted];
|
||||
|
||||
auto title = Q2NSString(_public->windowTitle());
|
||||
NSDictionary *attributes = _inFullScreen
|
||||
? nil
|
||||
: [NSDictionary dictionaryWithObjectsAndKeys: fgConverted, NSForegroundColorAttributeName, bgConverted, NSBackgroundColorAttributeName, nil];
|
||||
NSAttributedString *string = [[NSAttributedString alloc] initWithString:title attributes:attributes];
|
||||
[_nativeTitleWeak setAttributedStringValue:string];
|
||||
|
||||
}
|
||||
}
|
||||
#endif // !OS_MAC_OLD
|
||||
}
|
||||
|
||||
bool MainWindow::Private::clipboardHasText() {
|
||||
auto currentChangeCount = static_cast<int>([_generalPasteboard changeCount]);
|
||||
if (_generalPasteboardChangeCount != currentChangeCount) {
|
||||
|
@ -410,32 +220,6 @@ bool MainWindow::Private::clipboardHasText() {
|
|||
return _generalPasteboardHasText;
|
||||
}
|
||||
|
||||
void MainWindow::Private::willEnterFullScreen() {
|
||||
_inFullScreen = true;
|
||||
_public->setTitleVisible(false);
|
||||
}
|
||||
|
||||
void MainWindow::Private::willExitFullScreen() {
|
||||
_inFullScreen = false;
|
||||
_public->setTitleVisible(true);
|
||||
enforceCorrectStyleMask();
|
||||
}
|
||||
|
||||
void MainWindow::Private::didExitFullScreen() {
|
||||
enforceCorrectStyleMask();
|
||||
}
|
||||
|
||||
void MainWindow::Private::enforceCorrectStyleMask() {
|
||||
if (_nativeWindow && _public->_customTitleHeight > 0) {
|
||||
[_nativeWindow setStyleMask:[_nativeWindow styleMask] | NSFullSizeContentViewWindowMask];
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::Private::enableShadow(WId winId) {
|
||||
// [[(NSView*)winId window] setStyleMask:NSBorderlessWindowMask];
|
||||
// [[(NSView*)winId window] setHasShadow:YES];
|
||||
}
|
||||
|
||||
MainWindow::Private::~Private() {
|
||||
[_observer release];
|
||||
}
|
||||
|
@ -449,11 +233,6 @@ MainWindow::MainWindow(not_null<Window::Controller*> controller)
|
|||
#endif // !OS_MAC_OLD
|
||||
|
||||
_hideAfterFullScreenTimer.setCallback([this] { hideAndDeactivate(); });
|
||||
|
||||
style::PaletteChanged(
|
||||
) | rpl::start_with_next([=] {
|
||||
_private->updateNativeTitle();
|
||||
}, lifetime());
|
||||
}
|
||||
|
||||
void MainWindow::closeWithoutDestroy() {
|
||||
|
@ -475,8 +254,6 @@ void MainWindow::stateChangedHook(Qt::WindowState state) {
|
|||
}
|
||||
|
||||
void MainWindow::handleActiveChangedHook() {
|
||||
InvokeQueued(this, [this] { _private->updateNativeTitle(); });
|
||||
|
||||
// On macOS just remove trayIcon menu if the window is not active.
|
||||
// So we will activate the window on click instead of showing the menu.
|
||||
if (isActiveForTrayMenu()) {
|
||||
|
@ -506,10 +283,6 @@ void MainWindow::initHook() {
|
|||
void MainWindow::updateWindowIcon() {
|
||||
}
|
||||
|
||||
void MainWindow::titleVisibilityChangedHook() {
|
||||
updateTitleCounter();
|
||||
}
|
||||
|
||||
void MainWindow::hideAndDeactivate() {
|
||||
hide();
|
||||
}
|
||||
|
@ -591,12 +364,7 @@ void _placeCounter(QImage &img, int size, int count, style::color bg, style::col
|
|||
img.setDevicePixelRatio(savedRatio);
|
||||
}
|
||||
|
||||
void MainWindow::updateTitleCounter() {
|
||||
_private->setWindowTitle(titleVisible() ? QString() : titleText());
|
||||
}
|
||||
|
||||
void MainWindow::unreadCounterChangedHook() {
|
||||
updateTitleCounter();
|
||||
updateIconCounters();
|
||||
}
|
||||
|
||||
|
@ -649,10 +417,6 @@ QIcon MainWindow::generateIconForTray(int counter, bool muted) const {
|
|||
return result;
|
||||
}
|
||||
|
||||
void MainWindow::initShadows() {
|
||||
_private->enableShadow(winId());
|
||||
}
|
||||
|
||||
void MainWindow::createGlobalMenu() {
|
||||
const auto ensureWindowShown = [=] {
|
||||
if (isHidden()) {
|
||||
|
|
|
@ -1,48 +0,0 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "platform/platform_window_title.h"
|
||||
|
||||
namespace Ui {
|
||||
class PlainShadow;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Platform {
|
||||
|
||||
class MainWindow;
|
||||
|
||||
class TitleWidget : public Window::TitleWidget {
|
||||
public:
|
||||
TitleWidget(MainWindow *parent, int height);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
void resizeEvent(QResizeEvent *e) override;
|
||||
void mouseDoubleClickEvent(QMouseEvent *e) override;
|
||||
|
||||
private:
|
||||
object_ptr<Ui::PlainShadow> _shadow;
|
||||
QFont _font;
|
||||
|
||||
};
|
||||
|
||||
inline bool AllowNativeWindowFrameToggle() {
|
||||
return false;
|
||||
}
|
||||
|
||||
object_ptr<Window::TitleWidget> CreateTitleWidget(QWidget *parent);
|
||||
|
||||
inline bool NativeTitleRequiresShadow() {
|
||||
return false;
|
||||
}
|
||||
|
||||
int PreviewTitleHeight();
|
||||
void PreviewWindowFramePaint(QImage &preview, const style::palette &palette, QRect body, int outerWidth);
|
||||
|
||||
} // namespace Platform
|
|
@ -5,83 +5,18 @@ the official desktop application for the Telegram messaging service.
|
|||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#include "platform/mac/window_title_mac.h"
|
||||
#include "platform/platform_window_title.h"
|
||||
|
||||
#include "mainwindow.h"
|
||||
#include "ui/widgets/shadow.h"
|
||||
#include "ui/image/image_prepare.h"
|
||||
#include "core/application.h"
|
||||
#include "styles/style_window.h"
|
||||
#include "styles/style_media_view.h"
|
||||
#include "platform/platform_main_window.h"
|
||||
#include "window/window_controller.h"
|
||||
|
||||
#include <Cocoa/Cocoa.h>
|
||||
#include <CoreFoundation/CFURL.h>
|
||||
|
||||
namespace Platform {
|
||||
|
||||
TitleWidget::TitleWidget(MainWindow *parent, int height)
|
||||
: Window::TitleWidget(parent)
|
||||
, _shadow(this, st::titleShadow) {
|
||||
setAttribute(Qt::WA_OpaquePaintEvent);
|
||||
resize(width(), height);
|
||||
|
||||
#ifndef OS_MAC_OLD
|
||||
QStringList families = { qsl(".SF NS Text"), qsl("Helvetica Neue") };
|
||||
for (auto family : families) {
|
||||
_font.setFamily(family);
|
||||
if (QFontInfo(_font).family() == _font.family()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif // OS_MAC_OLD
|
||||
|
||||
if (QFontInfo(_font).family() == _font.family()) {
|
||||
_font.setPixelSize((height * 15) / 24);
|
||||
} else {
|
||||
_font = st::normalFont;
|
||||
}
|
||||
|
||||
Core::App().unreadBadgeChanges(
|
||||
) | rpl::start_with_next([=] {
|
||||
update();
|
||||
}, lifetime());
|
||||
}
|
||||
|
||||
void TitleWidget::paintEvent(QPaintEvent *e) {
|
||||
Painter p(this);
|
||||
|
||||
auto active = isActiveWindow();
|
||||
p.fillRect(rect(), active ? st::titleBgActive : st::titleBg);
|
||||
|
||||
p.setFont(_font);
|
||||
p.setPen(active ? st::titleFgActive : st::titleFg);
|
||||
p.drawText(rect(), static_cast<MainWindow*>(parentWidget())->titleText(), style::al_center);
|
||||
}
|
||||
|
||||
void TitleWidget::resizeEvent(QResizeEvent *e) {
|
||||
_shadow->setGeometry(0, height() - st::lineWidth, width(), st::lineWidth);
|
||||
}
|
||||
|
||||
void TitleWidget::mouseDoubleClickEvent(QMouseEvent *e) {
|
||||
auto window = parentWidget();
|
||||
if (window->windowState() == Qt::WindowMaximized) {
|
||||
window->setWindowState(Qt::WindowNoState);
|
||||
} else {
|
||||
window->setWindowState(Qt::WindowMaximized);
|
||||
}
|
||||
}
|
||||
|
||||
object_ptr<Window::TitleWidget> CreateTitleWidget(QWidget *parent) {
|
||||
if (auto window = qobject_cast<Platform::MainWindow*>(parent)) {
|
||||
if (auto height = window->getCustomTitleHeight()) {
|
||||
return object_ptr<TitleWidget>(window, height);
|
||||
}
|
||||
}
|
||||
return { nullptr };
|
||||
}
|
||||
|
||||
// All the window decorations preview is done without taking cScale() into
|
||||
// account, with 100% scale and without "px" dimensions, because thats
|
||||
// how it will look in real launched macOS app.
|
||||
|
|
|
@ -7,16 +7,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include "window/window_title.h"
|
||||
#include "window/window_title_qt.h"
|
||||
#include "window/themes/window_theme_preview.h"
|
||||
#include "base/object_ptr.h"
|
||||
#include "base/platform/base_platform_info.h"
|
||||
|
||||
namespace Platform {
|
||||
|
||||
bool AllowNativeWindowFrameToggle();
|
||||
object_ptr<Window::TitleWidget> CreateTitleWidget(QWidget *parent);
|
||||
bool NativeTitleRequiresShadow();
|
||||
inline bool NativeTitleRequiresShadow() {
|
||||
return Platform::IsWindows();
|
||||
}
|
||||
|
||||
int PreviewTitleHeight();
|
||||
void PreviewWindowFramePaint(QImage &preview, const style::palette &palette, QRect body, int outerWidth);
|
||||
|
@ -25,28 +23,10 @@ void PreviewWindowFramePaint(QImage &preview, const style::palette &palette, QRe
|
|||
|
||||
// Platform dependent implementations.
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
#include "platform/mac/window_title_mac.h"
|
||||
#elif defined Q_OS_WIN // Q_OS_MAC
|
||||
#include "platform/win/window_title_win.h"
|
||||
#elif defined Q_OS_UNIX // Q_OS_MAC || Q_OS_WIN
|
||||
#include "platform/linux/window_title_linux.h"
|
||||
#else // Q_OS_MAC || Q_OS_WIN || Q_OS_UNIX
|
||||
#ifndef Q_OS_MAC
|
||||
|
||||
namespace Platform {
|
||||
|
||||
inline bool AllowNativeWindowFrameToggle() {
|
||||
return true;
|
||||
}
|
||||
|
||||
inline object_ptr<Window::TitleWidget> CreateTitleWidget(QWidget *parent) {
|
||||
return object_ptr<Window::TitleWidgetQt>(parent);
|
||||
}
|
||||
|
||||
inline bool NativeTitleRequiresShadow() {
|
||||
return false;
|
||||
}
|
||||
|
||||
inline int PreviewTitleHeight() {
|
||||
return Window::Theme::DefaultPreviewTitleHeight();
|
||||
}
|
||||
|
@ -57,4 +37,4 @@ inline void PreviewWindowFramePaint(QImage &preview, const style::palette &palet
|
|||
|
||||
} // namespace Platform
|
||||
|
||||
#endif // Q_OS_MAC || Q_OS_WIN || Q_OS_UNIX
|
||||
#endif // !Q_OS_MAC
|
||||
|
|
|
@ -43,8 +43,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
HICON qt_pixmapToWinHICON(const QPixmap &);
|
||||
|
||||
Q_DECLARE_METATYPE(QMargins);
|
||||
|
||||
namespace ViewManagement = ABI::Windows::UI::ViewManagement;
|
||||
|
||||
namespace Platform {
|
||||
|
@ -122,12 +120,6 @@ MainWindow::MainWindow(not_null<Window::Controller*> controller)
|
|||
if (!kTaskbarCreatedMsgId) {
|
||||
kTaskbarCreatedMsgId = RegisterWindowMessage(L"TaskbarButtonCreated");
|
||||
}
|
||||
style::PaletteChanged(
|
||||
) | rpl::start_with_next([=] {
|
||||
if (_shadow) {
|
||||
_shadow->setColor(st::windowShadowFg->c);
|
||||
}
|
||||
}, lifetime());
|
||||
setupNativeWindowFrame();
|
||||
|
||||
using namespace rpl::mappers;
|
||||
|
@ -163,15 +155,7 @@ void MainWindow::setupNativeWindowFrame() {
|
|||
std::move(nativeFrame),
|
||||
std::move(nightMode)
|
||||
) | rpl::skip(1) | rpl::start_with_next([=](bool native, bool night) {
|
||||
const auto nativeChanged = (_wasNativeFrame != native);
|
||||
if (nativeChanged) {
|
||||
_wasNativeFrame = native;
|
||||
initShadows();
|
||||
}
|
||||
validateWindowTheme(native, night);
|
||||
if (nativeChanged) {
|
||||
fixMaximizedWindow();
|
||||
}
|
||||
}, lifetime());
|
||||
}
|
||||
|
||||
|
@ -186,23 +170,12 @@ void MainWindow::TaskbarCreated() {
|
|||
}
|
||||
}
|
||||
|
||||
void MainWindow::shadowsUpdate(
|
||||
Ui::Platform::WindowShadow::Changes changes,
|
||||
WINDOWPOS *position) {
|
||||
if (_shadow) {
|
||||
_shadow->update(changes, position);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::shadowsActivate() {
|
||||
_hasActiveFrame = true;
|
||||
// _shadow->setColor(_shActive);
|
||||
shadowsUpdate(Ui::Platform::WindowShadow::Change::Activate);
|
||||
}
|
||||
|
||||
void MainWindow::shadowsDeactivate() {
|
||||
_hasActiveFrame = false;
|
||||
// _shadow->setColor(_shInactive);
|
||||
}
|
||||
|
||||
void MainWindow::psShowTrayMenu() {
|
||||
|
@ -327,7 +300,7 @@ bool MainWindow::initSizeFromSystem() {
|
|||
if (!screen) {
|
||||
return false;
|
||||
}
|
||||
setGeometry(screen->availableGeometry());
|
||||
Ui::RpWidget::setGeometry(screen->availableGeometry());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -356,7 +329,6 @@ bool MainWindow::isActiveForTrayMenu() {
|
|||
}
|
||||
|
||||
void MainWindow::unreadCounterChangedHook() {
|
||||
setWindowTitle(titleText());
|
||||
updateIconCounters();
|
||||
}
|
||||
|
||||
|
@ -437,147 +409,9 @@ void MainWindow::initHook() {
|
|||
}
|
||||
}
|
||||
|
||||
psInitSysMenu();
|
||||
}
|
||||
|
||||
void MainWindow::initShadows() {
|
||||
if (Core::App().settings().nativeWindowFrame()) {
|
||||
_shadow.reset();
|
||||
} else {
|
||||
_shadow.emplace(this, st::windowShadowFg->c);
|
||||
}
|
||||
updateCustomMargins();
|
||||
firstShadowsUpdate();
|
||||
}
|
||||
|
||||
void MainWindow::firstShadowsUpdate() {
|
||||
using Change = Ui::Platform::WindowShadow::Change;
|
||||
if ((windowState() & (Qt::WindowMinimized | Qt::WindowMaximized))
|
||||
|| isHidden()) {
|
||||
shadowsUpdate(Change::Hidden);
|
||||
} else {
|
||||
shadowsUpdate(Change::Moved | Change::Resized | Change::Shown);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::stateChangedHook(Qt::WindowState state) {
|
||||
updateSystemMenu(state);
|
||||
}
|
||||
|
||||
void MainWindow::psInitSysMenu() {
|
||||
Qt::WindowStates states = windowState();
|
||||
ps_menu = GetSystemMenu(ps_hWnd, FALSE);
|
||||
updateSystemMenu(windowHandle()->windowState());
|
||||
}
|
||||
|
||||
void MainWindow::updateSystemMenu(Qt::WindowState state) {
|
||||
if (!ps_menu) return;
|
||||
|
||||
int menuToDisable = SC_RESTORE;
|
||||
if (state == Qt::WindowMaximized) {
|
||||
menuToDisable = SC_MAXIMIZE;
|
||||
} else if (state == Qt::WindowMinimized) {
|
||||
menuToDisable = SC_MINIMIZE;
|
||||
}
|
||||
int itemCount = GetMenuItemCount(ps_menu);
|
||||
for (int i = 0; i < itemCount; ++i) {
|
||||
MENUITEMINFO itemInfo = { 0 };
|
||||
itemInfo.cbSize = sizeof(itemInfo);
|
||||
itemInfo.fMask = MIIM_TYPE | MIIM_STATE | MIIM_ID;
|
||||
if (GetMenuItemInfo(ps_menu, i, TRUE, &itemInfo)) {
|
||||
if (itemInfo.fType & MFT_SEPARATOR) {
|
||||
continue;
|
||||
}
|
||||
if (itemInfo.wID && !(itemInfo.fState & MFS_DEFAULT)) {
|
||||
UINT fOldState = itemInfo.fState, fState = itemInfo.fState & ~MFS_DISABLED;
|
||||
if (itemInfo.wID == SC_CLOSE) {
|
||||
fState |= MFS_DEFAULT;
|
||||
} else if (itemInfo.wID == menuToDisable || (itemInfo.wID != SC_MINIMIZE && itemInfo.wID != SC_MAXIMIZE && itemInfo.wID != SC_RESTORE)) {
|
||||
fState |= MFS_DISABLED;
|
||||
}
|
||||
itemInfo.fMask = MIIM_STATE;
|
||||
itemInfo.fState = fState;
|
||||
if (!SetMenuItemInfo(ps_menu, i, TRUE, &itemInfo)) {
|
||||
DEBUG_LOG(("PS Error: could not set state %1 to menu item %2, old state %3, error %4").arg(fState).arg(itemInfo.wID).arg(fOldState).arg(GetLastError()));
|
||||
DestroyMenu(ps_menu);
|
||||
ps_menu = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
DEBUG_LOG(("PS Error: could not get state, menu item %1 of %2, error %3").arg(i).arg(itemCount).arg(GetLastError()));
|
||||
DestroyMenu(ps_menu);
|
||||
ps_menu = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::updateCustomMargins() {
|
||||
if (!ps_hWnd || _inUpdateMargins) {
|
||||
return;
|
||||
}
|
||||
|
||||
_inUpdateMargins = true;
|
||||
|
||||
const auto margins = computeCustomMargins();
|
||||
if (const auto native = QGuiApplication::platformNativeInterface()) {
|
||||
native->setWindowProperty(
|
||||
windowHandle()->handle(),
|
||||
qsl("WindowsCustomMargins"),
|
||||
QVariant::fromValue<QMargins>(margins));
|
||||
}
|
||||
if (!_themeInited) {
|
||||
_themeInited = true;
|
||||
validateWindowTheme(
|
||||
Core::App().settings().nativeWindowFrame(),
|
||||
Window::Theme::IsNightMode());
|
||||
}
|
||||
_inUpdateMargins = false;
|
||||
}
|
||||
|
||||
QMargins MainWindow::computeCustomMargins() {
|
||||
if (Core::App().settings().nativeWindowFrame()) {
|
||||
_deltaLeft = _deltaTop = _deltaRight = _deltaBottom = 0;
|
||||
return QMargins();
|
||||
}
|
||||
auto r = RECT();
|
||||
GetClientRect(ps_hWnd, &r);
|
||||
|
||||
auto a = r;
|
||||
const auto style = GetWindowLongPtr(ps_hWnd, GWL_STYLE);
|
||||
const auto styleEx = GetWindowLongPtr(ps_hWnd, GWL_EXSTYLE);
|
||||
AdjustWindowRectEx(&a, style, false, styleEx);
|
||||
auto margins = QMargins(a.left - r.left, a.top - r.top, r.right - a.right, r.bottom - a.bottom);
|
||||
if (style & WS_MAXIMIZE) {
|
||||
RECT w, m;
|
||||
GetWindowRect(ps_hWnd, &w);
|
||||
m = w;
|
||||
|
||||
HMONITOR hMonitor = MonitorFromRect(&w, MONITOR_DEFAULTTONEAREST);
|
||||
if (hMonitor) {
|
||||
MONITORINFO mi;
|
||||
mi.cbSize = sizeof(mi);
|
||||
GetMonitorInfo(hMonitor, &mi);
|
||||
m = mi.rcWork;
|
||||
}
|
||||
|
||||
_deltaLeft = w.left - m.left;
|
||||
_deltaTop = w.top - m.top;
|
||||
_deltaRight = m.right - w.right;
|
||||
_deltaBottom = m.bottom - w.bottom;
|
||||
|
||||
margins.setLeft(margins.left() - _deltaLeft);
|
||||
margins.setRight(margins.right() - _deltaRight);
|
||||
margins.setBottom(margins.bottom() - _deltaBottom);
|
||||
margins.setTop(margins.top() - _deltaTop);
|
||||
} else if (_deltaLeft != 0 || _deltaTop != 0 || _deltaRight != 0 || _deltaBottom != 0) {
|
||||
RECT w;
|
||||
GetWindowRect(ps_hWnd, &w);
|
||||
SetWindowPos(ps_hWnd, 0, 0, 0, w.right - w.left - _deltaLeft - _deltaRight, w.bottom - w.top - _deltaBottom - _deltaTop, SWP_NOMOVE | SWP_NOSENDCHANGING | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREPOSITION);
|
||||
_deltaLeft = _deltaTop = _deltaRight = _deltaBottom = 0;
|
||||
}
|
||||
return margins;
|
||||
validateWindowTheme(
|
||||
Core::App().settings().nativeWindowFrame(),
|
||||
Window::Theme::IsNightMode());
|
||||
}
|
||||
|
||||
void MainWindow::validateWindowTheme(bool native, bool night) {
|
||||
|
@ -673,25 +507,6 @@ void MainWindow::validateWindowTheme(bool native, bool night) {
|
|||
SendMessage(ps_hWnd, WM_NCACTIVATE, _hasActiveFrame ? 1 : 0, 0);
|
||||
}
|
||||
|
||||
void MainWindow::fixMaximizedWindow() {
|
||||
auto r = RECT();
|
||||
GetClientRect(ps_hWnd, &r);
|
||||
const auto style = GetWindowLongPtr(ps_hWnd, GWL_STYLE);
|
||||
const auto styleEx = GetWindowLongPtr(ps_hWnd, GWL_EXSTYLE);
|
||||
AdjustWindowRectEx(&r, style, false, styleEx);
|
||||
if (style & WS_MAXIMIZE) {
|
||||
auto w = RECT();
|
||||
GetWindowRect(ps_hWnd, &w);
|
||||
if (const auto hMonitor = MonitorFromRect(&w, MONITOR_DEFAULTTONEAREST)) {
|
||||
MONITORINFO mi;
|
||||
mi.cbSize = sizeof(mi);
|
||||
GetMonitorInfo(hMonitor, &mi);
|
||||
const auto m = mi.rcWork;
|
||||
SetWindowPos(ps_hWnd, 0, 0, 0, m.right - m.left - _deltaLeft - _deltaRight, m.bottom - m.top - _deltaTop - _deltaBottom, SWP_NOMOVE | SWP_NOSENDCHANGING | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREPOSITION);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::showFromTrayMenu() {
|
||||
// If we try to activate() window before the trayIconMenu is hidden,
|
||||
// then the window will be shown in semi-active state (Qt bug).
|
||||
|
@ -707,10 +522,6 @@ HWND MainWindow::psHwnd() const {
|
|||
return ps_hWnd;
|
||||
}
|
||||
|
||||
HMENU MainWindow::psMenu() const {
|
||||
return ps_menu;
|
||||
}
|
||||
|
||||
void MainWindow::psDestroyIcons() {
|
||||
if (ps_iconBig) {
|
||||
DestroyIcon(ps_iconBig);
|
||||
|
@ -735,7 +546,6 @@ MainWindow::~MainWindow() {
|
|||
taskbarList.Reset();
|
||||
}
|
||||
|
||||
if (ps_menu) DestroyMenu(ps_menu);
|
||||
psDestroyIcons();
|
||||
if (ps_tbHider_hWnd) DestroyWindow(ps_tbHider_hWnd);
|
||||
|
||||
|
|
|
@ -8,12 +8,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#pragma once
|
||||
|
||||
#include "platform/platform_main_window.h"
|
||||
#include "ui/platform/win/ui_window_shadow_win.h"
|
||||
#include "base/platform/win/base_windows_h.h"
|
||||
#include "base/flags.h"
|
||||
|
||||
#include <QtCore/QTimer>
|
||||
|
||||
namespace Ui {
|
||||
class PopupMenu;
|
||||
} // namespace Ui
|
||||
|
@ -27,11 +24,6 @@ public:
|
|||
void showFromTrayMenu() override;
|
||||
|
||||
HWND psHwnd() const;
|
||||
HMENU psMenu() const;
|
||||
|
||||
void psInitSysMenu();
|
||||
void updateSystemMenu(Qt::WindowState state);
|
||||
void updateCustomMargins();
|
||||
|
||||
void updateWindowIcon() override;
|
||||
bool isActiveForTrayMenu() override;
|
||||
|
@ -46,16 +38,6 @@ public:
|
|||
// Custom shadows.
|
||||
void shadowsActivate();
|
||||
void shadowsDeactivate();
|
||||
void shadowsUpdate(
|
||||
Ui::Platform::WindowShadow::Changes changes,
|
||||
WINDOWPOS *position = nullptr);
|
||||
|
||||
int deltaLeft() const {
|
||||
return _deltaLeft;
|
||||
}
|
||||
int deltaTop() const {
|
||||
return _deltaTop;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool hasTabletView() const;
|
||||
|
||||
|
@ -68,10 +50,6 @@ protected:
|
|||
int32 screenNameChecksum(const QString &name) const override;
|
||||
void unreadCounterChangedHook() override;
|
||||
|
||||
void initShadows() override;
|
||||
void firstShadowsUpdate() override;
|
||||
void stateChangedHook(Qt::WindowState state) override;
|
||||
|
||||
bool hasTrayIcon() const override {
|
||||
return trayIcon;
|
||||
}
|
||||
|
@ -91,25 +69,16 @@ protected:
|
|||
|
||||
QRect computeDesktopRect() const override;
|
||||
|
||||
QTimer psUpdatedPositionTimer;
|
||||
|
||||
private:
|
||||
struct Private;
|
||||
|
||||
void setupNativeWindowFrame();
|
||||
void updateIconCounters();
|
||||
QMargins computeCustomMargins();
|
||||
void validateWindowTheme(bool native, bool night);
|
||||
void psDestroyIcons();
|
||||
void fixMaximizedWindow();
|
||||
|
||||
const std::unique_ptr<Private> _private;
|
||||
|
||||
std::optional<Ui::Platform::WindowShadow> _shadow;
|
||||
|
||||
bool _themeInited = false;
|
||||
bool _inUpdateMargins = false;
|
||||
bool _wasNativeFrame = false;
|
||||
bool _hasActiveFrame = false;
|
||||
|
||||
// Workarounds for activation from tray icon.
|
||||
|
@ -118,16 +87,10 @@ private:
|
|||
|
||||
HWND ps_hWnd = nullptr;
|
||||
HWND ps_tbHider_hWnd = nullptr;
|
||||
HMENU ps_menu = nullptr;
|
||||
HICON ps_iconBig = nullptr;
|
||||
HICON ps_iconSmall = nullptr;
|
||||
HICON ps_iconOverlay = nullptr;
|
||||
|
||||
int _deltaLeft = 0;
|
||||
int _deltaTop = 0;
|
||||
int _deltaRight = 0;
|
||||
int _deltaBottom = 0;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Platform
|
||||
|
|
|
@ -1,136 +0,0 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#include "platform/win/window_title_win.h"
|
||||
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/shadow.h"
|
||||
#include "styles/style_window.h"
|
||||
|
||||
#include <QtGui/QWindow>
|
||||
|
||||
namespace Platform {
|
||||
|
||||
TitleWidget::TitleWidget(QWidget *parent)
|
||||
: Window::TitleWidget(parent)
|
||||
, _st(st::defaultWindowTitle)
|
||||
, _minimize(this, _st.minimize)
|
||||
, _maximizeRestore(this, _st.maximize)
|
||||
, _close(this, _st.close)
|
||||
, _shadow(this, st::titleShadow)
|
||||
, _maximizedState(parent->window()->windowState() & Qt::WindowMaximized) {
|
||||
_minimize->setClickedCallback([=] {
|
||||
window()->setWindowState(
|
||||
window()->windowState() | Qt::WindowMinimized);
|
||||
_minimize->clearState();
|
||||
});
|
||||
_minimize->setPointerCursor(false);
|
||||
_maximizeRestore->setClickedCallback([=] {
|
||||
window()->setWindowState(_maximizedState
|
||||
? Qt::WindowNoState
|
||||
: Qt::WindowMaximized);
|
||||
_maximizeRestore->clearState();
|
||||
});
|
||||
_maximizeRestore->setPointerCursor(false);
|
||||
_close->setClickedCallback([=] {
|
||||
window()->close();
|
||||
_close->clearState();
|
||||
});
|
||||
_close->setPointerCursor(false);
|
||||
|
||||
setAttribute(Qt::WA_OpaquePaintEvent);
|
||||
resize(width(), _st.height);
|
||||
}
|
||||
|
||||
void TitleWidget::init() {
|
||||
connect(
|
||||
window()->windowHandle(),
|
||||
&QWindow::windowStateChanged,
|
||||
this,
|
||||
[=](Qt::WindowState state) { windowStateChanged(state); });
|
||||
_maximizedState = (window()->windowState() & Qt::WindowMaximized);
|
||||
_activeState = isActiveWindow();
|
||||
updateButtonsState();
|
||||
}
|
||||
|
||||
void TitleWidget::paintEvent(QPaintEvent *e) {
|
||||
auto active = isActiveWindow();
|
||||
if (_activeState != active) {
|
||||
_activeState = active;
|
||||
updateButtonsState();
|
||||
}
|
||||
Painter(this).fillRect(rect(), active ? _st.bgActive : _st.bg);
|
||||
}
|
||||
|
||||
void TitleWidget::updateControlsPosition() {
|
||||
auto right = 0;
|
||||
_close->moveToRight(right, 0); right += _close->width();
|
||||
_maximizeRestore->moveToRight(right, 0); right += _maximizeRestore->width();
|
||||
_minimize->moveToRight(right, 0);
|
||||
}
|
||||
|
||||
void TitleWidget::resizeEvent(QResizeEvent *e) {
|
||||
updateControlsPosition();
|
||||
_shadow->setGeometry(0, height() - st::lineWidth, width(), st::lineWidth);
|
||||
}
|
||||
|
||||
void TitleWidget::windowStateChanged(Qt::WindowState state) {
|
||||
if (state == Qt::WindowMinimized) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto maximized = (state == Qt::WindowMaximized);
|
||||
if (_maximizedState != maximized) {
|
||||
_maximizedState = maximized;
|
||||
updateButtonsState();
|
||||
}
|
||||
}
|
||||
|
||||
void TitleWidget::updateButtonsState() {
|
||||
_minimize->setIconOverride(_activeState
|
||||
? &_st.minimizeIconActive
|
||||
: nullptr,
|
||||
_activeState
|
||||
? &_st.minimizeIconActiveOver
|
||||
: nullptr);
|
||||
if (_maximizedState) {
|
||||
_maximizeRestore->setIconOverride(
|
||||
_activeState
|
||||
? &_st.restoreIconActive : &_st.restoreIcon,
|
||||
_activeState
|
||||
? &_st.restoreIconActiveOver
|
||||
: &_st.restoreIconOver);
|
||||
} else {
|
||||
_maximizeRestore->setIconOverride(_activeState
|
||||
? &_st.maximizeIconActive
|
||||
: nullptr,
|
||||
_activeState
|
||||
? &_st.maximizeIconActiveOver
|
||||
: nullptr);
|
||||
}
|
||||
_close->setIconOverride(_activeState
|
||||
? &_st.closeIconActive
|
||||
: nullptr,
|
||||
_activeState
|
||||
? &_st.closeIconActiveOver
|
||||
: nullptr);
|
||||
}
|
||||
|
||||
Window::HitTestResult TitleWidget::hitTest(const QPoint &p) const {
|
||||
if (false
|
||||
|| (_minimize->geometry().contains(p))
|
||||
|| (_maximizeRestore->geometry().contains(p))
|
||||
|| (_close->geometry().contains(p))
|
||||
) {
|
||||
return Window::HitTestResult::SysButton;
|
||||
} else if (rect().contains(p)) {
|
||||
return Window::HitTestResult::Caption;
|
||||
}
|
||||
return Window::HitTestResult::None;
|
||||
}
|
||||
|
||||
} // namespace Platform
|
|
@ -1,82 +0,0 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "platform/platform_window_title.h"
|
||||
#include "base/object_ptr.h"
|
||||
|
||||
namespace style {
|
||||
struct WindowTitle;
|
||||
} // namespace style
|
||||
|
||||
namespace Ui {
|
||||
class IconButton;
|
||||
class PlainShadow;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Window {
|
||||
namespace Theme {
|
||||
|
||||
int DefaultPreviewTitleHeight();
|
||||
void DefaultPreviewWindowFramePaint(QImage &preview, const style::palette &palette, QRect body, int outerWidth);
|
||||
|
||||
} // namespace Theme
|
||||
} // namespace Window
|
||||
|
||||
namespace Platform {
|
||||
|
||||
class TitleWidget : public Window::TitleWidget {
|
||||
public:
|
||||
TitleWidget(QWidget *parent);
|
||||
|
||||
void init() override;
|
||||
|
||||
[[nodiscard]] Window::HitTestResult hitTest(
|
||||
const QPoint &p) const override;
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
void resizeEvent(QResizeEvent *e) override;
|
||||
|
||||
private:
|
||||
void windowStateChanged(Qt::WindowState state = Qt::WindowNoState);
|
||||
void updateButtonsState();
|
||||
void updateControlsPosition();
|
||||
|
||||
const style::WindowTitle &_st;
|
||||
object_ptr<Ui::IconButton> _minimize;
|
||||
object_ptr<Ui::IconButton> _maximizeRestore;
|
||||
object_ptr<Ui::IconButton> _close;
|
||||
object_ptr<Ui::PlainShadow> _shadow;
|
||||
|
||||
bool _maximizedState = false;
|
||||
bool _activeState = false;
|
||||
|
||||
};
|
||||
|
||||
inline bool AllowNativeWindowFrameToggle() {
|
||||
return true;
|
||||
}
|
||||
|
||||
inline object_ptr<Window::TitleWidget> CreateTitleWidget(QWidget *parent) {
|
||||
return object_ptr<TitleWidget>(parent);
|
||||
}
|
||||
|
||||
inline bool NativeTitleRequiresShadow() {
|
||||
return true;
|
||||
}
|
||||
|
||||
inline int PreviewTitleHeight() {
|
||||
return Window::Theme::DefaultPreviewTitleHeight();
|
||||
}
|
||||
|
||||
inline void PreviewWindowFramePaint(QImage &preview, const style::palette &palette, QRect body, int outerWidth) {
|
||||
return Window::Theme::DefaultPreviewWindowFramePaint(preview, palette, body, outerWidth);
|
||||
}
|
||||
|
||||
} // namespace Platform
|
|
@ -63,7 +63,6 @@ SafeIniter::SafeIniter() {
|
|||
LOAD_SYMBOL(LibPropSys, PSStringFromPropertyKey);
|
||||
|
||||
const auto LibDwmApi = LoadLibrary(L"dwmapi.dll");
|
||||
LOAD_SYMBOL(LibDwmApi, DwmIsCompositionEnabled);
|
||||
LOAD_SYMBOL(LibDwmApi, DwmSetWindowAttribute);
|
||||
|
||||
const auto LibPsApi = LoadLibrary(L"psapi.dll");
|
||||
|
|
|
@ -96,8 +96,6 @@ inline HRESULT(__stdcall *PSStringFromPropertyKey)(
|
|||
|
||||
// DWMAPI.DLL
|
||||
|
||||
inline HRESULT(__stdcall *DwmIsCompositionEnabled)(
|
||||
_Out_ BOOL* pfEnabled);
|
||||
inline HRESULT(__stdcall *DwmSetWindowAttribute)(
|
||||
HWND hwnd,
|
||||
DWORD dwAttribute,
|
||||
|
|
|
@ -7,12 +7,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#include "platform/win/windows_event_filter.h"
|
||||
|
||||
#include "platform/win/windows_dlls.h"
|
||||
#include "platform/win/specific_win.h"
|
||||
#include "core/sandbox.h"
|
||||
#include "core/core_settings.h"
|
||||
#include "core/application.h"
|
||||
#include "ui/inactive_press.h"
|
||||
#include "mainwindow.h"
|
||||
#include "app.h"
|
||||
|
||||
|
@ -23,67 +21,6 @@ namespace {
|
|||
|
||||
EventFilter *instance = nullptr;
|
||||
|
||||
int menuShown = 0, menuHidden = 0;
|
||||
|
||||
bool IsCompositionEnabled() {
|
||||
if (!Dlls::DwmIsCompositionEnabled) {
|
||||
return false;
|
||||
}
|
||||
auto result = BOOL(FALSE);
|
||||
const auto success = (Dlls::DwmIsCompositionEnabled(&result) == S_OK);
|
||||
return success && result;
|
||||
}
|
||||
|
||||
HWND FindTaskbarWindow(LPRECT rcMon = nullptr) {
|
||||
HWND hTaskbar = nullptr;
|
||||
RECT rcTaskbar, rcMatch;
|
||||
|
||||
while ((hTaskbar = FindWindowEx(
|
||||
nullptr,
|
||||
hTaskbar,
|
||||
L"Shell_TrayWnd",
|
||||
nullptr)) != nullptr) {
|
||||
if (!rcMon) {
|
||||
break; // OK, return first found
|
||||
}
|
||||
if (GetWindowRect(hTaskbar, &rcTaskbar)
|
||||
&& IntersectRect(&rcMatch, &rcTaskbar, rcMon)) {
|
||||
break; // OK, taskbar match monitor
|
||||
}
|
||||
}
|
||||
|
||||
return hTaskbar;
|
||||
}
|
||||
|
||||
bool IsTaskbarAutoHidden(LPRECT rcMon = nullptr, PUINT pEdge = nullptr) {
|
||||
HWND hTaskbar = FindTaskbarWindow(rcMon);
|
||||
if (!hTaskbar) {
|
||||
if (pEdge) {
|
||||
*pEdge = (UINT)-1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
APPBARDATA state = {sizeof(state), hTaskbar};
|
||||
APPBARDATA pos = {sizeof(pos), hTaskbar};
|
||||
|
||||
LRESULT lState = SHAppBarMessage(ABM_GETSTATE, &state);
|
||||
bool bAutoHidden = (lState & ABS_AUTOHIDE);
|
||||
|
||||
if (SHAppBarMessage(ABM_GETTASKBARPOS, &pos)) {
|
||||
if (pEdge) {
|
||||
*pEdge = pos.uEdge;
|
||||
}
|
||||
} else {
|
||||
LOG(("Failed to get taskbar pos"));
|
||||
if (pEdge) {
|
||||
*pEdge = ABE_BOTTOM;
|
||||
}
|
||||
}
|
||||
|
||||
return bAutoHidden;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
EventFilter *EventFilter::CreateInstance(not_null<MainWindow*> window) {
|
||||
|
@ -125,108 +62,18 @@ bool EventFilter::nativeEventFilter(
|
|||
});
|
||||
}
|
||||
|
||||
bool EventFilter::customWindowFrameEvent(
|
||||
HWND hWnd,
|
||||
UINT msg,
|
||||
WPARAM wParam,
|
||||
LPARAM lParam,
|
||||
LRESULT *result) {
|
||||
switch (msg) {
|
||||
case WM_NCPAINT: {
|
||||
if (QSysInfo::WindowsVersion >= QSysInfo::WV_WINDOWS8) return false;
|
||||
if (result) *result = 0;
|
||||
} return true;
|
||||
|
||||
case WM_NCCALCSIZE: {
|
||||
WINDOWPLACEMENT wp;
|
||||
wp.length = sizeof(WINDOWPLACEMENT);
|
||||
if (GetWindowPlacement(hWnd, &wp) && wp.showCmd == SW_SHOWMAXIMIZED) {
|
||||
LPNCCALCSIZE_PARAMS params = (LPNCCALCSIZE_PARAMS)lParam;
|
||||
LPRECT r = (wParam == TRUE) ? ¶ms->rgrc[0] : (LPRECT)lParam;
|
||||
HMONITOR hMonitor = MonitorFromPoint({ (r->left + r->right) / 2, (r->top + r->bottom) / 2 }, MONITOR_DEFAULTTONEAREST);
|
||||
if (hMonitor) {
|
||||
MONITORINFO mi;
|
||||
mi.cbSize = sizeof(mi);
|
||||
if (GetMonitorInfo(hMonitor, &mi)) {
|
||||
*r = mi.rcWork;
|
||||
UINT uEdge = (UINT)-1;
|
||||
if (IsTaskbarAutoHidden(&mi.rcMonitor, &uEdge)) {
|
||||
switch (uEdge) {
|
||||
case ABE_LEFT: r->left += 1; break;
|
||||
case ABE_RIGHT: r->right -= 1; break;
|
||||
case ABE_TOP: r->top += 1; break;
|
||||
case ABE_BOTTOM: r->bottom -= 1; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (result) *result = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
case WM_NCACTIVATE: {
|
||||
if (IsCompositionEnabled()) {
|
||||
const auto res = DefWindowProc(hWnd, msg, wParam, -1);
|
||||
if (result) *result = res;
|
||||
} else {
|
||||
// Thanks https://github.com/melak47/BorderlessWindow
|
||||
if (result) *result = 1;
|
||||
}
|
||||
} return true;
|
||||
|
||||
case WM_NCHITTEST: {
|
||||
if (!result) return false;
|
||||
|
||||
POINTS p = MAKEPOINTS(lParam);
|
||||
RECT r;
|
||||
GetWindowRect(hWnd, &r);
|
||||
auto res = _window->hitTest(QPoint(p.x - r.left + _window->deltaLeft(), p.y - r.top + _window->deltaTop()));
|
||||
switch (res) {
|
||||
case Window::HitTestResult::Client:
|
||||
case Window::HitTestResult::SysButton: *result = HTCLIENT; break;
|
||||
case Window::HitTestResult::Caption: *result = HTCAPTION; break;
|
||||
case Window::HitTestResult::Top: *result = HTTOP; break;
|
||||
case Window::HitTestResult::TopRight: *result = HTTOPRIGHT; break;
|
||||
case Window::HitTestResult::Right: *result = HTRIGHT; break;
|
||||
case Window::HitTestResult::BottomRight: *result = HTBOTTOMRIGHT; break;
|
||||
case Window::HitTestResult::Bottom: *result = HTBOTTOM; break;
|
||||
case Window::HitTestResult::BottomLeft: *result = HTBOTTOMLEFT; break;
|
||||
case Window::HitTestResult::Left: *result = HTLEFT; break;
|
||||
case Window::HitTestResult::TopLeft: *result = HTTOPLEFT; break;
|
||||
case Window::HitTestResult::None:
|
||||
default: *result = HTTRANSPARENT; break;
|
||||
};
|
||||
} return true;
|
||||
|
||||
case WM_NCRBUTTONUP: {
|
||||
SendMessage(hWnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam);
|
||||
} return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EventFilter::mainWindowEvent(
|
||||
HWND hWnd,
|
||||
UINT msg,
|
||||
WPARAM wParam,
|
||||
LPARAM lParam,
|
||||
LRESULT *result) {
|
||||
using Change = Ui::Platform::WindowShadow::Change;
|
||||
|
||||
if (const auto tbCreatedMsgId = Platform::MainWindow::TaskbarCreatedMsgId()) {
|
||||
if (msg == tbCreatedMsgId) {
|
||||
Platform::MainWindow::TaskbarCreated();
|
||||
}
|
||||
}
|
||||
|
||||
if (!Core::App().settings().nativeWindowFrame()) {
|
||||
if (customWindowFrameEvent(hWnd, msg, wParam, lParam, result)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
switch (msg) {
|
||||
|
||||
case WM_TIMECHANGE: {
|
||||
|
@ -246,91 +93,25 @@ bool EventFilter::mainWindowEvent(
|
|||
} return false;
|
||||
|
||||
case WM_ACTIVATE: {
|
||||
if (LOWORD(wParam) == WA_CLICKACTIVE) {
|
||||
Ui::MarkInactivePress(_window, true);
|
||||
}
|
||||
if (LOWORD(wParam) != WA_INACTIVE) {
|
||||
_window->shadowsActivate();
|
||||
} else {
|
||||
_window->shadowsDeactivate();
|
||||
}
|
||||
_window->update();
|
||||
} return false;
|
||||
|
||||
case WM_WINDOWPOSCHANGING:
|
||||
case WM_WINDOWPOSCHANGED: {
|
||||
WINDOWPLACEMENT wp;
|
||||
wp.length = sizeof(WINDOWPLACEMENT);
|
||||
if (_window->hasTabletView()
|
||||
|| (GetWindowPlacement(hWnd, &wp)
|
||||
&& (wp.showCmd == SW_SHOWMAXIMIZED
|
||||
|| wp.showCmd == SW_SHOWMINIMIZED))) {
|
||||
_window->shadowsUpdate(Change::Hidden);
|
||||
} else {
|
||||
_window->shadowsUpdate(Change::Moved | Change::Resized, (WINDOWPOS*)lParam);
|
||||
}
|
||||
} return false;
|
||||
|
||||
case WM_SIZE: {
|
||||
if (wParam == SIZE_MAXIMIZED || wParam == SIZE_RESTORED || wParam == SIZE_MINIMIZED) {
|
||||
if (wParam != SIZE_RESTORED || _window->windowState() != Qt::WindowNoState) {
|
||||
Qt::WindowState state = Qt::WindowNoState;
|
||||
if (wParam == SIZE_MAXIMIZED) {
|
||||
state = Qt::WindowMaximized;
|
||||
} else if (wParam == SIZE_MINIMIZED) {
|
||||
state = Qt::WindowMinimized;
|
||||
}
|
||||
_window->windowHandle()->windowStateChanged(state);
|
||||
} else {
|
||||
if (wParam == SIZE_RESTORED && _window->windowState() == Qt::WindowNoState) {
|
||||
_window->positionUpdated();
|
||||
}
|
||||
_window->updateCustomMargins();
|
||||
const auto changes = (wParam == SIZE_MINIMIZED || wParam == SIZE_MAXIMIZED) ? Change::Hidden : (Change::Resized | Change::Shown);
|
||||
_window->shadowsUpdate(changes);
|
||||
}
|
||||
} return false;
|
||||
|
||||
case WM_SHOWWINDOW: {
|
||||
LONG style = GetWindowLongPtr(hWnd, GWL_STYLE);
|
||||
const auto changes = Change::Resized | ((wParam && !(style & (WS_MAXIMIZE | WS_MINIMIZE))) ? Change::Shown : Change::Hidden);
|
||||
_window->shadowsUpdate(changes);
|
||||
} return false;
|
||||
|
||||
case WM_MOVE: {
|
||||
_window->shadowsUpdate(Change::Moved);
|
||||
_window->positionUpdated();
|
||||
} return false;
|
||||
|
||||
case WM_SYSCOMMAND: {
|
||||
if (wParam == SC_MOUSEMENU) {
|
||||
POINTS p = MAKEPOINTS(lParam);
|
||||
_window->updateSystemMenu(_window->windowHandle()->windowState());
|
||||
TrackPopupMenu(_window->psMenu(), TPM_LEFTALIGN | TPM_TOPALIGN | TPM_LEFTBUTTON, p.x, p.y, 0, hWnd, 0);
|
||||
}
|
||||
} return false;
|
||||
|
||||
case WM_COMMAND: {
|
||||
if (HIWORD(wParam)) {
|
||||
return false;
|
||||
}
|
||||
int cmd = LOWORD(wParam);
|
||||
switch (cmd) {
|
||||
case SC_CLOSE:
|
||||
_window->close();
|
||||
return true;
|
||||
case SC_MINIMIZE:
|
||||
_window->setWindowState(
|
||||
_window->windowState() | Qt::WindowMinimized);
|
||||
return true;
|
||||
case SC_MAXIMIZE:
|
||||
_window->setWindowState(Qt::WindowMaximized);
|
||||
return true;
|
||||
case SC_RESTORE:
|
||||
_window->setWindowState(Qt::WindowNoState);
|
||||
return true;
|
||||
}
|
||||
} return true;
|
||||
|
||||
case WM_SETTINGCHANGE: {
|
||||
Core::App().settings().setSystemDarkMode(Platform::IsDarkMode());
|
||||
} return false;
|
||||
|
|
|
@ -26,13 +26,6 @@ public:
|
|||
private:
|
||||
explicit EventFilter(not_null<MainWindow*> window);
|
||||
|
||||
bool customWindowFrameEvent(
|
||||
HWND hWnd,
|
||||
UINT msg,
|
||||
WPARAM wParam,
|
||||
LPARAM lParam,
|
||||
LRESULT *result);
|
||||
|
||||
not_null<MainWindow*> _window;
|
||||
|
||||
};
|
||||
|
|
|
@ -22,7 +22,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "boxes/about_box.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "platform/platform_specific.h"
|
||||
#include "platform/platform_window_title.h"
|
||||
#include "ui/platform/ui_platform_window.h"
|
||||
#include "base/platform/base_platform_info.h"
|
||||
#include "window/window_controller.h"
|
||||
#include "window/window_session_controller.h"
|
||||
|
@ -406,7 +406,7 @@ void SetupSystemIntegrationContent(
|
|||
}, taskbar->lifetime());
|
||||
}
|
||||
}
|
||||
if (Platform::AllowNativeWindowFrameToggle()) {
|
||||
if (Ui::Platform::NativeWindowFrameSupported()) {
|
||||
const auto nativeFrame = addCheckbox(
|
||||
tr::lng_settings_native_frame(),
|
||||
Core::App().settings().nativeWindowFrame());
|
||||
|
|
|
@ -9,9 +9,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
#include "storage/localstorage.h"
|
||||
#include "platform/platform_specific.h"
|
||||
#include "ui/platform/ui_platform_window.h"
|
||||
#include "platform/platform_window_title.h"
|
||||
#include "base/platform/base_platform_info.h"
|
||||
#include "ui/platform/ui_platform_utility.h"
|
||||
#include "history/history.h"
|
||||
#include "window/window_session_controller.h"
|
||||
#include "window/window_lock_widgets.h"
|
||||
|
@ -161,9 +161,8 @@ QIcon CreateIcon(Main::Session *session) {
|
|||
MainWindow::MainWindow(not_null<Controller*> controller)
|
||||
: _controller(controller)
|
||||
, _positionUpdatedTimer([=] { savePosition(); })
|
||||
, _outdated(CreateOutdatedBar(this))
|
||||
, _body(this)
|
||||
, _titleText(qsl("Telegram")) {
|
||||
, _outdated(CreateOutdatedBar(body()))
|
||||
, _body(body()) {
|
||||
style::PaletteChanged(
|
||||
) | rpl::start_with_next([=] {
|
||||
updatePalette();
|
||||
|
@ -266,8 +265,6 @@ QRect MainWindow::desktopRect() const {
|
|||
}
|
||||
|
||||
void MainWindow::init() {
|
||||
Expects(!windowHandle());
|
||||
|
||||
createWinId();
|
||||
|
||||
initHook();
|
||||
|
@ -293,7 +290,7 @@ void MainWindow::init() {
|
|||
|
||||
updatePalette();
|
||||
|
||||
if (Platform::AllowNativeWindowFrameToggle()) {
|
||||
if (Ui::Platform::NativeWindowFrameSupported()) {
|
||||
Core::App().settings().nativeWindowFrameChanges(
|
||||
) | rpl::start_with_next([=](bool native) {
|
||||
refreshTitleWidget();
|
||||
|
@ -308,7 +305,6 @@ void MainWindow::init() {
|
|||
|
||||
void MainWindow::handleStateChanged(Qt::WindowState state) {
|
||||
stateChangedHook(state);
|
||||
updateShadowSize();
|
||||
updateControlsGeometry();
|
||||
if (state == Qt::WindowMinimized) {
|
||||
controller().updateIsActiveBlur();
|
||||
|
@ -381,27 +377,6 @@ void MainWindow::updatePalette() {
|
|||
setPalette(p);
|
||||
}
|
||||
|
||||
HitTestResult MainWindow::hitTest(const QPoint &p) const {
|
||||
auto titleResult = _title ? _title->hitTest(p - _title->geometry().topLeft()) : Window::HitTestResult::None;
|
||||
if (titleResult != Window::HitTestResult::None) {
|
||||
return titleResult;
|
||||
} else if (rect().contains(p)) {
|
||||
return Window::HitTestResult::Client;
|
||||
}
|
||||
return Window::HitTestResult::None;
|
||||
}
|
||||
|
||||
bool MainWindow::hasShadow() const {
|
||||
const auto center = geometry().center();
|
||||
return Ui::Platform::WindowExtentsSupported()
|
||||
&& Ui::Platform::TranslucentWindowsSupported(center)
|
||||
&& _title;
|
||||
}
|
||||
|
||||
QRect MainWindow::inner() const {
|
||||
return rect().marginsRemoved(_padding);
|
||||
}
|
||||
|
||||
int MainWindow::computeMinWidth() const {
|
||||
auto result = st::windowMinWidth;
|
||||
if (const auto session = _controller->sessionController()) {
|
||||
|
@ -412,38 +387,32 @@ int MainWindow::computeMinWidth() const {
|
|||
if (_rightColumn) {
|
||||
result += _rightColumn->width();
|
||||
}
|
||||
return result + _padding.left() + _padding.right();
|
||||
return result;
|
||||
}
|
||||
|
||||
int MainWindow::computeMinHeight() const {
|
||||
const auto title = _title ? _title->height() : 0;
|
||||
const auto outdated = [&] {
|
||||
if (!_outdated) {
|
||||
return 0;
|
||||
}
|
||||
_outdated->resizeToWidth(st::windowMinWidth - _padding.left() - _padding.right());
|
||||
_outdated->resizeToWidth(st::windowMinWidth);
|
||||
return _outdated->height();
|
||||
}();
|
||||
return title + outdated + st::windowMinHeight + _padding.top() + _padding.bottom();
|
||||
return outdated + st::windowMinHeight;
|
||||
}
|
||||
|
||||
void MainWindow::refreshTitleWidget() {
|
||||
if (Platform::AllowNativeWindowFrameToggle()
|
||||
if (Ui::Platform::NativeWindowFrameSupported()
|
||||
&& Core::App().settings().nativeWindowFrame()) {
|
||||
_title.destroy();
|
||||
setNativeFrame(true);
|
||||
if (Platform::NativeTitleRequiresShadow()) {
|
||||
_titleShadow.create(this);
|
||||
_titleShadow->show();
|
||||
}
|
||||
} else if ((_title = Platform::CreateTitleWidget(this))) {
|
||||
_title->show();
|
||||
_title->init();
|
||||
} else {
|
||||
setNativeFrame(false);
|
||||
_titleShadow.destroy();
|
||||
}
|
||||
|
||||
const auto withShadow = hasShadow();
|
||||
windowHandle()->setFlag(Qt::NoDropShadowWindowHint, withShadow);
|
||||
setAttribute(Qt::WA_OpaquePaintEvent, !withShadow);
|
||||
}
|
||||
|
||||
void MainWindow::updateMinimumSize() {
|
||||
|
@ -451,21 +420,13 @@ void MainWindow::updateMinimumSize() {
|
|||
setMinimumHeight(computeMinHeight());
|
||||
}
|
||||
|
||||
void MainWindow::updateShadowSize() {
|
||||
_padding = hasShadow() && !isMaximized()
|
||||
? st::callShadow.extend
|
||||
: style::margins();
|
||||
}
|
||||
|
||||
void MainWindow::recountGeometryConstraints() {
|
||||
updateShadowSize();
|
||||
updateMinimumSize();
|
||||
updateControlsGeometry();
|
||||
fixOrder();
|
||||
}
|
||||
|
||||
void MainWindow::initSize() {
|
||||
updateShadowSize();
|
||||
updateMinimumSize();
|
||||
|
||||
if (initSizeFromSystem()) {
|
||||
|
@ -565,7 +526,6 @@ void MainWindow::initSize() {
|
|||
}
|
||||
}
|
||||
}
|
||||
geometry += _padding;
|
||||
DEBUG_LOG(("Window Pos: Setting first %1, %2, %3, %4").arg(geometry.x()).arg(geometry.y()).arg(geometry.width()).arg(geometry.height()));
|
||||
setGeometry(geometry);
|
||||
}
|
||||
|
@ -574,18 +534,6 @@ void MainWindow::positionUpdated() {
|
|||
_positionUpdatedTimer.callOnce(kSaveWindowPositionTimeout);
|
||||
}
|
||||
|
||||
bool MainWindow::titleVisible() const {
|
||||
return _title && !_title->isHidden();
|
||||
}
|
||||
|
||||
void MainWindow::setTitleVisible(bool visible) {
|
||||
if (_title && (_title->isHidden() == visible)) {
|
||||
_title->setVisible(visible);
|
||||
updateControlsGeometry();
|
||||
}
|
||||
titleVisibilityChangedHook();
|
||||
}
|
||||
|
||||
int32 MainWindow::screenNameChecksum(const QString &name) const {
|
||||
const auto bytes = name.toUtf8();
|
||||
return base::crc32(bytes.constData(), bytes.size());
|
||||
|
@ -605,15 +553,7 @@ void MainWindow::attachToTrayIcon(not_null<QSystemTrayIcon*> icon) {
|
|||
});
|
||||
}
|
||||
|
||||
void MainWindow::paintEvent(QPaintEvent *e) {
|
||||
if (hasShadow() && !isMaximized()) {
|
||||
QPainter p(this);
|
||||
Ui::Shadow::paint(p, inner(), width(), st::callShadow);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::resizeEvent(QResizeEvent *e) {
|
||||
updateShadowSize();
|
||||
updateControlsGeometry();
|
||||
}
|
||||
|
||||
|
@ -626,14 +566,10 @@ void MainWindow::leaveEventHook(QEvent *e) {
|
|||
}
|
||||
|
||||
void MainWindow::updateControlsGeometry() {
|
||||
const auto inner = this->inner();
|
||||
const auto inner = body()->rect();
|
||||
auto bodyLeft = inner.x();
|
||||
auto bodyTop = inner.y();
|
||||
auto bodyWidth = inner.width();
|
||||
if (_title && !_title->isHidden()) {
|
||||
_title->setGeometry(inner.x(), bodyTop, inner.width(), _title->height());
|
||||
bodyTop += _title->height();
|
||||
}
|
||||
if (_titleShadow) {
|
||||
_titleShadow->setGeometry(inner.x(), bodyTop, inner.width(), st::lineWidth);
|
||||
}
|
||||
|
@ -656,7 +592,7 @@ void MainWindow::updateUnreadCounter() {
|
|||
}
|
||||
|
||||
const auto counter = Core::App().unreadBadge();
|
||||
_titleText = (counter > 0) ? qsl("Telegram (%1)").arg(counter) : qsl("Telegram");
|
||||
setTitle((counter > 0) ? qsl("Telegram (%1)").arg(counter) : qsl("Telegram"));
|
||||
|
||||
unreadCounterChangedHook();
|
||||
}
|
||||
|
@ -683,7 +619,7 @@ void MainWindow::savePosition(Qt::WindowState state) {
|
|||
realPosition.maximized = 1;
|
||||
DEBUG_LOG(("Window Pos: Saving maximized position."));
|
||||
} else {
|
||||
auto r = geometry().marginsRemoved(_padding);
|
||||
auto r = body()->mapToGlobal(body()->rect());
|
||||
realPosition.x = r.x();
|
||||
realPosition.y = r.y();
|
||||
realPosition.w = r.width() - (_rightColumn ? _rightColumn->width() : 0);
|
||||
|
@ -774,7 +710,7 @@ void MainWindow::showRightColumn(object_ptr<TWidget> widget) {
|
|||
const auto wasRightWidth = _rightColumn ? _rightColumn->width() : 0;
|
||||
_rightColumn = std::move(widget);
|
||||
if (_rightColumn) {
|
||||
_rightColumn->setParent(this);
|
||||
_rightColumn->setParent(body());
|
||||
_rightColumn->show();
|
||||
_rightColumn->setFocus();
|
||||
} else {
|
||||
|
@ -799,12 +735,12 @@ void MainWindow::showRightColumn(object_ptr<TWidget> widget) {
|
|||
|
||||
int MainWindow::maximalExtendBy() const {
|
||||
auto desktop = QDesktopWidget().availableGeometry(this);
|
||||
return std::max(desktop.width() - inner().width(), 0);
|
||||
return std::max(desktop.width() - body()->width(), 0);
|
||||
}
|
||||
|
||||
bool MainWindow::canExtendNoMove(int extendBy) const {
|
||||
auto desktop = QDesktopWidget().availableGeometry(this);
|
||||
auto inner = geometry().marginsRemoved(_padding);
|
||||
auto inner = body()->mapToGlobal(body()->rect());
|
||||
auto innerRight = (inner.x() + inner.width() + extendBy);
|
||||
auto desktopRight = (desktop.x() + desktop.width());
|
||||
return innerRight <= desktopRight;
|
||||
|
@ -812,7 +748,7 @@ bool MainWindow::canExtendNoMove(int extendBy) const {
|
|||
|
||||
int MainWindow::tryToExtendWidthBy(int addToWidth) {
|
||||
auto desktop = QDesktopWidget().availableGeometry(this);
|
||||
auto inner = geometry();
|
||||
auto inner = body()->mapToGlobal(body()->rect());
|
||||
accumulate_min(
|
||||
addToWidth,
|
||||
std::max(desktop.width() - inner.width(), 0));
|
||||
|
@ -821,7 +757,7 @@ int MainWindow::tryToExtendWidthBy(int addToWidth) {
|
|||
inner.x(),
|
||||
desktop.x() + desktop.width() - newWidth);
|
||||
if (inner.x() != newLeft || inner.width() != newWidth) {
|
||||
setGeometry(newLeft, inner.y(), newWidth, inner.height());
|
||||
setGeometry(QRect(newLeft, inner.y(), newWidth, inner.height()));
|
||||
} else {
|
||||
updateControlsGeometry();
|
||||
}
|
||||
|
@ -841,8 +777,6 @@ void MainWindow::launchDrag(
|
|||
}
|
||||
|
||||
MainWindow::~MainWindow() {
|
||||
_title.destroy();
|
||||
|
||||
// Otherwise:
|
||||
// ~QWidget
|
||||
// QWidgetPrivate::close_helper
|
||||
|
|
|
@ -7,8 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include "window/window_title.h"
|
||||
#include "ui/rp_widget.h"
|
||||
#include "ui/widgets/rp_window.h"
|
||||
#include "base/timer.h"
|
||||
#include "base/object_ptr.h"
|
||||
#include "core/core_settings.h"
|
||||
|
@ -37,7 +36,7 @@ QImage LoadLogoNoMargin();
|
|||
QIcon CreateIcon(Main::Session *session = nullptr);
|
||||
void ConvertIconToBlack(QImage &image);
|
||||
|
||||
class MainWindow : public Ui::RpWidget {
|
||||
class MainWindow : public Ui::RpWindow {
|
||||
public:
|
||||
explicit MainWindow(not_null<Controller*> controller);
|
||||
virtual ~MainWindow();
|
||||
|
@ -60,7 +59,6 @@ public:
|
|||
[[nodiscard]] QRect desktopRect() const;
|
||||
|
||||
void init();
|
||||
[[nodiscard]] HitTestResult hitTest(const QPoint &p) const;
|
||||
|
||||
void updateIsActive();
|
||||
|
||||
|
@ -77,12 +75,6 @@ public:
|
|||
}
|
||||
void positionUpdated();
|
||||
|
||||
bool titleVisible() const;
|
||||
void setTitleVisible(bool visible);
|
||||
QString titleText() const {
|
||||
return _titleText;
|
||||
}
|
||||
|
||||
void reActivateWindow();
|
||||
|
||||
void showRightColumn(object_ptr<TWidget> widget);
|
||||
|
@ -112,22 +104,18 @@ public:
|
|||
|
||||
void clearWidgets();
|
||||
|
||||
QRect inner() const;
|
||||
int computeMinWidth() const;
|
||||
int computeMinHeight() const;
|
||||
|
||||
void recountGeometryConstraints();
|
||||
virtual void updateControlsGeometry();
|
||||
|
||||
bool hasShadow() const;
|
||||
|
||||
bool minimizeToTray();
|
||||
void updateGlobalMenu() {
|
||||
updateGlobalMenuHook();
|
||||
}
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
void resizeEvent(QResizeEvent *e) override;
|
||||
void leaveEventHook(QEvent *e) override;
|
||||
|
||||
|
@ -154,9 +142,6 @@ protected:
|
|||
virtual void stateChangedHook(Qt::WindowState state) {
|
||||
}
|
||||
|
||||
virtual void titleVisibilityChangedHook() {
|
||||
}
|
||||
|
||||
virtual void unreadCounterChangedHook() {
|
||||
}
|
||||
|
||||
|
@ -180,10 +165,6 @@ protected:
|
|||
|
||||
virtual void createGlobalMenu() {
|
||||
}
|
||||
virtual void initShadows() {
|
||||
}
|
||||
virtual void firstShadowsUpdate() {
|
||||
}
|
||||
|
||||
virtual bool initSizeFromSystem() {
|
||||
return false;
|
||||
|
@ -203,7 +184,6 @@ protected:
|
|||
private:
|
||||
void refreshTitleWidget();
|
||||
void updateMinimumSize();
|
||||
void updateShadowSize();
|
||||
void updatePalette();
|
||||
void initSize();
|
||||
|
||||
|
@ -214,7 +194,6 @@ private:
|
|||
base::Timer _positionUpdatedTimer;
|
||||
bool _positionInited = false;
|
||||
|
||||
object_ptr<TitleWidget> _title = { nullptr };
|
||||
object_ptr<Ui::PlainShadow> _titleShadow = { nullptr };
|
||||
object_ptr<Ui::RpWidget> _outdated;
|
||||
object_ptr<Ui::RpWidget> _body;
|
||||
|
@ -222,8 +201,6 @@ private:
|
|||
|
||||
QIcon _icon;
|
||||
bool _usingSupportIcon = false;
|
||||
QString _titleText;
|
||||
style::margins _padding;
|
||||
|
||||
bool _isActive = false;
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "core/application.h"
|
||||
#include "core/click_handler_types.h"
|
||||
#include "export/export_manager.h"
|
||||
#include "ui/platform/ui_platform_window.h"
|
||||
#include "platform/platform_window_title.h"
|
||||
#include "main/main_account.h"
|
||||
#include "main/main_domain.h"
|
||||
|
@ -267,7 +268,7 @@ void Controller::showSettings() {
|
|||
|
||||
int Controller::verticalShadowTop() const {
|
||||
return (Platform::NativeTitleRequiresShadow()
|
||||
&& Platform::AllowNativeWindowFrameToggle()
|
||||
&& Ui::Platform::NativeWindowFrameSupported()
|
||||
&& Core::App().settings().nativeWindowFrame())
|
||||
? st::lineWidth
|
||||
: 0;
|
||||
|
|
|
@ -1,44 +0,0 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "ui/rp_widget.h"
|
||||
|
||||
namespace Window {
|
||||
|
||||
enum class HitTestResult {
|
||||
None = 0,
|
||||
Client,
|
||||
SysButton,
|
||||
Caption,
|
||||
Top,
|
||||
TopRight,
|
||||
Right,
|
||||
BottomRight,
|
||||
Bottom,
|
||||
BottomLeft,
|
||||
Left,
|
||||
TopLeft,
|
||||
};
|
||||
|
||||
class TitleWidget : public Ui::RpWidget {
|
||||
public:
|
||||
using RpWidget::RpWidget;
|
||||
|
||||
virtual void init() {
|
||||
}
|
||||
virtual HitTestResult hitTest(const QPoint &p) const {
|
||||
return HitTestResult::None;
|
||||
}
|
||||
virtual QRect iconRect() const {
|
||||
return QRect();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // namespace Window
|
|
@ -1,417 +0,0 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#include "window/window_title_qt.h"
|
||||
|
||||
#include "ui/platform/ui_platform_utility.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/shadow.h"
|
||||
#include "styles/style_widgets.h"
|
||||
#include "styles/style_window.h"
|
||||
|
||||
#include <QtCore/QCoreApplication>
|
||||
#include <QtGui/QGuiApplication>
|
||||
#include <QtGui/QWindow>
|
||||
|
||||
namespace Window {
|
||||
namespace {
|
||||
|
||||
[[nodiscard]] style::margins ShadowExtents() {
|
||||
return st::callShadow.extend;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void RemoveDuplicates(std::vector<T> &v) {
|
||||
auto end = v.end();
|
||||
for (auto it = v.begin(); it != end; ++it) {
|
||||
end = std::remove(it + 1, end, *it);
|
||||
}
|
||||
|
||||
v.erase(end, v.end());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TitleWidgetQt::TitleWidgetQt(QWidget *parent)
|
||||
: TitleWidget(parent)
|
||||
, _st(st::defaultWindowTitle)
|
||||
, _minimize(this, _st.minimize)
|
||||
, _maximizeRestore(this, _st.maximize)
|
||||
, _close(this, _st.close)
|
||||
, _shadow(this, st::titleShadow)
|
||||
, _maximizedState(parent->window()->windowState() & Qt::WindowMaximized) {
|
||||
_minimize->setClickedCallback([=] {
|
||||
window()->setWindowState(
|
||||
window()->windowState() | Qt::WindowMinimized);
|
||||
_minimize->clearState();
|
||||
});
|
||||
_minimize->setPointerCursor(false);
|
||||
_maximizeRestore->setClickedCallback([=] {
|
||||
window()->setWindowState(_maximizedState
|
||||
? Qt::WindowNoState
|
||||
: Qt::WindowMaximized);
|
||||
_maximizeRestore->clearState();
|
||||
});
|
||||
_maximizeRestore->setPointerCursor(false);
|
||||
_close->setClickedCallback([=] {
|
||||
window()->close();
|
||||
_close->clearState();
|
||||
});
|
||||
_close->setPointerCursor(false);
|
||||
|
||||
Ui::Platform::TitleControlsLayoutChanged(
|
||||
) | rpl::start_with_next([=] {
|
||||
updateControlsPosition();
|
||||
}, lifetime());
|
||||
|
||||
QCoreApplication::instance()->installEventFilter(this);
|
||||
|
||||
_windowWasFrameless = (window()->windowFlags()
|
||||
& Qt::FramelessWindowHint) != 0;
|
||||
|
||||
if (!_windowWasFrameless) {
|
||||
toggleFramelessWindow(true);
|
||||
}
|
||||
|
||||
setAttribute(Qt::WA_OpaquePaintEvent);
|
||||
resize(width(), _st.height);
|
||||
|
||||
updateWindowExtents();
|
||||
}
|
||||
|
||||
TitleWidgetQt::~TitleWidgetQt() {
|
||||
restoreCursor();
|
||||
|
||||
if (!_windowWasFrameless) {
|
||||
toggleFramelessWindow(false);
|
||||
}
|
||||
|
||||
if (_extentsSet) {
|
||||
Ui::Platform::UnsetWindowExtents(window()->windowHandle());
|
||||
}
|
||||
}
|
||||
|
||||
void TitleWidgetQt::init() {
|
||||
connect(
|
||||
window()->windowHandle(),
|
||||
&QWindow::windowStateChanged,
|
||||
this,
|
||||
[=](Qt::WindowState state) { windowStateChanged(state); });
|
||||
connect(
|
||||
window()->windowHandle(),
|
||||
&QWindow::visibleChanged,
|
||||
this,
|
||||
[=](bool visible) { visibleChanged(visible); });
|
||||
_maximizedState = (window()->windowState() & Qt::WindowMaximized);
|
||||
_activeState = isActiveWindow();
|
||||
updateButtonsState();
|
||||
}
|
||||
|
||||
bool TitleWidgetQt::hasShadow() const {
|
||||
const auto center = window()->geometry().center();
|
||||
return Ui::Platform::WindowExtentsSupported()
|
||||
&& Ui::Platform::TranslucentWindowsSupported(center);
|
||||
}
|
||||
|
||||
Ui::IconButton *TitleWidgetQt::controlWidget(Control control) const {
|
||||
switch (control) {
|
||||
case Control::Minimize: return _minimize;
|
||||
case Control::Maximize: return _maximizeRestore;
|
||||
case Control::Close: return _close;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void TitleWidgetQt::paintEvent(QPaintEvent *e) {
|
||||
auto active = isActiveWindow();
|
||||
if (_activeState != active) {
|
||||
_activeState = active;
|
||||
updateButtonsState();
|
||||
}
|
||||
Painter(this).fillRect(rect(), active ? _st.bgActive : _st.bg);
|
||||
}
|
||||
|
||||
void TitleWidgetQt::toggleFramelessWindow(bool enabled) {
|
||||
window()->windowHandle()->setFlag(Qt::FramelessWindowHint, enabled);
|
||||
}
|
||||
|
||||
void TitleWidgetQt::updateWindowExtents() {
|
||||
if (hasShadow()) {
|
||||
Ui::Platform::SetWindowExtents(
|
||||
window()->windowHandle(),
|
||||
resizeArea());
|
||||
|
||||
_extentsSet = true;
|
||||
} else if (_extentsSet) {
|
||||
Ui::Platform::UnsetWindowExtents(window()->windowHandle());
|
||||
_extentsSet = false;
|
||||
}
|
||||
}
|
||||
|
||||
void TitleWidgetQt::updateControlsPosition() {
|
||||
const auto controlsLayout = Ui::Platform::TitleControlsLayout();
|
||||
const auto controlsLeft = controlsLayout.left;
|
||||
const auto controlsRight = controlsLayout.right;
|
||||
|
||||
const auto controlPresent = [&](Control control) {
|
||||
return ranges::contains(controlsLeft, control)
|
||||
|| ranges::contains(controlsRight, control);
|
||||
};
|
||||
|
||||
if (controlPresent(Control::Minimize)) {
|
||||
_minimize->show();
|
||||
} else {
|
||||
_minimize->hide();
|
||||
}
|
||||
|
||||
if (controlPresent(Control::Maximize)) {
|
||||
_maximizeRestore->show();
|
||||
} else {
|
||||
_maximizeRestore->hide();
|
||||
}
|
||||
|
||||
if (controlPresent(Control::Close)) {
|
||||
_close->show();
|
||||
} else {
|
||||
_close->hide();
|
||||
}
|
||||
|
||||
updateControlsPositionBySide(controlsLeft, false);
|
||||
updateControlsPositionBySide(controlsRight, true);
|
||||
}
|
||||
|
||||
void TitleWidgetQt::updateControlsPositionBySide(
|
||||
const std::vector<Control> &controls,
|
||||
bool right) {
|
||||
auto preparedControls = right
|
||||
? (ranges::views::reverse(controls) | ranges::to_vector)
|
||||
: controls;
|
||||
|
||||
RemoveDuplicates(preparedControls);
|
||||
|
||||
auto position = 0;
|
||||
for (const auto &control : preparedControls) {
|
||||
const auto widget = controlWidget(control);
|
||||
if (!widget) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (right) {
|
||||
widget->moveToRight(position, 0);
|
||||
} else {
|
||||
widget->moveToLeft(position, 0);
|
||||
}
|
||||
|
||||
position += widget->width();
|
||||
}
|
||||
}
|
||||
|
||||
void TitleWidgetQt::resizeEvent(QResizeEvent *e) {
|
||||
updateControlsPosition();
|
||||
_shadow->setGeometry(0, height() - st::lineWidth, width(), st::lineWidth);
|
||||
}
|
||||
|
||||
void TitleWidgetQt::mousePressEvent(QMouseEvent *e) {
|
||||
if (e->button() == Qt::LeftButton) {
|
||||
_mousePressed = true;
|
||||
} else if (e->button() == Qt::RightButton) {
|
||||
Ui::Platform::ShowWindowMenu(window()->windowHandle());
|
||||
}
|
||||
}
|
||||
|
||||
void TitleWidgetQt::mouseReleaseEvent(QMouseEvent *e) {
|
||||
if (e->button() == Qt::LeftButton) {
|
||||
_mousePressed = false;
|
||||
}
|
||||
}
|
||||
|
||||
void TitleWidgetQt::mouseMoveEvent(QMouseEvent *e) {
|
||||
if (_mousePressed) {
|
||||
window()->windowHandle()->startSystemMove();
|
||||
}
|
||||
}
|
||||
|
||||
void TitleWidgetQt::mouseDoubleClickEvent(QMouseEvent *e) {
|
||||
if (_maximizedState) {
|
||||
window()->setWindowState(Qt::WindowNoState);
|
||||
} else {
|
||||
window()->setWindowState(Qt::WindowMaximized);
|
||||
}
|
||||
}
|
||||
|
||||
bool TitleWidgetQt::eventFilter(QObject *obj, QEvent *e) {
|
||||
if (e->type() == QEvent::MouseMove
|
||||
|| e->type() == QEvent::MouseButtonPress) {
|
||||
if (obj->isWidgetType()
|
||||
&& window()->isAncestorOf(static_cast<QWidget*>(obj))) {
|
||||
const auto mouseEvent = static_cast<QMouseEvent*>(e);
|
||||
const auto currentPoint = mouseEvent->windowPos().toPoint();
|
||||
const auto edges = edgesFromPos(currentPoint);
|
||||
|
||||
if (e->type() == QEvent::MouseMove
|
||||
&& mouseEvent->buttons() == Qt::NoButton) {
|
||||
if (_mousePressed) {
|
||||
_mousePressed = false;
|
||||
}
|
||||
|
||||
updateCursor(edges);
|
||||
}
|
||||
|
||||
if (e->type() == QEvent::MouseButtonPress
|
||||
&& mouseEvent->button() == Qt::LeftButton
|
||||
&& edges) {
|
||||
return window()->windowHandle()->startSystemResize(edges);
|
||||
}
|
||||
}
|
||||
} else if (e->type() == QEvent::Leave) {
|
||||
if (obj->isWidgetType() && window() == static_cast<QWidget*>(obj)) {
|
||||
restoreCursor();
|
||||
}
|
||||
} else if (e->type() == QEvent::Move
|
||||
|| e->type() == QEvent::Resize) {
|
||||
if (obj->isWidgetType() && window() == static_cast<QWidget*>(obj)) {
|
||||
updateWindowExtents();
|
||||
}
|
||||
}
|
||||
|
||||
return TitleWidget::eventFilter(obj, e);
|
||||
}
|
||||
|
||||
void TitleWidgetQt::windowStateChanged(Qt::WindowState state) {
|
||||
if (state == Qt::WindowMinimized) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto maximized = (state == Qt::WindowMaximized);
|
||||
if (_maximizedState != maximized) {
|
||||
_maximizedState = maximized;
|
||||
updateButtonsState();
|
||||
updateWindowExtents();
|
||||
}
|
||||
}
|
||||
|
||||
void TitleWidgetQt::visibleChanged(bool visible) {
|
||||
if (visible) {
|
||||
updateWindowExtents();
|
||||
|
||||
// workaround a bug in Qt 5.12, works ok in Qt 5.15
|
||||
// https://github.com/telegramdesktop/tdesktop/issues/10119
|
||||
if (!_windowWasFrameless) {
|
||||
toggleFramelessWindow(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TitleWidgetQt::updateButtonsState() {
|
||||
_minimize->setIconOverride(_activeState
|
||||
? &_st.minimizeIconActive
|
||||
: nullptr,
|
||||
_activeState
|
||||
? &_st.minimizeIconActiveOver
|
||||
: nullptr);
|
||||
if (_maximizedState) {
|
||||
_maximizeRestore->setIconOverride(
|
||||
_activeState
|
||||
? &_st.restoreIconActive : &_st.restoreIcon,
|
||||
_activeState
|
||||
? &_st.restoreIconActiveOver
|
||||
: &_st.restoreIconOver);
|
||||
} else {
|
||||
_maximizeRestore->setIconOverride(_activeState
|
||||
? &_st.maximizeIconActive
|
||||
: nullptr,
|
||||
_activeState
|
||||
? &_st.maximizeIconActiveOver
|
||||
: nullptr);
|
||||
}
|
||||
_close->setIconOverride(_activeState
|
||||
? &_st.closeIconActive
|
||||
: nullptr,
|
||||
_activeState
|
||||
? &_st.closeIconActiveOver
|
||||
: nullptr);
|
||||
}
|
||||
|
||||
QMargins TitleWidgetQt::resizeArea() const {
|
||||
if (_maximizedState) {
|
||||
return QMargins();
|
||||
} else if (!hasShadow()) {
|
||||
return QMargins(
|
||||
st::windowResizeArea,
|
||||
st::windowResizeArea,
|
||||
st::windowResizeArea,
|
||||
st::windowResizeArea);
|
||||
}
|
||||
|
||||
return ShadowExtents();
|
||||
}
|
||||
|
||||
Qt::Edges TitleWidgetQt::edgesFromPos(const QPoint &pos) const {
|
||||
const auto area = resizeArea();
|
||||
|
||||
if (area.isNull()) {
|
||||
return Qt::Edges();
|
||||
} else if (pos.x() <= area.left()) {
|
||||
if (pos.y() <= area.top()) {
|
||||
return Qt::LeftEdge | Qt::TopEdge;
|
||||
} else if (pos.y() >= (window()->height() - area.bottom())) {
|
||||
return Qt::LeftEdge | Qt::BottomEdge;
|
||||
}
|
||||
|
||||
return Qt::LeftEdge;
|
||||
} else if (pos.x() >= (window()->width() - area.right())) {
|
||||
if (pos.y() <= area.top()) {
|
||||
return Qt::RightEdge | Qt::TopEdge;
|
||||
} else if (pos.y() >= (window()->height() - area.bottom())) {
|
||||
return Qt::RightEdge | Qt::BottomEdge;
|
||||
}
|
||||
|
||||
return Qt::RightEdge;
|
||||
} else if (pos.y() <= area.top()) {
|
||||
return Qt::TopEdge;
|
||||
} else if (pos.y() >= (window()->height() - area.bottom())) {
|
||||
return Qt::BottomEdge;
|
||||
}
|
||||
|
||||
return Qt::Edges();
|
||||
}
|
||||
|
||||
void TitleWidgetQt::updateCursor(Qt::Edges edges) {
|
||||
if (!edges) {
|
||||
restoreCursor();
|
||||
return;
|
||||
} else if (!QGuiApplication::overrideCursor()) {
|
||||
_cursorOverriden = false;
|
||||
}
|
||||
|
||||
if (!_cursorOverriden) {
|
||||
_cursorOverriden = true;
|
||||
QGuiApplication::setOverrideCursor(QCursor());
|
||||
}
|
||||
|
||||
if (((edges & Qt::LeftEdge) && (edges & Qt::TopEdge))
|
||||
|| ((edges & Qt::RightEdge) && (edges & Qt::BottomEdge))) {
|
||||
QGuiApplication::changeOverrideCursor(QCursor(Qt::SizeFDiagCursor));
|
||||
} else if (((edges & Qt::LeftEdge) && (edges & Qt::BottomEdge))
|
||||
|| ((edges & Qt::RightEdge) && (edges & Qt::TopEdge))) {
|
||||
QGuiApplication::changeOverrideCursor(QCursor(Qt::SizeBDiagCursor));
|
||||
} else if ((edges & Qt::LeftEdge) || (edges & Qt::RightEdge)) {
|
||||
QGuiApplication::changeOverrideCursor(QCursor(Qt::SizeHorCursor));
|
||||
} else if ((edges & Qt::TopEdge) || (edges & Qt::BottomEdge)) {
|
||||
QGuiApplication::changeOverrideCursor(QCursor(Qt::SizeVerCursor));
|
||||
}
|
||||
}
|
||||
|
||||
void TitleWidgetQt::restoreCursor() {
|
||||
if (_cursorOverriden) {
|
||||
_cursorOverriden = false;
|
||||
QGuiApplication::restoreOverrideCursor();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Window
|
|
@ -1,77 +0,0 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "window/window_title.h"
|
||||
#include "ui/platform/ui_platform_window_title.h"
|
||||
#include "base/object_ptr.h"
|
||||
|
||||
namespace style {
|
||||
struct WindowTitle;
|
||||
} // namespace style
|
||||
|
||||
namespace Ui {
|
||||
class IconButton;
|
||||
class PlainShadow;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Window {
|
||||
|
||||
class TitleWidgetQt : public TitleWidget {
|
||||
public:
|
||||
using Control = Ui::Platform::TitleControls::Control;
|
||||
|
||||
TitleWidgetQt(QWidget *parent);
|
||||
~TitleWidgetQt();
|
||||
|
||||
void init() override;
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
void resizeEvent(QResizeEvent *e) override;
|
||||
void mousePressEvent(QMouseEvent *e) override;
|
||||
void mouseReleaseEvent(QMouseEvent *e) override;
|
||||
void mouseMoveEvent(QMouseEvent *e) override;
|
||||
void mouseDoubleClickEvent(QMouseEvent *e) override;
|
||||
|
||||
bool eventFilter(QObject *obj, QEvent *e) override;
|
||||
|
||||
private:
|
||||
void windowStateChanged(Qt::WindowState state = Qt::WindowNoState);
|
||||
void visibleChanged(bool visible);
|
||||
void updateWindowExtents();
|
||||
void updateButtonsState();
|
||||
void updateControlsPosition();
|
||||
void updateControlsPositionBySide(
|
||||
const std::vector<Control> &controls,
|
||||
bool right);
|
||||
|
||||
void toggleFramelessWindow(bool enabled);
|
||||
bool hasShadow() const;
|
||||
Ui::IconButton *controlWidget(Control control) const;
|
||||
QMargins resizeArea() const;
|
||||
Qt::Edges edgesFromPos(const QPoint &pos) const;
|
||||
void updateCursor(Qt::Edges edges);
|
||||
void restoreCursor();
|
||||
|
||||
const style::WindowTitle &_st;
|
||||
object_ptr<Ui::IconButton> _minimize;
|
||||
object_ptr<Ui::IconButton> _maximizeRestore;
|
||||
object_ptr<Ui::IconButton> _close;
|
||||
object_ptr<Ui::PlainShadow> _shadow;
|
||||
|
||||
bool _maximizedState = false;
|
||||
bool _activeState = false;
|
||||
bool _windowWasFrameless = false;
|
||||
bool _cursorOverriden = false;
|
||||
bool _extentsSet = false;
|
||||
bool _mousePressed = false;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Window
|
Loading…
Add table
Reference in a new issue