From 2b092460101d25466d7dbf9a470f0a8a9eb02774 Mon Sep 17 00:00:00 2001 From: Pier Luigi Fiorini Date: Wed, 22 Oct 2014 20:29:00 +0200 Subject: [PATCH] QML compositor based on Green Island Add an initial compositor written with QML for Green Island. --- CMakeLists.txt | 1 + compositor/contents/ClientWindowWrapper.qml | 24 +++ compositor/contents/Compositor.qml | 60 ++++++ compositor/contents/ShellWindowWrapper.qml | 24 +++ compositor/contents/WindowManagement.js | 192 ++++++++++++++++++++ compositor/contents/WindowWrapper.qml | 37 ++++ compositor/metadata.desktop | 14 ++ 7 files changed, 352 insertions(+) create mode 100644 compositor/contents/ClientWindowWrapper.qml create mode 100644 compositor/contents/Compositor.qml create mode 100644 compositor/contents/ShellWindowWrapper.qml create mode 100644 compositor/contents/WindowManagement.js create mode 100644 compositor/contents/WindowWrapper.qml create mode 100644 compositor/metadata.desktop diff --git a/CMakeLists.txt b/CMakeLists.txt index 328bf27e..0502b2d0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,6 +33,7 @@ feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAG include(CheckIncludeFiles) +plasma_install_package(compositor org.kde.satellite.compositor.phone greenisland/compositors) plasma_install_package(look-and-feel org.kde.satellite.phone look-and-feel) plasma_install_package(shell org.kde.satellite.phone shells) install(DIRECTORY wallpaper/ DESTINATION "${WALLPAPER_INSTALL_DIR}/org.kde.satellite.lockers") diff --git a/compositor/contents/ClientWindowWrapper.qml b/compositor/contents/ClientWindowWrapper.qml new file mode 100644 index 00000000..3994a9fb --- /dev/null +++ b/compositor/contents/ClientWindowWrapper.qml @@ -0,0 +1,24 @@ +/* + * Copyright 2014 Pier Luigi Fiorini + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +import QtQuick 2.0 + +WindowWrapper { + objectName: "clientWindow" +} diff --git a/compositor/contents/Compositor.qml b/compositor/contents/Compositor.qml new file mode 100644 index 00000000..37c24801 --- /dev/null +++ b/compositor/contents/Compositor.qml @@ -0,0 +1,60 @@ +/* + * Copyright 2014 Pier Luigi Fiorini + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +import QtQuick 2.0 +import org.kde.plasma.core 2.0 as PlasmaCore +import "WindowManagement.js" as WindowManagement + +Rectangle { + readonly property alias layers: layers + readonly property real topBarHeight: units.iconSizes.small + + id: compositorRoot + color: "black" + + ListModel { + id: surfaceModel + } + + Connections { + target: compositor + onSurfaceMapped: WindowManagement.surfaceMapped(surface) + onSurfaceUnmapped: WindowManagement.surfaceUnmapped(surface) + onSurfaceDestroyed: WindowManagement.surfaceDestroyed(surface) + } + + Item { + readonly property alias desktop: desktopLayer + readonly property alias windows: windowsLayer + + id: layers + anchors.fill: parent + + Item { + id: desktopLayer + anchors.fill: parent + } + + Item { + id: windowsLayer + anchors.fill: parent + anchors.topMargin: topBarHeight + } + } +} diff --git a/compositor/contents/ShellWindowWrapper.qml b/compositor/contents/ShellWindowWrapper.qml new file mode 100644 index 00000000..00e30cce --- /dev/null +++ b/compositor/contents/ShellWindowWrapper.qml @@ -0,0 +1,24 @@ +/* + * Copyright 2014 Pier Luigi Fiorini + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +import QtQuick 2.0 + +WindowWrapper { + objectName: "shellWindow" +} diff --git a/compositor/contents/WindowManagement.js b/compositor/contents/WindowManagement.js new file mode 100644 index 00000000..67b29dab --- /dev/null +++ b/compositor/contents/WindowManagement.js @@ -0,0 +1,192 @@ +/* + * Copyright 2014 Pier Luigi Fiorini + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/* + * Main procedures + */ + +function surfaceMapped(surface) { + // Get the first view and if it has a role property than this + // is definitely a shell window + var firstView = compositor.firstViewOf(surface); + if (typeof(firstView.role) == "undefined") { + console.debug("Application surface", surface, "mapped"); + console.debug("\tappId:", surface.className); + console.debug("\ttitle:", surface.title); + console.debug("\tsize:", surface.size.width + "x" + surface.size.height); + } else { + console.debug("Shell surface", surface, "mapped"); + console.debug("\trole:", firstView.role); + console.debug("\tsize:", surface.size.width + "x" + surface.size.height); + } + + // Call a specialized method to deal with application or + // shell windows + if (typeof(firstView.role) == "undefined") + mapApplicationSurface(surface); + else + mapShellSurface(surface, firstView); +} + +function surfaceUnmapped(surface) { + // Get the first view and if it has a role property than this + // is definitely a shell window + var firstView = compositor.firstViewOf(surface); + if (typeof(firstView.role) == "undefined") { + console.debug("Application surface", surface, "unmapped"); + console.debug("\tappId:", surface.className); + console.debug("\ttitle:", surface.title); + } else { + console.debug("Shell surface", surface, "unmapped"); + console.debug("\trole:", firstView.role); + console.debug("\tsize:", surface.size.width + "x" + surface.size.height); + } + + // Call a specialized method to deal with application or + // shell windows + if (typeof(firstView.role) == "undefined") + unmapApplicationSurface(surface); + else + unmapShellSurface(surface); +} + +function surfaceDestroyed(surface) { + console.debug("Surface", surface, "destroyed"); + + // Remove surface from model + var i; + for (i = 0; i < surfaceModel.count; i++) { + var entry = surfaceModel.get(i); + + if (entry.surface === surface) { + // Destroy window representation and + // remove the surface from the model + if (entry.window.chrome) + entry.window.chrome.destroy(); + entry.window.destroy(); + surfaceModel.remove(i, 1); + break; + } + } +} + +/* + * Map surfaces + */ + +function mapApplicationSurface(surface) { + // Just exit if we already created a window representation + var i; + for (i = 0; i < surfaceModel.count; i++) { + var entry = surfaceModel.get(i); + + if (entry.surface === surface) + return; + } + + // Create surface item + var component = Qt.createComponent("ClientWindowWrapper.qml"); + if (component.status !== Component.Ready) { + console.error(component.errorString()); + return; + } + + // Window position: y is hard coded to the top bar height + var pos = Qt.point(0, compositorRoot.topBarHeight); + + // Request a view for this output although with phones will + // likely have just one output + var child = compositor.viewForOutput(surface, _greenisland_output); + + // Create and setup window container + var window = component.createObject(compositorRoot, {"child": child}); + window.child.parent = window; + window.child.touchEventsEnabled = true; + window.width = surface.size.width; + window.height = surface.size.height; + + // Move window + window.x = pos.x; + window.y = pos.y; + + // Reparent and give focus + window.parent = compositorRoot.layers.windows; + window.child.takeFocus(); + + // Set size to parent (windows layer) + window.child.resizeSurfaceToItem = true; + window.width = window.parent.width; + window.height = window.parent.height; + + // Log coordinates for debugging purpose + console.debug("\tposition:", window.x + "," + window.y); + + // Run map animation + if (typeof(window.runMapAnimation) != "undefined") + window.runMapAnimation(); + + // Add surface to the model + surfaceModel.append({"surface": surface, "window": window}); +} + +function mapShellSurface(surface, child) { + // Shell surfaces have only one view which is passed to us + // as an argument, check whether it's a view for this output + // or not + if (child.output !== _greenisland_output) + return; + + // Create surface item + var component = Qt.createComponent("ShellWindowWrapper.qml"); + if (component.status !== Component.Ready) { + console.error(component.errorString()); + return; + } + + // Create and setup window container + var window = component.createObject(compositorRoot, {"child": child}); + window.child.parent = window; + window.child.touchEventsEnabled = true; + window.width = surface.size.width; + window.height = surface.size.height; + + // Set initial position + // XXX: We only support desktop roles for now + window.x = window.y = 0; + + // Set appropriate parent + // XXX: We only support desktop roles for now + window.parent = compositorRoot.layers.desktop; + + // Log coordinates for debugging purpose + console.debug("\tposition:", window.x + "," + window.y); + + // Add surface to the model + surfaceModel.append({"surface": surface, "window": window}); +} + +/* + * Unmap surfaces + */ + +function unmapApplicationSurface(surface) { +} + +function unmapShellSurface(surface) { +} diff --git a/compositor/contents/WindowWrapper.qml b/compositor/contents/WindowWrapper.qml new file mode 100644 index 00000000..411480e2 --- /dev/null +++ b/compositor/contents/WindowWrapper.qml @@ -0,0 +1,37 @@ +/* + * Copyright 2014 Pier Luigi Fiorini + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +import QtQuick 2.0 +import QtCompositor 1.0 +import GreenIsland 1.0 + +Item { + property var child + property var role: child.surface.windowProperties.role + + onVisibleChanged: { + if (child) + child.surface.clientRenderingEnabled = visible; + } + + SurfaceRenderer { + anchors.fill: parent + source: child + } +} diff --git a/compositor/metadata.desktop b/compositor/metadata.desktop new file mode 100644 index 00000000..691f7100 --- /dev/null +++ b/compositor/metadata.desktop @@ -0,0 +1,14 @@ +[Desktop Entry] +Name=Phone +Type=Service + +X-KDE-ServiceTypes=GreenIsland/Compositor +X-KDE-ParentApp= +X-KDE-PluginInfo-Author=Pier Luigi Fiorini +X-KDE-PluginInfo-Category= +X-KDE-PluginInfo-Email=pierluigi.fiorini@gmail.com +X-KDE-PluginInfo-License=GPLv2+ +X-KDE-PluginInfo-Name=org.kde.satellite.compositor.phone +X-KDE-PluginInfo-Version=0.1 +X-KDE-PluginInfo-Website= +