swc

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

panel.c (7063B)


      1 /* swc: libswc/panel.c
      2  *
      3  * Copyright (c) 2013, 2014 Michael Forney
      4  *
      5  * Permission is hereby granted, free of charge, to any person obtaining a copy
      6  * of this software and associated documentation files (the "Software"), to deal
      7  * in the Software without restriction, including without limitation the rights
      8  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      9  * copies of the Software, and to permit persons to whom the Software is
     10  * furnished to do so, subject to the following conditions:
     11  *
     12  * The above copyright notice and this permission notice shall be included in
     13  * all copies or substantial portions of the Software.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     18  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     21  * SOFTWARE.
     22  */
     23 
     24 #include "panel.h"
     25 #include "compositor.h"
     26 #include "internal.h"
     27 #include "keyboard.h"
     28 #include "output.h"
     29 #include "screen.h"
     30 #include "seat.h"
     31 #include "surface.h"
     32 #include "text_input.h"
     33 #include "util.h"
     34 #include "view.h"
     35 
     36 #include <assert.h>
     37 #include <stdlib.h>
     38 #include "swc-server-protocol.h"
     39 
     40 struct panel {
     41 	struct wl_resource *resource;
     42 
     43 	struct wl_listener surface_destroy_listener;
     44 	struct compositor_view *view;
     45 	struct view_handler view_handler;
     46 	struct screen *screen;
     47 	struct screen_modifier modifier;
     48 	uint32_t edge;
     49 	uint32_t offset, strut_size;
     50 	bool docked;
     51 };
     52 
     53 static void
     54 update_position(struct panel *panel)
     55 {
     56 	int32_t x, y;
     57 	struct swc_rectangle *screen = &panel->screen->base.geometry, *view = &panel->view->base.geometry;
     58 
     59 	switch (panel->edge) {
     60 	case SWC_PANEL_EDGE_TOP:
     61 		x = screen->x + panel->offset;
     62 		y = screen->y;
     63 		break;
     64 	case SWC_PANEL_EDGE_BOTTOM:
     65 		x = screen->x + panel->offset;
     66 		y = screen->y + screen->height - view->height;
     67 		break;
     68 	case SWC_PANEL_EDGE_LEFT:
     69 		x = screen->x;
     70 		y = screen->y + screen->height - view->height - panel->offset;
     71 		break;
     72 	case SWC_PANEL_EDGE_RIGHT:
     73 		x = screen->x + screen->width - view->width;
     74 		y = screen->y + panel->offset;
     75 		break;
     76 	default:
     77 		return;
     78 	}
     79 
     80 	view_move(&panel->view->base, x, y);
     81 }
     82 
     83 static void
     84 dock(struct wl_client *client, struct wl_resource *resource, uint32_t edge, struct wl_resource *screen_resource, uint32_t focus)
     85 {
     86 	struct panel *panel = wl_resource_get_user_data(resource);
     87 	struct text_input_manager *timanager = wl_global_get_user_data(swc.text_input_manager);
     88 	struct screen *screen;
     89 	uint32_t length;
     90 
     91 	if (screen_resource)
     92 		screen = wl_resource_get_user_data(screen_resource);
     93 	else
     94 		screen = wl_container_of(swc.screens.next, screen, link);
     95 
     96 	switch (edge) {
     97 	case SWC_PANEL_EDGE_TOP:
     98 	case SWC_PANEL_EDGE_BOTTOM:
     99 		length = screen->base.geometry.width;
    100 		break;
    101 	case SWC_PANEL_EDGE_LEFT:
    102 	case SWC_PANEL_EDGE_RIGHT:
    103 		length = screen->base.geometry.height;
    104 		break;
    105 	default:
    106 		return;
    107 	}
    108 
    109 	if (panel->screen && screen != panel->screen) {
    110 		wl_list_remove(&panel->modifier.link);
    111 		screen_update_usable_geometry(panel->screen);
    112 	}
    113 
    114 	panel->screen = screen;
    115 	panel->edge = edge;
    116 	panel->docked = true;
    117 
    118 	update_position(panel);
    119 	compositor_view_show(panel->view);
    120 	wl_list_insert(&screen->modifiers, &panel->modifier.link);
    121 
    122 	if (focus) {
    123 		keyboard_set_focus(swc.seat->keyboard, panel->view);
    124 		text_input_set_focus(timanager, panel->view);
    125 	}
    126 
    127 	swc_panel_send_docked(resource, length);
    128 }
    129 
    130 static void
    131 set_offset(struct wl_client *client, struct wl_resource *resource, uint32_t offset)
    132 {
    133 	struct panel *panel = wl_resource_get_user_data(resource);
    134 
    135 	panel->offset = offset;
    136 	if (panel->docked)
    137 		update_position(panel);
    138 }
    139 
    140 static void
    141 set_strut(struct wl_client *client, struct wl_resource *resource, uint32_t size, uint32_t begin, uint32_t end)
    142 {
    143 	struct panel *panel = wl_resource_get_user_data(resource);
    144 
    145 	panel->strut_size = size;
    146 	if (panel->docked)
    147 		screen_update_usable_geometry(panel->screen);
    148 }
    149 
    150 static const struct swc_panel_interface panel_impl = {
    151 	.dock = dock,
    152 	.set_offset = set_offset,
    153 	.set_strut = set_strut,
    154 };
    155 
    156 static void
    157 handle_resize(struct view_handler *handler, uint32_t old_width, uint32_t old_height)
    158 {
    159 	struct panel *panel = wl_container_of(handler, panel, view_handler);
    160 	update_position(panel);
    161 }
    162 
    163 static const struct view_handler_impl view_handler_impl = {
    164 	.resize = handle_resize,
    165 };
    166 
    167 static void
    168 modify(struct screen_modifier *modifier, const struct swc_rectangle *geom, pixman_region32_t *usable)
    169 {
    170 	struct panel *panel = wl_container_of(modifier, panel, modifier);
    171 	pixman_box32_t box = {
    172 		.x1 = geom->x,
    173 		.y1 = geom->y,
    174 		.x2 = geom->x + geom->width,
    175 		.y2 = geom->y + geom->height
    176 	};
    177 
    178 	assert(panel->docked);
    179 
    180 	DEBUG("Original geometry { x1: %d, y1: %d, x2: %d, y2: %d }\n",
    181 	      box.x1, box.y1, box.x2, box.y2);
    182 
    183 	switch (panel->edge) {
    184 	case SWC_PANEL_EDGE_TOP:
    185 		box.y1 = MAX(box.y1, geom->y + panel->strut_size);
    186 		break;
    187 	case SWC_PANEL_EDGE_BOTTOM:
    188 		box.y2 = MIN(box.y2, geom->y + geom->height - panel->strut_size);
    189 		break;
    190 	case SWC_PANEL_EDGE_LEFT:
    191 		box.x1 = MAX(box.x1, geom->x + panel->strut_size);
    192 		break;
    193 	case SWC_PANEL_EDGE_RIGHT:
    194 		box.x2 = MIN(box.x2, geom->x + geom->width - panel->strut_size);
    195 		break;
    196 	}
    197 
    198 	DEBUG("Usable region { x1: %d, y1: %d, x2: %d, y2: %d }\n",
    199 	      box.x1, box.y1, box.x2, box.y2);
    200 
    201 	pixman_region32_reset(usable, &box);
    202 }
    203 
    204 static void
    205 destroy_panel(struct wl_resource *resource)
    206 {
    207 	struct panel *panel = wl_resource_get_user_data(resource);
    208 
    209 	if (panel->docked) {
    210 		wl_list_remove(&panel->modifier.link);
    211 		screen_update_usable_geometry(panel->screen);
    212 	}
    213 
    214 	compositor_view_destroy(panel->view);
    215 	free(panel);
    216 }
    217 
    218 static void
    219 handle_surface_destroy(struct wl_listener *listener, void *data)
    220 {
    221 	struct panel *panel = wl_container_of(listener, panel, surface_destroy_listener);
    222 	wl_resource_destroy(panel->resource);
    223 }
    224 
    225 struct panel *
    226 panel_new(struct wl_client *client, uint32_t version, uint32_t id, struct surface *surface)
    227 {
    228 	struct panel *panel;
    229 
    230 	panel = malloc(sizeof(*panel));
    231 
    232 	if (!panel)
    233 		goto error0;
    234 
    235 	panel->resource = wl_resource_create(client, &swc_panel_interface, version, id);
    236 
    237 	if (!panel->resource)
    238 		goto error1;
    239 
    240 	if (!(panel->view = compositor_create_view(surface)))
    241 		goto error2;
    242 
    243 	wl_resource_set_implementation(panel->resource, &panel_impl, panel, &destroy_panel);
    244 	panel->surface_destroy_listener.notify = &handle_surface_destroy;
    245 	panel->view_handler.impl = &view_handler_impl;
    246 	panel->modifier.modify = &modify;
    247 	panel->screen = NULL;
    248 	panel->offset = 0;
    249 	panel->strut_size = 0;
    250 	panel->docked = false;
    251 	wl_list_insert(&panel->view->base.handlers, &panel->view_handler.link);
    252 	wl_resource_add_destroy_listener(surface->resource, &panel->surface_destroy_listener);
    253 
    254 	return panel;
    255 
    256 error2:
    257 	wl_resource_destroy(panel->resource);
    258 error1:
    259 	free(panel);
    260 error0:
    261 	return NULL;
    262 }