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 wl_list outputs;
+};
+
+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 output {
+ struct wl_output *output;
+ struct wl_list link;
+
+ struct panel *panel;
+ struct background *background;
+};
+
struct panel_item {
struct item *item;
struct panel *panel;
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);
}
}
+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));
+
+ window_set_child_size(panel->window, width, 32);
+ window_schedule_redraw(panel->window);
+}
+
static struct panel *
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");
}
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;
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);
- }
+ s->configure(data, desktop_shell, time, edges, surface, width, height);
}
static void
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);
+
+ return background;
+}
+
+static void
+create_output(struct desktop *desktop, uint32_t id)
+{
+ struct output *output;
+
+ output = calloc(1, sizeof *output);
+ if (!output)
+ return;
+
+ output->output = wl_display_bind(display_get_display(desktop->display),
+ id, &wl_output_interface);
+
+ wl_list_insert(&desktop->outputs, &output->link);
+}
+
static void
global_handler(struct wl_display *display, uint32_t id,
const char *interface, uint32_t version, void *data)
desktop->shell =
wl_display_bind(display, id, &desktop_shell_interface);
desktop_shell_add_listener(desktop->shell, &listener, desktop);
+ } else if (!strcmp(interface, "wl_output")) {
+ create_output(desktop, id);
}
}
launcher_section_done(void *data)
{
struct desktop *desktop = data;
+ struct output *output;
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);
+ wl_list_for_each(output, &desktop->outputs, link)
+ panel_add_item(output->panel,
+ key_launcher_icon, key_launcher_path);
+
free(key_launcher_icon);
key_launcher_icon = NULL;
free(key_launcher_path);
{
struct desktop desktop = { 0 };
char *config_file;
+ struct output *output;
desktop.unlock_task.run = unlock_dialog_finish;
+ wl_list_init(&desktop.outputs);
desktop.display = display_create(&argc, &argv, NULL);
if (desktop.display == NULL) {
wl_display_add_global_listener(display_get_display(desktop.display),
global_handler, &desktop);
- desktop.panel = panel_create(desktop.display);
+ wl_list_for_each(output, &desktop.outputs, link) {
+ struct wl_surface *surface;
+
+ output->panel = panel_create(desktop.display);
+ surface = window_get_wl_surface(output->panel->window);
+ desktop_shell_set_panel(desktop.shell, output->output, surface);
+
+ output->background = background_create(&desktop);
+ surface = window_get_wl_surface(output->background->window);
+ desktop_shell_set_background(desktop.shell,
+ output->output, surface);
+ }
config_file = config_file_path("wayland-desktop-shell.ini");
parse_config_file(config_file,
&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);
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;
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;
};
enum shell_surface_type {
};
struct shell_surface {
+ struct wlsc_surface *surface;
struct wl_listener destroy_listener;
enum shell_surface_type type;
int32_t saved_x, saved_y;
+
+ struct wlsc_output *output;
+ struct wl_list link;
};
struct wlsc_move_grab {
destroy_shell_surface(struct shell_surface *priv)
{
wl_list_remove(&priv->destroy_listener.link);
+ wl_list_remove(&priv->link);
free(priv);
}
&priv->destroy_listener.link);
surface->shell_priv = priv;
+ priv->surface = surface;
+ /* init link so its safe to always remove it in destroy_shell_surface */
+ wl_list_init(&priv->link);
priv->type = SHELL_SURFACE_NORMAL;
};
static void
-handle_background_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);
-
- fprintf(stderr, "background surface gone\n");
- shell->background = NULL;
-}
-
-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 shell_surface *priv;
- shell->background = surface_resource->data;
- shell->background_listener.func = handle_background_surface_destroy;
- wl_list_insert(&surface_resource->destroy_listener_list,
- &shell->background_listener.link);
-
priv = get_shell_surface(surface);
priv->type = SHELL_SURFACE_BACKGROUND;
+ priv->output = output_resource->data;
+
+ wl_list_insert(&shell->backgrounds, &priv->link);
+
+ surface->x = priv->output->x;
+ surface->y = priv->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;
+ priv->output->current->width,
+ priv->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 shell_surface *priv;
- shell->panel = surface_resource->data;
+ priv = get_shell_surface(surface);
+ priv->type = SHELL_SURFACE_PANEL;
+ priv->output = output_resource->data;
- shell->panel_listener.func = handle_panel_surface_destroy;
- wl_list_insert(&surface_resource->destroy_listener_list,
- &shell->panel_listener.link);
+ wl_list_insert(&shell->panels, &priv->link);
- priv = get_shell_surface(shell->panel);
- priv->type = SHELL_SURFACE_PANEL;
+ surface->x = priv->output->x;
+ surface->y = priv->output->y;
wl_resource_post_event(resource,
DESKTOP_SHELL_CONFIGURE,
wlsc_compositor_get_time(), 0, surface_resource,
- output->current->width,
- output->current->height);
+ priv->output->current->width,
+ priv->output->current->height);
}
static void
resume_desktop(struct wl_shell *shell)
{
struct wlsc_surface *surface;
+ struct 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 shell_surface, link);
+ wl_list_insert_list(background->surface->link.prev,
&shell->hidden_surface_list);
wl_list_init(&shell->hidden_surface_list);
move_binding(struct wl_input_device *device, uint32_t time,
uint32_t key, uint32_t button, uint32_t state, void *data)
{
- struct wl_shell *shell = data;
struct wlsc_surface *surface =
(struct wlsc_surface *) device->pointer_focus;
struct shell_surface *priv;
- priv = get_shell_surface(surface);
-
- if (surface == NULL ||
- priv->type == SHELL_SURFACE_FULLSCREEN)
- return;
- if (surface == shell->panel)
- return;
- if (surface == shell->background)
+ if (surface == NULL)
return;
+ priv = get_shell_surface(surface);
+ switch (priv->type) {
+ case SHELL_SURFACE_PANEL:
+ case SHELL_SURFACE_BACKGROUND:
+ case SHELL_SURFACE_FULLSCREEN:
+ return;
+ default:
+ break;
+ }
+
wlsc_surface_move(surface, (struct wlsc_input_device *) device, time);
}
resize_binding(struct wl_input_device *device, uint32_t time,
uint32_t key, uint32_t button, uint32_t state, void *data)
{
- struct wl_shell *shell = data;
struct wlsc_surface *surface =
(struct wlsc_surface *) device->pointer_focus;
struct wl_resource *resource;
int32_t x, y;
struct shell_surface *priv;
- priv = get_shell_surface(surface);
-
- if (surface == NULL ||
- priv->type == SHELL_SURFACE_FULLSCREEN)
- if (surface == shell->panel)
- return;
- if (surface == shell->background)
+ if (surface == NULL)
return;
+
+ priv = get_shell_surface(surface);
+ switch (priv->type) {
+ case SHELL_SURFACE_PANEL:
+ case SHELL_SURFACE_BACKGROUND:
+ case SHELL_SURFACE_FULLSCREEN:
+ return;
+ default:
+ break;
+ }
x = device->grab_x - surface->x;
y = device->grab_y - surface->y;
/* already put on top */
break;
default:
- if (shell->panel && !shell->locked) {
+ if (!shell->locked) {
/* bring panel back to top */
- wl_list_remove(&shell->panel->link);
- wl_list_insert(&compositor->surface_list,
- &shell->panel->link);
+ struct 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);
+ }
}
}
}
break;
default:
/* everything else just below the panel */
- if (shell->panel)
- wl_list_insert(&shell->panel->link, &surface->link);
- else
+ if (!wl_list_empty(&shell->panels)) {
+ struct shell_surface *panel =
+ container_of(shell->panels.prev,
+ struct shell_surface, link);
+ wl_list_insert(&panel->surface->link, &surface->link);
+ } else {
wl_list_insert(list, &surface->link);
+ }
}
if (priv->type == SHELL_SURFACE_TOPLEVEL) {
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)