summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Franzke <benjaminfranzke@googlemail.com>2011-11-22 12:43:52 +0100
committerBenjamin Franzke <benjaminfranzke@googlemail.com>2011-11-22 20:40:29 +0100
commitea842d4ce4f8e374eeb4649cb25881ad8d84dc05 (patch)
tree0477d242c01648f03e63e6f881ceae5820d470c9
parentceafb7e0e4ccfff5982c42d444b4b2ff9807db14 (diff)
desktop-shell: Make panel and background output dependentshell-outputs
-rw-r--r--clients/desktop-shell.c156
-rw-r--r--compositor/shell.c146
-rw-r--r--protocol/desktop-shell.xml2
3 files changed, 222 insertions, 82 deletions
diff --git a/clients/desktop-shell.c b/clients/desktop-shell.c
index 95b557a..09e8bd6 100644
--- a/clients/desktop-shell.c
+++ b/clients/desktop-shell.c
@@ -41,18 +41,30 @@
struct desktop {
struct display *display;
struct desktop_shell *shell;
- struct panel *panel;
- struct window *background;
const char *background_path;
struct unlock_dialog *unlock_dialog;
struct task unlock_task;
};
+struct surface {
+ void (*configure)(void *data,
+ struct desktop_shell *desktop_shell,
+ uint32_t time, uint32_t edges,
+ struct wl_surface *surface,
+ int32_t width, int32_t height);
+};
+
struct panel {
+ struct surface base;
struct window *window;
struct window *menu;
};
+struct background {
+ struct surface base;
+ struct window *window;
+};
+
struct panel_item {
struct item *item;
struct panel *panel;
@@ -113,6 +125,7 @@ show_menu(struct panel *panel, struct input *input)
display = window_get_display(panel->window);
panel->menu = window_create_transient(display, panel->window,
x - 10, y - 10, width, height);
+ window_set_user_data(panel->menu, panel);
window_draw(panel->menu);
window_flush(panel->menu);
@@ -234,6 +247,22 @@ panel_button_handler(struct window *window,
}
}
+static void
+panel_configure(void *data,
+ struct desktop_shell *desktop_shell,
+ uint32_t time, uint32_t edges,
+ struct wl_surface *surface,
+ int32_t width, int32_t height)
+{
+ struct panel *panel =
+ window_get_user_data(wl_surface_get_user_data(surface));
+
+ if (surface == window_get_wl_surface(panel->window)) {
+ window_set_child_size(panel->window, width, 32);
+ window_schedule_redraw(panel->window);
+ }
+}
+
static struct panel *
panel_create(struct display *display)
{
@@ -242,8 +271,8 @@ panel_create(struct display *display)
panel = malloc(sizeof *panel);
memset(panel, 0, sizeof *panel);
+ panel->base.configure = panel_configure;
panel->window = window_create(display, 0, 0);
-
window_set_title(panel->window, "panel");
window_set_decoration(panel->window, 0);
window_set_redraw_handler(panel->window, panel_redraw_handler);
@@ -305,6 +334,21 @@ background_draw(struct window *window, int width, int height, const char *path)
}
static void
+background_configure(void *data,
+ struct desktop_shell *desktop_shell,
+ uint32_t time, uint32_t edges,
+ struct wl_surface *surface,
+ int32_t width, int32_t height)
+{
+ struct desktop *desktop = data;
+ struct background *background =
+ window_get_user_data(wl_surface_get_user_data(surface));
+
+ background_draw(background->window,
+ width, height, desktop->background_path);
+}
+
+static void
unlock_dialog_draw(struct unlock_dialog *dialog)
{
struct rectangle allocation;
@@ -453,15 +497,13 @@ desktop_shell_configure(void *data,
struct wl_surface *surface,
int32_t width, int32_t height)
{
- struct desktop *desktop = data;
+ struct surface *s =
+ window_get_user_data(wl_surface_get_user_data(surface));
- if (surface == window_get_wl_surface(desktop->panel->window)) {
- window_set_child_size(desktop->panel->window, width, 32);
- window_schedule_redraw(desktop->panel->window);
- } else if (surface == window_get_wl_surface(desktop->background)) {
- background_draw(desktop->background,
- width, height, desktop->background_path);
- }
+ if (s == NULL)
+ return;
+
+ s->configure(data, desktop_shell, time, edges, surface, width, height);
}
static void
@@ -481,6 +523,71 @@ static const struct desktop_shell_listener listener = {
desktop_shell_prepare_lock_surface
};
+static struct background *
+background_create(struct desktop *desktop)
+{
+ struct background *background;
+
+ background = malloc(sizeof *background);
+ memset(background, 0, sizeof *background);
+
+ background->base.configure = background_configure;
+ background->window = window_create(desktop->display, 0, 0);
+ window_set_decoration(background->window, 0);
+ window_set_custom(background->window);
+ window_set_user_data(background->window, background);
+
+ desktop->background_path = key_background_image;
+
+ return background;
+}
+
+static void
+output_handle_geometry(void *data,
+ struct wl_output *wl_output,
+ int x, int y,
+ int physical_width,
+ int physical_height,
+ int subpixel,
+ const char *make,
+ const char *model)
+{
+ struct desktop *desktop = data;
+ struct panel *panel;
+ struct background *background;
+ char *config_file;
+
+ panel = panel_create(desktop->display);
+
+ config_file = config_file_path("wayland-desktop-shell.ini");
+ parse_config_file(config_file,
+ config_sections, ARRAY_LENGTH(config_sections),
+ panel);
+ free(config_file);
+
+ desktop_shell_set_panel(desktop->shell, wl_output,
+ window_get_wl_surface(panel->window));
+
+ background = background_create(desktop);
+ desktop_shell_set_background(desktop->shell, wl_output,
+ window_get_wl_surface(background->window));
+}
+
+static void
+output_handle_mode(void *data,
+ struct wl_output *wl_output,
+ uint32_t flags,
+ int width,
+ int height,
+ int refresh)
+{
+}
+
+static const struct wl_output_listener output_listener = {
+ output_handle_geometry,
+ output_handle_mode
+};
+
static void
global_handler(struct wl_display *display, uint32_t id,
const char *interface, uint32_t version, void *data)
@@ -491,20 +598,24 @@ global_handler(struct wl_display *display, uint32_t id,
desktop->shell =
wl_display_bind(display, id, &desktop_shell_interface);
desktop_shell_add_listener(desktop->shell, &listener, desktop);
+ } else if (!strcmp(interface, "wl_output")) {
+ struct wl_output *output = wl_display_bind(display, id,
+ &wl_output_interface);
+ wl_output_add_listener(output, &output_listener, desktop);
}
}
static void
launcher_section_done(void *data)
{
- struct desktop *desktop = data;
+ struct panel *panel = data;
if (key_launcher_icon == NULL || key_launcher_path == NULL) {
fprintf(stderr, "invalid launcher section\n");
return;
}
- panel_add_item(desktop->panel, key_launcher_icon, key_launcher_path);
+ panel_add_item(panel, key_launcher_icon, key_launcher_path);
free(key_launcher_icon);
key_launcher_icon = NULL;
free(key_launcher_path);
@@ -514,7 +625,6 @@ launcher_section_done(void *data)
int main(int argc, char *argv[])
{
struct desktop desktop = { 0 };
- char *config_file;
desktop.unlock_task.run = unlock_dialog_finish;
@@ -530,24 +640,6 @@ int main(int argc, char *argv[])
wl_display_add_global_listener(display_get_display(desktop.display),
global_handler, &desktop);
- desktop.panel = panel_create(desktop.display);
-
- config_file = config_file_path("wayland-desktop-shell.ini");
- parse_config_file(config_file,
- config_sections, ARRAY_LENGTH(config_sections),
- &desktop);
- free(config_file);
-
- desktop_shell_set_panel(desktop.shell,
- window_get_wl_surface(desktop.panel->window));
-
- desktop.background = window_create(desktop.display, 0, 0);
- window_set_decoration(desktop.background, 0);
- window_set_custom(desktop.background);
- desktop.background_path = key_background_image;
- desktop_shell_set_background(desktop.shell,
- window_get_wl_surface(desktop.background));
-
signal(SIGCHLD, sigchild_handler);
display_run(desktop.display);
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)
diff --git a/protocol/desktop-shell.xml b/protocol/desktop-shell.xml
index d099925..fef6662 100644
--- a/protocol/desktop-shell.xml
+++ b/protocol/desktop-shell.xml
@@ -2,10 +2,12 @@
<interface name="desktop_shell" version="1">
<request name="set_background">
+ <arg name="output" type="object" interface="wl_output"/>
<arg name="surface" type="object" interface="wl_surface"/>
</request>
<request name="set_panel">
+ <arg name="output" type="object" interface="wl_output"/>
<arg name="surface" type="object" interface="wl_surface"/>
</request>