summaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
Diffstat (limited to 'shell')
-rw-r--r--shell/Makefile.am22
-rw-r--r--shell/gtk-shell.c12
-rw-r--r--shell/shell-helper.c255
3 files changed, 286 insertions, 3 deletions
diff --git a/shell/Makefile.am b/shell/Makefile.am
index dfbf2eb..ca52883 100644
--- a/shell/Makefile.am
+++ b/shell/Makefile.am
@@ -27,12 +27,16 @@ weston_gtk_shell_SOURCES = \
weston-gtk-shell-resources.h \
desktop-shell-client-protocol.h \
desktop-shell-protocol.c \
+ shell-helper-client-protocol.h \
+ shell-helper-protocol.c \
$(external_sources)
weston_gtk_shell_LDADD = $(GTK_LIBS)
BUILT_SOURCES = \
desktop-shell-client-protocol.h \
desktop-shell-protocol.c \
+ shell-helper-client-protocol.h \
+ shell-helper-protocol.c \
weston-gtk-shell-resources.c \
weston-gtk-shell-resources.h
@@ -45,6 +49,24 @@ weston-gtk-shell-resources.h: weston-gtk-shell.gresource.xml $(resource_files)
EXTRA_DIST = style.css
+# shell-helper weston module
+moduledir = $(libdir)/weston
+module_LTLIBRARIES = shell-helper.la
+
+# otherwise shell-helper-protocol.c is generated twice- once with
+# libtool and once without
+mod-%-protocol.c : $(wayland_protocoldir)/%.xml
+ $(AM_V_GEN)$(wayland_scanner) code < $< > $@
+
+shell_helper_la_LDFLAGS = -module -avoid-version
+shell_helper_la_LIBADD = $(GTK_LIBS)
+shell_helper_la_SOURCES = \
+ shell-helper.c
+nodist_shell_helper_la_SOURCES = \
+ mod-shell-helper-protocol.c \
+ shell-helper-server-protocol.h
+
+BUILT_SOURCES += $(nodist_shell_helper_la_SOURCES)
CLEANFILES = $(BUILT_SOURCES)
@wayland_scanner_rules@
diff --git a/shell/gtk-shell.c b/shell/gtk-shell.c
index a899a1e..a448947 100644
--- a/shell/gtk-shell.c
+++ b/shell/gtk-shell.c
@@ -5,6 +5,7 @@
#include <gdk/gdkwayland.h>
#include "desktop-shell-client-protocol.h"
+#include "shell-helper-client-protocol.h"
#include "weston-gtk-shell-resources.h"
@@ -28,6 +29,7 @@ struct desktop {
struct wl_registry *registry;
struct desktop_shell *shell;
struct wl_output *output;
+ struct shell_helper *helper;
GdkDisplay *gdk_display;
@@ -269,6 +271,9 @@ registry_handle_global(void *data, struct wl_registry *registry,
/* TODO: create multiple outputs */
d->output = wl_registry_bind(registry, name,
&wl_output_interface, 1);
+ } else if (!strcmp(interface, "shell_helper")) {
+ d->helper = wl_registry_bind(registry, name,
+ &shell_helper_interface, 1);
}
}
@@ -297,6 +302,7 @@ main(int argc, char *argv[])
desktop = malloc(sizeof *desktop);
desktop->output = NULL;
desktop->shell = NULL;
+ desktop->helper = NULL;
desktop->gdk_display = gdk_display_get_default();
desktop->display =
@@ -310,9 +316,9 @@ main(int argc, char *argv[])
wl_registry_add_listener(desktop->registry,
&registry_listener, desktop);
- /* Wait until we have been notified about the compositor and shell
- * objects */
- while (!desktop->output || !desktop->shell)
+ /* Wait until we have been notified about the compositor,
+ * shell, and shell helper objects */
+ while (!desktop->output || !desktop->shell || !desktop->helper)
wl_display_roundtrip (desktop->display);
css_setup(desktop);
diff --git a/shell/shell-helper.c b/shell/shell-helper.c
new file mode 100644
index 0000000..71e9b6f
--- /dev/null
+++ b/shell/shell-helper.c
@@ -0,0 +1,255 @@
+#include <stdio.h>
+#include <assert.h>
+
+#include <weston/compositor.h>
+
+#include "shell-helper-server-protocol.h"
+
+struct shell_helper {
+ struct weston_compositor *compositor;
+
+ struct wl_listener destroy_listener;
+
+ struct wl_list slide_list;
+};
+
+static void
+shell_helper_move_surface(struct wl_client *client,
+ struct wl_resource *resource,
+ struct wl_resource *surface_resource,
+ int32_t x,
+ int32_t y)
+{
+ struct shell_helper *helper = wl_resource_get_user_data(resource);
+ struct weston_surface *surface =
+ wl_resource_get_user_data(surface_resource);
+ struct weston_view *view;
+
+ view = container_of(surface->views.next, struct weston_view, surface_link);
+
+ if (!view)
+ return;
+
+ weston_view_set_position(view, x, y);
+ weston_view_update_transform(view);
+}
+
+enum SlideState {
+ SLIDE_STATE_NONE,
+ SLIDE_STATE_SLIDING_OUT,
+ SLIDE_STATE_OUT,
+ SLIDE_STATE_SLIDING_BACK,
+ SLIDE_STATE_BACK
+};
+
+enum SlideRequest {
+ SLIDE_REQUEST_NONE,
+ SLIDE_REQUEST_OUT,
+ SLIDE_REQUEST_BACK
+};
+
+struct slide {
+ struct weston_surface *surface;
+ struct weston_view *view;
+ int x;
+ int y;
+
+ enum SlideState state;
+ enum SlideRequest request;
+
+ struct weston_transform transform;
+
+ struct wl_list link;
+};
+
+static void slide_back(struct slide *slide);
+
+static void
+slide_done_cb(struct weston_view_animation *animation, void *data)
+{
+ struct slide *slide = data;
+
+ slide->state = SLIDE_STATE_OUT;
+
+ wl_list_insert(&slide->view->transform.position.link,
+ &slide->transform.link);
+ weston_matrix_init(&slide->transform.matrix);
+ weston_matrix_translate(&slide->transform.matrix,
+ slide->x,
+ slide->y,
+ 0);
+
+ weston_view_geometry_dirty(slide->view);
+ weston_compositor_schedule_repaint(slide->surface->compositor);
+
+ if (slide->request == SLIDE_REQUEST_BACK) {
+ slide->request = SLIDE_REQUEST_NONE;
+ slide_back(slide);
+ }
+}
+
+static void
+slide_out(struct slide *slide)
+{
+ assert(slide->state == SLIDE_STATE_NONE || slide->state == SLIDE_STATE_BACK);
+
+ slide->state = SLIDE_STATE_SLIDING_OUT;
+
+ weston_move_scale_run(slide->view, slide->x, slide->y,
+ 1.0, 1.0, 0,
+ slide_done_cb, slide);
+}
+
+static void
+slide_back_done_cb(struct weston_view_animation *animation, void *data)
+{
+ struct slide *slide = data;
+
+ slide->state = SLIDE_STATE_BACK;
+
+ wl_list_remove(&slide->transform.link);
+ weston_view_geometry_dirty(slide->view);
+
+ if (slide->request == SLIDE_REQUEST_OUT) {
+ slide->request = SLIDE_REQUEST_NONE;
+ slide_out(slide);
+ } else {
+ wl_list_remove(&slide->link);
+ free(slide);
+ }
+}
+
+static void
+slide_back(struct slide *slide)
+{
+ assert(slide->state == SLIDE_STATE_OUT);
+
+ slide->state = SLIDE_STATE_SLIDING_BACK;
+
+ weston_move_scale_run(slide->view, -slide->x, -slide->y,
+ 1.0, 1.0, 0,
+ slide_back_done_cb, slide);
+}
+
+static void
+shell_helper_slide_surface(struct wl_client *client,
+ struct wl_resource *resource,
+ struct wl_resource *surface_resource,
+ int32_t x,
+ int32_t y)
+{
+ struct shell_helper *helper = wl_resource_get_user_data(resource);
+ struct weston_surface *surface =
+ wl_resource_get_user_data(surface_resource);
+ struct weston_view *view;
+ struct slide *slide;
+
+ wl_list_for_each(slide, &helper->slide_list, link) {
+ if (slide->surface == surface) {
+ if (slide->state == SLIDE_STATE_SLIDING_BACK)
+ slide->request = SLIDE_REQUEST_OUT;
+ return;
+ }
+ }
+
+ view = container_of(surface->views.next, struct weston_view, surface_link);
+
+ if (!view)
+ return;
+
+ slide = malloc(sizeof *slide);
+ if (!slide)
+ return;
+
+ slide->surface = surface;
+ slide->view = view;
+ slide->x = x;
+ slide->y = y;
+
+ slide->state = SLIDE_STATE_NONE;
+ slide->request = SLIDE_REQUEST_NONE;
+
+ wl_list_insert(&helper->slide_list,
+ &slide->link);
+
+ slide_out(slide);
+}
+
+static void
+shell_helper_slide_surface_back(struct wl_client *client,
+ struct wl_resource *resource,
+ struct wl_resource *surface_resource)
+{
+ struct shell_helper *helper = wl_resource_get_user_data(resource);
+ struct weston_surface *surface =
+ wl_resource_get_user_data(surface_resource);
+ struct weston_view *view;
+ int found = 0;
+ struct slide *slide;
+
+ wl_list_for_each(slide, &helper->slide_list, link) {
+ if (slide->surface == surface) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found || slide->state == SLIDE_STATE_SLIDING_BACK)
+ return;
+
+ if (slide->state == SLIDE_STATE_SLIDING_OUT)
+ slide->request = SLIDE_REQUEST_BACK;
+ else
+ slide_back(slide);
+}
+
+static const struct shell_helper_interface helper_implementation = {
+ shell_helper_move_surface,
+ shell_helper_slide_surface,
+ shell_helper_slide_surface_back
+};
+
+static void
+bind_helper(struct wl_client *client, void *data, uint32_t version, uint32_t id)
+{
+ struct shell_helper *helper = data;
+ struct wl_resource *resource;
+
+ resource = wl_resource_create(client, &shell_helper_interface, 1, id);
+ if (resource)
+ wl_resource_set_implementation(resource, &helper_implementation,
+ helper, NULL);
+}
+
+static void
+helper_destroy(struct wl_listener *listener, void *data)
+{
+ struct shell_helper *helper =
+ container_of(listener, struct shell_helper, destroy_listener);
+
+ free(helper);
+}
+
+WL_EXPORT int
+module_init(struct weston_compositor *ec,
+ int *argc, char *argv[])
+{
+ struct shell_helper *helper;
+
+ helper = zalloc(sizeof *helper);
+ if (helper == NULL)
+ return -1;
+
+ helper->compositor = ec;
+
+ wl_list_init(&helper->slide_list);
+
+ helper->destroy_listener.notify = helper_destroy;
+ wl_signal_add(&ec->destroy_signal, &helper->destroy_listener);
+
+ if (wl_global_create(ec->wl_display, &shell_helper_interface, 1,
+ helper, bind_helper) == NULL)
+ return -1;
+
+ return 0;
+}