extensions,handlers: Add notification area support

notification-area.{c,h} are bare imports from the
wayland-notification-area project.

Signed-off-by: Quentin Glidic <sardemff7+git@sardemff7.net>
This commit is contained in:
Quentin Glidic 2016-05-07 12:19:45 +02:00
parent db8dacf76e
commit 5e969fd229
7 changed files with 305 additions and 0 deletions

View file

@ -3,6 +3,7 @@
#include <wayland-server.h>
#include <wlc/wlc-wayland.h>
#include "notification-area.h"
#include "wayland-desktop-shell-server-protocol.h"
#include "list.h"
@ -37,6 +38,7 @@ struct swaylock_state {
};
extern struct desktop_shell_state desktop_shell;
extern struct wlc_notification_area *notification_area;
void register_extensions(void);

View file

@ -0,0 +1,36 @@
/*
* Copyright © 2013-2016 Quentin Sardem FF7 Glidic
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef _WLC_NOTIFICATION_AREA_H_
#define _WLC_NOTIFICATION_AREA_H_
#include <wlc/wlc.h>
struct wlc_notification_area;
struct wlc_notification_area *wlc_notification_area_init(void);
void wlc_notification_area_uninit(struct wlc_notification_area *na);
WLC_PURE wlc_handle wlc_notification_area_get_output(struct wlc_notification_area *na);
void wlc_notification_area_set_output(struct wlc_notification_area *na, wlc_handle output);
void wlc_notification_area_view_destroy(struct wlc_notification_area *na, wlc_handle view);
#endif /* _WLC_NOTIFICATION_AREA_H_ */

View file

@ -22,12 +22,20 @@ WAYLAND_ADD_PROTOCOL_SERVER(proto-server-swaylock
swaylock
)
pkg_check_modules(WLC_NOTIFICATION_AREA "wayland-notification-area >= 3")
pkg_get_variable(WAYLAND_NOTIFICATION_AREA_PKGDATADIR wayland-notification-area pkgdatadir)
WAYLAND_ADD_PROTOCOL_SERVER(proto-server-wayland-notification-area
${WAYLAND_NOTIFICATION_AREA_PKGDATADIR}/notification-area-unstable-v2.xml
notification-area-unstable-v2
)
add_library(sway-protocols STATIC
${proto-client-xdg-shell}
${proto-client-desktop-shell}
${proto-server-desktop-shell}
${proto-client-swaylock}
${proto-server-swaylock}
${proto-server-wayland-notification-area}
)
set(PROTOCOLS_INCLUDE_DIRS ${CMAKE_BINARY_DIR}/protocols PARENT_SCOPE)

View file

@ -24,6 +24,7 @@ add_executable(sway
ipc-server.c
layout.c
main.c
notification-area.c
output.c
resize.c
workspace.c

View file

@ -10,6 +10,7 @@
#include "extensions.h"
struct desktop_shell_state desktop_shell;
struct wlc_notification_area *notification_area;
static struct panel_config *find_or_create_panel_config(struct wl_resource *resource) {
for (int i = 0; i < desktop_shell.panels->length; i++) {
@ -214,4 +215,5 @@ void register_extensions(void) {
desktop_shell.lock_surfaces = create_list();
desktop_shell.is_locked = false;
wl_global_create(wlc_get_wl_display(), &lock_interface, 1, NULL, swaylock_bind);
notification_area = wlc_notification_area_init();
}

View file

@ -86,6 +86,10 @@ static bool handle_output_created(wlc_handle output) {
wlc_handle prev = wlc_get_focused_output();
wlc_output_focus(output);
wlc_output_focus(prev);
if (wlc_notification_area_get_output(notification_area) == 0)
wlc_notification_area_set_output(notification_area, output);
return true;
}
@ -108,6 +112,11 @@ static void handle_output_destroyed(wlc_handle output) {
swayc_t *c = (swayc_t *)list->items[0];
// switch to other outputs active workspace
workspace_switch(c->focused);
if (wlc_notification_area_get_output(notification_area) == output)
wlc_notification_area_set_output(notification_area, c->handle);
} else {
if (wlc_notification_area_get_output(notification_area) == output)
wlc_notification_area_set_output(notification_area, 0);
}
}
@ -165,6 +174,9 @@ static void handle_output_resolution_change(wlc_handle output, const struct wlc_
c->width = to->w;
c->height = to->h;
arrange_windows(&root_container, -1, -1);
if (wlc_notification_area_get_output(notification_area) == output)
wlc_notification_area_set_output(notification_area, output);
}
static void handle_output_focused(wlc_handle output, bool focus) {

244
sway/notification-area.c Normal file
View file

@ -0,0 +1,244 @@
/*
* Copyright © 2013-2016 Quentin Sardem FF7 Glidic
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <stdlib.h>
#include <wayland-util.h>
#include <wlc/wlc.h>
#include <wlc/wlc-wayland.h>
#include "wayland-notification-area-unstable-v2-server-protocol.h"
#include "notification-area.h"
struct wlc_notification_area {
struct wl_global *global;
struct wl_resource *binding;
struct wl_list notifications;
wlc_handle output;
};
struct wlc_notification_area_notification {
struct wlc_notification_area *na;
struct wl_list link;
wlc_handle view;
};
static void
_wlc_notification_area_request_destroy(struct wl_client *client, struct wl_resource *resource)
{
(void) client;
wl_resource_destroy(resource);
}
static void
_wlc_notification_area_notification_set_output(struct wlc_notification_area_notification *notification, wlc_handle output)
{
if ( output == 0 )
{
wlc_view_set_mask(notification->view, 0);
return;
}
wlc_view_set_output(notification->view, output);
wlc_view_set_mask(notification->view, wlc_output_get_mask(output));
wlc_view_bring_to_front(notification->view);
}
static void
_wlc_notification_area_notification_request_move(struct wl_client *client, struct wl_resource *resource, int32_t x, int32_t y)
{
(void) client;
struct wlc_notification_area_notification *notification = wl_resource_get_user_data(resource);
struct wlc_geometry geometry;
geometry = *wlc_view_get_geometry(notification->view);
geometry.origin.x = x;
geometry.origin.y = y;
wlc_view_set_geometry(notification->view, WLC_RESIZE_EDGE_NONE, &geometry);
if ( wlc_view_get_mask(notification->view) == 0 )
_wlc_notification_area_notification_set_output(notification, notification->na->output);
}
static const struct zwna_notification_v2_interface wlc_notification_area_notification_implementation = {
.destroy = _wlc_notification_area_request_destroy,
.move = _wlc_notification_area_notification_request_move,
};
static void
_wlc_notification_area_destroy(struct wl_client *client, struct wl_resource *resource)
{
(void) client;
wl_resource_destroy(resource);
}
static void
_wlc_notification_area_create_notification(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *surface_resource)
{
struct wlc_notification_area *self = wl_resource_get_user_data(resource);
struct wlc_notification_area_notification *notification;
notification = calloc(1, sizeof(struct wlc_notification_area_notification));
if ( notification == NULL )
{
wl_resource_post_no_memory(surface_resource);
return;
}
notification->na = self;
wl_list_insert(&self->notifications, &notification->link);
notification->view = wlc_view_from_surface(wlc_resource_from_wl_surface_resource(surface_resource), client, &zwna_notification_v2_interface, &wlc_notification_area_notification_implementation, 1, id, notification);
if ( notification->view == 0 )
return;
wlc_view_set_type(notification->view, WLC_BIT_OVERRIDE_REDIRECT, true);
wlc_view_set_type(notification->view, WLC_BIT_UNMANAGED, true);
wlc_view_set_mask(notification->view, 0);
}
static const struct zwna_notification_area_v2_interface wlc_notification_area_implementation = {
.destroy = _wlc_notification_area_destroy,
.create_notification = _wlc_notification_area_create_notification,
};
static void
_wlc_notification_area_unbind(struct wl_resource *resource)
{
struct wlc_notification_area *self = resource->data;
self->binding = NULL;
}
static void
_wlc_notification_area_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id)
{
struct wlc_notification_area *self = data;
struct wl_resource *resource;
resource = wl_resource_create(client, &zwna_notification_area_v2_interface, version, id);
wl_resource_set_implementation(resource, &wlc_notification_area_implementation, self, _wlc_notification_area_unbind);
if ( self->binding != NULL )
{
wl_resource_post_error(resource, ZWNA_NOTIFICATION_AREA_V2_ERROR_BOUND, "interface object already bound");
wl_resource_destroy(resource);
return;
}
self->binding = resource;
const struct wlc_size *size;
if ( self->output == 0 )
size = &wlc_size_zero;
else
size = wlc_output_get_resolution(self->output);
zwna_notification_area_v2_send_geometry(self->binding, size->w, size->h, 1);
}
struct wlc_notification_area *
wlc_notification_area_init(void)
{
struct wlc_notification_area *self;
self = calloc(1, sizeof(struct wlc_notification_area));
wl_list_init(&self->notifications);
if ( ( self->global = wl_global_create(wlc_get_wl_display(), &zwna_notification_area_v2_interface, 1, self, _wlc_notification_area_bind) ) == NULL )
{
free(self);
return NULL;
}
wl_global_destroy(self->global);
if ( ( self->global = wl_global_create(wlc_get_wl_display(), &zwna_notification_area_v2_interface, 1, self, _wlc_notification_area_bind) ) == NULL )
{
free(self);
return NULL;
}
return self;
}
static void
_wlc_notification_area_view_destroy_internal(struct wlc_notification_area_notification *self)
{
//wlc_view_close(notification->view);
wl_list_remove(&self->link);
free(self);
}
void
wlc_notification_area_uninit(struct wlc_notification_area *self)
{
struct wlc_notification_area_notification *notification, *tmp;
wl_list_for_each_safe(notification, tmp, &self->notifications, link)
_wlc_notification_area_view_destroy_internal(notification);
wl_global_destroy(self->global);
free(self);
}
wlc_handle
wlc_notification_area_get_output(struct wlc_notification_area *self)
{
return self->output;
}
void
wlc_notification_area_set_output(struct wlc_notification_area *self, wlc_handle output)
{
if ( self->binding != NULL )
{
const struct wlc_size *size;
if ( output == 0 )
size = &wlc_size_zero;
else
size = wlc_output_get_resolution(output);
zwna_notification_area_v2_send_geometry(self->binding, size->w, size->h, 1);
}
if ( self->output == output )
return;
self->output = output;
struct wlc_notification_area_notification *notification;
wl_list_for_each(notification, &self->notifications, link)
{
if ( wlc_view_get_mask(notification->view) == 0 )
continue;
_wlc_notification_area_notification_set_output(notification, output);
}
}
void
wlc_notification_area_view_destroy(struct wlc_notification_area *self, wlc_handle view)
{
struct wlc_notification_area_notification *notification, *tmp;
wl_list_for_each_safe(notification, tmp, &self->notifications, link)
{
if ( notification->view != view )
continue;
_wlc_notification_area_view_destroy_internal(notification);
return;
}
}