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>
---
 src/.gitignore            |   2 +
 src/Makefile.am           |  17 +++
 src/notification-daemon.c | 266 ++++++++++++++++++++++++++++++++++++++++++++++
 weston.ini                |   5 +
 4 files changed, 290 insertions(+)
 create mode 100644 src/notification-daemon.c

diff --git a/src/.gitignore b/src/.gitignore
index ee62b84..ce7f5ab 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
+notification-daemon-protocol.c
+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 73c2d0d..e342a1c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -99,6 +99,7 @@ module_LTLIBRARIES =                          \
        $(desktop_shell)                        \
        $(tablet_shell)                         \
        $(cms_static)                           \
+       $(notification_daemon)                  \
        $(x11_backend)                          \
        $(drm_backend)                          \
        $(wayland_backend)                      \
@@ -267,6 +268,20 @@ cms_static_la_SOURCES =                            \
        cms-helper.h
 endif
 
+notification_daemon = notification-daemon.la
+notification_daemon_la_SOURCES =               \
+       notification-daemon.c                   \
+       notification-daemon-protocol.c          \
+       notification-daemon-server-protocol.h
+notification_daemon_la_CFLAGS = \
+       $(GCC_CFLAGS) \
+       $(COMPOSITOR_CFLAGS)
+notification_daemon_la_LDFLAGS = \
+       -module -avoid-version
+notification_daemon_la_LIBADD = \
+       $(COMPOSITOR_LIBS)      \
+       ../shared/libshared.la
+
 BUILT_SOURCES =                                        \
        screenshooter-server-protocol.h         \
        screenshooter-protocol.c                \
@@ -280,6 +295,8 @@ BUILT_SOURCES =                                     \
        text-server-protocol.h                  \
        input-method-protocol.c                 \
        input-method-server-protocol.h          \
+       notification-daemon-protocol.c          \
+       notification-daemon-server-protocol.h   \
        workspaces-server-protocol.h            \
        workspaces-protocol.c                   \
        subsurface-server-protocol.h            \
diff --git a/src/notification-daemon.c b/src/notification-daemon.c
new file mode 100644
index 0000000..ce77077
--- /dev/null
+++ b/src/notification-daemon.c
@@ -0,0 +1,266 @@
+/*
+ * Copyright © 2013 Quentin “Sardem FF7” Glidic
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the copyright holders not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission.  The copyright holders make
+ * no representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <string.h>
+#include <unistd.h>
+#include <linux/input.h>
+#include <assert.h>
+#include <signal.h>
+#include <math.h>
+#include <sys/types.h>
+
+#include <wayland-server.h>
+#include "compositor.h"
+#include "notification-daemon-server-protocol.h"
+#include "../shared/config-parser.h"
+
+#define DEFAULT_NOTIFICATIONS_MARGIN 20
+
+
+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 notification_daemon {
+       struct weston_compositor *compositor;
+
+       struct weston_layer layer;
+
+       enum corner_anchor corner;
+       enum notifications_order order;
+       int32_t margin;
+       struct weston_output *output;
+       struct wl_resource *binding;
+};
+
+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
+notification_daemon_configuration(struct notification_daemon *nd, const char 
*config_file)
+{
+       char *notifications_corner = NULL;
+       char *notifications_order = NULL;
+       int notifications_margin = DEFAULT_NOTIFICATIONS_MARGIN;
+
+       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[] = {
+               { "notifications", notifications_keys, 
ARRAY_LENGTH(notifications_keys), NULL },
+       };
+
+       parse_config_file(config_file, cs, ARRAY_LENGTH(cs), nd);
+
+       nd->corner = get_corner_anchor(notifications_corner, CORNER_TOP_RIGHT);
+       nd->order = get_notification_order(notifications_order);
+       nd->margin = notifications_margin;
+       nd->output = get_default_output(nd->compositor);
+
+       free(notifications_order);
+       free(notifications_corner);
+}
+
+static void
+notification_daemon_map_surfaces(struct notification_daemon *nd)
+{
+       bool right;
+       bool bottom;
+       int32_t x, y;
+       struct weston_surface *ws;
+
+       right = nd->corner & EDGE_RIGHT;
+       bottom = nd->corner & EDGE_BOTTOM;
+
+       if (right)
+               x = nd->output->width - nd->margin;
+       else
+               x = nd->margin;
+       if (bottom)
+               y = nd->output->height - nd->margin;
+       else
+               y = nd->margin;
+
+       wl_list_for_each(ws, &nd->layer.surface_list, layer_link) {
+               ws->output = nd->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 -= nd->margin;
+               else
+                       y += ws->geometry.height + nd->margin;
+       }
+}
+
+static void
+notification_configure(struct weston_surface *surface, int32_t sx, int32_t sy, 
int32_t width, int32_t height)
+{
+       struct notification_daemon *nd = surface->configure_private;
+
+       surface->geometry.width = width;
+       surface->geometry.height = height;
+       notification_daemon_map_surfaces(nd);
+
+}
+
+static void
+notification_daemon_add_surface(struct wl_client *client, struct wl_resource 
*resource,
+                               struct wl_resource *surface_resource)
+{
+       struct notification_daemon *nd = 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 (nd->order == ORDER_NEWEST_FIRST)
+               wl_list_insert(&nd->layer.surface_list, &surface->layer_link);
+       else
+               wl_list_insert(nd->layer.surface_list.prev, 
&surface->layer_link);
+
+       surface->configure = notification_configure;
+       surface->configure_private = nd;
+}
+
+static const struct notification_daemon_interface 
notification_daemon_implementation = {
+       notification_daemon_add_surface
+};
+
+static void
+unbind_notification_daemon(struct wl_resource *resource)
+{
+       struct notification_daemon *nd = resource->data;
+
+       nd->binding = NULL;
+       free(resource);
+}
+
+static void
+bind_notification_daemon(struct wl_client *client,
+                        void *data, uint32_t version, uint32_t id)
+{
+       struct notification_daemon *nd = data;
+       struct wl_resource *resource;
+
+       resource = wl_client_add_object(client, &notification_daemon_interface,
+                                       &notification_daemon_implementation,
+                                       id, nd);
+
+       if (nd->binding == NULL) {
+               resource->destroy = unbind_notification_daemon;
+               nd->binding = resource;
+               return;
+       }
+
+       wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
+                              "interface object already bound");
+       wl_resource_destroy(resource);
+}
+
+WL_EXPORT int
+module_init(struct weston_compositor *ec,
+           int *argc, char *argv[], const char *config_file)
+{
+       struct notification_daemon *nd;
+
+       nd = malloc(sizeof *nd);
+       if (nd == NULL)
+               return -1;
+
+       memset(nd, 0, sizeof *nd);
+       nd->compositor = ec;
+
+       weston_layer_init(&nd->layer, &ec->cursor_layer.link);
+
+       notification_daemon_configuration(nd, config_file);
+
+       if (wl_display_add_global(ec->wl_display, 
&notification_daemon_interface,
+                                 nd, bind_notification_daemon) == NULL)
+               return -1;
+
+       return 0;
+}
diff --git a/weston.ini b/weston.ini
index 49ba526..02e38b6 100644
--- a/weston.ini
+++ b/weston.ini
@@ -39,6 +39,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.1

_______________________________________________
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to