Migrate from wl_input_device to wl_seat
[profile/ivi/qtwayland.git] / src / compositor / wayland_wrapper / wlshellsurface.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the Qt Compositor.
7 **
8 ** $QT_BEGIN_LICENSE:BSD$
9 ** You may use this file under the terms of the BSD license as follows:
10 **
11 ** "Redistribution and use in source and binary forms, with or without
12 ** modification, are permitted provided that the following conditions are
13 ** met:
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
19 **     distribution.
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
23 **     permission.
24 **
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."
36 **
37 ** $QT_END_LICENSE$
38 **
39 ****************************************************************************/
40
41 #include "wlshellsurface.h"
42
43 #include "wlcompositor.h"
44 #include "wlsurface.h"
45 #include "wlinputdevice.h"
46 #include "wlsubsurface.h"
47
48 #include <QtCore/qglobal.h>
49 #include <QtCore/QDebug>
50
51 namespace Wayland {
52
53 Shell::Shell()
54 {
55 }
56
57 void Shell::bind_func(struct wl_client *client, void *data,
58                             uint32_t version, uint32_t id)
59 {
60     Q_UNUSED(version);
61     wl_client_add_object(client,&wl_shell_interface,&shell_interface,id,data);
62 }
63
64 void Shell::get_shell_surface(struct wl_client *client,
65               struct wl_resource *shell_resource,
66               uint32_t id,
67               struct wl_resource *surface_super)
68 {
69     Q_UNUSED(shell_resource);
70     Surface *surface = resolve<Surface>(surface_super);
71     new ShellSurface(client,id,surface);
72 }
73
74 const struct wl_shell_interface Shell::shell_interface = {
75     Shell::get_shell_surface
76 };
77
78 ShellSurface::ShellSurface(wl_client *client, uint32_t id, Surface *surface)
79     : m_surface(surface)
80     , m_resizeGrabber(0)
81     , m_moveGrabber(0)
82     , m_transientParent(0)
83     , m_xOffset(0)
84     , m_yOffset(0)
85 {
86     m_shellSurface = wl_client_add_object(client,&wl_shell_surface_interface,&shell_surface_interface,id,this);
87     surface->setShellSurface(this);
88 }
89
90 void ShellSurface::sendConfigure(uint32_t edges, int32_t width, int32_t height)
91 {
92     wl_shell_surface_send_configure(m_shellSurface,edges,width,height);
93 }
94
95 Surface *ShellSurface::surface() const
96 {
97     return m_surface;
98 }
99
100 void ShellSurface::adjustPosInResize()
101 {
102     if (m_transientParent)
103         return;
104     if (!m_resizeGrabber || !(m_resizeGrabber->resize_edges & WL_SHELL_SURFACE_RESIZE_TOP_LEFT))
105         return;
106
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();
115     QPointF newPos(x,y);
116     surface()->setPos(newPos);
117 }
118
119 QPointF ShellSurface::adjustedPosToTransientParent() const
120 {
121     if (!m_transientParent ||
122             (m_surface->subSurface() && m_surface->subSurface()->parent()))
123         return m_surface->nonAdjustedPos();
124
125     return m_transientParent->surface()->pos() + QPoint(m_xOffset,m_yOffset);
126 }
127
128 void ShellSurface::resetResizeGrabber()
129 {
130     m_resizeGrabber = 0;
131 }
132
133 void ShellSurface::resetMoveGrabber()
134 {
135     m_moveGrabber = 0;
136 }
137
138 ShellSurface *ShellSurface::transientParent() const
139 {
140     return m_transientParent;
141 }
142
143 void ShellSurface::setOffset(const QPointF &offset)
144 {
145     m_xOffset = offset.x();
146     m_yOffset = offset.y();
147 }
148
149 void ShellSurface::move(struct wl_client *client,
150                 struct wl_resource *shell_surface_resource,
151                 struct wl_resource *input_device_super,
152                 uint32_t time)
153 {
154     Q_UNUSED(client);
155     Q_UNUSED(time);
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";
160         return;
161     }
162
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();
169
170     wl_pointer_start_grab(pointer, self->m_moveGrabber->base());
171 }
172
173 void ShellSurface::resize(struct wl_client *client,
174                   struct wl_resource *shell_surface_resource,
175                   struct wl_resource *input_device_super,
176                   uint32_t time,
177                   uint32_t edges)
178 {
179     Q_UNUSED(shell_surface_resource);
180     Q_UNUSED(client);
181     Q_UNUSED(time);
182     Q_UNUSED(edges);
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";
187         return;
188     }
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();
196
197     wl_pointer_start_grab(pointer, self->m_resizeGrabber->base());
198 }
199
200 void ShellSurface::set_toplevel(struct wl_client *client,
201                      struct wl_resource *shell_surface_resource)
202 {
203     Q_UNUSED(client);
204     ShellSurface *self = static_cast<ShellSurface *>(shell_surface_resource->data);
205     self->m_transientParent = 0;
206     self->m_xOffset = 0;
207     self->m_yOffset = 0;
208
209 }
210
211 void ShellSurface::set_transient(struct wl_client *client,
212                       struct wl_resource *shell_surface_resource,
213                       struct wl_resource *parent_shell_surface_resource,
214                       int x,
215                       int y,
216                       uint32_t flags)
217 {
218
219     Q_UNUSED(client);
220     Q_UNUSED(flags);
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
227 }
228
229 void ShellSurface::set_fullscreen(struct wl_client *client,
230                        struct wl_resource *shell_surface_resource,
231                        uint32_t method,
232                        uint32_t framerate,
233                        struct wl_resource *output)
234 {
235     Q_UNUSED(client);
236     Q_UNUSED(shell_surface_resource);
237     Q_UNUSED(method);
238     Q_UNUSED(framerate);
239     Q_UNUSED(output);
240 }
241
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)
243 {
244     Q_UNUSED(client);
245     Q_UNUSED(resource);
246     Q_UNUSED(input_device);
247     Q_UNUSED(time);
248     Q_UNUSED(parent);
249     Q_UNUSED(x);
250     Q_UNUSED(y);
251     Q_UNUSED(flags);
252 }
253
254 void ShellSurface::set_maximized(struct wl_client *client,
255                        struct wl_resource *shell_surface_resource,
256                        struct wl_resource *output)
257 {
258     Q_UNUSED(client);
259     Q_UNUSED(shell_surface_resource);
260     Q_UNUSED(output);
261 }
262
263 void ShellSurface::pong(struct wl_client *client,
264                         struct wl_resource *resource,
265                         uint32_t serial)
266 {
267     Q_UNUSED(client);
268     Q_UNUSED(resource);
269     Q_UNUSED(serial);
270 }
271
272 void ShellSurface::set_title(struct wl_client *client,
273                              struct wl_resource *resource,
274                              const char *title)
275 {
276     Q_UNUSED(client);
277     ShellSurface *self = static_cast<ShellSurface *>(resource->data);
278     self->surface()->setTitle(QString::fromUtf8(title));
279 }
280
281 void ShellSurface::set_class(struct wl_client *client,
282                              struct wl_resource *resource,
283                              const char *class_)
284 {
285     Q_UNUSED(client);
286     Q_UNUSED(resource);
287     Q_UNUSED(class_);
288 }
289
290 const struct wl_shell_surface_interface ShellSurface::shell_surface_interface = {
291     ShellSurface::pong,
292     ShellSurface::move,
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
301 };
302
303 Qt::MouseButton toQtButton(uint32_t button)
304 {
305 #ifndef BTN_LEFT
306     static const uint32_t BTN_LEFT = 0x110;
307     static const uint32_t BTN_RIGHT = 0x111;
308     static const uint32_t BTN_MIDDLE = 0x112;
309 #endif
310     switch (button) {
311     case BTN_LEFT:
312         return Qt::LeftButton;
313     case BTN_RIGHT:
314         return Qt::RightButton;
315     case BTN_MIDDLE:
316         return Qt::MiddleButton;
317     default:
318         return Qt::NoButton;
319     }
320 }
321
322 ShellSurfaceGrabber::ShellSurfaceGrabber(ShellSurface *shellSurface, const struct wl_pointer_grab_interface *interface)
323     : shell_surface(shellSurface)
324 {
325     base()->interface = interface;
326     base()->focus = shell_surface->surface()->base();
327 }
328
329 ShellSurfaceGrabber::~ShellSurfaceGrabber()
330 {
331 }
332
333
334 void ShellSurfaceGrabber::destroy(wl_listener *listener, wl_resource *resource, uint32_t time)
335 {
336     Q_UNUSED(resource);
337     Q_UNUSED(time);
338     Q_UNUSED(listener);
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());
342 }
343
344
345 ShellSurfaceResizeGrabber::ShellSurfaceResizeGrabber(ShellSurface *shellSurface)
346     : ShellSurfaceGrabber(shellSurface,&resize_grabber_interface)
347 {
348 }
349
350 void ShellSurfaceResizeGrabber::focus(wl_pointer_grab *grab, wl_surface *surface, int32_t x, int32_t y)
351 {
352     Q_UNUSED(grab);
353     Q_UNUSED(surface);
354     Q_UNUSED(x);
355     Q_UNUSED(y);
356 }
357
358 void ShellSurfaceResizeGrabber::motion(wl_pointer_grab *grab, uint32_t time, int32_t x, int32_t y)
359 {
360     Q_UNUSED(time);
361     Q_UNUSED(x);
362     Q_UNUSED(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;
375             } else {
376                 new_height = 1;
377             }
378         }
379         if (resize_grabber->resize_edges & WL_SHELL_SURFACE_RESIZE_LEFT) {
380             if (new_width + width_delta > 0) {
381                 new_width += width_delta;
382             } else {
383                 new_width = 1;
384             }
385         }
386     }
387
388     if (resize_grabber->resize_edges & WL_SHELL_SURFACE_RESIZE_BOTTOM) {
389         if (new_height - height_delta > 0) {
390             new_height -= height_delta;
391         } else {
392             new_height = 1;
393         }
394     }
395     if (resize_grabber->resize_edges & WL_SHELL_SURFACE_RESIZE_RIGHT) {
396         if (new_width - width_delta > 0) {
397             new_width -= width_delta;
398         } else {
399             new_width =1;
400         }
401     }
402
403     shell_surface->sendConfigure(resize_grabber->resize_edges,new_width,new_height);
404 }
405
406 void ShellSurfaceResizeGrabber::button(wl_pointer_grab *grab, uint32_t time, uint32_t button, uint32_t state)
407 {
408     Q_UNUSED(time)
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();
414         delete self;
415     }
416 }
417
418 const struct wl_pointer_grab_interface ShellSurfaceResizeGrabber::resize_grabber_interface = {
419     ShellSurfaceResizeGrabber::focus,
420     ShellSurfaceResizeGrabber::motion,
421     ShellSurfaceResizeGrabber::button
422 };
423
424 ShellSurfaceMoveGrabber::ShellSurfaceMoveGrabber(ShellSurface *shellSurface)
425     : ShellSurfaceGrabber(shellSurface,&move_grabber_interface)
426 {
427 }
428
429 void ShellSurfaceMoveGrabber::focus(wl_pointer_grab *grab, wl_surface *surface, int32_t x, int32_t y)
430 {
431     Q_UNUSED(grab);
432     Q_UNUSED(surface);
433     Q_UNUSED(x);
434     Q_UNUSED(y);
435 }
436
437 void ShellSurfaceMoveGrabber::motion(wl_pointer_grab *grab, uint32_t time, int32_t x, int32_t y)
438 {
439     Q_UNUSED(time);
440     Q_UNUSED(x);
441     Q_UNUSED(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()));
451 }
452
453 void ShellSurfaceMoveGrabber::button(wl_pointer_grab *grab, uint32_t time, uint32_t button, uint32_t state)
454 {
455     Q_UNUSED(time)
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();
462         delete self;
463     }
464 }
465
466 const struct wl_pointer_grab_interface ShellSurfaceMoveGrabber::move_grabber_interface = {
467     ShellSurfaceMoveGrabber::focus,
468     ShellSurfaceMoveGrabber::motion,
469     ShellSurfaceMoveGrabber::button
470 };
471
472 }