Merge branch 'master' into kdecorations2

Conflicts:
	CMakeLists.txt
	paintredirector.cpp
	scene_opengl.h
	scene_qpainter.h
	scene_xrender.h
icc-effect-5.14.5
Martin Gräßlin 2014-10-20 16:04:52 +02:00
commit e32da9d9e0
148 changed files with 6893 additions and 2712 deletions

View File

@ -1,7 +1,10 @@
project(KWIN)
set(PROJECT_VERSION "5.1.90")
set(PROJECT_VERSION_MAJOR 5)
cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR)
set(QT_MIN_VERSION "5.3.0")
set(KF5_MIN_VERSION "5.3.0")
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules ${CMAKE_MODULE_PATH} )
@ -58,7 +61,7 @@ set_package_properties(Qt5Multimedia PROPERTIES
# required frameworks by Core
find_package(KF5 REQUIRED COMPONENTS
find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS
Config
ConfigWidgets
CoreAddons
@ -73,7 +76,7 @@ find_package(KF5 REQUIRED COMPONENTS
WindowSystem
)
# required frameworks by config modules
find_package(KF5 REQUIRED COMPONENTS
find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS
Completion
Declarative
KCMUtils
@ -83,14 +86,14 @@ find_package(KF5 REQUIRED COMPONENTS
)
# optional frameworks
find_package(KF5Activities CONFIG)
find_package(KF5Activities ${KF5_MIN_VERSION} CONFIG)
set_package_properties(KF5Activities PROPERTIES
PURPOSE "Enable building of KWin with kactivities support"
TYPE OPTIONAL
)
add_feature_info("KF5Activities" KF5Activities_FOUND "Enable building of KWin with kactivities support")
find_package(KF5DocTools CONFIG)
find_package(KF5DocTools ${KF5_MIN_VERSION} CONFIG)
set_package_properties(KF5DocTools PROPERTIES
PURPOSE "Enable building documentation"
TYPE OPTIONAL
@ -98,6 +101,11 @@ set_package_properties(KF5DocTools PROPERTIES
add_feature_info("KF5DocTools" KF5DocTools_FOUND "Enable building documentation")
find_package(KDecoration2 CONFIG REQUIRED)
find_package(KF5Wayland CONFIG)
set_package_properties(KF5Wayland PROPERTIES
TYPE OPTIONAL
)
add_feature_info("KF5Wayland" KF5Wayland_FOUND "Required for Wayland Compositor Information Module")
if(${Qt5Gui_OPENGL_IMPLEMENTATION} STREQUAL "GL")
find_package(OpenGL)
@ -126,7 +134,7 @@ set_package_properties(epoxy PROPERTIES DESCRIPTION "libepoxy"
PURPOSE "OpenGL dispatch library"
)
find_package(Wayland 1.2 COMPONENTS Client Egl Cursor)
find_package(Wayland 1.2 COMPONENTS Client Egl Cursor Server)
set_package_properties(Wayland PROPERTIES
TYPE OPTIONAL
PURPOSE "Required for building KWin with Wayland support"
@ -140,6 +148,20 @@ set_package_properties(XKB PROPERTIES
PURPOSE "Required for building KWin with Wayland support"
)
find_package(Libinput 0.5)
set_package_properties(Libinput PROPERTIES TYPE OPTIONAL PURPOSE "Required for input handling on Wayland.")
find_package(UDev)
set_package_properties(UDev PROPERTIES URL "http://www.freedesktop.org/software/systemd/libudev/"
DESCRIPTION "Linux device library."
TYPE OPTIONAL
PURPOSE "Required for input handling on Wayland."
)
set(HAVE_INPUT FALSE)
if (Libinput_FOUND AND UDEV_FOUND)
set(HAVE_INPUT TRUE)
endif()
find_package(X11)
set_package_properties(X11 PROPERTIES DESCRIPTION "X11 libraries"
URL "http://www.x.org"
@ -161,6 +183,7 @@ find_package(XCB
IMAGE
SHM
XTEST
GLX
OPTIONAL_COMPONENTS
ICCCM
)
@ -197,16 +220,8 @@ endif()
set(KWIN_NAME "kwin")
set(KWIN_INTERNAL_NAME_X11 "kwin_x11")
set(KWIN_INTERNAL_NAME_WAYLAND "kwin_wayland")
set(KWIN_VERSION_MAJOR 5)
set(KWIN_VERSION_MINOR 0)
set(KWIN_VERSION_PATCH 0)
set(KWIN_VERSION ${KWIN_VERSION_MAJOR}.${KWIN_VERSION_MINOR}.${KWIN_VERSION_PATCH} )
set(KWIN_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
set(GENERIC_LIB_SOVERSION ${KWIN_VERSION_MAJOR})
set(GENERIC_LIB_VERSION "${KWIN_VERSION_MAJOR}.${KWIN_VERSION_MINOR}.${KWIN_VERSION_PATCH}")
if(KWIN_PLASMA_ACTIVE)
set(KWIN_BUILD_DECORATIONS OFF)
set(KWIN_BUILD_KCMS OFF)
@ -247,7 +262,7 @@ endif()
# for things that are also used by kwin libraries
configure_file(libkwineffects/kwinconfig.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/libkwineffects/kwinconfig.h )
# for kwin internal things
if(Wayland_Client_FOUND AND XKB_FOUND)
if(Wayland_Client_FOUND AND XKB_FOUND AND KF5Wayland_FOUND)
set(HAVE_WAYLAND ${Wayland_Client_FOUND})
set(HAVE_XKB ${XKB_FOUND})
set(HAVE_WAYLAND_EGL ${Wayland_Egl_FOUND})
@ -344,6 +359,8 @@ set(kwin_KDEINIT_SRCS
compositingprefs.cpp
virtualdesktops.cpp
xcbutils.cpp
x11eventfilter.cpp
logind.cpp
scripting/scripting.cpp
scripting/workspace_wrapper.cpp
scripting/meta.cpp
@ -399,13 +416,26 @@ if(KWIN_HAVE_EGL)
set(kwin_KDEINIT_SRCS ${kwin_KDEINIT_SRCS} eglonxbackend.cpp)
endif()
if(Wayland_Client_FOUND AND XKB_FOUND)
set(kwin_KDEINIT_SRCS ${kwin_KDEINIT_SRCS} wayland_backend.cpp)
if(HAVE_WAYLAND)
set(kwin_KDEINIT_SRCS
${kwin_KDEINIT_SRCS}
screens_wayland.cpp
wayland_backend.cpp
)
if(KWIN_HAVE_EGL AND Wayland_Egl_FOUND)
set(kwin_KDEINIT_SRCS ${kwin_KDEINIT_SRCS} egl_wayland_backend.cpp)
endif()
endif()
if(HAVE_INPUT)
set(kwin_KDEINIT_SRCS
${kwin_KDEINIT_SRCS}
libinput/context.cpp
libinput/connection.cpp
libinput/events.cpp
)
endif()
kconfig_add_kcfg_files(kwin_KDEINIT_SRCS settings.kcfgc)
qt5_add_dbus_adaptor( kwin_KDEINIT_SRCS org.kde.KWin.xml dbusinterface.h KWin::DBusInterface )
@ -472,6 +502,7 @@ set(kwin_XCB_LIBS
XCB::KEYSYMS
XCB::SHM
XCB::XTEST
XCB::GLX
)
set(kwin_WAYLAND_LIBS
@ -479,6 +510,7 @@ set(kwin_WAYLAND_LIBS
Wayland::Cursor
XCB::XTEST
XKB::XKB
KF5::WaylandClient
)
set(kwin_WAYLAND_EGL_LIBS
@ -504,33 +536,53 @@ set(kwinLibs
${kwin_XCB_LIBS}
)
if(Wayland_Client_FOUND AND XKB_FOUND)
if(HAVE_WAYLAND)
set(kwinLibs ${kwinLibs} ${kwin_WAYLAND_LIBS})
if(KWIN_HAVE_EGL AND Wayland_Egl_FOUND)
set(kwinLibs ${kwinLibs} ${kwin_WAYLAND_EGL_LIBS})
endif()
endif()
kf5_add_kdeinit_executable( kwin ${kwin_KDEINIT_SRCS})
if(HAVE_INPUT)
set(kwinLibs ${kwinLibs} Libinput::Libinput ${UDEV_LIBS})
endif()
target_link_libraries(kdeinit_kwin ${kwinLibs})
set_target_properties(kwin PROPERTIES OUTPUT_NAME ${KWIN_INTERNAL_NAME_X11})
generate_export_header(kdeinit_kwin EXPORT_FILE_NAME kwin_export.h)
add_library(kwin SHARED ${kwin_KDEINIT_SRCS})
set_target_properties(kwin PROPERTIES
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR}
)
target_link_libraries(kwin ${kwinLibs})
generate_export_header(kwin EXPORT_FILE_NAME kwin_export.h)
if(KWIN_BUILD_OPENGL)
target_link_libraries(kdeinit_kwin kwinglutils ${epoxy_LIBRARY})
target_link_libraries(kwin kwinglutils ${epoxy_LIBRARY})
# -ldl used by OpenGL code
find_library(DL_LIBRARY dl)
if (DL_LIBRARY)
target_link_libraries(kdeinit_kwin ${DL_LIBRARY})
target_link_libraries(kwin ${DL_LIBRARY})
endif()
elseif(KWIN_BUILD_OPENGLES)
target_link_libraries(kdeinit_kwin ${kwinLibs} kwinglesutils ${epoxy_LIBRARY})
set_target_properties(kdeinit_kwin PROPERTIES COMPILE_FLAGS "-DKWIN_HAVE_OPENGLES")
target_link_libraries(kwin ${kwinLibs} kwinglesutils ${epoxy_LIBRARY})
set_target_properties(kwin PROPERTIES COMPILE_FLAGS "-DKWIN_HAVE_OPENGLES")
endif()
install(TARGETS kdeinit_kwin ${INSTALL_TARGETS_DEFAULT_ARGS} )
install(TARGETS kwin ${INSTALL_TARGETS_DEFAULT_ARGS} )
kf5_add_kdeinit_executable(kwin_x11 main_x11.cpp)
target_link_libraries(kdeinit_kwin_x11 kwin)
install(TARGETS kwin ${INSTALL_TARGETS_DEFAULT_ARGS} LIBRARY NAMELINK_SKIP )
install(TARGETS kdeinit_kwin_x11 ${INSTALL_TARGETS_DEFAULT_ARGS} )
install(TARGETS kwin_x11 ${INSTALL_TARGETS_DEFAULT_ARGS} )
if(HAVE_WAYLAND)
kf5_add_kdeinit_executable(kwin_wayland main_wayland.cpp)
target_link_libraries(kdeinit_kwin_wayland kwin)
install(TARGETS kdeinit_kwin_wayland ${INSTALL_TARGETS_DEFAULT_ARGS} )
install(TARGETS kwin_wayland ${INSTALL_TARGETS_DEFAULT_ARGS} )
endif()
########### install files ###############

View File

@ -846,7 +846,7 @@ void Client::startupIdChanged()
void Client::updateUrgency()
{
if (urgency)
if (info->urgency())
demandAttention();
}

View File

@ -1,4 +1,5 @@
add_definitions(-DKWIN_UNIT_TEST)
########################################################
# Test ScreenPaintData
########################################################
@ -178,3 +179,63 @@ target_link_libraries(fakeeffectplugin kwineffects)
add_library(effectversionplugin MODULE fakeeffectplugin_version.cpp)
set_target_properties(effectversionplugin PROPERTIES PREFIX "")
target_link_libraries(effectversionplugin kwineffects)
########################################################
# Test Screens
########################################################
set( testScreens_SRCS
test_screens.cpp
mock_client.cpp
mock_screens.cpp
mock_workspace.cpp
../screens.cpp
)
kconfig_add_kcfg_files(testScreens_SRCS ../settings.kcfgc)
add_executable( testScreens ${testScreens_SRCS})
target_include_directories(testScreens BEFORE PRIVATE ./)
target_link_libraries(testScreens
Qt5::Test
Qt5::X11Extras
KF5::ConfigCore
KF5::ConfigGui
KF5::WindowSystem
KF5::Service
)
add_test(kwin_testScreens testScreens)
ecm_mark_as_test(testScreens)
########################################################
# Test ScreenEdges
########################################################
set( testScreenEdges_SRCS
test_screen_edges.cpp
mock_client.cpp
mock_screens.cpp
mock_workspace.cpp
../atoms.cpp
../screens.cpp
../screenedge.cpp
../virtualdesktops.cpp
)
kconfig_add_kcfg_files(testScreenEdges_SRCS ../settings.kcfgc)
qt5_add_dbus_interface( testScreenEdges_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/../org.freedesktop.ScreenSaver.xml screenlocker_interface)
add_executable( testScreenEdges ${testScreenEdges_SRCS})
target_include_directories(testScreenEdges BEFORE PRIVATE ./)
target_link_libraries(testScreenEdges
Qt5::DBus
Qt5::Test
Qt5::X11Extras
KF5::ConfigCore
KF5::ConfigGui
KF5::I18n
KF5::GlobalAccel
KF5::WindowSystem
KF5::Service
XCB::XCB
)
add_test(kwin_testScreenEdges testScreenEdges)
ecm_mark_as_test(testScreenEdges)

1
autotests/client.h Normal file
View File

@ -0,0 +1 @@
#include "mock_client.h"

99
autotests/mock_client.cpp Normal file
View File

@ -0,0 +1,99 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2014 Martin Gräßlin <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 "mock_client.h"
namespace KWin
{
Client::Client(QObject *parent)
: QObject(parent)
, m_active(false)
, m_screen(0)
, m_fullscreen(false)
, m_hiddenInternal(false)
, m_geometry()
{
}
Client::~Client() = default;
bool Client::isActive() const
{
return m_active;
}
void Client::setActive(bool active)
{
m_active = active;
}
void Client::setScreen(int screen)
{
m_screen = screen;
}
bool Client::isOnScreen(int screen) const
{
// TODO: mock checking client geometry
return screen == m_screen;
}
int Client::screen() const
{
return m_screen;
}
void Client::showOnScreenEdge()
{
setHiddenInternal(false);
}
void Client::setFullScreen(bool set)
{
m_fullscreen = set;
}
bool Client::isFullScreen() const
{
return m_fullscreen;
}
bool Client::isHiddenInternal() const
{
return m_hiddenInternal;
}
void Client::setHiddenInternal(bool set)
{
m_hiddenInternal = set;
}
void Client::setGeometry(const QRect &rect)
{
m_geometry = rect;
emit geometryChanged();
}
QRect Client::geometry() const
{
return m_geometry;
}
}

64
autotests/mock_client.h Normal file
View File

@ -0,0 +1,64 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2014 Martin Gräßlin <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/>.
*********************************************************************/
#ifndef KWIN_MOCK_CLIENT_H
#define KWIN_MOCK_CLIENT_H
#include <QObject>
#include <QRect>
namespace KWin
{
class Client : public QObject
{
Q_OBJECT
public:
explicit Client(QObject *parent);
virtual ~Client();
int screen() const;
bool isOnScreen(int screen) const;
bool isActive() const;
bool isFullScreen() const;
bool isHiddenInternal() const;
QRect geometry() const;
void setActive(bool active);
void setScreen(int screen);
void setFullScreen(bool set);
void setHiddenInternal(bool set);
void setGeometry(const QRect &rect);
void showOnScreenEdge();
Q_SIGNALS:
void geometryChanged();
private:
bool m_active;
int m_screen;
bool m_fullscreen;
bool m_hiddenInternal;
QRect m_geometry;
};
}
#endif

View File

@ -0,0 +1,86 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2014 Martin Gräßlin <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 "mock_screens.h"
namespace KWin
{
MockScreens::MockScreens(QObject *parent)
: Screens(parent)
{
}
MockScreens::~MockScreens() = default;
QRect MockScreens::geometry(int screen) const
{
if (screen >= m_geometries.count()) {
return QRect();
}
return m_geometries.at(screen);
}
QSize MockScreens::size(int screen) const
{
return geometry(screen).size();
}
int MockScreens::number(const QPoint &pos) const
{
int bestScreen = 0;
int minDistance = INT_MAX;
for (int i = 0; i < m_geometries.size(); ++i) {
const QRect &geo = m_geometries.at(i);
if (geo.contains(pos)) {
return i;
}
int distance = QPoint(geo.topLeft() - pos).manhattanLength();
distance = qMin(distance, QPoint(geo.topRight() - pos).manhattanLength());
distance = qMin(distance, QPoint(geo.bottomRight() - pos).manhattanLength());
distance = qMin(distance, QPoint(geo.bottomLeft() - pos).manhattanLength());
if (distance < minDistance) {
minDistance = distance;
bestScreen = i;
}
}
return bestScreen;
}
void MockScreens::init()
{
Screens::init();
m_scheduledGeometries << QRect(0, 0, 100, 100);
updateCount();
}
void MockScreens::updateCount()
{
m_geometries = m_scheduledGeometries;
setCount(m_geometries.size());
emit changed();
}
void MockScreens::setGeometries(const QList< QRect > &geometries)
{
m_scheduledGeometries = geometries;
startChangedTimer();
}
}

51
autotests/mock_screens.h Normal file
View File

@ -0,0 +1,51 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2014 Martin Gräßlin <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/>.
*********************************************************************/
#ifndef KWIN_MOCK_SCREENS_H
#define KWIN_MOCK_SCREENS_H
#include "../screens.h"
namespace KWin
{
class MockScreens : public Screens
{
Q_OBJECT
public:
explicit MockScreens(QObject *parent = nullptr);
virtual ~MockScreens();
QRect geometry(int screen) const override;
int number(const QPoint &pos) const override;
QSize size(int screen) const override;
void init() override;
void setGeometries(const QList<QRect> &geometries);
protected Q_SLOTS:
void updateCount() override;
private:
QList<QRect> m_scheduledGeometries;
QList<QRect> m_geometries;
};
}
#endif

View File

@ -0,0 +1,80 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2014 Martin Gräßlin <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 "mock_workspace.h"
#include "mock_client.h"
namespace KWin
{
Workspace *MockWorkspace::s_self = nullptr;
MockWorkspace::MockWorkspace(QObject *parent)
: QObject(parent)
, m_activeClient(nullptr)
, m_movingClient(nullptr)
, m_showingDesktop(false)
{
s_self = this;
}
MockWorkspace::~MockWorkspace()
{
s_self = nullptr;
}
Client *MockWorkspace::activeClient() const
{
return m_activeClient;
}
void MockWorkspace::setActiveClient(Client *c)
{
m_activeClient = c;
}
Client *MockWorkspace::getMovingClient() const
{
return m_movingClient;
}
void MockWorkspace::setMovingClient(Client *c)
{
m_movingClient = c;
}
void MockWorkspace::setShowingDesktop(bool showing)
{
m_showingDesktop = showing;
}
bool MockWorkspace::showingDesktop() const
{
return m_showingDesktop;
}
QRect MockWorkspace::clientArea(clientAreaOption, int screen, int desktop) const
{
Q_UNUSED(screen)
Q_UNUSED(desktop)
return QRect();
}
}

View File

@ -0,0 +1,74 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2014 Martin Gräßlin <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/>.
*********************************************************************/
#ifndef KWIN_MOCK_WORKSPACE_H
#define KWIN_MOCK_WORKSPACE_H
#include <QObject>
#include <kwinglobals.h>
namespace KWin
{
class Client;
class MockWorkspace;
typedef MockWorkspace Workspace;
class MockWorkspace : public QObject
{
Q_OBJECT
public:
explicit MockWorkspace(QObject *parent = nullptr);
virtual ~MockWorkspace();
Client *activeClient() const;
Client *getMovingClient() const;
void setShowingDesktop(bool showing);
bool showingDesktop() const;
QRect clientArea(clientAreaOption, int screen, int desktop) const;
void setActiveClient(Client *c);
void setMovingClient(Client *c);
static Workspace *self();
Q_SIGNALS:
void clientRemoved(KWin::Client*);
private:
Client *m_activeClient;
Client *m_movingClient;
bool m_showingDesktop;
static Workspace *s_self;
};
inline
Workspace *MockWorkspace::self()
{
return s_self;
}
inline Workspace *workspace()
{
return Workspace::self();
}
}
#endif

View File

@ -0,0 +1,847 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2014 Martin Gräßlin <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/>.
*********************************************************************/
// kwin
#include "../atoms.h"
#include "../cursor.h"
#include "../input.h"
#include "../main.h"
#include "../screenedge.h"
#include "../screens.h"
#include "../utils.h"
#include "../virtualdesktops.h"
#include "../xcbutils.h"
#include "mock_client.h"
#include "mock_screens.h"
#include "mock_workspace.h"
// Frameworks
#include <KConfigGroup>
// Qt
#include <QtTest/QtTest>
// xcb
#include <xcb/xcb.h>
Q_DECLARE_METATYPE(KWin::ElectricBorder)
namespace KWin
{
Atoms* atoms;
int screen_number = 0;
Cursor *Cursor::s_self = nullptr;
static QPoint s_cursorPos = QPoint();
QPoint Cursor::pos()
{
return s_cursorPos;
}
void Cursor::setPos(const QPoint &pos)
{
s_cursorPos = pos;
}
void Cursor::setPos(int x, int y)
{
setPos(QPoint(x, y));
}
void Cursor::startMousePolling()
{
}
void Cursor::stopMousePolling()
{
}
InputRedirection *InputRedirection::s_self = nullptr;
void InputRedirection::registerShortcut(const QKeySequence &shortcut, QAction *action)
{
Q_UNUSED(shortcut)
Q_UNUSED(action)
}
void InputRedirection::registerAxisShortcut(Qt::KeyboardModifiers modifiers, PointerAxisDirection axis, QAction *action)
{
Q_UNUSED(modifiers)
Q_UNUSED(axis)
Q_UNUSED(action)
}
void updateXTime()
{
}
Application::OperationMode Application::operationMode() const
{
return OperationModeX11;
}
class TestObject : public QObject
{
Q_OBJECT
public Q_SLOTS:
bool callback(ElectricBorder border);
Q_SIGNALS:
void gotCallback(KWin::ElectricBorder);
};
bool TestObject::callback(KWin::ElectricBorder border)
{
emit gotCallback(border);
return true;
}
}
class TestScreenEdges : public QObject
{
Q_OBJECT
private Q_SLOTS:
void initTestCase();
void cleanupTestCase();
void init();
void cleanup();
void testInit();
void testCreatingInitialEdges();
void testCallback();
void testCallbackWithCheck();
void testPushBack_data();
void testPushBack();
void testFullScreenBlocking();
void testClientEdge();
};
void TestScreenEdges::initTestCase()
{
KWin::atoms = new KWin::Atoms;
qRegisterMetaType<KWin::ElectricBorder>();
}
void TestScreenEdges::cleanupTestCase()
{
delete KWin::atoms;
}
void TestScreenEdges::init()
{
using namespace KWin;
new MockWorkspace;
auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig);
Screens::create();
auto vd = VirtualDesktopManager::create();
vd->setConfig(config);
vd->load();
auto s = ScreenEdges::create();
s->setConfig(config);
}
void TestScreenEdges::cleanup()
{
using namespace KWin;
delete ScreenEdges::self();
delete VirtualDesktopManager::self();
delete Screens::self();
delete workspace();
}
void TestScreenEdges::testInit()
{
using namespace KWin;
auto s = ScreenEdges::self();
s->init();
QCOMPARE(s->isDesktopSwitching(), false);
QCOMPARE(s->isDesktopSwitchingMovingClients(), false);
QCOMPARE(s->timeThreshold(), 150);
QCOMPARE(s->reActivationThreshold(), 350);
QCOMPARE(s->cursorPushBackDistance(), QSize(1, 1));
QCOMPARE(s->actionTopLeft(), ElectricBorderAction::ElectricActionNone);
QCOMPARE(s->actionTop(), ElectricBorderAction::ElectricActionNone);
QCOMPARE(s->actionTopRight(), ElectricBorderAction::ElectricActionNone);
QCOMPARE(s->actionRight(), ElectricBorderAction::ElectricActionNone);
QCOMPARE(s->actionBottomRight(), ElectricBorderAction::ElectricActionNone);
QCOMPARE(s->actionBottom(), ElectricBorderAction::ElectricActionNone);
QCOMPARE(s->actionBottomLeft(), ElectricBorderAction::ElectricActionNone);
QCOMPARE(s->actionLeft(), ElectricBorderAction::ElectricActionNone);
QList<Edge*> edges = s->findChildren<Edge*>(QString(), Qt::FindDirectChildrenOnly);
QCOMPARE(edges.size(), 8);
for (auto e : edges) {
QVERIFY(!e->isReserved());
QVERIFY(e->inherits("KWin::WindowBasedEdge"));
QVERIFY(!e->inherits("KWin::AreaBasedEdge"));
QVERIFY(!e->client());
QVERIFY(!e->isApproaching());
}
Edge *te = edges.at(0);
QVERIFY(te->isCorner());
QVERIFY(!te->isScreenEdge());
QVERIFY(te->isLeft());
QVERIFY(te->isTop());
QVERIFY(!te->isRight());
QVERIFY(!te->isBottom());
QCOMPARE(te->border(), ElectricBorder::ElectricTopLeft);
te = edges.at(1);
QVERIFY(te->isCorner());
QVERIFY(!te->isScreenEdge());
QVERIFY(te->isLeft());
QVERIFY(!te->isTop());
QVERIFY(!te->isRight());
QVERIFY(te->isBottom());
QCOMPARE(te->border(), ElectricBorder::ElectricBottomLeft);
te = edges.at(2);
QVERIFY(!te->isCorner());
QVERIFY(te->isScreenEdge());
QVERIFY(te->isLeft());
QVERIFY(!te->isTop());
QVERIFY(!te->isRight());
QVERIFY(!te->isBottom());
QCOMPARE(te->border(), ElectricBorder::ElectricLeft);
te = edges.at(3);
QVERIFY(te->isCorner());
QVERIFY(!te->isScreenEdge());
QVERIFY(!te->isLeft());
QVERIFY(te->isTop());
QVERIFY(te->isRight());
QVERIFY(!te->isBottom());
QCOMPARE(te->border(), ElectricBorder::ElectricTopRight);
te = edges.at(4);
QVERIFY(te->isCorner());
QVERIFY(!te->isScreenEdge());
QVERIFY(!te->isLeft());
QVERIFY(!te->isTop());
QVERIFY(te->isRight());
QVERIFY(te->isBottom());
QCOMPARE(te->border(), ElectricBorder::ElectricBottomRight);
te = edges.at(5);
QVERIFY(!te->isCorner());
QVERIFY(te->isScreenEdge());
QVERIFY(!te->isLeft());
QVERIFY(!te->isTop());
QVERIFY(te->isRight());
QVERIFY(!te->isBottom());
QCOMPARE(te->border(), ElectricBorder::ElectricRight);
te = edges.at(6);
QVERIFY(!te->isCorner());
QVERIFY(te->isScreenEdge());
QVERIFY(!te->isLeft());
QVERIFY(te->isTop());
QVERIFY(!te->isRight());
QVERIFY(!te->isBottom());
QCOMPARE(te->border(), ElectricBorder::ElectricTop);
te = edges.at(7);
QVERIFY(!te->isCorner());
QVERIFY(te->isScreenEdge());
QVERIFY(!te->isLeft());
QVERIFY(!te->isTop());
QVERIFY(!te->isRight());
QVERIFY(te->isBottom());
QCOMPARE(te->border(), ElectricBorder::ElectricBottom);
// we shouldn't have any x windows, though
QCOMPARE(s->windows().size(), 0);
}
void TestScreenEdges::testCreatingInitialEdges()
{
using namespace KWin;
auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig);
config->group("Windows").writeEntry("ElectricBorders", 2/*ElectricAlways*/);
config->sync();
auto s = ScreenEdges::self();
s->setConfig(config);
s->init();
// we don't have multiple desktops, so it's returning false
QCOMPARE(s->isDesktopSwitching(), true);
QCOMPARE(s->isDesktopSwitchingMovingClients(), true);
QCOMPARE(s->actionTopLeft(), ElectricBorderAction::ElectricActionNone);
QCOMPARE(s->actionTop(), ElectricBorderAction::ElectricActionNone);
QCOMPARE(s->actionTopRight(), ElectricBorderAction::ElectricActionNone);
QCOMPARE(s->actionRight(), ElectricBorderAction::ElectricActionNone);
QCOMPARE(s->actionBottomRight(), ElectricBorderAction::ElectricActionNone);
QCOMPARE(s->actionBottom(), ElectricBorderAction::ElectricActionNone);
QCOMPARE(s->actionBottomLeft(), ElectricBorderAction::ElectricActionNone);
QCOMPARE(s->actionLeft(), ElectricBorderAction::ElectricActionNone);
QEXPECT_FAIL("", "needs fixing", Continue);
QCOMPARE(s->windows().size(), 0);
// set some reasonable virtual desktops
config->group("Desktops").writeEntry("Number", 4);
config->sync();
auto vd = VirtualDesktopManager::self();
vd->setConfig(config);
vd->load();
QCOMPARE(vd->count(), 4u);
QCOMPARE(vd->grid().width(), 2);
QCOMPARE(vd->grid().height(), 2);
// approach windows for edges not created as screen too small
s->updateLayout();
auto edgeWindows = s->windows();
QCOMPARE(edgeWindows.size(), 12);
auto testWindowGeometry = [&](int index) {
Xcb::WindowGeometry geo(edgeWindows[index]);
return geo.rect();
};
QRect sg = screens()->geometry();
const int co = s->cornerOffset();
QList<QRect> expectedGeometries{
QRect(0, 0, 1, 1),
QRect(0, 0, co, co),
QRect(0, sg.bottom(), 1, 1),
QRect(0, sg.height() - co, co, co),
QRect(0, co, 1, sg.height() - co*2),
// QRect(0, co * 2 + 1, co, sg.height() - co*4),
QRect(sg.right(), 0, 1, 1),
QRect(sg.right() - co + 1, 0, co, co),
QRect(sg.right(), sg.bottom(), 1, 1),
QRect(sg.right() - co + 1, sg.bottom() - co + 1, co, co),
QRect(sg.right(), co, 1, sg.height() - co*2),
// QRect(sg.right() - co + 1, co * 2, co, sg.height() - co*4),
QRect(co, 0, sg.width() - co * 2, 1),
// QRect(co * 2, 0, sg.width() - co * 4, co),
QRect(co, sg.bottom(), sg.width() - co * 2, 1),
// QRect(co * 2, sg.height() - co, sg.width() - co * 4, co)
};
for (int i = 0; i < 12; ++i) {
QCOMPARE(testWindowGeometry(i), expectedGeometries.at(i));
}
QList<Edge*> edges = s->findChildren<Edge*>(QString(), Qt::FindDirectChildrenOnly);
QCOMPARE(edges.size(), 8);
for (auto e : edges) {
QVERIFY(e->isReserved());
}
static_cast<MockScreens*>(screens())->setGeometries(QList<QRect>{QRect{0, 0, 1024, 768}});
QSignalSpy changedSpy(screens(), SIGNAL(changed()));
QVERIFY(changedSpy.isValid());
// first is before it's updated
QVERIFY(changedSpy.wait());
// second is after it's updated
QVERIFY(changedSpy.wait());
// let's update the layout and verify that we have edges
s->recreateEdges();
edgeWindows = s->windows();
QCOMPARE(edgeWindows.size(), 16);
sg = screens()->geometry();
expectedGeometries = QList<QRect>{
QRect(0, 0, 1, 1),
QRect(0, 0, co, co),
QRect(0, sg.bottom(), 1, 1),
QRect(0, sg.height() - co, co, co),
QRect(0, co, 1, sg.height() - co*2),
QRect(0, co * 2 + 1, co, sg.height() - co*4),
QRect(sg.right(), 0, 1, 1),
QRect(sg.right() - co + 1, 0, co, co),
QRect(sg.right(), sg.bottom(), 1, 1),
QRect(sg.right() - co + 1, sg.bottom() - co + 1, co, co),
QRect(sg.right(), co, 1, sg.height() - co*2),
QRect(sg.right() - co + 1, co * 2, co, sg.height() - co*4),
QRect(co, 0, sg.width() - co * 2, 1),
QRect(co * 2, 0, sg.width() - co * 4, co),
QRect(co, sg.bottom(), sg.width() - co * 2, 1),
QRect(co * 2, sg.height() - co, sg.width() - co * 4, co)
};
for (int i = 0; i < 16; ++i) {
QCOMPARE(testWindowGeometry(i), expectedGeometries.at(i));
}
// disable desktop switching again
config->group("Windows").writeEntry("ElectricBorders", 1/*ElectricMoveOnly*/);
s->reconfigure();
QCOMPARE(s->isDesktopSwitching(), false);
QCOMPARE(s->isDesktopSwitchingMovingClients(), true);
QCOMPARE(s->windows().size(), 0);
edges = s->findChildren<Edge*>(QString(), Qt::FindDirectChildrenOnly);
QCOMPARE(edges.size(), 8);
for (int i = 0; i < 8; ++i) {
auto e = edges.at(i);
QVERIFY(!e->isReserved());
QCOMPARE(e->approachGeometry(), expectedGeometries.at(i*2+1));
}
}
void TestScreenEdges::testCallback()
{
using namespace KWin;
MockWorkspace ws;
static_cast<MockScreens*>(screens())->setGeometries(QList<QRect>{QRect{0, 0, 1024, 768}, QRect{200, 768, 1024, 768}});
QSignalSpy changedSpy(screens(), SIGNAL(changed()));
QVERIFY(changedSpy.isValid());
// first is before it's updated
QVERIFY(changedSpy.wait());
// second is after it's updated
QVERIFY(changedSpy.wait());
auto s = ScreenEdges::self();
s->init();
TestObject callback;
QSignalSpy spy(&callback, SIGNAL(gotCallback(KWin::ElectricBorder)));
QVERIFY(spy.isValid());
s->reserve(ElectricLeft, &callback, "callback");
s->reserve(ElectricTopLeft, &callback, "callback");
s->reserve(ElectricTop, &callback, "callback");
s->reserve(ElectricTopRight, &callback, "callback");
s->reserve(ElectricRight, &callback, "callback");
s->reserve(ElectricBottomRight, &callback, "callback");
s->reserve(ElectricBottom, &callback, "callback");
s->reserve(ElectricBottomLeft, &callback, "callback");
QList<Edge*> edges = s->findChildren<Edge*>(QString(), Qt::FindDirectChildrenOnly);
QCOMPARE(edges.size(), 10);
for (auto e: edges) {
QVERIFY(e->isReserved());
}
auto it = std::find_if(edges.constBegin(), edges.constEnd(), [](Edge *e) {
return e->isScreenEdge() && e->isLeft() && e->approachGeometry().bottom() < 768;
});
QVERIFY(it != edges.constEnd());
xcb_enter_notify_event_t event;
auto setPos = [&event] (const QPoint &pos) {
Cursor::setPos(pos);
event.root_x = pos.x();
event.root_y = pos.y();
event.event_x = pos.x();
event.event_y = pos.y();
};
event.root = XCB_WINDOW_NONE;
event.child = XCB_WINDOW_NONE;
event.event = static_cast<WindowBasedEdge*>(*it)->window();
event.same_screen_focus = 1;
event.time = QDateTime::currentMSecsSinceEpoch();
setPos(QPoint(0, 50));
QVERIFY(s->isEntered(&event));
// doesn't trigger as the edge was not triggered yet
QVERIFY(spy.isEmpty());
QCOMPARE(Cursor::pos(), QPoint(1, 50));
// test doesn't trigger due to too much offset
QTest::qWait(160);
setPos(QPoint(0, 100));
event.time = QDateTime::currentMSecsSinceEpoch();
QVERIFY(s->isEntered(&event));
QVERIFY(spy.isEmpty());
QCOMPARE(Cursor::pos(), QPoint(1, 100));
// doesn't trigger as we are waiting too long already
QTest::qWait(200);
setPos(QPoint(0, 101));
event.time = QDateTime::currentMSecsSinceEpoch();
QVERIFY(s->isEntered(&event));
QVERIFY(spy.isEmpty());
QCOMPARE(Cursor::pos(), QPoint(1, 101));
// doesn't activate as we are waiting too short
QTest::qWait(50);
setPos(QPoint(0, 100));
event.time = QDateTime::currentMSecsSinceEpoch();
QVERIFY(s->isEntered(&event));
QVERIFY(spy.isEmpty());
QCOMPARE(Cursor::pos(), QPoint(1, 100));
// and this one triggers
QTest::qWait(110);
setPos(QPoint(0, 101));
event.time = QDateTime::currentMSecsSinceEpoch();
QVERIFY(s->isEntered(&event));
QVERIFY(!spy.isEmpty());
QCOMPARE(Cursor::pos(), QPoint(1, 101));
// now let's try to trigger again
QTest::qWait(100);
setPos(QPoint(0, 100));
event.time = QDateTime::currentMSecsSinceEpoch();
QVERIFY(s->isEntered(&event));
QCOMPARE(spy.count(), 1);
QCOMPARE(Cursor::pos(), QPoint(1, 100));
// it's still under the reactivation
QTest::qWait(50);
setPos(QPoint(0, 100));
event.time = QDateTime::currentMSecsSinceEpoch();
QVERIFY(s->isEntered(&event));
QCOMPARE(spy.count(), 1);
QCOMPARE(Cursor::pos(), QPoint(1, 100));
// now it should trigger again
QTest::qWait(250);
setPos(QPoint(0, 100));
event.time = QDateTime::currentMSecsSinceEpoch();
QVERIFY(s->isEntered(&event));
QCOMPARE(spy.count(), 2);
QCOMPARE(spy.first().first().value<ElectricBorder>(), ElectricLeft);
QCOMPARE(spy.last().first().value<ElectricBorder>(), ElectricLeft);
QCOMPARE(Cursor::pos(), QPoint(1, 100));
// let's disable pushback
auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig);
config->group("Windows").writeEntry("ElectricBorderPushbackPixels", 0);
config->sync();
s->setConfig(config);
s->reconfigure();
// it should trigger directly
event.time = QDateTime::currentMSecsSinceEpoch();
QVERIFY(s->isEntered(&event));
QCOMPARE(spy.count(), 3);
QCOMPARE(spy.at(0).first().value<ElectricBorder>(), ElectricLeft);
QCOMPARE(spy.at(1).first().value<ElectricBorder>(), ElectricLeft);
QCOMPARE(spy.at(2).first().value<ElectricBorder>(), ElectricLeft);
QCOMPARE(Cursor::pos(), QPoint(0, 100));
// now let's unreserve again
s->unreserve(ElectricTopLeft, &callback);
s->unreserve(ElectricTop, &callback);
s->unreserve(ElectricTopRight, &callback);
s->unreserve(ElectricRight, &callback);
s->unreserve(ElectricBottomRight, &callback);
s->unreserve(ElectricBottom, &callback);
s->unreserve(ElectricBottomLeft, &callback);
s->unreserve(ElectricLeft, &callback);
for (auto e: s->findChildren<Edge*>(QString(), Qt::FindDirectChildrenOnly)) {
QVERIFY(!e->isReserved());
}
}
void TestScreenEdges::testCallbackWithCheck()
{
using namespace KWin;
auto s = ScreenEdges::self();
s->init();
TestObject callback;
QSignalSpy spy(&callback, SIGNAL(gotCallback(KWin::ElectricBorder)));
QVERIFY(spy.isValid());
s->reserve(ElectricLeft, &callback, "callback");
// check activating a different edge doesn't do anything
s->check(QPoint(50, 0), QDateTime::currentDateTime(), true);
QVERIFY(spy.isEmpty());
// try a direct activate without pushback
Cursor::setPos(0, 50);
s->check(QPoint(0, 50), QDateTime::currentDateTime(), true);
QCOMPARE(spy.count(), 1);
QEXPECT_FAIL("", "Argument says force no pushback, but it gets pushed back. Needs investigation", Continue);
QCOMPARE(Cursor::pos(), QPoint(0, 50));
// use a different edge, this time with pushback
s->reserve(KWin::ElectricRight, &callback, "callback");
Cursor::setPos(99, 50);
s->check(QPoint(99, 50), QDateTime::currentDateTime());
QCOMPARE(spy.count(), 1);
QCOMPARE(spy.last().first().value<ElectricBorder>(), ElectricLeft);
QCOMPARE(Cursor::pos(), QPoint(98, 50));
// and trigger it again
QTest::qWait(160);
Cursor::setPos(99, 50);
s->check(QPoint(99, 50), QDateTime::currentDateTime());
QCOMPARE(spy.count(), 2);
QCOMPARE(spy.last().first().value<ElectricBorder>(), ElectricRight);
QCOMPARE(Cursor::pos(), QPoint(98, 50));
}
void TestScreenEdges::testPushBack_data()
{
QTest::addColumn<KWin::ElectricBorder>("border");
QTest::addColumn<int>("pushback");
QTest::addColumn<QPoint>("trigger");
QTest::addColumn<QPoint>("expected");
QTest::newRow("topleft-3") << KWin::ElectricTopLeft << 3 << QPoint(0, 0) << QPoint(3, 3);
QTest::newRow("top-5") << KWin::ElectricTop << 5 << QPoint(50, 0) << QPoint(50, 5);
QTest::newRow("toprigth-2") << KWin::ElectricTopRight << 2 << QPoint(99, 0) << QPoint(97, 2);
QTest::newRow("right-10") << KWin::ElectricRight << 10 << QPoint(99, 50) << QPoint(89, 50);
QTest::newRow("bottomright-5") << KWin::ElectricBottomRight << 5 << QPoint(99, 99) << QPoint(94, 94);
QTest::newRow("bottom-10") << KWin::ElectricBottom << 10 << QPoint(50, 99) << QPoint(50, 89);
QTest::newRow("bottomleft-3") << KWin::ElectricBottomLeft << 3 << QPoint(0, 99) << QPoint(3, 96);
QTest::newRow("left-10") << KWin::ElectricLeft << 10 << QPoint(0, 50) << QPoint(10, 50);
QTest::newRow("invalid") << KWin::ElectricLeft << 10 << QPoint(50, 0) << QPoint(50, 0);
}
void TestScreenEdges::testPushBack()
{
using namespace KWin;
QFETCH(int, pushback);
auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig);
config->group("Windows").writeEntry("ElectricBorderPushbackPixels", pushback);
config->sync();
// TODO: add screens
auto s = ScreenEdges::self();
s->setConfig(config);
s->init();
TestObject callback;
QSignalSpy spy(&callback, SIGNAL(gotCallback(KWin::ElectricBorder)));
QVERIFY(spy.isValid());
QFETCH(ElectricBorder, border);
s->reserve(border, &callback, "callback");
QFETCH(QPoint, trigger);
Cursor::setPos(trigger);
xcb_enter_notify_event_t event;
event.root_x = trigger.x();
event.root_y = trigger.y();
event.event_x = trigger.x();
event.event_y = trigger.y();
event.root = XCB_WINDOW_NONE;
event.child = XCB_WINDOW_NONE;
event.event = s->windows().first();
event.same_screen_focus = 1;
event.time = QDateTime::currentMSecsSinceEpoch();
QVERIFY(s->isEntered(&event));
QVERIFY(spy.isEmpty());
QTEST(Cursor::pos(), "expected");
// do the same without the event, but the check method
Cursor::setPos(trigger);
s->check(trigger, QDateTime::currentDateTime());
QVERIFY(spy.isEmpty());
QTEST(Cursor::pos(), "expected");
}
void TestScreenEdges::testFullScreenBlocking()
{
using namespace KWin;
MockWorkspace ws;
Client client(&ws);
auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig);
config->group("Windows").writeEntry("ElectricBorderPushbackPixels", 1);
config->sync();
auto s = ScreenEdges::self();
s->setConfig(config);
s->init();
TestObject callback;
QSignalSpy spy(&callback, SIGNAL(gotCallback(KWin::ElectricBorder)));
QVERIFY(spy.isValid());
s->reserve(KWin::ElectricLeft, &callback, "callback");
s->reserve(KWin::ElectricBottomRight, &callback, "callback");
// currently there is no active client yet, so check blocking shouldn't do anything
emit s->checkBlocking();
xcb_enter_notify_event_t event;
Cursor::setPos(0, 50);
event.root_x = 0;
event.root_y = 50;
event.event_x = 0;
event.event_y = 50;
event.root = XCB_WINDOW_NONE;
event.child = XCB_WINDOW_NONE;
event.event = s->windows().first();
event.same_screen_focus = 1;
event.time = QDateTime::currentMSecsSinceEpoch();
QVERIFY(s->isEntered(&event));
QVERIFY(spy.isEmpty());
QCOMPARE(Cursor::pos(), QPoint(1, 50));
client.setGeometry(screens()->geometry());
client.setActive(true);
client.setFullScreen(true);
ws.setActiveClient(&client);
emit s->checkBlocking();
// the signal doesn't trigger for corners, let's go over all windows just to be sure that it doesn't call for corners
for (auto e: s->findChildren<Edge*>()) {
e->checkBlocking();
}
// calling again should not trigger
QTest::qWait(160);
Cursor::setPos(0, 50);
event.time = QDateTime::currentMSecsSinceEpoch();
QVERIFY(s->isEntered(&event));
QVERIFY(spy.isEmpty());
// and no pushback
QCOMPARE(Cursor::pos(), QPoint(0, 50));
// let's make the client not fullscreen, which should trigger
client.setFullScreen(false);
emit s->checkBlocking();
event.time = QDateTime::currentMSecsSinceEpoch();
QVERIFY(s->isEntered(&event));
QVERIFY(!spy.isEmpty());
QCOMPARE(Cursor::pos(), QPoint(1, 50));
// let's make the client fullscreen again, but with a geometry not intersecting the left edge
client.setFullScreen(true);
client.setGeometry(client.geometry().translated(10, 0));
emit s->checkBlocking();
spy.clear();
Cursor::setPos(0, 50);
event.time = QDateTime::currentMSecsSinceEpoch();
QVERIFY(s->isEntered(&event));
QVERIFY(spy.isEmpty());
// and a pushback
QCOMPARE(Cursor::pos(), QPoint(1, 50));
// just to be sure, let's set geometry back
client.setGeometry(screens()->geometry());
emit s->checkBlocking();
Cursor::setPos(0, 50);
QVERIFY(s->isEntered(&event));
QVERIFY(spy.isEmpty());
// and no pushback
QCOMPARE(Cursor::pos(), QPoint(0, 50));
// the corner should always trigger
s->unreserve(KWin::ElectricLeft, &callback);
event.event_x = 99;
event.event_y = 99;
event.root_x = 99;
event.root_y = 99;
event.event = s->windows().first();
event.time = QDateTime::currentMSecsSinceEpoch();
Cursor::setPos(99, 99);
QVERIFY(s->isEntered(&event));
QVERIFY(spy.isEmpty());
// and pushback
QCOMPARE(Cursor::pos(), QPoint(98, 98));
QTest::qWait(160);
event.time = QDateTime::currentMSecsSinceEpoch();
Cursor::setPos(99, 99);
QVERIFY(s->isEntered(&event));
QVERIFY(!spy.isEmpty());
}
void TestScreenEdges::testClientEdge()
{
using namespace KWin;
Client client(workspace());
client.setGeometry(QRect(10, 50, 10, 50));
auto s = ScreenEdges::self();
s->init();
s->reserve(&client, KWin::ElectricBottom);
QPointer<Edge> edge = s->findChildren<Edge*>().last();
QCOMPARE(&client, edge->client());
QCOMPARE(edge->isScreenEdge(), true);
QCOMPARE(edge->isCorner(), false);
QCOMPARE(edge->isBottom(), true);
QCOMPARE(edge->isReserved(), false);
// reserve again shouldn't change anything
s->reserve(&client, KWin::ElectricBottom);
QCOMPARE(edge.data(), s->findChildren<Edge*>().last());
QCOMPARE(&client, edge->client());
QCOMPARE(edge->isReserved(), false);
// let's set the client to be hidden
client.setHiddenInternal(true);
s->reserve(&client, KWin::ElectricBottom);
QCOMPARE(edge.data(), s->findChildren<Edge*>().last());
QCOMPARE(edge->isReserved(), true);
// let's change the geometry, which should destroy the edge
QCOMPARE(client.isHiddenInternal(), true);
QCOMPARE(edge.isNull(), false);
client.setGeometry(QRect(2, 2, 20, 20));
QCOMPARE(client.isHiddenInternal(), false);
QCOMPARE(edge.isNull(), true);
// for none of the edges it should be able to be set
for (int i = 0; i < ELECTRIC_COUNT; ++i) {
client.setHiddenInternal(true);
s->reserve(&client, static_cast<ElectricBorder>(i));
QCOMPARE(client.isHiddenInternal(), false);
}
// now let's try to set it and activate it
client.setGeometry(screens()->geometry());
client.setHiddenInternal(true);
s->reserve(&client, KWin::ElectricLeft);
QCOMPARE(client.isHiddenInternal(), true);
xcb_enter_notify_event_t event;
Cursor::setPos(0, 50);
event.root_x = 0;
event.root_y = 50;
event.event_x = 0;
event.event_y = 50;
event.root = XCB_WINDOW_NONE;
event.child = XCB_WINDOW_NONE;
event.event = s->windows().first();
event.same_screen_focus = 1;
event.time = QDateTime::currentMSecsSinceEpoch();
QVERIFY(s->isEntered(&event));
// first attempt should be pushed back and not activated
QCOMPARE(client.isHiddenInternal(), true);
QCOMPARE(Cursor::pos(), QPoint(1, 50));
// but if we wait a little bit it should trigger
QTest::qWait(160);
Cursor::setPos(0, 50);
event.time = QDateTime::currentMSecsSinceEpoch();
QVERIFY(s->isEntered(&event));
QCOMPARE(client.isHiddenInternal(), false);
QCOMPARE(Cursor::pos(), QPoint(1, 50));
// now let's reserve the client for each of the edges, in the end for the right one
client.setHiddenInternal(true);
s->reserve(&client, KWin::ElectricTop);
s->reserve(&client, KWin::ElectricBottom);
QCOMPARE(client.isHiddenInternal(), true);
// corners shouldn't get reserved
s->reserve(&client, KWin::ElectricTopLeft);
QCOMPARE(client.isHiddenInternal(), false);
client.setHiddenInternal(true);
s->reserve(&client, KWin::ElectricTopRight);
QCOMPARE(client.isHiddenInternal(), false);
client.setHiddenInternal(true);
s->reserve(&client, KWin::ElectricBottomRight);
QCOMPARE(client.isHiddenInternal(), false);
client.setHiddenInternal(true);
s->reserve(&client, KWin::ElectricBottomLeft);
QCOMPARE(client.isHiddenInternal(), false);
// now finally reserve on right one
client.setHiddenInternal(true);
s->reserve(&client, KWin::ElectricRight);
QCOMPARE(client.isHiddenInternal(), true);
// now let's emulate the removal of a Client through Workspace
emit workspace()->clientRemoved(&client);
for (auto e : s->findChildren<Edge*>()) {
QVERIFY(!e->client());
}
QCOMPARE(client.isHiddenInternal(), true);
// now let's try to trigger the client showing with the check method instead of enter notify
s->reserve(&client, KWin::ElectricTop);
QCOMPARE(client.isHiddenInternal(), true);
Cursor::setPos(50, 0);
s->check(QPoint(50, 0), QDateTime::currentDateTime());
QCOMPARE(client.isHiddenInternal(), true);
QCOMPARE(Cursor::pos(), QPoint(50, 1));
// and trigger
QTest::qWait(160);
Cursor::setPos(50, 0);
s->check(QPoint(50, 0), QDateTime::currentDateTime());
QCOMPARE(client.isHiddenInternal(), false);
QCOMPARE(Cursor::pos(), QPoint(50, 1));
// unreserve by setting to none edge
s->reserve(&client, KWin::ElectricNone);
// check on previous edge again, should fail
client.setHiddenInternal(true);
Cursor::setPos(50, 0);
s->check(QPoint(50, 0), QDateTime::currentDateTime());
QCOMPARE(client.isHiddenInternal(), true);
QCOMPARE(Cursor::pos(), QPoint(50, 0));
}
QTEST_MAIN(TestScreenEdges)
#include "test_screen_edges.moc"

364
autotests/test_screens.cpp Normal file
View File

@ -0,0 +1,364 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2014 Martin Gräßlin <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 "mock_workspace.h"
#include "../cursor.h"
#include "mock_screens.h"
#include "mock_client.h"
// frameworks
#include <KConfigGroup>
// Qt
#include <QtTest/QtTest>
// Mock
namespace KWin
{
static QPoint s_cursorPos = QPoint();
QPoint Cursor::pos()
{
return s_cursorPos;
}
}
class TestScreens : public QObject
{
Q_OBJECT
private Q_SLOTS:
void init();
void testCurrentFollowsMouse();
void testReconfigure_data();
void testReconfigure();
void testSize_data();
void testSize();
void testCount();
void testIntersecting_data();
void testIntersecting();
void testCurrent_data();
void testCurrent();
void testCurrentClient();
void testCurrentWithFollowsMouse_data();
void testCurrentWithFollowsMouse();
void testCurrentPoint_data();
void testCurrentPoint();
};
void TestScreens::init()
{
KWin::s_cursorPos = QPoint();
}
void TestScreens::testCurrentFollowsMouse()
{
KWin::MockWorkspace ws;
KWin::Screens *screens = KWin::Screens::create(&ws);
QVERIFY(!screens->isCurrentFollowsMouse());
screens->setCurrentFollowsMouse(true);
QVERIFY(screens->isCurrentFollowsMouse());
// setting to same should not do anything
screens->setCurrentFollowsMouse(true);
QVERIFY(screens->isCurrentFollowsMouse());
// setting back to other value
screens->setCurrentFollowsMouse(false);
QVERIFY(!screens->isCurrentFollowsMouse());
// setting to same should not do anything
screens->setCurrentFollowsMouse(false);
QVERIFY(!screens->isCurrentFollowsMouse());
}
void TestScreens::testReconfigure_data()
{
QTest::addColumn<QString>("focusPolicy");
QTest::addColumn<bool>("expectedDefault");
QTest::addColumn<bool>("setting");
QTest::newRow("ClickToFocus") << QStringLiteral("ClickToFocus") << false << true;
QTest::newRow("FocusFollowsMouse") << QStringLiteral("FocusFollowsMouse") << true << false;
QTest::newRow("FocusUnderMouse") << QStringLiteral("FocusUnderMouse") << true << false;
QTest::newRow("FocusStrictlyUnderMouse") << QStringLiteral("FocusStrictlyUnderMouse") << true << false;
}
void TestScreens::testReconfigure()
{
using namespace KWin;
MockWorkspace ws;
Screens::create(&ws);
screens()->reconfigure();
QVERIFY(!screens()->isCurrentFollowsMouse());
QFETCH(QString, focusPolicy);
KSharedConfig::Ptr config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig);
config->group("Windows").writeEntry("FocusPolicy", focusPolicy);
config->group("Windows").sync();
config->sync();
screens()->setConfig(config);
screens()->reconfigure();
QTEST(screens()->isCurrentFollowsMouse(), "expectedDefault");
QFETCH(bool, setting);
config->group("Windows").writeEntry("ActiveMouseScreen", setting);
config->sync();
screens()->reconfigure();
QCOMPARE(screens()->isCurrentFollowsMouse(), setting);
}
void TestScreens::testSize_data()
{
QTest::addColumn< QList<QRect> >("geometries");
QTest::addColumn<QSize>("expectedSize");
QTest::newRow("empty") << QList<QRect>{{QRect()}} << QSize(0, 0);
QTest::newRow("cloned") << QList<QRect>{{QRect{0, 0, 200, 100}, QRect{0, 0, 200, 100}}} << QSize(200, 100);
QTest::newRow("adjacent") << QList<QRect>{{QRect{0, 0, 200, 100}, QRect{200, 100, 400, 300}}} << QSize(600, 400);
QTest::newRow("overlapping") << QList<QRect>{{QRect{-10, -20, 50, 100}, QRect{0, 0, 100, 200}}} << QSize(110, 220);
QTest::newRow("gap") << QList<QRect>{{QRect{0, 0, 10, 20}, QRect{20, 40, 10, 20}}} << QSize(30, 60);
}
void TestScreens::testSize()
{
using namespace KWin;
MockWorkspace ws;
MockScreens *mockScreens = static_cast<MockScreens*>(Screens::create(&ws));
QSignalSpy sizeChangedSpy(screens(), SIGNAL(sizeChanged()));
QVERIFY(sizeChangedSpy.isValid());
QCOMPARE(screens()->size(), QSize(100, 100));
QFETCH(QList<QRect>, geometries);
QVERIFY(!screens()->isChanging());
mockScreens->setGeometries(geometries);
QVERIFY(screens()->isChanging());
QVERIFY(sizeChangedSpy.wait());
QVERIFY(!screens()->isChanging());
QTEST(screens()->size(), "expectedSize");
}
void TestScreens::testCount()
{
using namespace KWin;
MockWorkspace ws;
MockScreens *mockScreens = static_cast<MockScreens*>(Screens::create(&ws));
QSignalSpy countChangedSpy(screens(), SIGNAL(countChanged(int,int)));
QVERIFY(countChangedSpy.isValid());
QCOMPARE(screens()->count(), 1);
// change to two screens
QList<QRect> geometries{{QRect{0, 0, 100, 200}, QRect{100, 0, 100, 200}}};
mockScreens->setGeometries(geometries);
QVERIFY(countChangedSpy.wait());
QCOMPARE(countChangedSpy.count(), 1);
QCOMPARE(countChangedSpy.first().first().toInt(), 1);
QCOMPARE(countChangedSpy.first().last().toInt(), 2);
QCOMPARE(screens()->count(), 2);
// go back to one screen
geometries.takeLast();
mockScreens->setGeometries(geometries);
QVERIFY(countChangedSpy.wait());
QCOMPARE(countChangedSpy.count(), 2);
QCOMPARE(countChangedSpy.last().first().toInt(), 2);
QCOMPARE(countChangedSpy.last().last().toInt(), 1);
QCOMPARE(screens()->count(), 1);
// setting the same geometries shouldn't emit the signal, but we should get a changed signal
QSignalSpy changedSpy(screens(), SIGNAL(changed()));
QVERIFY(changedSpy.isValid());
mockScreens->setGeometries(geometries);
QVERIFY(changedSpy.wait());
QCOMPARE(countChangedSpy.count(), 2);
}
void TestScreens::testIntersecting_data()
{
QTest::addColumn<QList<QRect>>("geometries");
QTest::addColumn<QRect>("testGeometry");
QTest::addColumn<int>("expectedCount");
QTest::newRow("null-rect") << QList<QRect>{{QRect{0, 0, 100, 100}}} << QRect() << 0;
QTest::newRow("non-overlapping") << QList<QRect>{{QRect{0, 0, 100, 100}}} << QRect(100, 0, 100, 100) << 0;
QTest::newRow("in-between") << QList<QRect>{{QRect{0, 0, 10, 20}, QRect{20, 40, 10, 20}}} << QRect(15, 0, 2, 2) << 0;
QTest::newRow("gap-overlapping") << QList<QRect>{{QRect{0, 0, 10, 20}, QRect{20, 40, 10, 20}}} << QRect(9, 10, 200, 200) << 2;
QTest::newRow("larger") << QList<QRect>{{QRect{0, 0, 100, 100}}} << QRect(-10, -10, 200, 200) << 1;
QTest::newRow("several") << QList<QRect>{{QRect{0, 0, 100, 100}, QRect{100, 0, 100, 100}, QRect{200, 100, 100, 100}, QRect{300, 100, 100, 100}}} << QRect(0, 0, 300, 300) << 3;
}
void TestScreens::testIntersecting()
{
using namespace KWin;
MockWorkspace ws;
MockScreens *mockScreens = static_cast<MockScreens*>(Screens::create(&ws));
QSignalSpy changedSpy(screens(), SIGNAL(changed()));
QVERIFY(changedSpy.isValid());
QFETCH(QList<QRect>, geometries);
mockScreens->setGeometries(geometries);
// first is before it's updated
QVERIFY(changedSpy.wait());
// second is after it's updated
QVERIFY(changedSpy.wait());
QFETCH(QRect, testGeometry);
QCOMPARE(screens()->count(), geometries.count());
QTEST(screens()->intersecting(testGeometry), "expectedCount");
}
void TestScreens::testCurrent_data()
{
QTest::addColumn<int>("current");
QTest::addColumn<bool>("signal");
QTest::newRow("unchanged") << 0 << false;
QTest::newRow("changed") << 1 << true;
}
void TestScreens::testCurrent()
{
using namespace KWin;
MockWorkspace ws;
Screens::create(&ws);
QSignalSpy currentChangedSpy(screens(), SIGNAL(currentChanged()));
QVERIFY(currentChangedSpy.isValid());
QFETCH(int, current);
screens()->setCurrent(current);
QCOMPARE(screens()->current(), current);
QTEST(!currentChangedSpy.isEmpty(), "signal");
}
void TestScreens::testCurrentClient()
{
using namespace KWin;
MockWorkspace ws;
MockScreens *mockScreens = static_cast<MockScreens*>(Screens::create(&ws));
QSignalSpy changedSpy(screens(), SIGNAL(changed()));
QVERIFY(changedSpy.isValid());
mockScreens->setGeometries(QList<QRect>{{QRect{0, 0, 100, 100}, QRect{100, 0, 100, 100}}});
// first is before it's updated
QVERIFY(changedSpy.wait());
// second is after it's updated
QVERIFY(changedSpy.wait());
QSignalSpy currentChangedSpy(screens(), SIGNAL(currentChanged()));
QVERIFY(currentChangedSpy.isValid());
// create a mock client
Client *client = new Client(&ws);
client->setScreen(1);
// it's not the active client, so changing won't work
screens()->setCurrent(client);
QVERIFY(currentChangedSpy.isEmpty());
QCOMPARE(screens()->current(), 0);
// making the client active should affect things
client->setActive(true);
ws.setActiveClient(client);
// first of all current should be changed just by the fact that there is an active client
QCOMPARE(screens()->current(), 1);
// but also calling setCurrent should emit the changed signal
screens()->setCurrent(client);
QCOMPARE(currentChangedSpy.count(), 1);
QCOMPARE(screens()->current(), 1);
// setting current with the same client again should not change, though
screens()->setCurrent(client);
QCOMPARE(currentChangedSpy.count(), 1);
// and it should even still be on screen 1 if we make the client non-current again
ws.setActiveClient(nullptr);
client->setActive(false);
QCOMPARE(screens()->current(), 1);
}
void TestScreens::testCurrentWithFollowsMouse_data()
{
QTest::addColumn< QList<QRect> >("geometries");
QTest::addColumn<QPoint>("cursorPos");
QTest::addColumn<int>("expected");
QTest::newRow("empty") << QList<QRect>{{QRect()}} << QPoint(100, 100) << 0;
QTest::newRow("cloned") << QList<QRect>{{QRect{0, 0, 200, 100}, QRect{0, 0, 200, 100}}} << QPoint(50, 50) << 0;
QTest::newRow("adjacent-0") << QList<QRect>{{QRect{0, 0, 200, 100}, QRect{200, 100, 400, 300}}} << QPoint(199, 99) << 0;
QTest::newRow("adjacent-1") << QList<QRect>{{QRect{0, 0, 200, 100}, QRect{200, 100, 400, 300}}} << QPoint(200, 100) << 1;
QTest::newRow("gap") << QList<QRect>{{QRect{0, 0, 10, 20}, QRect{20, 40, 10, 20}}} << QPoint(15, 30) << 1;
}
void TestScreens::testCurrentWithFollowsMouse()
{
using namespace KWin;
MockWorkspace ws;
MockScreens *mockScreens = static_cast<MockScreens*>(Screens::create(&ws));
QSignalSpy changedSpy(screens(), SIGNAL(changed()));
QVERIFY(changedSpy.isValid());
screens()->setCurrentFollowsMouse(true);
QCOMPARE(screens()->current(), 0);
QFETCH(QList<QRect>, geometries);
mockScreens->setGeometries(geometries);
// first is before it's updated
QVERIFY(changedSpy.wait());
// second is after it's updated
QVERIFY(changedSpy.wait());
QFETCH(QPoint, cursorPos);
KWin::s_cursorPos = cursorPos;
QTEST(screens()->current(), "expected");
}
void TestScreens::testCurrentPoint_data()
{
QTest::addColumn< QList<QRect> >("geometries");
QTest::addColumn<QPoint>("cursorPos");
QTest::addColumn<int>("expected");
QTest::newRow("empty") << QList<QRect>{{QRect()}} << QPoint(100, 100) << 0;
QTest::newRow("cloned") << QList<QRect>{{QRect{0, 0, 200, 100}, QRect{0, 0, 200, 100}}} << QPoint(50, 50) << 0;
QTest::newRow("adjacent-0") << QList<QRect>{{QRect{0, 0, 200, 100}, QRect{200, 100, 400, 300}}} << QPoint(199, 99) << 0;
QTest::newRow("adjacent-1") << QList<QRect>{{QRect{0, 0, 200, 100}, QRect{200, 100, 400, 300}}} << QPoint(200, 100) << 1;
QTest::newRow("gap") << QList<QRect>{{QRect{0, 0, 10, 20}, QRect{20, 40, 10, 20}}} << QPoint(15, 30) << 1;
}
void TestScreens::testCurrentPoint()
{
using namespace KWin;
MockWorkspace ws;
MockScreens *mockScreens = static_cast<MockScreens*>(Screens::create(&ws));
QSignalSpy changedSpy(screens(), SIGNAL(changed()));
QVERIFY(changedSpy.isValid());
QFETCH(QList<QRect>, geometries);
mockScreens->setGeometries(geometries);
// first is before it's updated
QVERIFY(changedSpy.wait());
// second is after it's updated
QVERIFY(changedSpy.wait());
QFETCH(QPoint, cursorPos);
screens()->setCurrent(cursorPos);
QTEST(screens()->current(), "expected");
}
QTEST_MAIN(TestScreens)
#include "test_screens.moc"

View File

@ -496,7 +496,7 @@ void TestVirtualDesktops::updateLayout_data()
QTest::addColumn<uint>("desktop");
QTest::addColumn<QSize>("result");
QTest::newRow("01") << (uint)1 << QSize(1, 2);
QTest::newRow("01") << (uint)1 << QSize(1, 1);
QTest::newRow("02") << (uint)2 << QSize(1, 2);
QTest::newRow("03") << (uint)3 << QSize(2, 2);
QTest::newRow("04") << (uint)4 << QSize(2, 2);

View File

@ -167,7 +167,6 @@ private Q_SLOTS:
void testOperatorMultiplyAssign();
void testOperatorPlus();
void testMultiplyOpacity();
void testMultiplyDecorationOpacity();
void testMultiplySaturation();
void testMultiplyBrightness();
};
@ -189,7 +188,6 @@ void TestWindowPaintData::testCtor()
QCOMPARE(data.rotationOrigin(), QVector3D());
QCOMPARE(data.rotationAxis(), QVector3D(0.0, 0.0, 1.0));
QCOMPARE(data.opacity(), 0.5);
QCOMPARE(data.decorationOpacity(), 1.0);
QCOMPARE(data.brightness(), 1.0);
QCOMPARE(data.saturation(), 1.0);
}
@ -212,7 +210,6 @@ void TestWindowPaintData::testCopyCtor()
QCOMPARE(data2.rotationOrigin(), QVector3D());
QCOMPARE(data2.rotationAxis(), QVector3D(0.0, 0.0, 1.0));
QCOMPARE(data2.opacity(), 1.0);
QCOMPARE(data2.decorationOpacity(), 1.0);
QCOMPARE(data2.brightness(), 1.0);
QCOMPARE(data2.saturation(), 1.0);
@ -222,7 +219,6 @@ void TestWindowPaintData::testCopyCtor()
data2.setRotationOrigin(QVector3D(1.0, 2.0, 3.0));
data2.setRotationAxis(QVector3D(1.0, 1.0, 0.0));
data2.setOpacity(0.1);
data2.setDecorationOpacity(0.2);
data2.setBrightness(0.3);
data2.setSaturation(0.4);
@ -238,7 +234,6 @@ void TestWindowPaintData::testCopyCtor()
QCOMPARE(data3.rotationOrigin(), QVector3D(1.0, 2.0, 3.0));
QCOMPARE(data3.rotationAxis(), QVector3D(1.0, 1.0, 0.0));
QCOMPARE(data3.opacity(), 0.1);
QCOMPARE(data3.decorationOpacity(), 0.2);
QCOMPARE(data3.brightness(), 0.3);
QCOMPARE(data3.saturation(), 0.4);
}
@ -303,22 +298,6 @@ void TestWindowPaintData::testMultiplyBrightness()
QCOMPARE(0.6, data.brightness());
// just for safety
QCOMPARE(1.0, data.opacity());
QCOMPARE(1.0, data.decorationOpacity());
QCOMPARE(1.0, data.saturation());
}
void TestWindowPaintData::testMultiplyDecorationOpacity()
{
MockEffectWindowHelper helper;
MockEffectWindow w(&helper);
WindowPaintData data(&w);
QCOMPARE(0.2, data.multiplyDecorationOpacity(0.2));
QCOMPARE(0.2, data.decorationOpacity());
QCOMPARE(0.6, data.multiplyDecorationOpacity(3.0));
QCOMPARE(0.6, data.decorationOpacity());
// just for safety
QCOMPARE(1.0, data.brightness());
QCOMPARE(1.0, data.opacity());
QCOMPARE(1.0, data.saturation());
}
@ -333,7 +312,6 @@ void TestWindowPaintData::testMultiplyOpacity()
QCOMPARE(0.6, data.opacity());
// just for safety
QCOMPARE(1.0, data.brightness());
QCOMPARE(1.0, data.decorationOpacity());
QCOMPARE(1.0, data.saturation());
}
@ -349,7 +327,6 @@ void TestWindowPaintData::testMultiplySaturation()
// just for safety
QCOMPARE(1.0, data.brightness());
QCOMPARE(1.0, data.opacity());
QCOMPARE(1.0, data.decorationOpacity());
}
QTEST_MAIN(TestWindowPaintData)

View File

@ -39,6 +39,7 @@ private Q_SLOTS:
void mapUnmap();
void geometry();
void destroy();
void destroyNotManaged();
};
void TestXcbWindow::defaultCtor()
@ -95,6 +96,10 @@ void TestXcbWindow::create()
window.create(geometry, XCB_CW_OVERRIDE_REDIRECT, values);
QCOMPARE(window.isValid(), true);
QVERIFY(window != XCB_WINDOW_NONE);
// and reset again
window.reset();
QCOMPARE(window.isValid(), false);
QVERIFY(window == XCB_WINDOW_NONE);
}
void TestXcbWindow::mapUnmap()
@ -115,6 +120,11 @@ void TestXcbWindow::mapUnmap()
Xcb::WindowAttributes attribs3(window);
QCOMPARE(attribs3.isNull(), false);
QVERIFY(attribs3->map_state == XCB_MAP_STATE_UNMAPPED);
// map, unmap shouldn't fail for an invalid window, it's just ignored
window.reset();
window.map();
window.unmap();
}
void TestXcbWindow::geometry()
@ -131,6 +141,12 @@ void TestXcbWindow::geometry()
Xcb::WindowGeometry windowGeometry2(window);
QCOMPARE(windowGeometry2.isNull(), false);
QCOMPARE(windowGeometry2.rect(), geometry2);
// setting a geometry on an invalid window should be ignored
window.reset();
window.setGeometry(geometry2);
Xcb::WindowGeometry windowGeometry3(window);
QCOMPARE(windowGeometry3.isNull(), true);
}
void TestXcbWindow::destroy()
@ -170,5 +186,19 @@ void TestXcbWindow::destroy()
free(error);
}
void TestXcbWindow::destroyNotManaged()
{
Xcb::Window window;
// just destroy the non-existing window
window.reset();
// now let's add a window
window.reset(createWindow(), false);
xcb_window_t w = window;
window.reset();
Xcb::WindowAttributes attribs(w);
QVERIFY(attribs);
}
KWIN_TEST_MAIN(TestXcbWindow)
#include "test_xcb_window.moc"

View File

@ -50,22 +50,23 @@ private Q_SLOTS:
void testTransientFor();
void testPropertyByteArray();
void testPropertyBool();
void testAtom();
private:
void testEmpty(WindowGeometry &geometry);
void testGeometry(WindowGeometry &geometry, const QRect &rect);
xcb_window_t m_testWindow;
Window m_testWindow;
};
void TestXcbWrapper::init()
{
m_testWindow = XCB_WINDOW_NONE;
const uint32_t values[] = { true };
m_testWindow.create(QRect(0, 0, 10, 10), XCB_WINDOW_CLASS_INPUT_ONLY, XCB_CW_OVERRIDE_REDIRECT, values);
QVERIFY(m_testWindow.isValid());
}
void TestXcbWrapper::cleanup()
{
if (m_testWindow != XCB_WINDOW_NONE) {
xcb_destroy_window(connection(), m_testWindow);
}
m_testWindow.reset();
}
void TestXcbWrapper::testEmpty(WindowGeometry &geometry)
@ -79,7 +80,7 @@ void TestXcbWrapper::testEmpty(WindowGeometry &geometry)
void TestXcbWrapper::testGeometry(WindowGeometry &geometry, const QRect &rect)
{
QCOMPARE(geometry.window(), m_testWindow);
QCOMPARE(geometry.window(), (xcb_window_t)m_testWindow);
// now lets retrieve some data
QCOMPARE(geometry.rect(), rect);
QVERIFY(geometry.isRetrieved());
@ -101,9 +102,6 @@ void TestXcbWrapper::defaultCtor()
void TestXcbWrapper::normalCtor()
{
m_testWindow = createWindow();
QVERIFY(m_testWindow != noneWindow());
WindowGeometry geometry(m_testWindow);
QVERIFY(!geometry.isRetrieved());
testGeometry(geometry, QRect(0, 0, 10, 10));
@ -121,8 +119,6 @@ void TestXcbWrapper::copyCtorEmpty()
void TestXcbWrapper::copyCtorBeforeRetrieve()
{
m_testWindow = createWindow();
QVERIFY(m_testWindow != noneWindow());
WindowGeometry geometry(m_testWindow);
QVERIFY(!geometry.isRetrieved());
WindowGeometry other(geometry);
@ -135,8 +131,6 @@ void TestXcbWrapper::copyCtorBeforeRetrieve()
void TestXcbWrapper::copyCtorAfterRetrieve()
{
m_testWindow = createWindow();
QVERIFY(m_testWindow != noneWindow());
WindowGeometry geometry(m_testWindow);
QVERIFY(geometry);
QVERIFY(geometry.isRetrieved());
@ -161,12 +155,15 @@ void TestXcbWrapper::assignementEmpty()
testEmpty(geometry);
testEmpty(other);
QVERIFY(!other.isRetrieved());
// test assignment to self
geometry = geometry;
other = other;
testEmpty(geometry);
testEmpty(other);
}
void TestXcbWrapper::assignmentBeforeRetrieve()
{
m_testWindow = createWindow();
QVERIFY(m_testWindow != noneWindow());
WindowGeometry geometry(m_testWindow);
WindowGeometry other = geometry;
QVERIFY(geometry.isRetrieved());
@ -177,15 +174,17 @@ void TestXcbWrapper::assignmentBeforeRetrieve()
other = WindowGeometry(m_testWindow);
QVERIFY(!other.isRetrieved());
QCOMPARE(other.window(), m_testWindow);
QCOMPARE(other.window(), (xcb_window_t)m_testWindow);
other = WindowGeometry();
testEmpty(geometry);
// test assignment to self
geometry = geometry;
other = other;
testEmpty(geometry);
}
void TestXcbWrapper::assignmentAfterRetrieve()
{
m_testWindow = createWindow();
QVERIFY(m_testWindow != noneWindow());
WindowGeometry geometry(m_testWindow);
QVERIFY(geometry);
QVERIFY(geometry.isRetrieved());
@ -195,6 +194,13 @@ void TestXcbWrapper::assignmentAfterRetrieve()
QVERIFY(other.isRetrieved());
testGeometry(other, QRect(0, 0, 10, 10));
// test assignment to self
geometry = geometry;
other = other;
testEmpty(geometry);
testGeometry(other, QRect(0, 0, 10, 10));
// set to empty again
other = WindowGeometry();
testEmpty(other);
}
@ -207,7 +213,6 @@ void TestXcbWrapper::discard()
WindowGeometry *geometry = new WindowGeometry();
delete geometry;
m_testWindow = createWindow();
geometry = new WindowGeometry(m_testWindow);
delete geometry;
@ -218,8 +223,6 @@ void TestXcbWrapper::discard()
void TestXcbWrapper::testQueryTree()
{
m_testWindow = createWindow();
QVERIFY(m_testWindow != noneWindow());
Tree tree(m_testWindow);
// should have root as parent
QCOMPARE(tree.parent(), static_cast<xcb_window_t>(QX11Info::appRootWindow()));
@ -251,29 +254,27 @@ void TestXcbWrapper::testQueryTree()
void TestXcbWrapper::testCurrentInput()
{
m_testWindow = createWindow();
xcb_connection_t *c = QX11Info::connection();
xcb_map_window(c, m_testWindow);
m_testWindow.map();
QX11Info::setAppTime(QX11Info::getTimestamp());
// let's set the input focus
xcb_set_input_focus(c, XCB_INPUT_FOCUS_PARENT, m_testWindow, QX11Info::appTime());
m_testWindow.focus(XCB_INPUT_FOCUS_PARENT, QX11Info::appTime());
xcb_flush(c);
CurrentInput input;
QCOMPARE(input.window(), m_testWindow);
QCOMPARE(input.window(), (xcb_window_t)m_testWindow);
// creating a copy should make the input object have no window any more
CurrentInput input2(input);
QCOMPARE(input2.window(), m_testWindow);
QCOMPARE(input2.window(), (xcb_window_t)m_testWindow);
QCOMPARE(input.window(), xcb_window_t(XCB_WINDOW_NONE));
}
void TestXcbWrapper::testTransientFor()
{
m_testWindow = createWindow();
TransientFor transient(m_testWindow);
QCOMPARE(transient.window(), m_testWindow);
QCOMPARE(transient.window(), (xcb_window_t)m_testWindow);
// our m_testWindow doesn't have a transient for hint
xcb_window_t compareWindow = XCB_WINDOW_NONE;
QVERIFY(!transient.getTransientFor(&compareWindow));
@ -292,18 +293,18 @@ void TestXcbWrapper::testTransientFor()
// let's get another transient object
TransientFor realTransient(transientWindow);
QVERIFY(realTransient.getTransientFor(&compareWindow));
QCOMPARE(compareWindow, m_testWindow);
QCOMPARE(compareWindow, (xcb_window_t)m_testWindow);
ok = false;
QCOMPARE(realTransient.value<xcb_window_t>(32, XCB_ATOM_WINDOW, XCB_WINDOW_NONE, &ok), m_testWindow);
QCOMPARE(realTransient.value<xcb_window_t>(32, XCB_ATOM_WINDOW, XCB_WINDOW_NONE, &ok), (xcb_window_t)m_testWindow);
QVERIFY(ok);
ok = false;
QCOMPARE(realTransient.value<xcb_window_t>(XCB_WINDOW_NONE, &ok), m_testWindow);
QCOMPARE(realTransient.value<xcb_window_t>(XCB_WINDOW_NONE, &ok), (xcb_window_t)m_testWindow);
QVERIFY(ok);
ok = false;
QCOMPARE(realTransient.value<xcb_window_t>(), m_testWindow);
QCOMPARE(realTransient.value<xcb_window_t*>(nullptr, &ok)[0], m_testWindow);
QCOMPARE(realTransient.value<xcb_window_t>(), (xcb_window_t)m_testWindow);
QCOMPARE(realTransient.value<xcb_window_t*>(nullptr, &ok)[0], (xcb_window_t)m_testWindow);
QVERIFY(ok);
QCOMPARE(realTransient.value<xcb_window_t*>()[0], m_testWindow);
QCOMPARE(realTransient.value<xcb_window_t*>()[0], (xcb_window_t)m_testWindow);
// test for a not existing window
TransientFor doesntExist(XCB_WINDOW_NONE);
@ -402,5 +403,23 @@ void TestXcbWrapper::testPropertyBool()
QVERIFY(!ok);
}
void TestXcbWrapper::testAtom()
{
Atom atom(QByteArrayLiteral("WM_CLIENT_MACHINE"));
QCOMPARE(atom.name(), QByteArrayLiteral("WM_CLIENT_MACHINE"));
QVERIFY(atom == XCB_ATOM_WM_CLIENT_MACHINE);
QVERIFY(atom.isValid());
// test the const paths
const Atom &atom2(atom);
QVERIFY(atom2.isValid());
QVERIFY(atom2 == XCB_ATOM_WM_CLIENT_MACHINE);
QCOMPARE(atom2.name(), QByteArrayLiteral("WM_CLIENT_MACHINE"));
//destroy before retrieved
Atom atom3(QByteArrayLiteral("WM_CLIENT_MACHINE"));
QCOMPARE(atom3.name(), QByteArrayLiteral("WM_CLIENT_MACHINE"));
}
KWIN_TEST_MAIN(TestXcbWrapper)
#include "test_xcb_wrapper.moc"

1
autotests/workspace.h Normal file
View File

@ -0,0 +1 @@
#include "mock_workspace.h"

View File

@ -200,7 +200,6 @@ Client::Client()
, delayedMoveResizeTimer(NULL)
, m_colormap(XCB_COLORMAP_NONE)
, in_group(NULL)
, m_windowGroup(XCB_WINDOW_NONE)
, tab_group(NULL)
, in_layer(UnknownLayer)
, ping_timer(NULL)
@ -259,7 +258,6 @@ Client::Client()
noborder = false;
app_noborder = false;
motif_noborder = false;
urgency = false;
ignore_focus_stealing = false;
demands_attention = false;
check_active_modal = false;
@ -268,7 +266,6 @@ Client::Client()
Ptakefocus = 0;
Pcontexthelp = 0;
Pping = 0;
input = false;
skip_pager = false;
max_mode = MaximizeRestore;
@ -984,7 +981,7 @@ void Client::setShade(ShadeMode mode)
QSize s(sizeForClientSize(clientSize()));
shade_geometry_change = false;
plainResize(s);
if ((shade_mode == ShadeHover || shade_mode == ShadeActivated) && rules()->checkAcceptFocus(input))
if ((shade_mode == ShadeHover || shade_mode == ShadeActivated) && rules()->checkAcceptFocus(info->input()))
setActive(true);
if (shade_mode == ShadeHover) {
ToplevelList order = workspace()->stackingOrder();
@ -1632,7 +1629,7 @@ void Client::takeFocus()
previous_focus_timestamp = xTime();
previous_client = this;
#endif
if (rules()->checkAcceptFocus(input))
if (rules()->checkAcceptFocus(info->input()))
m_client.focus();
else
demandAttention(false); // window cannot take input, at least withdraw urgency
@ -1685,13 +1682,13 @@ QString Client::readName() const
}
// The list is taken from http://www.unicode.org/reports/tr9/ (#154840)
QChar LRM(0x200E);
QChar RLM(0x200F);
QChar LRE(0x202A);
QChar RLE(0x202B);
QChar LRO(0x202D);
QChar RLO(0x202E);
QChar PDF(0x202C);
static const QChar LRM(0x200E);
static const QChar RLM(0x200F);
static const QChar LRE(0x202A);
static const QChar RLE(0x202B);
static const QChar LRO(0x202D);
static const QChar RLO(0x202E);
static const QChar PDF(0x202C);
void Client::setCaption(const QString& _s, bool force)
{
@ -1917,25 +1914,6 @@ void Client::setClientShown(bool shown)
}
}
void Client::getWMHints()
{
XWMHints* hints = XGetWMHints(display(), window());
input = true;
m_windowGroup = XCB_WINDOW_NONE;
urgency = false;
if (hints) {
if (hints->flags & InputHint)
input = hints->input;
if (hints->flags & WindowGroupHint)
m_windowGroup = hints->window_group;
urgency = !!(hints->flags & UrgencyHint); // Need boolean, it's a uint bitfield
XFree((char*)hints);
}
checkGroup();
updateUrgency();
updateAllowedActions(); // Group affects isMinimizable()
}
void Client::getMotifHints()
{
bool mgot_noborder, mnoborder, mresize, mmove, mminimize, mmaximize, mclose;
@ -2128,7 +2106,7 @@ bool Client::wantsTabFocus() const
bool Client::wantsInput() const
{
return rules()->checkAcceptFocus(input || Ptakefocus);
return rules()->checkAcceptFocus(info->input() || Ptakefocus);
}
bool Client::isSpecialWindow() const

View File

@ -918,7 +918,6 @@ private:
uint Ptakefocus : 1;///< Does the window understand the TakeFocus protocol?
uint Pcontexthelp : 1; ///< Does the window understand the ContextHelp protocol?
uint Pping : 1; ///< Does it support _NET_WM_PING?
uint input : 1; ///< Does the window want input in its wm_hints
uint skip_pager : 1;
uint skip_switcher : 1;
uint motif_may_resize : 1;
@ -931,12 +930,10 @@ private:
uint noborder : 1;
uint app_noborder : 1; ///< App requested no border via window type, shape extension, etc.
uint motif_noborder : 1; ///< App requested no border via Motif WM hints
uint urgency : 1; ///< XWMHints, UrgencyHint
uint ignore_focus_stealing : 1; ///< Don't apply focus stealing prevention to this client
uint demands_attention : 1;
bool blocks_compositing;
WindowRules client_rules;
void getWMHints();
void getWindowProtocols();
QIcon m_icon;
Qt::CursorShape m_cursor;
@ -956,7 +953,6 @@ private:
xcb_colormap_t m_colormap;
QString cap_normal, cap_iconic, cap_suffix, cap_deco;
Group* in_group;
xcb_window_t m_windowGroup;
TabGroup* tab_group;
Layer in_layer;
QTimer* ping_timer;

View File

@ -1,5 +1,3 @@
project(aurorae)
add_subdirectory(src)
#add_subdirectory(themes/example-deco)

View File

@ -16,7 +16,7 @@ Name[eo]=Aurorae Ornamaĵ-etosa Modulo
Name[es]=Motor de temas de decoración Aurorae
Name[et]=Aurorae dekoratsioonide teema mootor
Name[eu]=Aurorae apainketa-gaiaren motorra
Name[fi]=Revontulet-koristusteemakone
Name[fi]=Kehysten teemamoottori Aurorae
Name[fr]=Moteur de thèmes pour la décoration « Aurorae »
Name[fy]=Aurorae dekoraasje tema motor
Name[ga]=Inneall Téama Maisiúcháin Aurorae

View File

@ -14,7 +14,7 @@ Comment[en_GB]=KWin Window Decoration
Comment[es]=Decoración de ventanas de KWin
Comment[et]=KWini akna dekoratsioon
Comment[eu]=KWin leihoen apainketa
Comment[fi]=KWin-ikkunakoristus
Comment[fi]=KWin-ikkunan kehys
Comment[fr]=Décorations de fenêtres KWin
Comment[ga]=Maisiúchán Fuinneog KWin
Comment[gl]=Decoración de xanela de Kwin
@ -36,7 +36,7 @@ Comment[pl]=Wystrój okien KWin
Comment[pt]=Decoração das Janelas do KWin
Comment[pt_BR]=Decorações de janelas do KWin
Comment[ro]=Decorații de fereastră KWin
Comment[ru]=Оформление окон KWin
Comment[ru]=Оформление окон KWin
Comment[sk]=Dekorácie okien KWin
Comment[sl]=Okraski oken KWin
Comment[sr]=К‑винова декорација прозора
@ -46,6 +46,7 @@ Comment[sr@latin]=KWinova dekoracija prozora
Comment[sv]=Kwin-fönsterdekorationer
Comment[tr]=KWin Pencere Dekorasyonu
Comment[uk]=Обрамлення вікон KWin
Comment[vi]=Khung viền cửa sổ KWin
Comment[x-test]=xxKWin Window Decorationxx
Comment[zh_CN]=KWin 窗口装饰
Comment[zh_TW]=KWin 視窗裝飾

View File

@ -104,7 +104,7 @@ void ThemeConfig::load(const KConfig &conf)
m_alignment = Qt::AlignLeft;
}
else if (alignment == QStringLiteral("center")) {
m_alignment = Qt::AlignCenter;
m_alignment = Qt::AlignHCenter;
}
else {
m_alignment = Qt::AlignRight;

View File

@ -129,6 +129,7 @@ Comment[sr@latin]=Klasična tema poznata iz KDEa 3
Comment[sv]=Det klassiska temat känt från KDE 3
Comment[tr]=KDE 3'ten bilinen alışılmış tema
Comment[uk]=Класична тема, відома з часів KDE 3
Comment[vi]=Sắc thái cổ điển được biết đến từ KDE 3
Comment[x-test]=xxThe classic theme known from KDE 3xx
Comment[zh_CN]=KDE 3 时代的经典主题
Comment[zh_TW]=從 KDE3 以來的傳統主題

View File

@ -0,0 +1,125 @@
#.rst:
# FindLibinput
# -------
#
# Try to find libinput on a Unix system.
#
# This will define the following variables:
#
# ``Libinput_FOUND``
# True if (the requested version of) libinput is available
# ``Libinput_VERSION``
# The version of libinput
# ``Libinput_LIBRARIES``
# This can be passed to target_link_libraries() instead of the ``Libinput::Libinput``
# target
# ``Libinput_INCLUDE_DIRS``
# This should be passed to target_include_directories() if the target is not
# used for linking
# ``Libinput_DEFINITIONS``
# This should be passed to target_compile_options() if the target is not
# used for linking
#
# If ``Libinput_FOUND`` is TRUE, it will also define the following imported target:
#
# ``Libinput::Libinput``
# The libinput library
#
# In general we recommend using the imported target, as it is easier to use.
# Bear in mind, however, that if the target is in the link interface of an
# exported library, it must be made available by the package config file.
#=============================================================================
# Copyright 2014 Alex Merry <alex.merry@kde.org>
# Copyright 2014 Martin Gräßlin <mgraesslin@kde.org>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#=============================================================================
if(CMAKE_VERSION VERSION_LESS 2.8.12)
message(FATAL_ERROR "CMake 2.8.12 is required by FindLibinput.cmake")
endif()
if(CMAKE_MINIMUM_REQUIRED_VERSION VERSION_LESS 2.8.12)
message(AUTHOR_WARNING "Your project should require at least CMake 2.8.12 to use FindLibinput.cmake")
endif()
if(NOT WIN32)
# Use pkg-config to get the directories and then use these values
# in the FIND_PATH() and FIND_LIBRARY() calls
find_package(PkgConfig)
pkg_check_modules(PKG_Libinput QUIET libinput)
set(Libinput_DEFINITIONS ${PKG_Libinput_CFLAGS_OTHER})
set(Libinput_VERSION ${PKG_Libinput_VERSION})
find_path(Libinput_INCLUDE_DIR
NAMES
libinput.h
HINTS
${PKG_Libinput_INCLUDE_DIRS}
)
find_library(Libinput_LIBRARY
NAMES
input
HINTS
${PKG_Libinput_LIBRARY_DIRS}
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Libinput
FOUND_VAR
Libinput_FOUND
REQUIRED_VARS
Libinput_LIBRARY
Libinput_INCLUDE_DIR
VERSION_VAR
Libinput_VERSION
)
if(Libinput_FOUND AND NOT TARGET Libinput::Libinput)
add_library(Libinput::Libinput UNKNOWN IMPORTED)
set_target_properties(Libinput::Libinput PROPERTIES
IMPORTED_LOCATION "${Libinput_LIBRARY}"
INTERFACE_COMPILE_OPTIONS "${Libinput_DEFINITIONS}"
INTERFACE_INCLUDE_DIRECTORIES "${Libinput_INCLUDE_DIR}"
)
endif()
mark_as_advanced(Libinput_LIBRARY Libinput_INCLUDE_DIR)
# compatibility variables
set(Libinput_LIBRARIES ${Libinput_LIBRARY})
set(Libinput_INCLUDE_DIRS ${Libinput_INCLUDE_DIR})
set(Libinput_VERSION_STRING ${Libinput_VERSION})
else()
message(STATUS "FindLibinput.cmake cannot find libinput on Windows systems.")
set(Libinput_FOUND FALSE)
endif()
include(FeatureSummary)
set_package_properties(Libinput PROPERTIES
URL "http://www.freedesktop.org/wiki/Software/libinput/"
DESCRIPTION "Library to handle input devices in Wayland compositors and to provide a generic X.Org input driver."
)

View File

@ -0,0 +1,29 @@
# - Try to find the UDev library
# Once done this will define
#
# UDEV_FOUND - system has UDev
# UDEV_INCLUDE_DIR - the libudev include directory
# UDEV_LIBS - The libudev libraries
# Copyright (c) 2010, Rafael Fernández López, <ereslibre@kde.org>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
find_path(UDEV_INCLUDE_DIR libudev.h)
find_library(UDEV_LIBS udev)
if(UDEV_INCLUDE_DIR AND UDEV_LIBS)
include(CheckFunctionExists)
include(CMakePushCheckState)
cmake_push_check_state()
set(CMAKE_REQUIRED_LIBRARIES ${UDEV_LIBS} )
cmake_pop_check_state()
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(UDev DEFAULT_MSG UDEV_INCLUDE_DIR UDEV_LIBS)
mark_as_advanced(UDEV_INCLUDE_DIR UDEV_LIBS)

View File

@ -89,7 +89,8 @@ Compositor::Compositor(QObject* workspace)
, m_finishing(false)
, m_timeSinceLastVBlank(0)
, m_scene(NULL)
, m_waitingForFrameRendered(false)
, m_bufferSwapPending(false)
, m_composeAtSwapCompletion(false)
{
qRegisterMetaType<Compositor::SuspendReason>("Compositor::SuspendReason");
connect(&unredirectTimer, SIGNAL(timeout()), SLOT(delayedCheckUnredirect()));
@ -114,14 +115,16 @@ Compositor::Compositor(QObject* workspace)
if (kwinApp()->operationMode() != Application::OperationModeX11) {
connect(Wayland::WaylandBackend::self(), &Wayland::WaylandBackend::systemCompositorDied, this, &Compositor::finish);
connect(Wayland::WaylandBackend::self(), &Wayland::WaylandBackend::backendReady, this, &Compositor::setup);
}
} else
#endif
{
// delay the call to setup by one event cycle
// The ctor of this class is invoked from the Workspace ctor, that means before
// Workspace is completely constructed, so calling Workspace::self() would result
// in undefined behavior. This is fixed by using a delayed invocation.
QMetaObject::invokeMethod(this, "setup", Qt::QueuedConnection);
}
// register DBus
new CompositorDBusInterface(this);
@ -558,22 +561,35 @@ void Compositor::timerEvent(QTimerEvent *te)
QObject::timerEvent(te);
}
void Compositor::lastFrameRendered()
void Compositor::aboutToSwapBuffers()
{
if (!m_waitingForFrameRendered) {
return;
assert(!m_bufferSwapPending);
m_bufferSwapPending = true;
}
void Compositor::bufferSwapComplete()
{
assert(m_bufferSwapPending);
m_bufferSwapPending = false;
if (m_composeAtSwapCompletion) {
m_composeAtSwapCompletion = false;
performCompositing();
}
m_waitingForFrameRendered = false;
performCompositing();
}
void Compositor::performCompositing()
{
if (m_scene->usesOverlayWindow() && !isOverlayWindowVisible())
return; // nothing is visible anyway
if (!m_scene->isLastFrameRendered()) {
m_waitingForFrameRendered = true;
return; // frame wouldn't make it on the screen
// If a buffer swap is still pending, we return to the event loop and
// continue processing events until the swap has completed.
if (m_bufferSwapPending) {
m_composeAtSwapCompletion = true;
compositeTimer.stop();
return;
}
// Create a list of all windows in the stacking order
@ -587,8 +603,10 @@ void Compositor::performCompositing()
damaged << win;
}
if (damaged.count() > 0)
if (damaged.count() > 0) {
m_scene->triggerFence();
xcb_flush(connection());
}
// Move elevated windows to the top of the stacking order
foreach (EffectWindow *c, static_cast<EffectsHandlerImpl *>(effects)->elevatedWindows()) {
@ -672,6 +690,10 @@ void Compositor::setCompositeTimer()
if (!hasScene()) // should not really happen, but there may be e.g. some damage events still pending
return;
// Don't start the timer if we're waiting for a swap event
if (m_bufferSwapPending && m_composeAtSwapCompletion)
return;
uint waitTime = 1;
if (m_scene->blocksForRetrace()) {

View File

@ -90,13 +90,6 @@ public:
* Set's the Scene's Overlay X Window visibility to @p visible.
**/
void setOverlayWindowVisibility(bool visible);
/**
* @brief Hook for the Scene to notify about a that the last frame got rendered.
*
* In case the Compositor was waiting for the frame being rendered, the next rendering process
* is triggered.
*/
void lastFrameRendered();
Scene *scene() {
return m_scene;
@ -178,6 +171,18 @@ public Q_SLOTS:
void updateCompositeBlocking();
void updateCompositeBlocking(KWin::Client* c);
/**
* Notifies the compositor that SwapBuffers() is about to be called.
* Rendering of the next frame will be deferred until bufferSwapComplete()
* is called.
*/
void aboutToSwapBuffers();
/**
* Notifies the compositor that a pending buffer swap has completed.
*/
void bufferSwapComplete();
Q_SIGNALS:
void compositingToggled(bool active);
@ -229,7 +234,8 @@ private:
bool m_starting; // start() sets this variable while starting
qint64 m_timeSinceLastVBlank;
Scene *m_scene;
bool m_waitingForFrameRendered;
bool m_bufferSwapPending;
bool m_composeAtSwapCompletion;
KWIN_SINGLETON_VARIABLE(Compositor, s_compositor)
};

View File

@ -116,20 +116,9 @@ QString CompositingPrefs::compositingNotPossibleReason()
return QString();
}
static bool s_glxDetected = false;
static bool s_hasGlx = false;
bool CompositingPrefs::hasGlx()
{
if (s_glxDetected) {
return s_hasGlx;
}
#ifndef KWIN_HAVE_OPENGLES
int event_base, error_base;
s_hasGlx = glXQueryExtension(display(), &event_base, &error_base);
#endif
s_glxDetected = true;
return s_hasGlx;
return Xcb::Extensions::self()->hasGlx();
}
} // namespace

View File

@ -7,11 +7,12 @@
#define KWIN_NAME "${KWIN_NAME}"
#define KWIN_INTERNAL_NAME_X11 "${KWIN_INTERNAL_NAME_X11}"
#define KWIN_CONFIG "${KWIN_NAME}rc"
#define KWIN_VERSION_STRING "${KWIN_VERSION}"
#define KWIN_VERSION_STRING "${PROJECT_VERSION}"
#define KWIN_KILLER_BIN "${CMAKE_INSTALL_PREFIX}/${LIBEXEC_INSTALL_DIR}/kwin_killer_helper"
#cmakedefine01 HAVE_WAYLAND
#cmakedefine01 HAVE_WAYLAND_EGL
#cmakedefine01 HAVE_XKB
#cmakedefine01 HAVE_INPUT
/* Define to 1 if you have the <unistd.h> header file. */
#cmakedefine HAVE_UNISTD_H 1

View File

@ -43,13 +43,18 @@ namespace KWin
DBusInterface::DBusInterface(QObject *parent)
: QObject(parent)
, m_serviceName(QStringLiteral("org.kde.KWin"))
{
(void) new KWinAdaptor(this);
QDBusConnection dbus = QDBusConnection::sessionBus();
dbus.registerObject(QStringLiteral("/KWin"), this);
if (!dbus.registerService(QStringLiteral("org.kde.KWin"))) {
QDBusServiceWatcher *dog = new QDBusServiceWatcher(QStringLiteral("org.kde.KWin"), dbus, QDBusServiceWatcher::WatchForUnregistration, this);
const QByteArray dBusSuffix = qgetenv("KWIN_DBUS_SERVICE_SUFFIX");
if (!dBusSuffix.isNull()) {
m_serviceName = m_serviceName + QStringLiteral(".") + dBusSuffix;
}
if (!dbus.registerService(m_serviceName)) {
QDBusServiceWatcher *dog = new QDBusServiceWatcher(m_serviceName, dbus, QDBusServiceWatcher::WatchForUnregistration, this);
connect (dog, SIGNAL(serviceUnregistered(QString)), SLOT(becomeKWinService(QString)));
}
dbus.connect(QString(), QStringLiteral("/KWin"), QStringLiteral("org.kde.KWin"), QStringLiteral("reloadConfig"),
@ -60,14 +65,14 @@ void DBusInterface::becomeKWinService(const QString &service)
{
// TODO: this watchdog exists to make really safe that we at some point get the service
// but it's probably no longer needed since we explicitly unregister the service with the deconstructor
if (service == QStringLiteral("org.kde.KWin") && QDBusConnection::sessionBus().registerService(QStringLiteral("org.kde.KWin")) && sender()) {
if (service == m_serviceName && QDBusConnection::sessionBus().registerService(m_serviceName) && sender()) {
sender()->deleteLater(); // bye doggy :'(
}
}
DBusInterface::~DBusInterface()
{
QDBusConnection::sessionBus().unregisterService(QStringLiteral("org.kde.KWin")); // this is the long standing legal service
QDBusConnection::sessionBus().unregisterService(m_serviceName);
// KApplication automatically also grabs org.kde.kwin, so it's often been used externally - ensure to free it as well
QDBusConnection::sessionBus().unregisterService(QStringLiteral("org.kde.kwin"));
}

View File

@ -67,6 +67,9 @@ public Q_SLOTS: // METHODS
private Q_SLOTS:
void becomeKWinService(const QString &service);
private:
QString m_serviceName;
};
class CompositorDBusInterface : public QObject

View File

@ -58,6 +58,7 @@ Name[nds]=Ümdreihen
Name[ne]=उल्टाउनुहोस्
Name[nl]=Omkeren
Name[nn]=Snu fargane
Name[oc]=Enversar
Name[pa]=ਉਲਟ
Name[pl]=Odwróć
Name[pt]=Inverter

View File

@ -54,6 +54,7 @@ Name[nds]=Anmellen
Name[ne]=लगइन गर्नुहोस्
Name[nl]=Aanmelden
Name[nn]=Innlogging
Name[oc]=Connexion
Name[or]=ଲଗଇନ
Name[pa]=ਲਾਗਇਨ
Name[pl]=Logowanie
@ -147,6 +148,7 @@ Comment[th]=ค่อย ๆ ปรับภาพพื้นที่ทำง
Comment[tr]=Giriş yapılırken masaüstünü pürüzsüzce belirginleştir
Comment[ug]=تىزىمغا كىرگەندە ئۈستەلئۈستىگە تەكشى سۇسلاشتۇر
Comment[uk]=Плавна поява стільниці під час входу
Comment[vi]=Làm mờ dần màn hình khi đăng nhập
Comment[wa]=Dous fondou viè l' sicribanne a l' elodjaedje
Comment[x-test]=xxSmoothly fade to the desktop when logging inxx
Comment[zh_CN]=登录时平滑淡入到桌面

View File

@ -202,7 +202,7 @@ void MagnifierEffect::paintScreen(int mask, QRegion region, ScreenPaintData& dat
m_picture.reset(new XRenderPicture(m_pixmap, 32));
}
#define DOUBLE_TO_FIXED(d) ((xcb_render_fixed_t) ((d) * 65536))
static xcb_render_transform_t identity = {
static const xcb_render_transform_t identity = {
DOUBLE_TO_FIXED(1), DOUBLE_TO_FIXED(0), DOUBLE_TO_FIXED(0),
DOUBLE_TO_FIXED(0), DOUBLE_TO_FIXED(1), DOUBLE_TO_FIXED(0),
DOUBLE_TO_FIXED(0), DOUBLE_TO_FIXED(0), DOUBLE_TO_FIXED(1)

View File

@ -59,6 +59,7 @@ Name[nds]=Kiekglas
Name[ne]=परिमार्जक
Name[nl]=Vergrootglas
Name[nn]=Forstørr skjermdel
Name[oc]=Lópia
Name[pa]=ਵੱਡਦਰਸ਼ੀ
Name[pl]=Powiększenie
Name[pt]=Lupa

View File

@ -3,6 +3,7 @@ Comment=Animation for a window going to maximize/restore from maximize
Comment[bs]=Animacija za prozor koji ide u maksimiziranje/vraćanje iz maksimiziranja
Comment[ca]=Animació per una finestra que es maximitza/restaura des de maximització
Comment[ca@valencia]=Animació per una finestra que es maximitza/restaura des de maximització
Comment[cs]=Animace okna pro maximalizaci/obnovení z maximalizace
Comment[da]=Animation til et vindue der er ved at maksimere/gendanne fra maksimering
Comment[de]=Animation für ein Fenster beim Maximieren und Wiederherstellen
Comment[el]=Εφέ κίνησης για παράθυρο που πρόκειται να εκτελέσει μεγιστοποίηση / επαναφορά από μεγιστοποίηση
@ -38,6 +39,7 @@ Comment[sr@latin]=Animacija pri maksimizovanju i obnavljanju prozora
Comment[sv]=Animering för ett fönster som ska maximeras eller återställas från maximering
Comment[tr]=Pencerenin büyütülürken veya küçültülürken gösterilecek animasyon
Comment[uk]=Анімація для вікно під час максимізації/відновлення з максимізації
Comment[vi]=Hiệu ứng cho một cửa sổ chuẩn bị phóng to hoặc khôi phục lại từ trạng thái phóng to
Comment[x-test]=xxAnimation for a window going to maximize/restore from maximizexx
Comment[zh_CN]=窗口最大化/从最大化恢复时显示动画
Comment[zh_TW]=視窗最大化/回復時的動畫

View File

@ -276,10 +276,10 @@ void MouseClickEffect::paintScreenFinish(int mask, QRegion region, ScreenPaintDa
void MouseClickEffect::drawCircleGl(const QColor& color, float cx, float cy, float r)
{
static int num_segments = 80;
static float theta = 2 * 3.1415926 / float(num_segments);
static float c = cosf(theta); //precalculate the sine and cosine
static float s = sinf(theta);
static const int num_segments = 80;
static const float theta = 2 * 3.1415926 / float(num_segments);
static const float c = cosf(theta); //precalculate the sine and cosine
static const float s = sinf(theta);
float t;
float x = r;//we start at angle = 0

View File

@ -38,7 +38,7 @@ Name[pl]=Animacja kliknięcia myszy
Name[pt]=Animação do Botão do Rato
Name[pt_BR]=Animação de clique do mouse
Name[ro]=Animație la clic de maus
Name[ru]=Анимация щелчка мыши
Name[ru]=Анимация щелчка мышью
Name[sk]=Animácia kliknutia myšou
Name[sl]=Animacija klika z miško
Name[sr]=Анимација на клик мишем

View File

@ -21,8 +21,9 @@ import QtQuick 2.0
import org.kde.plasma.components 2.0 as Plasma
Item {
width: 32
height: 32
width: units.iconSizes.medium
height: width
Plasma.Button {
id: closeButton
objectName: "closeButton"

View File

@ -33,6 +33,7 @@ class StartupFeedbackEffect
: public Effect
{
Q_OBJECT
Q_PROPERTY(int type READ type)
public:
StartupFeedbackEffect();
virtual ~StartupFeedbackEffect();
@ -47,6 +48,10 @@ public:
return 90;
}
int type() const {
return int(m_type);
}
static bool supported();
private Q_SLOTS:

View File

@ -21,7 +21,6 @@ var translucencyEffect = {
activeWindow: effects.activeWindow,
settings: {
duration: animationTime(250),
decoration: 100,
moveresize: 100,
dialogs: 100,
inactive: 100,
@ -35,7 +34,6 @@ var translucencyEffect = {
"use strict";
var i, individualMenu, windows;
// TODO: add animation duration
translucencyEffect.settings.decoration = effect.readConfig("Decoration", 100);
translucencyEffect.settings.moveresize = effect.readConfig("MoveResize", 80);
translucencyEffect.settings.dialogs = effect.readConfig("Dialogs", 100);
translucencyEffect.settings.inactive = effect.readConfig("Inactive", 100);
@ -97,24 +95,6 @@ var translucencyEffect = {
} else if (window.menu === true) {
checkWindow(window, translucencyEffect.settings.tornoffmenus);
}
translucencyEffect.startDecorationAnimation(window);
},
startDecorationAnimation: function (window) {
"use strict";
var ids;
if (translucencyEffect.settings.decoration === 100 || window.hasDecoration === false) {
return;
}
ids = set({
window: window,
duration: 1,
animations: [{
type: Effect.DecorationOpacity,
from: translucencyEffect.settings.decoration / 100.0,
to: translucencyEffect.settings.decoration / 100.0
}]
});
window.decorationOpacityAnimation = ids;
},
/**
* @brief Cancels all animations for window type and inactive window
@ -130,10 +110,6 @@ var translucencyEffect = {
cancel(window.translucencyInactiveAnimation);
window.translucencyInactiveAnimation = undefined;
}
if (window.decorationOpacityAnimation !== undefined) {
cancel(window.decorationOpacityAnimation);
window.decorationOpacityAnimation = undefined;
}
},
moveResize: {
start: function (window) {

View File

@ -5,9 +5,6 @@
http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
<kcfgfile name=""/>
<group name="">
<entry name="Decoration" type="Int">
<default>100</default>
</entry>
<entry name="MoveResize" type="Int">
<default>80</default>
</entry>

View File

@ -20,83 +20,7 @@
<string>General Translucency Settings</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="4" column="1" colspan="2">
<widget class="QSlider" name="kcfg_Dialogs">
<property name="minimum">
<number>10</number>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="tickPosition">
<enum>QSlider::TicksBelow</enum>
</property>
<property name="tickInterval">
<number>10</number>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="dialogs_label">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Dialogs:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>kcfg_Dialogs</cstring>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="decorations_label">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Decorations:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>kcfg_Decoration</cstring>
</property>
</widget>
</item>
<item row="5" column="1" colspan="2">
<widget class="QSlider" name="kcfg_ComboboxPopups">
<property name="minimum">
<number>10</number>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="tickPosition">
<enum>QSlider::TicksBelow</enum>
</property>
<property name="tickInterval">
<number>10</number>
</property>
</widget>
</item>
<item row="6" column="1" colspan="2">
<widget class="QSlider" name="kcfg_Menus">
<property name="minimum">
<number>10</number>
@ -115,45 +39,20 @@
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="inactive_label">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<item row="6" column="0" colspan="2">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="text">
<string>Inactive windows:</string>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>kcfg_Inactive</cstring>
</property>
</widget>
</spacer>
</item>
<item row="3" column="0">
<widget class="QLabel" name="moveresize_label">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Moving windows:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>kcfg_MoveResize</cstring>
</property>
</widget>
</item>
<item row="5" column="0">
<item row="4" column="0">
<widget class="QLabel" name="comboboxpopup_label">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
@ -172,7 +71,26 @@
</property>
</widget>
</item>
<item row="3" column="1" colspan="2">
<item row="4" column="1" colspan="2">
<widget class="QSlider" name="kcfg_ComboboxPopups">
<property name="minimum">
<number>10</number>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="tickPosition">
<enum>QSlider::TicksBelow</enum>
</property>
<property name="tickInterval">
<number>10</number>
</property>
</widget>
</item>
<item row="2" column="1" colspan="2">
<widget class="QSlider" name="kcfg_MoveResize">
<property name="minimum">
<number>10</number>
@ -191,21 +109,132 @@
</property>
</widget>
</item>
<item row="7" column="0" colspan="2">
<spacer name="verticalSpacer_2">
<item row="0" column="2">
<widget class="QLabel" name="label_3">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Opaque</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="dialogs_label">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Dialogs:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>kcfg_Dialogs</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Transparent</string>
</property>
</widget>
</item>
<item row="3" column="1" colspan="2">
<widget class="QSlider" name="kcfg_Dialogs">
<property name="minimum">
<number>10</number>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>0</height>
</size>
<property name="tickPosition">
<enum>QSlider::TicksBelow</enum>
</property>
</spacer>
<property name="tickInterval">
<number>10</number>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="menus_label">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Menus:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>kcfg_Menus</cstring>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="moveresize_label">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Moving windows:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>kcfg_MoveResize</cstring>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="inactive_label">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Inactive windows:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>kcfg_Inactive</cstring>
</property>
</widget>
</item>
<item row="1" column="1" colspan="2">
<widget class="QSlider" name="kcfg_Decoration">
<widget class="QSlider" name="kcfg_Inactive">
<property name="minimumSize">
<size>
<width>170</width>
@ -229,73 +258,6 @@
</property>
</widget>
</item>
<item row="2" column="1" colspan="2">
<widget class="QSlider" name="kcfg_Inactive">
<property name="minimum">
<number>10</number>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="tickPosition">
<enum>QSlider::TicksBelow</enum>
</property>
<property name="tickInterval">
<number>10</number>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Transparent</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="label_3">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Opaque</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="menus_label">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Menus:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>kcfg_Menus</cstring>
</property>
</widget>
</item>
</layout>
</widget>
</item>
@ -479,7 +441,6 @@
</layout>
</widget>
<tabstops>
<tabstop>kcfg_Decoration</tabstop>
<tabstop>kcfg_Inactive</tabstop>
<tabstop>kcfg_MoveResize</tabstop>
<tabstop>kcfg_Dialogs</tabstop>

View File

@ -45,31 +45,31 @@ struct ParameterSet {
int move_factor;
};
ParameterSet set_0 = {
static const ParameterSet set_0 = {
15,
80,
10
};
ParameterSet set_1 = {
static const ParameterSet set_1 = {
10,
85,
10
};
ParameterSet set_2 = {
static const ParameterSet set_2 = {
6,
90,
10
};
ParameterSet set_3 = {
static const ParameterSet set_3 = {
3,
92,
20
};
ParameterSet set_4 = {
static const ParameterSet set_4 = {
1,
97,
25

View File

@ -380,7 +380,7 @@ void ZoomEffect::paintScreen(int mask, QRegion region, ScreenPaintData& data)
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
if (xrenderPicture) {
#define DOUBLE_TO_FIXED(d) ((xcb_render_fixed_t) ((d) * 65536))
static xcb_render_transform_t xrenderIdentity = {
static const xcb_render_transform_t xrenderIdentity = {
DOUBLE_TO_FIXED(1), DOUBLE_TO_FIXED(0), DOUBLE_TO_FIXED(0),
DOUBLE_TO_FIXED(0), DOUBLE_TO_FIXED(1), DOUBLE_TO_FIXED(0),
DOUBLE_TO_FIXED(0), DOUBLE_TO_FIXED(0), DOUBLE_TO_FIXED(1)

View File

@ -61,6 +61,7 @@ Name[nds]=Ansichtgrött
Name[ne]=जुम गर्नुहोस्
Name[nl]=Zoomen
Name[nn]=Forstørr skrivebordet
Name[oc]=Zoom
Name[pa]=ਜ਼ੂਮ
Name[pl]=Powiększanie
Name[pt]=Ampliação

View File

@ -23,6 +23,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "composite.h"
#include "options.h"
#include "wayland_backend.h"
#include <KWayland/Client/surface.h>
#include "xcbutils.h"
// kwin libs
#include <kwinglplatform.h>
@ -33,21 +34,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
namespace KWin
{
static void handleFrameCallback(void *data, wl_callback *callback, uint32_t time)
{
Q_UNUSED(data)
Q_UNUSED(time)
reinterpret_cast<EglWaylandBackend*>(data)->lastFrameRendered();
if (callback) {
wl_callback_destroy(callback);
}
}
static const struct wl_callback_listener s_surfaceFrameListener = {
handleFrameCallback
};
EglWaylandBackend::EglWaylandBackend()
: QObject(NULL)
, OpenGLBackend()
@ -55,7 +41,6 @@ EglWaylandBackend::EglWaylandBackend()
, m_bufferAge(0)
, m_wayland(Wayland::WaylandBackend::self())
, m_overlay(NULL)
, m_lastFrameRendered(true)
{
if (!m_wayland) {
setFailed("Wayland Backend has not been created");
@ -93,7 +78,29 @@ EglWaylandBackend::~EglWaylandBackend()
bool EglWaylandBackend::initializeEgl()
{
m_display = eglGetDisplay(m_wayland->display());
// Get the list of client extensions
const QByteArray clientExtensionString = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
if (clientExtensionString.isEmpty()) {
// If eglQueryString() returned NULL, the implementation doesn't support
// EGL_EXT_client_extensions. Expect an EGL_BAD_DISPLAY error.
(void) eglGetError();
}
const QList<QByteArray> clientExtensions = clientExtensionString.split(' ');
// Use eglGetPlatformDisplayEXT() to get the display pointer
// if the implementation supports it.
m_havePlatformBase = clientExtensions.contains("EGL_EXT_platform_base");
if (m_havePlatformBase) {
// Make sure that the wayland platform is supported
if (!clientExtensions.contains("EGL_EXT_platform_wayland"))
return false;
m_display = eglGetPlatformDisplayEXT(EGL_PLATFORM_WAYLAND_EXT, m_wayland->display(), nullptr);
} else {
m_display = eglGetDisplay(m_wayland->display());
}
if (m_display == EGL_NO_DISPLAY)
return false;
@ -186,13 +193,19 @@ bool EglWaylandBackend::initRenderingContext()
}
const QSize &size = m_wayland->shellSurfaceSize();
m_overlay = wl_egl_window_create(m_wayland->surface(), size.width(), size.height());
auto s = m_wayland->surface();
connect(s, &KWayland::Client::Surface::frameRendered, Compositor::self(), &Compositor::bufferSwapComplete);
m_overlay = wl_egl_window_create(*s, size.width(), size.height());
if (!m_overlay) {
qCritical() << "Creating Wayland Egl window failed";
return false;
}
m_surface = eglCreateWindowSurface(m_display, m_config, m_overlay, NULL);
if (m_havePlatformBase)
m_surface = eglCreatePlatformWindowSurfaceEXT(m_display, m_config, (void *) m_overlay, nullptr);
else
m_surface = eglCreateWindowSurface(m_display, m_config, m_overlay, nullptr);
if (m_surface == EGL_NO_SURFACE) {
qCritical() << "Create Window Surface failed";
return false;
@ -250,12 +263,9 @@ bool EglWaylandBackend::initBufferConfigs()
void EglWaylandBackend::present()
{
// need to dispatch pending events as eglSwapBuffers can block
m_wayland->dispatchEvents();
m_wayland->surface()->setupFrameCallback();
Compositor::self()->aboutToSwapBuffers();
m_lastFrameRendered = false;
wl_callback *callback = wl_surface_frame(m_wayland->surface());
wl_callback_add_listener(callback, &s_surfaceFrameListener, this);
if (supportsBufferAge()) {
eglSwapBuffers(m_display, m_surface);
eglQuerySurface(m_display, m_surface, EGL_BUFFER_AGE_EXT, &m_bufferAge);
@ -358,17 +368,6 @@ void EglWaylandBackend::overlaySizeChanged(const QSize &size)
wl_egl_window_resize(m_overlay, size.width(), size.height(), 0, 0);
}
bool EglWaylandBackend::isLastFrameRendered() const
{
return m_lastFrameRendered;
}
void EglWaylandBackend::lastFrameRendered()
{
m_lastFrameRendered = true;
Compositor::self()->lastFrameRendered();
}
bool EglWaylandBackend::usesOverlayWindow() const
{
return false;
@ -396,22 +395,17 @@ OpenGLBackend *EglWaylandTexture::backend()
return m_backend;
}
void EglWaylandTexture::findTarget()
bool EglWaylandTexture::loadTexture(xcb_pixmap_t pix, const QSize &size, xcb_visualid_t visual)
{
if (m_target != GL_TEXTURE_2D) {
m_target = GL_TEXTURE_2D;
}
}
Q_UNUSED(visual)
bool EglWaylandTexture::loadTexture(const Pixmap &pix, const QSize &size, int depth)
{
// HACK: egl wayland platform doesn't support texture from X11 pixmap through the KHR_image_pixmap
// extension. To circumvent this problem we copy the pixmap content into a SHM image and from there
// to the OpenGL texture. This is a temporary solution. In future we won't need to get the content
// from X11 pixmaps. That's what we have XWayland for to get the content into a nice Wayland buffer.
Q_UNUSED(depth)
if (pix == XCB_PIXMAP_NONE)
return false;
m_referencedPixmap = pix;
Xcb::Shm *shm = m_backend->shm();

View File

@ -66,9 +66,7 @@ public:
virtual void endRenderingFrame(const QRegion &renderedRegion, const QRegion &damagedRegion);
virtual bool makeCurrent() override;
virtual void doneCurrent() override;
virtual bool isLastFrameRendered() const override;
Xcb::Shm *shm();
void lastFrameRendered();
virtual bool usesOverlayWindow() const override;
protected:
@ -91,7 +89,7 @@ private:
Wayland::WaylandBackend *m_wayland;
wl_egl_window *m_overlay;
QScopedPointer<Xcb::Shm> m_shm;
bool m_lastFrameRendered;
bool m_havePlatformBase;
friend class EglWaylandTexture;
};
@ -102,8 +100,7 @@ class EglWaylandTexture : public SceneOpenGL::TexturePrivate
{
public:
virtual ~EglWaylandTexture();
virtual void findTarget();
virtual bool loadTexture(const Pixmap& pix, const QSize& size, int depth);
virtual bool loadTexture(xcb_pixmap_t pix, const QSize &size, xcb_visualid_t visual) override;
virtual OpenGLBackend *backend();
virtual bool update(const QRegion &damage);

View File

@ -33,6 +33,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
namespace KWin
{
extern int screen_number; // main.cpp
EglOnXBackend::EglOnXBackend()
: OpenGLBackend()
, m_overlayWindow(new OverlayWindow())
@ -158,7 +160,34 @@ void EglOnXBackend::init()
bool EglOnXBackend::initRenderingContext()
{
dpy = eglGetDisplay(display());
// Get the list of client extensions
const QByteArray clientExtensionString = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
if (clientExtensionString.isEmpty()) {
// If eglQueryString() returned NULL, the implementation doesn't support
// EGL_EXT_client_extensions. Expect an EGL_BAD_DISPLAY error.
(void) eglGetError();
}
const QList<QByteArray> clientExtensions = clientExtensionString.split(' ');
// Use eglGetPlatformDisplayEXT() to get the display pointer
// if the implementation supports it.
const bool havePlatformBase = clientExtensions.contains("EGL_EXT_platform_base");
if (havePlatformBase) {
// Make sure that the X11 platform is supported
if (!clientExtensions.contains("EGL_EXT_platform_x11"))
return false;
const int attribs[] = {
EGL_PLATFORM_X11_SCREEN_EXT, screen_number,
EGL_NONE
};
dpy = eglGetPlatformDisplayEXT(EGL_PLATFORM_X11_EXT, display(), attribs);
} else {
dpy = eglGetDisplay(display());
}
if (dpy == EGL_NO_DISPLAY)
return false;
@ -184,7 +213,16 @@ bool EglOnXBackend::initRenderingContext()
overlayWindow()->setup(None);
}
surface = eglCreateWindowSurface(dpy, config, overlayWindow()->window(), 0);
if (havePlatformBase) {
// Note: Window is 64 bits on a 64-bit architecture whereas xcb_window_t is
// always 32 bits. eglCreatePlatformWindowSurfaceEXT() expects the
// native_window parameter to be pointer to a Window, so this variable
// cannot be an xcb_window_t.
const Window window = overlayWindow()->window();
surface = eglCreatePlatformWindowSurfaceEXT(dpy, config, (void *) &window, nullptr);
} else {
surface = eglCreateWindowSurface(dpy, config, overlayWindow()->window(), nullptr);
}
#ifdef KWIN_HAVE_OPENGLES
const EGLint context_attribs[] = {
@ -459,17 +497,11 @@ OpenGLBackend *EglTexture::backend()
return m_backend;
}
void EglTexture::findTarget()
bool EglTexture::loadTexture(xcb_pixmap_t pix, const QSize &size, xcb_visualid_t visual)
{
if (m_target != GL_TEXTURE_2D) {
m_target = GL_TEXTURE_2D;
}
}
Q_UNUSED(visual)
bool EglTexture::loadTexture(const Pixmap &pix, const QSize &size, int depth)
{
Q_UNUSED(depth)
if (pix == None)
if (pix == XCB_NONE)
return false;
glGenTextures(1, &m_texture);

View File

@ -69,8 +69,7 @@ class EglTexture : public SceneOpenGL::TexturePrivate
public:
virtual ~EglTexture();
virtual void onDamage();
virtual void findTarget();
virtual bool loadTexture(const Pixmap& pix, const QSize& size, int depth);
virtual bool loadTexture(xcb_pixmap_t pix, const QSize &size, xcb_visualid_t visual) override;
virtual OpenGLBackend *backend();
private:

View File

@ -61,6 +61,20 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "composite.h"
#include "killwindow.h"
#include "x11eventfilter.h"
#ifndef XCB_GE_GENERIC
#define XCB_GE_GENERIC 35
typedef struct xcb_ge_generic_event_t {
uint8_t response_type; /**< */
uint8_t extension; /**< */
uint16_t sequence; /**< */
uint32_t length; /**< */
uint16_t event_type; /**< */
uint8_t pad0[22]; /**< */
uint32_t full_sequence; /**< */
} xcb_ge_generic_event_t;
#endif
namespace KWin
{
@ -158,6 +172,25 @@ QVector<QByteArray> s_xcbEerrors({
QByteArrayLiteral("BadLength"),
QByteArrayLiteral("BadImplementation"),
QByteArrayLiteral("Unknown")});
void Workspace::registerEventFilter(X11EventFilter *filter)
{
if (filter->eventType() == XCB_GE_GENERIC)
m_genericEventFilters.append(filter);
else
m_eventFilters.append(filter);
}
void Workspace::unregisterEventFilter(X11EventFilter *filter)
{
if (filter->eventType() == XCB_GE_GENERIC)
m_genericEventFilters.removeOne(filter);
else
m_eventFilters.removeOne(filter);
}
/*!
Handles workspace specific XCB event
*/
@ -193,6 +226,23 @@ bool Workspace::workspaceEvent(xcb_generic_event_t *e)
}
return false;
}
if (eventType == XCB_GE_GENERIC) {
xcb_ge_generic_event_t *ge = reinterpret_cast<xcb_ge_generic_event_t *>(e);
foreach (X11EventFilter *filter, m_genericEventFilters) {
if (filter->extension() == ge->extension && filter->genericEventType() == ge->event_type && filter->event(e)) {
return true;
}
}
} else {
foreach (X11EventFilter *filter, m_eventFilters) {
if (filter->eventType() == eventType && filter->event(e)) {
return true;
}
}
}
if (effects && static_cast< EffectsHandlerImpl* >(effects)->hasKeyboardGrab()
&& (eventType == XCB_KEY_PRESS || eventType == XCB_KEY_RELEASE))
return false; // let Qt process it, it'll be intercepted again in eventFilter()
@ -585,6 +635,13 @@ bool Client::windowEvent(xcb_generic_event_t *e)
if (dirtyProperties2.testFlag(NET::WM2BlockCompositing)) {
setBlockingCompositing(info->isBlockingCompositing());
}
if (dirtyProperties2.testFlag(NET::WM2GroupLeader)) {
checkGroup();
updateAllowedActions(); // Group affects isMinimizable()
}
if (dirtyProperties2.testFlag(NET::WM2Urgency)) {
updateUrgency();
}
}
const uint8_t eventType = e->response_type & ~0x80;
@ -843,7 +900,6 @@ void Client::propertyNotifyEvent(xcb_property_notify_event_t *e)
readTransient();
break;
case XCB_ATOM_WM_HINTS:
getWMHints();
getIcons(); // because KWin::icon() uses WMHints as fallback
break;
default:

View File

@ -30,16 +30,75 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "options.h"
#include "utils.h"
#include "overlaywindow.h"
#include "composite.h"
#include "xcbutils.h"
// kwin libs
#include <kwinglplatform.h>
#include <kwinxrenderutils.h>
// Qt
#include <QDebug>
#include <QOpenGLContext>
// system
#include <unistd.h>
#include <xcb/glx.h>
#ifndef XCB_GLX_BUFFER_SWAP_COMPLETE
#define XCB_GLX_BUFFER_SWAP_COMPLETE 1
typedef struct xcb_glx_buffer_swap_complete_event_t {
uint8_t response_type; /**< */
uint8_t pad0; /**< */
uint16_t sequence; /**< */
uint16_t event_type; /**< */
uint8_t pad1[2]; /**< */
xcb_glx_drawable_t drawable; /**< */
uint32_t ust_hi; /**< */
uint32_t ust_lo; /**< */
uint32_t msc_hi; /**< */
uint32_t msc_lo; /**< */
uint32_t sbc; /**< */
} xcb_glx_buffer_swap_complete_event_t;
#endif
#include <tuple>
#if __cplusplus <= 201103L
namespace std {
// C++-14
template<class T, class... Args>
unique_ptr<T> make_unique(Args&&... args) {
return unique_ptr<T>(new T(std::forward<Args>(args)...));
}
}
#endif
namespace KWin
{
SwapEventFilter::SwapEventFilter(xcb_drawable_t drawable)
: X11EventFilter(Xcb::Extensions::self()->glxEventBase() + XCB_GLX_BUFFER_SWAP_COMPLETE),
m_drawable(drawable)
{
}
bool SwapEventFilter::event(xcb_generic_event_t *event)
{
xcb_glx_buffer_swap_complete_event_t *ev =
reinterpret_cast<xcb_glx_buffer_swap_complete_event_t *>(event);
if (ev->drawable == m_drawable) {
Compositor::self()->bufferSwapComplete();
return true;
}
return false;
}
// -----------------------------------------------------------------------
GlxBackend::GlxBackend()
: OpenGLBackend()
, m_overlayWindow(new OverlayWindow())
@ -88,10 +147,6 @@ void GlxBackend::init()
setFailed(QStringLiteral("Requires at least GLX 1.3"));
return;
}
if (!initDrawableConfigs()) {
setFailed(QStringLiteral("Could not initialize the drawable configs"));
return;
}
if (!initBuffer()) {
setFailed(QStringLiteral("Could not initialize the buffer"));
return;
@ -100,6 +155,7 @@ void GlxBackend::init()
setFailed(QStringLiteral("Could not initialize rendering context"));
return;
}
// Initialize OpenGL
GLPlatform *glPlatform = GLPlatform::instance();
glPlatform->detect(GlxPlatformInterface);
@ -116,6 +172,21 @@ void GlxBackend::init()
m_haveMESASwapControl = hasGLExtension(QByteArrayLiteral("GLX_MESA_swap_control"));
m_haveEXTSwapControl = hasGLExtension(QByteArrayLiteral("GLX_EXT_swap_control"));
m_haveSGISwapControl = hasGLExtension(QByteArrayLiteral("GLX_SGI_swap_control"));
m_haveINTELSwapEvent = hasGLExtension(QByteArrayLiteral("GLX_INTEL_swap_event"));
if (m_haveINTELSwapEvent) {
const QList<QByteArray> tokens = QByteArray(qVersion()).split('.');
uint32_t version = tokens[0].toInt() << 16 | tokens[1].toInt() << 8 | tokens[2].toInt();
// Qt 5.3 doesn't forward swap events to the native event filter
if (version < 0x00050400)
m_haveINTELSwapEvent = false;
}
if (m_haveINTELSwapEvent) {
m_swapEventFilter = std::make_unique<SwapEventFilter>(window);
glXSelectEvent(display(), glxWindow, GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK);
}
haveSwapInterval = m_haveMESASwapControl || m_haveEXTSwapControl || m_haveSGISwapControl;
@ -168,6 +239,8 @@ void GlxBackend::init()
setIsDirectRendering(bool(glXIsDirect(display(), ctx)));
qDebug() << "Direct rendering:" << isDirectRendering() << endl;
initVisualDepthHashTable();
}
bool GlxBackend::initRenderingContext()
@ -304,18 +377,68 @@ bool GlxBackend::initFbConfig()
return true;
}
bool GlxBackend::initDrawableConfigs()
void GlxBackend::initVisualDepthHashTable()
{
const xcb_setup_t *setup = xcb_get_setup(connection());
for (auto screen = xcb_setup_roots_iterator(setup); screen.rem; xcb_screen_next(&screen)) {
for (auto depth = xcb_screen_allowed_depths_iterator(screen.data); depth.rem; xcb_depth_next(&depth)) {
const int len = xcb_depth_visuals_length(depth.data);
const xcb_visualtype_t *visuals = xcb_depth_visuals(depth.data);
for (int i = 0; i < len; i++)
m_visualDepthHash.insert(visuals[i].visual_id, depth.data->depth);
}
}
}
int GlxBackend::visualDepth(xcb_visualid_t visual) const
{
return m_visualDepthHash.value(visual);
}
FBConfigInfo *GlxBackend::infoForVisual(xcb_visualid_t visual)
{
FBConfigInfo *&info = m_fbconfigHash[visual];
if (info)
return info;
info = new FBConfigInfo;
info->fbconfig = nullptr;
info->bind_texture_format = 0;
info->texture_targets = 0;
info->y_inverted = 0;
info->mipmap = 0;
const xcb_render_pictformat_t format = XRenderUtils::findPictFormat(visual);
const xcb_render_directformat_t *direct = XRenderUtils::findPictFormatInfo(format);
if (!direct) {
qCritical().nospace() << "Could not find a picture format for visual 0x" << hex << visual;
return info;
}
const int red_bits = bitCount(direct->red_mask);
const int green_bits = bitCount(direct->green_mask);
const int blue_bits = bitCount(direct->blue_mask);
const int alpha_bits = bitCount(direct->alpha_mask);
const int depth = visualDepth(visual);
const auto rgb_sizes = std::tie(red_bits, green_bits, blue_bits);
const int attribs[] = {
GLX_RENDER_TYPE, GLX_RGBA_BIT,
GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT | GLX_PIXMAP_BIT,
GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR,
GLX_X_RENDERABLE, True,
GLX_CONFIG_CAVEAT, int(GLX_DONT_CARE), // The ARGB32 visual is marked non-conformant in Catalyst
GLX_RED_SIZE, 5,
GLX_GREEN_SIZE, 5,
GLX_BLUE_SIZE, 5,
GLX_ALPHA_SIZE, 0,
GLX_BUFFER_SIZE, red_bits + green_bits + blue_bits + alpha_bits,
GLX_RED_SIZE, red_bits,
GLX_GREEN_SIZE, green_bits,
GLX_BLUE_SIZE, blue_bits,
GLX_ALPHA_SIZE, alpha_bits,
GLX_STENCIL_SIZE, 0,
GLX_DEPTH_SIZE, 0,
0
@ -325,96 +448,64 @@ bool GlxBackend::initDrawableConfigs()
GLXFBConfig *configs = glXChooseFBConfig(display(), DefaultScreen(display()), attribs, &count);
if (count < 1) {
qCritical() << "Could not find any usable framebuffer configurations.";
return false;
qCritical().nospace() << "Could not find a framebuffer configuration for visual 0x" << hex << visual;
return info;
}
for (int i = 0; i <= 32; i++) {
fbcdrawableinfo[i].fbconfig = NULL;
fbcdrawableinfo[i].bind_texture_format = 0;
fbcdrawableinfo[i].texture_targets = 0;
fbcdrawableinfo[i].y_inverted = 0;
fbcdrawableinfo[i].mipmap = 0;
}
for (int i = 0; i < count; i++) {
int red, green, blue;
glXGetFBConfigAttrib(display(), configs[i], GLX_RED_SIZE, &red);
glXGetFBConfigAttrib(display(), configs[i], GLX_GREEN_SIZE, &green);
glXGetFBConfigAttrib(display(), configs[i], GLX_BLUE_SIZE, &blue);
// Find the first usable framebuffer configuration for each depth.
// Single-buffered ones will appear first in the list.
const int depths[] = { 15, 16, 24, 30, 32 };
for (unsigned int i = 0; i < sizeof(depths) / sizeof(depths[0]); i++) {
const int depth = depths[i];
for (int j = 0; j < count; j++) {
int alpha_size, buffer_size;
glXGetFBConfigAttrib(display(), configs[j], GLX_ALPHA_SIZE, &alpha_size);
glXGetFBConfigAttrib(display(), configs[j], GLX_BUFFER_SIZE, &buffer_size);
if (buffer_size != depth && (buffer_size - alpha_size) != depth)
continue;
if (depth == 32 && alpha_size != 8)
continue;
XVisualInfo *vi = glXGetVisualFromFBConfig(display(), configs[j]);
if (vi == NULL)
continue;
int visual_depth = vi->depth;
XFree(vi);
if (visual_depth != depth)
continue;
int bind_rgb, bind_rgba;
glXGetFBConfigAttrib(display(), configs[j], GLX_BIND_TO_TEXTURE_RGBA_EXT, &bind_rgba);
glXGetFBConfigAttrib(display(), configs[j], GLX_BIND_TO_TEXTURE_RGB_EXT, &bind_rgb);
// Skip this config if it cannot be bound to a texture
if (!bind_rgb && !bind_rgba)
continue;
int texture_format;
if (depth == 32)
texture_format = bind_rgba ? GLX_TEXTURE_FORMAT_RGBA_EXT : GLX_TEXTURE_FORMAT_RGB_EXT;
else
texture_format = bind_rgb ? GLX_TEXTURE_FORMAT_RGB_EXT : GLX_TEXTURE_FORMAT_RGBA_EXT;
int y_inverted, texture_targets;
glXGetFBConfigAttrib(display(), configs[j], GLX_BIND_TO_TEXTURE_TARGETS_EXT, &texture_targets);
glXGetFBConfigAttrib(display(), configs[j], GLX_Y_INVERTED_EXT, &y_inverted);
fbcdrawableinfo[depth].fbconfig = configs[j];
fbcdrawableinfo[depth].bind_texture_format = texture_format;
fbcdrawableinfo[depth].texture_targets = texture_targets;
fbcdrawableinfo[depth].y_inverted = y_inverted;
fbcdrawableinfo[depth].mipmap = 0;
break;
}
}
if (count)
XFree(configs);
if (fbcdrawableinfo[DefaultDepth(display(), DefaultScreen(display()))].fbconfig == NULL) {
qCritical() << "Could not find a framebuffer configuration for the default depth.";
return false;
}
if (fbcdrawableinfo[32].fbconfig == NULL) {
qCritical() << "Could not find a framebuffer configuration for depth 32.";
return false;
}
for (int i = 0; i <= 32; i++) {
if (fbcdrawableinfo[i].fbconfig == NULL)
if (std::tie(red, green, blue) != rgb_sizes)
continue;
int vis_drawable = 0;
glXGetFBConfigAttrib(display(), fbcdrawableinfo[i].fbconfig, GLX_VISUAL_ID, &vis_drawable);
xcb_visualid_t visual;
glXGetFBConfigAttrib(display(), configs[i], GLX_VISUAL_ID, (int *) &visual);
qDebug() << "Drawable visual (depth " << i << "): 0x" << QString::number(vis_drawable, 16);
if (visualDepth(visual) != depth)
continue;
int bind_rgb, bind_rgba;
glXGetFBConfigAttrib(display(), configs[i], GLX_BIND_TO_TEXTURE_RGBA_EXT, &bind_rgba);
glXGetFBConfigAttrib(display(), configs[i], GLX_BIND_TO_TEXTURE_RGB_EXT, &bind_rgb);
if (!bind_rgb && !bind_rgba)
continue;
int texture_format;
if (alpha_bits)
texture_format = bind_rgba ? GLX_TEXTURE_FORMAT_RGBA_EXT : GLX_TEXTURE_FORMAT_RGB_EXT;
else
texture_format = bind_rgb ? GLX_TEXTURE_FORMAT_RGB_EXT : GLX_TEXTURE_FORMAT_RGBA_EXT;
int y_inverted, texture_targets;
glXGetFBConfigAttrib(display(), configs[i], GLX_BIND_TO_TEXTURE_TARGETS_EXT, &texture_targets);
glXGetFBConfigAttrib(display(), configs[i], GLX_Y_INVERTED_EXT, &y_inverted);
info->fbconfig = configs[i];
info->bind_texture_format = texture_format;
info->texture_targets = texture_targets;
info->y_inverted = y_inverted;
info->mipmap = 0;
break;
}
return true;
if (count > 0)
XFree(configs);
if (info->fbconfig) {
int fbc_id = 0;
int visual_id = 0;
glXGetFBConfigAttrib(display(), info->fbconfig, GLX_FBCONFIG_ID, &fbc_id);
glXGetFBConfigAttrib(display(), info->fbconfig, GLX_VISUAL_ID, &visual_id);
qDebug().nospace() << "Using FBConfig 0x" << hex << fbc_id << " for visual 0x" << hex << visual_id;
}
return info;
}
void GlxBackend::setSwapInterval(int interval)
@ -453,6 +544,9 @@ void GlxBackend::present()
const bool fullRepaint = supportsBufferAge() || (lastDamage() == displayRegion);
if (fullRepaint) {
if (m_haveINTELSwapEvent)
Compositor::self()->aboutToSwapBuffers();
if (haveSwapInterval) {
if (gs_tripleBufferNeedsDetection) {
glXWaitGL();
@ -643,100 +737,50 @@ void GlxTexture::onDamage()
GLTexturePrivate::onDamage();
}
void GlxTexture::findTarget()
bool GlxTexture::loadTexture(xcb_pixmap_t pixmap, const QSize &size, xcb_visualid_t visual)
{
unsigned int new_target = 0;
if (glXQueryDrawable && m_glxpixmap != None)
glXQueryDrawable(display(), m_glxpixmap, GLX_TEXTURE_TARGET_EXT, &new_target);
// HACK: this used to be a hack for Xgl.
// without this hack the NVIDIA blob aborts when trying to bind a texture from
// a pixmap icon
if (new_target == 0) {
if (GLTexture::NPOTTextureSupported() ||
(isPowerOfTwo(m_size.width()) && isPowerOfTwo(m_size.height()))) {
new_target = GLX_TEXTURE_2D_EXT;
} else {
new_target = GLX_TEXTURE_RECTANGLE_EXT;
}
}
switch(new_target) {
case GLX_TEXTURE_2D_EXT:
if (pixmap == XCB_NONE || size.isEmpty() || visual == XCB_NONE)
return false;
const FBConfigInfo *info = m_backend->infoForVisual(visual);
if (!info || info->fbconfig == nullptr)
return false;
if ((info->texture_targets & GLX_TEXTURE_2D_BIT_EXT) &&
(GLTexture::NPOTTextureSupported() ||
(isPowerOfTwo(size.width()) && isPowerOfTwo(size.height())))) {
m_target = GL_TEXTURE_2D;
m_scale.setWidth(1.0f / m_size.width());
m_scale.setHeight(1.0f / m_size.height());
break;
case GLX_TEXTURE_RECTANGLE_EXT:
m_target = GL_TEXTURE_RECTANGLE_ARB;
} else {
assert(info->texture_targets & GLX_TEXTURE_RECTANGLE_BIT_EXT);
m_target = GL_TEXTURE_RECTANGLE;
m_scale.setWidth(1.0f);
m_scale.setHeight(1.0f);
break;
default:
abort();
}
}
bool GlxTexture::loadTexture(const Pixmap& pix, const QSize& size, int depth)
{
#ifdef CHECK_GL_ERROR
checkGLError("TextureLoad1");
#endif
if (pix == None || size.isEmpty() || depth < 1)
return false;
if (m_backend->fbcdrawableinfo[ depth ].fbconfig == NULL) {
qDebug() << "No framebuffer configuration for depth " << depth
<< "; not binding pixmap" << endl;
return false;
}
m_size = size;
// new texture, or texture contents changed; mipmaps now invalid
q->setDirty();
#ifdef CHECK_GL_ERROR
checkGLError("TextureLoad2");
#endif
// tfp mode, simply bind the pixmap to texture
glGenTextures(1, &m_texture);
// The GLX pixmap references the contents of the original pixmap, so it doesn't
// need to be recreated when the contents change.
// The texture may or may not use the same storage depending on the EXT_tfp
// implementation. When options->glStrictBinding is true, the texture uses
// a different storage and needs to be updated with a call to
// glXBindTexImageEXT() when the contents of the pixmap has changed.
int attrs[] = {
GLX_TEXTURE_FORMAT_EXT, m_backend->fbcdrawableinfo[ depth ].bind_texture_format,
GLX_MIPMAP_TEXTURE_EXT, m_backend->fbcdrawableinfo[ depth ].mipmap > 0,
None, None, None
const int attrs[] = {
GLX_TEXTURE_FORMAT_EXT, info->bind_texture_format,
GLX_MIPMAP_TEXTURE_EXT, info->mipmap,
GLX_TEXTURE_TARGET_EXT, m_target == GL_TEXTURE_2D ? GLX_TEXTURE_2D_EXT : GLX_TEXTURE_RECTANGLE_EXT,
0
};
if ((m_backend->fbcdrawableinfo[ depth ].texture_targets & GLX_TEXTURE_2D_BIT_EXT) &&
(GLTexture::NPOTTextureSupported() ||
(isPowerOfTwo(size.width()) && isPowerOfTwo(size.height())))) {
attrs[ 4 ] = GLX_TEXTURE_TARGET_EXT;
attrs[ 5 ] = GLX_TEXTURE_2D_EXT;
} else if (m_backend->fbcdrawableinfo[ depth ].texture_targets & GLX_TEXTURE_RECTANGLE_BIT_EXT) {
attrs[ 4 ] = GLX_TEXTURE_TARGET_EXT;
attrs[ 5 ] = GLX_TEXTURE_RECTANGLE_EXT;
}
m_glxpixmap = glXCreatePixmap(display(), m_backend->fbcdrawableinfo[ depth ].fbconfig, pix, attrs);
#ifdef CHECK_GL_ERROR
checkGLError("TextureLoadTFP1");
#endif
findTarget();
m_yInverted = m_backend->fbcdrawableinfo[ depth ].y_inverted ? true : false;
m_canUseMipmaps = m_backend->fbcdrawableinfo[ depth ].mipmap > 0;
q->setFilter(m_backend->fbcdrawableinfo[ depth ].mipmap > 0 ? GL_NEAREST_MIPMAP_LINEAR : GL_NEAREST);
m_glxpixmap = glXCreatePixmap(display(), info->fbconfig, pixmap, attrs);
m_size = size;
m_yInverted = info->y_inverted ? true : false;
m_canUseMipmaps = info->mipmap;
glGenTextures(1, &m_texture);
q->setDirty();
q->setFilter(info->mipmap > 0 ? GL_NEAREST_MIPMAP_LINEAR : GL_NEAREST);
glBindTexture(m_target, m_texture);
#ifdef CHECK_GL_ERROR
checkGLError("TextureLoadTFP2");
#endif
glXBindTexImageEXT(display(), m_glxpixmap, GLX_FRONT_LEFT_EXT, NULL);
#ifdef CHECK_GL_ERROR
checkGLError("TextureLoad0");
#endif
glXBindTexImageEXT(display(), m_glxpixmap, GLX_FRONT_LEFT_EXT, nullptr);
updateMatrix();
unbind();
return true;
}

View File

@ -20,6 +20,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef KWIN_GLX_BACKEND_H
#define KWIN_GLX_BACKEND_H
#include "scene_opengl.h"
#include "x11eventfilter.h"
#include <memory>
namespace KWin
{
@ -34,6 +37,21 @@ public:
int mipmap;
};
// ------------------------------------------------------------------
class SwapEventFilter : public X11EventFilter
{
public:
SwapEventFilter(xcb_drawable_t drawable);
bool event(xcb_generic_event_t *event) override;
private:
xcb_drawable_t m_drawable;
};
/**
* @brief OpenGL Backend using GLX over an X overlay window.
**/
@ -57,26 +75,32 @@ protected:
private:
void init();
bool initBuffer();
bool initDrawableConfigs();
void waitSync();
bool initRenderingContext();
bool initFbConfig();
void initVisualDepthHashTable();
void setSwapInterval(int interval);
int visualDepth(xcb_visualid_t visual) const;
FBConfigInfo *infoForVisual(xcb_visualid_t visual);
/**
* @brief The OverlayWindow used by this Backend.
**/
OverlayWindow *m_overlayWindow;
Window window;
FBConfigInfo fbcdrawableinfo[ 32 + 1 ];
GLXFBConfig fbconfig;
GLXWindow glxWindow;
GLXContext ctx;
QHash<xcb_visualid_t, FBConfigInfo *> m_fbconfigHash;
QHash<xcb_visualid_t, int> m_visualDepthHash;
std::unique_ptr<SwapEventFilter> m_swapEventFilter;
int m_bufferAge;
bool m_haveMESACopySubBuffer;
bool m_haveMESASwapControl;
bool m_haveEXTSwapControl;
bool m_haveSGISwapControl;
bool m_haveINTELSwapEvent;
bool haveSwapInterval, haveWaitSync;
friend class GlxTexture;
};
@ -89,8 +113,7 @@ class GlxTexture : public SceneOpenGL::TexturePrivate
public:
virtual ~GlxTexture();
virtual void onDamage();
virtual void findTarget();
virtual bool loadTexture(const Pixmap& pix, const QSize& size, int depth);
virtual bool loadTexture(xcb_pixmap_t pix, const QSize &size, xcb_visualid_t visual) override;
virtual OpenGLBackend *backend();
private:

View File

@ -920,15 +920,15 @@ void Client::checkGroup(Group* set_group, bool force)
in_group = set_group;
in_group->addMember(this);
}
} else if (m_windowGroup != XCB_WINDOW_NONE) {
Group* new_group = workspace()->findGroup(m_windowGroup);
} else if (info->groupLeader() != XCB_WINDOW_NONE) {
Group* new_group = workspace()->findGroup(info->groupLeader());
if (transientFor() != NULL && transientFor()->group() != new_group) {
// move the window to the right group (e.g. a dialog provided
// by different app, but transient for this one, so make it part of that group)
new_group = transientFor()->group();
}
if (new_group == NULL) // doesn't exist yet
new_group = new Group(m_windowGroup);
new_group = new Group(info->groupLeader());
if (new_group != in_group) {
if (in_group != NULL)
in_group->removeMember(this);
@ -1030,7 +1030,7 @@ void Client::changeClientLeaderGroup(Group* gr)
if (transientFor() != NULL)
return;
// also don't change the group for window which have group set
if (m_windowGroup)
if (info->groupLeader())
return;
checkGroup(gr); // change group
}

View File

@ -21,11 +21,17 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "client.h"
#include "effects.h"
#include "globalshortcuts.h"
#include "logind.h"
#include "main.h"
#ifdef KWIN_BUILD_TABBOX
#include "tabbox/tabbox.h"
#endif
#include "unmanaged.h"
#include "screens.h"
#include "workspace.h"
#if HAVE_INPUT
#include "libinput/connection.h"
#endif
// KDE
#include <kkeyserver.h>
// TODO: remove xtest
@ -166,6 +172,24 @@ InputRedirection::InputRedirection(QObject *parent)
, m_pointerWindow()
, m_shortcuts(new GlobalShortcutsManager(this))
{
#if HAVE_INPUT
if (Application::usesLibinput()) {
LogindIntegration *logind = LogindIntegration::self();
auto takeControl = [logind, this]() {
if (logind->hasSessionControl()) {
setupLibInput();
} else {
logind->takeControl();
connect(logind, &LogindIntegration::hasSessionControlChanged, this, &InputRedirection::setupLibInput);
}
};
if (logind->isConnected()) {
takeControl();
} else {
connect(logind, &LogindIntegration::connectedChanged, this, takeControl);
}
}
#endif
}
InputRedirection::~InputRedirection()
@ -173,6 +197,47 @@ InputRedirection::~InputRedirection()
s_self = NULL;
}
void InputRedirection::setupLibInput()
{
#if HAVE_INPUT
if (!Application::usesLibinput()) {
return;
}
LibInput::Connection *conn = LibInput::Connection::create(this);
if (conn) {
conn->setup();
conn->setScreenSize(screens()->size());
connect(screens(), &Screens::sizeChanged, this,
[this, conn] {
conn->setScreenSize(screens()->size());
}
);
connect(conn, &LibInput::Connection::pointerButtonChanged, this, &InputRedirection::processPointerButton);
connect(conn, &LibInput::Connection::pointerAxisChanged, this, &InputRedirection::processPointerAxis);
connect(conn, &LibInput::Connection::keyChanged, this, &InputRedirection::processKeyboardKey);
connect(conn, &LibInput::Connection::pointerMotion, this,
[this] (QPointF delta, uint32_t time) {
processPointerMotion(m_globalPointer + delta, time);
}
);
connect(conn, &LibInput::Connection::pointerMotionAbsolute, this,
[this] (QPointF orig, QPointF screen, uint32_t time) {
Q_UNUSED(orig)
processPointerMotion(screen, time);
}
);
connect(screens(), &Screens::changed, this, &InputRedirection::updatePointerAfterScreenChange);
// set pos to center of all screens
if (screens()) {
m_globalPointer = screens()->geometry().center();
emit globalPointerChanged(m_globalPointer);
// sanitize
updatePointerAfterScreenChange();
}
}
#endif
}
void InputRedirection::updatePointerWindow()
{
// TODO: handle pointer grab aka popups
@ -197,8 +262,7 @@ void InputRedirection::processPointerMotion(const QPointF &pos, uint32_t time)
Q_UNUSED(time)
// first update to new mouse position
// const QPointF oldPos = m_globalPointer;
m_globalPointer = pos;
emit globalPointerChanged(m_globalPointer);
updatePointerPosition(pos);
// TODO: check which part of KWin would like to intercept the event
QMouseEvent event(QEvent::MouseMove, m_globalPointer.toPoint(), m_globalPointer.toPoint(),
@ -496,4 +560,35 @@ void InputRedirection::registerAxisShortcut(Qt::KeyboardModifiers modifiers, Poi
m_shortcuts->registerAxisShortcut(action, modifiers, axis);
}
static bool screenContainsPos(const QPointF &pos)
{
for (int i = 0; i < screens()->count(); ++i) {
if (screens()->geometry(i).contains(pos.toPoint())) {
return true;
}
}
return false;
}
void InputRedirection::updatePointerPosition(const QPointF &pos)
{
// verify that at least one screen contains the pointer position
if (!screenContainsPos(pos)) {
return;
}
m_globalPointer = pos;
emit globalPointerChanged(m_globalPointer);
}
void InputRedirection::updatePointerAfterScreenChange()
{
if (screenContainsPos(m_globalPointer)) {
// pointer still on a screen
return;
}
// pointer no longer on a screen, reposition to closes screen
m_globalPointer = screens()->geometry(screens()->number(m_globalPointer.toPoint())).center();
emit globalPointerChanged(m_globalPointer);
}
} // namespace

View File

@ -155,6 +155,9 @@ private:
static QEvent::Type buttonStateToEvent(PointerButtonState state);
static Qt::MouseButton buttonToQtMouseButton(uint32_t button);
Toplevel *findToplevel(const QPoint &pos);
void setupLibInput();
void updatePointerPosition(const QPointF &pos);
void updatePointerAfterScreenChange();
QPointF m_globalPointer;
QHash<uint32_t, PointerButtonState> m_pointerButtons;
#if HAVE_XKB

View File

@ -16,6 +16,7 @@ Name=Desktop Effects
Name[ca]=Efectes d'escriptori
Name[ca@valencia]=Efectes d'escriptori
Name[cs]=Efekty na ploše
Name[da]=Skrivebordseffekter
Name[de]=Arbeitsflächen-Effekte
Name[en_GB]=Desktop Effects
Name[es]=Efectos del escritorio
@ -25,6 +26,7 @@ Name[gl]=Efectos do escritorio
Name[hu]=Asztali effektusok
Name[ia]=Effectos de scriptorio
Name[id]=Efek Desktop
Name[it]=Effetti del desktop
Name[ko]=데스크톱 효과
Name[nb]=Skrivebordseffekter
Name[nds]=Schriefdischeffekten
@ -34,6 +36,7 @@ Name[pa]=ਡੈਸਕਟਾਪ ਪਰਭਾਵ
Name[pl]=Efekty pulpitu
Name[pt]=Efeitos do Ecrã
Name[pt_BR]=Efeitos da área de trabalho
Name[ru]=Эффекты
Name[se]=Čállinbeavdeeffeavttat
Name[sk]=Efekty plochy
Name[sl]=Učinki namizja
@ -45,23 +48,29 @@ Name[sv]=Skrivbordseffekter
Name[tr]=Masaüstü Efektleri
Name[uk]=Ефекти стільниці
Name[x-test]=xxDesktop Effectsxx
Name[zh_CN]=桌面特效
Name[zh_TW]=桌面效果
Comment=Desktop Effects
Comment[ca]=Efectes d'escriptori
Comment[cs]=Efekty na ploše
Comment[da]=Skrivebordseffekter
Comment[de]=Arbeitsflächen-Effekte
Comment[en_GB]=Desktop Effects
Comment[es]=Efectos del escritorio
Comment[fi]=Työpöytätehosteet
Comment[fr]=Effets de bureau
Comment[hu]=Asztali effektusok
Comment[ia]=Effectos de scriptorio
Comment[id]=Efek Desktop
Comment[ko]=데스크톱 효과
Comment[nb]=Skrivebordseffekter
Comment[nds]=Schriefdischeffekten
Comment[nl]=Bureaubladeffecten
Comment[pa]=ਡੈਸਕਟਾਪ ਪਰਭਾਵ
Comment[pl]=Efekty pulpitu
Comment[pt]=Efeitos do Ecrã
Comment[pt_BR]=Efeitos da Área de Trabalho
Comment[ru]=Настройка эффектов рабочего стола
Comment[sk]=Efekty plochy
Comment[sl]=Učinki namizja
Comment[sr]=Ефекти површи
@ -71,10 +80,13 @@ Comment[sr@latin]=Efekti površi
Comment[sv]=Skrivbordseffekter
Comment[uk]=Ефекти стільниці
Comment[x-test]=xxDesktop Effectsxx
Comment[zh_CN]=桌面特效
Comment[zh_TW]=桌面效果
X-KDE-Keywords=kwin,window,manager,compositing,effect,3D effects,2D effects,OpenGL,XRender,video settings,graphical effects,desktop effects,animations,various animations,window management effects,window switching effect,desktop switching effect,animations,animation speed,desktop animations,drivers,driver settings,rendering,render,invert effect,looking glass effect,magnifier effect,snap helper effect,track mouse effect,zoom effect,blur effect,dashboard effect,explosion effect,fade effect,fade desktop effect,fall apart effect,glide effect,highlight window effect,login effect,logout effect,magic lamp effect,minimize animation effect,mouse mark effect,scale in effect,screenshot effect,sheet effect,slide effect,sliding popups effect,taskbar thumbnails effect,thumbnail aside effect,translucency,translucency effect,transparency,window geometry effect,wobbly windows effect,startup feedback effect,dialog parent effect,dim inactive effect,dim screen effect,slide back effect,eye candy,candy,show FPS effect,show paint effect,box switch effect,cover switch effect,desktop cube effect,desktop cube animation effect,desktop grid effect,flip switch effect,outline effect,present windows effect,resize window effect
X-KDE-Keywords[ca]=kwin,finestra,gestor,composició,efecte,efectes 3D,efectes 2D,OpenGL,XRender,arranjament de vídeo,efectes gràfics,efectes d'escriptori,animacions,animacions diverses,efectes de gestió de finestra,efecte de canvi de finestra,efecte de canvi d'escriptori,animacions,velocitat d'animació,animacions d'escriptori,controladors,configuració de controladors,renderització,render,efecte d'inversió,efecte d'aparença de vidre,efecte de lupa,efecte ajudant de desplaçament,efecte de seguiment de ratolí,efecte de zoom,efecte de difuminat,efecte de tauler,efecte d'explosió,efecte d'esvaïment,efecte d'esvaïment d'escriptori,efecte de trencament,efecte de lliscament,efecte de ressaltat de finestra,efecte de connexió,efecte de desconnexió,efecte de làmpada màgica,efecte d'animació de minimització,efecte de marca de ratolí,efecte d'apropament,efecte de captura de pantalla,efecte de full,efecte de diapositiva,efecte de missatges emergents lliscants,efecte de miniatures de barra de tasques,efecte de miniatures laterals,translucidesa,efecte de translucidesa,transparència,efecte de geometria de finestra,efecte de finestres sacsejades,efecte de confirmació d'engegada,efecte de diàleg principal,efecte d'enfosquiment d'inactiu,efecte d'enfosquiment de pantalla, efecte de diapositiva prèvia,decoració,efecte per mostrar FPS,efecte de mostra de pintat,efecte de quadre de commutació,efecte de canvi de coberta,efecte de cub d'escriptori,efecte d'animació de cub d'escriptori,efecte de graella d'escriptori,efecte de canvi en roda,efecte de contorn,efecte de presentació de finestres,efecte de redimensió de finestra
X-KDE-Keywords[ca@valencia]=kwin,finestra,gestor,composició,efecte,efectes 3D,efectes 2D,OpenGL,XRender,arranjament de vídeo,efectes gràfics,efectes d'escriptori,animacions,animacions diverses,efectes de gestió de finestra,efecte de canvi de finestra,efecte de canvi d'escriptori,animacions,velocitat d'animació,animacions d'escriptori,controladors,configuració de controladors,renderització,render,efecte d'inversió,efecte d'aparença de vidre,efecte de lupa,efecte ajudant de desplaçament,efecte de seguiment de ratolí,efecte de zoom,efecte de difuminat,efecte de tauler,efecte d'explosió,efecte d'esvaïment,efecte d'esvaïment d'escriptori,efecte de trencament,efecte de lliscament,efecte de ressaltat de finestra,efecte de connexió,efecte de desconnexió,efecte de làmpada màgica,efecte d'animació de minimització,efecte de marca de ratolí,efecte d'apropament,efecte de captura de pantalla,efecte de full,efecte de diapositiva,efecte de missatges emergents lliscants,efecte de miniatures de barra de tasques,efecte de miniatures laterals,translucidesa,efecte de translucidesa,transparència,efecte de geometria de finestra,efecte de finestres sacsejades,efecte de confirmació d'engegada,efecte de diàleg principal,efecte d'enfosquiment d'inactiu,efecte d'enfosquiment de pantalla, efecte de diapositiva prèvia,decoració,efecte per mostrar FPS,efecte de mostra de pintat,efecte de quadre de commutació,efecte de canvi de coberta,efecte de cub d'escriptori,efecte d'animació de cub d'escriptori,efecte de graella d'escriptori,efecte de canvi en roda,efecte de contorn,efecte de presentació de finestres,efecte de redimensió de finestra
X-KDE-Keywords[da]=kwin,vindue,vindueshåndtering,compositing,effekter,3D-effekter,2D-effekter,OpenGL,XRender,grafiske effekter,skrivebordseffekter,animationer,diverse animationer,vindueshåndteringseffekter,effekt til skift af vinduer,effekt til skrivebordsskift,animationshastighed,skrivebordsanimationer,drivere,driverindstillinger,rendering,render,invertereffect,kikkerteffekt,forstørrelsesglaseffekt,hægtehjælpereffekt,følg musen-effekt,zoomeffect,sløreffekt,instrumentbræt,eksplosionseffekt,fade-effect,svæve-effect,fremhæv vindue-effekt,login-effekt,log ud-effekt,magisk lampe-effekt,minimer-effekt,musemærke-effekt,skalerind-effekt,skærmbillede-effekt,glide-effekt,glidende pop-op-effekt,opgavelinjeminiaturer-effekt,gennemsigtighed,transparens,ugennemsigtighed,vinduesgeometri-effekt,wobbly,blævrende vinduer,eye candy,øjeguf,vis FPS-effekt,cube,terning,gitter
X-KDE-Keywords[de]=KWin,Fenster,Verwaltung,Compositing,Effekt,2D-Effekte,3D-Effekte,OpenGL,XRender,Videoeinstellungen,Gradische Effekte,Desktopeffekte,Arbeitsflächeneffekte,Animation,Fensterverwaltungs-Effekte,Fensterwechsel-Effekte,Decktopwechsel,Arbeitsflächenwechsel,Animationsgeschwindigkeit,Deskto-Animation,Arbeitsflächen-Animation,Treiber,Treibereinstellung,Rendering,Rendern,Invertierungseffekt,Bildschirmlupeneffekt,Vergrößerungseffekt,Einrasteffekt,Maus folgen,Zooneffekt,Dashboard.Effekt,Explosionseffekt,Überblendungseffekt,Gleiteneffekt,Fensterhervorhebungs-Effekt,Anmeldungseffekt,Abmeldungseffekt,Animierter Minimierungseffekt,Mausmarkierungseffekt,Skalierungseffekt,Bildschirmeffekt,Blatteffekt,Folieneffekt,Vorschaueffekt der Kontrollleiste,Vorschaueffekt,Durchsichtigkeit,Durchsichtigkeitseffekt,Fenstergeometrieffekt,Effekt Wabernde Fenster,Programmstartanzeigeneffekt,Inaktiveffekt,Bildschirmabdunkelungseffekt,FPS-Effekt,Zeichnungsbereicheffekt,Kasten mit Minibilderneffekt,3D-Fenstergalerieeffekt,Desktopgittereffekt,3D-Fensterstapelumschalteffekt,Umrisseffekt,Fensteranzeigeeffekt,Fenstergrößenänderungseffekt
X-KDE-Keywords[en_GB]=kwin,window,manager,compositing,effect,3D effects,2D effects,OpenGL,XRender,video settings,graphical effects,desktop effects,animations,various animations,window management effects,window switching effect,desktop switching effect,animations,animation speed,desktop animations,drivers,driver settings,rendering,render,invert effect,looking glass effect,magnifier effect,snap helper effect,track mouse effect,zoom effect,blur effect,dashboard effect,explosion effect,fade effect,fade desktop effect,fall apart effect,glide effect,highlight window effect,login effect,logout effect,magic lamp effect,minimize animation effect,mouse mark effect,scale in effect,screenshot effect,sheet effect,slide effect,sliding popups effect,taskbar thumbnails effect,thumbnail aside effect,translucency,translucency effect,transparency,window geometry effect,wobbly windows effect,startup feedback effect,dialog parent effect,dim inactive effect,dim screen effect,slide back effect,eye candy,candy,show FPS effect,show paint effect,box switch effect,cover switch effect,desktop cube effect,desktop cube animation effect,desktop grid effect,flip switch effect,outline effect,present windows effect,resize window effect
X-KDE-Keywords[es]=kwin,ventana,gestor,composición,efecto,efectos 3D,efectos 2D,OpenGL,XRender,preferencias de vídeo,efectos gráficos,efectos del escritorio,animaciones,animaciones diversas,efectos de la gestión de ventanas,efecto de cambio de ventana,efecto de cambio de escritorio,velocidad de animación,animaciones del escritorio,controladores,preferencias del controlador,renderización,renderizar,efecto de inversión,efecto de espejo,efecto de lupa,efecto auxiliar de instantánea,efecto de seguimiento del ratón,efecto de ampliación,efecto borroso,efecto del tablero de mandos,efecto de explosión,efecto de desvanecimiento,efecto de desvanecimiento del escritorio,efecto de romper en pedazos,efecto de planeo,efecto de resaltar ventanas,efecto de inicio de sesión,efecto de final de sesión,efecto de lámpara mágica,efecto de animación al minimizar,efecto de marcas del ratón,efecto de escalado,efecto de captura de pantalla,efecto de hoja,efecto de deslizamiento,efecto de ventanas emergentes deslizantes,efecto de miniaturas de la barra de tareas,efecto de miniaturas laterales,transparencia,efecto de transparencia,efecto de geometría de las ventanas,efecto de ventanas gelatinosas,efecto de notificación de inicio,efecto de padre de la ventana,efecto de oscurecer inactiva,efecto de oscurecer la pantalla,efecto atrás,efectos atractivos,efecto de mostrar FPS,efecto de mostrar pintura,efecto de selección de ventana en caja,efecto de selección de ventana en modo carátula,efecto de cubo del escritorio,efecto de animación del cubo del escritorio,efecto de rejilla del escritorio,efecto de selección de ventana en modo cascada,efecto de contorno,efecto de presentación de ventanas,efecto de cambiar tamaño de las ventanas
@ -84,6 +96,7 @@ X-KDE-Keywords[gl]=kwin,xanela,xestor,composición,efecto,efectos 3D,efectos 2D,
X-KDE-Keywords[hu]=kwin,ablak,kezelő,kompozitálás,hatás,3D hatás,2D hatás,OpenGL,XRender,videobeállítások,grafikai hatások,asztali hatások,animációk,különféle animációk,ablakkezelő hatások,ablakváltó hatások,asztalváltó hatások,animációk,animáció sebesség,asztali animációk,meghajtók,meghajtó beállítások,leképezés,renderelés,fordított hatás,tükörhatás,nagyító hatás,elkapás segítő hatás,egérkövetés hatás,nagyítás hatás,elmosás hatás,áttekintő hatás,robbanás hatás,elhalványulás hatás,asztal elhalványulása hatás,széteső hatás,csúszás hatás,ablak kiemelése hatás,belépés hatás,kilépés hatás,varázslámpa hatás,minimalizálás animáció hatás,egérjelölés hatás,méretezés hatás,képernyőkép hatás,munkalap hatás,dia hatás,csúszó felugrók hatás,feladatsáv bélyegképek hatás,bélyegképek félre hatás,áttetszőség,áttetszőség hatás,átlátszóság,ablak geometria hatás,ingó ablak hatás,indulási visszajelzés hatás,párbeszédablak szülő hatás,dim inaktív hatás,dim kijelző hatás,dia vissza hatás,látványelem,édesség,FPS megjelenítése hatás,festék megjelenése hatás,dobozváltás hatás,eltakarás váltás hatás,asztal kocka hatás,asztal kockaanimáció hatás,asztal rács hatás,tükrözésváltás hatás,körvonal hatás,jelenlegi ablakok hatás,ablak átméretezése hatás
X-KDE-Keywords[ia]=kwin,fenestra,gerente,componente,effecto,effectos 3D,effectos 2D,OpenGL,XRender,preferentias de video,effectos graphic,effectos de scriptorio,animationes,varie animationes,effectos de gestion de genestra,effecto de commutation de fenestra, effecto de commutation de scriptorio,animationes,velocitate de animation,animationes de scriptorio,drivers, preferentias de driver,rendering,render,effecto de inverter,effecto speculo,effecto aggrandor,effecto de adjuta de photo (snap),effecto de tracia de mus,effecto zoom,effecto indistincte,effecto tabuliero,effecto explosion,effecto discolorate,effect de scriptorio discolorate,effecto de collapsar,effecto glissante, effecto de fenestra evidentiare,effecto de authenticar se,effecto de clauder session ,effecto lampada magic,minimisa effecto de animation,effecto de marca de mus,effecto de scalar,effecto de captura schermo,effecto folio,effecto diapositiva, effecto de popups glissante,effecto de miniatura de barra de carga,effecto de miniatura a parte,translucentia, effecto translucentia,transparentia, effecto de geometria de fenestra, effecto de fenestra tremulante,effecto de retro action, effecto de geniytor de dialogo, effecto inactive obscur, effecto de schermo obscur,effecto de retro glissar,eye candy,candy,monstra effecto FPS,monstra effecto pictura, effecto commuta cassa,effecto de commuta coperturat,effecto cubo de scriptorio,animation de cubo de scriptorio,effecto grillia de scriptorio,effecto flip switch,effecto contorno,effecto de fenestra actual,effecto de fenestra redimensionante
X-KDE-Keywords[id]=kwin,jendela,manajer,menggabungkan,efek,efek 3D,efek 2D,OpenGL,XRender,pengaturan video,efek grafis,efek desktop,animasi,beragam animasi,efek manajemen jendela,efek berpindah jendela,efek berpindah desktop,animasi,kecepatan animasi,animasi desktop,penggerak,pengaturan penggerak,rendering,render,efek terbalik,efek seperti gelas,efek pembesar,efek pembantu patah,efek jejak tetikus,efek pembesaran,efek pudar,efek dasbor,efek ledakan,efek kabur,efek desktop kabur,efek hancur,efek luncur,efek jendela sorot,efek masuk,efek keluar,efek lampu ajaib,efek animasi minimalkan,efek tanda tetikus,efek skala masuk,efek cuplikan layar,efek lembar,efek salindia,efek popup geser,efek miniatur batang tugas,efek bergeser miniatur,translusensi,efek translusensi,transparan,efek geometri jendela,efek jendela gemetar,efek umpan balik startup,manisan,permen,efek tampilkan FPS,efek tampilkan lukisan,efek pindah kotak,efek pindah sampul,efek kubus desktop,efek animasi kubus desktop,efek grid,efek pindah balik,efek kerangka,efek jendela saat ini,efek ubah ukuran jendela
X-KDE-Keywords[it]=kwin,finestra,gestore,composizione,effetto,effetti 3D,effetti 2D,OpenGL,XRender,impostazioni video,effetti grefici,effetti desktop,animazioni,animazioni varie, effetti del gestore delle finestre,effetto dello scambiafinestre, effetto dello scambiatore di desktop,animazioni,velocità animazioni,animazioni desktop,driver,impostazioni driver,disegno,rendering,effetto invertito,effetto vetro,effetto lente,effetto snap helper,effetto evidenzia mouse,effetto ingrandimento, effetto sfocatura,effetto quadro degli strumenti,effetto esplosione,effetto dissolvenza,effetto dissolvenza desktop,effetto caduta,effetto planatura,effetto evidenziazione finestra,effetto schermata di accesso, effetto disconnessione,effetto lampada magica,effetto animazione di minimizzazione,effetto tracciatura mouse, effetto scalatura,effetto istantanea,effetto foglio,effetto diapositiva,effetto scivolamento,effetto icone nella barra delle applicazioni,effetto miniatura su un lato,translucenza,effetto translucenza, trasparenza,effetto geometria finestra,effetto finestre tremolanti,effetto segnale di avvio,effetto finestra padre,effetto oscura finestra inattiva,effetto oscura schermo,effetto scivola all'indietro,gradevole,effetto gradevole,effetto mostra FPS,effetto ridisegno,effetto scambio cubi,effetto scambio copertina,effetto cubi del desktop,effetto animazione cubi del desktop,effetto griglia desktop,effetto scambiatore con inversione,effetto riquadro,effetto finestra presente,effetto ridimensionamento finestra
X-KDE-Keywords[ko]=kwin,window,manager,compositing,effect,3D effects,2D effects,OpenGL,XRender,video settings,graphical effects,desktop effects,animations,various animations,window management effects,window switching effect,desktop switching effect,animations,animation speed,desktop animations,drivers,driver settings,rendering,render,invert effect,looking glass effect,magnifier effect,snap helper effect,track mouse effect,zoom effect,blur effect,dashboard effect,explosion effect,fade effect,fade desktop effect,fall apart effect,glide effect,highlight window effect,login effect,logout effect,magic lamp effect,minimize animation effect,mouse mark effect,scale in effect,screenshot effect,sheet effect,slide effect,sliding popups effect,taskbar thumbnails effect,thumbnail aside effect,translucency,translucency effect,transparency,window geometry effect,wobbly windows effect,startup feedback effect,dialog parent effect,dim inactive effect,dim screen effect,slide back effect,eye candy,candy,show FPS effect,show paint effect,box switch effect,cover switch effect,desktop cube effect,desktop cube animation effect,desktop grid effect,flip switch effect,outline effect,present windows effect,resize window effect,창,관리자,컴포지팅,효과,3D 효과,2D 효과,비디오 설정,그래픽 효과,데스크톱 효과,애니메이션,창 관리자,창 관리자 효과,데스크톱 전환,데스크톱 전환 효과,드라이버,드라이버 설정,렌더링,렌더링 설정,애니메이션 속도,투명 유리 효과,확대 축소 효과,흐림 효과,대시보드 효과,폭발 효과,페이드 효과,로그인 효과,창 강조 효과,글라이드 효과,로그아웃 효과,램프 효과,시트 효과,최소화 효과,최대화 효과,팝업 효과
X-KDE-Keywords[nb]=kwin,vindusbehandler,sammensetting,effekt,3D-effekter,2D-effekter,OpenGL,XRender,videoinnstillinger,grafiske effekter,skrivebordseffekter,animasjoner,diverse animasjoner,vindusbytteeffekter,effekter ved skrivebordsbytte,animasjoner,animasjonsfart,skrivebordsanimasjoner,drivere,driverinnstillinger,opptegning,opptegner,inverteringseffekt,speileffekt,lupeeffekt,gripehjelpereffekt,musesporeffekt,forstørreeffekt,sløreffekt,kontrollpulteffekt,eksplosjonseffekt,uttoningseffekt,skrivebordtoningseffekt,henfallseffekt,glidereffekt,framhev vindu-effekt,innlogingseffekt,utloggingsefffekt,magisk lampe-effekt, animasjonseffekt ved vindusminimering,musmerkeeffekt,innskaleringseffekt,skjermdumpeffekt,ark-effekt,lysbildeeffekt,glidende oppspretteffekt,effekt for minibilder på oppgavelinja,effekt for minibilder på siden,gjennomskinnelighetseffekt,gjennomsiktighet,vindusgeometri-effekt,skjelvende vinduer-effekt,effekt for oppstartsmelding,effekt for foreldredialog,effekt for mørk inaktiv,effekt for mørk skjerm,gli tilbake-effekt,øyesnop,snop,vis FPS-effekt,vis malingseffekt,boksbytteeffekt,lokkbytteeffekt,skrivebordsterning-effekt,effekt for animert skrivebordsterning,effekt for skrivebordsruter,effekt for flipp-bytte,omriss-effekt,effekt for vinduer tilstede,effekt for vinduer som endrer størrelse
X-KDE-Keywords[nds]=KWin,Finster,Pleger,Tosamensetten,Effekt,3D,2D,OpenGL,XRender,Videoinstellen,graafsche Effekten,Schriefdisch,Animeren,wesseln,Finsterwesseln,Schriefdischwesseln,Gauigkeit,Drievers,Dorstellen,ümdreihen,Kiekglas,Luup,andocken,Muusspoor,Grötter maken,Ansichtgrött,verwischen,Exploschoon,Utblennen,Uteneenbreken,glieden,markeren,anmellen,afmellen,magisch lamp,minimeren,Muusmark,Schirmfoto,Programmbalken,Vöransichten,Dörschienen,Finstergeometrie,Wabbeligkeit,Start,Torüchmelen,Böverfinster,Dialoog,afdüüstern,Ogenzucker,FPS,Kist,Schriefdischwörpel,Gadder,Dörgahn,Ümdreihen,Ümreet,Grött ännern
@ -91,6 +104,7 @@ X-KDE-Keywords[nl]=kwin,venster,beheerder,compositing,effect,3D effecten,2D effe
X-KDE-Keywords[pl]=kwin,okno,menadżer,kompozycje,efekt,efekty 3D,efekty 2D,OpenGL,XRender, ustawienia wideo,efekty graficzne,efekty pulpitu,animacje,różne animacje,efekty zarządzania oknami,efekty przełączania okien,efekty przełączania pulpitów,animacje, szybkość animacji,animacje pulpitu,sterowniki,ustawienia sterowników,renderowania, efekt odwrócenia,szkło powiększające,efekt powiększenia,efekt pomocnika przyciągania, efekt śledzenia myszy,efekt przybliżenia,efekt rozmycia,efekt tablicy,efekt eksplozji,efekt zanikania,efekt zanikania pulpitu,efekt rozpadania,efekt slajdu,efekt podświetlania okna, efekt logowania,efekt wylogowywania,efekt magicznej lampy,efekt animacji minimalizacji, efekt znacznika myszy,efekt skalowania,efekt zrzutu ekranu,efekt arkusza,efekt slajdu,efekt wysuwających się elementów wyskakujących,efekt prześwitywania,przezroczystość,efekt geometrii okna,efekt chwiejnych okien,efekt odczuć przy starcie,efekt okna rodzica,efekt przyciemniania nieaktywnych,efekt przyciemniania ekranu,efekt przesuwania do tył,efekt pokazania ilości klatek na sekundę
X-KDE-Keywords[pt]=kwin,janela,gestor,composição,efeito,efeitos 3D,efeitos 2D,OpenGL,XRender,configuração do vídeo,efeitos gráficos,efeitos do ecrã,animações,animações diversas,efeitos de gestão das janelas,efeito de mudança de janelas,efeito de mudança de ecrãs,animações,velocidade da animação,animações do ecrã,controladores,configuração dos controladores,desenho,efeito de inversão,efeito de lupa,efeito de lente,efeito de ajuda no ajuste, efeito de seguimento do rato,efeito de ampliação,efeito de borrão,efeito de quadro,efeito de explosão,efeito de desvanecimento,efeito de desvanecimento do ecrã,efeito de destruição,efeito de deslizamento,efeito de realce da janela,efeito na autenticação,efeito do encerramento,efeito de lâmpada mágica,efeito de animação na minimização,efeito de marcação com rato,efeito de escala,efeito de captura do ecrã,efeito de folha,efeito de mensagens deslizantes,efeito de miniaturas na barra de tarefas,efeito de miniaturas laterais,efeito de janelas a tremer,efeito do arranque inicial,efeito da janela-mãe,efeito de escurecimento de janelas inactivas,efeito de deslize para trás,efeitos visuais,beleza,efeito de apresentação das IPS,efeito de pintura,efeito de mudança em caixa,efeito de mudança de capas, efeito de animação do cubo do ecrã,efeito de grelha do ecrã,efeito de mudança por viragem,efeito de destaque,efeito de apresentação das janelas,efeito de dimensionamento das janelas
X-KDE-Keywords[pt_BR]=kwin,janela,gerenciador,composição,efeito,efeitos 3D,efeitos 2D,OpenGL,XRender,configuração do vídeo,efeitos gráficos,efeitos da área de trabalho,animações,animações diversas,efeitos do gerenciamento de janelas,efeito de mudança de janelas,efeito de mudança de área de trabalho,velocidade da animação,animações da área de trabalho,drivers,configuração dos drivers,desenho,renderização,efeito de inversão,efeito de lupa,efeito de lente,efeito de ajuda no ajuste,efeito de rastreamento do mouse,efeito de ampliação,efeito de borrão,efeito de quadro,efeito de explosão,efeito de escurecimento,efeito de escurecimento da área de trabalho,efeito de destruição,efeito de deslizamento,efeito de realce da janela,efeito na autenticação,efeito de encerramento de sessão,efeito de lâmpada mágica,efeito de animação na minimização,efeito de marcação com mouse,efeito em escala,efeito de captura de tela,efeito de folha,efeito de slide,efeito de mensagens deslizantes,efeito de miniaturas na barra de tarefas,efeito de miniaturas laterais,transparência,efeito de transparência,efeito de geometria de janelas,efeito de janelas trêmulas,efeito do inicialização,efeito da janela-mãe,efeito de escurecimento de janelas inativas,efeito de deslize para trás,efeitos visuais,beleza,efeito de apresentação de FPS,efeito de pintura,efeito de mudança em caixa,efeito de mudança de capas,efeito de animação do cubo da área de trabalho,efeito de grade da área de trabalho,efeito de mudança em pilha,efeito de destaque,efeito de apresentação das janelas,efeito de dimensionamento das janelas
X-KDE-Keywords[ru]=kwin,window,manager,compositing,effect,3D effects,2D effects,OpenGL,XRender,video settings,graphical effects,desktop effects,композитинг,композитный диспетчер окон,эффекты рабочего стола,графические эффекты,рендеринг,параметры видео,настройка видео,трёхмерные эффекты,двумерные эффекты,эффекты управления окнами,эффекты диспетчера окон,анимация куба рабочих столов,плавная смена рабочих столов,прокрутка,анимация всплывающих окон,анимация появления окна,вход в систему,завершение сеанса,завершение работы,колышущиеся окна,болтающиеся окна,колыхание окон,край экрана,лист,анимация распахивания,анимация максимизации,максимизация окна,распахивание окна,миниатюры окон сбоку,миниатюры окон на краю экрана,полупрозрачность окон,размытие фона,размывание фона,распад закрывающихся окон,растворение закрывающихся окон,рисование на экране,рисование мышью на экране,скольжение окон,анимация сворачивания,сворачивание окон,волшебная лампа,график производительности,производительность эффектов,подсветка отрисовки,подсветка рендеринга,подсветка обновляемых частей экрана,анимация щелчка мышью,инверсия цветов,инвертирование цветов,поиск курсора мыши,разметка экрана,сетка на экране,линейки на экране,экранная разметка,экранная сетка,линза,искажение линзой,лупа,увеличение области экрана,масштаб рабочего стола,изменение масштаба рабочего стола,управление окнами,специальные возможности,инструменты,внешний вид,анимация переключения рабочих столов,все окна,просмотр всех окон,все рабочие столы,просмотр всех рабочих столов,изменение размера окна,масштабирование текстуры окна,куб с рабочими столами,перелистывание окон,управление фокусом,затемнение неактивных окон,затемнение основного окна,затемнение под диалогом,затемнение экрана при административной задаче,соскальзывание окон при смене фокуса
X-KDE-Keywords[sk]=kwin, okno, manažér, kompozícia, efekt, 3D efekty, 2D efekty, OpenGL, XRender,nastavenia obrazu, grafické efekty, desktop efekty, animácie, rôzneanimácie, efekty správa okien, okno prepínanie efektov, stolnýspínacie efekt, animácie, animácie rýchlosť, stolný animácie, ovládače,nastavenie ovládača, renderovanie, poskytnúť, invertný skutočnosti zrkadlá účinok,lupa efekt, snap pomocník efekt, trať myš efekt, zoom efekt, rozmazaniuúčinok, prístrojová doska efekt, výbuch efekt, fade efekt, fade stolný efekt,rozpadnúť účinok, zostupovej efekt, zvýraznenie okno efekt, efekt prihlásenie, odhlásenieúčinok, čarovnú lampu účinok, minimálny efekt animácie, myši značky efekt, mierkav skutočnosti, screenshot efekt, list efekt, snímka efekt, posuvné vyskakovacie okná účinok,miniatúry na hlavnom paneli efekt, náhľad stranou efekt, priesvitnosť, translucencieúčinok, transparentnosť, okno geometrie efekt, vratkú okná efekt, uvedenie do prevádzkyspätná väzba, dialóg rodič efekt, matný efekt neaktívny, stlmiť obrazovku efekt,posunutím zadnej efekt, pastva pre oči, cukrík zobraziť FPS efekt, zobrazovať farby efekt, boxprepínač efekt, kryt prepínače účinok, desktop, desktop cube efekt kocky animácieúčinok, Desktop Grid efekt, flip switch efekt, obrys účinok, súčasné oknáúčinok, zmena veľkosti okna efekt
X-KDE-Keywords[sl]=kwin,upravljalnik oken,skladanje,učinek,učinki 3d,učinki 2d,opengl,xrender,grafične nastavitve,grafični učinki,namizni učinki,animacije,upravljanje z okni,preklapljanje oken,preklapljanje namizij,hitrost animacij,namizne animacije,gonilniki,izrisovanje,obrni,povečevalno steklo,pripenjalni pomagalnik,sledenje miški,približanje,zabriši,nadzorna plošča,eksplozija,pojemanje,pojemanje namizja,razpad,drsenje,poudari okno,učinek prijave,učinek odjave,čarobna svetilka,animacija skrčenja,risanje,animirano pojavljanje,zaslonska slika,list,drsenje,drseča pojavna okna,sličice za opravilno vrstico,sličica ob strani,prosojnost,prozornost,geometrija okna,majava okna,odziv zagona,nadrejeno pogovorno okno,potemni nedejavno,potemni zaslon,zdrs v ozadje,vidni bonbončki,pokaži sličice na sekundo,izrisovanje,preklapljanje - škatla,preklapljanje - ovitki,kocka z namizji,animacija kocka z namizji,mreža namizij,preklapljanje - sklad,oris,predstavi okna,spreminjanje velikosti okna
X-KDE-Keywords[sr]=kwin,window,manager,compositing,effect,3D effects,2D effects,OpenGL,XRender,video settings,graphical effects,desktop effects,animations,various animations,window management effects,window switching effect,desktop switching effect,animations,animation speed,desktop animations,drivers,driver settings,rendering,render,invert effect,looking glass effect,magnifier effect,snap helper effect,track mouse effect,zoom effect,blur effect,dashboard effect,explosion effect,fade effect,fade desktop effect,fall apart effect,glide effect,highlight window effect,login effect,logout effect,magic lamp effect,minimize animation effect,mouse mark effect,scale in effect,screenshot effect,sheet effect,slide effect,sliding popups effect,taskbar thumbnails effect,thumbnail aside effect,translucency,translucency effect,transparency,window geometry effect,wobbly windows effect,startup feedback effect,dialog parent effect,dim inactive effect,dim screen effect,slide back effect,eye candy,candy,show FPS effect,show paint effect,box switch effect,cover switch effect,desktop cube effect,desktop cube animation effect,desktop grid effect,flip switch effect,outline effect,present windows effect,resize window effect,К‑вин,прозор,менаџер,слагање,ефекат,3Д ефекти,2Д ефекти,опенГЛ,Икс‑рендер,видео поставке,графички ефекти,ефекти површи,анимације,разне анимације,ефекти управљања прозорима,ефекти мењања прозора,ефекти мењања површи,анимације,брзина анимације,анимације површи,драјвери,поставке драјвера,рендеровање,исцртавање,ефекат извртања,ефекат лупе,ефекат уклапања,ефекат праћења миша,ефекат увеличања,ефекат замућења,инструмент-табла,ефекат експлозије,ефекат утапања,ефеката утапања површи,ефекат распадања,ефекат распарчавања,ефекат клизања,ефекат истицања прозора,ефекат пријављивања,ефекат одјављивања,ефекат магичне лампе,ефекат минимизовања,ефекат трагова миша,ефекат скалирања,ефекат снимка екрана,ефекат листа,ефекат клизања,ефекат клизајућих искакача,ефекат ефекат сличица на траци задатака,ефекат прозирности,прозирност,провидност,ефекат геометрије прозора,ефекат лелујајућих прозора,ефекат одзива покретања,ефекат родитељског дијалог,ефекат потамњења неактивног,ефекат потамњења екрана,шминка,ефекат приказивања,ефекат кутијастог пребацивања,ефекат коцке површи,ефекат анимације коцке површи,ефекат мреже површи,ефекат превртања,ефекат представљања прозора,ефекат промене величине прозора
@ -100,5 +114,6 @@ X-KDE-Keywords[sr@latin]=kwin,window,manager,compositing,effect,3D effects,2D ef
X-KDE-Keywords[sv]=kwin,fönster,hanterare,sammansättning,effekt,3D-effekter,OpenGL,Xrender,videoinställningar,grafiska effekter,skrivbordseffekter,animeringar,diverse animeringar,fönsterhanteringseffekter,fönsterbyteseffekt,skrivbordsbyteseffekt,animeringshastighet,skrivbordsanimeringar,drivrutiner,drivrutininställningar,återgivning,återge,inverteringseffekt,förstoringsglaseffekt,förstoringseffekt,låshjälpeffekt,musföljningseffekt,zoomeffekt,suddighetseffekt,instrumentpaneleffekt,explosionseffekt,borttoningseffekt,skrivbordsborttoningseffekt,sönderfallseffekt,glidningseffekt,fönstermarkeringseffekt,inloggningseffekt,utloggningseffekt,magisk lampeffekt,minimeringsanimeringseffekt,musmarkeringseffekt,inskalningseffekt,skärmbildseffekt,bladeffekt,skjuteffekt,glidande ruteffekt,miniatyrbilder i aktivitetsfältet,miniatyrbild vid sidan om,genomskinlighet,genomskinlighetseffekt,fönstergeometrieffekt,ostadiga fönster,startgensvarseffekt,dialogrutors ägare,dämpa inaktiva,dämpa skärmen,glid tillbaka,ögongodis,visa ramar/s,visa uppritning,byte med ruta,omslagsbyte,skrivbordskub,animeringseffekt för skrivbordskub,skrivbordsrutnät,blädderbyteseffekt,kontureffekt,befintliga fönster,ändra fönsterstorlek
X-KDE-Keywords[tr]=kwin,pencere,yönetici,birleştirme,efekt,3D efektler,2D efektler,OpenGL,XRender,görüntü ayarları,grafiksel efektler,masaüstü efektleri,animasyonlar,çeşitli animasyonlar,pencere yönetimi efektleri,pencere geçiş efekti,masaüstü geçiş efekti,canlandırmalar,canlandırma hızı,masaüstü animasyonları,sürücüler,sürücü ayarları,hazırlama,hazırla,ters efekt,gözlük efekti,büyüteç efekti,yakalama yardımcısı efekti,fareyi izleme efekti,yakınlaştırma efekti,buğu efekti,pano efekti,patlama efekti,kaybolma efekti,masasütü kaybolma efekti,düşme efekti,sürülme efekti,pencere vurgulama efekti,oturum açma efekti,oturum kapatma efekti,sihirli lamba efekti,küçültme animasyonu efekti,fare işaretleme efekti,boyutlandırma efekti,ekran yakalama efekti,kağıt efekti,kaydırma efekti,kayan pencereler efekti,görev çubuğu önizlemeleri efekti,önizleme gösterme efekti,saydamlık,sayfamlık efekti,saeoydamlık,pencere geometri efekti,sallanan pencereler efekti,başlatma geribildirim efekti,üst pencere efekti,etkin olmayanı soldurma efekti,ekranı soldurma efekti,geri kayma efekti,göz alıcı,şeker,FPS gösterme efekti,boyama gösterme efekti,kutu değiştirme efekti,kapak değiştirme efekti,masaüstü küp efekti,masaüstü küp animasyonu efekti,masaüstü ızgara efekti,döndürme geçişi efekti,dış kenarlık efekti,güncel pencereler efekti,pencereyi yeniden boyutlandırma efekti
X-KDE-Keywords[uk]=kwin,window,manager,compositing,effect,3D effects,2D effects,OpenGL,XRender,video settings,graphical effects,desktop effects,animations,various animations,window management effects,window switching effect,desktop switching effect,animations,animation speed,desktop animations,drivers,driver settings,rendering,render,invert effect,looking glass effect,magnifier effect,snap helper effect,track mouse effect,zoom effect,blur effect,dashboard effect,explosion effect,fade effect,fade desktop effect,fall apart effect,glide effect,highlight window effect,login effect,logout effect,magic lamp effect,minimize animation effect,mouse mark effect,scale in effect,screenshot effect,sheet effect,slide effect,sliding popups effect,taskbar thumbnails effect,thumbnail aside effect,translucency,translucency effect,transparency,window geometry effect,wobbly windows effect,startup feedback effect,dialog parent effect,dim inactive effect,dim screen effect,slide back effect,eye candy,candy,show FPS effect,show paint effect,box switch effect,cover switch effect,desktop cube effect,desktop cube animation effect,desktop grid effect,flip switch effect,outline effect,present windows effect,resize window effect,вікно,керування вікнами,менеджер вікон,композитне відтворення,ефект,просторовий,плоский,параметри відео,графічні ефекти,анімації,анімація,перемикання вікон,швидкість анімації,драйвери,параметри драйверів,показ,відтворення,інвертування,інверсія,збільшувальне скло,збільшення,прилипання,шлейф за вказівником,шлейф,масштабування,масштаб,зміна розмірів,розмивання,панель приладів,панель,вибух,ефекти вибуху,згасання,поява,ковзання,підсвічування,підсвічування вікон,вихід,магічна лампа,чарівна лампа,джин,аркуші,стос,знімок екрана,мініатюри панелі задач,мініатюри,прозорість,ефект прозорості,желе,желейні вікна,супровід запуску,стрибунець,притлумлення,сірість,прикраси,показ частоти,малювання,обкладинки,стрибання,контур,поточні вікна,зміна розмірів
X-KDE-Keywords[vi]=kwin, cửa sổ, quản lý, hợp lại, hiệu lực, hiệu ứng 3D, hiệu ứng 2D, OpenGL, XRender, cài đặt video, hiệu ứng đồ họa, hiệu ứng máy tính để bàn, hình ảnh động, nhiều hình ảnh động, hiệu ứng quản lý cửa sổ, cửa sổ chuyển đổi có hiệu lực, máy tính để bàn chuyển đổi có hiệu lực, hình ảnh động, tốc độ hoạt hình, hoạt hình máy tính để bàn, trình điều khiển, cài đặt trình điều khiển, vẽ, vẽ lại, đảo ngược tác dụng, tìm hiệu ứng nhà kính, hiệu lực kính lúp, chụp hiệu quả trợ giúp, hiệu quả theo dõi chuột, hiệu ứng phóng to, mờ hiệu lực, hiệu quả bảng điều khiển, hiệu ứng nổ, mờ dần hiệu lực, hiệu ứng mờ dần máy tính để bàn, rơi ngoài có hiệu lực, hiệu quả lướt, làm nổi bật hiệu ứng cửa sổ, hiệu quả đăng nhập, đăng xuất hiệu lực, hiệu ứng đèn ma thuật, giảm thiểu hiệu ứng hoạt hình, hiệu ứng đánh dấu chuột, quy mô hiệu lực, hiệu ứng ảnh chụp màn hình, hiệu ứng tấm trượt có hiệu lực, hiệu quả quảng cáo trượt, hình thu nhỏ trên thanh tác vụ hiệu quả, thu nhỏ sang một bên có hiệu lực, mờ, mờ hiệu quả, minh bạch, hiệu quả vị trí cửa sổ, cửa sổ lung lay hiệu lực, khởi động hiệu quả thông tin phản hồi, hiệu ứng mẹ thoại, mờ hiệu quả hoạt động, hiệu ứng màn hình mờ, trượt lại hiệu quả, mắt kẹo, bánh kẹo, hiệu quả chương trình FPS, cho thấy hiệu quả sơn, hộp chuyển đổi có hiệu lực, hiệu ứng chuyển đổi bìa, hiệu ứng khối máy tính để bàn, máy tính để bàn hoạt hình khối lập phương hiệu lực, hiệu quả mạng lưới máy tính để bàn, hiệu ứng chuyển đổi flip, phác thảo có hiệu lực, hiện tại cửa sổ hiệu lực, hiệu ứng thay đổi kích thước cửa sổ
X-KDE-Keywords[x-test]=xxkwin,window,manager,compositing,effect,3D effects,2D effects,OpenGL,XRender,video settings,graphical effects,desktop effects,animations,various animations,window management effects,window switching effect,desktop switching effect,animations,animation speed,desktop animations,drivers,driver settings,rendering,render,invert effect,looking glass effect,magnifier effect,snap helper effect,track mouse effect,zoom effect,blur effect,dashboard effect,explosion effect,fade effect,fade desktop effect,fall apart effect,glide effect,highlight window effect,login effect,logout effect,magic lamp effect,minimize animation effect,mouse mark effect,scale in effect,screenshot effect,sheet effect,slide effect,sliding popups effect,taskbar thumbnails effect,thumbnail aside effect,translucency,translucency effect,transparency,window geometry effect,wobbly windows effect,startup feedback effect,dialog parent effect,dim inactive effect,dim screen effect,slide back effect,eye candy,candy,show FPS effect,show paint effect,box switch effect,cover switch effect,desktop cube effect,desktop cube animation effect,desktop grid effect,flip switch effect,outline effect,present windows effect,resize window effectxx
X-KDE-Keywords[zh_TW]=kwin,window,manager,compositing,effect,3D effects,2D effects,OpenGL,XRender,video settings,graphical effects,desktop effects,animations,various animations,window management effects,window switching effect,desktop switching effect,animations,animation speed,desktop animations,drivers,driver settings,rendering,render,invert effect,looking glass effect,magnifier effect,snap helper effect,track mouse effect,zoom effect,blur effect,dashboard effect,explosion effect,fade effect,fade desktop effect,fall apart effect,glide effect,highlight window effect,login effect,logout effect,magic lamp effect,minimize animation effect,mouse mark effect,scale in effect,screenshot effect,sheet effect,slide effect,sliding popups effect,taskbar thumbnails effect,thumbnail aside effect,translucency,translucency effect,transparency,window geometry effect,wobbly windows effect,startup feedback effect,dialog parent effect,dim inactive effect,dim screen effect,slide back effect,eye candy,candy,show FPS effect,show paint effect,box switch effect,cover switch effect,desktop cube effect,desktop cube animation effect,desktop grid effect,flip switch effect,outline effect,present windows effect,resize window effect

View File

@ -16,6 +16,7 @@ Name=Compositor
Name[ca]=Compositor
Name[ca@valencia]=Compositor
Name[cs]=Kompozitor
Name[da]=Compositor
Name[de]=Compositor
Name[en_GB]=Compositor
Name[es]=Compositor
@ -33,6 +34,7 @@ Name[pl]=Kompozytor
Name[pt]=Compositor
Name[pt_BR]=Compositor
Name[ro]=Compozitor
Name[ru]=Обеспечение эффектов
Name[sk]=Kompozítor
Name[sl]=Upravljalnik skladnje
Name[sr]=Слагач
@ -42,23 +44,30 @@ Name[sr@latin]=Slagač
Name[sv]=Sammansättning
Name[tr]=Birleştirici
Name[uk]=Засіб композиції
Name[vi]=Compositor
Name[x-test]=xxCompositorxx
Name[zh_CN]=混成器
Name[zh_TW]=組合器
Comment=Compositor Settings for Desktop Effects
Comment[ca]=Arranjament del compositor pels efectes d'escriptori
Comment[cs]=Nastavení kompozitoru pro efekty pracovní plochy
Comment[da]=Compositor-indstillinger til skrivebordseffekter
Comment[de]=Compositor-Einstellungen für Arbeitsflächen-Effekte
Comment[en_GB]=Compositor Settings for Desktop Effects
Comment[es]=Configurar las preferencias del compositor para los efectos del escritorio
Comment[fi]=Koostimen asetukset työpöytätehosteita varten
Comment[fr]=Paramétrage du compositeur pour les effets du bureau
Comment[hu]=A kompozitor beállításai az asztali effektusokhoz
Comment[ia]=Preferentias de compositor pro le effectos de scriptorio
Comment[id]=Pengaturan Kompositor untuk Efek Jendela
Comment[ko]=데스크톱 효과에 사용되는 컴포지터 설정
Comment[nb]=Sammensetter-innstillinger for skrivebordseffekter
Comment[nds]=Tosamensettoptschonen för de Schriefdischeffekten instellen
Comment[nl]=Instellingen van compositor configureren voor bureaubladeffecten
Comment[pl]=Ustawienia kompozytora dla efektów pulpitu
Comment[pt]=Configuração do Compositor para os Efeitos do Ecrã
Comment[pt_BR]=Definições do Compositor para os efeitos da área de trabalho
Comment[ru]=Настройка движка эффектов рабочего стола
Comment[sk]=Nastavenia kompozítora pre efekty plochy
Comment[sl]=Nastavitve upravljalnika skladnje za učinke namizja
Comment[sr]=Поставке слагача за ефекте површи
@ -67,11 +76,15 @@ Comment[sr@ijekavianlatin]=Postavke slagača za efekte površi
Comment[sr@latin]=Postavke slagača za efekte površi
Comment[sv]=Sammansättningsinställningar för skrivbordseffekter
Comment[uk]=Параметри засобу композиції для ефектів стільниці
Comment[vi]=Thiết lập Compositor cho hiệu ứng màn hình
Comment[x-test]=xxCompositor Settings for Desktop Effectsxx
Comment[zh_CN]=桌面特效混成器设置
Comment[zh_TW]=桌面效果使用的組合器設定
X-KDE-Keywords=kwin,window,manager,compositing,effect,3D effects,2D effects,OpenGL,XRender,video settings,graphical effects,desktop effects
X-KDE-Keywords[ca]=kwin,finestra,gestor,composició,efecte,efectes 3D,efectes 2D,OpenGL,XRender,arranjament de vídeo,efectes gràfics,efectes d'escriptori
X-KDE-Keywords[ca@valencia]=kwin,finestra,gestor,composició,efecte,efectes 3D,efectes 2D,OpenGL,XRender,arranjament de vídeo,efectes gràfics,efectes d'escriptori
X-KDE-Keywords[da]=kwin,vindue,håndtering,window,manager,compositing,effekt,3D effekter,2D effekter,OpenGL,XRender,video-indstillinger,grafiske effekter,skrivebordseffekter,desktop effects
X-KDE-Keywords[de]=kwin,Fenstermanager,Fensterverwaltung,Effekt,Fenster,Compositing,3D-Effekte,2D-Effekte,OpenGL,XRender,Video-Einstellungen,Grafikeffekte,Arbeitsflächeneffekte
X-KDE-Keywords[en_GB]=kwin,window,manager,compositing,effect,3D effects,2D effects,OpenGL,XRender,video settings,graphical effects,desktop effects
X-KDE-Keywords[es]=kwin,ventana,gestor,composición,efecto,efectos 3D,efectos 2D,OpenGL,XRender,preferencias de vídeo,efectos gráficos,efectos del escritorio
@ -87,6 +100,7 @@ X-KDE-Keywords[nl]=kwin,window,manager,beheerder,compositing,effecten,3D-effecte
X-KDE-Keywords[pl]=kwin,okno,menadżer,menedżer,zarządca,kompozytor,efekt,efekt 3D,efekt 2D,OpenGL,XRender,ustawienia wideo,efekty graficzne,efekty pulpitu
X-KDE-Keywords[pt]=kwin,janela,gestor,composição,efeito,efeitos 3D,efeitos 2D,OpenGL,XRender,configuração do vídeo,efeitos gráficos,efeitos do ecrã
X-KDE-Keywords[pt_BR]=kwin,janela,gerenciador,composição,efeito,efeitos 3D,efeitos 2D,OpenGL,XRender,configurações de vídeo,efeitos gráficos,efeitos da área de trabalho
X-KDE-Keywords[ru]=kwin,window,manager,compositing,effect,3D effects,2D effects,OpenGL,XRender,video settings,graphical effects,desktop effects,композитинг,композитный диспетчер окон,эффекты рабочего стола,графические эффекты,рендеринг,параметры видео,настройка видео
X-KDE-Keywords[sk]=kwin,okno,správca,kompozícia,efekt,3D efekty,2D efekty,OpenGL,XRender,nastavenia videa,grafické efekty,efekty plochy
X-KDE-Keywords[sl]=kwin,okna,upravljalnik,skladnja,učinek,3D učinki,2D učinki,OpenGL,XRender,nastavitve videa,video,grafični učinki,učinki namizja
X-KDE-Keywords[sr]=kwin,window,manager,compositing,effect,3D effects,2D effects,OpenGL,XRender,video settings,graphical effects,desktop effects,К‑вин,прозор,менаџер,слагање,ефекти,3Д ефекти,2Д ефекти,опенГЛ,Икс‑рендер,видео поставке,графички ефекти,ефекти површи

View File

@ -76,18 +76,23 @@ Name[zh_TW]=視窗裝飾
Comment=Look and Feel of Window Titles
Comment[ca]=Aspecte i comportament dels títols de les finestres
Comment[cs]=Vzhled a dekorace titulků oken
Comment[da]=Udseendet af vinduestitler
Comment[de]=Erscheinungsbild von Fenstertiteln
Comment[en_GB]=Look and Feel of Window Titles
Comment[es]=Aspecto visual de los títulos de las ventanas
Comment[fi]=Ikkunoiden kehysten ulkoasu
Comment[fr]=Apparence des titres de fenêtre
Comment[hu]=Az ablakok címsorának megjelenése
Comment[ia]=Semblantia de titulos de fenestra
Comment[id]=Tampilan dan Rasa dari Judul Jendela
Comment[ko]=창 제목 표시줄의 모습과 느낌 설정
Comment[nb]=Utseende og virkemåte for vindustitlene
Comment[nds]=Dat Utsehn vun de Finstertiteln instellen
Comment[nl]=Uiterlijk en gedrag van venstertitels
Comment[pl]=Wygląd i odczucia tytułów okien
Comment[pt]=Aparência e Comportamento dos Títulos das Janelas
Comment[pt_BR]=Aparência dos títulos das janelas
Comment[pt_BR]=Aparência do título das janelas
Comment[ru]=Настройка внешнего вида заголовков окон
Comment[sk]=Nastavenie vzhľadu titulkov okien
Comment[sl]=Videz in občutek naslovnih vrstic okna
Comment[sr]=Изглед и осећај за наслове прозора
@ -97,6 +102,8 @@ Comment[sr@latin]=Izgled i osećaj za naslove prozora
Comment[sv]=Namnlisternas utseende och känsla
Comment[uk]=Вигляд і поведінка смужок заголовків вікон
Comment[x-test]=xxLook and Feel of Window Titlesxx
Comment[zh_CN]=窗口标题的观感
Comment[zh_TW]=視窗標題列的外觀與感覺
X-KDE-Keywords=kwin,window,manager,border,style,theme,look,feel,layout,button,handle,edge,kwm,decoration
X-KDE-Keywords[bs]=kwin,prozor,upravitelj,granica,stil,tema,izgled,osjećati,izgled,dugme,držati,ivica,kwm,dekoracija

View File

@ -36,7 +36,7 @@
// close.xbm:
#define close_width 12
#define close_height 12
static unsigned char close_bits[] = {
static const unsigned char close_bits[] = {
0x00, 0x00, 0x06, 0x06, 0x0e, 0x07, 0x9c, 0x03, 0xf8, 0x01, 0xf0, 0x00,
0xf0, 0x00, 0xf8, 0x01, 0x9c, 0x03, 0x0e, 0x07, 0x06, 0x06, 0x00, 0x00
};
@ -44,7 +44,7 @@ static unsigned char close_bits[] = {
// help.xbm:
#define help_width 12
#define help_height 12
static unsigned char help_bits[] = {
static const unsigned char help_bits[] = {
0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0xfc, 0x01, 0x8c, 0x01, 0xc0, 0x01,
0xe0, 0x00, 0x60, 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00
};
@ -52,7 +52,7 @@ static unsigned char help_bits[] = {
// keepaboveothers.xbm:
#define keepaboveothers_width 12
#define keepaboveothers_height 12
static unsigned char keepaboveothers_bits[] = {
static const unsigned char keepaboveothers_bits[] = {
0x00, 0x00, 0x60, 0x00, 0xf0, 0x00, 0xf8, 0x01, 0x60, 0x00, 0xfe, 0x07,
0xfe, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
@ -60,7 +60,7 @@ static unsigned char keepaboveothers_bits[] = {
// keepbelowothers.xbm:
#define keepbelowothers_width 12
#define keepbelowothers_height 12
static unsigned char keepbelowothers_bits[] = {
static const unsigned char keepbelowothers_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x07,
0xfe, 0x07, 0x60, 0x00, 0xf8, 0x01, 0xf0, 0x00, 0x60, 0x00, 0x00, 0x00
};
@ -68,7 +68,7 @@ static unsigned char keepbelowothers_bits[] = {
// maximize.xbm:
#define maximize_width 12
#define maximize_height 12
static unsigned char maximize_bits[] = {
static const unsigned char maximize_bits[] = {
0x00, 0x00, 0xfe, 0x07, 0xfe, 0x07, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04,
0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0xfe, 0x07, 0x00, 0x00
};
@ -76,7 +76,7 @@ static unsigned char maximize_bits[] = {
// menu.xbm:
#define menu_width 12
#define menu_height 12
static unsigned char menu_bits[] = {
static const unsigned char menu_bits[] = {
0x00, 0x00, 0xfc, 0x03, 0xf4, 0x02, 0x04, 0x02, 0xf4, 0x02, 0x04, 0x02,
0xf4, 0x02, 0x04, 0x02, 0xf4, 0x02, 0x04, 0x02, 0xfc, 0x03, 0x00, 0x00
};
@ -84,7 +84,7 @@ static unsigned char menu_bits[] = {
// minimize.xbm:
#define minimize_width 12
#define minimize_height 12
static unsigned char minimize_bits[] = {
static const unsigned char minimize_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x07, 0xfe, 0x07, 0x00, 0x00
};
@ -92,7 +92,7 @@ static unsigned char minimize_bits[] = {
// onalldesktops.xbm:
#define onalldesktops_width 12
#define onalldesktops_height 12
static unsigned char onalldesktops_bits[] = {
static const unsigned char onalldesktops_bits[] = {
0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0xfe, 0x07,
0xfe, 0x07, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00
};
@ -100,7 +100,7 @@ static unsigned char onalldesktops_bits[] = {
// resize.xbm:
#define resize_width 12
#define resize_height 12
static unsigned char resize_bits[] = {
static const unsigned char resize_bits[] = {
0x00, 0x00, 0xfe, 0x07, 0x42, 0x04, 0x42, 0x04, 0x42, 0x04, 0x42, 0x04,
0x7e, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0xfe, 0x07, 0x00, 0x00
};
@ -108,7 +108,7 @@ static unsigned char resize_bits[] = {
// shade.xbm:
#define shade_width 12
#define shade_height 12
static unsigned char shade_bits[] = {
static const unsigned char shade_bits[] = {
0x00, 0x00, 0xfe, 0x07, 0xfe, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
@ -116,7 +116,7 @@ static unsigned char shade_bits[] = {
// spacer.xbm:
#define spacer_width 12
#define spacer_height 12
static unsigned char spacer_bits[] = {
static const unsigned char spacer_bits[] = {
0x00, 0x00, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x54, 0x03,
0xac, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x00, 0x00
};

View File

@ -77,16 +77,23 @@ Name[zh_TW]=虛擬桌面
Comment=Navigation, Number and Layout of Virtual Desktops
Comment[ca]=Navegació, nombre i disposició dels escriptoris virtuals
Comment[cs]=Navigace, počet a rozvržení virtuálních ploch
Comment[da]=Navigation, antal og layout af virtuelle skriveborde
Comment[de]=Navigation, Anzahl und Layout virtueller Arbeitsflächen
Comment[en_GB]=Navigation, Number and Layout of Virtual Desktops
Comment[es]=Navegación, número y disposición de los escritorios virtuales
Comment[fi]=Virtuaalityöpöytien vaihtaminen, määrä ja asettelu
Comment[fr]=Navigation, nombre et disposition des bureaux virtuels
Comment[hu]=Navigáció, a virtuális asztalok száma és elrendezése
Comment[id]=Navigasi, Jumlah dan Tata Letak Desktop Virtual
Comment[ko]=가상 데스크톱 탐색, 개수, 레이아웃
Comment[nb]=Navigering, antall og utlegg av virtuelle skrivebord
Comment[nds]=Tall, Anornen un dat Anstüern vun de virtuellen Schriefdischen fastleggen
Comment[nl]=Navigatie door, aantal en indeling van virtuele bureaubladen
Comment[pl]=Poruszanie się, liczba i układ wyobrażalnych pulpitów
Comment[pt]=Navegação, Número e Disposição dos Ecrãs Virtuais
Comment[pt_BR]=Navegação, quantidade e leiaute das áreas de trabalho virtuais
Comment[ru]=Число, расположение и способ переключения рабочих столов
Comment[sk]=Navigácia, počet a rozloženie virtuálnych plôch
Comment[sl]=Krmarjenje med, število in razporeditev navideznih namizij
Comment[sr]=Кретање, број и распоред виртуелних површи
@ -95,7 +102,10 @@ Comment[sr@ijekavianlatin]=Kretanje, broj i raspored virtuelnih površi
Comment[sr@latin]=Kretanje, broj i raspored virtuelnih površi
Comment[sv]=Navigering, antal och layout av virtuella skrivbord
Comment[uk]=Навігація, кількість та компонування віртуальних стільниць
Comment[vi]=Số lượng, bố trí và điều hướng của màn hình ảo
Comment[x-test]=xxNavigation, Number and Layout of Virtual Desktopsxx
Comment[zh_CN]=虚拟桌面的切换,数量和布局
Comment[zh_TW]=虛擬桌面的導覽、數字與佈局
X-KDE-Keywords=desktop,desktops,number,virtual desktop,multiple desktops,pager,pager widget,pager applet,pager settings
X-KDE-Keywords[bs]=pozadina,pozadine,broj,virtuelna pozadina,višestruka pozadina,pejdžer,dodatak pejdžeru,aplet pejdžer,pejdžer postavke
X-KDE-Keywords[ca]=escriptori,escriptoris,nombre,escriptori virtual,escriptoris múltiples,paginador,estri paginador,miniaplicació de paginació,arranjament de paginador

View File

@ -431,7 +431,7 @@ QString KWinDesktopConfig::extrapolatedShortcut(int desktop) const
}
QString before;
if (!shortcuts.isEmpty()) {
before = shortcuts.first().toString(QKeySequence::NativeText);
before = shortcuts.first().toString(QKeySequence::PortableText);
}
QString seq;
@ -494,8 +494,8 @@ void KWinDesktopConfig::slotChangeShortcuts(int number)
m_ui->messageLabel->show();
} else {
QKeySequence shortcut(shortcutString);
if (!shortcut.isEmpty() || KGlobalAccel::self()->isGlobalShortcutAvailable(shortcut)) {
KGlobalAccel::self()->setShortcut(action, QList<QKeySequence>(), KGlobalAccel::NoAutoloading);
if (!shortcut.isEmpty() && KGlobalAccel::self()->isGlobalShortcutAvailable(shortcut)) {
KGlobalAccel::self()->setShortcut(action, QList<QKeySequence>() << shortcut, KGlobalAccel::NoAutoloading);
m_ui->messageLabel->setText(i18n("Assigned global Shortcut \"%1\" to Desktop %2", shortcutString, desktop));
m_ui->messageLabel->show();
} else {

View File

@ -68,6 +68,7 @@ Name[nds]=Akschonen
Name[ne]=कार्य
Name[nl]=Acties
Name[nn]=Handlingar
Name[oc]=Accions
Name[pa]=ਕਾਰਵਾਈਆਂ
Name[pl]=Działania
Name[pt]=Acções
@ -102,18 +103,23 @@ Name[zh_TW]=動作
Comment=Mouse Actions on Windows
Comment[ca]=Accions del ratolí en les finestres
Comment[cs]=Činnosti myši na oknech
Comment[da]=Musehandlinger på vinduer
Comment[de]=Maus-Aktionen für Fenster
Comment[en_GB]=Mouse Actions on Windows
Comment[es]=Acciones del ratón sobre las ventanas
Comment[fi]=Ikkunoiden hiiritoiminnot
Comment[fr]=Actions de souris sur les fenêtres
Comment[hu]=Egérműveletek az ablakokon
Comment[ia]=Actiones de mus sur fenestras
Comment[id]=Aksi Tetikus di Jendela
Comment[ko]=창 마우스 동작 설정
Comment[nb]=Musehandlinger på vinduer
Comment[nds]=Muusakschonen för Finstern fastleggen
Comment[nl]=Muisacties op vensters
Comment[pl]=Działania myszy na oknach
Comment[pt]=Acções do Rato nas Janelas
Comment[pt_BR]=Ações do mouse nas janelas
Comment[ru]=Настройка действий мыши для окон
Comment[sk]=Akcie myši na oknách
Comment[sl]=Dejanja miške na oknih
Comment[sr]=Радње мишем над прозорима
@ -123,6 +129,8 @@ Comment[sr@latin]=Radnje mišem nad prozorima
Comment[sv]=Musåtgärder för fönster
Comment[uk]=Дії над вікнами за допомогою миші
Comment[x-test]=xxMouse Actions on Windowsxx
Comment[zh_CN]=窗口的鼠标动作
Comment[zh_TW]=視窗上的滑鼠動作
X-KDE-Keywords=shade,maximise,maximize,minimize,minimise,lower,operations menu,titlebar,resize
X-KDE-Keywords[bs]=sjena,povećali,povećala,smanjiti,umanjiti,sniziti,izbornik operacija,naslovnica,promjena veličine

View File

@ -67,6 +67,7 @@ Name[nds]=Verwiedert
Name[ne]=उन्नत
Name[nl]=Geavanceerd
Name[nn]=Avansert
Name[oc]=A_vançat
Name[pa]=ਤਕਨੀਕੀ
Name[pl]=Zaawansowane
Name[pt]=Avançado
@ -101,18 +102,23 @@ Name[zh_TW]=進階
Comment=Advanced Window Management Features
Comment[ca]=Característiques avançades de la gestió de finestres
Comment[cs]=Pokročilé vlastností správy oken
Comment[da]=Avancerede vindueshåndteringsegenskaber
Comment[de]=Erweiterte Fensterverwaltung
Comment[en_GB]=Advanced Window Management Features
Comment[es]=Funciones avanzadas del gestor de ventanas
Comment[fi]=Ikkunoinnin lisäominaisuudet
Comment[fr]=Fonctionnalités de gestion avancée des fenêtres
Comment[hu]=Speciális ablakkezelési szolgáltatások
Comment[ia]=Characteristicas avantiate de gestion de fenestra
Comment[id]=Fitur Manajemen Jendela Lanjutan
Comment[ko]=고급 창 관리자 기능 설정
Comment[nb]=Funksjoner for avansert vindusbehandling
Comment[nds]=Verwiedert Finsterinstellen
Comment[nl]=Geavanceerde vensterbeheermogelijkheden
Comment[pl]=Możliwości zaawansowanego zarządzania oknami
Comment[pt]=Funcionalidades de Gestão de Janelas Avançadas
Comment[pt_BR]=Recursos avançados de gerenciamento de janelas
Comment[ru]=Настройка дополнительных возможностей управления окнами
Comment[sk]=Pokročilé možnosti správy okien
Comment[sl]=Napredne zmožnosti upravljanja oken
Comment[sr]=Напредне могућности управљања прозорима
@ -122,6 +128,8 @@ Comment[sr@latin]=Napredne mogućnosti upravljanja prozorima
Comment[sv]=Avancerade fönsterhanteringsfunktioner
Comment[uk]=Додаткові можливості з керування вікнами
Comment[x-test]=xxAdvanced Window Management Featuresxx
Comment[zh_CN]=高级窗口管理特性
Comment[zh_TW]=進階視窗管理功能
X-KDE-Keywords=shading,border,hover,active borders,tiling,tabs,tabbing,window tabbing,window grouping,window tiling,window placement,placement of windows,window advanced behavior
X-KDE-Keywords[bs]=sjenčanje, granične, lebdjenje, aktivne granice, popločavanje, Kartice, tabovanje, prozorno tabovanje, grupiranje prozora, pločica, prozorna pločica, plasman przora, plasman prozorâ, napredo ponašanje prozora

View File

@ -99,17 +99,23 @@ Name[zh_TW]=焦點
Comment=Active Window Policy
Comment[ca]=Política de finestra activa
Comment[cs]=Chování aktivního okna
Comment[da]=Politik for aktivt vindue
Comment[de]=Richtlinie für aktives Fenster
Comment[en_GB]=Active Window Policy
Comment[es]=Política de la ventana activa
Comment[fi]=Aktiivisen ikkunan valintatapa
Comment[fr]=Politique pour les fenêtres actives
Comment[hu]=Aktív ablakok szabályai
Comment[id]=Kebijakan Jendela Aktif
Comment[ko]=활성 창 정책
Comment[nb]=ActiveWindow-styring
Comment[nds]=Regel för't aktive Finster
Comment[nl]=Beleid voor actief venster
Comment[pl]=Zasady aktywowania okna
Comment[pt]=Política da Janela Activa
Comment[pt_BR]=Política da janela ativa
Comment[ru]=Правила смены активного окна
Comment[sk]=Politika aktívneho okna
Comment[sl]=Pravilnik dejavnih oken
Comment[sr]=Смерница активирања прозора
@ -119,6 +125,8 @@ Comment[sr@latin]=Smernica aktiviranja prozora
Comment[sv]=Aktiv fönsterprincip
Comment[uk]=Правила для задіяння вікон
Comment[x-test]=xxActive Window Policyxx
Comment[zh_CN]=活动窗口策略
Comment[zh_TW]=作用中視窗政策
X-KDE-Keywords=focus,placement,auto raise,raise,click raise,keyboard,CDE,alt-tab,all desktop,focus follows mouse,focus prevention,focus stealing,focus policy,window focus behavior,window screen behavior
X-KDE-Keywords[bs]=fokus, smještaj, automatski rast, rast, kliknite na rast, tastatura, CDE, Alt-Tab, cijeli desktop, fokus slijedi miša, fokus prevenciju, usredotoči krade, fokus politike, fokus prozora ponašanje, prozor zaslon ponašanje

View File

@ -66,6 +66,7 @@ Name[nds]=Verschuven
Name[ne]=सार्दा
Name[nl]=Verplaatsing
Name[nn]=Flytting
Name[oc]=Desplaçament
Name[pa]=ਏਧਰ-ਓਧਰ
Name[pl]=Przesuwanie
Name[pt]=Mover
@ -100,18 +101,23 @@ Name[zh_TW]=移動
Comment=Window Moving
Comment[ca]=Moviment de les finestres
Comment[cs]=Posun oken
Comment[da]=Flytning af vinduer
Comment[de]=Fensterbewegung
Comment[en_GB]=Window Moving
Comment[es]=Movimiento de ventanas
Comment[fi]=Ikkunoiden siirtäminen
Comment[fr]=Déplacement des fenêtres
Comment[hu]=Ablakmozgatás
Comment[ia]=Movimento de fenestra
Comment[id]=Memindahkan Jendela
Comment[ko]=창 이동
Comment[nb]=Vindusflytting
Comment[nds]=Finstern bewegen
Comment[nl]=Verplaatsen van vensters
Comment[pl]=Przesuwanie okien
Comment[pt]=Movimentação das Janelas
Comment[pt_BR]=Movimentação da janela
Comment[ru]=Перемещение окон
Comment[sk]=Presuny okien
Comment[sl]=Premikanje oken
Comment[sr]=Померање прозора
@ -120,7 +126,10 @@ Comment[sr@ijekavianlatin]=Pomeranje prozora
Comment[sr@latin]=Pomeranje prozora
Comment[sv]=Fönsterförflyttning
Comment[uk]=Пересування вікон
Comment[vi]=Di chuyển cửa sổ
Comment[x-test]=xxWindow Movingxx
Comment[zh_CN]=窗口移动
Comment[zh_TW]=視窗移動
X-KDE-Keywords=moving,smart,cascade,maximize,maximise,snap zone,snap,border
X-KDE-Keywords[bs]=pomjeranje,pametno,kaskada,povećali,povećalo,namjestiti zonu,namjestiti,granica

View File

@ -104,18 +104,23 @@ Name[zh_TW]=視窗行為
Comment=Window Actions and Behavior
Comment[ca]=Accions i comportament de les finestres
Comment[cs]=Činnosti a chování oken
Comment[da]=Vindueshandlinger og -opførsel
Comment[de]=Fenster-Aktionen und -verhalten
Comment[en_GB]=Window Actions and Behavior
Comment[es]=Acciones y comportamiento de las ventanas
Comment[fi]=Ikkunoiden toiminnot ja toiminta
Comment[fr]=Actions et comportement des fenêtres
Comment[hu]=Ablakműveletek és működés
Comment[ia]=Comportamento e actiones de fenestra
Comment[id]=Aksi dan Perilaku Jendela
Comment[ko]=창 동작과 행동
Comment[nb]=Vindusoppførsel og handlinger
Comment[nds]=Finsterakschonen und -bedregen
Comment[nl]=Vensteracties en gedrag
Comment[pl]=Działania i zachowania okien
Comment[pt]=Acções e Comportamento das Janelas
Comment[pt_BR]=Ações e comportamento das janelas
Comment[ru]=Настройка поведения окон
Comment[sk]=Akcie a správanie okien
Comment[sl]=Dejanja in obnašanje oken
Comment[sr]=Понашање прозора и радње над њима
@ -125,21 +130,28 @@ Comment[sr@latin]=Ponašanje prozora i radnje nad njima
Comment[sv]=Fönsteråtgärder och beteende
Comment[uk]=Реакція і поведінка вікон
Comment[x-test]=xxWindow Actions and Behaviorxx
Comment[zh_CN]=窗口行为
Comment[zh_TW]=視窗動作與行為
X-KDE-Keywords=focus,placement,window behavior,window actions,animation,raise,auto raise,windows,frame,titlebar,doubleclick
X-KDE-Keywords[ca]=focus,emplaçament,comportament de finestra,accions de la finestra,animació,elevació,elevació automàtica,finestres,marc,barra de títol,clic doble
X-KDE-Keywords[da]=fokus,placering,vinduesopførsel,vindueshandlinger,animation,hæv,autohæv,vinduesramme,titelbjælke,dobbeltklik
X-KDE-Keywords[de]=Aktivierung,Platzierung,Fensterverhalten,Fensteraktionen,Animation,Nach vorn/hinten, Fenster,Rahmen,Umrandung,Titelleiste,Doppelklick
X-KDE-Keywords[en_GB]=focus,placement,window behaviour,window actions,animation,raise,auto raise,windows,frame,titlebar,doubleclick
X-KDE-Keywords[es]=foco,posicionamiento,comportamiento de las ventanas,acciones de las ventanas,animación,elevación,autoelevación,ventanas,marco,barra de título,doble clic
X-KDE-Keywords[fi]=kohdistus,sijoittelu,sijoitus,ikkunoiden toiminta,ikkunoiden toiminnot,animaatio,nosta,automaattinen nosto,ikkunat,kehys,otsikkopalkki,kaksoisnapsautus,tuplanapsautus,kaksoisklikkaus,tuplaklikkaus
X-KDE-Keywords[fr]=focus, placement, comportement de la fenêtre, actions sur les fenêtres, animation, agrandissement, agrandissement automatique, fenêtres, cadre, barre de titre, double clic
X-KDE-Keywords[hu]=fókusz,elhelyezés,ablakműködés,ablakműveletek,animáció,felemelés,automatikus felemelés,ablakok,keret,címsor,dupla kattintás
X-KDE-Keywords[ia]=focus,placiamento,comportamento de fenestra,actiones de fenestra,animation,altiar,auto altiar,fenestras,quadro,barra de titulo,duple click
X-KDE-Keywords[id]=fokus,penempatan,perilaku jendela,aksi jendela,animasi,naikkan,naikkan otomatis,jendela,bingkai,batang judul,klik ganda
X-KDE-Keywords[ko]=focus,placement,window behavior,animation,raise,auto raise,windows,frame,titlebar,doubleclick,초점,위치,창 행동,애니메이션,올리기,창,프레임,제목 표시줄
X-KDE-Keywords[nb]=fokus,plassering,vindusoppførsel,vindushandlinger,animering,hev,autohev,vinduer,ramme,tittellinje,dobbeltklikk
X-KDE-Keywords[nds]=Fokus,Platzeren,Finsterbedregen,Finsterakschonen,Animeren,na vörn,automaatsch,Finstern,Rahmen,Titelbalken,Dubbelklick
X-KDE-Keywords[nl]=focus,plaatsing,venstegedrag,vensteracties,animatie,omhoog,automatisch omhoog,vensters,frame,titelbalk,dubbelklik
X-KDE-Keywords[pl]=uaktywnienie,umieszczenie,zachowanie okna,działania okien,animacja,wzniesienie,auto-wzniesienie, okna,ramka,pasek tytułu,podwójne kliknięcie
X-KDE-Keywords[pt]=foco,colocação,comportamento da janela,acções das janelas,animação,elevar,elevar automaticamente,janelas,contorno,barra de título,duplo-click
X-KDE-Keywords[pt_BR]=foco,colocação,comportamento da janela,ações da janela,animação,elevar,elevar automaticamente,janelas,contorno,barra de título,clique duplo
X-KDE-Keywords[ru]=focus,placement,window behavior,window actions,animation,raise,auto raise,windows,frame,titlebar,doubleclick,фокус,местоположение,поведение окон,анимация,увеличение,автоувеличение,окна,рамка,заголовок,двойной щелчок,действия над окнами
X-KDE-Keywords[sk]=zameranie,umiestnenie,správanie okien,animácia,zdvihnúť,automaticky zdvihnúť,okná,rám,titulkový pruh,dvojklik
X-KDE-Keywords[sl]=fokus,žarišče,postavitev,postavljanje,obnašanje oken,dejanja oken,animacija,dvig,samodejni dvig,okna,okvir,naslovna vrstica,dvojni klik,dvoklik
X-KDE-Keywords[sr]=focus,placement,window behavior,window actions,animation,raise,auto raise,windows,frame,titlebar,doubleclick,фокус,постављење,понашање прозора,радње над прозорима,анимација,подигни,аутоматско подизање,прозор,оквир,насловна трака,двоклик
@ -149,6 +161,8 @@ X-KDE-Keywords[sr@latin]=focus,placement,window behavior,window actions,animatio
X-KDE-Keywords[sv]=fokus,placering,fönsterbeteende,animering,höj,höj automatiskt,fönster,ram,namnlist,dubbelklick
X-KDE-Keywords[uk]=focus,placement,window behavior,window actions,animation,raise,auto raise,windows,frame,titlebar,doubleclick,фокус,розташування,місце,вікно,поведінка,поведінка вікон,дії,реакція,дії з вікнами,реакція вікон,анімація,підняти,підняття,автоматична,автоматично,рамка,заголовок,смужка заголовка,клацання,подвійне
X-KDE-Keywords[x-test]=xxfocus,placement,window behavior,window actions,animation,raise,auto raise,windows,frame,titlebar,doubleclickxx
X-KDE-Keywords[zh_CN]=focus,placement,window behavior,window actions,animation,raise,auto raise,windows,frame,titlebar,doubleclick,焦点,位置,窗口行为,窗口动作,动画,升起,自动升起,窗口,边框,标题栏,双击
X-KDE-Keywords[zh_TW]=focus,placement,window behavior,window actions,animation,raise,auto raise,windows,frame,titlebar,doubleclick
Categories=Qt;KDE;X-KDE-settings-looknfeel;

View File

@ -277,7 +277,7 @@ const char* const tbl_All[] = {
""
};
const char* tbl_TiWAc[] = {
const char* const tbl_TiWAc[] = {
"Raise/Lower",
"Shade/Unshade",
"Maximize/Restore",
@ -289,7 +289,7 @@ const char* tbl_TiWAc[] = {
""
};
const char* tbl_AllW[] = {
const char* const tbl_AllW[] = {
"Raise/Lower",
"Shade/Unshade",
"Maximize/Restore",

View File

@ -14,7 +14,7 @@
<widget class="QLabel" name="textLabel2" >
<property name="text" >
<string>A single shortcut can be easily assigned or cleared using the two buttons. Only shortcuts with modifiers can be used.&lt;p>
It is possible to have several possible shortcuts, and the first available shortcut will be used. The shortcuts are specified using shortcut sets separated by &quot; - &quot;. One set is specified as &lt;i>base&lt;/i>+(&lt;i>list&lt;/i>), where base are modifiers and list is a list of keys.&lt;br>
It is possible to have several possible shortcuts, and the first available shortcut will be used. The shortcuts are specified using shortcut sets separated by " - ". One set is specified as &lt;i>base&lt;/i>+(&lt;i>list&lt;/i>), where base are modifiers and list is a list of keys.&lt;br>
For example "&lt;b>Shift+Alt+(123) Shift+Ctrl+(ABC)&lt;/b>" will first try &lt;b>Shift+Alt+1&lt;/b>, then others with &lt;b>Shift+Ctrl+C&lt;/b> as the last one.</string>
</property>
<property name="textFormat" >

View File

@ -77,18 +77,23 @@ Name[zh_TW]=視窗規則
Comment=Individual Window Behavior
Comment[ca]=Comportament individual de les finestres
Comment[cs]=Chování individuálních oken
Comment[da]=Opførsel af enkeltvinduer
Comment[de]=Individuelles Fensterverhalten
Comment[en_GB]=Individual Window Behavior
Comment[es]=Comportamiento de las ventanas individuales
Comment[fi]=Yksittäisten ikkunoiden toiminta
Comment[fr]=Comportement individuel des fenêtres
Comment[hu]=Egyéni ablakműveletek
Comment[ia]=Comportamento de fenestra individual
Comment[id]=Perilaku Jendela Individu
Comment[ko]=개별 창 동작
Comment[nb]=Oppførsel for individuelle vinduer
Comment[nds]=Bedregen vun enkelte Finstern
Comment[nl]=Individueel venstergedrag
Comment[pl]=Osobne zachowania okien
Comment[pt]=Comportamento das Janelas Individuais
Comment[pt_BR]=Comportamento das janelas individuais
Comment[ru]=Особые параметры конкретных окон
Comment[sk]=Individuálne správanie okien
Comment[sl]=Obnašanje posameznih oken
Comment[sr]=Понашање појединачних прозора
@ -98,6 +103,8 @@ Comment[sr@latin]=Ponašanje pojedinačnih prozora
Comment[sv]=Individuellt fönsterbeteende
Comment[uk]=Поведінка окремих вікон
Comment[x-test]=xxIndividual Window Behaviorxx
Comment[zh_CN]=个别窗口行为
Comment[zh_TW]=個別視窗行為
X-KDE-Keywords=size,position,state,window behavior,windows,specific,workarounds,remember,rules
X-KDE-Keywords[bs]=veličina,pozicija,grad,reagiranje prozora,prozori,specifičan,workarounds,sjećati se,pravila

View File

@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>584</width>
<width>592</width>
<height>588</height>
</rect>
</property>
@ -2467,7 +2467,7 @@ but this may sometimes fail or superact.
</property>
</widget>
</item>
<item row="1" column="3">
<item row="1" column="2" colspan="3">
<widget class="QComboBox" name="rule_decocolor">
<property name="enabled">
<bool>false</bool>
@ -2496,16 +2496,16 @@ but this may sometimes fail or superact.
</layout>
</widget>
<customwidgets>
<customwidget>
<class>KLineEdit</class>
<extends>QLineEdit</extends>
<header>klineedit.h</header>
</customwidget>
<customwidget>
<class>KComboBox</class>
<extends>QComboBox</extends>
<header>kcombobox.h</header>
</customwidget>
<customwidget>
<class>KLineEdit</class>
<extends>QLineEdit</extends>
<header>klineedit.h</header>
</customwidget>
<customwidget>
<class>YesNoBox</class>
<extends>QWidget</extends>

View File

@ -83,17 +83,23 @@ Name[zh_TW]=螢幕邊緣
Comment=Active Screen Corners and Edges
Comment[ca]=Cantonades i vores de la pantalla activa
Comment[cs]=Aktivní rohy a hrany obrazovky
Comment[da]=Aktive skærmhjørner og -kanter
Comment[de]=Aktive Bildschirmränder
Comment[en_GB]=Active Screen Corners and Edges
Comment[es]=Esquinas y bordes de la pantalla activa
Comment[fi]=Näytön kulmien ja reunojen toiminnot
Comment[fr]=Bords et coins actifs de l'écran
Comment[hu]=Aktív képernyősarkok és szélek
Comment[id]=Sudut dan Tepi Layar Aktif
Comment[ko]=활성 화면 경계와 꼭지점
Comment[nb]=Aktive skjemkanter og hjørner
Comment[nds]=Aktive Schirmkanten un -hörns
Comment[nl]=Hoeken en randen van het actieve scherm
Comment[pl]=Narożniki i krawędzie aktywnego ekranu
Comment[pt]=Cantos e Extremos do Ecrã Activo
Comment[pt_BR]=Cantos e bordas da tela ativa
Comment[ru]=Настройка действий для краёв экрана
Comment[sk]=Rohy a okraje aktívneho okna
Comment[sl]=Dejavni robovi in koti zaslona
Comment[sr]=Активни углови и ивице екрана
@ -103,21 +109,28 @@ Comment[sr@latin]=Aktivni uglovi i ivice ekrana
Comment[sv]=Aktiva skärmhörn och kanter
Comment[uk]=Активні кути та краї екрана
Comment[x-test]=xxActive Screen Corners and Edgesxx
Comment[zh_CN]=活动屏幕边缘
Comment[zh_TW]=作用中螢幕角落與邊緣
X-KDE-Keywords=kwin,window,manager,effect,corner,edge,border,action,switch,desktop,kwin screen edges,desktop edges,screen edges,maximize windows,tile windows,side of screen,screen behavior,switch desktop,virtual desktop,screen corners
X-KDE-Keywords[ca]=kwin,finestra,gestor,efecte,cantonada,vora,borde,acció,canvi,escriptori,vores de pantalla del kwin,vores d'escriptori,vores de pantalla,maximitza finestres,mosaic de finestres,costat de pantalla,comportament de pantalla,canvi d'escriptori,escriptori virtual,cantonades de pantalla
X-KDE-Keywords[da]=kwin,vindue,håndtering,manager,effekt,hjørne,kant,handling,skift,skrivebord,kwin skærmkanter,skrivebordskanter,skærmkanter,maksimer vinduer,tile windows,fliser,felter,siden af skærmen,skærmens opførsel,skift skrivebord,virtuelle skriveborde,skærmhjørner,hjørner
X-KDE-Keywords[de]=KWin,Fenster,Verwaltung,Effekt,Kante,Rand,Aktion,Wechseln,Desktop,Arbeitsfläche,KWin Bildschirmkanten,Desktopkanten,Bildschirmkanten,Fenster maximieren,Fenster kacheln,Bildschirmseite,Bildschirmverhalten,Desktop wechseln,Arbeitsfläche wechseln,Virtueller Desktop,Virtuelle Arbeitsfläche,Bildschirmecken
X-KDE-Keywords[en_GB]=kwin,window,manager,effect,corner,edge,border,action,switch,desktop,kwin screen edges,desktop edges,screen edges,maximise windows,tile windows,side of screen,screen behaviour,switch desktop,virtual desktop,screen corners
X-KDE-Keywords[es]=kwin,ventana,gestor,efecto,esquina,borde,acción,cambiar,escritorio,bordes de pantalla de kwin,bordes del escritorio,bordes de la pantalla,maximizar ventanas,ventanas en mosaico,lado de la pantalla,comportamiento de la pantalla,cambiar escritorio,escritorio virtual,esquinas de la pantalla
X-KDE-Keywords[fi]=kwin,window,manager,effect,corner,edge,border,action,switch,desktop,kwin screen edges,desktop edges,screen edges,maximize windows,tile windows,side of screen,screen behavior,switch desktop,virtual desktop,screen corners,ikkunamanageri,ikkunointiohjelma,tehoste,kulma,reuna,vaihda,vaihto,työpöytä,näytön reunat,työpöydän reunat,suurenna ikkuna,kasaa ikkunat,näytön toiminta,vaihda työpöytää,virtuaalityöpöytä,näytön reunat
X-KDE-Keywords[fr]=kwin, fenêtre, gestionnaire, effet, bord, coin, bordure, action, bascule, bureau, bords de l'écran kwin, bords du bureau, bords de l'écran, maximisation des fenêtres, mosaïque de fenêtres, cotés de l'écran, comportement de l'écran, changement de bureau, bureaux virtuels, coins de l'écran
X-KDE-Keywords[hu]=kwin,ablak,kezelő,effektus,sarok,szél,szegély,művelet,váltás,asztal,kwin képernyőszél,asztalszél,képernyőszél,ablakok maximalizálása,ablakcím,képernyőoldal,képernyő működése,asztalváltás,virtuális asztal,képernyősarkok
X-KDE-Keywords[ia]=kwin,fenestra,gerente,effecto,bordo,margine,action,commuta,scriptorio,bordos de schermo de kwin,bordos de scriptorio,bordos de scriptorio,maximisa fenestras,tegula fenestras,parte de schermo, comportamento de schermo,commuta scriptorio,scriptorio virtual,angulos de schermo
X-KDE-Keywords[id]=kwin,jendela,manajer,efek,sudut,tepi,batas,aksi,ganti,desktop,tepi layar kwin,tepi desktop,tepi layar,maksimalkan jendela,jendela ubin,tepi layar,perilaku layar,ganti desktop,desktop virtual,sudut layar
X-KDE-Keywords[ko]=kwin,window,manager,effect,corner,edge,border,action,switch,desktop,kwin screen edges,desktop edges,screen edges,maximize windows,tile windows,side of screen,screen behavior,switch desktop,virtual desktop,screen corners,창,관리자,효과,경계,경계선,동작,액션,전환,kwin 화면 경계,화면 경계,창 최대화,최대화,바둑판식 배열,화면 행동,데스크톱 전환,가상 데스크톱,화면 모서리,꼭지점
X-KDE-Keywords[nb]=kwin,vindu,behandler,effekt,kant,hjørne,ramme,handling,bytte,skrivebord,kwin skjermkanter,skrivebordkanter,skjermkanter,maksimere vinduer,flislegge vinduer,skjermside,skjermoppførsel,bytte skrivebord,virtuelt skrivebord,skjermhjørner
X-KDE-Keywords[nds]=KWin,Finster,Pleger,Effekt,Hörn,Kant,Rahmen,Akschoon,wesseln,Schriefdisch,maximeren,kacheln,Schirmkant,Schirmbedregen,Schirmhuuk
X-KDE-Keywords[nl]=kwin,venster,beheerder,effect,hoek,kant,rand,actie,omschakelen,bureaublad,schermranden van kwin,bureaubladkanten,schermkanten,vensters maximaliseren,venster schuin achter elkaar,zijkant van het scherm,schermgedrag,bureaublad omschakelen,virtueel bureaublad,schermhoeken
X-KDE-Keywords[pl]=kwin,okno,menadżer,efekt,narożnik,krawędź,obramowanie,działanie,przełącz,pulpit, krawędzie ekranu kwin,krawędzie pulpitu,krawędzie ekranu,maksymalizacja okien, kafelkowanie okien,strona ekranu,zachowanie ekranu,przełączanie pulpitu,wirtualny pulpit, krawędzie ekranu
X-KDE-Keywords[pt]=kwin,janela,gestor,efeito,extremo,contorno,acção,mudar,ecrã,extremos do ecrã no kwin,extremos do ecrã,maximizar as janelas,janelas lado-a-lado,lado do ecrã,comportamento do ecrã,mudar de ecrã,ecrã virtual,cantos do ecrã
X-KDE-Keywords[pt_BR]=kwin,janela,gerenciador,efeito,canto,contorno,borda,ação,mudar,área de trabalho,cantos da área de trabalho no kwin,cantos da área de trabalho,maximizar as janelas,janelas lado a lado,lado da tela,comportamento da tela,mudar de área de trabalho virtual,desktop,cantos da tela
X-KDE-Keywords[ru]=kwin,window,manager,effect,corner,edge,border,action,switch,desktop,kwin screen edges,desktop edges,screen edges,maximize windows,tile windows,side of screen,screen behavior,switch desktop,virtual desktop,screen corners,окно,окон,диспетчер,эффект,край,граница,действие,переключить,рабочий стол,края экрана kwin,края экрана,края рабочего стола,распахнуть окна,мозаика окон,край экрана,поведение экрана,переключить рабочий стол,виртуальный рабочий стол,углы рабочего стола,углы экрана
X-KDE-Keywords[sk]=kwin,okno, správca,efekt,okraj,hrana,akcia,prepnúť,plocha,okraje obrazovky kwin, efekty plochy,okraje obrazovky,maximalizovať okná,dlaždicové okná,strana obrazovky, správanie obrazovky,prepnúť plochu,virtuálna plocha,okraje obrazovky
X-KDE-Keywords[sl]=kwin,okno,upravljalnik oken,upravljanje oken,učinki,kot,rob,obroba,dejanje,preklopi,preklapljanje,robovi zaslona,robovi namizja,razpni okna,povečaj okna,tlakuj okna,rob zaslona,obnašanje zaslona,preklopi namizje,preklapljanje namizij,navidezno namizje,koti zaslona
X-KDE-Keywords[sr]=kwin,window,manager,effect,corner,edge,border,action,switch,desktop,kwin screen edges,desktop edges,screen edges,maximize windows,tile windows,side of screen,screen behavior,switch desktop,virtual desktop,screen corners,К‑вин,прозор,менаџер,ефекат,угао,ивица,радња,пребаци,површ,ивице екрана,ивице површи,максимизовање прозора,поплочавање прозора,странице прозора,понашање прозора,мењање површи,виртуелна површ,углови екрана
@ -127,3 +140,5 @@ X-KDE-Keywords[sr@latin]=kwin,window,manager,effect,corner,edge,border,action,sw
X-KDE-Keywords[sv]=kwin,fönster,hanterare,effekt,kant,gräns,åtgärd,byta,skrivbord,kwin skärmkanter,skrivbordskanter,maximera fönster,lägg fönster sida vid sida,skärmsidan, skärmbeteende,skrivbordsbyte,virtuellt skrivbord,skärmhörn
X-KDE-Keywords[uk]=kwin,window,manager,effect,corner,edge,border,action,switch,desktop,kwin screen edges,desktop edges,screen edges,maximize windows,tile windows,side of screen,screen behavior,switch desktop,virtual desktop,screen corners,вікно,керування,край,кут,межа,сторона,бік,дія,перемикання,стільниця,краї екрана,максимізація,мозаїка,плитка,край екрана,поведінка екрана,перемикання стільниць,віртуальна стільниця
X-KDE-Keywords[x-test]=xxkwin,window,manager,effect,corner,edge,border,action,switch,desktop,kwin screen edges,desktop edges,screen edges,maximize windows,tile windows,side of screen,screen behavior,switch desktop,virtual desktop,screen cornersxx
X-KDE-Keywords[zh_CN]=kwin,window,manager,effect,corner,edge,border,action,switch,desktop,kwin screen edges,desktop edges,screen edges,maximize windows,tile windows,side of screen,screen behavior,switch desktop,virtual desktop,screen corners,窗口,管理,特效,角,边缘,动作,切换,桌面,kwin 屏幕边缘,屏幕边缘,桌面边缘,最大化窗口,平铺窗口,屏幕行为,桌面切换,虚拟桌面,屏幕角落
X-KDE-Keywords[zh_TW]= kwin,window,manager,effect,edge,border,action,switch,desktop,kwin screen edges,desktop edges,screen edges,maximize windows,tile windows,side of screen,screen behavior,switch desktop,virtual desktop,screen corners

View File

@ -73,17 +73,23 @@ Name[zh_CN]=任务切换器
Name[zh_TW]=工作切換器
Comment=Navigation Through Windows
Comment[ca]=Navegació per les finestres
Comment[cs]=Navigace skrz okna
Comment[da]=Navigation igennem vinduer
Comment[de]=Zwischen Fenstern wechseln
Comment[en_GB]=Navigation Through Windows
Comment[es]=Navegación a través de las ventanas
Comment[fi]=Ikkunoiden välillä liikkuminen
Comment[fi]=Ikkunoiden välillä siirtyminen
Comment[fr]=Navigation dans les fenêtres
Comment[hu]=Navigálás az ablakok közt
Comment[id]=Navigasi Melalui Jendela
Comment[ko]=창간 탐색
Comment[nb]=Navigasjon gjennom vinduer
Comment[nds]=Finstern dörgahn
Comment[nl]=Navigatie door vensters
Comment[pl]=Przechodzenie pomiędzy oknami
Comment[pt]=Navegação pelas Janelas
Comment[pt_BR]=Navegação pelas janelas
Comment[ru]=Настройка переключателя окон
Comment[sk]=Navigácia cez okná
Comment[sl]=Krmarjenje med okni
Comment[sr]=Кретање између прозора
@ -92,7 +98,10 @@ Comment[sr@ijekavianlatin]=Kretanje između prozora
Comment[sr@latin]=Kretanje između prozora
Comment[sv]=Navigering via fönster
Comment[uk]=Навігація ввікнами
Comment[vi]=Điều hướng qua các cửa sổ
Comment[x-test]=xxNavigation Through Windowsxx
Comment[zh_CN]=遍历窗口
Comment[zh_TW]=透過視窗導覽
X-KDE-Keywords=window,windows,switcher,window switcher,switching,window switching,alttab,alt-tab,alt+tab,alt tab
X-KDE-Keywords[bs]=prozor,prozori,razmijenjivati,razimjenjivati prozor,gašenje prozora,alttab,alt-tab,alt+tab,alt tab
X-KDE-Keywords[ca]=finestra,finestres,commutador,commutador de finestres,commutació,commutació de finestres,alttab,alt-tab,alt+tab,alt tab

View File

@ -242,6 +242,7 @@ Comment=A graphics reset event occurred
Comment[bs]=Grafički reset događaj se desio
Comment[ca]=Ha ocorregut un esdeveniment de reinici dels gràfics
Comment[ca@valencia]=Ha ocorregut un esdeveniment de reinici dels gràfics
Comment[cs]=Nastala událost resetování grafiky
Comment[da]=En grafiknulstillingshændelse fandt sted
Comment[de]=Ein Zurücksetzen der Grafik ist aufgetreten
Comment[el]=Συνέβη μια επαναφορά των γραφικών

145
libinput/connection.cpp Normal file
View File

@ -0,0 +1,145 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2014 Martin Gräßlin <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 "connection.h"
#include "context.h"
#include "events.h"
#include "../logind.h"
#include <QDebug>
#include <QSocketNotifier>
#include <libinput.h>
namespace KWin
{
namespace LibInput
{
Connection *Connection::s_self = nullptr;
static Context *s_context = nullptr;
Connection::Connection(QObject *parent) = delete;
Connection *Connection::create(QObject *parent)
{
Q_ASSERT(!s_self);
static Udev s_udev;
if (!s_udev.isValid()) {
qWarning() << "Failed to initialize udev";
return nullptr;
}
if (!s_context) {
s_context = new Context(s_udev);
if (!s_context->isValid()) {
qWarning() << "Failed to create context from udev";
delete s_context;
s_context = nullptr;
return nullptr;
}
// TODO: don't hardcode seat name
if (!s_context->assignSeat("seat0")) {
qWarning() << "Failed to assign seat seat0";
delete s_context;
s_context = nullptr;
return nullptr;
}
}
s_self = new Connection(s_context, parent);
return s_self;
}
Connection::Connection(Context *input, QObject *parent)
: QObject(parent)
, m_input(input)
, m_notifier(nullptr)
{
Q_ASSERT(m_input);
}
Connection::~Connection()
{
s_self = nullptr;
delete s_context;
s_context = nullptr;
}
void Connection::setup()
{
Q_ASSERT(!m_notifier);
m_notifier = new QSocketNotifier(m_input->fileDescriptor(), QSocketNotifier::Read, this);
connect(m_notifier, &QSocketNotifier::activated, this, &Connection::handleEvent);
LogindIntegration *logind = LogindIntegration::self();
connect(logind, &LogindIntegration::sessionActiveChanged, this,
[this](bool active) {
active ? m_input->resume() : m_input->suspend();
}
);
}
void Connection::handleEvent()
{
do {
m_input->dispatch();
QScopedPointer<Event> event(m_input->event());
if (event.isNull()) {
break;
}
switch (event->type()) {
case LIBINPUT_EVENT_KEYBOARD_KEY: {
KeyEvent *ke = static_cast<KeyEvent*>(event.data());
emit keyChanged(ke->key(), ke->state(), ke->time());
break;
}
case LIBINPUT_EVENT_POINTER_AXIS: {
PointerEvent *pe = static_cast<PointerEvent*>(event.data());
emit pointerAxisChanged(pe->axis(), pe->axisValue(), pe->time());
break;
}
case LIBINPUT_EVENT_POINTER_BUTTON: {
PointerEvent *pe = static_cast<PointerEvent*>(event.data());
emit pointerButtonChanged(pe->button(), pe->buttonState(), pe->time());
break;
}
case LIBINPUT_EVENT_POINTER_MOTION: {
PointerEvent *pe = static_cast<PointerEvent*>(event.data());
emit pointerMotion(pe->delta(), pe->time());
break;
}
case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE: {
PointerEvent *pe = static_cast<PointerEvent*>(event.data());
emit pointerMotionAbsolute(pe->absolutePos(), pe->absolutePos(m_size), pe->time());
break;
}
default:
// nothing
break;
}
} while (true);
}
void Connection::setScreenSize(const QSize &size)
{
m_size = size;
}
}
}

71
libinput/connection.h Normal file
View File

@ -0,0 +1,71 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2014 Martin Gräßlin <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/>.
*********************************************************************/
#ifndef KWIN_LIBINPUT_CONNECTION_H
#define KWIN_LIBINPUT_CONNECTION_H
#include "../input.h"
#include <kwinglobals.h>
#include <QObject>
#include <QSize>
class QSocketNotifier;
namespace KWin
{
namespace LibInput
{
class Context;
class Connection : public QObject
{
Q_OBJECT
public:
~Connection();
void setup();
/**
* Sets the screen @p size. This is needed for mapping absolute pointer events to
* the screen data.
**/
void setScreenSize(const QSize &size);
Q_SIGNALS:
void keyChanged(uint32_t key, InputRedirection::KeyboardKeyState, uint32_t time);
void pointerButtonChanged(uint32_t button, InputRedirection::PointerButtonState state, uint32_t time);
void pointerMotionAbsolute(QPointF orig, QPointF screen, uint32_t time);
void pointerMotion(QPointF delta, uint32_t time);
void pointerAxisChanged(InputRedirection::PointerAxis axis, qreal delta, uint32_t time);
private:
Connection(Context *input, QObject *parent = nullptr);
void handleEvent();
Context *m_input;
QSocketNotifier *m_notifier;
QSize m_size;
KWIN_SINGLETON(Connection)
};
}
}
#endif

173
libinput/context.cpp Normal file
View File

@ -0,0 +1,173 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2014 Martin Gräßlin <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 "context.h"
#include "events.h"
#include "../logind.h"
#include <libudev.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
namespace KWin
{
namespace LibInput
{
Udev::Udev()
: m_udev(udev_new())
{
}
Udev::~Udev()
{
if (m_udev) {
udev_unref(m_udev);
}
}
Context::Context(const Udev &udev)
: m_libinput(libinput_udev_create_context(&Context::s_interface, this, udev))
, m_suspended(false)
{
libinput_log_set_priority(m_libinput, LIBINPUT_LOG_PRIORITY_DEBUG);
}
Context::~Context()
{
if (m_libinput) {
libinput_unref(m_libinput);
}
}
bool Context::assignSeat(const char *seat)
{
if (!isValid()) {
return false;
}
return libinput_udev_assign_seat(m_libinput, seat) == 0;
}
int Context::fileDescriptor()
{
if (!isValid()) {
return 0;
}
return libinput_get_fd(m_libinput);
}
void Context::dispatch()
{
libinput_dispatch(m_libinput);
}
const struct libinput_interface Context::s_interface = {
Context::openRestrictedCallback,
Context::closeRestrictedCallBack
};
int Context::openRestrictedCallback(const char *path, int flags, void *user_data)
{
return ((Context*)user_data)->openRestricted(path, flags);
}
void Context::closeRestrictedCallBack(int fd, void *user_data)
{
((Context*)user_data)->closeRestricted(fd);
}
int Context::openRestricted(const char *path, int flags)
{
LogindIntegration *logind = LogindIntegration::self();
Q_ASSERT(logind);
int fd = logind->takeDevice(path);
if (fd < 0) {
// failed
return fd;
}
// adjust flags - based on Weston (logind-util.c)
int fl = fcntl(fd, F_GETFL);
auto errorHandling = [fd, this]() {
close(fd);
closeRestricted(fd);
};
if (fl < 0) {
errorHandling();
return -1;
}
if (flags & O_NONBLOCK) {
fl |= O_NONBLOCK;
}
if (fcntl(fd, F_SETFL, fl) < 0) {
errorHandling();
return -1;
}
fl = fcntl(fd, F_GETFD);
if (fl < 0) {
errorHandling();
return -1;
}
if (!(flags & O_CLOEXEC)) {
fl &= ~FD_CLOEXEC;
}
if (fcntl(fd, F_SETFD, fl) < 0) {
errorHandling();
return -1;
}
return fd;
}
void Context::closeRestricted(int fd)
{
LogindIntegration *logind = LogindIntegration::self();
Q_ASSERT(logind);
logind->releaseDevice(fd);
}
Event *Context::event()
{
return Event::create(libinput_get_event(m_libinput));
}
void Context::suspend()
{
if (m_suspended) {
return;
}
libinput_suspend(m_libinput);
m_suspended = true;
}
void Context::resume()
{
if (!m_suspended) {
return;
}
libinput_resume(m_libinput);
m_suspended = false;
}
}
}

95
libinput/context.h Normal file
View File

@ -0,0 +1,95 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2014 Martin Gräßlin <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/>.
*********************************************************************/
#ifndef KWIN_LIBINPUT_CONTEXT_H
#define KWIN_LIBINPUT_CONTEXT_H
#include <libinput.h>
struct udev;
namespace KWin
{
namespace LibInput
{
class Event;
class Udev
{
public:
Udev();
~Udev();
bool isValid() const {
return m_udev != nullptr;
}
operator udev*() const {
return m_udev;
}
operator udev*() {
return m_udev;
}
private:
struct udev *m_udev;
};
class Context
{
public:
Context(const Udev &udev);
~Context();
bool assignSeat(const char *seat);
bool isValid() const {
return m_libinput != nullptr;
}
int fileDescriptor();
void dispatch();
void suspend();
void resume();
operator libinput*() {
return m_libinput;
}
operator libinput*() const {
return m_libinput;
}
/**
* Gets the next event, if there is no new event @c null is returned.
* The caller takes ownership of the returned pointer.
**/
Event *event();
static int openRestrictedCallback(const char *path, int flags, void *user_data);
static void closeRestrictedCallBack(int fd, void *user_data);
static const struct libinput_interface s_interface;
private:
int openRestricted(const char *path, int flags);
void closeRestricted(int fd);
struct libinput *m_libinput;
bool m_suspended;
};
}
}
#endif

165
libinput/events.cpp Normal file
View File

@ -0,0 +1,165 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2014 Martin Gräßlin <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 "events.h"
#include <QSize>
namespace KWin
{
namespace LibInput
{
Event *Event::create(libinput_event *event)
{
if (!event) {
return nullptr;
}
const auto t = libinput_event_get_type(event);
// TODO: add touch events
// TODO: add device notify events
switch (t) {
case LIBINPUT_EVENT_KEYBOARD_KEY:
return new KeyEvent(event);
case LIBINPUT_EVENT_POINTER_AXIS:
case LIBINPUT_EVENT_POINTER_BUTTON:
case LIBINPUT_EVENT_POINTER_MOTION:
case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
return new PointerEvent(event, t);
default:
return new Event(event, t);
}
}
Event::Event(libinput_event *event, libinput_event_type type)
: m_event(event)
, m_type(type)
{
}
Event::~Event()
{
libinput_event_destroy(m_event);
}
libinput_device *Event::device() const
{
return libinput_event_get_device(m_event);
}
KeyEvent::KeyEvent(libinput_event *event)
: Event(event, LIBINPUT_EVENT_KEYBOARD_KEY)
, m_keyboardEvent(libinput_event_get_keyboard_event(event))
{
}
KeyEvent::~KeyEvent() = default;
uint32_t KeyEvent::key() const
{
return libinput_event_keyboard_get_key(m_keyboardEvent);
}
InputRedirection::KeyboardKeyState KeyEvent::state() const
{
switch (libinput_event_keyboard_get_key_state(m_keyboardEvent)) {
case LIBINPUT_KEY_STATE_PRESSED:
return InputRedirection::KeyboardKeyPressed;
case LIBINPUT_KEY_STATE_RELEASED:
return InputRedirection::KeyboardKeyReleased;
}
abort();
}
uint32_t KeyEvent::time() const
{
return libinput_event_keyboard_get_time(m_keyboardEvent);
}
PointerEvent::PointerEvent(libinput_event *event, libinput_event_type type)
: Event(event, type)
, m_pointerEvent(libinput_event_get_pointer_event(event))
{
}
PointerEvent::~PointerEvent() = default;
QPointF PointerEvent::absolutePos() const
{
Q_ASSERT(type() == LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE);
return QPointF(libinput_event_pointer_get_absolute_x(m_pointerEvent),
libinput_event_pointer_get_absolute_y(m_pointerEvent));
}
QPointF PointerEvent::absolutePos(const QSize &size) const
{
Q_ASSERT(type() == LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE);
return QPointF(libinput_event_pointer_get_absolute_x_transformed(m_pointerEvent, size.width()),
libinput_event_pointer_get_absolute_y_transformed(m_pointerEvent, size.height()));
}
QPointF PointerEvent::delta() const
{
Q_ASSERT(type() == LIBINPUT_EVENT_POINTER_MOTION);
return QPointF(libinput_event_pointer_get_dx(m_pointerEvent), libinput_event_pointer_get_dy(m_pointerEvent));
}
uint32_t PointerEvent::time() const
{
return libinput_event_pointer_get_time(m_pointerEvent);
}
uint32_t PointerEvent::button() const
{
Q_ASSERT(type() == LIBINPUT_EVENT_POINTER_BUTTON);
return libinput_event_pointer_get_button(m_pointerEvent);
}
InputRedirection::PointerButtonState PointerEvent::buttonState() const
{
Q_ASSERT(type() == LIBINPUT_EVENT_POINTER_BUTTON);
switch (libinput_event_pointer_get_button_state(m_pointerEvent)) {
case LIBINPUT_BUTTON_STATE_PRESSED:
return InputRedirection::PointerButtonPressed;
case LIBINPUT_BUTTON_STATE_RELEASED:
return InputRedirection::PointerButtonReleased;
}
abort();
}
InputRedirection::PointerAxis PointerEvent::axis() const
{
Q_ASSERT(type() == LIBINPUT_EVENT_POINTER_AXIS);
switch (libinput_event_pointer_get_axis(m_pointerEvent)) {
case LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL:
return InputRedirection::PointerAxisHorizontal;
case LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL:
return InputRedirection::PointerAxisVertical;
}
abort();
}
qreal PointerEvent::axisValue() const
{
Q_ASSERT(type() == LIBINPUT_EVENT_POINTER_AXIS);
return libinput_event_pointer_get_axis_value(m_pointerEvent);
}
}
}

113
libinput/events.h Normal file
View File

@ -0,0 +1,113 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2014 Martin Gräßlin <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/>.
*********************************************************************/
#ifndef KWIN_LIBINPUT_EVENTS_H
#define KWIN_LIBINPUT_EVENTS_H
#include "../input.h"
#include <libinput.h>
namespace KWin
{
namespace LibInput
{
class Event
{
public:
virtual ~Event();
libinput_event_type type() const;
libinput_device *device() const;
operator libinput_event*() {
return m_event;
}
operator libinput_event*() const {
return m_event;
}
static Event *create(libinput_event *event);
protected:
Event(libinput_event *event, libinput_event_type type);
private:
libinput_event *m_event;
libinput_event_type m_type;
};
class KeyEvent : public Event
{
public:
KeyEvent(libinput_event *event);
virtual ~KeyEvent();
uint32_t key() const;
InputRedirection::KeyboardKeyState state() const;
uint32_t time() const;
operator libinput_event_keyboard*() {
return m_keyboardEvent;
}
operator libinput_event_keyboard*() const {
return m_keyboardEvent;
}
private:
libinput_event_keyboard *m_keyboardEvent;
};
class PointerEvent : public Event
{
public:
PointerEvent(libinput_event* event, libinput_event_type type);
virtual ~PointerEvent();
QPointF absolutePos() const;
QPointF absolutePos(const QSize &size) const;
QPointF delta() const;
uint32_t button() const;
InputRedirection::PointerButtonState buttonState() const;
uint32_t time() const;
InputRedirection::PointerAxis axis() const;
qreal axisValue() const;
operator libinput_event_pointer*() {
return m_pointerEvent;
}
operator libinput_event_pointer*() const {
return m_pointerEvent;
}
private:
libinput_event_pointer *m_pointerEvent;
};
inline
libinput_event_type Event::type() const
{
return m_type;
}
}
}
#endif

View File

@ -27,11 +27,11 @@ target_link_libraries(kdecorations
include(ECMPackageConfigHelpers)
include(ECMSetupVersion)
ecm_setup_version(${KWIN_VERSION}
ecm_setup_version(${PROJECT_VERSION}
VARIABLE_PREFIX KDECORATIONS
VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/kdecorations_version.h"
PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/KDecorationsConfigVersion.cmake"
SOVERSION 5
SOVERSION ${PROJECT_VERSION_MAJOR}
)
set_target_properties(kdecorations PROPERTIES

View File

@ -1,11 +1,11 @@
########### next target ###############
include(ECMSetupVersion)
ecm_setup_version(${KWIN_VERSION}
ecm_setup_version(${PROJECT_VERSION}
VARIABLE_PREFIX KWINEFFECTS
VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/kwineffects_version.h"
PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/KWinEffectsConfigVersion.cmake"
SOVERSION 5
SOVERSION ${PROJECT_VERSION_MAJOR}
)
### xrenderutils lib ###

View File

@ -29,7 +29,7 @@ QDebug operator<<(QDebug dbg, const KWin::AniData &a)
}
using namespace KWin;
static int Gaussian = 46;
static const int Gaussian = 46;
AniData::AniData()
{

View File

@ -441,7 +441,7 @@ void AnimationEffect::prePaintWindow( EffectWindow* w, WindowPrePaintData& data,
continue;
isUsed = true;
if (anim->attribute == Opacity || anim->attribute == DecorationOpacity || anim->attribute == CrossFadePrevious)
if (anim->attribute == Opacity || anim->attribute == CrossFadePrevious)
data.setTranslucent();
else if (!(anim->attribute == Brightness || anim->attribute == Saturation)) {
data.setTransformed();
@ -488,8 +488,6 @@ void AnimationEffect::paintWindow( EffectWindow* w, int mask, QRegion region, Wi
switch (anim->attribute) {
case Opacity:
data.multiplyOpacity(interpolated(*anim)); break;
case DecorationOpacity:
data.multiplyDecorationOpacity(interpolated(*anim)); break;
case Brightness:
data.multiplyBrightness(interpolated(*anim)); break;
case Saturation:
@ -746,7 +744,6 @@ void AnimationEffect::updateLayerRepaints()
continue;
switch (anim->attribute) {
case Opacity:
case DecorationOpacity:
case Brightness:
case Saturation:
case CrossFadePrevious:

View File

@ -100,7 +100,7 @@ public:
enum Anchor { Left = 1<<0, Top = 1<<1, Right = 1<<2, Bottom = 1<<3,
Horizontal = Left|Right, Vertical = Top|Bottom, Mouse = 1<<4 };
enum Attribute {
Opacity = 0, Brightness, Saturation, Scale, Rotation, DecorationOpacity,
Opacity = 0, Brightness, Saturation, Scale, Rotation,
Position, Size, Translation, Clip, Generic, CrossFadePrevious,
NonFloatBase = Position
};

View File

@ -226,7 +226,6 @@ void PaintData::setRotationOrigin(const QVector3D &origin)
class WindowPaintDataPrivate {
public:
qreal opacity;
qreal decorationOpacity;
qreal saturation;
qreal brightness;
int screen;
@ -240,7 +239,6 @@ WindowPaintData::WindowPaintData(EffectWindow* w)
{
quads = w->buildQuads();
setOpacity(w->opacity());
setDecorationOpacity(1.0);
setSaturation(1.0);
setBrightness(1.0);
setScreen(0);
@ -261,7 +259,6 @@ WindowPaintData::WindowPaintData(const WindowPaintData &other)
setRotationAxis(other.rotationAxis());
setRotationAngle(other.rotationAngle());
setOpacity(other.opacity());
setDecorationOpacity(other.decorationOpacity());
setSaturation(other.saturation());
setBrightness(other.brightness());
setScreen(other.screen());
@ -273,11 +270,6 @@ WindowPaintData::~WindowPaintData()
delete d;
}
qreal WindowPaintData::decorationOpacity() const
{
return d->decorationOpacity;
}
qreal WindowPaintData::opacity() const
{
return d->opacity;
@ -298,11 +290,6 @@ int WindowPaintData::screen() const
return d->screen;
}
void WindowPaintData::setDecorationOpacity(qreal opacity)
{
d->decorationOpacity = opacity;
}
void WindowPaintData::setOpacity(qreal opacity)
{
d->opacity = opacity;
@ -333,12 +320,6 @@ void WindowPaintData::setCrossFadeProgress(qreal factor)
d->crossFadeProgress = qBound(qreal(0.0), factor, qreal(1.0));
}
qreal WindowPaintData::multiplyDecorationOpacity(qreal factor)
{
d->decorationOpacity *= factor;
return d->decorationOpacity;
}
qreal WindowPaintData::multiplyOpacity(qreal factor)
{
d->opacity *= factor;

View File

@ -2224,14 +2224,10 @@ public:
WindowPaintData& operator+=(const QVector3D &translation);
/**
* Window opacity, in range 0 = transparent to 1 = fully opaque
* Opacity for decoration is opacity*decorationOpacity
* @see decorationOpacity
* @see setOpacity
* @see setDecorationOpacity
* @since 4.10
*/
qreal opacity() const;
qreal decorationOpacity() const;
/**
* Sets the window opacity to the new @p opacity.
* If you want to modify the existing opacity level consider using multiplyOpacity.
@ -2239,7 +2235,6 @@ public:
* @since 4.10
**/
void setOpacity(qreal opacity);
void setDecorationOpacity(qreal opacity);
/**
* Multiplies the current opacity with the @p factor.
* @param factor Factor with which the opacity should be multiplied
@ -2247,13 +2242,6 @@ public:
* @since 4.10
**/
qreal multiplyOpacity(qreal factor);
/**
* Multiplies the current decoration opacity with the @p factor.
* @param factor Factor with which the opacity should be multiplied
* @return New decoration opacity level
* @since 4.10
**/
qreal multiplyDecorationOpacity(qreal factor);
/**
* Saturation of the window, in range [0; 1]
* 1 means that the window is unchanged, 0 means that it's completely

View File

@ -30,7 +30,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <kwinconfig.h>
#define KWIN_QT5_PORTING 0
#define KWIN_EXPORT KDEINIT_KWIN_EXPORT
namespace KWin
{

View File

@ -254,9 +254,9 @@ void GLTexture::update(const QImage &image, const QPoint &offset, const QRect &s
Q_D(GLTexture);
#ifdef KWIN_HAVE_OPENGLES
static bool s_supportsUnpack = hasGLExtension(QByteArrayLiteral("GL_EXT_unpack_subimage"));
static const bool s_supportsUnpack = hasGLExtension(QByteArrayLiteral("GL_EXT_unpack_subimage"));
#else
static bool s_supportsUnpack = true;
static const bool s_supportsUnpack = true;
#endif
int width = image.width();

View File

@ -23,6 +23,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <QDebug>
#include <QStack>
#include <QPixmap>
#include <QGlobalStatic>
namespace KWin
{
@ -226,4 +227,60 @@ xcb_render_picture_t xRenderOffscreenTarget()
return s_offscreenTarget;
}
} // namespace
namespace XRenderUtils
{
struct PictFormatData
{
PictFormatData() {
// Fetch the render pict formats
reply = xcb_render_query_pict_formats_reply(s_connection,
xcb_render_query_pict_formats_unchecked(s_connection), nullptr);
// Init the visual ID -> format ID hash table
for (auto screens = xcb_render_query_pict_formats_screens_iterator(reply); screens.rem; xcb_render_pictscreen_next(&screens)) {
for (auto depths = xcb_render_pictscreen_depths_iterator(screens.data); depths.rem; xcb_render_pictdepth_next(&depths)) {
const xcb_render_pictvisual_t *visuals = xcb_render_pictdepth_visuals(depths.data);
const int len = xcb_render_pictdepth_visuals_length(depths.data);
for (int i = 0; i < len; i++)
visualHash.insert(visuals[i].visual, visuals[i].format);
}
}
// Init the format ID -> xcb_render_directformat_t* hash table
const xcb_render_pictforminfo_t *formats = xcb_render_query_pict_formats_formats(reply);
const int len = xcb_render_query_pict_formats_formats_length(reply);
for (int i = 0; i < len; i++) {
if (formats[i].type == XCB_RENDER_PICT_TYPE_DIRECT)
formatInfoHash.insert(formats[i].id, &formats[i].direct);
}
}
~PictFormatData() {
free(reply);
}
xcb_render_query_pict_formats_reply_t *reply;
QHash<xcb_visualid_t, xcb_render_pictformat_t> visualHash;
QHash<xcb_render_pictformat_t, const xcb_render_directformat_t *> formatInfoHash;
};
Q_GLOBAL_STATIC(PictFormatData, g_pictFormatData)
xcb_render_pictformat_t findPictFormat(xcb_visualid_t visual)
{
PictFormatData *d = g_pictFormatData;
return d->visualHash.value(visual);
}
const xcb_render_directformat_t *findPictFormatInfo(xcb_render_pictformat_t format)
{
PictFormatData *d = g_pictFormatData;
return d->formatInfoHash.value(format);
}
} // namespace XRenderUtils
} // namespace KWin

View File

@ -169,9 +169,20 @@ namespace XRenderUtils
* @internal
**/
KWINXRENDERUTILS_EXPORT void init(xcb_connection_t *connection, xcb_window_t rootWindow);
}
} // namespace
/**
* Returns the Xrender format that corresponds to the given visual ID.
*/
KWINXRENDERUTILS_EXPORT xcb_render_pictformat_t findPictFormat(xcb_visualid_t visual);
/**
* Returns the xcb_render_directformat_t for the given Xrender format.
*/
KWINXRENDERUTILS_EXPORT const xcb_render_directformat_t *findPictFormatInfo(xcb_render_pictformat_t format);
} // namespace XRenderUtils
} // namespace KWin
/** @} */

252
logind.cpp Normal file
View File

@ -0,0 +1,252 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2014 Martin Gräßlin <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 "logind.h"
#include <QCoreApplication>
#include <QDebug>
#include <QDBusConnection>
#include <QDBusConnectionInterface>
#include <QDBusPendingCallWatcher>
#include <QDBusServiceWatcher>
#include <QDBusUnixFileDescriptor>
#include <sys/stat.h>
#include <unistd.h>
namespace KWin
{
const static QString s_login1Service = QStringLiteral("org.freedesktop.login1");
const static QString s_login1Path = QStringLiteral("/org/freedesktop/login1");
const static QString s_login1ManagerInterface = QStringLiteral("org.freedesktop.login1.Manager");
const static QString s_login1SessionInterface = QStringLiteral("org.freedesktop.login1.Session");
const static QString s_dbusPropertiesInterface = QStringLiteral("org.freedesktop.DBus.Properties");
LogindIntegration *LogindIntegration::s_self = nullptr;
LogindIntegration *LogindIntegration::create(QObject *parent)
{
Q_ASSERT(!s_self);
s_self = new LogindIntegration(parent);
return s_self;
}
LogindIntegration::LogindIntegration(const QDBusConnection &connection, QObject *parent)
: QObject(parent)
, m_bus(connection)
, m_logindServiceWatcher(new QDBusServiceWatcher(s_login1Service,
m_bus,
QDBusServiceWatcher::WatchForUnregistration | QDBusServiceWatcher::WatchForRegistration,
this))
, m_connected(false)
, m_sessionControl(false)
, m_sessionActive(false)
{
connect(m_logindServiceWatcher, &QDBusServiceWatcher::serviceRegistered, this, &LogindIntegration::logindServiceRegistered);
connect(m_logindServiceWatcher, &QDBusServiceWatcher::serviceUnregistered, this,
[this]() {
m_connected = false;
emit connectedChanged();
}
);
// check whether the logind service is registered
QDBusMessage message = QDBusMessage::createMethodCall(QStringLiteral("org.freedesktop.DBus"),
QStringLiteral("/"),
QStringLiteral("org.freedesktop.DBus"),
QStringLiteral("ListNames"));
QDBusPendingReply<QStringList> async = m_bus.asyncCall(message);
QDBusPendingCallWatcher *callWatcher = new QDBusPendingCallWatcher(async, this);
connect(callWatcher, &QDBusPendingCallWatcher::finished, this,
[this](QDBusPendingCallWatcher *self) {
QDBusPendingReply<QStringList> reply = *self;
self->deleteLater();
if (!reply.isValid()) {
return;
}
if (reply.value().contains(s_login1Service)) {
logindServiceRegistered();
}
}
);
}
LogindIntegration::LogindIntegration(QObject *parent)
: LogindIntegration(QDBusConnection::systemBus(), parent)
{
}
LogindIntegration::~LogindIntegration()
{
s_self = nullptr;
}
void LogindIntegration::logindServiceRegistered()
{
// get the current session
QDBusMessage message = QDBusMessage::createMethodCall(s_login1Service,
s_login1Path,
s_login1ManagerInterface,
QStringLiteral("GetSessionByPID"));
message.setArguments(QVariantList() << (quint32) QCoreApplication::applicationPid());
QDBusPendingReply<QDBusObjectPath> session = m_bus.asyncCall(message);
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(session, this);
connect(watcher, &QDBusPendingCallWatcher::finished, this,
[this](QDBusPendingCallWatcher *self) {
QDBusPendingReply<QDBusObjectPath> reply = *self;
self->deleteLater();
if (m_connected) {
return;
}
if (!reply.isValid()) {
qDebug() << "The session is not registered with logind" << reply.error().message();
return;
}
m_sessionPath = reply.value().path();
qDebug() << "Session path:" << m_sessionPath;
m_connected = true;
connectSessionPropertiesChanged();
getSessionActive();
emit connectedChanged();
}
);
}
void LogindIntegration::connectSessionPropertiesChanged()
{
m_bus.connect(s_login1Service,
m_sessionPath,
s_dbusPropertiesInterface,
QStringLiteral("PropertiesChanged"),
this,
SLOT(getSessionActive()));
}
void LogindIntegration::getSessionActive()
{
if (!m_connected || m_sessionPath.isEmpty()) {
return;
}
QDBusMessage message = QDBusMessage::createMethodCall(s_login1Service,
m_sessionPath,
s_dbusPropertiesInterface,
QStringLiteral("Get"));
message.setArguments(QVariantList({s_login1SessionInterface, QStringLiteral("Active")}));
QDBusPendingReply<QVariant> reply = m_bus.asyncCall(message);
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this);
connect(watcher, &QDBusPendingCallWatcher::finished, this,
[this](QDBusPendingCallWatcher *self) {
QDBusPendingReply<QVariant> reply = *self;
self->deleteLater();
if (!reply.isValid()) {
qDebug() << "Failed to get Active Property of logind session:" << reply.error().message();
return;
}
const bool active = reply.value().toBool();
if (m_sessionActive != active) {
m_sessionActive = active;
emit sessionActiveChanged(m_sessionActive);
}
}
);
}
void LogindIntegration::takeControl()
{
if (!m_connected || m_sessionPath.isEmpty() || m_sessionControl) {
return;
}
QDBusMessage message = QDBusMessage::createMethodCall(s_login1Service,
m_sessionPath,
s_login1SessionInterface,
QStringLiteral("TakeControl"));
message.setArguments(QVariantList({QVariant(false)}));
QDBusPendingReply<void> session = m_bus.asyncCall(message);
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(session, this);
connect(watcher, &QDBusPendingCallWatcher::finished, this,
[this](QDBusPendingCallWatcher *self) {
QDBusPendingReply<void> reply = *self;
self->deleteLater();
if (!reply.isValid()) {
qDebug() << "Failed to get session control" << reply.error().message();
emit hasSessionControlChanged(false);
return;
}
qDebug() << "Gained session control";
m_sessionControl = true;
emit hasSessionControlChanged(true);
}
);
}
void LogindIntegration::releaseControl()
{
if (!m_connected || m_sessionPath.isEmpty() || !m_sessionControl) {
return;
}
QDBusMessage message = QDBusMessage::createMethodCall(s_login1Service,
m_sessionPath,
s_login1SessionInterface,
QStringLiteral("ReleaseControl"));
m_bus.asyncCall(message);
m_sessionControl = false;
emit hasSessionControlChanged(false);
}
int LogindIntegration::takeDevice(const char *path)
{
struct stat st;
if (stat(path, &st) < 0) {
qDebug() << "Could not stat the path";
return -1;
}
QDBusMessage message = QDBusMessage::createMethodCall(s_login1Service,
m_sessionPath,
s_login1SessionInterface,
QStringLiteral("TakeDevice"));
message.setArguments(QVariantList({QVariant(major(st.st_rdev)), QVariant(minor(st.st_rdev))}));
// intended to be a blocking call
QDBusMessage reply = m_bus.call(message);
if (reply.type() == QDBusMessage::ErrorMessage) {
qDebug() << "Could not take device" << path << ", cause: " << reply.errorMessage();
return -1;
}
return dup(reply.arguments().first().value<QDBusUnixFileDescriptor>().fileDescriptor());
}
void LogindIntegration::releaseDevice(int fd)
{
struct stat st;
if (fstat(fd, &st) < 0) {
qDebug() << "Could not stat the file descriptor";
return;
}
QDBusMessage message = QDBusMessage::createMethodCall(s_login1Service,
m_sessionPath,
s_login1SessionInterface,
QStringLiteral("ReleaseDevice"));
message.setArguments(QVariantList({QVariant(major(st.st_rdev)), QVariant(minor(st.st_rdev))}));
m_bus.asyncCall(message);
}
} // namespace

85
logind.h Normal file
View File

@ -0,0 +1,85 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2014 Martin Gräßlin <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/>.
*********************************************************************/
#ifndef KWIN_LOGIND_H
#define KWIN_LOGIND_H
#include <kwinglobals.h>
#include <QDBusConnection>
#include <QObject>
class QDBusServiceWatcher;
namespace KWin
{
class LogindIntegration : public QObject
{
Q_OBJECT
public:
~LogindIntegration();
bool isConnected() const {
return m_connected;
}
bool hasSessionControl() const {
return m_sessionControl;
}
bool isActiveSession() const {
return m_sessionActive;
}
void takeControl();
void releaseControl();
int takeDevice(const char *path);
void releaseDevice(int fd);
Q_SIGNALS:
void connectedChanged();
void hasSessionControlChanged(bool);
void sessionActiveChanged(bool);
private Q_SLOTS:
void getSessionActive();
private:
friend class LogindTest;
/**
* The DBusConnection argument is needed for the unit test. Logind uses the system bus
* on which the unit test's fake logind cannot register to. Thus the unit test need to
* be able to do everything over the session bus. This ctor allows the LogindTest to
* create a LogindIntegration which listens on the session bus.
**/
explicit LogindIntegration(const QDBusConnection &connection, QObject *parent = nullptr);
void logindServiceRegistered();
void connectSessionPropertiesChanged();
QDBusConnection m_bus;
QDBusServiceWatcher *m_logindServiceWatcher;
bool m_connected;
QString m_sessionPath;
bool m_sessionControl;
bool m_sessionActive;
KWIN_SINGLETON(LogindIntegration)
};
}
#endif

470
main.cpp
View File

@ -26,7 +26,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "options.h"
#include "sm.h"
#include "workspace.h"
#include "xcbutils.h"
// KDE
#include <KAboutData>
@ -48,9 +47,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <QStandardPaths>
#include <QVBoxLayout>
#include <QtDBus/QtDBus>
#include <QX11Info>
// TODO: remove once QX11Info provides the X screen
#include <X11/Xlib.h>
// system
#ifdef HAVE_UNISTD_H
@ -71,68 +67,6 @@ Atoms* atoms;
int screen_number = -1;
bool is_multihead = false;
//************************************
// KWinSelectionOwner
//************************************
KWinSelectionOwner::KWinSelectionOwner(int screen_P)
: KSelectionOwner(make_selection_atom(screen_P), screen_P)
{
}
xcb_atom_t KWinSelectionOwner::make_selection_atom(int screen_P)
{
if (screen_P < 0)
screen_P = QX11Info::appScreen();
QByteArray screen(QByteArrayLiteral("WM_S"));
screen.append(QByteArray::number(screen_P));
ScopedCPointer<xcb_intern_atom_reply_t> atom(xcb_intern_atom_reply(
connection(),
xcb_intern_atom_unchecked(connection(), false, screen.length(), screen.constData()),
nullptr));
if (atom.isNull()) {
return XCB_ATOM_NONE;
}
return atom->atom;
}
void KWinSelectionOwner::getAtoms()
{
KSelectionOwner::getAtoms();
if (xa_version == XCB_ATOM_NONE) {
const QByteArray name(QByteArrayLiteral("VERSION"));
ScopedCPointer<xcb_intern_atom_reply_t> atom(xcb_intern_atom_reply(
connection(),
xcb_intern_atom_unchecked(connection(), false, name.length(), name.constData()),
nullptr));
if (!atom.isNull()) {
xa_version = atom->atom;
}
}
}
void KWinSelectionOwner::replyTargets(xcb_atom_t property_P, xcb_window_t requestor_P)
{
KSelectionOwner::replyTargets(property_P, requestor_P);
xcb_atom_t atoms[ 1 ] = { xa_version };
// PropModeAppend !
xcb_change_property(connection(), XCB_PROP_MODE_APPEND, requestor_P,
property_P, XCB_ATOM_ATOM, 32, 1, atoms);
}
bool KWinSelectionOwner::genericReply(xcb_atom_t target_P, xcb_atom_t property_P, xcb_window_t requestor_P)
{
if (target_P == xa_version) {
int32_t version[] = { 2, 0 };
xcb_change_property(connection(), XCB_PROP_MODE_REPLACE, requestor_P,
property_P, XCB_ATOM_INTEGER, 32, 2, version);
} else
return KSelectionOwner::genericReply(target_P, property_P, requestor_P);
return true;
}
xcb_atom_t KWinSelectionOwner::xa_version = XCB_ATOM_NONE;
class AlternativeWMDialog : public QDialog
{
public:
@ -181,13 +115,31 @@ private:
int Application::crashes = 0;
Application::Application(int &argc, char **argv)
bool Application::isX11MultiHead()
{
return is_multihead;
}
void Application::setX11MultiHead(bool multiHead)
{
is_multihead = multiHead;
}
void Application::setX11ScreenNumber(int screenNumber)
{
screen_number = screenNumber;
}
int Application::x11ScreenNumber()
{
return screen_number;
}
Application::Application(Application::OperationMode mode, int &argc, char **argv)
: QApplication(argc, argv)
, owner()
, m_eventFilter(new XcbEventFilter())
, m_replace(false)
, m_configLock(false)
, m_operationMode(OperationModeX11)
, m_operationMode(mode)
{
}
@ -196,11 +148,6 @@ void Application::setConfigLock(bool lock)
m_configLock = lock;
}
void Application::setReplace(bool replace)
{
m_replace = replace;
}
Application::OperationMode Application::operationMode() const
{
return m_operationMode;
@ -232,67 +179,13 @@ void Application::start()
config->reparseConfiguration();
}
if (screen_number == -1)
screen_number = QX11Info::appScreen();
owner.reset(new KWinSelectionOwner(screen_number));
connect(owner.data(), &KSelectionOwner::failedToClaimOwnership, []{
fputs(i18n("kwin: unable to claim manager selection, another wm running? (try using --replace)\n").toLocal8Bit().constData(), stderr);
::exit(1);
});
connect(owner.data(), SIGNAL(lostOwnership()), SLOT(lostSelection()));
connect(owner.data(), &KSelectionOwner::claimedOwnership, [this]{
// we want all QQuickWindows with an alpha buffer
QQuickWindow::setDefaultAlphaBuffer(true);
installNativeEventFilter(m_eventFilter.data());
// first load options - done internally by a different thread
options = new Options;
// Check whether another windowmanager is running
const uint32_t maskValues[] = {XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT};
ScopedCPointer<xcb_generic_error_t> redirectCheck(xcb_request_check(connection(),
xcb_change_window_attributes_checked(connection(),
rootWindow(),
XCB_CW_EVENT_MASK,
maskValues)));
if (!redirectCheck.isNull()) {
fputs(i18n("kwin: another window manager is running (try using --replace)\n").toLocal8Bit().constData(), stderr);
::exit(1);
}
atoms->retrieveHelpers();
// This tries to detect compositing options and can use GLX. GLX problems
// (X errors) shouldn't cause kwin to abort, so this is out of the
// critical startup section where x errors cause kwin to abort.
// create workspace.
(void) new Workspace(isSessionRestored());
Xcb::sync(); // Trigger possible errors, there's still a chance to abort
// Tell KSplash that KWin has started
QDBusMessage ksplashProgressMessage = QDBusMessage::createMethodCall(QStringLiteral("org.kde.KSplash"),
QStringLiteral("/KSplash"),
QStringLiteral("org.kde.KSplash"),
QStringLiteral("setStage"));
ksplashProgressMessage.setArguments(QList<QVariant>() << QStringLiteral("wm"));
QDBusConnection::sessionBus().asyncCall(ksplashProgressMessage);
});
crashChecking();
// we need to do an XSync here, otherwise the QPA might crash us later on
Xcb::sync();
owner->claim(m_replace, true);
atoms = new Atoms;
performStartup();
}
Application::~Application()
{
delete Workspace::self();
if (!owner.isNull() && owner->ownerWindow() != XCB_WINDOW_NONE) // If there was no --replace (no new WM)
Xcb::setInputFocus(XCB_INPUT_FOCUS_POINTER_ROOT);
delete options;
delete atoms;
}
@ -328,15 +221,6 @@ void Application::crashChecking()
QTimer::singleShot(15 * 1000, this, SLOT(resetCrashesCount()));
}
void Application::lostSelection()
{
sendPostedEvents();
delete Workspace::self();
// Remove windowmanager privileges
Xcb::selectInput(rootWindow(), XCB_EVENT_MASK_PROPERTY_CHANGE);
quit();
}
bool Application::notify(QObject* o, QEvent* e)
{
if (Workspace::self()->workspaceEvent(e))
@ -344,11 +228,6 @@ bool Application::notify(QObject* o, QEvent* e)
return QApplication::notify(o, e);
}
static void sighandler(int)
{
QApplication::exit();
}
void Application::crashHandler(int signal)
{
crashes++;
@ -377,26 +256,68 @@ bool Application::wasCrash()
return crashes > 0;
}
bool XcbEventFilter::nativeEventFilter(const QByteArray &eventType, void *message, long int *result)
{
Q_UNUSED(result)
if (!Workspace::self()) {
// Workspace not yet created
return false;
}
if (eventType != "xcb_generic_event_t") {
return false;
}
return Workspace::self()->workspaceEvent(static_cast<xcb_generic_event_t *>(message));
}
} // namespace
static const char version[] = KWIN_VERSION_STRING;
static const char description[] = I18N_NOOP("KDE window manager");
extern "C"
KWIN_EXPORT int kdemain(int argc, char * argv[])
void Application::createAboutData()
{
KAboutData aboutData(QStringLiteral(KWIN_NAME), // The program name used internally
i18n("KWin"), // A displayable program name string
QStringLiteral(KWIN_VERSION_STRING), // The program version string
i18n(description), // Short description of what the app does
KAboutLicense::GPL, // The license this code is released under
i18n("(c) 1999-2013, The KDE Developers")); // Copyright Statement
aboutData.addAuthor(i18n("Matthias Ettrich"), QString(), QStringLiteral("ettrich@kde.org"));
aboutData.addAuthor(i18n("Cristian Tibirna"), QString(), QStringLiteral("tibirna@kde.org"));
aboutData.addAuthor(i18n("Daniel M. Duley"), QString(), QStringLiteral("mosfet@kde.org"));
aboutData.addAuthor(i18n("Luboš Luňák"), QString(), QStringLiteral("l.lunak@kde.org"));
aboutData.addAuthor(i18n("Martin Gräßlin"), i18n("Maintainer"), QStringLiteral("mgraesslin@kde.org"));
KAboutData::setApplicationData(aboutData);
}
static const QString s_lockOption = QStringLiteral("lock");
static const QString s_crashesOption = QStringLiteral("crashes");
void Application::setupCommandLine(QCommandLineParser *parser)
{
QCommandLineOption lockOption(s_lockOption, i18n("Disable configuration options"));
QCommandLineOption crashesOption(s_crashesOption, i18n("Indicate that KWin has recently crashed n times"), QStringLiteral("n"));
parser->setApplicationDescription(i18n("KDE window manager"));
parser->addVersionOption();
parser->addHelpOption();
parser->addOption(lockOption);
parser->addOption(crashesOption);
KAboutData::applicationData().setupCommandLine(parser);
}
void Application::processCommandLine(QCommandLineParser *parser)
{
setConfigLock(parser->isSet(s_lockOption));
Application::setCrashCount(parser->value(s_crashesOption).toInt());
}
void Application::registerDBusService()
{
QString appname;
if (x11ScreenNumber() == 0)
appname = QStringLiteral("org.kde.kwin");
else
appname.sprintf("org.kde.kwin-screen-%d", KWin::Application::x11ScreenNumber());
QDBusConnection::sessionBus().interface()->registerService(
appname, QDBusConnectionInterface::DontQueueService);
}
void Application::setupTranslator()
{
QTranslator qtTranslator;
qtTranslator.load("qt_" + QLocale::system().name(),
QLibraryInfo::location(QLibraryInfo::TranslationsPath));
installTranslator(&qtTranslator);
}
void Application::setupMalloc()
{
#ifdef M_TRIM_THRESHOLD
// Prevent fragmentation of the heap by malloc (glibc).
@ -412,146 +333,91 @@ KWIN_EXPORT int kdemain(int argc, char * argv[])
#endif // HAVE_UNISTD_H
mallopt(M_TRIM_THRESHOLD, 5*pagesize);
#endif // M_TRIM_THRESHOLD
KLocalizedString::setApplicationDomain("kwin");
QLoggingCategory::setFilterRules(QStringLiteral("aurorae.debug = true\n") +
QStringLiteral("kwineffects.debug = true"));
int primaryScreen = 0;
xcb_connection_t *c = xcb_connect(nullptr, &primaryScreen);
if (!c || xcb_connection_has_error(c)) {
fprintf(stderr, "%s: FATAL ERROR while trying to open display %s\n",
argv[0], qgetenv("DISPLAY").constData());
exit(1);
}
const int number_of_screens = xcb_setup_roots_length(xcb_get_setup(c));
// multi head
auto isMultiHead = []() -> bool {
QByteArray multiHead = qgetenv("KDE_MULTIHEAD");
if (!multiHead.isEmpty()) {
return (multiHead.toLower() == "true");
}
return true;
};
if (number_of_screens != 1 && isMultiHead()) {
KWin::is_multihead = true;
KWin::screen_number = primaryScreen;
int pos; // Temporarily needed to reconstruct DISPLAY var if multi-head
QByteArray display_name = qgetenv("DISPLAY");
xcb_disconnect(c);
c = nullptr;
if ((pos = display_name.lastIndexOf('.')) != -1)
display_name.remove(pos, 10); // 10 is enough to be sure we removed ".s"
QString envir;
for (int i = 0; i < number_of_screens; i++) {
// If execution doesn't pass by here, then kwin
// acts exactly as previously
if (i != KWin::screen_number && fork() == 0) {
KWin::screen_number = i;
// Break here because we are the child process, we don't
// want to fork() anymore
break;
}
}
// In the next statement, display_name shouldn't contain a screen
// number. If it had it, it was removed at the "pos" check
envir.sprintf("DISPLAY=%s.%d", display_name.data(), KWin::screen_number);
if (putenv(strdup(envir.toAscii().constData()))) {
fprintf(stderr, "%s: WARNING: unable to set DISPLAY environment variable\n", argv[0]);
perror("putenv()");
}
}
if (signal(SIGTERM, KWin::sighandler) == SIG_IGN)
signal(SIGTERM, SIG_IGN);
if (signal(SIGINT, KWin::sighandler) == SIG_IGN)
signal(SIGINT, SIG_IGN);
if (signal(SIGHUP, KWin::sighandler) == SIG_IGN)
signal(SIGHUP, SIG_IGN);
// Disable the glib event loop integration, since it seems to be responsible
// for several bug reports about high CPU usage (bug #239963)
setenv("QT_NO_GLIB", "1", true);
// enforce xcb plugin, unfortunately command line switch has precedence
setenv("QT_QPA_PLATFORM", "xcb", true);
KWin::Application a(argc, argv);
QTranslator qtTranslator;
qtTranslator.load("qt_" + QLocale::system().name(),
QLibraryInfo::location(QLibraryInfo::TranslationsPath));
a.installTranslator(&qtTranslator);
KAboutData aboutData(QStringLiteral(KWIN_NAME), // The program name used internally
i18n("KWin"), // A displayable program name string
QStringLiteral(KWIN_VERSION_STRING), // The program version string
i18n(description), // Short description of what the app does
KAboutLicense::GPL, // The license this code is released under
i18n("(c) 1999-2013, The KDE Developers")); // Copyright Statement
aboutData.addAuthor(i18n("Matthias Ettrich"), QString(), QStringLiteral("ettrich@kde.org"));
aboutData.addAuthor(i18n("Cristian Tibirna"), QString(), QStringLiteral("tibirna@kde.org"));
aboutData.addAuthor(i18n("Daniel M. Duley"), QString(), QStringLiteral("mosfet@kde.org"));
aboutData.addAuthor(i18n("Luboš Luňák"), QString(), QStringLiteral("l.lunak@kde.org"));
aboutData.addAuthor(i18n("Martin Gräßlin"), i18n("Maintainer"), QStringLiteral("mgraesslin@kde.org"));
KAboutData::setApplicationData(aboutData);
QCommandLineOption lockOption(QStringLiteral("lock"), i18n("Disable configuration options"));
QCommandLineOption replaceOption(QStringLiteral("replace"), i18n("Replace already-running ICCCM2.0-compliant window manager"));
QCommandLineOption crashesOption(QStringLiteral("crashes"), i18n("Indicate that KWin has recently crashed n times"), QStringLiteral("n"));
QCommandLineParser parser;
parser.setApplicationDescription(i18n("KDE window manager"));
parser.addVersionOption();
parser.addHelpOption();
parser.addOption(lockOption);
parser.addOption(replaceOption);
parser.addOption(crashesOption);
aboutData.setupCommandLine(&parser);
parser.process(a);
aboutData.processCommandLine(&parser);
KWin::Application::setCrashCount(parser.value(crashesOption).toInt());
a.setConfigLock(parser.isSet(lockOption));
a.setReplace(parser.isSet(replaceOption));
// perform sanity checks
if (a.platformName().toLower() != QStringLiteral("xcb")) {
fprintf(stderr, "%s: FATAL ERROR expecting platform xcb but got platform %s\n",
argv[0], qPrintable(a.platformName()));
exit(1);
}
if (!KWin::display()) {
fprintf(stderr, "%s: FATAL ERROR KWin requires Xlib support in the xcb plugin. Do not configure Qt with -no-xcb-xlib\n",
argv[0]);
exit(1);
}
a.start();
#warning SessionManager needs porting
#if KWIN_QT5_PORTING
KWin::SessionManager weAreIndeed;
#endif
KWin::SessionSaveDoneHelper helper;
QString appname;
if (KWin::screen_number == 0)
appname = QStringLiteral("org.kde.kwin");
else
appname.sprintf("org.kde.kwin-screen-%d", KWin::screen_number);
QDBusConnection::sessionBus().interface()->registerService(
appname, QDBusConnectionInterface::DontQueueService);
return a.exec();
}
void Application::setupLocalizedString()
{
KLocalizedString::setApplicationDomain("kwin");
}
void Application::setupLoggingCategoryFilters()
{
QLoggingCategory::setFilterRules(QStringLiteral("aurorae.debug = true\n") +
QStringLiteral("kwineffects.debug = true"));
}
void Application::notifyKSplash()
{
// Tell KSplash that KWin has started
QDBusMessage ksplashProgressMessage = QDBusMessage::createMethodCall(QStringLiteral("org.kde.KSplash"),
QStringLiteral("/KSplash"),
QStringLiteral("org.kde.KSplash"),
QStringLiteral("setStage"));
ksplashProgressMessage.setArguments(QList<QVariant>() << QStringLiteral("wm"));
QDBusConnection::sessionBus().asyncCall(ksplashProgressMessage);
}
void Application::createWorkspace()
{
// ensure the helper atoms are retrieved before we create the Workspace
atoms->retrieveHelpers();
// we want all QQuickWindows with an alpha buffer, do here as Workspace might create QQuickWindows
QQuickWindow::setDefaultAlphaBuffer(true);
// This tries to detect compositing options and can use GLX. GLX problems
// (X errors) shouldn't cause kwin to abort, so this is out of the
// critical startup section where x errors cause kwin to abort.
// create workspace.
(void) new Workspace(isSessionRestored());
}
void Application::createAtoms()
{
atoms = new Atoms;
}
void Application::createOptions()
{
options = new Options;
}
void Application::setupEventFilters()
{
installNativeEventFilter(m_eventFilter.data());
}
void Application::destroyWorkspace()
{
delete Workspace::self();
}
bool XcbEventFilter::nativeEventFilter(const QByteArray &eventType, void *message, long int *result)
{
Q_UNUSED(result)
if (!Workspace::self()) {
// Workspace not yet created
return false;
}
if (eventType != "xcb_generic_event_t") {
return false;
}
return Workspace::self()->workspaceEvent(static_cast<xcb_generic_event_t *>(message));
}
static bool s_useLibinput = false;
void Application::setUseLibinput(bool use)
{
s_useLibinput = use;
}
bool Application::usesLibinput()
{
return s_useLibinput;
}
} // namespace
#include "main.moc"

75
main.h
View File

@ -22,12 +22,17 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef MAIN_H
#define MAIN_H
#include <kwinglobals.h>
#include <config-kwin.h>
#include <KSelectionWatcher>
#include <KSelectionOwner>
// Qt
#include <QApplication>
#include <QAbstractNativeEventFilter>
class QCommandLineParser;
namespace KWin
{
@ -37,22 +42,7 @@ public:
virtual bool nativeEventFilter(const QByteArray &eventType, void *message, long int *result) override;
};
class KWinSelectionOwner
: public KSelectionOwner
{
Q_OBJECT
public:
explicit KWinSelectionOwner(int screen);
protected:
virtual bool genericReply(xcb_atom_t target, xcb_atom_t property, xcb_window_t requestor);
virtual void replyTargets(xcb_atom_t property, xcb_window_t requestor);
virtual void getAtoms();
private:
xcb_atom_t make_selection_atom(int screen);
static xcb_atom_t xa_version;
};
class Application : public QApplication
class KWIN_EXPORT Application : public QApplication
{
Q_OBJECT
public:
@ -73,10 +63,8 @@ public:
*/
OperationModeWaylandAndX11
};
Application(int &argc, char **argv);
~Application();
virtual ~Application();
void setReplace(bool replace);
void setConfigLock(bool lock);
void start();
@ -90,22 +78,65 @@ public:
bool shouldUseWaylandForCompositing() const;
bool requiresCompositing() const;
void setupTranslator();
void setupCommandLine(QCommandLineParser *parser);
void processCommandLine(QCommandLineParser *parser);
void registerDBusService();
static void setCrashCount(int count);
static bool wasCrash();
/**
* Creates the KAboutData object for the KWin instance and registers it as
* KAboutData::setApplicationData.
**/
static void createAboutData();
/**
* @returns the X11 Screen number. If not applicable it's set to @c -1.
**/
static int x11ScreenNumber();
/**
* Sets the X11 screen number of this KWin instance to @p screenNumber.
**/
static void setX11ScreenNumber(int screenNumber);
/**
* @returns whether this is a multi head setup on X11.
**/
static bool isX11MultiHead();
/**
* Sets whether this is a multi head setup on X11.
*/
static void setX11MultiHead(bool multiHead);
static void setupMalloc();
static void setupLocalizedString();
static void setupLoggingCategoryFilters();
static bool usesLibinput();
static void setUseLibinput(bool use);
protected:
Application(OperationMode mode, int &argc, char **argv);
virtual void performStartup() = 0;
void notifyKSplash();
void createWorkspace();
void createAtoms();
void createOptions();
void setupEventFilters();
void destroyWorkspace();
bool notify(QObject* o, QEvent* e);
static void crashHandler(int signal);
private Q_SLOTS:
void lostSelection();
void resetCrashesCount();
private:
void crashChecking();
QScopedPointer<KWinSelectionOwner> owner;
QScopedPointer<XcbEventFilter> m_eventFilter;
bool m_replace;
bool m_configLock;
OperationMode m_operationMode;
static int crashes;

273
main_wayland.cpp Normal file
View File

@ -0,0 +1,273 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2014 Martin Gräßlin <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 "main_wayland.h"
#include <config-kwin.h>
// kwin
#include "wayland_backend.h"
#include "xcbutils.h"
// KDE
#include <KLocalizedString>
// Qt
#include <qplatformdefs.h>
#include <QCommandLineParser>
#include <QFile>
// system
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif // HAVE_UNISTD_H
#include <iostream>
namespace KWin
{
static void sighandler(int)
{
QApplication::exit();
}
//************************************
// ApplicationWayland
//************************************
ApplicationWayland::ApplicationWayland(int &argc, char **argv)
: Application(OperationModeWaylandAndX11, argc, argv)
{
}
ApplicationWayland::~ApplicationWayland()
{
destroyWorkspace();
delete Wayland::WaylandBackend::self();
// TODO: only if we support X11
Xcb::setInputFocus(XCB_INPUT_FOCUS_POINTER_ROOT);
}
void ApplicationWayland::performStartup()
{
// we don't support X11 multi-head in Wayland
Application::setX11ScreenNumber(0);
// we need to do an XSync here, otherwise the QPA might crash us later on
// TODO: remove
Xcb::sync();
createAtoms();
setupEventFilters();
// first load options - done internally by a different thread
createOptions();
// Check whether another windowmanager is running
const uint32_t maskValues[] = {XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT};
ScopedCPointer<xcb_generic_error_t> redirectCheck(xcb_request_check(connection(),
xcb_change_window_attributes_checked(connection(),
rootWindow(),
XCB_CW_EVENT_MASK,
maskValues)));
if (!redirectCheck.isNull()) {
fputs(i18n("kwin_wayland: an X11 window manager is running on the X11 Display.\n").toLocal8Bit().constData(), stderr);
::exit(1);
}
// try creating the Wayland Backend
Wayland::WaylandBackend *backend = Wayland::WaylandBackend::create();
connect(backend, &Wayland::WaylandBackend::connectionFailed, this,
[] () {
fputs(i18n("kwin_wayland: could not connect to Wayland Server, ensure WAYLAND_DISPLAY is set.\n").toLocal8Bit().constData(), stderr);
::exit(1);
}
);
createWorkspace();
Xcb::sync(); // Trigger possible errors, there's still a chance to abort
notifyKSplash();
}
/**
* Starts the X-Server with binary name @p process on @p display.
* The new process is started by forking into it.
**/
static void startXServer(const QByteArray &process, const QByteArray &display)
{
int pipeFds[2];
if (pipe(pipeFds) != 0) {
std::cerr << "FATAL ERROR failed to create pipe to start X Server "
<< process.constData()
<< " with arguments "
<< display.constData()
<< std::endl;
exit(1);
}
pid_t pid = fork();
if (pid == 0) {
// child process - should be turned into X-Server
// writes to pipe, closes read side
close(pipeFds[0]);
char fdbuf[16];
sprintf(fdbuf, "%d", pipeFds[1]);
execlp(process.constData(), process.constData(), "-displayfd", fdbuf, display.constData(), (char *)0);
close(pipeFds[1]);
exit(20);
}
// parent process - this is KWin
// reads from pipe, closes write side
close(pipeFds[1]);
QFile readPipe;
if (!readPipe.open(pipeFds[0], QIODevice::ReadOnly)) {
std::cerr << "FATAL ERROR failed to open pipe to start X Server "
<< process.constData()
<< " with arguments "
<< display.constData()
<< std::endl;
exit(1);
}
QByteArray displayNumber = readPipe.readLine();
displayNumber.prepend(QByteArray(":"));
displayNumber.remove(displayNumber.size() -1, 1);
std::cout << "X-Server started on display " << displayNumber.constData();
setenv("DISPLAY", displayNumber.constData(), true);
// close our pipe
close(pipeFds[0]);
}
} // namespace
extern "C"
KWIN_EXPORT int kdemain(int argc, char * argv[])
{
// process command line arguments to figure out whether we have to start an X-Server
bool startXephyr = false;
bool startXvfb = false;
bool startXwayland = false;
QByteArray xDisplay;
QByteArray xServer;
for (int i = 1; i < argc; ++i) {
QByteArray arg = argv[i];
if (arg == "-x" || arg == "--start-X-Server") {
if (++i < argc) {
xServer = argv[i];
}
startXephyr = (xServer == QStringLiteral("xephyr"));
startXvfb = (xServer == QStringLiteral("xvfb"));
startXwayland = (xServer == QStringLiteral("xwayland"));
if (!startXephyr && !startXvfb && !startXwayland) {
fprintf(stderr, "%s: FATAL ERROR unknown X-Server %s specified to start\n",
argv[0], qPrintable(xServer));
exit(1);
}
continue;
}
if (arg == "--display") {
if (++i < argc) {
xDisplay = argv[i];
}
}
}
if (startXephyr) {
KWin::startXServer(QByteArrayLiteral("Xephyr"), xDisplay);
}
if (startXvfb) {
KWin::startXServer(QByteArrayLiteral("Xvfb"), xDisplay);
}
if (startXwayland) {
KWin::startXServer(QByteArrayLiteral("Xwayland"), xDisplay);
}
KWin::Application::setupMalloc();
KWin::Application::setupLocalizedString();
KWin::Application::setupLoggingCategoryFilters();
// TODO: check whether we have a wayland connection
// Disable the glib event loop integration, since it seems to be responsible
// for several bug reports about high CPU usage (bug #239963)
setenv("QT_NO_GLIB", "1", true);
// enforce xcb plugin, unfortunately command line switch has precedence
// TODO: ensure it's not xcb once we support the Wayland QPA
setenv("QT_QPA_PLATFORM", "xcb", true);
if (signal(SIGTERM, KWin::sighandler) == SIG_IGN)
signal(SIGTERM, SIG_IGN);
if (signal(SIGINT, KWin::sighandler) == SIG_IGN)
signal(SIGINT, SIG_IGN);
if (signal(SIGHUP, KWin::sighandler) == SIG_IGN)
signal(SIGHUP, SIG_IGN);
KWin::ApplicationWayland a(argc, argv);
a.setupTranslator();
KWin::Application::createAboutData();
QCommandLineOption startXServerOption(QStringList({QStringLiteral("x"), QStringLiteral("x-server")}),
i18n("Start a nested X Server."),
QStringLiteral("xephyr|xvfb|xwayland"));
QCommandLineOption x11DisplayOption(QStringLiteral("display"),
i18n("The X11 Display to connect to, required if option x-server is used."),
QStringLiteral("display"));
QCommandLineParser parser;
a.setupCommandLine(&parser);
parser.addOption(startXServerOption);
parser.addOption(x11DisplayOption);
#if HAVE_INPUT
QCommandLineOption libinputOption(QStringLiteral("libinput"),
i18n("Enable libinput support for input events processing. Note: never use in a nested session."));
parser.addOption(libinputOption);
#endif
parser.process(a);
a.processCommandLine(&parser);
#if HAVE_INPUT
KWin::Application::setUseLibinput(parser.isSet(libinputOption));
#endif
// perform sanity checks
// TODO: remove those two
if (a.platformName().toLower() != QStringLiteral("xcb")) {
fprintf(stderr, "%s: FATAL ERROR expecting platform xcb but got platform %s\n",
argv[0], qPrintable(a.platformName()));
exit(1);
}
if (!KWin::display()) {
fprintf(stderr, "%s: FATAL ERROR KWin requires Xlib support in the xcb plugin. Do not configure Qt with -no-xcb-xlib\n",
argv[0]);
exit(1);
}
a.start();
// TODO: is this still needed?
a.registerDBusService();
return a.exec();
}

40
main_wayland.h Normal file
View File

@ -0,0 +1,40 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2014 Martin Gräßlin <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/>.
*********************************************************************/
#ifndef KWIN_MAIN_WAYLAND_H
#define KWIN_MAIN_WAYLAND_H
#include "main.h"
namespace KWin
{
class ApplicationWayland : public Application
{
Q_OBJECT
public:
ApplicationWayland(int &argc, char **argv);
virtual ~ApplicationWayland();
protected:
void performStartup() override;
};
}
#endif

295
main_x11.cpp Normal file
View File

@ -0,0 +1,295 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 1999, 2000 Matthias Ettrich <ettrich@kde.org>
Copyright (C) 2003 Lubos Lunak <l.lunak@kde.org>
Copyright (C) 2014 Martin Gräßlin <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 "main_x11.h"
#include <config-kwin.h>
// kwin
#include "sm.h"
#include "xcbutils.h"
// KDE
#include <KLocalizedString>
// Qt
#include <qplatformdefs.h>
#include <QCommandLineParser>
// system
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif // HAVE_UNISTD_H
namespace KWin
{
static void sighandler(int)
{
QApplication::exit();
}
//************************************
// KWinSelectionOwner
//************************************
KWinSelectionOwner::KWinSelectionOwner(int screen_P)
: KSelectionOwner(make_selection_atom(screen_P), screen_P)
{
}
xcb_atom_t KWinSelectionOwner::make_selection_atom(int screen_P)
{
if (screen_P < 0)
screen_P = QX11Info::appScreen();
QByteArray screen(QByteArrayLiteral("WM_S"));
screen.append(QByteArray::number(screen_P));
ScopedCPointer<xcb_intern_atom_reply_t> atom(xcb_intern_atom_reply(
connection(),
xcb_intern_atom_unchecked(connection(), false, screen.length(), screen.constData()),
nullptr));
if (atom.isNull()) {
return XCB_ATOM_NONE;
}
return atom->atom;
}
void KWinSelectionOwner::getAtoms()
{
KSelectionOwner::getAtoms();
if (xa_version == XCB_ATOM_NONE) {
const QByteArray name(QByteArrayLiteral("VERSION"));
ScopedCPointer<xcb_intern_atom_reply_t> atom(xcb_intern_atom_reply(
connection(),
xcb_intern_atom_unchecked(connection(), false, name.length(), name.constData()),
nullptr));
if (!atom.isNull()) {
xa_version = atom->atom;
}
}
}
void KWinSelectionOwner::replyTargets(xcb_atom_t property_P, xcb_window_t requestor_P)
{
KSelectionOwner::replyTargets(property_P, requestor_P);
xcb_atom_t atoms[ 1 ] = { xa_version };
// PropModeAppend !
xcb_change_property(connection(), XCB_PROP_MODE_APPEND, requestor_P,
property_P, XCB_ATOM_ATOM, 32, 1, atoms);
}
bool KWinSelectionOwner::genericReply(xcb_atom_t target_P, xcb_atom_t property_P, xcb_window_t requestor_P)
{
if (target_P == xa_version) {
int32_t version[] = { 2, 0 };
xcb_change_property(connection(), XCB_PROP_MODE_REPLACE, requestor_P,
property_P, XCB_ATOM_INTEGER, 32, 2, version);
} else
return KSelectionOwner::genericReply(target_P, property_P, requestor_P);
return true;
}
xcb_atom_t KWinSelectionOwner::xa_version = XCB_ATOM_NONE;
//************************************
// ApplicationX11
//************************************
ApplicationX11::ApplicationX11(int &argc, char **argv)
: Application(OperationModeX11, argc, argv)
, owner()
, m_replace(false)
{
}
ApplicationX11::~ApplicationX11()
{
destroyWorkspace();
if (!owner.isNull() && owner->ownerWindow() != XCB_WINDOW_NONE) // If there was no --replace (no new WM)
Xcb::setInputFocus(XCB_INPUT_FOCUS_POINTER_ROOT);
}
void ApplicationX11::setReplace(bool replace)
{
m_replace = replace;
}
void ApplicationX11::lostSelection()
{
sendPostedEvents();
destroyWorkspace();
// Remove windowmanager privileges
Xcb::selectInput(rootWindow(), XCB_EVENT_MASK_PROPERTY_CHANGE);
quit();
}
void ApplicationX11::performStartup()
{
if (Application::x11ScreenNumber() == -1) {
Application::setX11ScreenNumber(QX11Info::appScreen());
}
owner.reset(new KWinSelectionOwner(Application::x11ScreenNumber()));
connect(owner.data(), &KSelectionOwner::failedToClaimOwnership, []{
fputs(i18n("kwin: unable to claim manager selection, another wm running? (try using --replace)\n").toLocal8Bit().constData(), stderr);
::exit(1);
});
connect(owner.data(), SIGNAL(lostOwnership()), SLOT(lostSelection()));
connect(owner.data(), &KSelectionOwner::claimedOwnership, [this]{
setupEventFilters();
// first load options - done internally by a different thread
createOptions();
// Check whether another windowmanager is running
const uint32_t maskValues[] = {XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT};
ScopedCPointer<xcb_generic_error_t> redirectCheck(xcb_request_check(connection(),
xcb_change_window_attributes_checked(connection(),
rootWindow(),
XCB_CW_EVENT_MASK,
maskValues)));
if (!redirectCheck.isNull()) {
fputs(i18n("kwin: another window manager is running (try using --replace)\n").toLocal8Bit().constData(), stderr);
::exit(1);
}
createWorkspace();
Xcb::sync(); // Trigger possible errors, there's still a chance to abort
notifyKSplash();
});
// we need to do an XSync here, otherwise the QPA might crash us later on
Xcb::sync();
owner->claim(m_replace, true);
createAtoms();
}
} // namespace
extern "C"
KWIN_EXPORT int kdemain(int argc, char * argv[])
{
KWin::Application::setupMalloc();
KWin::Application::setupLocalizedString();
KWin::Application::setupLoggingCategoryFilters();
int primaryScreen = 0;
xcb_connection_t *c = xcb_connect(nullptr, &primaryScreen);
if (!c || xcb_connection_has_error(c)) {
fprintf(stderr, "%s: FATAL ERROR while trying to open display %s\n",
argv[0], qgetenv("DISPLAY").constData());
exit(1);
}
const int number_of_screens = xcb_setup_roots_length(xcb_get_setup(c));
// multi head
auto isMultiHead = []() -> bool {
QByteArray multiHead = qgetenv("KDE_MULTIHEAD");
if (!multiHead.isEmpty()) {
return (multiHead.toLower() == "true");
}
return true;
};
if (number_of_screens != 1 && isMultiHead()) {
KWin::Application::setX11MultiHead(true);
KWin::Application::setX11ScreenNumber(primaryScreen);
int pos; // Temporarily needed to reconstruct DISPLAY var if multi-head
QByteArray display_name = qgetenv("DISPLAY");
xcb_disconnect(c);
c = nullptr;
if ((pos = display_name.lastIndexOf('.')) != -1)
display_name.remove(pos, 10); // 10 is enough to be sure we removed ".s"
QString envir;
for (int i = 0; i < number_of_screens; i++) {
// If execution doesn't pass by here, then kwin
// acts exactly as previously
if (i != KWin::Application::x11ScreenNumber() && fork() == 0) {
KWin::Application::setX11ScreenNumber(i);
// Break here because we are the child process, we don't
// want to fork() anymore
break;
}
}
// In the next statement, display_name shouldn't contain a screen
// number. If it had it, it was removed at the "pos" check
envir.sprintf("DISPLAY=%s.%d", display_name.data(), KWin::Application::x11ScreenNumber());
if (putenv(strdup(envir.toAscii().constData()))) {
fprintf(stderr, "%s: WARNING: unable to set DISPLAY environment variable\n", argv[0]);
perror("putenv()");
}
}
if (signal(SIGTERM, KWin::sighandler) == SIG_IGN)
signal(SIGTERM, SIG_IGN);
if (signal(SIGINT, KWin::sighandler) == SIG_IGN)
signal(SIGINT, SIG_IGN);
if (signal(SIGHUP, KWin::sighandler) == SIG_IGN)
signal(SIGHUP, SIG_IGN);
// Disable the glib event loop integration, since it seems to be responsible
// for several bug reports about high CPU usage (bug #239963)
setenv("QT_NO_GLIB", "1", true);
// enforce xcb plugin, unfortunately command line switch has precedence
setenv("QT_QPA_PLATFORM", "xcb", true);
KWin::ApplicationX11 a(argc, argv);
a.setupTranslator();
KWin::Application::createAboutData();
QCommandLineOption replaceOption(QStringLiteral("replace"), i18n("Replace already-running ICCCM2.0-compliant window manager"));
QCommandLineParser parser;
a.setupCommandLine(&parser);
parser.addOption(replaceOption);
parser.process(a);
a.processCommandLine(&parser);
a.setReplace(parser.isSet(replaceOption));
// perform sanity checks
if (a.platformName().toLower() != QStringLiteral("xcb")) {
fprintf(stderr, "%s: FATAL ERROR expecting platform xcb but got platform %s\n",
argv[0], qPrintable(a.platformName()));
exit(1);
}
if (!KWin::display()) {
fprintf(stderr, "%s: FATAL ERROR KWin requires Xlib support in the xcb plugin. Do not configure Qt with -no-xcb-xlib\n",
argv[0]);
exit(1);
}
a.start();
#warning SessionManager needs porting
#if KWIN_QT5_PORTING
KWin::SessionManager weAreIndeed;
#endif
KWin::SessionSaveDoneHelper helper;
// TODO: is this still needed?
a.registerDBusService();
return a.exec();
}

64
main_x11.h Normal file
View File

@ -0,0 +1,64 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2014 Martin Gräßlin <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/>.
*********************************************************************/
#ifndef KWIN_MAIN_X11_H
#define KWIN_MAIN_X11_H
#include "main.h"
namespace KWin
{
class KWinSelectionOwner
: public KSelectionOwner
{
Q_OBJECT
public:
explicit KWinSelectionOwner(int screen);
protected:
virtual bool genericReply(xcb_atom_t target, xcb_atom_t property, xcb_window_t requestor);
virtual void replyTargets(xcb_atom_t property, xcb_window_t requestor);
virtual void getAtoms();
private:
xcb_atom_t make_selection_atom(int screen);
static xcb_atom_t xa_version;
};
class ApplicationX11 : public Application
{
Q_OBJECT
public:
ApplicationX11(int &argc, char **argv);
virtual ~ApplicationX11();
void setReplace(bool replace);
protected:
void performStartup() override;
private Q_SLOTS:
void lostSelection();
private:
QScopedPointer<KWinSelectionOwner> owner;
bool m_replace;
};
}
#endif

Some files were not shown because too many files have changed in this diff Show More