Merge branch 'Plasma/5.10'
This commit is contained in:
commit
33ca5025e7
12 changed files with 181 additions and 33 deletions
|
@ -43,6 +43,7 @@ integrationTest(NAME testGlobalShortcuts SRCS globalshortcuts_test.cpp)
|
|||
integrationTest(NAME testWindowSelection SRCS window_selection_test.cpp)
|
||||
integrationTest(NAME testPointerConstraints SRCS pointer_constraints_test.cpp)
|
||||
integrationTest(NAME testKeyboardLayout SRCS keyboard_layout_test.cpp)
|
||||
integrationTest(NAME testKeymapCreationFailure SRCS keymap_creation_failure_test.cpp)
|
||||
|
||||
if (XCB_ICCCM_FOUND)
|
||||
integrationTest(NAME testMoveResize SRCS move_resize_window_test.cpp LIBS XCB::ICCCM)
|
||||
|
|
102
autotests/integration/keymap_creation_failure_test.cpp
Normal file
102
autotests/integration/keymap_creation_failure_test.cpp
Normal file
|
@ -0,0 +1,102 @@
|
|||
/********************************************************************
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
Copyright (C) 2017 Martin Flöser <mgraesslin@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/>.
|
||||
*********************************************************************/
|
||||
#include "kwin_wayland_test.h"
|
||||
#include "keyboard_input.h"
|
||||
#include "keyboard_layout.h"
|
||||
#include "platform.h"
|
||||
#include "shell_client.h"
|
||||
#include "virtualdesktops.h"
|
||||
#include "wayland_server.h"
|
||||
#include "workspace.h"
|
||||
|
||||
#include <KConfigGroup>
|
||||
#include <KGlobalAccel>
|
||||
|
||||
#include <linux/input.h>
|
||||
|
||||
using namespace KWin;
|
||||
using namespace KWayland::Client;
|
||||
|
||||
static const QString s_socketName = QStringLiteral("wayland_test_kwin_keymap_creation_failure-0");
|
||||
|
||||
class KeymapCreationFailureTest : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
private Q_SLOTS:
|
||||
void initTestCase();
|
||||
void init();
|
||||
void cleanup();
|
||||
|
||||
void testPointerButton();
|
||||
};
|
||||
|
||||
void KeymapCreationFailureTest::initTestCase()
|
||||
{
|
||||
// situation for for BUG 381210
|
||||
// this will fail to create keymap
|
||||
qputenv("XKB_DEFAULT_RULES", "no");
|
||||
qputenv("XKB_DEFAULT_MODEL", "no");
|
||||
qputenv("XKB_DEFAULT_LAYOUT", "no");
|
||||
qputenv("XKB_DEFAULT_VARIANT", "no");
|
||||
qputenv("XKB_DEFAULT_OPTIONS", "no");
|
||||
|
||||
qRegisterMetaType<KWin::ShellClient*>();
|
||||
qRegisterMetaType<KWin::AbstractClient*>();
|
||||
QSignalSpy workspaceCreatedSpy(kwinApp(), &Application::workspaceCreated);
|
||||
QVERIFY(workspaceCreatedSpy.isValid());
|
||||
kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024));
|
||||
QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit()));
|
||||
|
||||
kwinApp()->setConfig(KSharedConfig::openConfig(QString(), KConfig::SimpleConfig));
|
||||
kwinApp()->setKxkbConfig(KSharedConfig::openConfig(QString(), KConfig::SimpleConfig));
|
||||
KConfigGroup layoutGroup = kwinApp()->kxkbConfig()->group("Layout");
|
||||
layoutGroup.writeEntry("LayoutList", QStringLiteral("no"));
|
||||
layoutGroup.writeEntry("Model", "no");
|
||||
layoutGroup.writeEntry("Options", "no");
|
||||
layoutGroup.sync();
|
||||
|
||||
kwinApp()->start();
|
||||
QVERIFY(workspaceCreatedSpy.wait());
|
||||
waylandServer()->initWorkspace();
|
||||
}
|
||||
|
||||
void KeymapCreationFailureTest::init()
|
||||
{
|
||||
QVERIFY(Test::setupWaylandConnection());
|
||||
}
|
||||
|
||||
void KeymapCreationFailureTest::cleanup()
|
||||
{
|
||||
Test::destroyWaylandConnection();
|
||||
}
|
||||
|
||||
void KeymapCreationFailureTest::testPointerButton()
|
||||
{
|
||||
// test case for BUG 381210
|
||||
// pressing a pointer button results in crash
|
||||
|
||||
// now create the crashing condition
|
||||
// which is sending in a pointer event
|
||||
kwinApp()->platform()->pointerButtonPressed(BTN_LEFT, 0);
|
||||
kwinApp()->platform()->pointerButtonReleased(BTN_LEFT, 1);
|
||||
}
|
||||
|
||||
WAYLANDTEST_MAIN(KeymapCreationFailureTest)
|
||||
#include "keymap_creation_failure_test.moc"
|
|
@ -30,6 +30,7 @@ AbstractClient::AbstractClient(QObject *parent)
|
|||
, m_hiddenInternal(false)
|
||||
, m_keepBelow(false)
|
||||
, m_geometry()
|
||||
, m_resize(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -103,4 +104,14 @@ void AbstractClient::setKeepBelow(bool keepBelow)
|
|||
emit keepBelowChanged();
|
||||
}
|
||||
|
||||
bool AbstractClient::isResize() const
|
||||
{
|
||||
return m_resize;
|
||||
}
|
||||
|
||||
void AbstractClient::setResize(bool set)
|
||||
{
|
||||
m_resize = set;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -47,6 +47,8 @@ public:
|
|||
void setHiddenInternal(bool set);
|
||||
void setGeometry(const QRect &rect);
|
||||
void setKeepBelow(bool);
|
||||
bool isResize() const;
|
||||
void setResize(bool set);
|
||||
virtual void showOnScreenEdge() = 0;
|
||||
|
||||
Q_SIGNALS:
|
||||
|
@ -60,6 +62,7 @@ private:
|
|||
bool m_hiddenInternal;
|
||||
bool m_keepBelow;
|
||||
QRect m_geometry;
|
||||
bool m_resize;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -35,9 +35,4 @@ void Client::showOnScreenEdge()
|
|||
setHiddenInternal(false);
|
||||
}
|
||||
|
||||
bool Client::isResize() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -34,8 +34,6 @@ class Client : public AbstractClient
|
|||
public:
|
||||
explicit Client(QObject *parent);
|
||||
virtual ~Client();
|
||||
|
||||
bool isResize() const;
|
||||
void showOnScreenEdge() override;
|
||||
|
||||
};
|
||||
|
|
|
@ -392,6 +392,27 @@ void TestScreenEdges::testCreatingInitialEdges()
|
|||
QCOMPARE(e->activatesForTouchGesture(), false);
|
||||
QCOMPARE(e->approachGeometry(), expectedGeometries.at(i*2+1));
|
||||
}
|
||||
|
||||
// let's start a move of window.
|
||||
Client client(workspace());
|
||||
workspace()->setMovingClient(&client);
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
auto e = edges.at(i);
|
||||
QVERIFY(!e->isReserved());
|
||||
QCOMPARE(e->activatesForPointer(), true);
|
||||
QCOMPARE(e->activatesForTouchGesture(), false);
|
||||
QCOMPARE(e->approachGeometry(), expectedGeometries.at(i*2+1));
|
||||
}
|
||||
// not for resize
|
||||
client.setResize(true);
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
auto e = edges.at(i);
|
||||
QVERIFY(!e->isReserved());
|
||||
QCOMPARE(e->activatesForPointer(), false);
|
||||
QCOMPARE(e->activatesForTouchGesture(), false);
|
||||
QCOMPARE(e->approachGeometry(), expectedGeometries.at(i*2+1));
|
||||
}
|
||||
workspace()->setMovingClient(nullptr);
|
||||
}
|
||||
|
||||
void TestScreenEdges::testCallback()
|
||||
|
|
|
@ -48,6 +48,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include "kwinglutils.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QDesktopWidget>
|
||||
|
||||
#include <Plasma/Theme>
|
||||
|
||||
|
@ -599,6 +600,11 @@ bool EffectsHandlerImpl::grabKeyboard(Effect* effect)
|
|||
bool ret = grabXKeyboard();
|
||||
if (!ret)
|
||||
return false;
|
||||
// Workaround for Qt 5.9 regression introduced with 2b34aefcf02f09253473b096eb4faffd3e62b5f4
|
||||
// we no longer get any events for the root window, one needs to call winId() on the desktop window
|
||||
// TODO: change effects event handling to create the appropriate QKeyEvent without relying on Qt
|
||||
// as it's done already in the Wayland case.
|
||||
qApp->desktop()->winId();
|
||||
}
|
||||
keyboard_grab_effect = effect;
|
||||
return true;
|
||||
|
|
|
@ -183,6 +183,12 @@ bool Edge::activatesForPointer() const
|
|||
if (m_edges->isDesktopSwitching()) {
|
||||
return true;
|
||||
}
|
||||
if (m_edges->isDesktopSwitchingMovingClients()) {
|
||||
auto c = Workspace::self()->getMovingClient();
|
||||
if (c && !c->isResize()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (!m_callBacks.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
@ -293,10 +299,7 @@ bool Edge::canActivate(const QPoint &cursorPos, const QDateTime &triggerTime)
|
|||
void Edge::handle(const QPoint &cursorPos)
|
||||
{
|
||||
AbstractClient *movingClient = Workspace::self()->getMovingClient();
|
||||
bool isResize = false;
|
||||
if (Client *movingClientClient = qobject_cast<Client*>(movingClient))
|
||||
isResize = movingClientClient->isResize();
|
||||
if ((edges()->isDesktopSwitchingMovingClients() && movingClient && !isResize) ||
|
||||
if ((edges()->isDesktopSwitchingMovingClients() && movingClient && !movingClient->isResize()) ||
|
||||
(edges()->isDesktopSwitching() && isScreenEdge())) {
|
||||
// always switch desktops in case:
|
||||
// moving a Client and option for switch on client move is enabled
|
||||
|
|
|
@ -284,7 +284,7 @@ TabBoxClientList TabBoxHandlerImpl::stackingOrder() const
|
|||
ToplevelList stacking = Workspace::self()->stackingOrder();
|
||||
TabBoxClientList ret;
|
||||
foreach (Toplevel *toplevel, stacking) {
|
||||
if (Client *client = qobject_cast<Client*>(toplevel)) {
|
||||
if (auto client = qobject_cast<AbstractClient*>(toplevel)) {
|
||||
ret.append(client->tabBoxClient());
|
||||
}
|
||||
}
|
||||
|
@ -331,7 +331,7 @@ void TabBoxHandlerImpl::shadeClient(TabBoxClient *c, bool b) const
|
|||
QWeakPointer<TabBoxClient> TabBoxHandlerImpl::desktopClient() const
|
||||
{
|
||||
foreach (Toplevel *toplevel, Workspace::self()->stackingOrder()) {
|
||||
Client *client = qobject_cast<Client*>(toplevel);
|
||||
auto client = qobject_cast<AbstractClient*>(toplevel);
|
||||
if (client && client->isDesktop() && client->isOnCurrentDesktop() && client->screen() == screens()->current()) {
|
||||
return client->tabBoxClient();
|
||||
}
|
||||
|
@ -1319,7 +1319,7 @@ void TabBox::walkThroughDesktops(bool forward)
|
|||
|
||||
void TabBox::CDEWalkThroughWindows(bool forward)
|
||||
{
|
||||
Client* c = nullptr;
|
||||
AbstractClient* c = nullptr;
|
||||
// this function find the first suitable client for unreasonable focus
|
||||
// policies - the topmost one, with some exceptions (can't be keepabove/below,
|
||||
// otherwise it gets stuck on them)
|
||||
|
@ -1327,7 +1327,7 @@ void TabBox::CDEWalkThroughWindows(bool forward)
|
|||
for (int i = Workspace::self()->stackingOrder().size() - 1;
|
||||
i >= 0 ;
|
||||
--i) {
|
||||
Client* it = qobject_cast<Client*>(Workspace::self()->stackingOrder().at(i));
|
||||
auto it = qobject_cast<AbstractClient*>(Workspace::self()->stackingOrder().at(i));
|
||||
if (it && it->isOnCurrentActivity() && it->isOnCurrentDesktop() && !it->isSpecialWindow()
|
||||
&& it->isShown(false) && it->wantsTabFocus()
|
||||
&& !it->keepAbove() && !it->keepBelow()) {
|
||||
|
@ -1335,14 +1335,14 @@ void TabBox::CDEWalkThroughWindows(bool forward)
|
|||
break;
|
||||
}
|
||||
}
|
||||
Client* nc = c;
|
||||
AbstractClient* nc = c;
|
||||
bool options_traverse_all;
|
||||
{
|
||||
KConfigGroup group(kwinApp()->config(), "TabBox");
|
||||
options_traverse_all = group.readEntry("TraverseAll", false);
|
||||
}
|
||||
|
||||
Client* firstClient = nullptr;
|
||||
AbstractClient* firstClient = nullptr;
|
||||
do {
|
||||
nc = forward ? nextClientStatic(nc) : previousClientStatic(nc);
|
||||
if (!firstClient) {
|
||||
|
@ -1641,34 +1641,36 @@ int TabBox::previousDesktopStatic(int iDesktop) const
|
|||
auxiliary functions to travers all clients according to the static
|
||||
order. Useful for the CDE-style Alt-tab feature.
|
||||
*/
|
||||
Client* TabBox::nextClientStatic(Client* c) const
|
||||
AbstractClient* TabBox::nextClientStatic(AbstractClient* c) const
|
||||
{
|
||||
if (!c || Workspace::self()->clientList().isEmpty())
|
||||
const auto &list = Workspace::self()->allClientList();
|
||||
if (!c || list.isEmpty())
|
||||
return 0;
|
||||
int pos = Workspace::self()->clientList().indexOf(c);
|
||||
int pos = list.indexOf(c);
|
||||
if (pos == -1)
|
||||
return Workspace::self()->clientList().first();
|
||||
return list.first();
|
||||
++pos;
|
||||
if (pos == Workspace::self()->clientList().count())
|
||||
return Workspace::self()->clientList().first();
|
||||
return Workspace::self()->clientList()[ pos ];
|
||||
if (pos == list.count())
|
||||
return list.first();
|
||||
return list.at(pos);
|
||||
}
|
||||
|
||||
/*!
|
||||
auxiliary functions to travers all clients according to the static
|
||||
order. Useful for the CDE-style Alt-tab feature.
|
||||
*/
|
||||
Client* TabBox::previousClientStatic(Client* c) const
|
||||
AbstractClient* TabBox::previousClientStatic(AbstractClient* c) const
|
||||
{
|
||||
if (!c || Workspace::self()->clientList().isEmpty())
|
||||
const auto &list = Workspace::self()->allClientList();
|
||||
if (!c || list.isEmpty())
|
||||
return 0;
|
||||
int pos = Workspace::self()->clientList().indexOf(c);
|
||||
int pos = list.indexOf(c);
|
||||
if (pos == -1)
|
||||
return Workspace::self()->clientList().last();
|
||||
return list.last();
|
||||
if (pos == 0)
|
||||
return Workspace::self()->clientList().last();
|
||||
return list.last();
|
||||
--pos;
|
||||
return Workspace::self()->clientList()[ pos ];
|
||||
return list.at(pos);
|
||||
}
|
||||
|
||||
bool TabBox::establishTabBoxGrab()
|
||||
|
|
|
@ -176,8 +176,8 @@ public:
|
|||
|
||||
void initShortcuts();
|
||||
|
||||
Client* nextClientStatic(Client*) const;
|
||||
Client* previousClientStatic(Client*) const;
|
||||
AbstractClient* nextClientStatic(AbstractClient*) const;
|
||||
AbstractClient* previousClientStatic(AbstractClient*) const;
|
||||
int nextDesktopStatic(int iDesktop) const;
|
||||
int previousDesktopStatic(int iDesktop) const;
|
||||
void keyPress(int key);
|
||||
|
|
8
xkb.cpp
8
xkb.cpp
|
@ -354,13 +354,16 @@ QString Xkb::layoutName() const
|
|||
|
||||
QString Xkb::layoutName(xkb_layout_index_t layout) const
|
||||
{
|
||||
if (!m_keymap) {
|
||||
return QString{};
|
||||
}
|
||||
return QString::fromLocal8Bit(xkb_keymap_layout_get_name(m_keymap, layout));
|
||||
}
|
||||
|
||||
QMap<xkb_layout_index_t, QString> Xkb::layoutNames() const
|
||||
{
|
||||
QMap<xkb_layout_index_t, QString> layouts;
|
||||
const auto size = xkb_keymap_num_layouts(m_keymap);
|
||||
const auto size = m_keymap ? xkb_keymap_num_layouts(m_keymap) : 0u;
|
||||
for (xkb_layout_index_t i = 0; i < size; i++) {
|
||||
layouts.insert(i, layoutName(i));
|
||||
}
|
||||
|
@ -387,6 +390,9 @@ void Xkb::updateConsumedModifiers(uint32_t key)
|
|||
|
||||
Qt::KeyboardModifiers Xkb::modifiersRelevantForGlobalShortcuts() const
|
||||
{
|
||||
if (!m_state) {
|
||||
return Qt::NoModifier;
|
||||
}
|
||||
Qt::KeyboardModifiers mods = Qt::NoModifier;
|
||||
if (xkb_state_mod_index_is_active(m_state, m_shiftModifier, XKB_STATE_MODS_EFFECTIVE) == 1) {
|
||||
mods |= Qt::ShiftModifier;
|
||||
|
|
Loading…
Reference in a new issue