[PATCH weston] shell: Implement wl_notification_daemon
Quentin Glidic
sardemff7+git at sardemff7.net
Mon Jan 21 06:33:03 PST 2013
Implement the "bubbles list" style notifications.
Corner anchor, margin and order can be changed in the configuration.
---
src/shell.c | 195 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
weston.ini | 5 ++
2 files changed, 192 insertions(+), 8 deletions(-)
diff --git a/src/shell.c b/src/shell.c
index 43f100e..04b48ff 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,14 @@ struct desktop_shell {
struct wl_list surfaces;
} input_panel;
+ struct {
+ enum corner_anchor corner;
+ enum notifications_order order;
+ int32_t margin;
+ struct weston_output *output;
+ struct wl_resource *binding;
+ } notification_daemon;
+
uint32_t binding_modifier;
enum animation_type win_animation_type;
};
@@ -337,6 +367,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)
{
@@ -346,6 +413,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 +429,16 @@ shell_configuration(struct desktop_shell *shell)
{ "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 },
};
config_file = config_file_path("weston.ini");
@@ -373,6 +450,13 @@ 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->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
@@ -1415,13 +1499,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)
{
@@ -2084,6 +2161,72 @@ static const struct wl_shell_interface shell_implementation = {
};
static void
+notification_daemon_map(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) {
+ 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;
+ }
+ weston_compositor_schedule_repaint(shell->compositor);
+}
+
+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 already added as a notification surface");
+ return;
+ }
+
+ surface->output = shell->notification_daemon.output;
+ surface->private = shell;
+
+ 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);
+ notification_daemon_map(shell);
+
+ weston_surface_update_transform(surface);
+}
+
+static const struct wl_notification_daemon_interface notification_daemon_implementation = {
+ notification_daemon_add_surface
+};
+
+static void
handle_screensaver_sigchld(struct weston_process *proc, int status)
{
proc->pid = 0;
@@ -3116,6 +3259,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;
@@ -3849,7 +4023,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);
@@ -3879,6 +4054,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 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.1
More information about the wayland-devel
mailing list