swc

Unnamed repository; edit this file 'description' to name the repository.
git clone git://git.nihaljere.xyz/swc
Log | Files | Refs | README | LICENSE

commit ec48a73fe5e91f8593c664763d7b9ff9939c75c5
parent f743751ccb35c53b944df2f1cbad37d3adbd13a3
Author: Michael Forney <mforney@mforney.org>
Date:   Wed, 22 Jan 2014 17:29:14 -0800

Implement panels

Diffstat:
MMakefile | 2+-
Mconfig.mk | 1+
Mlibswc/local.mk | 4++++
Alibswc/panel.c | 261+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alibswc/panel.h | 50++++++++++++++++++++++++++++++++++++++++++++++++++
Alibswc/panel_manager.c | 82+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alibswc/panel_manager.h | 33+++++++++++++++++++++++++++++++++
Mlibswc/swc.c | 14+++++++++++++-
Mprotocol/local.mk | 4++++
Aprotocol/swc.xml | 40++++++++++++++++++++++++++++++++++++++++
10 files changed, 489 insertions(+), 2 deletions(-)

diff --git a/Makefile b/Makefile @@ -48,7 +48,7 @@ pkgconfig = $(sort $(foreach pkg,$(1),$(if $($(pkg)_$(3)),$($(pkg)_$(3)), \ include $(SUBDIRS:%=%/local.mk) -$(foreach dir,BIN LIB INCLUDE PKGCONFIG,$(DESTDIR)$($(dir)DIR)): +$(foreach dir,BIN LIB INCLUDE PKGCONFIG,$(DESTDIR)$($(dir)DIR)) $(DESTDIR)$(DATADIR)/swc: mkdir -p "$@" .PHONY: check-dependencies diff --git a/config.mk b/config.mk @@ -4,6 +4,7 @@ PREFIX = /usr/local BINDIR = $(PREFIX)/bin LIBDIR = $(PREFIX)/lib INCLUDEDIR = $(PREFIX)/include +DATADIR = $(PREFIX)/share PKGCONFIGDIR = $(LIBDIR)/pkgconfig CC = gcc diff --git a/libswc/local.mk b/libswc/local.mk @@ -44,6 +44,8 @@ SWC_SOURCES = \ libswc/launch.c \ libswc/mode.c \ libswc/output.c \ + libswc/panel.c \ + libswc/panel_manager.c \ libswc/pointer.c \ libswc/region.c \ libswc/screen.c \ @@ -58,6 +60,7 @@ SWC_SOURCES = \ libswc/wayland_buffer.c \ libswc/window.c \ libswc/xkb.c \ + protocol/swc-protocol.c \ protocol/wayland-drm-protocol.c ifeq ($(ENABLE_HOTPLUGGING),1) @@ -85,6 +88,7 @@ SWC_SHARED_OBJECTS = $(SWC_SOURCES:%.c=%.lo) objects = $(foreach obj,$(1),$(dir)/$(obj).o $(dir)/$(obj).lo) $(call objects,drm drm_buffer): protocol/wayland-drm-server-protocol.h $(call objects,xserver): protocol/xserver-server-protocol.h +$(call objects,panel_manager panel): protocol/swc-server-protocol.h $(call objects,pointer): cursor/cursor_data.h $(dir)/libswc.a: $(SWC_STATIC_OBJECTS) diff --git a/libswc/panel.c b/libswc/panel.c @@ -0,0 +1,261 @@ +/* swc: libswc/panel.c + * + * Copyright (c) 2013, 2014 Michael Forney + * + * 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 "panel.h" +#include "compositor.h" +#include "internal.h" +#include "keyboard.h" +#include "output.h" +#include "screen.h" +#include "seat.h" +#include "surface.h" +#include "util.h" +#include "view.h" +#include "protocol/swc-server-protocol.h" + +#include <assert.h> +#include <stdlib.h> + +static void update_position(struct swc_panel * panel) +{ + int32_t x, y; + struct swc_rectangle * screen = &panel->screen->base.geometry, + * view = &panel->surface->view->geometry; + + switch (panel->edge) + { + case SWC_PANEL_EDGE_TOP: + x = screen->x + panel->offset; + y = screen->y; + break; + case SWC_PANEL_EDGE_BOTTOM: + x = screen->x + panel->offset; + y = screen->y + screen->height - view->height; + break; + case SWC_PANEL_EDGE_LEFT: + x = screen->x; + y = screen->y + screen->height - view->height - panel->offset; + break; + case SWC_PANEL_EDGE_RIGHT: + x = screen->x + screen->width - view->width; + y = screen->y + panel->offset; + break; + } + + swc_view_move(panel->surface->view, x, y); +} + +static void dock(struct wl_client * client, struct wl_resource * resource, + uint32_t edge, struct wl_resource * output_resource, + uint32_t focus) +{ + struct swc_panel * panel = wl_resource_get_user_data(resource); + struct swc_output * output = output_resource + ? wl_resource_get_user_data(output_resource) : NULL; + struct swc_screen_internal * screen = output + ? output->screen : CONTAINER_OF(swc.screens.next, + struct swc_screen_internal, link); + bool screen_changed = screen != panel->screen; + uint32_t length; + + if (panel->docked) + wl_list_remove(&panel->view_listener.link); + + if (panel->screen && screen_changed) + { + wl_list_remove(&panel->modifier.link); + swc_screen_update_usable_geometry(panel->screen); + } + + panel->screen = screen; + panel->edge = edge; + panel->docked = true; + + switch (edge) + { + case SWC_PANEL_EDGE_TOP: + case SWC_PANEL_EDGE_BOTTOM: + length = panel->screen->base.geometry.width; + break; + case SWC_PANEL_EDGE_LEFT: + case SWC_PANEL_EDGE_RIGHT: + length = panel->screen->base.geometry.height; + break; + } + + swc_compositor_add_surface(panel->surface); + update_position(panel); + swc_compositor_surface_show(panel->surface); + wl_signal_add(&panel->surface->view->event_signal, &panel->view_listener); + wl_list_insert(&screen->modifiers, &panel->modifier.link); + + if (focus) + swc_keyboard_set_focus(swc.seat->keyboard, panel->surface); + + swc_panel_send_docked(resource, length); +} + +static void set_offset(struct wl_client * client, struct wl_resource * resource, + uint32_t offset) +{ + struct swc_panel * panel = wl_resource_get_user_data(resource); + + panel->offset = offset; + + if (panel->docked) + update_position(panel); +} + +static void set_strut(struct wl_client * client, struct wl_resource * resource, + uint32_t size, uint32_t begin, uint32_t end) +{ + struct swc_panel * panel = wl_resource_get_user_data(resource); + + panel->strut_size = size; + + if (panel->docked) + swc_screen_update_usable_geometry(panel->screen); +} + +static const struct swc_panel_interface panel_implementation = { + .dock = &dock, + .set_offset = &set_offset, + .set_strut = &set_strut +}; + +static void modify(struct swc_screen_modifier * modifier, + const struct swc_rectangle * geometry, + pixman_region32_t * usable) +{ + struct swc_panel * panel = CONTAINER_OF(modifier, typeof(*panel), modifier); + pixman_box32_t box = { + .x1 = geometry->x, .y1 = geometry->y, + .x2 = geometry->x + geometry->width, + .y2 = geometry->y + geometry->height + }; + + assert(panel->docked); + + DEBUG("Original geometry { x1: %d, y1: %d, x2: %d, y2: %d }\n", + box.x1, box.y1, box.x2, box.y2); + + switch (panel->edge) + { + case SWC_PANEL_EDGE_TOP: + box.y1 = MAX(box.y1, geometry->y + panel->strut_size); + break; + case SWC_PANEL_EDGE_BOTTOM: + box.y2 = MIN(box.y2, geometry->y + geometry->height + - panel->strut_size); + break; + case SWC_PANEL_EDGE_LEFT: + box.x1 = MAX(box.x1, geometry->x + panel->strut_size); + break; + case SWC_PANEL_EDGE_RIGHT: + box.x2 = MIN(box.x2, geometry->x + geometry->width + - panel->strut_size); + break; + } + + DEBUG("Usable region { x1: %d, y1: %d, x2: %d, y2: %d }\n", + box.x1, box.y1, box.x2, box.y2); + + pixman_region32_reset(usable, &box); +} + +static void destroy_panel(struct wl_resource * resource) +{ + struct swc_panel * panel = wl_resource_get_user_data(resource); + + if (panel->docked) + { + wl_list_remove(&panel->view_listener.link); + wl_list_remove(&panel->modifier.link); + swc_screen_update_usable_geometry(panel->screen); + swc_compositor_remove_surface(panel->surface); + } + + free(panel); +} + +static void handle_view_event(struct wl_listener * listener, void * data) +{ + struct swc_panel * panel; + struct swc_event * event = data; + + panel = CONTAINER_OF(listener, typeof(*panel), view_listener); + + switch (event->type) + { + case SWC_VIEW_EVENT_RESIZED: + update_position(panel); + break; + } +} + +static void handle_surface_destroy(struct wl_listener * listener, void * data) +{ + struct swc_panel * panel; + + panel = CONTAINER_OF(listener, typeof(*panel), surface_destroy_listener); + wl_resource_destroy(panel->resource); +} + +struct swc_panel * swc_panel_new(struct wl_client * client, uint32_t id, + struct swc_surface * surface) +{ + struct swc_panel * panel; + + panel = malloc(sizeof *panel); + + if (!panel) + goto error0; + + panel->resource = wl_resource_create(client, &swc_panel_interface, 1, id); + + if (!panel->resource) + goto error1; + + wl_resource_set_implementation(panel->resource, &panel_implementation, + panel, &destroy_panel); + + panel->surface = surface; + panel->surface_destroy_listener.notify = &handle_surface_destroy; + panel->view_listener.notify = &handle_view_event; + panel->modifier.modify = &modify; + panel->screen = NULL; + panel->offset = 0; + panel->strut_size = 0; + panel->docked = false; + + wl_resource_add_destroy_listener(surface->resource, + &panel->surface_destroy_listener); + + return panel; + + error1: + free(panel); + error0: + return NULL; +} + diff --git a/libswc/panel.h b/libswc/panel.h @@ -0,0 +1,50 @@ +/* swc: libswc/panel.h + * + * Copyright (c) 2013, 2014 Michael Forney + * + * 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 SWC_PANEL_H +#define SWC_PANEL_H + +#include "screen.h" + +#include <stdbool.h> +#include <wayland-server.h> + +struct swc_panel +{ + struct wl_resource * resource; + + struct swc_surface * surface; + struct wl_listener surface_destroy_listener; + struct wl_listener view_listener; + struct swc_screen_internal * screen; + struct swc_screen_modifier modifier; + uint32_t edge; + uint32_t offset, strut_size; + bool docked; +}; + +struct swc_panel * swc_panel_new(struct wl_client * client, uint32_t id, + struct swc_surface * surface); + +#endif + diff --git a/libswc/panel_manager.c b/libswc/panel_manager.c @@ -0,0 +1,82 @@ +/* swc: libswc/panel_manager.c + * + * Copyright (c) 2013, 2014 Michael Forney + * + * 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 "panel_manager.h" +#include "internal.h" +#include "panel.h" + +#include <wayland-server.h> +#include "protocol/swc-server-protocol.h" + +static struct +{ + struct wl_global * global; + struct wl_resource * resource; +} panel_manager; + +static void create_panel(struct wl_client * client, + struct wl_resource * resource, uint32_t id, + struct wl_resource * surface_resource) +{ + struct swc_surface * surface = wl_resource_get_user_data(surface_resource); + struct swc_panel * panel; + + panel = swc_panel_new(client, id, surface); + + if (!panel) + wl_client_post_no_memory(client); +} + +static const struct swc_panel_manager_interface panel_manager_implementation = { + .create_panel = &create_panel +}; + +static void bind_panel_manager(struct wl_client * client, void * data, + uint32_t version, uint32_t id) +{ + struct wl_resource * resource; + + resource = wl_resource_create(client, &swc_panel_manager_interface, 1, id); + wl_resource_set_implementation(resource, &panel_manager_implementation, + NULL, NULL); +} + +bool swc_panel_manager_initialize() +{ + panel_manager.global = wl_global_create(swc.display, + &swc_panel_manager_interface, 1, + NULL, &bind_panel_manager); + + if (!panel_manager.global) + return false; + + return true; +} + +void swc_panel_manager_finalize() +{ + wl_global_destroy(panel_manager.global); +} + +// vim: fdm=syntax fo=croql et sw=4 sts=4 ts=8 + diff --git a/libswc/panel_manager.h b/libswc/panel_manager.h @@ -0,0 +1,33 @@ +/* swc: libswc/panel_manager.h + * + * Copyright (c) 2013 Michael Forney + * + * 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 SWC_PANEL_MANAGER_H +#define SWC_PANEL_MANAGER_H + +#include <stdbool.h> + +bool swc_panel_manager_initialize(); +void swc_panel_manager_finalize(); + +#endif + diff --git a/libswc/swc.c b/libswc/swc.c @@ -29,6 +29,7 @@ #include "internal.h" #include "launch.h" #include "keyboard.h" +#include "panel_manager.h" #include "pointer.h" #include "screen.h" #include "seat.h" @@ -147,11 +148,17 @@ bool swc_initialize(struct wl_display * display, goto error8; } + if (!swc_panel_manager_initialize()) + { + ERROR("Could not initialize panel manager\n"); + goto error9; + } + #ifdef ENABLE_XWAYLAND if (!swc_xserver_initialize()) { ERROR("Could not initialize xwayland\n"); - goto error9; + goto error10; } #endif @@ -159,6 +166,10 @@ bool swc_initialize(struct wl_display * display, return true; +#ifdef ENABLE_XWAYLAND + error10: + swc_panel_manager_finalize(); +#endif error9: swc_shell_finalize(); error8: @@ -187,6 +198,7 @@ void swc_finalize() #ifdef ENABLE_XWAYLAND swc_xserver_finalize(); #endif + swc_panel_manager_finalize(); swc_shell_finalize(); swc_seat_finalize(); swc_data_device_manager_finalize(); diff --git a/protocol/local.mk b/protocol/local.mk @@ -3,6 +3,7 @@ dir := protocol PROTOCOL_EXTENSIONS = \ + $(dir)/swc.xml \ $(dir)/wayland-drm.xml \ $(dir)/xserver.xml @@ -15,5 +16,8 @@ $(dir)/%-protocol.c: $(dir)/%.xml $(dir)/%-server-protocol.h: $(dir)/%.xml $(call quiet,GEN,$(WAYLAND_SCANNER)) server-header < $< > $@ +install-protocol: | $(DESTDIR)$(DATADIR)/swc + install -m0644 protocol/swc.xml "$(DESTDIR)$(DATADIR)/swc" + include common.mk diff --git a/protocol/swc.xml b/protocol/swc.xml @@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="UTF-8"?> +<protocol name="swc"> + <interface name="swc_panel_manager" version="1"> + <request name="create_panel"> + <arg name="id" type="new_id" interface="swc_panel" /> + <arg name="surface" type="object" interface="wl_surface" /> + </request> + </interface> + + <interface name="swc_panel" version="1"> + <enum name="edge"> + <entry name="top" value="0" /> + <entry name="bottom" value="1" /> + <entry name="left" value="2" /> + <entry name="right" value="3" /> + </enum> + + <request name="dock"> + <arg name="edge" type="uint" /> + <arg name="output" type="object" interface="wl_output" + allow-null="true" /> + <arg name="focus" type="uint" /> + </request> + + <request name="set_offset"> + <arg name="offset" type="uint" /> + </request> + + <request name="set_strut"> + <arg name="size" type="uint" /> + <arg name="begin" type="uint" /> + <arg name="end" type="uint" /> + </request> + + <event name="docked"> + <arg name="length" type="uint" /> + </event> + </interface> +</protocol> +