diff options
Diffstat (limited to 'src/compositor/wayland_wrapper/wlcompositor.cpp')
-rw-r--r-- | src/compositor/wayland_wrapper/wlcompositor.cpp | 428 |
1 files changed, 428 insertions, 0 deletions
diff --git a/src/compositor/wayland_wrapper/wlcompositor.cpp b/src/compositor/wayland_wrapper/wlcompositor.cpp new file mode 100644 index 000000000..168094734 --- /dev/null +++ b/src/compositor/wayland_wrapper/wlcompositor.cpp @@ -0,0 +1,428 @@ +/**************************************************************************** +** +** This file is part of QtCompositor** +** +** Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** Contact: Nokia Corporation qt-info@nokia.com +** +** You may use this file under the terms of the BSD license as follows: +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** +** Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +****************************************************************************/ + +#include "wlcompositor.h" + +#include "waylandobject.h" +#include "wldisplay.h" +#include "wlshmbuffer.h" +#include "wlsurface.h" +#include "wlinputdevice.h" +#include "waylandcompositor.h" +#include "wldatadevicemanager.h" +#include "wldatadevice.h" + +#include <QWindow> +#include <QSocketNotifier> +#include <QDebug> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stddef.h> +#include <errno.h> +#include <fcntl.h> +#include <unistd.h> + +#include <sys/mman.h> +#include <sys/select.h> +#include <sys/time.h> + +#include <wayland-server.h> + +#include "hardware_integration/graphicshardwareintegration.h" +#include "waylandwindowmanagerintegration.h" + +namespace Wayland { + +static Compositor *compositor; + +static void shmBufferDestroyed(ShmBuffer *buf) +{ +// if (currentCursor == buf) { +// compositor->qtCompositor()->changeCursor(QImage(), 0, 0); +// currentCursor = 0; +// } +} + +void destroy_surface(struct wl_resource *resource) +{ + Surface *surface = wayland_cast<Surface *>((wl_surface *)resource); + delete surface; +} + +void compositor_create_surface(struct wl_client *client, + struct wl_resource *resource, uint32_t id) +{ + static_cast<Compositor *>(resource->data)->createSurface(client,id); +} + +const static struct wl_compositor_interface compositor_interface = { + compositor_create_surface +}; + +void Compositor::bind_func(struct wl_client *client, void *data, + uint32_t version, uint32_t id) +{ + wl_client_add_object(client,&wl_compositor_interface, &compositor_interface, id,data); +} + + +Compositor *Compositor::instance() +{ + return compositor; +} + +Compositor::Compositor(WaylandCompositor *qt_compositor) + : m_display(new Display) + , m_shell(this) + , m_shm(m_display) + , m_current_frame(0) + , m_last_queued_buf(-1) + , m_qt_compositor(qt_compositor) + , m_orientation(Qt::UnknownOrientation) + , m_pointerFocusSurface(0) + , m_keyFocusSurface(0) + , m_directRenderSurface(0) +#if defined (QT_COMPOSITOR_WAYLAND_GL) + , m_graphics_hw_integration(0) +#endif +{ + compositor = this; + qDebug() << "Compositor instance is" << this; + m_shm.addDestroyCallback(shmBufferDestroyed); + +#if defined (QT_COMPOSITOR_WAYLAND_GL) + QWindow *window = qt_compositor->window(); + if (window && window->surfaceType() != QWindow::RasterSurface) + m_graphics_hw_integration = GraphicsHardwareIntegration::createGraphicsHardwareIntegration(qt_compositor); +#endif + m_windowManagerWaylandProtocol = new WindowManagerServerIntegration(this); + connect(m_windowManagerWaylandProtocol, + SIGNAL(windowPropertyChanged(wl_client*,wl_surface*,QString,QVariant)), + SLOT(windowPropertyChanged(wl_client*,wl_surface*,QString,QVariant))); + + wl_display_add_global(m_display->handle(),&wl_compositor_interface,this,Compositor::bind_func); + + m_input = new InputDevice(this); + + m_data_device_manager = new DataDeviceManager(this); + wl_display_add_global(m_display->handle(),&wl_output_interface,m_output.base(),Output::output_bind_func); + + wl_display_add_global(m_display->handle(), &wl_shell_interface, m_shell.base(), Shell::bind_func); + + + if (wl_display_add_socket(m_display->handle(), qt_compositor->socketName())) { + fprintf(stderr, "Fatal: Failed to open server socket\n"); + exit(EXIT_FAILURE); + } + + m_loop = wl_display_get_event_loop(m_display->handle()); + + int fd = wl_event_loop_get_fd(m_loop); + + QSocketNotifier *sockNot = new QSocketNotifier(fd, QSocketNotifier::Read, this); + connect(sockNot, SIGNAL(activated(int)), this, SLOT(processWaylandEvents())); + + //initialize distancefieldglyphcache here +} + +Compositor::~Compositor() +{ + delete m_input; + delete m_data_device_manager; + + delete m_display; +} + +void Compositor::frameFinished(Surface *surface) +{ + if (surface && m_dirty_surfaces.contains(surface)) { + surface->sendFrameCallback(); + m_dirty_surfaces.remove(surface); + } else if (!surface) { + foreach (Surface *surface, m_dirty_surfaces) + surface->sendFrameCallback(); + m_dirty_surfaces.clear(); + } +} + +void Compositor::createSurface(struct wl_client *client, int id) +{ + Surface *surface = new Surface(client, this); + printf("Compositor::createSurface: %p %d\n", client, id); + + addClientResource(client, &surface->base()->resource, id, &wl_surface_interface, + &Surface::surface_interface, destroy_surface); + + QList<struct wl_client *> prevClientList = clients(); + m_surfaces << surface; + if (!prevClientList.contains(client)) { + m_windowManagerWaylandProtocol->setScreenOrientation(client, m_output.base(), m_orientation); + emit clientAdded(client); + } + + m_qt_compositor->surfaceCreated(surface->handle()); +} + +struct wl_client *Compositor::getClientFromWinId(uint winId) const +{ + Surface *surface = getSurfaceFromWinId(winId); + if (surface) + return surface->base()->resource.client; + + return 0; +} + +Surface *Compositor::getSurfaceFromWinId(uint winId) const +{ + foreach (Surface *surface, m_surfaces) { + if (surface->id() == winId) + return surface; + } + + return 0; +} + +QImage Compositor::image(uint winId) const +{ + printf("Compositor::image(%x)\n", winId); + foreach (Surface *surface, m_surfaces) { + if (surface->id() == winId) { + return surface->image(); + } + } + + return QImage(); +} + +uint Compositor::currentTimeMsecs() +{ + //### we throw away the time information + struct timeval tv; + int ret = gettimeofday(&tv, 0); + if (ret == 0) + return tv.tv_sec*1000 + tv.tv_usec/1000; + return 0; +} + +void Compositor::releaseBuffer(void *bufferHandle) +{ + struct wl_buffer *buffer = static_cast<struct wl_buffer*>(bufferHandle); + if (buffer) { + //qDebug() << "WL_BUFFER_RELEASE" << buffer<< buffer->resource.client; + wl_resource_post_event(&buffer->resource, WL_BUFFER_RELEASE); + } + +} + +void Compositor::processWaylandEvents() +{ + int ret = wl_event_loop_dispatch(m_loop, 0); + if (ret) + fprintf(stderr, "wl_event_loop_dispatch error: %d\n", ret); +} + +void Compositor::windowPropertyChanged(wl_client *client, wl_surface *changedSurface, const QString &name, const QVariant &value) +{ + for(int i = 0; i < m_surfaces.length(); ++i) { + Surface *surface = m_surfaces[i]; + if (surface->clientHandle() == client && surface->base() == changedSurface) { + surface->setWindowProperty(name, value, false); + } + } +} + +void Compositor::surfaceDestroyed(Surface *surface) +{ + m_surfaces.removeOne(surface); + if (m_keyFocusSurface == surface) + setKeyFocus(0); + if (m_pointerFocusSurface == surface) + setPointerFocus(0); + if (m_directRenderSurface == surface) + setDirectRenderSurface(0); +} + +void Compositor::markSurfaceAsDirty(Wayland::Surface *surface) +{ + m_dirty_surfaces.insert(surface); +} + +void Compositor::destroyClientForSurface(Surface *surface) +{ + wl_client *client = surface->base()->resource.client; + + if (client) { + m_windowManagerWaylandProtocol->removeClient(client); + wl_client_destroy(client); + } +} + +void Compositor::setInputFocus(Surface *surface) +{ + setKeyFocus(surface); + setPointerFocus(surface); +} + +void Compositor::setKeyFocus(Surface *surface) +{ + m_input->sendSelectionFocus(surface); + m_keyFocusSurface = surface; + wl_input_device_set_keyboard_focus(m_input->base(), surface ? surface->base() : 0, currentTimeMsecs()); +} + +Surface *Compositor::keyFocus() const +{ + return m_keyFocusSurface; +} + +void Compositor::setPointerFocus(Surface *surface, const QPoint &pos) +{ + m_pointerFocusSurface = surface; + wl_input_device_set_pointer_focus(m_input->base(), surface ? surface->base() : 0, currentTimeMsecs(), pos.x(), pos.y(), pos.x(), pos.y()); +} + +Surface *Compositor::pointerFocus() const +{ + return m_pointerFocusSurface; +} + +QWindow *Compositor::window() const +{ + return m_qt_compositor->window(); +} + +GraphicsHardwareIntegration * Compositor::graphicsHWIntegration() const +{ +#ifdef QT_COMPOSITOR_WAYLAND_GL + return m_graphics_hw_integration; +#else + return 0; +#endif +} + +void Compositor::initializeHardwareIntegration() +{ +#ifdef QT_COMPOSITOR_WAYLAND_GL + if (m_graphics_hw_integration) + m_graphics_hw_integration->initializeHardware(m_display); +#endif +} + +void Compositor::initializeWindowManagerProtocol() +{ + m_windowManagerWaylandProtocol->initialize(m_display); +} + +bool Compositor::setDirectRenderSurface(Surface *surface) +{ +#ifdef QT_COMPOSITOR_WAYLAND_GL + if (m_graphics_hw_integration && m_graphics_hw_integration->setDirectRenderSurface(surface ? surface->handle() : 0)) { + m_directRenderSurface = surface; + return true; + } +#else + Q_UNUSED(surface); +#endif + return false; +} + +QList<struct wl_client *> Compositor::clients() const +{ + QList<struct wl_client *> list; + foreach (Surface *surface, m_surfaces) { + struct wl_client *client = surface->base()->resource.client; + if (!list.contains(client)) + list.append(client); + } + return list; +} + +void Compositor::setScreenOrientation(Qt::ScreenOrientation orientation) +{ + m_orientation = orientation; + + QList<struct wl_client*> clientList = clients(); + for (int i = 0; i < clientList.length(); ++i) { + struct wl_client *client = clientList.at(i); + m_windowManagerWaylandProtocol->setScreenOrientation(client, m_output.base(), orientation); + } +} + +void Compositor::setOutputGeometry(const QRect &geometry) +{ + m_output.setGeometry(geometry); +} + +InputDevice* Compositor::defaultInputDevice() +{ + return m_input; +} + +QList<Wayland::Surface *> Compositor::surfacesForClient(wl_client *client) +{ + QList<Wayland::Surface *> ret; + + for (int i=0; i < m_surfaces.count(); ++i) { + if (m_surfaces.at(i)->clientHandle() == client) { + ret.append(m_surfaces.at(i)); + } + } + return ret; +} + +bool Compositor::isDragging() const +{ + return false; +} + +void Compositor::sendDragMoveEvent(const QPoint &global, const QPoint &local, + Surface *surface) +{ +// Drag::instance()->dragMove(global, local, surface); +} + +void Compositor::sendDragEndEvent() +{ +// Drag::instance()->dragEnd(); +} + +} // namespace Wayland |