Changeset View
Changeset View
Standalone View
Standalone View
shell_client.cpp
1 | /******************************************************************** | 1 | /******************************************************************** | ||
---|---|---|---|---|---|
2 | KWin - the KDE window manager | 2 | KWin - the KDE window manager | ||
3 | This file is part of the KDE project. | 3 | This file is part of the KDE project. | ||
4 | 4 | | |||
5 | Copyright (C) 2015 Martin Gräßlin <mgraesslin@kde.org> | 5 | Copyright (C) 2015 Martin Gräßlin <mgraesslin@kde.org> | ||
6 | Copyright (C) 2018 David Edmundson <davidedmundson@kde.org> | 6 | Copyright (C) 2018 David Edmundson <davidedmundson@kde.org> | ||
7 | Copyright (C) 2019 Vlad Zagorodniy <vladzzag@gmail.com> | ||||
7 | 8 | | |||
8 | This program is free software; you can redistribute it and/or modify | 9 | This program is free software; you can redistribute it and/or modify | ||
9 | it under the terms of the GNU General Public License as published by | 10 | it under the terms of the GNU General Public License as published by | ||
10 | the Free Software Foundation; either version 2 of the License, or | 11 | the Free Software Foundation; either version 2 of the License, or | ||
11 | (at your option) any later version. | 12 | (at your option) any later version. | ||
12 | 13 | | |||
13 | This program is distributed in the hope that it will be useful, | 14 | This program is distributed in the hope that it will be useful, | ||
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
▲ Show 20 Lines • Show All 51 Lines • ▼ Show 20 Line(s) | |||||
66 | namespace KWin | 67 | namespace KWin | ||
67 | { | 68 | { | ||
68 | 69 | | |||
69 | ShellClient::ShellClient(ShellSurfaceInterface *surface) | 70 | ShellClient::ShellClient(ShellSurfaceInterface *surface) | ||
70 | : AbstractClient() | 71 | : AbstractClient() | ||
71 | , m_shellSurface(surface) | 72 | , m_shellSurface(surface) | ||
72 | , m_xdgShellSurface(nullptr) | 73 | , m_xdgShellSurface(nullptr) | ||
73 | , m_xdgShellPopup(nullptr) | 74 | , m_xdgShellPopup(nullptr) | ||
74 | , m_internal(surface->client() == waylandServer()->internalConnection()) | | |||
75 | { | 75 | { | ||
76 | setSurface(surface->surface()); | 76 | setSurface(surface->surface()); | ||
77 | init(); | 77 | init(); | ||
78 | m_isInitialized = true; | 78 | m_isInitialized = true; | ||
79 | } | 79 | } | ||
80 | 80 | | |||
81 | ShellClient::ShellClient(XdgShellSurfaceInterface *surface) | 81 | ShellClient::ShellClient(XdgShellSurfaceInterface *surface) | ||
82 | : AbstractClient() | 82 | : AbstractClient() | ||
83 | , m_shellSurface(nullptr) | 83 | , m_shellSurface(nullptr) | ||
84 | , m_xdgShellSurface(surface) | 84 | , m_xdgShellSurface(surface) | ||
85 | , m_xdgShellPopup(nullptr) | 85 | , m_xdgShellPopup(nullptr) | ||
86 | , m_internal(surface->client() == waylandServer()->internalConnection()) | | |||
87 | { | 86 | { | ||
88 | setSurface(surface->surface()); | 87 | setSurface(surface->surface()); | ||
89 | m_requestGeometryBlockCounter++; | 88 | m_requestGeometryBlockCounter++; | ||
90 | init(); | 89 | init(); | ||
91 | connect(surface->surface(), &SurfaceInterface::committed, this, &ShellClient::finishInit); | 90 | connect(surface->surface(), &SurfaceInterface::committed, this, &ShellClient::finishInit); | ||
92 | } | 91 | } | ||
93 | 92 | | |||
94 | ShellClient::ShellClient(XdgShellPopupInterface *surface) | 93 | ShellClient::ShellClient(XdgShellPopupInterface *surface) | ||
95 | : AbstractClient() | 94 | : AbstractClient() | ||
96 | , m_shellSurface(nullptr) | 95 | , m_shellSurface(nullptr) | ||
97 | , m_xdgShellSurface(nullptr) | 96 | , m_xdgShellSurface(nullptr) | ||
98 | , m_xdgShellPopup(surface) | 97 | , m_xdgShellPopup(surface) | ||
99 | , m_internal(surface->client() == waylandServer()->internalConnection()) | | |||
100 | { | 98 | { | ||
101 | setSurface(surface->surface()); | 99 | setSurface(surface->surface()); | ||
102 | m_requestGeometryBlockCounter++; | 100 | m_requestGeometryBlockCounter++; | ||
103 | init(); | 101 | init(); | ||
104 | connect(surface->surface(), &SurfaceInterface::committed, this, &ShellClient::finishInit); | 102 | connect(surface->surface(), &SurfaceInterface::committed, this, &ShellClient::finishInit); | ||
105 | } | 103 | } | ||
106 | 104 | | |||
107 | ShellClient::~ShellClient() = default; | 105 | ShellClient::~ShellClient() = default; | ||
▲ Show 20 Lines • Show All 115 Lines • ▼ Show 20 Line(s) | 219 | if (s->buffer()) { | |||
223 | if (shouldExposeToWindowManagement()) { | 221 | if (shouldExposeToWindowManagement()) { | ||
224 | setupWindowManagementInterface(); | 222 | setupWindowManagementInterface(); | ||
225 | } | 223 | } | ||
226 | m_unmapped = false; | 224 | m_unmapped = false; | ||
227 | m_clientSize = s->size(); | 225 | m_clientSize = s->size(); | ||
228 | } else { | 226 | } else { | ||
229 | ready_for_painting = false; | 227 | ready_for_painting = false; | ||
230 | } | 228 | } | ||
231 | if (!m_internal) { | | |||
232 | doSetGeometry(QRect(QPoint(0, 0), m_clientSize)); | 229 | doSetGeometry(QRect(QPoint(0, 0), m_clientSize)); | ||
233 | } | | |||
234 | if (waylandServer()->inputMethodConnection() == s->client()) { | 230 | if (waylandServer()->inputMethodConnection() == s->client()) { | ||
235 | m_windowType = NET::OnScreenDisplay; | 231 | m_windowType = NET::OnScreenDisplay; | ||
236 | } | 232 | } | ||
237 | 233 | | |||
238 | connect(s, &SurfaceInterface::sizeChanged, this, | 234 | connect(s, &SurfaceInterface::sizeChanged, this, | ||
239 | [this] { | 235 | [this] { | ||
240 | m_clientSize = surface()->size(); | 236 | m_clientSize = surface()->size(); | ||
241 | doSetGeometry(QRect(pos(), m_clientSize + QSize(borderLeft() + borderRight(), borderTop() + borderBottom()))); | 237 | doSetGeometry(QRect(pos(), m_clientSize + QSize(borderLeft() + borderRight(), borderTop() + borderBottom()))); | ||
▲ Show 20 Lines • Show All 90 Lines • ▼ Show 20 Line(s) | 320 | } else if (m_xdgShellPopup) { | |||
332 | connect(m_xdgShellPopup, &XdgShellPopupInterface::configureAcknowledged, this, [this](int serial) { | 328 | connect(m_xdgShellPopup, &XdgShellPopupInterface::configureAcknowledged, this, [this](int serial) { | ||
333 | m_lastAckedConfigureRequest = serial; | 329 | m_lastAckedConfigureRequest = serial; | ||
334 | }); | 330 | }); | ||
335 | 331 | | |||
336 | connect(m_xdgShellPopup, &XdgShellPopupInterface::destroyed, this, &ShellClient::destroyClient); | 332 | connect(m_xdgShellPopup, &XdgShellPopupInterface::destroyed, this, &ShellClient::destroyClient); | ||
337 | } | 333 | } | ||
338 | 334 | | |||
339 | // set initial desktop | 335 | // set initial desktop | ||
340 | setDesktop(m_internal ? int(NET::OnAllDesktops) : VirtualDesktopManager::self()->current()); | 336 | setDesktop(VirtualDesktopManager::self()->current()); | ||
341 | 337 | | |||
342 | // setup shadow integration | 338 | // setup shadow integration | ||
343 | getShadow(); | 339 | getShadow(); | ||
344 | connect(s, &SurfaceInterface::shadowChanged, this, &Toplevel::getShadow); | 340 | connect(s, &SurfaceInterface::shadowChanged, this, &Toplevel::getShadow); | ||
345 | 341 | | |||
346 | connect(waylandServer(), &WaylandServer::foreignTransientChanged, this, [this](KWayland::Server::SurfaceInterface *child) { | 342 | connect(waylandServer(), &WaylandServer::foreignTransientChanged, this, [this](KWayland::Server::SurfaceInterface *child) { | ||
347 | if (child == surface()) { | 343 | if (child == surface()) { | ||
348 | setTransient(); | 344 | setTransient(); | ||
▲ Show 20 Lines • Show All 811 Lines • ▼ Show 20 Line(s) | 1155 | if (m_xdgShellSurface) { | |||
1160 | // TODO: proper | 1156 | // TODO: proper | ||
1161 | return true; | 1157 | return true; | ||
1162 | } | 1158 | } | ||
1163 | return false; | 1159 | return false; | ||
1164 | } | 1160 | } | ||
1165 | 1161 | | |||
1166 | void ShellClient::createWindowId() | 1162 | void ShellClient::createWindowId() | ||
1167 | { | 1163 | { | ||
1168 | if (!m_internal) { | | |||
1169 | m_windowId = waylandServer()->createWindowId(surface()); | 1164 | m_windowId = waylandServer()->createWindowId(surface()); | ||
1170 | } | 1165 | } | ||
1171 | } | | |||
1172 | 1166 | | |||
1173 | pid_t ShellClient::pid() const | 1167 | pid_t ShellClient::pid() const | ||
1174 | { | 1168 | { | ||
1175 | return surface()->client()->processId(); | 1169 | return surface()->client()->processId(); | ||
1176 | } | 1170 | } | ||
1177 | 1171 | | |||
1178 | bool ShellClient::isLockScreen() const | 1172 | bool ShellClient::isLockScreen() const | ||
1179 | { | 1173 | { | ||
1180 | return surface()->client() == waylandServer()->screenLockerClientConnection(); | 1174 | return surface()->client() == waylandServer()->screenLockerClientConnection(); | ||
1181 | } | 1175 | } | ||
1182 | 1176 | | |||
1183 | bool ShellClient::isInputMethod() const | 1177 | bool ShellClient::isInputMethod() const | ||
1184 | { | 1178 | { | ||
1185 | return surface()->client() == waylandServer()->inputMethodConnection(); | 1179 | return surface()->client() == waylandServer()->inputMethodConnection(); | ||
1186 | } | 1180 | } | ||
1187 | 1181 | | |||
1188 | bool ShellClient::requestGeometry(const QRect &rect) | 1182 | void ShellClient::requestGeometry(const QRect &rect) | ||
1189 | { | 1183 | { | ||
1190 | if (m_requestGeometryBlockCounter != 0) { | 1184 | if (m_requestGeometryBlockCounter != 0) { | ||
1191 | m_blockedRequestGeometry = rect; | 1185 | m_blockedRequestGeometry = rect; | ||
1192 | return false; | 1186 | return; | ||
1193 | } | 1187 | } | ||
1194 | 1188 | | |||
1195 | QSize size; | 1189 | QSize size; | ||
1196 | if (rect.isValid()) { | 1190 | if (rect.isValid()) { | ||
1197 | size = toWindowGeometry(rect.size()); | 1191 | size = toWindowGeometry(rect.size()); | ||
1198 | } else { | 1192 | } else { | ||
1199 | size = QSize(0, 0); | 1193 | size = QSize(0, 0); | ||
1200 | } | 1194 | } | ||
Show All 20 Lines | 1214 | if (rect.isValid()) { //if there's no requested size, then there's implicity no positional information worth using | |||
1221 | PendingConfigureRequest configureRequest; | 1215 | PendingConfigureRequest configureRequest; | ||
1222 | configureRequest.serialId = serialId; | 1216 | configureRequest.serialId = serialId; | ||
1223 | configureRequest.positionAfterResize = rect.topLeft(); | 1217 | configureRequest.positionAfterResize = rect.topLeft(); | ||
1224 | configureRequest.maximizeMode = m_requestedMaximizeMode; | 1218 | configureRequest.maximizeMode = m_requestedMaximizeMode; | ||
1225 | m_pendingConfigureRequests.append(configureRequest); | 1219 | m_pendingConfigureRequests.append(configureRequest); | ||
1226 | } | 1220 | } | ||
1227 | 1221 | | |||
1228 | m_blockedRequestGeometry = QRect(); | 1222 | m_blockedRequestGeometry = QRect(); | ||
1229 | return true; | | |||
1230 | } | 1223 | } | ||
1231 | 1224 | | |||
1232 | void ShellClient::updatePendingGeometry() | 1225 | void ShellClient::updatePendingGeometry() | ||
1233 | { | 1226 | { | ||
1234 | QPoint position = pos(); | 1227 | QPoint position = pos(); | ||
1235 | MaximizeMode maximizeMode = m_maximizeMode; | 1228 | MaximizeMode maximizeMode = m_maximizeMode; | ||
1236 | for (auto it = m_pendingConfigureRequests.begin(); it != m_pendingConfigureRequests.end(); it++) { | 1229 | for (auto it = m_pendingConfigureRequests.begin(); it != m_pendingConfigureRequests.end(); it++) { | ||
1237 | if (it->serialId > m_lastAckedConfigureRequest) { | 1230 | if (it->serialId > m_lastAckedConfigureRequest) { | ||
▲ Show 20 Lines • Show All 55 Lines • ▼ Show 20 Line(s) | 1275 | { | |||
1293 | emit windowHidden(this); | 1286 | emit windowHidden(this); | ||
1294 | } | 1287 | } | ||
1295 | 1288 | | |||
1296 | void ShellClient::installPlasmaShellSurface(PlasmaShellSurfaceInterface *surface) | 1289 | void ShellClient::installPlasmaShellSurface(PlasmaShellSurfaceInterface *surface) | ||
1297 | { | 1290 | { | ||
1298 | m_plasmaShellSurface = surface; | 1291 | m_plasmaShellSurface = surface; | ||
1299 | auto updatePosition = [this, surface] { | 1292 | auto updatePosition = [this, surface] { | ||
1300 | QRect rect = QRect(surface->position(), m_clientSize + QSize(borderLeft() + borderRight(), borderTop() + borderBottom())); | 1293 | QRect rect = QRect(surface->position(), m_clientSize + QSize(borderLeft() + borderRight(), borderTop() + borderBottom())); | ||
1301 | // Shell surfaces of internal windows are sometimes desync to current value. | | |||
1302 | // Make sure to not set window geometry of internal windows to invalid values (bug 386304). | | |||
1303 | // This is a workaround. | | |||
1304 | if (!m_internal || rect.isValid()) { | | |||
1305 | doSetGeometry(rect); | 1294 | doSetGeometry(rect); | ||
1306 | } | | |||
1307 | }; | 1295 | }; | ||
1308 | auto updateRole = [this, surface] { | 1296 | auto updateRole = [this, surface] { | ||
1309 | NET::WindowType type = NET::Unknown; | 1297 | NET::WindowType type = NET::Unknown; | ||
1310 | switch (surface->role()) { | 1298 | switch (surface->role()) { | ||
1311 | case PlasmaShellSurfaceInterface::Role::Desktop: | 1299 | case PlasmaShellSurfaceInterface::Role::Desktop: | ||
1312 | type = NET::Desktop; | 1300 | type = NET::Desktop; | ||
1313 | break; | 1301 | break; | ||
1314 | case PlasmaShellSurfaceInterface::Role::Panel: | 1302 | case PlasmaShellSurfaceInterface::Role::Panel: | ||
▲ Show 20 Lines • Show All 510 Lines • ▼ Show 20 Line(s) | 1812 | connect(m_xdgDecoration, &XdgDecorationInterface::modeRequested, this, | |||
1825 | [this] () { | 1813 | [this] () { | ||
1826 | //force is true as we must send a new configure response | 1814 | //force is true as we must send a new configure response | ||
1827 | updateDecoration(false, true); | 1815 | updateDecoration(false, true); | ||
1828 | }); | 1816 | }); | ||
1829 | } | 1817 | } | ||
1830 | 1818 | | |||
1831 | bool ShellClient::shouldExposeToWindowManagement() | 1819 | bool ShellClient::shouldExposeToWindowManagement() | ||
1832 | { | 1820 | { | ||
1833 | if (m_internal) { | | |||
1834 | return false; | | |||
1835 | } | | |||
1836 | if (isLockScreen()) { | 1821 | if (isLockScreen()) { | ||
1837 | return false; | 1822 | return false; | ||
1838 | } | 1823 | } | ||
1839 | if (m_xdgShellPopup) { | 1824 | if (m_xdgShellPopup) { | ||
1840 | return false; | 1825 | return false; | ||
1841 | } | 1826 | } | ||
1842 | if (m_shellSurface) { | 1827 | if (m_shellSurface) { | ||
1843 | if (m_shellSurface->isTransient() && !m_shellSurface->acceptsKeyboardFocus()) { | 1828 | if (m_shellSurface->isTransient() && !m_shellSurface->acceptsKeyboardFocus()) { | ||
Show All 26 Lines | 1854 | { | |||
1870 | if (isMinimized()) { | 1855 | if (isMinimized()) { | ||
1871 | workspace()->clientHidden(this); | 1856 | workspace()->clientHidden(this); | ||
1872 | } else { | 1857 | } else { | ||
1873 | emit windowShown(this); | 1858 | emit windowShown(this); | ||
1874 | } | 1859 | } | ||
1875 | workspace()->updateMinimizedOfTransients(this); | 1860 | workspace()->updateMinimizedOfTransients(this); | ||
1876 | } | 1861 | } | ||
1877 | 1862 | | |||
1878 | bool ShellClient::setupCompositing() | | |||
1879 | { | | |||
1880 | if (m_compositingSetup) { | | |||
1881 | return true; | | |||
1882 | } | | |||
1883 | m_compositingSetup = Toplevel::setupCompositing(); | | |||
1884 | return m_compositingSetup; | | |||
1885 | } | | |||
1886 | | ||||
1887 | void ShellClient::finishCompositing(ReleaseReason releaseReason) | | |||
1888 | { | | |||
1889 | m_compositingSetup = false; | | |||
1890 | Toplevel::finishCompositing(releaseReason); | | |||
1891 | } | | |||
1892 | | ||||
1893 | void ShellClient::placeIn(QRect &area) | 1863 | void ShellClient::placeIn(QRect &area) | ||
1894 | { | 1864 | { | ||
1895 | Placement::self()->place(this, area); | 1865 | Placement::self()->place(this, area); | ||
1896 | setGeometryRestore(geometry()); | 1866 | setGeometryRestore(geometry()); | ||
1897 | } | 1867 | } | ||
1898 | 1868 | | |||
1899 | void ShellClient::showOnScreenEdge() | 1869 | void ShellClient::showOnScreenEdge() | ||
1900 | { | 1870 | { | ||
▲ Show 20 Lines • Show All 97 Lines • ▼ Show 20 Line(s) | 1967 | if (m_shellSurface != nullptr) { | |||
1998 | return m_shellSurface->isPopup(); | 1968 | return m_shellSurface->isPopup(); | ||
1999 | } | 1969 | } | ||
2000 | if (m_xdgShellPopup != nullptr) { | 1970 | if (m_xdgShellPopup != nullptr) { | ||
2001 | return true; | 1971 | return true; | ||
2002 | } | 1972 | } | ||
2003 | return false; | 1973 | return false; | ||
2004 | } | 1974 | } | ||
2005 | 1975 | | |||
2006 | QWindow *ShellClient::internalWindow() const | | |||
2007 | { | | |||
2008 | return nullptr; | | |||
2009 | } | | |||
2010 | | ||||
2011 | bool ShellClient::supportsWindowRules() const | 1976 | bool ShellClient::supportsWindowRules() const | ||
2012 | { | 1977 | { | ||
2013 | if (m_plasmaShellSurface) { | 1978 | if (m_plasmaShellSurface) { | ||
2014 | return false; | 1979 | return false; | ||
2015 | } | 1980 | } | ||
2016 | return m_xdgShellSurface; | 1981 | return m_xdgShellSurface; | ||
2017 | } | 1982 | } | ||
2018 | 1983 | | |||
2019 | } | 1984 | } |