Revert "Add main window shadow for Linux"

This reverts commit d02092f09e.

Conflicts:
	Telegram/SourceFiles/mainwindow.cpp
	Telegram/SourceFiles/platform/linux/specific_linux.cpp
	Telegram/SourceFiles/window/main_window.cpp
This commit is contained in:
John Preston 2020-08-23 16:38:49 +04:00
parent 97076dbf83
commit b7f5cfe083
9 changed files with 54 additions and 361 deletions

View File

@ -39,7 +39,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "apiwrap.h"
#include "api/api_updates.h"
#include "settings/settings_intro.h"
#include "platform/platform_specific.h"
#include "platform/platform_notifications_manager.h"
#include "base/platform/base_platform_info.h"
#include "base/call_delayed.h"
@ -111,12 +110,7 @@ MainWindow::MainWindow(not_null<Window::Controller*> controller)
}, lifetime());
setAttribute(Qt::WA_NoSystemBackground);
if (Platform::WindowsNeedShadow()) {
setAttribute(Qt::WA_TranslucentBackground);
} else {
setAttribute(Qt::WA_OpaquePaintEvent);
}
setAttribute(Qt::WA_OpaquePaintEvent);
}
void MainWindow::initHook() {

View File

@ -81,8 +81,6 @@ constexpr auto kXDGDesktopPortalService = "org.freedesktop.portal.Desktop"_cs;
constexpr auto kXDGDesktopPortalObjectPath = "/org/freedesktop/portal/desktop"_cs;
constexpr auto kPropertiesInterface = "org.freedesktop.DBus.Properties"_cs;
constexpr auto kXCBFrameExtentsAtomName = "_GTK_FRAME_EXTENTS"_cs;
QStringList PlatformThemes;
bool IsTrayIconSupported = true;
@ -300,91 +298,6 @@ bool GetImageFromClipboardSupported() {
}
#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() {
const auto native = QGuiApplication::platformNativeInterface();
if (!native) {
@ -398,24 +311,24 @@ std::optional<crl::time> XCBLastUserInputTime() {
return std::nullopt;
}
const auto root = static_cast<xcb_window_t>(reinterpret_cast<quintptr>(
native->nativeResourceForIntegration(QByteArray("rootwindow"))));
const auto screen = xcb_setup_roots_iterator(xcb_get_setup(connection)).data;
if (!screen) {
return std::nullopt;
}
const auto cookie = xcb_screensaver_query_info(
connection,
root);
const auto cookie = xcb_screensaver_query_info(connection, screen->root);
auto reply = xcb_screensaver_query_info_reply(
auto info = xcb_screensaver_query_info_reply(
connection,
cookie,
nullptr);
if (!reply) {
if (!info) {
return std::nullopt;
}
const auto idle = reply->ms_since_user_input;
free(reply);
const auto idle = info->ms_since_user_input;
free(info);
return (crl::now() - static_cast<crl::time>(idle));
}
@ -555,6 +468,7 @@ enum wl_shell_surface_resize WlResizeFromEdges(Qt::Edges edges) {
bool StartXCBMoveResize(QWindow *window, int edges) {
const auto native = QGuiApplication::platformNativeInterface();
if (!native) {
return false;
}
@ -573,16 +487,29 @@ bool StartXCBMoveResize(QWindow *window, int edges) {
return false;
}
const auto moveResize = GetXCBAtom(connection, "_NET_WM_MOVERESIZE");
if (!moveResize.has_value()) {
const auto moveResizeCookie = xcb_intern_atom(
connection,
0,
strlen("_NET_WM_MOVERESIZE"),
"_NET_WM_MOVERESIZE");
auto moveResizeReply = xcb_intern_atom_reply(
connection,
moveResizeCookie,
nullptr);
if (!moveResizeReply) {
return false;
}
const auto moveResize = moveResizeReply->atom;
free(moveResizeReply);
const auto globalPos = QCursor::pos();
xcb_client_message_event_t xev;
xev.response_type = XCB_CLIENT_MESSAGE;
xev.type = *moveResize;
xev.type = moveResize;
xev.sequence = 0;
xev.window = window->winId();
xev.format = 32;
@ -655,87 +582,6 @@ bool ShowWaylandWindowMenu(QWindow *window) {
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) {
if (keyword == qstr("minimize")) {
return Window::Control::Minimize;
@ -1080,31 +926,6 @@ bool ShowWindowMenu(QWindow *window) {
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() {
#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION
if (Libs::GtkSettingSupported()

View File

@ -44,10 +44,6 @@ inline bool TrayIconSupported() {
return true;
}
inline bool WindowsNeedShadow() {
return false;
}
namespace ThirdParty {
inline void start() {

View File

@ -56,8 +56,6 @@ QImage GetImageFromClipboard();
bool StartSystemMove(QWindow *window);
bool StartSystemResize(QWindow *window, Qt::Edges edges);
bool ShowWindowMenu(QWindow *window);
bool WindowsNeedShadow();
bool SetWindowExtents(QWindow *window, const QMargins &extents);
Window::ControlsLayout WindowControlsLayout();
namespace ThirdParty {

View File

@ -38,10 +38,6 @@ inline bool TrayIconSupported() {
return true;
}
inline bool WindowsNeedShadow() {
return false;
}
namespace ThirdParty {
void start();

View File

@ -10,7 +10,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "storage/localstorage.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/themes/window_theme.h"
#include "window/window_session_controller.h"
@ -34,7 +33,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "facades.h"
#include "app.h"
#include "styles/style_window.h"
#include "styles/style_calls.h" // st::callShadow
#include <QtWidgets/QDesktopWidget>
#include <QtCore/QMimeData>
@ -294,17 +292,6 @@ HitTestResult MainWindow::hitTest(const QPoint &p) const {
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 {
auto result = st::windowMinWidth;
if (const auto session = _controller->sessionController()) {
@ -315,7 +302,7 @@ int MainWindow::computeMinWidth() const {
if (_rightColumn) {
result += _rightColumn->width();
}
return result + _padding.left() + _padding.right();
return result;
}
int MainWindow::computeMinHeight() const {
@ -324,10 +311,10 @@ int MainWindow::computeMinHeight() const {
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 title + outdated + st::windowMinHeight;
}
void MainWindow::refreshTitleWidget() {
@ -350,20 +337,7 @@ void MainWindow::updateMinimumSize() {
setMinimumHeight(computeMinHeight());
}
void MainWindow::updateShadowSize() {
_padding = hasShadow() && !isMaximized()
? st::callShadow.extend
: style::margins();
}
void MainWindow::recountGeometryConstraints() {
#ifdef Q_OS_LINUX
const auto hasShadow = this->hasShadow();
setWindowFlag(Qt::NoDropShadowWindowHint, hasShadow);
setAttribute(Qt::WA_OpaquePaintEvent, !hasShadow);
#endif // Q_OS_LINUX
updateShadowSize();
updateMinimumSize();
updateControlsGeometry();
fixOrder();
@ -462,15 +436,7 @@ void MainWindow::attachToTrayIcon(not_null<QSystemTrayIcon*> icon) {
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) {
updateShadowSize();
updateControlsGeometry();
}
@ -483,28 +449,27 @@ void MainWindow::leaveEventHook(QEvent *e) {
}
void MainWindow::updateControlsGeometry() {
const auto inner = this->inner();
auto bodyLeft = inner.x();
auto bodyTop = inner.y();
auto bodyWidth = inner.width();
auto bodyLeft = 0;
auto bodyTop = 0;
auto bodyWidth = width();
if (_title && !_title->isHidden()) {
_title->setGeometry(inner.x(), bodyTop, inner.width(), _title->height());
_title->setGeometry(0, bodyTop, width(), _title->height());
bodyTop += _title->height();
}
if (_titleShadow) {
_titleShadow->setGeometry(inner.x(), bodyTop, inner.width(), st::lineWidth);
_titleShadow->setGeometry(0, bodyTop, width(), st::lineWidth);
}
if (_outdated) {
Ui::SendPendingMoveResizeEvents(_outdated.data());
_outdated->resizeToWidth(inner.width());
_outdated->moveToLeft(inner.x(), bodyTop);
_outdated->resizeToWidth(width());
_outdated->moveToLeft(0, bodyTop);
bodyTop += _outdated->height();
}
if (_rightColumn) {
bodyWidth -= _rightColumn->width();
_rightColumn->setGeometry(bodyWidth, bodyTop, inner.width() - bodyWidth, inner.height() - (bodyTop - inner.y()));
_rightColumn->setGeometry(bodyWidth, bodyTop, width() - bodyWidth, height() - bodyTop);
}
_body->setGeometry(bodyLeft, bodyTop, bodyWidth, inner.height() - (bodyTop - inner.y()));
_body->setGeometry(bodyLeft, bodyTop, bodyWidth, height() - bodyTop);
}
void MainWindow::updateUnreadCounter() {
@ -634,12 +599,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() - geometry().width(), 0);
}
bool MainWindow::canExtendNoMove(int extendBy) const {
auto desktop = QDesktopWidget().availableGeometry(this);
auto inner = geometry().marginsRemoved(_padding);
auto inner = geometry();
auto innerRight = (inner.x() + inner.width() + extendBy);
auto desktopRight = (desktop.x() + desktop.width());
return innerRight <= desktopRight;

View File

@ -101,15 +101,12 @@ public:
void clearWidgets();
QRect inner() const;
int computeMinWidth() const;
int computeMinHeight() const;
void recountGeometryConstraints();
virtual void updateControlsGeometry();
bool hasShadow() const;
public slots:
bool minimizeToTray();
void updateGlobalMenu() {
@ -117,7 +114,6 @@ public slots:
}
protected:
void paintEvent(QPaintEvent *e) override;
void resizeEvent(QResizeEvent *e) override;
void leaveEventHook(QEvent *e) override;
@ -183,7 +179,6 @@ protected:
private:
void refreshTitleWidget();
void updateMinimumSize();
void updateShadowSize();
void updatePalette();
void initSize();
@ -203,7 +198,6 @@ private:
QIcon _icon;
bool _usingSupportIcon = false;
QString _titleText;
style::margins _padding;
bool _isActive = false;

View File

@ -8,13 +8,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "window/window_title_qt.h"
#include "platform/platform_specific.h"
#include "ui/platform/ui_platform_utility.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/shadow.h"
#include "core/core_settings.h"
#include "core/application.h"
#include "styles/style_window.h"
#include "styles/style_calls.h" // st::callShadow
#include "base/call_delayed.h"
#include <QtGui/QGuiApplication>
@ -29,10 +27,6 @@ namespace {
// that window. If we show the window back with this delay it works.
constexpr auto kShowAfterFramelessToggleDelay = crl::time(1000);
style::margins ShadowExtents() {
return st::callShadow.extend;
}
} // namespace
TitleWidgetQt::TitleWidgetQt(QWidget *parent)
@ -69,17 +63,12 @@ TitleWidgetQt::TitleWidgetQt(QWidget *parent)
QCoreApplication::instance()->installEventFilter(this);
_windowWasFrameless = (window()->windowFlags()
& Qt::FramelessWindowHint) != 0;
_windowWasFrameless = (window()->windowFlags() & Qt::FramelessWindowHint) != 0;
if (!_windowWasFrameless) {
toggleFramelessWindow(true);
}
setAttribute(Qt::WA_OpaquePaintEvent);
resize(width(), _st.height);
updateWindowExtents();
}
TitleWidgetQt::~TitleWidgetQt() {
@ -87,7 +76,6 @@ TitleWidgetQt::~TitleWidgetQt() {
if (!_windowWasFrameless) {
toggleFramelessWindow(false);
}
Platform::SetWindowExtents(window()->windowHandle(), QMargins());
}
void TitleWidgetQt::toggleFramelessWindow(bool enabled) {
@ -110,22 +98,11 @@ void TitleWidgetQt::init() {
&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 Platform::WindowsNeedShadow()
&& Ui::Platform::TranslucentWindowsSupported(center);
}
void TitleWidgetQt::paintEvent(QPaintEvent *e) {
auto active = isActiveWindow();
if (_activeState != active) {
@ -135,14 +112,6 @@ void TitleWidgetQt::paintEvent(QPaintEvent *e) {
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() {
const auto controlsLayout = Core::App().settings().windowControlsLayout();
const auto controlsLeft = controlsLayout.left;
@ -228,7 +197,7 @@ void TitleWidgetQt::mousePressEvent(QMouseEvent *e) {
}
void TitleWidgetQt::mouseDoubleClickEvent(QMouseEvent *e) {
if (_maximizedState) {
if (window()->windowState() == Qt::WindowMaximized) {
window()->setWindowState(Qt::WindowNoState);
} else {
window()->setWindowState(Qt::WindowMaximized);
@ -236,19 +205,11 @@ void TitleWidgetQt::mouseDoubleClickEvent(QMouseEvent *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
|| e->type() == QEvent::MouseButtonPress) {
if (window()->isAncestorOf(static_cast<QWidget*>(obj))) {
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
&& mouseEvent->buttons() == Qt::NoButton) {
@ -257,7 +218,7 @@ bool TitleWidgetQt::eventFilter(QObject *obj, QEvent *e) {
if (e->type() == QEvent::MouseButtonPress
&& mouseEvent->button() == Qt::LeftButton
&& !_maximizedState) {
&& window()->windowState() != Qt::WindowMaximized) {
return startResize(edges);
}
}
@ -282,12 +243,6 @@ void TitleWidgetQt::windowStateChanged(Qt::WindowState state) {
}
}
void TitleWidgetQt::visibleChanged(bool visible) {
if (visible) {
updateWindowExtents();
}
}
void TitleWidgetQt::updateButtonsState() {
_minimize->setIconOverride(_activeState
? &_st.minimizeIconActive
@ -318,48 +273,26 @@ void TitleWidgetQt::updateButtonsState() {
: 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) {
if (pos.x() <= getResizeArea(Qt::LeftEdge)) {
if (pos.y() <= getResizeArea(Qt::TopEdge)) {
if (pos.x() <= st::windowResizeArea) {
if (pos.y() <= st::windowResizeArea) {
return Qt::LeftEdge | Qt::TopEdge;
} else if (pos.y()
>= (window()->height() - getResizeArea(Qt::BottomEdge))) {
} else if (pos.y() >= (window()->height() - st::windowResizeArea)) {
return Qt::LeftEdge | Qt::BottomEdge;
}
return Qt::LeftEdge;
} else if (pos.x()
>= (window()->width() - getResizeArea(Qt::RightEdge))) {
if (pos.y() <= getResizeArea(Qt::TopEdge)) {
} else if (pos.x() >= (window()->width() - st::windowResizeArea)) {
if (pos.y() <= st::windowResizeArea) {
return Qt::RightEdge | Qt::TopEdge;
} else if (pos.y()
>= (window()->height() - getResizeArea(Qt::BottomEdge))) {
} else if (pos.y() >= (window()->height() - st::windowResizeArea)) {
return Qt::RightEdge | Qt::BottomEdge;
}
return Qt::RightEdge;
} else if (pos.y() <= getResizeArea(Qt::TopEdge)) {
} else if (pos.y() <= st::windowResizeArea) {
return Qt::TopEdge;
} else if (pos.y()
>= (window()->height() - getResizeArea(Qt::BottomEdge))) {
} else if (pos.y() >= (window()->height() - st::windowResizeArea)) {
return Qt::BottomEdge;
} else {
return 0;
@ -374,7 +307,7 @@ void TitleWidgetQt::restoreCursor() {
}
void TitleWidgetQt::updateCursor(Qt::Edges edges) {
if (!edges || _maximizedState) {
if (!edges || window()->windowState() == Qt::WindowMaximized) {
restoreCursor();
return;
} else if (!QGuiApplication::overrideCursor()) {

View File

@ -39,8 +39,6 @@ protected:
private:
void windowStateChanged(Qt::WindowState state = Qt::WindowNoState);
void visibleChanged(bool visible);
void updateWindowExtents();
void updateButtonsState();
void updateControlsPosition();
void updateControlsPositionBySide(
@ -48,8 +46,6 @@ private:
bool right);
void toggleFramelessWindow(bool enabled);
bool hasShadow() const;
int getResizeArea(Qt::Edge edge) const;
Qt::Edges edgesFromPos(const QPoint &pos);
void updateCursor(Qt::Edges edges);
void restoreCursor();