Change copyrights from Nokia to Digia
[profile/ivi/qtwayland.git] / src / plugins / platforms / wayland / qwaylanddatadevicemanager.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the plugins of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.  For licensing terms and
14 ** conditions see http://qt.digia.com/licensing.  For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file.  Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights.  These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file.  Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qwaylanddatadevicemanager.h"
43
44 #include "qwaylandinputdevice.h"
45 #include "qwaylanddataoffer.h"
46 #include "qwaylanddatasource.h"
47 #include "qwaylandshmbackingstore.h"
48
49 #include <wayland-client-protocol.h>
50 #include <wayland-client.h>
51
52 #include <QtGui/QGuiApplication>
53 #include <QtGui/private/qguiapplication_p.h>
54 #include <qpa/qplatformclipboard.h>
55 #include <QtGui/QPainter>
56
57 #include <QWindowSystemInterface>
58
59 #include <QtCore/QDebug>
60
61 void QWaylandDataDeviceManager::data_offer(void *data,
62                    struct wl_data_device *data_device,
63                    struct wl_data_offer *id)
64 {
65     QWaylandDataDeviceManager *handler = static_cast<QWaylandDataDeviceManager *>(data);
66
67     new QWaylandDataOffer(handler->display(),id);
68 }
69
70 void QWaylandDataDeviceManager::enter(void *data,
71               struct wl_data_device *wl_data_device,
72               uint32_t time,
73               struct wl_surface *surface,
74               wl_fixed_t x,
75               wl_fixed_t y,
76               struct wl_data_offer *id)
77 {
78
79     Q_UNUSED(wl_data_device);
80     Q_UNUSED(x);
81     Q_UNUSED(y);
82     QWaylandDataDeviceManager *data_device_manager = static_cast<QWaylandDataDeviceManager *>(data);
83     if (time < data_device_manager->m_drag_last_event_time)
84         return;
85     data_device_manager->m_drag_last_event_time = time;
86
87     data_device_manager->m_drag_current_event_window = static_cast<QWaylandWindow *>(wl_surface_get_user_data(surface));
88     if (!surface)
89         return;
90     QWaylandDataOffer *offer = static_cast<QWaylandDataOffer *>(wl_data_offer_get_user_data(id));
91     if (!offer)
92         return;
93
94 //    QPoint point(x,y);
95 //    Qt::DropActions allActions =  Qt::CopyAction | Qt::MoveAction | Qt::LinkAction;
96 //    QPlatformDragQtResponse response = QWindowSystemInterface::handleDrag(data_device_manager->m_drag_current_event_window->window(),
97 //                                                                          offer,point,allActions);
98 //    data_device_manager->m_drag_can_drop = response.accepted();
99     data_device_manager->m_drag_data_offer = offer;
100     if (data_device_manager->m_drag_can_drop) {
101         const char *first_offer = qPrintable(offer->formats_sys().at(0));
102         wl_data_offer_accept(offer->handle(),QWaylandDisplay::currentTimeMillisec(),first_offer);
103     } else {
104         wl_data_offer_accept(offer->handle(),QWaylandDisplay::currentTimeMillisec(),0);
105     }
106 }
107
108 void QWaylandDataDeviceManager::leave(void *data,
109               struct wl_data_device *wl_data_device)
110 {
111     Q_UNUSED(wl_data_device);
112     QWaylandDataDeviceManager *data_device_manager = static_cast<QWaylandDataDeviceManager *>(data);
113 //    QWindowSystemInterface::handleDrag(data_device_manager->m_drag_current_event_window->window(),0,QPoint(0,0),Qt::IgnoreAction);
114     data_device_manager->m_drag_can_drop = false;
115     data_device_manager->m_drag_data_offer = 0;
116     data_device_manager->m_drag_last_event_time = 0;
117     data_device_manager->m_drag_current_event_window = 0;
118     data_device_manager->m_drag_position = QPoint();
119 }
120
121 void QWaylandDataDeviceManager::motion(void *data,
122                struct wl_data_device *wl_data_device,
123                uint32_t time,
124                wl_fixed_t x,
125                wl_fixed_t y)
126 {
127     Q_UNUSED(wl_data_device);
128     QWaylandDataDeviceManager *data_device_manager = static_cast<QWaylandDataDeviceManager *>(data);
129     if (time < data_device_manager->m_drag_last_event_time)
130         return;
131     data_device_manager->m_drag_position = QPoint(wl_fixed_to_int(x), wl_fixed_to_int(y));
132
133 //    Qt::DropActions allActions =  Qt::CopyAction | Qt::MoveAction | Qt::LinkAction;
134 //    QPlatformDragQtResponse response = QWindowSystemInterface::handleDrag(data_device_manager->m_drag_current_event_window->window(),
135 //                                       data_device_manager->m_drag_data_offer, data_device_manager->m_drag_position ,allActions);
136 //    data_device_manager->m_drag_can_drop = response.accepted();
137     const char *offerMime = 0;
138     if (data_device_manager->m_drag_can_drop) {
139         offerMime = qPrintable(data_device_manager->m_drag_data_offer->formats_sys().at(0));
140     }
141     wl_data_offer_accept(data_device_manager->m_drag_data_offer->handle(),QWaylandDisplay::currentTimeMillisec(),offerMime);
142 }
143
144 void QWaylandDataDeviceManager::drop(void *data,
145              struct wl_data_device *wl_data_device)
146 {
147     Q_UNUSED(wl_data_device);
148     QWaylandDataDeviceManager *data_device_manager = static_cast<QWaylandDataDeviceManager *>(data);
149     QWindow *window = data_device_manager->m_drag_current_event_window->window();
150     QMimeData *mime = data_device_manager->m_drag_data_offer;
151 //    QPoint point = data_device_manager->m_drag_position;
152 //    Qt::DropActions allActions =  Qt::CopyAction | Qt::MoveAction | Qt::LinkAction;
153
154     Q_UNUSED(window);
155     Q_UNUSED(mime);
156 //    QWindowSystemInterface::handleDrop(window,mime,point,allActions);
157 }
158
159
160 void QWaylandDataDeviceManager::selection(void *data,
161                                             struct wl_data_device *wl_data_device,
162                                             struct wl_data_offer *id)
163 {
164     Q_UNUSED(wl_data_device);
165
166     QWaylandDataDeviceManager *handler = static_cast<QWaylandDataDeviceManager *>(data);
167     QWaylandDataOffer *mime = handler->m_selection_data_offer;
168     delete mime;
169     QWaylandDataSource *transfer_source = handler->m_selection_data_source;
170     delete transfer_source;
171     handler->m_selection_data_source = 0;
172
173     if (id) {
174         mime = static_cast<QWaylandDataOffer *>(wl_data_offer_get_user_data(id));
175         handler->m_selection_data_offer = mime;
176     } else {
177         handler->m_selection_data_offer = 0;
178     }
179
180     QGuiApplicationPrivate::platformIntegration()->clipboard()->emitChanged(QClipboard::Clipboard);
181 }
182
183 const struct wl_data_device_listener QWaylandDataDeviceManager::transfer_device_listener = {
184     QWaylandDataDeviceManager::data_offer,
185     QWaylandDataDeviceManager::enter,
186     QWaylandDataDeviceManager::leave,
187     QWaylandDataDeviceManager::motion,
188     QWaylandDataDeviceManager::drop,
189     QWaylandDataDeviceManager::selection
190 };
191
192 QWaylandDataDeviceManager::QWaylandDataDeviceManager(QWaylandDisplay *display, uint32_t id)
193     : m_display(display)
194     , m_selection_data_offer(0)
195     , m_selection_data_source(0)
196     , m_drag_data_offer(0)
197     , m_drag_data_source(0)
198     , m_drag_surface(0)
199     , m_drag_icon_surface(0)
200     , m_drag_icon_buffer(0)
201     , m_drag_can_drop(false)
202 {
203     m_data_device_manager = static_cast<struct wl_data_device_manager *>(wl_display_bind(display->wl_display(),id,&wl_data_device_manager_interface));
204
205     // Create transfer devices for all input devices.
206     // ### This only works if we get the global before all devices and is surely wrong when hotplugging.
207     QList<QWaylandInputDevice *> inputDevices = m_display->inputDevices();
208     for (int i = 0; i < inputDevices.size();i++) {
209         inputDevices.at(i)->setTransferDevice(getDataDevice(inputDevices.at(i)));
210     }
211 }
212
213 QWaylandDataDeviceManager::~QWaylandDataDeviceManager()
214 {
215     wl_data_device_manager_destroy(m_data_device_manager);
216 }
217
218 struct wl_data_device *QWaylandDataDeviceManager::getDataDevice(QWaylandInputDevice *inputDevice)
219 {
220     struct wl_data_device *transfer_device = wl_data_device_manager_get_data_device(m_data_device_manager,
221                                                                                     inputDevice->wl_seat());
222     wl_data_device_add_listener(transfer_device,&transfer_device_listener,this);
223
224     return transfer_device;
225 }
226
227 QWaylandDataOffer *QWaylandDataDeviceManager::selectionTransfer() const
228 {
229     return m_selection_data_offer;
230 }
231
232 void QWaylandDataDeviceManager::createAndSetDrag(QDrag *drag)
233 {
234     QWaylandInputDevice *inputDevice = m_display->lastKeyboardFocusInputDevice();
235     if (!inputDevice)
236         return;
237
238     if (m_drag_data_source) {
239         qDebug() << "QWaylandDndSelectionHandler::createAndSetDrag: Allready have a valid drag";
240         delete m_drag_data_source;
241     }
242
243     delete m_drag_data_offer;
244     m_drag_data_offer = 0;
245
246     m_drag_data_source = new QWaylandDataSource(this,drag->mimeData());
247
248     struct wl_data_device *transfer_device = inputDevice->transferDevice();
249     m_drag_surface = m_display->createSurface(this);
250     QPixmap pixmap = drag->pixmap();
251     if (pixmap.isNull()) {
252 //        pixmap = QPlatformDrag::defaultPixmap();
253     }
254
255     m_drag_icon_buffer = new QWaylandShmBuffer(m_display, pixmap.size(), QImage::Format_ARGB32_Premultiplied);
256
257     {
258         QPainter p(m_drag_icon_buffer->image());
259         p.drawPixmap(0,0,pixmap);
260     }
261
262     m_drag_icon_surface = wl_compositor_create_surface(m_display->wl_compositor());
263     wl_surface_attach(m_drag_icon_surface, m_drag_icon_buffer->buffer(), -drag->hotSpot().x(), -drag->hotSpot().y());
264
265     wl_data_device_start_drag(transfer_device, m_drag_data_source->handle(), m_drag_surface, m_drag_icon_surface, QWaylandDisplay::currentTimeMillisec());
266 }
267
268 QMimeData *QWaylandDataDeviceManager::dragMime() const
269 {
270     if (m_drag_data_offer) {
271         return m_drag_data_offer;
272     } else if (m_drag_data_source){
273         return m_drag_data_source->mimeData();
274     }
275     return 0;
276 }
277
278 bool QWaylandDataDeviceManager::canDropDrag() const
279 {
280     return m_drag_can_drop;
281 }
282
283 void QWaylandDataDeviceManager::cancelDrag()
284 {
285     wl_data_source_destroy(m_drag_data_source->handle() );
286     wl_surface_destroy(m_drag_icon_surface);
287     m_drag_data_source = 0;
288 }
289
290 void QWaylandDataDeviceManager::createAndSetSelectionSource(QMimeData *mimeData, QClipboard::Mode mode)
291 {
292     Q_UNUSED(mode);
293     QWaylandDataSource *transfer_source = m_selection_data_source;
294     delete transfer_source;
295
296     transfer_source = new QWaylandDataSource(this,mimeData);
297     m_selection_data_source = transfer_source;
298     QWaylandInputDevice *inputDevice = m_display->lastKeyboardFocusInputDevice();
299     if (!inputDevice)
300         inputDevice = m_display->inputDevices().first(); // try to survive in apps without any surfaces
301     struct wl_data_device *transfer_device = inputDevice->transferDevice();
302     wl_data_device_set_selection(transfer_device,transfer_source->handle(),QWaylandDisplay::currentTimeMillisec());
303
304     QGuiApplicationPrivate::platformIntegration()->clipboard()->emitChanged(QClipboard::Clipboard);
305 }
306
307 QWaylandDataSource *QWaylandDataDeviceManager::selectionTransferSource()
308 {
309     return m_selection_data_source;
310 }
311
312
313 QWaylandDisplay * QWaylandDataDeviceManager::display() const
314 {
315     return m_display;
316 }
317
318 struct wl_data_device_manager *QWaylandDataDeviceManager::handle() const
319 {
320     return m_data_device_manager;
321 }
322
323