[mutter/wip/resize: 1/2] workspaces



commit 7e2149364c6021bce3ff5e2f10e6f422dbd5d793
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Mon Feb 3 19:24:09 2014 -0500

    workspaces

 .gitignore                          |    2 +
 protocol/workspaces.xml             |   27 ++++++++
 src/Makefile.am                     |    2 +
 src/core/display.c                  |    7 ++
 src/wayland/meta-wayland-private.h  |    7 ++
 src/wayland/meta-wayland-versions.h |    1 +
 src/wayland/meta-wayland.c          |  112 +++++++++++++++++++++++++++++++++++
 7 files changed, 158 insertions(+), 0 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index ba75840..ebf215a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -80,6 +80,8 @@ src/meta-dbus-idle-monitor.[ch]
 src/mutter-plugins.pc
 src/wayland/gtk-shell-protocol.c
 src/wayland/gtk-shell-server-protocol.h
+src/wayland/workspaces-protocol.c
+src/wayland/workspaces-server-protocol.h
 src/wayland/xdg-shell-protocol.c
 src/wayland/xdg-shell-server-protocol.h
 src/wayland/xserver-protocol.c
diff --git a/protocol/workspaces.xml b/protocol/workspaces.xml
new file mode 100644
index 0000000..22f4802
--- /dev/null
+++ b/protocol/workspaces.xml
@@ -0,0 +1,27 @@
+<protocol name="workspaces">
+
+  <interface name="workspace_manager" version="1">
+    <description summary="workspaces manager">
+      An interface for managing surfaces in workspaces.
+    </description>
+
+    <request name="move_surface">
+      <description summary="move surface to workspace">
+       Move the given surface to the specified workspace.
+      </description>
+      <arg name="surface" type="object" interface="wl_surface"/>
+      <arg name="workspace" type="uint"/>
+    </request>
+
+    <event name="state">
+      <description summary="workspace state">
+       The current workspace state, such as current workspace and workspace
+       count, has changed.
+      </description>
+      <arg name="current" type="uint"/>
+      <arg name="count" type="uint"/>
+    </event>
+
+  </interface>
+
+</protocol>
diff --git a/src/Makefile.am b/src/Makefile.am
index 89d2521..4a6ec0e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -42,6 +42,8 @@ mutter_built_sources = \
        mutter-enum-types.c                     \
        wayland/gtk-shell-protocol.c            \
        wayland/gtk-shell-server-protocol.h     \
+       wayland/workspaces-protocol.c           \
+       wayland/workspaces-server-protocol.h    \
        wayland/xdg-shell-protocol.c            \
        wayland/xdg-shell-server-protocol.h     \
        wayland/xserver-protocol.c              \
diff --git a/src/core/display.c b/src/core/display.c
index e5da0ec..683fb38 100644
--- a/src/core/display.c
+++ b/src/core/display.c
@@ -72,6 +72,7 @@
 #include <string.h>
 #include <unistd.h>
 
+#include "meta-wayland-private.h"
 #include "meta-xwayland-private.h"
 
 #define GRAB_OP_IS_WINDOW_SWITCH(g)                     \
@@ -830,6 +831,12 @@ meta_display_open (void)
   if (!meta_is_wayland_compositor ())
     meta_screen_manage_all_windows (screen);
 
+  if (meta_is_wayland_compositor ())
+    {
+      MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
+      meta_wayland_compositor_set_screen (compositor, screen);
+    }
+
   {
     Window focus;
     int ret_to;
diff --git a/src/wayland/meta-wayland-private.h b/src/wayland/meta-wayland-private.h
index cba6ed3..5eb60ab 100644
--- a/src/wayland/meta-wayland-private.h
+++ b/src/wayland/meta-wayland-private.h
@@ -84,12 +84,17 @@ struct _MetaWaylandCompositor
   GList *surfaces;
   struct wl_list frame_callbacks;
 
+  struct wl_list workspace_managers;
+
   MetaXWaylandManager xwayland_manager;
 
   MetaLauncher *launcher;
   gboolean native;
 
   MetaWaylandSeat *seat;
+
+  MetaScreen *screen;
+  int workspace_switched_id;
 };
 
 void                    meta_wayland_init                       (void);
@@ -119,5 +124,7 @@ void                    meta_wayland_compositor_paint_finished  (MetaWaylandComp
 gboolean                meta_wayland_compositor_activate_vt     (MetaWaylandCompositor  *compositor,
                                                                  int                     vt,
                                                                  GError                **error);
+void                    meta_wayland_compositor_set_screen      (MetaWaylandCompositor  *compositor,
+                                                                 MetaScreen             *screen);
 
 #endif /* META_WAYLAND_PRIVATE_H */
diff --git a/src/wayland/meta-wayland-versions.h b/src/wayland/meta-wayland-versions.h
index 531cbd4..1dd39a3 100644
--- a/src/wayland/meta-wayland-versions.h
+++ b/src/wayland/meta-wayland-versions.h
@@ -57,6 +57,7 @@
 #define META_XDG_SURFACE_VERSION            1 /* from xdg_shell */
 #define META_XDG_POPUP_VERSION              1 /* from xdg_shell */
 #define META_WL_SUBSURFACE_VERSION          1 /* from wl_subcompositor */
+#define META_WORKSPACE_MANAGER_VERSION      1 /* from workspace_manager */
 
 /* The first version to implement a specific event */
 #define META_WL_SEAT_HAS_NAME               2
diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c
index 254b4d0..75a9128 100644
--- a/src/wayland/meta-wayland.c
+++ b/src/wayland/meta-wayland.c
@@ -55,6 +55,8 @@
 #include "meta-weston-launch.h"
 #include "monitor-private.h"
 
+#include "workspaces-server-protocol.h"
+
 static MetaWaylandCompositor _meta_wayland_compositor;
 
 MetaWaylandCompositor *
@@ -618,6 +620,91 @@ are_we_native (int *out_drm_fd)
     }
 }
 
+typedef struct {
+  struct wl_resource *resource;
+  struct wl_listener user_data_listener;
+  struct wl_list link;
+} MetaWaylandWorkspaceManager;
+
+static void
+workspace_manager_handle_client_destroy (struct wl_listener *listener, void *data)
+{
+  MetaWaylandWorkspaceManager *manager = wl_container_of (listener, manager, user_data_listener);
+
+  g_slice_free (MetaWaylandWorkspaceManager, manager);
+}
+
+static void
+workspace_manager_move_surface (struct wl_client *client,
+                                struct wl_resource *workspace_manager_resource,
+                                struct wl_resource *surface_resource,
+                                uint32_t workspace)
+{
+  MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
+
+  if (!surface->window)
+    return;
+
+  meta_window_change_workspace_by_index (surface->window, workspace, FALSE);
+}
+
+static const struct workspace_manager_interface meta_wayland_workspace_manager_interface = {
+  workspace_manager_move_surface,
+};
+
+static void
+workspace_manager_send_current_state (MetaWaylandCompositor       *compositor,
+                                      MetaWaylandWorkspaceManager *manager)
+{
+  MetaDisplay *display = meta_get_display ();
+  MetaScreen *screen = display->screens->data;
+
+  workspace_manager_send_state (manager->resource,
+                                meta_screen_get_active_workspace_index (screen),
+                                meta_screen_get_n_workspaces (screen));
+}
+
+static void
+bind_workspace_manager (struct wl_client *client,
+                        void             *data,
+                        guint32           version,
+                        guint32           id)
+{
+  MetaWaylandCompositor *compositor = data;
+  MetaWaylandWorkspaceManager *manager = g_slice_new0 (MetaWaylandWorkspaceManager);
+
+  manager->resource = wl_resource_create (client, &workspace_manager_interface,
+                                          MIN (META_WORKSPACE_MANAGER_VERSION, version), id);
+  wl_resource_set_implementation (manager->resource, &meta_wayland_workspace_manager_interface, manager, 
NULL);
+
+  manager->user_data_listener.notify = workspace_manager_handle_client_destroy;
+  wl_client_add_destroy_listener (client, &manager->user_data_listener);
+
+  wl_list_insert (&compositor->workspace_managers, &manager->link);
+
+  workspace_manager_send_current_state (compositor, manager);
+}
+
+static void
+meta_wayland_active_workspace_changed (MetaWaylandCompositor *compositor)
+{
+  MetaWaylandWorkspaceManager *manager;
+
+  wl_list_for_each (manager, &compositor->workspace_managers, link)
+    workspace_manager_send_current_state (compositor, manager);
+}
+
+static void
+on_workspace_switched (MetaScreen          *screen,
+                       int                  from,
+                       int                  to,
+                       MetaMotionDirection  direction,
+                       gpointer             user_data)
+{
+  MetaWaylandCompositor *compositor = (MetaWaylandCompositor *) user_data;
+  meta_wayland_active_workspace_changed (compositor);
+}
+
 void
 meta_wayland_init (void)
 {
@@ -700,6 +787,13 @@ meta_wayland_init (void)
 
   compositor->seat = meta_wayland_seat_new (compositor->wayland_display, compositor->native);
 
+  wl_list_init (&compositor->workspace_managers);
+  if (wl_global_create (compositor->wayland_display,
+                        &workspace_manager_interface,
+                        META_WORKSPACE_MANAGER_VERSION,
+                        compositor, bind_workspace_manager) == NULL)
+    g_error ("Failed to create a global workspace-manager object");
+
   meta_wayland_init_shell (compositor);
 
   clutter_actor_show (compositor->stage);
@@ -733,6 +827,14 @@ meta_wayland_finalize (void)
 
   compositor = meta_wayland_compositor_get_default ();
 
+  if (compositor->workspace_switched_id > 0)
+    {
+      g_signal_handler_disconnect (compositor->screen, compositor->workspace_switched_id);
+      compositor->workspace_switched_id = 0;
+    }
+
+  g_clear_object (&compositor->screen);
+
   meta_xwayland_stop (&compositor->xwayland_manager);
 
   if (compositor->launcher)
@@ -760,3 +862,13 @@ meta_wayland_compositor_activate_vt (MetaWaylandCompositor  *compositor,
       return TRUE;
     }
 }
+
+void
+meta_wayland_compositor_set_screen (MetaWaylandCompositor *compositor,
+                                    MetaScreen            *screen)
+{
+  compositor->screen = g_object_ref (screen);
+
+  compositor->workspace_switched_id = g_signal_connect (screen, "workspace-switched",
+                                                        G_CALLBACK (on_workspace_switched), compositor);
+}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]