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;
226 if (flags & WL_SHELL_SURFACE_TRANSIENT_INACTIVE)
227 shell_surface->surface()->setTransientInactive(true);
230 void ShellSurface::set_fullscreen(struct wl_client *client,
231 struct wl_resource *shell_surface_resource,
234 struct wl_resource *output)
237 Q_UNUSED(shell_surface_resource);
243 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)
247 Q_UNUSED(input_device);
255 void ShellSurface::set_maximized(struct wl_client *client,
256 struct wl_resource *shell_surface_resource,
257 struct wl_resource *output)
260 Q_UNUSED(shell_surface_resource);
264 void ShellSurface::pong(struct wl_client *client,
265 struct wl_resource *resource,
273 void ShellSurface::set_title(struct wl_client *client,
274 struct wl_resource *resource,
278 ShellSurface *self = static_cast<ShellSurface *>(resource->data);
279 self->surface()->setTitle(QString::fromUtf8(title));
282 void ShellSurface::set_class(struct wl_client *client,
283 struct wl_resource *resource,
291 const struct wl_shell_surface_interface ShellSurface::shell_surface_interface = {
294 ShellSurface::resize,
295 ShellSurface::set_toplevel,
296 ShellSurface::set_transient,
297 ShellSurface::set_fullscreen,
298 ShellSurface::set_popup,
299 ShellSurface::set_maximized,
300 ShellSurface::set_title,
301 ShellSurface::set_class
304 Qt::MouseButton toQtButton(uint32_t button)
307 static const uint32_t BTN_LEFT = 0x110;
308 static const uint32_t BTN_RIGHT = 0x111;
309 static const uint32_t BTN_MIDDLE = 0x112;
313 return Qt::LeftButton;
315 return Qt::RightButton;
317 return Qt::MiddleButton;
323 ShellSurfaceGrabber::ShellSurfaceGrabber(ShellSurface *shellSurface, const struct wl_pointer_grab_interface *interface)
324 : shell_surface(shellSurface)
326 base()->interface = interface;
327 base()->focus = shell_surface->surface()->base();
330 ShellSurfaceGrabber::~ShellSurfaceGrabber()
335 void ShellSurfaceGrabber::destroy(wl_listener *listener, wl_resource *resource, uint32_t time)
340 //ShellSurfaceGrabber *shell_surface_grabber = container_of(listener, ShellSurfaceGrabber,surface_destroy_listener);
341 Q_ASSERT(false); //hasn't been enabled yet
342 //wl_input_device_end_grab(shell_surface_grabber->base()->input_device,Compositor::currentTimeMsecs());
346 ShellSurfaceResizeGrabber::ShellSurfaceResizeGrabber(ShellSurface *shellSurface)
347 : ShellSurfaceGrabber(shellSurface,&resize_grabber_interface)
351 void ShellSurfaceResizeGrabber::focus(wl_pointer_grab *grab, wl_surface *surface, int32_t x, int32_t y)
359 void ShellSurfaceResizeGrabber::motion(wl_pointer_grab *grab, uint32_t time, int32_t x, int32_t y)
364 //Should be more structured
365 ShellSurfaceResizeGrabber *resize_grabber = reinterpret_cast<ShellSurfaceResizeGrabber *>(grab);
366 ShellSurface *shell_surface = resize_grabber->shell_surface;
367 wl_pointer *pointer = grab->pointer;
368 int width_delta = wl_fixed_to_int(grab->x) - wl_fixed_to_int(pointer->x);
369 int height_delta = wl_fixed_to_int(grab->y) - wl_fixed_to_int(pointer->y);
370 int new_width = resize_grabber->width;
371 int new_height = resize_grabber->height;
372 if (resize_grabber->resize_edges & WL_SHELL_SURFACE_RESIZE_TOP_LEFT) {
373 if (resize_grabber->resize_edges & WL_SHELL_SURFACE_RESIZE_TOP) {
374 if (new_height + height_delta > 0) {
375 new_height += height_delta;
380 if (resize_grabber->resize_edges & WL_SHELL_SURFACE_RESIZE_LEFT) {
381 if (new_width + width_delta > 0) {
382 new_width += width_delta;
389 if (resize_grabber->resize_edges & WL_SHELL_SURFACE_RESIZE_BOTTOM) {
390 if (new_height - height_delta > 0) {
391 new_height -= height_delta;
396 if (resize_grabber->resize_edges & WL_SHELL_SURFACE_RESIZE_RIGHT) {
397 if (new_width - width_delta > 0) {
398 new_width -= width_delta;
404 shell_surface->sendConfigure(resize_grabber->resize_edges,new_width,new_height);
407 void ShellSurfaceResizeGrabber::button(wl_pointer_grab *grab, uint32_t time, uint32_t button, uint32_t state)
410 ShellSurfaceResizeGrabber *self = reinterpret_cast<ShellSurfaceResizeGrabber *>(grab);
411 ShellSurface *shell_surface = self->shell_surface;
412 if (toQtButton(button) == Qt::LeftButton && !state) {
413 wl_pointer_end_grab(grab->pointer);
414 shell_surface->resetResizeGrabber();
419 const struct wl_pointer_grab_interface ShellSurfaceResizeGrabber::resize_grabber_interface = {
420 ShellSurfaceResizeGrabber::focus,
421 ShellSurfaceResizeGrabber::motion,
422 ShellSurfaceResizeGrabber::button
425 ShellSurfaceMoveGrabber::ShellSurfaceMoveGrabber(ShellSurface *shellSurface)
426 : ShellSurfaceGrabber(shellSurface,&move_grabber_interface)
430 void ShellSurfaceMoveGrabber::focus(wl_pointer_grab *grab, wl_surface *surface, int32_t x, int32_t y)
438 void ShellSurfaceMoveGrabber::motion(wl_pointer_grab *grab, uint32_t time, int32_t x, int32_t y)
443 ShellSurfaceMoveGrabber *shell_surface_grabber = reinterpret_cast<ShellSurfaceMoveGrabber *>(grab);
444 ShellSurface *shell_surface = shell_surface_grabber->shell_surface;
445 wl_pointer *pointer = grab->pointer;
446 QPointF pos(wl_fixed_to_int(pointer->x) - shell_surface_grabber->offset_x,
447 wl_fixed_to_int(pointer->y) - shell_surface_grabber->offset_y);
448 shell_surface->surface()->setPos(pos);
449 if (shell_surface->transientParent())
450 shell_surface->setOffset(pos - shell_surface->transientParent()->surface()->pos());
451 shell_surface->surface()->damage(QRect(QPoint(0,0),shell_surface->surface()->size()));
454 void ShellSurfaceMoveGrabber::button(wl_pointer_grab *grab, uint32_t time, uint32_t button, uint32_t state)
457 ShellSurfaceResizeGrabber *self = reinterpret_cast<ShellSurfaceResizeGrabber *>(grab);
458 ShellSurface *shell_surface = self->shell_surface;
459 if (toQtButton(button) == Qt::LeftButton && !state) {
460 wl_pointer_set_focus(grab->pointer, 0, 0, 0);
461 wl_pointer_end_grab(grab->pointer);
462 shell_surface->resetMoveGrabber();
467 const struct wl_pointer_grab_interface ShellSurfaceMoveGrabber::move_grabber_interface = {
468 ShellSurfaceMoveGrabber::focus,
469 ShellSurfaceMoveGrabber::motion,
470 ShellSurfaceMoveGrabber::button