From: Quentin Glidic <sardemff7+...@sardemff7.net> Implement the "bubbles list" style notifications. Corner anchor, margin and order can be changed in the configuration.
Signed-off-by: Quentin Glidic <sardemff7+...@sardemff7.net> --- Nothing really new here, just using the configure callback to place the surfaces correctly when a new buffer is attached src/.gitignore | 2 + src/Makefile.am | 6 +- src/shell.c | 205 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- weston.ini | 5 ++ 4 files changed, 209 insertions(+), 9 deletions(-) diff --git a/src/.gitignore b/src/.gitignore index 8c0fea6..a287676 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -14,6 +14,8 @@ desktop-shell-protocol.c desktop-shell-server-protocol.h text-protocol.c text-server-protocol.h +wl-notification-daemon-protocol.c +wl-notification-daemon-server-protocol.h workspaces-protocol.c workspaces-server-protocol.h input-method-protocol.c diff --git a/src/Makefile.am b/src/Makefile.am index d33ebc5..2108382 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -237,7 +237,9 @@ desktop_shell_la_CFLAGS = $(GCC_CFLAGS) $(COMPOSITOR_CFLAGS) desktop_shell_la_SOURCES = \ shell.c \ desktop-shell-protocol.c \ - desktop-shell-server-protocol.h + desktop-shell-server-protocol.h \ + wl-notification-daemon-protocol.c \ + wl-notification-daemon-server-protocol.h endif if ENABLE_TABLET_SHELL @@ -264,6 +266,8 @@ BUILT_SOURCES = \ text-server-protocol.h \ input-method-protocol.c \ input-method-server-protocol.h \ + wl-notification-daemon-protocol.c \ + wl-notification-daemon-server-protocol.h \ workspaces-server-protocol.h \ workspaces-protocol.c \ git-version.h diff --git a/src/shell.c b/src/shell.c index de5d6f6..48eb9dc 100644 --- a/src/shell.c +++ b/src/shell.c @@ -37,11 +37,14 @@ #include "desktop-shell-server-protocol.h" #include "input-method-server-protocol.h" #include "workspaces-server-protocol.h" +#include "wl-notification-daemon-server-protocol.h" #include "../shared/config-parser.h" #define DEFAULT_NUM_WORKSPACES 1 #define DEFAULT_WORKSPACE_CHANGE_ANIMATION_LENGTH 200 +#define DEFAULT_NOTIFICATIONS_MARGIN 20 + enum animation_type { ANIMATION_NONE, @@ -54,6 +57,25 @@ enum fade_type { FADE_OUT }; +enum edge_anchor { + EDGE_TOP = 1<<0, + EDGE_BOTTOM = 1<<1, + EDGE_LEFT = 1<<2, + EDGE_RIGHT = 1<<3 +}; + +enum corner_anchor { + CORNER_TOP_RIGHT = EDGE_TOP | EDGE_RIGHT, + CORNER_TOP_LEFT = EDGE_TOP | EDGE_LEFT, + CORNER_BOTTOM_RIGHT = EDGE_BOTTOM | EDGE_RIGHT, + CORNER_BOTTOM_LEFT = EDGE_BOTTOM | EDGE_LEFT, +}; + +enum notifications_order { + ORDER_NEWEST_FIRST, + ORDER_OLDEST_FIRST +}; + struct focus_state { struct weston_seat *seat; struct workspace *ws; @@ -89,6 +111,7 @@ struct desktop_shell { struct wl_listener show_input_panel_listener; struct wl_listener hide_input_panel_listener; + struct weston_layer notification_layer; struct weston_layer fullscreen_layer; struct weston_layer panel_layer; struct weston_layer background_layer; @@ -144,6 +167,14 @@ struct desktop_shell { } input_panel; struct { + enum corner_anchor corner; + enum notifications_order order; + int32_t margin; + struct weston_output *output; + struct wl_resource *binding; + } notification_daemon; + + struct { struct weston_surface *surface; struct weston_surface_animation *animation; enum fade_type type; @@ -366,6 +397,43 @@ get_animation_type(char *animation) return ANIMATION_NONE; } +static enum corner_anchor +get_corner_anchor(char *placement, enum corner_anchor default_anchor) +{ + if (placement == NULL) + return default_anchor; + + if (strcmp("top-left", placement) == 0) + return CORNER_TOP_LEFT; + if (strcmp("top-right", placement) == 0) + return CORNER_TOP_RIGHT; + if (strcmp("bottom-right", placement) == 0) + return CORNER_BOTTOM_RIGHT; + if (strcmp("bottom-left", placement) == 0) + return CORNER_BOTTOM_LEFT; + + return default_anchor; +} + +static enum notifications_order +get_notification_order(char *order) +{ + if (order == NULL) + return ORDER_NEWEST_FIRST; + + if (strcmp("oldest-first", order) == 0) + return ORDER_OLDEST_FIRST; + + return ORDER_NEWEST_FIRST; +} + +static struct weston_output * +get_default_output(struct weston_compositor *compositor) +{ + return container_of(compositor->output_list.next, + struct weston_output, link); +} + static void shell_configuration(struct desktop_shell *shell, const char *config_file) { @@ -374,6 +442,9 @@ shell_configuration(struct desktop_shell *shell, const char *config_file) unsigned int num_workspaces = DEFAULT_NUM_WORKSPACES; char *modifier = NULL; char *win_animation = NULL; + char *notifications_corner = NULL; + char *notifications_order = NULL; + int notifications_margin = DEFAULT_NOTIFICATIONS_MARGIN; struct config_key shell_keys[] = { { "binding-modifier", CONFIG_KEY_STRING, &modifier }, @@ -387,9 +458,16 @@ shell_configuration(struct desktop_shell *shell, const char *config_file) { "duration", CONFIG_KEY_INTEGER, &duration }, }; + struct config_key notifications_keys[] = { + { "corner", CONFIG_KEY_STRING, ¬ifications_corner }, + { "order", CONFIG_KEY_STRING, ¬ifications_order }, + { "margin", CONFIG_KEY_INTEGER, ¬ifications_margin }, + }; + struct config_section cs[] = { { "shell", shell_keys, ARRAY_LENGTH(shell_keys), NULL }, { "screensaver", saver_keys, ARRAY_LENGTH(saver_keys), NULL }, + { "notifications", notifications_keys, ARRAY_LENGTH(notifications_keys), NULL }, }; parse_config_file(config_file, cs, ARRAY_LENGTH(cs), shell); @@ -399,6 +477,13 @@ shell_configuration(struct desktop_shell *shell, const char *config_file) shell->binding_modifier = get_modifier(modifier); shell->win_animation_type = get_animation_type(win_animation); shell->workspaces.num = num_workspaces > 0 ? num_workspaces : 1; + shell->notification_daemon.corner = get_corner_anchor(notifications_corner, CORNER_TOP_RIGHT); + shell->notification_daemon.order = get_notification_order(notifications_order); + shell->notification_daemon.margin = notifications_margin; + shell->notification_daemon.output = get_default_output(shell->compositor); + + free(notifications_order); + free(notifications_corner); } static void @@ -1445,13 +1530,6 @@ shell_surface_set_class(struct wl_client *client, shsurf->class = strdup(class); } -static struct weston_output * -get_default_output(struct weston_compositor *compositor) -{ - return container_of(compositor->output_list.next, - struct weston_output, link); -} - static void shell_unset_fullscreen(struct shell_surface *shsurf) { @@ -2241,6 +2319,81 @@ static const struct wl_shell_interface shell_implementation = { }; static void +notification_daemon_map_surfaces(struct desktop_shell *shell) +{ + bool right; + bool bottom; + int32_t x, y; + struct weston_surface *ws; + + right = shell->notification_daemon.corner & EDGE_RIGHT; + bottom = shell->notification_daemon.corner & EDGE_BOTTOM; + + if (right) + x = shell->notification_daemon.output->width - shell->notification_daemon.margin; + else + x = shell->notification_daemon.margin; + if (bottom) + y = shell->notification_daemon.output->height - shell->notification_daemon.margin; + else + y = shell->notification_daemon.margin; + + wl_list_for_each(ws, &shell->notification_layer.surface_list, layer_link) { + ws->output = shell->notification_daemon.output; + + if (bottom) + y -= ws->geometry.height; + if (right) + x -= ws->geometry.width; + weston_surface_set_position(ws, x, y); + if (right) + x += ws->geometry.width; + if (bottom) + y -= shell->notification_daemon.margin; + else + y += ws->geometry.height + shell->notification_daemon.margin; + } +} + +static void +notification_configure(struct weston_surface *surface, int32_t sx, int32_t sy, int32_t width, int32_t height) +{ + struct desktop_shell *shell = surface->configure_private; + + surface->geometry.width = width; + surface->geometry.height = height; + notification_daemon_map_surfaces(shell); + +} + +static void +notification_daemon_add_surface(struct wl_client *client, struct wl_resource *resource, + struct wl_resource *surface_resource) +{ + struct desktop_shell *shell = resource->data; + struct weston_surface *surface = surface_resource->data; + + if (surface->configure != NULL) { + wl_resource_post_error(surface_resource, + WL_DISPLAY_ERROR_INVALID_OBJECT, + "surface role already assigned"); + return; + } + + if (shell->notification_daemon.order == ORDER_NEWEST_FIRST) + wl_list_insert(&shell->notification_layer.surface_list, &surface->layer_link); + else + wl_list_insert(shell->notification_layer.surface_list.prev, &surface->layer_link); + + surface->configure = notification_configure; + surface->configure_private = shell; +} + +static const struct wl_notification_daemon_interface notification_daemon_implementation = { + notification_daemon_add_surface +}; + +static void shell_fade(struct desktop_shell *shell, enum fade_type type); static int @@ -3376,6 +3529,37 @@ bind_shell(struct wl_client *client, void *data, uint32_t version, uint32_t id) } static void +unbind_notification_daemon(struct wl_resource *resource) +{ + struct desktop_shell *shell = resource->data; + + shell->notification_daemon.binding = NULL; + free(resource); +} + +static void +bind_notification_daemon(struct wl_client *client, + void *data, uint32_t version, uint32_t id) +{ + struct desktop_shell *shell = data; + struct wl_resource *resource; + + resource = wl_client_add_object(client, &wl_notification_daemon_interface, + ¬ification_daemon_implementation, + id, shell); + + if (shell->notification_daemon.binding == NULL) { + resource->destroy = unbind_notification_daemon; + shell->notification_daemon.binding = resource; + return; + } + + wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT, + "interface object already bound"); + wl_resource_destroy(resource); +} + +static void unbind_desktop_shell(struct wl_resource *resource) { struct desktop_shell *shell = resource->data; @@ -4205,7 +4389,8 @@ module_init(struct weston_compositor *ec, wl_list_init(&shell->input_panel.surfaces); - weston_layer_init(&shell->fullscreen_layer, &ec->cursor_layer.link); + weston_layer_init(&shell->notification_layer, &ec->cursor_layer.link); + weston_layer_init(&shell->fullscreen_layer, &shell->notification_layer.link); weston_layer_init(&shell->panel_layer, &shell->fullscreen_layer.link); weston_layer_init(&shell->background_layer, &shell->panel_layer.link); weston_layer_init(&shell->lock_layer, NULL); @@ -4235,6 +4420,10 @@ module_init(struct weston_compositor *ec, shell, bind_shell) == NULL) return -1; + if (wl_display_add_global(ec->wl_display, &wl_notification_daemon_interface, + shell, bind_notification_daemon) == NULL) + return -1; + if (wl_display_add_global(ec->wl_display, &desktop_shell_interface, shell, bind_desktop_shell) == NULL) diff --git a/weston.ini b/weston.ini index c6cff76..b01f03b 100644 --- a/weston.ini +++ b/weston.ini @@ -38,6 +38,11 @@ path=./clients/flower path=/usr/libexec/weston-screensaver duration=600 +[notifications] +#corner=top-right +#order=newest-first +#margin=20 + [input-method] path=/usr/libexec/weston-keyboard -- 1.8.2 _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel