summaryrefslogtreecommitdiff
path: root/compositor/shell.c
diff options
context:
space:
mode:
Diffstat (limited to 'compositor/shell.c')
-rw-r--r--compositor/shell.c146
1 files changed, 96 insertions, 50 deletions
diff --git a/compositor/shell.c b/compositor/shell.c
index 7bae944..0cefa43 100644
--- a/compositor/shell.c
+++ b/compositor/shell.c
@@ -39,10 +39,6 @@
struct wl_shell {
struct wlsc_compositor *compositor;
struct wlsc_shell shell;
- struct wlsc_surface *panel;
- struct wl_listener panel_listener;
- struct wlsc_surface *background;
- struct wl_listener background_listener;
struct {
struct wlsc_process process;
@@ -56,6 +52,17 @@ struct wl_shell {
struct wlsc_surface *lock_surface;
struct wl_listener lock_surface_listener;
struct wl_list hidden_surface_list;
+
+ struct wl_list backgrounds;
+ struct wl_list panels;
+};
+
+struct wlsc_shell_surface {
+ struct wlsc_surface *surface;
+ struct wl_listener destroy_listener;
+ const char *type;
+
+ struct wl_list link;
};
struct wlsc_move_grab {
@@ -64,6 +71,19 @@ struct wlsc_move_grab {
int32_t dx, dy;
};
+static int
+shell_surface_list_has_surface(struct wl_list *list,
+ struct wlsc_surface *surface)
+{
+ struct wlsc_shell_surface *s;
+
+ wl_list_for_each(s, list, link)
+ if (s->surface == surface)
+ return 1;
+
+ return 0;
+}
+
static void
move_grab_motion(struct wl_grab *grab,
uint32_t time, int32_t x, int32_t y)
@@ -762,71 +782,85 @@ static const struct wl_shell_interface shell_interface = {
};
static void
-handle_background_surface_destroy(struct wl_listener *listener,
- struct wl_resource *resource, uint32_t time)
+handle_shell_surface_destroy(struct wl_listener *listener,
+ struct wl_resource *resource, uint32_t time)
{
- struct wl_shell *shell =
- container_of(listener, struct wl_shell, background_listener);
+ struct wlsc_shell_surface *s =
+ container_of(listener, struct wlsc_shell_surface,
+ destroy_listener);
- fprintf(stderr, "background surface gone\n");
- shell->background = NULL;
+ fprintf(stderr, "%s surface gone\n", s->type);
+ wl_list_remove(&s->link);
+ free(s);
}
static void
desktop_shell_set_background(struct wl_client *client,
struct wl_resource *resource,
+ struct wl_resource *output_resource,
struct wl_resource *surface_resource)
{
struct wl_shell *shell = resource->data;
struct wlsc_surface *surface = surface_resource->data;
- struct wlsc_output *output =
- container_of(shell->compositor->output_list.next,
- struct wlsc_output, link);
+ struct wlsc_shell_surface *background;
- shell->background = surface_resource->data;
- shell->background_listener.func = handle_background_surface_destroy;
+ background = malloc(sizeof *background);
+ if (!background) {
+ wl_resource_post_no_memory(resource);
+ return;
+ }
+
+ surface->output = output_resource->data;
+ background->surface = surface;
+ background->type = "background";
+ background->destroy_listener.func = handle_shell_surface_destroy;
wl_list_insert(&surface_resource->destroy_listener_list,
- &shell->background_listener.link);
+ &background->destroy_listener.link);
+ wl_list_insert(&shell->backgrounds, &background->link);
+
+ surface->x = surface->output->x;
+ surface->y = surface->output->y;
wl_resource_post_event(resource,
DESKTOP_SHELL_CONFIGURE,
wlsc_compositor_get_time(), 0, surface,
- output->current->width,
- output->current->height);
-}
-
-static void
-handle_panel_surface_destroy(struct wl_listener *listener,
- struct wl_resource *resource, uint32_t time)
-{
- struct wl_shell *shell =
- container_of(listener, struct wl_shell, panel_listener);
-
- fprintf(stderr, "panel surface gone\n");
- shell->panel = NULL;
+ surface->output->current->width,
+ surface->output->current->height);
}
static void
desktop_shell_set_panel(struct wl_client *client,
struct wl_resource *resource,
+ struct wl_resource *output_resource,
struct wl_resource *surface_resource)
{
struct wl_shell *shell = resource->data;
- struct wlsc_output *output =
- container_of(shell->compositor->output_list.next,
- struct wlsc_output, link);
+ struct wlsc_surface *surface = surface_resource->data;
+ struct wlsc_shell_surface *panel;
- shell->panel = surface_resource->data;
+ panel = malloc(sizeof *panel);
+ if (!panel) {
+ wl_resource_post_no_memory(resource);
+ return;
+ }
+
+ surface->output = output_resource->data;
+ panel->surface = surface;
- shell->panel_listener.func = handle_panel_surface_destroy;
+ panel->type = "panel";
+ panel->destroy_listener.func = handle_shell_surface_destroy;
wl_list_insert(&surface_resource->destroy_listener_list,
- &shell->panel_listener.link);
+ &panel->destroy_listener.link);
+ wl_list_insert(&shell->panels, &panel->link);
+
+ surface->x = surface->output->x;
+ surface->y = surface->output->y;
wl_resource_post_event(resource,
DESKTOP_SHELL_CONFIGURE,
wlsc_compositor_get_time(), 0, surface_resource,
- output->current->width,
- output->current->height);
+ surface->output->current->width,
+ surface->output->current->height);
}
static void
@@ -863,12 +897,15 @@ static void
resume_desktop(struct wl_shell *shell)
{
struct wlsc_surface *surface;
+ struct wlsc_shell_surface *background;
wl_list_for_each(surface, &shell->hidden_surface_list, link)
wlsc_surface_configure(surface, surface->x, surface->y,
surface->width, surface->height);
- wl_list_insert_list(shell->background->link.prev,
+ background = container_of(shell->backgrounds.prev,
+ struct wlsc_shell_surface, link);
+ wl_list_insert_list(background->surface->link.prev,
&shell->hidden_surface_list);
wl_list_init(&shell->hidden_surface_list);
@@ -907,9 +944,9 @@ move_binding(struct wl_input_device *device, uint32_t time,
if (surface == NULL ||
surface->map_type == WLSC_SURFACE_MAP_FULLSCREEN)
return;
- if (surface == shell->panel)
+ if (shell_surface_list_has_surface(&shell->panels, surface))
return;
- if (surface == shell->background)
+ if (shell_surface_list_has_surface(&shell->backgrounds, surface))
return;
wlsc_surface_move(surface, (struct wlsc_input_device *) device, time);
@@ -928,9 +965,9 @@ resize_binding(struct wl_input_device *device, uint32_t time,
if (surface == NULL ||
surface->map_type == WLSC_SURFACE_MAP_FULLSCREEN)
- if (surface == shell->panel)
+ if (shell_surface_list_has_surface(&shell->panels, surface))
return;
- if (surface == shell->background)
+ if (shell_surface_list_has_surface(&shell->backgrounds, surface))
return;
x = device->grab_x - surface->x;
@@ -970,12 +1007,16 @@ activate(struct wlsc_shell *base, struct wlsc_surface *es,
if (compositor->wxs)
wlsc_xserver_surface_activate(es);
- if (es == shell->background) {
+ if (shell_surface_list_has_surface(&shell->backgrounds, es)) {
wl_list_remove(&es->link);
wl_list_insert(compositor->surface_list.prev, &es->link);
- } else if (shell->panel && !shell->locked) {
- wl_list_remove(&shell->panel->link);
- wl_list_insert(&compositor->surface_list, &shell->panel->link);
+ } else if (!shell->locked) {
+ struct wlsc_shell_surface *panel;
+ wl_list_for_each(panel, &shell->panels, link) {
+ wl_list_remove(&panel->surface->link);
+ wl_list_insert(&compositor->surface_list,
+ &panel->surface->link);
+ }
}
}
@@ -1009,7 +1050,7 @@ lock(struct wlsc_shell *base)
if (cur->surface.resource.client == NULL)
continue;
- if (cur == shell->background)
+ if (shell_surface_list_has_surface(&shell->backgrounds, cur))
continue;
cur->output = NULL;
@@ -1070,11 +1111,11 @@ map(struct wlsc_shell *base,
list = &compositor->surface_list;
/* surface stacking order, see also activate() */
- if (surface == shell->background) {
+ if (shell_surface_list_has_surface(&shell->backgrounds, surface)) {
/* background always visible, at the bottom */
wl_list_insert(compositor->surface_list.prev, &surface->link);
- } else if (surface == shell->panel) {
+ } else if (shell_surface_list_has_surface(&shell->panels, surface)) {
/* panel always on top, hidden while locked */
wl_list_insert(list, &surface->link);
@@ -1086,7 +1127,10 @@ map(struct wlsc_shell *base,
wlsc_compositor_wake(compositor);
} else {
/* everything else just below the panel */
- wl_list_insert(&shell->panel->link, &surface->link);
+ struct wlsc_shell_surface *panel =
+ container_of(shell->panels.prev,
+ struct wlsc_shell_surface, link);
+ wl_list_insert(&panel->surface->link, &surface->link);
}
if (surface->map_type == WLSC_SURFACE_MAP_TOPLEVEL) {
@@ -1237,6 +1281,8 @@ shell_init(struct wlsc_compositor *ec)
shell->shell.set_selection_focus = wlsc_selection_set_focus;
wl_list_init(&shell->hidden_surface_list);
+ wl_list_init(&shell->backgrounds);
+ wl_list_init(&shell->panels);
if (wl_display_add_global(ec->wl_display, &wl_shell_interface,
shell, bind_shell) == NULL)