desktop-shell: Make panel and background output dependent

dev
Benjamin Franzke 13 years ago
parent 8193bc1e9a
commit d0f79ab5ab
  1. 130
      clients/desktop-shell.c
  2. 138
      compositor/shell.c
  3. 2
      protocol/desktop-shell.xml

@ -41,18 +41,39 @@
struct desktop { struct desktop {
struct display *display; struct display *display;
struct desktop_shell *shell; struct desktop_shell *shell;
struct panel *panel;
struct window *background;
const char *background_path; const char *background_path;
struct unlock_dialog *unlock_dialog; struct unlock_dialog *unlock_dialog;
struct task unlock_task; 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 panel {
struct surface base;
struct window *window; struct window *window;
struct window *menu; 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 panel_item {
struct item *item; struct item *item;
struct panel *panel; struct panel *panel;
@ -113,6 +134,7 @@ show_menu(struct panel *panel, struct input *input)
display = window_get_display(panel->window); display = window_get_display(panel->window);
panel->menu = window_create_transient(display, panel->window, panel->menu = window_create_transient(display, panel->window,
x - 10, y - 10, width, height); x - 10, y - 10, width, height);
window_set_user_data(panel->menu, panel);
window_draw(panel->menu); window_draw(panel->menu);
window_flush(panel->menu); window_flush(panel->menu);
@ -234,6 +256,20 @@ 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));
window_set_child_size(panel->window, width, 32);
window_schedule_redraw(panel->window);
}
static struct panel * static struct panel *
panel_create(struct display *display) panel_create(struct display *display)
{ {
@ -242,6 +278,7 @@ panel_create(struct display *display)
panel = malloc(sizeof *panel); panel = malloc(sizeof *panel);
memset(panel, 0, sizeof *panel); memset(panel, 0, sizeof *panel);
panel->base.configure = panel_configure;
panel->window = window_create(display, 0, 0); panel->window = window_create(display, 0, 0);
window_set_title(panel->window, "panel"); window_set_title(panel->window, "panel");
@ -304,6 +341,21 @@ background_draw(struct window *window, int width, int height, const char *path)
window_flush(window); window_flush(window);
} }
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 static void
unlock_dialog_draw(struct unlock_dialog *dialog) unlock_dialog_draw(struct unlock_dialog *dialog)
{ {
@ -454,15 +506,10 @@ desktop_shell_configure(void *data,
struct wl_surface *surface, struct wl_surface *surface,
int32_t width, int32_t height) 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)) { s->configure(data, desktop_shell, time, edges, surface, width, height);
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);
}
} }
static void static void
@ -482,6 +529,38 @@ static const struct desktop_shell_listener listener = {
desktop_shell_prepare_lock_surface 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 static void
global_handler(struct wl_display *display, uint32_t id, global_handler(struct wl_display *display, uint32_t id,
const char *interface, uint32_t version, void *data) const char *interface, uint32_t version, void *data)
@ -492,6 +571,8 @@ global_handler(struct wl_display *display, uint32_t id,
desktop->shell = desktop->shell =
wl_display_bind(display, id, &desktop_shell_interface); wl_display_bind(display, id, &desktop_shell_interface);
desktop_shell_add_listener(desktop->shell, &listener, desktop); desktop_shell_add_listener(desktop->shell, &listener, desktop);
} else if (!strcmp(interface, "wl_output")) {
create_output(desktop, id);
} }
} }
@ -499,13 +580,17 @@ static void
launcher_section_done(void *data) launcher_section_done(void *data)
{ {
struct desktop *desktop = data; struct desktop *desktop = data;
struct output *output;
if (key_launcher_icon == NULL || key_launcher_path == NULL) { if (key_launcher_icon == NULL || key_launcher_path == NULL) {
fprintf(stderr, "invalid launcher section\n"); fprintf(stderr, "invalid launcher section\n");
return; 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); free(key_launcher_icon);
key_launcher_icon = NULL; key_launcher_icon = NULL;
free(key_launcher_path); free(key_launcher_path);
@ -516,8 +601,10 @@ int main(int argc, char *argv[])
{ {
struct desktop desktop = { 0 }; struct desktop desktop = { 0 };
char *config_file; char *config_file;
struct output *output;
desktop.unlock_task.run = unlock_dialog_finish; desktop.unlock_task.run = unlock_dialog_finish;
wl_list_init(&desktop.outputs);
desktop.display = display_create(&argc, &argv, NULL); desktop.display = display_create(&argc, &argv, NULL);
if (desktop.display == NULL) { if (desktop.display == NULL) {
@ -531,7 +618,18 @@ int main(int argc, char *argv[])
wl_display_add_global_listener(display_get_display(desktop.display), wl_display_add_global_listener(display_get_display(desktop.display),
global_handler, &desktop); 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"); config_file = config_file_path("wayland-desktop-shell.ini");
parse_config_file(config_file, parse_config_file(config_file,
@ -539,15 +637,7 @@ int main(int argc, char *argv[])
&desktop); &desktop);
free(config_file); 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.background_path = key_background_image;
desktop_shell_set_background(desktop.shell,
window_get_wl_surface(desktop.background));
signal(SIGCHLD, sigchild_handler); signal(SIGCHLD, sigchild_handler);

@ -39,10 +39,6 @@
struct wl_shell { struct wl_shell {
struct wlsc_compositor *compositor; struct wlsc_compositor *compositor;
struct wlsc_shell shell; struct wlsc_shell shell;
struct wlsc_surface *panel;
struct wl_listener panel_listener;
struct wlsc_surface *background;
struct wl_listener background_listener;
struct { struct {
struct wlsc_process process; struct wlsc_process process;
@ -56,6 +52,9 @@ struct wl_shell {
struct wlsc_surface *lock_surface; struct wlsc_surface *lock_surface;
struct wl_listener lock_surface_listener; struct wl_listener lock_surface_listener;
struct wl_list hidden_surface_list; struct wl_list hidden_surface_list;
struct wl_list backgrounds;
struct wl_list panels;
}; };
enum shell_surface_type { enum shell_surface_type {
@ -71,10 +70,14 @@ enum shell_surface_type {
}; };
struct shell_surface { struct shell_surface {
struct wlsc_surface *surface;
struct wl_listener destroy_listener; struct wl_listener destroy_listener;
enum shell_surface_type type; enum shell_surface_type type;
int32_t saved_x, saved_y; int32_t saved_x, saved_y;
struct wlsc_output *output;
struct wl_list link;
}; };
struct wlsc_move_grab { struct wlsc_move_grab {
@ -87,6 +90,7 @@ static void
destroy_shell_surface(struct shell_surface *priv) destroy_shell_surface(struct shell_surface *priv)
{ {
wl_list_remove(&priv->destroy_listener.link); wl_list_remove(&priv->destroy_listener.link);
wl_list_remove(&priv->link);
free(priv); free(priv);
} }
@ -116,6 +120,9 @@ get_shell_surface(struct wlsc_surface *surface)
&priv->destroy_listener.link); &priv->destroy_listener.link);
surface->shell_priv = priv; 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; priv->type = SHELL_SURFACE_NORMAL;
@ -825,80 +832,56 @@ static const struct wl_shell_interface shell_interface = {
shell_set_fullscreen shell_set_fullscreen
}; };
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 static void
desktop_shell_set_background(struct wl_client *client, desktop_shell_set_background(struct wl_client *client,
struct wl_resource *resource, struct wl_resource *resource,
struct wl_resource *output_resource,
struct wl_resource *surface_resource) struct wl_resource *surface_resource)
{ {
struct wl_shell *shell = resource->data; struct wl_shell *shell = resource->data;
struct wlsc_surface *surface = surface_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; 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 = get_shell_surface(surface);
priv->type = SHELL_SURFACE_BACKGROUND; 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, wl_resource_post_event(resource,
DESKTOP_SHELL_CONFIGURE, DESKTOP_SHELL_CONFIGURE,
wlsc_compositor_get_time(), 0, surface, wlsc_compositor_get_time(), 0, surface,
output->current->width, priv->output->current->width,
output->current->height); priv->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;
} }
static void static void
desktop_shell_set_panel(struct wl_client *client, desktop_shell_set_panel(struct wl_client *client,
struct wl_resource *resource, struct wl_resource *resource,
struct wl_resource *output_resource,
struct wl_resource *surface_resource) struct wl_resource *surface_resource)
{ {
struct wl_shell *shell = resource->data; struct wl_shell *shell = resource->data;
struct wlsc_output *output = struct wlsc_surface *surface = surface_resource->data;
container_of(shell->compositor->output_list.next,
struct wlsc_output, link);
struct shell_surface *priv; 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(&shell->panels, &priv->link);
wl_list_insert(&surface_resource->destroy_listener_list,
&shell->panel_listener.link);
priv = get_shell_surface(shell->panel); surface->x = priv->output->x;
priv->type = SHELL_SURFACE_PANEL; surface->y = priv->output->y;
wl_resource_post_event(resource, wl_resource_post_event(resource,
DESKTOP_SHELL_CONFIGURE, DESKTOP_SHELL_CONFIGURE,
wlsc_compositor_get_time(), 0, surface_resource, wlsc_compositor_get_time(), 0, surface_resource,
output->current->width, priv->output->current->width,
output->current->height); priv->output->current->height);
} }
static void static void
@ -939,12 +922,15 @@ static void
resume_desktop(struct wl_shell *shell) resume_desktop(struct wl_shell *shell)
{ {
struct wlsc_surface *surface; struct wlsc_surface *surface;
struct shell_surface *background;
wl_list_for_each(surface, &shell->hidden_surface_list, link) wl_list_for_each(surface, &shell->hidden_surface_list, link)
wlsc_surface_configure(surface, surface->x, surface->y, wlsc_surface_configure(surface, surface->x, surface->y,
surface->width, surface->height); 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); &shell->hidden_surface_list);
wl_list_init(&shell->hidden_surface_list); wl_list_init(&shell->hidden_surface_list);
@ -976,20 +962,22 @@ static void
move_binding(struct wl_input_device *device, uint32_t time, move_binding(struct wl_input_device *device, uint32_t time,
uint32_t key, uint32_t button, uint32_t state, void *data) uint32_t key, uint32_t button, uint32_t state, void *data)
{ {
struct wl_shell *shell = data;
struct wlsc_surface *surface = struct wlsc_surface *surface =
(struct wlsc_surface *) device->pointer_focus; (struct wlsc_surface *) device->pointer_focus;
struct shell_surface *priv; struct shell_surface *priv;
priv = get_shell_surface(surface); if (surface == NULL)
if (surface == NULL ||
priv->type == SHELL_SURFACE_FULLSCREEN)
return;
if (surface == shell->panel)
return; return;
if (surface == shell->background)
priv = get_shell_surface(surface);
switch (priv->type) {
case SHELL_SURFACE_PANEL:
case SHELL_SURFACE_BACKGROUND:
case SHELL_SURFACE_FULLSCREEN:
return; return;
default:
break;
}
wlsc_surface_move(surface, (struct wlsc_input_device *) device, time); wlsc_surface_move(surface, (struct wlsc_input_device *) device, time);
} }
@ -998,7 +986,6 @@ static void
resize_binding(struct wl_input_device *device, uint32_t time, resize_binding(struct wl_input_device *device, uint32_t time,
uint32_t key, uint32_t button, uint32_t state, void *data) uint32_t key, uint32_t button, uint32_t state, void *data)
{ {
struct wl_shell *shell = data;
struct wlsc_surface *surface = struct wlsc_surface *surface =
(struct wlsc_surface *) device->pointer_focus; (struct wlsc_surface *) device->pointer_focus;
struct wl_resource *resource; struct wl_resource *resource;
@ -1006,14 +993,18 @@ resize_binding(struct wl_input_device *device, uint32_t time,
int32_t x, y; int32_t x, y;
struct shell_surface *priv; struct shell_surface *priv;
priv = get_shell_surface(surface); if (surface == NULL)
if (surface == NULL ||
priv->type == SHELL_SURFACE_FULLSCREEN)
if (surface == shell->panel)
return; return;
if (surface == shell->background)
priv = get_shell_surface(surface);
switch (priv->type) {
case SHELL_SURFACE_PANEL:
case SHELL_SURFACE_BACKGROUND:
case SHELL_SURFACE_FULLSCREEN:
return; return;
default:
break;
}
x = device->grab_x - surface->x; x = device->grab_x - surface->x;
y = device->grab_y - surface->y; y = device->grab_y - surface->y;
@ -1065,11 +1056,14 @@ activate(struct wlsc_shell *base, struct wlsc_surface *es,
/* already put on top */ /* already put on top */
break; break;
default: default:
if (shell->panel && !shell->locked) { if (!shell->locked) {
/* bring panel back to top */ /* bring panel back to top */
wl_list_remove(&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, wl_list_insert(&compositor->surface_list,
&shell->panel->link); &panel->surface->link);
}
} }
} }
} }
@ -1188,11 +1182,15 @@ map(struct wlsc_shell *base,
break; break;
default: default:
/* everything else just below the panel */ /* everything else just below the panel */
if (shell->panel) if (!wl_list_empty(&shell->panels)) {
wl_list_insert(&shell->panel->link, &surface->link); struct shell_surface *panel =
else container_of(shell->panels.prev,
struct shell_surface, link);
wl_list_insert(&panel->surface->link, &surface->link);
} else {
wl_list_insert(list, &surface->link); wl_list_insert(list, &surface->link);
} }
}
if (priv->type == SHELL_SURFACE_TOPLEVEL) { if (priv->type == SHELL_SURFACE_TOPLEVEL) {
surface->x = 10 + random() % 400; surface->x = 10 + random() % 400;
@ -1348,6 +1346,8 @@ shell_init(struct wlsc_compositor *ec)
shell->shell.set_selection_focus = wlsc_selection_set_focus; shell->shell.set_selection_focus = wlsc_selection_set_focus;
wl_list_init(&shell->hidden_surface_list); 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, if (wl_display_add_global(ec->wl_display, &wl_shell_interface,
shell, bind_shell) == NULL) shell, bind_shell) == NULL)

@ -2,10 +2,12 @@
<interface name="desktop_shell" version="1"> <interface name="desktop_shell" version="1">
<request name="set_background"> <request name="set_background">
<arg name="output" type="object" interface="wl_output"/>
<arg name="surface" type="object" interface="wl_surface"/> <arg name="surface" type="object" interface="wl_surface"/>
</request> </request>
<request name="set_panel"> <request name="set_panel">
<arg name="output" type="object" interface="wl_output"/>
<arg name="surface" type="object" interface="wl_surface"/> <arg name="surface" type="object" interface="wl_surface"/>
</request> </request>

Loading…
Cancel
Save