Split into a core repository that only holds the core Wayland libraries
|
|
@ -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
|
||||
13
clients/.gitignore
vendored
|
|
@ -1,13 +0,0 @@
|
|||
dnd
|
||||
eventdemo
|
||||
flower
|
||||
gears
|
||||
image
|
||||
resizor
|
||||
screenshooter-client-protocol.h
|
||||
screenshooter-protocol.c
|
||||
screenshot
|
||||
simple-client
|
||||
smoke
|
||||
terminal
|
||||
view
|
||||
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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
|
||||
695
clients/dnd.c
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
166
clients/flower.c
|
|
@ -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;
|
||||
}
|
||||
433
clients/gears.c
|
|
@ -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;
|
||||
}
|
||||
259
clients/image.c
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
296
clients/smoke.c
|
|
@ -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;
|
||||
}
|
||||
2398
clients/terminal.c
268
clients/view.c
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
1741
clients/window.c
245
clients/window.h
|
|
@ -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
|
||||
3
compositor/.gitignore
vendored
|
|
@ -1,3 +0,0 @@
|
|||
compositor
|
||||
screenshooter-protocol.c
|
||||
screenshooter-server-protocol.h
|
||||
|
|
@ -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"
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
246
compositor/drm.c
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
};
|
||||
|
|
@ -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;
|
||||
}
|
||||
174
compositor/shm.c
|
|
@ -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;
|
||||
}
|
||||
160
compositor/tty.c
|
|
@ -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);
|
||||
}
|
||||
57
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
|
||||
|
|
|
|||
1
data/.gitignore
vendored
|
|
@ -1 +0,0 @@
|
|||
wayland.png
|
||||
|
|
@ -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.
|
||||
|
|
@ -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
|
||||
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1 KiB |
|
Before Width: | Height: | Size: 994 B |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1,004 B |
BIN
data/hand1.png
|
Before Width: | Height: | Size: 1.1 KiB |
BIN
data/hand2.png
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1 KiB |
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
103
data/wayland.svg
BIN
data/xterm.png
|
Before Width: | Height: | Size: 615 B |
16
wayland-scanner.m4.in
Normal file
|
|
@ -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}
|
||||
])
|
||||
8
wayland-scanner.mk
Normal file
|
|
@ -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 < $< > $@
|
||||
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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 < $< > $@
|
||||
|
|
|
|||