Compare commits

..

34 Commits

Author SHA1 Message Date
eaac59ef13 Update version number for 5.24.6
GIT_SILENT
2022-07-11 10:17:41 +01:00
7f555ba9bd Mark required deps as required
BUG: 454912
(cherry picked from commit 34e7c90c2d)
2022-06-06 12:40:30 +02:00
a450e3b4b3 Update version number for 5.24.5
GIT_SILENT
2022-05-03 10:51:36 +01:00
2d00bfd62d Update version number for 5.24.4
GIT_SILENT
2022-03-29 11:47:55 +01:00
6c5072cb9e Update version number for 5.24.3
GIT_SILENT
2022-03-08 11:01:23 +00:00
5217d4cee6 Update version number for 5.24.2
GIT_SILENT
2022-02-22 11:36:14 +00:00
6107b5a296 Update version number for 5.24.1
GIT_SILENT
2022-02-15 12:07:47 +00:00
15a66e8960 Update version number for 5.24.0
GIT_SILENT
2022-02-03 12:13:36 +00:00
e557008b56 Update version number for 5.23.90
GIT_SILENT
2022-01-13 10:34:20 +00:00
80f6a629bb GIT_SILENT: add missing override 2021-10-27 13:43:28 +02:00
662afeba22 Update kf5 version requirement to 5.86
GIT_SILENT
2021-10-11 20:48:40 +01:00
3dac2dd012 Add FreeBSD CI 2021-10-07 01:27:09 +02:00
5b280a4602 Add Linux CI 2021-10-05 15:14:20 +02:00
eb6fb8ab13 Add .kde-ci.yml 2021-10-05 15:14:05 +02:00
06815f2817 Update version number for 5.23.80
GIT_SILENT
2021-09-16 10:34:01 +01:00
dc07e14630 Update version number for 5.22.90
GIT_SILENT
2021-09-16 09:21:32 +01:00
4a439143ba Fix a crash when creating views on the placeholder screen
When a compositor has no outputs listed Qt creates a dummy placeholder
QScreen object that does not represent a wl_output.

This should still be fixed in the clients to not create a view, it's
wasteful and probably will still have plenty of other bugs, hence the
giant warning, but it's still worth guarding.

CCBUG: 439096
2021-09-15 22:55:35 +00:00
331505a4d2 Explicitly set KDE_COMPILERSETTINGS_LEVEL 2021-08-24 22:41:46 +02:00
f6084b2c43 Fix compile with last ecm.
("we have disabled the C and C++ specific compiler extensions.")
2021-06-28 07:51:57 +02:00
9af3c35020 Mark .gitignore file as non-copyrightable 2021-05-21 15:35:56 +02:00
525fa9b819 Update version number for 5.22.80
GIT_SILENT
2021-05-13 15:09:54 +01:00
1021ca5ab5 Update version number for 5.21.90
GIT_SILENT
2021-05-13 10:21:51 +01:00
204eeaf1c9 Update kf5 version requirement to 5.82
GIT_SILENT
2021-05-13 09:56:28 +01:00
42a87ad728 Update .gitignore 2021-05-09 17:54:28 +00:00
7d46bd63c5 Port away from ECMSetupVersion's deprecated *_VERSION_STRING CMake variable
GIT_SILENT
2021-05-04 23:35:44 +02:00
710152a7f3 GIT_SILENT Add auto generated files to .gitignore 2021-05-03 14:54:12 +02:00
8d1aeb7bf1 Store QWaylandLayerShell using a QScopedPointer
This is to ensure that the QWaylandLayerShell will be eventually
destroyed.
2021-04-20 16:02:33 +00:00
93f3ed2c07 Fix a memory leak
The dynamically allocated QtWayland::zwlr_layer_shell_v1 object in
QWaylandLayerShellIntegration::registryLayer() isn't deleted anywhere.
2021-04-20 16:02:33 +00:00
efd32eed53 Add missing parenthesis
This is to make the compiler happier.
2021-04-20 18:38:24 +03:00
11a811061f Introduce KeyboardInteractivity enum 2021-04-20 15:27:43 +03:00
549f5ad682 Link against xkbcommon
Otherwise the build fails with missing xkbcommon headers
2021-04-15 20:46:25 +02:00
cd409ed50e Add width and height to test
This is needed if we are not anchoring to the full screen
2021-04-15 09:59:18 +01:00
2b1219cfdd Ensure we can set per-window properties before the intial commit
In the current implementation we cannot use a LayerShellQt before the
shell surface is created.

At the moment a shell surface is created, the constructor is run and
then QtWayland commits the current state. This means the compositor
configures the window before a client has any chance to set anchors or
margins.

This works whilst we're just being a simple fullscreen window, but won't
scale for plasmashell in the future.

This patch makes LayerShellQt::Window always creatable, and we can set
and cache properties before the platform window is created, just like
one can on QWindow and XDGShell properties.

This also makes it less potentially crashy as ::get always returns a
valid result, and
sets up the public API to be QML-able as an attached property in future.

Co-authored on Aleix's patch for the unit test
2021-04-15 09:58:57 +01:00
29d0078909 Ensure we can set per-window properties before the intial commit
In the current implementation we cannot use a LayerShellQt before the
shell surface is created.

At the moment a shell surface is created, the constructor is run and
then QtWayland commits the current state. This means the compositor
configures the window before a client has any chance to set anchors or
margins.

This works whilst we're just being a simple fullscreen window, but won't
scale for plasmashell in the future.

This patch makes LayerShellQt::Window always creatable, and we can set
and cache properties before the platform window is created, just like
one can on QWindow and XDGShell properties.

This also makes it less potentially crashy as ::get always returns a
valid result, and
sets up the public API to be QML-able as an attached property in future.

Co-authored on Aleix's patch for the unit test
2021-04-14 23:49:30 +01:00
17 changed files with 338 additions and 141 deletions

29
.gitignore vendored Normal file
View File

@ -0,0 +1,29 @@
# SPDX-License-Identifier: CC0-1.0
# SPDX-FileCopyrightText: none
# Ignore the following files
.vscode
*~
*.[oa]
*.diff
*.kate-swp
*.kdev4
.kdev_include_paths
*.kdevelop.pcs
*.moc
*.moc.cpp
*.orig
*.user
.*.swp
.swp.*
Doxyfile
Makefile
avail
random_seed
/build*/
CMakeLists.txt.user*
.clang-format
/compile_commands.json
.clangd
.idea
/cmake-build*
.cache

6
.gitlab-ci.yml Normal file
View File

@ -0,0 +1,6 @@
# SPDX-FileCopyrightText: None
# SPDX-License-Identifier: CC0-1.0
include:
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/linux.yml
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/freebsd.yml

7
.kde-ci.yml Normal file
View File

@ -0,0 +1,7 @@
# SPDX-FileCopyrightText: None
# SPDX-License-Identifier: CC0-1.0
Dependencies:
- 'on': ['@all']
'require':
'frameworks/extra-cmake-modules': '@latest'

View File

@ -4,11 +4,14 @@
cmake_minimum_required(VERSION 3.16)
project(layershellqt)
set(PROJECT_VERSION "5.21.80")
set(PROJECT_VERSION "5.24.6")
set(PROJECT_VERSION_MAJOR 5)
set(CMAKE_C_STANDARD 99)
set(QT_MIN_VERSION "5.15.0")
set(KF5_MIN_VERSION "5.78")
set(KF5_MIN_VERSION "5.86")
set(KDE_COMPILERSETTINGS_LEVEL "5.82")
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
@ -29,10 +32,13 @@ include(GenerateExportHeader)
include(KDEClangFormat)
include(ECMQtDeclareLoggingCategory)
find_package(WaylandScanner)
find_package(QtWaylandScanner)
find_package(WaylandScanner REQUIRED)
find_package(QtWaylandScanner REQUIRED)
find_package(Wayland 1.3 COMPONENTS Client Server)
find_package(WaylandProtocols)
find_package(WaylandProtocols REQUIRED)
find_package(PkgConfig REQUIRED)
pkg_check_modules(XKBCOMMON xkbcommon REQUIRED IMPORTED_TARGET)
set_package_properties(Wayland PROPERTIES
TYPE REQUIRED)

View File

@ -16,18 +16,18 @@ ecm_qt_declare_logging_category(LAYER_SHELL_SOURCES
)
add_library(LayerShellQtInterface SHARED qwaylandlayersurface.cpp interfaces/window.cpp interfaces/shell.cpp qwaylandlayershellintegration.cpp qwaylandlayershell.cpp ${LAYER_SHELL_SOURCES})
target_link_libraries(LayerShellQtInterface PRIVATE Qt::Gui Qt::WaylandClientPrivate Qt::XkbCommonSupportPrivate Wayland::Client)
target_link_libraries(LayerShellQtInterface PRIVATE Qt::Gui Qt::WaylandClientPrivate Qt::XkbCommonSupportPrivate Wayland::Client PkgConfig::XKBCOMMON)
target_include_directories(LayerShellQtInterface PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/LayerShellQt>"
INTERFACE "$<INSTALL_INTERFACE:${KDE_INSTALL_INCLUDEDIR}/>"
)
set_target_properties(LayerShellQtInterface PROPERTIES VERSION ${LAYERSHELLQT_VERSION_STRING}
set_target_properties(LayerShellQtInterface PROPERTIES VERSION ${LAYERSHELLQT_VERSION}
SOVERSION ${LAYERSHELLQT_SOVERSION}
EXPORT_NAME Interface
)
add_library(layer-shell SHARED qwaylandlayershellintegrationplugin.cpp)
target_link_libraries(layer-shell LayerShellQtInterface Qt::WaylandClient Qt::WaylandClientPrivate Qt::XkbCommonSupportPrivate Wayland::Client)
target_link_libraries(layer-shell LayerShellQtInterface Qt::WaylandClient Qt::WaylandClientPrivate Qt::XkbCommonSupportPrivate Wayland::Client PkgConfig::XKBCOMMON)
ecm_generate_headers(LayerShellQt_HEADERS
HEADER_NAMES

View File

@ -18,51 +18,3 @@ void Shell::useLayerShell()
qCDebug(LAYERSHELLQT) << "Unable to set QT_WAYLAND_SHELL_INTEGRATION=layer-shell";
}
}
struct Defaults {
QString scope = QStringLiteral("normal");
Window::Anchors anchors = {Window::AnchorTop | Window::AnchorBottom | Window::AnchorLeft | Window::AnchorRight};
Window::Layer layer = Window::LayerTop;
QMargins margins;
};
Q_GLOBAL_STATIC(Defaults, s_defaults);
void Shell::setDefaultScope(const QString &scope)
{
s_defaults->scope = scope;
}
QString Shell::defaultScope()
{
return s_defaults->scope;
}
void Shell::setDefaultLayer(Window::Layer defaultLayer)
{
s_defaults->layer = defaultLayer;
}
Window::Layer Shell::defaultLayer()
{
return s_defaults->layer;
}
void Shell::setDefaultAnchors(Window::Anchors anchors)
{
s_defaults->anchors = anchors;
}
Window::Anchors Shell::defaultAnchors()
{
return s_defaults->anchors;
}
void Shell::setDefaultMargins(const QMargins &margins)
{
s_defaults->margins = margins;
}
QMargins Shell::defaultMargins()
{
return s_defaults->margins;
}

View File

@ -20,18 +20,6 @@ class LAYERSHELLQT_EXPORT Shell
{
public:
static void useLayerShell();
static void setDefaultMargins(const QMargins &margins);
static QMargins defaultMargins();
static void setDefaultScope(const QString &scope);
static QString defaultScope();
static void setDefaultLayer(Window::Layer defaultLayer);
static Window::Layer defaultLayer();
static void setDefaultAnchors(Window::Anchors defaultAnchors);
static Window::Anchors defaultAnchors();
};
}

View File

@ -15,58 +15,134 @@ using namespace LayerShellQt;
class LayerShellQt::WindowPrivate
{
public:
WindowPrivate(QWaylandLayerSurface *surface)
: surface(surface)
WindowPrivate(QWindow *window)
: parentWindow(window)
{
}
QWaylandLayerSurface *const surface;
QWindow *parentWindow;
QString scope = QStringLiteral("window");
Window::Anchors anchors = {Window::AnchorTop | Window::AnchorBottom | Window::AnchorLeft | Window::AnchorRight};
int32_t exclusionZone = 0;
Window::KeyboardInteractivity keyboardInteractivity = Window::KeyboardInteractivityExclusive;
Window::Layer layer = Window::LayerTop;
QMargins margins;
QWaylandLayerSurface *getSurface() const;
};
Window::~Window() = default;
static QMap<QWindow *, Window *> s_map;
void Window::setAnchor(Anchor anchor)
Window::~Window()
{
d->surface->setAnchor(anchor);
s_map.remove(d->parentWindow);
}
void Window::setAnchors(Anchors anchors)
{
d->anchors = anchors;
if (auto surface = d->getSurface()) {
surface->setAnchor(anchors);
}
}
Window::Anchors Window::anchors() const
{
return d->anchors;
}
void Window::setExclusiveZone(int32_t zone)
{
d->surface->setExclusiveZone(zone);
d->exclusionZone = zone;
if (auto surface = d->getSurface()) {
surface->setExclusiveZone(zone);
}
}
int32_t Window::exclusionZone() const
{
return d->exclusionZone;
}
void Window::setMargins(const QMargins &margins)
{
d->surface->setMargins(margins);
d->margins = margins;
if (auto surface = d->getSurface()) {
surface->setMargins(margins);
}
}
void Window::setKeyboardInteractivity(bool enabled)
QMargins Window::margins() const
{
d->surface->setKeyboardInteractivity(enabled);
return d->margins;
}
void Window::setKeyboardInteractivity(KeyboardInteractivity interactivity)
{
d->keyboardInteractivity = interactivity;
if (auto surface = d->getSurface()) {
surface->setKeyboardInteractivity(interactivity);
}
}
Window::KeyboardInteractivity Window::keyboardInteractivity() const
{
return d->keyboardInteractivity;
}
void Window::setLayer(Layer layer)
{
d->surface->setLayer(layer);
d->layer = layer;
if (auto surface = d->getSurface()) {
surface->setLayer(layer);
}
}
Window::Window(WindowPrivate *d)
: d(d)
void Window::setScope(const QString &scope)
{
d->scope = scope;
// this is static and must be set before the platform window is created
}
QString Window::scope() const
{
return d->scope;
}
Window::Layer Window::layer() const
{
return d->layer;
}
Window::Window(QWindow *window)
: QObject(window)
, d(new WindowPrivate(window))
{
s_map.insert(d->parentWindow, this);
}
Window *Window::get(QWindow *window)
{
auto ww = dynamic_cast<QtWaylandClient::QWaylandWindow *>(window->handle());
auto layerShellWindow = s_map.value(window);
if (layerShellWindow) {
return layerShellWindow;
}
return new Window(window);
}
QWaylandLayerSurface *WindowPrivate::getSurface() const
{
if (!parentWindow) {
return nullptr;
}
auto ww = dynamic_cast<QtWaylandClient::QWaylandWindow *>(parentWindow->handle());
if (!ww) {
qCDebug(LAYERSHELLQT) << "window not a wayland window" << window;
qCDebug(LAYERSHELLQT) << "window not a wayland window" << parentWindow;
return nullptr;
}
QWaylandLayerSurface *s = qobject_cast<QWaylandLayerSurface *>(ww->shellSurface());
if (!s) {
qCDebug(LAYERSHELLQT) << "window not using wlr-layer-shell" << window << ww->shellSurface();
qCDebug(LAYERSHELLQT) << "window not using wlr-layer-shell" << parentWindow << ww->shellSurface();
return nullptr;
}
return new Window(new WindowPrivate(s));
return s;
}

View File

@ -43,16 +43,49 @@ public:
};
Q_ENUM(Layer)
void setAnchor(Anchor anchor);
void setExclusiveZone(int32_t zone);
void setMargins(const QMargins &margins);
void setKeyboardInteractivity(bool enabled);
void setLayer(Layer layer);
/**
* This enum type is used to specify how the layer surface handles keyboard focus.
*/
enum KeyboardInteractivity {
KeyboardInteractivityNone = 0,
KeyboardInteractivityExclusive = 1,
KeyboardInteractivityOnDemand = 2,
};
Q_ENUM(KeyboardInteractivity)
void setAnchors(Anchors anchor);
Anchors anchors() const;
void setExclusiveZone(int32_t zone);
int32_t exclusionZone() const;
void setMargins(const QMargins &margins);
QMargins margins() const;
void setKeyboardInteractivity(KeyboardInteractivity interactivity);
KeyboardInteractivity keyboardInteractivity() const;
void setLayer(Layer layer);
Layer layer() const;
/**
* Sets a string based identifier for this window.
* This may be used by a compositor to determine stacking
* order within a given layer.
*
* May also be referred to as a role
*/
void setScope(const QString &scope);
QString scope() const;
/**
* Gets the LayerShell Window for a given Qt Window
* Ownership is not transferred
*/
static Window *get(QWindow *window);
private:
Window(WindowPrivate *d);
Window(QWindow *window);
QScopedPointer<WindowPrivate> d;
};

View File

@ -10,8 +10,8 @@
namespace LayerShellQt
{
QWaylandLayerShell::QWaylandLayerShell(QtWayland::zwlr_layer_shell_v1 *shell)
: QtWayland::zwlr_layer_shell_v1(shell->object())
QWaylandLayerShell::QWaylandLayerShell(::wl_registry *registry, uint32_t id, uint32_t version)
: QtWayland::zwlr_layer_shell_v1(registry, id, version)
{
}

View File

@ -20,8 +20,8 @@ namespace LayerShellQt
class LAYERSHELLQT_EXPORT QWaylandLayerShell : public QtWayland::zwlr_layer_shell_v1
{
public:
QWaylandLayerShell(QtWayland::zwlr_layer_shell_v1 *shell);
virtual ~QWaylandLayerShell();
QWaylandLayerShell(::wl_registry *registry, uint32_t id, uint32_t version);
~QWaylandLayerShell() override;
QWaylandLayerSurface *createLayerSurface(QtWaylandClient::QWaylandWindow *window);
// TODO: Popups

View File

@ -18,6 +18,10 @@ QWaylandLayerShellIntegration::QWaylandLayerShellIntegration()
{
}
QWaylandLayerShellIntegration::~QWaylandLayerShellIntegration()
{
}
bool QWaylandLayerShellIntegration::initialize(QtWaylandClient::QWaylandDisplay *display)
{
QWaylandShellIntegration::initialize(display);
@ -35,7 +39,7 @@ void QWaylandLayerShellIntegration::registryLayer(void *data, struct wl_registry
QWaylandLayerShellIntegration *shell = static_cast<QWaylandLayerShellIntegration *>(data);
if (interface == zwlr_layer_shell_v1_interface.name)
shell->m_layerShell = new QWaylandLayerShell(new QtWayland::zwlr_layer_shell_v1(registry, id, std::min(version, 3u)));
shell->m_layerShell.reset(new QWaylandLayerShell(registry, id, std::min(version, 4u)));
}
}

View File

@ -21,6 +21,7 @@ class LAYERSHELLQT_EXPORT QWaylandLayerShellIntegration : public QtWaylandClient
{
public:
QWaylandLayerShellIntegration();
~QWaylandLayerShellIntegration() override;
bool initialize(QtWaylandClient::QWaylandDisplay *display) override;
QtWaylandClient::QWaylandShellSurface *createShellSurface(QtWaylandClient::QWaylandWindow *window) override;
@ -28,7 +29,7 @@ public:
private:
static void registryLayer(void *data, struct wl_registry *registry, uint32_t id, const QString &interface, uint32_t version);
QWaylandLayerShell *m_layerShell = nullptr;
QScopedPointer<QWaylandLayerShell> m_layerShell;
};
}

View File

@ -8,6 +8,7 @@
#include "interfaces/shell.h"
#include "qwaylandlayershell_p.h"
#include "qwaylandlayersurface_p.h"
#include "layershellqt_logging.h"
#include <QtWaylandClient/private/qwaylandscreen_p.h>
#include <QtWaylandClient/private/qwaylandsurface_p.h>
@ -17,21 +18,32 @@ namespace LayerShellQt
{
QWaylandLayerSurface::QWaylandLayerSurface(QWaylandLayerShell *shell, QtWaylandClient::QWaylandWindow *window)
: QtWaylandClient::QWaylandShellSurface(window)
, QtWayland::zwlr_layer_surface_v1(
shell->get_layer_surface(window->waylandSurface()->object(), window->waylandScreen()->output(), Shell::defaultLayer(), Shell::defaultScope()))
, QtWayland::zwlr_layer_surface_v1()
{
const auto anchors = Shell::defaultAnchors();
set_anchor(anchors);
LayerShellQt::Window *interface = Window::get(window->window());
Q_ASSERT(interface);
if (!Shell::defaultMargins().isNull()) {
setMargins(Shell::defaultMargins());
// Qt will always assign a screen to a window, but if the compositor has no screens available a dummy QScreen object is created
// this will not cast to a QWaylandScreen
QtWaylandClient::QWaylandScreen *screen = window->waylandScreen();
if (screen->isPlaceholder()) {
qCWarning(LAYERSHELLQT) << "Creating a layer shell for placeholder screen. This will be positioned incorrectly";
}
init(shell->get_layer_surface(window->waylandSurface()->object(), screen->isPlaceholder() ? nullptr : screen->output(), interface->layer(), interface->scope()));
Window::Anchors anchors = interface->anchors();
set_anchor(interface->anchors());
setMargins(interface->margins());
setKeyboardInteractivity(interface->keyboardInteractivity());
setExclusiveZone(interface->exclusionZone());
QSize size = window->surfaceSize();
if (anchors & Window::AnchorLeft && anchors & Window::AnchorRight) {
if ((anchors & Window::AnchorLeft) && (anchors & Window::AnchorRight)) {
size.setWidth(0);
}
if (anchors & Window::AnchorTop && anchors & Window::AnchorBottom) {
if ((anchors & Window::AnchorTop) && (anchors & Window::AnchorBottom)) {
size.setHeight(0);
}
if (size.isValid() && size != QSize(0, 0)) {
@ -85,9 +97,9 @@ void QWaylandLayerSurface::setMargins(const QMargins &margins)
set_margin(margins.top(), margins.right(), margins.bottom(), margins.left());
}
void QWaylandLayerSurface::setKeyboardInteractivity(bool enabled)
void QWaylandLayerSurface::setKeyboardInteractivity(uint32_t interactivity)
{
set_keyboard_interactivity(enabled);
set_keyboard_interactivity(interactivity);
}
void QWaylandLayerSurface::setLayer(uint32_t layer)

View File

@ -23,7 +23,7 @@ class LAYERSHELLQT_EXPORT QWaylandLayerSurface : public QtWaylandClient::QWaylan
Q_OBJECT
public:
QWaylandLayerSurface(QWaylandLayerShell *shell, QtWaylandClient::QWaylandWindow *window);
virtual ~QWaylandLayerSurface();
~QWaylandLayerSurface() override;
bool isExposed() const override
{
@ -33,7 +33,7 @@ public:
void setAnchor(uint32_t anchor);
void setExclusiveZone(int32_t zone);
void setMargins(const QMargins &margins);
void setKeyboardInteractivity(bool enabled);
void setKeyboardInteractivity(uint32_t interactivity);
void setLayer(uint32_t layer);
void applyConfigure() override;

View File

@ -25,7 +25,7 @@
THIS SOFTWARE.
</copyright>
<interface name="zwlr_layer_shell_v1" version="3">
<interface name="zwlr_layer_shell_v1" version="4">
<description summary="create surfaces that are layers of the desktop">
Clients can use this interface to assign the surface_layer role to
wl_surfaces. Such surfaces are assigned to a "layer" of the output and
@ -100,7 +100,7 @@
</request>
</interface>
<interface name="zwlr_layer_surface_v1" version="3">
<interface name="zwlr_layer_surface_v1" version="4">
<description summary="layer metadata interface">
An interface that may be implemented by a wl_surface, for surfaces that
are designed to be rendered as a layer of a stacked desktop-like
@ -203,21 +203,85 @@
<arg name="left" type="int"/>
</request>
<enum name="keyboard_interactivity">
<description summary="types of keyboard interaction possible for a layer shell surface">
Types of keyboard interaction possible for layer shell surfaces. The
rationale for this is twofold: (1) some applications are not interested
in keyboard events and not allowing them to be focused can improve the
desktop experience; (2) some applications will want to take exclusive
keyboard focus.
</description>
<entry name="none" value="0">
<description summary="no keyboard focus is possible">
This value indicates that this surface is not interested in keyboard
events and the compositor should never assign it the keyboard focus.
This is the default value, set for newly created layer shell surfaces.
This is useful for e.g. desktop widgets that display information or
only have interaction with non-keyboard input devices.
</description>
</entry>
<entry name="exclusive" value="1">
<description summary="request exclusive keyboard focus">
Request exclusive keyboard focus if this surface is above the shell surface layer.
For the top and overlay layers, the seat will always give
exclusive keyboard focus to the top-most layer which has keyboard
interactivity set to exclusive. If this layer contains multiple
surfaces with keyboard interactivity set to exclusive, the compositor
determines the one receiving keyboard events in an implementation-
defined manner. In this case, no guarantee is made when this surface
will receive keyboard focus (if ever).
For the bottom and background layers, the compositor is allowed to use
normal focus semantics.
This setting is mainly intended for applications that need to ensure
they receive all keyboard events, such as a lock screen or a password
prompt.
</description>
</entry>
<entry name="on_demand" value="2" since="4">
<description summary="request regular keyboard focus semantics">
This requests the compositor to allow this surface to be focused and
unfocused by the user in an implementation-defined manner. The user
should be able to unfocus this surface even regardless of the layer
it is on.
Typically, the compositor will want to use its normal mechanism to
manage keyboard focus between layer shell surfaces with this setting
and regular toplevels on the desktop layer (e.g. click to focus).
Nevertheless, it is possible for a compositor to require a special
interaction to focus or unfocus layer shell surfaces (e.g. requiring
a click even if focus follows the mouse normally, or providing a
keybinding to switch focus between layers).
This setting is mainly intended for desktop shell components (e.g.
panels) that allow keyboard interaction. Using this option can allow
implementing a desktop shell that can be fully usable without the
mouse.
</description>
</entry>
</enum>
<request name="set_keyboard_interactivity">
<description summary="requests keyboard events">
Set to 1 to request that the seat send keyboard events to this layer
surface. For layers below the shell surface layer, the seat will use
normal focus semantics. For layers above the shell surface layers, the
seat will always give exclusive keyboard focus to the top-most layer
which has keyboard interactivity set to true.
Set how keyboard events are delivered to this surface. By default,
layer shell surfaces do not receive keyboard events; this request can
be used to change this.
This setting is inherited by child surfaces set by the get_popup
request.
Layer surfaces receive pointer, touch, and tablet events normally. If
you do not want to receive them, set the input region on your surface
to an empty region.
Events is double-buffered, see wl_surface.commit.
Keyboard interactivity is double-buffered, see wl_surface.commit.
</description>
<arg name="keyboard_interactivity" type="uint"/>
<arg name="keyboard_interactivity" type="uint" enum="keyboard_interactivity"/>
</request>
<request name="get_popup">
@ -302,6 +366,7 @@
<entry name="invalid_surface_state" value="0" summary="provided surface state is invalid"/>
<entry name="invalid_size" value="1" summary="size is invalid"/>
<entry name="invalid_anchor" value="2" summary="anchor bitfield is invalid"/>
<entry name="invalid_keyboard_interactivity" value="3" summary="keyboard interactivity is invalid"/>
</enum>
<enum name="anchor" bitfield="true">

View File

@ -5,8 +5,15 @@
*/
#include <QCommandLineParser>
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QPainter>
#include <QRasterWindow>
#include <QTimer>
#include <QWindow>
#include <QMetaEnum>
#include <interfaces/shell.h>
#include <interfaces/window.h>
@ -33,6 +40,15 @@ T stringToEnum(QMetaEnum metaEnum, const QString &str)
return ret;
}
class BasicWindow : public QRasterWindow
{
void paintEvent(QPaintEvent *)
{
QPainter p(this);
p.fillRect(QRect(0, 0, width(), height()), Qt::red);
}
};
int main(int argc, char **argv)
{
Shell::useLayerShell();
@ -53,38 +69,40 @@ int main(int argc, char **argv)
QStringLiteral("One of ") + enumsToStringList(layerMetaEnum).join(QLatin1String("|")),
QStringLiteral("layer"),
QStringLiteral("LayerTop"));
parser.addOptions({marginsOption, scopeOption, anchorsOption, layerOption});
QCommandLineOption widthOption(QStringLiteral("width"), QStringLiteral("Width of the window"), QStringLiteral("pixels"), QStringLiteral("0"));
QCommandLineOption heightOption(QStringLiteral("height"), QStringLiteral("Height of the window"), QStringLiteral("pixels"), QStringLiteral("0"));
parser.addOptions({marginsOption, scopeOption, anchorsOption, layerOption, widthOption, heightOption});
parser.addHelpOption();
parser.process(app);
static int margins = 0;
BasicWindow window;
LayerShellQt::Window *layerShell = LayerShellQt::Window::get(&window);
if (parser.isSet(marginsOption)) {
margins = parser.value(marginsOption).toInt();
Shell::setDefaultMargins({margins, margins, margins, margins});
int margins = parser.value(marginsOption).toInt();
layerShell->setMargins({margins, margins, margins, margins});
}
if (parser.isSet(scopeOption)) {
Shell::setDefaultScope(parser.value(scopeOption));
layerShell->setScope(parser.value(scopeOption));
}
if (parser.isSet(layerOption)) {
Shell::setDefaultLayer(Window::Layer(layerMetaEnum.keyToValue(qPrintable(parser.value(layerOption)))));
layerShell->setLayer(Window::Layer(layerMetaEnum.keyToValue(qPrintable(parser.value(layerOption)))));
}
if (parser.isSet(anchorsOption)) {
Shell::setDefaultAnchors(stringToEnum<Window::Anchors>(anchorMetaEnum, parser.value(anchorsOption)));
layerShell->setAnchors(stringToEnum<Window::Anchors>(anchorMetaEnum, parser.value(anchorsOption)));
}
if (parser.isSet(widthOption)) {
window.setWidth(parser.value(widthOption).toInt());
}
if (parser.isSet(heightOption)) {
window.setHeight(parser.value(heightOption).toInt());
}
QQmlApplicationEngine engine;
engine.loadData(
"import QtQuick.Controls 2.10\n"
"import QtQuick 2.10\n"
"\n"
"ApplicationWindow {"
" width: 100; height: 100\n"
" visible: true\n"
" Rectangle { color: 'red'; anchors.fill: parent }"
"}"
,
QStringLiteral("bananaland:/potato.qml"));
window.show();
// just so you don't block yourself out whilst testing
QTimer::singleShot(5000, &app, &QGuiApplication::quit);
return app.exec();
}