summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJørgen Lind <jorgen.lind@nokia.com>2012-02-13 10:23:41 +0100
committerJørgen Lind <jorgen.lind@nokia.com>2012-04-11 13:41:59 +0200
commitf984c7985ca26096dd293f18ba4d0b8271fdb4f5 (patch)
tree76293fd58a3124a2216585951ccb58fa47f14f9a
parent921fefbf2a5e4078f4dff19c3c664cbbd9b751d1 (diff)
Client side decoration
Something is alot better than nothing :) This gives window decorations for QWidgets and other applications that use QBackingStore Change-Id: Ic748ee1df88236b20416029e20e26532f7fb4476 Reviewed-by: Samuel Rødal <samuel.rodal@nokia.com>
-rw-r--r--src/compositor/compositor_api/waylandsurface.cpp8
-rw-r--r--src/compositor/compositor_api/waylandsurface.h2
-rw-r--r--src/compositor/wayland_wrapper/wlshellsurface.cpp256
-rw-r--r--src/compositor/wayland_wrapper/wlshellsurface.h72
-rw-r--r--src/compositor/wayland_wrapper/wlsubsurface.cpp7
-rw-r--r--src/compositor/wayland_wrapper/wlsurface.cpp6
-rw-r--r--src/compositor/wayland_wrapper/wlsurface.h3
-rw-r--r--src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandeglwindow.cpp16
-rw-r--r--src/plugins/platforms/wayland/qwaylanddecoration.cpp189
-rw-r--r--src/plugins/platforms/wayland/qwaylanddecoration.h80
-rw-r--r--src/plugins/platforms/wayland/qwaylanddisplay.cpp1
-rw-r--r--src/plugins/platforms/wayland/qwaylandinputdevice.cpp49
-rw-r--r--src/plugins/platforms/wayland/qwaylandinputdevice.h4
-rw-r--r--src/plugins/platforms/wayland/qwaylandshell.cpp2
-rw-r--r--src/plugins/platforms/wayland/qwaylandshell.h2
-rw-r--r--src/plugins/platforms/wayland/qwaylandshellsurface.cpp38
-rw-r--r--src/plugins/platforms/wayland/qwaylandshellsurface.h12
-rw-r--r--src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp191
-rw-r--r--src/plugins/platforms/wayland/qwaylandshmbackingstore.h46
-rw-r--r--src/plugins/platforms/wayland/qwaylandsubsurface.cpp31
-rw-r--r--src/plugins/platforms/wayland/qwaylandsubsurface.h2
-rw-r--r--src/plugins/platforms/wayland/qwaylandwindow.cpp140
-rw-r--r--src/plugins/platforms/wayland/qwaylandwindow.h34
-rw-r--r--src/plugins/platforms/wayland/wayland.pro6
24 files changed, 1109 insertions, 88 deletions
diff --git a/src/compositor/compositor_api/waylandsurface.cpp b/src/compositor/compositor_api/waylandsurface.cpp
index 995c81abd..cf15b578d 100644
--- a/src/compositor/compositor_api/waylandsurface.cpp
+++ b/src/compositor/compositor_api/waylandsurface.cpp
@@ -46,6 +46,7 @@
#include "wayland_wrapper/wlextendedsurface.h"
#include "wayland_wrapper/wlsubsurface.h"
#include "wayland_wrapper/wlcompositor.h"
+#include "wayland_wrapper/wlshellsurface.h"
#include "waylandcompositor.h"
#include "waylandwindowmanagerintegration.h"
@@ -309,6 +310,13 @@ void WaylandSurface::frameFinished()
d->surface->frameFinished();
}
+WaylandSurface *WaylandSurface::transientParent() const
+{
+ Q_D(const WaylandSurface);
+ if (d->surface->shellSurface() && d->surface->shellSurface()->transientParent())
+ return d->surface->shellSurface()->transientParent()->surface()->waylandSurface();
+}
+
void WaylandSurface::sendOnScreenVisibilityChange(bool visible)
{
Q_D(WaylandSurface);
diff --git a/src/compositor/compositor_api/waylandsurface.h b/src/compositor/compositor_api/waylandsurface.h
index d9fbc3915..8a0637eac 100644
--- a/src/compositor/compositor_api/waylandsurface.h
+++ b/src/compositor/compositor_api/waylandsurface.h
@@ -127,6 +127,8 @@ public:
void frameFinished();
+ WaylandSurface *transientParent() const;
+
Wayland::Surface *handle() const;
#ifdef QT_COMPOSITOR_QUICK
diff --git a/src/compositor/wayland_wrapper/wlshellsurface.cpp b/src/compositor/wayland_wrapper/wlshellsurface.cpp
index ea4b54b62..9e37a330f 100644
--- a/src/compositor/wayland_wrapper/wlshellsurface.cpp
+++ b/src/compositor/wayland_wrapper/wlshellsurface.cpp
@@ -43,6 +43,7 @@
#include "wlcompositor.h"
#include "wlsurface.h"
#include "wlinputdevice.h"
+#include "wlsubsurface.h"
#include <QtCore/qglobal.h>
#include <QtCore/QDebug>
@@ -75,22 +76,92 @@ const struct wl_shell_interface Shell::shell_interface = {
};
ShellSurface::ShellSurface(wl_client *client, uint32_t id, Surface *surface)
+ : m_surface(surface)
+ , m_resizeGrabber(0)
+ , m_moveGrabber(0)
+ , m_transientParent(0)
+ , m_xOffset(0)
+ , m_yOffset(0)
{
m_shellSurface = wl_client_add_object(client,&wl_shell_surface_interface,&shell_surface_interface,id,this);
surface->setShellSurface(this);
+}
+
+void ShellSurface::sendConfigure(uint32_t edges, int32_t width, int32_t height)
+{
+ wl_resource_post_event(m_shellSurface,WL_SHELL_SURFACE_CONFIGURE, Compositor::currentTimeMsecs(),edges,width,height);
+}
+
+Surface *ShellSurface::surface() const
+{
+ return m_surface;
+}
+
+void ShellSurface::adjustPosInResize()
+{
+ if (m_transientParent)
+ return;
+ if (!m_resizeGrabber || !(m_resizeGrabber->resize_edges & WL_SHELL_SURFACE_RESIZE_TOP_LEFT))
+ return;
+
+ int bottomLeftX = m_resizeGrabber->base()->x + m_resizeGrabber->width;
+ int bottomLeftY = m_resizeGrabber->base()->y + m_resizeGrabber->height;
+ qreal x = surface()->pos().x();
+ qreal y = surface()->pos().y();
+ if (m_resizeGrabber->resize_edges & WL_SHELL_SURFACE_RESIZE_TOP)
+ y = bottomLeftY - surface()->size().height();
+ if (m_resizeGrabber->resize_edges & WL_SHELL_SURFACE_RESIZE_LEFT)
+ x = bottomLeftX - surface()->size().width();
+ QPointF newPos(x,y);
+ surface()->setPos(newPos);
+}
+
+void ShellSurface::adjustPosToTransientParent()
+{
+ if (!m_transientParent ||
+ (m_surface->subSurface() && m_surface->subSurface()->parent()))
+ return;
+
+ m_surface->setPos(m_transientParent->surface()->pos() + QPoint(m_xOffset,m_yOffset));
+}
+void ShellSurface::resetResizeGrabber()
+{
+ m_resizeGrabber = 0;
+}
+
+void ShellSurface::resetMoveGrabber()
+{
+ m_moveGrabber = 0;
+}
+
+ShellSurface *ShellSurface::transientParent() const
+{
+ return m_transientParent;
}
void ShellSurface::move(struct wl_client *client,
struct wl_resource *shell_surface_resource,
- struct wl_resource *input_device,
+ struct wl_resource *input_device_super,
uint32_t time)
{
Q_UNUSED(client);
- Q_UNUSED(shell_surface_resource);
- Q_UNUSED(input_device);
Q_UNUSED(time);
+ ShellSurface *self = static_cast<ShellSurface *>(shell_surface_resource->data);
+ InputDevice *input_device = static_cast<InputDevice *>(input_device_super->data);
+ if (self->m_resizeGrabber || self->m_moveGrabber) {
+ qDebug() << "invalid state";
+ return;
+ }
+
+ self->m_moveGrabber = new ShellSurfaceMoveGrabber(self);
+ self->m_moveGrabber->base()->x = input_device->base()->x;
+ self->m_moveGrabber->base()->y = input_device->base()->y;
+ self->m_moveGrabber->offset_x = input_device->base()->x - self->surface()->pos().x();
+ self->m_moveGrabber->offset_y = input_device->base()->y - self->surface()->pos().y();
+
+ wl_input_device_start_pointer_grab(input_device->base(),self->m_moveGrabber->base(),Compositor::currentTimeMsecs());
}
void ShellSurface::resize(struct wl_client *client,
@@ -103,18 +174,31 @@ void ShellSurface::resize(struct wl_client *client,
Q_UNUSED(client);
Q_UNUSED(time);
Q_UNUSED(edges);
- ShellSurface *shell_surface = static_cast<ShellSurface *>(shell_surface_resource->data);
- Q_UNUSED(shell_surface);
+ ShellSurface *self = static_cast<ShellSurface *>(shell_surface_resource->data);
InputDevice *input_device = static_cast<InputDevice *>(input_device_super->data);
- Q_UNUSED(input_device);
+ if (self->m_moveGrabber || self->m_resizeGrabber) {
+ qDebug() << "invalid state2";
+ return;
+ }
+ self->m_resizeGrabber = new ShellSurfaceResizeGrabber(self);
+ self->m_resizeGrabber->base()->x = input_device->base()->x;
+ self->m_resizeGrabber->base()->y = input_device->base()->y;
+ self->m_resizeGrabber->resize_edges = wl_shell_surface_resize(edges);
+ self->m_resizeGrabber->width = self->surface()->size().width();
+ self->m_resizeGrabber->height = self->surface()->size().height();
+ wl_input_device_start_pointer_grab(input_device->base(),self->m_resizeGrabber->base(),Compositor::currentTimeMsecs());
}
void ShellSurface::set_toplevel(struct wl_client *client,
struct wl_resource *shell_surface_resource)
{
Q_UNUSED(client);
- Q_UNUSED(shell_surface_resource);
+ ShellSurface *self = static_cast<ShellSurface *>(shell_surface_resource->data);
+ self->m_transientParent = 0;
+ self->m_xOffset = 0;
+ self->m_yOffset = 0;
+
}
void ShellSurface::set_transient(struct wl_client *client,
@@ -129,8 +213,10 @@ void ShellSurface::set_transient(struct wl_client *client,
Q_UNUSED(flags);
ShellSurface *shell_surface = static_cast<ShellSurface *>(shell_surface_resource->data);
ShellSurface *parent_shell_surface = static_cast<ShellSurface *>(parent_shell_surface_resource->data);
- QPointF point = parent_shell_surface->m_surface->pos() + QPoint(x,y);
- shell_surface->m_surface->setPos(point);
+ shell_surface->m_transientParent = parent_shell_surface;
+ shell_surface->m_xOffset = x;
+ shell_surface->m_yOffset = y;
+
}
void ShellSurface::set_fullscreen(struct wl_client *client,
@@ -177,4 +263,156 @@ const struct wl_shell_surface_interface ShellSurface::shell_surface_interface =
ShellSurface::set_maximized
};
+Qt::MouseButton toQtButton(uint32_t button)
+{
+#ifndef BTN_LEFT
+ static const uint32_t BTN_LEFT = 0x110;
+ static const uint32_t BTN_RIGHT = 0x111;
+ static const uint32_t BTN_MIDDLE = 0x112;
+#endif
+ switch (button) {
+ case BTN_LEFT:
+ return Qt::LeftButton;
+ case BTN_RIGHT:
+ return Qt::RightButton;
+ case BTN_MIDDLE:
+ return Qt::MiddleButton;
+ default:
+ return Qt::NoButton;
+ }
+}
+
+ShellSurfaceGrabber::ShellSurfaceGrabber(ShellSurface *shellSurface, const struct wl_pointer_grab_interface *interface)
+ : shell_surface(shellSurface)
+{
+ base()->interface = interface;
+ base()->focus = shell_surface->surface()->base();
+}
+
+ShellSurfaceGrabber::~ShellSurfaceGrabber()
+{
+}
+
+
+void ShellSurfaceGrabber::destroy(wl_listener *listener, wl_resource *resource, uint32_t time)
+{
+ Q_UNUSED(resource);
+ Q_UNUSED(time);
+ //ShellSurfaceGrabber *shell_surface_grabber = container_of(listener, ShellSurfaceGrabber,surface_destroy_listener);
+ Q_ASSERT(false); //hasn't been enabled yet
+ //wl_input_device_end_grab(shell_surface_grabber->base()->input_device,Compositor::currentTimeMsecs());
+}
+
+
+ShellSurfaceResizeGrabber::ShellSurfaceResizeGrabber(ShellSurface *shellSurface)
+ : ShellSurfaceGrabber(shellSurface,&resize_grabber_interface)
+{
+}
+
+void ShellSurfaceResizeGrabber::focus(wl_pointer_grab *grab, uint32_t time, wl_surface *surface, int32_t x, int32_t y)
+{
+}
+
+void ShellSurfaceResizeGrabber::motion(wl_pointer_grab *grab, uint32_t time, int32_t x, int32_t y)
+{
+ //Should be more structured
+ ShellSurfaceResizeGrabber *resize_grabber = reinterpret_cast<ShellSurfaceResizeGrabber *>(grab);
+ ShellSurface *shell_surface = resize_grabber->shell_surface;
+ InputDevice *input_device = reinterpret_cast<InputDevice *>(grab->input_device);
+ int width_delta = grab->x - input_device->base()->x;
+ int height_delta = grab->y - input_device->base()->y;
+ int new_width = resize_grabber->width;
+ int new_height = resize_grabber->height;
+ if (resize_grabber->resize_edges & WL_SHELL_SURFACE_RESIZE_TOP_LEFT) {
+ if (resize_grabber->resize_edges & WL_SHELL_SURFACE_RESIZE_TOP) {
+ if (new_height + height_delta > 0) {
+ new_height += height_delta;
+ } else {
+ new_height = 1;
+ }
+ }
+ if (resize_grabber->resize_edges & WL_SHELL_SURFACE_RESIZE_LEFT) {
+ if (new_width + width_delta > 0) {
+ new_width += width_delta;
+ } else {
+ new_width = 1;
+ }
+ }
+ }
+
+ if (resize_grabber->resize_edges & WL_SHELL_SURFACE_RESIZE_BOTTOM) {
+ if (new_height - height_delta > 0) {
+ new_height -= height_delta;
+ } else {
+ new_height = 1;
+ }
+ }
+ if (resize_grabber->resize_edges & WL_SHELL_SURFACE_RESIZE_RIGHT) {
+ if (new_width - width_delta > 0) {
+ new_width -= width_delta;
+ } else {
+ new_width =1;
+ }
+ }
+
+ shell_surface->sendConfigure(resize_grabber->resize_edges,new_width,new_height);
+}
+
+void ShellSurfaceResizeGrabber::button(wl_pointer_grab *grab, uint32_t time, uint32_t button, int32_t state)
+{
+ Q_UNUSED(time)
+ ShellSurfaceResizeGrabber *self = reinterpret_cast<ShellSurfaceResizeGrabber *>(grab);
+ ShellSurface *shell_surface = self->shell_surface;
+ if (toQtButton(button) == Qt::LeftButton && !state) {
+ wl_input_device_end_pointer_grab(grab->input_device,Compositor::currentTimeMsecs());
+ shell_surface->resetResizeGrabber();
+ delete self;
+ }
+}
+
+const struct wl_pointer_grab_interface ShellSurfaceResizeGrabber::resize_grabber_interface = {
+ ShellSurfaceResizeGrabber::focus,
+ ShellSurfaceResizeGrabber::motion,
+ ShellSurfaceResizeGrabber::button
+};
+
+ShellSurfaceMoveGrabber::ShellSurfaceMoveGrabber(ShellSurface *shellSurface)
+ : ShellSurfaceGrabber(shellSurface,&move_grabber_interface)
+{
+}
+
+void ShellSurfaceMoveGrabber::focus(wl_pointer_grab *grab, uint32_t time, wl_surface *surface, int32_t x, int32_t y)
+{
+}
+
+void ShellSurfaceMoveGrabber::motion(wl_pointer_grab *grab, uint32_t time, int32_t x, int32_t y)
+{
+ ShellSurfaceMoveGrabber *shell_surface_grabber = reinterpret_cast<ShellSurfaceMoveGrabber *>(grab);
+ ShellSurface *shell_surface = shell_surface_grabber->shell_surface;
+ InputDevice *input_device = reinterpret_cast<InputDevice *>(grab->input_device);
+ QPointF pos(input_device->base()->x - shell_surface_grabber->offset_x,
+ input_device->base()->y - shell_surface_grabber->offset_y);
+ shell_surface->surface()->setPos(pos);
+ shell_surface->surface()->damage(QRect(QPoint(0,0),shell_surface->surface()->size()));
+}
+
+void ShellSurfaceMoveGrabber::button(wl_pointer_grab *grab, uint32_t time, uint32_t button, int32_t state)
+{
+ Q_UNUSED(time)
+ ShellSurfaceResizeGrabber *self = reinterpret_cast<ShellSurfaceResizeGrabber *>(grab);
+ ShellSurface *shell_surface = self->shell_surface;
+ if (toQtButton(button) == Qt::LeftButton && !state) {
+ wl_input_device_set_pointer_focus(grab->input_device,0,Compositor::currentTimeMsecs(),0,0);
+ wl_input_device_end_pointer_grab(grab->input_device,Compositor::currentTimeMsecs());
+ shell_surface->resetMoveGrabber();
+ delete self;
+ }
+}
+
+const struct wl_pointer_grab_interface ShellSurfaceMoveGrabber::move_grabber_interface = {
+ ShellSurfaceMoveGrabber::focus,
+ ShellSurfaceMoveGrabber::motion,
+ ShellSurfaceMoveGrabber::button
+};
+
}
diff --git a/src/compositor/wayland_wrapper/wlshellsurface.h b/src/compositor/wayland_wrapper/wlshellsurface.h
index a4eacd7b1..dc6491471 100644
--- a/src/compositor/wayland_wrapper/wlshellsurface.h
+++ b/src/compositor/wayland_wrapper/wlshellsurface.h
@@ -41,12 +41,17 @@
#ifndef WLSHELLSURFACE_H
#define WLSHELLSURFACE_H
+#include "waylandobject.h"
+
#include <wayland-server.h>
namespace Wayland {
class Compositor;
class Surface;
+class ShellSurface;
+class ShellSurfaceResizeGrabber;
+class ShellSurfaceMoveGrabber;
class Shell
{
@@ -68,11 +73,28 @@ class ShellSurface
{
public:
ShellSurface(struct wl_client *client, uint32_t id, Surface *surface);
+ void sendConfigure(uint32_t edges, int32_t width, int32_t height);
+
+ Surface *surface() const;
+ void adjustPosInResize();
+ void adjustPosToTransientParent();
+ void resetResizeGrabber();
+ void resetMoveGrabber();
+
+ ShellSurface *transientParent() const;
private:
struct wl_resource *m_shellSurface;
Surface *m_surface;
+ ShellSurfaceResizeGrabber *m_resizeGrabber;
+ ShellSurfaceMoveGrabber *m_moveGrabber;
+
+ ShellSurface *m_transientParent;
+
+ int32_t m_xOffset;
+ int32_t m_yOffset;
+
static void move(struct wl_client *client,
struct wl_resource *shell_surface_resource,
struct wl_resource *input_device_super,
@@ -108,9 +130,59 @@ private:
struct wl_resource *output);
static const struct wl_shell_surface_interface shell_surface_interface;
+};
+
+class ShellSurfaceGrabber : public Object<wl_pointer_grab>
+{
+public:
+ ShellSurfaceGrabber(ShellSurface *shellSurface, const struct wl_pointer_grab_interface *interface);
+ ~ShellSurfaceGrabber();
+
+ struct wl_listener surface_destroy_listener;
+ static void destroy(struct wl_listener *listener,
+ struct wl_resource *resource, uint32_t time);
+
+ ShellSurface *shell_surface;
+};
+class ShellSurfaceResizeGrabber : public ShellSurfaceGrabber
+{
+public:
+ ShellSurfaceResizeGrabber(ShellSurface *shellSurface);
+
+
+ enum wl_shell_surface_resize resize_edges;
+ int32_t width;
+ int32_t height;
+
+ static void focus(struct wl_pointer_grab *grab, uint32_t time,
+ struct wl_surface *surface, int32_t x, int32_t y);
+ static void motion(struct wl_pointer_grab *grab,
+ uint32_t time, int32_t x, int32_t y);
+ static void button(struct wl_pointer_grab *grab,
+ uint32_t time, uint32_t mouse_grabber_button, int32_t state);
+ static const struct wl_pointer_grab_interface resize_grabber_interface;
};
+class ShellSurfaceMoveGrabber : public ShellSurfaceGrabber
+{
+public:
+ ShellSurfaceMoveGrabber(ShellSurface *shellSurface);
+
+ int32_t offset_x;
+ int32_t offset_y;
+
+ static void focus(struct wl_pointer_grab *grab, uint32_t time,
+ struct wl_surface *surface, int32_t x, int32_t y);
+ static void motion(struct wl_pointer_grab *grab,
+ uint32_t time, int32_t x, int32_t y);
+ static void button(struct wl_pointer_grab *grab,
+ uint32_t time, uint32_t mouse_grabber_button, int32_t state);
+ static const struct wl_pointer_grab_interface move_grabber_interface;
+};
+
+
+
}
#endif // WLSHELLSURFACE_H
diff --git a/src/compositor/wayland_wrapper/wlsubsurface.cpp b/src/compositor/wayland_wrapper/wlsubsurface.cpp
index 564045896..379c23c9d 100644
--- a/src/compositor/wayland_wrapper/wlsubsurface.cpp
+++ b/src/compositor/wayland_wrapper/wlsubsurface.cpp
@@ -91,9 +91,10 @@ SubSurface::~SubSurface()
void SubSurface::setSubSurface(SubSurface *subSurface, int x, int y)
{
- Q_ASSERT(!m_sub_surfaces.contains(subSurface->m_surface->waylandSurface()));
- m_sub_surfaces.append(subSurface->m_surface->waylandSurface());
- subSurface->setParent(this);
+ if (!m_sub_surfaces.contains(subSurface->m_surface->waylandSurface())) {
+ m_sub_surfaces.append(subSurface->m_surface->waylandSurface());
+ subSurface->setParent(this);
+ }
subSurface->m_surface->setPos(QPointF(x,y));
}
diff --git a/src/compositor/wayland_wrapper/wlsurface.cpp b/src/compositor/wayland_wrapper/wlsurface.cpp
index e280ba05a..7afed8daf 100644
--- a/src/compositor/wayland_wrapper/wlsurface.cpp
+++ b/src/compositor/wayland_wrapper/wlsurface.cpp
@@ -146,6 +146,9 @@ bool Surface::visible() const
QPointF Surface::pos() const
{
+ if (m_shellSurface) {
+ m_shellSurface->adjustPosToTransientParent();
+ }
return m_position;
}
@@ -168,6 +171,9 @@ void Surface::setSize(const QSize &size)
m_opaqueRegion = QRegion();
m_inputRegion = QRegion(QRect(QPoint(), size));
m_size = size;
+ if (m_shellSurface) {
+ m_shellSurface->adjustPosInResize();
+ }
m_waylandSurface->sizeChanged();
}
}
diff --git a/src/compositor/wayland_wrapper/wlsurface.h b/src/compositor/wayland_wrapper/wlsurface.h
index 294a467d2..cd069598e 100644
--- a/src/compositor/wayland_wrapper/wlsurface.h
+++ b/src/compositor/wayland_wrapper/wlsurface.h
@@ -118,6 +118,8 @@ public:
Compositor *compositor() const;
+ void damage(const QRect &rect);
+
static const struct wl_surface_interface surface_interface;
private:
@@ -157,7 +159,6 @@ private:
bool postBuffer();
void attach(struct wl_buffer *buffer);
- void damage(const QRect &rect);
static void surface_destroy(struct wl_client *client, struct wl_resource *_surface);
static void surface_attach(struct wl_client *client, struct wl_resource *surface,
diff --git a/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandeglwindow.cpp b/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandeglwindow.cpp
index 44e7fdecc..4db506c18 100644
--- a/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandeglwindow.cpp
+++ b/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandeglwindow.cpp
@@ -70,9 +70,7 @@ QWaylandEglWindow::~QWaylandEglWindow()
m_eglSurface = 0;
}
- if (m_waylandEglWindow) {
- wl_egl_window_destroy(m_waylandEglWindow);
- }
+ wl_egl_window_destroy(m_waylandEglWindow);
}
QWaylandWindow::WindowType QWaylandEglWindow::windowType() const
@@ -82,13 +80,14 @@ QWaylandWindow::WindowType QWaylandEglWindow::windowType() const
void QWaylandEglWindow::setGeometry(const QRect &rect)
{
- QWaylandWindow::setGeometry(rect);
- if (m_waylandEglWindow){
+ int current_width, current_height;
+ wl_egl_window_get_attached_size(m_waylandEglWindow,&current_width,&current_height);
+ if (current_width != rect.width() || current_height != rect.height()) {
+ waitForFrameSync();
wl_egl_window_resize(m_waylandEglWindow, rect.width(), rect.height(), 0, 0);
- QWindowSystemInterface::handleGeometryChange(window(), rect);
}
+ QWaylandWindow::setGeometry(rect);
}
-
QSurfaceFormat QWaylandEglWindow::format() const
{
return m_format;
@@ -96,9 +95,6 @@ QSurfaceFormat QWaylandEglWindow::format() const
EGLSurface QWaylandEglWindow::eglSurface() const
{
- if (!m_waylandEglWindow)
- return 0;
-
if (!m_eglSurface) {
m_eglConfig = q_configFromGLFormat(m_eglIntegration->eglDisplay(), window()->format(), true);
const_cast<QWaylandEglWindow *>(this)->m_format = q_glFormatFromConfig(m_eglIntegration->eglDisplay(),m_eglConfig);
diff --git a/src/plugins/platforms/wayland/qwaylanddecoration.cpp b/src/plugins/platforms/wayland/qwaylanddecoration.cpp
new file mode 100644
index 000000000..749d12611
--- /dev/null
+++ b/src/plugins/platforms/wayland/qwaylanddecoration.cpp
@@ -0,0 +1,189 @@
+#include "qwaylanddecoration.h"
+
+#include "qwaylandwindow.h"
+#include "qwaylandshmbackingstore.h"
+#include "qwaylandshellsurface.h"
+#include "qwaylandinputdevice.h"
+
+#include <QtGui/QGuiApplication>
+#include <QtGui/QCursor>
+#include <QtGui/QPainter>
+#include <QtGui/QRadialGradient>
+QWaylandDecoration::QWaylandDecoration(QWindow *window, QWaylandShmBackingStore *backing_store)
+ : m_window(window)
+ , m_wayland_window(static_cast<QWaylandWindow *>(window->handle()))
+ , m_backing_store(backing_store)
+ , m_margins(3,30,3,3)
+ , m_mouseButtons(Qt::NoButton)
+ , m_hasSetCursor(false)
+{
+ m_wayland_window->setDecoration(this);
+ QTextOption option(Qt::AlignHCenter | Qt::AlignVCenter);
+ option.setWrapMode(QTextOption::NoWrap);
+ m_windowTitle.setTextOption(option);
+}
+
+QWaylandDecoration::~QWaylandDecoration()
+{
+ m_wayland_window->setDecoration(0);
+}
+
+void QWaylandDecoration::paintDecoration()
+{
+ QRect surfaceRect(QPoint(), m_backing_store->entireSurface()->size());
+ QRect clips[] =
+ {
+ QRect(0, 0, surfaceRect.width(), m_margins.top()),
+ QRect(0, surfaceRect.height() - m_margins.bottom(), surfaceRect.width(), m_margins.bottom()),
+ QRect(0, m_margins.top(), m_margins.left(), surfaceRect.height() - m_margins.top() - m_margins.bottom()),
+ QRect(surfaceRect.width() - m_margins.right(), m_margins.top(), m_margins.left(), surfaceRect.height() - m_margins.top() - m_margins.bottom())
+ };
+ QRect top = clips[0];
+ QPainter p(m_backing_store->entireSurface());
+ p.setRenderHint(QPainter::Antialiasing);
+ QPoint gradCenter(top.center()+ QPoint(30,60));
+ QRadialGradient grad(gradCenter, top.width() / 2, gradCenter);
+ QColor base(90, 90, 100);
+ grad.setColorAt(1, base);
+ grad.setColorAt(0, base.lighter(123));
+ QPainterPath roundedRect;
+ roundedRect.addRoundedRect(surfaceRect, 6, 6);
+ for (int i = 0; i < 4; ++i) {
+ p.save();
+ p.setClipRect(clips[i]);
+ p.fillPath(roundedRect, grad);
+ p.restore();
+ }
+
+
+ QString windowTitleText = m_window->windowTitle();
+ if (!windowTitleText.isEmpty()) {
+ if (m_windowTitle.text() != windowTitleText) {
+ m_windowTitle.setText(windowTitleText);
+ m_windowTitle.prepare();
+ }
+ p.save();
+ p.setClipRect(top);
+ p.setPen(QColor(0xee,0xee,0xee));
+ QSizeF size = m_windowTitle.size();
+ int dx = (top.width() - size.width()) /2;
+ int dy = (top.height()- size.height()) /2;
+ QPoint windowTitlePoint(top.topLeft().x() + dx,
+ top.topLeft().y() + dy);
+ p.drawStaticText(windowTitlePoint,m_windowTitle);
+ p.restore();
+ }
+}
+
+void QWaylandDecoration::handleMouse(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global, Qt::MouseButtons b, Qt::KeyboardModifiers mods)
+
+{
+ //figure out what area mouse is in
+ if (local.y() <= m_margins.top()) {
+ processMouseTop(inputDevice,local,b,mods);
+ } else if (local.y() > m_window->height() - m_margins.bottom()) {
+ processMouseBottom(inputDevice,local,b,mods);
+ } else if (local.x() <= m_margins.left()) {
+ processMouseLeft(inputDevice,local,b,mods);
+ } else if (local.x() > m_window->width() - m_margins.right()) {
+ processMouseRight(inputDevice,local,b,mods);
+ } else {
+ restoreMouseCursor();
+ }
+ m_mouseButtons = b;
+}
+
+void QWaylandDecoration::restoreMouseCursor()
+{
+ if (m_hasSetCursor) {
+ QGuiApplication::restoreOverrideCursor();
+ m_hasSetCursor = false;
+ }
+}
+
+bool QWaylandDecoration::inMouseButtonPressedState() const
+{
+ return m_mouseButtons & Qt::NoButton;
+}
+
+void QWaylandDecoration::startResize(QWaylandInputDevice *inputDevice, enum wl_shell_surface_resize resize, Qt::MouseButtons buttons)
+{
+ if (isLeftClicked(buttons)) {
+ m_wayland_window->shellSurface()->resize(inputDevice, resize);
+ inputDevice->removeMouseButtonFromState(Qt::LeftButton);
+ }
+}
+
+void QWaylandDecoration::startMove(QWaylandInputDevice *inputDevice, Qt::MouseButtons buttons)
+{
+ if (isLeftClicked(buttons)) {
+ m_wayland_window->shellSurface()->move(inputDevice);
+ inputDevice->removeMouseButtonFromState(Qt::LeftButton);
+ }
+}
+
+void QWaylandDecoration::processMouseTop(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b, Qt::KeyboardModifiers mods)
+{
+ if (local.y() <= m_margins.bottom()) {
+ if (local.x() <= margins().left()) {
+ //top left bit
+ startResize(inputDevice,WL_SHELL_SURFACE_RESIZE_TOP_LEFT,b);
+ } else if (local.x() > m_window->width() - margins().right()) {
+ //top right bit
+ startResize(inputDevice,WL_SHELL_SURFACE_RESIZE_TOP_RIGHT,b);
+ } else {
+ //top reszie bit
+ overrideCursor(Qt::SplitVCursor);
+ startResize(inputDevice,WL_SHELL_SURFACE_RESIZE_TOP,b);
+ }
+ } else {
+ restoreMouseCursor();
+ startMove(inputDevice,b);
+ }
+
+}
+
+void QWaylandDecoration::processMouseBottom(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b, Qt::KeyboardModifiers mods)
+{
+ if (local.x() <= margins().left()) {
+ //bottom left bit
+ startResize(inputDevice, WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT,b);
+ } else if (local.x() > m_window->width() - margins().right()) {
+ //bottom right bit
+ startResize(inputDevice, WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT,b);
+ } else {
+ //bottom bit
+ overrideCursor(Qt::SplitVCursor);
+ startResize(inputDevice,WL_SHELL_SURFACE_RESIZE_BOTTOM,b);
+ }
+}
+
+void QWaylandDecoration::processMouseLeft(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b, Qt::KeyboardModifiers mods)
+{
+ Q_UNUSED(local);
+ Q_UNUSED(mods);
+ overrideCursor(Qt::SplitHCursor);
+ startResize(inputDevice,WL_SHELL_SURFACE_RESIZE_LEFT,b);
+}
+
+void QWaylandDecoration::processMouseRight(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b, Qt::KeyboardModifiers mods)
+{
+ Q_UNUSED(local);
+ Q_UNUSED(mods);
+ overrideCursor(Qt::SplitHCursor);
+ startResize(inputDevice, WL_SHELL_SURFACE_RESIZE_RIGHT,b);
+}
+
+bool QWaylandDecoration::isLeftClicked(Qt::MouseButtons newMouseButtonState)
+{
+ if ((!m_mouseButtons & Qt::LeftButton) && (newMouseButtonState & Qt::LeftButton))
+ return true;
+ return false;
+}
+
+bool QWaylandDecoration::isLeftReleased(Qt::MouseButtons newMouseButtonState)
+{
+ if ((m_mouseButtons & Qt::LeftButton) && !(newMouseButtonState & Qt::LeftButton))
+ return true;
+ return false;
+}
diff --git a/src/plugins/platforms/wayland/qwaylanddecoration.h b/src/plugins/platforms/wayland/qwaylanddecoration.h
new file mode 100644
index 000000000..df237f6f0
--- /dev/null
+++ b/src/plugins/platforms/wayland/qwaylanddecoration.h
@@ -0,0 +1,80 @@
+#ifndef QWAYLANDDECORATION_H
+#define QWAYLANDDECORATION_H
+
+#include <QtCore/QMargins>
+#include <QtCore/QPointF>
+#include <QtGui/QGuiApplication>
+#include <QtGui/QCursor>
+#include <QtGui/QImage>
+#include <QtGui/QStaticText>
+
+#include <wayland-client.h>
+
+#include <QtCore/QDebug>
+
+class QWindow;
+class QPaintDevice;
+class QPainter;
+class QEvent;
+class QWaylandWindow;
+class QWaylandShmBackingStore;
+class QWaylandInputDevice;
+
+class QWaylandDecoration
+{
+public:
+ QWaylandDecoration(QWindow *window, QWaylandShmBackingStore *backing_store);
+ ~QWaylandDecoration();
+ void paintDecoration();
+ void handleMouse(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global,Qt::MouseButtons b,Qt::KeyboardModifiers mods);
+ void restoreMouseCursor();
+ bool inMouseButtonPressedState() const;
+
+ void startResize(QWaylandInputDevice *inputDevice,enum wl_shell_surface_resize resize, Qt::MouseButtons buttons);
+ void startMove(QWaylandInputDevice *inputDevice, Qt::MouseButtons buttons);
+ QMargins margins() const;
+private:
+ void overrideCursor(Qt::CursorShape shape);
+
+ void processMouseTop(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b,Qt::KeyboardModifiers mods);
+ void processMouseBottom(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b,Qt::KeyboardModifiers mods);
+ void processMouseLeft(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b,Qt::KeyboardModifiers mods);
+ void processMouseRight(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b,Qt::KeyboardModifiers mods);
+
+ bool isLeftClicked(Qt::MouseButtons newMouseButtonState);
+ bool isLeftReleased(Qt::MouseButtons newMouseButtonState);
+
+ QWindow *m_window;
+ QWaylandWindow *m_wayland_window;
+ QWaylandShmBackingStore *m_backing_store;
+
+ QMargins m_margins;
+ bool m_hasSetCursor;
+ Qt::CursorShape m_cursorShape;
+ Qt::MouseButtons m_mouseButtons;
+
+ QStaticText m_windowTitle;
+
+ QImage m_borderImage;
+};
+
+inline QMargins QWaylandDecoration::margins() const
+{
+ return m_margins;
+}
+
+inline void QWaylandDecoration::overrideCursor(Qt::CursorShape shape)
+{
+ if (m_hasSetCursor) {
+ if (m_cursorShape != shape) {
+ QGuiApplication::changeOverrideCursor(QCursor(shape));
+ m_cursorShape = shape;
+ }
+ } else {
+ QGuiApplication::setOverrideCursor(QCursor(shape));
+ m_hasSetCursor = true;
+ m_cursorShape = shape;
+ }
+}
+
+#endif // QWAYLANDDECORATION_H
diff --git a/src/plugins/platforms/wayland/qwaylanddisplay.cpp b/src/plugins/platforms/wayland/qwaylanddisplay.cpp
index 15551e7c6..be8a09678 100644
--- a/src/plugins/platforms/wayland/qwaylanddisplay.cpp
+++ b/src/plugins/platforms/wayland/qwaylanddisplay.cpp
@@ -101,7 +101,6 @@ QWaylandInputDevice *QWaylandDisplay::lastKeyboardFocusInputDevice() const
void QWaylandDisplay::setLastKeyboardFocusInputDevice(QWaylandInputDevice *device)
{
- qDebug() << "setting last keyboard focus input device" << device;
mLastKeyboardFocusInputDevice = device;
}
diff --git a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp
index ac5ac8b17..2be5946b2 100644
--- a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp
+++ b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp
@@ -121,12 +121,24 @@ struct wl_data_device *QWaylandInputDevice::transferDevice() const
return mTransferDevice;
}
+struct wl_input_device *QWaylandInputDevice::handle() const
+{
+ return mInputDevice;
+}
+
+void QWaylandInputDevice::removeMouseButtonFromState(Qt::MouseButton button)
+{
+ mButtons = mButtons & !button;
+}
+
void QWaylandInputDevice::inputHandleMotion(void *data,
struct wl_input_device *input_device,
uint32_t time,
int32_t surface_x, int32_t surface_y)
{
Q_UNUSED(input_device);
+ Q_UNUSED(surface_x);
+ Q_UNUSED(surface_y);
QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data;
QWaylandWindow *window = inputDevice->mPointerFocus;
@@ -142,9 +154,13 @@ void QWaylandInputDevice::inputHandleMotion(void *data,
inputDevice->mSurfacePos = pos;
inputDevice->mGlobalPos = global;
inputDevice->mTime = time;
- QWindowSystemInterface::handleMouseEvent(window->window(),
- time, pos, global,
- inputDevice->mButtons);
+
+ window->handleMouse(inputDevice,
+ time,
+ inputDevice->mSurfacePos,
+ inputDevice->mSurfacePos,
+ inputDevice->mButtons,
+ Qt::NoModifier);
}
void QWaylandInputDevice::inputHandleButton(void *data,
@@ -156,11 +172,6 @@ void QWaylandInputDevice::inputHandleButton(void *data,
QWaylandWindow *window = inputDevice->mPointerFocus;
Qt::MouseButton qt_button;
- if (window == NULL) {
- /* We destroyed the pointer focus surface, but the server
- * didn't get the message yet. */
- return;
- }
// translate from kernel (input.h) 'button' to corresponding Qt:MouseButton.
// The range of mouse values is 0x110 <= mouse_button < 0x120, the first Joystick button.
@@ -190,11 +201,15 @@ void QWaylandInputDevice::inputHandleButton(void *data,
inputDevice->mButtons &= ~qt_button;
inputDevice->mTime = time;
- QWindowSystemInterface::handleMouseEvent(window->window(),
- time,
- inputDevice->mSurfacePos,
- inputDevice->mGlobalPos,
- inputDevice->mButtons);
+
+ if (window) {
+ window->handleMouse(inputDevice,
+ time,
+ inputDevice->mSurfacePos,
+ inputDevice->mSurfacePos,
+ inputDevice->mButtons,
+ Qt::NoModifier);
+ }
}
void QWaylandInputDevice::inputHandleAxis(void *data,
@@ -351,7 +366,7 @@ void QWaylandInputDevice::inputHandlePointerEnter(void *data,
Q_ASSERT(surface);
QWaylandWindow *window = (QWaylandWindow *) wl_surface_get_user_data(surface);
- QWindowSystemInterface::handleEnterEvent(window->window());
+ window->handleMouseEnter();
inputDevice->mPointerFocus = window;
inputDevice->mTime = time;
@@ -368,8 +383,9 @@ void QWaylandInputDevice::inputHandlePointerLeave(void *data,
Q_ASSERT(surface);
QWaylandWindow *window = (QWaylandWindow *) wl_surface_get_user_data(surface);
- QWindowSystemInterface::handleLeaveEvent(window->window());
+ window->handleMouseLeave();
inputDevice->mPointerFocus = 0;
+ inputDevice->mButtons = Qt::NoButton;
inputDevice->mTime = time;
}
@@ -494,7 +510,8 @@ void QWaylandInputDevice::handleTouchPoint(int id, int x, int y, Qt::TouchPointS
return;
tp.area = QRectF(0, 0, 8, 8);
- tp.area.moveCenter(win->window()->mapToGlobal(QPoint(x, y)));
+ QMargins margins = win->frameMargins();
+ tp.area.moveCenter(win->window()->mapToGlobal(QPoint(x+margins.left(), y+margins.top())));
}
tp.state = state;
diff --git a/src/plugins/platforms/wayland/qwaylandinputdevice.h b/src/plugins/platforms/wayland/qwaylandinputdevice.h
index 9d512a69a..7c80c1fca 100644
--- a/src/plugins/platforms/wayland/qwaylandinputdevice.h
+++ b/src/plugins/platforms/wayland/qwaylandinputdevice.h
@@ -63,11 +63,13 @@ public:
void attach(QWaylandBuffer *buffer, int x, int y);
void handleWindowDestroyed(QWaylandWindow *window);
struct wl_input_device *wl_input_device() const { return mInputDevice; }
- QWaylandWindow *pointerFocus() const { return mPointerFocus; }
void setTransferDevice(struct wl_data_device *device);
struct wl_data_device *transferDevice() const;
+ struct wl_input_device *handle() const;
+
+ void removeMouseButtonFromState(Qt::MouseButton button);
private:
QWaylandDisplay *mQDisplay;
struct wl_display *mDisplay;
diff --git a/src/plugins/platforms/wayland/qwaylandshell.cpp b/src/plugins/platforms/wayland/qwaylandshell.cpp
index 1118f0d3f..86ff5b12b 100644
--- a/src/plugins/platforms/wayland/qwaylandshell.cpp
+++ b/src/plugins/platforms/wayland/qwaylandshell.cpp
@@ -51,7 +51,7 @@ QWaylandShell::QWaylandShell(QWaylandDisplay *display, uint32_t id, uint32_t ver
m_shell = static_cast<struct wl_shell *>(wl_display_bind(m_display->wl_display(), id, &wl_shell_interface));
}
-QWaylandShellSurface *QWaylandShell::createShellSurface(QWaylandWindow *window)
+QWaylandShellSurface *QWaylandShell::getShellSurface(QWaylandWindow *window)
{
Q_ASSERT(window->wl_surface());
struct wl_shell_surface *shell_surface = wl_shell_get_shell_surface(m_shell,window->wl_surface());
diff --git a/src/plugins/platforms/wayland/qwaylandshell.h b/src/plugins/platforms/wayland/qwaylandshell.h
index e4dbad57b..2f2a92f4c 100644
--- a/src/plugins/platforms/wayland/qwaylandshell.h
+++ b/src/plugins/platforms/wayland/qwaylandshell.h
@@ -52,7 +52,7 @@ class QWaylandShell
public:
QWaylandShell(QWaylandDisplay *display, uint32_t id, uint32_t version);
- QWaylandShellSurface *createShellSurface(QWaylandWindow *window);
+ QWaylandShellSurface *getShellSurface(QWaylandWindow *window);
private:
struct wl_shell *m_shell;
diff --git a/src/plugins/platforms/wayland/qwaylandshellsurface.cpp b/src/plugins/platforms/wayland/qwaylandshellsurface.cpp
index 79788a31b..69848f282 100644
--- a/src/plugins/platforms/wayland/qwaylandshellsurface.cpp
+++ b/src/plugins/platforms/wayland/qwaylandshellsurface.cpp
@@ -43,6 +43,10 @@
#include "qwaylanddisplay.h"
#include "qwaylandwindow.h"
+#include "qwaylandinputdevice.h"
+#include "qwaylanddecoration.h"
+
+#include <QtCore/QDebug>
QWaylandShellSurface::QWaylandShellSurface(struct wl_shell_surface *shell_surface, QWaylandWindow *window)
: m_shell_surface(shell_surface)
@@ -51,6 +55,38 @@ QWaylandShellSurface::QWaylandShellSurface(struct wl_shell_surface *shell_surfac
wl_shell_surface_add_listener(m_shell_surface,&m_shell_surface_listener,this);
}
+void QWaylandShellSurface::resize(QWaylandInputDevice *inputDevice, enum wl_shell_surface_resize edges)
+{
+ wl_shell_surface_resize(m_shell_surface,inputDevice->wl_input_device(),QWaylandDisplay::currentTimeMillisec(),edges);
+}
+
+void QWaylandShellSurface::move(QWaylandInputDevice *inputDevice)
+{
+ wl_shell_surface_move(m_shell_surface,inputDevice->wl_input_device(),QWaylandDisplay::currentTimeMillisec());
+}
+
+void QWaylandShellSurface::setTopLevel()
+{
+ wl_shell_surface_set_toplevel(m_shell_surface);
+}
+
+void QWaylandShellSurface::updateTransientParent(QWindow *parent)
+{
+ QWaylandWindow *parent_wayland_window = static_cast<QWaylandWindow *>(parent->handle());
+ if (!parent_wayland_window || !parent_wayland_window->shellSurface())
+ return;
+
+ QPoint transientPos = m_window->geometry().topLeft();
+ if (parent_wayland_window->decoration()) {
+ transientPos.setX(transientPos.x() + parent_wayland_window->decoration()->margins().left());
+ transientPos.setY(transientPos.y() + parent_wayland_window->decoration()->margins().top());
+ }
+ wl_shell_surface_set_transient(m_shell_surface,
+ parent_wayland_window->shellSurface()->m_shell_surface,
+ transientPos.x(),
+ transientPos.y(),
+ 0);
+}
void QWaylandShellSurface::configure(void *data,
wl_shell_surface *wl_shell_surface,
@@ -61,7 +97,7 @@ void QWaylandShellSurface::configure(void *data,
{
Q_UNUSED(wl_shell_surface);
QWaylandShellSurface *shell_surface = static_cast<QWaylandShellSurface *>(data);
- shell_surface->m_window->configure(time,edges,0,0,width,height);
+ shell_surface->m_window->configure(time,edges,width,height);
}
void QWaylandShellSurface::popup_done(void *data,
diff --git a/src/plugins/platforms/wayland/qwaylandshellsurface.h b/src/plugins/platforms/wayland/qwaylandshellsurface.h
index 4c77b70f8..e7e46ab6d 100644
--- a/src/plugins/platforms/wayland/qwaylandshellsurface.h
+++ b/src/plugins/platforms/wayland/qwaylandshellsurface.h
@@ -42,15 +42,25 @@
#ifndef QWAYLANDSHELLSURFACE_H
#define QWAYLANDSHELLSURFACE_H
-#include <inttypes.h>
+#include <QtCore/QSize>
+
+#include <wayland-client.h>
class QWaylandWindow;
+class QWaylandInputDevice;
+class QWindow;
class QWaylandShellSurface
{
public:
QWaylandShellSurface(struct wl_shell_surface *shell_surface, QWaylandWindow *window);
+ void resize(QWaylandInputDevice *inputDevice, enum wl_shell_surface_resize edges);
+ void move(QWaylandInputDevice *inputDevice);
+
+ void setTopLevel();
+ void updateTransientParent(QWindow *parent);
+
struct wl_shell_surface *handle() const { return m_shell_surface; }
private:
diff --git a/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp b/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp
index 6aafd1c98..0d4d06f82 100644
--- a/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp
+++ b/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp
@@ -45,6 +45,9 @@
#include "qwaylanddisplay.h"
#include "qwaylandshmwindow.h"
#include "qwaylandscreen.h"
+#include "qwaylanddecoration.h"
+
+#include <QtGui/QPainter>
#include <wayland-client.h>
#include <unistd.h>
@@ -55,27 +58,28 @@
QT_BEGIN_NAMESPACE
QWaylandShmBuffer::QWaylandShmBuffer(QWaylandDisplay *display,
- const QSize &size, QImage::Format format)
+ const QSize &size, QImage::Format format)
+ : mMarginsImage(0)
{
int stride = size.width() * 4;
int alloc = stride * size.height();
char filename[] = "/tmp/wayland-shm-XXXXXX";
int fd = mkstemp(filename);
if (fd < 0)
- qWarning("open %s failed: %s", filename, strerror(errno));
+ qWarning("open %s failed: %s", filename, strerror(errno));
if (ftruncate(fd, alloc) < 0) {
- qWarning("ftruncate failed: %s", strerror(errno));
- close(fd);
- return;
+ qWarning("ftruncate failed: %s", strerror(errno));
+ close(fd);
+ return;
}
uchar *data = (uchar *)
- mmap(NULL, alloc, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ mmap(NULL, alloc, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
unlink(filename);
if (data == (uchar *) MAP_FAILED) {
- qWarning("mmap /dev/zero failed: %s", strerror(errno));
- close(fd);
- return;
+ qWarning("mmap /dev/zero failed: %s", strerror(errno));
+ close(fd);
+ return;
}
mImage = QImage(data, size.width(), size.height(), stride, format);
@@ -92,57 +96,194 @@ QWaylandShmBuffer::~QWaylandShmBuffer(void)
wl_shm_pool_destroy(mShmPool);
}
+QImage *QWaylandShmBuffer::imageInsideMargins(const QMargins &margins)
+{
+ if (!margins.isNull() && margins != mMargins) {
+ if (mMarginsImage) {
+ delete mMarginsImage;
+ }
+ uchar *bits = const_cast<uchar *>(mImage.constBits());
+ uchar *b_s_data = bits + margins.top() * mImage.bytesPerLine() + margins.left() * 4;
+ int b_s_width = mImage.size().width() - margins.left() - margins.right();
+ int b_s_height = mImage.size().height() - margins.top() - margins.bottom();
+ mMarginsImage = new QImage(b_s_data, b_s_width,b_s_height,mImage.bytesPerLine(),mImage.format());
+ }
+ if (margins.isNull()) {
+ delete mMarginsImage;
+ mMarginsImage = 0;
+ }
+
+ mMargins = margins;
+ if (!mMarginsImage)
+ return &mImage;
+
+ return mMarginsImage;
+
+}
+
QWaylandShmBackingStore::QWaylandShmBackingStore(QWindow *window)
: QPlatformBackingStore(window)
- , mBuffer(0)
, mDisplay(QWaylandScreen::waylandScreenFromWindow(window)->display())
+ , mFrontBuffer(0)
+ , mBackBuffer(0)
+ , mFrontBufferIsDirty(false)
+ , mPainting(false)
+ , mWindowDecoration(0)
+ , mFrameCallback(0)
{
}
QWaylandShmBackingStore::~QWaylandShmBackingStore()
{
+// if (mFrontBuffer == waylandWindow()->attached())
+// waylandWindow()->attach(0);
+
+ if (mFrontBuffer != mBackBuffer)
+ delete mFrontBuffer;
+
+ delete mBackBuffer;
}
QPaintDevice *QWaylandShmBackingStore::paintDevice()
{
- return mBuffer->image();
+ if (!mWindowDecoration)
+ return mBackBuffer->image();
+ return mBackBuffer->imageInsideMargins(mWindowDecoration->margins());
}
void QWaylandShmBackingStore::beginPaint(const QRegion &)
{
- QWaylandShmWindow *waylandWindow = static_cast<QWaylandShmWindow *>(window()->handle());
- Q_ASSERT(waylandWindow->windowType() == QWaylandWindow::Shm);
- waylandWindow->waitForFrameSync();
+ mPainting = true;
+ ensureSize();
+
+ if (waylandWindow()->attached() && mBackBuffer == waylandWindow()->attached()) {
+ QWaylandShmWindow *waylandWindow = static_cast<QWaylandShmWindow *>(window()->handle());
+ Q_ASSERT(waylandWindow->windowType() == QWaylandWindow::Shm);
+ waylandWindow->waitForFrameSync();
+ }
+
+}
+
+void QWaylandShmBackingStore::endPaint()
+{
+ mPainting = false;
+}
+
+void QWaylandShmBackingStore::ensureSize()
+{
+ bool decoration = false;
+ switch (window()->windowType()) {
+ case Qt::Window:
+ case Qt::Widget:
+ case Qt::Dialog:
+ case Qt::Tool:
+ case Qt::Drawer:
+ decoration = true;
+ break;
+ default:
+ break;
+ }
+ if (window()->windowFlags() & Qt::FramelessWindowHint) {
+ decoration = false;
+ }
+
+ if (decoration) {
+ if (!mWindowDecoration) {
+ mWindowDecoration = new QWaylandDecoration(window(), this);
+ }
+ } else {
+ delete mWindowDecoration;
+ mWindowDecoration = 0;
+ }
+ resize(mRequestedSize);
}
void QWaylandShmBackingStore::flush(QWindow *window, const QRegion &region, const QPoint &offset)
{
Q_UNUSED(window);
Q_UNUSED(offset);
- QWaylandShmWindow *waylandWindow = static_cast<QWaylandShmWindow *>(window->handle());
- Q_ASSERT(waylandWindow->windowType() == QWaylandWindow::Shm);
+ Q_ASSERT(waylandWindow()->windowType() == QWaylandWindow::Shm);
+
+ mFrontBuffer = mBackBuffer;
+
+ if (mFrameCallback) {
+ mFrontBufferIsDirty = true;
+ return;
+ }
+
+ mFrameCallback = wl_surface_frame(waylandWindow()->wl_surface());
+ wl_callback_add_listener(mFrameCallback,&frameCallbackListener,this);
+ QMargins margins = windowDecorationMargins();
+
+ if (waylandWindow()->attached() != mFrontBuffer) {
+ delete waylandWindow()->attached();
+ waylandWindow()->attach(mFrontBuffer);
+ }
+
QVector<QRect> rects = region.rects();
for (int i = 0; i < rects.size(); i++) {
- const QRect rect = rects.at(i);
- waylandWindow->damage(rect);
+ QRect rect = rects.at(i);
+ rect.translate(margins.left(),margins.top());
+ waylandWindow()->damage(rect);
}
+ mFrontBufferIsDirty = false;
}
void QWaylandShmBackingStore::resize(const QSize &size, const QRegion &)
{
- QWaylandShmWindow *waylandWindow = static_cast<QWaylandShmWindow *>(window()->handle());
+ mRequestedSize = size;
+}
+
+void QWaylandShmBackingStore::resize(const QSize &size)
+{
+
+ QMargins margins = windowDecorationMargins();
+ QSize sizeWithMargins = size + QSize(margins.left()+margins.right(),margins.top()+margins.bottom());
QImage::Format format = QPlatformScreen::platformScreenForWindow(window())->format();
- if (mBuffer != NULL && mBuffer->size() == size)
- return;
+ if (mBackBuffer != NULL && mBackBuffer->size() == sizeWithMargins)
+ return;
- if (mBuffer != NULL)
- delete mBuffer;
+ if (mBackBuffer != mFrontBuffer) {
+ delete mBackBuffer; //we delete the attached buffer when we flush
+ }
+
+ mBackBuffer = new QWaylandShmBuffer(mDisplay, sizeWithMargins, format);
- mBuffer = new QWaylandShmBuffer(mDisplay, size, format);
+ if (mWindowDecoration)
+ mWindowDecoration->paintDecoration();
+}
- waylandWindow->attach(mBuffer);
+QImage *QWaylandShmBackingStore::entireSurface() const
+{
+ return mBackBuffer->image();
}
+void QWaylandShmBackingStore::done(void *data, wl_callback *callback, uint32_t time)
+{
+ Q_UNUSED(callback);
+ Q_UNUSED(time);
+ QWaylandShmBackingStore *self =
+ static_cast<QWaylandShmBackingStore *>(data);
+ QWaylandWindow *window = self->waylandWindow();
+ wl_callback_destroy(self->mFrameCallback);
+ self->mFrameCallback = 0;
+ if (self->mFrontBuffer != self->waylandWindow()->attached()) {
+ delete self->waylandWindow()->attached();
+ self->waylandWindow()->attach(self->mFrontBuffer);
+ }
+
+ if (self->mFrontBufferIsDirty && !self->mPainting) {
+ self->mFrontBufferIsDirty = false;
+ self->mFrameCallback = wl_surface_frame(self->waylandWindow()->wl_surface());
+ wl_callback_add_listener(self->mFrameCallback,&self->frameCallbackListener,self);
+ self->waylandWindow()->damage(QRect(QPoint(0,0),self->mFrontBuffer->size()));
+ }
+}
+
+const struct wl_callback_listener QWaylandShmBackingStore::frameCallbackListener = {
+ QWaylandShmBackingStore::done
+};
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wayland/qwaylandshmbackingstore.h b/src/plugins/platforms/wayland/qwaylandshmbackingstore.h
index e1940776c..d61df2041 100644
--- a/src/plugins/platforms/wayland/qwaylandshmbackingstore.h
+++ b/src/plugins/platforms/wayland/qwaylandshmbackingstore.h
@@ -43,6 +43,10 @@
#define QWAYLANDSHMBACKINGSTORE_H
#include "qwaylandbuffer.h"
+
+#include "qwaylanddecoration.h"
+#include "qwaylandwindow.h"
+
#include <QtGui/QPlatformBackingStore>
#include <QtGui/QImage>
#include <QtGui/QPlatformWindow>
@@ -54,13 +58,17 @@ class QWaylandDisplay;
class QWaylandShmBuffer : public QWaylandBuffer {
public:
QWaylandShmBuffer(QWaylandDisplay *display,
- const QSize &size, QImage::Format format);
+ const QSize &size, QImage::Format format);
~QWaylandShmBuffer();
QSize size() const { return mImage.size(); }
QImage *image() { return &mImage; }
+
+ QImage *imageInsideMargins(const QMargins &margins);
private:
QImage mImage;
struct wl_shm_pool *mShmPool;
+ QMargins mMargins;
+ QImage *mMarginsImage;
};
class QWaylandShmBackingStore : public QPlatformBackingStore
@@ -72,13 +80,47 @@ public:
QPaintDevice *paintDevice();
void flush(QWindow *window, const QRegion &region, const QPoint &offset);
void resize(const QSize &size, const QRegion &staticContents);
+ void resize(const QSize &size);
void beginPaint(const QRegion &);
+ void endPaint();
+
+ QMargins windowDecorationMargins() const;
+ QImage *entireSurface() const;
+ void ensureSize();
+
+ QWaylandWindow *waylandWindow() const;
+ void iterateBuffer();
private:
- QWaylandShmBuffer *mBuffer;
QWaylandDisplay *mDisplay;
+ QWaylandShmBuffer *mFrontBuffer;
+ QWaylandShmBuffer *mBackBuffer;
+ bool mFrontBufferIsDirty;
+ bool mPainting;
+
+ QWaylandDecoration *mWindowDecoration;
+ QSize mRequestedSize;
+ Qt::WindowFlags mCurrentWindowFlags;
+
+ static const struct wl_callback_listener frameCallbackListener;
+ static void done(void *data,
+ struct wl_callback *callback,
+ uint32_t time);
+ struct wl_callback *mFrameCallback;
};
+inline QMargins QWaylandShmBackingStore::windowDecorationMargins() const
+{
+ if (mWindowDecoration)
+ return mWindowDecoration->margins();
+ return QMargins();
+}
+
+inline QWaylandWindow *QWaylandShmBackingStore::waylandWindow() const
+{
+ return static_cast<QWaylandWindow *>(window()->handle());
+}
+
QT_END_NAMESPACE
#endif
diff --git a/src/plugins/platforms/wayland/qwaylandsubsurface.cpp b/src/plugins/platforms/wayland/qwaylandsubsurface.cpp
index 642d3b450..404d7e029 100644
--- a/src/plugins/platforms/wayland/qwaylandsubsurface.cpp
+++ b/src/plugins/platforms/wayland/qwaylandsubsurface.cpp
@@ -45,6 +45,8 @@
#include "wayland-sub-surface-extension-client-protocol.h"
+#include <QtCore/QDebug>
+
QWaylandSubSurfaceExtension::QWaylandSubSurfaceExtension(QWaylandDisplay *display, uint32_t id)
{
m_sub_surface_extension = static_cast<struct wl_sub_surface_extension *>(
@@ -72,8 +74,33 @@ void QWaylandSubSurface::setParent(const QWaylandWindow *parent)
{
QWaylandSubSurface *parentSurface = parent? parent->subSurfaceWindow():0;
if (parentSurface) {
- int x = m_window->geometry().x();
- int y = m_window->geometry().y();
+ int x = m_window->geometry().x() + parent->frameMargins().left();
+ int y = m_window->geometry().y() + parent->frameMargins().top();
wl_sub_surface_attach_sub_surface(parentSurface->m_sub_surface,m_sub_surface,x,y);
}
}
+
+static void setPositionToParent(QWaylandWindow *parentWaylandWindow)
+{
+ QObjectList children = parentWaylandWindow->window()->children();
+ for (int i = 0; i < children.size(); i++) {
+ QWindow *childWindow = qobject_cast<QWindow *>(children.at(i));
+ if (!childWindow)
+ continue;
+
+ if (childWindow->handle()) {
+ QWaylandWindow *waylandWindow = static_cast<QWaylandWindow *>(childWindow->handle());
+ waylandWindow->subSurfaceWindow()->setParent(parentWaylandWindow);
+ setPositionToParent(waylandWindow);
+ }
+ }
+}
+
+void QWaylandSubSurface::adjustPositionOfChildren()
+{
+ QWindow *window = m_window->window();
+ if (window->parent()) {
+ qDebug() << "QWaylandSubSurface::adjustPositionOfChildren not called for toplevel window";
+ }
+ setPositionToParent(m_window);
+}
diff --git a/src/plugins/platforms/wayland/qwaylandsubsurface.h b/src/plugins/platforms/wayland/qwaylandsubsurface.h
index 2b8b039e4..4d3ff19df 100644
--- a/src/plugins/platforms/wayland/qwaylandsubsurface.h
+++ b/src/plugins/platforms/wayland/qwaylandsubsurface.h
@@ -66,6 +66,8 @@ public:
void setParent(const QWaylandWindow *parent);
+ void adjustPositionOfChildren();
+
private:
QWaylandWindow *m_window;
struct wl_sub_surface *m_sub_surface;
diff --git a/src/plugins/platforms/wayland/qwaylandwindow.cpp b/src/plugins/platforms/wayland/qwaylandwindow.cpp
index 0273cd294..9f0d31c6f 100644
--- a/src/plugins/platforms/wayland/qwaylandwindow.cpp
+++ b/src/plugins/platforms/wayland/qwaylandwindow.cpp
@@ -47,6 +47,9 @@
#include "qwaylandscreen.h"
#include "qwaylandshell.h"
#include "qwaylandshellsurface.h"
+#include "qwaylandextendedsurface.h"
+#include "qwaylandsubsurface.h"
+#include "qwaylanddecoration.h"
#include <QtGui/QWindow>
@@ -54,19 +57,21 @@
#include "windowmanager_integration/qwaylandwindowmanagerintegration.h"
#endif
-#include "qwaylandextendedsurface.h"
-#include "qwaylandsubsurface.h"
-
#include <QCoreApplication>
#include <QtGui/QWindowSystemInterface>
+#include <QtCore/QDebug>
+
QWaylandWindow::QWaylandWindow(QWindow *window)
: QPlatformWindow(window)
, mDisplay(QWaylandScreen::waylandScreenFromWindow(window)->display())
, mSurface(mDisplay->createSurface(this))
- , mShellSurface(mDisplay->shell()->createShellSurface(this))
+ , mShellSurface(0)
, mExtendedWindow(0)
, mSubSurfaceWindow(0)
+ , mWindowDecoration(0)
+ , mMouseEventsInContentArea(false)
+ , mMousePressedInContentArea(Qt::NoButton)
, mBuffer(0)
, mWaitingForFrameSync(false)
, mFrameCallback(0)
@@ -75,6 +80,8 @@ QWaylandWindow::QWaylandWindow(QWindow *window)
static WId id = 1;
mWindowId = id++;
+ if (mDisplay->shell())
+ mShellSurface = mDisplay->shell()->getShellSurface(this);
if (mDisplay->windowExtension())
mExtendedWindow = mDisplay->windowExtension()->getExtendedWindow(this);
if (mDisplay->subSurfaceExtension())
@@ -87,8 +94,12 @@ QWaylandWindow::QWaylandWindow(QWindow *window)
if (parent() && mSubSurfaceWindow) {
mSubSurfaceWindow->setParent(static_cast<const QWaylandWindow *>(parent()));
- } else {
- wl_shell_surface_set_toplevel(mShellSurface->handle());
+ }else if (window->transientParent()) {
+ if (window->transientParent()) {
+ mShellSurface->updateTransientParent(window->transientParent());
+ } else {
+ mShellSurface->setTopLevel();
+ }
}
}
@@ -118,6 +129,22 @@ void QWaylandWindow::setParent(const QPlatformWindow *parent)
}
}
+void QWaylandWindow::setWindowTitle(const QString &title)
+{
+ Q_UNUSED(title);
+ if (mWindowDecoration && window()->visible()) {
+ mWindowDecoration->paintDecoration();
+ }
+}
+
+void QWaylandWindow::setGeometry(const QRect &rect)
+{
+ QPlatformWindow::setGeometry(rect);
+
+ if (shellSurface() && window()->transientParent())
+ shellSurface()->updateTransientParent(window()->transientParent());
+}
+
void QWaylandWindow::setVisible(bool visible)
{
@@ -134,6 +161,7 @@ void QWaylandWindow::setVisible(bool visible)
} else {
QWindowSystemInterface::handleSynchronousExposeEvent(window(), QRect(QPoint(), geometry().size()));
wl_surface_attach(mSurface, 0,0,0);
+ damage(QRect(QPoint(0,0),geometry().size()));
}
}
@@ -149,15 +177,19 @@ bool QWaylandWindow::isExposed() const
void QWaylandWindow::configure(uint32_t time, uint32_t edges,
- int32_t x, int32_t y,
int32_t width, int32_t height)
{
Q_UNUSED(time);
Q_UNUSED(edges);
- QRect geometry = QRect(x, y, width, height);
- setGeometry(geometry);
+ int widthWithoutMargins = qMax(width-(frameMargins().left() +frameMargins().right()),1);
+ int heightWithoutMargins = qMax(height-(frameMargins().top()+frameMargins().bottom()),1);
+ widthWithoutMargins = qMax(widthWithoutMargins, window()->minimumSize().width());
+ heightWithoutMargins = qMax(heightWithoutMargins, window()->minimumSize().height());
+ QRect geometry = QRect(0,0,
+ widthWithoutMargins, heightWithoutMargins);
+ setGeometry(geometry);
QWindowSystemInterface::handleGeometryChange(window(), geometry);
}
@@ -167,11 +199,14 @@ void QWaylandWindow::attach(QWaylandBuffer *buffer)
if (window()->isVisible()) {
wl_surface_attach(mSurface, mBuffer->buffer(),0,0);
- if (buffer)
- QWindowSystemInterface::handleSynchronousExposeEvent(window(), QRect(QPoint(), geometry().size()));
}
}
+QWaylandBuffer *QWaylandWindow::attached() const
+{
+ return mBuffer;
+}
+
void QWaylandWindow::damage(const QRect &rect)
{
//We have to do sync stuff before calling damage, or we might
@@ -204,11 +239,20 @@ void QWaylandWindow::frameCallback(void *data, struct wl_callback *wl_callback,
void QWaylandWindow::waitForFrameSync()
{
+ if (!mWaitingForFrameSync)
+ return;
mDisplay->flushRequests();
while (mWaitingForFrameSync)
mDisplay->blockingReadEvents();
}
+QMargins QWaylandWindow::frameMargins() const
+{
+ if (mWindowDecoration)
+ return mWindowDecoration->margins();
+ return QPlatformWindow::frameMargins();
+}
+
QWaylandShellSurface *QWaylandWindow::shellSurface() const
{
return mShellSurface;
@@ -260,3 +304,77 @@ Qt::WindowFlags QWaylandWindow::setWindowFlags(Qt::WindowFlags flags)
{
return mExtendedWindow->setWindowFlags(flags);
}
+
+QWaylandDecoration *QWaylandWindow::decoration() const
+{
+ return mWindowDecoration;
+}
+
+void QWaylandWindow::setDecoration(QWaylandDecoration *decoration)
+{
+ mWindowDecoration = decoration;
+ if (subSurfaceWindow()) {
+ subSurfaceWindow()->adjustPositionOfChildren();
+ }
+}
+
+void QWaylandWindow::handleMouse(QWaylandInputDevice *inputDevice, ulong timestamp, const QPointF &local, const QPointF &global, Qt::MouseButtons b, Qt::KeyboardModifiers mods)
+{
+ if (mWindowDecoration) {
+ handleMouseEventWithDecoration(inputDevice, timestamp,local,global,b,mods);
+ return;
+ }
+
+ QWindowSystemInterface::handleMouseEvent(window(),timestamp,local,global,b,mods);
+}
+
+void QWaylandWindow::handleMouseEnter()
+{
+ if (!mWindowDecoration) {
+ QWindowSystemInterface::handleEnterEvent(window());
+ }
+}
+
+void QWaylandWindow::handleMouseLeave()
+{
+ if (mWindowDecoration) {
+ if (mMouseEventsInContentArea) {
+ QWindowSystemInterface::handleLeaveEvent(window());
+ }
+ mWindowDecoration->restoreMouseCursor();
+ } else {
+ QWindowSystemInterface::handleLeaveEvent(window());
+ }
+}
+
+void QWaylandWindow::handleMouseEventWithDecoration(QWaylandInputDevice *inputDevice, ulong timestamp, const QPointF &local, const QPointF &global, Qt::MouseButtons b, Qt::KeyboardModifiers mods)
+{
+ if (mWindowDecoration->inMouseButtonPressedState()) {
+ mWindowDecoration->handleMouse(inputDevice,local,global,b,mods);
+ return;
+ }
+
+ QPointF localTranslated = local;
+ QMargins marg = frameMargins();
+ QRect windowRect(0 + marg.left(),
+ 0 + marg.top(),
+ geometry().size().width() - marg.right(),
+ geometry().size().height() - marg.bottom());
+ if (windowRect.contains(local.toPoint()) || mMousePressedInContentArea != Qt::NoButton) {
+ localTranslated.setX(localTranslated.x() - marg.left());
+ localTranslated.setY(localTranslated.y() - marg.top());
+ if (!mMouseEventsInContentArea) {
+ mWindowDecoration->restoreMouseCursor();
+ QWindowSystemInterface::handleEnterEvent(window());
+ }
+ QWindowSystemInterface::handleMouseEvent(window(),timestamp,localTranslated,global,b,mods);
+ mMouseEventsInContentArea = true;
+ mMousePressedInContentArea = b;
+ } else {
+ if (mMouseEventsInContentArea) {
+ QWindowSystemInterface::handleLeaveEvent(window());
+ mMouseEventsInContentArea = false;
+ }
+ mWindowDecoration->handleMouse(inputDevice,local,global,b,mods);
+ }
+}
diff --git a/src/plugins/platforms/wayland/qwaylandwindow.h b/src/plugins/platforms/wayland/qwaylandwindow.h
index 8fcfd8f2e..a07368b70 100644
--- a/src/plugins/platforms/wayland/qwaylandwindow.h
+++ b/src/plugins/platforms/wayland/qwaylandwindow.h
@@ -52,6 +52,7 @@ class QWaylandBuffer;
class QWaylandShellSurface;
class QWaylandExtendedSurface;
class QWaylandSubSurface;
+class QWaylandDecoration;
struct wl_egl_window;
@@ -71,14 +72,22 @@ public:
void setVisible(bool visible);
void setParent(const QPlatformWindow *parent);
+ void setWindowTitle(const QString &title);
+
+ void setGeometry(const QRect &rect);
+
void configure(uint32_t time, uint32_t edges,
- int32_t x, int32_t y, int32_t width, int32_t height);
+ int32_t width, int32_t height);
void attach(QWaylandBuffer *buffer);
+ QWaylandBuffer *attached() const;
+
void damage(const QRect &rect);
void waitForFrameSync();
+ QMargins frameMargins() const;
+
struct wl_surface *wl_surface() const { return mSurface; }
QWaylandShellSurface *shellSurface() const;
@@ -93,6 +102,18 @@ public:
bool isExposed() const;
+ QWaylandDecoration *decoration() const;
+ void setDecoration(QWaylandDecoration *decoration);
+
+
+ void handleMouse(QWaylandInputDevice *inputDevice,
+ ulong timestamp,
+ const QPointF & local,
+ const QPointF & global,
+ Qt::MouseButtons b,
+ Qt::KeyboardModifiers mods);
+ void handleMouseEnter();
+ void handleMouseLeave();
protected:
QWaylandDisplay *mDisplay;
struct wl_surface *mSurface;
@@ -100,6 +121,10 @@ protected:
QWaylandExtendedSurface *mExtendedWindow;
QWaylandSubSurface *mSubSurfaceWindow;
+ QWaylandDecoration *mWindowDecoration;
+ bool mMouseEventsInContentArea;
+ Qt::MouseButtons mMousePressedInContentArea;
+
QWaylandBuffer *mBuffer;
WId mWindowId;
bool mWaitingForFrameSync;
@@ -109,6 +134,13 @@ protected:
bool mSentInitialResize;
private:
+ void handleMouseEventWithDecoration(QWaylandInputDevice *inputDevice,
+ ulong timestamp,
+ const QPointF & local,
+ const QPointF & global,
+ Qt::MouseButtons b,
+ Qt::KeyboardModifiers mods);
+
static const wl_callback_listener callbackListener;
static void frameCallback(void *data, struct wl_callback *wl_callback, uint32_t time);
diff --git a/src/plugins/platforms/wayland/wayland.pro b/src/plugins/platforms/wayland/wayland.pro
index 7bc515b5f..92a04c07f 100644
--- a/src/plugins/platforms/wayland/wayland.pro
+++ b/src/plugins/platforms/wayland/wayland.pro
@@ -30,7 +30,8 @@ SOURCES = main.cpp \
qwaylandsubsurface.cpp \
qwaylandtouch.cpp \
qwaylandqtkey.cpp \
- $$PWD/../../../shared/qwaylandmimehelper.cpp
+ $$PWD/../../../shared/qwaylandmimehelper.cpp \
+ qwaylanddecoration.cpp
HEADERS = qwaylandintegration.h \
qwaylandnativeinterface.h \
@@ -53,7 +54,8 @@ HEADERS = qwaylandintegration.h \
qwaylandsubsurface.h \
qwaylandtouch.h \
qwaylandqtkey.h \
- $$PWD/../../../shared/qwaylandmimehelper.h
+ $$PWD/../../../shared/qwaylandmimehelper.h \
+ qwaylanddecoration.h
DEFINES += Q_PLATFORM_WAYLAND