diff --git a/abstract_client.h b/abstract_client.h
--- a/abstract_client.h
+++ b/abstract_client.h
@@ -873,6 +873,11 @@
**/
virtual bool supportsWindowRules() const;
+ /**
+ * Returns extents of the decoration for each side.
+ **/
+ QMargins frameMargins() const;
+
public Q_SLOTS:
virtual void closeWindow() = 0;
diff --git a/abstract_client.cpp b/abstract_client.cpp
--- a/abstract_client.cpp
+++ b/abstract_client.cpp
@@ -2092,4 +2092,9 @@
return true;
}
+QMargins AbstractClient::frameMargins() const
+{
+ return QMargins(borderLeft(), borderTop(), borderRight(), borderBottom());
+}
+
}
diff --git a/autotests/integration/debug_console_test.cpp b/autotests/integration/debug_console_test.cpp
--- a/autotests/integration/debug_console_test.cpp
+++ b/autotests/integration/debug_console_test.cpp
@@ -18,11 +18,13 @@
along with this program. If not, see .
*********************************************************************/
#include "kwin_wayland_test.h"
-#include "platform.h"
#include "debug_console.h"
+#include "internal_client.h"
+#include "platform.h"
#include "screens.h"
#include "shell_client.h"
#include "wayland_server.h"
+#include "workspace.h"
#include "xcbutils.h"
#include
@@ -57,8 +59,9 @@
void DebugConsoleTest::initTestCase()
{
- qRegisterMetaType();
- qRegisterMetaType();
+ qRegisterMetaType();
+ qRegisterMetaType();
+ qRegisterMetaType();
QSignalSpy workspaceCreatedSpy(kwinApp(), &Application::workspaceCreated);
QVERIFY(workspaceCreatedSpy.isValid());
kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024));
@@ -511,12 +514,12 @@
QSignalSpy destroyedSpy(console, &QObject::destroyed);
QVERIFY(destroyedSpy.isValid());
- QSignalSpy clientAddedSpy(waylandServer(), &WaylandServer::shellClientAdded);
+ QSignalSpy clientAddedSpy(workspace(), &Workspace::internalClientAdded);
QVERIFY(clientAddedSpy.isValid());
console->show();
QCOMPARE(console->windowHandle()->isVisible(), true);
QTRY_COMPARE(clientAddedSpy.count(), 1);
- ShellClient *c = clientAddedSpy.first().first().value();
+ InternalClient *c = clientAddedSpy.first().first().value();
QVERIFY(c->isInternal());
QCOMPARE(c->internalWindow(), console->windowHandle());
QVERIFY(c->isDecorated());
diff --git a/autotests/integration/decoration_input_test.cpp b/autotests/integration/decoration_input_test.cpp
--- a/autotests/integration/decoration_input_test.cpp
+++ b/autotests/integration/decoration_input_test.cpp
@@ -18,16 +18,17 @@
along with this program. If not, see .
*********************************************************************/
#include "kwin_wayland_test.h"
-#include "platform.h"
#include "abstract_client.h"
#include "cursor.h"
+#include "internal_client.h"
+#include "platform.h"
#include "pointer_input.h"
#include "touch_input.h"
#include "screenedge.h"
#include "screens.h"
+#include "shell_client.h"
#include "wayland_server.h"
#include "workspace.h"
-#include "shell_client.h"
#include
#include "decorations/decoratedclient.h"
@@ -133,8 +134,8 @@
void DecorationInputTest::initTestCase()
{
- qRegisterMetaType();
- qRegisterMetaType();
+ qRegisterMetaType();
+ qRegisterMetaType();
QSignalSpy workspaceCreatedSpy(kwinApp(), &Application::workspaceCreated);
QVERIFY(workspaceCreatedSpy.isValid());
kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024));
@@ -910,12 +911,12 @@
QSignalSpy keyEvent(keyboard, &KWayland::Client::Keyboard::keyChanged);
QVERIFY(keyEvent.isValid());
- QSignalSpy clientAddedSpy(waylandServer(), &WaylandServer::shellClientAdded);
+ QSignalSpy clientAddedSpy(workspace(), &Workspace::internalClientAdded);
QVERIFY(clientAddedSpy.isValid());
c->decoratedClient()->requestShowToolTip(QStringLiteral("test"));
// now we should get an internal window
QVERIFY(clientAddedSpy.wait());
- ShellClient *internal = clientAddedSpy.first().first().value();
+ InternalClient *internal = clientAddedSpy.first().first().value();
QVERIFY(internal->isInternal());
QVERIFY(internal->internalWindow()->flags().testFlag(Qt::ToolTip));
diff --git a/autotests/integration/effects/popup_open_close_animation_test.cpp b/autotests/integration/effects/popup_open_close_animation_test.cpp
--- a/autotests/integration/effects/popup_open_close_animation_test.cpp
+++ b/autotests/integration/effects/popup_open_close_animation_test.cpp
@@ -24,6 +24,7 @@
#include "deleted.h"
#include "effectloader.h"
#include "effects.h"
+#include "internal_client.h"
#include "platform.h"
#include "shell_client.h"
#include "useractions.h"
@@ -248,11 +249,11 @@
QVERIFY(!effect->isActive());
// Show a decoration tooltip.
- QSignalSpy tooltipAddedSpy(waylandServer(), &WaylandServer::shellClientAdded);
+ QSignalSpy tooltipAddedSpy(workspace(), &Workspace::internalClientAdded);
QVERIFY(tooltipAddedSpy.isValid());
client->decoratedClient()->requestShowToolTip(QStringLiteral("KWin rocks!"));
QVERIFY(tooltipAddedSpy.wait());
- ShellClient *tooltip = tooltipAddedSpy.first().first().value();
+ InternalClient *tooltip = tooltipAddedSpy.first().first().value();
QVERIFY(tooltip->isInternal());
QVERIFY(tooltip->isPopupWindow());
QVERIFY(tooltip->internalWindow()->flags().testFlag(Qt::ToolTip));
@@ -262,7 +263,7 @@
QTRY_VERIFY(!effect->isActive());
// Hide the decoration tooltip.
- QSignalSpy tooltipClosedSpy(tooltip, &ShellClient::windowClosed);
+ QSignalSpy tooltipClosedSpy(tooltip, &InternalClient::windowClosed);
QVERIFY(tooltipClosedSpy.isValid());
client->decoratedClient()->requestHideToolTip();
QVERIFY(tooltipClosedSpy.wait());
diff --git a/autotests/integration/internal_window.cpp b/autotests/integration/internal_window.cpp
--- a/autotests/integration/internal_window.cpp
+++ b/autotests/integration/internal_window.cpp
@@ -22,8 +22,8 @@
#include "cursor.h"
#include "effects.h"
#include "internal_client.h"
-#include "shell_client.h"
#include "screens.h"
+#include "shell_client.h"
#include "wayland_server.h"
#include "workspace.h"
@@ -184,8 +184,8 @@
void InternalWindowTest::initTestCase()
{
- qRegisterMetaType();
- qRegisterMetaType();
+ qRegisterMetaType();
+ qRegisterMetaType();
QSignalSpy workspaceCreatedSpy(kwinApp(), &Application::workspaceCreated);
QVERIFY(workspaceCreatedSpy.isValid());
kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024));
@@ -215,22 +215,22 @@
void InternalWindowTest::testEnterLeave()
{
- QSignalSpy clientAddedSpy(waylandServer(), &WaylandServer::shellClientAdded);
+ QSignalSpy clientAddedSpy(workspace(), &Workspace::internalClientAdded);
QVERIFY(clientAddedSpy.isValid());
HelperWindow win;
- QVERIFY(!workspace()->findToplevel(nullptr));
- QVERIFY(!workspace()->findToplevel(&win));
+ QVERIFY(!workspace()->findInternal(nullptr));
+ QVERIFY(!workspace()->findInternal(&win));
win.setGeometry(0, 0, 100, 100);
win.show();
QTRY_COMPARE(clientAddedSpy.count(), 1);
QVERIFY(!workspace()->activeClient());
- ShellClient *c = clientAddedSpy.first().first().value();
+ InternalClient *c = clientAddedSpy.first().first().value();
QVERIFY(c->isInternal());
QVERIFY(qobject_cast(c));
QCOMPARE(c->icon().name(), QStringLiteral("wayland"));
QVERIFY(!c->isDecorated());
- QCOMPARE(workspace()->findToplevel(&win), c);
+ QCOMPARE(workspace()->findInternal(&win), c);
QCOMPARE(c->geometry(), QRect(0, 0, 100, 100));
QVERIFY(c->isShown(false));
QVERIFY(workspace()->xStackingOrder().contains(c));
@@ -276,7 +276,7 @@
void InternalWindowTest::testPointerPressRelease()
{
- QSignalSpy clientAddedSpy(waylandServer(), &WaylandServer::shellClientAdded);
+ QSignalSpy clientAddedSpy(workspace(), &Workspace::internalClientAdded);
QVERIFY(clientAddedSpy.isValid());
HelperWindow win;
win.setGeometry(0, 0, 100, 100);
@@ -299,7 +299,7 @@
void InternalWindowTest::testPointerAxis()
{
- QSignalSpy clientAddedSpy(waylandServer(), &WaylandServer::shellClientAdded);
+ QSignalSpy clientAddedSpy(workspace(), &Workspace::internalClientAdded);
QVERIFY(clientAddedSpy.isValid());
HelperWindow win;
win.setGeometry(0, 0, 100, 100);
@@ -327,7 +327,7 @@
void InternalWindowTest::testKeyboard()
{
- QSignalSpy clientAddedSpy(waylandServer(), &WaylandServer::shellClientAdded);
+ QSignalSpy clientAddedSpy(workspace(), &Workspace::internalClientAdded);
QVERIFY(clientAddedSpy.isValid());
HelperWindow win;
win.setGeometry(0, 0, 100, 100);
@@ -337,7 +337,7 @@
QSignalSpy releaseSpy(&win, &HelperWindow::keyReleased);
QVERIFY(releaseSpy.isValid());
QTRY_COMPARE(clientAddedSpy.count(), 1);
- auto internalClient = clientAddedSpy.first().first().value();
+ auto internalClient = clientAddedSpy.first().first().value();
QVERIFY(internalClient);
QVERIFY(internalClient->isInternal());
QVERIFY(internalClient->readyForPainting());
@@ -356,7 +356,7 @@
void InternalWindowTest::testKeyboardShowWithoutActivating()
{
- QSignalSpy clientAddedSpy(waylandServer(), &WaylandServer::shellClientAdded);
+ QSignalSpy clientAddedSpy(workspace(), &Workspace::internalClientAdded);
QVERIFY(clientAddedSpy.isValid());
HelperWindow win;
win.setProperty("_q_showWithoutActivating", true);
@@ -367,7 +367,7 @@
QSignalSpy releaseSpy(&win, &HelperWindow::keyReleased);
QVERIFY(releaseSpy.isValid());
QTRY_COMPARE(clientAddedSpy.count(), 1);
- auto internalClient = clientAddedSpy.first().first().value();
+ auto internalClient = clientAddedSpy.first().first().value();
QVERIFY(internalClient);
QVERIFY(internalClient->isInternal());
QVERIFY(internalClient->readyForPainting());
@@ -412,7 +412,7 @@
QCOMPARE(enteredSpy.count(), 1);
// create internal window
- QSignalSpy clientAddedSpy(waylandServer(), &WaylandServer::shellClientAdded);
+ QSignalSpy clientAddedSpy(workspace(), &Workspace::internalClientAdded);
QVERIFY(clientAddedSpy.isValid());
HelperWindow win;
win.setGeometry(0, 0, 100, 100);
@@ -422,7 +422,7 @@
QSignalSpy releaseSpy(&win, &HelperWindow::keyReleased);
QVERIFY(releaseSpy.isValid());
QTRY_COMPARE(clientAddedSpy.count(), 1);
- auto internalClient = clientAddedSpy.first().first().value();
+ auto internalClient = clientAddedSpy.first().first().value();
QVERIFY(internalClient);
QVERIFY(internalClient->isInternal());
QVERIFY(internalClient->readyForPainting());
@@ -449,7 +449,7 @@
void InternalWindowTest::testTouch()
{
// touch events for internal windows are emulated through mouse events
- QSignalSpy clientAddedSpy(waylandServer(), &WaylandServer::shellClientAdded);
+ QSignalSpy clientAddedSpy(workspace(), &Workspace::internalClientAdded);
QVERIFY(clientAddedSpy.isValid());
HelperWindow win;
win.setGeometry(0, 0, 100, 100);
@@ -513,36 +513,36 @@
void InternalWindowTest::testOpacity()
{
- // this test verifies that opacity is properly synced from QWindow to ShellClient
- QSignalSpy clientAddedSpy(waylandServer(), &WaylandServer::shellClientAdded);
+ // this test verifies that opacity is properly synced from QWindow to InternalClient
+ QSignalSpy clientAddedSpy(workspace(), &Workspace::internalClientAdded);
QVERIFY(clientAddedSpy.isValid());
HelperWindow win;
win.setOpacity(0.5);
win.setGeometry(0, 0, 100, 100);
win.show();
QTRY_COMPARE(clientAddedSpy.count(), 1);
- auto internalClient = clientAddedSpy.first().first().value();
+ auto internalClient = clientAddedSpy.first().first().value();
QVERIFY(internalClient);
QVERIFY(internalClient->isInternal());
QCOMPARE(internalClient->opacity(), 0.5);
- QSignalSpy opacityChangedSpy(internalClient, &ShellClient::opacityChanged);
+ QSignalSpy opacityChangedSpy(internalClient, &InternalClient::opacityChanged);
QVERIFY(opacityChangedSpy.isValid());
win.setOpacity(0.75);
QCOMPARE(opacityChangedSpy.count(), 1);
QCOMPARE(internalClient->opacity(), 0.75);
}
void InternalWindowTest::testMove()
{
- QSignalSpy clientAddedSpy(waylandServer(), &WaylandServer::shellClientAdded);
+ QSignalSpy clientAddedSpy(workspace(), &Workspace::internalClientAdded);
QVERIFY(clientAddedSpy.isValid());
HelperWindow win;
win.setOpacity(0.5);
win.setGeometry(0, 0, 100, 100);
win.show();
QTRY_COMPARE(clientAddedSpy.count(), 1);
- auto internalClient = clientAddedSpy.first().first().value();
+ auto internalClient = clientAddedSpy.first().first().value();
QVERIFY(internalClient);
QCOMPARE(internalClient->geometry(), QRect(0, 0, 100, 100));
@@ -576,16 +576,16 @@
void InternalWindowTest::testSkipCloseAnimation()
{
- QSignalSpy clientAddedSpy(waylandServer(), &WaylandServer::shellClientAdded);
+ QSignalSpy clientAddedSpy(workspace(), &Workspace::internalClientAdded);
QVERIFY(clientAddedSpy.isValid());
HelperWindow win;
win.setOpacity(0.5);
win.setGeometry(0, 0, 100, 100);
QFETCH(bool, initial);
win.setProperty("KWIN_SKIP_CLOSE_ANIMATION", initial);
win.show();
QTRY_COMPARE(clientAddedSpy.count(), 1);
- auto internalClient = clientAddedSpy.first().first().value();
+ auto internalClient = clientAddedSpy.first().first().value();
QVERIFY(internalClient);
QCOMPARE(internalClient->skipsCloseAnimation(), initial);
QSignalSpy skipCloseChangedSpy(internalClient, &Toplevel::skipCloseAnimationChanged);
@@ -600,14 +600,14 @@
void InternalWindowTest::testModifierClickUnrestrictedMove()
{
- QSignalSpy clientAddedSpy(waylandServer(), &WaylandServer::shellClientAdded);
+ QSignalSpy clientAddedSpy(workspace(), &Workspace::internalClientAdded);
QVERIFY(clientAddedSpy.isValid());
HelperWindow win;
win.setGeometry(0, 0, 100, 100);
win.setFlags(win.flags() & ~Qt::FramelessWindowHint);
win.show();
QTRY_COMPARE(clientAddedSpy.count(), 1);
- auto internalClient = clientAddedSpy.first().first().value();
+ auto internalClient = clientAddedSpy.first().first().value();
QVERIFY(internalClient);
QVERIFY(internalClient->isDecorated());
@@ -642,14 +642,14 @@
void InternalWindowTest::testModifierScroll()
{
- QSignalSpy clientAddedSpy(waylandServer(), &WaylandServer::shellClientAdded);
+ QSignalSpy clientAddedSpy(workspace(), &Workspace::internalClientAdded);
QVERIFY(clientAddedSpy.isValid());
HelperWindow win;
win.setGeometry(0, 0, 100, 100);
win.setFlags(win.flags() & ~Qt::FramelessWindowHint);
win.show();
QTRY_COMPARE(clientAddedSpy.count(), 1);
- auto internalClient = clientAddedSpy.first().first().value();
+ auto internalClient = clientAddedSpy.first().first().value();
QVERIFY(internalClient);
QVERIFY(internalClient->isDecorated());
@@ -676,14 +676,14 @@
void InternalWindowTest::testPopup()
{
- QSignalSpy clientAddedSpy(waylandServer(), &WaylandServer::shellClientAdded);
+ QSignalSpy clientAddedSpy(workspace(), &Workspace::internalClientAdded);
QVERIFY(clientAddedSpy.isValid());
HelperWindow win;
win.setGeometry(0, 0, 100, 100);
win.setFlags(win.flags() | Qt::Popup);
win.show();
QTRY_COMPARE(clientAddedSpy.count(), 1);
- auto internalClient = clientAddedSpy.first().first().value();
+ auto internalClient = clientAddedSpy.first().first().value();
QVERIFY(internalClient);
QCOMPARE(internalClient->isPopupWindow(), true);
}
@@ -695,15 +695,15 @@
Q_ARG(QVector, QVector({QRect(0,0,1280, 1024), QRect(1280/2, 0, 1280, 1024)})),
Q_ARG(QVector, QVector({2,2})));
- QSignalSpy clientAddedSpy(waylandServer(), &WaylandServer::shellClientAdded);
+ QSignalSpy clientAddedSpy(workspace(), &Workspace::internalClientAdded);
QVERIFY(clientAddedSpy.isValid());
HelperWindow win;
win.setGeometry(0, 0, 100, 100);
win.setFlags(win.flags() | Qt::Popup);
win.show();
QCOMPARE(win.devicePixelRatio(), 2.0);
QTRY_COMPARE(clientAddedSpy.count(), 1);
- auto internalClient = clientAddedSpy.first().first().value();
+ auto internalClient = clientAddedSpy.first().first().value();
QCOMPARE(internalClient->surface()->scale(), 2);
QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(int, 2));
@@ -732,15 +732,15 @@
void InternalWindowTest::testWindowType()
{
- QSignalSpy clientAddedSpy(waylandServer(), &WaylandServer::shellClientAdded);
+ QSignalSpy clientAddedSpy(workspace(), &Workspace::internalClientAdded);
QVERIFY(clientAddedSpy.isValid());
HelperWindow win;
win.setGeometry(0, 0, 100, 100);
QFETCH(NET::WindowType, windowType);
KWindowSystem::setType(win.winId(), windowType);
win.show();
QTRY_COMPARE(clientAddedSpy.count(), 1);
- auto internalClient = clientAddedSpy.first().first().value();
+ auto internalClient = clientAddedSpy.first().first().value();
QVERIFY(internalClient);
QCOMPARE(internalClient->windowType(), windowType);
}
@@ -767,13 +767,13 @@
void InternalWindowTest::testChangeWindowType()
{
- QSignalSpy clientAddedSpy(waylandServer(), &WaylandServer::shellClientAdded);
+ QSignalSpy clientAddedSpy(workspace(), &Workspace::internalClientAdded);
QVERIFY(clientAddedSpy.isValid());
HelperWindow win;
win.setGeometry(0, 0, 100, 100);
win.show();
QTRY_COMPARE(clientAddedSpy.count(), 1);
- auto internalClient = clientAddedSpy.first().first().value();
+ auto internalClient = clientAddedSpy.first().first().value();
QVERIFY(internalClient);
QCOMPARE(internalClient->windowType(), NET::Normal);
@@ -787,13 +787,13 @@
void InternalWindowTest::testEffectWindow()
{
- QSignalSpy clientAddedSpy(waylandServer(), &WaylandServer::shellClientAdded);
+ QSignalSpy clientAddedSpy(workspace(), &Workspace::internalClientAdded);
QVERIFY(clientAddedSpy.isValid());
HelperWindow win;
win.setGeometry(0, 0, 100, 100);
win.show();
QTRY_COMPARE(clientAddedSpy.count(), 1);
- auto internalClient = clientAddedSpy.first().first().value();
+ auto internalClient = clientAddedSpy.first().first().value();
QVERIFY(internalClient);
QVERIFY(internalClient->effectWindow());
QCOMPARE(internalClient->effectWindow()->internalWindow(), &win);
diff --git a/composite.cpp b/composite.cpp
--- a/composite.cpp
+++ b/composite.cpp
@@ -24,6 +24,7 @@
#include "decorations/decoratedclient.h"
#include "deleted.h"
#include "effects.h"
+#include "internal_client.h"
#include "overlaywindow.h"
#include "platform.h"
#include "scene.h"
@@ -342,17 +343,17 @@
c->setupCompositing();
c->getShadow();
}
+ const InternalClientList internalClients = workspace()->internalClients();
+ for (InternalClient *c : internalClients) {
+ c->setupCompositing();
+ c->getShadow();
+ }
if (auto w = waylandServer()) {
const auto clients = w->clients();
for (auto c : clients) {
c->setupCompositing();
c->getShadow();
}
- const auto internalClients = w->internalClients();
- for (auto c : internalClients) {
- c->setupCompositing();
- c->getShadow();
- }
}
m_state = State::On;
@@ -389,18 +390,25 @@
effects = nullptr;
if (Workspace::self()) {
+ const InternalClientList internalClients = workspace()->internalClients();
foreach (Client * c, Workspace::self()->clientList())
m_scene->removeToplevel(c);
foreach (Client * c, Workspace::self()->desktopList())
m_scene->removeToplevel(c);
foreach (Unmanaged * c, Workspace::self()->unmanagedList())
m_scene->removeToplevel(c);
+ for (InternalClient *client : internalClients) {
+ m_scene->removeToplevel(client);
+ }
foreach (Client * c, Workspace::self()->clientList())
c->finishCompositing();
foreach (Client * c, Workspace::self()->desktopList())
c->finishCompositing();
foreach (Unmanaged * c, Workspace::self()->unmanagedList())
c->finishCompositing();
+ for (InternalClient *client : internalClients) {
+ client->finishCompositing();
+ }
if (auto c = kwinApp()->x11Connection()) {
xcb_composite_unredirect_subwindows(c, kwinApp()->x11RootWindow(), XCB_COMPOSITE_REDIRECT_MANUAL);
}
@@ -412,15 +420,9 @@
foreach (ShellClient *c, waylandServer()->clients()) {
m_scene->removeToplevel(c);
}
- foreach (ShellClient *c, waylandServer()->internalClients()) {
- m_scene->removeToplevel(c);
- }
foreach (ShellClient *c, waylandServer()->clients()) {
c->finishCompositing();
}
- foreach (ShellClient *c, waylandServer()->internalClients()) {
- c->finishCompositing();
- }
}
delete m_scene;
m_scene = NULL;
@@ -793,13 +795,13 @@
if (std::any_of(clients.begin(), clients.end(), test)) {
return true;
}
- const auto &internalClients = w->internalClients();
- auto internalTest = [] (ShellClient *c) {
- return c->isShown(true) && !c->repaints().isEmpty();
- };
- if (std::any_of(internalClients.begin(), internalClients.end(), internalTest)) {
- return true;
- }
+ }
+ const auto &internalClients = workspace()->internalClients();
+ auto internalTest = [] (InternalClient *c) {
+ return c->isShown(true) && !c->repaints().isEmpty();
+ };
+ if (std::any_of(internalClients.begin(), internalClients.end(), internalTest)) {
+ return true;
}
return false;
}
diff --git a/debug_console.h b/debug_console.h
--- a/debug_console.h
+++ b/debug_console.h
@@ -40,6 +40,7 @@
{
class Client;
+class InternalClient;
class ShellClient;
class Unmanaged;
class DebugConsoleFilter;
@@ -73,13 +74,13 @@
template
void remove(int parentRow, QVector &clients, T *client);
ShellClient *shellClient(const QModelIndex &index) const;
- ShellClient *internalClient(const QModelIndex &index) const;
+ InternalClient *internalClient(const QModelIndex &index) const;
Client *x11Client(const QModelIndex &index) const;
Unmanaged *unmanaged(const QModelIndex &index) const;
int topLevelRowCount() const;
QVector m_shellClients;
- QVector m_internalClients;
+ QVector m_internalClients;
QVector m_x11Clients;
QVector m_unmanageds;
diff --git a/debug_console.cpp b/debug_console.cpp
--- a/debug_console.cpp
+++ b/debug_console.cpp
@@ -21,6 +21,7 @@
#include "composite.h"
#include "client.h"
#include "input_event.h"
+#include "internal_client.h"
#include "main.h"
#include "scene.h"
#include "shell_client.h"
@@ -795,23 +796,14 @@
for (auto c : clients) {
m_shellClients.append(c);
}
- const auto internals = waylandServer()->internalClients();
- for (auto c : internals) {
- m_internalClients.append(c);
- }
// TODO: that only includes windows getting shown, not those which are only created
connect(waylandServer(), &WaylandServer::shellClientAdded, this,
[this] (ShellClient *c) {
- if (c->isInternal()) {
- add(s_waylandInternalId -1, m_internalClients, c);
- } else {
- add(s_waylandClientId -1, m_shellClients, c);
- }
+ add(s_waylandClientId -1, m_shellClients, c);
}
);
connect(waylandServer(), &WaylandServer::shellClientRemoved, this,
[this] (ShellClient *c) {
- remove(s_waylandInternalId -1, m_internalClients, c);
remove(s_waylandClientId -1, m_shellClients, c);
}
);
@@ -853,6 +845,20 @@
remove(s_x11UnmanagedId -1, m_unmanageds, u);
}
);
+ const auto internals = workspace()->internalClients();
+ for (auto c : internals) {
+ m_internalClients.append(c);
+ }
+ connect(workspace(), &Workspace::internalClientAdded, this,
+ [this](InternalClient *client) {
+ add(s_waylandInternalId -1, m_internalClients, client);
+ }
+ );
+ connect(workspace(), &Workspace::internalClientRemoved, this,
+ [this](InternalClient *client) {
+ remove(s_waylandInternalId -1, m_internalClients, client);
+ }
+ );
}
DebugConsoleModel::~DebugConsoleModel() = default;
@@ -1110,7 +1116,7 @@
}
if (ShellClient *c = shellClient(index)) {
return propertyData(c, index, role);
- } else if (ShellClient *c = internalClient(index)) {
+ } else if (InternalClient *c = internalClient(index)) {
return propertyData(c, index, role);
} else if (Client *c = x11Client(index)) {
return propertyData(c, index, role);
@@ -1161,7 +1167,7 @@
return clientForIndex(index, m_shellClients, s_waylandClientId);
}
-ShellClient *DebugConsoleModel::internalClient(const QModelIndex &index) const
+InternalClient *DebugConsoleModel::internalClient(const QModelIndex &index) const
{
return clientForIndex(index, m_internalClients, s_waylandInternalId);
}
@@ -1207,9 +1213,6 @@
connect(c->surface(), &SurfaceInterface::subSurfaceTreeChanged, this, reset);
}
if (waylandServer()) {
- for (auto c : waylandServer()->internalClients()) {
- connect(c->surface(), &SurfaceInterface::subSurfaceTreeChanged, this, reset);
- }
connect(waylandServer(), &WaylandServer::shellClientAdded, this,
[this, reset] (ShellClient *c) {
connect(c->surface(), &SurfaceInterface::subSurfaceTreeChanged, this, reset);
@@ -1235,6 +1238,8 @@
}
);
connect(workspace(), &Workspace::unmanagedRemoved, this, reset);
+ connect(workspace(), &Workspace::internalClientAdded, this, reset);
+ connect(workspace(), &Workspace::internalClientRemoved, this, reset);
}
SurfaceTreeModel::~SurfaceTreeModel() = default;
@@ -1255,12 +1260,11 @@
}
return 0;
}
- const int internalClientsCount = waylandServer() ? waylandServer()->internalClients().count() : 0;
// toplevel are all windows
return workspace()->allClientList().count() +
workspace()->desktopList().count() +
workspace()->unmanagedList().count() +
- internalClientsCount;
+ workspace()->internalClients().count();
}
QModelIndex SurfaceTreeModel::index(int row, int column, const QModelIndex &parent) const
@@ -1297,11 +1301,9 @@
return createIndex(row, column, unmanaged.at(row-reference)->surface());
}
reference += unmanaged.count();
- if (waylandServer()) {
- const auto &internal = waylandServer()->internalClients();
- if (row < reference + internal.count()) {
- return createIndex(row, column, internal.at(row-reference)->surface());
- }
+ const auto &internal = workspace()->internalClients();
+ if (row < reference + internal.count()) {
+ return createIndex(row, column, internal.at(row-reference)->surface());
}
// not found
return QModelIndex();
@@ -1359,14 +1361,6 @@
}
}
row += unmanaged.count();
- if (waylandServer()) {
- const auto &internal = waylandServer()->internalClients();
- for (int i = 0; i < internal.count(); i++) {
- if (internal.at(i)->surface() == parent) {
- return createIndex(row + i, 0, parent);
- }
- }
- }
}
return QModelIndex();
}
diff --git a/effects.h b/effects.h
--- a/effects.h
+++ b/effects.h
@@ -293,6 +293,7 @@
void slotClientShown(KWin::Toplevel*);
void slotShellClientShown(KWin::Toplevel*);
void slotUnmanagedShown(KWin::Toplevel*);
+ void slotInternalClientShown(KWin::Toplevel *client);
void slotWindowClosed(KWin::Toplevel *c, KWin::Deleted *d);
void slotClientMaximized(KWin::AbstractClient *c, MaximizeMode maxMode);
void slotOpacityChanged(KWin::Toplevel *t, qreal oldOpacity);
diff --git a/effects.cpp b/effects.cpp
--- a/effects.cpp
+++ b/effects.cpp
@@ -30,6 +30,7 @@
#include "client.h"
#include "cursor.h"
#include "group.h"
+#include "internal_client.h"
#include "osd.h"
#include "pointer_input.h"
#include "unmanaged.h"
@@ -180,6 +181,15 @@
connect(u, &Toplevel::windowShown, this, &EffectsHandlerImpl::slotUnmanagedShown);
}
);
+ connect(ws, &Workspace::internalClientAdded, this,
+ [this](InternalClient *client) {
+ if (client->readyForPainting()) {
+ slotInternalClientShown(client);
+ } else {
+ connect(client, &Toplevel::windowShown, this, &EffectsHandlerImpl::slotInternalClientShown);
+ }
+ }
+ );
connect(ws, &Workspace::clientActivated, this,
[this](KWin::AbstractClient *c) {
emit windowActivated(c ? c->effectWindow() : nullptr);
@@ -247,6 +257,10 @@
for (Unmanaged *u : ws->unmanagedList()) {
setupUnmanagedConnections(u);
}
+ const InternalClientList internalClients = ws->internalClients();
+ for (InternalClient *client : internalClients) {
+ setupAbstractClientConnections(client);
+ }
if (auto w = waylandServer()) {
connect(w, &WaylandServer::shellClientAdded, this,
[this](ShellClient *c) {
@@ -582,6 +596,13 @@
emit windowAdded(u->effectWindow());
}
+void EffectsHandlerImpl::slotInternalClientShown(KWin::Toplevel *toplevel)
+{
+ InternalClient *client = static_cast(toplevel);
+ setupAbstractClientConnections(client);
+ emit windowAdded(client->effectWindow());
+}
+
void EffectsHandlerImpl::slotWindowClosed(KWin::Toplevel *c, KWin::Deleted *d)
{
c->disconnect(this);
@@ -1090,13 +1111,8 @@
EffectWindow *EffectsHandlerImpl::findWindow(QWindow *w) const
{
- if (waylandServer()) {
- if (auto c = waylandServer()->findClient(w)) {
- return c->effectWindow();
- }
- }
- if (auto u = Workspace::self()->findUnmanaged(w->winId())) {
- return u->effectWindow();
+ if (Toplevel *toplevel = workspace()->findInternal(w)) {
+ return toplevel->effectWindow();
}
return nullptr;
}
@@ -1965,7 +1981,7 @@
QWindow *EffectWindowImpl::internalWindow() const
{
- auto client = qobject_cast(toplevel);
+ auto client = qobject_cast(toplevel);
if (!client) {
return nullptr;
}
diff --git a/geometry.cpp b/geometry.cpp
--- a/geometry.cpp
+++ b/geometry.cpp
@@ -39,6 +39,7 @@
#include "screens.h"
#include "effects.h"
#include "screenedge.h"
+#include "internal_client.h"
#include
#include
#include
@@ -200,7 +201,7 @@
}
}
if (waylandServer()) {
- auto updateStrutsForWaylandClient = [&] (ShellClient *c) {
+ auto updateStrutsForWaylandClient = [&] (AbstractClient *c) {
// assuming that only docks have "struts" and that all docks have a strut
if (!c->hasStrut()) {
return;
@@ -268,9 +269,10 @@
for (auto c : clients) {
updateStrutsForWaylandClient(c);
}
- const auto internalClients = waylandServer()->internalClients();
- for (auto c : internalClients) {
- updateStrutsForWaylandClient(c);
+ // FIXME: Update struts on X11 too.
+ const InternalClientList internalClients = workspace()->internalClients();
+ for (InternalClient *client : internalClients) {
+ updateStrutsForWaylandClient(client);
}
}
#if 0
diff --git a/input.cpp b/input.cpp
--- a/input.cpp
+++ b/input.cpp
@@ -46,6 +46,7 @@
#include "shell_client.h"
#include "wayland_server.h"
#include "xwl/xwayland_interface.h"
+#include "internal_client.h"
#include
#include
#include
@@ -818,7 +819,7 @@
{
case QEvent::MouseButtonPress:
case QEvent::MouseButtonRelease: {
- auto s = waylandServer()->findClient(internal);
+ auto s = static_cast(workspace()->findInternal(internal));
if (s && s->isDecorated()) {
// only perform mouse commands on decorated internal windows
const auto actionResult = performClientMouseAction(event, s);
@@ -845,7 +846,7 @@
return false;
}
if (event->angleDelta().y() != 0) {
- auto s = waylandServer()->findClient(internal);
+ auto s = static_cast(workspace()->findInternal(internal));
if (s && s->isDecorated()) {
// client window action only on vertical scrolling
const auto actionResult = performClientWheelAction(event, s);
@@ -868,7 +869,7 @@
return e.isAccepted();
}
bool keyEvent(QKeyEvent *event) override {
- const auto &internalClients = waylandServer()->internalClients();
+ const InternalClientList &internalClients = workspace()->internalClients();
if (internalClients.isEmpty()) {
return false;
}
@@ -2349,7 +2350,7 @@
const auto pos = position().toPoint();
internalWindow = findInternalWindow(pos);
if (internalWindow) {
- toplevel = waylandServer()->findClient(internalWindow);
+ toplevel = workspace()->findInternal(internalWindow);
} else {
toplevel = input()->findToplevel(pos);
}
@@ -2394,7 +2395,7 @@
return nullptr;
}
- const auto &internalClients = waylandServer()->internalClients();
+ const InternalClientList &internalClients = workspace()->internalClients();
if (internalClients.isEmpty()) {
return nullptr;
}
diff --git a/internal_client.h b/internal_client.h
--- a/internal_client.h
+++ b/internal_client.h
@@ -3,6 +3,7 @@
This file is part of the KDE project.
Copyright (C) 2019 Martin Flöser
+Copyright (C) 2019 Vlad Zagorodniy
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -19,31 +20,41 @@
*********************************************************************/
#pragma once
-#include "shell_client.h"
-
+#include "abstract_client.h"
namespace KWin
{
-class KWIN_EXPORT InternalClient : public ShellClient
+class KWIN_EXPORT InternalClient : public AbstractClient
{
Q_OBJECT
+
public:
- InternalClient(KWayland::Server::ShellSurfaceInterface *surface);
- // needed for template void WaylandServer::createSurface(T *surface)
- InternalClient(KWayland::Server::XdgShellSurfaceInterface *surface);
- // needed for template void WaylandServer::createSurface(T *surface)
- InternalClient(KWayland::Server::XdgShellPopupInterface *surface);
+ explicit InternalClient(QWindow *window);
~InternalClient() override;
bool eventFilter(QObject *watched, QEvent *event) override;
+ void blockActivityUpdates(bool b = true) override;
+ QStringList activities() const override;
+ QPoint clientContentPos() const override;
+ QSize clientSize() const override;
+ QRect transparentRect() const override;
NET::WindowType windowType(bool direct = false, int supported_types = 0) const override;
+ void debug(QDebug &stream) const override;
+ double opacity() const override;
+ void setOpacity(double opacity) override;
void killWindow() override;
bool isPopupWindow() const override;
void setInternalFramebufferObject(const QSharedPointer &fbo) override;
+ void setInternalImageObject(const QImage &image) override;
+ QString captionNormal() const override;
+ QString captionSuffix() const override;
+ QByteArray windowRole() const override;
void closeWindow() override;
bool isCloseable() const override;
+ bool isFullScreenable() const override;
+ bool isFullScreen() const override;
bool isMaximizable() const override;
bool isMinimizable() const override;
bool isMovable() const override;
@@ -57,27 +68,61 @@
bool isInputMethod() const override;
bool isOutline() const override;
quint32 windowId() const override;
+ MaximizeMode maximizeMode() const override;
+ QRect geometryRestore() const override;
+ bool isShown(bool shaded_is_shown) const override;
+ bool isHiddenInternal() const override;
+ void hideClient(bool hide) override;
using AbstractClient::resizeWithChecks;
void resizeWithChecks(int w, int h, ForceGeometry_t force = NormalGeometrySet) override;
- QWindow *internalWindow() const override;
+ using AbstractClient::setGeometry;
+ void setGeometry(int x, int y, int w, int h, ForceGeometry_t force = NormalGeometrySet) override;
+ void setGeometryRestore(const QRect &geo) override;
bool supportsWindowRules() const override;
+ AbstractClient *findModal(bool allow_itself = false) override;
+ void setOnAllActivities(bool set) override;
+ void takeFocus() override;
+ bool userCanSetFullScreen() const override;
+ void setFullScreen(bool set, bool user = true) override;
+ void setNoBorder(bool set) override;
+ void updateDecoration(bool check_workspace_pos, bool force = false) override;
+ void updateColorScheme() override;
+ void showOnScreenEdge() override;
+
+ void destroyClient();
+ QWindow *internalWindow() const;
protected:
bool acceptsFocus() const override;
+ bool belongsToSameApplication(const AbstractClient *other, SameApplicationChecks checks) const override;
+ void changeMaximize(bool horizontal, bool vertical, bool adjust) override;
void doMove(int x, int y) override;
void doResizeSync() override;
- bool requestGeometry(const QRect &rect) override;
- void doSetGeometry(const QRect &rect) override;
+ void doSetGeometry(const QRect &rect);
+ void requestGeometry(const QRect &rect);
+ void updateCaption() override;
private:
- void findInternalWindow();
+ QRect contentToFrame(const QRect &rect) const;
+ QRect frameToContent(const QRect &rect) const;
+ void map(QSharedPointer fbo);
+ void map(const QImage &image);
+ void unmap();
+ void markAsMapped();
void updateInternalWindowGeometry();
void syncGeometryToInternalWindow();
+ QWindow *m_internalWindow = nullptr;
+ QSize m_clientSize = QSize(0, 0);
+ QString m_captionNormal;
+ QString m_captionSuffix;
+ double m_opacity = 1.0;
NET::WindowType m_windowType = NET::Normal;
quint32 m_windowId = 0;
- QWindow *m_internalWindow = nullptr;
Qt::WindowFlags m_internalWindowFlags = Qt::WindowFlags();
+ bool m_isUnmapped = true;
+
+ Q_DISABLE_COPY(InternalClient)
};
}
diff --git a/internal_client.cpp b/internal_client.cpp
--- a/internal_client.cpp
+++ b/internal_client.cpp
@@ -3,6 +3,7 @@
This file is part of the KDE project.
Copyright (C) 2019 Martin Flöser
+Copyright (C) 2019 Vlad Zagorodniy
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -18,72 +19,50 @@
along with this program. If not, see .
*********************************************************************/
#include "internal_client.h"
+#include "deleted.h"
#include "workspace.h"
-#include
-#include
-
#include
+#include
Q_DECLARE_METATYPE(NET::WindowType)
static const QByteArray s_skipClosePropertyName = QByteArrayLiteral("KWIN_SKIP_CLOSE_ANIMATION");
namespace KWin
{
-InternalClient::InternalClient(KWayland::Server::ShellSurfaceInterface *surface)
- : ShellClient(surface)
+InternalClient::InternalClient(QWindow *window)
+ : m_internalWindow(window)
+ , m_windowId(window->winId())
+ , m_internalWindowFlags(window->flags())
{
- findInternalWindow();
+ connect(m_internalWindow, &QWindow::xChanged, this, &InternalClient::updateInternalWindowGeometry);
+ connect(m_internalWindow, &QWindow::yChanged, this, &InternalClient::updateInternalWindowGeometry);
+ connect(m_internalWindow, &QWindow::widthChanged, this, &InternalClient::updateInternalWindowGeometry);
+ connect(m_internalWindow, &QWindow::heightChanged, this, &InternalClient::updateInternalWindowGeometry);
+ connect(m_internalWindow, &QWindow::opacityChanged, this, &InternalClient::setOpacity);
+ connect(m_internalWindow, &QWindow::destroyed, this, &InternalClient::destroyClient);
+
+ const QVariant windowType = m_internalWindow->property("kwin_windowType");
+ if (!windowType.isNull()) {
+ m_windowType = windowType.value();
+ }
+
+ setOnAllDesktops(true);
+ setOpacity(m_internalWindow->opacity());
+ setSkipCloseAnimation(m_internalWindow->property(s_skipClosePropertyName).toBool());
+
updateInternalWindowGeometry();
updateDecoration(true);
-}
-InternalClient::InternalClient(KWayland::Server::XdgShellSurfaceInterface *surface)
- : ShellClient(surface)
-{
-}
+ setupCompositing();
-InternalClient::InternalClient(KWayland::Server::XdgShellPopupInterface *surface)
- : ShellClient(surface)
-{
+ m_internalWindow->installEventFilter(this);
}
-InternalClient::~InternalClient() = default;
-
-void InternalClient::findInternalWindow()
+InternalClient::~InternalClient()
{
- const QWindowList windows = kwinApp()->topLevelWindows();
- for (QWindow *w: windows) {
- auto s = KWayland::Client::Surface::fromWindow(w);
- if (!s) {
- continue;
- }
- if (s->id() != surface()->id()) {
- continue;
- }
- m_internalWindow = w;
- m_windowId = m_internalWindow->winId();
- m_internalWindowFlags = m_internalWindow->flags();
- connect(m_internalWindow, &QWindow::xChanged, this, &InternalClient::updateInternalWindowGeometry);
- connect(m_internalWindow, &QWindow::yChanged, this, &InternalClient::updateInternalWindowGeometry);
- connect(m_internalWindow, &QWindow::destroyed, this, [this] { m_internalWindow = nullptr; });
- connect(m_internalWindow, &QWindow::opacityChanged, this, &InternalClient::setOpacity);
-
- const QVariant windowType = m_internalWindow->property("kwin_windowType");
- if (!windowType.isNull()) {
- m_windowType = windowType.value();
- }
- setOpacity(m_internalWindow->opacity());
-
- // skip close animation support
- setSkipCloseAnimation(m_internalWindow->property(s_skipClosePropertyName).toBool());
- m_internalWindow->installEventFilter(this);
- return;
- }
-
- qCWarning(KWIN_CORE, "Couldn't find an internal window for surface with id %x", surface()->id());
}
bool InternalClient::eventFilter(QObject *watched, QEvent *event)
@@ -101,38 +80,106 @@
return false;
}
+void InternalClient::blockActivityUpdates(bool b)
+{
+ Q_UNUSED(b)
+
+ // Internal clients do not support activities.
+}
+
+QStringList InternalClient::activities() const
+{
+ return QStringList();
+}
+
+QPoint InternalClient::clientContentPos() const
+{
+ return -1 * clientPos();
+}
+
+QSize InternalClient::clientSize() const
+{
+ return m_clientSize;
+}
+
+QRect InternalClient::transparentRect() const
+{
+ return QRect();
+}
+
NET::WindowType InternalClient::windowType(bool direct, int supported_types) const
{
Q_UNUSED(direct)
Q_UNUSED(supported_types)
return m_windowType;
}
+void InternalClient::debug(QDebug &stream) const
+{
+ stream.nospace() << "\'InternalClient:" << m_internalWindow << "\'";
+}
+
+double InternalClient::opacity() const
+{
+ return m_opacity;
+}
+
+void InternalClient::setOpacity(double opacity)
+{
+ if (m_opacity == opacity) {
+ return;
+ }
+
+ const double oldOpacity = m_opacity;
+ m_opacity = opacity;
+
+ emit opacityChanged(this, oldOpacity);
+}
+
void InternalClient::killWindow()
{
- // we don't kill our internal windows
+ // We don't kill our internal windows.
}
bool InternalClient::isPopupWindow() const
{
- if (Toplevel::isPopupWindow()) {
+ if (AbstractClient::isPopupWindow()) {
return true;
}
return m_internalWindowFlags.testFlag(Qt::Popup);
}
void InternalClient::setInternalFramebufferObject(const QSharedPointer &fbo)
{
- if (fbo.isNull()) {
+ if (!fbo.isNull()) {
+ map(fbo);
+ } else {
unmap();
- return;
}
+}
- setClientSize(fbo->size() / surface()->scale());
- markAsMapped();
- doSetGeometry(QRect(geom.topLeft(), clientSize()));
- Toplevel::setInternalFramebufferObject(fbo);
- Toplevel::addDamage(QRegion(0, 0, width(), height()));
+void InternalClient::setInternalImageObject(const QImage &image)
+{
+ if (!image.isNull()) {
+ map(image);
+ } else {
+ unmap();
+ }
+}
+
+QString InternalClient::captionNormal() const
+{
+ return m_captionNormal;
+}
+
+QString InternalClient::captionSuffix() const
+{
+ return m_captionSuffix;
+}
+
+QByteArray InternalClient::windowRole() const
+{
+ return QByteArray();
}
void InternalClient::closeWindow()
@@ -147,6 +194,16 @@
return true;
}
+bool InternalClient::isFullScreenable() const
+{
+ return false;
+}
+
+bool InternalClient::isFullScreen() const
+{
+ return false;
+}
+
bool InternalClient::isMaximizable() const
{
return false;
@@ -187,11 +244,6 @@
return false;
}
-bool InternalClient::acceptsFocus() const
-{
- return false;
-}
-
bool InternalClient::isInternal() const
{
return true;
@@ -226,111 +278,345 @@
return m_windowId;
}
-void InternalClient::updateInternalWindowGeometry()
+MaximizeMode InternalClient::maximizeMode() const
+{
+ return MaximizeRestore;
+}
+
+QRect InternalClient::geometryRestore() const
{
+ return QRect();
+}
+
+bool InternalClient::isShown(bool shaded_is_shown) const
+{
+ Q_UNUSED(shaded_is_shown)
+
+ return !m_isUnmapped;
+}
+
+bool InternalClient::isHiddenInternal() const
+{
+ return m_isUnmapped;
+}
+
+void InternalClient::hideClient(bool hide)
+{
+ // FIXME
+}
+
+void InternalClient::resizeWithChecks(int w, int h, ForceGeometry_t force)
+{
+ Q_UNUSED(force)
if (!m_internalWindow) {
return;
}
- doSetGeometry(QRect(m_internalWindow->geometry().topLeft() - QPoint(borderLeft(), borderTop()),
- m_internalWindow->geometry().size() + QSize(borderLeft() + borderRight(), borderTop() + borderBottom())));
+ QRect area = workspace()->clientArea(WorkArea, this);
+ // don't allow growing larger than workarea
+ if (w > area.width()) {
+ w = area.width();
+ }
+ if (h > area.height()) {
+ h = area.height();
+ }
+ m_internalWindow->setGeometry(frameToContent(area));
}
-bool InternalClient::requestGeometry(const QRect &rect)
+void InternalClient::setGeometry(int x, int y, int w, int h, ForceGeometry_t force)
{
- if (!ShellClient::requestGeometry(rect)) {
- return false;
+ if (areGeometryUpdatesBlocked()) {
+ // when the GeometryUpdateBlocker exits the current geom is passed to setGeometry
+ // thus we need to set it here.
+ geom = QRect(x, y, w, h);
+ if (pendingGeometryUpdate() == PendingGeometryForced) {
+ // Maximum, nothing needed.
+ } else if (force == ForceGeometrySet) {
+ setPendingGeometryUpdate(PendingGeometryForced);
+ } else {
+ setPendingGeometryUpdate(PendingGeometryNormal);
+ }
+ return;
}
- if (m_internalWindow) {
- m_internalWindow->setGeometry(QRect(rect.topLeft() + QPoint(borderLeft(), borderTop()), rect.size() - QSize(borderLeft() + borderRight(), borderTop() + borderBottom())));
+
+ if (pendingGeometryUpdate() != PendingGeometryNone) {
+ // Reset geometry to the one before blocking, so that we can compare properly.
+ geom = geometryBeforeUpdateBlocking();
}
- return true;
+
+ const QRect windowRect = frameToContent(geom);
+
+ if (windowRect.size() == m_clientSize) {
+ doSetGeometry(geom);
+ } else {
+ requestGeometry(geom);
+ }
+}
+
+void InternalClient::setGeometryRestore(const QRect &geo)
+{
+ Q_UNUSED(geo)
+
+ // Internal clients are not maximizable.
+}
+
+bool InternalClient::supportsWindowRules() const
+{
+ return false;
+}
+
+AbstractClient *InternalClient::findModal(bool allow_itself)
+{
+ Q_UNUSED(allow_itself)
+ return nullptr;
+}
+
+void InternalClient::setOnAllActivities(bool set)
+{
+ Q_UNUSED(set)
+
+ // Internal clients do not support activities.
+}
+
+void InternalClient::takeFocus()
+{
+ // FIXME
+}
+
+bool InternalClient::userCanSetFullScreen() const
+{
+ // FIXME
+ return false;
+}
+
+void InternalClient::setFullScreen(bool set, bool user)
+{
+ // FIXME
+}
+
+void InternalClient::setNoBorder(bool set)
+{
+ // FIXME
+}
+
+void InternalClient::updateDecoration(bool check_workspace_pos, bool force)
+{
+ // FIXME
+}
+
+void InternalClient::updateColorScheme()
+{
+ // FIXME
+}
+
+void InternalClient::showOnScreenEdge()
+{
+ // FIXME
+}
+
+QWindow *InternalClient::internalWindow() const
+{
+ return m_internalWindow;
+}
+
+bool InternalClient::acceptsFocus() const
+{
+ return false;
+}
+
+bool InternalClient::belongsToSameApplication(const AbstractClient *other, SameApplicationChecks checks) const
+{
+ Q_UNUSED(checks)
+
+ return qobject_cast(other) != nullptr;
+}
+
+void InternalClient::doMove(int x, int y)
+{
+ Q_UNUSED(x)
+ Q_UNUSED(y)
+
+ syncGeometryToInternalWindow();
+}
+
+void InternalClient::changeMaximize(bool horizontal, bool vertical, bool adjust)
+{
+ Q_UNUSED(horizontal)
+ Q_UNUSED(vertical)
+ Q_UNUSED(adjust)
+
+ // Internal clients are not maximizable.
+}
+
+void InternalClient::doResizeSync()
+{
+ requestGeometry(moveResizeGeometry());
}
void InternalClient::doSetGeometry(const QRect &rect)
{
if (geom == rect && pendingGeometryUpdate() == PendingGeometryNone) {
return;
}
- if (!isUnmapped()) {
+
+ if (m_isUnmapped) {
addWorkspaceRepaint(visibleRect());
}
+
geom = rect;
- if (isUnmapped() && geometryRestore().isEmpty() && !geom.isEmpty()) {
+ if (m_isUnmapped && geometryRestore().isEmpty() && !geom.isEmpty()) {
// use first valid geometry as restore geometry
setGeometryRestore(geom);
}
- if (!isUnmapped()) {
+ if (!m_isUnmapped) {
addWorkspaceRepaint(visibleRect());
}
+
syncGeometryToInternalWindow();
+
if (hasStrut()) {
workspace()->updateClientArea();
}
- const auto old = geometryBeforeUpdateBlocking();
+
+ const QRect old = geometryBeforeUpdateBlocking();
updateGeometryBeforeUpdateBlocking();
emit geometryShapeChanged(this, old);
if (isResize()) {
performMoveResize();
}
}
-void InternalClient::doMove(int x, int y)
+void InternalClient::requestGeometry(const QRect &rect)
{
- Q_UNUSED(x)
- Q_UNUSED(y)
- syncGeometryToInternalWindow();
+ if (m_internalWindow) {
+ m_internalWindow->setGeometry(frameToContent(rect));
+ }
}
-void InternalClient::syncGeometryToInternalWindow()
+void InternalClient::updateCaption()
{
- if (!m_internalWindow) {
- return;
+ // FIXME
+}
+
+void InternalClient::destroyClient()
+{
+ if (isMoveResize()) {
+ leaveMoveResize();
+ }
+
+ Deleted *deleted = nullptr;
+ if (workspace()) {
+ deleted = Deleted::create(this);
}
- const QRect windowRect = QRect(geom.topLeft() + QPoint(borderLeft(), borderTop()),
- geom.size() - QSize(borderLeft() + borderRight(), borderTop() + borderBottom()));
- if (m_internalWindow->geometry() != windowRect) {
- // delay to end of cycle to prevent freeze, see BUG 384441
- QTimer::singleShot(0, m_internalWindow, std::bind(static_cast(&QWindow::setGeometry), m_internalWindow, windowRect));
+
+ emit windowClosed(this, deleted);
+
+ destroyDecoration();
+
+ workspace()->removeInternalClient(this);
+
+ if (deleted) {
+ deleted->unrefWindow();
}
+
+ m_internalWindow = nullptr;
+
+ delete this;
}
-void InternalClient::resizeWithChecks(int w, int h, ForceGeometry_t force)
+QRect InternalClient::contentToFrame(const QRect &rect) const
{
- Q_UNUSED(force)
- if (!m_internalWindow) {
+ return rect + frameMargins();
+}
+
+QRect InternalClient::frameToContent(const QRect &rect) const
+{
+ return rect - frameMargins();
+}
+
+void InternalClient::markAsMapped()
+{
+ if (!m_isUnmapped) {
return;
}
- QRect area = workspace()->clientArea(WorkArea, this);
- // don't allow growing larger than workarea
- if (w > area.width()) {
- w = area.width();
- }
- if (h > area.height()) {
- h = area.height();
+
+ if (!ready_for_painting) {
+ setReadyForPainting();
+ } else {
+ addRepaintFull();
+ emit windowShown(this);
}
- m_internalWindow->setGeometry(QRect(pos() + QPoint(borderLeft(), borderTop()), QSize(w, h) - QSize(borderLeft() + borderRight(), borderTop() + borderBottom())));
+
+ m_isUnmapped = false;
+
+ // TODO: See if there's better place when this method should be invoked.
+ workspace()->addInternalClient(this);
}
-void InternalClient::doResizeSync()
+void InternalClient::map(QSharedPointer fbo)
{
- if (!m_internalWindow) {
- return;
+ // TODO: Retrieve buffer device pixel ratio.
+
+ m_clientSize = fbo->size();
+
+ markAsMapped();
+
+ doSetGeometry(QRect(geom.topLeft(), m_clientSize));
+
+ Toplevel::setInternalFramebufferObject(fbo);
+ Toplevel::addDamage(QRegion(0, 0, width(), height()));
+}
+
+void InternalClient::map(const QImage &image)
+{
+ const qreal devicePixelRatio = image.devicePixelRatio();
+
+ m_clientSize = image.size() / devicePixelRatio;
+
+ markAsMapped();
+
+ doSetGeometry(QRect(geom.topLeft(), m_clientSize));
+
+ Toplevel::setInternalImageObject(image);
+ Toplevel::addDamage(QRegion(0, 0, width(), height()));
+}
+
+void InternalClient::unmap()
+{
+ m_isUnmapped = true;
+
+ if (isMoveResize()) {
+ leaveMoveResize();
+ }
+
+ if (workspace()) {
+ addWorkspaceRepaint(visibleRect());
+ workspace()->clientHidden(this);
}
- const auto rect = moveResizeGeometry();
- m_internalWindow->setGeometry(QRect(rect.topLeft() + QPoint(borderLeft(), borderTop()), rect.size() - QSize(borderLeft() + borderRight(), borderTop() + borderBottom())));
+
+ emit windowHidden(this);
}
-QWindow *InternalClient::internalWindow() const
+void InternalClient::updateInternalWindowGeometry()
{
- return m_internalWindow;
+ if (m_internalWindow) {
+ doSetGeometry(contentToFrame(m_internalWindow->geometry()));
+ }
}
-bool InternalClient::supportsWindowRules() const
+void InternalClient::syncGeometryToInternalWindow()
{
- return false;
+ if (!m_internalWindow) {
+ return;
+ }
+
+ if (contentToFrame(m_internalWindow->geometry()) == geometry()) {
+ return;
+ }
+
+ QTimer::singleShot(0, this, [this] { requestGeometry(geometry()); });
}
}
diff --git a/layers.cpp b/layers.cpp
--- a/layers.cpp
+++ b/layers.cpp
@@ -95,6 +95,7 @@
#include "screenedge.h"
#include "shell_client.h"
#include "wayland_server.h"
+#include "internal_client.h"
#include
@@ -764,14 +765,14 @@
}
}
}
- if (waylandServer()) {
- const auto clients = waylandServer()->internalClients();
- for (auto c: clients) {
- if (c->isShown(false)) {
- x_stacking << c;
- }
+
+ const InternalClientList clients = workspace()->internalClients();
+ for (InternalClient *client : clients) {
+ if (client->isShown(false)) {
+ x_stacking.append(client);
}
}
+
m_xStackingDirty = false;
}
diff --git a/platformsupport/scenes/opengl/abstract_egl_backend.h b/platformsupport/scenes/opengl/abstract_egl_backend.h
--- a/platformsupport/scenes/opengl/abstract_egl_backend.h
+++ b/platformsupport/scenes/opengl/abstract_egl_backend.h
@@ -110,8 +110,10 @@
private:
bool loadShmTexture(const QPointer &buffer);
bool loadEglTexture(const QPointer &buffer);
+ bool loadInternalImageObject(WindowPixmap *pixmap);
EGLImageKHR attach(const QPointer &buffer);
bool updateFromFBO(const QSharedPointer &fbo);
+ bool updateFromInternalImageObject(WindowPixmap *pixmap);
SceneOpenGLTexture *q;
AbstractEglBackend *m_backend;
EGLImageKHR m_image;
diff --git a/platformsupport/scenes/opengl/abstract_egl_backend.cpp b/platformsupport/scenes/opengl/abstract_egl_backend.cpp
--- a/platformsupport/scenes/opengl/abstract_egl_backend.cpp
+++ b/platformsupport/scenes/opengl/abstract_egl_backend.cpp
@@ -341,11 +341,16 @@
bool AbstractEglTexture::loadTexture(WindowPixmap *pixmap)
{
+ // FIXME: Refactor this method, it's a huge mess.
+
const auto &buffer = pixmap->buffer();
if (buffer.isNull()) {
if (updateFromFBO(pixmap->fbo())) {
return true;
}
+ if (loadInternalImageObject(pixmap)) {
+ return true;
+ }
return false;
}
// try Wayland loading
@@ -361,13 +366,14 @@
void AbstractEglTexture::updateTexture(WindowPixmap *pixmap)
{
+ // FIXME: Refactor this method, it's a huge mess.
+
const auto &buffer = pixmap->buffer();
if (buffer.isNull()) {
- const auto &fbo = pixmap->fbo();
- if (!fbo.isNull()) {
- if (m_texture != fbo->texture()) {
- updateFromFBO(fbo);
- }
+ if (updateFromFBO(pixmap->fbo())) {
+ return;
+ }
+ if (updateFromInternalImageObject(pixmap)) {
return;
}
return;
@@ -504,6 +510,58 @@
return true;
}
+bool AbstractEglTexture::loadInternalImageObject(WindowPixmap *pixmap)
+{
+ // FIXME: Lame! Lame! Lame! Lame! Lame! Lame!
+
+ const QImage image = pixmap->internalImage();
+ if (image.isNull()) {
+ return false;
+ }
+
+ glGenTextures(1, &m_texture);
+ q->setFilter(GL_LINEAR);
+ q->setWrapMode(GL_CLAMP_TO_EDGE);
+ q->setYInverted(true);
+ q->bind();
+
+ const QSize &size = image.size();
+ // TODO: this should be shared with GLTexture(const QImage&, GLenum)
+ GLenum format = 0;
+ switch (image.format()) {
+ case QImage::Format_ARGB32:
+ case QImage::Format_ARGB32_Premultiplied:
+ format = GL_RGBA8;
+ break;
+ case QImage::Format_RGB32:
+ format = GL_RGB8;
+ break;
+ default:
+ return false;
+ }
+ if (GLPlatform::instance()->isGLES()) {
+ if (s_supportsARGB32 && format == GL_RGBA8) {
+ const QImage im = image.convertToFormat(QImage::Format_ARGB32_Premultiplied);
+ glTexImage2D(m_target, 0, GL_BGRA_EXT, im.width(), im.height(),
+ 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, im.bits());
+ } else {
+ const QImage im = image.convertToFormat(QImage::Format_RGBA8888_Premultiplied);
+ glTexImage2D(m_target, 0, GL_RGBA, im.width(), im.height(),
+ 0, GL_RGBA, GL_UNSIGNED_BYTE, im.bits());
+ }
+ } else {
+ glTexImage2D(m_target, 0, format, size.width(), size.height(), 0,
+ GL_BGRA, GL_UNSIGNED_BYTE, image.bits());
+ }
+
+ q->unbind();
+
+ m_size = size;
+ updateMatrix();
+
+ return true;
+}
+
EGLImageKHR AbstractEglTexture::attach(const QPointer< KWayland::Server::BufferInterface > &buffer)
{
EGLint format, yInverted;
@@ -546,5 +604,55 @@
return true;
}
+bool AbstractEglTexture::updateFromInternalImageObject(WindowPixmap *pixmap)
+{
+ // FIXME: Lame! Lame! Lame! Lame! Lame! Lame!
+
+ const QImage image = pixmap->internalImage();
+ if (image.isNull()) {
+ return false;
+ }
+
+ if (m_size != image.size()) {
+ glDeleteTextures(1, &m_texture);
+ return loadInternalImageObject(pixmap);
+ }
+
+ const QRegion damage = pixmap->toplevel()->damage();
+ const qreal scale = image.devicePixelRatio();
+
+ q->bind();
+
+ // TODO: this should be shared with GLTexture::update
+ if (GLPlatform::instance()->isGLES()) {
+ if (s_supportsARGB32 && (image.format() == QImage::Format_ARGB32 || image.format() == QImage::Format_ARGB32_Premultiplied)) {
+ const QImage im = image.convertToFormat(QImage::Format_ARGB32_Premultiplied);
+ for (const QRect &rect : damage) {
+ auto scaledRect = QRect(rect.x() * scale, rect.y() * scale, rect.width() * scale, rect.height() * scale);
+ glTexSubImage2D(m_target, 0, scaledRect.x(), scaledRect.y(), scaledRect.width(), scaledRect.height(),
+ GL_BGRA_EXT, GL_UNSIGNED_BYTE, im.copy(scaledRect).bits());
+ }
+ } else {
+ const QImage im = image.convertToFormat(QImage::Format_RGBA8888_Premultiplied);
+ for (const QRect &rect : damage) {
+ auto scaledRect = QRect(rect.x() * scale, rect.y() * scale, rect.width() * scale, rect.height() * scale);
+ glTexSubImage2D(m_target, 0, scaledRect.x(), scaledRect.y(), scaledRect.width(), scaledRect.height(),
+ GL_RGBA, GL_UNSIGNED_BYTE, im.copy(scaledRect).bits());
+ }
+ }
+ } else {
+ const QImage im = image.convertToFormat(QImage::Format_ARGB32_Premultiplied);
+ for (const QRect &rect : damage) {
+ auto scaledRect = QRect(rect.x() * scale, rect.y() * scale, rect.width() * scale, rect.height() * scale);
+ glTexSubImage2D(m_target, 0, scaledRect.x(), scaledRect.y(), scaledRect.width(), scaledRect.height(),
+ GL_BGRA, GL_UNSIGNED_BYTE, im.copy(scaledRect).bits());
+ }
+ }
+
+ q->unbind();
+
+ return true;
+}
+
}
diff --git a/plugins/qpa/CMakeLists.txt b/plugins/qpa/CMakeLists.txt
--- a/plugins/qpa/CMakeLists.txt
+++ b/plugins/qpa/CMakeLists.txt
@@ -7,7 +7,6 @@
eglhelpers.cpp
integration.cpp
main.cpp
- nativeinterface.cpp
offscreensurface.cpp
platformcursor.cpp
screen.cpp
@@ -29,7 +28,6 @@
target_link_libraries(KWinQpaPlugin
kwin
- KF5::WaylandClient
${QT5PLATFORMSUPPORT_LIBS}
Fontconfig::Fontconfig
${FREETYPE_LIBRARIES}
diff --git a/plugins/qpa/backingstore.h b/plugins/qpa/backingstore.h
--- a/plugins/qpa/backingstore.h
+++ b/plugins/qpa/backingstore.h
@@ -3,6 +3,7 @@
This file is part of the KDE project.
Copyright (C) 2015 Martin Gräßlin
+Copyright (C) 2019 Vlad Zagorodniy
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -22,37 +23,23 @@
#include
-namespace KWayland
-{
-namespace Client
-{
-class Buffer;
-class ShmPool;
-}
-}
-
namespace KWin
{
namespace QPA
{
class BackingStore : public QPlatformBackingStore
{
public:
- explicit BackingStore(QWindow *w, KWayland::Client::ShmPool *shm);
+ explicit BackingStore(QWindow *window);
~BackingStore() override;
QPaintDevice *paintDevice() override;
void flush(QWindow *window, const QRegion ®ion, const QPoint &offset) override;
void resize(const QSize &size, const QRegion &staticContents) override;
- void beginPaint(const QRegion &) override;
private:
- int scale() const;
- KWayland::Client::ShmPool *m_shm;
- QWeakPointer m_buffer;
QImage m_backBuffer;
- QSize m_size;
};
}
diff --git a/plugins/qpa/backingstore.cpp b/plugins/qpa/backingstore.cpp
--- a/plugins/qpa/backingstore.cpp
+++ b/plugins/qpa/backingstore.cpp
@@ -3,6 +3,7 @@
This file is part of the KDE project.
Copyright (C) 2015 Martin Gräßlin
+Copyright (C) 2019 Vlad Zagorodniy
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -17,39 +18,21 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*********************************************************************/
-#include "window.h"
#include "backingstore.h"
-#include "../../wayland_server.h"
+#include "window.h"
-#include
-#include
-#include
-#include
+#include "internal_client.h"
+
+#include
namespace KWin
{
namespace QPA
{
-BackingStore::BackingStore(QWindow *w, KWayland::Client::ShmPool *shm)
- : QPlatformBackingStore(w)
- , m_shm(shm)
- , m_backBuffer(QSize(), QImage::Format_ARGB32_Premultiplied)
+BackingStore::BackingStore(QWindow *window)
+ : QPlatformBackingStore(window)
{
- QObject::connect(m_shm, &KWayland::Client::ShmPool::poolResized,
- [this] {
- if (!m_buffer) {
- return;
- }
- auto b = m_buffer.toStrongRef();
- if (!b->isUsed()){
- return;
- }
- const QSize size = m_backBuffer.size();
- m_backBuffer = QImage(b->address(), size.width(), size.height(), QImage::Format_ARGB32_Premultiplied);
- m_backBuffer.setDevicePixelRatio(scale());
- }
- );
}
BackingStore::~BackingStore() = default;
@@ -62,66 +45,30 @@
void BackingStore::resize(const QSize &size, const QRegion &staticContents)
{
Q_UNUSED(staticContents)
- m_size = size * scale();
- if (!m_buffer) {
+
+ if (m_backBuffer.size() == size) {
return;
}
- m_buffer.toStrongRef()->setUsed(false);
- m_buffer.clear();
+
+ const QPlatformWindow *platformWindow = static_cast(window()->handle());
+ const qreal devicePixelRatio = platformWindow->devicePixelRatio();
+
+ m_backBuffer = QImage(size * devicePixelRatio, QImage::Format_ARGB32_Premultiplied);
+ m_backBuffer.setDevicePixelRatio(devicePixelRatio);
}
void BackingStore::flush(QWindow *window, const QRegion ®ion, const QPoint &offset)
{
Q_UNUSED(region)
Q_UNUSED(offset)
- auto w = static_cast(window->handle());
- auto s = w->surface();
- if (!s) {
+ Window *platformWindow = static_cast(window->handle());
+ InternalClient *client = platformWindow->client();
+ if (!client) {
return;
}
- s->attachBuffer(m_buffer);
- // TODO: proper damage region
- s->damage(QRect(QPoint(0, 0), m_backBuffer.size() / scale()));
- s->commit(KWayland::Client::Surface::CommitFlag::None);
- waylandServer()->internalClientConection()->flush();
- waylandServer()->dispatch();
-}
-void BackingStore::beginPaint(const QRegion&)
-{
- if (m_buffer) {
- auto b = m_buffer.toStrongRef();
- if (b->isReleased()) {
- // we can re-use this buffer
- b->setReleased(false);
- return;
- } else {
- // buffer is still in use, get a new one
- b->setUsed(false);
- }
- }
- auto oldBuffer = m_buffer.toStrongRef();
- m_buffer.clear();
- m_buffer = m_shm->getBuffer(m_size, m_size.width() * 4);
- if (!m_buffer) {
- m_backBuffer = QImage();
- return;
- }
- auto b = m_buffer.toStrongRef();
- b->setUsed(true);
- m_backBuffer = QImage(b->address(), m_size.width(), m_size.height(), QImage::Format_ARGB32_Premultiplied);
- m_backBuffer.setDevicePixelRatio(scale());
- if (oldBuffer) {
- b->copy(oldBuffer->address());
- } else {
- m_backBuffer.fill(Qt::transparent);
- }
-}
-
-int BackingStore::scale() const
-{
- return static_cast(window()->handle())->scale();
+ client->setInternalImageObject(m_backBuffer);
}
}
diff --git a/plugins/qpa/integration.h b/plugins/qpa/integration.h
--- a/plugins/qpa/integration.h
+++ b/plugins/qpa/integration.h
@@ -27,15 +27,6 @@
#include
#include
-namespace KWayland
-{
-namespace Client
-{
-class Compositor;
-class Shell;
-}
-}
-
namespace KWin
{
namespace QPA
@@ -58,24 +49,16 @@
QPlatformFontDatabase *fontDatabase() const override;
QStringList themeNames() const override;
QPlatformTheme *createPlatformTheme(const QString &name) const override;
- QPlatformNativeInterface *nativeInterface() const override;
QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const override;
-
- void initialize() override;
QPlatformInputContext *inputContext() const override;
- KWayland::Client::Compositor *compositor() const;
- EGLDisplay eglDisplay() const;
+ void initialize() override;
private:
void initScreens();
- KWayland::Client::Shell *shell() const;
QPlatformFontDatabase *m_fontDb;
QPlatformNativeInterface *m_nativeInterface;
- KWayland::Client::Compositor *m_compositor = nullptr;
- KWayland::Client::Shell *m_shell = nullptr;
- EGLDisplay m_eglDisplay = EGL_NO_DISPLAY;
Screen *m_dummyScreen = nullptr;
QScopedPointer m_inputContext;
QVector m_screens;
diff --git a/plugins/qpa/integration.cpp b/plugins/qpa/integration.cpp
--- a/plugins/qpa/integration.cpp
+++ b/plugins/qpa/integration.cpp
@@ -19,23 +19,14 @@
*********************************************************************/
#include "integration.h"
#include "backingstore.h"
-#include "nativeinterface.h"
#include "offscreensurface.h"
#include "screen.h"
#include "sharingplatformcontext.h"
#include "window.h"
#include "../../main.h"
#include "../../platform.h"
#include "../../screens.h"
#include "../../virtualkeyboard.h"
-#include "../../wayland_server.h"
-
-#include
-#include
-#include
-#include
-#include
-#include
#include
#include
@@ -59,7 +50,6 @@
: QObject()
, QPlatformIntegration()
, m_fontDb(new QGenericUnixFontDatabase())
- , m_nativeInterface(new NativeInterface(this))
, m_inputContext()
{
}
@@ -139,25 +129,12 @@
QPlatformBackingStore *Integration::createPlatformBackingStore(QWindow *window) const
{
- auto registry = waylandServer()->internalClientRegistry();
- const auto shm = registry->interface(KWayland::Client::Registry::Interface::Shm);
- if (shm.name == 0u) {
- return nullptr;
- }
- return new BackingStore(window, registry->createShmPool(shm.name, shm.version, window));
+ return new BackingStore(window);
}
QPlatformWindow *Integration::createPlatformWindow(QWindow *window) const
{
- auto c = compositor();
- auto s = shell();
- if (!s || !c) {
- return new QPlatformWindow(window);
- } else {
- // don't set window as parent, cause infinite recursion in PlasmaQuick::Dialog
- auto surface = c->createSurface(c);
- return new Window(window, surface, s->createSurface(surface, surface), this);
- }
+ return new Window(window);
}
QPlatformOffscreenSurface *Integration::createPlatformOffscreenSurface(QOffscreenSurface *surface) const
@@ -183,11 +160,6 @@
return QStringList({QLatin1String(QGenericUnixTheme::name)});
}
-QPlatformNativeInterface *Integration::nativeInterface() const
-{
- return m_nativeInterface;
-}
-
QPlatformOpenGLContext *Integration::createPlatformOpenGLContext(QOpenGLContext *context) const
{
if (kwinApp()->platform()->supportsQpaContext()) {
@@ -235,37 +207,6 @@
m_screens = newScreens;
}
-KWayland::Client::Compositor *Integration::compositor() const
-{
- if (!m_compositor) {
- using namespace KWayland::Client;
- auto registry = waylandServer()->internalClientRegistry();
- const auto c = registry->interface(Registry::Interface::Compositor);
- if (c.name != 0u) {
- const_cast(this)->m_compositor = registry->createCompositor(c.name, c.version, registry);
- }
- }
- return m_compositor;
-}
-
-KWayland::Client::Shell *Integration::shell() const
-{
- if (!m_shell) {
- using namespace KWayland::Client;
- auto registry = waylandServer()->internalClientRegistry();
- const auto s = registry->interface(Registry::Interface::Shell);
- if (s.name != 0u) {
- const_cast(this)->m_shell = registry->createShell(s.name, s.version, registry);
- }
- }
- return m_shell;
-}
-
-EGLDisplay Integration::eglDisplay() const
-{
- return m_eglDisplay;
-}
-
QPlatformInputContext *Integration::inputContext() const
{
return m_inputContext.data();
diff --git a/plugins/qpa/nativeinterface.h b/plugins/qpa/nativeinterface.h
deleted file mode 100644
--- a/plugins/qpa/nativeinterface.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/********************************************************************
- KWin - the KDE window manager
- This file is part of the KDE project.
-
-Copyright (C) 2015 Martin Gräßlin
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see .
-*********************************************************************/
-#ifndef KWIN_QPA_NATIVEINTERFACE_H
-#define KWIN_QPA_NATIVEINTERFACE_H
-
-#include
-
-namespace KWin
-{
-namespace QPA
-{
-
-class Integration;
-
-class NativeInterface : public QPlatformNativeInterface
-{
-public:
- explicit NativeInterface(Integration *integration);
- void *nativeResourceForIntegration(const QByteArray &resource) override;
- void *nativeResourceForWindow(const QByteArray &resourceString, QWindow *window) override;
- QFunctionPointer platformFunction(const QByteArray &function) const override;
-
-private:
- Integration *m_integration;
-};
-
-}
-}
-
-#endif
diff --git a/plugins/qpa/nativeinterface.cpp b/plugins/qpa/nativeinterface.cpp
deleted file mode 100644
--- a/plugins/qpa/nativeinterface.cpp
+++ /dev/null
@@ -1,106 +0,0 @@
-/********************************************************************
- KWin - the KDE window manager
- This file is part of the KDE project.
-
-Copyright (C) 2015 Martin Gräßlin
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see .
-*********************************************************************/
-#include "nativeinterface.h"
-#include "integration.h"
-#include "window.h"
-#include "../../wayland_server.h"
-
-#include
-#include
-#include
-
-#include
-
-namespace KWin
-{
-namespace QPA
-{
-
-static const QByteArray s_displayKey = QByteArrayLiteral("display");
-static const QByteArray s_wlDisplayKey = QByteArrayLiteral("wl_display");
-static const QByteArray s_compositorKey = QByteArrayLiteral("compositor");
-static const QByteArray s_surfaceKey = QByteArrayLiteral("surface");
-
-NativeInterface::NativeInterface(Integration *integration)
- : QPlatformNativeInterface()
- , m_integration(integration)
-{
-}
-
-void *NativeInterface::nativeResourceForIntegration(const QByteArray &resource)
-{
- const QByteArray r = resource.toLower();
- if (r == s_displayKey || r == s_wlDisplayKey) {
- if (!waylandServer() || !waylandServer()->internalClientConection()) {
- return nullptr;
- }
- return waylandServer()->internalClientConection()->display();
- }
- if (r == s_compositorKey) {
- return static_cast(*m_integration->compositor());
- }
- return nullptr;
-}
-
-void *NativeInterface::nativeResourceForWindow(const QByteArray &resource, QWindow *window)
-{
- const QByteArray r = resource.toLower();
- if (r == s_displayKey || r == s_wlDisplayKey) {
- if (!waylandServer() || !waylandServer()->internalClientConection()) {
- return nullptr;
- }
- return waylandServer()->internalClientConection()->display();
- }
- if (r == s_compositorKey) {
- return static_cast(*m_integration->compositor());
- }
- if (r == s_surfaceKey && window) {
- if (auto handle = window->handle()) {
- if (auto surface = static_cast(handle)->surface()) {
- return static_cast(*surface);
- }
- }
- }
- return nullptr;
-}
-
-static void roundtrip()
-{
- if (!waylandServer()) {
- return;
- }
- auto c = waylandServer()->internalClientConection();
- if (!c) {
- return;
- }
- c->flush();
- waylandServer()->dispatch();
-}
-
-QFunctionPointer NativeInterface::platformFunction(const QByteArray &function) const
-{
- if (qstrcmp(function.toLower(), "roundtrip") == 0) {
- return &roundtrip;
- }
- return nullptr;
-}
-
-}
-}
diff --git a/plugins/qpa/sharingplatformcontext.cpp b/plugins/qpa/sharingplatformcontext.cpp
--- a/plugins/qpa/sharingplatformcontext.cpp
+++ b/plugins/qpa/sharingplatformcontext.cpp
@@ -20,8 +20,11 @@
#include "sharingplatformcontext.h"
#include "offscreensurface.h"
#include "window.h"
+
+#include "../../internal_client.h"
+#include "../../main.h"
#include "../../platform.h"
-#include "../../shell_client.h"
+
#include
#include
@@ -82,14 +85,13 @@
{
if (surface->surface()->surfaceClass() == QSurface::Window) {
Window *window = static_cast(surface);
- auto c = window->shellClient();
- if (!c) {
- qCDebug(KWIN_QPA) << "SwapBuffers called but there is no ShellClient";
+ InternalClient *client = window->client();
+ if (!client) {
return;
}
context()->makeCurrent(surface->surface());
glFlush();
- c->setInternalFramebufferObject(window->swapFBO());
+ client->setInternalFramebufferObject(window->swapFBO());
window->bindContentFBO();
}
}
diff --git a/plugins/qpa/window.h b/plugins/qpa/window.h
--- a/plugins/qpa/window.h
+++ b/plugins/qpa/window.h
@@ -3,6 +3,7 @@
This file is part of the KDE project.
Copyright (C) 2015 Martin Gräßlin
+Copyright (C) 2019 Vlad Zagorodniy
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -20,69 +21,44 @@
#ifndef KWIN_QPA_WINDOW_H
#define KWIN_QPA_WINDOW_H
-#include
-#include "fixqopengl.h"
-
-#include
#include
class QOpenGLFramebufferObject;
-
-namespace KWayland
-{
-namespace Client
-{
-class Surface;
-class ShellSurface;
-}
-}
-
namespace KWin
{
-class ShellClient;
+class InternalClient;
namespace QPA
{
-class Integration;
-
class Window : public QPlatformWindow
{
public:
- explicit Window(QWindow *window, KWayland::Client::Surface *surface, KWayland::Client::ShellSurface *shellSurface, const Integration *integration);
+ explicit Window(QWindow *window);
~Window() override;
void setVisible(bool visible) override;
void setGeometry(const QRect &rect) override;
WId winId() const override;
-
- KWayland::Client::Surface *surface() const {
- return m_surface;
- }
-
- int scale() const;
qreal devicePixelRatio() const override;
void bindContentFBO();
- const QSharedPointer &contentFBO() const {
- return m_contentFBO;
- }
+ const QSharedPointer &contentFBO() const;
QSharedPointer swapFBO();
- ShellClient *shellClient();
+
+ InternalClient *client() const;
private:
- void unmap();
void createFBO();
+ void map();
+ void unmap();
- KWayland::Client::Surface *m_surface;
- KWayland::Client::ShellSurface *m_shellSurface;
+ InternalClient *m_handle = nullptr;
QSharedPointer m_contentFBO;
- bool m_resized = false;
- ShellClient *m_shellClient = nullptr;
quint32 m_windowId;
- const Integration *m_integration;
+ bool m_resized = false;
int m_scale = 1;
};
diff --git a/plugins/qpa/window.cpp b/plugins/qpa/window.cpp
--- a/plugins/qpa/window.cpp
+++ b/plugins/qpa/window.cpp
@@ -3,6 +3,7 @@
This file is part of the KDE project.
Copyright (C) 2015 Martin Gräßlin
+Copyright (C) 2019 Vlad Zagorodniy
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -18,58 +19,41 @@
along with this program. If not, see .
*********************************************************************/
#include "window.h"
-#include "integration.h"
#include "screens.h"
-#include "../../shell_client.h"
-#include "../../wayland_server.h"
+
+#include "internal_client.h"
+
#include
#include
#include
-#include
-#include
-#include
-#include
-
namespace KWin
{
namespace QPA
{
static quint32 s_windowId = 0;
-Window::Window(QWindow *window, KWayland::Client::Surface *surface, KWayland::Client::ShellSurface *shellSurface, const Integration *integration)
+Window::Window(QWindow *window)
: QPlatformWindow(window)
- , m_surface(surface)
- , m_shellSurface(shellSurface)
, m_windowId(++s_windowId)
- , m_integration(integration)
, m_scale(screens()->maxScale())
{
- m_surface->setScale(m_scale);
-
- QObject::connect(m_surface, &QObject::destroyed, window, [this] { m_surface = nullptr;});
- QObject::connect(m_shellSurface, &QObject::destroyed, window, [this] { m_shellSurface = nullptr;});
- waylandServer()->internalClientConection()->flush();
}
Window::~Window()
{
unmap();
- delete m_shellSurface;
- delete m_surface;
-}
-
-WId Window::winId() const
-{
- return m_windowId;
}
void Window::setVisible(bool visible)
{
- if (!visible) {
+ if (visible) {
+ map();
+ } else {
unmap();
}
+
QPlatformWindow::setVisible(visible);
}
@@ -100,18 +84,14 @@
QWindowSystemInterface::handleGeometryChange(window(), geometry());
}
-void Window::unmap()
+WId Window::winId() const
{
- if (m_shellClient) {
- m_shellClient->setInternalFramebufferObject(QSharedPointer());
- }
- if (m_surface) {
- m_surface->attachBuffer(KWayland::Client::Buffer::Ptr());
- m_surface->commit(KWayland::Client::Surface::CommitFlag::None);
- }
- if (waylandServer()->internalClientConection()) {
- waylandServer()->internalClientConection()->flush();
- }
+ return m_windowId;
+}
+
+qreal Window::devicePixelRatio() const
+{
+ return m_scale;
}
void Window::bindContentFBO()
@@ -122,14 +102,23 @@
m_contentFBO->bind();
}
+const QSharedPointer &Window::contentFBO() const
+{
+ return m_contentFBO;
+}
+
QSharedPointer Window::swapFBO()
{
- auto fbo = m_contentFBO;
+ QSharedPointer fbo = m_contentFBO;
m_contentFBO.clear();
- m_surface->commit(KWayland::Client::Surface::CommitFlag::None);
return fbo;
}
+InternalClient *Window::client() const
+{
+ return m_handle;
+}
+
void Window::createFBO()
{
const QRect &r = geometry();
@@ -144,23 +133,25 @@
m_resized = false;
}
-ShellClient *Window::shellClient()
+void Window::map()
{
- if (!m_shellClient) {
- waylandServer()->dispatch();
- m_shellClient = waylandServer()->findClient(window());
+ if (m_handle) {
+ return;
}
- return m_shellClient;
-}
-int Window::scale() const
-{
- return m_scale;
+ m_handle = new InternalClient(window());
}
-qreal Window::devicePixelRatio() const
+void Window::unmap()
{
- return m_scale;
+ if (!m_handle) {
+ return;
+ }
+
+ m_handle->destroyClient();
+ m_handle = nullptr;
+
+ m_contentFBO = nullptr;
}
}
diff --git a/scene.h b/scene.h
--- a/scene.h
+++ b/scene.h
@@ -427,6 +427,7 @@
**/
QPointer buffer() const;
const QSharedPointer &fbo() const;
+ QImage internalImage() const;
/**
* @brief Whether this WindowPixmap is considered as discarded. This means the window has changed in a way that a new
* WindowPixmap should have been created already.
@@ -514,6 +515,7 @@
QRect m_contentsRect;
QPointer m_buffer;
QSharedPointer m_fbo;
+ QImage m_internalImage;
WindowPixmap *m_parent = nullptr;
QVector m_children;
QPointer m_subSurface;
@@ -620,6 +622,12 @@
return m_fbo;
}
+inline
+QImage WindowPixmap::internalImage() const
+{
+ return m_internalImage;
+}
+
template
inline
T* Scene::Window::windowPixmap()
diff --git a/scene.cpp b/scene.cpp
--- a/scene.cpp
+++ b/scene.cpp
@@ -1057,7 +1057,7 @@
bool WindowPixmap::isValid() const
{
- if (!m_buffer.isNull() || !m_fbo.isNull()) {
+ if (!m_buffer.isNull() || !m_fbo.isNull() || !m_internalImage.isNull()) {
return true;
}
return m_pixmap != XCB_PIXMAP_NONE;
@@ -1108,13 +1108,12 @@
m_buffer->unref();
m_buffer.clear();
}
- } else {
- // might be an internal window
- const auto &fbo = toplevel()->internalFramebufferObject();
- if (!fbo.isNull()) {
- m_fbo = fbo;
- }
}
+ } else if (toplevel()->internalFramebufferObject()) {
+ // Might be an internal window.
+ m_fbo = toplevel()->internalFramebufferObject();
+ } else if (!toplevel()->internalImageObject().isNull()) {
+ m_internalImage = toplevel()->internalImageObject();
} else {
if (m_buffer) {
QObject::disconnect(m_buffer.data(), &BufferInterface::aboutToBeDestroyed, m_buffer.data(), &BufferInterface::unref);
diff --git a/shell_client.h b/shell_client.h
--- a/shell_client.h
+++ b/shell_client.h
@@ -4,6 +4,7 @@
Copyright (C) 2015 Martin Gräßlin
Copyright (C) 2018 David Edmundson
+Copyright (C) 2019 Vlad Zagorodniy
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -125,7 +126,6 @@
bool isLockScreen() const override;
bool isInputMethod() const override;
- virtual QWindow *internalWindow() const;
void installPlasmaShellSurface(KWayland::Server::PlasmaShellSurfaceInterface *surface);
void installServerSideDecoration(KWayland::Server::ServerSideDecorationInterface *decoration);
@@ -181,11 +181,6 @@
void doMinimize() override;
void updateCaption() override;
- virtual bool requestGeometry(const QRect &rect);
- virtual void doSetGeometry(const QRect &rect);
- void unmap();
- void markAsMapped();
-
void setClientSize(const QSize &size) {
m_clientSize = size;
}
@@ -223,6 +218,10 @@
// called on surface commit and processes all m_pendingConfigureRequests up to m_lastAckedConfigureReqest
void updatePendingGeometry();
QPoint popupOffset(const QRect &anchorRect, const Qt::Edges anchorEdge, const Qt::Edges gravity, const QSize popupSize) const;
+ void requestGeometry(const QRect &rect);
+ void doSetGeometry(const QRect &rect);
+ void unmap();
+ void markAsMapped();
static void deleteClient(ShellClient *c);
QSize toWindowGeometry(const QSize &geometry) const;
@@ -268,7 +267,6 @@
bool m_fullScreen = false;
bool m_transient = false;
bool m_hidden = false;
- bool m_internal;
bool m_hasPopupGrab = false;
qreal m_opacity = 1.0;
diff --git a/shell_client.cpp b/shell_client.cpp
--- a/shell_client.cpp
+++ b/shell_client.cpp
@@ -4,6 +4,7 @@
Copyright (C) 2015 Martin Gräßlin
Copyright (C) 2018 David Edmundson
+Copyright (C) 2019 Vlad Zagorodniy
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -73,7 +74,6 @@
, m_shellSurface(surface)
, m_xdgShellSurface(nullptr)
, m_xdgShellPopup(nullptr)
- , m_internal(surface->client() == waylandServer()->internalConnection())
{
setSurface(surface->surface());
init();
@@ -85,7 +85,6 @@
, m_shellSurface(nullptr)
, m_xdgShellSurface(surface)
, m_xdgShellPopup(nullptr)
- , m_internal(surface->client() == waylandServer()->internalConnection())
{
setSurface(surface->surface());
m_requestGeometryBlockCounter++;
@@ -98,7 +97,6 @@
, m_shellSurface(nullptr)
, m_xdgShellSurface(nullptr)
, m_xdgShellPopup(surface)
- , m_internal(surface->client() == waylandServer()->internalConnection())
{
setSurface(surface->surface());
m_requestGeometryBlockCounter++;
@@ -224,9 +222,7 @@
} else {
ready_for_painting = false;
}
- if (!m_internal) {
- doSetGeometry(QRect(QPoint(0, 0), m_clientSize));
- }
+ doSetGeometry(QRect(QPoint(0, 0), m_clientSize));
if (waylandServer()->inputMethodConnection() == s->client()) {
m_windowType = NET::OnScreenDisplay;
}
@@ -333,7 +329,7 @@
}
// set initial desktop
- setDesktop(m_internal ? int(NET::OnAllDesktops) : VirtualDesktopManager::self()->current());
+ setDesktop(VirtualDesktopManager::self()->current());
// setup shadow integration
getShadow();
@@ -1116,9 +1112,7 @@
void ShellClient::createWindowId()
{
- if (!m_internal) {
- m_windowId = waylandServer()->createWindowId(surface());
- }
+ m_windowId = waylandServer()->createWindowId(surface());
}
pid_t ShellClient::pid() const
@@ -1136,11 +1130,11 @@
return surface()->client() == waylandServer()->inputMethodConnection();
}
-bool ShellClient::requestGeometry(const QRect &rect)
+void ShellClient::requestGeometry(const QRect &rect)
{
if (m_requestGeometryBlockCounter != 0) {
m_blockedRequestGeometry = rect;
- return false;
+ return;
}
QSize size;
@@ -1177,7 +1171,6 @@
}
m_blockedRequestGeometry = QRect();
- return true;
}
void ShellClient::updatePendingGeometry()
@@ -1249,12 +1242,7 @@
m_plasmaShellSurface = surface;
auto updatePosition = [this, surface] {
QRect rect = QRect(surface->position(), m_clientSize + QSize(borderLeft() + borderRight(), borderTop() + borderBottom()));
- // Shell surfaces of internal windows are sometimes desync to current value.
- // Make sure to not set window geometry of internal windows to invalid values (bug 386304).
- // This is a workaround.
- if (!m_internal || rect.isValid()) {
- doSetGeometry(rect);
- }
+ doSetGeometry(rect);
};
auto updateRole = [this, surface] {
NET::WindowType type = NET::Unknown;
@@ -1779,9 +1767,6 @@
bool ShellClient::shouldExposeToWindowManagement()
{
- if (m_internal) {
- return false;
- }
if (isLockScreen()) {
return false;
}
@@ -1952,11 +1937,6 @@
return false;
}
-QWindow *ShellClient::internalWindow() const
-{
- return nullptr;
-}
-
bool ShellClient::supportsWindowRules() const
{
if (m_plasmaShellSurface) {
diff --git a/tabbox/tabbox.cpp b/tabbox/tabbox.cpp
--- a/tabbox/tabbox.cpp
+++ b/tabbox/tabbox.cpp
@@ -355,7 +355,7 @@
if (window) {
windows << static_cast(window)->client()->effectWindow();
}
- if (auto t = Workspace::self()->findToplevel(controller)) {
+ if (Toplevel *t = workspace()->findInternal(controller)) {
windows << t->effectWindow();
}
static_cast(effects)->highlightWindows(windows);
diff --git a/toplevel.h b/toplevel.h
--- a/toplevel.h
+++ b/toplevel.h
@@ -440,9 +440,34 @@
KWayland::Server::SurfaceInterface *surface() const;
void setSurface(KWayland::Server::SurfaceInterface *surface);
+ /**
+ * TODO: Document this one.
+ *
+ * @todo Move this method to the InternalClient class.
+ **/
virtual void setInternalFramebufferObject(const QSharedPointer &fbo);
+
+ /**
+ * TODO: Document this one.
+ *
+ * @todo Move this method to the InternalClient class.
+ **/
const QSharedPointer &internalFramebufferObject() const;
+ /**
+ * TODO: Document this one.
+ *
+ * @todo Move this method to the InternalClient class.
+ **/
+ virtual void setInternalImageObject(const QImage &image);
+
+ /**
+ * TODO: Document this one.
+ *
+ * @todo Move this method to the InternalClient class.
+ **/
+ QImage internalImageObject() const;
+
/**
* @returns Transformation to map from global to window coordinates.
*
@@ -652,6 +677,7 @@
* An FBO object KWin internal windows might render to.
**/
QSharedPointer m_internalFBO;
+ QImage m_internalImage;
// when adding new data members, check also copyToDeleted()
qreal m_screenScale = 1.0;
};
@@ -918,6 +944,11 @@
return m_internalFBO;
}
+inline QImage Toplevel::internalImageObject() const
+{
+ return m_internalImage;
+}
+
inline QPoint Toplevel::clientContentPos() const
{
return QPoint(0, 0);
diff --git a/toplevel.cpp b/toplevel.cpp
--- a/toplevel.cpp
+++ b/toplevel.cpp
@@ -780,6 +780,13 @@
setDepth(32);
}
+void Toplevel::setInternalImageObject(const QImage &image)
+{
+ discardWindowPixmap();
+ m_internalImage = image;
+ setDepth(32);
+}
+
QMatrix4x4 Toplevel::inputTransformation() const
{
QMatrix4x4 m;
diff --git a/utils.h b/utils.h
--- a/utils.h
+++ b/utils.h
@@ -63,12 +63,14 @@
class Deleted;
class Group;
class Options;
+class InternalClient;
typedef QList< Toplevel* > ToplevelList;
typedef QList< Client* > ClientList;
typedef QList< const Client* > ConstClientList;
typedef QList< Unmanaged* > UnmanagedList;
typedef QList< Deleted* > DeletedList;
+typedef QList< InternalClient* > InternalClientList;
typedef QList< Group* > GroupList;
diff --git a/wayland_server.h b/wayland_server.h
--- a/wayland_server.h
+++ b/wayland_server.h
@@ -126,14 +126,10 @@
QList clients() const {
return m_clients;
}
- QList internalClients() const {
- return m_internalClients;
- }
void removeClient(ShellClient *c);
ShellClient *findClient(quint32 id) const;
ShellClient *findClient(KWayland::Server::SurfaceInterface *surface) const;
AbstractClient *findAbstractClient(KWayland::Server::SurfaceInterface *surface) const;
- ShellClient *findClient(QWindow *w) const;
/**
* @returns a transient parent of a surface imported with the foreign protocol, if any
@@ -280,7 +276,6 @@
KWayland::Server::XdgForeignInterface *m_XdgForeign = nullptr;
KWayland::Server::KeyStateInterface *m_keyState = nullptr;
QList m_clients;
- QList m_internalClients;
QHash m_clientIds;
InitalizationFlags m_initFlags;
QVector m_plasmaShellSurfaces;
diff --git a/wayland_server.cpp b/wayland_server.cpp
--- a/wayland_server.cpp
+++ b/wayland_server.cpp
@@ -22,7 +22,6 @@
#include "platform.h"
#include "composite.h"
#include "idle_inhibition.h"
-#include "internal_client.h"
#include "screens.h"
#include "shell_client.h"
#include "workspace.h"
@@ -156,12 +155,7 @@
if (surface->client() == m_screenLockerClientConnection) {
ScreenLocker::KSldApp::self()->lockScreenShown();
}
- ShellClient *client;
- if (surface->client() == waylandServer()->internalConnection()) {
- client = new InternalClient(surface);
- } else {
- client = new ShellClient(surface);
- }
+ ShellClient *client = new ShellClient(surface);
if (ServerSideDecorationInterface *deco = ServerSideDecorationInterface::get(surface->surface())) {
client->installServerSideDecoration(deco);
}
@@ -180,11 +174,7 @@
if (auto palette = m_paletteManager->paletteForSurface(surface->surface())) {
client->installPalette(palette);
}
- if (client->isInternal()) {
- m_internalClients << client;
- } else {
- m_clients << client;
- }
+ m_clients << client;
if (client->readyForPainting()) {
emit shellClientAdded(client);
} else {
@@ -601,7 +591,6 @@
void WaylandServer::removeClient(ShellClient *c)
{
m_clients.removeAll(c);
- m_internalClients.removeAll(c);
emit shellClientRemoved(c);
}
@@ -650,9 +639,6 @@
if (ShellClient *c = findClientInList(m_clients, id)) {
return c;
}
- if (ShellClient *c = findClientInList(m_internalClients, id)) {
- return c;
- }
return nullptr;
}
@@ -664,33 +650,14 @@
if (ShellClient *c = findClientInList(m_clients, surface)) {
return c;
}
- if (ShellClient *c = findClientInList(m_internalClients, surface)) {
- return c;
- }
return nullptr;
}
AbstractClient *WaylandServer::findAbstractClient(SurfaceInterface *surface) const
{
return findClient(surface);
}
-ShellClient *WaylandServer::findClient(QWindow *w) const
-{
- if (!w) {
- return nullptr;
- }
- auto it = std::find_if(m_internalClients.constBegin(), m_internalClients.constEnd(),
- [w] (const ShellClient *c) {
- return c->internalWindow() == w;
- }
- );
- if (it != m_internalClients.constEnd()) {
- return *it;
- }
- return nullptr;
-}
-
quint32 WaylandServer::createWindowId(SurfaceInterface *surface)
{
auto it = m_clientIds.constFind(surface->client());
diff --git a/workspace.h b/workspace.h
--- a/workspace.h
+++ b/workspace.h
@@ -129,11 +129,6 @@
Unmanaged *findUnmanaged(xcb_window_t w) const;
void forEachUnmanaged(std::function func);
Toplevel *findToplevel(std::function func) const;
- /**
- * Finds the Toplevel for the KWin internal window @p w.
- * On Wayland this is normally a ShellClient. For X11 an Unmanaged.
- **/
- Toplevel *findToplevel(QWindow *w) const;
/**
* @brief Finds a Toplevel for the internal window @p w.
*
@@ -240,6 +235,13 @@
return m_allClients;
}
+ /**
+ * @returns List of all internal clients currently managed by Workspace
+ **/
+ const InternalClientList &internalClients() const {
+ return m_internalClients;
+ }
+
void stackScreenEdgesUnderOverrideRedirect();
public:
@@ -503,6 +505,16 @@
**/
void stackingOrderChanged();
+ /**
+ * This signal is emitted whenever an internal client is created.
+ **/
+ void internalClientAdded(KWin::InternalClient *client);
+
+ /**
+ * This signal is emitted whenever an internal client gets removed.
+ **/
+ void internalClientRemoved(KWin::InternalClient *client);
+
private:
void init();
void initWithX11();
@@ -534,6 +546,9 @@
Unmanaged* createUnmanaged(xcb_window_t w);
void addUnmanaged(Unmanaged* c);
+ void addInternalClient(InternalClient *client);
+ void removeInternalClient(InternalClient *client);
+
//---------------------------------------------------------------------
void closeActivePopup();
@@ -569,6 +584,7 @@
ClientList desktops;
UnmanagedList unmanaged;
DeletedList deleted;
+ InternalClientList m_internalClients;
ToplevelList unconstrained_stacking_order; // Topmost last
ToplevelList stacking_order; // Topmost last
@@ -636,6 +652,8 @@
QList m_genericEventFilters;
QScopedPointer m_movingClientFilter;
+ friend class InternalClient;
+
private:
friend bool performTransiencyCheck();
friend Workspace *workspace();
diff --git a/workspace.cpp b/workspace.cpp
--- a/workspace.cpp
+++ b/workspace.cpp
@@ -37,6 +37,7 @@
#include "focuschain.h"
#include "group.h"
#include "input.h"
+#include "internal_client.h"
#include "logind.h"
#include "moving_client_x11_filter.h"
#include "killwindow.h"
@@ -1649,7 +1650,7 @@
return ret;
}
if (waylandServer()) {
- if (AbstractClient *ret = Toplevel::findInList(waylandServer()->internalClients(), func)) {
+ if (AbstractClient *ret = Toplevel::findInList(workspace()->internalClients(), func)) {
return ret;
}
}
@@ -1705,19 +1706,6 @@
return nullptr;
}
-Toplevel *Workspace::findToplevel(QWindow *w) const
-{
- if (!w) {
- return nullptr;
- }
- if (waylandServer()) {
- if (auto c = waylandServer()->findClient(w)) {
- return c;
- }
- }
- return findUnmanaged(w->winId());
-}
-
bool Workspace::hasClient(const AbstractClient *c)
{
if (auto cc = dynamic_cast(c)) {
@@ -1743,9 +1731,13 @@
}
if (kwinApp()->operationMode() == Application::OperationModeX11) {
return findUnmanaged(w->winId());
- } else {
- return waylandServer()->findClient(w);
}
+ for (InternalClient *client : m_internalClients) {
+ if (client->internalWindow() == w) {
+ return client;
+ }
+ }
+ return nullptr;
}
bool Workspace::compositing() const
@@ -1775,5 +1767,31 @@
);
}
+void Workspace::addInternalClient(InternalClient *client)
+{
+ m_internalClients.append(client);
+
+ setupClientConnections(client);
+ client->updateDecoration(false);
+ client->updateLayer();
+
+ markXStackingOrderAsDirty();
+ updateStackingOrder(true);
+ updateClientArea();
+
+ emit internalClientAdded(client);
+}
+
+void Workspace::removeInternalClient(InternalClient *client)
+{
+ m_internalClients.removeOne(client);
+
+ markXStackingOrderAsDirty();
+ updateStackingOrder(true);
+ updateClientArea();
+
+ emit internalClientRemoved(client);
+}
+
} // namespace