[wayland] Use the new plasma virtual desktop protocol
Summary: implement virtual desktop support for Wayland. use the new virtual desktop protocol from D12820 The VirtualDesktopManager class needed some big change in order to accomodate it, which is where most changes are. Other than that, it's mostly connections to wire up VirtualDesktopsManager and VirtualDesktopsManagement(the wayland protocol impl) Depends on D12820 Other notable detail, is the client visibility updated to reflect the presence of the client in the plasmavirtualdesktop. (and the unSetDesktop concept) Test Plan: used a bit a plasma session together with D12820, D13748 and D13746 Reviewers: #plasma, #kwin, graesslin, davidedmundson Reviewed By: #plasma, #kwin, davidedmundson Subscribers: hein, zzag, davidedmundson, kwin Tags: #kwin Maniphest Tasks: T4457 Differential Revision: https://phabricator.kde.org/D13887
This commit is contained in:
parent
e0aa3a3049
commit
7e8facc3fd
30 changed files with 1326 additions and 118 deletions
|
@ -381,6 +381,7 @@ add_subdirectory(helpers)
|
|||
set(kwin_KDEINIT_SRCS
|
||||
workspace.cpp
|
||||
dbusinterface.cpp
|
||||
virtualdesktopsdbustypes.cpp
|
||||
abstract_client.cpp
|
||||
client.cpp
|
||||
client_machine.cpp
|
||||
|
@ -533,6 +534,7 @@ qt5_add_dbus_adaptor( kwin_KDEINIT_SRCS org.kde.kwin.Compositing.xml dbusinterfa
|
|||
qt5_add_dbus_adaptor( kwin_KDEINIT_SRCS org.kde.kwin.ColorCorrect.xml colorcorrection/colorcorrectdbusinterface.h KWin::ColorCorrect::ColorCorrectDBusInterface )
|
||||
qt5_add_dbus_adaptor( kwin_KDEINIT_SRCS ${kwin_effects_dbus_xml} effects.h KWin::EffectsHandlerImpl )
|
||||
qt5_add_dbus_adaptor( kwin_KDEINIT_SRCS org.kde.kwin.OrientationSensor.xml orientation_sensor.h KWin::OrientationSensor)
|
||||
qt5_add_dbus_adaptor( kwin_KDEINIT_SRCS org.kde.KWin.VirtualDesktopManager.xml dbusinterface.h KWin::VirtualDesktopManagerDBusInterface )
|
||||
|
||||
qt5_add_dbus_interface( kwin_KDEINIT_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/org.freedesktop.ScreenSaver.xml screenlocker_interface)
|
||||
|
||||
|
@ -671,6 +673,7 @@ install(
|
|||
org.kde.kwin.Compositing.xml
|
||||
org.kde.kwin.ColorCorrect.xml
|
||||
org.kde.kwin.Effects.xml
|
||||
org.kde.KWin.VirtualDesktopManager.xml
|
||||
DESTINATION
|
||||
${KDE_INSTALL_DBUSINTERFACEDIR}
|
||||
)
|
||||
|
|
|
@ -489,16 +489,44 @@ void AbstractClient::setDesktop(int desktop)
|
|||
if (desktop != NET::OnAllDesktops) // Do range check
|
||||
desktop = qMax(1, qMin(numberOfDesktops, desktop));
|
||||
desktop = qMin(numberOfDesktops, rules()->checkDesktop(desktop));
|
||||
if (m_desktop == desktop)
|
||||
return;
|
||||
|
||||
int was_desk = m_desktop;
|
||||
const bool wasOnCurrentDesktop = isOnCurrentDesktop();
|
||||
m_desktop = desktop;
|
||||
VirtualDesktop *virtualDesktop = desktop == NET::OnAllDesktops ? nullptr : VirtualDesktopManager::self()->desktopForX11Id(desktop);
|
||||
|
||||
// Don't do anything if we're already there, if the desktop is already in desktops or if the desktop is NET::OnAllDesktops and m_desktops is already empty.
|
||||
if (m_desktops.contains(virtualDesktop) ||
|
||||
(desktop == NET::OnAllDesktops && m_desktops.isEmpty())) {
|
||||
return;
|
||||
}
|
||||
|
||||
int was_desk = AbstractClient::desktop();
|
||||
const bool wasOnCurrentDesktop = isOnCurrentDesktop() && was_desk >= 0;
|
||||
|
||||
//on x11 we can have only one desktop at a time
|
||||
if (kwinApp()->operationMode() == Application::OperationModeX11) {
|
||||
m_desktops.clear();
|
||||
}
|
||||
if (desktop == NET::OnAllDesktops) {
|
||||
m_desktops.clear();
|
||||
} else {
|
||||
//if would become on all desktops, clear the list, as empty == on all desktops
|
||||
if (m_desktops.count() > 1 && static_cast<uint>(m_desktops.count()) == VirtualDesktopManager::self()->count() - 1) {
|
||||
m_desktops.clear();
|
||||
} else {
|
||||
m_desktops << virtualDesktop;
|
||||
}
|
||||
}
|
||||
if (windowManagementInterface()) {
|
||||
if (m_desktops.isEmpty()) {
|
||||
windowManagementInterface()->setOnAllDesktops(true);
|
||||
} else {
|
||||
windowManagementInterface()->addPlasmaVirtualDesktop(virtualDesktop->id());
|
||||
}
|
||||
}
|
||||
|
||||
if (info) {
|
||||
info->setDesktop(desktop);
|
||||
}
|
||||
|
||||
if ((was_desk == NET::OnAllDesktops) != (desktop == NET::OnAllDesktops)) {
|
||||
// onAllDesktops changed
|
||||
workspace()->updateOnAllDesktopsOfTransients(this);
|
||||
|
@ -526,6 +554,7 @@ void AbstractClient::setDesktop(int desktop)
|
|||
emit desktopChanged();
|
||||
if (wasOnCurrentDesktop != isOnCurrentDesktop())
|
||||
emit desktopPresenceChanged(this, was_desk);
|
||||
emit x11DesktopIdsChanged();
|
||||
}
|
||||
|
||||
void AbstractClient::doSetDesktop(int desktop, int was_desk)
|
||||
|
@ -534,6 +563,34 @@ void AbstractClient::doSetDesktop(int desktop, int was_desk)
|
|||
Q_UNUSED(was_desk)
|
||||
}
|
||||
|
||||
void AbstractClient::unSetDesktop(int desktop)
|
||||
{
|
||||
// Case in which we are on all desktops and gets asked to unset
|
||||
if (desktop == NET::OnAllDesktops) {
|
||||
if (m_desktops.isEmpty()) {
|
||||
setOnAllDesktops(false);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Out of range
|
||||
if (desktop < 1 || desktop > VirtualDesktopManager::self()->count()) {
|
||||
return;
|
||||
}
|
||||
|
||||
VirtualDesktop *virtualDesktop = VirtualDesktopManager::self()->desktopForX11Id(desktop);
|
||||
|
||||
m_desktops.removeAll(virtualDesktop);
|
||||
|
||||
if (!windowManagementInterface()) {
|
||||
return;
|
||||
}
|
||||
|
||||
windowManagementInterface()->removePlasmaVirtualDesktop(virtualDesktop->id());
|
||||
emit x11DesktopIdsChanged();
|
||||
}
|
||||
|
||||
void AbstractClient::setOnAllDesktops(bool b)
|
||||
{
|
||||
if ((b && isOnAllDesktops()) ||
|
||||
|
@ -545,6 +602,20 @@ void AbstractClient::setOnAllDesktops(bool b)
|
|||
setDesktop(VirtualDesktopManager::self()->current());
|
||||
}
|
||||
|
||||
QList<int> AbstractClient::x11DesktopIds() const
|
||||
{
|
||||
const auto desks = desktops();
|
||||
QList<int> x11Ids;
|
||||
x11Ids.reserve(desks.count());
|
||||
std::transform(desks.constBegin(), desks.constEnd(),
|
||||
std::back_inserter(x11Ids),
|
||||
[] (const VirtualDesktop *vd) {
|
||||
return vd->x11DesktopNumber();
|
||||
}
|
||||
);
|
||||
return x11Ids;
|
||||
}
|
||||
|
||||
bool AbstractClient::isShadeable() const
|
||||
{
|
||||
return false;
|
||||
|
@ -808,16 +879,7 @@ void AbstractClient::setupWindowManagementInterface()
|
|||
}
|
||||
);
|
||||
connect(this, &AbstractClient::captionChanged, w, [w, this] { w->setTitle(caption()); });
|
||||
connect(this, &AbstractClient::desktopChanged, w,
|
||||
[w, this] {
|
||||
if (isOnAllDesktops()) {
|
||||
w->setOnAllDesktops(true);
|
||||
return;
|
||||
}
|
||||
w->setVirtualDesktop(desktop() - 1);
|
||||
w->setOnAllDesktops(false);
|
||||
}
|
||||
);
|
||||
|
||||
connect(this, &AbstractClient::activeChanged, w, [w, this] { w->setActive(isActive()); });
|
||||
connect(this, &AbstractClient::fullScreenChanged, w, [w, this] { w->setFullscreen(isFullScreen()); });
|
||||
connect(this, &AbstractClient::keepAboveChanged, w, &PlasmaWindowInterface::setKeepAbove);
|
||||
|
@ -912,6 +974,48 @@ void AbstractClient::setupWindowManagementInterface()
|
|||
setShade(set);
|
||||
}
|
||||
);
|
||||
|
||||
for (const auto vd : m_desktops) {
|
||||
w->addPlasmaVirtualDesktop(vd->id());
|
||||
}
|
||||
|
||||
//this is only for the legacy
|
||||
connect(this, &AbstractClient::desktopChanged, w,
|
||||
[w, this] {
|
||||
if (isOnAllDesktops()) {
|
||||
w->setOnAllDesktops(true);
|
||||
return;
|
||||
}
|
||||
w->setVirtualDesktop(desktop() - 1);
|
||||
w->setOnAllDesktops(false);
|
||||
}
|
||||
);
|
||||
|
||||
//Plasma Virtual desktop management
|
||||
//show/hide when the window enters/exits from desktop
|
||||
connect(w, &PlasmaWindowInterface::enterPlasmaVirtualDesktopRequested, this,
|
||||
[this] (const QString &desktopId) {
|
||||
VirtualDesktop *vd = VirtualDesktopManager::self()->desktopForId(desktopId.toUtf8());
|
||||
if (vd) {
|
||||
workspace()->sendClientToDesktop(this, vd->x11DesktopNumber(), false);
|
||||
}
|
||||
}
|
||||
);
|
||||
connect(w, &PlasmaWindowInterface::enterNewPlasmaVirtualDesktopRequested, this,
|
||||
[this] () {
|
||||
VirtualDesktopManager::self()->setCount(VirtualDesktopManager::self()->count() + 1);
|
||||
workspace()->sendClientToDesktop(this, VirtualDesktopManager::self()->count(), false);
|
||||
}
|
||||
);
|
||||
connect(w, &PlasmaWindowInterface::leavePlasmaVirtualDesktopRequested, this,
|
||||
[this] (const QString &desktopId) {
|
||||
VirtualDesktop *vd = VirtualDesktopManager::self()->desktopForId(desktopId.toUtf8());
|
||||
if (vd) {
|
||||
unSetDesktop(vd->x11DesktopNumber());
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
m_windowManagementInterface = w;
|
||||
}
|
||||
|
||||
|
|
|
@ -84,12 +84,17 @@ class KWIN_EXPORT AbstractClient : public Toplevel
|
|||
Q_PROPERTY(bool active READ isActive NOTIFY activeChanged)
|
||||
/**
|
||||
* The desktop this Client is on. If the Client is on all desktops the property has value -1.
|
||||
* This is a legacy property, use x11DesktopIds instead
|
||||
**/
|
||||
Q_PROPERTY(int desktop READ desktop WRITE setDesktop NOTIFY desktopChanged)
|
||||
/**
|
||||
* Whether the Client is on all desktops. That is desktop is -1.
|
||||
**/
|
||||
Q_PROPERTY(bool onAllDesktops READ isOnAllDesktops WRITE setOnAllDesktops NOTIFY desktopChanged)
|
||||
/**
|
||||
* The x11 ids for all desktops this client is in. On X11 this list will always have a length of 1
|
||||
**/
|
||||
Q_PROPERTY(QList<int> x11DesktopIds READ x11DesktopIds NOTIFY x11DesktopIdsChanged)
|
||||
/**
|
||||
* Indicates that the window should not be included on a taskbar.
|
||||
**/
|
||||
|
@ -423,9 +428,18 @@ public:
|
|||
virtual bool performMouseCommand(Options::MouseCommand, const QPoint &globalPos);
|
||||
void setOnAllDesktops(bool set);
|
||||
void setDesktop(int);
|
||||
Q_INVOKABLE virtual void unSetDesktop(int desktop);
|
||||
int desktop() const override {
|
||||
return m_desktop;
|
||||
return m_desktops.isEmpty() ? (int)NET::OnAllDesktops : m_desktops.last()->x11DesktopNumber();
|
||||
}
|
||||
virtual QList<VirtualDesktop *> desktops() const {
|
||||
return m_desktops;
|
||||
}
|
||||
void removeDesktop(VirtualDesktop *desktop) {
|
||||
m_desktops.removeAll(desktop);
|
||||
}
|
||||
QList<int> x11DesktopIds() const;
|
||||
|
||||
void setMinimized(bool set);
|
||||
/**
|
||||
* Minimizes this client plus its transients
|
||||
|
@ -757,6 +771,7 @@ Q_SIGNALS:
|
|||
void demandsAttentionChanged();
|
||||
void desktopPresenceChanged(KWin::AbstractClient*, int); // to be forwarded by Workspace
|
||||
void desktopChanged();
|
||||
void x11DesktopIdsChanged();
|
||||
void shadeChanged();
|
||||
void minimizedChanged();
|
||||
void clientMinimized(KWin::AbstractClient* client, bool animate);
|
||||
|
@ -1107,7 +1122,7 @@ private:
|
|||
bool m_demandsAttention = false;
|
||||
bool m_minimized = false;
|
||||
QTimer *m_autoRaiseTimer = nullptr;
|
||||
int m_desktop = 0; // 0 means not on any desktop yet
|
||||
QList <VirtualDesktop *> m_desktops;
|
||||
|
||||
QString m_colorScheme;
|
||||
std::shared_ptr<Decoration::DecorationPalette> m_palette;
|
||||
|
|
|
@ -43,6 +43,7 @@ target_link_libraries( testVirtualDesktops
|
|||
KF5::GlobalAccel
|
||||
KF5::ConfigCore
|
||||
KF5::WindowSystem
|
||||
KF5::WaylandServer
|
||||
)
|
||||
add_test(NAME kwin-testVirtualDesktops COMMAND testVirtualDesktops)
|
||||
ecm_mark_as_test(testVirtualDesktops)
|
||||
|
@ -336,6 +337,7 @@ target_link_libraries(testScreenEdges
|
|||
KF5::GlobalAccel
|
||||
KF5::Notifications
|
||||
KF5::WindowSystem
|
||||
KF5::WaylandServer
|
||||
XCB::XCB
|
||||
XCB::RANDR
|
||||
XCB::XFIXES
|
||||
|
|
|
@ -43,6 +43,10 @@ private Q_SLOTS:
|
|||
void testNetCurrentDesktop();
|
||||
void testLastDesktopRemoved_data();
|
||||
void testLastDesktopRemoved();
|
||||
void testWindowOnMultipleDesktops_data();
|
||||
void testWindowOnMultipleDesktops();
|
||||
void testRemoveDesktopWithWindow_data();
|
||||
void testRemoveDesktopWithWindow();
|
||||
};
|
||||
|
||||
void VirtualDesktopTest::initTestCase()
|
||||
|
@ -157,12 +161,154 @@ void VirtualDesktopTest::testLastDesktopRemoved()
|
|||
QSignalSpy desktopPresenceChangedSpy(client, &ShellClient::desktopPresenceChanged);
|
||||
QVERIFY(desktopPresenceChangedSpy.isValid());
|
||||
|
||||
QCOMPARE(client->desktops().count(), 1u);
|
||||
QCOMPARE(VirtualDesktopManager::self()->currentDesktop(), client->desktops().first());
|
||||
|
||||
// and remove last desktop
|
||||
VirtualDesktopManager::self()->setCount(1);
|
||||
QCOMPARE(VirtualDesktopManager::self()->count(), 1u);
|
||||
// now the client should be moved as well
|
||||
QTRY_COMPARE(desktopPresenceChangedSpy.count(), 1);
|
||||
QCOMPARE(client->desktop(), 1);
|
||||
|
||||
QCOMPARE(client->desktops().count(), 1u);
|
||||
QCOMPARE(VirtualDesktopManager::self()->currentDesktop(), client->desktops().first());
|
||||
}
|
||||
|
||||
void VirtualDesktopTest::testWindowOnMultipleDesktops_data()
|
||||
{
|
||||
QTest::addColumn<Test::ShellSurfaceType>("type");
|
||||
|
||||
QTest::newRow("wlShell") << Test::ShellSurfaceType::WlShell;
|
||||
QTest::newRow("xdgShellV5") << Test::ShellSurfaceType::XdgShellV5;
|
||||
QTest::newRow("xdgShellV6") << Test::ShellSurfaceType::XdgShellV6;
|
||||
}
|
||||
|
||||
void VirtualDesktopTest::testWindowOnMultipleDesktops()
|
||||
{
|
||||
// first create two new desktops
|
||||
QCOMPARE(VirtualDesktopManager::self()->count(), 1u);
|
||||
VirtualDesktopManager::self()->setCount(3);
|
||||
QCOMPARE(VirtualDesktopManager::self()->count(), 3u);
|
||||
|
||||
// switch to last desktop
|
||||
VirtualDesktopManager::self()->setCurrent(VirtualDesktopManager::self()->desktops().last());
|
||||
QCOMPARE(VirtualDesktopManager::self()->current(), 3u);
|
||||
|
||||
// now create a window on this desktop
|
||||
QScopedPointer<Surface> surface(Test::createSurface());
|
||||
QFETCH(Test::ShellSurfaceType, type);
|
||||
QScopedPointer<QObject> shellSurface(Test::createShellSurface(type, surface.data()));
|
||||
auto client = Test::renderAndWaitForShown(surface.data(), QSize(100, 50), Qt::blue);
|
||||
|
||||
QVERIFY(client);
|
||||
QCOMPARE(client->desktop(), 3u);
|
||||
QSignalSpy desktopPresenceChangedSpy(client, &ShellClient::desktopPresenceChanged);
|
||||
QVERIFY(desktopPresenceChangedSpy.isValid());
|
||||
|
||||
QCOMPARE(client->desktops().count(), 1u);
|
||||
QCOMPARE(VirtualDesktopManager::self()->currentDesktop(), client->desktops().first());
|
||||
|
||||
//Set the window on desktop 2 as well
|
||||
client->setDesktop(2u);
|
||||
QCOMPARE(client->desktops().count(), 2u);
|
||||
QCOMPARE(VirtualDesktopManager::self()->desktops()[2], client->desktops()[0]);
|
||||
QCOMPARE(VirtualDesktopManager::self()->desktops()[1], client->desktops()[1]);
|
||||
QVERIFY(client->isOnDesktop(2));
|
||||
QVERIFY(client->isOnDesktop(3));
|
||||
|
||||
//leave desktop 3
|
||||
client->unSetDesktop(3);
|
||||
QCOMPARE(client->desktops().count(), 1u);
|
||||
//leave desktop 2
|
||||
client->unSetDesktop(2);
|
||||
QCOMPARE(client->desktops().count(), 0u);
|
||||
//we should be on all desktops now
|
||||
QVERIFY(client->isOnAllDesktops());
|
||||
//put on desktop 1
|
||||
client->setDesktop(1);
|
||||
QVERIFY(client->isOnDesktop(1));
|
||||
QVERIFY(!client->isOnDesktop(2));
|
||||
QVERIFY(!client->isOnDesktop(3));
|
||||
QCOMPARE(client->desktops().count(), 1u);
|
||||
//put on desktop 2
|
||||
client->setDesktop(2);
|
||||
QVERIFY(client->isOnDesktop(1));
|
||||
QVERIFY(client->isOnDesktop(2));
|
||||
QVERIFY(!client->isOnDesktop(3));
|
||||
QCOMPARE(client->desktops().count(), 2u);
|
||||
//put on desktop 3
|
||||
client->setDesktop(3);
|
||||
QVERIFY(client->isOnDesktop(1));
|
||||
QVERIFY(client->isOnDesktop(2));
|
||||
QVERIFY(client->isOnDesktop(3));
|
||||
QVERIFY(client->isOnAllDesktops());
|
||||
//when it gets on all desktops, it loses all desktops()
|
||||
QCOMPARE(client->desktops().count(), 0u);
|
||||
}
|
||||
|
||||
void VirtualDesktopTest::testRemoveDesktopWithWindow_data()
|
||||
{
|
||||
QTest::addColumn<Test::ShellSurfaceType>("type");
|
||||
|
||||
QTest::newRow("wlShell") << Test::ShellSurfaceType::WlShell;
|
||||
QTest::newRow("xdgShellV5") << Test::ShellSurfaceType::XdgShellV5;
|
||||
QTest::newRow("xdgShellV6") << Test::ShellSurfaceType::XdgShellV6;
|
||||
}
|
||||
|
||||
void VirtualDesktopTest::testRemoveDesktopWithWindow()
|
||||
{
|
||||
// first create two new desktops
|
||||
QCOMPARE(VirtualDesktopManager::self()->count(), 1u);
|
||||
VirtualDesktopManager::self()->setCount(3);
|
||||
QCOMPARE(VirtualDesktopManager::self()->count(), 3u);
|
||||
|
||||
// switch to last desktop
|
||||
VirtualDesktopManager::self()->setCurrent(VirtualDesktopManager::self()->desktops().last());
|
||||
QCOMPARE(VirtualDesktopManager::self()->current(), 3u);
|
||||
|
||||
// now create a window on this desktop
|
||||
QScopedPointer<Surface> surface(Test::createSurface());
|
||||
QFETCH(Test::ShellSurfaceType, type);
|
||||
QScopedPointer<QObject> shellSurface(Test::createShellSurface(type, surface.data()));
|
||||
auto client = Test::renderAndWaitForShown(surface.data(), QSize(100, 50), Qt::blue);
|
||||
|
||||
QVERIFY(client);
|
||||
QCOMPARE(client->desktop(), 3u);
|
||||
QSignalSpy desktopPresenceChangedSpy(client, &ShellClient::desktopPresenceChanged);
|
||||
QVERIFY(desktopPresenceChangedSpy.isValid());
|
||||
|
||||
QCOMPARE(client->desktops().count(), 1u);
|
||||
QCOMPARE(VirtualDesktopManager::self()->currentDesktop(), client->desktops().first());
|
||||
|
||||
//Set the window on desktop 2 as well
|
||||
client->setDesktop(2u);
|
||||
QCOMPARE(client->desktops().count(), 2u);
|
||||
QCOMPARE(VirtualDesktopManager::self()->desktops()[2], client->desktops()[0]);
|
||||
QCOMPARE(VirtualDesktopManager::self()->desktops()[1], client->desktops()[1]);
|
||||
QVERIFY(client->isOnDesktop(2));
|
||||
QVERIFY(client->isOnDesktop(3));
|
||||
|
||||
//remove desktop 3
|
||||
VirtualDesktopManager::self()->setCount(2);
|
||||
QCOMPARE(client->desktops().count(), 1u);
|
||||
//window is only on desktop 2
|
||||
QCOMPARE(VirtualDesktopManager::self()->desktops()[1], client->desktops()[0]);
|
||||
|
||||
//Again 3 desktops
|
||||
VirtualDesktopManager::self()->setCount(3);
|
||||
//move window to be only on desktop 3
|
||||
client->setDesktop(3);
|
||||
client->unSetDesktop(2);
|
||||
QCOMPARE(client->desktops().count(), 1u);
|
||||
//window is only on desktop 3
|
||||
QCOMPARE(VirtualDesktopManager::self()->desktops()[2], client->desktops()[0]);
|
||||
|
||||
//remove desktop 3
|
||||
VirtualDesktopManager::self()->setCount(2);
|
||||
QCOMPARE(client->desktops().count(), 1u);
|
||||
//window is only on desktop 2
|
||||
QCOMPARE(VirtualDesktopManager::self()->desktops()[1], client->desktops()[0]);
|
||||
}
|
||||
|
||||
WAYLANDTEST_MAIN(VirtualDesktopTest)
|
||||
|
|
|
@ -132,8 +132,10 @@ void TestVirtualDesktops::count()
|
|||
vds->setCount(s_countInitValue);
|
||||
|
||||
QSignalSpy spy(vds, SIGNAL(countChanged(uint,uint)));
|
||||
QSignalSpy desktopsRemoved(vds, SIGNAL(desktopsRemoved(uint)));
|
||||
QSignalSpy desktopsRemoved(vds, SIGNAL(desktopRemoved(KWin::VirtualDesktop *)));
|
||||
|
||||
auto vdToRemove = vds->desktops().last();
|
||||
|
||||
QFETCH(uint, request);
|
||||
QFETCH(uint, result);
|
||||
QFETCH(bool, signal);
|
||||
|
@ -153,8 +155,7 @@ void TestVirtualDesktops::count()
|
|||
if (!desktopsRemoved.isEmpty()) {
|
||||
QList<QVariant> arguments = desktopsRemoved.takeFirst();
|
||||
QCOMPARE(arguments.count(), 1);
|
||||
QCOMPARE(arguments.at(0).type(), QVariant::UInt);
|
||||
QCOMPARE(arguments.at(0).toUInt(), s_countInitValue);
|
||||
QCOMPARE(arguments.at(0).value<KWin::VirtualDesktop*>(), vdToRemove);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
*********************************************************************/
|
||||
|
||||
#include <kwineffects.h>
|
||||
#include "../virtualdesktops.h"
|
||||
|
||||
#include <QVector2D>
|
||||
#include <QGraphicsRotation>
|
||||
|
@ -72,6 +73,7 @@ public:
|
|||
virtual void setData(int role, const QVariant &data);
|
||||
virtual void referencePreviousWindowPixmap() {}
|
||||
virtual void unreferencePreviousWindowPixmap() {}
|
||||
QList<int> desktops() const { return {};}
|
||||
};
|
||||
|
||||
MockEffectWindow::MockEffectWindow(QObject *parent)
|
||||
|
|
|
@ -21,6 +21,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
// own
|
||||
#include "dbusinterface.h"
|
||||
#include "compositingadaptor.h"
|
||||
#include "virtualdesktopmanageradaptor.h"
|
||||
|
||||
// kwin
|
||||
#include "abstract_client.h"
|
||||
|
@ -315,4 +316,180 @@ QStringList CompositorDBusInterface::supportedOpenGLPlatformInterfaces() const
|
|||
return interfaces;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
VirtualDesktopManagerDBusInterface::VirtualDesktopManagerDBusInterface(VirtualDesktopManager *parent)
|
||||
: QObject(parent)
|
||||
, m_manager(parent)
|
||||
{
|
||||
qDBusRegisterMetaType<KWin::DBusDesktopDataStruct>();
|
||||
qDBusRegisterMetaType<KWin::DBusDesktopDataVector>();
|
||||
|
||||
new VirtualDesktopManagerAdaptor(this);
|
||||
QDBusConnection::sessionBus().registerObject(QStringLiteral("/VirtualDesktopManager"),
|
||||
QStringLiteral("org.kde.KWin.VirtualDesktopManager"),
|
||||
this
|
||||
);
|
||||
|
||||
connect(m_manager, &VirtualDesktopManager::currentChanged, this,
|
||||
[this](uint previousDesktop, uint newDesktop) {
|
||||
Q_UNUSED(previousDesktop);
|
||||
Q_UNUSED(newDesktop);
|
||||
emit currentChanged(m_manager->currentDesktop()->id());
|
||||
}
|
||||
);
|
||||
|
||||
connect(m_manager, &VirtualDesktopManager::countChanged, this,
|
||||
[this](uint previousCount, uint newCount) {
|
||||
Q_UNUSED(previousCount);
|
||||
emit countChanged(newCount);
|
||||
emit desktopsChanged(desktops());
|
||||
}
|
||||
);
|
||||
|
||||
connect(m_manager, &VirtualDesktopManager::navigationWrappingAroundChanged, this,
|
||||
[this]() {
|
||||
emit navigationWrappingAroundChanged(isNavigationWrappingAround());
|
||||
}
|
||||
);
|
||||
|
||||
connect(m_manager, &VirtualDesktopManager::rowsChanged, this, &VirtualDesktopManagerDBusInterface::rowsChanged);
|
||||
|
||||
for (auto *vd : m_manager->desktops()) {
|
||||
connect(vd, &VirtualDesktop::x11DesktopNumberChanged, this,
|
||||
[this, vd]() {
|
||||
DBusDesktopDataStruct data{.position = vd->x11DesktopNumber() - 1, .id = vd->id(), .name = vd->name()};
|
||||
emit desktopDataChanged(vd->id(), data);
|
||||
emit desktopsChanged(desktops());
|
||||
}
|
||||
);
|
||||
connect(vd, &VirtualDesktop::nameChanged, this,
|
||||
[this, vd]() {
|
||||
DBusDesktopDataStruct data{.position = vd->x11DesktopNumber() - 1, .id = vd->id(), .name = vd->name()};
|
||||
emit desktopDataChanged(vd->id(), data);
|
||||
emit desktopsChanged(desktops());
|
||||
}
|
||||
);
|
||||
}
|
||||
connect(m_manager, &VirtualDesktopManager::desktopCreated, this,
|
||||
[this](VirtualDesktop *vd) {
|
||||
connect(vd, &VirtualDesktop::x11DesktopNumberChanged, this,
|
||||
[this, vd]() {
|
||||
DBusDesktopDataStruct data{.position = vd->x11DesktopNumber() - 1, .id = vd->id(), .name = vd->name()};
|
||||
emit desktopDataChanged(vd->id(), data);
|
||||
emit desktopsChanged(desktops());
|
||||
}
|
||||
);
|
||||
connect(vd, &VirtualDesktop::nameChanged, this,
|
||||
[this, vd]() {
|
||||
DBusDesktopDataStruct data{.position = vd->x11DesktopNumber() - 1, .id = vd->id(), .name = vd->name()};
|
||||
emit desktopDataChanged(vd->id(), data);
|
||||
emit desktopsChanged(desktops());
|
||||
}
|
||||
);
|
||||
DBusDesktopDataStruct data{.position = vd->x11DesktopNumber() - 1, .id = vd->id(), .name = vd->name()};
|
||||
emit desktopCreated(vd->id(), data);
|
||||
emit desktopsChanged(desktops());
|
||||
}
|
||||
);
|
||||
connect(m_manager, &VirtualDesktopManager::desktopRemoved, this,
|
||||
[this](VirtualDesktop *vd) {
|
||||
emit desktopRemoved(vd->id());
|
||||
emit desktopsChanged(desktops());
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
uint VirtualDesktopManagerDBusInterface::count() const
|
||||
{
|
||||
return m_manager->count();
|
||||
}
|
||||
|
||||
void VirtualDesktopManagerDBusInterface::setRows(uint rows)
|
||||
{
|
||||
if (static_cast<uint>(m_manager->grid().height()) == rows) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_manager->setRows(rows);
|
||||
m_manager->save();
|
||||
}
|
||||
|
||||
uint VirtualDesktopManagerDBusInterface::rows() const
|
||||
{
|
||||
return m_manager->rows();
|
||||
}
|
||||
|
||||
void VirtualDesktopManagerDBusInterface::setCurrent(const QString &id)
|
||||
{
|
||||
if (m_manager->currentDesktop()->id() == id) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto *vd = m_manager->desktopForId(id.toUtf8());
|
||||
if (vd) {
|
||||
m_manager->setCurrent(vd);
|
||||
}
|
||||
}
|
||||
|
||||
QString VirtualDesktopManagerDBusInterface::current() const
|
||||
{
|
||||
return m_manager->currentDesktop()->id();
|
||||
}
|
||||
|
||||
void VirtualDesktopManagerDBusInterface::setNavigationWrappingAround(bool wraps)
|
||||
{
|
||||
if (m_manager->isNavigationWrappingAround() == wraps) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_manager->setNavigationWrappingAround(wraps);
|
||||
}
|
||||
|
||||
bool VirtualDesktopManagerDBusInterface::isNavigationWrappingAround() const
|
||||
{
|
||||
return m_manager->isNavigationWrappingAround();
|
||||
}
|
||||
|
||||
DBusDesktopDataVector VirtualDesktopManagerDBusInterface::desktops() const
|
||||
{
|
||||
const auto desks = m_manager->desktops();
|
||||
DBusDesktopDataVector desktopVect;
|
||||
desktopVect.reserve(m_manager->count());
|
||||
|
||||
std::transform(desks.constBegin(), desks.constEnd(),
|
||||
std::back_inserter(desktopVect),
|
||||
[] (const VirtualDesktop *vd) {
|
||||
return DBusDesktopDataStruct{.position = vd->x11DesktopNumber() - 1, .id = vd->id(), .name = vd->name()};
|
||||
}
|
||||
);
|
||||
|
||||
return desktopVect;
|
||||
}
|
||||
|
||||
void VirtualDesktopManagerDBusInterface::createDesktop(uint position, const QString &name)
|
||||
{
|
||||
m_manager->createVirtualDesktop(position + 1, name);
|
||||
}
|
||||
|
||||
void VirtualDesktopManagerDBusInterface::setDesktopName(const QString &id, const QString &name)
|
||||
{
|
||||
VirtualDesktop *vd = m_manager->desktopForId(id.toUtf8());
|
||||
if (!vd) {
|
||||
return;
|
||||
}
|
||||
if (vd->name() == name) {
|
||||
return;
|
||||
}
|
||||
|
||||
vd->setName(name);
|
||||
m_manager->save();
|
||||
}
|
||||
|
||||
void VirtualDesktopManagerDBusInterface::removeDesktop(const QString &id)
|
||||
{
|
||||
m_manager->removeVirtualDesktop(id.toUtf8());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -24,10 +24,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include <QObject>
|
||||
#include <QtDBus>
|
||||
|
||||
#include "virtualdesktopsdbustypes.h"
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
class Compositor;
|
||||
class VirtualDesktopManager;
|
||||
|
||||
/**
|
||||
* @brief This class is a wrapper for the org.kde.KWin D-Bus interface.
|
||||
|
@ -169,6 +172,76 @@ private:
|
|||
Compositor *m_compositor;
|
||||
};
|
||||
|
||||
//TODO: disable all of this in case of kiosk?
|
||||
|
||||
class VirtualDesktopManagerDBusInterface : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_CLASSINFO("D-Bus Interface", "org.kde.KWin.VirtualDesktopManager")
|
||||
|
||||
/**
|
||||
* The number of virtual desktops currently available.
|
||||
* The ids of the virtual desktops are in the range [1, VirtualDesktopManager::maximum()].
|
||||
**/
|
||||
Q_PROPERTY(uint count READ count NOTIFY countChanged)
|
||||
/**
|
||||
* The number of rows the virtual desktops will be laid out in
|
||||
**/
|
||||
Q_PROPERTY(uint rows READ rows WRITE setRows NOTIFY rowsChanged)
|
||||
/**
|
||||
* The id of the virtual desktop which is currently in use.
|
||||
**/
|
||||
Q_PROPERTY(QString current READ current WRITE setCurrent NOTIFY currentChanged)
|
||||
/**
|
||||
* Whether navigation in the desktop layout wraps around at the borders.
|
||||
**/
|
||||
Q_PROPERTY(bool navigationWrappingAround READ isNavigationWrappingAround WRITE setNavigationWrappingAround NOTIFY navigationWrappingAroundChanged)
|
||||
|
||||
/**
|
||||
* list of key/value pairs which every one of them is representing a desktop
|
||||
*/
|
||||
Q_PROPERTY(KWin::DBusDesktopDataVector desktops READ desktops NOTIFY desktopsChanged);
|
||||
|
||||
public:
|
||||
VirtualDesktopManagerDBusInterface(VirtualDesktopManager *parent);
|
||||
~VirtualDesktopManagerDBusInterface() = default;
|
||||
|
||||
uint count() const;
|
||||
|
||||
void setRows(uint rows);
|
||||
uint rows() const;
|
||||
|
||||
void setCurrent(const QString &id);
|
||||
QString current() const;
|
||||
|
||||
void setNavigationWrappingAround(bool wraps);
|
||||
bool isNavigationWrappingAround() const;
|
||||
|
||||
KWin::DBusDesktopDataVector desktops() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void countChanged(uint count);
|
||||
void rowsChanged(uint rows);
|
||||
void currentChanged(const QString &id);
|
||||
void navigationWrappingAroundChanged(bool wraps);
|
||||
void desktopsChanged(KWin::DBusDesktopDataVector);
|
||||
void desktopDataChanged(const QString &id, KWin::DBusDesktopDataStruct);
|
||||
void desktopCreated(const QString &id, KWin::DBusDesktopDataStruct);
|
||||
void desktopRemoved(const QString &id);
|
||||
|
||||
public Q_SLOTS:
|
||||
/**
|
||||
* Create a desktop with a new name at a given position
|
||||
* note: the position starts from 1
|
||||
*/
|
||||
void createDesktop(uint position, const QString &name);
|
||||
void setDesktopName(const QString &id, const QString &name);
|
||||
void removeDesktop(const QString &id);
|
||||
|
||||
private:
|
||||
VirtualDesktopManager *m_manager;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // KWIN_DBUS_INTERFACE_H
|
||||
|
|
|
@ -94,6 +94,7 @@ void Deleted::copyToDeleted(Toplevel* c)
|
|||
assert(dynamic_cast< Deleted* >(c) == NULL);
|
||||
Toplevel::copyToDeleted(c);
|
||||
desk = c->desktop();
|
||||
m_desktops = c->desktops();
|
||||
activityList = c->activities();
|
||||
contentsRect = QRect(c->clientPos(), c->clientSize());
|
||||
m_contentPos = c->clientContentPos();
|
||||
|
@ -177,6 +178,11 @@ QStringList Deleted::activities() const
|
|||
return activityList;
|
||||
}
|
||||
|
||||
QList<VirtualDesktop *> Deleted::desktops() const
|
||||
{
|
||||
return m_desktops;
|
||||
}
|
||||
|
||||
QPoint Deleted::clientPos() const
|
||||
{
|
||||
return contentsRect.topLeft();
|
||||
|
|
|
@ -52,6 +52,7 @@ public:
|
|||
void discard();
|
||||
virtual int desktop() const;
|
||||
virtual QStringList activities() const;
|
||||
virtual QList<VirtualDesktop *> desktops() const;
|
||||
virtual QPoint clientPos() const;
|
||||
virtual QSize clientSize() const;
|
||||
QPoint clientContentPos() const override {
|
||||
|
@ -195,6 +196,7 @@ private:
|
|||
QPoint m_contentPos;
|
||||
QRect transparent_rect;
|
||||
xcb_window_t m_frame;
|
||||
QList <VirtualDesktop *> m_desktops;
|
||||
|
||||
bool no_border;
|
||||
QRect decoration_left;
|
||||
|
|
|
@ -911,8 +911,9 @@ void EffectsHandlerImpl::moveWindow(EffectWindow* w, const QPoint& pos, bool sna
|
|||
void EffectsHandlerImpl::windowToDesktop(EffectWindow* w, int desktop)
|
||||
{
|
||||
AbstractClient* cl = dynamic_cast< AbstractClient* >(static_cast<EffectWindowImpl*>(w)->window());
|
||||
if (cl && !cl->isDesktop() && !cl->isDock())
|
||||
if (cl && !cl->isDesktop() && !cl->isDock()) {
|
||||
Workspace::self()->sendClientToDesktop(cl, desktop, true);
|
||||
}
|
||||
}
|
||||
|
||||
void EffectsHandlerImpl::windowToScreen(EffectWindow* w, int screen)
|
||||
|
|
|
@ -42,6 +42,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include <QQmlEngine>
|
||||
#include <QQuickItem>
|
||||
|
||||
#include <KWayland/Server/surface_interface.h>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
|
@ -52,6 +54,7 @@ DesktopGridEffect::DesktopGridEffect()
|
|||
, timeline()
|
||||
, keyboardGrab(false)
|
||||
, wasWindowMove(false)
|
||||
, wasWindowCopy(false)
|
||||
, wasDesktopMove(false)
|
||||
, isValidMove(false)
|
||||
, windowMove(NULL)
|
||||
|
@ -297,7 +300,9 @@ void DesktopGridEffect::prePaintWindow(EffectWindow* w, WindowPrePaintData& data
|
|||
void DesktopGridEffect::paintWindow(EffectWindow* w, int mask, QRegion region, WindowPaintData& data)
|
||||
{
|
||||
if (timeline.currentValue() != 0 || (isUsingPresentWindows() && isMotionManagerMovingWindows())) {
|
||||
if (isUsingPresentWindows() && w == windowMove && wasWindowMove) {
|
||||
if (isUsingPresentWindows() && w == windowMove && wasWindowMove &&
|
||||
((!wasWindowCopy && sourceDesktop == paintingDesktop) ||
|
||||
(sourceDesktop != highlightedDesktop && highlightedDesktop == paintingDesktop))) {
|
||||
return; // will be painted on top of all other windows
|
||||
}
|
||||
foreach (DesktopButtonsView *view, m_desktopButtonsViews) {
|
||||
|
@ -487,7 +492,6 @@ void DesktopGridEffect::windowInputMouseEvent(QEvent* e)
|
|||
if (!wasWindowMove) { // Activate on move
|
||||
if (isUsingPresentWindows()) {
|
||||
foreach (const int i, desktopList(windowMove)) {
|
||||
const int sourceDesktop = windowMove->isOnAllDesktops() ? d : windowMove->desktop();
|
||||
WindowMotionManager& manager = m_managers[(i)*(effects->numScreens()) + windowMove->screen()];
|
||||
if ((i + 1) == sourceDesktop) {
|
||||
const QRectF transformedGeo = manager.transformedGeometry(windowMove);
|
||||
|
@ -513,9 +517,18 @@ void DesktopGridEffect::windowInputMouseEvent(QEvent* e)
|
|||
effects->moveWindow(windowMove, unscalePos(me->pos(), NULL) + windowMoveDiff, true, 1.0 / scale[screen]);
|
||||
}
|
||||
if (wasWindowMove) {
|
||||
effects->defineCursor(Qt::ClosedHandCursor);
|
||||
if (!effects->waylandDisplay() || (me->modifiers() & Qt::ControlModifier)) {
|
||||
wasWindowCopy = true;
|
||||
effects->defineCursor(Qt::DragCopyCursor);
|
||||
} else {
|
||||
wasWindowCopy = false;
|
||||
effects->defineCursor(Qt::ClosedHandCursor);
|
||||
}
|
||||
if (d != highlightedDesktop) {
|
||||
effects->windowToDesktop(windowMove, d); // Not true all desktop move
|
||||
if (highlightedDesktop != sourceDesktop || !wasWindowCopy) {
|
||||
effects->removeWindowFromDesktop(windowMove, highlightedDesktop);
|
||||
}
|
||||
const int screen = effects->screenNumber(me->pos());
|
||||
if (screen != windowMove->screen())
|
||||
effects->windowToScreen(windowMove, screen);
|
||||
|
@ -549,6 +562,8 @@ void DesktopGridEffect::windowInputMouseEvent(QEvent* e)
|
|||
continue;
|
||||
foreach (EffectWindow *w, stack[i]) {
|
||||
effects->windowToDesktop(w, desks[i+1]);
|
||||
effects->removeWindowFromDesktop(w, desks[i]);
|
||||
|
||||
if (isUsingPresentWindows()) {
|
||||
m_managers[(desks[i]-1)*(effects->numScreens()) + w->screen()].unmanage(w);
|
||||
m_managers[(desks[i+1]-1)*(effects->numScreens()) + w->screen()].manage(w);
|
||||
|
@ -572,12 +587,15 @@ void DesktopGridEffect::windowInputMouseEvent(QEvent* e)
|
|||
if (me->buttons() == Qt::LeftButton) {
|
||||
isValidMove = true;
|
||||
dragStartPos = me->pos();
|
||||
bool isDesktop = (me->modifiers() & Qt::ControlModifier);
|
||||
sourceDesktop = posToDesktop(me->pos());
|
||||
bool isDesktop = (me->modifiers() & Qt::ShiftModifier);
|
||||
EffectWindow* w = isDesktop ? NULL : windowAt(me->pos());
|
||||
if (w != NULL)
|
||||
isDesktop = w->isDesktop();
|
||||
if (isDesktop)
|
||||
m_originalMovingDesktop = posToDesktop(me->pos());
|
||||
else
|
||||
m_originalMovingDesktop = 0;
|
||||
if (w != NULL && !w->isDesktop() && (w->isMovable() || w->isMovableAcrossScreens() || isUsingPresentWindows())) {
|
||||
// Prepare it for moving
|
||||
windowMoveDiff = w->pos() - unscalePos(me->pos(), NULL);
|
||||
|
@ -590,12 +608,10 @@ void DesktopGridEffect::windowInputMouseEvent(QEvent* e)
|
|||
w = nullptr;
|
||||
}
|
||||
if (w != NULL) {
|
||||
int desktop = 0;
|
||||
const int desktop = posToDesktop(me->pos());
|
||||
if (w->isOnAllDesktops()) {
|
||||
desktop = posToDesktop(me->pos());
|
||||
effects->windowToDesktop(w, desktop);
|
||||
} else {
|
||||
desktop = w->desktop();
|
||||
effects->windowToDesktop(w, NET::OnAllDesktops);
|
||||
}
|
||||
const bool isOnAllDesktops = w->isOnAllDesktops();
|
||||
|
@ -630,7 +646,7 @@ void DesktopGridEffect::windowInputMouseEvent(QEvent* e)
|
|||
}
|
||||
if (windowMove) {
|
||||
if (wasWindowMove && isUsingPresentWindows()) {
|
||||
const int targetDesktop = windowMove->isOnAllDesktops() ? posToDesktop(cursorPos()) : windowMove->desktop();
|
||||
const int targetDesktop = posToDesktop(cursorPos());
|
||||
foreach (const int i, desktopList(windowMove)) {
|
||||
WindowMotionManager& manager = m_managers[(i)*(effects->numScreens()) + windowMove->screen()];
|
||||
manager.manage(windowMove);
|
||||
|
@ -648,6 +664,7 @@ void DesktopGridEffect::windowInputMouseEvent(QEvent* e)
|
|||
windowMove = NULL;
|
||||
}
|
||||
wasWindowMove = false;
|
||||
wasWindowCopy = false;
|
||||
wasDesktopMove = false;
|
||||
}
|
||||
}
|
||||
|
@ -1360,7 +1377,7 @@ void DesktopGridEffect::desktopsRemoved(int old)
|
|||
// and repaint
|
||||
effects->addRepaintFull();
|
||||
}
|
||||
|
||||
//TODO: kill this function? or at least keep a consistent numeration with desktops starting from 1
|
||||
QVector<int> DesktopGridEffect::desktopList(const EffectWindow *w) const
|
||||
{
|
||||
if (w->isOnAllDesktops()) {
|
||||
|
@ -1373,16 +1390,13 @@ QVector<int> DesktopGridEffect::desktopList(const EffectWindow *w) const
|
|||
return allDesktops;
|
||||
}
|
||||
|
||||
if (w->desktop() > effects->numberOfDesktops() || w->desktop() < 1) { // sic! desktops are [1,n]
|
||||
static QVector<int> emptyVector;
|
||||
emptyVector.resize(0);
|
||||
return emptyVector;
|
||||
QVector<int> desks;
|
||||
desks.resize(w->desktops().count());
|
||||
int i = 0;
|
||||
for (const int desk : w->desktops()) {
|
||||
desks[i++] = desk-1;
|
||||
}
|
||||
|
||||
static QVector<int> singleDesktop;
|
||||
singleDesktop.resize(1);
|
||||
singleDesktop[0] = w->desktop() - 1;
|
||||
return singleDesktop;
|
||||
return desks;
|
||||
}
|
||||
|
||||
bool DesktopGridEffect::isActive() const
|
||||
|
|
|
@ -151,9 +151,10 @@ private:
|
|||
QTimeLine timeline;
|
||||
int paintingDesktop;
|
||||
int highlightedDesktop;
|
||||
int sourceDesktop;
|
||||
int m_originalMovingDesktop;
|
||||
bool keyboardGrab;
|
||||
bool wasWindowMove, wasDesktopMove, isValidMove;
|
||||
bool wasWindowMove, wasWindowCopy, wasDesktopMove, isValidMove;
|
||||
EffectWindow* windowMove;
|
||||
QPoint windowMoveDiff;
|
||||
QPoint dragStartPos;
|
||||
|
|
|
@ -762,6 +762,13 @@ bool EffectsHandler::isOpenGLCompositing() const
|
|||
return compositing_type & OpenGLCompositing;
|
||||
}
|
||||
|
||||
void EffectsHandler::removeWindowFromDesktop(KWin::EffectWindow* w, int desktop)
|
||||
{
|
||||
if (w->parent() && !w->isDesktop() && !w->isDock()) {
|
||||
QMetaObject::invokeMethod(w->parent(), "unSetDesktop", Q_ARG(int, desktop));
|
||||
}
|
||||
}
|
||||
|
||||
EffectsHandler* effects = nullptr;
|
||||
|
||||
|
||||
|
@ -826,7 +833,9 @@ WINDOW_HELPER(int, screen, "screen")
|
|||
WINDOW_HELPER(QRect, geometry, "geometry")
|
||||
WINDOW_HELPER(QRect, expandedGeometry, "visibleRect")
|
||||
WINDOW_HELPER(QRect, rect, "rect")
|
||||
#ifndef KWIN_NO_DEPRECATED
|
||||
WINDOW_HELPER(int, desktop, "desktop")
|
||||
#endif
|
||||
WINDOW_HELPER(bool, isDesktop, "desktopWindow")
|
||||
WINDOW_HELPER(bool, isDock, "dock")
|
||||
WINDOW_HELPER(bool, isToolbar, "toolbar")
|
||||
|
@ -849,6 +858,11 @@ WINDOW_HELPER(QStringList, activities, "activities")
|
|||
WINDOW_HELPER(bool, skipsCloseAnimation, "skipsCloseAnimation")
|
||||
WINDOW_HELPER(KWayland::Server::SurfaceInterface *, surface, "surface")
|
||||
|
||||
QList<int> EffectWindow::desktops() const
|
||||
{
|
||||
return parent()->property("x11DesktopIds").value<QList<int> >();
|
||||
}
|
||||
|
||||
QString EffectWindow::windowClass() const
|
||||
{
|
||||
return parent()->property("resourceName").toString() + QLatin1Char(' ') + parent()->property("resourceClass").toString();
|
||||
|
@ -974,12 +988,13 @@ bool EffectWindow::isOnCurrentDesktop() const
|
|||
|
||||
bool EffectWindow::isOnDesktop(int d) const
|
||||
{
|
||||
return desktop() == d || isOnAllDesktops();
|
||||
const QList<int> ds = desktops();
|
||||
return ds.isEmpty() || ds.contains(d);
|
||||
}
|
||||
|
||||
bool EffectWindow::isOnAllDesktops() const
|
||||
{
|
||||
return desktop() == NET::OnAllDesktops;
|
||||
return desktops().isEmpty();
|
||||
}
|
||||
|
||||
bool EffectWindow::hasDecoration() const
|
||||
|
|
|
@ -944,6 +944,10 @@ public:
|
|||
virtual KWin::EffectWindow* activeWindow() const = 0 ;
|
||||
Q_SCRIPTABLE virtual void moveWindow(KWin::EffectWindow* w, const QPoint& pos, bool snap = false, double snapAdjust = 1.0) = 0;
|
||||
Q_SCRIPTABLE virtual void windowToDesktop(KWin::EffectWindow* w, int desktop) = 0;
|
||||
/**
|
||||
* Removes a window from a desktop on wayland, no-op on X11
|
||||
*/
|
||||
Q_SCRIPTABLE void removeWindowFromDesktop(KWin::EffectWindow* w, int desktop);
|
||||
Q_SCRIPTABLE virtual void windowToScreen(KWin::EffectWindow* w, int screen) = 0;
|
||||
virtual void setShowingDesktop(bool showing) = 0;
|
||||
|
||||
|
@ -2071,7 +2075,23 @@ public:
|
|||
Q_SCRIPTABLE bool isOnDesktop(int d) const;
|
||||
bool isOnCurrentDesktop() const;
|
||||
bool isOnAllDesktops() const;
|
||||
int desktop() const; // prefer isOnXXX()
|
||||
/**
|
||||
* The desktop this window is in. This mkaes sense only on X11
|
||||
* where desktops are mutually exclusive, on Wayland it's the last
|
||||
* desktop the window has been added to.
|
||||
* use desktops() instead.
|
||||
* @see desktops()
|
||||
* @deprecated
|
||||
*/
|
||||
#ifndef KWIN_NO_DEPRECATED
|
||||
int KWIN_DEPRECATED desktop() const; // prefer isOnXXX()
|
||||
#endif
|
||||
/**
|
||||
* All the desktops by number that the window is in. On X11 this list will always have
|
||||
* a length of 1, on Wayland can be any subset.
|
||||
* If the list is empty it means the window is on all desktops
|
||||
*/
|
||||
QList<int> desktops() const;
|
||||
|
||||
int x() const;
|
||||
int y() const;
|
||||
|
|
50
org.kde.KWin.VirtualDesktopManager.xml
Normal file
50
org.kde.KWin.VirtualDesktopManager.xml
Normal file
|
@ -0,0 +1,50 @@
|
|||
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
||||
<node>
|
||||
<interface name="org.kde.KWin.VirtualDesktopManager">
|
||||
<property name="count" type="u" access="read"/>
|
||||
<property name="current" type="s" access="readwrite"/>
|
||||
<property name="rows" type="u" access="readwrite"/>
|
||||
<property name="navigationWrappingAround" type="b" access="readwrite"/>
|
||||
<property name="desktops" type="a(iss)" access="read">
|
||||
<annotation name="org.qtproject.QtDBus.QtTypeName" value="KWin::DBusDesktopDataVector"/>
|
||||
</property>
|
||||
|
||||
<signal name="countChanged">
|
||||
<arg name="count" type="u" direction="out"/>
|
||||
</signal>
|
||||
<signal name="rowsChanged">
|
||||
<arg name="rows" type="u" direction="out"/>
|
||||
</signal>
|
||||
<signal name="currentChanged">
|
||||
<arg name="id" type="s" direction="out"/>
|
||||
</signal>
|
||||
<signal name="navigationWrappingAroundChanged">
|
||||
<arg name="navigationWrappingAround" type="b" direction="out"/>
|
||||
</signal>
|
||||
<signal name="desktopDataChanged">
|
||||
<arg name="id" type="s" direction="out"/>
|
||||
<annotation name="org.qtproject.QtDBus.QtTypeName.Out1" value="KWin::DBusDesktopDataStruct"/>
|
||||
<arg name="desktopData" type="(iss)" direction="out"/>
|
||||
</signal>
|
||||
<signal name="desktopCreated">
|
||||
<arg name="id" type="s" direction="out"/>
|
||||
<annotation name="org.qtproject.QtDBus.QtTypeName.Out1" value="KWin::DBusDesktopDataStruct"/>
|
||||
<arg name="desktopData" type="(iss)" direction="out"/>
|
||||
</signal>
|
||||
<signal name="desktopRemoved">
|
||||
<arg name="id" type="s" direction="out"/>
|
||||
</signal>
|
||||
|
||||
<method name="createDesktop">
|
||||
<arg name="position" type="u" direction="in"/>
|
||||
<arg name="name" type="s" direction="in"/>
|
||||
</method>
|
||||
<method name="setDesktopName">
|
||||
<arg name="id" type="s" direction="in"/>
|
||||
<arg name="name" type="s" direction="in"/>
|
||||
</method>
|
||||
<method name="removeDesktop">
|
||||
<arg name="id" type="s" direction="in"/>
|
||||
</method>
|
||||
</interface>
|
||||
</node>
|
14
toplevel.h
14
toplevel.h
|
@ -290,6 +290,7 @@ public:
|
|||
* isOnDesktop() instead.
|
||||
*/
|
||||
virtual int desktop() const = 0;
|
||||
virtual QList<VirtualDesktop *> desktops() const = 0;
|
||||
virtual QStringList activities() const = 0;
|
||||
bool isOnDesktop(int d) const;
|
||||
bool isOnActivity(const QString &activity) const;
|
||||
|
@ -790,7 +791,12 @@ const EffectWindowImpl* Toplevel::effectWindow() const
|
|||
|
||||
inline bool Toplevel::isOnAllDesktops() const
|
||||
{
|
||||
return desktop() == NET::OnAllDesktops;
|
||||
return kwinApp()->operationMode() == Application::OperationModeWaylandOnly ||
|
||||
kwinApp()->operationMode() == Application::OperationModeXwayland
|
||||
//Wayland
|
||||
? desktops().isEmpty()
|
||||
//X11
|
||||
: desktop() == NET::OnAllDesktops;
|
||||
}
|
||||
|
||||
inline bool Toplevel::isOnAllActivities() const
|
||||
|
@ -800,7 +806,11 @@ inline bool Toplevel::isOnAllActivities() const
|
|||
|
||||
inline bool Toplevel::isOnDesktop(int d) const
|
||||
{
|
||||
return desktop() == d || /*desk == 0 ||*/ isOnAllDesktops();
|
||||
return (kwinApp()->operationMode() == Application::OperationModeWaylandOnly ||
|
||||
kwinApp()->operationMode() == Application::OperationModeXwayland
|
||||
? desktops().contains(VirtualDesktopManager::self()->desktopForX11Id(d))
|
||||
: desktop() == d
|
||||
) || isOnAllDesktops();
|
||||
}
|
||||
|
||||
inline bool Toplevel::isOnActivity(const QString &activity) const
|
||||
|
|
|
@ -123,6 +123,11 @@ QStringList Unmanaged::activities() const
|
|||
return QStringList();
|
||||
}
|
||||
|
||||
QList<VirtualDesktop *> Unmanaged::desktops() const
|
||||
{
|
||||
return QList<VirtualDesktop *>();
|
||||
}
|
||||
|
||||
QPoint Unmanaged::clientPos() const
|
||||
{
|
||||
return QPoint(0, 0); // unmanaged windows don't have decorations
|
||||
|
|
|
@ -39,6 +39,7 @@ public:
|
|||
static void deleteUnmanaged(Unmanaged* c);
|
||||
virtual int desktop() const;
|
||||
virtual QStringList activities() const;
|
||||
virtual QList<VirtualDesktop *> desktops() const override;
|
||||
virtual QPoint clientPos() const;
|
||||
virtual QSize clientSize() const;
|
||||
virtual QRect transparentRect() const;
|
||||
|
|
120
useractions.cpp
120
useractions.cpp
|
@ -402,6 +402,7 @@ void UserActionsMenu::discard()
|
|||
delete m_menu;
|
||||
m_menu = NULL;
|
||||
m_desktopMenu = NULL;
|
||||
m_multipleDesktopsMenu = nullptr;
|
||||
m_screenMenu = NULL;
|
||||
m_activityMenu = NULL;
|
||||
m_switchToTabMenu = NULL;
|
||||
|
@ -417,6 +418,8 @@ void UserActionsMenu::menuAboutToShow()
|
|||
if (VirtualDesktopManager::self()->count() == 1) {
|
||||
delete m_desktopMenu;
|
||||
m_desktopMenu = 0;
|
||||
delete m_multipleDesktopsMenu;
|
||||
m_multipleDesktopsMenu = nullptr;
|
||||
} else {
|
||||
initDesktopPopup();
|
||||
}
|
||||
|
@ -604,17 +607,34 @@ void UserActionsMenu::initTabbingPopups()
|
|||
|
||||
void UserActionsMenu::initDesktopPopup()
|
||||
{
|
||||
if (m_desktopMenu)
|
||||
return;
|
||||
if (kwinApp()->operationMode() == Application::OperationModeWaylandOnly ||
|
||||
kwinApp()->operationMode() == Application::OperationModeXwayland) {
|
||||
if (m_multipleDesktopsMenu) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_desktopMenu = new QMenu(m_menu);
|
||||
connect(m_desktopMenu, &QMenu::triggered, this, &UserActionsMenu::slotSendToDesktop);
|
||||
connect(m_desktopMenu, &QMenu::aboutToShow, this, &UserActionsMenu::desktopPopupAboutToShow);
|
||||
m_multipleDesktopsMenu = new QMenu(m_menu);
|
||||
connect(m_multipleDesktopsMenu, &QMenu::triggered, this, &UserActionsMenu::slotToggleOnVirtualDesktop);
|
||||
connect(m_multipleDesktopsMenu, &QMenu::aboutToShow, this, &UserActionsMenu::multipleDesktopsPopupAboutToShow);
|
||||
|
||||
QAction *action = m_desktopMenu->menuAction();
|
||||
// set it as the first item
|
||||
m_menu->insertAction(m_minimizeOperation, action);
|
||||
action->setText(i18n("Move To &Desktop"));
|
||||
QAction *action = m_multipleDesktopsMenu->menuAction();
|
||||
// set it as the first item
|
||||
m_menu->insertAction(m_minimizeOperation, action);
|
||||
action->setText(i18n("&Desktops"));
|
||||
|
||||
} else {
|
||||
if (m_desktopMenu)
|
||||
return;
|
||||
|
||||
m_desktopMenu = new QMenu(m_menu);
|
||||
connect(m_desktopMenu, &QMenu::triggered, this, &UserActionsMenu::slotSendToDesktop);
|
||||
connect(m_desktopMenu, &QMenu::aboutToShow, this, &UserActionsMenu::desktopPopupAboutToShow);
|
||||
|
||||
QAction *action = m_desktopMenu->menuAction();
|
||||
// set it as the first item
|
||||
m_menu->insertAction(m_minimizeOperation, action);
|
||||
action->setText(i18n("Move To &Desktop"));
|
||||
}
|
||||
}
|
||||
|
||||
void UserActionsMenu::initScreenPopup()
|
||||
|
@ -667,6 +687,7 @@ void UserActionsMenu::desktopPopupAboutToShow()
|
|||
m_desktopMenu->addSeparator();
|
||||
|
||||
const uint BASE = 10;
|
||||
|
||||
for (uint i = 1; i <= vds->count(); ++i) {
|
||||
QString basic_name(QStringLiteral("%1 %2"));
|
||||
if (i < BASE) {
|
||||
|
@ -690,6 +711,58 @@ void UserActionsMenu::desktopPopupAboutToShow()
|
|||
action->setEnabled(false);
|
||||
}
|
||||
|
||||
void UserActionsMenu::multipleDesktopsPopupAboutToShow()
|
||||
{
|
||||
if (!m_multipleDesktopsMenu)
|
||||
return;
|
||||
const VirtualDesktopManager *vds = VirtualDesktopManager::self();
|
||||
|
||||
m_multipleDesktopsMenu->clear();
|
||||
m_multipleDesktopsMenu->setPalette(m_client.data()->palette());
|
||||
QAction *action = m_multipleDesktopsMenu->addAction(i18n("&All Desktops"));
|
||||
action->setData(0);
|
||||
action->setCheckable(true);
|
||||
QActionGroup *allDesktopsGroup = new QActionGroup(m_multipleDesktopsMenu);
|
||||
allDesktopsGroup->addAction(action);
|
||||
|
||||
if (!m_client.isNull() && m_client.data()->isOnAllDesktops()) {
|
||||
action->setChecked(true);
|
||||
}
|
||||
m_multipleDesktopsMenu->addSeparator();
|
||||
|
||||
|
||||
const uint BASE = 10;
|
||||
|
||||
for (uint i = 1; i <= vds->count(); ++i) {
|
||||
QString basic_name(QStringLiteral("%1 %2"));
|
||||
if (i < BASE) {
|
||||
basic_name.prepend(QLatin1Char('&'));
|
||||
}
|
||||
QWidgetAction *action = new QWidgetAction(m_multipleDesktopsMenu);
|
||||
QCheckBox *box = new QCheckBox(basic_name.arg(i).arg(vds->name(i).replace(QLatin1Char('&'), QStringLiteral("&&"))), m_multipleDesktopsMenu);
|
||||
action->setDefaultWidget(box);
|
||||
|
||||
box->setBackgroundRole(m_multipleDesktopsMenu->backgroundRole());
|
||||
box->setForegroundRole(m_multipleDesktopsMenu->foregroundRole());
|
||||
box->setPalette(m_multipleDesktopsMenu->palette());
|
||||
connect(box, &QCheckBox::clicked, action, &QAction::triggered);
|
||||
m_multipleDesktopsMenu->addAction(action);
|
||||
action->setData(i);
|
||||
|
||||
if (!m_client.isNull() &&
|
||||
!m_client.data()->isOnAllDesktops() && m_client.data()->isOnDesktop(i)) {
|
||||
box->setChecked(true);
|
||||
}
|
||||
}
|
||||
|
||||
m_multipleDesktopsMenu->addSeparator();
|
||||
action = m_multipleDesktopsMenu->addAction(i18nc("Create a new desktop and move there the window", "&New Desktop"));
|
||||
action->setData(vds->count() + 1);
|
||||
|
||||
if (vds->count() >= vds->maximum())
|
||||
action->setEnabled(false);
|
||||
}
|
||||
|
||||
void UserActionsMenu::screenPopupAboutToShow()
|
||||
{
|
||||
if (!m_screenMenu) {
|
||||
|
@ -816,6 +889,35 @@ void UserActionsMenu::slotSendToDesktop(QAction *action)
|
|||
ws->sendClientToDesktop(m_client.data(), desk, false);
|
||||
}
|
||||
|
||||
void UserActionsMenu::slotToggleOnVirtualDesktop(QAction *action)
|
||||
{
|
||||
bool ok = false;
|
||||
uint desk = action->data().toUInt(&ok);
|
||||
if (!ok) {
|
||||
return;
|
||||
}
|
||||
if (m_client.isNull()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Workspace *ws = Workspace::self();
|
||||
VirtualDesktopManager *vds = VirtualDesktopManager::self();
|
||||
if (desk == 0) {
|
||||
// the 'on_all_desktops' menu entry
|
||||
m_client.data()->setOnAllDesktops(!m_client.data()->isOnAllDesktops());
|
||||
return;
|
||||
} else if (desk > vds->count()) {
|
||||
vds->setCount(desk);
|
||||
}
|
||||
|
||||
VirtualDesktop *virtualDesktop = VirtualDesktopManager::self()->desktopForX11Id(desk);
|
||||
if (m_client.data()->desktops().contains(virtualDesktop)) {
|
||||
m_client.data()->unSetDesktop(desk);
|
||||
} else {
|
||||
ws->sendClientToDesktop(m_client.data(), desk, false);
|
||||
}
|
||||
}
|
||||
|
||||
void UserActionsMenu::slotSendToScreen(QAction *action)
|
||||
{
|
||||
const int screen = action->data().toInt();
|
||||
|
|
|
@ -144,6 +144,11 @@ private Q_SLOTS:
|
|||
* the Client.
|
||||
**/
|
||||
void desktopPopupAboutToShow();
|
||||
/**
|
||||
* Adjusts the multipleDesktopsMenu popup to the current values and the location of
|
||||
* the Client, Wayland only.
|
||||
**/
|
||||
void multipleDesktopsPopupAboutToShow();
|
||||
/**
|
||||
* Adjusts the screen popup to the current values and the location of
|
||||
* the Client.
|
||||
|
@ -160,6 +165,12 @@ private Q_SLOTS:
|
|||
* @param action Invoked Action containing the Desktop as data element
|
||||
**/
|
||||
void slotSendToDesktop(QAction *action);
|
||||
/**
|
||||
* Toggle whether the Client is on a desktop (Wayland only)
|
||||
*
|
||||
* @param action Invoked Action containing the Desktop as data element
|
||||
**/
|
||||
void slotToggleOnVirtualDesktop(QAction *action);
|
||||
/**
|
||||
* Sends the Client to screen \a screen
|
||||
*
|
||||
|
@ -217,6 +228,10 @@ private:
|
|||
* The move to desktop sub menu.
|
||||
**/
|
||||
QMenu* m_desktopMenu;
|
||||
/**
|
||||
* The move to desktop sub menu, with the Wayland protocol.
|
||||
**/
|
||||
QMenu* m_multipleDesktopsMenu;
|
||||
/**
|
||||
* The move to screen sub menu.
|
||||
**/
|
||||
|
|
|
@ -25,11 +25,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include <KGlobalAccel>
|
||||
#include <KLocalizedString>
|
||||
#include <NETWM>
|
||||
|
||||
#include <KWayland/Server/plasmavirtualdesktop_interface.h>
|
||||
// Qt
|
||||
#include <QAction>
|
||||
#include <QUuid>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <QDebug>
|
||||
namespace KWin {
|
||||
|
||||
extern int screen_number;
|
||||
|
@ -44,6 +47,81 @@ VirtualDesktop::~VirtualDesktop()
|
|||
emit aboutToBeDestroyed();
|
||||
}
|
||||
|
||||
void VirtualDesktopManager::setVirtualDesktopManagement(KWayland::Server::PlasmaVirtualDesktopManagementInterface *management)
|
||||
{
|
||||
using namespace KWayland::Server;
|
||||
Q_ASSERT(!m_virtualDesktopManagement);
|
||||
m_virtualDesktopManagement = management;
|
||||
|
||||
connect(this, &VirtualDesktopManager::desktopCreated, this,
|
||||
[this](VirtualDesktop *desktop) {
|
||||
using namespace KWayland::Server;
|
||||
PlasmaVirtualDesktopInterface *pvd = m_virtualDesktopManagement->createDesktop(desktop->id(), desktop->x11DesktopNumber() - 1);
|
||||
pvd->setName(desktop->name());
|
||||
pvd->sendDone();
|
||||
connect(desktop, &VirtualDesktop::nameChanged, this,
|
||||
[this, desktop, pvd]() {
|
||||
pvd->setName(desktop->name());
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
//handle removed: from VirtualDesktopManager to the wayland interface
|
||||
connect(this, &VirtualDesktopManager::desktopRemoved, this,
|
||||
[this](VirtualDesktop *desktop) {
|
||||
m_virtualDesktopManagement->removeDesktop(desktop->id());
|
||||
}
|
||||
);
|
||||
|
||||
//create a new desktop when the client asks to
|
||||
connect (m_virtualDesktopManagement, &PlasmaVirtualDesktopManagementInterface::desktopCreateRequested, this,
|
||||
[this](const QString &name, quint32 position) {
|
||||
VirtualDesktop *vd = createVirtualDesktop(position);
|
||||
if (vd) {
|
||||
vd->setName(name);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
//remove when the client asks to
|
||||
connect (m_virtualDesktopManagement, &PlasmaVirtualDesktopManagementInterface::desktopRemoveRequested, this,
|
||||
[this](const QString &id) {
|
||||
//here there can be some nice kauthorized check?
|
||||
//remove only from VirtualDesktopManager, the other connections will remove it from m_virtualDesktopManagement as well
|
||||
removeVirtualDesktop(id.toUtf8());
|
||||
}
|
||||
);
|
||||
|
||||
for (quint32 i = 1; i <= count(); ++i) {
|
||||
VirtualDesktop *internalDesktop = desktopForX11Id(i);
|
||||
PlasmaVirtualDesktopInterface *desktop = m_virtualDesktopManagement->createDesktop(internalDesktop->id());
|
||||
|
||||
desktop->setName(desktop->name());
|
||||
desktop->sendDone();
|
||||
|
||||
connect(desktop, &PlasmaVirtualDesktopInterface::activateRequested, this,
|
||||
[this, desktop] () {
|
||||
setCurrent(desktopForId(desktop->id().toUtf8()));
|
||||
}
|
||||
);
|
||||
}
|
||||
//Now we are sure all ids are there
|
||||
save();
|
||||
|
||||
connect(this, &VirtualDesktopManager::currentChanged, this,
|
||||
[this]() {
|
||||
for (auto *deskInt : m_virtualDesktopManagement->desktops()) {
|
||||
if (deskInt->id() == currentDesktop()->id()) {
|
||||
deskInt->setActive(true);
|
||||
} else {
|
||||
deskInt->setActive(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
void VirtualDesktop::setId(const QByteArray &id)
|
||||
{
|
||||
Q_ASSERT(m_id.isEmpty());
|
||||
|
@ -52,8 +130,16 @@ void VirtualDesktop::setId(const QByteArray &id)
|
|||
|
||||
void VirtualDesktop::setX11DesktopNumber(uint number)
|
||||
{
|
||||
Q_ASSERT(m_x11DesktopNumber == 0);
|
||||
//x11DesktopNumber can be changed now
|
||||
if (static_cast<uint>(m_x11DesktopNumber) == number) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_x11DesktopNumber = number;
|
||||
|
||||
if (m_x11DesktopNumber != 0) {
|
||||
emit x11DesktopNumberChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void VirtualDesktop::setName(const QString &name)
|
||||
|
@ -68,7 +154,7 @@ void VirtualDesktop::setName(const QString &name)
|
|||
VirtualDesktopGrid::VirtualDesktopGrid()
|
||||
: m_size(1, 2) // Default to tow rows
|
||||
, m_grid(QVector<QVector<VirtualDesktop*>>{QVector<VirtualDesktop*>{}, QVector<VirtualDesktop*>{}})
|
||||
{
|
||||
{
|
||||
}
|
||||
|
||||
VirtualDesktopGrid::~VirtualDesktopGrid() = default;
|
||||
|
@ -325,6 +411,99 @@ VirtualDesktop *VirtualDesktopManager::desktopForX11Id(uint id) const
|
|||
return m_desktops.at(id - 1);
|
||||
}
|
||||
|
||||
VirtualDesktop *VirtualDesktopManager::desktopForId(const QByteArray &id) const
|
||||
{
|
||||
auto desk = std::find_if(
|
||||
m_desktops.constBegin(),
|
||||
m_desktops.constEnd(),
|
||||
[id] (const VirtualDesktop *desk ) {
|
||||
return desk->id() == id;
|
||||
}
|
||||
);
|
||||
|
||||
if (desk != m_desktops.constEnd()) {
|
||||
return *desk;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
VirtualDesktop *VirtualDesktopManager::createVirtualDesktop(uint number, const QString &name)
|
||||
{
|
||||
//too many, can't insert new ones
|
||||
if ((uint)m_desktops.count() == VirtualDesktopManager::maximum()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const uint actualNumber = qBound<uint>(0, number, VirtualDesktopManager::maximum());
|
||||
auto *vd = new VirtualDesktop(this);
|
||||
vd->setX11DesktopNumber(actualNumber);
|
||||
//TODO: depend on Qt 5.11, use toString(QUuid::WithoutBraces)
|
||||
vd->setId(QUuid::createUuid().toString().toUtf8());
|
||||
vd->setName(name);
|
||||
if (m_rootInfo) {
|
||||
connect(vd, &VirtualDesktop::nameChanged, this,
|
||||
[this, vd]() {
|
||||
if (m_rootInfo) {
|
||||
m_rootInfo->setDesktopName(vd->x11DesktopNumber(), vd->name().toUtf8().data());
|
||||
}
|
||||
}
|
||||
);
|
||||
m_rootInfo->setDesktopName(vd->x11DesktopNumber(), vd->name().toUtf8().data());
|
||||
}
|
||||
|
||||
//update the id of displaced desktops
|
||||
for (uint i = actualNumber; i < (uint)m_desktops.count(); ++i) {
|
||||
m_desktops[i]->setX11DesktopNumber(i + 1);
|
||||
if (m_rootInfo) {
|
||||
m_rootInfo->setDesktopName(i + 1, m_desktops[i]->name().toUtf8().data());
|
||||
}
|
||||
}
|
||||
|
||||
m_desktops.insert(actualNumber - 1, vd);
|
||||
save();
|
||||
|
||||
updateRootInfo();
|
||||
emit desktopCreated(vd);
|
||||
emit countChanged(m_desktops.count()-1, m_desktops.count());
|
||||
return vd;
|
||||
}
|
||||
|
||||
void VirtualDesktopManager::removeVirtualDesktop(const QByteArray &id)
|
||||
{
|
||||
//don't end up without any desktop
|
||||
if (m_desktops.count() == 1) {
|
||||
return;
|
||||
}
|
||||
auto desktop = desktopForId(id);
|
||||
if (!desktop) {
|
||||
return;
|
||||
}
|
||||
|
||||
const uint oldCurrent = m_current->x11DesktopNumber();
|
||||
const uint i = desktop->x11DesktopNumber() - 1;
|
||||
m_desktops.remove(i);
|
||||
|
||||
for (uint j = i; j < (uint)m_desktops.count(); ++j) {
|
||||
m_desktops[j]->setX11DesktopNumber(j + 1);
|
||||
if (m_rootInfo) {
|
||||
m_rootInfo->setDesktopName(j + 1, m_desktops[j]->name().toUtf8().data());
|
||||
}
|
||||
}
|
||||
|
||||
const uint newCurrent = qMin(oldCurrent, (uint)m_desktops.count());
|
||||
m_current = m_desktops.at(newCurrent - 1);
|
||||
if (oldCurrent != newCurrent) {
|
||||
emit currentChanged(oldCurrent, newCurrent);
|
||||
}
|
||||
|
||||
updateRootInfo();
|
||||
emit desktopRemoved(desktop);
|
||||
emit countChanged(m_desktops.count()+1, m_desktops.count());
|
||||
|
||||
desktop->deleteLater();
|
||||
}
|
||||
|
||||
uint VirtualDesktopManager::current() const
|
||||
{
|
||||
return m_current ? m_current->x11DesktopNumber() : 0;
|
||||
|
@ -364,33 +543,79 @@ void VirtualDesktopManager::setCount(uint count)
|
|||
// nothing to change
|
||||
return;
|
||||
}
|
||||
QList<VirtualDesktop *> newDesktops;
|
||||
const uint oldCount = m_desktops.count();
|
||||
const uint oldCurrent = current();
|
||||
while (uint(m_desktops.count()) > count) {
|
||||
delete m_desktops.takeLast();
|
||||
}
|
||||
while (uint(m_desktops.count()) < count) {
|
||||
auto vd = new VirtualDesktop(this);
|
||||
vd->setX11DesktopNumber(m_desktops.count() + 1);
|
||||
m_desktops << vd;
|
||||
}
|
||||
if (oldCount > count) {
|
||||
handleDesktopsRemoved(oldCount, oldCurrent);
|
||||
//this explicit check makes it more readable
|
||||
if ((uint)m_desktops.count() > count) {
|
||||
const auto desktopsToRemove = m_desktops.mid(count);
|
||||
m_desktops.resize(count);
|
||||
if (m_current) {
|
||||
uint oldCurrent = current();
|
||||
uint newCurrent = qMin(oldCurrent, count);
|
||||
m_current = m_desktops.at(newCurrent - 1);
|
||||
if (oldCurrent != newCurrent) {
|
||||
emit currentChanged(oldCurrent, newCurrent);
|
||||
}
|
||||
}
|
||||
for (auto desktop : desktopsToRemove) {
|
||||
emit desktopRemoved(desktop);
|
||||
desktop->deleteLater();
|
||||
}
|
||||
} else {
|
||||
while (uint(m_desktops.count()) < count) {
|
||||
auto vd = new VirtualDesktop(this);
|
||||
vd->setX11DesktopNumber(m_desktops.count() + 1);
|
||||
if (!m_isLoading) {
|
||||
vd->setId(QUuid::createUuid().toString().toUtf8());
|
||||
}
|
||||
m_desktops << vd;
|
||||
newDesktops << vd;
|
||||
if (m_rootInfo) {
|
||||
connect(vd, &VirtualDesktop::nameChanged, this,
|
||||
[this, vd]() {
|
||||
if (m_rootInfo) {
|
||||
m_rootInfo->setDesktopName(vd->x11DesktopNumber(), vd->name().toUtf8().data());
|
||||
}
|
||||
}
|
||||
);
|
||||
m_rootInfo->setDesktopName(vd->x11DesktopNumber(), vd->name().toUtf8().data());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateRootInfo();
|
||||
|
||||
save();
|
||||
for (auto vd : newDesktops) {
|
||||
emit desktopCreated(vd);
|
||||
}
|
||||
emit countChanged(oldCount, m_desktops.count());
|
||||
}
|
||||
|
||||
void VirtualDesktopManager::handleDesktopsRemoved(uint previousCount, uint previousCurrent)
|
||||
|
||||
uint VirtualDesktopManager::rows() const
|
||||
{
|
||||
if (!m_current) {
|
||||
m_current = m_desktops.last();
|
||||
emit currentChanged(previousCurrent, m_current->x11DesktopNumber());
|
||||
return grid().height();
|
||||
}
|
||||
|
||||
void VirtualDesktopManager::setRows(uint rows)
|
||||
{
|
||||
if (static_cast<uint>(grid().height()) == rows || rows == 0 || rows > count()) {
|
||||
return;
|
||||
}
|
||||
emit desktopsRemoved(previousCount);
|
||||
|
||||
int columns = count() / rows;
|
||||
if (count() % rows > 0) {
|
||||
columns++;
|
||||
}
|
||||
if (m_rootInfo) {
|
||||
m_rootInfo->setDesktopLayout(NET::OrientationHorizontal, columns, rows, NET::DesktopLayoutCornerTopLeft);
|
||||
m_rootInfo->activate();
|
||||
}
|
||||
|
||||
updateLayout();
|
||||
|
||||
//rowsChanged will be emitted by setNETDesktopLayout called by updateLayout
|
||||
}
|
||||
|
||||
void VirtualDesktopManager::updateRootInfo()
|
||||
|
@ -437,6 +662,8 @@ void VirtualDesktopManager::load()
|
|||
if (!m_config) {
|
||||
return;
|
||||
}
|
||||
//FIXME: how to avoid this?
|
||||
m_isLoading = true;
|
||||
QString groupname;
|
||||
if (screen_number == 0) {
|
||||
groupname = QStringLiteral("Desktops");
|
||||
|
@ -446,14 +673,31 @@ void VirtualDesktopManager::load()
|
|||
KConfigGroup group(m_config, groupname);
|
||||
const int n = group.readEntry("Number", 1);
|
||||
setCount(n);
|
||||
if (m_rootInfo) {
|
||||
for (int i = 1; i <= n; i++) {
|
||||
QString s = group.readEntry(QStringLiteral("Name_%1").arg(i), i18n("Desktop %1", i));
|
||||
|
||||
for (int i = 1; i <= n; i++) {
|
||||
QString s = group.readEntry(QStringLiteral("Name_%1").arg(i), i18n("Desktop %1", i));
|
||||
if (m_rootInfo) {
|
||||
m_rootInfo->setDesktopName(i, s.toUtf8().data());
|
||||
// TODO: update desktop focus chain, why?
|
||||
// m_desktopFocusChain.value()[i-1] = i;
|
||||
}
|
||||
m_desktops[i-1]->setName(s.toUtf8().data());
|
||||
|
||||
QString sId = group.readEntry(QStringLiteral("Id_%1").arg(i), QString());
|
||||
|
||||
//load gets called 2 times, see workspace.cpp line 416 and BUG 385260
|
||||
if (m_desktops[i-1]->id().isEmpty()) {
|
||||
if (sId.isEmpty()) {
|
||||
sId = QUuid::createUuid().toString();
|
||||
}
|
||||
m_desktops[i-1]->setId(sId.toUtf8().data());
|
||||
} else {
|
||||
Q_ASSERT(sId.isEmpty() || m_desktops[i-1]->id() == sId.toUtf8().data());
|
||||
}
|
||||
|
||||
// TODO: update desktop focus chain, why?
|
||||
// m_desktopFocusChain.value()[i-1] = i;
|
||||
}
|
||||
|
||||
if (m_rootInfo) {
|
||||
int rows = group.readEntry<int>("Rows", 2);
|
||||
rows = qBound(1, rows, n);
|
||||
// avoid weird cases like having 3 rows for 4 desktops, where the last row is unused
|
||||
|
@ -464,7 +708,9 @@ void VirtualDesktopManager::load()
|
|||
m_rootInfo->setDesktopLayout(NET::OrientationHorizontal, columns, rows, NET::DesktopLayoutCornerTopLeft);
|
||||
m_rootInfo->activate();
|
||||
}
|
||||
|
||||
s_loadingDesktopSettings = false;
|
||||
m_isLoading = false;
|
||||
}
|
||||
|
||||
void VirtualDesktopManager::save()
|
||||
|
@ -502,6 +748,7 @@ void VirtualDesktopManager::save()
|
|||
group.deleteEntry(QStringLiteral("Name_%1").arg(i));
|
||||
}
|
||||
}
|
||||
group.writeEntry(QStringLiteral("Id_%1").arg(i), m_desktops[i-1]->id());
|
||||
}
|
||||
|
||||
// Save to disk
|
||||
|
@ -536,6 +783,7 @@ void VirtualDesktopManager::setNETDesktopLayout(Qt::Orientation orientation, uin
|
|||
m_grid.update(QSize(width, height), orientation, m_desktops);
|
||||
// TODO: why is there no call to m_rootInfo->setDesktopLayout?
|
||||
emit layoutChanged(width, height);
|
||||
emit rowsChanged(height);
|
||||
}
|
||||
|
||||
void VirtualDesktopManager::initShortcuts()
|
||||
|
|
|
@ -27,6 +27,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include <QPoint>
|
||||
#include <QPointer>
|
||||
#include <QSize>
|
||||
|
||||
// KDE includes
|
||||
#include <KConfig>
|
||||
#include <KSharedConfig>
|
||||
|
@ -35,13 +36,21 @@ class KLocalizedString;
|
|||
class NETRootInfo;
|
||||
class QAction;
|
||||
|
||||
namespace KWayland
|
||||
{
|
||||
namespace Server
|
||||
{
|
||||
class PlasmaVirtualDesktopManagementInterface;
|
||||
}
|
||||
}
|
||||
|
||||
namespace KWin {
|
||||
|
||||
class KWIN_EXPORT VirtualDesktop : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QByteArray id READ id CONSTANT)
|
||||
Q_PROPERTY(uint x11DesktopNumber READ x11DesktopNumber CONSTANT)
|
||||
Q_PROPERTY(uint x11DesktopNumber READ x11DesktopNumber NOTIFY x11DesktopNumberChanged)
|
||||
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
|
||||
public:
|
||||
explicit VirtualDesktop(QObject *parent = nullptr);
|
||||
|
@ -64,6 +73,7 @@ public:
|
|||
|
||||
Q_SIGNALS:
|
||||
void nameChanged();
|
||||
void x11DesktopNumberChanged();
|
||||
/**
|
||||
* Emitted just before the desktop gets destroyed.
|
||||
**/
|
||||
|
@ -148,9 +158,13 @@ class KWIN_EXPORT VirtualDesktopManager : public QObject
|
|||
public:
|
||||
virtual ~VirtualDesktopManager();
|
||||
/**
|
||||
* @internal
|
||||
* @internal, for X11 case
|
||||
**/
|
||||
void setRootInfo(NETRootInfo *info);
|
||||
/**
|
||||
* @internal, for Wayland case
|
||||
**/
|
||||
void setVirtualDesktopManagement(KWayland::Server::PlasmaVirtualDesktopManagementInterface *management);
|
||||
/**
|
||||
* @internal
|
||||
**/
|
||||
|
@ -161,6 +175,12 @@ public:
|
|||
* @see countChanged
|
||||
*/
|
||||
uint count() const;
|
||||
/**
|
||||
* @returns the number of rows the layout has.
|
||||
* @see setRows
|
||||
* @see rowsChanged
|
||||
*/
|
||||
uint rows() const;
|
||||
/**
|
||||
* @returns The ID of the current desktop.
|
||||
* @see setCurrent
|
||||
|
@ -263,6 +283,30 @@ public:
|
|||
**/
|
||||
VirtualDesktop *desktopForX11Id(uint id) const;
|
||||
|
||||
/**
|
||||
* @returns The VirtualDesktop for the internal desktop string @p id, if no such VirtualDesktop @c null is returned
|
||||
**/
|
||||
VirtualDesktop *desktopForId(const QByteArray &id) const;
|
||||
|
||||
/**
|
||||
* Create a new virtual desktop at the requested position.
|
||||
* The difference with setCount is that setCount always adds new desktops at the end of the chain. The Id is automatically generated.
|
||||
* @param x11DesktopNumber number for the desktop. The desktop created will have an
|
||||
* x11DesktopNumber guaranteed to be between 1 and numberOfDesktops().
|
||||
* Existing desktops will eventually have their x11DesktopNumber increased.
|
||||
* @param name The name for the new desktop, if empty the default name will be used.
|
||||
* @returns the new VirtualDesktop, nullptr if we reached the maximum number of desktops
|
||||
*/
|
||||
VirtualDesktop *createVirtualDesktop(uint x11DesktopNumber, const QString &name = QString());
|
||||
|
||||
/**
|
||||
* Remove the virtual desktop identified by id, if it exists
|
||||
* difference with setCount is that is possible to remove an arbitrary desktop,
|
||||
* not only the last one.
|
||||
* @param id the string id of the desktop to remove
|
||||
*/
|
||||
void removeVirtualDesktop(const QByteArray &id);
|
||||
|
||||
/**
|
||||
* Updates the net root info for new number of desktops
|
||||
**/
|
||||
|
@ -283,13 +327,14 @@ public Q_SLOTS:
|
|||
* @link countChanged signal.
|
||||
*
|
||||
* In case the @link current desktop is on a desktop higher than the new count, the current desktop
|
||||
* is changed to be the new desktop with highest id. In that situation the signal @link desktopsRemoved
|
||||
* is changed to be the new desktop with highest id. In that situation the signal @link desktopRemoved
|
||||
* is emitted.
|
||||
* @param count The new number of desktops to use
|
||||
* @see count
|
||||
* @see maximum
|
||||
* @see countChanged
|
||||
* @see desktopsRemoved
|
||||
* @see desktopCreated
|
||||
* @see desktopRemoved
|
||||
*/
|
||||
void setCount(uint count);
|
||||
/**
|
||||
|
@ -308,6 +353,10 @@ public Q_SLOTS:
|
|||
* @see moveTo
|
||||
**/
|
||||
bool setCurrent(VirtualDesktop *current);
|
||||
/**
|
||||
* Updates the layout to a new number of rows. The number of columns will be calculated accordingly
|
||||
*/
|
||||
void setRows(uint rows);
|
||||
/**
|
||||
* Called from within setCount() to ensure the desktop layout is still valid.
|
||||
*/
|
||||
|
@ -334,18 +383,27 @@ Q_SIGNALS:
|
|||
* @param newCount The new current number of desktops
|
||||
**/
|
||||
void countChanged(uint previousCount, uint newCount);
|
||||
|
||||
/**
|
||||
* Signal emitted whenever the number of virtual desktops changes in a way
|
||||
* that existing desktops are removed.
|
||||
*
|
||||
* The signal is emitted after the @c count property has been updated but prior
|
||||
* to the @link countChanged signal being emitted.
|
||||
* @param previousCount The number of desktops prior to the change.
|
||||
* @see countChanged
|
||||
* @see setCount
|
||||
* @see count
|
||||
**/
|
||||
void desktopsRemoved(uint previousCount);
|
||||
* Signal when the number of rows in the layout changes
|
||||
* @param new number of rows
|
||||
*/
|
||||
void rowsChanged(uint rows);
|
||||
|
||||
/**
|
||||
* A new desktop has been created
|
||||
* @param desktop the new just crated desktop
|
||||
*/
|
||||
void desktopCreated(KWin::VirtualDesktop *desktop);
|
||||
|
||||
/**
|
||||
* A desktop has been removed and is about to be deleted
|
||||
* @param desktop the desktop that has been removed.
|
||||
* It's guaranteed to stil la valid pointer when the signal arrives,
|
||||
* but it's about to be deleted.
|
||||
*/
|
||||
void desktopRemoved(KWin::VirtualDesktop *desktop);
|
||||
|
||||
/**
|
||||
* Signal emitted whenever the current desktop changes.
|
||||
* @param previousDesktop The virtual desktop changed from
|
||||
|
@ -396,21 +454,6 @@ private Q_SLOTS:
|
|||
void slotDown();
|
||||
|
||||
private:
|
||||
/**
|
||||
* This method is called when the number of desktops is updated in a way that desktops
|
||||
* are removed. At the time when this method is invoked the count property is already
|
||||
* updated but the corresponding signal has not been emitted yet.
|
||||
*
|
||||
* Ensures that in case the current desktop is on one of the removed
|
||||
* desktops the last desktop after the change becomes the new desktop.
|
||||
* Emits the signal @link desktopsRemoved.
|
||||
*
|
||||
* @param previousCount The number of desktops prior to the change.
|
||||
* @param previousCurrent The number of the previously current desktop.
|
||||
* @see setCount
|
||||
* @see desktopsRemoved
|
||||
**/
|
||||
void handleDesktopsRemoved(uint previousCount, uint previousCurrent);
|
||||
/**
|
||||
* Generate a desktop layout from EWMH _NET_DESKTOP_LAYOUT property parameters.
|
||||
*/
|
||||
|
@ -450,7 +493,9 @@ private:
|
|||
VirtualDesktopGrid m_grid;
|
||||
// TODO: QPointer
|
||||
NETRootInfo *m_rootInfo;
|
||||
KWayland::Server::PlasmaVirtualDesktopManagementInterface *m_virtualDesktopManagement = nullptr;
|
||||
KSharedConfig::Ptr m_config;
|
||||
bool m_isLoading = false;
|
||||
|
||||
KWIN_SINGLETON_VARIABLE(VirtualDesktopManager, s_manager)
|
||||
};
|
||||
|
|
70
virtualdesktopsdbustypes.cpp
Normal file
70
virtualdesktopsdbustypes.cpp
Normal file
|
@ -0,0 +1,70 @@
|
|||
/********************************************************************
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
Copyright (C) 2018 Marco Martin <mart@kde.org>
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************/
|
||||
|
||||
// own
|
||||
#include "virtualdesktopsdbustypes.h"
|
||||
|
||||
|
||||
// Marshall the DBusDesktopDataStruct data into a D-BUS argument
|
||||
const QDBusArgument &operator<<(QDBusArgument &argument, const KWin::DBusDesktopDataStruct &desk)
|
||||
{
|
||||
argument.beginStructure();
|
||||
argument << desk.position;
|
||||
argument << desk.id;
|
||||
argument << desk.name;
|
||||
argument.endStructure();
|
||||
return argument;
|
||||
}
|
||||
// Retrieve
|
||||
const QDBusArgument &operator>>(const QDBusArgument &argument, KWin::DBusDesktopDataStruct &desk)
|
||||
{
|
||||
argument.beginStructure();
|
||||
argument >> desk.position;
|
||||
argument >> desk.id;
|
||||
argument >> desk.name;
|
||||
argument.endStructure();
|
||||
return argument;
|
||||
}
|
||||
|
||||
const QDBusArgument &operator<<(QDBusArgument &argument, const KWin::DBusDesktopDataVector &deskVector)
|
||||
{
|
||||
argument.beginArray(qMetaTypeId<KWin::DBusDesktopDataStruct>());
|
||||
for (int i = 0; i < deskVector.size(); ++i) {
|
||||
argument << deskVector[i];
|
||||
}
|
||||
argument.endArray();
|
||||
return argument;
|
||||
}
|
||||
|
||||
const QDBusArgument &operator>>(const QDBusArgument &argument, KWin::DBusDesktopDataVector &deskVector)
|
||||
{
|
||||
argument.beginArray();
|
||||
deskVector.clear();
|
||||
|
||||
while (!argument.atEnd()) {
|
||||
KWin::DBusDesktopDataStruct element;
|
||||
argument >> element;
|
||||
deskVector.append(element);
|
||||
}
|
||||
|
||||
argument.endArray();
|
||||
|
||||
return argument;
|
||||
}
|
47
virtualdesktopsdbustypes.h
Normal file
47
virtualdesktopsdbustypes.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
/********************************************************************
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
Copyright (C) 2018 Marco Martin <mart@kde.org>
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************/
|
||||
|
||||
#ifndef KWIN_VIRTUALDESKTOPS_DBUS_TYPES_H
|
||||
#define KWIN_VIRTUALDESKTOPS_DBUS_TYPES_H
|
||||
|
||||
#include <QtDBus>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
struct DBusDesktopDataStruct {
|
||||
uint position;
|
||||
QString id;
|
||||
QString name;
|
||||
};
|
||||
typedef QVector<DBusDesktopDataStruct> DBusDesktopDataVector;
|
||||
}
|
||||
|
||||
const QDBusArgument &operator<<(QDBusArgument &argument, const KWin::DBusDesktopDataStruct &desk);
|
||||
const QDBusArgument &operator>>(const QDBusArgument &argument, KWin::DBusDesktopDataStruct &desk);
|
||||
|
||||
Q_DECLARE_METATYPE(KWin::DBusDesktopDataStruct)
|
||||
|
||||
const QDBusArgument &operator<<(QDBusArgument &argument, const KWin::DBusDesktopDataVector &deskVector);
|
||||
const QDBusArgument &operator>>(const QDBusArgument &argument, KWin::DBusDesktopDataVector &deskVector);
|
||||
|
||||
Q_DECLARE_METATYPE(KWin::DBusDesktopDataVector)
|
||||
|
||||
#endif // KWIN_VIRTUALDESKTOPS_DBUS_TYPES_H
|
|
@ -43,6 +43,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include <KWayland/Server/idleinhibit_interface.h>
|
||||
#include <KWayland/Server/output_interface.h>
|
||||
#include <KWayland/Server/plasmashell_interface.h>
|
||||
#include <KWayland/Server/plasmavirtualdesktop_interface.h>
|
||||
#include <KWayland/Server/plasmawindowmanagement_interface.h>
|
||||
#include <KWayland/Server/pointerconstraints_interface.h>
|
||||
#include <KWayland/Server/pointergestures_interface.h>
|
||||
|
@ -333,6 +334,12 @@ bool WaylandServer::init(const QByteArray &socketName, InitalizationFlags flags)
|
|||
workspace()->setShowingDesktop(set);
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
m_virtualDesktopManagement = m_display->createPlasmaVirtualDesktopManagement(m_display);
|
||||
m_virtualDesktopManagement->create();
|
||||
m_windowManagement->setPlasmaVirtualDesktopManagementInterface(m_virtualDesktopManagement);
|
||||
|
||||
auto shadowManager = m_display->createShadowManager(m_display);
|
||||
shadowManager->create();
|
||||
|
||||
|
@ -390,6 +397,8 @@ void WaylandServer::shellClientShown(Toplevel *t)
|
|||
|
||||
void WaylandServer::initWorkspace()
|
||||
{
|
||||
VirtualDesktopManager::self()->setVirtualDesktopManagement(m_virtualDesktopManagement);
|
||||
|
||||
if (m_windowManagement) {
|
||||
connect(workspace(), &Workspace::showingDesktopChanged, this,
|
||||
[this] (bool set) {
|
||||
|
|
|
@ -54,6 +54,7 @@ class SurfaceInterface;
|
|||
class OutputInterface;
|
||||
class PlasmaShellInterface;
|
||||
class PlasmaShellSurfaceInterface;
|
||||
class PlasmaVirtualDesktopManagementInterface;
|
||||
class PlasmaWindowManagementInterface;
|
||||
class QtSurfaceExtensionInterface;
|
||||
class OutputManagementInterface;
|
||||
|
@ -99,6 +100,9 @@ public:
|
|||
KWayland::Server::ShellInterface *shell() {
|
||||
return m_shell;
|
||||
}
|
||||
KWayland::Server::PlasmaVirtualDesktopManagementInterface *virtualDesktopManagement() {
|
||||
return m_virtualDesktopManagement;
|
||||
}
|
||||
KWayland::Server::PlasmaWindowManagementInterface *windowManagement() {
|
||||
return m_windowManagement;
|
||||
}
|
||||
|
@ -227,6 +231,7 @@ private:
|
|||
KWayland::Server::XdgShellInterface *m_xdgShell = nullptr;
|
||||
KWayland::Server::PlasmaShellInterface *m_plasmaShell = nullptr;
|
||||
KWayland::Server::PlasmaWindowManagementInterface *m_windowManagement = nullptr;
|
||||
KWayland::Server::PlasmaVirtualDesktopManagementInterface *m_virtualDesktopManagement = nullptr;
|
||||
KWayland::Server::QtSurfaceExtensionInterface *m_qtExtendedSurface = nullptr;
|
||||
KWayland::Server::ServerSideDecorationManagerInterface *m_decorationManager = nullptr;
|
||||
KWayland::Server::OutputManagementInterface *m_outputManagement = nullptr;
|
||||
|
|
|
@ -165,6 +165,8 @@ Workspace::Workspace(const QString &sessionKey)
|
|||
// and prior to TabBox, due to TabBox connecting to signals
|
||||
// actual initialization happens in init()
|
||||
VirtualDesktopManager::create(this);
|
||||
//dbus interface
|
||||
new VirtualDesktopManagerDBusInterface(VirtualDesktopManager::self());
|
||||
|
||||
#ifdef KWIN_BUILD_TABBOX
|
||||
// need to create the tabbox before compositing scene is setup
|
||||
|
@ -219,7 +221,30 @@ void Workspace::init()
|
|||
|
||||
// create VirtualDesktopManager and perform dependency injection
|
||||
VirtualDesktopManager *vds = VirtualDesktopManager::self();
|
||||
connect(vds, SIGNAL(desktopsRemoved(uint)), SLOT(moveClientsFromRemovedDesktops()));
|
||||
connect(vds, &VirtualDesktopManager::desktopRemoved, this,
|
||||
[this](KWin::VirtualDesktop *desktop) {
|
||||
//Wayland
|
||||
if (kwinApp()->operationMode() == Application::OperationModeWaylandOnly ||
|
||||
kwinApp()->operationMode() == Application::OperationModeXwayland) {
|
||||
for (auto it = m_allClients.constBegin(); it != m_allClients.constEnd(); ++it) {
|
||||
const bool needsMove = (*it)->desktops().count() == 1;
|
||||
(*it)->removeDesktop(desktop);
|
||||
if (needsMove) {
|
||||
const VirtualDesktop *otherDesktop = VirtualDesktopManager::self()->desktops().first();
|
||||
sendClientToDesktop(*it, qMin(desktop->x11DesktopNumber(), VirtualDesktopManager::self()->count()), true);
|
||||
}
|
||||
}
|
||||
//X11
|
||||
} else {
|
||||
for (auto it = m_allClients.constBegin(); it != m_allClients.constEnd(); ++it) {
|
||||
if (!(*it)->isOnAllDesktops() && ((*it)->desktop() > static_cast<int>(VirtualDesktopManager::self()->count()))) {
|
||||
sendClientToDesktop(*it, VirtualDesktopManager::self()->count(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
connect(vds, SIGNAL(countChanged(uint,uint)), SLOT(slotDesktopCountChanged(uint,uint)));
|
||||
connect(vds, SIGNAL(currentChanged(uint,uint)), SLOT(slotCurrentDesktopChanged(uint,uint)));
|
||||
vds->setNavigationWrappingAround(options->isRollOverDesktops());
|
||||
|
@ -232,6 +257,9 @@ void Workspace::init()
|
|||
// positioning object needs to be created before the virtual desktops are loaded.
|
||||
vds->load();
|
||||
vds->updateLayout();
|
||||
//makes sure any autogenerated id is saved, necessary as in case of xwayland, load will be called 2 times
|
||||
// load is needed to be called again when starting xwayalnd to sync to RootInfo, see BUG 385260
|
||||
vds->save();
|
||||
|
||||
if (!VirtualDesktopManager::self()->setCurrent(m_initialDesktop))
|
||||
VirtualDesktopManager::self()->setCurrent(1);
|
||||
|
@ -1074,14 +1102,6 @@ void Workspace::updateCurrentActivity(const QString &new_activity)
|
|||
#endif
|
||||
}
|
||||
|
||||
void Workspace::moveClientsFromRemovedDesktops()
|
||||
{
|
||||
for (auto it = m_allClients.constBegin(); it != m_allClients.constEnd(); ++it) {
|
||||
if (!(*it)->isOnAllDesktops() && (*it)->desktop() > static_cast<int>(VirtualDesktopManager::self()->count()))
|
||||
sendClientToDesktop(*it, VirtualDesktopManager::self()->count(), true);
|
||||
}
|
||||
}
|
||||
|
||||
void Workspace::slotDesktopCountChanged(uint previousCount, uint newCount)
|
||||
{
|
||||
Q_UNUSED(previousCount)
|
||||
|
|
|
@ -457,7 +457,6 @@ private Q_SLOTS:
|
|||
void slotReloadConfig();
|
||||
void updateCurrentActivity(const QString &new_activity);
|
||||
// virtual desktop handling
|
||||
void moveClientsFromRemovedDesktops();
|
||||
void slotDesktopCountChanged(uint previousCount, uint newCount);
|
||||
void slotCurrentDesktopChanged(uint oldDesktop, uint newDesktop);
|
||||
|
||||
|
|
Loading…
Reference in a new issue