diff options
author | Kristian Høgsberg <krh@bitplanet.net> | 2011-02-14 22:17:41 -0500 |
---|---|---|
committer | Kristian Høgsberg <krh@bitplanet.net> | 2011-02-14 22:21:13 -0500 |
commit | fcfb4e30a47a4cd2416dac210521594b489c8bfd (patch) | |
tree | e940236740627c99898ad726246226977c9d7af8 | |
parent | 525e4c0beae832afc2c098c1368a19ad164e1b2b (diff) |
Split into a core repository that only holds the core Wayland libraries
61 files changed, 44 insertions, 13320 deletions
diff --git a/Makefile.am b/Makefile.am index 03d15db..ec2798a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,3 +1,6 @@ -SUBDIRS = wayland compositor clients data +SUBDIRS = wayland ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS} + +aclocaldir = $(datadir)/aclocal +aclocal_DATA = wayland-scanner.m4 wayland-scanner.mk
\ No newline at end of file diff --git a/clients/.gitignore b/clients/.gitignore deleted file mode 100644 index 8b3c40c..0000000 --- a/clients/.gitignore +++ /dev/null @@ -1,13 +0,0 @@ -dnd -eventdemo -flower -gears -image -resizor -screenshooter-client-protocol.h -screenshooter-protocol.c -screenshot -simple-client -smoke -terminal -view diff --git a/clients/Makefile.am b/clients/Makefile.am deleted file mode 100644 index 6c92a1c..0000000 --- a/clients/Makefile.am +++ /dev/null @@ -1,82 +0,0 @@ -noinst_PROGRAMS = \ - gears \ - flower \ - screenshot \ - terminal \ - image \ - $(poppler_programs) \ - dnd \ - smoke \ - resizor \ - simple-client \ - eventdemo - -noinst_LTLIBRARIES = libtoytoolkit.la - -AM_CFLAGS = $(GCC_CFLAGS) -AM_CPPFLAGS = \ - -DDATADIR='"$(datadir)"' \ - -I$(top_builddir)/wayland \ - -I$(top_srcdir)/wayland \ - $(CLIENT_CFLAGS) - -libtoytoolkit_la_SOURCES = \ - window.c \ - window.h \ - wayland-glib.c \ - wayland-glib.h \ - cairo-util.c \ - cairo-util.h - -toolkit_libs = \ - libtoytoolkit.la \ - $(top_builddir)/wayland/libwayland-client.la \ - $(CLIENT_LIBS) -lrt -lm -lwayland-egl - -gears_SOURCES = gears.c -gears_LDADD = $(toolkit_libs) - -flower_SOURCES = flower.c -flower_LDADD = $(toolkit_libs) - -screenshot_SOURCES = screenshot.c screenshooter-protocol.c -screenshot_LDADD = $(toolkit_libs) - -terminal_SOURCES = terminal.c -terminal_LDADD = $(toolkit_libs) -lutil - -image_SOURCES = image.c -image_LDADD = $(toolkit_libs) - -dnd_SOURCES = dnd.c -dnd_LDADD = $(toolkit_libs) - -smoke_SOURCES = smoke.c -smoke_LDADD = $(toolkit_libs) - -resizor_SOURCES = resizor.c -resizor_LDADD = $(toolkit_libs) - -simple_client_SOURCES = simple-client.c -simple_client_LDADD = \ - $(top_builddir)/wayland/libwayland-client.la -lm \ - $(GLES2_LIBS) \ - -lwayland-egl - -eventdemo_SOURCES = eventdemo.c -eventdemo_LDADD = $(toolkit_libs) - -BUILT_SOURCES = \ - screenshooter-client-protocol.h \ - screenshooter-protocol.c - -CLEANFILES = $(BUILT_SOURCES) - -include $(top_srcdir)/wayland/scanner.mk - -if HAVE_POPPLER -poppler_programs = view -view_SOURCES = view.c -view_LDADD = $(toolkit_libs) $(POPPLER_LIBS) -view_CPPFLAGS = $(AM_CPPFLAGS) $(POPPLER_CFLAGS) -endif diff --git a/clients/cairo-util.c b/clients/cairo-util.c deleted file mode 100644 index 5aa9857..0000000 --- a/clients/cairo-util.c +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Copyright © 2008 Kristian Høgsberg - * - * 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 <stdint.h> -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#include <math.h> -#include <cairo.h> -#include "cairo-util.h" - -#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0]) - -void -blur_surface(cairo_surface_t *surface, int margin) -{ - int32_t width, height, stride, x, y, z, w; - uint8_t *src, *dst; - uint32_t *s, *d, a, p; - int i, j, k, size, half; - uint32_t kernel[49]; - double f; - - size = ARRAY_LENGTH(kernel); - width = cairo_image_surface_get_width(surface); - height = cairo_image_surface_get_height(surface); - stride = cairo_image_surface_get_stride(surface); - src = cairo_image_surface_get_data(surface); - - dst = malloc(height * stride); - - half = size / 2; - a = 0; - for (i = 0; i < size; i++) { - f = (i - half); - kernel[i] = exp(- f * f / ARRAY_LENGTH(kernel)) * 10000; - a += kernel[i]; - } - - for (i = 0; i < height; i++) { - s = (uint32_t *) (src + i * stride); - d = (uint32_t *) (dst + i * stride); - for (j = 0; j < width; j++) { - if (margin < j && j < width - margin) { - d[j] = s[j]; - continue; - } - - x = 0; - y = 0; - z = 0; - w = 0; - for (k = 0; k < size; k++) { - if (j - half + k < 0 || j - half + k >= width) - continue; - p = s[j - half + k]; - - x += (p >> 24) * kernel[k]; - y += ((p >> 16) & 0xff) * kernel[k]; - z += ((p >> 8) & 0xff) * kernel[k]; - w += (p & 0xff) * kernel[k]; - } - d[j] = (x / a << 24) | (y / a << 16) | (z / a << 8) | w / a; - } - } - - for (i = 0; i < height; i++) { - s = (uint32_t *) (dst + i * stride); - d = (uint32_t *) (src + i * stride); - for (j = 0; j < width; j++) { - if (margin <= i && i < height - margin) { - d[j] = s[j]; - continue; - } - - x = 0; - y = 0; - z = 0; - w = 0; - for (k = 0; k < size; k++) { - if (i - half + k < 0 || i - half + k >= height) - continue; - s = (uint32_t *) (dst + (i - half + k) * stride); - p = s[j]; - - x += (p >> 24) * kernel[k]; - y += ((p >> 16) & 0xff) * kernel[k]; - z += ((p >> 8) & 0xff) * kernel[k]; - w += (p & 0xff) * kernel[k]; - } - d[j] = (x / a << 24) | (y / a << 16) | (z / a << 8) | w / a; - } - } - - free(dst); - cairo_surface_mark_dirty(surface); -} - -void -tile_mask(cairo_t *cr, cairo_surface_t *surface, - int x, int y, int width, int height, int margin, int top_margin) -{ - cairo_pattern_t *pattern; - cairo_matrix_t matrix; - int i, fx, fy, vmargin; - - cairo_set_operator(cr, CAIRO_OPERATOR_OVER); - pattern = cairo_pattern_create_for_surface (surface); - - for (i = 0; i < 4; i++) { - fx = i & 1; - fy = i >> 1; - - cairo_matrix_init_translate(&matrix, - -x + fx * (128 - width), - -y + fy * (128 - height)); - cairo_pattern_set_matrix(pattern, &matrix); - - if (fy) - vmargin = margin; - else - vmargin = top_margin; - - cairo_reset_clip(cr); - cairo_rectangle(cr, - x + fx * (width - margin), - y + fy * (height - vmargin), - margin, vmargin); - cairo_clip (cr); - cairo_mask(cr, pattern); - } - - /* Top strecth */ - cairo_matrix_init_translate(&matrix, 64, 0); - cairo_matrix_scale(&matrix, 64.0 / (width - 2 * margin), 1); - cairo_matrix_translate(&matrix, -x - width / 2, -y); - cairo_pattern_set_matrix(pattern, &matrix); - cairo_rectangle(cr, x + margin, y, width - 2 * margin, margin); - - cairo_reset_clip(cr); - cairo_rectangle(cr, - x + margin, - y, - width - 2 * margin, margin); - cairo_clip (cr); - cairo_mask(cr, pattern); - - /* Bottom strecth */ - cairo_matrix_translate(&matrix, 0, -height + 128); - cairo_pattern_set_matrix(pattern, &matrix); - - cairo_reset_clip(cr); - cairo_rectangle(cr, x + margin, y + height - margin, - width - 2 * margin, margin); - cairo_clip (cr); - cairo_mask(cr, pattern); - - /* Left strecth */ - cairo_matrix_init_translate(&matrix, 0, 64); - cairo_matrix_scale(&matrix, 1, 64.0 / (height - 2 * margin)); - cairo_matrix_translate(&matrix, -x, -y - height / 2); - cairo_pattern_set_matrix(pattern, &matrix); - cairo_reset_clip(cr); - cairo_rectangle(cr, x, y + margin, margin, height - 2 * margin); - cairo_clip (cr); - cairo_mask(cr, pattern); - - /* Right strecth */ - cairo_matrix_translate(&matrix, -width + 128, 0); - cairo_pattern_set_matrix(pattern, &matrix); - cairo_rectangle(cr, x + width - margin, y + margin, - margin, height - 2 * margin); - cairo_reset_clip(cr); - cairo_clip (cr); - cairo_mask(cr, pattern); - - cairo_pattern_destroy(pattern); - cairo_reset_clip(cr); -} - -void -tile_source(cairo_t *cr, cairo_surface_t *surface, - int x, int y, int width, int height, int margin, int top_margin) -{ - cairo_pattern_t *pattern; - cairo_matrix_t matrix; - int i, fx, fy, vmargin; - - cairo_set_operator(cr, CAIRO_OPERATOR_OVER); - pattern = cairo_pattern_create_for_surface (surface); - cairo_set_source(cr, pattern); - cairo_pattern_destroy(pattern); - - for (i = 0; i < 4; i++) { - fx = i & 1; - fy = i >> 1; - - cairo_matrix_init_translate(&matrix, - -x + fx * (128 - width), - -y + fy * (128 - height)); - cairo_pattern_set_matrix(pattern, &matrix); - - if (fy) - vmargin = margin; - else - vmargin = top_margin; - - cairo_rectangle(cr, - x + fx * (width - margin), - y + fy * (height - vmargin), - margin, vmargin); - cairo_fill(cr); - } - - /* Top strecth */ - cairo_matrix_init_translate(&matrix, 64, 0); - cairo_matrix_scale(&matrix, 64.0 / (width - 2 * margin), 1); - cairo_matrix_translate(&matrix, -x - width / 2, -y); - cairo_pattern_set_matrix(pattern, &matrix); - cairo_rectangle(cr, x + margin, y, width - 2 * margin, top_margin); - cairo_fill(cr); - - /* Bottom strecth */ - cairo_matrix_translate(&matrix, 0, -height + 128); - cairo_pattern_set_matrix(pattern, &matrix); - cairo_rectangle(cr, x + margin, y + height - margin, - width - 2 * margin, margin); - cairo_fill(cr); - - /* Left strecth */ - cairo_matrix_init_translate(&matrix, 0, 64); - cairo_matrix_scale(&matrix, 1, 64.0 / (height - margin - top_margin)); - cairo_matrix_translate(&matrix, -x, -y - height / 2); - cairo_pattern_set_matrix(pattern, &matrix); - cairo_rectangle(cr, x, y + top_margin, - margin, height - margin - top_margin); - cairo_fill(cr); - - /* Right strecth */ - cairo_matrix_translate(&matrix, -width + 128, 0); - cairo_pattern_set_matrix(pattern, &matrix); - cairo_rectangle(cr, x + width - margin, y + top_margin, - margin, height - margin - top_margin); - cairo_fill(cr); -} diff --git a/clients/cairo-util.h b/clients/cairo-util.h deleted file mode 100644 index f28ac5f..0000000 --- a/clients/cairo-util.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright © 2008 Kristian Høgsberg - * - * 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. - */ - -#ifndef _CAIRO_UTIL_H -#define _CAIRO_UTIL_H - -void -blur_surface(cairo_surface_t *surface, int margin); - -void -tile_mask(cairo_t *cr, cairo_surface_t *surface, - int x, int y, int width, int height, int margin, int top_margin); - -void -tile_source(cairo_t *cr, cairo_surface_t *surface, - int x, int y, int width, int height, int margin, int top_margin); - -#endif diff --git a/clients/dnd.c b/clients/dnd.c deleted file mode 100644 index 1625ffd..0000000 --- a/clients/dnd.c +++ /dev/null @@ -1,695 +0,0 @@ -/* - * Copyright © 2010 Kristian Høgsberg - * - * 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 <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <fcntl.h> -#include <unistd.h> -#include <math.h> -#include <sys/time.h> -#include <cairo.h> -#include <glib.h> -#include <gdk-pixbuf/gdk-pixbuf.h> - -#include "wayland-client.h" -#include "wayland-glib.h" - -#include "window.h" - -struct dnd { - struct window *window; - struct display *display; - uint32_t key; - struct item *items[16]; -}; - -struct dnd_drag { - cairo_surface_t *translucent; - cairo_surface_t *opaque; - int hotspot_x, hotspot_y; - struct dnd *dnd; - struct input *input; - uint32_t time; - struct item *item; - int x_offset, y_offset; - const char *mime_type; -}; - -struct dnd_offer { - int refcount; - struct dnd *dnd; - struct wl_array types; - const char *drag_type; - uint32_t tag; - int x, y; -}; - -struct item { - cairo_surface_t *surface; - int seed; - int x, y; -}; - -struct dnd_flower_message { - int seed, x_offset, y_offset; -}; - - -static const int item_width = 64; -static const int item_height = 64; -static const int item_padding = 16; - -static struct item * -item_create(struct display *display, int x, int y, int seed) -{ - struct item *item; - struct timeval tv; - - item = malloc(sizeof *item); - if (item == NULL) - return NULL; - - - gettimeofday(&tv, NULL); - item->seed = seed ? seed : tv.tv_usec; - srandom(item->seed); - - const int petal_count = 3 + random() % 5; - const double r1 = 20 + random() % 10; - const double r2 = 5 + random() % 12; - const double u = (10 + random() % 90) / 100.0; - const double v = (random() % 90) / 100.0; - - cairo_t *cr; - int i; - double t, dt = 2 * M_PI / (petal_count * 2); - double x1, y1, x2, y2, x3, y3; - struct rectangle rect; - - - rect.width = item_width; - rect.height = item_height; - item->surface = display_create_surface(display, &rect); - - item->x = x; - item->y = y; - - cr = cairo_create(item->surface); - cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); - cairo_set_source_rgba(cr, 0, 0, 0, 0); - cairo_paint(cr); - - cairo_set_operator(cr, CAIRO_OPERATOR_OVER); - cairo_translate(cr, item_width / 2, item_height / 2); - t = random(); - cairo_move_to(cr, cos(t) * r1, sin(t) * r1); - for (i = 0; i < petal_count; i++, t += dt * 2) { - x1 = cos(t) * r1; - y1 = sin(t) * r1; - x2 = cos(t + dt) * r2; - y2 = sin(t + dt) * r2; - x3 = cos(t + 2 * dt) * r1; - y3 = sin(t + 2 * dt) * r1; - - cairo_curve_to(cr, - x1 - y1 * u, y1 + x1 * u, - x2 + y2 * v, y2 - x2 * v, - x2, y2); - - cairo_curve_to(cr, - x2 - y2 * v, y2 + x2 * v, - x3 + y3 * u, y3 - x3 * u, - x3, y3); - } - - cairo_close_path(cr); - - cairo_set_source_rgba(cr, - 0.5 + (random() % 50) / 49.0, - 0.5 + (random() % 50) / 49.0, - 0.5 + (random() % 50) / 49.0, - 0.5 + (random() % 100) / 99.0); - - cairo_fill_preserve(cr); - - cairo_set_line_width(cr, 1); - cairo_set_source_rgba(cr, - 0.5 + (random() % 50) / 49.0, - 0.5 + (random() % 50) / 49.0, - 0.5 + (random() % 50) / 49.0, - 0.5 + (random() % 100) / 99.0); - cairo_stroke(cr); - - cairo_destroy(cr); - - return item; -} - -static void -dnd_draw(struct dnd *dnd) -{ - struct rectangle allocation; - cairo_t *cr; - cairo_surface_t *surface; - int i; - - window_draw(dnd->window); - - surface = window_get_surface(dnd->window); - cr = cairo_create(surface); - window_get_child_allocation(dnd->window, &allocation); - cairo_rectangle(cr, allocation.x, allocation.y, - allocation.width, allocation.height); - cairo_clip(cr); - cairo_push_group(cr); - - cairo_translate(cr, allocation.x, allocation.y); - cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); - cairo_set_source_rgba(cr, 0, 0, 0, 0.8); - cairo_paint(cr); - - cairo_set_operator(cr, CAIRO_OPERATOR_OVER); - for (i = 0; i < ARRAY_LENGTH(dnd->items); i++) { - if (!dnd->items[i]) - continue; - cairo_set_source_surface(cr, dnd->items[i]->surface, - dnd->items[i]->x, dnd->items[i]->y); - cairo_paint(cr); - } - - cairo_pop_group_to_source(cr); - cairo_paint(cr); - cairo_destroy(cr); - cairo_surface_destroy(surface); - window_flush(dnd->window); -} - -static void -redraw_handler(struct window *window, void *data) -{ - struct dnd *dnd = data; - - dnd_draw(dnd); -} - -static void -keyboard_focus_handler(struct window *window, - struct input *device, void *data) -{ - struct dnd *dnd = data; - - window_schedule_redraw(dnd->window); -} - -static void -dnd_offer_destroy(struct dnd_offer *dnd_offer) -{ - dnd_offer->refcount--; - if (dnd_offer->refcount == 0) { - wl_array_release(&dnd_offer->types); - free(dnd_offer); - } -} - -static int -dnd_add_item(struct dnd *dnd, struct item *item) -{ - int i; - - for (i = 0; i < ARRAY_LENGTH(dnd->items); i++) { - if (dnd->items[i] == 0) { - dnd->items[i] = item; - return i; - } - } - return -1; -} - -static struct item * -dnd_get_item(struct dnd *dnd, int32_t x, int32_t y) -{ - struct item *item; - struct rectangle allocation; - int i; - - window_get_child_allocation(dnd->window, &allocation); - - x -= allocation.x; - y -= allocation.y; - - for (i = 0; i < ARRAY_LENGTH(dnd->items); i++) { - item = dnd->items[i]; - if (item && - item->x <= x && x < item->x + item_width && - item->y <= y && y < item->y + item_height) - return item; - } - - return NULL; -} - -static void -drag_target(void *data, - struct wl_drag *drag, const char *mime_type) -{ - struct dnd_drag *dnd_drag = data; - struct dnd *dnd = dnd_drag->dnd; - struct wl_input_device *device; - cairo_surface_t *surface; - struct wl_buffer *buffer; - - fprintf(stderr, "target %s\n", mime_type); - device = input_get_input_device(dnd_drag->input); - dnd_drag->mime_type = mime_type; - if (mime_type) - surface = dnd_drag->opaque; - else - surface = dnd_drag->translucent; - - buffer = display_get_buffer_for_surface(dnd->display, surface); - wl_input_device_attach(device, dnd_drag->time, buffer, - dnd_drag->hotspot_x, dnd_drag->hotspot_y); -} - -static void -drag_finish(void *data, struct wl_drag *drag, int fd) -{ - struct dnd_drag *dnd_drag = data; - - if (!dnd_drag->mime_type) { - dnd_add_item(dnd_drag->dnd, dnd_drag->item); - window_schedule_redraw(dnd_drag->dnd->window); - return; - } - - struct dnd_flower_message dnd_flower_message; - - - dnd_flower_message.seed = dnd_drag->item->seed; - - dnd_flower_message.x_offset = dnd_drag->x_offset; - dnd_flower_message.y_offset = dnd_drag->y_offset; - - fprintf(stderr, "got 'finish', fd %d, sending dnd_flower_message\n", fd); - - write(fd, &dnd_flower_message, sizeof dnd_flower_message); - close(fd); - - /* The 'finish' event marks the end of the session on the drag - * source side and we need to clean up the drag object created - * and the local state. */ - wl_drag_destroy(drag); - - /* Destroy the item that has been dragged out */ - cairo_surface_destroy(dnd_drag->item->surface); - free(dnd_drag->item); - - cairo_surface_destroy(dnd_drag->translucent); - cairo_surface_destroy(dnd_drag->opaque); - free(dnd_drag); -} - -static void -drag_reject(void *data, struct wl_drag *drag) -{ - struct dnd_drag *dnd_drag = data; - - dnd_add_item(dnd_drag->dnd, dnd_drag->item); - window_schedule_redraw(dnd_drag->dnd->window); -} - -static const struct wl_drag_listener drag_listener = { - drag_target, - drag_finish, - drag_reject -}; - -static void -drag_offer_offer(void *data, - struct wl_drag_offer *offer, const char *type) -{ - struct dnd_offer *dnd_offer = data; - char **p; - - p = wl_array_add(&dnd_offer->types, sizeof *p); - if (p) - *p = strdup(type); -} - -static void -drag_offer_pointer_focus(void *data, - struct wl_drag_offer *offer, - uint32_t time, struct wl_surface *surface, - int32_t x, int32_t y, - int32_t surface_x, int32_t surface_y) -{ - struct dnd_offer *dnd_offer = data; - struct window *window; - char **p, **end; - - /* The last event in a dnd session is pointer_focus with a - * NULL surface, whether or not we get the drop event. We - * need to clean up the dnd_offer proxy and whatever state we - * allocated. */ - if (!surface) { - fprintf(stderr, "pointer focus NULL, session over\n"); - wl_drag_offer_destroy(offer); - dnd_offer_destroy(dnd_offer); - return; - } - - fprintf(stderr, "drag pointer focus %p\n", surface); - fprintf(stderr, "offered types:\n"); - end = dnd_offer->types.data + dnd_offer->types.size; - for (p = dnd_offer->types.data; p < end; p++) - fprintf(stderr, "\%s\n", *p); - - window = wl_surface_get_user_data(surface); - dnd_offer->dnd = window_get_user_data(window); - - if (!dnd_get_item(dnd_offer->dnd, surface_x, surface_y)) { - wl_drag_offer_accept(offer, time, "application/x-wayland-dnd-flower"); - dnd_offer->drag_type = "application/x-wayland-dnd-flower"; - dnd_offer->x = surface_x; - dnd_offer->y = surface_y; - } else { - wl_drag_offer_accept(offer, time, NULL); - dnd_offer->drag_type = NULL; - } -} - -static void -drag_offer_motion(void *data, - struct wl_drag_offer *offer, uint32_t time, - int32_t x, int32_t y, int32_t surface_x, int32_t surface_y) -{ - struct dnd_offer *dnd_offer = data; - - if (!dnd_get_item(dnd_offer->dnd, surface_x, surface_y)) { - fprintf(stderr, "drag offer motion %d, %d, accepting\n", - surface_x, surface_y); - wl_drag_offer_accept(offer, time, "application/x-wayland-dnd-flower"); - dnd_offer->drag_type = "application/x-wayland-dnd-flower"; - dnd_offer->x = surface_x; - dnd_offer->y = surface_y; - } else { - fprintf(stderr, "drag offer motion %d, %d, declining\n", - surface_x, surface_y); - wl_drag_offer_accept(offer, time, NULL); - dnd_offer->drag_type = NULL; - } -} - -static gboolean -drop_io_func(GIOChannel *source, GIOCondition condition, gpointer data) -{ - struct dnd_offer *dnd_offer = data; - struct dnd *dnd = dnd_offer->dnd; - struct dnd_flower_message dnd_flower_message; - int fd; - unsigned int len; - struct item *item; - - fd = g_io_channel_unix_get_fd(source); - len = read(fd, &dnd_flower_message, sizeof dnd_flower_message); - fprintf(stderr, "read %d bytes\n", len); - - close(fd); - g_source_remove(dnd_offer->tag); - - g_io_channel_unref(source); - - item = item_create(dnd->display, - dnd_offer->x - dnd_flower_message.x_offset - 26, - dnd_offer->y - dnd_flower_message.y_offset - 66, - dnd_flower_message.seed); - - dnd_add_item(dnd, item); - window_schedule_redraw(dnd->window); - - dnd_offer_destroy(dnd_offer); - - return TRUE; -} - -static void -drag_offer_drop(void *data, struct wl_drag_offer *offer) -{ - struct dnd_offer *dnd_offer = data; - GIOChannel *channel; - int p[2]; - - if (!dnd_offer->drag_type) { - fprintf(stderr, "got 'drop', but no target\n"); - wl_drag_offer_reject(offer); - return; - } - - fprintf(stderr, "got 'drop', sending write end of pipe\n"); - - dnd_offer->refcount++; - pipe(p); - wl_drag_offer_receive(offer, p[1]); - close(p[1]); - - channel = g_io_channel_unix_new(p[0]); - dnd_offer->tag = g_io_add_watch(channel, G_IO_IN, - drop_io_func, dnd_offer); -} - -static const struct wl_drag_offer_listener drag_offer_listener = { - drag_offer_offer, - drag_offer_pointer_focus, - drag_offer_motion, - drag_offer_drop, -}; - -static void -global_handler(struct display *display, - const char *interface, uint32_t id, uint32_t version) -{ - struct wl_drag_offer *offer; - struct dnd_offer *dnd_offer; - - if (strcmp(interface, "drag_offer") != 0) - return; - - offer = wl_drag_offer_create(display_get_display(display), id); - - dnd_offer = malloc(sizeof *dnd_offer); - if (dnd_offer == NULL) - return; - - dnd_offer->refcount = 1; - - wl_drag_offer_add_listener(offer, &drag_offer_listener, dnd_offer); - wl_array_init(&dnd_offer->types); -} - -static cairo_surface_t * -create_drag_cursor(struct dnd_drag *dnd_drag, - struct item *item, int32_t x, int32_t y, double opacity) -{ - struct dnd *dnd = dnd_drag->dnd; - cairo_surface_t *surface, *pointer; - int32_t pointer_width, pointer_height, hotspot_x, hotspot_y; - struct rectangle rectangle; - cairo_pattern_t *pattern; - cairo_t *cr; - - pointer = display_get_pointer_surface(dnd->display, - POINTER_DRAGGING, - &pointer_width, - &pointer_height, - &hotspot_x, - &hotspot_y); - - rectangle.width = item_width + 2 * pointer_width; - rectangle.height = item_height + 2 * pointer_height; - surface = display_create_surface(dnd->display, &rectangle); - - cr = cairo_create(surface); - cairo_translate(cr, pointer_width, pointer_height); - - cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); - cairo_set_source_rgba(cr, 0, 0, 0, 0); - cairo_paint(cr); - - cairo_set_operator(cr, CAIRO_OPERATOR_OVER); - cairo_set_source_surface(cr, item->surface, 0, 0); - pattern = cairo_pattern_create_rgba(0, 0, 0, opacity); - cairo_mask(cr, pattern); - cairo_pattern_destroy(pattern); - - cairo_set_source_surface(cr, pointer, - x - item->x - hotspot_x, - y - item->y - hotspot_y); - cairo_surface_destroy(pointer); - cairo_paint(cr); - /* FIXME: more cairo-gl brokeness */ - display_flush_cairo_device(dnd->display); - cairo_destroy(cr); - - dnd_drag->hotspot_x = pointer_width + x - item->x; - dnd_drag->hotspot_y = pointer_height + y - item->y; - - return surface; -} - -static void -dnd_button_handler(struct window *window, - struct input *input, uint32_t time, - int button, int state, void *data) -{ - struct dnd *dnd = data; - int32_t x, y; - struct item *item; - struct rectangle allocation; - struct dnd_drag *dnd_drag; - struct wl_drag *drag; - int i; - - window_get_child_allocation(dnd->window, &allocation); - input_get_position(input, &x, &y); - item = dnd_get_item(dnd, x, y); - x -= allocation.x; - y -= allocation.y; - - if (item && state == 1) { - fprintf(stderr, "start drag, item %p\n", item); - - dnd_drag = malloc(sizeof *dnd_drag); - dnd_drag->dnd = dnd; - dnd_drag->input = input; - dnd_drag->time = time; - dnd_drag->item = item; - dnd_drag->x_offset = x - item->x; - dnd_drag->y_offset = y - item->y; - - for (i = 0; i < ARRAY_LENGTH(dnd->items); i++) { - if (item == dnd->items[i]){ - dnd->items[i] = 0; - break; - } - } - - dnd_drag->opaque = - create_drag_cursor(dnd_drag, item, x, y, 1); - dnd_drag->translucent = - create_drag_cursor(dnd_drag, item, x, y, 0.2); - - drag = window_create_drag(window); - wl_drag_offer(drag, "application/x-wayland-dnd-flower"); - window_activate_drag(drag, window, input, time); - wl_drag_add_listener(drag, &drag_listener, dnd_drag); - window_schedule_redraw(dnd->window); - } -} - -static int -dnd_motion_handler(struct window *window, - struct input *input, uint32_t time, - int32_t x, int32_t y, - int32_t sx, int32_t sy, void *data) -{ - struct dnd *dnd = data; - struct item *item; - - item = dnd_get_item(dnd, sx, sy); - - if (item) - return POINTER_HAND1; - else - return POINTER_LEFT_PTR; -} - -static struct dnd * -dnd_create(struct display *display) -{ - struct dnd *dnd; - int i, x, y; - int32_t width, height; - - dnd = malloc(sizeof *dnd); - if (dnd == NULL) - return dnd; - memset(dnd, 0, sizeof *dnd); - - dnd->window = window_create(display, 400, 400); - window_set_title(dnd->window, "Wayland Drag and Drop Demo"); - - dnd->display = display; - dnd->key = 100; - - for (i = 0; i < ARRAY_LENGTH(dnd->items); i++) { - x = (i % 4) * (item_width + item_padding) + item_padding; - y = (i / 4) * (item_height + item_padding) + item_padding; - if ((i ^ (i >> 2)) & 1) - dnd->items[i] = item_create(display, x, y, 0); - else - dnd->items[i] = NULL; - } - - window_set_user_data(dnd->window, dnd); - window_set_redraw_handler(dnd->window, redraw_handler); - window_set_keyboard_focus_handler(dnd->window, - keyboard_focus_handler); - window_set_button_handler(dnd->window, - dnd_button_handler); - - window_set_motion_handler(dnd->window, - dnd_motion_handler); - - width = 4 * (item_width + item_padding) + item_padding; - height = 4 * (item_height + item_padding) + item_padding; - window_set_child_size(dnd->window, width, height); - - dnd_draw(dnd); - - return dnd; -} - -static const GOptionEntry option_entries[] = { - { NULL } -}; - -int -main(int argc, char *argv[]) -{ - struct display *d; - - d = display_create(&argc, &argv, option_entries); - if (d == NULL) { - fprintf(stderr, "failed to create display: %m\n"); - return -1; - } - - display_set_global_handler(d, global_handler); - - dnd_create(d); - - display_run(d); - - return 0; -} diff --git a/clients/eventdemo.c b/clients/eventdemo.c deleted file mode 100644 index 8de620a..0000000 --- a/clients/eventdemo.c +++ /dev/null @@ -1,396 +0,0 @@ -/* - * Copyright © 2011 Tim Wiederhake - * - * 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. - */ - -/** - * \file eventdemo.c - * \brief Demonstrate the use of Wayland's toytoolkit. - * - * Heavily commented demo program that can report all events that are - * dispatched to the window. For other functionality, eg. opengl/egl, - * drag and drop, etc. have a look at the other demos. - * \author Tim Wiederhake - */ - -#include <stdio.h> -#include <stdlib.h> - -#include <cairo.h> -#include <glib.h> - -#include "window.h" - -/** window title */ -static char *title = "EventDemo"; - -/** window width */ -static int width = 500; - -/** window height */ -static int height = 400; - -/** set if window has no borders */ -static int noborder = 0; - -/** if non-zero, maximum window width */ -static int width_max = 0; - -/** if non-zero, maximum window height */ -static int height_max = 0; - -/** set to log redrawing */ -static int log_redraw = 0; - -/** set to log resizing */ -static int log_resize = 0; - -/** set to log keyboard focus */ -static int log_focus = 0; - -/** set to log key events */ -static int log_key = 0; - -/** set to log button events */ -static int log_button = 0; - -/** set to log motion events */ -static int log_motion = 0; - -/** - * \struct eventdemo - * \brief Holds all data the program needs per window - * - * In this demo the struct holds the position of a - * red rectangle that is drawn in the window's area. - */ -struct eventdemo { - struct window *window; - struct display *display; - - unsigned int x, y, w, h; -}; - -/** - * \brief Redraws the window - * - * Draws a red rectangle as demonstration of per-window data. - */ -static void -eventdemo_draw(struct eventdemo *e) { - if (log_redraw) - printf("redraw\n"); - - cairo_surface_t *surface; - cairo_t *cr; - struct rectangle rect; - - window_draw(e->window); - window_get_child_allocation(e->window, &rect); - surface = window_get_surface(e->window); - - cr = cairo_create(surface); - cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); - - cairo_rectangle(cr, rect.x, rect.y, rect.width, rect.height); - cairo_set_source_rgba(cr, 0, 0, 0, 0.8); - cairo_fill(cr); - - cairo_rectangle(cr, e->x, e->y, e->w, e->h); - cairo_set_source_rgba(cr, 1.0, 0, 0, 1); - cairo_fill(cr); - - cairo_destroy(cr); - cairo_surface_destroy(surface); - window_flush(e->window); -} - -/** - * \brief CALLBACK function, Wayland requests the window to redraw. - * \param window window to be redrawn - * \param data user data associated to the window - */ -static void -redraw_handler(struct window *window, void *data) -{ - struct eventdemo *e = data; - eventdemo_draw(e); -} - -/** - * \brief CALLBACK function, Wayland requests the window to resize. - * \param window window to be resized - * \param width desired width - * \param height desired height - * \param data user data associated to the window - */ - -static void -resize_handler(struct window *window, - int32_t width, int32_t height, void *data) -{ - struct eventdemo *e = data; - if (log_resize) - printf("resize width: %d, height: %d\n", width, height); - - /* if a maximum width is set, constrain to it */ - if (width_max && width_max < width) - width = width_max; - - /* if a maximum height is set, constrain to it */ - if (height_max && height_max < height) - height = height_max; - - /* set the new window dimensions */ - window_set_child_size(e->window, width, height); - - /* inform Wayland that the window needs to be redrawn */ - window_schedule_redraw(e->window); -} - -/** - * \brief CALLBACK function, Wayland informs about keyboard focus change - * \param window window - * \param device device that caused the focus change - * \param data user data associated to the window - */ -static void -keyboard_focus_handler(struct window *window, - struct input *device, void *data) -{ - int32_t x, y; - struct eventdemo *e = data; - - if(log_focus) { - if(device) { - input_get_position(device, &x, &y); - printf("focus x: %d, y: %d\n", x, y); - } else { - printf("focus lost\n"); - } - } - - window_schedule_redraw(e->window); -} - -/** - * \brief CALLBACK function, Wayland informs about key event - * \param window window - * \param key keycode - * \param unicode associated character - * \param state pressed or released - * \param modifiers modifiers: ctrl, alt, meta etc. - * \param data user data associated to the window - */ -static void -key_handler(struct window *window, struct input *input, uint32_t time, - uint32_t key, uint32_t unicode, uint32_t state, void *data) -{ - uint32_t modifiers = input_get_modifiers(input); - - if(!log_key) - return; - - printf("key key: %d, unicode: %d, state: %d, modifiers: %d\n", - key, unicode, state, modifiers); -} - -/** - * \brief CALLBACK function, Wayland informs about button event - * \param window window - * \param input input device that caused the button event - * \param time time the event happend - * \param button button - * \param state pressed or released - * \param data user data associated to the window - */ -static void -button_handler(struct window *window, struct input *input, uint32_t time, - int button, int state, void *data) -{ - int32_t x, y; - - if (!log_button) - return; - - input_get_position(input, &x, &y); - printf("button time: %d, button: %d, state: %d, x: %d, y: %d\n", - time, button, state, x, y); -} - -/** - * \brief CALLBACK function, Waylands informs about pointer motion - * \param window window - * \param input input device that caused the motion event - * \param time time the event happend - * \param x absolute x position - * \param y absolute y position - * \param sx x position relative to the window - * \param sy y position relative to the window - * \param data user data associated to the window - * - * Demonstrates the use of different cursors - */ -static int -motion_handler(struct window *window, struct input *input, uint32_t time, - int32_t x, int32_t y, int32_t sx, int32_t sy, void *data) -{ - struct eventdemo *e = data; - - if (log_motion) { - printf("motion time: %d, x: %d, y: %d, sx: %d, sy: %d\n", - time, x, y, sx, sy); - } - - if(sx > e->x && sx < e->x + e->w) - if(sy > e->y && sy < e->y + e->h) - return POINTER_HAND1; - - return POINTER_LEFT_PTR; -} - -/** - * \brief Create and initialise a new eventdemo window. - * \param d associated display - */ -static struct eventdemo * -eventdemo_create(struct display *d) -{ - struct eventdemo *e; - - e = malloc(sizeof (struct eventdemo)); - if(e == NULL) - return NULL; - - /* Creates a new window with the given title, width and height. - * To set the size of the window for a given usable areas width - * and height in a window decoration agnostic way use: - * window_set_child_size(struct window *window, - * int32_t width, int32_t height); - */ - e->window = window_create(d, width, height); - window_set_title(e->window, title); - e->display = d; - - /* The eventdemo window draws a red rectangle as a demonstration - * of per-window data. The dimensions of that rectangle are set - * here. - */ - e->x = width * 1.0 / 4.0; - e->w = width * 2.0 / 4.0; - e->y = height * 1.0 / 4.0; - e->h = height * 2.0 / 4.0; - - /* Connect the user data to the window */ - window_set_user_data(e->window, e); - - /* Set the callback redraw handler for the window */ - window_set_redraw_handler(e->window, redraw_handler); - - /* Set the callback resize handler for the window */ - window_set_resize_handler(e->window, resize_handler); - - /* Set the callback focus handler for the window */ - window_set_keyboard_focus_handler(e->window, - keyboard_focus_handler); - - /* Set the callback key handler for the window */ - window_set_key_handler(e->window, key_handler); - - /* Set the callback button handler for the window */ - window_set_button_handler(e->window, button_handler); - - /* Set the callback motion handler for the window */ - window_set_motion_handler(e->window, motion_handler); - - /* Demonstrate how to create a borderless window. - Move windows with META + left mouse button. - */ - if(noborder) { - window_set_decoration(e->window, 0); - } - - /* Initial drawing of the window */ - eventdemo_draw(e); - - return e; -} -/** - * \brief command line options for eventdemo - * - * see - * http://developer.gimp.org/api/2.0/glib/glib-Commandline-option-parser.html - */ -static const GOptionEntry option_entries[] = { - {"title", 0, 0, G_OPTION_ARG_STRING, - &title, "Set the window title to TITLE", "TITLE"}, - {"width", 'w', 0, G_OPTION_ARG_INT, - &width, "Set the window's width to W", "W"}, - {"height", 'h', 0, G_OPTION_ARG_INT, - &height, "Set the window's height to H", "H"}, - {"maxwidth", 0, 0, G_OPTION_ARG_INT, - &width_max, "Set the window's maximum width to W", "W"}, - {"maxheight", 0, 0, G_OPTION_ARG_INT, - &height_max, "Set the window's maximum height to H", "H"}, - {"noborder", 'b', 0, G_OPTION_ARG_NONE, - &noborder, "Don't draw window borders", 0}, - {"log-redraw", 0, 0, G_OPTION_ARG_NONE, - &log_redraw, "Log redraw events to stdout", 0}, - {"log-resize", 0, 0, G_OPTION_ARG_NONE, - &log_resize, "Log resize events to stdout", 0}, - {"log-focus", 0, 0, G_OPTION_ARG_NONE, - &log_focus, "Log keyboard focus events to stdout", 0}, - {"log-key", 0, 0, G_OPTION_ARG_NONE, - &log_key, "Log key events to stdout", 0}, - {"log-button", 0, 0, G_OPTION_ARG_NONE, - &log_button, "Log button events to stdout", 0}, - {"log-motion", 0, 0, G_OPTION_ARG_NONE, - &log_motion, "Log motion events to stdout", 0}, - {NULL} -}; - -/** - * \brief Connects to the display, creates the window and hands over - * to the main loop. - */ -int -main(int argc, char *argv[]) -{ - struct display *d; - struct eventdemo *e; - - /* Connect to the display and have the arguments parsed */ - d = display_create(&argc, &argv, option_entries); - if (d == NULL) { - fprintf(stderr, "failed to create display: %m\n"); - return -1; - } - - /* Create new eventdemo window */ - e = eventdemo_create(d); - if (e == NULL) { - fprintf(stderr, "failed to create eventdemo: %m\n"); - return -1; - } - - display_run(d); - - return 0; -} diff --git a/clients/flower.c b/clients/flower.c deleted file mode 100644 index a87e20f..0000000 --- a/clients/flower.c +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright © 2008 Kristian Høgsberg - * - * 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 <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include <fcntl.h> -#include <unistd.h> -#include <math.h> -#include <time.h> -#include <cairo.h> -#include <sys/time.h> -#include <glib.h> - -#include "wayland-client.h" -#include "wayland-glib.h" -#include "window.h" - -static void -set_random_color(cairo_t *cr) -{ - cairo_set_source_rgba(cr, - 0.5 + (random() % 50) / 49.0, - 0.5 + (random() % 50) / 49.0, - 0.5 + (random() % 50) / 49.0, - 0.5 + (random() % 100) / 99.0); -} - - -static void -draw_stuff(cairo_surface_t *surface, int width, int height) -{ - const int petal_count = 3 + random() % 5; - const double r1 = 60 + random() % 35; - const double r2 = 20 + random() % 40; - const double u = (10 + random() % 90) / 100.0; - const double v = (random() % 90) / 100.0; - - cairo_t *cr; - int i; - double t, dt = 2 * M_PI / (petal_count * 2); - double x1, y1, x2, y2, x3, y3; - - cr = cairo_create(surface); - cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); - cairo_set_source_rgba(cr, 0, 0, 0, 0); - cairo_paint(cr); - - cairo_set_operator(cr, CAIRO_OPERATOR_OVER); - cairo_translate(cr, width / 2, height / 2); - cairo_move_to(cr, cos(0) * r1, sin(0) * r1); - for (t = 0, i = 0; i < petal_count; i++, t += dt * 2) { - x1 = cos(t) * r1; - y1 = sin(t) * r1; - x2 = cos(t + dt) * r2; - y2 = sin(t + dt) * r2; - x3 = cos(t + 2 * dt) * r1; - y3 = sin(t + 2 * dt) * r1; - - cairo_curve_to(cr, - x1 - y1 * u, y1 + x1 * u, - x2 + y2 * v, y2 - x2 * v, - x2, y2); - - cairo_curve_to(cr, - x2 - y2 * v, y2 + x2 * v, - x3 + y3 * u, y3 - x3 * u, - x3, y3); - } - - cairo_close_path(cr); - set_random_color(cr); - cairo_fill_preserve(cr); - set_random_color(cr); - cairo_stroke(cr); - - cairo_destroy(cr); -} - -static int -motion_handler(struct window *window, - struct input *input, uint32_t time, - int32_t x, int32_t y, - int32_t sx, int32_t sy, void *data) -{ - return POINTER_HAND1; -} - -static void -button_handler(struct window *window, - struct input *input, uint32_t time, - int button, int state, void *data) -{ - if (state) - window_move(window, input, time); -} - -struct flower { - struct display *display; - struct window *window; - int width, height; -}; - -int main(int argc, char *argv[]) -{ - cairo_surface_t *s; - struct flower flower; - struct display *d; - struct timeval tv; - - d = display_create(&argc, &argv, NULL); - if (d == NULL) { - fprintf(stderr, "failed to create display: %m\n"); - return -1; - } - - gettimeofday(&tv, NULL); - srandom(tv.tv_usec); - - flower.width = 200; - flower.height = 200; - flower.display = d; - flower.window = window_create(d, flower.width, flower.height); - - window_set_title(flower.window, "flower"); - window_set_decoration(flower.window, 0); - window_draw(flower.window); - s = window_get_surface(flower.window); - if (s == NULL || cairo_surface_status (s) != CAIRO_STATUS_SUCCESS) { - fprintf(stderr, "failed to create cairo egl surface\n"); - return -1; - } - - draw_stuff(s, flower.width, flower.height); - cairo_surface_flush(s); - cairo_surface_destroy(s); - window_flush(flower.window); - - window_set_motion_handler(flower.window, motion_handler); - window_set_button_handler(flower.window, button_handler); - window_set_user_data(flower.window, &flower); - display_run(d); - - return 0; -} diff --git a/clients/gears.c b/clients/gears.c deleted file mode 100644 index 8496abb..0000000 --- a/clients/gears.c +++ /dev/null @@ -1,433 +0,0 @@ -/* - * Copyright © 2008 Kristian Høgsberg - * - * 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 "config.h" - -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <fcntl.h> -#include <unistd.h> -#include <math.h> -#include <time.h> -#include <cairo.h> -#include <glib.h> - -#define GL_GLEXT_PROTOTYPES -#define EGL_EGLEXT_PROTOTYPES -#include <GL/gl.h> -#include <EGL/egl.h> -#include <EGL/eglext.h> - -#include "wayland-util.h" -#include "wayland-client.h" -#include "wayland-glib.h" - -#include "window.h" - -struct gears { - struct window *window; - - struct display *d; - - EGLDisplay display; - EGLContext context; - GLfloat angle; - cairo_surface_t *cairo_surface; - - GLint gear_list[3]; - GLuint fbo, color_rbo[2], depth_rbo; - cairo_surface_t *surface[2]; - int current; -}; - -struct gear_template { - GLfloat material[4]; - GLfloat inner_radius; - GLfloat outer_radius; - GLfloat width; - GLint teeth; - GLfloat tooth_depth; -}; - -const static struct gear_template gear_templates[] = { - { { 0.8, 0.1, 0.0, 1.0 }, 1.0, 4.0, 1.0, 20, 0.7 }, - { { 0.0, 0.8, 0.2, 1.0 }, 0.5, 2.0, 2.0, 10, 0.7 }, - { { 0.2, 0.2, 1.0, 1.0 }, 1.3, 2.0, 0.5, 10, 0.7 }, -}; - -static GLfloat light_pos[4] = {5.0, 5.0, 10.0, 0.0}; - -static void die(const char *msg) -{ - fprintf(stderr, "%s", msg); - exit(EXIT_FAILURE); -} - -static void -make_gear(const struct gear_template *t) -{ - GLint i; - GLfloat r0, r1, r2; - GLfloat angle, da; - GLfloat u, v, len; - - glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, t->material); - - r0 = t->inner_radius; - r1 = t->outer_radius - t->tooth_depth / 2.0; - r2 = t->outer_radius + t->tooth_depth / 2.0; - - da = 2.0 * M_PI / t->teeth / 4.0; - - glShadeModel(GL_FLAT); - - glNormal3f(0.0, 0.0, 1.0); - - /* draw front face */ - glBegin(GL_QUAD_STRIP); - for (i = 0; i <= t->teeth; i++) { - angle = i * 2.0 * M_PI / t->teeth; - glVertex3f(r0 * cos(angle), r0 * sin(angle), t->width * 0.5); - glVertex3f(r1 * cos(angle), r1 * sin(angle), t->width * 0.5); - if (i < t->teeth) { - glVertex3f(r0 * cos(angle), r0 * sin(angle), t->width * 0.5); - glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), t->width * 0.5); - } - } - glEnd(); - - /* draw front sides of teeth */ - glBegin(GL_QUADS); - da = 2.0 * M_PI / t->teeth / 4.0; - for (i = 0; i < t->teeth; i++) { - angle = i * 2.0 * M_PI / t->teeth; - - glVertex3f(r1 * cos(angle), r1 * sin(angle), t->width * 0.5); - glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), t->width * 0.5); - glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), t->width * 0.5); - glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), t->width * 0.5); - } - glEnd(); - - glNormal3f(0.0, 0.0, -1.0); - - /* draw back face */ - glBegin(GL_QUAD_STRIP); - for (i = 0; i <= t->teeth; i++) { - angle = i * 2.0 * M_PI / t->teeth; - glVertex3f(r1 * cos(angle), r1 * sin(angle), -t->width * 0.5); - glVertex3f(r0 * cos(angle), r0 * sin(angle), -t->width * 0.5); - if (i < t->teeth) { - glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -t->width * 0.5); - glVertex3f(r0 * cos(angle), r0 * sin(angle), -t->width * 0.5); - } - } - glEnd(); - - /* draw back sides of teeth */ - glBegin(GL_QUADS); - da = 2.0 * M_PI / t->teeth / 4.0; - for (i = 0; i < t->teeth; i++) { - angle = i * 2.0 * M_PI / t->teeth; - - glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -t->width * 0.5); - glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), -t->width * 0.5); - glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -t->width * 0.5); - glVertex3f(r1 * cos(angle), r1 * sin(angle), -t->width * 0.5); - } - glEnd(); - - /* draw outward faces of teeth */ - glBegin(GL_QUAD_STRIP); - for (i = 0; i < t->teeth; i++) { - angle = i * 2.0 * M_PI / t->teeth; - - glVertex3f(r1 * cos(angle), r1 * sin(angle), t->width * 0.5); - glVertex3f(r1 * cos(angle), r1 * sin(angle), -t->width * 0.5); - u = r2 * cos(angle + da) - r1 * cos(angle); - v = r2 * sin(angle + da) - r1 * sin(angle); - len = sqrt(u * u + v * v); - u /= len; - v /= len; - glNormal3f(v, -u, 0.0); - glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), t->width * 0.5); - glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -t->width * 0.5); - glNormal3f(cos(angle), sin(angle), 0.0); - glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), t->width * 0.5); - glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), -t->width * 0.5); - u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da); - v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da); - glNormal3f(v, -u, 0.0); - glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), t->width * 0.5); - glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -t->width * 0.5); - glNormal3f(cos(angle), sin(angle), 0.0); - } - - glVertex3f(r1 * cos(0), r1 * sin(0), t->width * 0.5); - glVertex3f(r1 * cos(0), r1 * sin(0), -t->width * 0.5); - - glEnd(); - - glShadeModel(GL_SMOOTH); - - /* draw inside radius cylinder */ - glBegin(GL_QUAD_STRIP); - for (i = 0; i <= t->teeth; i++) { - angle = i * 2.0 * M_PI / t->teeth; - glNormal3f(-cos(angle), -sin(angle), 0.0); - glVertex3f(r0 * cos(angle), r0 * sin(angle), -t->width * 0.5); - glVertex3f(r0 * cos(angle), r0 * sin(angle), t->width * 0.5); - } - glEnd(); -} - -static void -allocate_buffer(struct gears *gears) -{ - EGLImageKHR image; - struct rectangle allocation; - - window_draw(gears->window); - - gears->surface[gears->current] = window_get_surface(gears->window); -#ifdef HAVE_CAIRO_EGL - image = display_get_image_for_egl_image_surface(gears->display, - gears->surface[gears->current]); -#else /* XXX: hack to make Wayland compile, even if this example doesn't run */ - die("gears cannot allocate buffer: it was compiled without cairo-gl\n"); - return; -#endif - if (!eglMakeCurrent(gears->display, NULL, NULL, gears->context)) - die("faile to make context current\n"); - - glBindRenderbuffer(GL_RENDERBUFFER_EXT, - gears->color_rbo[gears->current]); - glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, image); - - glBindRenderbuffer(GL_RENDERBUFFER_EXT, gears->depth_rbo); - window_get_child_allocation(gears->window, &allocation); - glRenderbufferStorage(GL_RENDERBUFFER_EXT, - GL_DEPTH_COMPONENT, - allocation.width + 20 + 32, - allocation.height + 60 + 32); -} - -static void -draw_gears(struct gears *gears) -{ - GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0; - struct rectangle allocation; - - if (gears->surface[gears->current] == NULL) - allocate_buffer(gears); - - glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT, - GL_COLOR_ATTACHMENT0_EXT, - GL_RENDERBUFFER_EXT, - gears->color_rbo[gears->current]); - - window_get_child_allocation(gears->window, &allocation); - glViewport(allocation.x, allocation.y, - allocation.width, allocation.height); - glScissor(allocation.x, allocation.y, - allocation.width, allocation.height); - - glEnable(GL_SCISSOR_TEST); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glPushMatrix(); - - glTranslatef(0.0, 0.0, -50); - - glRotatef(view_rotx, 1.0, 0.0, 0.0); - glRotatef(view_roty, 0.0, 1.0, 0.0); - glRotatef(view_rotz, 0.0, 0.0, 1.0); - - glPushMatrix(); - glTranslatef(-3.0, -2.0, 0.0); - glRotatef(gears->angle, 0.0, 0.0, 1.0); - glCallList(gears->gear_list[0]); - glPopMatrix(); - - glPushMatrix(); - glTranslatef(3.1, -2.0, 0.0); - glRotatef(-2.0 * gears->angle - 9.0, 0.0, 0.0, 1.0); - glCallList(gears->gear_list[1]); - glPopMatrix(); - - glPushMatrix(); - glTranslatef(-3.1, 4.2, 0.0); - glRotatef(-2.0 * gears->angle - 25.0, 0.0, 0.0, 1.0); - glCallList(gears->gear_list[2]); - glPopMatrix(); - - glPopMatrix(); - - glFlush(); - - window_set_surface(gears->window, gears->surface[gears->current]); - window_flush(gears->window); -} - -static void -resize_handler(struct window *window, - int32_t width, int32_t height, void *data) -{ - struct gears *gears = data; - - cairo_surface_destroy(gears->surface[0]); - gears->surface[0] = NULL; - cairo_surface_destroy(gears->surface[1]); - gears->surface[1] = NULL; - - /* Constrain child size to be square and at least 300x300 */ - if (width > height) - height = width; - else - width = height; - if (width < 300) { - width = 300; - height = 300; - } - - window_set_child_size(gears->window, width, height); -} - -static void -keyboard_focus_handler(struct window *window, - struct input *device, void *data) -{ - struct gears *gears = data; - struct rectangle allocation; - - window_get_child_allocation(gears->window, &allocation); - resize_handler(window, allocation.width, allocation.height, gears); -} - -static void -redraw_handler(struct window *window, void *data) -{ - struct gears *gears = data; - - draw_gears(gears); -} - -static void -frame_callback(void *data, uint32_t time) -{ - struct gears *gears = data; - - gears->current = 1 - gears->current; - - gears->angle = (GLfloat) (time % 8192) * 360 / 8192.0; - - window_schedule_redraw(gears->window); - wl_display_frame_callback(display_get_display(gears->d), - frame_callback, gears); -} - -static struct gears * -gears_create(struct display *display) -{ - const int width = 450, height = 500; - struct gears *gears; - int i; - - gears = malloc(sizeof *gears); - memset(gears, 0, sizeof *gears); - gears->d = display; - gears->window = window_create(display, width, height); - window_set_title(gears->window, "Wayland Gears"); - - gears->display = display_get_egl_display(gears->d); - if (gears->display == NULL) - die("failed to create egl display\n"); - - eglBindAPI(EGL_OPENGL_API); - - gears->context = eglCreateContext(gears->display, - NULL, EGL_NO_CONTEXT, NULL); - if (gears->context == NULL) - die("failed to create context\n"); - - if (!eglMakeCurrent(gears->display, NULL, NULL, gears->context)) - die("faile to make context current\n"); - - glGenFramebuffers(1, &gears->fbo); - glBindFramebuffer(GL_FRAMEBUFFER_EXT, gears->fbo); - - glGenRenderbuffers(2, gears->color_rbo); - glGenRenderbuffers(1, &gears->depth_rbo); - glBindRenderbuffer(GL_RENDERBUFFER_EXT, gears->depth_rbo); - glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT, - GL_DEPTH_ATTACHMENT_EXT, - GL_RENDERBUFFER_EXT, - gears->depth_rbo); - for (i = 0; i < 3; i++) { - gears->gear_list[i] = glGenLists(1); - glNewList(gears->gear_list[i], GL_COMPILE); - make_gear(&gear_templates[i]); - glEndList(); - } - - glEnable(GL_NORMALIZE); - - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 200.0); - glMatrixMode(GL_MODELVIEW); - - glLightfv(GL_LIGHT0, GL_POSITION, light_pos); - glEnable(GL_CULL_FACE); - glEnable(GL_LIGHTING); - glEnable(GL_LIGHT0); - glEnable(GL_DEPTH_TEST); - glClearColor(0, 0, 0, 0.92); - - window_set_user_data(gears->window, gears); - window_set_resize_handler(gears->window, resize_handler); - window_set_keyboard_focus_handler(gears->window, keyboard_focus_handler); - window_set_redraw_handler(gears->window, redraw_handler); - - draw_gears(gears); - wl_display_frame_callback(display_get_display(gears->d), - frame_callback, gears); - - return gears; -} - -int main(int argc, char *argv[]) -{ - struct display *d; - - d = display_create(&argc, &argv, NULL); - if (d == NULL) { - fprintf(stderr, "failed to create display: %m\n"); - return -1; - } - gears_create(d); - display_run(d); - - return 0; -} diff --git a/clients/image.c b/clients/image.c deleted file mode 100644 index 3eada1e..0000000 --- a/clients/image.c +++ /dev/null @@ -1,259 +0,0 @@ -/* - * Copyright © 2008 Kristian Høgsberg - * Copyright © 2009 Chris Wilson - * - * 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 <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <fcntl.h> -#include <unistd.h> -#include <math.h> -#include <time.h> -#include <cairo.h> -#include <glib.h> -#include <gdk-pixbuf/gdk-pixbuf.h> - -#include "wayland-client.h" -#include "wayland-glib.h" - -#include "window.h" - -struct image { - struct window *window; - struct display *display; - uint32_t key; - gchar *filename; -}; - -static void -set_source_pixbuf(cairo_t *cr, - const GdkPixbuf *pixbuf, - double src_x, - double src_y, - double src_width, - double src_height) -{ - gint width = gdk_pixbuf_get_width (pixbuf); - gint height = gdk_pixbuf_get_height (pixbuf); - guchar *gdk_pixels = gdk_pixbuf_get_pixels (pixbuf); - int gdk_rowstride = gdk_pixbuf_get_rowstride (pixbuf); - int n_channels = gdk_pixbuf_get_n_channels (pixbuf); - int cairo_stride; - guchar *cairo_pixels; - cairo_format_t format; - cairo_surface_t *surface; - int j; - - if (n_channels == 3) - format = CAIRO_FORMAT_RGB24; - else - format = CAIRO_FORMAT_ARGB32; - - surface = cairo_image_surface_create(format, width, height); - if (cairo_surface_status(surface)) { - cairo_set_source_surface(cr, surface, 0, 0); - return; - } - - cairo_stride = cairo_image_surface_get_stride(surface); - cairo_pixels = cairo_image_surface_get_data(surface); - - for (j = height; j; j--) { - guchar *p = gdk_pixels; - guchar *q = cairo_pixels; - - if (n_channels == 3) { - guchar *end = p + 3 * width; - - while (p < end) { -#if G_BYTE_ORDER == G_LITTLE_ENDIAN - q[0] = p[2]; - q[1] = p[1]; - q[2] = p[0]; -#else - q[1] = p[0]; - q[2] = p[1]; - q[3] = p[2]; -#endif - p += 3; - q += 4; - } - } else { - guchar *end = p + 4 * width; - guint t1,t2,t3; - -#define MULT(d,c,a,t) G_STMT_START { t = c * a + 0x7f; d = ((t >> 8) + t) >> 8; } G_STMT_END - - while (p < end) { -#if G_BYTE_ORDER == G_LITTLE_ENDIAN - MULT(q[0], p[2], p[3], t1); - MULT(q[1], p[1], p[3], t2); - MULT(q[2], p[0], p[3], t3); - q[3] = p[3]; -#else - q[0] = p[3]; - MULT(q[1], p[0], p[3], t1); - MULT(q[2], p[1], p[3], t2); - MULT(q[3], p[2], p[3], t3); -#endif - - p += 4; - q += 4; - } -#undef MULT - } - - gdk_pixels += gdk_rowstride; - cairo_pixels += cairo_stride; - } - cairo_surface_mark_dirty(surface); - - cairo_set_source_surface(cr, surface, - src_x + .5 * (src_width - width), - src_y + .5 * (src_height - height)); - cairo_surface_destroy(surface); -} - -static void -image_draw(struct image *image) -{ - struct rectangle allocation; - GdkPixbuf *pb; - cairo_t *cr; - cairo_surface_t *surface; - - window_draw(image->window); - - window_get_child_allocation(image->window, &allocation); - - pb = gdk_pixbuf_new_from_file_at_size(image->filename, - allocation.width, - allocation.height, - NULL); - if (pb == NULL) - return; - - surface = window_get_surface(image->window); - cr = cairo_create(surface); - window_get_child_allocation(image->window, &allocation); - cairo_rectangle(cr, allocation.x, allocation.y, - allocation.width, allocation.height); - cairo_clip(cr); - cairo_push_group(cr); - cairo_translate(cr, allocation.x, allocation.y); - - cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); - cairo_set_source_rgba(cr, 0, 0, 0, 1); - cairo_paint(cr); - set_source_pixbuf(cr, pb, - 0, 0, - allocation.width, allocation.height); - cairo_set_operator(cr, CAIRO_OPERATOR_OVER); - cairo_paint(cr); - - g_object_unref(pb); - - cairo_pop_group_to_source(cr); - cairo_paint(cr); - cairo_destroy(cr); - - window_flush(image->window); - cairo_surface_destroy(surface); -} - -static void -redraw_handler(struct window *window, void *data) -{ - struct image *image = data; - - image_draw(image); -} - -static void -keyboard_focus_handler(struct window *window, - struct input *device, void *data) -{ - struct image *image = data; - - window_schedule_redraw(image->window); -} - -static struct image * -image_create(struct display *display, uint32_t key, const char *filename) -{ - struct image *image; - gchar *basename; - gchar *title; - - image = malloc(sizeof *image); - if (image == NULL) - return image; - memset(image, 0, sizeof *image); - - basename = g_path_get_basename(filename); - title = g_strdup_printf("Wayland Image - %s", basename); - g_free(basename); - - image->filename = g_strdup(filename); - - image->window = window_create(display, 500, 400); - window_set_title(image->window, title); - image->display = display; - - /* FIXME: Window uses key 1 for moves, need some kind of - * allocation scheme here. Or maybe just a real toolkit. */ - image->key = key + 100; - - window_set_user_data(image->window, image); - window_set_redraw_handler(image->window, redraw_handler); - window_set_keyboard_focus_handler(image->window, - keyboard_focus_handler); - - image_draw(image); - - return image; -} - -static const GOptionEntry option_entries[] = { - { NULL } -}; - -int -main(int argc, char *argv[]) -{ - struct display *d; - int i; - - d = display_create(&argc, &argv, option_entries); - if (d == NULL) { - fprintf(stderr, "failed to create display: %m\n"); - return -1; - } - - for (i = 1; i < argc; i++) - image_create (d, i, argv[i]); - - display_run(d); - - return 0; -} diff --git a/clients/resizor.c b/clients/resizor.c deleted file mode 100644 index 0ac02f6..0000000 --- a/clients/resizor.c +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright © 2010 Intel Corporation - * - * 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 <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <cairo.h> -#include <math.h> - -#include "wayland-util.h" -#include "wayland-client.h" -#include "wayland-glib.h" - -#include "window.h" - -#include <X11/keysym.h> - -struct resizor { - struct display *display; - struct window *window; - struct window *menu; - int32_t width; - - struct { - double current; - double target; - double previous; - } height; -}; - -static void -frame_callback(void *data, uint32_t time) -{ - struct resizor *resizor = data; - double force, height; - - height = resizor->height.current; - force = (resizor->height.target - height) / 10.0 + - (resizor->height.previous - height); - - resizor->height.current = - height + (height - resizor->height.previous) + force; - resizor->height.previous = height; - - if (resizor->height.current >= 400) { - resizor->height.current = 400; - resizor->height.previous = 400; - } - - if (resizor->height.current <= 200) { - resizor->height.current = 200; - resizor->height.previous = 200; - } - - window_set_child_size(resizor->window, resizor->width, height + 0.5); - - window_schedule_redraw(resizor->window); -} - -static void -resizor_draw(struct resizor *resizor) -{ - cairo_surface_t *surface; - cairo_t *cr; - struct rectangle allocation; - - window_draw(resizor->window); - - window_get_child_allocation(resizor->window, &allocation); - - surface = window_get_surface(resizor->window); - - cr = cairo_create(surface); - cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); - cairo_rectangle(cr, - allocation.x, - allocation.y, - allocation.width, - allocation.height); - cairo_set_source_rgba(cr, 0, 0, 0, 0.8); - cairo_fill(cr); - cairo_destroy(cr); - - cairo_surface_destroy(surface); - - window_flush(resizor->window); - - if (fabs(resizor->height.previous - resizor->height.target) > 0.1) { - wl_display_frame_callback(display_get_display(resizor->display), - frame_callback, resizor); - } -} - -static void -redraw_handler(struct window *window, void *data) -{ - struct resizor *resizor = data; - - resizor_draw(resizor); -} - -static void -keyboard_focus_handler(struct window *window, - struct input *device, void *data) -{ - struct resizor *resizor = data; - - window_schedule_redraw(resizor->window); -} - -static void -key_handler(struct window *window, struct input *input, uint32_t time, - uint32_t key, uint32_t sym, uint32_t state, void *data) -{ - struct resizor *resizor = data; - - if (state == 0) - return; - - switch (sym) { - case XK_Down: - resizor->height.target = 400; - frame_callback(resizor, 0); - break; - case XK_Up: - resizor->height.target = 200; - frame_callback(resizor, 0); - break; - } -} - -static void -show_menu(struct resizor *resizor, struct input *input) -{ - int32_t x, y, width = 200, height = 200; - - input_get_position(input, &x, &y); - resizor->menu = window_create_transient(resizor->display, - resizor->window, - x - 10, y - 10, width, height); - - window_draw(resizor->menu); - window_flush(resizor->menu); -} - -static void -button_handler(struct window *window, - struct input *input, uint32_t time, - int button, int state, void *data) -{ - struct resizor *resizor = data; - - switch (button) { - case 274: - if (state) - show_menu(resizor, input); - else - window_destroy(resizor->menu); - break; - } -} - -static struct resizor * -resizor_create(struct display *display) -{ - struct resizor *resizor; - int32_t height; - - resizor = malloc(sizeof *resizor); - if (resizor == NULL) - return resizor; - memset(resizor, 0, sizeof *resizor); - - resizor->window = window_create(display, 500, 400); - window_set_title(resizor->window, "Wayland Resizor"); - resizor->display = display; - - window_set_key_handler(resizor->window, key_handler); - window_set_user_data(resizor->window, resizor); - window_set_redraw_handler(resizor->window, redraw_handler); - window_set_keyboard_focus_handler(resizor->window, - keyboard_focus_handler); - - resizor->width = 300; - resizor->height.current = 400; - resizor->height.previous = resizor->height.current; - resizor->height.target = resizor->height.current; - height = resizor->height.current + 0.5; - - window_set_child_size(resizor->window, resizor->width, height); - window_set_button_handler(resizor->window, button_handler); - - resizor_draw(resizor); - - return resizor; -} - -int -main(int argc, char *argv[]) -{ - struct display *d; - - d = display_create(&argc, &argv, NULL); - if (d == NULL) { - fprintf(stderr, "failed to create display: %m\n"); - return -1; - } - - resizor_create (d); - - display_run(d); - - return 0; -} diff --git a/clients/screenshot.c b/clients/screenshot.c deleted file mode 100644 index 8f44460..0000000 --- a/clients/screenshot.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright © 2008 Kristian Høgsberg - * - * 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 <stdint.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <fcntl.h> -#include <glib.h> - -#include "wayland-client.h" -#include "wayland-glib.h" -#include "screenshooter-client-protocol.h" - -/* The screenshooter is a good example of a custom object exposed by - * the compositor and serves as a test bed for implementing client - * side marshalling outside libwayland.so */ - -static void -handle_global(struct wl_display *display, uint32_t id, - const char *interface, uint32_t version, void *data) -{ - struct wl_screenshooter **screenshooter = data; - - if (strcmp(interface, "screenshooter") == 0) - *screenshooter = wl_screenshooter_create(display, id); -} - -int main(int argc, char *argv[]) -{ - struct wl_display *display; - GMainLoop *loop; - GSource *source; - struct wl_screenshooter *screenshooter; - - display = wl_display_connect(NULL); - if (display == NULL) { - fprintf(stderr, "failed to create display: %m\n"); - return -1; - } - - screenshooter = NULL; - wl_display_add_global_listener(display, handle_global, &screenshooter); - wl_display_iterate(display, WL_DISPLAY_READABLE); - if (screenshooter == NULL) { - fprintf(stderr, "display doesn't support screenshooter\n"); - return -1; - } - - loop = g_main_loop_new(NULL, FALSE); - source = wl_glib_source_new(display); - g_source_attach(source, NULL); - - wl_screenshooter_shoot(screenshooter); - - g_idle_add((GSourceFunc) g_main_loop_quit, loop); - g_main_loop_run(loop); - - return 0; -} diff --git a/clients/simple-client.c b/clients/simple-client.c deleted file mode 100644 index 89718df..0000000 --- a/clients/simple-client.c +++ /dev/null @@ -1,325 +0,0 @@ -/* - * Copyright © 2011 Benjamin Franzke - * - * 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 <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <stdbool.h> -#include <math.h> -#include <assert.h> - -#include <wayland-client.h> -#include <wayland-egl.h> - -#include <GLES2/gl2.h> -#include <EGL/egl.h> - -struct display { - struct wl_display *display; - struct wl_egl_display *native; - struct wl_compositor *compositor; - struct { - EGLDisplay dpy; - EGLContext ctx; - EGLConfig conf; - } egl; - uint32_t mask; -}; - -struct window { - struct display *display; - struct { - int width, height; - } geometry; - struct { - GLuint fbo; - GLuint color_rbo; - - GLuint program; - GLuint rotation_uniform; - - GLuint pos; - GLuint col; - } gl; - - struct wl_egl_window *native; - struct wl_surface *surface; - EGLSurface egl_surface; -}; - -static const char *vert_shader_text = - "uniform mat4 rotation;\n" - "attribute vec4 pos;\n" - "attribute vec4 color;\n" - "varying vec4 v_color;\n" - "void main() {\n" - " gl_Position = rotation * pos;\n" - " v_color = color;\n" - "}\n"; - -static const char *frag_shader_text = - "precision mediump float;\n" - "varying vec4 v_color;\n" - "void main() {\n" - " gl_FragColor = v_color;\n" - "}\n"; - -static void -init_egl(struct display *display) -{ - static const EGLint context_attribs[] = { - EGL_CONTEXT_CLIENT_VERSION, 2, - EGL_NONE - }; - - static const EGLint config_attribs[] = { - EGL_SURFACE_TYPE, EGL_WINDOW_BIT, - EGL_RED_SIZE, 1, - EGL_GREEN_SIZE, 1, - EGL_BLUE_SIZE, 1, - EGL_DEPTH_SIZE, 1, - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, - EGL_NONE - }; - - EGLint major, minor, n; - EGLBoolean ret; - - display->egl.dpy = - eglGetDisplay(display->native); - assert(display->egl.dpy); - - ret = eglInitialize(display->egl.dpy, &major, &minor); - assert(ret == EGL_TRUE); - ret = eglBindAPI(EGL_OPENGL_ES_API); - assert(ret == EGL_TRUE); - - assert(eglChooseConfig(display->egl.dpy, config_attribs, - &display->egl.conf, 1, &n) && n == 1); - - display->egl.ctx = eglCreateContext(display->egl.dpy, - display->egl.conf, - EGL_NO_CONTEXT, context_attribs); - assert(display->egl.ctx); - -} - -static GLuint -create_shader(struct window *window, const char *source, GLenum shader_type) -{ - GLuint shader; - GLint status; - - shader = glCreateShader(shader_type); - assert(shader != 0); - - glShaderSource(shader, 1, (const char **) &source, NULL); - glCompileShader(shader); - - glGetShaderiv(shader, GL_COMPILE_STATUS, &status); - if (!status) { - char log[1000]; - GLsizei len; - glGetShaderInfoLog(shader, 1000, &len, log); - fprintf(stderr, "Error: compiling %s: %*s\n", - shader_type == GL_VERTEX_SHADER ? "vertex" : "fragment", - len, log); - exit(1); - } - - return shader; -} - -static void -init_gl(struct window *window) -{ - GLuint frag, vert; - GLint status; - - glViewport(0, 0, window->geometry.width, window->geometry.height); - - frag = create_shader(window, frag_shader_text, GL_FRAGMENT_SHADER); - vert = create_shader(window, vert_shader_text, GL_VERTEX_SHADER); - - window->gl.program = glCreateProgram(); - glAttachShader(window->gl.program, frag); - glAttachShader(window->gl.program, vert); - glLinkProgram(window->gl.program); - - glGetProgramiv(window->gl.program, GL_LINK_STATUS, &status); - if (!status) { - char log[1000]; - GLsizei len; - glGetProgramInfoLog(window->gl.program, 1000, &len, log); - fprintf(stderr, "Error: linking:\n%*s\n", len, log); - exit(1); - } - - glUseProgram(window->gl.program); - - window->gl.pos = 0; - window->gl.pos = 1; - - glBindAttribLocation(window->gl.program, window->gl.pos, "pos"); - glBindAttribLocation(window->gl.program, window->gl.col, "color"); - glLinkProgram(window->gl.program); - - window->gl.rotation_uniform = - glGetUniformLocation(window->gl.program, "rotation"); -} - -static void -create_surface(struct window *window) -{ - struct display *display = window->display; - struct wl_visual *visual; - EGLBoolean ret; - - window->surface = wl_compositor_create_surface(display->compositor); - visual = wl_display_get_premultiplied_argb_visual(display->display); - window->native = - wl_egl_window_create(display->native, - window->surface, - window->geometry.width, - window->geometry.height, - visual); - window->egl_surface = - eglCreateWindowSurface(display->egl.dpy, - display->egl.conf, - window->native, - NULL); - - wl_surface_map_toplevel(window->surface); - - ret = eglMakeCurrent(window->display->egl.dpy, window->egl_surface, - window->egl_surface, window->display->egl.ctx); - assert(ret == EGL_TRUE); -} - -static void -redraw(void *data, uint32_t time) -{ - struct window *window = data; - static const GLfloat verts[3][2] = { - { -0.5, -0.5 }, - { 0.5, -0.5 }, - { 0, 0.5 } - }; - static const GLfloat colors[3][3] = { - { 1, 0, 0 }, - { 0, 1, 0 }, - { 0, 0, 1 } - }; - GLfloat angle; - GLfloat rotation[4][4] = { - { 1, 0, 0, 0 }, - { 0, 1, 0, 0 }, - { 0, 0, 1, 0 }, - { 0, 0, 0, 1 } - }; - static const int32_t speed_div = 5; - static uint32_t start_time = 0; - - if (start_time == 0) - start_time = time; - - angle = ((time-start_time) / speed_div) % 360 * M_PI / 180.0; - rotation[0][0] = cos(angle); - rotation[0][2] = sin(angle); - rotation[2][0] = -sin(angle); - rotation[2][2] = cos(angle); - - glUniformMatrix4fv(window->gl.rotation_uniform, 1, GL_FALSE, - (GLfloat *) rotation); - - glClearColor(0.0, 0.0, 0.0, 0.5); - glClear(GL_COLOR_BUFFER_BIT); - - glVertexAttribPointer(window->gl.pos, 2, GL_FLOAT, GL_FALSE, 0, verts); - glVertexAttribPointer(window->gl.col, 3, GL_FLOAT, GL_FALSE, 0, colors); - glEnableVertexAttribArray(window->gl.pos); - glEnableVertexAttribArray(window->gl.col); - - glDrawArrays(GL_TRIANGLES, 0, 3); - - glDisableVertexAttribArray(window->gl.pos); - glDisableVertexAttribArray(window->gl.col); - - glFlush(); - - eglSwapBuffers(window->display->egl.dpy, window->egl_surface); - wl_display_frame_callback(window->display->display, redraw, window); -} - -static void -display_handle_global(struct wl_display *display, uint32_t id, - const char *interface, uint32_t version, void *data) -{ - struct display *d = data; - - if (strcmp(interface, "compositor") == 0) - d->compositor = wl_compositor_create(display, id); -} - -static int -event_mask_update(uint32_t mask, void *data) -{ - struct display *d = data; - - d->mask = mask; - - return 0; -} - -int -main(int argc, char **argv) -{ - struct display display = { 0 }; - struct window window = { 0 }; - - memset(&display, 0, sizeof display); - memset(&window, 0, sizeof window); - - window.display = &display; - window.geometry.width = 250; - window.geometry.height = 250; - - display.display = wl_display_connect(NULL); - assert(display.display); - - wl_display_add_global_listener(display.display, - display_handle_global, &display); - - display.native = wl_egl_display_create(display.display); - - init_egl(&display); - create_surface(&window); - init_gl(&window); - - wl_display_frame_callback(display.display, redraw, &window); - - wl_display_get_fd(display.display, event_mask_update, &display); - while (true) - wl_display_iterate(display.display, display.mask); - - return 0; -} diff --git a/clients/smoke.c b/clients/smoke.c deleted file mode 100644 index 0710b3a..0000000 --- a/clients/smoke.c +++ /dev/null @@ -1,296 +0,0 @@ -/* - * Copyright © 2010 Kristian Høgsberg - * - * 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 <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include <fcntl.h> -#include <unistd.h> -#include <math.h> -#include <time.h> -#include <cairo.h> -#include <glib.h> - -#include "wayland-client.h" -#include "wayland-glib.h" -#include "window.h" - -struct smoke { - struct display *display; - struct window *window; - cairo_surface_t *surface; - int x, y, width, height; - int offset, current; - struct { float *d, *u, *v; } b[2]; -}; - -static void diffuse(struct smoke *smoke, uint32_t time, - float *source, float *dest) -{ - float *s, *d; - int x, y, k, stride; - float t, a = 0.0002; - - stride = smoke->width; - - for (k = 0; k < 5; k++) { - for (y = 1; y < smoke->height - 1; y++) { - s = source + y * stride; - d = dest + y * stride; - for (x = 1; x < smoke->width - 1; x++) { - t = d[x - 1] + d[x + 1] + - d[x - stride] + d[x + stride]; - d[x] = (s[x] + a * t) / (1 + 4 * a) * 0.995; - } - } - } -} - -static void advect(struct smoke *smoke, uint32_t time, - float *uu, float *vv, float *source, float *dest) -{ - float *s, *d; - float *u, *v; - int x, y, stride; - int i, j; - float px, py, fx, fy; - - stride = smoke->width; - - for (y = 1; y < smoke->height - 1; y++) { - d = dest + y * stride; - u = uu + y * stride; - v = vv + y * stride; - - for (x = 1; x < smoke->width - 1; x++) { - px = x - u[x]; - py = y - v[x]; - if (px < 0.5) - px = 0.5; - if (py < 0.5) - py = 0.5; - if (px > smoke->width - 0.5) - px = smoke->width - 0.5; - if (py > smoke->height - 0.5) - py = smoke->height - 0.5; - i = (int) px; - j = (int) py; - fx = px - i; - fy = py - j; - s = source + j * stride + i; - d[x] = (s[0] * (1 - fx) + s[1] * fx) * (1 - fy) + - (s[stride] * (1 - fx) + s[stride + 1] * fx) * fy; - } - } -} - -static void project(struct smoke *smoke, uint32_t time, - float *u, float *v, float *p, float *div) -{ - int x, y, k, l, s; - float h; - - h = 1.0 / smoke->width; - s = smoke->width; - memset(p, 0, smoke->height * smoke->width); - for (y = 1; y < smoke->height - 1; y++) { - l = y * s; - for (x = 1; x < smoke->width - 1; x++) { - div[l + x] = -0.5 * h * (u[l + x + 1] - u[l + x - 1] + - v[l + x + s] - v[l + x - s]); - p[l + x] = 0; - } - } - - for (k = 0; k < 5; k++) { - for (y = 1; y < smoke->height - 1; y++) { - l = y * s; - for (x = 1; x < smoke->width - 1; x++) { - p[l + x] = (div[l + x] + - p[l + x - 1] + - p[l + x + 1] + - p[l + x - s] + - p[l + x + s]) / 4; - } - } - } - - for (y = 1; y < smoke->height - 1; y++) { - l = y * s; - for (x = 1; x < smoke->width - 1; x++) { - u[l + x] -= 0.5 * (p[l + x + 1] - p[l + x - 1]) / h; - v[l + x] -= 0.5 * (p[l + x + s] - p[l + x - s]) / h; - } - } -} - -static void render(struct smoke *smoke) -{ - unsigned char *dest; - int x, y, width, height, stride; - float *s; - uint32_t *d, c, a; - - dest = cairo_image_surface_get_data (smoke->surface); - width = cairo_image_surface_get_width (smoke->surface); - height = cairo_image_surface_get_height (smoke->surface); - stride = cairo_image_surface_get_stride (smoke->surface); - - for (y = 1; y < height - 1; y++) { - s = smoke->b[smoke->current].d + y * smoke->height; - d = (uint32_t *) (dest + y * stride); - for (x = 1; x < width - 1; x++) { - c = (int) (s[x] * 800); - if (c > 255) - c = 255; - a = c; - if (a < 0x33) - a = 0x33; - d[x] = (a << 24) | (c << 16) | (c << 8) | c; - } - } -} - -static void -frame_callback(void *data, uint32_t time) -{ - struct smoke *smoke = data; - - diffuse(smoke, time / 30, smoke->b[0].u, smoke->b[1].u); - diffuse(smoke, time / 30, smoke->b[0].v, smoke->b[1].v); - project(smoke, time / 30, - smoke->b[1].u, smoke->b[1].v, - smoke->b[0].u, smoke->b[0].v); - advect(smoke, time / 30, - smoke->b[1].u, smoke->b[1].v, - smoke->b[1].u, smoke->b[0].u); - advect(smoke, time / 30, - smoke->b[1].u, smoke->b[1].v, - smoke->b[1].v, smoke->b[0].v); - project(smoke, time / 30, - smoke->b[0].u, smoke->b[0].v, - smoke->b[1].u, smoke->b[1].v); - - diffuse(smoke, time / 30, smoke->b[0].d, smoke->b[1].d); - advect(smoke, time / 30, - smoke->b[0].u, smoke->b[0].v, - smoke->b[1].d, smoke->b[0].d); - - render(smoke); - - window_damage(smoke->window, 0, 0, smoke->width, smoke->height); - wl_display_frame_callback(display_get_display(smoke->display), - frame_callback, smoke); -} - -static int -smoke_motion_handler(struct window *window, - struct input *input, uint32_t time, - int32_t x, int32_t y, - int32_t surface_x, int32_t surface_y, void *data) -{ - struct smoke *smoke = data; - int i, i0, i1, j, j0, j1, k, d = 5; - - if (surface_x - d < 1) - i0 = 1; - else - i0 = surface_x - d; - if (i0 + 2 * d > smoke->width - 1) - i1 = smoke->width - 1; - else - i1 = i0 + 2 * d; - - if (surface_y - d < 1) - j0 = 1; - else - j0 = surface_y - d; - if (j0 + 2 * d > smoke->height - 1) - j1 = smoke->height - 1; - else - j1 = j0 + 2 * d; - - for (i = i0; i < i1; i++) - for (j = j0; j < j1; j++) { - k = j * smoke->width + i; - smoke->b[0].u[k] += 256 - (random() & 512); - smoke->b[0].v[k] += 256 - (random() & 512); - smoke->b[0].d[k] += 1; - } - - return POINTER_HAND1; -} - -int main(int argc, char *argv[]) -{ - struct timespec ts; - struct smoke smoke; - struct display *d; - int size; - - d = display_create(&argc, &argv, NULL); - if (d == NULL) { - fprintf(stderr, "failed to create display: %m\n"); - return -1; - } - - smoke.x = 200; - smoke.y = 200; - smoke.width = 200; - smoke.height = 200; - smoke.display = d; - smoke.window = window_create(d, smoke.width, smoke.height); - window_set_title(smoke.window, "smoke"); - - window_set_buffer_type(smoke.window, WINDOW_BUFFER_TYPE_SHM); - clock_gettime(CLOCK_MONOTONIC, &ts); - srandom(ts.tv_nsec); - smoke.offset = random(); - - smoke.current = 0; - size = smoke.height * smoke.width; - smoke.b[0].d = calloc(size, sizeof(float)); - smoke.b[0].u = calloc(size, sizeof(float)); - smoke.b[0].v = calloc(size, sizeof(float)); - smoke.b[1].d = calloc(size, sizeof(float)); - smoke.b[1].u = calloc(size, sizeof(float)); - smoke.b[1].v = calloc(size, sizeof(float)); - - window_set_decoration(smoke.window, 0); - window_create_surface(smoke.window); - smoke.surface = window_get_surface(smoke.window); - - window_flush(smoke.window); - - window_set_motion_handler(smoke.window, - smoke_motion_handler); - - window_set_user_data(smoke.window, &smoke); - wl_display_frame_callback(display_get_display(d), - frame_callback, &smoke); - - display_run(d); - - return 0; -} diff --git a/clients/terminal.c b/clients/terminal.c deleted file mode 100644 index 3573382..0000000 --- a/clients/terminal.c +++ /dev/null @@ -1,2398 +0,0 @@ -/* - * Copyright © 2008 Kristian Høgsberg - * - * 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 <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <fcntl.h> -#include <unistd.h> -#include <math.h> -#include <time.h> -#include <pty.h> -#include <ctype.h> -#include <cairo.h> -#include <glib.h> - -#include <X11/keysym.h> - -#include "wayland-util.h" -#include "wayland-client.h" -#include "wayland-glib.h" - -#include "window.h" - -static int option_fullscreen; - -#define MOD_SHIFT 0x01 -#define MOD_ALT 0x02 -#define MOD_CTRL 0x04 - -#define ATTRMASK_BOLD 0x01 -#define ATTRMASK_UNDERLINE 0x02 -#define ATTRMASK_BLINK 0x04 -#define ATTRMASK_INVERSE 0x08 -#define ATTRMASK_CONCEALED 0x10 - -/* Buffer sizes */ -#define MAX_RESPONSE 256 -#define MAX_ESCAPE 255 - -/* Terminal modes */ -#define MODE_SHOW_CURSOR 0x00000001 -#define MODE_INVERSE 0x00000002 -#define MODE_AUTOWRAP 0x00000004 -#define MODE_AUTOREPEAT 0x00000008 -#define MODE_LF_NEWLINE 0x00000010 -#define MODE_IRM 0x00000020 -#define MODE_DELETE_SENDS_DEL 0x00000040 -#define MODE_ALT_SENDS_ESC 0x00000080 - -union utf8_char { - unsigned char byte[4]; - uint32_t ch; -}; - -enum utf8_state { - utf8state_start, - utf8state_accept, - utf8state_reject, - utf8state_expect3, - utf8state_expect2, - utf8state_expect1 -}; - -struct utf8_state_machine { - enum utf8_state state; - int len; - union utf8_char s; -}; - -static void -init_state_machine(struct utf8_state_machine *machine) -{ - machine->state = utf8state_start; - machine->len = 0; - machine->s.ch = 0; -} - -static enum utf8_state -utf8_next_char(struct utf8_state_machine *machine, char c) -{ - switch(machine->state) { - case utf8state_start: - case utf8state_accept: - case utf8state_reject: - machine->s.ch = 0; - machine->len = 0; - if(c == 0xC0 || c == 0xC1) { - /* overlong encoding, reject */ - machine->state = utf8state_reject; - } else if((c & 0x80) == 0) { - /* single byte, accept */ - machine->s.byte[machine->len++] = c; - machine->state = utf8state_accept; - } else if((c & 0xC0) == 0x80) { - /* parser out of sync, ignore byte */ - machine->state = utf8state_start; - } else if((c & 0xE0) == 0xC0) { - /* start of two byte sequence */ - machine->s.byte[machine->len++] = c; - machine->state = utf8state_expect1; - } else if((c & 0xF0) == 0xE0) { - /* start of three byte sequence */ - machine->s.byte[machine->len++] = c; - machine->state = utf8state_expect2; - } else if((c & 0xF8) == 0xF0) { - /* start of four byte sequence */ - machine->s.byte[machine->len++] = c; - machine->state = utf8state_expect3; - } else { - /* overlong encoding, reject */ - machine->state = utf8state_reject; - } - break; - case utf8state_expect3: - machine->s.byte[machine->len++] = c; - if((c & 0xC0) == 0x80) { - /* all good, continue */ - machine->state = utf8state_expect2; - } else { - /* missing extra byte, reject */ - machine->state = utf8state_reject; - } - break; - case utf8state_expect2: - machine->s.byte[machine->len++] = c; - if((c & 0xC0) == 0x80) { - /* all good, continue */ - machine->state = utf8state_expect1; - } else { - /* missing extra byte, reject */ - machine->state = utf8state_reject; - } - break; - case utf8state_expect1: - machine->s.byte[machine->len++] = c; - if((c & 0xC0) == 0x80) { - /* all good, accept */ - machine->state = utf8state_accept; - } else { - /* missing extra byte, reject */ - machine->state = utf8state_reject; - } - break; - default: - machine->state = utf8state_reject; - break; - } - - return machine->state; -} - -struct char_sub { - union utf8_char match; - union utf8_char replace; -}; -/* Set last char_sub match to NULL char */ -typedef struct char_sub *character_set; - -struct char_sub CS_US[] = { - {{{0, }}, {{0, }}} -}; -static struct char_sub CS_UK[] = { - {{{'#', 0, }}, {{0xC2, 0xA3, 0, }}}, - {{{0, }}, {{0, }}} -}; -static struct char_sub CS_SPECIAL[] = { - {{{'`', 0, }}, {{0xE2, 0x99, 0xA6, 0}}}, /* diamond */ - {{{'a', 0, }}, {{0xE2, 0x96, 0x92, 0}}}, /* 50% cell */ - {{{'b', 0, }}, {{0xE2, 0x90, 0x89, 0}}}, /* HT */ - {{{'c', 0, }}, {{0xE2, 0x90, 0x8C, 0}}}, /* FF */ - {{{'d', 0, }}, {{0xE2, 0x90, 0x8D, 0}}}, /* CR */ - {{{'e', 0, }}, {{0xE2, 0x90, 0x8A, 0}}}, /* LF */ - {{{'f', 0, }}, {{0xC2, 0xB0, 0, }}}, /* Degree */ - {{{'g', 0, }}, {{0xC2, 0xB1, 0, }}}, /* Plus/Minus */ - {{{'h', 0, }}, {{0xE2, 0x90, 0xA4, 0}}}, /* NL */ - {{{'i', 0, }}, {{0xE2, 0x90, 0x8B, 0}}}, /* VT */ - {{{'j', 0, }}, {{0xE2, 0x94, 0x98, 0}}}, /* CN_RB */ - {{{'k', 0, }}, {{0xE2, 0x94, 0x90, 0}}}, /* CN_RT */ - {{{'l', 0, }}, {{0xE2, 0x94, 0x8C, 0}}}, /* CN_LT */ - {{{'m', 0, }}, {{0xE2, 0x94, 0x94, 0}}}, /* CN_RB */ - {{{'n', 0, }}, {{0xE2, 0x94, 0xBC, 0}}}, /* CROSS */ - {{{'o', 0, }}, {{0xE2, 0x94, 0x80, 0}}}, /* H */ - {{{'p', 0, }}, {{0xE2, 0x94, 0x80, 0}}}, /* H */ - {{{'q', 0, }}, {{0xE2, 0x94, 0x80, 0}}}, /* H */ - {{{'r', 0, }}, {{0xE2, 0x94, 0x80, 0}}}, /* H */ - {{{'s', 0, }}, {{0xE2, 0x94, 0x80, 0}}}, /* H */ - {{{'t', 0, }}, {{0xE2, 0x94, 0x9C, 0}}}, /* TR */ - {{{'u', 0, }}, {{0xE2, 0x94, 0xA4, 0}}}, /* TL */ - {{{'v', 0, }}, {{0xE2, 0x94, 0xB4, 0}}}, /* TU */ - {{{'w', 0, }}, {{0xE2, 0x94, 0xAC, 0}}}, /* TD */ - {{{'x', 0, }}, {{0xE2, 0x94, 0x82, 0}}}, /* V */ - {{{'y', 0, }}, {{0xE2, 0x89, 0xA4, 0}}}, /* LE */ - {{{'z', 0, }}, {{0xE2, 0x89, 0xA5, 0}}}, /* GE */ - {{{'{', 0, }}, {{0xCF, 0x80, 0, }}}, /* PI */ - {{{'|', 0, }}, {{0xE2, 0x89, 0xA0, 0}}}, /* NEQ */ - {{{'}', 0, }}, {{0xC2, 0xA3, 0, }}}, /* POUND */ - {{{'~', 0, }}, {{0xE2, 0x8B, 0x85, 0}}}, /* DOT */ - {{{0, }}, {{0, }}} -}; - -static void -apply_char_set(character_set cs, union utf8_char *utf8) -{ - int i = 0; - - while (cs[i].match.byte[0]) { - if ((*utf8).ch == cs[i].match.ch) { - *utf8 = cs[i].replace; - break; - } - i++; - } -} - -struct key_map { - int sym; - int num; - char escape; - char code; -}; -/* Set last key_sub sym to NULL */ -typedef struct key_map *keyboard_mode; - -static struct key_map KM_NORMAL[] = { - {XK_Left, 1, '[', 'D'}, - {XK_Right, 1, '[', 'C'}, - {XK_Up, 1, '[', 'A'}, - {XK_Down, 1, '[', 'B'}, - {XK_Home, 1, '[', 'H'}, - {XK_End, 1, '[', 'F'}, - {0, 0, 0, 0} -}; -static struct key_map KM_APPLICATION[] = { - {XK_Left, 1, 'O', 'D'}, - {XK_Right, 1, 'O', 'C'}, - {XK_Up, 1, 'O', 'A'}, - {XK_Down, 1, 'O', 'B'}, - {XK_Home, 1, 'O', 'H'}, - {XK_End, 1, 'O', 'F'}, - {XK_KP_Enter, 1, 'O', 'M'}, - {XK_KP_Multiply, 1, 'O', 'j'}, - {XK_KP_Add, 1, 'O', 'k'}, - {XK_KP_Separator, 1, 'O', 'l'}, - {XK_KP_Subtract, 1, 'O', 'm'}, - {XK_KP_Divide, 1, 'O', 'o'}, - {0, 0, 0, 0} -}; - -static int -function_key_response(char escape, int num, uint32_t modifiers, - char code, char *response) -{ - int mod_num = 0; - int len; - - if (modifiers & XKB_COMMON_SHIFT_MASK) mod_num |= 1; - if (modifiers & XKB_COMMON_MOD1_MASK) mod_num |= 2; - if (modifiers & XKB_COMMON_CONTROL_MASK) mod_num |= 4; - - if (mod_num != 0) - len = snprintf(response, MAX_RESPONSE, "\e[%d;%d%c", - num, mod_num + 1, code); - else if (code != '~') - len = snprintf(response, MAX_RESPONSE, "\e%c%c", - escape, code); - else - len = snprintf(response, MAX_RESPONSE, "\e%c%d%c", - escape, num, code); - - if (len >= MAX_RESPONSE) return MAX_RESPONSE - 1; - else return len; -} - -/* returns the number of bytes written into response, - * which must have room for MAX_RESPONSE bytes */ -static int -apply_key_map(keyboard_mode mode, int sym, uint32_t modifiers, char *response) -{ - struct key_map map; - int len = 0; - int i = 0; - - while (mode[i].sym) { - map = mode[i++]; - if (sym == map.sym) { - len = function_key_response(map.escape, map.num, - modifiers, map.code, - response); - break; - } - } - - return len; -} - -struct terminal_color { double r, g, b, a; }; -struct attr { - unsigned char fg, bg; - char a; /* attributes format: - * 76543210 - * cilub */ - char s; /* in selection */ -}; -struct color_scheme { - struct terminal_color palette[16]; - char border; - struct attr default_attr; -}; - -static void -attr_init(struct attr *data_attr, struct attr attr, int n) -{ - int i; - for (i = 0; i < n; i++) { - data_attr[i] = attr; - } -} - -enum escape_state { - escape_state_normal = 0, - escape_state_escape, - escape_state_dcs, - escape_state_csi, - escape_state_osc, - escape_state_inner_escape, - escape_state_ignore, - escape_state_special -}; - -#define ESC_FLAG_WHAT 0x01 -#define ESC_FLAG_GT 0x02 -#define ESC_FLAG_BANG 0x04 -#define ESC_FLAG_CASH 0x08 -#define ESC_FLAG_SQUOTE 0x10 -#define ESC_FLAG_DQUOTE 0x20 -#define ESC_FLAG_SPACE 0x40 - -struct terminal { - struct window *window; - struct display *display; - union utf8_char *data; - char *tab_ruler; - struct attr *data_attr; - struct attr curr_attr; - uint32_t mode; - char origin_mode; - char saved_origin_mode; - struct attr saved_attr; - union utf8_char last_char; - int margin_top, margin_bottom; - character_set cs, g0, g1; - character_set saved_cs, saved_g0, saved_g1; - keyboard_mode key_mode; - int data_pitch, attr_pitch; /* The width in bytes of a line */ - int width, height, start, row, column; - int saved_row, saved_column; - int fd, master; - GIOChannel *channel; - uint32_t modifiers; - char escape[MAX_ESCAPE+1]; - int escape_length; - enum escape_state state; - enum escape_state outer_state; - int escape_flags; - struct utf8_state_machine state_machine; - int margin; - int fullscreen; - int focused; - struct color_scheme *color_scheme; - struct terminal_color color_table[256]; - cairo_font_extents_t extents; - cairo_scaled_font_t *font_normal, *font_bold; - - struct wl_selection *selection; - struct wl_selection_offer *selection_offer; - uint32_t selection_offer_has_text; - int32_t dragging, selection_active; - int selection_start_x, selection_start_y; - int selection_end_x, selection_end_y; -}; - -/* Create default tab stops, every 8 characters */ -static void -terminal_init_tabs(struct terminal *terminal) -{ - int i = 0; - - while (i < terminal->width) { - if (i % 8 == 0) - terminal->tab_ruler[i] = 1; - else - terminal->tab_ruler[i] = 0; - i++; - } -} - -static void -terminal_init(struct terminal *terminal) -{ - terminal->curr_attr = terminal->color_scheme->default_attr; - terminal->origin_mode = 0; - terminal->mode = MODE_SHOW_CURSOR | - MODE_AUTOREPEAT | - MODE_ALT_SENDS_ESC | - MODE_AUTOWRAP; - - terminal->row = 0; - terminal->column = 0; - - terminal->g0 = CS_US; - terminal->g1 = CS_US; - terminal->cs = terminal->g0; - terminal->key_mode = KM_NORMAL; - - terminal->saved_g0 = terminal->g0; - terminal->saved_g1 = terminal->g1; - terminal->saved_cs = terminal->cs; - - terminal->saved_attr = terminal->curr_attr; - terminal->saved_origin_mode = terminal->origin_mode; - terminal->saved_row = terminal->row; - terminal->saved_column = terminal->column; - - if (terminal->tab_ruler != NULL) terminal_init_tabs(terminal); -} - -static void -init_color_table(struct terminal *terminal) -{ - int c, r; - struct terminal_color *color_table = terminal->color_table; - - for (c = 0; c < 256; c ++) { - if (c < 16) { - color_table[c] = terminal->color_scheme->palette[c]; - } else if (c < 232) { - r = c - 16; - color_table[c].b = ((double)(r % 6) / 6.0); r /= 6; - color_table[c].g = ((double)(r % 6) / 6.0); r /= 6; - color_table[c].r = ((double)(r % 6) / 6.0); - color_table[c].a = 1.0; - } else { - r = (c - 232) * 10 + 8; - color_table[c].r = ((double) r) / 256.0; - color_table[c].g = color_table[c].r; - color_table[c].b = color_table[c].r; - color_table[c].a = 1.0; - } - } -} - -static union utf8_char * -terminal_get_row(struct terminal *terminal, int row) -{ - int index; - - index = (row + terminal->start) % terminal->height; - - return &terminal->data[index * terminal->width]; -} - -static struct attr* -terminal_get_attr_row(struct terminal *terminal, int row) -{ - int index; - - index = (row + terminal->start) % terminal->height; - - return &terminal->data_attr[index * terminal->width]; -} - -union decoded_attr { - struct attr attr; - uint32_t key; -}; - -static int -terminal_compare_position(struct terminal *terminal, - int x, int y, int32_t ref_row, int32_t ref_col) -{ - struct rectangle allocation; - int top_margin, side_margin, col, row, ref_x; - - window_get_child_allocation(terminal->window, &allocation); - side_margin = allocation.x + (allocation.width - terminal->width * terminal->extents.max_x_advance) / 2; - top_margin = allocation.y + (allocation.height - terminal->height * terminal->extents.height) / 2; - - col = (x - side_margin) / terminal->extents.max_x_advance; - row = (y - top_margin) / terminal->extents.height; - - ref_x = side_margin + ref_col * terminal->extents.max_x_advance + - terminal->extents.max_x_advance / 2; - - if (row < ref_row) - return -1; - if (row == ref_row) { - if (col < ref_col) - return -1; - if (col == ref_col && x < ref_x) - return -1; - } - - return 1; -} - -static void -terminal_decode_attr(struct terminal *terminal, int row, int col, - union decoded_attr *decoded) -{ - struct attr attr; - int foreground, background, tmp; - int start_cmp, end_cmp; - - start_cmp = - terminal_compare_position(terminal, - terminal->selection_start_x, - terminal->selection_start_y, - row, col); - end_cmp = - terminal_compare_position(terminal, - terminal->selection_end_x, - terminal->selection_end_y, - row, col); - decoded->attr.s = 0; - if (start_cmp < 0 && end_cmp > 0) - decoded->attr.s = 1; - else if (end_cmp < 0 && start_cmp > 0) - decoded->attr.s = 1; - - /* get the attributes for this character cell */ - attr = terminal_get_attr_row(terminal, row)[col]; - if ((attr.a & ATTRMASK_INVERSE) || - decoded->attr.s || - ((terminal->mode & MODE_SHOW_CURSOR) && - terminal->focused && terminal->row == row && - terminal->column == col)) { - foreground = attr.bg; - background = attr.fg; - if (attr.a & ATTRMASK_BOLD) { - if (foreground <= 16) foreground |= 0x08; - if (background <= 16) background &= 0x07; - } - } else { - foreground = attr.fg; - background = attr.bg; - } - - if (terminal->mode & MODE_INVERSE) { - tmp = foreground; - foreground = background; - background = tmp; - if (attr.a & ATTRMASK_BOLD) { - if (foreground <= 16) foreground |= 0x08; - if (background <= 16) background &= 0x07; - } - } - - decoded->attr.fg = foreground; - decoded->attr.bg = background; - decoded->attr.a = attr.a; -} - - -static void -terminal_scroll_buffer(struct terminal *terminal, int d) -{ - int i; - - d = d % (terminal->height + 1); - terminal->start = (terminal->start + d) % terminal->height; - if (terminal->start < 0) terminal->start = terminal->height + terminal->start; - if(d < 0) { - d = 0 - d; - for(i = 0; i < d; i++) { - memset(terminal_get_row(terminal, i), 0, terminal->data_pitch); - attr_init(terminal_get_attr_row(terminal, i), - terminal->curr_attr, terminal->width); - } - } else { - for(i = terminal->height - d; i < terminal->height; i++) { - memset(terminal_get_row(terminal, i), 0, terminal->data_pitch); - attr_init(terminal_get_attr_row(terminal, i), - terminal->curr_attr, terminal->width); - } - } -} - -static void -terminal_scroll_window(struct terminal *terminal, int d) -{ - int i; - int window_height; - int from_row, to_row; - - // scrolling range is inclusive - window_height = terminal->margin_bottom - terminal->margin_top + 1; - d = d % (window_height + 1); - if(d < 0) { - d = 0 - d; - to_row = terminal->margin_bottom; - from_row = terminal->margin_bottom - d; - - for (i = 0; i < (window_height - d); i++) { - memcpy(terminal_get_row(terminal, to_row - i), - terminal_get_row(terminal, from_row - i), - terminal->data_pitch); - memcpy(terminal_get_attr_row(terminal, to_row - i), - terminal_get_attr_row(terminal, from_row - i), - terminal->attr_pitch); - } - for (i = terminal->margin_top; i < (terminal->margin_top + d); i++) { - memset(terminal_get_row(terminal, i), 0, terminal->data_pitch); - attr_init(terminal_get_attr_row(terminal, i), - terminal->curr_attr, terminal->width); - } - } else { - to_row = terminal->margin_top; - from_row = terminal->margin_top + d; - - for (i = 0; i < (window_height - d); i++) { - memcpy(terminal_get_row(terminal, to_row + i), - terminal_get_row(terminal, from_row + i), - terminal->data_pitch); - memcpy(terminal_get_attr_row(terminal, to_row + i), - terminal_get_attr_row(terminal, from_row + i), - terminal->attr_pitch); - } - for (i = terminal->margin_bottom - d + 1; i <= terminal->margin_bottom; i++) { - memset(terminal_get_row(terminal, i), 0, terminal->data_pitch); - attr_init(terminal_get_attr_row(terminal, i), - terminal->curr_attr, terminal->width); - } - } -} - -static void -terminal_scroll(struct terminal *terminal, int d) -{ - if(terminal->margin_top == 0 && terminal->margin_bottom == terminal->height - 1) - terminal_scroll_buffer(terminal, d); - else - terminal_scroll_window(terminal, d); -} - -static void -terminal_shift_line(struct terminal *terminal, int d) -{ - union utf8_char *row; - struct attr *attr_row; - - row = terminal_get_row(terminal, terminal->row); - attr_row = terminal_get_attr_row(terminal, terminal->row); - - if ((terminal->width + d) <= terminal->column) - d = terminal->column + 1 - terminal->width; - if ((terminal->column + d) >= terminal->width) - d = terminal->width - terminal->column - 1; - - if (d < 0) { - d = 0 - d; - memmove(&row[terminal->column], - &row[terminal->column + d], - (terminal->width - terminal->column - d) * sizeof(union utf8_char)); - memmove(&attr_row[terminal->column], &attr_row[terminal->column + d], - (terminal->width - terminal->column - d) * sizeof(struct attr)); - memset(&row[terminal->width - d], 0, d * sizeof(union utf8_char)); - attr_init(&attr_row[terminal->width - d], terminal->curr_attr, d); - } else { - memmove(&row[terminal->column + d], &row[terminal->column], - (terminal->width - terminal->column - d) * sizeof(union utf8_char)); - memmove(&attr_row[terminal->column + d], &attr_row[terminal->column], - (terminal->width - terminal->column - d) * sizeof(struct attr)); - memset(&row[terminal->column], 0, d * sizeof(union utf8_char)); - attr_init(&attr_row[terminal->column], terminal->curr_attr, d); - } -} - -static void -terminal_resize(struct terminal *terminal, int width, int height) -{ - size_t size; - union utf8_char *data; - struct attr *data_attr; - char *tab_ruler; - int data_pitch, attr_pitch; - int i, l, total_rows; - struct rectangle allocation; - struct winsize ws; - int32_t pixel_width, pixel_height; - - if (width < 1) - width = 1; - if (height < 1) - height = 1; - if (terminal->width == width && terminal->height == height) - return; - - if (!terminal->fullscreen) { - pixel_width = width * - terminal->extents.max_x_advance + 2 * terminal->margin; - pixel_height = height * - terminal->extents.height + 2 * terminal->margin; - window_set_child_size(terminal->window, - pixel_width, pixel_height); - } - - window_schedule_redraw (terminal->window); - - data_pitch = width * sizeof(union utf8_char); - size = data_pitch * height; - data = malloc(size); - attr_pitch = width * sizeof(struct attr); - data_attr = malloc(attr_pitch * height); - tab_ruler = malloc(width); - memset(data, 0, size); - memset(tab_ruler, 0, width); - attr_init(data_attr, terminal->curr_attr, width * height); - if (terminal->data && terminal->data_attr) { - if (width > terminal->width) - l = terminal->width; - else - l = width; - - if (terminal->height > height) { - total_rows = height; - } else { - total_rows = terminal->height; - } - - for (i = 0; i < total_rows; i++) { - memcpy(&data[width * i], - terminal_get_row(terminal, i), - l * sizeof(union utf8_char)); - memcpy(&data_attr[width * i], - terminal_get_attr_row(terminal, i), - l * sizeof(struct attr)); - } - - free(terminal->data); - free(terminal->data_attr); - free(terminal->tab_ruler); - } - - terminal->data_pitch = data_pitch; - terminal->attr_pitch = attr_pitch; - terminal->margin_bottom = - height - (terminal->height - terminal->margin_bottom); - terminal->width = width; - terminal->height = height; - terminal->data = data; - terminal->data_attr = data_attr; - terminal->tab_ruler = tab_ruler; - terminal_init_tabs(terminal); - - /* Update the window size */ - ws.ws_row = terminal->height; - ws.ws_col = terminal->width; - window_get_child_allocation(terminal->window, &allocation); - ws.ws_xpixel = allocation.width; - ws.ws_ypixel = allocation.height; - ioctl(terminal->master, TIOCSWINSZ, &ws); -} - -struct color_scheme DEFAULT_COLORS = { - { - {0, 0, 0, 1}, /* black */ - {0.66, 0, 0, 1}, /* red */ - {0 , 0.66, 0, 1}, /* green */ - {0.66, 0.33, 0, 1}, /* orange (nicer than muddy yellow) */ - {0 , 0 , 0.66, 1}, /* blue */ - {0.66, 0 , 0.66, 1}, /* magenta */ - {0, 0.66, 0.66, 1}, /* cyan */ - {0.66, 0.66, 0.66, 1}, /* light grey */ - {0.22, 0.33, 0.33, 1}, /* dark grey */ - {1, 0.33, 0.33, 1}, /* high red */ - {0.33, 1, 0.33, 1}, /* high green */ - {1, 1, 0.33, 1}, /* high yellow */ - {0.33, 0.33, 1, 1}, /* high blue */ - {1, 0.33, 1, 1}, /* high magenta */ - {0.33, 1, 1, 1}, /* high cyan */ - {1, 1, 1, 1} /* white */ - }, - 0, /* black border */ - {7, 0, 0, } /* bg:black (0), fg:light gray (7) */ -}; - -static void -terminal_set_color(struct terminal *terminal, cairo_t *cr, int index) -{ - cairo_set_source_rgba(cr, - terminal->color_table[index].r, - terminal->color_table[index].g, - terminal->color_table[index].b, - terminal->color_table[index].a); -} - -static void -terminal_send_selection(struct terminal *terminal, int fd) -{ - int row, col; - union utf8_char *p_row; - union decoded_attr attr; - FILE *fp; - int len; - - fp = fdopen(fd, "w"); - for (row = 0; row < terminal->height; row++) { - p_row = terminal_get_row(terminal, row); - for (col = 0; col < terminal->width; col++) { - /* get the attributes for this character cell */ - terminal_decode_attr(terminal, row, col, &attr); - if (!attr.attr.s) - continue; - len = strnlen((char *) p_row[col].byte, 4); - fwrite(p_row[col].byte, 1, len, fp); - } - } - fclose(fp); -} - -struct glyph_run { - struct terminal *terminal; - cairo_t *cr; - int count; - union decoded_attr attr; - cairo_glyph_t glyphs[256], *g; -}; - -static void -glyph_run_init(struct glyph_run *run, struct terminal *terminal, cairo_t *cr) -{ - run->terminal = terminal; - run->cr = cr; - run->g = run->glyphs; - run->count = 0; - run->attr.key = 0; -} - -static void -glyph_run_flush(struct glyph_run *run, union decoded_attr attr) -{ - cairo_scaled_font_t *font; - - if (run->count > ARRAY_LENGTH(run->glyphs) - 10 || - (attr.key != run->attr.key)) { - if (run->attr.attr.a & (ATTRMASK_BOLD | ATTRMASK_BLINK)) - font = run->terminal->font_bold; - else - font = run->terminal->font_normal; - cairo_set_scaled_font(run->cr, font); - terminal_set_color(run->terminal, run->cr, - run->attr.attr.fg); - - if (!(run->attr.attr.a & ATTRMASK_CONCEALED)) - cairo_show_glyphs (run->cr, run->glyphs, run->count); - run->g = run->glyphs; - run->count = 0; - } - run->attr = attr; -} - -static void -glyph_run_add(struct glyph_run *run, int x, int y, union utf8_char *c) -{ - int num_glyphs; - cairo_scaled_font_t *font; - - num_glyphs = ARRAY_LENGTH(run->glyphs) - run->count; - - if (run->attr.attr.a & (ATTRMASK_BOLD | ATTRMASK_BLINK)) - font = run->terminal->font_bold; - else - font = run->terminal->font_normal; - - cairo_move_to(run->cr, x, y); - cairo_scaled_font_text_to_glyphs (font, x, y, - (char *) c->byte, 4, - &run->g, &num_glyphs, - NULL, NULL, NULL); - run->g += num_glyphs; - run->count += num_glyphs; -} - -static void -terminal_draw_contents(struct terminal *terminal) -{ - struct rectangle allocation; - cairo_t *cr; - int top_margin, side_margin; - int row, col; - union utf8_char *p_row; - union decoded_attr attr; - int text_x, text_y; - cairo_surface_t *surface; - double d; - struct glyph_run run; - cairo_font_extents_t extents; - - surface = window_get_surface(terminal->window); - window_get_child_allocation(terminal->window, &allocation); - cr = cairo_create(surface); - cairo_rectangle(cr, allocation.x, allocation.y, - allocation.width, allocation.height); - cairo_clip(cr); - cairo_push_group(cr); - - cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); - terminal_set_color(terminal, cr, terminal->color_scheme->border); - cairo_paint(cr); - - cairo_set_scaled_font(cr, terminal->font_normal); - - extents = terminal->extents; - side_margin = (allocation.width - terminal->width * extents.max_x_advance) / 2; - top_margin = (allocation.height - terminal->height * extents.height) / 2; - - cairo_set_line_width(cr, 1.0); - cairo_translate(cr, allocation.x + side_margin, - allocation.y + top_margin); - /* paint the background */ - for (row = 0; row < terminal->height; row++) { - for (col = 0; col < terminal->width; col++) { - /* get the attributes for this character cell */ - terminal_decode_attr(terminal, row, col, &attr); - - if (attr.attr.bg == terminal->color_scheme->border) - continue; - - terminal_set_color(terminal, cr, attr.attr.bg); - cairo_move_to(cr, col * extents.max_x_advance, - row * extents.height); - cairo_rel_line_to(cr, extents.max_x_advance, 0); - cairo_rel_line_to(cr, 0, extents.height); - cairo_rel_line_to(cr, -extents.max_x_advance, 0); - cairo_close_path(cr); - cairo_fill(cr); - } - } - - cairo_set_operator(cr, CAIRO_OPERATOR_OVER); - - /* paint the foreground */ - glyph_run_init(&run, terminal, cr); - for (row = 0; row < terminal->height; row++) { - p_row = terminal_get_row(terminal, row); - for (col = 0; col < terminal->width; col++) { - /* get the attributes for this character cell */ - terminal_decode_attr(terminal, row, col, &attr); - - glyph_run_flush(&run, attr); - - text_x = col * extents.max_x_advance; - text_y = extents.ascent + row * extents.height; - if (attr.attr.a & ATTRMASK_UNDERLINE) { - terminal_set_color(terminal, cr, attr.attr.fg); - cairo_move_to(cr, text_x, (double)text_y + 1.5); - cairo_line_to(cr, text_x + extents.max_x_advance, (double) text_y + 1.5); - cairo_stroke(cr); - } - - glyph_run_add(&run, text_x, text_y, &p_row[col]); - } - } - - attr.key = ~0; - glyph_run_flush(&run, attr); - - if ((terminal->mode & MODE_SHOW_CURSOR) && !terminal->focused) { - d = 0.5; - - cairo_set_line_width(cr, 1); - cairo_move_to(cr, terminal->column * extents.max_x_advance + d, - terminal->row * extents.height + d); - cairo_rel_line_to(cr, extents.max_x_advance - 2 * d, 0); - cairo_rel_line_to(cr, 0, extents.height - 2 * d); - cairo_rel_line_to(cr, -extents.max_x_advance + 2 * d, 0); - cairo_close_path(cr); - - cairo_stroke(cr); - } - - cairo_pop_group_to_source(cr); - cairo_paint(cr); - cairo_destroy(cr); - cairo_surface_destroy(surface); -} - -static void -resize_handler(struct window *window, - int32_t pixel_width, int32_t pixel_height, void *data) -{ - struct terminal *terminal = data; - int32_t width, height; - - width = (pixel_width - 2 * terminal->margin) / - (int32_t) terminal->extents.max_x_advance; - height = (pixel_height - 2 * terminal->margin) / - (int32_t) terminal->extents.height; - - if (terminal->fullscreen) - window_set_child_size(terminal->window, - pixel_width, pixel_height); - - terminal_resize(terminal, width, height); -} - -static void -terminal_draw(struct terminal *terminal) -{ - window_draw(terminal->window); - terminal_draw_contents(terminal); - window_flush(terminal->window); -} - -static void -redraw_handler(struct window *window, void *data) -{ - struct terminal *terminal = data; - - terminal_draw(terminal); -} - -static void -terminal_data(struct terminal *terminal, const char *data, size_t length); - -static void -handle_char(struct terminal *terminal, union utf8_char utf8); - -static void -handle_sgr(struct terminal *terminal, int code); - -static void -handle_term_parameter(struct terminal *terminal, int code, int sr) -{ - int i; - - if (terminal->escape_flags & ESC_FLAG_WHAT) { - switch(code) { - case 1: /* DECCKM */ - if (sr) terminal->key_mode = KM_APPLICATION; - else terminal->key_mode = KM_NORMAL; - break; - case 2: /* DECANM */ - /* No VT52 support yet */ - terminal->g0 = CS_US; - terminal->g1 = CS_US; - terminal->cs = terminal->g0; - break; - case 3: /* DECCOLM */ - if (sr) - terminal_resize(terminal, 132, 24); - else - terminal_resize(terminal, 80, 24); - - /* set columns, but also home cursor and clear screen */ - terminal->row = 0; terminal->column = 0; - for (i = 0; i < terminal->height; i++) { - memset(terminal_get_row(terminal, i), - 0, terminal->data_pitch); - attr_init(terminal_get_attr_row(terminal, i), - terminal->curr_attr, terminal->width); - } - break; - case 5: /* DECSCNM */ - if (sr) terminal->mode |= MODE_INVERSE; - else terminal->mode &= ~MODE_INVERSE; - break; - case 6: /* DECOM */ - terminal->origin_mode = sr; - if (terminal->origin_mode) - terminal->row = terminal->margin_top; - else - terminal->row = 0; - terminal->column = 0; - break; - case 7: /* DECAWM */ - if (sr) terminal->mode |= MODE_AUTOWRAP; - else terminal->mode &= ~MODE_AUTOWRAP; - break; - case 8: /* DECARM */ - if (sr) terminal->mode |= MODE_AUTOREPEAT; - else terminal->mode &= ~MODE_AUTOREPEAT; - break; - case 25: - if (sr) terminal->mode |= MODE_SHOW_CURSOR; - else terminal->mode &= ~MODE_SHOW_CURSOR; - break; - case 1037: /* deleteSendsDel */ - if (sr) terminal->mode |= MODE_DELETE_SENDS_DEL; - else terminal->mode &= ~MODE_DELETE_SENDS_DEL; - break; - case 1039: /* altSendsEscape */ - if (sr) terminal->mode |= MODE_ALT_SENDS_ESC; - else terminal->mode &= ~MODE_ALT_SENDS_ESC; - break; - default: - fprintf(stderr, "Unknown parameter: ?%d\n", code); - break; - } - } else { - switch(code) { - case 4: /* IRM */ - if (sr) terminal->mode |= MODE_IRM; - else terminal->mode &= ~MODE_IRM; - break; - case 20: /* LNM */ - if (sr) terminal->mode |= MODE_LF_NEWLINE; - else terminal->mode &= ~MODE_LF_NEWLINE; - break; - default: - fprintf(stderr, "Unknown parameter: %d\n", code); - break; - } - } -} - -static void -handle_dcs(struct terminal *terminal) -{ -} - -static void -handle_osc(struct terminal *terminal) -{ - char *p; - int code; - - terminal->escape[terminal->escape_length++] = '\0'; - p = &terminal->escape[2]; - code = strtol(p, &p, 10); - if (*p == ';') p++; - - switch (code) { - case 0: /* Icon name and window title */ - case 1: /* Icon label */ - case 2: /* Window title*/ - window_set_title(terminal->window, p); - break; - default: - fprintf(stderr, "Unknown OSC escape code %d\n", code); - break; - } -} - -static void -handle_escape(struct terminal *terminal) -{ - union utf8_char *row; - struct attr *attr_row; - char *p; - int i, count, x, y, top, bottom; - int args[10], set[10] = { 0, }; - char response[MAX_RESPONSE] = {0, }; - struct rectangle allocation; - - terminal->escape[terminal->escape_length++] = '\0'; - i = 0; - p = &terminal->escape[2]; - while ((isdigit(*p) || *p == ';') && i < 10) { - if (*p == ';') { - if (!set[i]) { - args[i] = 0; - set[i] = 1; - } - p++; - i++; - } else { - args[i] = strtol(p, &p, 10); - set[i] = 1; - } - } - - switch (*p) { - case '@': /* ICH */ - count = set[0] ? args[0] : 1; - if (count == 0) count = 1; - terminal_shift_line(terminal, count); - break; - case 'A': /* CUU */ - count = set[0] ? args[0] : 1; - if (count == 0) count = 1; - if (terminal->row - count >= terminal->margin_top) - terminal->row -= count; - else - terminal->row = terminal->margin_top; - break; - case 'B': /* CUD */ - count = set[0] ? args[0] : 1; - if (count == 0) count = 1; - if (terminal->row + count <= terminal->margin_bottom) - terminal->row += count; - else - terminal->row = terminal->margin_bottom; - break; - case 'C': /* CUF */ - count = set[0] ? args[0] : 1; - if (count == 0) count = 1; - if ((terminal->column + count) < terminal->width) - terminal->column += count; - else - terminal->column = terminal->width - 1; - break; - case 'D': /* CUB */ - count = set[0] ? args[0] : 1; - if (count == 0) count = 1; - if ((terminal->column - count) >= 0) - terminal->column -= count; - else - terminal->column = 0; - break; - case 'E': /* CNL */ - count = set[0] ? args[0] : 1; - if (terminal->row + count <= terminal->margin_bottom) - terminal->row += count; - else - terminal->row = terminal->margin_bottom; - terminal->column = 0; - break; - case 'F': /* CPL */ - count = set[0] ? args[0] : 1; - if (terminal->row - count >= terminal->margin_top) - terminal->row -= count; - else - terminal->row = terminal->margin_top; - terminal->column = 0; - break; - case 'G': /* CHA */ - y = set[0] ? args[0] : 1; - y = y <= 0 ? 1 : y > terminal->width ? terminal->width : y; - - terminal->column = y - 1; - break; - case 'f': /* HVP */ - case 'H': /* CUP */ - x = (set[1] ? args[1] : 1) - 1; - x = x < 0 ? 0 : - (x >= terminal->width ? terminal->width - 1 : x); - - y = (set[0] ? args[0] : 1) - 1; - if (terminal->origin_mode) { - y += terminal->margin_top; - y = y < terminal->margin_top ? terminal->margin_top : - (y > terminal->margin_bottom ? terminal->margin_bottom : y); - } else { - y = y < 0 ? 0 : - (y >= terminal->height ? terminal->height - 1 : y); - } - - terminal->row = y; - terminal->column = x; - break; - case 'I': /* CHT */ - count = set[0] ? args[0] : 1; - if (count == 0) count = 1; - while (count > 0 && terminal->column < terminal->width) { - if (terminal->tab_ruler[terminal->column]) count--; - terminal->column++; - } - terminal->column--; - break; - case 'J': /* ED */ - row = terminal_get_row(terminal, terminal->row); - attr_row = terminal_get_attr_row(terminal, terminal->row); - if (!set[0] || args[0] == 0 || args[0] > 2) { - memset(&row[terminal->column], - 0, (terminal->width - terminal->column) * sizeof(union utf8_char)); - attr_init(&attr_row[terminal->column], - terminal->curr_attr, terminal->width - terminal->column); - for (i = terminal->row + 1; i < terminal->height; i++) { - memset(terminal_get_row(terminal, i), - 0, terminal->data_pitch); - attr_init(terminal_get_attr_row(terminal, i), - terminal->curr_attr, terminal->width); - } - } else if (args[0] == 1) { - memset(row, 0, (terminal->column+1) * sizeof(union utf8_char)); - attr_init(attr_row, terminal->curr_attr, terminal->column+1); - for (i = 0; i < terminal->row; i++) { - memset(terminal_get_row(terminal, i), - 0, terminal->data_pitch); - attr_init(terminal_get_attr_row(terminal, i), - terminal->curr_attr, terminal->width); - } - } else if (args[0] == 2) { - for (i = 0; i < terminal->height; i++) { - memset(terminal_get_row(terminal, i), - 0, terminal->data_pitch); - attr_init(terminal_get_attr_row(terminal, i), - terminal->curr_attr, terminal->width); - } - } - break; - case 'K': /* EL */ - row = terminal_get_row(terminal, terminal->row); - attr_row = terminal_get_attr_row(terminal, terminal->row); - if (!set[0] || args[0] == 0 || args[0] > 2) { - memset(&row[terminal->column], 0, - (terminal->width - terminal->column) * sizeof(union utf8_char)); - attr_init(&attr_row[terminal->column], terminal->curr_attr, - terminal->width - terminal->column); - } else if (args[0] == 1) { - memset(row, 0, (terminal->column+1) * sizeof(union utf8_char)); - attr_init(attr_row, terminal->curr_attr, terminal->column+1); - } else if (args[0] == 2) { - memset(row, 0, terminal->data_pitch); - attr_init(attr_row, terminal->curr_attr, terminal->width); - } - break; - case 'L': /* IL */ - count = set[0] ? args[0] : 1; - if (count == 0) count = 1; - if (terminal->row >= terminal->margin_top && - terminal->row < terminal->margin_bottom) - { - top = terminal->margin_top; - terminal->margin_top = terminal->row; - terminal_scroll(terminal, 0 - count); - terminal->margin_top = top; - } else if (terminal->row == terminal->margin_bottom) { - memset(terminal_get_row(terminal, terminal->row), - 0, terminal->data_pitch); - attr_init(terminal_get_attr_row(terminal, terminal->row), - terminal->curr_attr, terminal->width); - } - break; - case 'M': /* DL */ - count = set[0] ? args[0] : 1; - if (count == 0) count = 1; - if (terminal->row >= terminal->margin_top && - terminal->row < terminal->margin_bottom) - { - top = terminal->margin_top; - terminal->margin_top = terminal->row; - terminal_scroll(terminal, count); - terminal->margin_top = top; - } else if (terminal->row == terminal->margin_bottom) { - memset(terminal_get_row(terminal, terminal->row), - 0, terminal->data_pitch); - } - break; - case 'P': /* DCH */ - count = set[0] ? args[0] : 1; - if (count == 0) count = 1; - terminal_shift_line(terminal, 0 - count); - break; - case 'S': /* SU */ - terminal_scroll(terminal, set[0] ? args[0] : 1); - break; - case 'T': /* SD */ - terminal_scroll(terminal, 0 - (set[0] ? args[0] : 1)); - break; - case 'X': /* ECH */ - count = set[0] ? args[0] : 1; - if (count == 0) count = 1; - if ((terminal->column + count) > terminal->width) - count = terminal->width - terminal->column; - row = terminal_get_row(terminal, terminal->row); - attr_row = terminal_get_attr_row(terminal, terminal->row); - memset(&row[terminal->column], 0, count * sizeof(union utf8_char)); - attr_init(&attr_row[terminal->column], terminal->curr_attr, count); - break; - case 'Z': /* CBT */ - count = set[0] ? args[0] : 1; - if (count == 0) count = 1; - while (count > 0 && terminal->column >= 0) { - if (terminal->tab_ruler[terminal->column]) count--; - terminal->column--; - } - terminal->column++; - break; - case '`': /* HPA */ - y = set[0] ? args[0] : 1; - y = y <= 0 ? 1 : y > terminal->width ? terminal->width : y; - - terminal->column = y - 1; - break; - case 'b': /* REP */ - count = set[0] ? args[0] : 1; - if (count == 0) count = 1; - if (terminal->last_char.byte[0]) - for (i = 0; i < count; i++) - handle_char(terminal, terminal->last_char); - terminal->last_char.byte[0] = 0; - break; - case 'c': /* Primary DA */ - write(terminal->master, "\e[?6c", 5); - break; - case 'd': /* VPA */ - x = set[0] ? args[0] : 1; - x = x <= 0 ? 1 : x > terminal->height ? terminal->height : x; - - terminal->row = x - 1; - break; - case 'g': /* TBC */ - if (!set[0] || args[0] == 0) { - terminal->tab_ruler[terminal->column] = 0; - } else if (args[0] == 3) { - memset(terminal->tab_ruler, 0, terminal->width); - } - break; - case 'h': /* SM */ - for(i = 0; i < 10 && set[i]; i++) { - handle_term_parameter(terminal, args[i], 1); - } - break; - case 'l': /* RM */ - for(i = 0; i < 10 && set[i]; i++) { - handle_term_parameter(terminal, args[i], 0); - } - break; - case 'm': /* SGR */ - for(i = 0; i < 10; i++) { - if (i <= 7 && set[i] && set[i + 1] && - set[i + 2] && args[i + 1] == 5) - { - if (args[i] == 38) { - handle_sgr(terminal, args[i + 2] + 256); - break; - } else if (args[i] == 48) { - handle_sgr(terminal, args[i + 2] + 512); - break; - } - } - if(set[i]) { - handle_sgr(terminal, args[i]); - } else if(i == 0) { - handle_sgr(terminal, 0); - break; - } else { - break; - } - } - break; - case 'n': /* DSR */ - i = set[0] ? args[0] : 0; - if (i == 0 || i == 5) { - write(terminal->master, "\e[0n", 4); - } else if (i == 6) { - snprintf(response, MAX_RESPONSE, "\e[%d;%dR", - terminal->origin_mode ? - terminal->row+terminal->margin_top : terminal->row+1, - terminal->column+1); - write(terminal->master, response, strlen(response)); - } - break; - case 'r': - if(!set[0]) { - terminal->margin_top = 0; - terminal->margin_bottom = terminal->height-1; - terminal->row = 0; - terminal->column = 0; - } else { - top = (set[0] ? args[0] : 1) - 1; - top = top < 0 ? 0 : - (top >= terminal->height ? terminal->height - 1 : top); - bottom = (set[1] ? args[1] : 1) - 1; - bottom = bottom < 0 ? 0 : - (bottom >= terminal->height ? terminal->height - 1 : bottom); - if(bottom > top) { - terminal->margin_top = top; - terminal->margin_bottom = bottom; - } else { - terminal->margin_top = 0; - terminal->margin_bottom = terminal->height-1; - } - if(terminal->origin_mode) - terminal->row = terminal->margin_top; - else - terminal->row = 0; - terminal->column = 0; - } - break; - case 's': - terminal->saved_row = terminal->row; - terminal->saved_column = terminal->column; - break; - case 't': /* windowOps */ - if (!set[0]) break; - switch (args[0]) { - case 4: /* resize px */ - if (set[1] && set[2]) { - window_set_child_size(terminal->window, - args[2], args[1]); - resize_handler(terminal->window, - args[2], args[1], terminal); - } - break; - case 8: /* resize ch */ - if (set[1] && set[2]) { - terminal_resize(terminal, args[2], args[1]); - } - break; - case 13: /* report position */ - window_get_child_allocation(terminal->window, &allocation); - snprintf(response, MAX_RESPONSE, "\e[3;%d;%dt", - allocation.x, allocation.y); - write(terminal->master, response, strlen(response)); - break; - case 14: /* report px */ - window_get_child_allocation(terminal->window, &allocation); - snprintf(response, MAX_RESPONSE, "\e[4;%d;%dt", - allocation.height, allocation.width); - write(terminal->master, response, strlen(response)); - break; - case 18: /* report ch */ - snprintf(response, MAX_RESPONSE, "\e[9;%d;%dt", - terminal->height, terminal->width); - write(terminal->master, response, strlen(response)); - break; - case 21: /* report title */ - snprintf(response, MAX_RESPONSE, "\e]l%s\e\\", - window_get_title(terminal->window)); - write(terminal->master, response, strlen(response)); - break; - default: - if (args[0] >= 24) - terminal_resize(terminal, terminal->width, args[0]); - else - fprintf(stderr, "Unimplemented windowOp %d\n", args[0]); - break; - } - case 'u': - terminal->row = terminal->saved_row; - terminal->column = terminal->saved_column; - break; - default: - fprintf(stderr, "Unknown CSI escape: %c\n", *p); - break; - } -} - -static void -handle_non_csi_escape(struct terminal *terminal, char code) -{ - switch(code) { - case 'M': /* RI */ - terminal->row -= 1; - if(terminal->row < terminal->margin_top) { - terminal->row = terminal->margin_top; - terminal_scroll(terminal, -1); - } - break; - case 'E': /* NEL */ - terminal->column = 0; - // fallthrough - case 'D': /* IND */ - terminal->row += 1; - if(terminal->row > terminal->margin_bottom) { - terminal->row = terminal->margin_bottom; - terminal_scroll(terminal, +1); - } - break; - case 'c': /* RIS */ - terminal_init(terminal); - break; - case 'H': /* HTS */ - terminal->tab_ruler[terminal->column] = 1; - break; - case '7': /* DECSC */ - terminal->saved_row = terminal->row; - terminal->saved_column = terminal->column; - terminal->saved_attr = terminal->curr_attr; - terminal->saved_origin_mode = terminal->origin_mode; - terminal->saved_cs = terminal->cs; - terminal->saved_g0 = terminal->g0; - terminal->saved_g1 = terminal->g1; - break; - case '8': /* DECRC */ - terminal->row = terminal->saved_row; - terminal->column = terminal->saved_column; - terminal->curr_attr = terminal->saved_attr; - terminal->origin_mode = terminal->saved_origin_mode; - terminal->cs = terminal->saved_cs; - terminal->g0 = terminal->saved_g0; - terminal->g1 = terminal->saved_g1; - break; - case '=': /* DECPAM */ - terminal->key_mode = KM_APPLICATION; - break; - case '>': /* DECPNM */ - terminal->key_mode = KM_NORMAL; - break; - default: - fprintf(stderr, "Unknown escape code: %c\n", code); - break; - } -} - -static void -handle_special_escape(struct terminal *terminal, char special, char code) -{ - int i, numChars; - - if (special == '#') { - switch(code) { - case '8': - /* fill with 'E', no cheap way to do this */ - memset(terminal->data, 0, terminal->data_pitch * terminal->height); - numChars = terminal->width * terminal->height; - for(i = 0; i < numChars; i++) { - terminal->data[i].byte[0] = 'E'; - } - break; - default: - fprintf(stderr, "Unknown HASH escape #%c\n", code); - break; - } - } else if (special == '(' || special == ')') { - switch(code) { - case '0': - if (special == '(') - terminal->g0 = CS_SPECIAL; - else - terminal->g1 = CS_SPECIAL; - break; - case 'A': - if (special == '(') - terminal->g0 = CS_UK; - else - terminal->g1 = CS_UK; - break; - case 'B': - if (special == '(') - terminal->g0 = CS_US; - else - terminal->g1 = CS_US; - break; - default: - fprintf(stderr, "Unknown character set %c\n", code); - break; - } - } else { - fprintf(stderr, "Unknown special escape %c%c\n", special, code); - } -} - -static void -handle_sgr(struct terminal *terminal, int code) -{ - switch(code) { - case 0: - terminal->curr_attr = terminal->color_scheme->default_attr; - break; - case 1: - terminal->curr_attr.a |= ATTRMASK_BOLD; - if (terminal->curr_attr.fg < 8) - terminal->curr_attr.fg += 8; - break; - case 4: - terminal->curr_attr.a |= ATTRMASK_UNDERLINE; - break; - case 5: - terminal->curr_attr.a |= ATTRMASK_BLINK; - break; - case 8: - terminal->curr_attr.a |= ATTRMASK_CONCEALED; - break; - case 2: - case 21: - case 22: - terminal->curr_attr.a &= ~ATTRMASK_BOLD; - if (terminal->curr_attr.fg < 16 && terminal->curr_attr.fg >= 8) - terminal->curr_attr.fg -= 8; - break; - case 24: - terminal->curr_attr.a &= ~ATTRMASK_UNDERLINE; - break; - case 25: - terminal->curr_attr.a &= ~ATTRMASK_BLINK; - break; - case 7: - case 26: - terminal->curr_attr.a |= ATTRMASK_INVERSE; - break; - case 27: - terminal->curr_attr.a &= ~ATTRMASK_INVERSE; - break; - case 28: - terminal->curr_attr.a &= ~ATTRMASK_CONCEALED; - break; - case 39: - terminal->curr_attr.fg = terminal->color_scheme->default_attr.fg; - break; - case 49: - terminal->curr_attr.bg = terminal->color_scheme->default_attr.bg; - break; - default: - if(code >= 30 && code <= 37) { - terminal->curr_attr.fg = code - 30; - if (terminal->curr_attr.a & ATTRMASK_BOLD) - terminal->curr_attr.fg += 8; - } else if(code >= 40 && code <= 47) { - terminal->curr_attr.bg = code - 40; - } else if (code >= 90 && code <= 97) { - terminal->curr_attr.fg = code - 90 + 8; - } else if (code >= 100 && code <= 107) { - terminal->curr_attr.bg = code - 100 + 8; - } else if(code >= 256 && code < 512) { - terminal->curr_attr.fg = code - 256; - } else if(code >= 512 && code < 768) { - terminal->curr_attr.bg = code - 512; - } else { - fprintf(stderr, "Unknown SGR code: %d\n", code); - } - break; - } -} - -/* Returns 1 if c was special, otherwise 0 */ -static int -handle_special_char(struct terminal *terminal, char c) -{ - union utf8_char *row; - struct attr *attr_row; - - row = terminal_get_row(terminal, terminal->row); - attr_row = terminal_get_attr_row(terminal, terminal->row); - - switch(c) { - case '\r': - terminal->column = 0; - break; - case '\n': - if (terminal->mode & MODE_LF_NEWLINE) { - terminal->column = 0; - } - /* fallthrough */ - case '\v': - case '\f': - terminal->row++; - if(terminal->row > terminal->margin_bottom) { - terminal->row = terminal->margin_bottom; - terminal_scroll(terminal, +1); - } - - break; - case '\t': - while (terminal->column < terminal->width) { - if (terminal->tab_ruler[terminal->column]) break; - if (terminal->mode & MODE_IRM) - terminal_shift_line(terminal, +1); - row[terminal->column].byte[0] = ' '; - row[terminal->column].byte[1] = '\0'; - attr_row[terminal->column] = terminal->curr_attr; - terminal->column++; - } - if (terminal->column >= terminal->width) { - terminal->column = terminal->width - 1; - } - - break; - case '\b': - if (terminal->column >= terminal->width) { - terminal->column = terminal->width - 2; - } else if (terminal->column > 0) { - terminal->column--; - } else if (terminal->mode & MODE_AUTOWRAP) { - terminal->column = terminal->width - 1; - terminal->row -= 1; - if (terminal->row < terminal->margin_top) { - terminal->row = terminal->margin_top; - terminal_scroll(terminal, -1); - } - } - - break; - case '\a': - /* Bell */ - break; - case '\x0E': /* SO */ - terminal->cs = terminal->g1; - break; - case '\x0F': /* SI */ - terminal->cs = terminal->g0; - break; - default: - return 0; - } - - return 1; -} - -static void -handle_char(struct terminal *terminal, union utf8_char utf8) -{ - union utf8_char *row; - struct attr *attr_row; - - if (handle_special_char(terminal, utf8.byte[0])) return; - - apply_char_set(terminal->cs, &utf8); - - /* There are a whole lot of non-characters, control codes, - * and formatting codes that should probably be ignored, - * for example: */ - if (strncmp((char*) utf8.byte, "\xEF\xBB\xBF", 3) == 0) { - /* BOM, ignore */ - return; - } - - /* Some of these non-characters should be translated, e.g.: */ - if (utf8.byte[0] < 32) { - utf8.byte[0] = utf8.byte[0] + 64; - } - - /* handle right margin effects */ - if (terminal->column >= terminal->width) { - if (terminal->mode & MODE_AUTOWRAP) { - terminal->column = 0; - terminal->row += 1; - if (terminal->row > terminal->margin_bottom) { - terminal->row = terminal->margin_bottom; - terminal_scroll(terminal, +1); - } - } else { - terminal->column--; - } - } - - row = terminal_get_row(terminal, terminal->row); - attr_row = terminal_get_attr_row(terminal, terminal->row); - - if (terminal->mode & MODE_IRM) - terminal_shift_line(terminal, +1); - row[terminal->column] = utf8; - attr_row[terminal->column++] = terminal->curr_attr; - - if (utf8.ch != terminal->last_char.ch) - terminal->last_char = utf8; -} - -static void -escape_append_utf8(struct terminal *terminal, union utf8_char utf8) -{ - int len, i; - - if ((utf8.byte[0] & 0x80) == 0x00) len = 1; - else if ((utf8.byte[0] & 0xE0) == 0xC0) len = 2; - else if ((utf8.byte[0] & 0xF0) == 0xE0) len = 3; - else if ((utf8.byte[0] & 0xF8) == 0xF0) len = 4; - else len = 1; /* Invalid, cannot happen */ - - if (terminal->escape_length + len <= MAX_ESCAPE) { - for (i = 0; i < len; i++) - terminal->escape[terminal->escape_length + i] = utf8.byte[i]; - terminal->escape_length += len; - } else if (terminal->escape_length < MAX_ESCAPE) { - terminal->escape[terminal->escape_length++] = 0; - } -} - -static void -terminal_data(struct terminal *terminal, const char *data, size_t length) -{ - int i; - union utf8_char utf8; - enum utf8_state parser_state; - - for (i = 0; i < length; i++) { - parser_state = - utf8_next_char(&terminal->state_machine, data[i]); - switch(parser_state) { - case utf8state_accept: - utf8.ch = terminal->state_machine.s.ch; - break; - case utf8state_reject: - /* the unicode replacement character */ - utf8.byte[0] = 0xEF; - utf8.byte[1] = 0xBF; - utf8.byte[2] = 0xBD; - utf8.byte[3] = 0x00; - break; - default: - continue; - } - - /* assume escape codes never use non-ASCII characters */ - switch (terminal->state) { - case escape_state_escape: - escape_append_utf8(terminal, utf8); - switch (utf8.byte[0]) { - case 'P': /* DCS */ - terminal->state = escape_state_dcs; - break; - case '[': /* CSI */ - terminal->state = escape_state_csi; - break; - case ']': /* OSC */ - terminal->state = escape_state_osc; - break; - case '#': - case '(': - case ')': /* special */ - terminal->state = escape_state_special; - break; - case '^': /* PM (not implemented) */ - case '_': /* APC (not implemented) */ - terminal->state = escape_state_ignore; - break; - default: - terminal->state = escape_state_normal; - handle_non_csi_escape(terminal, utf8.byte[0]); - break; - } - continue; - case escape_state_csi: - if (handle_special_char(terminal, utf8.byte[0]) != 0) { - /* do nothing */ - } else if (utf8.byte[0] == '?') { - terminal->escape_flags |= ESC_FLAG_WHAT; - } else if (utf8.byte[0] == '>') { - terminal->escape_flags |= ESC_FLAG_GT; - } else if (utf8.byte[0] == '!') { - terminal->escape_flags |= ESC_FLAG_BANG; - } else if (utf8.byte[0] == '$') { - terminal->escape_flags |= ESC_FLAG_CASH; - } else if (utf8.byte[0] == '\'') { - terminal->escape_flags |= ESC_FLAG_SQUOTE; - } else if (utf8.byte[0] == '"') { - terminal->escape_flags |= ESC_FLAG_DQUOTE; - } else if (utf8.byte[0] == ' ') { - terminal->escape_flags |= ESC_FLAG_SPACE; - } else { - escape_append_utf8(terminal, utf8); - if (terminal->escape_length >= MAX_ESCAPE) - terminal->state = escape_state_normal; - } - - if (isalpha(utf8.byte[0]) || utf8.byte[0] == '@' || - utf8.byte[0] == '`') - { - terminal->state = escape_state_normal; - handle_escape(terminal); - } else { - } - continue; - case escape_state_inner_escape: - if (utf8.byte[0] == '\\') { - terminal->state = escape_state_normal; - if (terminal->outer_state == escape_state_dcs) { - handle_dcs(terminal); - } else if (terminal->outer_state == escape_state_osc) { - handle_osc(terminal); - } - } else if (utf8.byte[0] == '\e') { - terminal->state = terminal->outer_state; - escape_append_utf8(terminal, utf8); - if (terminal->escape_length >= MAX_ESCAPE) - terminal->state = escape_state_normal; - } else { - terminal->state = terminal->outer_state; - if (terminal->escape_length < MAX_ESCAPE) - terminal->escape[terminal->escape_length++] = '\e'; - escape_append_utf8(terminal, utf8); - if (terminal->escape_length >= MAX_ESCAPE) - terminal->state = escape_state_normal; - } - continue; - case escape_state_dcs: - case escape_state_osc: - case escape_state_ignore: - if (utf8.byte[0] == '\e') { - terminal->outer_state = terminal->state; - terminal->state = escape_state_inner_escape; - } else if (utf8.byte[0] == '\a' && terminal->state == escape_state_osc) { - terminal->state = escape_state_normal; - handle_osc(terminal); - } else { - escape_append_utf8(terminal, utf8); - if (terminal->escape_length >= MAX_ESCAPE) - terminal->state = escape_state_normal; - } - continue; - case escape_state_special: - escape_append_utf8(terminal, utf8); - terminal->state = escape_state_normal; - if (isdigit(utf8.byte[0]) || isalpha(utf8.byte[0])) { - handle_special_escape(terminal, terminal->escape[1], - utf8.byte[0]); - } - continue; - default: - break; - } - - /* this is valid, because ASCII characters are never used to - * introduce a multibyte sequence in UTF-8 */ - if (utf8.byte[0] == '\e') { - terminal->state = escape_state_escape; - terminal->outer_state = escape_state_normal; - terminal->escape[0] = '\e'; - terminal->escape_length = 1; - terminal->escape_flags = 0; - } else { - handle_char(terminal, utf8); - } /* if */ - } /* for */ - - window_schedule_redraw(terminal->window); -} - -static void -selection_listener_send(void *data, struct wl_selection *selection, - const char *mime_type, int fd) -{ - struct terminal *terminal = data; - - fprintf(stderr, "selection send, fd is %d\n", fd); - terminal_send_selection(terminal, fd); - close(fd); -} - -static void -selection_listener_cancelled(void *data, struct wl_selection *selection) -{ - fprintf(stderr, "selection cancelled\n"); - wl_selection_destroy(selection); -} - -static const struct wl_selection_listener selection_listener = { - selection_listener_send, - selection_listener_cancelled -}; - -static int -handle_bound_key(struct terminal *terminal, - struct input *input, uint32_t sym, uint32_t time) -{ - struct wl_shell *shell; - - switch (sym) { - case XK_C: - shell = display_get_shell(terminal->display); - terminal->selection = wl_shell_create_selection(shell); - wl_selection_add_listener(terminal->selection, - &selection_listener, terminal); - wl_selection_offer(terminal->selection, "text/plain"); - wl_selection_activate(terminal->selection, - input_get_input_device(input), time); - - return 1; - case XK_V: - /* Just pass the master fd of the pty to receive the - * selection. */ - if (input_offers_mime_type(input, "text/plain")) - input_receive_mime_type(input, "text/plain", - terminal->master); - return 1; - case XK_X: - /* cut selection; terminal doesn't do cut */ - return 0; - default: - return 0; - } -} - -static void -key_handler(struct window *window, struct input *input, uint32_t time, - uint32_t key, uint32_t sym, uint32_t state, void *data) -{ - struct terminal *terminal = data; - char ch[MAX_RESPONSE]; - uint32_t modifiers; - int len = 0; - - modifiers = input_get_modifiers(input); - if ((modifiers & XKB_COMMON_CONTROL_MASK) && - (modifiers & XKB_COMMON_SHIFT_MASK) && - state && handle_bound_key(terminal, input, sym, 0)) - return; - - switch (sym) { - case XK_F11: - if (!state) - break; - terminal->fullscreen ^= 1; - window_set_fullscreen(window, terminal->fullscreen); - window_schedule_redraw(terminal->window); - break; - - case XK_BackSpace: - case XK_Tab: - case XK_Linefeed: - case XK_Clear: - case XK_Pause: - case XK_Scroll_Lock: - case XK_Sys_Req: - case XK_Escape: - ch[len++] = sym & 0x7f; - break; - - case XK_Return: - if (terminal->mode & MODE_LF_NEWLINE) { - ch[len++] = 0x0D; - ch[len++] = 0x0A; - } else { - ch[len++] = 0x0D; - } - break; - - case XK_Shift_L: - case XK_Shift_R: - case XK_Control_L: - case XK_Control_R: - case XK_Alt_L: - case XK_Alt_R: - break; - - case XK_Insert: - len = function_key_response('[', 2, modifiers, '~', ch); - break; - case XK_Delete: - if (terminal->mode & MODE_DELETE_SENDS_DEL) { - ch[len++] = '\x04'; - } else { - len = function_key_response('[', 3, modifiers, '~', ch); - } - break; - case XK_Page_Up: - len = function_key_response('[', 5, modifiers, '~', ch); - break; - case XK_Page_Down: - len = function_key_response('[', 6, modifiers, '~', ch); - break; - case XK_F1: - len = function_key_response('O', 1, modifiers, 'P', ch); - break; - case XK_F2: - len = function_key_response('O', 1, modifiers, 'Q', ch); - break; - case XK_F3: - len = function_key_response('O', 1, modifiers, 'R', ch); - break; - case XK_F4: - len = function_key_response('O', 1, modifiers, 'S', ch); - break; - case XK_F5: - len = function_key_response('[', 15, modifiers, '~', ch); - break; - case XK_F6: - len = function_key_response('[', 17, modifiers, '~', ch); - break; - case XK_F7: - len = function_key_response('[', 18, modifiers, '~', ch); - break; - case XK_F8: - len = function_key_response('[', 19, modifiers, '~', ch); - break; - case XK_F9: - len = function_key_response('[', 20, modifiers, '~', ch); - break; - case XK_F10: - len = function_key_response('[', 21, modifiers, '~', ch); - break; - case XK_F12: - len = function_key_response('[', 24, modifiers, '~', ch); - break; - default: - /* Handle special keys with alternate mappings */ - len = apply_key_map(terminal->key_mode, sym, modifiers, ch); - if (len != 0) break; - - if (modifiers & XKB_COMMON_CONTROL_MASK) { - if (sym >= '3' && sym <= '7') - sym = (sym & 0x1f) + 8; - - if (!((sym >= '!' && sym <= '/') || - (sym >= '8' && sym <= '?') || - (sym >= '0' && sym <= '2'))) sym = sym & 0x1f; - else if (sym == '2') sym = 0x00; - else if (sym == '/') sym = 0x1F; - else if (sym == '8' || sym == '?') sym = 0x7F; - } else if ((terminal->mode & MODE_ALT_SENDS_ESC) && - (modifiers & XKB_COMMON_MOD1_MASK)) - { - ch[len++] = 0x1b; - } else if (modifiers & XKB_COMMON_MOD1_MASK) { - sym = sym | 0x80; - } - - if (sym < 256) - ch[len++] = sym; - break; - } - - if (state && len > 0) - write(terminal->master, ch, len); -} - -static void -keyboard_focus_handler(struct window *window, - struct input *device, void *data) -{ - struct terminal *terminal = data; - - terminal->focused = (device != NULL); - window_schedule_redraw(terminal->window); -} - -static void -button_handler(struct window *window, - struct input *input, uint32_t time, - int button, int state, void *data) -{ - struct terminal *terminal = data; - - switch (button) { - case 272: - if (state) { - terminal->dragging = 1; - terminal->selection_active = 0; - input_get_position(input, - &terminal->selection_start_x, - &terminal->selection_start_y); - terminal->selection_end_x = terminal->selection_start_x; - terminal->selection_end_y = terminal->selection_start_y; - window_schedule_redraw(window); - } else { - terminal->dragging = 0; - } - break; - } -} - -static int -motion_handler(struct window *window, - struct input *input, uint32_t time, - int32_t x, int32_t y, - int32_t sx, int32_t sy, void *data) -{ - struct terminal *terminal = data; - - if (terminal->dragging) { - terminal->selection_active = 1; - input_get_position(input, - &terminal->selection_end_x, - &terminal->selection_end_y); - window_schedule_redraw(window); - } - - return POINTER_IBEAM; -} - -static struct terminal * -terminal_create(struct display *display, int fullscreen) -{ - struct terminal *terminal; - cairo_surface_t *surface; - cairo_t *cr; - - terminal = malloc(sizeof *terminal); - if (terminal == NULL) - return terminal; - - memset(terminal, 0, sizeof *terminal); - terminal->fullscreen = fullscreen; - terminal->color_scheme = &DEFAULT_COLORS; - terminal_init(terminal); - terminal->margin_top = 0; - terminal->margin_bottom = -1; - terminal->window = window_create(display, 500, 400); - window_set_title(terminal->window, "Wayland Terminal"); - - init_state_machine(&terminal->state_machine); - init_color_table(terminal); - - terminal->display = display; - terminal->margin = 5; - - window_set_user_data(terminal->window, terminal); - window_set_redraw_handler(terminal->window, redraw_handler); - window_set_resize_handler(terminal->window, resize_handler); - - window_set_key_handler(terminal->window, key_handler); - window_set_keyboard_focus_handler(terminal->window, - keyboard_focus_handler); - window_set_button_handler(terminal->window, button_handler); - window_set_motion_handler(terminal->window, motion_handler); - - surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 0, 0); - cr = cairo_create(surface); - cairo_set_font_size(cr, 14); - cairo_select_font_face (cr, "mono", - CAIRO_FONT_SLANT_NORMAL, - CAIRO_FONT_WEIGHT_BOLD); - terminal->font_bold = cairo_get_scaled_font (cr); - cairo_scaled_font_reference(terminal->font_bold); - - cairo_select_font_face (cr, "mono", - CAIRO_FONT_SLANT_NORMAL, - CAIRO_FONT_WEIGHT_NORMAL); - terminal->font_normal = cairo_get_scaled_font (cr); - cairo_scaled_font_reference(terminal->font_normal); - - cairo_font_extents(cr, &terminal->extents); - cairo_destroy(cr); - cairo_surface_destroy(surface); - - terminal_resize(terminal, 80, 24); - terminal_draw(terminal); - - return terminal; -} - -static gboolean -io_handler(GIOChannel *source, - GIOCondition condition, - gpointer data) -{ - struct terminal *terminal = data; - gchar buffer[256]; - gsize bytes_read; - GError *error = NULL; - - if(condition == G_IO_HUP) - exit(0); - - g_io_channel_read_chars(source, buffer, sizeof buffer, - &bytes_read, &error); - - terminal_data(terminal, buffer, bytes_read); - - return TRUE; -} - -static int -terminal_run(struct terminal *terminal, const char *path) -{ - int master; - pid_t pid; - - pid = forkpty(&master, NULL, NULL, NULL); - if (pid == 0) { - setenv("TERM", "xterm-256color", 1); - setenv("COLORTERM", "xterm-256color", 1); - if (execl(path, path, NULL)) { - printf("exec failed: %m\n"); - exit(EXIT_FAILURE); - } - } else if (pid < 0) { - fprintf(stderr, "failed to fork and create pty (%m).\n"); - return -1; - } - - terminal->master = master; - terminal->channel = g_io_channel_unix_new(master); - fcntl(master, F_SETFL, O_NONBLOCK); - g_io_add_watch(terminal->channel, G_IO_IN, io_handler, terminal); - g_io_add_watch(terminal->channel, G_IO_HUP, io_handler, terminal); - - return 0; -} - -static const GOptionEntry option_entries[] = { - { "fullscreen", 'f', 0, G_OPTION_ARG_NONE, - &option_fullscreen, "Run in fullscreen mode" }, - { NULL } -}; - -int main(int argc, char *argv[]) -{ - struct display *d; - struct terminal *terminal; - - d = display_create(&argc, &argv, option_entries); - if (d == NULL) { - fprintf(stderr, "failed to create display: %m\n"); - return -1; - } - - terminal = terminal_create(d, option_fullscreen); - if (terminal_run(terminal, "/bin/bash")) - exit(EXIT_FAILURE); - - display_run(d); - - return 0; -} diff --git a/clients/view.c b/clients/view.c deleted file mode 100644 index 05edf3f..0000000 --- a/clients/view.c +++ /dev/null @@ -1,268 +0,0 @@ -/* - * Copyright © 2008 Kristian Høgsberg - * Copyright © 2009 Chris Wilson - * - * 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 <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <fcntl.h> -#include <unistd.h> -#include <math.h> -#include <time.h> -#include <cairo.h> -#include <glib.h> -#include <linux/input.h> - -#include <glib/poppler-document.h> -#include <glib/poppler-page.h> - -#include "wayland-util.h" -#include "wayland-client.h" -#include "wayland-glib.h" - -#include "window.h" - -struct view { - struct window *window; - struct display *display; - - PopplerDocument *document; - int page; - int fullscreen; -}; - -static void -view_draw(struct view *view) -{ - struct rectangle allocation; - cairo_surface_t *surface; - cairo_t *cr; - PopplerPage *page; - double width, height, doc_aspect, window_aspect, scale; - - window_draw(view->window); - - window_get_child_allocation(view->window, &allocation); - - surface = window_get_surface(view->window); - - cr = cairo_create(surface); - cairo_rectangle(cr, allocation.x, allocation.y, - allocation.width, allocation.height); - cairo_clip(cr); - - cairo_set_source_rgba(cr, 0, 0, 0, 0.8); - cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); - cairo_paint(cr); - - if(!view->document) { - cairo_destroy(cr); - cairo_surface_destroy(surface); - window_flush(view->window); - return; - } - - page = poppler_document_get_page(view->document, view->page); - poppler_page_get_size(page, &width, &height); - doc_aspect = width / height; - window_aspect = (double) allocation.width / allocation.height; - if (doc_aspect < window_aspect) - scale = allocation.height / height; - else - scale = allocation.width / width; - cairo_translate(cr, allocation.x, allocation.y); - cairo_scale(cr, scale, scale); - cairo_translate(cr, - (allocation.width - width * scale) / 2 / scale, - (allocation.height - height * scale) / 2 / scale); - cairo_rectangle(cr, 0, 0, width, height); - cairo_set_operator(cr, CAIRO_OPERATOR_OVER); - cairo_set_source_rgb(cr, 1, 1, 1); - cairo_fill(cr); - poppler_page_render(page, cr); - cairo_destroy(cr); - cairo_surface_destroy(surface); - g_object_unref(G_OBJECT(page)); - window_flush(view->window); -} - -static void -redraw_handler(struct window *window, void *data) -{ - struct view *view = data; - - view_draw(view); -} - -static void -view_page_up(struct view *view) -{ - if(view->page <= 0) - return; - - view->page--; - window_schedule_redraw(view->window); -} - -static void -view_page_down(struct view *view) -{ - if(!view->document || - view->page >= poppler_document_get_n_pages(view->document) - 1) { - return; - } - - view->page++; - window_schedule_redraw(view->window); -} - -static void -button_handler(struct window *window, struct input *input, uint32_t time, - int button, int state, void *data) -{ - struct view *view = data; - - if(!state) - return; - - switch(button) { - case 275: - view_page_up(view); - break; - case 276: - view_page_down(view); - break; - default: - break; - } -} - -static void -key_handler(struct window *window, struct input *input, uint32_t time, - uint32_t key, uint32_t unicode, uint32_t state, void *data) -{ - struct view *view = data; - - if(!state) - return; - - switch (key) { - case KEY_F11: - view->fullscreen ^= 1; - window_set_fullscreen(window, view->fullscreen); - window_schedule_redraw(view->window); - break; - case KEY_SPACE: - case KEY_PAGEDOWN: - case KEY_RIGHT: - case KEY_DOWN: - view_page_down(view); - break; - case KEY_BACKSPACE: - case KEY_PAGEUP: - case KEY_LEFT: - case KEY_UP: - view_page_up(view); - break; - default: - break; - } -} - -static void -keyboard_focus_handler(struct window *window, - struct input *device, void *data) -{ - struct view *view = data; - window_schedule_redraw(view->window); -} - -static struct view * -view_create(struct display *display, uint32_t key, const char *filename) -{ - struct view *view; - gchar *basename; - gchar *title; - GFile *file = NULL; - GError *error = NULL; - - view = malloc(sizeof *view); - if (view == NULL) - return view; - memset(view, 0, sizeof *view); - - file = g_file_new_for_commandline_arg(filename); - basename = g_file_get_basename(file); - if(!basename) { - title = "Wayland View"; - } else { - title = g_strdup_printf("Wayland View - %s", basename); - g_free(basename); - } - - view->document = poppler_document_new_from_file(g_file_get_uri(file), - NULL, &error); - - if(error) { - title = "File not found"; - } - - view->window = window_create(display, 500, 400); - window_set_title(view->window, title); - view->display = display; - - window_set_user_data(view->window, view); - window_set_redraw_handler(view->window, redraw_handler); - window_set_key_handler(view->window, key_handler); - window_set_keyboard_focus_handler(view->window, - keyboard_focus_handler); - window_set_button_handler(view->window, button_handler); - view->page = 0; - view_draw(view); - - return view; -} - -static const GOptionEntry option_entries[] = { - { NULL } -}; - -int -main(int argc, char *argv[]) -{ - struct display *d; - int i; - - d = display_create(&argc, &argv, option_entries); - if (d == NULL) { - fprintf(stderr, "failed to create display: %m\n"); - return -1; - } - - for (i = 1; i < argc; i++) - view_create (d, i, argv[i]); - - display_run(d); - - return 0; -} diff --git a/clients/wayland-glib.c b/clients/wayland-glib.c deleted file mode 100644 index fa7a9f5..0000000 --- a/clients/wayland-glib.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright © 2008 Kristian Høgsberg - * - * 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 <stdint.h> -#include <glib/giochannel.h> -#include "wayland-client.h" -#include "wayland-glib.h" - -typedef struct _WlSource { - GSource source; - GPollFD pfd; - uint32_t mask; - struct wl_display *display; -} WlSource; - -static gboolean -wl_glib_source_prepare(GSource *base, gint *timeout) -{ - WlSource *source = (WlSource *) base; - - *timeout = -1; - - /* We have to add/remove the GPollFD if we want to update our - * poll event mask dynamically. Instead, let's just flush all - * write on idle instead, which is what this amounts to. */ - - while (source->mask & WL_DISPLAY_WRITABLE) - wl_display_iterate(source->display, - WL_DISPLAY_WRITABLE); - - return FALSE; -} - -static gboolean -wl_glib_source_check(GSource *base) -{ - WlSource *source = (WlSource *) base; - - return source->pfd.revents; -} - -static gboolean -wl_glib_source_dispatch(GSource *base, - GSourceFunc callback, - gpointer data) -{ - WlSource *source = (WlSource *) base; - - wl_display_iterate(source->display, - WL_DISPLAY_READABLE); - - return TRUE; -} - -static GSourceFuncs wl_glib_source_funcs = { - wl_glib_source_prepare, - wl_glib_source_check, - wl_glib_source_dispatch, - NULL -}; - -static int -wl_glib_source_update(uint32_t mask, void *data) -{ - WlSource *source = data; - - source->mask = mask; - - return 0; -} - -GSource * -wl_glib_source_new(struct wl_display *display) -{ - WlSource *source; - - source = (WlSource *) g_source_new(&wl_glib_source_funcs, - sizeof (WlSource)); - source->display = display; - source->pfd.fd = wl_display_get_fd(display, - wl_glib_source_update, source); - source->pfd.events = G_IO_IN | G_IO_ERR; - g_source_add_poll(&source->source, &source->pfd); - - return &source->source; -} diff --git a/clients/wayland-glib.h b/clients/wayland-glib.h deleted file mode 100644 index 13ff2ca..0000000 --- a/clients/wayland-glib.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright © 2008 Kristian Høgsberg - * - * 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. - */ - -#ifndef _WAYLAND_GLIB_H_ -#define _WAYLAND_GLIB_H_ - -#include <glib/gmain.h> -#include <wayland-client.h> - -GSource *wl_glib_source_new(struct wl_display *display); - - -#endif diff --git a/clients/window.c b/clients/window.c deleted file mode 100644 index 0c93b9c..0000000 --- a/clients/window.c +++ /dev/null @@ -1,1741 +0,0 @@ -/* - * Copyright © 2008 Kristian Høgsberg - * - * 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 "../config.h" - -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <fcntl.h> -#include <unistd.h> -#include <math.h> -#include <time.h> -#include <cairo.h> -#include <glib.h> -#include <glib-object.h> -#include <gdk-pixbuf/gdk-pixbuf.h> -#include <sys/mman.h> - -#include <wayland-egl.h> - -#include <GL/gl.h> -#include <EGL/egl.h> -#include <EGL/eglext.h> - -#ifdef HAVE_CAIRO_EGL -#include <cairo-gl.h> -#endif - -#include <X11/extensions/XKBcommon.h> - -#include <linux/input.h> -#include "wayland-util.h" -#include "wayland-client.h" -#include "wayland-glib.h" -#include "cairo-util.h" - -#include "window.h" - -struct display { - struct wl_display *display; - struct wl_egl_display *native_dpy; - struct wl_compositor *compositor; - struct wl_shell *shell; - struct wl_shm *shm; - struct wl_output *output; - struct rectangle screen_allocation; - int authenticated; - EGLDisplay dpy; - EGLContext ctx; - cairo_device_t *device; - int fd; - GMainLoop *loop; - GSource *source; - struct wl_list window_list; - struct wl_list input_list; - char *device_name; - cairo_surface_t *active_frame, *inactive_frame, *shadow; - struct xkb_desc *xkb; - cairo_surface_t **pointer_surfaces; - - display_global_handler_t global_handler; - - PFNGLEGLIMAGETARGETTEXTURE2DOESPROC image_target_texture_2d; - PFNEGLCREATEIMAGEKHRPROC create_image; - PFNEGLDESTROYIMAGEKHRPROC destroy_image; -}; - -struct window { - struct display *display; - struct window *parent; - struct wl_surface *surface; - char *title; - struct rectangle allocation, saved_allocation, server_allocation; - int x, y; - int resize_edges; - int redraw_scheduled; - int minimum_width, minimum_height; - int margin; - int fullscreen; - int decoration; - struct input *grab_device; - struct input *keyboard_device; - uint32_t name; - enum window_buffer_type buffer_type; - - EGLImageKHR *image; - cairo_surface_t *cairo_surface, *pending_surface; - - window_resize_handler_t resize_handler; - window_redraw_handler_t redraw_handler; - window_key_handler_t key_handler; - window_button_handler_t button_handler; - window_keyboard_focus_handler_t keyboard_focus_handler; - window_motion_handler_t motion_handler; - - void *user_data; - struct wl_list link; -}; - -struct input { - struct display *display; - struct wl_input_device *input_device; - struct window *pointer_focus; - struct window *keyboard_focus; - struct selection_offer *offer; - uint32_t current_pointer_image; - uint32_t modifiers; - int32_t x, y, sx, sy; - struct wl_list link; -}; - -enum { - POINTER_DEFAULT = 100, - POINTER_UNSET -}; - -enum window_location { - WINDOW_INTERIOR = 0, - WINDOW_RESIZING_TOP = 1, - WINDOW_RESIZING_BOTTOM = 2, - WINDOW_RESIZING_LEFT = 4, - WINDOW_RESIZING_TOP_LEFT = 5, - WINDOW_RESIZING_BOTTOM_LEFT = 6, - WINDOW_RESIZING_RIGHT = 8, - WINDOW_RESIZING_TOP_RIGHT = 9, - WINDOW_RESIZING_BOTTOM_RIGHT = 10, - WINDOW_RESIZING_MASK = 15, - WINDOW_EXTERIOR = 16, - WINDOW_TITLEBAR = 17, - WINDOW_CLIENT_AREA = 18, -}; - -const char *option_xkb_layout = "us"; -const char *option_xkb_variant = ""; -const char *option_xkb_options = ""; - -static const GOptionEntry xkb_option_entries[] = { - { "xkb-layout", 0, 0, G_OPTION_ARG_STRING, - &option_xkb_layout, "XKB Layout" }, - { "xkb-variant", 0, 0, G_OPTION_ARG_STRING, - &option_xkb_variant, "XKB Variant" }, - { "xkb-options", 0, 0, G_OPTION_ARG_STRING, - &option_xkb_options, "XKB Options" }, - { NULL } -}; - -static void -rounded_rect(cairo_t *cr, int x0, int y0, int x1, int y1, int radius) -{ - cairo_move_to(cr, x0, y0 + radius); - cairo_arc(cr, x0 + radius, y0 + radius, radius, M_PI, 3 * M_PI / 2); - cairo_line_to(cr, x1 - radius, y0); - cairo_arc(cr, x1 - radius, y0 + radius, radius, 3 * M_PI / 2, 2 * M_PI); - cairo_line_to(cr, x1, y1 - radius); - cairo_arc(cr, x1 - radius, y1 - radius, radius, 0, M_PI / 2); - cairo_line_to(cr, x0 + radius, y1); - cairo_arc(cr, x0 + radius, y1 - radius, radius, M_PI / 2, M_PI); - cairo_close_path(cr); -} - -static const cairo_user_data_key_t surface_data_key; -struct surface_data { - struct wl_buffer *buffer; -}; - -#define MULT(_d,c,a,t) \ - do { t = c * a + 0x7f; _d = ((t >> 8) + t) >> 8; } while (0) - -#ifdef HAVE_CAIRO_EGL - -struct egl_image_surface_data { - struct surface_data data; - EGLImageKHR image; - GLuint texture; - struct display *display; - struct wl_egl_pixmap *pixmap; -}; - -static void -egl_image_surface_data_destroy(void *p) -{ - struct egl_image_surface_data *data = p; - struct display *d = data->display; - - cairo_device_acquire(d->device); - glDeleteTextures(1, &data->texture); - cairo_device_release(d->device); - - d->destroy_image(d->dpy, data->image); - wl_buffer_destroy(data->data.buffer); - wl_egl_pixmap_destroy(data->pixmap); - free(p); -} - -EGLImageKHR -display_get_image_for_egl_image_surface(struct display *display, - cairo_surface_t *surface) -{ - struct egl_image_surface_data *data; - - data = cairo_surface_get_user_data (surface, &surface_data_key); - - return data->image; -} - -static cairo_surface_t * -display_create_egl_image_surface(struct display *display, - struct rectangle *rectangle) -{ - struct egl_image_surface_data *data; - EGLDisplay dpy = display->dpy; - cairo_surface_t *surface; - struct wl_visual *visual; - - data = malloc(sizeof *data); - if (data == NULL) - return NULL; - - data->display = display; - - visual = wl_display_get_premultiplied_argb_visual(display->display); - data->pixmap =wl_egl_pixmap_create(display->native_dpy, - rectangle->width, - rectangle->height, - visual, 0); - if (data->pixmap == NULL) { - free(data); - return NULL; - } - - data->image = display->create_image(dpy, NULL, - EGL_NATIVE_PIXMAP_KHR, - (EGLClientBuffer) data->pixmap, - NULL); - if (data->image == EGL_NO_IMAGE_KHR) { - wl_egl_pixmap_destroy(data->pixmap); - free(data); - return NULL; - } - - data->data.buffer = - wl_egl_pixmap_create_buffer(display->native_dpy, data->pixmap); - - cairo_device_acquire(display->device); - glGenTextures(1, &data->texture); - glBindTexture(GL_TEXTURE_2D, data->texture); - display->image_target_texture_2d(GL_TEXTURE_2D, data->image); - cairo_device_release(display->device); - - surface = cairo_gl_surface_create_for_texture(display->device, - CAIRO_CONTENT_COLOR_ALPHA, - data->texture, - rectangle->width, - rectangle->height); - - cairo_surface_set_user_data (surface, &surface_data_key, - data, egl_image_surface_data_destroy); - - return surface; -} - -static cairo_surface_t * -display_create_egl_image_surface_from_file(struct display *display, - const char *filename, - struct rectangle *rect) -{ - cairo_surface_t *surface; - GdkPixbuf *pixbuf; - GError *error = NULL; - int stride, i; - unsigned char *pixels, *p, *end; - struct egl_image_surface_data *data; - - pixbuf = gdk_pixbuf_new_from_file_at_scale(filename, - rect->width, rect->height, - FALSE, &error); - if (error != NULL) - return NULL; - - if (!gdk_pixbuf_get_has_alpha(pixbuf) || - gdk_pixbuf_get_n_channels(pixbuf) != 4) { - g_object_unref(pixbuf); - return NULL; - } - - - stride = gdk_pixbuf_get_rowstride(pixbuf); - pixels = gdk_pixbuf_get_pixels(pixbuf); - - for (i = 0; i < rect->height; i++) { - p = pixels + i * stride; - end = p + rect->width * 4; - while (p < end) { - unsigned int t; - - MULT(p[0], p[0], p[3], t); - MULT(p[1], p[1], p[3], t); - MULT(p[2], p[2], p[3], t); - p += 4; - - } - } - - surface = display_create_egl_image_surface(display, rect); - if (surface == NULL) { - g_object_unref(pixbuf); - return NULL; - } - - data = cairo_surface_get_user_data(surface, &surface_data_key); - - cairo_device_acquire(display->device); - glBindTexture(GL_TEXTURE_2D, data->texture); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, rect->width, rect->height, - GL_RGBA, GL_UNSIGNED_BYTE, pixels); - cairo_device_release(display->device); - - g_object_unref(pixbuf); - - return surface; -} - -#endif - -struct wl_buffer * -display_get_buffer_for_surface(struct display *display, - cairo_surface_t *surface) -{ - struct surface_data *data; - - data = cairo_surface_get_user_data (surface, &surface_data_key); - - return data->buffer; -} - -struct shm_surface_data { - struct surface_data data; - void *map; - size_t length; -}; - -static void -shm_surface_data_destroy(void *p) -{ - struct shm_surface_data *data = p; - - wl_buffer_destroy(data->data.buffer); - munmap(data->map, data->length); -} - -static cairo_surface_t * -display_create_shm_surface(struct display *display, - struct rectangle *rectangle) -{ - struct shm_surface_data *data; - cairo_surface_t *surface; - struct wl_visual *visual; - int stride, fd; - char filename[] = "/tmp/wayland-shm-XXXXXX"; - - data = malloc(sizeof *data); - if (data == NULL) - return NULL; - - stride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32, - rectangle->width); - data->length = stride * rectangle->height; - fd = mkstemp(filename); - if (fd < 0) { - fprintf(stderr, "open %s failed: %m\n", filename); - return NULL; - } - if (ftruncate(fd, data->length) < 0) { - fprintf(stderr, "ftruncate failed: %m\n"); - close(fd); - return NULL; - } - - data->map = mmap(NULL, data->length, - PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - unlink(filename); - - if (data->map == MAP_FAILED) { - fprintf(stderr, "mmap failed: %m\n"); - close(fd); - return NULL; - } - - surface = cairo_image_surface_create_for_data (data->map, - CAIRO_FORMAT_ARGB32, - rectangle->width, - rectangle->height, - stride); - - cairo_surface_set_user_data (surface, &surface_data_key, - data, shm_surface_data_destroy); - - visual = wl_display_get_premultiplied_argb_visual(display->display); - data->data.buffer = wl_shm_create_buffer(display->shm, - fd, - rectangle->width, - rectangle->height, - stride, visual); - - close(fd); - - return surface; -} - -static cairo_surface_t * -display_create_shm_surface_from_file(struct display *display, - const char *filename, - struct rectangle *rect) -{ - cairo_surface_t *surface; - GdkPixbuf *pixbuf; - GError *error = NULL; - int stride, i; - unsigned char *pixels, *p, *end, *dest_data; - int dest_stride; - uint32_t *d; - - pixbuf = gdk_pixbuf_new_from_file_at_scale(filename, - rect->width, rect->height, - FALSE, &error); - if (error != NULL) - return NULL; - - if (!gdk_pixbuf_get_has_alpha(pixbuf) || - gdk_pixbuf_get_n_channels(pixbuf) != 4) { - g_object_unref(pixbuf); - return NULL; - } - - stride = gdk_pixbuf_get_rowstride(pixbuf); - pixels = gdk_pixbuf_get_pixels(pixbuf); - - surface = display_create_shm_surface(display, rect); - if (surface == NULL) { - g_object_unref(pixbuf); - return NULL; - } - - dest_data = cairo_image_surface_get_data (surface); - dest_stride = cairo_image_surface_get_stride (surface); - - for (i = 0; i < rect->height; i++) { - d = (uint32_t *) (dest_data + i * dest_stride); - p = pixels + i * stride; - end = p + rect->width * 4; - while (p < end) { - unsigned int t; - unsigned char a, r, g, b; - - a = p[3]; - MULT(r, p[0], a, t); - MULT(g, p[1], a, t); - MULT(b, p[2], a, t); - p += 4; - *d++ = (a << 24) | (r << 16) | (g << 8) | b; - } - } - - g_object_unref(pixbuf); - - return surface; -} - -static int -check_size(struct rectangle *rect) -{ - if (rect->width && rect->height) - return 0; - - fprintf(stderr, "tried to create surface of " - "width: %d, height: %d\n", rect->width, rect->height); - return -1; -} - -cairo_surface_t * -display_create_surface(struct display *display, - struct rectangle *rectangle) -{ - if (check_size(rectangle) < 0) - return NULL; -#ifdef HAVE_CAIRO_EGL - if (display->dpy) { - return display_create_egl_image_surface(display, rectangle); - } -#endif - return display_create_shm_surface(display, rectangle); -} - -static cairo_surface_t * -display_create_surface_from_file(struct display *display, - const char *filename, - struct rectangle *rectangle) -{ - if (check_size(rectangle) < 0) - return NULL; -#ifdef HAVE_CAIRO_EGL - if (display->dpy) { - return display_create_egl_image_surface_from_file(display, - filename, - rectangle); - } -#endif - return display_create_shm_surface_from_file(display, filename, rectangle); -} - static const struct { - const char *filename; - int hotspot_x, hotspot_y; -} pointer_images[] = { - { DATADIR "/wayland/bottom_left_corner.png", 6, 30 }, - { DATADIR "/wayland/bottom_right_corner.png", 28, 28 }, - { DATADIR "/wayland/bottom_side.png", 16, 20 }, - { DATADIR "/wayland/grabbing.png", 20, 17 }, - { DATADIR "/wayland/left_ptr.png", 10, 5 }, - { DATADIR "/wayland/left_side.png", 10, 20 }, - { DATADIR "/wayland/right_side.png", 30, 19 }, - { DATADIR "/wayland/top_left_corner.png", 8, 8 }, - { DATADIR "/wayland/top_right_corner.png", 26, 8 }, - { DATADIR "/wayland/top_side.png", 18, 8 }, - { DATADIR "/wayland/xterm.png", 15, 15 }, - { DATADIR "/wayland/hand1.png", 18, 11 } -}; - -static void -create_pointer_surfaces(struct display *display) -{ - int i, count; - const int width = 32, height = 32; - struct rectangle rect; - - count = ARRAY_LENGTH(pointer_images); - display->pointer_surfaces = - malloc(count * sizeof *display->pointer_surfaces); - rect.width = width; - rect.height = height; - for (i = 0; i < count; i++) { - display->pointer_surfaces[i] = - display_create_surface_from_file(display, - pointer_images[i].filename, - &rect); - } - -} - -cairo_surface_t * -display_get_pointer_surface(struct display *display, int pointer, - int *width, int *height, - int *hotspot_x, int *hotspot_y) -{ - cairo_surface_t *surface; - - surface = display->pointer_surfaces[pointer]; -#if HAVE_CAIRO_EGL - *width = cairo_gl_surface_get_width(surface); - *height = cairo_gl_surface_get_height(surface); -#else - *width = cairo_image_surface_get_width(surface); - *height = cairo_image_surface_get_height(surface); -#endif - *hotspot_x = pointer_images[pointer].hotspot_x; - *hotspot_y = pointer_images[pointer].hotspot_y; - - return cairo_surface_reference(surface); -} - - -static void -window_attach_surface(struct window *window); - -static void -free_surface(void *data) -{ - struct window *window = data; - - cairo_surface_destroy(window->pending_surface); - window->pending_surface = NULL; - if (window->cairo_surface) - window_attach_surface(window); -} - -static void -window_attach_surface(struct window *window) -{ - struct display *display = window->display; - struct wl_buffer *buffer; - int32_t x, y; - - if (window->pending_surface != NULL) - return; - - window->pending_surface = window->cairo_surface; - window->cairo_surface = NULL; - - buffer = display_get_buffer_for_surface(display, - window->pending_surface); - if (window->resize_edges & WINDOW_RESIZING_LEFT) - x = window->server_allocation.width - - window->allocation.width; - else - x = 0; - - if (window->resize_edges & WINDOW_RESIZING_TOP) - y = window->server_allocation.height - - window->allocation.height; - else - y = 0; - - window->server_allocation = window->allocation; - window->resize_edges = 0; - wl_surface_attach(window->surface, buffer, x, y); - wl_display_sync_callback(display->display, free_surface, window); - - if (window->fullscreen) - wl_surface_map_fullscreen(window->surface); - else if (!window->parent) - wl_surface_map_toplevel(window->surface); - else - wl_surface_map_transient(window->surface, - window->parent->surface, - window->x, window->y, 0); - - wl_surface_damage(window->surface, 0, 0, - window->allocation.width, - window->allocation.height); -} - -void -window_flush(struct window *window) -{ - if (window->cairo_surface) - window_attach_surface(window); -} - -void -window_set_surface(struct window *window, cairo_surface_t *surface) -{ - cairo_surface_reference(surface); - - if (window->cairo_surface != NULL) - cairo_surface_destroy(window->cairo_surface); - - window->cairo_surface = surface; -} - -void -window_create_surface(struct window *window) -{ - cairo_surface_t *surface; - - switch (window->buffer_type) { -#ifdef HAVE_CAIRO_EGL - case WINDOW_BUFFER_TYPE_EGL_IMAGE: - surface = display_create_surface(window->display, - &window->allocation); - break; -#endif - case WINDOW_BUFFER_TYPE_SHM: - surface = display_create_shm_surface(window->display, - &window->allocation); - break; - default: - surface = NULL; - break; - } - - window_set_surface(window, surface); - cairo_surface_destroy(surface); -} - -static void -window_draw_menu(struct window *window) -{ - cairo_t *cr; - int width, height, r = 5; - - window_create_surface(window); - - cr = cairo_create(window->cairo_surface); - cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); - cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.0); - cairo_paint(cr); - - width = window->allocation.width; - height = window->allocation.height; - rounded_rect(cr, r, r, width - r, height - r, r); - cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); - cairo_set_source_rgba(cr, 1.0, 1.0, 0.0, 0.5); - cairo_fill(cr); - cairo_destroy(cr); -} - -static void -window_draw_decorations(struct window *window) -{ - cairo_t *cr; - cairo_text_extents_t extents; - cairo_surface_t *frame; - int width, height, shadow_dx = 3, shadow_dy = 3; - - window_create_surface(window); - - width = window->allocation.width; - height = window->allocation.height; - - cr = cairo_create(window->cairo_surface); - - cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); - cairo_set_source_rgba(cr, 0, 0, 0, 0); - cairo_paint(cr); - - cairo_set_source_rgba(cr, 0, 0, 0, 0.6); - tile_mask(cr, window->display->shadow, - shadow_dx, shadow_dy, width, height, - window->margin + 10 - shadow_dx, - window->margin + 10 - shadow_dy); - - if (window->keyboard_device) - frame = window->display->active_frame; - else - frame = window->display->inactive_frame; - - tile_source(cr, frame, 0, 0, width, height, - window->margin + 10, window->margin + 50); - - cairo_set_operator(cr, CAIRO_OPERATOR_OVER); - cairo_set_font_size(cr, 14); - cairo_text_extents(cr, window->title, &extents); - cairo_move_to(cr, (width - extents.width) / 2, 32 - extents.y_bearing); - if (window->keyboard_device) - cairo_set_source_rgb(cr, 0, 0, 0); - else - cairo_set_source_rgb(cr, 0.8, 0.8, 0.8); - cairo_show_text(cr, window->title); - - cairo_destroy(cr); - - cairo_device_flush (window->display->device); -} - -void -window_destroy(struct window *window) -{ - wl_surface_destroy(window->surface); - wl_list_remove(&window->link); - free(window); -} - -void -display_flush_cairo_device(struct display *display) -{ - cairo_device_flush (display->device); -} - -void -window_draw(struct window *window) -{ - if (window->parent) - window_draw_menu(window); - else if (window->fullscreen || !window->decoration) - window_create_surface(window); - else - window_draw_decorations(window); -} - -cairo_surface_t * -window_get_surface(struct window *window) -{ - return cairo_surface_reference(window->cairo_surface); -} - -static int -get_pointer_location(struct window *window, int32_t x, int32_t y) -{ - int vlocation, hlocation, location; - const int grip_size = 8; - - if (!window->decoration) - return WINDOW_CLIENT_AREA; - - if (x < window->margin) - hlocation = WINDOW_EXTERIOR; - else if (window->margin <= x && x < window->margin + grip_size) - hlocation = WINDOW_RESIZING_LEFT; - else if (x < window->allocation.width - window->margin - grip_size) - hlocation = WINDOW_INTERIOR; - else if (x < window->allocation.width - window->margin) - hlocation = WINDOW_RESIZING_RIGHT; - else - hlocation = WINDOW_EXTERIOR; - - if (y < window->margin) - vlocation = WINDOW_EXTERIOR; - else if (window->margin <= y && y < window->margin + grip_size) - vlocation = WINDOW_RESIZING_TOP; - else if (y < window->allocation.height - window->margin - grip_size) - vlocation = WINDOW_INTERIOR; - else if (y < window->allocation.height - window->margin) - vlocation = WINDOW_RESIZING_BOTTOM; - else - vlocation = WINDOW_EXTERIOR; - - location = vlocation | hlocation; - if (location & WINDOW_EXTERIOR) - location = WINDOW_EXTERIOR; - if (location == WINDOW_INTERIOR && y < window->margin + 50) - location = WINDOW_TITLEBAR; - else if (location == WINDOW_INTERIOR) - location = WINDOW_CLIENT_AREA; - - return location; -} - -static void -set_pointer_image(struct input *input, uint32_t time, int pointer) -{ - struct display *display = input->display; - struct wl_buffer *buffer; - cairo_surface_t *surface; - int location; - - location = get_pointer_location(input->pointer_focus, - input->sx, input->sy); - switch (location) { - case WINDOW_RESIZING_TOP: - pointer = POINTER_TOP; - break; - case WINDOW_RESIZING_BOTTOM: - pointer = POINTER_BOTTOM; - break; - case WINDOW_RESIZING_LEFT: - pointer = POINTER_LEFT; - break; - case WINDOW_RESIZING_RIGHT: - pointer = POINTER_RIGHT; - break; - case WINDOW_RESIZING_TOP_LEFT: - pointer = POINTER_TOP_LEFT; - break; - case WINDOW_RESIZING_TOP_RIGHT: - pointer = POINTER_TOP_RIGHT; - break; - case WINDOW_RESIZING_BOTTOM_LEFT: - pointer = POINTER_BOTTOM_LEFT; - break; - case WINDOW_RESIZING_BOTTOM_RIGHT: - pointer = POINTER_BOTTOM_RIGHT; - break; - case WINDOW_EXTERIOR: - case WINDOW_TITLEBAR: - if (input->current_pointer_image == POINTER_DEFAULT) - return; - - wl_input_device_attach(input->input_device, time, NULL, 0, 0); - input->current_pointer_image = POINTER_DEFAULT; - return; - default: - break; - } - - if (pointer == input->current_pointer_image) - return; - - input->current_pointer_image = pointer; - surface = display->pointer_surfaces[pointer]; - buffer = display_get_buffer_for_surface(display, surface); - wl_input_device_attach(input->input_device, time, buffer, - pointer_images[pointer].hotspot_x, - pointer_images[pointer].hotspot_y); -} - -static void -window_handle_motion(void *data, struct wl_input_device *input_device, - uint32_t time, - int32_t x, int32_t y, int32_t sx, int32_t sy) -{ - struct input *input = data; - struct window *window = input->pointer_focus; - int pointer = POINTER_LEFT_PTR; - - input->x = x; - input->y = y; - input->sx = sx; - input->sy = sy; - - if (window->motion_handler) - pointer = (*window->motion_handler)(window, input, time, - x, y, sx, sy, - window->user_data); - - set_pointer_image(input, time, pointer); -} - -static void -window_handle_button(void *data, - struct wl_input_device *input_device, - uint32_t time, uint32_t button, uint32_t state) -{ - struct input *input = data; - struct window *window = input->pointer_focus; - int location; - - location = get_pointer_location(window, input->sx, input->sy); - - if (button == BTN_LEFT && state == 1) { - switch (location) { - case WINDOW_TITLEBAR: - wl_shell_move(window->display->shell, - window->surface, input_device, time); - break; - case WINDOW_RESIZING_TOP: - case WINDOW_RESIZING_BOTTOM: - case WINDOW_RESIZING_LEFT: - case WINDOW_RESIZING_RIGHT: - case WINDOW_RESIZING_TOP_LEFT: - case WINDOW_RESIZING_TOP_RIGHT: - case WINDOW_RESIZING_BOTTOM_LEFT: - case WINDOW_RESIZING_BOTTOM_RIGHT: - wl_shell_resize(window->display->shell, - window->surface, input_device, time, - location); - break; - case WINDOW_CLIENT_AREA: - if (window->button_handler) - (*window->button_handler)(window, - input, time, - button, state, - window->user_data); - break; - } - } else { - if (window->button_handler) - (*window->button_handler)(window, - input, time, - button, state, - window->user_data); - } -} - -static void -window_handle_key(void *data, struct wl_input_device *input_device, - uint32_t time, uint32_t key, uint32_t state) -{ - struct input *input = data; - struct window *window = input->keyboard_focus; - struct display *d = window->display; - uint32_t code, sym, level; - - code = key + d->xkb->min_key_code; - if (window->keyboard_device != input) - return; - - level = 0; - if (input->modifiers & XKB_COMMON_SHIFT_MASK && - XkbKeyGroupWidth(d->xkb, code, 0) > 1) - level = 1; - - sym = XkbKeySymEntry(d->xkb, code, level, 0); - - if (state) - input->modifiers |= d->xkb->map->modmap[code]; - else - input->modifiers &= ~d->xkb->map->modmap[code]; - - if (window->key_handler) - (*window->key_handler)(window, input, time, key, sym, state, - window->user_data); -} - -static void -window_handle_pointer_focus(void *data, - struct wl_input_device *input_device, - uint32_t time, struct wl_surface *surface, - int32_t x, int32_t y, int32_t sx, int32_t sy) -{ - struct input *input = data; - struct window *window; - int pointer; - - if (surface) { - input->pointer_focus = wl_surface_get_user_data(surface); - window = input->pointer_focus; - - input->x = x; - input->y = y; - input->sx = sx; - input->sy = sy; - - pointer = POINTER_LEFT_PTR; - if (window->motion_handler) - pointer = (*window->motion_handler)(window, - input, time, - x, y, sx, sy, - window->user_data); - - set_pointer_image(input, time, pointer); - } else { - input->pointer_focus = NULL; - input->current_pointer_image = POINTER_UNSET; - } -} - -static void -window_handle_keyboard_focus(void *data, - struct wl_input_device *input_device, - uint32_t time, - struct wl_surface *surface, - struct wl_array *keys) -{ - struct input *input = data; - struct window *window = input->keyboard_focus; - struct display *d = input->display; - uint32_t *k, *end; - - window = input->keyboard_focus; - if (window) { - window->keyboard_device = NULL; - if (window->keyboard_focus_handler) - (*window->keyboard_focus_handler)(window, NULL, - window->user_data); - } - - if (surface) - input->keyboard_focus = wl_surface_get_user_data(surface); - else - input->keyboard_focus = NULL; - - end = keys->data + keys->size; - input->modifiers = 0; - for (k = keys->data; k < end; k++) - input->modifiers |= d->xkb->map->modmap[*k]; - - window = input->keyboard_focus; - if (window) { - window->keyboard_device = input; - if (window->keyboard_focus_handler) - (*window->keyboard_focus_handler)(window, - window->keyboard_device, - window->user_data); - } -} - -static const struct wl_input_device_listener input_device_listener = { - window_handle_motion, - window_handle_button, - window_handle_key, - window_handle_pointer_focus, - window_handle_keyboard_focus, -}; - -void -input_get_position(struct input *input, int32_t *x, int32_t *y) -{ - *x = input->sx; - *y = input->sy; -} - -struct wl_input_device * -input_get_input_device(struct input *input) -{ - return input->input_device; -} - -uint32_t -input_get_modifiers(struct input *input) -{ - return input->modifiers; -} - -struct wl_drag * -window_create_drag(struct window *window) -{ - cairo_device_flush (window->display->device); - - return wl_shell_create_drag(window->display->shell); -} - -void -window_move(struct window *window, struct input *input, uint32_t time) -{ - wl_shell_move(window->display->shell, - window->surface, input->input_device, time); -} - -void -window_activate_drag(struct wl_drag *drag, struct window *window, - struct input *input, uint32_t time) -{ - wl_drag_activate(drag, window->surface, input->input_device, time); -} - -static void -handle_configure(void *data, struct wl_shell *shell, - uint32_t time, uint32_t edges, - struct wl_surface *surface, int32_t width, int32_t height) -{ - struct window *window = wl_surface_get_user_data(surface); - int32_t child_width, child_height; - - /* FIXME: this is probably the wrong place to check for width - * or height <= 0, but it prevents the compositor from crashing - */ - if (width <= 0 || height <= 0) - return; - - window->resize_edges = edges; - - if (window->resize_handler) { - child_width = width - 20 - window->margin * 2; - child_height = height - 60 - window->margin * 2; - - (*window->resize_handler)(window, - child_width, child_height, - window->user_data); - } else { - window->allocation.width = width; - window->allocation.height = height; - - if (window->redraw_handler) - window_schedule_redraw(window); - } -} - -static const struct wl_shell_listener shell_listener = { - handle_configure, -}; - -void -window_get_child_allocation(struct window *window, - struct rectangle *allocation) -{ - if (window->fullscreen || !window->decoration) { - *allocation = window->allocation; - } else { - allocation->x = window->margin + 10; - allocation->y = window->margin + 50; - allocation->width = - window->allocation.width - 20 - window->margin * 2; - allocation->height = - window->allocation.height - 60 - window->margin * 2; - } -} - -void -window_set_child_size(struct window *window, int32_t width, int32_t height) -{ - if (!window->fullscreen) { - window->allocation.x = 20 + window->margin; - window->allocation.y = 60 + window->margin; - window->allocation.width = width + 20 + window->margin * 2; - window->allocation.height = height + 60 + window->margin * 2; - } else { - window->allocation.x = 0; - window->allocation.y = 0; - window->allocation.width = width; - window->allocation.height = height; - } -} - -static gboolean -idle_redraw(void *data) -{ - struct window *window = data; - - window->redraw_handler(window, window->user_data); - - window->redraw_scheduled = 0; - - return FALSE; -} - -void -window_schedule_redraw(struct window *window) -{ - if (!window->redraw_scheduled) { - g_idle_add(idle_redraw, window); - window->redraw_scheduled = 1; - } -} - -void -window_set_fullscreen(struct window *window, int fullscreen) -{ - int32_t width, height; - - if (window->fullscreen == fullscreen) - return; - - window->fullscreen = fullscreen; - if (window->fullscreen) { - window->saved_allocation = window->allocation; - width = window->display->screen_allocation.width; - height = window->display->screen_allocation.height; - } else { - width = window->saved_allocation.width - 20 - window->margin * 2; - height = window->saved_allocation.height - 60 - window->margin * 2; - } - - (*window->resize_handler)(window, width, height, window->user_data); -} - -void -window_set_decoration(struct window *window, int decoration) -{ - window->decoration = decoration; -} - -void -window_set_user_data(struct window *window, void *data) -{ - window->user_data = data; -} - -void * -window_get_user_data(struct window *window) -{ - return window->user_data; -} - -void -window_set_resize_handler(struct window *window, - window_resize_handler_t handler) -{ - window->resize_handler = handler; -} - -void -window_set_redraw_handler(struct window *window, - window_redraw_handler_t handler) -{ - window->redraw_handler = handler; -} - -void -window_set_key_handler(struct window *window, - window_key_handler_t handler) -{ - window->key_handler = handler; -} - -void -window_set_button_handler(struct window *window, - window_button_handler_t handler) -{ - window->button_handler = handler; -} - -void -window_set_motion_handler(struct window *window, - window_motion_handler_t handler) -{ - window->motion_handler = handler; -} - -void -window_set_keyboard_focus_handler(struct window *window, - window_keyboard_focus_handler_t handler) -{ - window->keyboard_focus_handler = handler; -} - -void -window_set_title(struct window *window, const char *title) -{ - free(window->title); - window->title = strdup(title); -} - -const char * -window_get_title(struct window *window) -{ - return window->title; -} - -void -window_damage(struct window *window, int32_t x, int32_t y, - int32_t width, int32_t height) -{ - wl_surface_damage(window->surface, x, y, width, height); -} - -static struct window * -window_create_internal(struct display *display, struct window *parent, - int32_t width, int32_t height) -{ - struct window *window; - - window = malloc(sizeof *window); - if (window == NULL) - return NULL; - - memset(window, 0, sizeof *window); - window->display = display; - window->parent = parent; - window->surface = wl_compositor_create_surface(display->compositor); - window->allocation.x = 0; - window->allocation.y = 0; - window->allocation.width = width; - window->allocation.height = height; - window->saved_allocation = window->allocation; - window->margin = 16; - window->decoration = 1; - - if (display->dpy) - window->buffer_type = WINDOW_BUFFER_TYPE_EGL_IMAGE; - else - window->buffer_type = WINDOW_BUFFER_TYPE_SHM; - - wl_surface_set_user_data(window->surface, window); - wl_list_insert(display->window_list.prev, &window->link); - - return window; -} - -struct window * -window_create(struct display *display, int32_t width, int32_t height) -{ - struct window *window; - - window = window_create_internal(display, NULL, width, height); - if (!window) - return NULL; - - return window; -} - -struct window * -window_create_transient(struct display *display, struct window *parent, - int32_t x, int32_t y, int32_t width, int32_t height) -{ - struct window *window; - - window = window_create_internal(parent->display, - parent, width, height); - if (!window) - return NULL; - - window->x = x; - window->y = y; - - return window; -} - -void -window_set_buffer_type(struct window *window, enum window_buffer_type type) -{ - window->buffer_type = type; -} - -static void -display_handle_geometry(void *data, - struct wl_output *output, - int32_t x, int32_t y, int32_t width, int32_t height) -{ - struct display *display = data; - - display->screen_allocation.x = x; - display->screen_allocation.y = y; - display->screen_allocation.width = width; - display->screen_allocation.height = height; -} - -static const struct wl_output_listener output_listener = { - display_handle_geometry, -}; - -static void -display_add_input(struct display *d, uint32_t id) -{ - struct input *input; - - input = malloc(sizeof *input); - if (input == NULL) - return; - - memset(input, 0, sizeof *input); - input->display = d; - input->input_device = wl_input_device_create(d->display, id); - input->pointer_focus = NULL; - input->keyboard_focus = NULL; - wl_list_insert(d->input_list.prev, &input->link); - - wl_input_device_add_listener(input->input_device, - &input_device_listener, input); - wl_input_device_set_user_data(input->input_device, input); -} - -struct selection_offer { - struct display *display; - struct wl_selection_offer *offer; - struct wl_array types; - struct input *input; -}; - -int -input_offers_mime_type(struct input *input, const char *type) -{ - struct selection_offer *offer = input->offer; - char **p, **end; - - if (offer == NULL) - return 0; - - end = offer->types.data + offer->types.size; - for (p = offer->types.data; p < end; p++) - if (strcmp(*p, type) == 0) - return 1; - - return 0; -} - -void -input_receive_mime_type(struct input *input, const char *type, int fd) -{ - struct selection_offer *offer = input->offer; - - /* FIXME: A number of things can go wrong here: the object may - * not be the current selection offer any more (which could - * still work, but the source may have gone away or just - * destroyed its wl_selection) or the offer may not have the - * requested type after all (programmer/client error, - * typically) */ - wl_selection_offer_receive(offer->offer, type, fd); -} - -static void -selection_offer_offer(void *data, - struct wl_selection_offer *selection_offer, - const char *type) -{ - struct selection_offer *offer = data; - - char **p; - - p = wl_array_add(&offer->types, sizeof *p); - if (p) - *p = strdup(type); -}; - -static void -selection_offer_keyboard_focus(void *data, - struct wl_selection_offer *selection_offer, - struct wl_input_device *input_device) -{ - struct selection_offer *offer = data; - struct input *input; - char **p, **end; - - if (input_device == NULL) { - printf("selection offer retracted %p\n", selection_offer); - input = offer->input; - input->offer = NULL; - wl_selection_offer_destroy(selection_offer); - wl_array_release(&offer->types); - free(offer); - return; - } - - input = wl_input_device_get_user_data(input_device); - printf("new selection offer %p:", selection_offer); - - offer->input = input; - input->offer = offer; - end = offer->types.data + offer->types.size; - for (p = offer->types.data; p < end; p++) - printf(" %s", *p); - - printf("\n"); -} - -struct wl_selection_offer_listener selection_offer_listener = { - selection_offer_offer, - selection_offer_keyboard_focus -}; - -static void -add_selection_offer(struct display *d, uint32_t id) -{ - struct selection_offer *offer; - - offer = malloc(sizeof *offer); - if (offer == NULL) - return; - - offer->offer = wl_selection_offer_create(d->display, id); - offer->display = d; - wl_array_init(&offer->types); - offer->input = NULL; - - wl_selection_offer_add_listener(offer->offer, - &selection_offer_listener, offer); -} - -static void -display_handle_global(struct wl_display *display, uint32_t id, - const char *interface, uint32_t version, void *data) -{ - struct display *d = data; - - if (strcmp(interface, "compositor") == 0) { - d->compositor = wl_compositor_create(display, id); - } else if (strcmp(interface, "output") == 0) { - d->output = wl_output_create(display, id); - wl_output_add_listener(d->output, &output_listener, d); - } else if (strcmp(interface, "input_device") == 0) { - display_add_input(d, id); - } else if (strcmp(interface, "shell") == 0) { - d->shell = wl_shell_create(display, id); - wl_shell_add_listener(d->shell, &shell_listener, d); - } else if (strcmp(interface, "shm") == 0) { - d->shm = wl_shm_create(display, id); - } else if (strcmp(interface, "selection_offer") == 0) { - add_selection_offer(d, id); - } else if (d->global_handler) { - d->global_handler(d, interface, id, version); - } -} - -static void -display_render_frame(struct display *d) -{ - int radius = 8; - cairo_t *cr; - - d->shadow = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 128, 128); - cr = cairo_create(d->shadow); - cairo_set_operator(cr, CAIRO_OPERATOR_OVER); - cairo_set_source_rgba(cr, 0, 0, 0, 1); - rounded_rect(cr, 16, 16, 112, 112, radius); - cairo_fill(cr); - cairo_destroy(cr); - blur_surface(d->shadow, 64); - - d->active_frame = - cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 128, 128); - cr = cairo_create(d->active_frame); - cairo_set_operator(cr, CAIRO_OPERATOR_OVER); - cairo_set_source_rgba(cr, 0.8, 0.8, 0.4, 1); - rounded_rect(cr, 16, 16, 112, 112, radius); - cairo_fill(cr); - cairo_destroy(cr); - - d->inactive_frame = - cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 128, 128); - cr = cairo_create(d->inactive_frame); - cairo_set_operator(cr, CAIRO_OPERATOR_OVER); - cairo_set_source_rgba(cr, 0.6, 0.6, 0.6, 1); - rounded_rect(cr, 16, 16, 112, 112, radius); - cairo_fill(cr); - cairo_destroy(cr); -} - -static void -init_xkb(struct display *d) -{ - struct xkb_rule_names names; - - names.rules = "evdev"; - names.model = "pc105"; - names.layout = option_xkb_layout; - names.variant = option_xkb_variant; - names.options = option_xkb_options; - - d->xkb = xkb_compile_keymap_from_rules(&names); - if (!d->xkb) { - fprintf(stderr, "Failed to compile keymap\n"); - exit(1); - } -} - -static int -init_egl(struct display *d) -{ - EGLint major, minor; - - d->dpy = eglGetDisplay(d->native_dpy); - if (!eglInitialize(d->dpy, &major, &minor)) { - fprintf(stderr, "failed to initialize display\n"); - return -1; - } - - if (!eglBindAPI(EGL_OPENGL_API)) { - fprintf(stderr, "failed to bind api EGL_OPENGL_API\n"); - return -1; - } - - d->ctx = eglCreateContext(d->dpy, NULL, EGL_NO_CONTEXT, NULL); - if (d->ctx == NULL) { - fprintf(stderr, "failed to create context\n"); - return -1; - } - - if (!eglMakeCurrent(d->dpy, NULL, NULL, d->ctx)) { - fprintf(stderr, "failed to make context current\n"); - return -1; - } - -#ifdef HAVE_CAIRO_EGL - d->device = cairo_egl_device_create(d->dpy, d->ctx); - if (d->device == NULL) { - fprintf(stderr, "failed to get cairo egl device\n"); - return -1; - } -#endif - - return 0; -} - -struct display * -display_create(int *argc, char **argv[], const GOptionEntry *option_entries) -{ - struct display *d; - GOptionContext *context; - GOptionGroup *xkb_option_group; - GError *error; - - g_type_init(); - - context = g_option_context_new(NULL); - if (option_entries) - g_option_context_add_main_entries(context, option_entries, "Wayland View"); - - xkb_option_group = g_option_group_new("xkb", - "Keyboard options", - "Show all XKB options", - NULL, NULL); - g_option_group_add_entries(xkb_option_group, xkb_option_entries); - g_option_context_add_group (context, xkb_option_group); - - if (!g_option_context_parse(context, argc, argv, &error)) { - fprintf(stderr, "option parsing failed: %s\n", error->message); - exit(EXIT_FAILURE); - } - - g_option_context_free(context); - - d = malloc(sizeof *d); - if (d == NULL) - return NULL; - - memset(d, 0, sizeof *d); - - d->display = wl_display_connect(NULL); - if (d->display == NULL) { - fprintf(stderr, "failed to create display: %m\n"); - return NULL; - } - - wl_list_init(&d->input_list); - - /* Set up listener so we'll catch all events. */ - wl_display_add_global_listener(d->display, - display_handle_global, d); - - d->native_dpy = wl_egl_display_create(d->display); - - /* Process connection events. */ - wl_display_iterate(d->display, WL_DISPLAY_READABLE); - - if (init_egl(d) < 0) - return NULL; - - d->image_target_texture_2d = - (void *) eglGetProcAddress("glEGLImageTargetTexture2DOES"); - d->create_image = (void *) eglGetProcAddress("eglCreateImageKHR"); - d->destroy_image = (void *) eglGetProcAddress("eglDestroyImageKHR"); - - create_pointer_surfaces(d); - - display_render_frame(d); - - d->loop = g_main_loop_new(NULL, FALSE); - d->source = wl_glib_source_new(d->display); - g_source_attach(d->source, NULL); - - wl_list_init(&d->window_list); - - init_xkb(d); - - return d; -} - -struct wl_display * -display_get_display(struct display *display) -{ - return display->display; -} - -struct wl_compositor * -display_get_compositor(struct display *display) -{ - return display->compositor; -} - -EGLDisplay -display_get_egl_display(struct display *d) -{ - return d->dpy; -} - -struct wl_shell * -display_get_shell(struct display *display) -{ - return display->shell; -} - -void -display_run(struct display *d) -{ - g_main_loop_run(d->loop); -} - -void -display_set_global_handler(struct display *display, - display_global_handler_t handler) -{ - display->global_handler = handler; -} diff --git a/clients/window.h b/clients/window.h deleted file mode 100644 index 7073f4a..0000000 --- a/clients/window.h +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Copyright © 2008 Kristian Høgsberg - * - * 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. - */ - -#ifndef _WINDOW_H_ -#define _WINDOW_H_ - -#include <X11/extensions/XKBcommon.h> -#include <glib.h> -#include <wayland-client.h> - -struct window; - -struct rectangle { - int32_t x; - int32_t y; - int32_t width; - int32_t height; -}; - -struct display; -struct input; - -struct display * -display_create(int *argc, char **argv[], const GOptionEntry *option_entries); - -struct wl_display * -display_get_display(struct display *display); - -struct wl_compositor * -display_get_compositor(struct display *display); - -struct wl_shell * -display_get_shell(struct display *display); - -#ifdef EGL_NO_DISPLAY -EGLDisplay -display_get_egl_display(struct display *d); - -#ifdef HAVE_CAIRO_EGL -EGLImageKHR -display_get_image_for_egl_image_surface(struct display *display, - cairo_surface_t *surface); -#endif -#endif - -cairo_surface_t * -display_create_surface(struct display *display, - struct rectangle *rectangle); - -struct wl_buffer * -display_get_buffer_for_surface(struct display *display, - cairo_surface_t *surface); - -cairo_surface_t * -display_get_pointer_surface(struct display *display, int pointer, - int *width, int *height, - int *hotspot_x, int *hotspot_y); - -void -display_add_drag_listener(struct display *display, - const struct wl_drag_listener *drag_listener, - void *data); - -void -display_flush_cairo_device(struct display *display); - -void -display_run(struct display *d); - -enum pointer_type { - POINTER_BOTTOM_LEFT, - POINTER_BOTTOM_RIGHT, - POINTER_BOTTOM, - POINTER_DRAGGING, - POINTER_LEFT_PTR, - POINTER_LEFT, - POINTER_RIGHT, - POINTER_TOP_LEFT, - POINTER_TOP_RIGHT, - POINTER_TOP, - POINTER_IBEAM, - POINTER_HAND1, -}; - -typedef void (*window_resize_handler_t)(struct window *window, - int32_t width, int32_t height, - void *data); -typedef void (*window_redraw_handler_t)(struct window *window, void *data); - -typedef void (*window_key_handler_t)(struct window *window, struct input *input, - uint32_t time, uint32_t key, uint32_t unicode, - uint32_t state, void *data); - -typedef void (*window_keyboard_focus_handler_t)(struct window *window, - struct input *device, void *data); - -typedef void (*window_button_handler_t)(struct window *window, - struct input *input, uint32_t time, - int button, int state, void *data); - -typedef int (*window_motion_handler_t)(struct window *window, - struct input *input, uint32_t time, - int32_t x, int32_t y, - int32_t sx, int32_t sy, void *data); - -typedef void (*display_global_handler_t)(struct display *display, - const char *interface, - uint32_t id, - uint32_t version); - -struct window * -window_create(struct display *display, int32_t width, int32_t height); -struct window * -window_create_transient(struct display *display, struct window *parent, - int32_t x, int32_t y, int32_t width, int32_t height); - -void -window_destroy(struct window *window); - -void -window_move(struct window *window, struct input *input, uint32_t time); - -void -window_draw(struct window *window); -void -window_get_child_allocation(struct window *window, - struct rectangle *allocation); - -void -window_set_child_size(struct window *window, int32_t width, int32_t height); -void -window_schedule_redraw(struct window *window); - -void -window_damage(struct window *window, int32_t x, int32_t y, - int32_t width, int32_t height); - -cairo_surface_t * -window_get_surface(struct window *window); - -void -window_flush(struct window *window); - -void -window_set_surface(struct window *window, cairo_surface_t *surface); - -void -window_create_surface(struct window *window); - -enum window_buffer_type { - WINDOW_BUFFER_TYPE_EGL_IMAGE, - WINDOW_BUFFER_TYPE_SHM, -}; - -void -window_set_buffer_type(struct window *window, enum window_buffer_type type); - -void -window_set_fullscreen(struct window *window, int fullscreen); - -void -window_set_user_data(struct window *window, void *data); - -void * -window_get_user_data(struct window *window); - -void -window_set_redraw_handler(struct window *window, - window_redraw_handler_t handler); - -void -window_set_decoration(struct window *window, int decoration); - -void -window_set_resize_handler(struct window *window, - window_resize_handler_t handler); - -void -window_set_key_handler(struct window *window, - window_key_handler_t handler); - -void -window_set_button_handler(struct window *window, - window_button_handler_t handler); - -void -window_set_motion_handler(struct window *window, - window_motion_handler_t handler); - -void -window_set_keyboard_focus_handler(struct window *window, - window_keyboard_focus_handler_t handler); - -void -window_set_title(struct window *window, const char *title); - -const char * -window_get_title(struct window *window); - -void -display_set_global_handler(struct display *display, - display_global_handler_t handler); - -struct wl_drag * -window_create_drag(struct window *window); - -void -window_activate_drag(struct wl_drag *drag, struct window *window, - struct input *input, uint32_t time); - -void -input_get_position(struct input *input, int32_t *x, int32_t *y); - -uint32_t -input_get_modifiers(struct input *input); - -struct wl_input_device * -input_get_input_device(struct input *input); - -int -input_offers_mime_type(struct input *input, const char *type); -void -input_receive_mime_type(struct input *input, const char *type, int fd); - - -#endif diff --git a/compositor/.gitignore b/compositor/.gitignore deleted file mode 100644 index dc926c1..0000000 --- a/compositor/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -compositor -screenshooter-protocol.c -screenshooter-server-protocol.h diff --git a/compositor/70-wayland.rules b/compositor/70-wayland.rules deleted file mode 100644 index 1b7ca66..0000000 --- a/compositor/70-wayland.rules +++ /dev/null @@ -1,7 +0,0 @@ -KERNEL=="event*", ENV{ID_INPUT_KEYBOARD}=="1", ENV{WAYLAND_SEAT}="1" -KERNEL=="event*", ENV{ID_INPUT_MOUSE}=="1", ENV{WAYLAND_SEAT}="1" -KERNEL=="event*", ENV{ID_INPUT_TOUCHPAD}=="1", ENV{WAYLAND_SEAT}="1" -KERNEL=="event*", ENV{ID_INPUT_TOUCHSCREEN}=="1", ENV{WAYLAND_SEAT}="1" -KERNEL=="event*", ENV{ID_INPUT_TABLET}=="1", ENV{WAYLAND_SEAT}="1" -KERNEL=="card0", ENV{WAYLAND_SEAT}="1" - diff --git a/compositor/Makefile.am b/compositor/Makefile.am deleted file mode 100644 index d2baa43..0000000 --- a/compositor/Makefile.am +++ /dev/null @@ -1,55 +0,0 @@ -noinst_PROGRAMS = compositor - -AM_CPPFLAGS = \ - -DDATADIR='"$(datadir)"' \ - -I$(top_builddir)/wayland \ - -I$(top_srcdir)/wayland \ - $(COMPOSITOR_CFLAGS) - -AM_CFLAGS = $(GCC_CFLAGS) - -compositor_LDADD = \ - $(top_builddir)/wayland/libwayland-server.la \ - $(top_builddir)/wayland/libwayland-client.la \ - $(COMPOSITOR_LIBS) - -if ENABLE_DRM_COMPOSITOR -drm_compositor_sources = compositor-drm.c tty.c evdev.c -drm_sources = drm.c -endif - -if ENABLE_X11_COMPOSITOR -x11_compositor_sources = compositor-x11.c -drm_sources = drm.c -endif - -if ENABLE_WAYLAND_COMPOSITOR -wayland_compositor_sources = compositor-wayland.c -drm_sources = drm.c -endif - -compositor_SOURCES = \ - compositor.c \ - compositor.h \ - shell.c \ - screenshooter.c \ - screenshooter-protocol.c \ - screenshooter-server-protocol.h \ - shm.c \ - $(drm_compositor_sources) \ - $(x11_compositor_sources) \ - $(wayland_compositor_sources) \ - $(drm_sources) - -udevrulesddir = $(sysconfdir)/udev/rules.d - -dist_udevrulesd_DATA = \ - 70-wayland.rules - -BUILT_SOURCES = \ - screenshooter-server-protocol.h \ - screenshooter-protocol.c - -CLEANFILES = $(BUILT_SOURCES) - -include $(top_srcdir)/wayland/scanner.mk diff --git a/compositor/compositor-drm.c b/compositor/compositor-drm.c deleted file mode 100644 index 50f353b..0000000 --- a/compositor/compositor-drm.c +++ /dev/null @@ -1,383 +0,0 @@ -/* - * Copyright © 2008-2010 Kristian Høgsberg - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <fcntl.h> -#include <unistd.h> - -#define GL_GLEXT_PROTOTYPES -#define EGL_EGLEXT_PROTOTYPES -#include <GLES2/gl2.h> -#include <GLES2/gl2ext.h> -#include <EGL/egl.h> -#include <EGL/eglext.h> - -#include "compositor.h" - -struct drm_compositor { - struct wlsc_compositor base; - - struct udev *udev; - struct wl_event_source *drm_source; - - struct tty *tty; -}; - -struct drm_output { - struct wlsc_output base; - - drmModeModeInfo mode; - uint32_t crtc_id; - uint32_t connector_id; - GLuint rbo[2]; - uint32_t fb_id[2]; - EGLImageKHR image[2]; - uint32_t current; -}; - -static void -drm_compositor_present(struct wlsc_compositor *ec) -{ - struct drm_compositor *c = (struct drm_compositor *) ec; - struct drm_output *output; - - wl_list_for_each(output, &ec->output_list, base.link) { - output->current ^= 1; - - glFramebufferRenderbuffer(GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_RENDERBUFFER, - output->rbo[output->current]); - glFlush(); - - drmModePageFlip(c->base.drm.fd, output->crtc_id, - output->fb_id[output->current ^ 1], - DRM_MODE_PAGE_FLIP_EVENT, output); - } -} - -static void -page_flip_handler(int fd, unsigned int frame, - unsigned int sec, unsigned int usec, void *data) -{ - struct wlsc_output *output = data; - struct wlsc_compositor *compositor = output->compositor; - uint32_t msecs; - - msecs = sec * 1000 + usec / 1000; - wlsc_compositor_finish_frame(compositor, msecs); -} - -static void -on_drm_input(int fd, uint32_t mask, void *data) -{ - drmEventContext evctx; - - memset(&evctx, 0, sizeof evctx); - evctx.version = DRM_EVENT_CONTEXT_VERSION; - evctx.page_flip_handler = page_flip_handler; - drmHandleEvent(fd, &evctx); -} - -static int -init_egl(struct drm_compositor *ec, struct udev_device *device) -{ - EGLint major, minor; - const char *extensions, *filename; - int fd; - static const EGLint context_attribs[] = { - EGL_CONTEXT_CLIENT_VERSION, 2, - EGL_NONE - }; - - filename = udev_device_get_devnode(device); - fd = open(filename, O_RDWR); - if (fd < 0) { - /* Probably permissions error */ - fprintf(stderr, "couldn't open %s, skipping\n", - udev_device_get_devnode(device)); - return -1; - } - - wlsc_drm_init(&ec->base, fd, filename); - - ec->base.display = eglGetDRMDisplayMESA(ec->base.drm.fd); - if (ec->base.display == NULL) { - fprintf(stderr, "failed to create display\n"); - return -1; - } - - if (!eglInitialize(ec->base.display, &major, &minor)) { - fprintf(stderr, "failed to initialize display\n"); - return -1; - } - - extensions = eglQueryString(ec->base.display, EGL_EXTENSIONS); - if (!strstr(extensions, "EGL_KHR_surfaceless_opengl")) { - fprintf(stderr, "EGL_KHR_surfaceless_opengl not available\n"); - return -1; - } - - if (!eglBindAPI(EGL_OPENGL_ES_API)) { - fprintf(stderr, "failed to bind api EGL_OPENGL_ES_API\n"); - return -1; - } - - ec->base.context = eglCreateContext(ec->base.display, NULL, - EGL_NO_CONTEXT, context_attribs); - if (ec->base.context == NULL) { - fprintf(stderr, "failed to create context\n"); - return -1; - } - - if (!eglMakeCurrent(ec->base.display, EGL_NO_SURFACE, - EGL_NO_SURFACE, ec->base.context)) { - fprintf(stderr, "failed to make context current\n"); - return -1; - } - - return 0; -} - -static drmModeModeInfo builtin_1024x768 = { - 63500, /* clock */ - 1024, 1072, 1176, 1328, 0, - 768, 771, 775, 798, 0, - 59920, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC, - 0, - "1024x768" -}; - -static int -create_output_for_connector(struct drm_compositor *ec, - drmModeRes *resources, - drmModeConnector *connector) -{ - struct drm_output *output; - drmModeEncoder *encoder; - drmModeModeInfo *mode; - int i, ret; - EGLint handle, stride, attribs[] = { - EGL_WIDTH, 0, - EGL_HEIGHT, 0, - EGL_DRM_BUFFER_FORMAT_MESA, EGL_DRM_BUFFER_FORMAT_ARGB32_MESA, - EGL_DRM_BUFFER_USE_MESA, EGL_DRM_BUFFER_USE_SCANOUT_MESA, - EGL_NONE - }; - - output = malloc(sizeof *output); - if (output == NULL) - return -1; - - if (connector->count_modes > 0) - mode = &connector->modes[0]; - else - mode = &builtin_1024x768; - - encoder = drmModeGetEncoder(ec->base.drm.fd, connector->encoders[0]); - if (encoder == NULL) { - fprintf(stderr, "No encoder for connector.\n"); - return -1; - } - - for (i = 0; i < resources->count_crtcs; i++) { - if (encoder->possible_crtcs & (1 << i)) - break; - } - if (i == resources->count_crtcs) { - fprintf(stderr, "No usable crtc for encoder.\n"); - return -1; - } - - memset(output, 0, sizeof *output); - wlsc_output_init(&output->base, &ec->base, 0, 0, - mode->hdisplay, mode->vdisplay); - - output->crtc_id = resources->crtcs[i]; - output->connector_id = connector->connector_id; - output->mode = *mode; - - drmModeFreeEncoder(encoder); - - glGenRenderbuffers(2, output->rbo); - for (i = 0; i < 2; i++) { - glBindRenderbuffer(GL_RENDERBUFFER, output->rbo[i]); - - attribs[1] = output->base.width; - attribs[3] = output->base.height; - output->image[i] = - eglCreateDRMImageMESA(ec->base.display, attribs); - glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, - output->image[i]); - eglExportDRMImageMESA(ec->base.display, output->image[i], - NULL, &handle, &stride); - - ret = drmModeAddFB(ec->base.drm.fd, - output->base.width, output->base.height, - 32, 32, stride, handle, &output->fb_id[i]); - if (ret) { - fprintf(stderr, "failed to add fb %d: %m\n", i); - return -1; - } - } - - output->current = 0; - glFramebufferRenderbuffer(GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_RENDERBUFFER, - output->rbo[output->current]); - ret = drmModeSetCrtc(ec->base.drm.fd, output->crtc_id, - output->fb_id[output->current ^ 1], 0, 0, - &output->connector_id, 1, &output->mode); - if (ret) { - fprintf(stderr, "failed to set mode: %m\n"); - return -1; - } - - wl_list_insert(ec->base.output_list.prev, &output->base.link); - - return 0; -} - -static int -create_outputs(struct drm_compositor *ec, int option_connector) -{ - drmModeConnector *connector; - drmModeRes *resources; - int i; - - resources = drmModeGetResources(ec->base.drm.fd); - if (!resources) { - fprintf(stderr, "drmModeGetResources failed\n"); - return -1; - } - - for (i = 0; i < resources->count_connectors; i++) { - connector = drmModeGetConnector(ec->base.drm.fd, resources->connectors[i]); - if (connector == NULL) - continue; - - if (connector->connection == DRM_MODE_CONNECTED && - (option_connector == 0 || - connector->connector_id == option_connector)) - if (create_output_for_connector(ec, resources, connector) < 0) - return -1; - - drmModeFreeConnector(connector); - } - - if (wl_list_empty(&ec->base.output_list)) { - fprintf(stderr, "No currently active connector found.\n"); - return -1; - } - - drmModeFreeResources(resources); - - return 0; -} - -static int -drm_authenticate(struct wlsc_compositor *c, uint32_t id) -{ - struct drm_compositor *ec = (struct drm_compositor *) c; - - return drmAuthMagic(ec->base.drm.fd, id); -} - -static void -drm_destroy(struct wlsc_compositor *ec) -{ - struct drm_compositor *d = (struct drm_compositor *) ec; - - tty_destroy(d->tty); - - free(d); -} - -struct wlsc_compositor * -drm_compositor_create(struct wl_display *display, int connector) -{ - struct drm_compositor *ec; - struct udev_enumerate *e; - struct udev_list_entry *entry; - struct udev_device *device; - const char *path; - struct wl_event_loop *loop; - - ec = malloc(sizeof *ec); - if (ec == NULL) - return NULL; - - memset(ec, 0, sizeof *ec); - ec->udev = udev_new(); - if (ec->udev == NULL) { - fprintf(stderr, "failed to initialize udev context\n"); - return NULL; - } - - e = udev_enumerate_new(ec->udev); - udev_enumerate_add_match_subsystem(e, "drm"); - udev_enumerate_add_match_property(e, "WAYLAND_SEAT", "1"); - udev_enumerate_scan_devices(e); - device = NULL; - udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) { - path = udev_list_entry_get_name(entry); - device = udev_device_new_from_syspath(ec->udev, path); - break; - } - udev_enumerate_unref(e); - - if (device == NULL) { - fprintf(stderr, "no drm device found\n"); - return NULL; - } - - ec->base.wl_display = display; - if (init_egl(ec, device) < 0) { - fprintf(stderr, "failed to initialize egl\n"); - return NULL; - } - - ec->base.destroy = drm_destroy; - ec->base.authenticate = drm_authenticate; - ec->base.present = drm_compositor_present; - ec->base.create_buffer = wlsc_drm_buffer_create; - ec->base.focus = 1; - - /* Can't init base class until we have a current egl context */ - if (wlsc_compositor_init(&ec->base, display) < 0) - return NULL; - - if (create_outputs(ec, connector) < 0) { - fprintf(stderr, "failed to create output for %s\n", path); - return NULL; - } - - evdev_input_add_devices(&ec->base, ec->udev); - - loop = wl_display_get_event_loop(ec->base.wl_display); - ec->drm_source = - wl_event_loop_add_fd(loop, ec->base.drm.fd, - WL_EVENT_READABLE, on_drm_input, ec); - ec->tty = tty_create(&ec->base); - - return &ec->base; -} diff --git a/compositor/compositor-wayland.c b/compositor/compositor-wayland.c deleted file mode 100644 index 11320d8..0000000 --- a/compositor/compositor-wayland.c +++ /dev/null @@ -1,542 +0,0 @@ -/* - * Copyright © 2010 Benjamin Franzke - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stddef.h> -#define _GNU_SOURCE -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <fcntl.h> -#include <unistd.h> - -#include "wayland-client.h" - -#define GL_GLEXT_PROTOTYPES -#define EGL_EGLEXT_PROTOTYPES -#include <GLES2/gl2.h> -#include <GLES2/gl2ext.h> -#include <EGL/egl.h> -#include <EGL/eglext.h> - -#include "compositor.h" - -struct wayland_compositor { - struct wlsc_compositor base; - - struct { - struct wl_display *display; - struct wl_compositor *compositor; - struct wl_shell *shell; - struct wl_drm *drm; - struct wl_output *output; - - struct { - int32_t x, y, width, height; - } screen_allocation; - - char *device_name; - int authenticated; - - struct wl_event_source *wl_source; - uint32_t event_mask; - } parent; - - struct wl_list input_list; -}; - -struct wayland_output { - struct wlsc_output base; - - struct { - struct wl_surface *surface; - struct wl_buffer *buffer[2]; - } parent; - EGLImageKHR image[2]; - GLuint rbo[2]; - uint32_t fb_id[2]; - uint32_t current; -}; - -struct wayland_input { - struct wayland_compositor *compositor; - struct wl_input_device *input_device; - struct wl_list link; -}; - -static int -wayland_input_create(struct wayland_compositor *c) -{ - struct wlsc_input_device *input; - - input = malloc(sizeof *input); - if (input == NULL) - return -1; - - memset(input, 0, sizeof *input); - wlsc_input_device_init(input, &c->base); - - c->base.input_device = &input->input_device; - - return 0; -} - -static int -wayland_compositor_init_egl(struct wayland_compositor *c) -{ - EGLint major, minor; - const char *extensions; - drm_magic_t magic; - int fd; - static const EGLint context_attribs[] = { - EGL_CONTEXT_CLIENT_VERSION, 2, - EGL_NONE - }; - - fd = open(c->parent.device_name, O_RDWR); - if (fd < 0) { - fprintf(stderr, "drm open failed: %m\n"); - return -1; - } - - wlsc_drm_init(&c->base, fd, c->parent.device_name); - - if (drmGetMagic(fd, &magic)) { - fprintf(stderr, "DRI2: failed to get drm magic"); - return -1; - } - - wl_drm_authenticate(c->parent.drm, magic); - wl_display_iterate(c->parent.display, WL_DISPLAY_WRITABLE); - while (!c->parent.authenticated) - wl_display_iterate(c->parent.display, WL_DISPLAY_READABLE); - - c->base.display = eglGetDRMDisplayMESA(fd); - if (c->base.display == NULL) { - fprintf(stderr, "failed to create display\n"); - return -1; - } - - if (!eglInitialize(c->base.display, &major, &minor)) { - fprintf(stderr, "failed to initialize display\n"); - return -1; - } - - extensions = eglQueryString(c->base.display, EGL_EXTENSIONS); - if (!strstr(extensions, "EGL_KHR_surfaceless_opengl")) { - fprintf(stderr, "EGL_KHR_surfaceless_opengl not available\n"); - return -1; - } - - if (!eglBindAPI(EGL_OPENGL_ES_API)) { - fprintf(stderr, "failed to bind EGL_OPENGL_ES_API\n"); - return -1; - } - - c->base.context = eglCreateContext(c->base.display, NULL, - EGL_NO_CONTEXT, context_attribs); - if (c->base.context == NULL) { - fprintf(stderr, "failed to create context\n"); - return -1; - } - - if (!eglMakeCurrent(c->base.display, EGL_NO_SURFACE, - EGL_NO_SURFACE, c->base.context)) { - fprintf(stderr, "failed to make context current\n"); - return -1; - } - - return 0; -} - -static void -frame_callback(void *data, uint32_t time) -{ - struct wayland_compositor *c = (struct wayland_compositor *) data; - - wlsc_compositor_finish_frame(&c->base, time); -} - -static void -wayland_compositor_present(struct wlsc_compositor *base) -{ - struct wayland_compositor *c = (struct wayland_compositor *) base; - struct wayland_output *output; - - glFlush(); - - wl_list_for_each(output, &base->output_list, base.link) { - output->current ^= 1; - - glFramebufferRenderbuffer(GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_RENDERBUFFER, - output->rbo[output->current]); - - wl_surface_attach(output->parent.surface, - output->parent.buffer[output->current ^ 1], - 0, 0); - wl_surface_damage(output->parent.surface, 0, 0, - output->base.width, output->base.height); - } - - wl_display_frame_callback(c->parent.display, frame_callback, c); -} - -static int -wayland_authenticate(struct wlsc_compositor *ec, uint32_t id) -{ - struct wayland_compositor *c = (struct wayland_compositor *) ec; - - wl_drm_authenticate(c->parent.drm, id); - /* FIXME: recv drm_authenticated event from parent? */ - wl_display_iterate(c->parent.display, WL_DISPLAY_WRITABLE); - - return 0; -} - -static int -wayland_compositor_create_output(struct wayland_compositor *c, - int width, int height) -{ - struct wayland_output *output; - struct wl_visual *visual; - int i; - EGLint name, stride, attribs[] = { - EGL_WIDTH, 0, - EGL_HEIGHT, 0, - EGL_DRM_BUFFER_FORMAT_MESA, EGL_DRM_BUFFER_FORMAT_ARGB32_MESA, - EGL_DRM_BUFFER_USE_MESA, EGL_DRM_BUFFER_USE_SCANOUT_MESA, - EGL_NONE - }; - - output = malloc(sizeof *output); - if (output == NULL) - return -1; - memset(output, 0, sizeof *output); - - wlsc_output_init(&output->base, &c->base, 0, 0, width, height); - output->parent.surface = - wl_compositor_create_surface(c->parent.compositor); - wl_surface_set_user_data(output->parent.surface, output); - - glGenRenderbuffers(2, output->rbo); - visual = wl_display_get_premultiplied_argb_visual(c->parent.display); - for (i = 0; i < 2; i++) { - glBindRenderbuffer(GL_RENDERBUFFER, output->rbo[i]); - - attribs[1] = width; - attribs[3] = height; - output->image[i] = - eglCreateDRMImageMESA(c->base.display, attribs); - glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, - output->image[i]); - eglExportDRMImageMESA(c->base.display, output->image[i], - &name, NULL, &stride); - output->parent.buffer[i] = - wl_drm_create_buffer(c->parent.drm, name, - width, height, - stride, visual); - } - - output->current = 0; - glFramebufferRenderbuffer(GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_RENDERBUFFER, - output->rbo[output->current]); - - wl_surface_attach(output->parent.surface, - output->parent.buffer[output->current], 0, 0); - wl_surface_map_toplevel(output->parent.surface); - - glClearColor(0, 0, 0, 0.5); - - wl_list_insert(c->base.output_list.prev, &output->base.link); - - return 0; -} - -/* Events received from the wayland-server this compositor is client of: */ - -/* parent output interface */ -static void -display_handle_geometry(void *data, - struct wl_output *output, - int32_t x, int32_t y, - int32_t width, int32_t height) -{ - struct wayland_compositor *c = data; - - c->parent.screen_allocation.x = x; - c->parent.screen_allocation.y = y; - c->parent.screen_allocation.width = width; - c->parent.screen_allocation.height = height; -} - -static const struct wl_output_listener output_listener = { - display_handle_geometry, -}; - -/* parent shell interface */ -static void -handle_configure(void *data, struct wl_shell *shell, - uint32_t time, uint32_t edges, - struct wl_surface *surface, int32_t width, int32_t height) -{ -#if 0 - struct output *output = wl_surface_get_user_data(surface); - - /* FIXME: add resize? */ -#endif -} - -static const struct wl_shell_listener shell_listener = { - handle_configure, -}; - -/* parent drm interface */ -static void -drm_handle_device(void *data, struct wl_drm *drm, const char *device) -{ - struct wayland_compositor *c = data; - - c->parent.device_name = strdup(device); -} - -static void drm_handle_authenticated(void *data, struct wl_drm *drm) -{ - struct wayland_compositor *c = data; - - c->parent.authenticated = 1; -} - -static const struct wl_drm_listener drm_listener = { - drm_handle_device, - drm_handle_authenticated -}; - -/* parent input interface */ -static void -input_handle_motion(void *data, struct wl_input_device *input_device, - uint32_t time, - int32_t x, int32_t y, int32_t sx, int32_t sy) -{ - struct wayland_input *input = data; - struct wayland_compositor *c = input->compositor; - - notify_motion(c->base.input_device, time, sx, sy); -} - -static void -input_handle_button(void *data, - struct wl_input_device *input_device, - uint32_t time, uint32_t button, uint32_t state) -{ - struct wayland_input *input = data; - struct wayland_compositor *c = input->compositor; - - notify_button(c->base.input_device, time, button, state); -} - -static void -input_handle_key(void *data, struct wl_input_device *input_device, - uint32_t time, uint32_t key, uint32_t state) -{ - struct wayland_input *input = data; - struct wayland_compositor *c = input->compositor; - - notify_key(c->base.input_device, time, key, state); -} - -static void -input_handle_pointer_focus(void *data, - struct wl_input_device *input_device, - uint32_t time, struct wl_surface *surface, - int32_t x, int32_t y, int32_t sx, int32_t sy) -{ - struct wayland_input *input = data; - struct wayland_output *output; - struct wayland_compositor *c = input->compositor; - - if (surface) { - output = wl_surface_get_user_data(surface); - notify_pointer_focus(c->base.input_device, - time, &output->base, sx, sy); - } else { - notify_pointer_focus(c->base.input_device, time, NULL, 0, 0); - } -} - -static void -input_handle_keyboard_focus(void *data, - struct wl_input_device *input_device, - uint32_t time, - struct wl_surface *surface, - struct wl_array *keys) -{ - struct wayland_input *input = data; - struct wayland_compositor *c = input->compositor; - struct wayland_output *output; - - if (surface) { - output = wl_surface_get_user_data(surface); - notify_keyboard_focus(c->base.input_device, - time, &output->base, keys); - } else { - notify_keyboard_focus(c->base.input_device, time, NULL, NULL); - } -} - -static const struct wl_input_device_listener input_device_listener = { - input_handle_motion, - input_handle_button, - input_handle_key, - input_handle_pointer_focus, - input_handle_keyboard_focus, -}; - -static void -display_add_input(struct wayland_compositor *c, uint32_t id) -{ - struct wayland_input *input; - - input = malloc(sizeof *input); - if (input == NULL) - return; - - memset(input, 0, sizeof *input); - - input->compositor = c; - input->input_device = wl_input_device_create(c->parent.display, id); - wl_list_insert(c->input_list.prev, &input->link); - - wl_input_device_add_listener(input->input_device, - &input_device_listener, input); - wl_input_device_set_user_data(input->input_device, input); -} - -static void -display_handle_global(struct wl_display *display, uint32_t id, - const char *interface, uint32_t version, void *data) -{ - struct wayland_compositor *c = data; - - if (strcmp(interface, "compositor") == 0) { - c->parent.compositor = wl_compositor_create(display, id); - } else if (strcmp(interface, "output") == 0) { - c->parent.output = wl_output_create(display, id); - wl_output_add_listener(c->parent.output, &output_listener, c); - } else if (strcmp(interface, "input_device") == 0) { - display_add_input(c, id); - } else if (strcmp(interface, "shell") == 0) { - c->parent.shell = wl_shell_create(display, id); - wl_shell_add_listener(c->parent.shell, &shell_listener, c); - } else if (strcmp(interface, "drm") == 0) { - c->parent.drm = wl_drm_create(display, id); - wl_drm_add_listener(c->parent.drm, &drm_listener, c); - } -} - -static int -update_event_mask(uint32_t mask, void *data) -{ - struct wayland_compositor *c = data; - - c->parent.event_mask = mask; - if (c->parent.wl_source) - wl_event_source_fd_update(c->parent.wl_source, mask); - - return 0; -} - -static void -wayland_compositor_handle_event(int fd, uint32_t mask, void *data) -{ - struct wayland_compositor *c = data; - - if (mask & WL_EVENT_READABLE) - wl_display_iterate(c->parent.display, WL_DISPLAY_READABLE); - if (mask & WL_EVENT_WRITEABLE) - wl_display_iterate(c->parent.display, WL_DISPLAY_WRITABLE); -} - -static void -wayland_destroy(struct wlsc_compositor *ec) -{ - free(ec); -} - -struct wlsc_compositor * -wayland_compositor_create(struct wl_display *display, int width, int height) -{ - struct wayland_compositor *c; - struct wl_event_loop *loop; - int fd; - - c = malloc(sizeof *c); - if (c == NULL) - return NULL; - - memset(c, 0, sizeof *c); - - c->parent.display = wl_display_connect(NULL); - - if (c->parent.display == NULL) { - fprintf(stderr, "failed to create display: %m\n"); - return NULL; - } - - wl_list_init(&c->input_list); - wl_display_add_global_listener(c->parent.display, - display_handle_global, c); - - wl_display_iterate(c->parent.display, WL_DISPLAY_READABLE); - - c->base.wl_display = display; - if (wayland_compositor_init_egl(c) < 0) - return NULL; - - c->base.destroy = wayland_destroy; - c->base.authenticate = wayland_authenticate; - c->base.present = wayland_compositor_present; - c->base.create_buffer = wlsc_drm_buffer_create; - - /* Can't init base class until we have a current egl context */ - if (wlsc_compositor_init(&c->base, display) < 0) - return NULL; - - if (wayland_compositor_create_output(c, width, height) < 0) - return NULL; - - if (wayland_input_create(c) < 0) - return NULL; - - loop = wl_display_get_event_loop(c->base.wl_display); - - fd = wl_display_get_fd(c->parent.display, update_event_mask, c); - c->parent.wl_source = - wl_event_loop_add_fd(loop, fd, c->parent.event_mask, - wayland_compositor_handle_event, c); - if (c->parent.wl_source == NULL) - return NULL; - - return &c->base; -} diff --git a/compositor/compositor-x11.c b/compositor/compositor-x11.c deleted file mode 100644 index 4365c0a..0000000 --- a/compositor/compositor-x11.c +++ /dev/null @@ -1,795 +0,0 @@ -/* - * Copyright © 2008-2010 Kristian Høgsberg - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stddef.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <fcntl.h> -#include <unistd.h> -#include <errno.h> -#include <sys/time.h> -#include <linux/input.h> - -#include <xcb/xcb.h> -#include <xcb/dri2.h> -#include <xcb/xfixes.h> - -#define GL_GLEXT_PROTOTYPES -#define EGL_EGLEXT_PROTOTYPES -#include <GLES2/gl2.h> -#include <GLES2/gl2ext.h> -#include <EGL/egl.h> -#include <EGL/eglext.h> - -#include "compositor.h" - -#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0])) - -struct x11_compositor { - struct wlsc_compositor base; - - xcb_connection_t *conn; - xcb_screen_t *screen; - xcb_cursor_t null_cursor; - int dri2_major; - int dri2_minor; - struct wl_array keys; - struct wl_event_source *xcb_source; - struct { - xcb_atom_t wm_protocols; - xcb_atom_t wm_normal_hints; - xcb_atom_t wm_size_hints; - xcb_atom_t wm_delete_window; - xcb_atom_t wm_class; - xcb_atom_t net_wm_name; - xcb_atom_t net_wm_icon; - xcb_atom_t string; - xcb_atom_t utf8_string; - xcb_atom_t cardinal; - } atom; -}; - -struct x11_output { - struct wlsc_output base; - - xcb_xfixes_region_t region; - xcb_window_t window; - GLuint rbo; - EGLImageKHR image; - xcb_rectangle_t damage[16]; - int damage_count; -}; - -struct x11_input { - struct wlsc_input_device base; -}; - - -static int -x11_input_create(struct x11_compositor *c) -{ - struct x11_input *input; - - input = malloc(sizeof *input); - if (input == NULL) - return -1; - - memset(input, 0, sizeof *input); - wlsc_input_device_init(&input->base, &c->base); - - c->base.input_device = &input->base.input_device; - - return 0; -} - - -static int -dri2_connect(struct x11_compositor *c) -{ - xcb_xfixes_query_version_reply_t *xfixes_query; - xcb_xfixes_query_version_cookie_t xfixes_query_cookie; - xcb_dri2_query_version_reply_t *dri2_query; - xcb_dri2_query_version_cookie_t dri2_query_cookie; - xcb_dri2_connect_reply_t *connect; - xcb_dri2_connect_cookie_t connect_cookie; - xcb_generic_error_t *error; - char path[256]; - int fd; - - xcb_prefetch_extension_data (c->conn, &xcb_xfixes_id); - xcb_prefetch_extension_data (c->conn, &xcb_dri2_id); - - xfixes_query_cookie = - xcb_xfixes_query_version(c->conn, - XCB_XFIXES_MAJOR_VERSION, - XCB_XFIXES_MINOR_VERSION); - - dri2_query_cookie = - xcb_dri2_query_version (c->conn, - XCB_DRI2_MAJOR_VERSION, - XCB_DRI2_MINOR_VERSION); - - connect_cookie = xcb_dri2_connect_unchecked (c->conn, - c->screen->root, - XCB_DRI2_DRIVER_TYPE_DRI); - - xfixes_query = - xcb_xfixes_query_version_reply (c->conn, - xfixes_query_cookie, &error); - if (xfixes_query == NULL || - error != NULL || xfixes_query->major_version < 2) { - free(error); - return -1; - } - free(xfixes_query); - - dri2_query = - xcb_dri2_query_version_reply (c->conn, - dri2_query_cookie, &error); - if (dri2_query == NULL || error != NULL) { - fprintf(stderr, "DRI2: failed to query version\n"); - free(error); - return EGL_FALSE; - } - c->dri2_major = dri2_query->major_version; - c->dri2_minor = dri2_query->minor_version; - free(dri2_query); - - connect = xcb_dri2_connect_reply (c->conn, - connect_cookie, NULL); - if (connect == NULL || - connect->driver_name_length + connect->device_name_length == 0) { - fprintf(stderr, "DRI2: failed to connect, DRI2 version: %u.%u\n", - c->dri2_major, c->dri2_minor); - return -1; - } - -#ifdef XCB_DRI2_CONNECT_DEVICE_NAME_BROKEN - { - char *driver_name, *device_name; - - driver_name = xcb_dri2_connect_driver_name (connect); - device_name = driver_name + - ((connect->driver_name_length + 3) & ~3); - snprintf(path, sizeof path, "%.*s", - xcb_dri2_connect_device_name_length (connect), - device_name); - } -#else - snprintf(path, sizeof path, "%.*s", - xcb_dri2_connect_device_name_length (connect), - xcb_dri2_connect_device_name (connect)); -#endif - free(connect); - - fd = open(path, O_RDWR); - if (fd < 0) { - fprintf(stderr, - "DRI2: could not open %s (%s)\n", path, strerror(errno)); - return -1; - } - - return wlsc_drm_init(&c->base, fd, path); -} - -static int -dri2_authenticate(struct x11_compositor *c, uint32_t magic) -{ - xcb_dri2_authenticate_reply_t *authenticate; - xcb_dri2_authenticate_cookie_t authenticate_cookie; - - authenticate_cookie = - xcb_dri2_authenticate_unchecked(c->conn, - c->screen->root, magic); - authenticate = - xcb_dri2_authenticate_reply(c->conn, - authenticate_cookie, NULL); - if (authenticate == NULL || !authenticate->authenticated) { - fprintf(stderr, "DRI2: failed to authenticate\n"); - free(authenticate); - return -1; - } - - free(authenticate); - - return 0; -} - -static int -x11_compositor_init_egl(struct x11_compositor *c) -{ - EGLint major, minor; - const char *extensions; - drm_magic_t magic; - static const EGLint context_attribs[] = { - EGL_CONTEXT_CLIENT_VERSION, 2, - EGL_NONE - }; - - if (dri2_connect(c) < 0) - return -1; - - if (drmGetMagic(c->base.drm.fd, &magic)) { - fprintf(stderr, "DRI2: failed to get drm magic\n"); - return -1; - } - - if (dri2_authenticate(c, magic) < 0) - return -1; - - c->base.display = eglGetDRMDisplayMESA(c->base.drm.fd); - if (c->base.display == NULL) { - fprintf(stderr, "failed to create display\n"); - return -1; - } - - if (!eglInitialize(c->base.display, &major, &minor)) { - fprintf(stderr, "failed to initialize display\n"); - return -1; - } - - extensions = eglQueryString(c->base.display, EGL_EXTENSIONS); - if (!strstr(extensions, "EGL_KHR_surfaceless_opengl")) { - fprintf(stderr, "EGL_KHR_surfaceless_opengl not available\n"); - return -1; - } - - if (!eglBindAPI(EGL_OPENGL_ES_API)) { - fprintf(stderr, "failed to bind EGL_OPENGL_ES_API\n"); - return -1; - } - - c->base.context = eglCreateContext(c->base.display, NULL, - EGL_NO_CONTEXT, context_attribs); - if (c->base.context == NULL) { - fprintf(stderr, "failed to create context\n"); - return -1; - } - - if (!eglMakeCurrent(c->base.display, EGL_NO_SURFACE, - EGL_NO_SURFACE, c->base.context)) { - fprintf(stderr, "failed to make context current\n"); - return -1; - } - - return 0; -} - -static void -x11_compositor_present(struct wlsc_compositor *base) -{ - struct x11_compositor *c = (struct x11_compositor *) base; - struct x11_output *output; - xcb_dri2_copy_region_cookie_t cookie; - struct timeval tv; - uint32_t msec; - - glFlush(); - - wl_list_for_each(output, &c->base.output_list, base.link) { - cookie = xcb_dri2_copy_region_unchecked(c->conn, - output->window, - output->region, - XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT, - XCB_DRI2_ATTACHMENT_BUFFER_BACK_LEFT); - free(xcb_dri2_copy_region_reply(c->conn, cookie, NULL)); - } - - gettimeofday(&tv, NULL); - msec = tv.tv_sec * 1000 + tv.tv_usec / 1000; - wlsc_compositor_finish_frame(&c->base, msec); -} - -static void -x11_output_set_wm_protocols(struct x11_output *output) -{ - xcb_atom_t list[1]; - struct x11_compositor *c = - (struct x11_compositor *) output->base.compositor; - - list[0] = c->atom.wm_delete_window; - xcb_change_property (c->conn, - XCB_PROP_MODE_REPLACE, - output->window, - c->atom.wm_protocols, - XCB_ATOM_ATOM, - 32, - ARRAY_SIZE(list), - list); -} - -struct wm_normal_hints { - uint32_t flags; - uint32_t pad[4]; - int32_t min_width, min_height; - int32_t max_width, max_height; - int32_t width_inc, height_inc; - int32_t min_aspect_x, min_aspect_y; - int32_t max_aspect_x, max_aspect_y; - int32_t base_width, base_height; - int32_t win_gravity; -}; - -#define WM_NORMAL_HINTS_MIN_SIZE 16 -#define WM_NORMAL_HINTS_MAX_SIZE 32 - -static void -x11_output_set_icon(struct x11_compositor *c, struct x11_output *output, - const char *filename, int width, int height) -{ - uint32_t *icon, *pixels; - - pixels = wlsc_load_image(filename, width, height); - if (!pixels) - return; - icon = malloc(width * height * 4 + 8); - if (!icon) { - free(pixels); - return; - } - - icon[0] = width; - icon[1] = height; - memcpy(icon + 2, pixels, width * height * 4); - xcb_change_property(c->conn, XCB_PROP_MODE_REPLACE, output->window, - c->atom.net_wm_icon, c->atom.cardinal, 32, - width * height + 2, icon); - free(icon); - free(pixels); -} - -static int -x11_compositor_create_output(struct x11_compositor *c, int width, int height) -{ - static const char name[] = "Wayland Compositor"; - static const char class[] = "wayland-1\0Wayland Compositor"; - struct x11_output *output; - xcb_dri2_dri2_buffer_t *buffers; - xcb_dri2_get_buffers_reply_t *reply; - xcb_dri2_get_buffers_cookie_t cookie; - xcb_screen_iterator_t iter; - xcb_rectangle_t rectangle; - struct wm_normal_hints normal_hints; - unsigned int attachments[] = - { XCB_DRI2_ATTACHMENT_BUFFER_BACK_LEFT}; - uint32_t mask = XCB_CW_EVENT_MASK | XCB_CW_CURSOR; - uint32_t values[2] = { - XCB_EVENT_MASK_KEY_PRESS | - XCB_EVENT_MASK_KEY_RELEASE | - XCB_EVENT_MASK_BUTTON_PRESS | - XCB_EVENT_MASK_BUTTON_RELEASE | - XCB_EVENT_MASK_POINTER_MOTION | - XCB_EVENT_MASK_EXPOSURE | - XCB_EVENT_MASK_STRUCTURE_NOTIFY | - XCB_EVENT_MASK_ENTER_WINDOW | - XCB_EVENT_MASK_LEAVE_WINDOW | - XCB_EVENT_MASK_KEYMAP_STATE | - XCB_EVENT_MASK_FOCUS_CHANGE, - 0 - }; - - EGLint attribs[] = { - EGL_WIDTH, 0, - EGL_HEIGHT, 0, - EGL_DRM_BUFFER_STRIDE_MESA, 0, - EGL_DRM_BUFFER_FORMAT_MESA, EGL_DRM_BUFFER_FORMAT_ARGB32_MESA, - EGL_NONE - }; - - output = malloc(sizeof *output); - if (output == NULL) - return -1; - - memset(output, 0, sizeof *output); - wlsc_output_init(&output->base, &c->base, 0, 0, width, height); - - values[1] = c->null_cursor; - output->window = xcb_generate_id(c->conn); - iter = xcb_setup_roots_iterator(xcb_get_setup(c->conn)); - xcb_create_window(c->conn, - XCB_COPY_FROM_PARENT, - output->window, - iter.data->root, - 0, 0, - width, height, - 0, - XCB_WINDOW_CLASS_INPUT_OUTPUT, - iter.data->root_visual, - mask, values); - - /* Don't resize me. */ - memset(&normal_hints, 0, sizeof normal_hints); - normal_hints.flags = - WM_NORMAL_HINTS_MAX_SIZE | WM_NORMAL_HINTS_MIN_SIZE; - normal_hints.min_width = width; - normal_hints.min_height = height; - normal_hints.max_width = width; - normal_hints.max_height = height; - xcb_change_property (c->conn, XCB_PROP_MODE_REPLACE, output->window, - c->atom.wm_normal_hints, - c->atom.wm_size_hints, 32, - sizeof normal_hints / 4, - (uint8_t *) &normal_hints); - - /* Set window name. Don't bother with non-EWMH WMs. */ - xcb_change_property(c->conn, XCB_PROP_MODE_REPLACE, output->window, - c->atom.net_wm_name, c->atom.utf8_string, 8, - strlen(name), name); - xcb_change_property(c->conn, XCB_PROP_MODE_REPLACE, output->window, - c->atom.wm_class, c->atom.string, 8, - sizeof class, class); - - x11_output_set_icon(c, output, - DATADIR "/wayland/wayland.png", 128, 128); - - xcb_map_window(c->conn, output->window); - - rectangle.x = 0; - rectangle.y = 0; - rectangle.width = width; - rectangle.height = height; - output->region = xcb_generate_id(c->conn); - xcb_xfixes_create_region(c->conn, output->region, 1, &rectangle); - - xcb_dri2_create_drawable (c->conn, output->window); - - x11_output_set_wm_protocols(output); - - cookie = xcb_dri2_get_buffers_unchecked (c->conn, - output->window, - 1, 1, attachments); - reply = xcb_dri2_get_buffers_reply (c->conn, cookie, NULL); - if (reply == NULL) - return -1; - buffers = xcb_dri2_get_buffers_buffers (reply); - if (buffers == NULL) - return -1; - - if (reply->count != 1) { - fprintf(stderr, - "got wrong number of buffers (%d)\n", reply->count); - return -1; - } - - attribs[1] = reply->width; - attribs[3] = reply->height; - attribs[5] = buffers[0].pitch / 4; - output->image = - eglCreateImageKHR(c->base.display, - EGL_NO_CONTEXT, - EGL_DRM_BUFFER_MESA, - (EGLClientBuffer) buffers[0].name, - attribs); - free(reply); - - glGenRenderbuffers(1, &output->rbo); - glBindRenderbuffer(GL_RENDERBUFFER, output->rbo); - - glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, - output->image); - - glFramebufferRenderbuffer(GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_RENDERBUFFER, - output->rbo); - - wl_list_insert(c->base.output_list.prev, &output->base.link); - - return 0; -} - -static void -idle_repaint(void *data) -{ - struct x11_output *output = data; - struct x11_compositor *c = - (struct x11_compositor *) output->base.compositor; - xcb_xfixes_region_t region; - xcb_dri2_copy_region_cookie_t cookie; - - if (output->damage_count <= ARRAY_SIZE(output->damage)) { - region = xcb_generate_id(c->conn); - xcb_xfixes_create_region(c->conn, region, - output->damage_count, output->damage); - } else { - region = output->region; - } - - cookie = xcb_dri2_copy_region_unchecked(c->conn, - output->window, - region, - XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT, - XCB_DRI2_ATTACHMENT_BUFFER_BACK_LEFT); - - if (region != output->region) - xcb_xfixes_destroy_region(c->conn, region); - - free(xcb_dri2_copy_region_reply(c->conn, cookie, NULL)); - output->damage_count = 0; -} - -static struct x11_output * -x11_compositor_find_output(struct x11_compositor *c, xcb_window_t window) -{ - struct x11_output *output; - - wl_list_for_each(output, &c->base.output_list, base.link) { - if (output->window == window) - return output; - } - - return NULL; -} - -static void -x11_compositor_handle_event(int fd, uint32_t mask, void *data) -{ - struct x11_compositor *c = data; - struct x11_output *output; - xcb_generic_event_t *event; - struct wl_event_loop *loop; - xcb_client_message_event_t *client_message; - xcb_motion_notify_event_t *motion_notify; - xcb_enter_notify_event_t *enter_notify; - xcb_key_press_event_t *key_press; - xcb_button_press_event_t *button_press; - xcb_keymap_notify_event_t *keymap_notify; - xcb_focus_in_event_t *focus_in; - xcb_expose_event_t *expose; - xcb_rectangle_t *r; - xcb_atom_t atom; - uint32_t *k; - int i, set; - - loop = wl_display_get_event_loop(c->base.wl_display); - while (event = xcb_poll_for_event (c->conn), event != NULL) { - switch (event->response_type & ~0x80) { - - case XCB_KEY_PRESS: - key_press = (xcb_key_press_event_t *) event; - notify_key(c->base.input_device, - key_press->time, key_press->detail - 8, 1); - break; - case XCB_KEY_RELEASE: - key_press = (xcb_key_press_event_t *) event; - notify_key(c->base.input_device, - key_press->time, key_press->detail - 8, 0); - break; - case XCB_BUTTON_PRESS: - button_press = (xcb_button_press_event_t *) event; - notify_button(c->base.input_device, - button_press->time, - button_press->detail + BTN_LEFT - 1, 1); - break; - case XCB_BUTTON_RELEASE: - button_press = (xcb_button_press_event_t *) event; - notify_button(c->base.input_device, - button_press->time, - button_press->detail + BTN_LEFT - 1, 0); - break; - - case XCB_MOTION_NOTIFY: - motion_notify = (xcb_motion_notify_event_t *) event; - notify_motion(c->base.input_device, - motion_notify->time, - motion_notify->event_x, - motion_notify->event_y); - break; - - case XCB_EXPOSE: - expose = (xcb_expose_event_t *) event; - output = x11_compositor_find_output(c, expose->window); - if (output->damage_count == 0) - wl_event_loop_add_idle(loop, - idle_repaint, output); - - r = &output->damage[output->damage_count++]; - if (output->damage_count > 16) - break; - r->x = expose->x; - r->y = expose->y; - r->width = expose->width; - r->height = expose->height; - break; - - case XCB_ENTER_NOTIFY: - enter_notify = (xcb_enter_notify_event_t *) event; - if (enter_notify->state >= Button1Mask) - break; - output = x11_compositor_find_output(c, enter_notify->event); - notify_pointer_focus(c->base.input_device, - enter_notify->time, - &output->base, - enter_notify->event_x, - enter_notify->event_y); - break; - - case XCB_LEAVE_NOTIFY: - enter_notify = (xcb_enter_notify_event_t *) event; - if (enter_notify->state >= Button1Mask) - break; - notify_pointer_focus(c->base.input_device, - enter_notify->time, - NULL, - enter_notify->event_x, - enter_notify->event_y); - break; - - case XCB_CLIENT_MESSAGE: - client_message = (xcb_client_message_event_t *) event; - atom = client_message->data.data32[0]; - if (atom == c->atom.wm_delete_window) - wl_display_terminate(c->base.wl_display); - break; - - case XCB_FOCUS_IN: - focus_in = (xcb_focus_in_event_t *) event; - if (focus_in->mode == XCB_NOTIFY_MODE_WHILE_GRABBED) - break; - - output = x11_compositor_find_output(c, focus_in->event); - notify_keyboard_focus(c->base.input_device, - get_time(), - &output->base, &c->keys); - break; - - case XCB_FOCUS_OUT: - focus_in = (xcb_focus_in_event_t *) event; - if (focus_in->mode == XCB_NOTIFY_MODE_WHILE_GRABBED) - break; - notify_keyboard_focus(c->base.input_device, - get_time(), NULL, NULL); - break; - - case XCB_KEYMAP_NOTIFY: - keymap_notify = (xcb_keymap_notify_event_t *) event; - c->keys.size = 0; - for (i = 0; i < ARRAY_LENGTH(keymap_notify->keys) * 8; i++) { - set = keymap_notify->keys[i >> 3] & - (1 << (i & 7)); - if (set) { - k = wl_array_add(&c->keys, sizeof *k); - *k = i; - } - } - break; - default: - break; - } - - free (event); - } -} - -#define F(field) offsetof(struct x11_compositor, field) - -static void -x11_compositor_get_resources(struct x11_compositor *c) -{ - static const struct { const char *name; int offset; } atoms[] = { - { "WM_PROTOCOLS", F(atom.wm_protocols) }, - { "WM_NORMAL_HINTS", F(atom.wm_normal_hints) }, - { "WM_SIZE_HINTS", F(atom.wm_size_hints) }, - { "WM_DELETE_WINDOW", F(atom.wm_delete_window) }, - { "WM_CLASS", F(atom.wm_class) }, - { "_NET_WM_NAME", F(atom.net_wm_name) }, - { "_NET_WM_ICON", F(atom.net_wm_icon) }, - { "STRING", F(atom.string) }, - { "UTF8_STRING", F(atom.utf8_string) }, - { "CARDINAL", F(atom.cardinal) }, - }; - - xcb_intern_atom_cookie_t cookies[ARRAY_SIZE(atoms)]; - xcb_intern_atom_reply_t *reply; - xcb_pixmap_t pixmap; - xcb_gc_t gc; - int i; - uint8_t data[] = { 0, 0, 0, 0 }; - - for (i = 0; i < ARRAY_SIZE(atoms); i++) - cookies[i] = xcb_intern_atom (c->conn, 0, - strlen(atoms[i].name), - atoms[i].name); - - for (i = 0; i < ARRAY_SIZE(atoms); i++) { - reply = xcb_intern_atom_reply (c->conn, cookies[i], NULL); - *(xcb_atom_t *) ((char *) c + atoms[i].offset) = reply->atom; - free(reply); - } - - pixmap = xcb_generate_id(c->conn); - gc = xcb_generate_id(c->conn); - xcb_create_pixmap(c->conn, 1, pixmap, c->screen->root, 1, 1); - xcb_create_gc(c->conn, gc, pixmap, 0, NULL); - xcb_put_image(c->conn, XCB_IMAGE_FORMAT_XY_PIXMAP, - pixmap, gc, 1, 1, 0, 0, 0, 32, sizeof data, data); - c->null_cursor = xcb_generate_id(c->conn); - xcb_create_cursor (c->conn, c->null_cursor, - pixmap, pixmap, 0, 0, 0, 0, 0, 0, 1, 1); - xcb_free_gc(c->conn, gc); - xcb_free_pixmap(c->conn, pixmap); -} - -static int -x11_authenticate(struct wlsc_compositor *c, uint32_t id) -{ - return dri2_authenticate((struct x11_compositor *) c, id); -} - -static void -x11_destroy(struct wlsc_compositor *ec) -{ - free(ec); -} - -struct wlsc_compositor * -x11_compositor_create(struct wl_display *display, int width, int height) -{ - struct x11_compositor *c; - struct wl_event_loop *loop; - xcb_screen_iterator_t s; - - c = malloc(sizeof *c); - if (c == NULL) - return NULL; - - memset(c, 0, sizeof *c); - c->conn = xcb_connect(0, 0); - - if (xcb_connection_has_error(c->conn)) - return NULL; - - s = xcb_setup_roots_iterator(xcb_get_setup(c->conn)); - c->screen = s.data; - wl_array_init(&c->keys); - - x11_compositor_get_resources(c); - - c->base.wl_display = display; - if (x11_compositor_init_egl(c) < 0) - return NULL; - - c->base.destroy = x11_destroy; - c->base.authenticate = x11_authenticate; - c->base.present = x11_compositor_present; - c->base.create_buffer = wlsc_drm_buffer_create; - - /* Can't init base class until we have a current egl context */ - if (wlsc_compositor_init(&c->base, display) < 0) - return NULL; - - if (x11_compositor_create_output(c, width, height) < 0) - return NULL; - - if (x11_input_create(c) < 0) - return NULL; - - loop = wl_display_get_event_loop(c->base.wl_display); - - c->xcb_source = - wl_event_loop_add_fd(loop, xcb_get_file_descriptor(c->conn), - WL_EVENT_READABLE, - x11_compositor_handle_event, c); - - return &c->base; -} diff --git a/compositor/compositor.c b/compositor/compositor.c deleted file mode 100644 index afff961..0000000 --- a/compositor/compositor.c +++ /dev/null @@ -1,1411 +0,0 @@ -/* - * Copyright © 2008 Kristian Høgsberg - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#define _GNU_SOURCE - -#include "config.h" - -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <stdint.h> -#include <stdarg.h> -#include <sys/ioctl.h> -#include <fcntl.h> -#include <unistd.h> -#include <gdk-pixbuf/gdk-pixbuf.h> -#include <math.h> -#include <linux/input.h> - -#include "wayland-server.h" -#include "compositor.h" - -struct wlsc_switcher { - struct wlsc_compositor *compositor; - struct wlsc_surface *current; - struct wl_listener listener; -}; - -/* The plan here is to generate a random anonymous socket name and - * advertise that through a service on the session dbus. - */ -static const char *option_socket_name = NULL; -static const char *option_background = "background.jpg"; -static const char *option_geometry = "1024x640"; -static int option_connector = 0; - -static const GOptionEntry option_entries[] = { - { "background", 'b', 0, G_OPTION_ARG_STRING, - &option_background, "Background image" }, - { "connector", 'c', 0, G_OPTION_ARG_INT, - &option_connector, "KMS connector" }, - { "geometry", 'g', 0, G_OPTION_ARG_STRING, - &option_geometry, "Geometry" }, - { "socket", 's', 0, G_OPTION_ARG_STRING, - &option_socket_name, "Socket Name" }, - { NULL } -}; - -static void -wlsc_matrix_init(struct wlsc_matrix *matrix) -{ - static const struct wlsc_matrix identity = { - { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 } - }; - - memcpy(matrix, &identity, sizeof identity); -} - -static void -wlsc_matrix_multiply(struct wlsc_matrix *m, const struct wlsc_matrix *n) -{ - struct wlsc_matrix tmp; - const GLfloat *row, *column; - div_t d; - int i, j; - - for (i = 0; i < 16; i++) { - tmp.d[i] = 0; - d = div(i, 4); - row = m->d + d.quot * 4; - column = n->d + d.rem; - for (j = 0; j < 4; j++) - tmp.d[i] += row[j] * column[j * 4]; - } - memcpy(m, &tmp, sizeof tmp); -} - -static void -wlsc_matrix_translate(struct wlsc_matrix *matrix, GLfloat x, GLfloat y, GLfloat z) -{ - struct wlsc_matrix translate = { - { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, x, y, z, 1 } - }; - - wlsc_matrix_multiply(matrix, &translate); -} - -static void -wlsc_matrix_scale(struct wlsc_matrix *matrix, GLfloat x, GLfloat y, GLfloat z) -{ - struct wlsc_matrix scale = { - { x, 0, 0, 0, 0, y, 0, 0, 0, 0, z, 0, 0, 0, 0, 1 } - }; - - wlsc_matrix_multiply(matrix, &scale); -} - -static void -wlsc_matrix_transform(struct wlsc_matrix *matrix, struct wlsc_vector *v) -{ - int i, j; - struct wlsc_vector t; - - for (i = 0; i < 4; i++) { - t.f[i] = 0; - for (j = 0; j < 4; j++) - t.f[i] += v->f[j] * matrix->d[i + j * 4]; - } - - *v = t; -} - -static struct wlsc_surface * -wlsc_surface_create(struct wlsc_compositor *compositor, - int32_t x, int32_t y, int32_t width, int32_t height) -{ - struct wlsc_surface *surface; - - surface = malloc(sizeof *surface); - if (surface == NULL) - return NULL; - - wl_list_init(&surface->surface.destroy_listener_list); - wl_list_init(&surface->link); - surface->map_type = WLSC_SURFACE_MAP_UNMAPPED; - - glGenTextures(1, &surface->texture); - glBindTexture(GL_TEXTURE_2D, surface->texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - surface->compositor = compositor; - surface->visual = NULL; - surface->x = x; - surface->y = y; - surface->width = width; - surface->height = height; - wlsc_matrix_init(&surface->matrix); - wlsc_matrix_scale(&surface->matrix, width, height, 1); - wlsc_matrix_translate(&surface->matrix, x, y, 0); - - wlsc_matrix_init(&surface->matrix_inv); - wlsc_matrix_translate(&surface->matrix_inv, -x, -y, 0); - wlsc_matrix_scale(&surface->matrix_inv, 1.0 / width, 1.0 / height, 1); - - return surface; -} - -void -wlsc_surface_damage_rectangle(struct wlsc_surface *surface, - int32_t x, int32_t y, - int32_t width, int32_t height) -{ - struct wlsc_compositor *compositor = surface->compositor; - - pixman_region32_union_rect(&compositor->damage_region, - &compositor->damage_region, - surface->x + x, surface->y + y, - width, height); - wlsc_compositor_schedule_repaint(compositor); -} - -void -wlsc_surface_damage(struct wlsc_surface *surface) -{ - wlsc_surface_damage_rectangle(surface, 0, 0, - surface->width, surface->height); -} - -uint32_t -get_time(void) -{ - struct timeval tv; - - gettimeofday(&tv, NULL); - - return tv.tv_sec * 1000 + tv.tv_usec / 1000; -} - -static void -destroy_surface(struct wl_resource *resource, struct wl_client *client) -{ - struct wlsc_surface *surface = - container_of(resource, struct wlsc_surface, surface.resource); - struct wl_listener *l, *next; - uint32_t time; - - wlsc_surface_damage(surface); - - wl_list_remove(&surface->link); - glDeleteTextures(1, &surface->texture); - - time = get_time(); - wl_list_for_each_safe(l, next, - &surface->surface.destroy_listener_list, link) - l->func(l, &surface->surface, time); - - free(surface); -} - -uint32_t * -wlsc_load_image(const char *filename, int width, int height) -{ - GdkPixbuf *pixbuf; - GError *error = NULL; - int stride, i, n_channels; - unsigned char *pixels, *end, *argb_pixels, *s, *d; - - pixbuf = gdk_pixbuf_new_from_file_at_scale(filename, - width, height, - FALSE, &error); - if (error != NULL) { - fprintf(stderr, "failed to load image: %s\n", error->message); - g_error_free(error); - return NULL; - } - - stride = gdk_pixbuf_get_rowstride(pixbuf); - pixels = gdk_pixbuf_get_pixels(pixbuf); - n_channels = gdk_pixbuf_get_n_channels(pixbuf); - - argb_pixels = malloc (height * width * 4); - if (argb_pixels == NULL) { - g_object_unref(pixbuf); - return NULL; - } - - if (n_channels == 4) { - for (i = 0; i < height; i++) { - s = pixels + i * stride; - end = s + width * 4; - d = argb_pixels + i * width * 4; - while (s < end) { - unsigned int t; - -#define MULT(_d,c,a,t) \ - do { t = c * a + 0x7f; _d = ((t >> 8) + t) >> 8; } while (0) - - MULT(d[0], s[2], s[3], t); - MULT(d[1], s[1], s[3], t); - MULT(d[2], s[0], s[3], t); - d[3] = s[3]; - s += 4; - d += 4; - } - } - } else if (n_channels == 3) { - for (i = 0; i < height; i++) { - s = pixels + i * stride; - end = s + width * 3; - d = argb_pixels + i * width * 4; - while (s < end) { - d[0] = s[2]; - d[1] = s[1]; - d[2] = s[0]; - d[3] = 0xff; - s += 3; - d += 4; - } - } - } - - g_object_unref(pixbuf); - - return (uint32_t *) argb_pixels; -} - -static struct wl_buffer * -create_buffer_from_png(struct wlsc_compositor *ec, - const char *filename, int width, int height) -{ - uint32_t *pixels; - struct wl_buffer *buffer; - - pixels = wlsc_load_image(filename, width, height); - if(pixels == NULL) - return NULL; - - buffer = ec->create_buffer(ec, width, height, - &ec->compositor.premultiplied_argb_visual, - pixels); - - free(pixels); - - return buffer; -} - -static const struct { - const char *filename; - int hotspot_x, hotspot_y; -} pointer_images[] = { - { DATADIR "/wayland/bottom_left_corner.png", 6, 30 }, - { DATADIR "/wayland/bottom_right_corner.png", 28, 28 }, - { DATADIR "/wayland/bottom_side.png", 16, 20 }, - { DATADIR "/wayland/grabbing.png", 20, 17 }, - { DATADIR "/wayland/left_ptr.png", 10, 5 }, - { DATADIR "/wayland/left_side.png", 10, 20 }, - { DATADIR "/wayland/right_side.png", 30, 19 }, - { DATADIR "/wayland/top_left_corner.png", 8, 8 }, - { DATADIR "/wayland/top_right_corner.png", 26, 8 }, - { DATADIR "/wayland/top_side.png", 18, 8 }, - { DATADIR "/wayland/xterm.png", 15, 15 } -}; - -static void -create_pointer_images(struct wlsc_compositor *ec) -{ - int i, count; - const int width = 32, height = 32; - - count = ARRAY_LENGTH(pointer_images); - ec->pointer_buffers = malloc(count * sizeof *ec->pointer_buffers); - for (i = 0; i < count; i++) { - ec->pointer_buffers[i] = - create_buffer_from_png(ec, - pointer_images[i].filename, - width, height); - } -} - -static struct wlsc_surface * -background_create(struct wlsc_output *output, const char *filename) -{ - struct wlsc_surface *background; - struct wl_buffer *buffer; - - background = wlsc_surface_create(output->compositor, - output->x, output->y, - output->width, output->height); - if (background == NULL) - return NULL; - - buffer = create_buffer_from_png(output->compositor, - filename, - output->width, output->height); - if (buffer == NULL) { - free(background); - return NULL; - } - buffer->attach(buffer, &background->surface); - - return background; -} - -static void -wlsc_surface_draw(struct wlsc_surface *es, - struct wlsc_output *output, pixman_region32_t *clip) -{ - struct wlsc_compositor *ec = es->compositor; - GLfloat *v, inv_width, inv_height; - unsigned int *p; - pixman_region32_t repaint; - pixman_box32_t *rectangles; - int i, n; - - pixman_region32_init_rect(&repaint, - es->x, es->y, es->width, es->height); - pixman_region32_intersect(&repaint, &repaint, clip); - if (!pixman_region32_not_empty(&repaint)) - return; - - if (es->visual == &ec->compositor.argb_visual) { - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_BLEND); - } else if (es->visual == &ec->compositor.premultiplied_argb_visual) { - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_BLEND); - } else { - glDisable(GL_BLEND); - } - - rectangles = pixman_region32_rectangles(&repaint, &n); - v = wl_array_add(&ec->vertices, n * 16 * sizeof *v); - p = wl_array_add(&ec->indices, n * 6 * sizeof *p); - inv_width = 1.0 / es->width; - inv_height = 1.0 / es->height; - for (i = 0; i < n; i++, v += 16, p += 6) { - v[ 0] = rectangles[i].x1; - v[ 1] = rectangles[i].y1; - v[ 2] = (GLfloat) (rectangles[i].x1 - es->x) * inv_width; - v[ 3] = (GLfloat) (rectangles[i].y1 - es->y) * inv_height; - - v[ 4] = rectangles[i].x1; - v[ 5] = rectangles[i].y2; - v[ 6] = v[ 2]; - v[ 7] = (GLfloat) (rectangles[i].y2 - es->y) * inv_height; - - v[ 8] = rectangles[i].x2; - v[ 9] = rectangles[i].y1; - v[10] = (GLfloat) (rectangles[i].x2 - es->x) * inv_width; - v[11] = v[ 3]; - - v[12] = rectangles[i].x2; - v[13] = rectangles[i].y2; - v[14] = v[10]; - v[15] = v[ 7]; - - p[0] = i * 4 + 0; - p[1] = i * 4 + 1; - p[2] = i * 4 + 2; - p[3] = i * 4 + 2; - p[4] = i * 4 + 1; - p[5] = i * 4 + 3; - } - - glBindTexture(GL_TEXTURE_2D, es->texture); - v = ec->vertices.data; - glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[0]); - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[2]); - glEnableVertexAttribArray(0); - glEnableVertexAttribArray(1); - glDrawElements(GL_TRIANGLES, n * 6, GL_UNSIGNED_INT, ec->indices.data); - - ec->vertices.size = 0; - ec->indices.size = 0; - pixman_region32_fini(&repaint); -} - -static void -wlsc_surface_raise(struct wlsc_surface *surface) -{ - struct wlsc_compositor *compositor = surface->compositor; - - wl_list_remove(&surface->link); - wl_list_insert(&compositor->surface_list, &surface->link); -} - -void -wlsc_surface_update_matrix(struct wlsc_surface *es) -{ - wlsc_matrix_init(&es->matrix); - wlsc_matrix_scale(&es->matrix, es->width, es->height, 1); - wlsc_matrix_translate(&es->matrix, es->x, es->y, 0); - - wlsc_matrix_init(&es->matrix_inv); - wlsc_matrix_translate(&es->matrix_inv, -es->x, -es->y, 0); - wlsc_matrix_scale(&es->matrix_inv, - 1.0 / es->width, 1.0 / es->height, 1); -} - -void -wlsc_compositor_finish_frame(struct wlsc_compositor *compositor, int msecs) -{ - wl_display_post_frame(compositor->wl_display, msecs); - wl_event_source_timer_update(compositor->timer_source, 5); - compositor->repaint_on_timeout = 1; -} - -static void -wlsc_output_repaint(struct wlsc_output *output) -{ - struct wlsc_compositor *ec = output->compositor; - struct wlsc_surface *es; - struct wlsc_input_device *eid; - pixman_region32_t new_damage, total_damage; - - glViewport(0, 0, output->width, output->height); - - glUniformMatrix4fv(ec->proj_uniform, 1, GL_FALSE, output->matrix.d); - glUniform1i(ec->tex_uniform, 0); - - pixman_region32_init(&new_damage); - pixman_region32_init(&total_damage); - pixman_region32_intersect_rect(&new_damage, - &ec->damage_region, - output->x, output->y, - output->width, output->height); - pixman_region32_subtract(&ec->damage_region, - &ec->damage_region, &new_damage); - pixman_region32_union(&total_damage, &new_damage, - &output->previous_damage_region); - pixman_region32_copy(&output->previous_damage_region, &new_damage); - - es = container_of(ec->surface_list.next, struct wlsc_surface, link); - if (es->map_type == WLSC_SURFACE_MAP_FULLSCREEN && - es->fullscreen_output == output) { - if (es->width < output->width || es->height < output->height) - glClear(GL_COLOR_BUFFER_BIT); - wlsc_surface_draw(es, output, &total_damage); - } else { - if (output->background) - wlsc_surface_draw(output->background, - output, &total_damage); - else - glClear(GL_COLOR_BUFFER_BIT); - - wl_list_for_each_reverse(es, &ec->surface_list, link) { - if (ec->switcher && - ec->switcher->current == es) - continue; - - wlsc_surface_draw(es, output, &total_damage); - } - } - - if (ec->switcher) - wlsc_surface_draw(ec->switcher->current, - output, &total_damage); - - if (ec->focus) - wl_list_for_each(eid, &ec->input_device_list, link) - wlsc_surface_draw(eid->sprite, output, &total_damage); -} - -static void -repaint(void *data) -{ - struct wlsc_compositor *ec = data; - struct wlsc_output *output; - - if (!ec->repaint_needed) { - ec->repaint_on_timeout = 0; - return; - } - - wl_list_for_each(output, &ec->output_list, link) - wlsc_output_repaint(output); - - ec->present(ec); - - ec->repaint_needed = 0; -} - -void -wlsc_compositor_schedule_repaint(struct wlsc_compositor *compositor) -{ - compositor->repaint_needed = 1; - if (compositor->repaint_on_timeout) - return; - - wl_event_source_timer_update(compositor->timer_source, 1); - compositor->repaint_on_timeout = 1; -} - -static void -surface_destroy(struct wl_client *client, - struct wl_surface *surface) -{ - wl_resource_destroy(&surface->resource, client); -} - -static void -surface_attach(struct wl_client *client, - struct wl_surface *surface, struct wl_buffer *buffer, - int32_t x, int32_t y) -{ - struct wlsc_surface *es = (struct wlsc_surface *) surface; - - /* FIXME: This damages the entire old surface, but we should - * really just damage the part that's no longer covered by the - * surface. Anything covered by the new surface will be - * damaged by the client. */ - wlsc_surface_damage(es); - - buffer->attach(buffer, surface); - es->buffer = buffer; - es->x += x; - es->y += y; - es->width = buffer->width; - es->height = buffer->height; - wlsc_surface_update_matrix(es); -} - -static void -surface_map_toplevel(struct wl_client *client, - struct wl_surface *surface) -{ - struct wlsc_surface *es = (struct wlsc_surface *) surface; - - switch (es->map_type) { - case WLSC_SURFACE_MAP_UNMAPPED: - es->x = 10 + random() % 400; - es->y = 10 + random() % 400; - wlsc_surface_update_matrix(es); - wl_list_insert(&es->compositor->surface_list, &es->link); - break; - case WLSC_SURFACE_MAP_TOPLEVEL: - return; - case WLSC_SURFACE_MAP_FULLSCREEN: - es->fullscreen_output = NULL; - es->x = es->saved_x; - es->y = es->saved_y; - wlsc_surface_update_matrix(es); - break; - default: - break; - } - - wlsc_surface_damage(es); - es->map_type = WLSC_SURFACE_MAP_TOPLEVEL; -} - -static void -surface_map_transient(struct wl_client *client, - struct wl_surface *surface, struct wl_surface *parent, - int x, int y, uint32_t flags) -{ - struct wlsc_surface *es = (struct wlsc_surface *) surface; - struct wlsc_surface *pes = (struct wlsc_surface *) parent; - - switch (es->map_type) { - case WLSC_SURFACE_MAP_UNMAPPED: - wl_list_insert(&es->compositor->surface_list, &es->link); - break; - case WLSC_SURFACE_MAP_FULLSCREEN: - es->fullscreen_output = NULL; - break; - default: - break; - } - - es->x = pes->x + x; - es->y = pes->y + y; - - wlsc_surface_update_matrix(es); - wlsc_surface_damage(es); - es->map_type = WLSC_SURFACE_MAP_TRANSIENT; -} - -static void -surface_map_fullscreen(struct wl_client *client, struct wl_surface *surface) -{ - struct wlsc_surface *es = (struct wlsc_surface *) surface; - struct wlsc_output *output; - - switch (es->map_type) { - case WLSC_SURFACE_MAP_UNMAPPED: - es->x = 10 + random() % 400; - es->y = 10 + random() % 400; - wl_list_insert(&es->compositor->surface_list, &es->link); - break; - case WLSC_SURFACE_MAP_FULLSCREEN: - return; - default: - break; - } - - /* FIXME: Fullscreen on first output */ - /* FIXME: Handle output going away */ - output = container_of(es->compositor->output_list.next, - struct wlsc_output, link); - - es->saved_x = es->x; - es->saved_y = es->y; - es->x = (output->width - es->width) / 2; - es->y = (output->height - es->height) / 2; - es->fullscreen_output = output; - wlsc_surface_update_matrix(es); - wlsc_surface_damage(es); - es->map_type = WLSC_SURFACE_MAP_FULLSCREEN; -} - -static void -surface_damage(struct wl_client *client, - struct wl_surface *surface, - int32_t x, int32_t y, int32_t width, int32_t height) -{ - struct wlsc_surface *es = (struct wlsc_surface *) surface; - - es->buffer->damage(es->buffer, surface, x, y, width, height); - - wlsc_surface_damage_rectangle(es, x, y, width, height); -} - -const static struct wl_surface_interface surface_interface = { - surface_destroy, - surface_attach, - surface_map_toplevel, - surface_map_transient, - surface_map_fullscreen, - surface_damage -}; - -static void -wlsc_input_device_attach(struct wlsc_input_device *device, - struct wl_buffer *buffer, int x, int y) -{ - wlsc_surface_damage(device->sprite); - - buffer->attach(buffer, &device->sprite->surface); - device->hotspot_x = x; - device->hotspot_y = y; - - device->sprite->x = device->input_device.x - device->hotspot_x; - device->sprite->y = device->input_device.y - device->hotspot_y; - device->sprite->width = buffer->width; - device->sprite->height = buffer->height; - wlsc_surface_update_matrix(device->sprite); - - wlsc_surface_damage(device->sprite); -} - - -void -wlsc_input_device_set_pointer_image(struct wlsc_input_device *device, - enum wlsc_pointer_type type) -{ - struct wlsc_compositor *compositor = - (struct wlsc_compositor *) device->input_device.compositor; - - wlsc_input_device_attach(device, - compositor->pointer_buffers[type], - pointer_images[type].hotspot_x, - pointer_images[type].hotspot_y); -} - -static void -compositor_create_surface(struct wl_client *client, - struct wl_compositor *compositor, uint32_t id) -{ - struct wlsc_compositor *ec = (struct wlsc_compositor *) compositor; - struct wlsc_surface *surface; - - surface = wlsc_surface_create(ec, 0, 0, 0, 0); - if (surface == NULL) { - wl_client_post_no_memory(client); - return; - } - - surface->surface.resource.destroy = destroy_surface; - - surface->surface.resource.object.id = id; - surface->surface.resource.object.interface = &wl_surface_interface; - surface->surface.resource.object.implementation = - (void (**)(void)) &surface_interface; - surface->surface.client = client; - - wl_client_add_resource(client, &surface->surface.resource); -} - -const static struct wl_compositor_interface compositor_interface = { - compositor_create_surface, -}; - -static void -wlsc_surface_transform(struct wlsc_surface *surface, - int32_t x, int32_t y, int32_t *sx, int32_t *sy) -{ - struct wlsc_vector v = { { x, y, 0, 1 } }; - - wlsc_matrix_transform(&surface->matrix_inv, &v); - *sx = v.f[0] * surface->width; - *sy = v.f[1] * surface->height; -} - -struct wlsc_surface * -pick_surface(struct wl_input_device *device, int32_t *sx, int32_t *sy) -{ - struct wlsc_compositor *ec = - (struct wlsc_compositor *) device->compositor; - struct wlsc_surface *es; - - wl_list_for_each(es, &ec->surface_list, link) { - wlsc_surface_transform(es, device->x, device->y, sx, sy); - if (0 <= *sx && *sx < es->width && - 0 <= *sy && *sy < es->height) - return es; - } - - return NULL; -} - - -static void -motion_grab_motion(struct wl_grab *grab, - uint32_t time, int32_t x, int32_t y) -{ - struct wlsc_input_device *device = - (struct wlsc_input_device *) grab->input_device; - struct wlsc_surface *es = - (struct wlsc_surface *) device->input_device.pointer_focus; - int32_t sx, sy; - - wlsc_surface_transform(es, x, y, &sx, &sy); - wl_client_post_event(es->surface.client, - &device->input_device.object, - WL_INPUT_DEVICE_MOTION, - time, x, y, sx, sy); -} - -static void -motion_grab_button(struct wl_grab *grab, - uint32_t time, int32_t button, int32_t state) -{ - wl_client_post_event(grab->input_device->pointer_focus->client, - &grab->input_device->object, - WL_INPUT_DEVICE_BUTTON, - time, button, state); -} - -static void -motion_grab_end(struct wl_grab *grab, uint32_t time) -{ -} - -static const struct wl_grab_interface motion_grab_interface = { - motion_grab_motion, - motion_grab_button, - motion_grab_end -}; - -void -notify_motion(struct wl_input_device *device, uint32_t time, int x, int y) -{ - struct wlsc_surface *es; - struct wlsc_compositor *ec = - (struct wlsc_compositor *) device->compositor; - struct wlsc_output *output; - const struct wl_grab_interface *interface; - struct wlsc_input_device *wd = (struct wlsc_input_device *) device; - int32_t sx, sy; - - /* FIXME: We need some multi head love here. */ - output = container_of(ec->output_list.next, struct wlsc_output, link); - if (x < output->x) - x = 0; - if (y < output->y) - y = 0; - if (x >= output->x + output->width) - x = output->x + output->width - 1; - if (y >= output->y + output->height) - y = output->y + output->height - 1; - - device->x = x; - device->y = y; - - if (device->grab) { - interface = device->grab->interface; - interface->motion(device->grab, time, x, y); - } else { - es = pick_surface(device, &sx, &sy); - wl_input_device_set_pointer_focus(device, - &es->surface, - time, x, y, sx, sy); - if (es) - wl_client_post_event(es->surface.client, - &device->object, - WL_INPUT_DEVICE_MOTION, - time, x, y, sx, sy); - } - - wlsc_surface_damage(wd->sprite); - - wd->sprite->x = device->x - wd->hotspot_x; - wd->sprite->y = device->y - wd->hotspot_y; - wlsc_surface_update_matrix(wd->sprite); - - wlsc_surface_damage(wd->sprite); -} - -static void -wlsc_surface_activate(struct wlsc_surface *surface, - struct wlsc_input_device *device, uint32_t time) -{ - wlsc_surface_raise(surface); - if (device->selection) - wlsc_selection_set_focus(device->selection, - &surface->surface, time); - - wl_input_device_set_keyboard_focus(&device->input_device, - &surface->surface, - time); -} - -void -notify_button(struct wl_input_device *device, - uint32_t time, int32_t button, int32_t state) -{ - struct wlsc_input_device *wd = (struct wlsc_input_device *) device; - struct wlsc_surface *surface; - struct wlsc_compositor *compositor = - (struct wlsc_compositor *) device->compositor; - - surface = (struct wlsc_surface *) device->pointer_focus; - uint32_t edges = 0; - int32_t x, y; - - if (state && surface && device->grab == NULL) { - wlsc_surface_activate(surface, wd, time); - wl_input_device_start_grab(device, - &device->motion_grab, - button, time); - } - - if (state && surface && button == BTN_LEFT && - (wd->modifier_state & MODIFIER_SUPER)) - shell_move(NULL, - (struct wl_shell *) &compositor->shell, - &surface->surface, device, time); - else if (state && surface && button == BTN_MIDDLE && - (wd->modifier_state & MODIFIER_SUPER)) { - - x = device->grab_x - surface->x; - y = device->grab_y - surface->y; - - if (x < surface->width / 3) - edges |= WL_SHELL_RESIZE_LEFT; - else if (x < 2 * surface->width / 3) - edges |= 0; - else - edges |= WL_SHELL_RESIZE_RIGHT; - - if (y < surface->height / 3) - edges |= WL_SHELL_RESIZE_TOP; - else if (y < 2 * surface->height / 3) - edges |= 0; - else - edges |= WL_SHELL_RESIZE_BOTTOM; - - shell_resize(NULL, - (struct wl_shell *) &compositor->shell, - &surface->surface, device, time, edges); - } - - if (device->grab) - device->grab->interface->button(device->grab, time, - button, state); - - if (!state && device->grab && device->grab_button == button) - wl_input_device_end_grab(device, time); -} - -static void -wlsc_switcher_next(struct wlsc_switcher *switcher) -{ - struct wl_list *l; - - wlsc_surface_damage(switcher->current); - l = switcher->current->link.next; - if (l == &switcher->compositor->surface_list) - l = switcher->compositor->surface_list.next; - switcher->current = container_of(l, struct wlsc_surface, link); - wl_list_remove(&switcher->listener.link); - wl_list_insert(switcher->current->surface.destroy_listener_list.prev, - &switcher->listener.link); - wlsc_surface_damage(switcher->current); -} - -static void -switcher_handle_surface_destroy(struct wl_listener *listener, - struct wl_surface *surface, uint32_t time) -{ - struct wlsc_switcher *switcher = - container_of(listener, struct wlsc_switcher, listener); - - wlsc_switcher_next(switcher); -} - -static struct wlsc_switcher * -wlsc_switcher_create(struct wlsc_compositor *compositor) -{ - struct wlsc_switcher *switcher; - - switcher = malloc(sizeof *switcher); - switcher->compositor = compositor; - switcher->current = container_of(compositor->surface_list.next, - struct wlsc_surface, link); - switcher->listener.func = switcher_handle_surface_destroy; - wl_list_init(&switcher->listener.link); - - return switcher; -} - -static void -wlsc_switcher_destroy(struct wlsc_switcher *switcher) -{ - wl_list_remove(&switcher->listener.link); - free(switcher); -} - -void -notify_key(struct wl_input_device *device, - uint32_t time, uint32_t key, uint32_t state) -{ - struct wlsc_input_device *wd = (struct wlsc_input_device *) device; - struct wlsc_compositor *compositor = - (struct wlsc_compositor *) device->compositor; - uint32_t *k, *end; - uint32_t modifier; - - switch (key | wd->modifier_state) { - case KEY_BACKSPACE | MODIFIER_CTRL | MODIFIER_ALT: - wl_display_terminate(compositor->wl_display); - return; - - case KEY_TAB | MODIFIER_SUPER: - if (!state) - return; - if (wl_list_empty(&compositor->surface_list)) - return; - if (compositor->switcher == NULL) - compositor->switcher = wlsc_switcher_create(compositor); - - wlsc_switcher_next(compositor->switcher); - return; - - case KEY_LEFTMETA | MODIFIER_SUPER: - case KEY_RIGHTMETA | MODIFIER_SUPER: - if (compositor->switcher && !state) { - wlsc_surface_activate(compositor->switcher->current, - wd, time); - wlsc_switcher_destroy(compositor->switcher); - compositor->switcher = NULL; - } - break; - } - - switch (key) { - case KEY_LEFTCTRL: - case KEY_RIGHTCTRL: - modifier = MODIFIER_CTRL; - break; - - case KEY_LEFTALT: - case KEY_RIGHTALT: - modifier = MODIFIER_ALT; - break; - - case KEY_LEFTMETA: - case KEY_RIGHTMETA: - modifier = MODIFIER_SUPER; - break; - - default: - modifier = 0; - break; - } - - if (state) - wd->modifier_state |= modifier; - else - wd->modifier_state &= ~modifier; - - end = device->keys.data + device->keys.size; - for (k = device->keys.data; k < end; k++) { - if (*k == key) - *k = *--end; - } - device->keys.size = (void *) end - device->keys.data; - if (state) { - k = wl_array_add(&device->keys, sizeof *k); - *k = key; - } - - if (device->keyboard_focus != NULL) - wl_client_post_event(device->keyboard_focus->client, - &device->object, - WL_INPUT_DEVICE_KEY, time, key, state); -} - -void -notify_pointer_focus(struct wl_input_device *device, - uint32_t time, struct wlsc_output *output, - int32_t x, int32_t y) -{ - struct wlsc_input_device *wd = (struct wlsc_input_device *) device; - struct wlsc_compositor *compositor = - (struct wlsc_compositor *) device->compositor; - struct wlsc_surface *es; - int32_t sx, sy; - - if (output) { - device->x = x; - device->y = y; - es = pick_surface(device, &sx, &sy); - wl_input_device_set_pointer_focus(device, - &es->surface, - time, x, y, sx, sy); - - compositor->focus = 1; - - wd->sprite->x = device->x - wd->hotspot_x; - wd->sprite->y = device->y - wd->hotspot_y; - wlsc_surface_update_matrix(wd->sprite); - } else { - wl_input_device_set_pointer_focus(device, NULL, - time, 0, 0, 0, 0); - compositor->focus = 0; - } - - wlsc_surface_damage(wd->sprite); -} - -void -notify_keyboard_focus(struct wl_input_device *device, - uint32_t time, struct wlsc_output *output, - struct wl_array *keys) -{ - struct wlsc_input_device *wd = - (struct wlsc_input_device *) device; - struct wlsc_compositor *compositor = - (struct wlsc_compositor *) device->compositor; - struct wlsc_surface *es; - - if (!wl_list_empty(&compositor->surface_list)) - es = container_of(compositor->surface_list.next, - struct wlsc_surface, link); - else - es = NULL; - - if (output) { - wl_array_copy(&wd->input_device.keys, keys); - wl_input_device_set_keyboard_focus(&wd->input_device, - &es->surface, time); - } else { - wl_input_device_set_keyboard_focus(&wd->input_device, - NULL, time); - } -} - - -static void -input_device_attach(struct wl_client *client, - struct wl_input_device *device_base, - uint32_t time, - struct wl_buffer *buffer, int32_t x, int32_t y) -{ - struct wlsc_input_device *device = - (struct wlsc_input_device *) device_base; - - if (time < device->input_device.pointer_focus_time) - return; - if (device->input_device.pointer_focus == NULL) - return; - if (device->input_device.pointer_focus->client != client) - return; - - if (buffer == NULL) { - wlsc_input_device_set_pointer_image(device, - WLSC_POINTER_LEFT_PTR); - return; - } - - wlsc_input_device_attach(device, buffer, x, y); -} - -const static struct wl_input_device_interface input_device_interface = { - input_device_attach, -}; - -void -wlsc_input_device_init(struct wlsc_input_device *device, - struct wlsc_compositor *ec) -{ - wl_input_device_init(&device->input_device, &ec->compositor); - - device->input_device.object.interface = &wl_input_device_interface; - device->input_device.object.implementation = - (void (**)(void)) &input_device_interface; - wl_display_add_object(ec->wl_display, &device->input_device.object); - wl_display_add_global(ec->wl_display, &device->input_device.object, NULL); - - device->sprite = wlsc_surface_create(ec, - device->input_device.x, - device->input_device.y, 32, 32); - device->hotspot_x = 16; - device->hotspot_y = 16; - - device->input_device.motion_grab.interface = &motion_grab_interface; - - wl_list_insert(ec->input_device_list.prev, &device->link); - - wlsc_input_device_set_pointer_image(device, WLSC_POINTER_LEFT_PTR); -} - -static void -wlsc_output_post_geometry(struct wl_client *client, struct wl_object *global) -{ - struct wlsc_output *output = - container_of(global, struct wlsc_output, object); - - wl_client_post_event(client, global, - WL_OUTPUT_GEOMETRY, - output->x, output->y, - output->width, output->height); -} - -static const char vertex_shader[] = - "uniform mat4 proj;\n" - "attribute vec2 position;\n" - "attribute vec2 texcoord;\n" - "varying vec2 v_texcoord;\n" - "void main()\n" - "{\n" - " gl_Position = proj * vec4(position, 0.0, 1.0);\n" - " v_texcoord = texcoord;\n" - "}\n"; - -static const char fragment_shader[] = - "precision mediump float;\n" - "varying vec2 v_texcoord;\n" - "uniform sampler2D tex;\n" - "void main()\n" - "{\n" - " gl_FragColor = texture2D(tex, v_texcoord)\n;" - "}\n"; - -static int -init_shaders(struct wlsc_compositor *ec) -{ - GLuint v, f, program; - const char *p; - char msg[512]; - GLint status; - - p = vertex_shader; - v = glCreateShader(GL_VERTEX_SHADER); - glShaderSource(v, 1, &p, NULL); - glCompileShader(v); - glGetShaderiv(v, GL_COMPILE_STATUS, &status); - if (!status) { - glGetShaderInfoLog(v, sizeof msg, NULL, msg); - fprintf(stderr, "vertex shader info: %s\n", msg); - return -1; - } - - p = fragment_shader; - f = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(f, 1, &p, NULL); - glCompileShader(f); - glGetShaderiv(f, GL_COMPILE_STATUS, &status); - if (!status) { - glGetShaderInfoLog(f, sizeof msg, NULL, msg); - fprintf(stderr, "fragment shader info: %s\n", msg); - return -1; - } - - program = glCreateProgram(); - glAttachShader(program, v); - glAttachShader(program, f); - glBindAttribLocation(program, 0, "position"); - glBindAttribLocation(program, 1, "texcoord"); - - glLinkProgram(program); - glGetProgramiv(program, GL_LINK_STATUS, &status); - if (!status) { - glGetProgramInfoLog(program, sizeof msg, NULL, msg); - fprintf(stderr, "link info: %s\n", msg); - return -1; - } - - glUseProgram(program); - ec->proj_uniform = glGetUniformLocation(program, "proj"); - ec->tex_uniform = glGetUniformLocation(program, "tex"); - - return 0; -} - -void -wlsc_output_init(struct wlsc_output *output, struct wlsc_compositor *c, - int x, int y, int width, int height) -{ - output->compositor = c; - output->x = x; - output->y = y; - output->width = width; - output->height = height; - - pixman_region32_init(&output->previous_damage_region); - - output->background = - background_create(output, option_background); - - wlsc_matrix_init(&output->matrix); - wlsc_matrix_translate(&output->matrix, - -output->x - output->width / 2.0, - -output->y - output->height / 2.0, 0); - wlsc_matrix_scale(&output->matrix, - 2.0 / output->width, 2.0 / output->height, 1); - - output->object.interface = &wl_output_interface; - wl_display_add_object(c->wl_display, &output->object); - wl_display_add_global(c->wl_display, &output->object, - wlsc_output_post_geometry); - - pixman_region32_union_rect(&c->damage_region, - &c->damage_region, - x, y, width, height); -} - -int -wlsc_compositor_init(struct wlsc_compositor *ec, struct wl_display *display) -{ - struct wl_event_loop *loop; - const char *extensions; - - ec->wl_display = display; - - wl_compositor_init(&ec->compositor, &compositor_interface, display); - - wlsc_shm_init(ec); - - wlsc_shell_init(ec); - - wl_list_init(&ec->surface_list); - wl_list_init(&ec->input_device_list); - wl_list_init(&ec->output_list); - - create_pointer_images(ec); - - screenshooter_create(ec); - - extensions = (const char *) glGetString(GL_EXTENSIONS); - if (!strstr(extensions, "GL_EXT_texture_format_BGRA8888")) { - fprintf(stderr, - "GL_EXT_texture_format_BGRA8888 not available\n"); - return -1; - } - - glGenFramebuffers(1, &ec->fbo); - glBindFramebuffer(GL_FRAMEBUFFER, ec->fbo); - glActiveTexture(GL_TEXTURE0); - if (init_shaders(ec) < 0) - return -1; - - loop = wl_display_get_event_loop(ec->wl_display); - ec->timer_source = wl_event_loop_add_timer(loop, repaint, ec); - pixman_region32_init(&ec->damage_region); - wlsc_compositor_schedule_repaint(ec); - - return 0; -} - -static void on_term_signal(int signal_number, void *data) -{ - struct wlsc_compositor *ec = data; - - wl_display_terminate(ec->wl_display); -} - -int main(int argc, char *argv[]) -{ - struct wl_display *display; - struct wlsc_compositor *ec; - struct wl_event_loop *loop; - GError *error = NULL; - GOptionContext *context; - int width, height; - - g_type_init(); /* GdkPixbuf needs this, it seems. */ - - context = g_option_context_new(NULL); - g_option_context_add_main_entries(context, option_entries, "Wayland"); - if (!g_option_context_parse(context, &argc, &argv, &error)) { - fprintf(stderr, "option parsing failed: %s\n", error->message); - exit(EXIT_FAILURE); - } - if (sscanf(option_geometry, "%dx%d", &width, &height) != 2) { - fprintf(stderr, "invalid geometry option: %s \n", - option_geometry); - exit(EXIT_FAILURE); - } - - display = wl_display_create(); - - ec = NULL; - -#if BUILD_WAYLAND_COMPOSITOR - if (getenv("WAYLAND_DISPLAY")) - ec = wayland_compositor_create(display, width, height); -#endif - -#if BUILD_X11_COMPOSITOR - if (ec == NULL && getenv("DISPLAY")) - ec = x11_compositor_create(display, width, height); -#endif - -#if BUILD_DRM_COMPOSITOR - if (ec == NULL) - ec = drm_compositor_create(display, option_connector); -#endif - - if (ec == NULL) { - fprintf(stderr, "failed to create compositor\n"); - exit(EXIT_FAILURE); - } - - if (wl_display_add_socket(display, option_socket_name)) { - fprintf(stderr, "failed to add socket: %m\n"); - exit(EXIT_FAILURE); - } - - loop = wl_display_get_event_loop(ec->wl_display); - wl_event_loop_add_signal(loop, SIGTERM, on_term_signal, ec); - wl_event_loop_add_signal(loop, SIGINT, on_term_signal, ec); - - wl_display_run(display); - - wl_display_destroy(display); - - ec->destroy(ec); - - return 0; -} diff --git a/compositor/compositor.h b/compositor/compositor.h deleted file mode 100644 index b0901e8..0000000 --- a/compositor/compositor.h +++ /dev/null @@ -1,269 +0,0 @@ -/* - * Copyright © 2008 Kristian Høgsberg - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef _WAYLAND_SYSTEM_COMPOSITOR_H_ -#define _WAYLAND_SYSTEM_COMPOSITOR_H_ - -#include <xf86drm.h> -#include <xf86drmMode.h> -#include <libudev.h> -#include <pixman.h> -#include "wayland-server.h" -#include "wayland-util.h" - -#define GL_GLEXT_PROTOTYPES -#define EGL_EGLEXT_PROTOTYPES -#include <GLES2/gl2.h> -#include <GLES2/gl2ext.h> -#include <EGL/egl.h> -#include <EGL/eglext.h> - -#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0]) - -struct wlsc_matrix { - GLfloat d[16]; -}; - -struct wlsc_surface; - -struct wlsc_output { - struct wl_object object; - struct wl_list link; - struct wlsc_compositor *compositor; - struct wlsc_surface *background; - struct wlsc_matrix matrix; - int32_t x, y, width, height; - pixman_region32_t previous_damage_region; -}; - -enum wlsc_pointer_type { - WLSC_POINTER_BOTTOM_LEFT, - WLSC_POINTER_BOTTOM_RIGHT, - WLSC_POINTER_BOTTOM, - WLSC_POINTER_DRAGGING, - WLSC_POINTER_LEFT_PTR, - WLSC_POINTER_LEFT, - WLSC_POINTER_RIGHT, - WLSC_POINTER_TOP_LEFT, - WLSC_POINTER_TOP_RIGHT, - WLSC_POINTER_TOP, - WLSC_POINTER_IBEAM, -}; - -struct wlsc_input_device { - struct wl_input_device input_device; - struct wlsc_surface *sprite; - int32_t hotspot_x, hotspot_y; - struct wl_list link; - uint32_t modifier_state; - struct wl_selection *selection; -}; - -struct wlsc_drm { - struct wl_object object; - int fd; - char *filename; -}; - -struct wlsc_shm { - struct wl_object object; -}; - -struct wlsc_compositor { - struct wl_compositor compositor; - - struct wlsc_drm drm; - struct wlsc_shm shm; - EGLDisplay display; - EGLContext context; - GLuint fbo; - GLuint proj_uniform, tex_uniform; - struct wl_buffer **pointer_buffers; - struct wl_display *wl_display; - - /* We implement the shell interface. */ - struct wl_shell shell; - - /* There can be more than one, but not right now... */ - struct wl_input_device *input_device; - - struct wl_list output_list; - struct wl_list input_device_list; - struct wl_list surface_list; - - /* Repaint state. */ - struct wl_event_source *timer_source; - int repaint_needed; - int repaint_on_timeout; - struct timespec previous_swap; - pixman_region32_t damage_region; - struct wl_array vertices, indices; - - struct wlsc_switcher *switcher; - uint32_t focus; - - void (*destroy)(struct wlsc_compositor *ec); - int (*authenticate)(struct wlsc_compositor *c, uint32_t id); - void (*present)(struct wlsc_compositor *c); - struct wl_buffer *(*create_buffer)(struct wlsc_compositor *c, - int32_t width, int32_t height, - struct wl_visual *visual, - const void *data); -}; - -#define MODIFIER_CTRL (1 << 8) -#define MODIFIER_ALT (1 << 9) -#define MODIFIER_SUPER (1 << 10) - -struct wlsc_vector { - GLfloat f[4]; -}; - -enum wlsc_surface_map_type { - WLSC_SURFACE_MAP_UNMAPPED, - WLSC_SURFACE_MAP_TOPLEVEL, - WLSC_SURFACE_MAP_TRANSIENT, - WLSC_SURFACE_MAP_FULLSCREEN -}; - -struct wlsc_surface { - struct wl_surface surface; - struct wlsc_compositor *compositor; - GLuint texture; - int32_t x, y, width, height; - int32_t saved_x, saved_y; - struct wl_list link; - struct wlsc_matrix matrix; - struct wlsc_matrix matrix_inv; - struct wl_visual *visual; - struct wl_buffer *buffer; - enum wlsc_surface_map_type map_type; - struct wlsc_output *fullscreen_output; -}; - -void -wlsc_surface_update_matrix(struct wlsc_surface *es); - -void -notify_motion(struct wl_input_device *device, - uint32_t time, int x, int y); -void -notify_button(struct wl_input_device *device, - uint32_t time, int32_t button, int32_t state); -void -notify_key(struct wl_input_device *device, - uint32_t time, uint32_t key, uint32_t state); - -void -notify_pointer_focus(struct wl_input_device *device, - uint32_t time, - struct wlsc_output *output, - int32_t x, int32_t y); - -void -notify_keyboard_focus(struct wl_input_device *device, - uint32_t time, struct wlsc_output *output, - struct wl_array *keys); - -void -wlsc_compositor_finish_frame(struct wlsc_compositor *compositor, int msecs); -void -wlsc_compositor_schedule_repaint(struct wlsc_compositor *compositor); - -void -wlsc_surface_damage(struct wlsc_surface *surface); - -void -wlsc_surface_damage_rectangle(struct wlsc_surface *surface, - int32_t x, int32_t y, - int32_t width, int32_t height); - -void -wlsc_input_device_set_pointer_image(struct wlsc_input_device *device, - enum wlsc_pointer_type type); -struct wlsc_surface * -pick_surface(struct wl_input_device *device, int32_t *sx, int32_t *sy); - -void -wlsc_selection_set_focus(struct wl_selection *selection, - struct wl_surface *surface, uint32_t time); - -uint32_t -get_time(void); - -struct wl_buffer * -wlsc_drm_buffer_create(struct wlsc_compositor *ec, - int width, int height, - struct wl_visual *visual, const void *data); - -int -wlsc_compositor_init(struct wlsc_compositor *ec, struct wl_display *display); -void -wlsc_output_init(struct wlsc_output *output, struct wlsc_compositor *c, - int x, int y, int width, int height); -void -wlsc_input_device_init(struct wlsc_input_device *device, - struct wlsc_compositor *ec); -int -wlsc_drm_init(struct wlsc_compositor *ec, int fd, const char *filename); - -int -wlsc_shm_init(struct wlsc_compositor *ec); - -int -wlsc_shell_init(struct wlsc_compositor *ec); - -void -shell_move(struct wl_client *client, struct wl_shell *shell, - struct wl_surface *surface, - struct wl_input_device *device, uint32_t time); - -void -shell_resize(struct wl_client *client, struct wl_shell *shell, - struct wl_surface *surface, - struct wl_input_device *device, uint32_t time, uint32_t edges); - -struct wl_buffer * -wl_buffer_create_drm(struct wlsc_compositor *compositor, - struct wl_visual *visual); - -struct wlsc_compositor * -x11_compositor_create(struct wl_display *display, int width, int height); - -struct wlsc_compositor * -drm_compositor_create(struct wl_display *display, int connector); - -struct wlsc_compositor * -wayland_compositor_create(struct wl_display *display, int width, int height); - -void -evdev_input_add_devices(struct wlsc_compositor *c, struct udev *udev); - -struct tty * -tty_create(struct wlsc_compositor *compositor); - -void -tty_destroy(struct tty *tty); - -void -screenshooter_create(struct wlsc_compositor *ec); - -uint32_t * -wlsc_load_image(const char *filename, int width, int height); - -#endif diff --git a/compositor/drm.c b/compositor/drm.c deleted file mode 100644 index 9e25d33..0000000 --- a/compositor/drm.c +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Copyright © 2010 Kristian Høgsberg - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "compositor.h" - -struct wlsc_drm_buffer { - struct wl_buffer buffer; - EGLImageKHR image; -}; - -static void -drm_authenticate(struct wl_client *client, - struct wl_drm *drm_base, uint32_t id) -{ - struct wlsc_drm *drm = (struct wlsc_drm *) drm_base; - struct wlsc_compositor *compositor = - container_of(drm, struct wlsc_compositor, drm); - - if (compositor->authenticate(compositor, id) < 0) - wl_client_post_event(client, - (struct wl_object *) compositor->wl_display, - WL_DISPLAY_INVALID_OBJECT, 0); - else - wl_client_post_event(client, &drm->object, - WL_DRM_AUTHENTICATED); -} - -static void -destroy_buffer(struct wl_resource *resource, struct wl_client *client) -{ - struct wlsc_drm_buffer *buffer = - container_of(resource, struct wlsc_drm_buffer, buffer.resource); - struct wlsc_compositor *compositor = - (struct wlsc_compositor *) buffer->buffer.compositor; - - eglDestroyImageKHR(compositor->display, buffer->image); - free(buffer); -} - -static void -buffer_destroy(struct wl_client *client, struct wl_buffer *buffer) -{ - wl_resource_destroy(&buffer->resource, client); -} - -const static struct wl_buffer_interface buffer_interface = { - buffer_destroy -}; - -static void -drm_buffer_attach(struct wl_buffer *buffer_base, struct wl_surface *surface) -{ - struct wlsc_surface *es = (struct wlsc_surface *) surface; - struct wlsc_drm_buffer *buffer = - (struct wlsc_drm_buffer *) buffer_base; - - glBindTexture(GL_TEXTURE_2D, es->texture); - glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, buffer->image); - es->visual = buffer->buffer.visual; -} - -static void -drm_buffer_damage(struct wl_buffer *buffer, - struct wl_surface *surface, - int32_t x, int32_t y, int32_t width, int32_t height) -{ -} - -static struct wlsc_drm_buffer * -wlsc_drm_buffer_create_for_image(struct wlsc_compositor *compositor, - EGLImageKHR *image, - int32_t width, int32_t height, - struct wl_visual *visual) -{ - struct wlsc_drm_buffer *buffer; - - buffer = malloc(sizeof *buffer); - if (buffer == NULL) - return NULL; - - buffer->buffer.compositor = &compositor->compositor; - buffer->buffer.width = width; - buffer->buffer.height = height; - buffer->buffer.visual = visual; - buffer->buffer.attach = drm_buffer_attach; - buffer->buffer.damage = drm_buffer_damage; - buffer->image = image; - - return buffer; -} - -static void -drm_create_buffer(struct wl_client *client, struct wl_drm *drm_base, - uint32_t id, uint32_t name, int32_t width, int32_t height, - uint32_t stride, struct wl_visual *visual) -{ - struct wlsc_drm *drm = (struct wlsc_drm *) drm_base; - struct wlsc_compositor *compositor = - container_of(drm, struct wlsc_compositor, drm); - struct wlsc_drm_buffer *buffer; - EGLImageKHR image; - EGLint attribs[] = { - EGL_WIDTH, 0, - EGL_HEIGHT, 0, - EGL_DRM_BUFFER_STRIDE_MESA, 0, - EGL_DRM_BUFFER_FORMAT_MESA, EGL_DRM_BUFFER_FORMAT_ARGB32_MESA, - EGL_NONE - }; - - if (visual->object.interface != &wl_visual_interface) { - /* FIXME: Define a real exception event instead of - * abusing this one */ - wl_client_post_event(client, - (struct wl_object *) compositor->wl_display, - WL_DISPLAY_INVALID_OBJECT, 0); - fprintf(stderr, "invalid visual in create_buffer\n"); - return; - } - - attribs[1] = width; - attribs[3] = height; - attribs[5] = stride / 4; - image = eglCreateImageKHR(compositor->display, - EGL_NO_CONTEXT, - EGL_DRM_BUFFER_MESA, - (EGLClientBuffer) name, attribs); - if (image == NULL) { - /* FIXME: Define a real exception event instead of - * abusing this one */ - wl_client_post_event(client, - (struct wl_object *) compositor->wl_display, - WL_DISPLAY_INVALID_OBJECT, 0); - fprintf(stderr, "failed to create image for name %d\n", name); - return; - } - - buffer = wlsc_drm_buffer_create_for_image(compositor, image, - width, height, visual); - if (buffer == NULL) { - eglDestroyImageKHR(compositor->display, image); - wl_client_post_no_memory(client); - return; - } - - buffer->buffer.resource.object.id = id; - buffer->buffer.resource.object.interface = &wl_buffer_interface; - buffer->buffer.resource.object.implementation = (void (**)(void)) - &buffer_interface; - - buffer->buffer.resource.destroy = destroy_buffer; - - wl_client_add_resource(client, &buffer->buffer.resource); -} - -const static struct wl_drm_interface drm_interface = { - drm_authenticate, - drm_create_buffer -}; - -static void -post_drm_device(struct wl_client *client, struct wl_object *global) -{ - struct wlsc_drm *drm = container_of(global, struct wlsc_drm, object); - - wl_client_post_event(client, global, WL_DRM_DEVICE, drm->filename); -} - -int -wlsc_drm_init(struct wlsc_compositor *ec, int fd, const char *filename) -{ - struct wlsc_drm *drm = &ec->drm; - - drm->fd = fd; - drm->filename = strdup(filename); - if (drm->filename == NULL) - return -1; - - drm->object.interface = &wl_drm_interface; - drm->object.implementation = (void (**)(void)) &drm_interface; - wl_display_add_object(ec->wl_display, &drm->object); - wl_display_add_global(ec->wl_display, &drm->object, post_drm_device); - - return 0; -} - -struct wl_buffer * -wlsc_drm_buffer_create(struct wlsc_compositor *ec, int width, int height, - struct wl_visual *visual, const void *data) -{ - struct wlsc_drm_buffer *buffer; - EGLImageKHR image; - GLuint texture; - - EGLint image_attribs[] = { - EGL_WIDTH, 0, - EGL_HEIGHT, 0, - EGL_DRM_BUFFER_FORMAT_MESA, EGL_DRM_BUFFER_FORMAT_ARGB32_MESA, - EGL_DRM_BUFFER_USE_MESA, EGL_DRM_BUFFER_USE_SCANOUT_MESA, - EGL_NONE - }; - - image_attribs[1] = width; - image_attribs[3] = height; - - image = eglCreateDRMImageMESA(ec->display, image_attribs); - if (image == NULL) - return NULL; - - buffer = wlsc_drm_buffer_create_for_image(ec, image, - width, height, visual); - - glGenTextures(1, &texture); - glBindTexture(GL_TEXTURE_2D, texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, buffer->image); - - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, - GL_BGRA_EXT, GL_UNSIGNED_BYTE, data); - - glDeleteTextures(1, &texture); - - return &buffer->buffer; -} diff --git a/compositor/evdev.c b/compositor/evdev.c deleted file mode 100644 index 6ff7b69..0000000 --- a/compositor/evdev.c +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Copyright © 2010 Intel Corporation - * - * 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 <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <linux/input.h> -#include <unistd.h> -#include <fcntl.h> - -#include "compositor.h" - -struct evdev_input { - struct wlsc_input_device base; -}; - -struct evdev_input_device { - struct evdev_input *master; - struct wl_event_source *source; - int tool, new_x, new_y; - int base_x, base_y; - int fd; - int min_x, max_x, min_y, max_y; -}; - -static void evdev_input_device_data(int fd, uint32_t mask, void *data) -{ - struct wlsc_compositor *ec; - struct evdev_input_device *device = data; - struct input_event ev[8], *e, *end; - int len, value, dx, dy, absolute_event; - int x, y; - uint32_t time; - - /* FIXME: Obviously we need to not hardcode these here, but - * instead get the values from the output it's associated with. */ - const int screen_width = 1024, screen_height = 600; - - ec = (struct wlsc_compositor *) - device->master->base.input_device.compositor; - if (!ec->focus) - return; - - dx = 0; - dy = 0; - absolute_event = 0; - x = device->master->base.input_device.x; - y = device->master->base.input_device.y; - - len = read(fd, &ev, sizeof ev); - if (len < 0 || len % sizeof e[0] != 0) { - /* FIXME: handle error... reopen device? */; - return; - } - - e = ev; - end = (void *) ev + len; - for (e = ev; e < end; e++) { - /* Get the signed value, earlier kernels had this as unsigned */ - value = e->value; - time = e->time.tv_sec * 1000 + e->time.tv_usec / 1000; - - switch (e->type) { - case EV_REL: - switch (e->code) { - case REL_X: - dx += value; - break; - - case REL_Y: - dy += value; - break; - } - break; - - case EV_ABS: - switch (e->code) { - case ABS_X: - absolute_event = device->tool; - x = (value - device->min_x) * screen_width / - (device->max_x - device->min_x); - break; - case ABS_Y: - absolute_event = device->tool; - y = (value - device->min_y) * screen_height / - (device->max_y - device->min_y); - break; - } - break; - - case EV_KEY: - if (value == 2) - break; - - switch (e->code) { - case BTN_TOUCH: - case BTN_TOOL_PEN: - case BTN_TOOL_RUBBER: - case BTN_TOOL_BRUSH: - case BTN_TOOL_PENCIL: - case BTN_TOOL_AIRBRUSH: - case BTN_TOOL_FINGER: - case BTN_TOOL_MOUSE: - case BTN_TOOL_LENS: - device->tool = value ? e->code : 0; - break; - - case BTN_LEFT: - case BTN_RIGHT: - case BTN_MIDDLE: - case BTN_SIDE: - case BTN_EXTRA: - case BTN_FORWARD: - case BTN_BACK: - case BTN_TASK: - notify_button(&device->master->base.input_device, - time, e->code, value); - break; - - default: - notify_key(&device->master->base.input_device, - time, e->code, value); - break; - } - } - } - - if (dx != 0 || dy != 0) - notify_motion(&device->master->base.input_device, - time, x + dx, y + dy); - if (absolute_event) - notify_motion(&device->master->base.input_device, time, x, y); -} - -#define TEST_BIT(b, i) (b[(i) / 32] & (1 << (i & 31))) - -static struct evdev_input_device * -evdev_input_device_create(struct evdev_input *master, - struct wl_display *display, const char *path) -{ - struct evdev_input_device *device; - struct wl_event_loop *loop; - struct input_absinfo absinfo; - uint32_t ev_bits[EV_MAX]; - uint32_t key_bits[KEY_MAX]; - - device = malloc(sizeof *device); - if (device == NULL) - return NULL; - - device->tool = 1; - device->new_x = 1; - device->new_y = 1; - device->master = master; - - device->fd = open(path, O_RDONLY); - if (device->fd < 0) { - free(device); - fprintf(stderr, "couldn't create pointer for %s: %m\n", path); - return NULL; - } - - ioctl(device->fd, EVIOCGBIT(0, EV_MAX), ev_bits); - if (TEST_BIT(ev_bits, EV_ABS)) { - ioctl(device->fd, EVIOCGBIT(EV_ABS, EV_MAX), key_bits); - if (TEST_BIT(key_bits, ABS_X)) { - ioctl(device->fd, EVIOCGABS(ABS_X), &absinfo); - device->min_x = absinfo.minimum; - device->max_x = absinfo.maximum; - } - if (TEST_BIT(key_bits, ABS_Y)) { - ioctl(device->fd, EVIOCGABS(ABS_Y), &absinfo); - device->min_y = absinfo.minimum; - device->max_y = absinfo.maximum; - } - } - - loop = wl_display_get_event_loop(display); - device->source = wl_event_loop_add_fd(loop, device->fd, - WL_EVENT_READABLE, - evdev_input_device_data, device); - if (device->source == NULL) { - close(device->fd); - free(device); - return NULL; - } - - return device; -} - -void -evdev_input_add_devices(struct wlsc_compositor *c, struct udev *udev) -{ - struct evdev_input *input; - struct udev_enumerate *e; - struct udev_list_entry *entry; - struct udev_device *device; - const char *path; - - input = malloc(sizeof *input); - if (input == NULL) - return; - - memset(input, 0, sizeof *input); - wlsc_input_device_init(&input->base, c); - - e = udev_enumerate_new(udev); - udev_enumerate_add_match_subsystem(e, "input"); - udev_enumerate_add_match_property(e, "WAYLAND_SEAT", "1"); - udev_enumerate_scan_devices(e); - udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) { - path = udev_list_entry_get_name(entry); - device = udev_device_new_from_syspath(udev, path); - evdev_input_device_create(input, c->wl_display, - udev_device_get_devnode(device)); - } - udev_enumerate_unref(e); - - c->input_device = &input->base.input_device; -} diff --git a/compositor/screenshooter.c b/compositor/screenshooter.c deleted file mode 100644 index 53ed931..0000000 --- a/compositor/screenshooter.c +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright © 2008 Kristian Høgsberg - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include <stdlib.h> -#include <GLES2/gl2.h> -#include <gdk-pixbuf/gdk-pixbuf.h> - -#include "compositor.h" -#include "screenshooter-server-protocol.h" - -struct wl_screenshooter { - struct wl_object base; - struct wlsc_compositor *ec; -}; - -static void -screenshooter_shoot(struct wl_client *client, struct wl_screenshooter *shooter) -{ - struct wlsc_compositor *ec = shooter->ec; - struct wlsc_output *output; - char buffer[256]; - GdkPixbuf *pixbuf; - GError *error = NULL; - unsigned char *data; - int i, j; - - i = 0; - wl_list_for_each(output, &ec->output_list, link) { - snprintf(buffer, sizeof buffer, "wayland-screenshot-%d.png", i++); - data = malloc(output->width * output->height * 4); - if (data == NULL) { - fprintf(stderr, "couldn't allocate image buffer\n"); - continue; - } - - glPixelStorei(GL_PACK_ALIGNMENT, 1); - glReadPixels(0, 0, output->width, output->height, - GL_RGBA, GL_UNSIGNED_BYTE, data); - - /* FIXME: We should just use a RGB visual for the frontbuffer. */ - for (j = 3; j < output->width * output->height * 4; j += 4) - data[j] = 0xff; - - pixbuf = gdk_pixbuf_new_from_data(data, GDK_COLORSPACE_RGB, TRUE, - 8, output->width, output->height, output->width * 4, - NULL, NULL); - gdk_pixbuf_save(pixbuf, buffer, "png", &error, NULL); - g_object_unref(pixbuf); - free(data); - } -} - -struct wl_screenshooter_interface screenshooter_implementation = { - screenshooter_shoot -}; - -void -screenshooter_create(struct wlsc_compositor *ec) -{ - struct wl_screenshooter *shooter; - - shooter = malloc(sizeof *shooter); - if (shooter == NULL) - return; - - shooter->base.interface = &wl_screenshooter_interface; - shooter->base.implementation = - (void(**)(void)) &screenshooter_implementation; - shooter->ec = ec; - - wl_display_add_object(ec->wl_display, &shooter->base); - wl_display_add_global(ec->wl_display, &shooter->base, NULL); -}; diff --git a/compositor/shell.c b/compositor/shell.c deleted file mode 100644 index a19d3db..0000000 --- a/compositor/shell.c +++ /dev/null @@ -1,676 +0,0 @@ -/* - * Copyright © 2010 Intel Corporation - * - * 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 <string.h> -#include <unistd.h> - -#include "wayland-server.h" -#include "compositor.h" - -struct wlsc_move_grab { - struct wl_grab grab; - struct wlsc_surface *surface; - int32_t dx, dy; -}; - -static void -move_grab_motion(struct wl_grab *grab, - uint32_t time, int32_t x, int32_t y) -{ - struct wlsc_move_grab *move = (struct wlsc_move_grab *) grab; - struct wlsc_surface *es = move->surface; - - wlsc_surface_damage(es); - es->x = x + move->dx; - es->y = y + move->dy; - wlsc_surface_update_matrix(es); - wlsc_surface_damage(es); -} - -static void -move_grab_button(struct wl_grab *grab, - uint32_t time, int32_t button, int32_t state) -{ -} - -static void -move_grab_end(struct wl_grab *grab, uint32_t time) -{ - struct wlsc_surface *es; - struct wl_input_device *device = grab->input_device; - int32_t sx, sy; - - es = pick_surface(grab->input_device, &sx, &sy); - wl_input_device_set_pointer_focus(device, - &es->surface, time, - device->x, device->y, sx, sy); - free(grab); -} - -static const struct wl_grab_interface move_grab_interface = { - move_grab_motion, - move_grab_button, - move_grab_end -}; - -void -shell_move(struct wl_client *client, struct wl_shell *shell, - struct wl_surface *surface, - struct wl_input_device *device, uint32_t time) -{ - struct wlsc_input_device *wd = (struct wlsc_input_device *) device; - struct wlsc_surface *es = (struct wlsc_surface *) surface; - struct wlsc_move_grab *move; - - /* FIXME: Reject if fullscreen */ - - move = malloc(sizeof *move); - if (!move) { - wl_client_post_no_memory(client); - return; - } - - move->grab.interface = &move_grab_interface; - move->dx = es->x - wd->input_device.grab_x; - move->dy = es->y - wd->input_device.grab_y; - move->surface = es; - - if (wl_input_device_update_grab(&wd->input_device, - &move->grab, surface, time) < 0) - return; - - wlsc_input_device_set_pointer_image(wd, WLSC_POINTER_DRAGGING); - wl_input_device_set_pointer_focus(device, NULL, time, 0, 0, 0, 0); -} - -struct wlsc_resize_grab { - struct wl_grab grab; - uint32_t edges; - int32_t dx, dy, width, height; - struct wlsc_surface *surface; -}; - -static void -resize_grab_motion(struct wl_grab *grab, - uint32_t time, int32_t x, int32_t y) -{ - struct wlsc_resize_grab *resize = (struct wlsc_resize_grab *) grab; - struct wl_input_device *device = grab->input_device; - struct wlsc_compositor *ec = - (struct wlsc_compositor *) device->compositor; - struct wl_surface *surface = &resize->surface->surface; - int32_t width, height; - - if (resize->edges & WL_SHELL_RESIZE_LEFT) { - width = device->grab_x - x + resize->width; - } else if (resize->edges & WL_SHELL_RESIZE_RIGHT) { - width = x - device->grab_x + resize->width; - } else { - width = resize->width; - } - - if (resize->edges & WL_SHELL_RESIZE_TOP) { - height = device->grab_y - y + resize->height; - } else if (resize->edges & WL_SHELL_RESIZE_BOTTOM) { - height = y - device->grab_y + resize->height; - } else { - height = resize->height; - } - - wl_client_post_event(surface->client, &ec->shell.object, - WL_SHELL_CONFIGURE, time, resize->edges, - surface, width, height); -} - -static void -resize_grab_button(struct wl_grab *grab, - uint32_t time, int32_t button, int32_t state) -{ -} - -static void -resize_grab_end(struct wl_grab *grab, uint32_t time) -{ - struct wlsc_surface *es; - struct wl_input_device *device = grab->input_device; - int32_t sx, sy; - - es = pick_surface(grab->input_device, &sx, &sy); - wl_input_device_set_pointer_focus(device, - &es->surface, time, - device->x, device->y, sx, sy); - free(grab); -} - -static const struct wl_grab_interface resize_grab_interface = { - resize_grab_motion, - resize_grab_button, - resize_grab_end -}; - -void -shell_resize(struct wl_client *client, struct wl_shell *shell, - struct wl_surface *surface, - struct wl_input_device *device, uint32_t time, uint32_t edges) -{ - struct wlsc_input_device *wd = (struct wlsc_input_device *) device; - struct wlsc_resize_grab *resize; - enum wlsc_pointer_type pointer = WLSC_POINTER_LEFT_PTR; - struct wlsc_surface *es = (struct wlsc_surface *) surface; - - /* FIXME: Reject if fullscreen */ - - resize = malloc(sizeof *resize); - if (!resize) { - wl_client_post_no_memory(client); - return; - } - - resize->grab.interface = &resize_grab_interface; - resize->edges = edges; - resize->dx = es->x - wd->input_device.grab_x; - resize->dy = es->y - wd->input_device.grab_y; - resize->width = es->width; - resize->height = es->height; - resize->surface = es; - - if (edges == 0 || edges > 15 || - (edges & 3) == 3 || (edges & 12) == 12) - return; - - switch (edges) { - case WL_SHELL_RESIZE_TOP: - pointer = WLSC_POINTER_TOP; - break; - case WL_SHELL_RESIZE_BOTTOM: - pointer = WLSC_POINTER_BOTTOM; - break; - case WL_SHELL_RESIZE_LEFT: - pointer = WLSC_POINTER_LEFT; - break; - case WL_SHELL_RESIZE_TOP_LEFT: - pointer = WLSC_POINTER_TOP_LEFT; - break; - case WL_SHELL_RESIZE_BOTTOM_LEFT: - pointer = WLSC_POINTER_BOTTOM_LEFT; - break; - case WL_SHELL_RESIZE_RIGHT: - pointer = WLSC_POINTER_RIGHT; - break; - case WL_SHELL_RESIZE_TOP_RIGHT: - pointer = WLSC_POINTER_TOP_RIGHT; - break; - case WL_SHELL_RESIZE_BOTTOM_RIGHT: - pointer = WLSC_POINTER_BOTTOM_RIGHT; - break; - } - - if (wl_input_device_update_grab(&wd->input_device, - &resize->grab, surface, time) < 0) - return; - - wlsc_input_device_set_pointer_image(wd, pointer); - wl_input_device_set_pointer_focus(device, NULL, time, 0, 0, 0, 0); -} - -static void -destroy_drag(struct wl_resource *resource, struct wl_client *client) -{ - struct wl_drag *drag = - container_of(resource, struct wl_drag, resource); - - wl_list_remove(&drag->drag_focus_listener.link); - if (drag->grab.input_device) - wl_input_device_end_grab(drag->grab.input_device, get_time()); - - free(drag); -} - - -static void -wl_drag_set_pointer_focus(struct wl_drag *drag, - struct wl_surface *surface, uint32_t time, - int32_t x, int32_t y, int32_t sx, int32_t sy) -{ - char **p, **end; - - if (drag->drag_focus == surface) - return; - - if (drag->drag_focus && - (!surface || drag->drag_focus->client != surface->client)) - wl_client_post_event(drag->drag_focus->client, - &drag->drag_offer.object, - WL_DRAG_OFFER_POINTER_FOCUS, - time, NULL, 0, 0, 0, 0); - - if (surface && - (!drag->drag_focus || - drag->drag_focus->client != surface->client)) { - wl_client_post_global(surface->client, - &drag->drag_offer.object); - - end = drag->types.data + drag->types.size; - for (p = drag->types.data; p < end; p++) - wl_client_post_event(surface->client, - &drag->drag_offer.object, - WL_DRAG_OFFER_OFFER, *p); - } - - if (surface) { - wl_client_post_event(surface->client, - &drag->drag_offer.object, - WL_DRAG_OFFER_POINTER_FOCUS, - time, surface, - x, y, sx, sy); - - } - - drag->drag_focus = surface; - drag->pointer_focus_time = time; - drag->target = NULL; - - wl_list_remove(&drag->drag_focus_listener.link); - if (surface) - wl_list_insert(surface->destroy_listener_list.prev, - &drag->drag_focus_listener.link); -} - -static void -drag_offer_accept(struct wl_client *client, - struct wl_drag_offer *offer, uint32_t time, const char *type) -{ - struct wl_drag *drag = container_of(offer, struct wl_drag, drag_offer); - char **p, **end; - - /* If the client responds to drag pointer_focus or motion - * events after the pointer has left the surface, we just - * discard the accept requests. The drag source just won't - * get the corresponding 'target' events and eventually the - * next surface/root will start sending events. */ - if (time < drag->pointer_focus_time) - return; - - drag->target = client; - drag->type = NULL; - end = drag->types.data + drag->types.size; - for (p = drag->types.data; p < end; p++) - if (type && strcmp(*p, type) == 0) - drag->type = *p; - - wl_client_post_event(drag->source->client, &drag->resource.object, - WL_DRAG_TARGET, drag->type); -} - -static void -drag_offer_receive(struct wl_client *client, - struct wl_drag_offer *offer, int fd) -{ - struct wl_drag *drag = container_of(offer, struct wl_drag, drag_offer); - - wl_client_post_event(drag->source->client, &drag->resource.object, - WL_DRAG_FINISH, fd); - close(fd); -} - -static void -drag_offer_reject(struct wl_client *client, struct wl_drag_offer *offer) -{ - struct wl_drag *drag = container_of(offer, struct wl_drag, drag_offer); - - wl_client_post_event(drag->source->client, &drag->resource.object, - WL_DRAG_REJECT); -} - -static const struct wl_drag_offer_interface drag_offer_interface = { - drag_offer_accept, - drag_offer_receive, - drag_offer_reject -}; - -static void -drag_offer(struct wl_client *client, struct wl_drag *drag, const char *type) -{ - char **p; - - p = wl_array_add(&drag->types, sizeof *p); - if (p) - *p = strdup(type); - if (!p || !*p) - wl_client_post_no_memory(client); -} - -static void -drag_grab_motion(struct wl_grab *grab, - uint32_t time, int32_t x, int32_t y) -{ - struct wl_drag *drag = container_of(grab, struct wl_drag, grab); - struct wlsc_surface *es; - int32_t sx, sy; - - es = pick_surface(grab->input_device, &sx, &sy); - wl_drag_set_pointer_focus(drag, &es->surface, time, x, y, sx, sy); - if (es) - wl_client_post_event(es->surface.client, - &drag->drag_offer.object, - WL_DRAG_OFFER_MOTION, - time, x, y, sx, sy); -} - -static void -drag_grab_button(struct wl_grab *grab, - uint32_t time, int32_t button, int32_t state) -{ -} - -static void -drag_grab_end(struct wl_grab *grab, uint32_t time) -{ - struct wl_drag *drag = container_of(grab, struct wl_drag, grab); - struct wlsc_surface *es; - struct wl_input_device *device = grab->input_device; - int32_t sx, sy; - - if (drag->target) - wl_client_post_event(drag->target, - &drag->drag_offer.object, - WL_DRAG_OFFER_DROP); - - wl_drag_set_pointer_focus(drag, NULL, time, 0, 0, 0, 0); - - es = pick_surface(grab->input_device, &sx, &sy); - wl_input_device_set_pointer_focus(device, - &es->surface, time, - device->x, device->y, sx, sy); -} - -static const struct wl_grab_interface drag_grab_interface = { - drag_grab_motion, - drag_grab_button, - drag_grab_end -}; - -static void -drag_activate(struct wl_client *client, - struct wl_drag *drag, - struct wl_surface *surface, - struct wl_input_device *device, uint32_t time) -{ - struct wl_display *display = wl_client_get_display (client); - struct wlsc_surface *target; - int32_t sx, sy; - - if (wl_input_device_update_grab(device, - &drag->grab, surface, time) < 0) - return; - - drag->grab.interface = &drag_grab_interface; - - drag->source = surface; - - drag->drag_offer.object.interface = &wl_drag_offer_interface; - drag->drag_offer.object.implementation = - (void (**)(void)) &drag_offer_interface; - - wl_display_add_object(display, &drag->drag_offer.object); - - target = pick_surface(device, &sx, &sy); - wl_input_device_set_pointer_focus(device, NULL, time, 0, 0, 0, 0); - wl_drag_set_pointer_focus(drag, &target->surface, time, - device->x, device->y, sx, sy); -} - -static void -drag_destroy(struct wl_client *client, struct wl_drag *drag) -{ - wl_resource_destroy(&drag->resource, client); -} - -static const struct wl_drag_interface drag_interface = { - drag_offer, - drag_activate, - drag_destroy, -}; - -static void -drag_handle_surface_destroy(struct wl_listener *listener, - struct wl_surface *surface, uint32_t time) -{ - struct wl_drag *drag = - container_of(listener, struct wl_drag, drag_focus_listener); - - if (drag->drag_focus == surface) - wl_drag_set_pointer_focus(drag, NULL, time, 0, 0, 0, 0); -} - -static void -shell_create_drag(struct wl_client *client, - struct wl_shell *shell, uint32_t id) -{ - struct wl_drag *drag; - - drag = malloc(sizeof *drag); - if (drag == NULL) { - wl_client_post_no_memory(client); - return; - } - - memset(drag, 0, sizeof *drag); - drag->resource.object.id = id; - drag->resource.object.interface = &wl_drag_interface; - drag->resource.object.implementation = - (void (**)(void)) &drag_interface; - - drag->resource.destroy = destroy_drag; - - drag->drag_focus_listener.func = drag_handle_surface_destroy; - wl_list_init(&drag->drag_focus_listener.link); - - wl_client_add_resource(client, &drag->resource); -} - -void -wlsc_selection_set_focus(struct wl_selection *selection, - struct wl_surface *surface, uint32_t time) -{ - char **p, **end; - - if (selection->selection_focus == surface) - return; - - if (selection->selection_focus != NULL) - wl_client_post_event(selection->selection_focus->client, - &selection->selection_offer.object, - WL_SELECTION_OFFER_KEYBOARD_FOCUS, - NULL); - - if (surface) { - wl_client_post_global(surface->client, - &selection->selection_offer.object); - - end = selection->types.data + selection->types.size; - for (p = selection->types.data; p < end; p++) - wl_client_post_event(surface->client, - &selection->selection_offer.object, - WL_SELECTION_OFFER_OFFER, *p); - - wl_list_remove(&selection->selection_focus_listener.link); - wl_list_insert(surface->destroy_listener_list.prev, - &selection->selection_focus_listener.link); - - wl_client_post_event(surface->client, - &selection->selection_offer.object, - WL_SELECTION_OFFER_KEYBOARD_FOCUS, - selection->input_device); - } - - selection->selection_focus = surface; - - wl_list_remove(&selection->selection_focus_listener.link); - if (surface) - wl_list_insert(surface->destroy_listener_list.prev, - &selection->selection_focus_listener.link); -} - -static void -selection_offer_receive(struct wl_client *client, - struct wl_selection_offer *offer, - const char *mime_type, int fd) -{ - struct wl_selection *selection = - container_of(offer, struct wl_selection, selection_offer); - - wl_client_post_event(selection->client, - &selection->resource.object, - WL_SELECTION_SEND, mime_type, fd); - close(fd); -} - -static const struct wl_selection_offer_interface selection_offer_interface = { - selection_offer_receive -}; - -static void -selection_offer(struct wl_client *client, - struct wl_selection *selection, const char *type) -{ - char **p; - - p = wl_array_add(&selection->types, sizeof *p); - if (p) - *p = strdup(type); - if (!p || !*p) - wl_client_post_no_memory(client); -} - -static void -selection_activate(struct wl_client *client, - struct wl_selection *selection, - struct wl_input_device *device, uint32_t time) -{ - struct wlsc_input_device *wd = (struct wlsc_input_device *) device; - struct wl_display *display = wl_client_get_display (client); - - selection->input_device = device; - - selection->selection_offer.object.interface = - &wl_selection_offer_interface; - selection->selection_offer.object.implementation = - (void (**)(void)) &selection_offer_interface; - - wl_display_add_object(display, &selection->selection_offer.object); - - if (wd->selection) { - wl_client_post_event(wd->selection->client, - &wd->selection->resource.object, - WL_SELECTION_CANCELLED); - } - wd->selection = selection; - - wlsc_selection_set_focus(selection, device->keyboard_focus, time); -} - -static void -selection_destroy(struct wl_client *client, struct wl_selection *selection) -{ - wl_resource_destroy(&selection->resource, client); -} - -static const struct wl_selection_interface selection_interface = { - selection_offer, - selection_activate, - selection_destroy -}; - -static void -destroy_selection(struct wl_resource *resource, struct wl_client *client) -{ - struct wl_selection *selection = - container_of(resource, struct wl_selection, resource); - struct wlsc_input_device *wd = - (struct wlsc_input_device *) selection->input_device; - - if (wd && wd->selection == selection) { - wd->selection = NULL; - wlsc_selection_set_focus(selection, NULL, get_time()); - } - - wl_list_remove(&selection->selection_focus_listener.link); - free(selection); -} - -static void -selection_handle_surface_destroy(struct wl_listener *listener, - struct wl_surface *surface, uint32_t time) -{ -} - -static void -shell_create_selection(struct wl_client *client, - struct wl_shell *shell, uint32_t id) -{ - struct wl_selection *selection; - - selection = malloc(sizeof *selection); - if (selection == NULL) { - wl_client_post_no_memory(client); - return; - } - - memset(selection, 0, sizeof *selection); - selection->resource.object.id = id; - selection->resource.object.interface = &wl_selection_interface; - selection->resource.object.implementation = - (void (**)(void)) &selection_interface; - - selection->client = client; - selection->resource.destroy = destroy_selection; - selection->selection_focus = NULL; - - selection->selection_focus_listener.func = - selection_handle_surface_destroy; - wl_list_init(&selection->selection_focus_listener.link); - - wl_client_add_resource(client, &selection->resource); -} - -const static struct wl_shell_interface shell_interface = { - shell_move, - shell_resize, - shell_create_drag, - shell_create_selection -}; - -int -wlsc_shell_init(struct wlsc_compositor *ec) -{ - struct wl_shell *shell = &ec->shell; - - shell->object.interface = &wl_shell_interface; - shell->object.implementation = (void (**)(void)) &shell_interface; - wl_display_add_object(ec->wl_display, &shell->object); - if (wl_display_add_global(ec->wl_display, &shell->object, NULL)) - return -1; - - return 0; -} diff --git a/compositor/shm.c b/compositor/shm.c deleted file mode 100644 index 389eeaa..0000000 --- a/compositor/shm.c +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright © 2010 Kristian Høgsberg - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/mman.h> -#include <unistd.h> - -#include "compositor.h" - -struct wlsc_shm_buffer { - struct wl_buffer buffer; - int32_t stride; - void *data; -}; - -static void -destroy_buffer(struct wl_resource *resource, struct wl_client *client) -{ - struct wlsc_shm_buffer *buffer = - container_of(resource, struct wlsc_shm_buffer, buffer.resource); - - munmap(buffer->data, buffer->stride * buffer->buffer.height); - free(buffer); -} - -static void -buffer_destroy(struct wl_client *client, struct wl_buffer *buffer) -{ - // wl_resource_destroy(&buffer->base, client); -} - -const static struct wl_buffer_interface buffer_interface = { - buffer_destroy -}; - -static void -shm_buffer_attach(struct wl_buffer *buffer_base, struct wl_surface *surface) -{ - struct wlsc_surface *es = (struct wlsc_surface *) surface; - struct wlsc_shm_buffer *buffer = - (struct wlsc_shm_buffer *) buffer_base; - - glBindTexture(GL_TEXTURE_2D, es->texture); - - /* Unbind any EGLImage texture that may be bound, so we don't - * overwrite it.*/ - glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, - 0, 0, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, NULL); - glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, - buffer->buffer.width, buffer->buffer.height, 0, - GL_BGRA_EXT, GL_UNSIGNED_BYTE, buffer->data); - es->visual = buffer->buffer.visual; -} - -static void -shm_buffer_damage(struct wl_buffer *buffer_base, - struct wl_surface *surface, - int32_t x, int32_t y, int32_t width, int32_t height) -{ - struct wlsc_surface *es = (struct wlsc_surface *) surface; - struct wlsc_shm_buffer *buffer = - (struct wlsc_shm_buffer *) buffer_base; - - glBindTexture(GL_TEXTURE_2D, es->texture); - glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, - buffer->buffer.width, buffer->buffer.height, 0, - GL_BGRA_EXT, GL_UNSIGNED_BYTE, buffer->data); - - /* Hmm, should use glTexSubImage2D() here but GLES2 doesn't - * support any unpack attributes except GL_UNPACK_ALIGNMENT. */ -} - -static void -shm_create_buffer(struct wl_client *client, struct wl_shm *shm, - uint32_t id, int fd, int32_t width, int32_t height, - uint32_t stride, struct wl_visual *visual) -{ - struct wlsc_compositor *compositor = - container_of((struct wlsc_shm *) shm, - struct wlsc_compositor, shm); - struct wlsc_shm_buffer *buffer; - - /* FIXME: Define a real exception event instead of abusing the - * display.invalid_object error */ - if (visual->object.interface != &wl_visual_interface) { - wl_client_post_event(client, - (struct wl_object *) compositor->wl_display, - WL_DISPLAY_INVALID_OBJECT, 0); - fprintf(stderr, "invalid visual in create_buffer\n"); - close(fd); - return; - } - - if (width < 0 || height < 0 || stride < width) { - wl_client_post_event(client, - (struct wl_object *) compositor->wl_display, - WL_DISPLAY_INVALID_OBJECT, 0); - fprintf(stderr, - "invalid width, height or stride in create_buffer\n"); - close(fd); - return; - } - - buffer = malloc(sizeof *buffer); - if (buffer == NULL) { - close(fd); - wl_client_post_no_memory(client); - return; - } - - buffer->buffer.compositor = (struct wl_compositor *) compositor; - buffer->buffer.width = width; - buffer->buffer.height = height; - buffer->buffer.visual = visual; - buffer->buffer.attach = shm_buffer_attach; - buffer->buffer.damage = shm_buffer_damage; - buffer->stride = stride; - buffer->data = - mmap(NULL, stride * height, PROT_READ, MAP_SHARED, fd, 0); - close(fd); - if (buffer->data == MAP_FAILED) { - /* FIXME: Define a real exception event instead of - * abusing this one */ - free(buffer); - wl_client_post_event(client, - (struct wl_object *) compositor->wl_display, - WL_DISPLAY_INVALID_OBJECT, 0); - fprintf(stderr, "failed to create image for fd %d\n", fd); - return; - } - - buffer->buffer.resource.object.id = id; - buffer->buffer.resource.object.interface = &wl_buffer_interface; - buffer->buffer.resource.object.implementation = (void (**)(void)) - &buffer_interface; - - buffer->buffer.resource.destroy = destroy_buffer; - - wl_client_add_resource(client, &buffer->buffer.resource); -} - -const static struct wl_shm_interface shm_interface = { - shm_create_buffer -}; - -int -wlsc_shm_init(struct wlsc_compositor *ec) -{ - struct wlsc_shm *shm = &ec->shm; - - shm->object.interface = &wl_shm_interface; - shm->object.implementation = (void (**)(void)) &shm_interface; - wl_display_add_object(ec->wl_display, &shm->object); - wl_display_add_global(ec->wl_display, &shm->object, NULL); - - return 0; -} diff --git a/compositor/tty.c b/compositor/tty.c deleted file mode 100644 index 0de7584..0000000 --- a/compositor/tty.c +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright © 2010 Intel Corporation - * - * 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 <termios.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <fcntl.h> -#include <signal.h> -#include <linux/kd.h> -#include <linux/vt.h> -#include <sys/ioctl.h> - -#include "compositor.h" - -struct tty { - struct wlsc_compositor *compositor; - int fd; - struct termios terminal_attributes; - - struct wl_event_source *input_source; - struct wl_event_source *enter_vt_source; - struct wl_event_source *leave_vt_source; -}; - -static void on_enter_vt(int signal_number, void *data) -{ - struct tty *tty = data; - int ret; - - fprintf(stderr, "enter vt\n"); - - ioctl(tty->fd, VT_RELDISP, VT_ACKACQ); - ret = ioctl(tty->fd, KDSETMODE, KD_GRAPHICS); - if (ret) - fprintf(stderr, "failed to set KD_GRAPHICS mode on console: %m\n"); -} - -static void on_leave_vt(int signal_number, void *data) -{ - struct tty *tty = data; - int ret; - - ioctl (tty->fd, VT_RELDISP, 1); - ret = ioctl(tty->fd, KDSETMODE, KD_TEXT); - if (ret) - fprintf(stderr, - "failed to set KD_TEXT mode on console: %m\n"); -} - -static void -on_tty_input(int fd, uint32_t mask, void *data) -{ - struct tty *tty = data; - - /* Ignore input to tty. We get keyboard events from evdev - */ - tcflush(tty->fd, TCIFLUSH); -} - -struct tty * -tty_create(struct wlsc_compositor *compositor) -{ - struct termios raw_attributes; - struct vt_mode mode = { 0 }; - int ret; - struct tty *tty; - struct wl_event_loop *loop; - - tty = malloc(sizeof *tty); - if (tty == NULL) - return NULL; - - memset(tty, 0, sizeof *tty); - tty->compositor = compositor; - tty->fd = open("/dev/tty0", O_RDWR | O_NOCTTY); - if (tty->fd <= 0) { - fprintf(stderr, "failed to open active tty: %m\n"); - return NULL; - } - - if (tcgetattr(tty->fd, &tty->terminal_attributes) < 0) { - fprintf(stderr, "could not get terminal attributes: %m\n"); - return NULL; - } - - /* Ignore control characters and disable echo */ - raw_attributes = tty->terminal_attributes; - cfmakeraw(&raw_attributes); - - /* Fix up line endings to be normal (cfmakeraw hoses them) */ - raw_attributes.c_oflag |= OPOST | OCRNL; - - if (tcsetattr(tty->fd, TCSANOW, &raw_attributes) < 0) - fprintf(stderr, "could not put terminal into raw mode: %m\n"); - - loop = wl_display_get_event_loop(compositor->wl_display); - tty->input_source = - wl_event_loop_add_fd(loop, tty->fd, - WL_EVENT_READABLE, on_tty_input, tty); - - ret = ioctl(tty->fd, KDSETMODE, KD_GRAPHICS); - if (ret) { - fprintf(stderr, "failed to set KD_GRAPHICS mode on tty: %m\n"); - return NULL; - } - - tty->compositor->focus = 1; - mode.mode = VT_PROCESS; - mode.relsig = SIGUSR1; - mode.acqsig = SIGUSR2; - if (!ioctl(tty->fd, VT_SETMODE, &mode) < 0) { - fprintf(stderr, "failed to take control of vt handling\n"); - return NULL; - } - - tty->leave_vt_source = - wl_event_loop_add_signal(loop, SIGUSR1, on_leave_vt, tty); - tty->enter_vt_source = - wl_event_loop_add_signal(loop, SIGUSR2, on_enter_vt, tty); - - return tty; -} - -void -tty_destroy(struct tty *tty) -{ - if(!tty) - return; - - if (ioctl(tty->fd, KDSETMODE, KD_TEXT)) - fprintf(stderr, - "failed to set KD_TEXT mode on tty: %m\n"); - - if (tcsetattr(tty->fd, TCSANOW, &tty->terminal_attributes) < 0) - fprintf(stderr, - "could not restore terminal to canonical mode\n"); - - free(tty); -} diff --git a/configure.ac b/configure.ac index 48b9169..34b8dbc 100644 --- a/configure.ac +++ b/configure.ac @@ -22,48 +22,6 @@ LT_INIT PKG_PROG_PKG_CONFIG() PKG_CHECK_MODULES(FFI, [libffi]) -PKG_CHECK_MODULES(COMPOSITOR, - [egl >= 7.10 glesv2 gdk-pixbuf-2.0 libudev >= 136 libdrm >= 2.4.23] pixman-1 xcb-dri2 xcb-xfixes) -PKG_CHECK_MODULES(GLES2, [egl >= 7.10 glesv2]) -PKG_CHECK_MODULES(CLIENT, [egl >= 7.10 gl cairo >= 1.10.0 gdk-pixbuf-2.0 glib-2.0 gobject-2.0 xkbcommon]) -PKG_CHECK_MODULES(POPPLER, [poppler-glib gdk-2.0 gio-2.0], - [have_poppler=yes], [have_poppler=no]) -AM_CONDITIONAL(HAVE_POPPLER, test "x$have_poppler" = "xyes") - -AC_CHECK_PROG(RSVG_CONVERT, rsvg-convert, rsvg-convert) -AM_CONDITIONAL(HAVE_RSVG_CONVERT, test -n "$RSVG_CONVERT") - -AC_ARG_ENABLE(x11-compositor, [ --enable-x11-compositor],, - enable_x11_compositor=yes) -AM_CONDITIONAL(ENABLE_X11_COMPOSITOR, test x$enable_x11_compositor == xyes) -if test x$enable_x11_compositor == xyes; then - AC_DEFINE([BUILD_X11_COMPOSITOR], [1], [Build the X11 compositor]) -fi - - -AC_ARG_ENABLE(drm-compositor, [ --enable-drm-compositor],, - enable_drm_compositor=yes) -AM_CONDITIONAL(ENABLE_DRM_COMPOSITOR, test x$enable_drm_compositor == xyes) -if test x$enable_drm_compositor == xyes; then - AC_DEFINE([BUILD_DRM_COMPOSITOR], [1], [Build the DRM compositor]) -fi - - -AC_ARG_ENABLE(wayland-compositor, [ --enable-wayland-compositor],, - enable_wayland_compositor=yes) -AM_CONDITIONAL(ENABLE_WAYLAND_COMPOSITOR, - test x$enable_wayland_compositor == xyes) -if test x$enable_wayland_compositor == xyes; then - AC_DEFINE([BUILD_WAYLAND_COMPOSITOR], [1], - [Build the Wayland (nested) compositor]) -fi - - -PKG_CHECK_MODULES(CAIRO_EGL, [cairo-egl], - [have_cairo_egl=yes], [have_cairo_egl=no]) -AS_IF([test "x$have_cairo_egl" = "xyes"], - [AC_DEFINE([HAVE_CAIRO_EGL], [1], [Have cairo-egl])]) - if test "x$GCC" = "xyes"; then GCC_CFLAGS="-Wall -g -Wstrict-prototypes -Wmissing-prototypes -fvisibility=hidden" fi @@ -80,16 +38,9 @@ AC_CHECK_LIB(expat, XML_ParserCreate, [EXPAT_LIBS="-lexpat"], [AC_MSG_ERROR([Can't find expat library. Please install expat.])]) AC_SUBST(EXPAT_LIBS) -# workaround a bug in xcb-dri2 generated by xcb-proto 1.6 -AC_CHECK_LIB(xcb-dri2, xcb_dri2_connect_alignment_pad, [], - [AC_DEFINE([XCB_DRI2_CONNECT_DEVICE_NAME_BROKEN], [1], - [Define to 1 if xcb_dri2_connect_device_name is broken])]) - -AC_CONFIG_FILES([wayland/wayland-server.pc - wayland/wayland-client.pc - Makefile +AC_CONFIG_FILES([Makefile + wayland-scanner.m4 wayland/Makefile - compositor/Makefile - clients/Makefile - data/Makefile]) + wayland/wayland-server.pc + wayland/wayland-client.pc]) AC_OUTPUT diff --git a/data/.gitignore b/data/.gitignore deleted file mode 100644 index 8ea50a6..0000000 --- a/data/.gitignore +++ /dev/null @@ -1 +0,0 @@ -wayland.png diff --git a/data/COPYING b/data/COPYING deleted file mode 100644 index b9d6c37..0000000 --- a/data/COPYING +++ /dev/null @@ -1,6 +0,0 @@ -(c) 2007-2010 Novell, Inc. - -This work is licenced under the Creative Commons Attribution-Share Alike 3.0 -United States License. To view a copy of this licence, visit -http://creativecommons.org/licenses/by-sa/3.0/ or send a letter to Creative -Commons, 171 Second Street, Suite 300, San Francisco, California 94105, USA. diff --git a/data/Makefile.am b/data/Makefile.am deleted file mode 100644 index fbafceb..0000000 --- a/data/Makefile.am +++ /dev/null @@ -1,30 +0,0 @@ -waylanddatadir = $(datadir)/wayland - -dist_waylanddata_DATA = \ - bottom_left_corner.png \ - bottom_right_corner.png \ - bottom_side.png \ - dnd-copy.png \ - dnd-link.png \ - dnd-move.png \ - grabbing.png \ - hand1.png \ - hand2.png \ - left_ptr.png \ - left_side.png \ - right_side.png \ - sb_h_double_arrow.png \ - sb_v_double_arrow.png \ - top_left_corner.png \ - top_right_corner.png \ - top_side.png \ - xterm.png \ - wayland.svg \ - $(wayland_icon_png) - -if HAVE_RSVG_CONVERT -wayland_icon_png = wayland.png - -wayland.png : $(top_srcdir)/data/wayland.svg - $(RSVG_CONVERT) -w 128 -h 128 $< -o $@ -endif diff --git a/data/bottom_left_corner.png b/data/bottom_left_corner.png Binary files differdeleted file mode 100644 index 2d4370f..0000000 --- a/data/bottom_left_corner.png +++ /dev/null diff --git a/data/bottom_right_corner.png b/data/bottom_right_corner.png Binary files differdeleted file mode 100644 index 768e777..0000000 --- a/data/bottom_right_corner.png +++ /dev/null diff --git a/data/bottom_side.png b/data/bottom_side.png Binary files differdeleted file mode 100644 index ac7c70e..0000000 --- a/data/bottom_side.png +++ /dev/null diff --git a/data/dnd-copy.png b/data/dnd-copy.png Binary files differdeleted file mode 100644 index fd044ae..0000000 --- a/data/dnd-copy.png +++ /dev/null diff --git a/data/dnd-link.png b/data/dnd-link.png Binary files differdeleted file mode 100644 index 5183bf9..0000000 --- a/data/dnd-link.png +++ /dev/null diff --git a/data/dnd-move.png b/data/dnd-move.png Binary files differdeleted file mode 100644 index c3ccd6e..0000000 --- a/data/dnd-move.png +++ /dev/null diff --git a/data/grabbing.png b/data/grabbing.png Binary files differdeleted file mode 100644 index 0469459..0000000 --- a/data/grabbing.png +++ /dev/null diff --git a/data/hand1.png b/data/hand1.png Binary files differdeleted file mode 100644 index c13aa36..0000000 --- a/data/hand1.png +++ /dev/null diff --git a/data/hand2.png b/data/hand2.png Binary files differdeleted file mode 100644 index 016b9a6..0000000 --- a/data/hand2.png +++ /dev/null diff --git a/data/left_ptr.png b/data/left_ptr.png Binary files differdeleted file mode 100644 index c42ac55..0000000 --- a/data/left_ptr.png +++ /dev/null diff --git a/data/left_side.png b/data/left_side.png Binary files differdeleted file mode 100644 index 2e2fab5..0000000 --- a/data/left_side.png +++ /dev/null diff --git a/data/right_side.png b/data/right_side.png Binary files differdeleted file mode 100644 index d49b114..0000000 --- a/data/right_side.png +++ /dev/null diff --git a/data/sb_h_double_arrow.png b/data/sb_h_double_arrow.png Binary files differdeleted file mode 100644 index 8e55c0a..0000000 --- a/data/sb_h_double_arrow.png +++ /dev/null diff --git a/data/sb_v_double_arrow.png b/data/sb_v_double_arrow.png Binary files differdeleted file mode 100644 index 822f622..0000000 --- a/data/sb_v_double_arrow.png +++ /dev/null diff --git a/data/top_left_corner.png b/data/top_left_corner.png Binary files differdeleted file mode 100644 index 25c4e84..0000000 --- a/data/top_left_corner.png +++ /dev/null diff --git a/data/top_right_corner.png b/data/top_right_corner.png Binary files differdeleted file mode 100644 index fb7727c..0000000 --- a/data/top_right_corner.png +++ /dev/null diff --git a/data/top_side.png b/data/top_side.png Binary files differdeleted file mode 100644 index bf351f1..0000000 --- a/data/top_side.png +++ /dev/null diff --git a/data/wayland.svg b/data/wayland.svg deleted file mode 100644 index 29cb8f0..0000000 --- a/data/wayland.svg +++ /dev/null @@ -1,103 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<!-- Copyright © 2010 Kristian Høgsberg - - 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. --> - -<!-- Created with Inkscape (http://www.inkscape.org/) --> - -<svg - xmlns:dc="http://purl.org/dc/elements/1.1/" - xmlns:cc="http://creativecommons.org/ns#" - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:svg="http://www.w3.org/2000/svg" - xmlns="http://www.w3.org/2000/svg" - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - width="128" - height="128" - id="svg2" - version="1.1" - inkscape:version="0.48.0 r9654" - sodipodi:docname="wayland.svg" - inkscape:export-filename="/home/krh/wayland.png" - inkscape:export-xdpi="41.302303" - inkscape:export-ydpi="41.302303"> - <defs - id="defs4" /> - <sodipodi:namedview - id="base" - pagecolor="#ffffff" - bordercolor="#666666" - borderopacity="1.0" - inkscape:pageopacity="0" - inkscape:pageshadow="2" - inkscape:zoom="1.1" - inkscape:cx="246.80131" - inkscape:cy="58.818182" - inkscape:document-units="px" - inkscape:current-layer="layer1" - showgrid="false" - inkscape:window-width="1278" - inkscape:window-height="740" - inkscape:window-x="0" - inkscape:window-y="26" - inkscape:window-maximized="0" /> - <metadata - id="metadata7"> - <rdf:RDF> - <cc:Work - rdf:about=""> - <dc:format>image/svg+xml</dc:format> - <dc:type - rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> - <dc:title /> - </cc:Work> - </rdf:RDF> - </metadata> - <g - inkscape:label="Layer 1" - inkscape:groupmode="layer" - id="layer1" - style="display:inline" - transform="translate(0,-924.36218)"> - <path - sodipodi:type="arc" - style="fill:#ffbc00;fill-opacity:1;stroke:none" - id="path2985" - sodipodi:cx="341.42856" - sodipodi:cy="465.21933" - sodipodi:rx="122.85714" - sodipodi:ry="122.85714" - d="m 464.2857,465.21933 a 122.85714,122.85714 0 1 1 -245.71428,0 122.85714,122.85714 0 1 1 245.71428,0 z" - transform="matrix(0.49134614,0,0,0.49134614,-102.99669,759.57895)" /> - <g - transform="matrix(0.44987141,0,0,0.53664452,-102.99669,759.57895)" - style="font-size:437.47387695px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none" - id="text2987"> - <path - d="m 443.91049,314.59549 2.34971,0 -1.49527,1.49528 -0.85444,0 0,-1.49528 m -173.02434,3.63138 0,1.70888 -5.55387,6.83553 -0.85444,0 -0.85444,-5.34026 c 3.27538,-2.13591 5.69629,-3.20396 7.26275,-3.20415 m 202.50256,2.34971 c 4.84164,1.9e-4 7.54736,3.06194 8.11719,9.18524 l -4.0586,28.83739 1.49528,0 3.20415,-2.1361 0.85444,0 0,0.64083 c -4.41481,2.70589 -8.68701,10.11103 -12.81662,22.21547 -1.56666,10.39583 -4.20118,20.00828 -7.90358,28.83739 -3.27553,9.11414 -4.91321,17.51613 -4.91303,25.20602 l -6.1947,15.16633 c -1.7e-4,1.28172 2.34954,2.56338 7.04914,3.84498 -0.85462,2.9906 -2.13628,4.48587 -3.84499,4.48582 l 0,0.85444 1.49527,0 0,0.64083 c -1.7e-4,1.56653 -2.42108,2.34977 -7.26275,2.34971 l 0.85444,0.85444 0,2.99055 -1.49527,0 c 0.99668,2.99059 3.13279,4.48586 6.40831,4.48581 l 0,1.49528 -6.40831,0 0,0.85444 c 2.13594,4e-5 3.20399,1.2817 3.20416,3.84498 l -8.97163,2.99055 0.85444,0.85444 0,0.64083 c -1.6e-4,0.99688 -1.06821,1.4953 -3.20416,1.49527 l 0,0.85444 c 2.70557,3e-5 4.05844,0.49846 4.0586,1.49527 -3.84515,1.28169 -8.90058,7.61879 -15.16633,19.01132 -6.40845,10.11089 -11.96231,15.16633 -16.66161,15.16633 l -1.70888,0 c -3.56029,-2.27851 -6.47963,-9.82607 -8.75802,-22.64269 -9.11415,-19.5097 -13.67116,-30.97344 -13.67106,-34.39126 -1e-4,-8.82916 -2.91944,-18.228 -8.75802,-28.19656 -1.56657,-4.41452 -2.63462,-9.96839 -3.20416,-16.6616 l -3.84498,-0.85444 c -9.68375,14.66799 -14.73919,26.13173 -15.16633,34.39126 -2.7058,4.84189 -4.8419,10.68057 -6.40831,17.51604 5.83861,1.56652 8.75795,3.06179 8.75802,4.48582 l 0,0.85444 c -4.55709,-0.56959 -7.76124,-1.63764 -9.61246,-3.20416 -1.99376,3.84503 -4.62829,14.52553 -7.90358,32.04155 -2.56338,8.11719 -5.76753,12.17578 -9.61247,12.17578 -10.82295,-3.56016 -19.86578,-9.39884 -27.1285,-17.51604 -1.13928,2e-5 -2.99057,-4.05857 -5.55387,-12.17579 -1.56649,3e-5 -2.63454,-4.05856 -3.20415,-12.17578 -5.41147,-11.5349 -9.11405,-24.70753 -11.10774,-39.51791 l 0,-22.21547 -0.85444,0 -3.84499,0.85444 0,-0.85444 c 1e-5,-0.99674 1.28167,-1.49516 3.84499,-1.49527 l -0.85444,-12.81662 0,-10.03968 -6.1947,-32.04154 0,-13.67106 c 2.70573,-8.54423 7.40515,-12.81643 14.09828,-12.81662 l 44.85816,0 0,1.49527 c -3.56022,0.14259 -5.98114,0.92583 -7.26275,2.34972 -2.70577,-1.5663 -5.3403,-2.34953 -7.90358,-2.34972 l -8.75802,0 -4.91304,0.64083 -0.85444,-0.64083 -0.64083,0 -6.40831,0.64083 -3.20415,-0.64083 -2.34972,0.64083 -2.56332,-0.64083 c 10.39568,11.39272 16.51917,21.00518 18.37048,28.83739 l 7.26275,0 0,1.49527 -5.55386,0 0,1.70889 c 2.13607,6.55086 3.70254,9.82621 4.69942,9.82607 l 1.70889,0 3.84498,-0.85444 0.85444,0.85444 0.85444,-0.85444 0.85444,0.85444 0,0.64083 c -2.84817,1.70902 -4.77066,4.05873 -5.76747,7.04914 l -0.64083,0 0,1.49527 1.49527,0 c 1.99366,23.78206 5.69623,41.79651 11.10773,54.04341 l 3.20416,2.1361 1.70888,0 c 2.13605,8e-5 6.62186,-8.33072 13.45745,-24.99241 4.41454,-7.54745 7.61869,-14.16936 9.61246,-19.86575 l -0.85444,-2.34972 c 4.41453,-5.55373 8.97155,-8.33066 13.67106,-8.3308 l 1.49527,0 c 2.99045,1.4e-4 5.12655,1.56661 6.40831,4.69943 3.98729,4.69955 7.19144,11.74868 9.61246,21.14742 l 11.96218,22.21547 c 1.56635,1.56656 2.34959,3.34664 2.34971,5.34026 4.41449,8.40207 8.40188,13.95593 11.96218,16.6616 l 2.56332,0 c 2.99041,6e-5 6.9778,-10.39563 11.96218,-31.1871 0.85429,9e-5 3.204,-5.55377 7.04914,-16.66161 l 0,-0.85444 -13.45745,-1.49527 -3.20416,0.85444 -4.05859,0 0,-1.70888 8.11719,-0.64083 15.80716,0 c 6.12333,-18.37035 11.7484,-32.61103 16.87521,-42.72206 1.70871,-20.79122 4.05842,-31.18691 7.04914,-31.1871 l 9.61247,-3.84499 m -45.49899,2.34971 c -0.85459,1.99389 -2.70588,2.99074 -5.55387,2.99055 l 0,-1.49527 5.55387,-1.49528 m -80.53108,3.84499 21.57464,0 0,1.49527 -4.91304,0.64083 -4.69943,-0.64083 -4.05859,1.49527 -1.49528,-1.49527 -6.4083,0 0,-1.49527 m -112.35902,2.99054 2.34972,0 1.49527,1.49528 0,0.85444 -4.69943,4.48581 0,3.84499 -1.70888,0 0,-2.34971 0.85444,-0.64084 0,-0.85444 -4.0586,-3.84498 c 0.99691,-1.99352 2.9194,-2.99036 5.76748,-2.99055 m 157.00357,9.18525 2.34971,0 0,0.64083 c -1.1e-4,0.99702 -0.78335,1.49544 -2.34971,1.49527 l -0.85444,0.85444 0,0.85444 -2.34972,-0.85444 0,-1.49527 3.20416,-1.49527 m -11.96218,8.3308 0,0.85444 c -1e-4,1.13942 -3.41786,2.34988 -10.25329,3.63137 l 0,-1.49527 4.69942,-2.1361 0.85444,0.64083 0.64083,0 4.0586,-1.49527 m -139.48752,7.68997 0,0.64083 -1.70888,1.49527 -0.64083,-0.64083 0,-0.85444 0.64083,-0.64083 1.70888,0 m 116.41761,0 0,0.64083 c -2.99062,2.27866 -7.83244,4.34356 -14.5255,6.1947 l 0,-1.49527 c 1.13919,1.5e-4 1.70882,-0.78309 1.70888,-2.34972 l 12.81662,-2.99054 m 40.58595,7.47636 0.85445,0.85444 0,0.64083 -1.49528,1.70888 -0.85444,0 -1.70888,-1.70888 0,-0.64083 3.20415,-0.85444 m 29.47822,0.85444 0.85445,0 0,0.64083 -1.49528,1.70888 -0.85444,0 0,-0.85444 1.49527,-1.49527 m -13.45744,10.68051 3.20415,2.13611 c -0.56976,1.56661 -2.13623,2.34985 -4.69943,2.34971 l -1.70888,-2.34971 c -1.3e-4,-0.7119 1.06792,-1.42393 3.20416,-2.13611 m 19.22492,9.82608 0.64083,0.85444 0,0.64083 -0.64083,0.85444 -1.70888,0 0,-0.85444 1.70888,-1.49527 m -30.33266,7.68997 0,0.64083 -4.05859,3.20415 -2.34972,0 0,-0.85444 c -1.1e-4,-1.28154 2.13599,-2.27839 6.40831,-2.99054 m -132.43838,29.69183 0.85444,0 0,0.64083 c -2.13609,4.69951 -3.98737,7.54765 -5.55387,8.54441 l -1.70888,0 0,-3.20415 6.40831,-5.98109 m 104.45543,35.67292 0.85444,0 0,1.49527 -6.4083,3.20415 -0.85445,-0.85444 0,-1.49527 6.40831,-2.34971 m -87.79383,10.03968 1.49527,0 2.56333,8.3308 -1.70888,0 -2.34972,-7.68997 0,-0.64083 m 85.44412,9.82607 0.64083,0 2.56332,2.34972 -0.85444,0.64083 -0.85444,0 -1.49527,-2.1361 0,-0.85445" - id="path2986" - inkscape:connector-curvature="0" - sodipodi:nodetypes="cccccccccccccccccccccccccccccccccccccccccccsccccccccccccccccccccsccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc" /> - </g> - </g> -</svg> diff --git a/data/xterm.png b/data/xterm.png Binary files differdeleted file mode 100644 index dc054c9..0000000 --- a/data/xterm.png +++ /dev/null diff --git a/wayland-scanner.m4.in b/wayland-scanner.m4.in new file mode 100644 index 0000000..29bc788 --- /dev/null +++ b/wayland-scanner.m4.in @@ -0,0 +1,16 @@ +AC_DEFUN([WAYLAND_SCANNER_RULES], [ + wayland__prefix=${prefix} + wayland__exec_prefix=${exec_prefix} + + prefix=@prefix@ + exec_prefix=@exec_prefix@ + + AC_PATH_PROG([wayland_scanner], [wayland-scanner], [/bin/false], + [@bindir@$PATH_SEPARATOR$PATH]) + AC_SUBST_FILE([wayland_scanner_rules]) + AC_SUBST([wayland_protocoldir], [$1]) + wayland_scanner_rules=@datarootdir@/aclocal/wayland-scanner.mk + + prefix=${wayland__prefix} + exec_prefix=${wayland__exec_prefix} +]) diff --git a/wayland-scanner.mk b/wayland-scanner.mk new file mode 100644 index 0000000..0a72062 --- /dev/null +++ b/wayland-scanner.mk @@ -0,0 +1,8 @@ +%-protocol.c : $(wayland_protocoldir)/%.xml + $(AM_V_GEN)$(wayland_scanner) code < $< > $@ + +%-server-protocol.h : $(wayland_protocoldir)/%.xml + $(AM_V_GEN)$(wayland_scanner) server-header < $< > $@ + +%-client-protocol.h : $(wayland_protocoldir)/%.xml + $(AM_V_GEN)$(wayland_scanner) client-header < $< > $@ diff --git a/wayland/Makefile.am b/wayland/Makefile.am index cf91c8d..495eb03 100644 --- a/wayland/Makefile.am +++ b/wayland/Makefile.am @@ -33,16 +33,18 @@ pkgconfig_DATA = wayland-client.pc wayland-server.pc AM_CPPFLAGS = $(FFI_CFLAGS) AM_CFLAGS = $(GCC_CFLAGS) +protocoldir = $(top_srcdir)/protocol +wayland_scanner = $(top_builddir)/wayland/wayland-scanner include $(top_srcdir)/wayland/scanner.mk -noinst_PROGRAMS = scanner +bin_PROGRAMS = wayland-scanner -scanner_SOURCES = \ +wayland_scanner_SOURCES = \ scanner.c -scanner_LDADD = $(EXPAT_LIBS) libwayland-util.la +wayland_scanner_LDADD = $(EXPAT_LIBS) libwayland-util.la -$(BUILT_SOURCES) : scanner +$(BUILT_SOURCES) : wayland-scanner BUILT_SOURCES = \ wayland-server-protocol.h \ diff --git a/wayland/scanner.mk b/wayland/scanner.mk index efdb42b..1b6963c 100644 --- a/wayland/scanner.mk +++ b/wayland/scanner.mk @@ -1,8 +1,8 @@ -%-protocol.c : $(top_srcdir)/protocol/%.xml - $(AM_V_GEN)$(top_builddir)/wayland/scanner code < $< > $@ +%-protocol.c : $(protocoldir)/%.xml + $(AM_V_GEN)$(wayland_scanner) code < $< > $@ -%-server-protocol.h : $(top_srcdir)/protocol/%.xml - $(AM_V_GEN)$(top_builddir)/wayland/scanner server-header < $< > $@ +%-server-protocol.h : $(protocoldir)/%.xml + $(AM_V_GEN)$(wayland_scanner) server-header < $< > $@ -%-client-protocol.h : $(top_srcdir)/protocol/%.xml - $(AM_V_GEN)$(top_builddir)/wayland/scanner client-header < $< > $@ +%-client-protocol.h : $(protocoldir)/%.xml + $(AM_V_GEN)$(wayland_scanner) client-header < $< > $@ |