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, ¬ifications_corner }, + { "order", CONFIG_KEY_STRING, ¬ifications_order }, + { "margin", CONFIG_KEY_INTEGER, ¬ifications_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, ¬ification_daemon_interface, + ¬ification_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, ¬ification_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