Add main window shadow for Linux
This commit is contained in:
		
							parent
							
								
									c529974da5
								
							
						
					
					
						commit
						d02092f09e
					
				
					 9 changed files with 352 additions and 49 deletions
				
			
		| 
						 | 
					@ -39,6 +39,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 | 
				
			||||||
#include "apiwrap.h"
 | 
					#include "apiwrap.h"
 | 
				
			||||||
#include "api/api_updates.h"
 | 
					#include "api/api_updates.h"
 | 
				
			||||||
#include "settings/settings_intro.h"
 | 
					#include "settings/settings_intro.h"
 | 
				
			||||||
 | 
					#include "platform/platform_specific.h"
 | 
				
			||||||
#include "platform/platform_notifications_manager.h"
 | 
					#include "platform/platform_notifications_manager.h"
 | 
				
			||||||
#include "base/platform/base_platform_info.h"
 | 
					#include "base/platform/base_platform_info.h"
 | 
				
			||||||
#include "base/call_delayed.h"
 | 
					#include "base/call_delayed.h"
 | 
				
			||||||
| 
						 | 
					@ -110,7 +111,10 @@ MainWindow::MainWindow(not_null<Window::Controller*> controller)
 | 
				
			||||||
	}, lifetime());
 | 
						}, lifetime());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	setAttribute(Qt::WA_NoSystemBackground);
 | 
						setAttribute(Qt::WA_NoSystemBackground);
 | 
				
			||||||
	setAttribute(Qt::WA_OpaquePaintEvent);
 | 
					
 | 
				
			||||||
 | 
						if (Platform::WindowsNeedShadow()) {
 | 
				
			||||||
 | 
							setAttribute(Qt::WA_TranslucentBackground);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void MainWindow::initHook() {
 | 
					void MainWindow::initHook() {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -81,6 +81,8 @@ constexpr auto kXDGDesktopPortalService = "org.freedesktop.portal.Desktop"_cs;
 | 
				
			||||||
constexpr auto kXDGDesktopPortalObjectPath = "/org/freedesktop/portal/desktop"_cs;
 | 
					constexpr auto kXDGDesktopPortalObjectPath = "/org/freedesktop/portal/desktop"_cs;
 | 
				
			||||||
constexpr auto kPropertiesInterface = "org.freedesktop.DBus.Properties"_cs;
 | 
					constexpr auto kPropertiesInterface = "org.freedesktop.DBus.Properties"_cs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					constexpr auto kXCBFrameExtentsAtomName = "_GTK_FRAME_EXTENTS"_cs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
QStringList PlatformThemes;
 | 
					QStringList PlatformThemes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool IsTrayIconSupported = true;
 | 
					bool IsTrayIconSupported = true;
 | 
				
			||||||
| 
						 | 
					@ -298,6 +300,91 @@ bool GetImageFromClipboardSupported() {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION
 | 
					#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					std::optional<xcb_atom_t> GetXCBAtom(
 | 
				
			||||||
 | 
							xcb_connection_t *connection,
 | 
				
			||||||
 | 
							const QString &name) {
 | 
				
			||||||
 | 
						const auto cookie = xcb_intern_atom(
 | 
				
			||||||
 | 
							connection,
 | 
				
			||||||
 | 
							0,
 | 
				
			||||||
 | 
							name.size(),
 | 
				
			||||||
 | 
							name.toUtf8());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto reply = xcb_intern_atom_reply(
 | 
				
			||||||
 | 
							connection,
 | 
				
			||||||
 | 
							cookie,
 | 
				
			||||||
 | 
							nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!reply) {
 | 
				
			||||||
 | 
							return std::nullopt;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const auto atom = reply->atom;
 | 
				
			||||||
 | 
						free(reply);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return atom;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					std::vector<xcb_atom_t> GetXCBWMSupported(xcb_connection_t *connection) {
 | 
				
			||||||
 | 
						auto netWmAtoms = std::vector<xcb_atom_t>{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const auto native = QGuiApplication::platformNativeInterface();
 | 
				
			||||||
 | 
						if (!native) {
 | 
				
			||||||
 | 
							return netWmAtoms;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const auto root = static_cast<xcb_window_t>(reinterpret_cast<quintptr>(
 | 
				
			||||||
 | 
							native->nativeResourceForIntegration(QByteArray("rootwindow"))));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const auto supportedAtom = GetXCBAtom(connection, "_NET_SUPPORTED");
 | 
				
			||||||
 | 
						if (!supportedAtom.has_value()) {
 | 
				
			||||||
 | 
							return netWmAtoms;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto offset = 0;
 | 
				
			||||||
 | 
						auto remaining = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						do {
 | 
				
			||||||
 | 
							const auto cookie = xcb_get_property(
 | 
				
			||||||
 | 
								connection,
 | 
				
			||||||
 | 
								false,
 | 
				
			||||||
 | 
								root,
 | 
				
			||||||
 | 
								*supportedAtom,
 | 
				
			||||||
 | 
								XCB_ATOM_ATOM,
 | 
				
			||||||
 | 
								offset,
 | 
				
			||||||
 | 
								1024);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							auto reply = xcb_get_property_reply(
 | 
				
			||||||
 | 
								connection,
 | 
				
			||||||
 | 
								cookie,
 | 
				
			||||||
 | 
								nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!reply) {
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							remaining = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (reply->type == XCB_ATOM_ATOM && reply->format == 32) {
 | 
				
			||||||
 | 
								const auto len = xcb_get_property_value_length(reply)
 | 
				
			||||||
 | 
									/ sizeof(xcb_atom_t);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								const auto atoms = reinterpret_cast<xcb_atom_t*>(
 | 
				
			||||||
 | 
									xcb_get_property_value(reply));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								const auto s = netWmAtoms.size();
 | 
				
			||||||
 | 
								netWmAtoms.resize(s + len);
 | 
				
			||||||
 | 
								memcpy(netWmAtoms.data() + s, atoms, len * sizeof(xcb_atom_t));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								remaining = reply->bytes_after;
 | 
				
			||||||
 | 
								offset += len;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							free(reply);
 | 
				
			||||||
 | 
						} while (remaining > 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return netWmAtoms;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
std::optional<crl::time> XCBLastUserInputTime() {
 | 
					std::optional<crl::time> XCBLastUserInputTime() {
 | 
				
			||||||
	if (const auto native = QGuiApplication::platformNativeInterface()) {
 | 
						if (const auto native = QGuiApplication::platformNativeInterface()) {
 | 
				
			||||||
		const auto connection = reinterpret_cast<xcb_connection_t*>(
 | 
							const auto connection = reinterpret_cast<xcb_connection_t*>(
 | 
				
			||||||
| 
						 | 
					@ -318,17 +405,17 @@ std::optional<crl::time> XCBLastUserInputTime() {
 | 
				
			||||||
			connection,
 | 
								connection,
 | 
				
			||||||
			screen->root);
 | 
								screen->root);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		auto info = xcb_screensaver_query_info_reply(
 | 
							auto reply = xcb_screensaver_query_info_reply(
 | 
				
			||||||
			connection,
 | 
								connection,
 | 
				
			||||||
			cookie,
 | 
								cookie,
 | 
				
			||||||
			nullptr);
 | 
								nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!info) {
 | 
							if (!reply) {
 | 
				
			||||||
			return std::nullopt;
 | 
								return std::nullopt;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		const auto idle = info->ms_since_user_input;
 | 
							const auto idle = reply->ms_since_user_input;
 | 
				
			||||||
		free(info);
 | 
							free(reply);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return (crl::now() - static_cast<crl::time>(idle));
 | 
							return (crl::now() - static_cast<crl::time>(idle));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -471,7 +558,6 @@ enum wl_shell_surface_resize WlResizeFromEdges(Qt::Edges edges) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool StartXCBMoveResize(QWindow *window, int edges) {
 | 
					bool StartXCBMoveResize(QWindow *window, int edges) {
 | 
				
			||||||
	const auto native = QGuiApplication::platformNativeInterface();
 | 
						const auto native = QGuiApplication::platformNativeInterface();
 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!native) {
 | 
						if (!native) {
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -490,29 +576,16 @@ bool StartXCBMoveResize(QWindow *window, int edges) {
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const auto moveResizeCookie = xcb_intern_atom(
 | 
						const auto moveResize = GetXCBAtom(connection, "_NET_WM_MOVERESIZE");
 | 
				
			||||||
		connection,
 | 
						if (!moveResize.has_value()) {
 | 
				
			||||||
		0,
 | 
					 | 
				
			||||||
		strlen("_NET_WM_MOVERESIZE"),
 | 
					 | 
				
			||||||
		"_NET_WM_MOVERESIZE");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	auto moveResizeReply = xcb_intern_atom_reply(
 | 
					 | 
				
			||||||
		connection,
 | 
					 | 
				
			||||||
		moveResizeCookie,
 | 
					 | 
				
			||||||
		nullptr);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!moveResizeReply) {
 | 
					 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const auto moveResize = moveResizeReply->atom;
 | 
					 | 
				
			||||||
	free(moveResizeReply);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	const auto globalPos = QCursor::pos();
 | 
						const auto globalPos = QCursor::pos();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	xcb_client_message_event_t xev;
 | 
						xcb_client_message_event_t xev;
 | 
				
			||||||
	xev.response_type = XCB_CLIENT_MESSAGE;
 | 
						xev.response_type = XCB_CLIENT_MESSAGE;
 | 
				
			||||||
	xev.type = moveResize;
 | 
						xev.type = *moveResize;
 | 
				
			||||||
	xev.sequence = 0;
 | 
						xev.sequence = 0;
 | 
				
			||||||
	xev.window = window->winId();
 | 
						xev.window = window->winId();
 | 
				
			||||||
	xev.format = 32;
 | 
						xev.format = 32;
 | 
				
			||||||
| 
						 | 
					@ -585,6 +658,87 @@ bool ShowWaylandWindowMenu(QWindow *window) {
 | 
				
			||||||
	return false;
 | 
						return false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool XCBFrameExtentsSupported() {
 | 
				
			||||||
 | 
						const auto native = QGuiApplication::platformNativeInterface();
 | 
				
			||||||
 | 
						if (!native) {
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const auto connection = reinterpret_cast<xcb_connection_t*>(
 | 
				
			||||||
 | 
							native->nativeResourceForIntegration(QByteArray("connection")));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!connection) {
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const auto frameExtentsAtom = GetXCBAtom(
 | 
				
			||||||
 | 
							connection,
 | 
				
			||||||
 | 
							kXCBFrameExtentsAtomName.utf16());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!frameExtentsAtom.has_value()) {
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ranges::contains(GetXCBWMSupported(connection), *frameExtentsAtom);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool SetXCBFrameExtents(QWindow *window, const QMargins &extents) {
 | 
				
			||||||
 | 
						const auto native = QGuiApplication::platformNativeInterface();
 | 
				
			||||||
 | 
						if (!native) {
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const auto connection = reinterpret_cast<xcb_connection_t*>(
 | 
				
			||||||
 | 
							native->nativeResourceForIntegration(QByteArray("connection")));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!connection) {
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const auto frameExtentsAtom = GetXCBAtom(
 | 
				
			||||||
 | 
							connection,
 | 
				
			||||||
 | 
							kXCBFrameExtentsAtomName.utf16());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!frameExtentsAtom.has_value()) {
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const auto extentsVector = std::vector<uint>{
 | 
				
			||||||
 | 
							uint(extents.left()),
 | 
				
			||||||
 | 
							uint(extents.right()),
 | 
				
			||||||
 | 
							uint(extents.top()),
 | 
				
			||||||
 | 
							uint(extents.bottom()),
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						xcb_change_property(
 | 
				
			||||||
 | 
							connection,
 | 
				
			||||||
 | 
							XCB_PROP_MODE_REPLACE,
 | 
				
			||||||
 | 
							window->winId(),
 | 
				
			||||||
 | 
							*frameExtentsAtom,
 | 
				
			||||||
 | 
							XCB_ATOM_CARDINAL,
 | 
				
			||||||
 | 
							32,
 | 
				
			||||||
 | 
							extentsVector.size(),
 | 
				
			||||||
 | 
							extentsVector.data());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool SetWaylandWindowGeometry(QWindow *window, const QRect &geometry) {
 | 
				
			||||||
 | 
					#if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0) || defined DESKTOP_APP_QT_PATCHED
 | 
				
			||||||
 | 
						if (const auto waylandWindow = static_cast<QWaylandWindow*>(
 | 
				
			||||||
 | 
							window->handle())) {
 | 
				
			||||||
 | 
							if (const auto seat = waylandWindow->display()->lastInputDevice()) {
 | 
				
			||||||
 | 
								if (const auto shellSurface = waylandWindow->shellSurface()) {
 | 
				
			||||||
 | 
									shellSurface->setWindowGeometry(geometry);
 | 
				
			||||||
 | 
									return true;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					#endif // Qt >= 5.13 || DESKTOP_APP_QT_PATCHED
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Window::Control GtkKeywordToWindowControl(const QString &keyword) {
 | 
					Window::Control GtkKeywordToWindowControl(const QString &keyword) {
 | 
				
			||||||
	if (keyword == qstr("minimize")) {
 | 
						if (keyword == qstr("minimize")) {
 | 
				
			||||||
		return Window::Control::Minimize;
 | 
							return Window::Control::Minimize;
 | 
				
			||||||
| 
						 | 
					@ -929,6 +1083,31 @@ bool ShowWindowMenu(QWindow *window) {
 | 
				
			||||||
	return false;
 | 
						return false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool SetWindowExtents(QWindow *window, const QMargins &extents) {
 | 
				
			||||||
 | 
						if (IsWayland()) {
 | 
				
			||||||
 | 
							const auto geometry = QRect(QPoint(), window->size())
 | 
				
			||||||
 | 
								.marginsRemoved(extents);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return SetWaylandWindowGeometry(window, geometry);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							return SetXCBFrameExtents(window, extents);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool WindowsNeedShadow() {
 | 
				
			||||||
 | 
					#if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0) || defined DESKTOP_APP_QT_PATCHED
 | 
				
			||||||
 | 
						if (IsWayland()) {
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					#endif // Qt >= 5.13 || DESKTOP_APP_QT_PATCHED
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!IsWayland() && XCBFrameExtentsSupported()) {
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Window::ControlsLayout WindowControlsLayout() {
 | 
					Window::ControlsLayout WindowControlsLayout() {
 | 
				
			||||||
#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION
 | 
					#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION
 | 
				
			||||||
	if (Libs::GtkSettingSupported()
 | 
						if (Libs::GtkSettingSupported()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -44,6 +44,10 @@ inline bool TrayIconSupported() {
 | 
				
			||||||
	return true;
 | 
						return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline bool WindowsNeedShadow() {
 | 
				
			||||||
 | 
						return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace ThirdParty {
 | 
					namespace ThirdParty {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
inline void start() {
 | 
					inline void start() {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -56,6 +56,8 @@ QImage GetImageFromClipboard();
 | 
				
			||||||
bool StartSystemMove(QWindow *window);
 | 
					bool StartSystemMove(QWindow *window);
 | 
				
			||||||
bool StartSystemResize(QWindow *window, Qt::Edges edges);
 | 
					bool StartSystemResize(QWindow *window, Qt::Edges edges);
 | 
				
			||||||
bool ShowWindowMenu(QWindow *window);
 | 
					bool ShowWindowMenu(QWindow *window);
 | 
				
			||||||
 | 
					bool WindowsNeedShadow();
 | 
				
			||||||
 | 
					bool SetWindowExtents(QWindow *window, const QMargins &extents);
 | 
				
			||||||
Window::ControlsLayout WindowControlsLayout();
 | 
					Window::ControlsLayout WindowControlsLayout();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace ThirdParty {
 | 
					namespace ThirdParty {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -38,6 +38,10 @@ inline bool TrayIconSupported() {
 | 
				
			||||||
	return true;
 | 
						return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline bool WindowsNeedShadow() {
 | 
				
			||||||
 | 
						return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace ThirdParty {
 | 
					namespace ThirdParty {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void start();
 | 
					void start();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 | 
				
			||||||
#include "storage/localstorage.h"
 | 
					#include "storage/localstorage.h"
 | 
				
			||||||
#include "platform/platform_window_title.h"
 | 
					#include "platform/platform_window_title.h"
 | 
				
			||||||
#include "base/platform/base_platform_info.h"
 | 
					#include "base/platform/base_platform_info.h"
 | 
				
			||||||
 | 
					#include "ui/platform/ui_platform_utility.h"
 | 
				
			||||||
#include "history/history.h"
 | 
					#include "history/history.h"
 | 
				
			||||||
#include "window/themes/window_theme.h"
 | 
					#include "window/themes/window_theme.h"
 | 
				
			||||||
#include "window/window_session_controller.h"
 | 
					#include "window/window_session_controller.h"
 | 
				
			||||||
| 
						 | 
					@ -33,6 +34,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 | 
				
			||||||
#include "facades.h"
 | 
					#include "facades.h"
 | 
				
			||||||
#include "app.h"
 | 
					#include "app.h"
 | 
				
			||||||
#include "styles/style_window.h"
 | 
					#include "styles/style_window.h"
 | 
				
			||||||
 | 
					#include "styles/style_calls.h" // st::callShadow
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <QtWidgets/QDesktopWidget>
 | 
					#include <QtWidgets/QDesktopWidget>
 | 
				
			||||||
#include <QtCore/QMimeData>
 | 
					#include <QtCore/QMimeData>
 | 
				
			||||||
| 
						 | 
					@ -292,6 +294,17 @@ HitTestResult MainWindow::hitTest(const QPoint &p) const {
 | 
				
			||||||
	return Window::HitTestResult::None;
 | 
						return Window::HitTestResult::None;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool MainWindow::hasShadow() const {
 | 
				
			||||||
 | 
						const auto center = geometry().center();
 | 
				
			||||||
 | 
						return Platform::WindowsNeedShadow()
 | 
				
			||||||
 | 
							&& Ui::Platform::TranslucentWindowsSupported(center)
 | 
				
			||||||
 | 
							&& _title;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					QRect MainWindow::inner() const {
 | 
				
			||||||
 | 
						return rect().marginsRemoved(_padding);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int MainWindow::computeMinWidth() const {
 | 
					int MainWindow::computeMinWidth() const {
 | 
				
			||||||
	auto result = st::windowMinWidth;
 | 
						auto result = st::windowMinWidth;
 | 
				
			||||||
	if (const auto session = _controller->sessionController()) {
 | 
						if (const auto session = _controller->sessionController()) {
 | 
				
			||||||
| 
						 | 
					@ -302,7 +315,7 @@ int MainWindow::computeMinWidth() const {
 | 
				
			||||||
	if (_rightColumn) {
 | 
						if (_rightColumn) {
 | 
				
			||||||
		result += _rightColumn->width();
 | 
							result += _rightColumn->width();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return result;
 | 
						return result + _padding.left() + _padding.right();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int MainWindow::computeMinHeight() const {
 | 
					int MainWindow::computeMinHeight() const {
 | 
				
			||||||
| 
						 | 
					@ -311,10 +324,10 @@ int MainWindow::computeMinHeight() const {
 | 
				
			||||||
		if (!_outdated) {
 | 
							if (!_outdated) {
 | 
				
			||||||
			return 0;
 | 
								return 0;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		_outdated->resizeToWidth(st::windowMinWidth);
 | 
							_outdated->resizeToWidth(st::windowMinWidth - _padding.left() - _padding.right());
 | 
				
			||||||
		return _outdated->height();
 | 
							return _outdated->height();
 | 
				
			||||||
	}();
 | 
						}();
 | 
				
			||||||
	return title + outdated + st::windowMinHeight;
 | 
						return title + outdated + st::windowMinHeight + _padding.top() + _padding.bottom();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void MainWindow::refreshTitleWidget() {
 | 
					void MainWindow::refreshTitleWidget() {
 | 
				
			||||||
| 
						 | 
					@ -337,7 +350,18 @@ void MainWindow::updateMinimumSize() {
 | 
				
			||||||
	setMinimumHeight(computeMinHeight());
 | 
						setMinimumHeight(computeMinHeight());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void MainWindow::updateShadowSize() {
 | 
				
			||||||
 | 
						_padding = hasShadow() && !isMaximized()
 | 
				
			||||||
 | 
							? st::callShadow.extend
 | 
				
			||||||
 | 
							: style::margins();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void MainWindow::recountGeometryConstraints() {
 | 
					void MainWindow::recountGeometryConstraints() {
 | 
				
			||||||
 | 
						const auto hasShadow = this->hasShadow();
 | 
				
			||||||
 | 
						setWindowFlag(Qt::NoDropShadowWindowHint, hasShadow);
 | 
				
			||||||
 | 
						setAttribute(Qt::WA_OpaquePaintEvent, !hasShadow);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						updateShadowSize();
 | 
				
			||||||
	updateMinimumSize();
 | 
						updateMinimumSize();
 | 
				
			||||||
	updateControlsGeometry();
 | 
						updateControlsGeometry();
 | 
				
			||||||
	fixOrder();
 | 
						fixOrder();
 | 
				
			||||||
| 
						 | 
					@ -436,7 +460,15 @@ void MainWindow::attachToTrayIcon(not_null<QSystemTrayIcon*> icon) {
 | 
				
			||||||
	App::wnd()->updateTrayMenu();
 | 
						App::wnd()->updateTrayMenu();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void MainWindow::paintEvent(QPaintEvent *e) {
 | 
				
			||||||
 | 
						if (hasShadow() && !isMaximized()) {
 | 
				
			||||||
 | 
							QPainter p(this);
 | 
				
			||||||
 | 
							Ui::Shadow::paint(p, inner(), width(), st::callShadow);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void MainWindow::resizeEvent(QResizeEvent *e) {
 | 
					void MainWindow::resizeEvent(QResizeEvent *e) {
 | 
				
			||||||
 | 
						updateShadowSize();
 | 
				
			||||||
	updateControlsGeometry();
 | 
						updateControlsGeometry();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -449,27 +481,28 @@ void MainWindow::leaveEventHook(QEvent *e) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void MainWindow::updateControlsGeometry() {
 | 
					void MainWindow::updateControlsGeometry() {
 | 
				
			||||||
	auto bodyLeft = 0;
 | 
						const auto inner = this->inner();
 | 
				
			||||||
	auto bodyTop = 0;
 | 
						auto bodyLeft = inner.x();
 | 
				
			||||||
	auto bodyWidth = width();
 | 
						auto bodyTop = inner.y();
 | 
				
			||||||
 | 
						auto bodyWidth = inner.width();
 | 
				
			||||||
	if (_title && !_title->isHidden()) {
 | 
						if (_title && !_title->isHidden()) {
 | 
				
			||||||
		_title->setGeometry(0, bodyTop, width(), _title->height());
 | 
							_title->setGeometry(inner.x(), bodyTop, inner.width(), _title->height());
 | 
				
			||||||
		bodyTop += _title->height();
 | 
							bodyTop += _title->height();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (_titleShadow) {
 | 
						if (_titleShadow) {
 | 
				
			||||||
		_titleShadow->setGeometry(0, bodyTop, width(), st::lineWidth);
 | 
							_titleShadow->setGeometry(inner.x(), bodyTop, inner.width(), st::lineWidth);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (_outdated) {
 | 
						if (_outdated) {
 | 
				
			||||||
		Ui::SendPendingMoveResizeEvents(_outdated.data());
 | 
							Ui::SendPendingMoveResizeEvents(_outdated.data());
 | 
				
			||||||
		_outdated->resizeToWidth(width());
 | 
							_outdated->resizeToWidth(inner.width());
 | 
				
			||||||
		_outdated->moveToLeft(0, bodyTop);
 | 
							_outdated->moveToLeft(inner.x(), bodyTop);
 | 
				
			||||||
		bodyTop += _outdated->height();
 | 
							bodyTop += _outdated->height();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (_rightColumn) {
 | 
						if (_rightColumn) {
 | 
				
			||||||
		bodyWidth -= _rightColumn->width();
 | 
							bodyWidth -= _rightColumn->width();
 | 
				
			||||||
		_rightColumn->setGeometry(bodyWidth, bodyTop, width() - bodyWidth, height() - bodyTop);
 | 
							_rightColumn->setGeometry(bodyWidth, bodyTop, inner.width() - bodyWidth, inner.height() - (bodyTop - inner.y()));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	_body->setGeometry(bodyLeft, bodyTop, bodyWidth, height() - bodyTop);
 | 
						_body->setGeometry(bodyLeft, bodyTop, bodyWidth, inner.height() - (bodyTop - inner.y()));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void MainWindow::updateUnreadCounter() {
 | 
					void MainWindow::updateUnreadCounter() {
 | 
				
			||||||
| 
						 | 
					@ -599,12 +632,12 @@ void MainWindow::showRightColumn(object_ptr<TWidget> widget) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int MainWindow::maximalExtendBy() const {
 | 
					int MainWindow::maximalExtendBy() const {
 | 
				
			||||||
	auto desktop = QDesktopWidget().availableGeometry(this);
 | 
						auto desktop = QDesktopWidget().availableGeometry(this);
 | 
				
			||||||
	return std::max(desktop.width() - geometry().width(), 0);
 | 
						return std::max(desktop.width() - inner().width(), 0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool MainWindow::canExtendNoMove(int extendBy) const {
 | 
					bool MainWindow::canExtendNoMove(int extendBy) const {
 | 
				
			||||||
	auto desktop = QDesktopWidget().availableGeometry(this);
 | 
						auto desktop = QDesktopWidget().availableGeometry(this);
 | 
				
			||||||
	auto inner = geometry();
 | 
						auto inner = geometry().marginsRemoved(_padding);
 | 
				
			||||||
	auto innerRight = (inner.x() + inner.width() + extendBy);
 | 
						auto innerRight = (inner.x() + inner.width() + extendBy);
 | 
				
			||||||
	auto desktopRight = (desktop.x() + desktop.width());
 | 
						auto desktopRight = (desktop.x() + desktop.width());
 | 
				
			||||||
	return innerRight <= desktopRight;
 | 
						return innerRight <= desktopRight;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -101,12 +101,15 @@ public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void clearWidgets();
 | 
						void clearWidgets();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						QRect inner() const;
 | 
				
			||||||
	int computeMinWidth() const;
 | 
						int computeMinWidth() const;
 | 
				
			||||||
	int computeMinHeight() const;
 | 
						int computeMinHeight() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void recountGeometryConstraints();
 | 
						void recountGeometryConstraints();
 | 
				
			||||||
	virtual void updateControlsGeometry();
 | 
						virtual void updateControlsGeometry();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool hasShadow() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public slots:
 | 
					public slots:
 | 
				
			||||||
	bool minimizeToTray();
 | 
						bool minimizeToTray();
 | 
				
			||||||
	void updateGlobalMenu() {
 | 
						void updateGlobalMenu() {
 | 
				
			||||||
| 
						 | 
					@ -114,6 +117,7 @@ public slots:
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
protected:
 | 
					protected:
 | 
				
			||||||
 | 
						void paintEvent(QPaintEvent *e) override;
 | 
				
			||||||
	void resizeEvent(QResizeEvent *e) override;
 | 
						void resizeEvent(QResizeEvent *e) override;
 | 
				
			||||||
	void leaveEventHook(QEvent *e) override;
 | 
						void leaveEventHook(QEvent *e) override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -179,6 +183,7 @@ protected:
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
	void refreshTitleWidget();
 | 
						void refreshTitleWidget();
 | 
				
			||||||
	void updateMinimumSize();
 | 
						void updateMinimumSize();
 | 
				
			||||||
 | 
						void updateShadowSize();
 | 
				
			||||||
	void updatePalette();
 | 
						void updatePalette();
 | 
				
			||||||
	void initSize();
 | 
						void initSize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -198,6 +203,7 @@ private:
 | 
				
			||||||
	QIcon _icon;
 | 
						QIcon _icon;
 | 
				
			||||||
	bool _usingSupportIcon = false;
 | 
						bool _usingSupportIcon = false;
 | 
				
			||||||
	QString _titleText;
 | 
						QString _titleText;
 | 
				
			||||||
 | 
						style::margins _padding;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool _isActive = false;
 | 
						bool _isActive = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,11 +8,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 | 
				
			||||||
#include "window/window_title_qt.h"
 | 
					#include "window/window_title_qt.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "platform/platform_specific.h"
 | 
					#include "platform/platform_specific.h"
 | 
				
			||||||
 | 
					#include "ui/platform/ui_platform_utility.h"
 | 
				
			||||||
#include "ui/widgets/buttons.h"
 | 
					#include "ui/widgets/buttons.h"
 | 
				
			||||||
#include "ui/widgets/shadow.h"
 | 
					#include "ui/widgets/shadow.h"
 | 
				
			||||||
#include "core/core_settings.h"
 | 
					#include "core/core_settings.h"
 | 
				
			||||||
#include "core/application.h"
 | 
					#include "core/application.h"
 | 
				
			||||||
#include "styles/style_window.h"
 | 
					#include "styles/style_window.h"
 | 
				
			||||||
 | 
					#include "styles/style_calls.h" // st::callShadow
 | 
				
			||||||
#include "base/call_delayed.h"
 | 
					#include "base/call_delayed.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <QtGui/QGuiApplication>
 | 
					#include <QtGui/QGuiApplication>
 | 
				
			||||||
| 
						 | 
					@ -27,6 +29,10 @@ namespace {
 | 
				
			||||||
// that window. If we show the window back with this delay it works.
 | 
					// that window. If we show the window back with this delay it works.
 | 
				
			||||||
constexpr auto kShowAfterFramelessToggleDelay = crl::time(1000);
 | 
					constexpr auto kShowAfterFramelessToggleDelay = crl::time(1000);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					style::margins ShadowExtents() {
 | 
				
			||||||
 | 
						return st::callShadow.extend;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace
 | 
					} // namespace
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TitleWidgetQt::TitleWidgetQt(QWidget *parent)
 | 
					TitleWidgetQt::TitleWidgetQt(QWidget *parent)
 | 
				
			||||||
| 
						 | 
					@ -63,12 +69,17 @@ TitleWidgetQt::TitleWidgetQt(QWidget *parent)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	QCoreApplication::instance()->installEventFilter(this);
 | 
						QCoreApplication::instance()->installEventFilter(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_windowWasFrameless = (window()->windowFlags() & Qt::FramelessWindowHint) != 0;
 | 
						_windowWasFrameless = (window()->windowFlags()
 | 
				
			||||||
 | 
							& Qt::FramelessWindowHint) != 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!_windowWasFrameless) {
 | 
						if (!_windowWasFrameless) {
 | 
				
			||||||
		toggleFramelessWindow(true);
 | 
							toggleFramelessWindow(true);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	setAttribute(Qt::WA_OpaquePaintEvent);
 | 
						setAttribute(Qt::WA_OpaquePaintEvent);
 | 
				
			||||||
	resize(width(), _st.height);
 | 
						resize(width(), _st.height);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						updateWindowExtents();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TitleWidgetQt::~TitleWidgetQt() {
 | 
					TitleWidgetQt::~TitleWidgetQt() {
 | 
				
			||||||
| 
						 | 
					@ -76,6 +87,7 @@ TitleWidgetQt::~TitleWidgetQt() {
 | 
				
			||||||
	if (!_windowWasFrameless) {
 | 
						if (!_windowWasFrameless) {
 | 
				
			||||||
		toggleFramelessWindow(false);
 | 
							toggleFramelessWindow(false);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						Platform::SetWindowExtents(window()->windowHandle(), QMargins());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void TitleWidgetQt::toggleFramelessWindow(bool enabled) {
 | 
					void TitleWidgetQt::toggleFramelessWindow(bool enabled) {
 | 
				
			||||||
| 
						 | 
					@ -98,11 +110,22 @@ void TitleWidgetQt::init() {
 | 
				
			||||||
		&QWindow::windowStateChanged,
 | 
							&QWindow::windowStateChanged,
 | 
				
			||||||
		this,
 | 
							this,
 | 
				
			||||||
		[=](Qt::WindowState state) { windowStateChanged(state); });
 | 
							[=](Qt::WindowState state) { windowStateChanged(state); });
 | 
				
			||||||
 | 
						connect(
 | 
				
			||||||
 | 
							window()->windowHandle(),
 | 
				
			||||||
 | 
							&QWindow::visibleChanged,
 | 
				
			||||||
 | 
							this,
 | 
				
			||||||
 | 
							[=](bool visible) { visibleChanged(visible); });
 | 
				
			||||||
	_maximizedState = (window()->windowState() & Qt::WindowMaximized);
 | 
						_maximizedState = (window()->windowState() & Qt::WindowMaximized);
 | 
				
			||||||
	_activeState = isActiveWindow();
 | 
						_activeState = isActiveWindow();
 | 
				
			||||||
	updateButtonsState();
 | 
						updateButtonsState();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool TitleWidgetQt::hasShadow() const {
 | 
				
			||||||
 | 
						const auto center = window()->geometry().center();
 | 
				
			||||||
 | 
						return Platform::WindowsNeedShadow()
 | 
				
			||||||
 | 
							&& Ui::Platform::TranslucentWindowsSupported(center);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void TitleWidgetQt::paintEvent(QPaintEvent *e) {
 | 
					void TitleWidgetQt::paintEvent(QPaintEvent *e) {
 | 
				
			||||||
	auto active = isActiveWindow();
 | 
						auto active = isActiveWindow();
 | 
				
			||||||
	if (_activeState != active) {
 | 
						if (_activeState != active) {
 | 
				
			||||||
| 
						 | 
					@ -112,6 +135,14 @@ void TitleWidgetQt::paintEvent(QPaintEvent *e) {
 | 
				
			||||||
	Painter(this).fillRect(rect(), active ? _st.bgActive : _st.bg);
 | 
						Painter(this).fillRect(rect(), active ? _st.bgActive : _st.bg);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void TitleWidgetQt::updateWindowExtents() {
 | 
				
			||||||
 | 
						if (hasShadow() && !_maximizedState) {
 | 
				
			||||||
 | 
							Platform::SetWindowExtents(window()->windowHandle(), ShadowExtents());
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							Platform::SetWindowExtents(window()->windowHandle(), QMargins());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void TitleWidgetQt::updateControlsPosition() {
 | 
					void TitleWidgetQt::updateControlsPosition() {
 | 
				
			||||||
	const auto controlsLayout = Core::App().settings().windowControlsLayout();
 | 
						const auto controlsLayout = Core::App().settings().windowControlsLayout();
 | 
				
			||||||
	const auto controlsLeft = controlsLayout.left;
 | 
						const auto controlsLeft = controlsLayout.left;
 | 
				
			||||||
| 
						 | 
					@ -197,7 +228,7 @@ void TitleWidgetQt::mousePressEvent(QMouseEvent *e) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void TitleWidgetQt::mouseDoubleClickEvent(QMouseEvent *e) {
 | 
					void TitleWidgetQt::mouseDoubleClickEvent(QMouseEvent *e) {
 | 
				
			||||||
	if (window()->windowState() == Qt::WindowMaximized) {
 | 
						if (_maximizedState) {
 | 
				
			||||||
		window()->setWindowState(Qt::WindowNoState);
 | 
							window()->setWindowState(Qt::WindowNoState);
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		window()->setWindowState(Qt::WindowMaximized);
 | 
							window()->setWindowState(Qt::WindowMaximized);
 | 
				
			||||||
| 
						 | 
					@ -205,11 +236,19 @@ void TitleWidgetQt::mouseDoubleClickEvent(QMouseEvent *e) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool TitleWidgetQt::eventFilter(QObject *obj, QEvent *e) {
 | 
					bool TitleWidgetQt::eventFilter(QObject *obj, QEvent *e) {
 | 
				
			||||||
 | 
						// I tried to listen only QEvent::Move and QEvent::Resize
 | 
				
			||||||
 | 
						// but that didn't work
 | 
				
			||||||
 | 
						if (obj->isWidgetType()
 | 
				
			||||||
 | 
							&& window() == static_cast<QWidget*>(obj)) {
 | 
				
			||||||
 | 
							updateWindowExtents();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (e->type() == QEvent::MouseMove
 | 
						if (e->type() == QEvent::MouseMove
 | 
				
			||||||
		|| e->type() == QEvent::MouseButtonPress) {
 | 
							|| e->type() == QEvent::MouseButtonPress) {
 | 
				
			||||||
		if (window()->isAncestorOf(static_cast<QWidget*>(obj))) {
 | 
							if (window()->isAncestorOf(static_cast<QWidget*>(obj))) {
 | 
				
			||||||
			const auto mouseEvent = static_cast<QMouseEvent*>(e);
 | 
								const auto mouseEvent = static_cast<QMouseEvent*>(e);
 | 
				
			||||||
			const auto edges = edgesFromPos(mouseEvent->windowPos().toPoint());
 | 
								const auto edges = edgesFromPos(
 | 
				
			||||||
 | 
									mouseEvent->windowPos().toPoint());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (e->type() == QEvent::MouseMove
 | 
								if (e->type() == QEvent::MouseMove
 | 
				
			||||||
				&& mouseEvent->buttons() == Qt::NoButton) {
 | 
									&& mouseEvent->buttons() == Qt::NoButton) {
 | 
				
			||||||
| 
						 | 
					@ -218,7 +257,7 @@ bool TitleWidgetQt::eventFilter(QObject *obj, QEvent *e) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (e->type() == QEvent::MouseButtonPress
 | 
								if (e->type() == QEvent::MouseButtonPress
 | 
				
			||||||
				&& mouseEvent->button() == Qt::LeftButton
 | 
									&& mouseEvent->button() == Qt::LeftButton
 | 
				
			||||||
				&& window()->windowState() != Qt::WindowMaximized) {
 | 
									&& !_maximizedState) {
 | 
				
			||||||
				return startResize(edges);
 | 
									return startResize(edges);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -243,6 +282,12 @@ void TitleWidgetQt::windowStateChanged(Qt::WindowState state) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void TitleWidgetQt::visibleChanged(bool visible) {
 | 
				
			||||||
 | 
						if (visible) {
 | 
				
			||||||
 | 
							updateWindowExtents();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void TitleWidgetQt::updateButtonsState() {
 | 
					void TitleWidgetQt::updateButtonsState() {
 | 
				
			||||||
	_minimize->setIconOverride(_activeState
 | 
						_minimize->setIconOverride(_activeState
 | 
				
			||||||
		? &_st.minimizeIconActive
 | 
							? &_st.minimizeIconActive
 | 
				
			||||||
| 
						 | 
					@ -273,26 +318,48 @@ void TitleWidgetQt::updateButtonsState() {
 | 
				
			||||||
		: nullptr);
 | 
							: nullptr);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int TitleWidgetQt::getResizeArea(Qt::Edge edge) const {
 | 
				
			||||||
 | 
						if (!hasShadow()) {
 | 
				
			||||||
 | 
							return st::windowResizeArea;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (edge == Qt::LeftEdge) {
 | 
				
			||||||
 | 
							return ShadowExtents().left();
 | 
				
			||||||
 | 
						} else if (edge == Qt::RightEdge) {
 | 
				
			||||||
 | 
							return ShadowExtents().right();
 | 
				
			||||||
 | 
						} else if (edge == Qt::TopEdge) {
 | 
				
			||||||
 | 
							return ShadowExtents().top();
 | 
				
			||||||
 | 
						} else if (edge == Qt::BottomEdge) {
 | 
				
			||||||
 | 
							return ShadowExtents().bottom();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Qt::Edges TitleWidgetQt::edgesFromPos(const QPoint &pos) {
 | 
					Qt::Edges TitleWidgetQt::edgesFromPos(const QPoint &pos) {
 | 
				
			||||||
	if (pos.x() <= st::windowResizeArea) {
 | 
						if (pos.x() <= getResizeArea(Qt::LeftEdge)) {
 | 
				
			||||||
		if (pos.y() <= st::windowResizeArea) {
 | 
							if (pos.y() <= getResizeArea(Qt::TopEdge)) {
 | 
				
			||||||
			return Qt::LeftEdge | Qt::TopEdge;
 | 
								return Qt::LeftEdge | Qt::TopEdge;
 | 
				
			||||||
		} else if (pos.y() >= (window()->height() - st::windowResizeArea)) {
 | 
							} else if (pos.y()
 | 
				
			||||||
 | 
								>= (window()->height() - getResizeArea(Qt::BottomEdge))) {
 | 
				
			||||||
			return Qt::LeftEdge | Qt::BottomEdge;
 | 
								return Qt::LeftEdge | Qt::BottomEdge;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return Qt::LeftEdge;
 | 
							return Qt::LeftEdge;
 | 
				
			||||||
	} else if (pos.x() >= (window()->width() - st::windowResizeArea)) {
 | 
						} else if (pos.x()
 | 
				
			||||||
		if (pos.y() <= st::windowResizeArea) {
 | 
							>= (window()->width() - getResizeArea(Qt::RightEdge))) {
 | 
				
			||||||
 | 
							if (pos.y() <= getResizeArea(Qt::TopEdge)) {
 | 
				
			||||||
			return Qt::RightEdge | Qt::TopEdge;
 | 
								return Qt::RightEdge | Qt::TopEdge;
 | 
				
			||||||
		} else if (pos.y() >= (window()->height() - st::windowResizeArea)) {
 | 
							} else if (pos.y()
 | 
				
			||||||
 | 
								>= (window()->height() - getResizeArea(Qt::BottomEdge))) {
 | 
				
			||||||
			return Qt::RightEdge | Qt::BottomEdge;
 | 
								return Qt::RightEdge | Qt::BottomEdge;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return Qt::RightEdge;
 | 
							return Qt::RightEdge;
 | 
				
			||||||
	} else if (pos.y() <= st::windowResizeArea) {
 | 
						} else if (pos.y() <= getResizeArea(Qt::TopEdge)) {
 | 
				
			||||||
		return Qt::TopEdge;
 | 
							return Qt::TopEdge;
 | 
				
			||||||
	} else if (pos.y() >= (window()->height() - st::windowResizeArea)) {
 | 
						} else if (pos.y()
 | 
				
			||||||
 | 
							>= (window()->height() - getResizeArea(Qt::BottomEdge))) {
 | 
				
			||||||
		return Qt::BottomEdge;
 | 
							return Qt::BottomEdge;
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
| 
						 | 
					@ -307,7 +374,7 @@ void TitleWidgetQt::restoreCursor() {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void TitleWidgetQt::updateCursor(Qt::Edges edges) {
 | 
					void TitleWidgetQt::updateCursor(Qt::Edges edges) {
 | 
				
			||||||
	if (!edges || window()->windowState() == Qt::WindowMaximized) {
 | 
						if (!edges || _maximizedState) {
 | 
				
			||||||
		restoreCursor();
 | 
							restoreCursor();
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	} else if (!QGuiApplication::overrideCursor()) {
 | 
						} else if (!QGuiApplication::overrideCursor()) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -39,6 +39,8 @@ protected:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
	void windowStateChanged(Qt::WindowState state = Qt::WindowNoState);
 | 
						void windowStateChanged(Qt::WindowState state = Qt::WindowNoState);
 | 
				
			||||||
 | 
						void visibleChanged(bool visible);
 | 
				
			||||||
 | 
						void updateWindowExtents();
 | 
				
			||||||
	void updateButtonsState();
 | 
						void updateButtonsState();
 | 
				
			||||||
	void updateControlsPosition();
 | 
						void updateControlsPosition();
 | 
				
			||||||
	void updateControlsPositionBySide(
 | 
						void updateControlsPositionBySide(
 | 
				
			||||||
| 
						 | 
					@ -46,6 +48,8 @@ private:
 | 
				
			||||||
		bool right);
 | 
							bool right);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void toggleFramelessWindow(bool enabled);
 | 
						void toggleFramelessWindow(bool enabled);
 | 
				
			||||||
 | 
						bool hasShadow() const;
 | 
				
			||||||
 | 
						int getResizeArea(Qt::Edge edge) const;
 | 
				
			||||||
	Qt::Edges edgesFromPos(const QPoint &pos);
 | 
						Qt::Edges edgesFromPos(const QPoint &pos);
 | 
				
			||||||
	void updateCursor(Qt::Edges edges);
 | 
						void updateCursor(Qt::Edges edges);
 | 
				
			||||||
	void restoreCursor();
 | 
						void restoreCursor();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue