diff --git a/src/wayland/shell.cpp b/src/wayland/shell.cpp new file mode 100644 index 0000000000..ffeb47f590 --- /dev/null +++ b/src/wayland/shell.cpp @@ -0,0 +1,164 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2014 Martin Gräßlin + +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 . +*********************************************************************/ +#include "shell.h" +#include "output.h" + +namespace KWin +{ +namespace Wayland +{ + +Shell::Shell(QObject *parent) + : QObject(parent) + , m_shell(nullptr) +{ +} + +Shell::~Shell() +{ + release(); +} + +void Shell::destroy() +{ + if (!m_shell) { + return; + } + emit interfaceAboutToBeDestroyed(); + free(m_shell); + m_shell = nullptr; +} + +void Shell::release() +{ + if (!m_shell) { + return; + } + emit interfaceAboutToBeReleased(); + wl_shell_destroy(m_shell); + m_shell = nullptr; +} + +void Shell::setup(wl_shell *shell) +{ + Q_ASSERT(!m_shell); + Q_ASSERT(shell); + m_shell = shell; +} + +ShellSurface *Shell::createSurface(wl_surface *surface, QObject *parent) +{ + Q_ASSERT(isValid()); + ShellSurface *s = new ShellSurface(parent); + connect(this, &Shell::interfaceAboutToBeReleased, s, &ShellSurface::release); + connect(this, &Shell::interfaceAboutToBeDestroyed, s, &ShellSurface::destroy); + s->setup(wl_shell_get_shell_surface(m_shell, surface)); + return s; +} + +ShellSurface::ShellSurface(QObject *parent) + : QObject(parent) + , m_surface(nullptr) + , m_size() +{ +} + +ShellSurface::~ShellSurface() +{ + release(); +} + +void ShellSurface::release() +{ + if (!isValid()) { + return; + } + wl_shell_surface_destroy(m_surface); + m_surface = nullptr; +} + +void ShellSurface::destroy() +{ + if (!isValid()) { + return; + } + free(m_surface); + m_surface = nullptr; +} + +const struct wl_shell_surface_listener ShellSurface::s_listener = { + ShellSurface::pingCallback, + ShellSurface::configureCallback, + ShellSurface::popupDoneCallback +}; + +void ShellSurface::configureCallback(void *data, wl_shell_surface *shellSurface, uint32_t edges, int32_t width, int32_t height) +{ + Q_UNUSED(edges) + ShellSurface *s = reinterpret_cast(data); + Q_ASSERT(s->m_surface == shellSurface); + s->setSize(QSize(width, height)); +} + +void ShellSurface::pingCallback(void *data, wl_shell_surface *shellSurface, uint32_t serial) +{ + ShellSurface *s = reinterpret_cast(data); + Q_ASSERT(s->m_surface == shellSurface); + s->ping(serial); +} + +void ShellSurface::popupDoneCallback(void *data, wl_shell_surface *shellSurface) +{ + // not needed, we don't have popups + Q_UNUSED(data) + Q_UNUSED(shellSurface) +} + +void ShellSurface::setup(wl_shell_surface *surface) +{ + Q_ASSERT(surface); + Q_ASSERT(!m_surface); + m_surface = surface; + wl_shell_surface_add_listener(m_surface, &s_listener, this); +} + +void ShellSurface::ping(uint32_t serial) +{ + wl_shell_surface_pong(m_surface, serial); + emit pinged(); +} + +void ShellSurface::setSize(const QSize &size) +{ + if (m_size == size) { + return; + } + m_size = size; + emit sizeChanged(size); +} + +void ShellSurface::setFullscreen(Output *output) +{ + Q_ASSERT(isValid()); + wl_shell_surface_set_fullscreen(m_surface, WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT, 0, output ? output->output() : nullptr); +} + +} +} diff --git a/src/wayland/shell.h b/src/wayland/shell.h new file mode 100644 index 0000000000..a61c081301 --- /dev/null +++ b/src/wayland/shell.h @@ -0,0 +1,112 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2014 Martin Gräßlin + +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 . +*********************************************************************/ +#ifndef KWIN_WAYLAND_SHELL_H +#define KWIN_WAYLAND_SHELL_H + +#include +#include + +#include + +namespace KWin +{ +namespace Wayland +{ +class ShellSurface; +class Output; + +class Shell : public QObject +{ + Q_OBJECT +public: + explicit Shell(QObject *parent = nullptr); + virtual ~Shell(); + + bool isValid() const { + return m_shell != nullptr; + } + void release(); + void destroy(); + void setup(wl_shell *shell); + + ShellSurface *createSurface(wl_surface *surface, QObject *parent = nullptr); + + operator wl_shell*() { + return m_shell; + } + operator wl_shell*() const { + return m_shell; + } + +Q_SIGNALS: + void interfaceAboutToBeReleased(); + void interfaceAboutToBeDestroyed(); + +private: + wl_shell *m_shell; +}; + +class ShellSurface : public QObject +{ + Q_OBJECT + Q_PROPERTY(QSize size READ size WRITE setSize NOTIFY sizeChanged) +public: + explicit ShellSurface(QObject *parent); + virtual ~ShellSurface(); + + void release(); + void destroy(); + void setup(wl_shell_surface *surface); + QSize size() const { + return m_size; + } + void setSize(const QSize &size); + + void setFullscreen(Output *output = nullptr); + + bool isValid() const { + return m_surface != nullptr; + } + operator wl_shell_surface*() { + return m_surface; + } + operator wl_shell_surface*() const { + return m_surface; + } + + static void pingCallback(void *data, struct wl_shell_surface *shellSurface, uint32_t serial); + static void configureCallback(void *data, struct wl_shell_surface *shellSurface, uint32_t edges, int32_t width, int32_t height); + static void popupDoneCallback(void *data, struct wl_shell_surface *shellSurface); + +Q_SIGNALS: + void pinged(); + void sizeChanged(const QSize &); + +private: + void ping(uint32_t serial); + wl_shell_surface *m_surface; + QSize m_size; + static const struct wl_shell_surface_listener s_listener; +}; + +} +} + +#endif