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,  &notifications_corner },
+               { "order",     CONFIG_KEY_STRING,  &notifications_order },
+               { "margin",    CONFIG_KEY_INTEGER, &notifications_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,
+                                       &notification_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

Reply via email to