diff options
author | Benjamin Franzke <benjaminfranzke@googlemail.com> | 2011-11-22 12:43:52 +0100 |
---|---|---|
committer | Benjamin Franzke <benjaminfranzke@googlemail.com> | 2011-11-22 20:40:29 +0100 |
commit | ea842d4ce4f8e374eeb4649cb25881ad8d84dc05 (patch) | |
tree | 0477d242c01648f03e63e6f881ceae5820d470c9 | |
parent | ceafb7e0e4ccfff5982c42d444b4b2ff9807db14 (diff) |
desktop-shell: Make panel and background output dependentshell-outputs
-rw-r--r-- | clients/desktop-shell.c | 156 | ||||
-rw-r--r-- | compositor/shell.c | 146 | ||||
-rw-r--r-- | protocol/desktop-shell.xml | 2 |
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> |