shell: Introduce workspace manager interface
The workspace manager interface purpose is to provide clients with control and knowledge about the current workspace state. Initially only one function and one event exists; moving a surface and state updated event. A workspace is represented as an index in a 1 dimensional array. A client keeps track of the state by being broadcasted events when the state changes, currently limited to current workspace or number of workspaces available. A client can send an asynchronous request to the manager asking to move a surface to workspace identified by an index. It is up to the shell to actually move it. Signed-off-by: Jonas Ådahl <jadahl@gmail.com>
This commit is contained in:
committed by
Kristian Høgsberg
parent
8de6a1ddae
commit
e9d2250549
@@ -2,5 +2,6 @@ EXTRA_DIST = \
|
|||||||
desktop-shell.xml \
|
desktop-shell.xml \
|
||||||
screenshooter.xml \
|
screenshooter.xml \
|
||||||
tablet-shell.xml \
|
tablet-shell.xml \
|
||||||
xserver.xml \
|
xserver.xml \
|
||||||
text.xml
|
text.xml \
|
||||||
|
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>
|
||||||
@@ -28,6 +28,8 @@ weston_SOURCES = \
|
|||||||
text-backend.c \
|
text-backend.c \
|
||||||
text-protocol.c \
|
text-protocol.c \
|
||||||
text-server-protocol.h \
|
text-server-protocol.h \
|
||||||
|
workspaces-protocol.c \
|
||||||
|
workspaces-server-protocol.h \
|
||||||
util.c \
|
util.c \
|
||||||
matrix.c \
|
matrix.c \
|
||||||
matrix.h \
|
matrix.h \
|
||||||
@@ -173,6 +175,8 @@ BUILT_SOURCES = \
|
|||||||
desktop-shell-server-protocol.h \
|
desktop-shell-server-protocol.h \
|
||||||
text-protocol.c \
|
text-protocol.c \
|
||||||
text-server-protocol.h \
|
text-server-protocol.h \
|
||||||
|
workspaces-server-protocol.h \
|
||||||
|
workspaces-protocol.c \
|
||||||
git-version.h
|
git-version.h
|
||||||
|
|
||||||
CLEANFILES = $(BUILT_SOURCES)
|
CLEANFILES = $(BUILT_SOURCES)
|
||||||
|
|||||||
+108
-3
@@ -35,6 +35,7 @@
|
|||||||
#include <wayland-server.h>
|
#include <wayland-server.h>
|
||||||
#include "compositor.h"
|
#include "compositor.h"
|
||||||
#include "desktop-shell-server-protocol.h"
|
#include "desktop-shell-server-protocol.h"
|
||||||
|
#include "workspaces-server-protocol.h"
|
||||||
#include "../shared/config-parser.h"
|
#include "../shared/config-parser.h"
|
||||||
|
|
||||||
#define DEFAULT_NUM_WORKSPACES 1
|
#define DEFAULT_NUM_WORKSPACES 1
|
||||||
@@ -108,6 +109,8 @@ struct desktop_shell {
|
|||||||
unsigned int current;
|
unsigned int current;
|
||||||
unsigned int num;
|
unsigned int num;
|
||||||
|
|
||||||
|
struct wl_list client_list;
|
||||||
|
|
||||||
struct weston_animation animation;
|
struct weston_animation animation;
|
||||||
struct wl_list anim_sticky_list;
|
struct wl_list anim_sticky_list;
|
||||||
int anim_dir;
|
int anim_dir;
|
||||||
@@ -607,6 +610,17 @@ workspace_translate_in(struct workspace *ws, double fraction)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
broadcast_current_workspace_state(struct desktop_shell *shell)
|
||||||
|
{
|
||||||
|
struct wl_resource *resource;
|
||||||
|
|
||||||
|
wl_list_for_each(resource, &shell->workspaces.client_list, link)
|
||||||
|
workspace_manager_send_state(resource,
|
||||||
|
shell->workspaces.current,
|
||||||
|
shell->workspaces.num);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
reverse_workspace_change_animation(struct desktop_shell *shell,
|
reverse_workspace_change_animation(struct desktop_shell *shell,
|
||||||
unsigned int index,
|
unsigned int index,
|
||||||
@@ -771,6 +785,7 @@ change_workspace(struct desktop_shell *shell, unsigned int index)
|
|||||||
shell->workspaces.anim_to == from) {
|
shell->workspaces.anim_to == from) {
|
||||||
restore_focus_state(shell, to);
|
restore_focus_state(shell, to);
|
||||||
reverse_workspace_change_animation(shell, index, from, to);
|
reverse_workspace_change_animation(shell, index, from, to);
|
||||||
|
broadcast_current_workspace_state(shell);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -785,6 +800,8 @@ change_workspace(struct desktop_shell *shell, unsigned int index)
|
|||||||
update_workspace(shell, index, from, to);
|
update_workspace(shell, index, from, to);
|
||||||
else
|
else
|
||||||
animate_workspace_change(shell, index, from, to);
|
animate_workspace_change(shell, index, from, to);
|
||||||
|
|
||||||
|
broadcast_current_workspace_state(shell);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
@@ -804,13 +821,41 @@ workspace_has_only(struct workspace *ws, struct weston_surface *surface)
|
|||||||
return container_of(e, struct weston_surface, layer_link) == surface;
|
return container_of(e, struct weston_surface, layer_link) == surface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
move_surface_to_workspace(struct desktop_shell *shell,
|
||||||
|
struct weston_surface *surface,
|
||||||
|
uint32_t workspace)
|
||||||
|
{
|
||||||
|
struct workspace *from;
|
||||||
|
struct workspace *to;
|
||||||
|
struct weston_seat *seat;
|
||||||
|
|
||||||
|
if (workspace == shell->workspaces.current)
|
||||||
|
return;
|
||||||
|
|
||||||
|
from = get_current_workspace(shell);
|
||||||
|
to = get_workspace(shell, workspace);
|
||||||
|
|
||||||
|
wl_list_remove(&surface->layer_link);
|
||||||
|
wl_list_insert(&to->layer.surface_list, &surface->layer_link);
|
||||||
|
|
||||||
|
drop_focus_state(shell, from, surface);
|
||||||
|
wl_list_for_each(seat, &shell->compositor->seat_list, link)
|
||||||
|
if (seat->has_keyboard &&
|
||||||
|
seat->keyboard.focus == &surface->surface)
|
||||||
|
wl_keyboard_set_focus(&seat->keyboard, NULL);
|
||||||
|
|
||||||
|
weston_surface_damage_below(surface);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
take_surface_to_workspace_by_seat(struct desktop_shell *shell,
|
take_surface_to_workspace_by_seat(struct desktop_shell *shell,
|
||||||
struct wl_seat *seat,
|
struct wl_seat *wl_seat,
|
||||||
unsigned int index)
|
unsigned int index)
|
||||||
{
|
{
|
||||||
|
struct weston_seat *seat = (struct weston_seat *) wl_seat;
|
||||||
struct weston_surface *surface =
|
struct weston_surface *surface =
|
||||||
(struct weston_surface *) seat->keyboard->focus;
|
(struct weston_surface *) wl_seat->keyboard->focus;
|
||||||
struct shell_surface *shsurf;
|
struct shell_surface *shsurf;
|
||||||
struct workspace *from;
|
struct workspace *from;
|
||||||
struct workspace *to;
|
struct workspace *to;
|
||||||
@@ -825,12 +870,17 @@ take_surface_to_workspace_by_seat(struct desktop_shell *shell,
|
|||||||
wl_list_remove(&surface->layer_link);
|
wl_list_remove(&surface->layer_link);
|
||||||
wl_list_insert(&to->layer.surface_list, &surface->layer_link);
|
wl_list_insert(&to->layer.surface_list, &surface->layer_link);
|
||||||
|
|
||||||
replace_focus_state(shell, to, (struct weston_seat *) seat);
|
replace_focus_state(shell, to, seat);
|
||||||
drop_focus_state(shell, from, surface);
|
drop_focus_state(shell, from, surface);
|
||||||
|
|
||||||
if (shell->workspaces.anim_from == to &&
|
if (shell->workspaces.anim_from == to &&
|
||||||
shell->workspaces.anim_to == from) {
|
shell->workspaces.anim_to == from) {
|
||||||
|
wl_list_remove(&to->layer.link);
|
||||||
|
wl_list_insert(from->layer.link.prev, &to->layer.link);
|
||||||
|
|
||||||
reverse_workspace_change_animation(shell, index, from, to);
|
reverse_workspace_change_animation(shell, index, from, to);
|
||||||
|
broadcast_current_workspace_state(shell);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -850,6 +900,56 @@ take_surface_to_workspace_by_seat(struct desktop_shell *shell,
|
|||||||
|
|
||||||
animate_workspace_change(shell, index, from, to);
|
animate_workspace_change(shell, index, from, to);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
broadcast_current_workspace_state(shell);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
workspace_manager_move_surface(struct wl_client *client,
|
||||||
|
struct wl_resource *resource,
|
||||||
|
struct wl_resource *surface_resource,
|
||||||
|
uint32_t workspace)
|
||||||
|
{
|
||||||
|
struct desktop_shell *shell = resource->data;
|
||||||
|
struct weston_surface *surface =
|
||||||
|
(struct weston_surface *) surface_resource;
|
||||||
|
|
||||||
|
move_surface_to_workspace(shell, surface, workspace);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct workspace_manager_interface workspace_manager_implementation = {
|
||||||
|
workspace_manager_move_surface,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
unbind_resource(struct wl_resource *resource)
|
||||||
|
{
|
||||||
|
wl_list_remove(&resource->link);
|
||||||
|
free(resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
bind_workspace_manager(struct wl_client *client,
|
||||||
|
void *data, uint32_t version, uint32_t id)
|
||||||
|
{
|
||||||
|
struct desktop_shell *shell = data;
|
||||||
|
struct wl_resource *resource;
|
||||||
|
|
||||||
|
resource = wl_client_add_object(client, &workspace_manager_interface,
|
||||||
|
&workspace_manager_implementation,
|
||||||
|
id, shell);
|
||||||
|
|
||||||
|
if (resource == NULL) {
|
||||||
|
weston_log("couldn't add workspace manager object");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
resource->destroy = unbind_resource;
|
||||||
|
wl_list_insert(&shell->workspaces.client_list, &resource->link);
|
||||||
|
|
||||||
|
workspace_manager_send_state(resource,
|
||||||
|
shell->workspaces.current,
|
||||||
|
shell->workspaces.num);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -3618,6 +3718,7 @@ shell_init(struct weston_compositor *ec)
|
|||||||
weston_layer_init(&shell->input_panel_layer, NULL);
|
weston_layer_init(&shell->input_panel_layer, NULL);
|
||||||
|
|
||||||
wl_array_init(&shell->workspaces.array);
|
wl_array_init(&shell->workspaces.array);
|
||||||
|
wl_list_init(&shell->workspaces.client_list);
|
||||||
|
|
||||||
shell_configuration(shell);
|
shell_configuration(shell);
|
||||||
|
|
||||||
@@ -3653,6 +3754,10 @@ shell_init(struct weston_compositor *ec)
|
|||||||
shell, bind_input_panel) == NULL)
|
shell, bind_input_panel) == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
if (wl_display_add_global(ec->wl_display, &workspace_manager_interface,
|
||||||
|
shell, bind_workspace_manager) == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
shell->child.deathstamp = weston_compositor_get_time();
|
shell->child.deathstamp = weston_compositor_get_time();
|
||||||
if (launch_desktop_shell_process(shell) != 0)
|
if (launch_desktop_shell_process(shell) != 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
Reference in New Issue
Block a user