---
 src/shell.c | 141 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 weston.ini  |   5 +++
 2 files changed, 143 insertions(+), 3 deletions(-)

diff --git a/src/shell.c b/src/shell.c
index aa1c7c1..968843a 100644
--- a/src/shell.c
+++ b/src/shell.c
@@ -41,6 +41,8 @@
 #define DEFAULT_NUM_WORKSPACES 1
 #define DEFAULT_WORKSPACE_CHANGE_ANIMATION_LENGTH 200
 
+#define DEFAULT_NOTIFICATIONS_MARGIN 20
+
 enum animation_type {
        ANIMATION_NONE,
 
@@ -48,6 +50,25 @@ enum animation_type {
        ANIMATION_FADE
 };
 
+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;
@@ -79,6 +100,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;
@@ -133,6 +155,12 @@ struct desktop_shell {
                struct wl_list surfaces;
        } input_panel;
 
+       struct {
+               enum corner_anchor corner;
+               enum notifications_order order;
+               int32_t margin;
+       } notifications;
+
        uint32_t binding_modifier;
        enum animation_type win_animation_type;
 };
@@ -143,7 +171,8 @@ enum shell_surface_type {
        SHELL_SURFACE_TRANSIENT,
        SHELL_SURFACE_FULLSCREEN,
        SHELL_SURFACE_MAXIMIZED,
-       SHELL_SURFACE_POPUP
+       SHELL_SURFACE_POPUP,
+       SHELL_SURFACE_NOTIFICATION
 };
 
 struct ping_timer {
@@ -337,6 +366,36 @@ 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 void
 shell_configuration(struct desktop_shell *shell)
 {
@@ -346,6 +405,9 @@ shell_configuration(struct desktop_shell *shell)
        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 },
@@ -359,9 +421,16 @@ shell_configuration(struct desktop_shell *shell)
                { "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 },
        };
 
        config_file = config_file_path("weston.ini");
@@ -373,6 +442,12 @@ shell_configuration(struct desktop_shell *shell)
        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->notifications.corner = get_corner_anchor(notifications_corner, 
CORNER_TOP_RIGHT);
+       shell->notifications.order = 
get_notification_order(notifications_order);
+       shell->notifications.margin = notifications_margin;
+
+       free(notifications_order);
+       free(notifications_corner);
 }
 
 static void
@@ -1457,6 +1532,9 @@ static int
 reset_shell_surface_type(struct shell_surface *surface)
 {
        switch (surface->type) {
+       case SHELL_SURFACE_NOTIFICATION:
+               wl_list_remove(&surface->surface->layer_link);
+               break;
        case SHELL_SURFACE_FULLSCREEN:
                shell_unset_fullscreen(surface);
                break;
@@ -1914,6 +1992,57 @@ shell_surface_set_popup(struct wl_client *client,
        shsurf->popup.y = y;
 }
 
+static void
+shell_map_notifications(struct desktop_shell *shell)
+{
+    bool right;
+    bool bottom;
+    right = shell->notifications.corner & EDGE_RIGHT;
+    bottom = shell->notifications.corner & EDGE_BOTTOM;
+
+       struct weston_output *output;
+       output = get_default_output(shell->compositor);
+
+       int32_t x, y;
+       if (right)
+               x = output->width - shell->notifications.margin;
+       else
+               x = shell->notifications.margin;
+       if (bottom)
+               y = output->height - shell->notifications.margin;
+       else
+               y = shell->notifications.margin;
+
+       struct weston_surface *ws;
+       wl_list_for_each(ws, &shell->notification_layer.surface_list, 
layer_link) {
+               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->notifications.margin;
+               else
+                       y += ws->geometry.height + shell->notifications.margin;
+       }
+}
+
+static void
+shell_surface_set_notification(struct wl_client *client, struct wl_resource 
*resource)
+{
+       struct shell_surface *shsurf = resource->data;
+       struct desktop_shell *shell = shsurf->shell;
+       struct weston_surface *es = shsurf->surface;
+
+       shsurf->type = SHELL_SURFACE_NOTIFICATION;
+       if (shell->notifications.order == ORDER_NEWEST_FIRST)
+               wl_list_insert(&shell->notification_layer.surface_list, 
&es->layer_link);
+       else
+               wl_list_insert(shell->notification_layer.surface_list.prev, 
&es->layer_link);
+}
+
 static const struct wl_shell_surface_interface shell_surface_implementation = {
        shell_surface_pong,
        shell_surface_move,
@@ -1924,7 +2053,8 @@ static const struct wl_shell_surface_interface 
shell_surface_implementation = {
        shell_surface_set_popup,
        shell_surface_set_maximized,
        shell_surface_set_title,
-       shell_surface_set_class
+       shell_surface_set_class,
+       shell_surface_set_notification
 };
 
 static void
@@ -2923,6 +3053,9 @@ map(struct desktop_shell *shell, struct weston_surface 
*surface,
        case SHELL_SURFACE_POPUP:
                shell_map_popup(shsurf);
                break;
+       case SHELL_SURFACE_NOTIFICATION:
+               shell_map_notifications(shell);
+               break;
        case SHELL_SURFACE_NONE:
                weston_surface_set_position(surface,
                                            surface->geometry.x + sx,
@@ -2939,6 +3072,7 @@ map(struct desktop_shell *shell, struct weston_surface 
*surface,
                parent = shsurf->parent;
                wl_list_insert(parent->layer_link.prev, &surface->layer_link);
                break;
+       case SHELL_SURFACE_NOTIFICATION:
        case SHELL_SURFACE_FULLSCREEN:
        case SHELL_SURFACE_NONE:
                break;
@@ -3848,7 +3982,8 @@ module_init(struct weston_compositor *ec)
        wl_list_init(&shell->screensaver.surfaces);
        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);
diff --git a/weston.ini b/weston.ini
index c213460..9c9c07f 100644
--- a/weston.ini
+++ b/weston.ini
@@ -36,6 +36,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.0.2

_______________________________________________
wayland-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to