From 307b1aafa2c6505e305f90676c464b1913893b53c043bb034a57d5d0b794b4a5 Mon Sep 17 00:00:00 2001 From: Marcel Kuehlhorn Date: Wed, 30 Sep 2020 16:06:12 +0000 Subject: [PATCH] Accepting request 838770 from home:tux93 - Add check_if_xcb-screensaver_present.patch * fixes boo#1176626: Telegram-desktop crashes on Xwayland OBS-URL: https://build.opensuse.org/request/show/838770 OBS-URL: https://build.opensuse.org/package/show/server:messaging/telegram-desktop?expand=0&rev=155 --- check_if_xcb-screensaver_present.patch | 860 +++++++++++++++++++++++++ telegram-desktop.changes | 6 + telegram-desktop.spec | 9 +- 3 files changed, 872 insertions(+), 3 deletions(-) create mode 100644 check_if_xcb-screensaver_present.patch diff --git a/check_if_xcb-screensaver_present.patch b/check_if_xcb-screensaver_present.patch new file mode 100644 index 0000000..8583716 --- /dev/null +++ b/check_if_xcb-screensaver_present.patch @@ -0,0 +1,860 @@ +From ea8e256a235082157b942344f4683ec54d3b337e Mon Sep 17 00:00:00 2001 +From: Ilya Fedin +Date: Fri, 28 Aug 2020 16:07:29 +0400 +Subject: [PATCH] Revert "Revert "Add main window shadow for Linux"" + +This reverts commit b7f5cfe0833232a727c1ff212df13d00273ba2a3. +--- + Telegram/SourceFiles/mainwindow.cpp | 8 +- + .../platform/linux/specific_linux.cpp | 231 ++++++++++++++++-- + .../SourceFiles/platform/mac/specific_mac.h | 4 + + .../SourceFiles/platform/platform_specific.h | 2 + + .../SourceFiles/platform/win/specific_win.h | 4 + + Telegram/SourceFiles/window/main_window.cpp | 63 +++-- + Telegram/SourceFiles/window/main_window.h | 6 + + .../SourceFiles/window/window_title_qt.cpp | 93 ++++++- + Telegram/SourceFiles/window/window_title_qt.h | 4 + + 9 files changed, 361 insertions(+), 54 deletions(-) + +diff --git a/Telegram/SourceFiles/mainwindow.cpp b/Telegram/SourceFiles/mainwindow.cpp +index 39aca78a1a..66272f6004 100644 +--- a/Telegram/SourceFiles/mainwindow.cpp ++++ b/Telegram/SourceFiles/mainwindow.cpp +@@ -39,6 +39,7 @@ For license and copyright information please follow this link: + #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" +@@ -110,7 +111,12 @@ MainWindow::MainWindow(not_null controller) + }, lifetime()); + + setAttribute(Qt::WA_NoSystemBackground); +- setAttribute(Qt::WA_OpaquePaintEvent); ++ ++ if (Platform::WindowsNeedShadow()) { ++ setAttribute(Qt::WA_TranslucentBackground); ++ } else { ++ setAttribute(Qt::WA_OpaquePaintEvent); ++ } + } + + void MainWindow::initHook() { +diff --git a/Telegram/SourceFiles/platform/linux/specific_linux.cpp b/Telegram/SourceFiles/platform/linux/specific_linux.cpp +index cefceb8d23..eda4684eb6 100644 +--- a/Telegram/SourceFiles/platform/linux/specific_linux.cpp ++++ b/Telegram/SourceFiles/platform/linux/specific_linux.cpp +@@ -81,6 +81,8 @@ 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; +@@ -298,6 +300,91 @@ bool GetImageFromClipboardSupported() { + } + #endif // !TDESKTOP_DISABLE_GTK_INTEGRATION + ++std::optional 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 GetXCBWMSupported(xcb_connection_t *connection) { ++ auto netWmAtoms = std::vector{}; ++ ++ const auto native = QGuiApplication::platformNativeInterface(); ++ if (!native) { ++ return netWmAtoms; ++ } ++ ++ const auto root = static_cast(reinterpret_cast( ++ 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_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 XCBLastUserInputTime() { + const auto native = QGuiApplication::platformNativeInterface(); + if (!native) { +@@ -311,24 +398,24 @@ std::optional XCBLastUserInputTime() { + return std::nullopt; + } + +- const auto screen = xcb_setup_roots_iterator(xcb_get_setup(connection)).data; +- if (!screen) { +- return std::nullopt; +- } ++ const auto root = static_cast(reinterpret_cast( ++ native->nativeResourceForIntegration(QByteArray("rootwindow")))); + +- const auto cookie = xcb_screensaver_query_info(connection, screen->root); ++ const auto cookie = xcb_screensaver_query_info( ++ connection, ++ root); + +- auto info = xcb_screensaver_query_info_reply( ++ auto reply = xcb_screensaver_query_info_reply( + connection, + cookie, + nullptr); + +- if (!info) { ++ if (!reply) { + return std::nullopt; + } + +- const auto idle = info->ms_since_user_input; +- free(info); ++ const auto idle = reply->ms_since_user_input; ++ free(reply); + + return (crl::now() - static_cast(idle)); + } +@@ -468,7 +555,6 @@ enum wl_shell_surface_resize WlResizeFromEdges(Qt::Edges edges) { + + bool StartXCBMoveResize(QWindow *window, int edges) { + const auto native = QGuiApplication::platformNativeInterface(); +- + if (!native) { + return false; + } +@@ -487,29 +573,16 @@ bool StartXCBMoveResize(QWindow *window, int edges) { + return false; + } + +- 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) { ++ const auto moveResize = GetXCBAtom(connection, "_NET_WM_MOVERESIZE"); ++ if (!moveResize.has_value()) { + 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; +@@ -582,6 +655,87 @@ bool ShowWaylandWindowMenu(QWindow *window) { + return false; + } + ++bool XCBFrameExtentsSupported() { ++ const auto native = QGuiApplication::platformNativeInterface(); ++ if (!native) { ++ return false; ++ } ++ ++ const auto connection = reinterpret_cast( ++ 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( ++ 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(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( ++ 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; +@@ -926,6 +1080,31 @@ 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() +diff --git a/Telegram/SourceFiles/platform/mac/specific_mac.h b/Telegram/SourceFiles/platform/mac/specific_mac.h +index 7db80f1a48..6c966f9b6f 100644 +--- a/Telegram/SourceFiles/platform/mac/specific_mac.h ++++ b/Telegram/SourceFiles/platform/mac/specific_mac.h +@@ -44,6 +44,10 @@ inline bool TrayIconSupported() { + return true; + } + ++inline bool WindowsNeedShadow() { ++ return false; ++} ++ + namespace ThirdParty { + + inline void start() { +diff --git a/Telegram/SourceFiles/platform/platform_specific.h b/Telegram/SourceFiles/platform/platform_specific.h +index ec419bab7b..dd4cb60204 100644 +--- a/Telegram/SourceFiles/platform/platform_specific.h ++++ b/Telegram/SourceFiles/platform/platform_specific.h +@@ -56,6 +56,8 @@ 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 { +diff --git a/Telegram/SourceFiles/platform/win/specific_win.h b/Telegram/SourceFiles/platform/win/specific_win.h +index 71a7ff30a0..46b8e7d2a0 100644 +--- a/Telegram/SourceFiles/platform/win/specific_win.h ++++ b/Telegram/SourceFiles/platform/win/specific_win.h +@@ -38,6 +38,10 @@ inline bool TrayIconSupported() { + return true; + } + ++inline bool WindowsNeedShadow() { ++ return false; ++} ++ + namespace ThirdParty { + + void start(); +diff --git a/Telegram/SourceFiles/window/main_window.cpp b/Telegram/SourceFiles/window/main_window.cpp +index e567d93809..9a808233a4 100644 +--- a/Telegram/SourceFiles/window/main_window.cpp ++++ b/Telegram/SourceFiles/window/main_window.cpp +@@ -10,6 +10,7 @@ For license and copyright information please follow this link: + #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" +@@ -33,6 +34,7 @@ For license and copyright information please follow this link: + #include "facades.h" + #include "app.h" + #include "styles/style_window.h" ++#include "styles/style_calls.h" // st::callShadow + + #include + #include +@@ -292,6 +294,17 @@ 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()) { +@@ -302,7 +315,7 @@ int MainWindow::computeMinWidth() const { + if (_rightColumn) { + result += _rightColumn->width(); + } +- return result; ++ return result + _padding.left() + _padding.right(); + } + + int MainWindow::computeMinHeight() const { +@@ -311,10 +324,10 @@ int MainWindow::computeMinHeight() const { + if (!_outdated) { + return 0; + } +- _outdated->resizeToWidth(st::windowMinWidth); ++ _outdated->resizeToWidth(st::windowMinWidth - _padding.left() - _padding.right()); + return _outdated->height(); + }(); +- return title + outdated + st::windowMinHeight; ++ return title + outdated + st::windowMinHeight + _padding.top() + _padding.bottom(); + } + + void MainWindow::refreshTitleWidget() { +@@ -337,7 +350,20 @@ 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(); +@@ -436,7 +462,15 @@ void MainWindow::attachToTrayIcon(not_null 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(); + } + +@@ -449,27 +483,28 @@ void MainWindow::leaveEventHook(QEvent *e) { + } + + void MainWindow::updateControlsGeometry() { +- auto bodyLeft = 0; +- auto bodyTop = 0; +- auto bodyWidth = width(); ++ const auto inner = this->inner(); ++ auto bodyLeft = inner.x(); ++ auto bodyTop = inner.y(); ++ auto bodyWidth = inner.width(); + if (_title && !_title->isHidden()) { +- _title->setGeometry(0, bodyTop, width(), _title->height()); ++ _title->setGeometry(inner.x(), bodyTop, inner.width(), _title->height()); + bodyTop += _title->height(); + } + if (_titleShadow) { +- _titleShadow->setGeometry(0, bodyTop, width(), st::lineWidth); ++ _titleShadow->setGeometry(inner.x(), bodyTop, inner.width(), st::lineWidth); + } + if (_outdated) { + Ui::SendPendingMoveResizeEvents(_outdated.data()); +- _outdated->resizeToWidth(width()); +- _outdated->moveToLeft(0, bodyTop); ++ _outdated->resizeToWidth(inner.width()); ++ _outdated->moveToLeft(inner.x(), bodyTop); + bodyTop += _outdated->height(); + } + if (_rightColumn) { + 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() { +@@ -599,12 +634,12 @@ void MainWindow::showRightColumn(object_ptr widget) { + + int MainWindow::maximalExtendBy() const { + 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 { + auto desktop = QDesktopWidget().availableGeometry(this); +- auto inner = geometry(); ++ auto inner = geometry().marginsRemoved(_padding); + auto innerRight = (inner.x() + inner.width() + extendBy); + auto desktopRight = (desktop.x() + desktop.width()); + return innerRight <= desktopRight; +diff --git a/Telegram/SourceFiles/window/main_window.h b/Telegram/SourceFiles/window/main_window.h +index ceb6cdedac..9483e30e7a 100644 +--- a/Telegram/SourceFiles/window/main_window.h ++++ b/Telegram/SourceFiles/window/main_window.h +@@ -101,12 +101,15 @@ class MainWindow : public Ui::RpWidget, protected base::Subscriber { + + 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() { +@@ -114,6 +117,7 @@ public slots: + } + + protected: ++ void paintEvent(QPaintEvent *e) override; + void resizeEvent(QResizeEvent *e) override; + void leaveEventHook(QEvent *e) override; + +@@ -179,6 +183,7 @@ public slots: + private: + void refreshTitleWidget(); + void updateMinimumSize(); ++ void updateShadowSize(); + void updatePalette(); + void initSize(); + +@@ -198,6 +203,7 @@ public slots: + QIcon _icon; + bool _usingSupportIcon = false; + QString _titleText; ++ style::margins _padding; + + bool _isActive = false; + +diff --git a/Telegram/SourceFiles/window/window_title_qt.cpp b/Telegram/SourceFiles/window/window_title_qt.cpp +index a8a02de5b6..1763ef659e 100644 +--- a/Telegram/SourceFiles/window/window_title_qt.cpp ++++ b/Telegram/SourceFiles/window/window_title_qt.cpp +@@ -8,11 +8,13 @@ For license and copyright information please follow this link: + #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 +@@ -27,6 +29,10 @@ 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) +@@ -63,12 +69,17 @@ 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() { +@@ -76,6 +87,7 @@ TitleWidgetQt::~TitleWidgetQt() { + if (!_windowWasFrameless) { + toggleFramelessWindow(false); + } ++ Platform::SetWindowExtents(window()->windowHandle(), QMargins()); + } + + void TitleWidgetQt::toggleFramelessWindow(bool enabled) { +@@ -98,11 +110,22 @@ 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) { +@@ -112,6 +135,14 @@ 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; +@@ -197,7 +228,7 @@ void TitleWidgetQt::mousePressEvent(QMouseEvent *e) { + } + + void TitleWidgetQt::mouseDoubleClickEvent(QMouseEvent *e) { +- if (window()->windowState() == Qt::WindowMaximized) { ++ if (_maximizedState) { + window()->setWindowState(Qt::WindowNoState); + } else { + window()->setWindowState(Qt::WindowMaximized); +@@ -205,11 +236,19 @@ 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(obj)) { ++ updateWindowExtents(); ++ } ++ + if (e->type() == QEvent::MouseMove + || e->type() == QEvent::MouseButtonPress) { + if (window()->isAncestorOf(static_cast(obj))) { + const auto mouseEvent = static_cast(e); +- const auto edges = edgesFromPos(mouseEvent->windowPos().toPoint()); ++ const auto edges = edgesFromPos( ++ mouseEvent->windowPos().toPoint()); + + if (e->type() == QEvent::MouseMove + && mouseEvent->buttons() == Qt::NoButton) { +@@ -218,7 +257,7 @@ bool TitleWidgetQt::eventFilter(QObject *obj, QEvent *e) { + + if (e->type() == QEvent::MouseButtonPress + && mouseEvent->button() == Qt::LeftButton +- && window()->windowState() != Qt::WindowMaximized) { ++ && !_maximizedState) { + return startResize(edges); + } + } +@@ -243,6 +282,12 @@ void TitleWidgetQt::windowStateChanged(Qt::WindowState state) { + } + } + ++void TitleWidgetQt::visibleChanged(bool visible) { ++ if (visible) { ++ updateWindowExtents(); ++ } ++} ++ + void TitleWidgetQt::updateButtonsState() { + _minimize->setIconOverride(_activeState + ? &_st.minimizeIconActive +@@ -273,26 +318,48 @@ 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() <= st::windowResizeArea) { +- if (pos.y() <= st::windowResizeArea) { ++ if (pos.x() <= getResizeArea(Qt::LeftEdge)) { ++ if (pos.y() <= getResizeArea(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; +- } else if (pos.x() >= (window()->width() - st::windowResizeArea)) { +- if (pos.y() <= st::windowResizeArea) { ++ } else if (pos.x() ++ >= (window()->width() - getResizeArea(Qt::RightEdge))) { ++ if (pos.y() <= getResizeArea(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; +- } else if (pos.y() <= st::windowResizeArea) { ++ } else if (pos.y() <= getResizeArea(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; + } else { + return 0; +@@ -307,7 +374,7 @@ void TitleWidgetQt::restoreCursor() { + } + + void TitleWidgetQt::updateCursor(Qt::Edges edges) { +- if (!edges || window()->windowState() == Qt::WindowMaximized) { ++ if (!edges || _maximizedState) { + restoreCursor(); + return; + } else if (!QGuiApplication::overrideCursor()) { +diff --git a/Telegram/SourceFiles/window/window_title_qt.h b/Telegram/SourceFiles/window/window_title_qt.h +index c3536587d4..02db001f7c 100644 +--- a/Telegram/SourceFiles/window/window_title_qt.h ++++ b/Telegram/SourceFiles/window/window_title_qt.h +@@ -39,6 +39,8 @@ class TitleWidgetQt : public TitleWidget { + + private: + void windowStateChanged(Qt::WindowState state = Qt::WindowNoState); ++ void visibleChanged(bool visible); ++ void updateWindowExtents(); + void updateButtonsState(); + void updateControlsPosition(); + void updateControlsPositionBySide( +@@ -46,6 +48,8 @@ class TitleWidgetQt : public TitleWidget { + 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(); +From 6635d03818c90f62cfddb516acadc293255b8905 Mon Sep 17 00:00:00 2001 +From: Ilya Fedin +Date: Sat, 29 Aug 2020 03:55:38 +0400 +Subject: [PATCH] Check if xcb-screensaver extension present + +--- + .../platform/linux/specific_linux.cpp | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +diff --git a/Telegram/SourceFiles/platform/linux/specific_linux.cpp b/Telegram/SourceFiles/platform/linux/specific_linux.cpp +index a5a8274189..fc06381584 100644 +--- a/Telegram/SourceFiles/platform/linux/specific_linux.cpp ++++ b/Telegram/SourceFiles/platform/linux/specific_linux.cpp +@@ -324,6 +324,20 @@ std::optional GetXCBAtom( + return atom; + } + ++bool IsXCBExtensionPresent( ++ xcb_connection_t *connection, ++ xcb_extension_t *ext) { ++ const auto reply = xcb_get_extension_data( ++ connection, ++ ext); ++ ++ if (!reply) { ++ return false; ++ } ++ ++ return reply->present; ++} ++ + std::vector GetXCBWMSupported(xcb_connection_t *connection) { + auto netWmAtoms = std::vector{}; + +@@ -398,6 +412,10 @@ std::optional XCBLastUserInputTime() { + return std::nullopt; + } + ++ if (!IsXCBExtensionPresent(connection, &xcb_screensaver_id)) { ++ return std::nullopt; ++ } ++ + const auto root = static_cast(reinterpret_cast( + native->nativeResourceForIntegration(QByteArray("rootwindow")))); + diff --git a/telegram-desktop.changes b/telegram-desktop.changes index 283f31a..b19f56f 100644 --- a/telegram-desktop.changes +++ b/telegram-desktop.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Wed Sep 30 10:36:43 UTC 2020 - Marcel Kuehlhorn + +- Add check_if_xcb-screensaver_present.patch + * fixes boo#1176626: Telegram-desktop crashes on Xwayland + ------------------------------------------------------------------- Sun Aug 30 22:25:52 UTC 2020 - Xu Zhao diff --git a/telegram-desktop.spec b/telegram-desktop.spec index 34e9a40..61d1d89 100644 --- a/telegram-desktop.spec +++ b/telegram-desktop.spec @@ -38,14 +38,16 @@ License: GPL-3.0-only Group: Productivity/Networking/Instant Messenger URL: https://github.com/telegramdesktop/tdesktop Source0: https://github.com/telegramdesktop/tdesktop/releases/download/v%{version}/tdesktop-%{version}-full.tar.gz -# tg_owt: https://github.com/desktop-app/tg_owt/archive/master.zip -Source1: tg_owt-master.zip +# tg_owt: https://github.com/desktop-app/tg_owt/archive/master.zip +Source1: tg_owt-master.zip # PATCH-FIX-OPENSUSE Patch0: 0000-gtk2-default.patch # PATCH-FIX-OPENSUSE Patch1: 0001-use-bundled-ranged-exptected-gsl.patch # PATCH-FIX-OPENSUSE Patch2: 0002-tg_owt-fix-name-confliction.patch +# PATCH-FIX-UPSTREAM: boo#1176626: Telegram-desktop crashes on Xwayland +Patch3: check_if_xcb-screensaver_present.patch BuildRequires: appstream-glib BuildRequires: chrpath BuildRequires: cmake >= 3.16 @@ -149,6 +151,7 @@ The service also provides APIs to independent developers. %setup -q -n tdesktop-%{version}-full %patch0 -p1 %patch1 -p2 +%patch3 -p1 cd ../ unzip %{S:1} @@ -173,7 +176,7 @@ cmake -G Ninja \ -DTG_OWT_OPUS_INCLUDE_PATH=/usr/include/opus \ -DTG_OWT_FFMPEG_INCLUDE_PATH=/usr/include/ffmpeg \ ../.. -sed -i 's,gnu++2a,gnu++17,g' build.ninja +sed -i 's,gnu++2a,gnu++17,g' build.ninja ninja cd %{_builddir}/tdesktop-%{version}-full