1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the Qt Compositor.
8 ** $QT_BEGIN_LICENSE:BSD$
9 ** You may use this file under the terms of the BSD license as follows:
11 ** "Redistribution and use in source and binary forms, with or without
12 ** modification, are permitted provided that the following conditions are
14 ** * Redistributions of source code must retain the above copyright
15 ** notice, this list of conditions and the following disclaimer.
16 ** * Redistributions in binary form must reproduce the above copyright
17 ** notice, this list of conditions and the following disclaimer in
18 ** the documentation and/or other materials provided with the
20 ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
21 ** the names of its contributors may be used to endorse or promote
22 ** products derived from this software without specific prior written
25 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
39 ****************************************************************************/
41 #include "wlshellsurface.h"
43 #include "wlcompositor.h"
44 #include "wlsurface.h"
45 #include "wlinputdevice.h"
46 #include "wlsubsurface.h"
48 #include <QtCore/qglobal.h>
49 #include <QtCore/QDebug>
57 void Shell::bind_func(struct wl_client *client, void *data,
58 uint32_t version, uint32_t id)
61 wl_client_add_object(client,&wl_shell_interface,&shell_interface,id,data);
64 void Shell::get_shell_surface(struct wl_client *client,
65 struct wl_resource *shell_resource,
67 struct wl_resource *surface_super)
69 Q_UNUSED(shell_resource);
70 Surface *surface = resolve<Surface>(surface_super);
71 new ShellSurface(client,id,surface);
74 const struct wl_shell_interface Shell::shell_interface = {
75 Shell::get_shell_surface
78 ShellSurface::ShellSurface(wl_client *client, uint32_t id, Surface *surface)
82 , m_transientParent(0)
86 m_shellSurface = wl_client_add_object(client,&wl_shell_surface_interface,&shell_surface_interface,id,this);
87 surface->setShellSurface(this);
90 void ShellSurface::sendConfigure(uint32_t edges, int32_t width, int32_t height)
92 wl_shell_surface_send_configure(m_shellSurface,edges,width,height);
95 Surface *ShellSurface::surface() const
100 void ShellSurface::adjustPosInResize()
102 if (m_transientParent)
104 if (!m_resizeGrabber || !(m_resizeGrabber->resize_edges & WL_SHELL_SURFACE_RESIZE_TOP_LEFT))
107 int bottomLeftX = wl_fixed_to_int(m_resizeGrabber->base()->x) + m_resizeGrabber->width;
108 int bottomLeftY = wl_fixed_to_int(m_resizeGrabber->base()->y) + m_resizeGrabber->height;
109 qreal x = surface()->pos().x();
110 qreal y = surface()->pos().y();
111 if (m_resizeGrabber->resize_edges & WL_SHELL_SURFACE_RESIZE_TOP)
112 y = bottomLeftY - surface()->size().height();
113 if (m_resizeGrabber->resize_edges & WL_SHELL_SURFACE_RESIZE_LEFT)
114 x = bottomLeftX - surface()->size().width();
116 surface()->setPos(newPos);
119 QPointF ShellSurface::adjustedPosToTransientParent() const
121 if (!m_transientParent ||
122 (m_surface->subSurface() && m_surface->subSurface()->parent()))
123 return m_surface->nonAdjustedPos();
125 return m_transientParent->surface()->pos() + QPoint(m_xOffset,m_yOffset);
128 void ShellSurface::resetResizeGrabber()
133 void ShellSurface::resetMoveGrabber()
138 ShellSurface *ShellSurface::transientParent() const
140 return m_transientParent;
143 void ShellSurface::setOffset(const QPointF &offset)
145 m_xOffset = offset.x();
146 m_yOffset = offset.y();
149 void ShellSurface::move(struct wl_client *client,
150 struct wl_resource *shell_surface_resource,
151 struct wl_resource *input_device_super,
156 ShellSurface *self = static_cast<ShellSurface *>(shell_surface_resource->data);
157 InputDevice *input_device = static_cast<InputDevice *>(input_device_super->data);
158 if (self->m_resizeGrabber || self->m_moveGrabber) {
159 qDebug() << "invalid state";
163 self->m_moveGrabber = new ShellSurfaceMoveGrabber(self);
164 wl_pointer *pointer = input_device->pointerDevice();
165 self->m_moveGrabber->base()->x = pointer->x;
166 self->m_moveGrabber->base()->y = pointer->y;
167 self->m_moveGrabber->offset_x = wl_fixed_to_int(pointer->x) - self->surface()->pos().x();
168 self->m_moveGrabber->offset_y = wl_fixed_to_int(pointer->y) - self->surface()->pos().y();
170 wl_pointer_start_grab(pointer, self->m_moveGrabber->base());
173 void ShellSurface::resize(struct wl_client *client,
174 struct wl_resource *shell_surface_resource,
175 struct wl_resource *input_device_super,
179 Q_UNUSED(shell_surface_resource);
183 ShellSurface *self = static_cast<ShellSurface *>(shell_surface_resource->data);
184 InputDevice *input_device = static_cast<InputDevice *>(input_device_super->data);
185 if (self->m_moveGrabber || self->m_resizeGrabber) {
186 qDebug() << "invalid state2";
189 self->m_resizeGrabber = new ShellSurfaceResizeGrabber(self);
190 wl_pointer *pointer = input_device->pointerDevice();
191 self->m_resizeGrabber->base()->x = pointer->x;
192 self->m_resizeGrabber->base()->y = pointer->y;
193 self->m_resizeGrabber->resize_edges = wl_shell_surface_resize(edges);
194 self->m_resizeGrabber->width = self->surface()->size().width();
195 self->m_resizeGrabber->height = self->surface()->size().height();
197 wl_pointer_start_grab(pointer, self->m_resizeGrabber->base());
200 void ShellSurface::set_toplevel(struct wl_client *client,
201 struct wl_resource *shell_surface_resource)
204 ShellSurface *self = static_cast<ShellSurface *>(shell_surface_resource->data);
205 self->m_transientParent = 0;
211 void ShellSurface::set_transient(struct wl_client *client,
212 struct wl_resource *shell_surface_resource,
213 struct wl_resource *parent_shell_surface_resource,
221 ShellSurface *shell_surface = static_cast<ShellSurface *>(shell_surface_resource->data);
222 ShellSurface *parent_shell_surface = static_cast<ShellSurface *>(parent_shell_surface_resource->data);
223 shell_surface->m_transientParent = parent_shell_surface;
224 shell_surface->m_xOffset = x;
225 shell_surface->m_yOffset = y;
229 void ShellSurface::set_fullscreen(struct wl_client *client,
230 struct wl_resource *shell_surface_resource,
233 struct wl_resource *output)
236 Q_UNUSED(shell_surface_resource);
242 void ShellSurface::set_popup(wl_client *client, wl_resource *resource, wl_resource *input_device, uint32_t time, wl_resource *parent, int32_t x, int32_t y, uint32_t flags)
246 Q_UNUSED(input_device);
254 void ShellSurface::set_maximized(struct wl_client *client,
255 struct wl_resource *shell_surface_resource,
256 struct wl_resource *output)
259 Q_UNUSED(shell_surface_resource);
263 void ShellSurface::pong(struct wl_client *client,
264 struct wl_resource *resource,
272 void ShellSurface::set_title(struct wl_client *client,
273 struct wl_resource *resource,
277 ShellSurface *self = static_cast<ShellSurface *>(resource->data);
278 self->surface()->setTitle(QString::fromUtf8(title));
281 void ShellSurface::set_class(struct wl_client *client,
282 struct wl_resource *resource,
290 const struct wl_shell_surface_interface ShellSurface::shell_surface_interface = {
293 ShellSurface::resize,
294 ShellSurface::set_toplevel,
295 ShellSurface::set_transient,
296 ShellSurface::set_fullscreen,
297 ShellSurface::set_popup,
298 ShellSurface::set_maximized,
299 ShellSurface::set_title,
300 ShellSurface::set_class
303 Qt::MouseButton toQtButton(uint32_t button)
306 static const uint32_t BTN_LEFT = 0x110;
307 static const uint32_t BTN_RIGHT = 0x111;
308 static const uint32_t BTN_MIDDLE = 0x112;
312 return Qt::LeftButton;
314 return Qt::RightButton;
316 return Qt::MiddleButton;
322 ShellSurfaceGrabber::ShellSurfaceGrabber(ShellSurface *shellSurface, const struct wl_pointer_grab_interface *interface)
323 : shell_surface(shellSurface)
325 base()->interface = interface;
326 base()->focus = shell_surface->surface()->base();
329 ShellSurfaceGrabber::~ShellSurfaceGrabber()
334 void ShellSurfaceGrabber::destroy(wl_listener *listener, wl_resource *resource, uint32_t time)
339 //ShellSurfaceGrabber *shell_surface_grabber = container_of(listener, ShellSurfaceGrabber,surface_destroy_listener);
340 Q_ASSERT(false); //hasn't been enabled yet
341 //wl_input_device_end_grab(shell_surface_grabber->base()->input_device,Compositor::currentTimeMsecs());
345 ShellSurfaceResizeGrabber::ShellSurfaceResizeGrabber(ShellSurface *shellSurface)
346 : ShellSurfaceGrabber(shellSurface,&resize_grabber_interface)
350 void ShellSurfaceResizeGrabber::focus(wl_pointer_grab *grab, wl_surface *surface, int32_t x, int32_t y)
358 void ShellSurfaceResizeGrabber::motion(wl_pointer_grab *grab, uint32_t time, int32_t x, int32_t y)
363 //Should be more structured
364 ShellSurfaceResizeGrabber *resize_grabber = reinterpret_cast<ShellSurfaceResizeGrabber *>(grab);
365 ShellSurface *shell_surface = resize_grabber->shell_surface;
366 wl_pointer *pointer = grab->pointer;
367 int width_delta = wl_fixed_to_int(grab->x) - wl_fixed_to_int(pointer->x);
368 int height_delta = wl_fixed_to_int(grab->y) - wl_fixed_to_int(pointer->y);
369 int new_width = resize_grabber->width;
370 int new_height = resize_grabber->height;
371 if (resize_grabber->resize_edges & WL_SHELL_SURFACE_RESIZE_TOP_LEFT) {
372 if (resize_grabber->resize_edges & WL_SHELL_SURFACE_RESIZE_TOP) {
373 if (new_height + height_delta > 0) {
374 new_height += height_delta;
379 if (resize_grabber->resize_edges & WL_SHELL_SURFACE_RESIZE_LEFT) {
380 if (new_width + width_delta > 0) {
381 new_width += width_delta;
388 if (resize_grabber->resize_edges & WL_SHELL_SURFACE_RESIZE_BOTTOM) {
389 if (new_height - height_delta > 0) {
390 new_height -= height_delta;
395 if (resize_grabber->resize_edges & WL_SHELL_SURFACE_RESIZE_RIGHT) {
396 if (new_width - width_delta > 0) {
397 new_width -= width_delta;
403 shell_surface->sendConfigure(resize_grabber->resize_edges,new_width,new_height);
406 void ShellSurfaceResizeGrabber::button(wl_pointer_grab *grab, uint32_t time, uint32_t button, uint32_t state)
409 ShellSurfaceResizeGrabber *self = reinterpret_cast<ShellSurfaceResizeGrabber *>(grab);
410 ShellSurface *shell_surface = self->shell_surface;
411 if (toQtButton(button) == Qt::LeftButton && !state) {
412 wl_pointer_end_grab(grab->pointer);
413 shell_surface->resetResizeGrabber();
418 const struct wl_pointer_grab_interface ShellSurfaceResizeGrabber::resize_grabber_interface = {
419 ShellSurfaceResizeGrabber::focus,
420 ShellSurfaceResizeGrabber::motion,
421 ShellSurfaceResizeGrabber::button
424 ShellSurfaceMoveGrabber::ShellSurfaceMoveGrabber(ShellSurface *shellSurface)
425 : ShellSurfaceGrabber(shellSurface,&move_grabber_interface)
429 void ShellSurfaceMoveGrabber::focus(wl_pointer_grab *grab, wl_surface *surface, int32_t x, int32_t y)
437 void ShellSurfaceMoveGrabber::motion(wl_pointer_grab *grab, uint32_t time, int32_t x, int32_t y)
442 ShellSurfaceMoveGrabber *shell_surface_grabber = reinterpret_cast<ShellSurfaceMoveGrabber *>(grab);
443 ShellSurface *shell_surface = shell_surface_grabber->shell_surface;
444 wl_pointer *pointer = grab->pointer;
445 QPointF pos(wl_fixed_to_int(pointer->x) - shell_surface_grabber->offset_x,
446 wl_fixed_to_int(pointer->y) - shell_surface_grabber->offset_y);
447 shell_surface->surface()->setPos(pos);
448 if (shell_surface->transientParent())
449 shell_surface->setOffset(pos - shell_surface->transientParent()->surface()->pos());
450 shell_surface->surface()->damage(QRect(QPoint(0,0),shell_surface->surface()->size()));
453 void ShellSurfaceMoveGrabber::button(wl_pointer_grab *grab, uint32_t time, uint32_t button, uint32_t state)
456 ShellSurfaceResizeGrabber *self = reinterpret_cast<ShellSurfaceResizeGrabber *>(grab);
457 ShellSurface *shell_surface = self->shell_surface;
458 if (toQtButton(button) == Qt::LeftButton && !state) {
459 wl_pointer_set_focus(grab->pointer, 0, 0, 0);
460 wl_pointer_end_grab(grab->pointer);
461 shell_surface->resetMoveGrabber();
466 const struct wl_pointer_grab_interface ShellSurfaceMoveGrabber::move_grabber_interface = {
467 ShellSurfaceMoveGrabber::focus,
468 ShellSurfaceMoveGrabber::motion,
469 ShellSurfaceMoveGrabber::button