Merge branch 'master' into kdecorations2
Conflicts: CMakeLists.txt paintredirector.cpp scene_opengl.h scene_qpainter.h scene_xrender.hicc-effect-5.14.5
commit
e32da9d9e0
106
CMakeLists.txt
106
CMakeLists.txt
|
@ -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 ###############
|
||||
|
||||
|
|
|
@ -846,7 +846,7 @@ void Client::startupIdChanged()
|
|||
|
||||
void Client::updateUrgency()
|
||||
{
|
||||
if (urgency)
|
||||
if (info->urgency())
|
||||
demandAttention();
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
#include "mock_client.h"
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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"
|
|
@ -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"
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
#include "mock_workspace.h"
|
42
client.cpp
42
client.cpp
|
@ -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
|
||||
|
|
4
client.h
4
client.h
|
@ -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;
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
project(aurorae)
|
||||
|
||||
add_subdirectory(src)
|
||||
#add_subdirectory(themes/example-deco)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 視窗裝飾
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -129,6 +129,7 @@ Comment[sr@latin]=Klasična tema poznata iz KDE‑a 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 以來的傳統主題
|
||||
|
|
|
@ -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."
|
||||
)
|
|
@ -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)
|
|
@ -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()) {
|
||||
|
|
22
composite.h
22
composite.h
|
@ -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)
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"));
|
||||
}
|
||||
|
|
|
@ -67,6 +67,9 @@ public Q_SLOTS: // METHODS
|
|||
|
||||
private Q_SLOTS:
|
||||
void becomeKWinService(const QString &service);
|
||||
|
||||
private:
|
||||
QString m_serviceName;
|
||||
};
|
||||
|
||||
class CompositorDBusInterface : public QObject
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]=登录时平滑淡入到桌面
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]=視窗最大化/回復時的動畫
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]=Анимација на клик мишем
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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:
|
||||
|
|
58
events.cpp
58
events.cpp
|
@ -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:
|
||||
|
|
390
glxbackend.cpp
390
glxbackend.cpp
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
31
glxbackend.h
31
glxbackend.h
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
99
input.cpp
99
input.cpp
|
@ -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
|
||||
|
|
3
input.h
3
input.h
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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Д ефекти,опенГЛ,Икс‑рендер,видео поставке,графички ефекти,ефекти површи
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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.<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 " - ". One set is specified as <i>base</i>+(<i>list</i>), where base are modifiers and list is a list of keys.<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 <i>base</i>+(<i>list</i>), where base are modifiers and list is a list of keys.<br>
|
||||
For example "<b>Shift+Alt+(123) Shift+Ctrl+(ABC)</b>" will first try <b>Shift+Alt+1</b>, then others with <b>Shift+Ctrl+C</b> as the last one.</string>
|
||||
</property>
|
||||
<property name="textFormat" >
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]=Συνέβη μια επαναφορά των γραφικών
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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 ###
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
/** @} */
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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
470
main.cpp
|
@ -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
75
main.h
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -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
|
|
@ -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();
|
||||
}
|
|
@ -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
Loading…
Reference in New Issue