mirror of
https://gitlab.freedesktop.org/wayland/wayland.git
synced 2025-11-21 06:59:46 -05:00
Merge branch 'master' of git://anongit.freedesktop.org/wayland
Conflicts: clients/window.h
This commit is contained in:
commit
6eeeb30021
26 changed files with 2254 additions and 1053 deletions
|
|
@ -7,21 +7,17 @@ noinst_PROGRAMS = \
|
|||
$(poppler_programs) \
|
||||
dnd \
|
||||
smoke \
|
||||
resizor
|
||||
resizor \
|
||||
simple-client
|
||||
|
||||
noinst_LTLIBRARIES = libtoytoolkit.la
|
||||
|
||||
INCLUDES = \
|
||||
-I$(top_srcdir)/wayland \
|
||||
-I$(top_builddir)/wayland \
|
||||
$(CLIENT_CFLAGS)
|
||||
|
||||
LDADD = libtoytoolkit.la \
|
||||
$(top_builddir)/wayland/libwayland-client.la \
|
||||
$(CLIENT_LIBS) -lrt -lm
|
||||
|
||||
AM_CFLAGS = $(GCC_CFLAGS)
|
||||
AM_CPPFLAGS = -DDATADIR='"$(datadir)"'
|
||||
AM_CPPFLAGS = \
|
||||
-DDATADIR='"$(datadir)"' \
|
||||
-I$(top_srcdir)/wayland \
|
||||
-I$(top_builddir)/wayland \
|
||||
$(CLIENT_CFLAGS)
|
||||
|
||||
libtoytoolkit_la_SOURCES = \
|
||||
window.c \
|
||||
|
|
@ -31,14 +27,38 @@ libtoytoolkit_la_SOURCES = \
|
|||
cairo-util.c \
|
||||
cairo-util.h
|
||||
|
||||
flower_SOURCES = flower.c
|
||||
smoke_SOURCES = smoke.c
|
||||
toolkit_libs = \
|
||||
libtoytoolkit.la \
|
||||
$(top_builddir)/wayland/libwayland-client.la \
|
||||
$(CLIENT_LIBS) -lrt -lm
|
||||
|
||||
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)
|
||||
|
||||
BUILT_SOURCES = \
|
||||
screenshooter-client-protocol.h \
|
||||
|
|
@ -48,11 +68,9 @@ CLEANFILES = $(BUILT_SOURCES)
|
|||
|
||||
include $(top_srcdir)/wayland/scanner.mk
|
||||
|
||||
terminal_LDADD = $(LDADD) -lutil
|
||||
|
||||
if HAVE_POPPLER
|
||||
poppler_programs = view
|
||||
view_SOURCES = view.c
|
||||
view_LDADD = $(LDADD) $(POPPLER_LIBS)
|
||||
view_CPPFLAGS = $(POPPLER_CFLAGS)
|
||||
view_LDADD = $(toolkit_libs) $(POPPLER_LIBS)
|
||||
view_CPPFLAGS = $(AM_CPPFLAGS) $(POPPLER_CFLAGS)
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -171,21 +171,20 @@ dnd_draw(struct dnd *dnd)
|
|||
{
|
||||
struct rectangle allocation;
|
||||
cairo_t *cr;
|
||||
cairo_surface_t *wsurface, *surface;
|
||||
cairo_surface_t *surface;
|
||||
int i;
|
||||
|
||||
window_draw(dnd->window);
|
||||
|
||||
window_get_child_allocation(dnd->window, &allocation);
|
||||
|
||||
wsurface = window_get_surface(dnd->window);
|
||||
surface = cairo_surface_create_similar(wsurface,
|
||||
CAIRO_CONTENT_COLOR_ALPHA,
|
||||
allocation.width,
|
||||
allocation.height);
|
||||
cairo_surface_destroy(wsurface);
|
||||
|
||||
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);
|
||||
|
|
@ -199,9 +198,9 @@ dnd_draw(struct dnd *dnd)
|
|||
cairo_paint(cr);
|
||||
}
|
||||
|
||||
cairo_pop_group_to_source(cr);
|
||||
cairo_paint(cr);
|
||||
cairo_destroy(cr);
|
||||
|
||||
window_copy_surface(dnd->window, &allocation, surface);
|
||||
cairo_surface_destroy(surface);
|
||||
window_flush(dnd->window);
|
||||
}
|
||||
|
|
@ -487,14 +486,21 @@ static const struct wl_drag_offer_listener drag_offer_listener = {
|
|||
};
|
||||
|
||||
static void
|
||||
drag_offer_handler(struct wl_drag_offer *offer, struct display *display)
|
||||
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);
|
||||
|
|
@ -681,7 +687,7 @@ main(int argc, char *argv[])
|
|||
return -1;
|
||||
}
|
||||
|
||||
display_set_drag_offer_handler(d, drag_offer_handler);
|
||||
display_set_global_handler(d, global_handler);
|
||||
|
||||
dnd = dnd_create (d);
|
||||
|
||||
|
|
|
|||
|
|
@ -212,7 +212,7 @@ allocate_buffer(struct gears *gears)
|
|||
window_draw(gears->window);
|
||||
|
||||
gears->surface[gears->current] = window_get_surface(gears->window);
|
||||
#ifdef HAVE_CAIRO_GL
|
||||
#ifdef HAVE_CAIRO_EGL
|
||||
image = display_get_image_for_drm_surface(gears->display,
|
||||
gears->surface[gears->current]);
|
||||
#else /* XXX: hack to make Wayland compile, even if this example doesn't run */
|
||||
|
|
|
|||
|
|
@ -140,7 +140,7 @@ image_draw(struct image *image)
|
|||
struct rectangle allocation;
|
||||
GdkPixbuf *pb;
|
||||
cairo_t *cr;
|
||||
cairo_surface_t *wsurface, *surface;
|
||||
cairo_surface_t *surface;
|
||||
|
||||
window_draw(image->window);
|
||||
|
||||
|
|
@ -153,14 +153,15 @@ image_draw(struct image *image)
|
|||
if (pb == NULL)
|
||||
return;
|
||||
|
||||
wsurface = window_get_surface(image->window);
|
||||
surface = cairo_surface_create_similar(wsurface,
|
||||
CAIRO_CONTENT_COLOR_ALPHA,
|
||||
allocation.width,
|
||||
allocation.height);
|
||||
|
||||
cairo_surface_destroy(wsurface);
|
||||
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);
|
||||
|
|
@ -169,11 +170,13 @@ image_draw(struct image *image)
|
|||
allocation.width, allocation.height);
|
||||
cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
|
||||
cairo_paint(cr);
|
||||
cairo_destroy(cr);
|
||||
|
||||
g_object_unref(pb);
|
||||
|
||||
window_copy_surface(image->window, &allocation, surface);
|
||||
cairo_pop_group_to_source(cr);
|
||||
cairo_paint(cr);
|
||||
cairo_destroy(cr);
|
||||
|
||||
window_flush(image->window);
|
||||
cairo_surface_destroy(surface);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -128,8 +128,8 @@ keyboard_focus_handler(struct window *window,
|
|||
}
|
||||
|
||||
static void
|
||||
key_handler(struct window *window, uint32_t key, uint32_t sym,
|
||||
uint32_t state, uint32_t modifiers, void *data)
|
||||
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;
|
||||
|
||||
|
|
|
|||
393
clients/simple-client.c
Normal file
393
clients/simple-client.c
Normal file
|
|
@ -0,0 +1,393 @@
|
|||
/*
|
||||
* 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 <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <math.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <wayland-client.h>
|
||||
#include <xf86drm.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>
|
||||
|
||||
struct display {
|
||||
struct wl_display *display;
|
||||
struct {
|
||||
struct wl_compositor *compositor;
|
||||
struct wl_drm *drm;
|
||||
} interface;
|
||||
struct {
|
||||
EGLDisplay dpy;
|
||||
EGLContext ctx;
|
||||
} egl;
|
||||
struct {
|
||||
int fd;
|
||||
const char *device_name;
|
||||
bool authenticated;
|
||||
} drm;
|
||||
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 {
|
||||
struct wl_buffer *buffer;
|
||||
struct wl_surface *surface;
|
||||
EGLImageKHR image;
|
||||
} drm_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
|
||||
};
|
||||
|
||||
EGLint major, minor;
|
||||
EGLBoolean ret;
|
||||
|
||||
display->egl.dpy = eglGetDRMDisplayMESA(display->drm.fd);
|
||||
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);
|
||||
|
||||
display->egl.ctx = eglCreateContext(display->egl.dpy, NULL,
|
||||
EGL_NO_CONTEXT, context_attribs);
|
||||
assert(display->egl.ctx);
|
||||
ret = eglMakeCurrent(display->egl.dpy, NULL, NULL, display->egl.ctx);
|
||||
assert(ret == EGL_TRUE);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
GLfloat ar;
|
||||
GLuint frag, vert;
|
||||
GLint status;
|
||||
|
||||
glGenFramebuffers(1, &window->gl.fbo);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, window->gl.fbo);
|
||||
|
||||
glGenRenderbuffers(1, &window->gl.color_rbo);
|
||||
|
||||
glViewport(0, 0, window->geometry.width, window->geometry.height);
|
||||
ar = (GLfloat)window->geometry.width / (GLfloat)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;
|
||||
EGLint name, stride;
|
||||
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
|
||||
};
|
||||
|
||||
window->drm_surface.surface =
|
||||
wl_compositor_create_surface(display->interface.compositor);
|
||||
|
||||
image_attribs[1] = window->geometry.width;
|
||||
image_attribs[3] = window->geometry.height;
|
||||
|
||||
window->drm_surface.image = eglCreateDRMImageMESA(display->egl.dpy,
|
||||
image_attribs);
|
||||
eglExportDRMImageMESA(display->egl.dpy, window->drm_surface.image,
|
||||
&name, NULL, &stride);
|
||||
visual = wl_display_get_premultiplied_argb_visual(display->display);
|
||||
|
||||
window->drm_surface.buffer =
|
||||
wl_drm_create_buffer(display->interface.drm, name,
|
||||
window->geometry.width,
|
||||
window->geometry.height,
|
||||
stride, visual);
|
||||
|
||||
wl_surface_attach(window->drm_surface.surface,
|
||||
window->drm_surface.buffer, 0, 0);
|
||||
wl_surface_map_toplevel(window->drm_surface.surface);
|
||||
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, window->gl.color_rbo);
|
||||
glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER,
|
||||
window->drm_surface.image);
|
||||
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER,
|
||||
GL_COLOR_ATTACHMENT0,
|
||||
GL_RENDERBUFFER,
|
||||
window->gl.color_rbo);
|
||||
|
||||
assert(glCheckFramebufferStatus(GL_FRAMEBUFFER) ==
|
||||
GL_FRAMEBUFFER_COMPLETE);
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
wl_surface_damage(window->drm_surface.surface, 0, 0,
|
||||
window->geometry.width, window->geometry.height);
|
||||
|
||||
wl_display_frame_callback(window->display->display, redraw, window);
|
||||
}
|
||||
|
||||
static void
|
||||
drm_handle_device(void *data, struct wl_drm *drm, const char *device)
|
||||
{
|
||||
struct display *d = data;
|
||||
|
||||
d->drm.device_name = strdup(device);
|
||||
}
|
||||
|
||||
static void
|
||||
drm_handle_authenticated(void *data, struct wl_drm *drm)
|
||||
{
|
||||
struct display *d = data;
|
||||
|
||||
d->drm.authenticated = true;
|
||||
}
|
||||
|
||||
static const struct wl_drm_listener drm_listener = {
|
||||
drm_handle_device,
|
||||
drm_handle_authenticated
|
||||
};
|
||||
|
||||
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->interface.compositor = wl_compositor_create(display, id);
|
||||
} else if (strcmp(interface, "drm") == 0) {
|
||||
d->interface.drm = wl_drm_create(display, id);
|
||||
wl_drm_add_listener(d->interface.drm, &drm_listener, d);
|
||||
}
|
||||
}
|
||||
|
||||
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 };
|
||||
drm_magic_t magic;
|
||||
int ret;
|
||||
|
||||
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);
|
||||
/* process connection events */
|
||||
wl_display_iterate(display.display, WL_DISPLAY_READABLE);
|
||||
|
||||
display.drm.fd = open(display.drm.device_name, O_RDWR);
|
||||
assert(display.drm.fd >= 0);
|
||||
|
||||
ret = drmGetMagic(display.drm.fd, &magic);
|
||||
assert(ret == 0);
|
||||
wl_drm_authenticate(display.interface.drm, magic);
|
||||
wl_display_iterate(display.display, WL_DISPLAY_WRITABLE);
|
||||
while (!display.drm.authenticated)
|
||||
wl_display_iterate(display.display, WL_DISPLAY_READABLE);
|
||||
|
||||
init_egl(&display);
|
||||
init_gl(&window);
|
||||
create_surface(&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;
|
||||
}
|
||||
|
|
@ -273,9 +273,9 @@ function_key_response(char escape, int num, uint32_t modifiers,
|
|||
int mod_num = 0;
|
||||
int len;
|
||||
|
||||
if (modifiers & WINDOW_MODIFIER_SHIFT) mod_num |= 1;
|
||||
if (modifiers & WINDOW_MODIFIER_ALT) mod_num |= 2;
|
||||
if (modifiers & WINDOW_MODIFIER_CONTROL) mod_num |= 4;
|
||||
if (modifiers & XKB_COMMON_SHIFT_MASK) mod_num |= 1;
|
||||
if (modifiers & XKB_COMMON_MOD1_MASK) mod_num |= 2;
|
||||
if (modifiers & XKB_COMMON_CONTROL_MASK) mod_num |= 4;
|
||||
|
||||
if (mod_num != 0)
|
||||
len = snprintf(response, MAX_RESPONSE, "\e[%d;%d%c",
|
||||
|
|
@ -390,6 +390,14 @@ struct terminal {
|
|||
struct terminal_color color_table[256];
|
||||
cairo_font_extents_t extents;
|
||||
cairo_scaled_font_t *font_normal, *font_bold;
|
||||
|
||||
uint32_t tag;
|
||||
struct wl_selection *selection;
|
||||
struct wl_selection_offer *selection_offer;
|
||||
uint32_t selection_offer_has_text;
|
||||
int32_t dragging, selection_active;
|
||||
int selection_start_x, selection_start_y;
|
||||
int selection_end_x, selection_end_y;
|
||||
};
|
||||
|
||||
/* Create default tab stops, every 8 characters */
|
||||
|
|
@ -487,16 +495,62 @@ union decoded_attr {
|
|||
uint32_t key;
|
||||
};
|
||||
|
||||
static int
|
||||
terminal_compare_position(struct terminal *terminal,
|
||||
int x, int y, int32_t ref_row, int32_t ref_col)
|
||||
{
|
||||
struct rectangle allocation;
|
||||
int top_margin, side_margin, col, row, ref_x;
|
||||
|
||||
window_get_child_allocation(terminal->window, &allocation);
|
||||
side_margin = allocation.x + (allocation.width - terminal->width * terminal->extents.max_x_advance) / 2;
|
||||
top_margin = allocation.y + (allocation.height - terminal->height * terminal->extents.height) / 2;
|
||||
|
||||
col = (x - side_margin) / terminal->extents.max_x_advance;
|
||||
row = (y - top_margin) / terminal->extents.height;
|
||||
|
||||
ref_x = side_margin + ref_col * terminal->extents.max_x_advance +
|
||||
terminal->extents.max_x_advance / 2;
|
||||
|
||||
if (row < ref_row)
|
||||
return -1;
|
||||
if (row == ref_row) {
|
||||
if (col < ref_col)
|
||||
return -1;
|
||||
if (col == ref_col && x < ref_x)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
terminal_decode_attr(struct terminal *terminal, int row, int col,
|
||||
union decoded_attr *decoded)
|
||||
{
|
||||
struct attr attr;
|
||||
int foreground, background, tmp;
|
||||
int inverse = 0, start_cmp, end_cmp;
|
||||
|
||||
start_cmp =
|
||||
terminal_compare_position(terminal,
|
||||
terminal->selection_start_x,
|
||||
terminal->selection_start_y,
|
||||
row, col);
|
||||
end_cmp =
|
||||
terminal_compare_position(terminal,
|
||||
terminal->selection_end_x,
|
||||
terminal->selection_end_y,
|
||||
row, col);
|
||||
if (start_cmp < 0 && end_cmp > 0)
|
||||
inverse = 1;
|
||||
else if (end_cmp < 0 && start_cmp > 0)
|
||||
inverse = 1;
|
||||
|
||||
/* get the attributes for this character cell */
|
||||
attr = terminal_get_attr_row(terminal, row)[col];
|
||||
if ((attr.a & ATTRMASK_INVERSE) ||
|
||||
inverse ||
|
||||
((terminal->mode & MODE_SHOW_CURSOR) &&
|
||||
terminal->focused && terminal->row == row &&
|
||||
terminal->column == col)) {
|
||||
|
|
@ -830,7 +884,6 @@ terminal_draw_contents(struct terminal *terminal)
|
|||
{
|
||||
struct rectangle allocation;
|
||||
cairo_t *cr;
|
||||
cairo_font_extents_t extents;
|
||||
int top_margin, side_margin;
|
||||
int row, col;
|
||||
union utf8_char *p_row;
|
||||
|
|
@ -839,23 +892,29 @@ terminal_draw_contents(struct terminal *terminal)
|
|||
cairo_surface_t *surface;
|
||||
double d;
|
||||
struct glyph_run run;
|
||||
cairo_font_extents_t extents;
|
||||
|
||||
surface = window_get_surface(terminal->window);
|
||||
window_get_child_allocation(terminal->window, &allocation);
|
||||
|
||||
surface = display_create_surface(terminal->display, &allocation);
|
||||
cr = cairo_create(surface);
|
||||
cairo_rectangle(cr, allocation.x, allocation.y,
|
||||
allocation.width, allocation.height);
|
||||
cairo_clip(cr);
|
||||
cairo_push_group(cr);
|
||||
|
||||
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
|
||||
terminal_set_color(terminal, cr, terminal->color_scheme->border);
|
||||
cairo_paint(cr);
|
||||
|
||||
cairo_set_scaled_font(cr, terminal->font_normal);
|
||||
|
||||
cairo_font_extents(cr, &extents);
|
||||
extents = terminal->extents;
|
||||
side_margin = (allocation.width - terminal->width * extents.max_x_advance) / 2;
|
||||
top_margin = (allocation.height - terminal->height * extents.height) / 2;
|
||||
|
||||
cairo_set_line_width(cr, 1.0);
|
||||
|
||||
cairo_translate(cr, allocation.x + side_margin,
|
||||
allocation.y + top_margin);
|
||||
/* paint the background */
|
||||
for (row = 0; row < terminal->height; row++) {
|
||||
for (col = 0; col < terminal->width; col++) {
|
||||
|
|
@ -866,8 +925,8 @@ terminal_draw_contents(struct terminal *terminal)
|
|||
continue;
|
||||
|
||||
terminal_set_color(terminal, cr, attr.attr.bg);
|
||||
cairo_move_to(cr, side_margin + (col * extents.max_x_advance),
|
||||
top_margin + (row * extents.height));
|
||||
cairo_move_to(cr, col * extents.max_x_advance,
|
||||
row * extents.height);
|
||||
cairo_rel_line_to(cr, extents.max_x_advance, 0);
|
||||
cairo_rel_line_to(cr, 0, extents.height);
|
||||
cairo_rel_line_to(cr, -extents.max_x_advance, 0);
|
||||
|
|
@ -888,8 +947,8 @@ terminal_draw_contents(struct terminal *terminal)
|
|||
|
||||
glyph_run_flush(&run, attr);
|
||||
|
||||
text_x = side_margin + col * extents.max_x_advance;
|
||||
text_y = top_margin + extents.ascent + row * extents.height;
|
||||
text_x = col * extents.max_x_advance;
|
||||
text_y = extents.ascent + row * extents.height;
|
||||
if (attr.attr.a & ATTRMASK_UNDERLINE) {
|
||||
terminal_set_color(terminal, cr, attr.attr.fg);
|
||||
cairo_move_to(cr, text_x, (double)text_y + 1.5);
|
||||
|
|
@ -908,8 +967,8 @@ terminal_draw_contents(struct terminal *terminal)
|
|||
d = 0.5;
|
||||
|
||||
cairo_set_line_width(cr, 1);
|
||||
cairo_move_to(cr, side_margin + terminal->column * extents.max_x_advance + d,
|
||||
top_margin + terminal->row * extents.height + d);
|
||||
cairo_move_to(cr, terminal->column * extents.max_x_advance + d,
|
||||
terminal->row * extents.height + d);
|
||||
cairo_rel_line_to(cr, extents.max_x_advance - 2 * d, 0);
|
||||
cairo_rel_line_to(cr, 0, extents.height - 2 * d);
|
||||
cairo_rel_line_to(cr, -extents.max_x_advance + 2 * d, 0);
|
||||
|
|
@ -918,10 +977,9 @@ terminal_draw_contents(struct terminal *terminal)
|
|||
cairo_stroke(cr);
|
||||
}
|
||||
|
||||
cairo_pop_group_to_source(cr);
|
||||
cairo_paint(cr);
|
||||
cairo_destroy(cr);
|
||||
|
||||
window_copy_surface(terminal->window, &allocation, surface);
|
||||
|
||||
cairo_surface_destroy(surface);
|
||||
}
|
||||
|
||||
|
|
@ -1936,13 +1994,102 @@ terminal_data(struct terminal *terminal, const char *data, size_t length)
|
|||
}
|
||||
|
||||
static void
|
||||
key_handler(struct window *window, uint32_t key, uint32_t sym,
|
||||
uint32_t state, uint32_t modifiers, void *data)
|
||||
selection_listener_send(void *data, struct wl_selection *selection,
|
||||
const char *mime_type, int fd)
|
||||
{
|
||||
static const char msg[] = "selection data";
|
||||
|
||||
fprintf(stderr, "selection send, fd is %d\n", fd);
|
||||
write(fd, msg, sizeof msg - 1);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
static void
|
||||
selection_listener_cancelled(void *data, struct wl_selection *selection)
|
||||
{
|
||||
fprintf(stderr, "selection cancelled\n");
|
||||
wl_selection_destroy(selection);
|
||||
}
|
||||
|
||||
static const struct wl_selection_listener selection_listener = {
|
||||
selection_listener_send,
|
||||
selection_listener_cancelled
|
||||
};
|
||||
|
||||
static gboolean
|
||||
selection_io_func(GIOChannel *source, GIOCondition condition, gpointer data)
|
||||
{
|
||||
struct terminal *terminal = data;
|
||||
char buffer[256];
|
||||
unsigned int len;
|
||||
int fd;
|
||||
|
||||
fd = g_io_channel_unix_get_fd(source);
|
||||
len = read(fd, buffer, sizeof buffer);
|
||||
fprintf(stderr, "read %d bytes: %.*s\n", len, len, buffer);
|
||||
|
||||
write(terminal->master, buffer, len);
|
||||
|
||||
close(fd);
|
||||
g_source_remove(terminal->tag);
|
||||
|
||||
g_io_channel_unref(source);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int
|
||||
handle_bound_key(struct terminal *terminal,
|
||||
struct input *input, uint32_t sym, uint32_t time)
|
||||
{
|
||||
struct wl_shell *shell;
|
||||
GIOChannel *channel;
|
||||
int fd;
|
||||
|
||||
switch (sym) {
|
||||
case XK_C:
|
||||
shell = display_get_shell(terminal->display);
|
||||
terminal->selection = wl_shell_create_selection(shell);
|
||||
wl_selection_add_listener(terminal->selection,
|
||||
&selection_listener, terminal);
|
||||
wl_selection_offer(terminal->selection, "text/plain");
|
||||
wl_selection_activate(terminal->selection,
|
||||
input_get_input_device(input), time);
|
||||
|
||||
return 1;
|
||||
case XK_V:
|
||||
if (input_offers_mime_type(input, "text/plain")) {
|
||||
fd = input_receive_mime_type(input, "text/plain");
|
||||
channel = g_io_channel_unix_new(fd);
|
||||
terminal->tag = g_io_add_watch(channel, G_IO_IN,
|
||||
selection_io_func,
|
||||
terminal);
|
||||
}
|
||||
|
||||
return 1;
|
||||
case XK_X:
|
||||
/* cut selection; terminal doesn't do cut */
|
||||
return 0;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
key_handler(struct window *window, struct input *input, uint32_t time,
|
||||
uint32_t key, uint32_t sym, uint32_t state, void *data)
|
||||
{
|
||||
struct terminal *terminal = data;
|
||||
char ch[MAX_RESPONSE];
|
||||
uint32_t modifiers;
|
||||
int len = 0;
|
||||
|
||||
modifiers = input_get_modifiers(input);
|
||||
if ((modifiers & XKB_COMMON_CONTROL_MASK) &&
|
||||
(modifiers & XKB_COMMON_SHIFT_MASK) &&
|
||||
state && handle_bound_key(terminal, input, sym, 0))
|
||||
return;
|
||||
|
||||
switch (sym) {
|
||||
case XK_F11:
|
||||
if (!state)
|
||||
|
|
@ -2034,7 +2181,7 @@ key_handler(struct window *window, uint32_t key, uint32_t sym,
|
|||
len = apply_key_map(terminal->key_mode, sym, modifiers, ch);
|
||||
if (len != 0) break;
|
||||
|
||||
if (modifiers & WINDOW_MODIFIER_CONTROL) {
|
||||
if (modifiers & XKB_COMMON_CONTROL_MASK) {
|
||||
if (sym >= '3' && sym <= '7')
|
||||
sym = (sym & 0x1f) + 8;
|
||||
|
||||
|
|
@ -2045,10 +2192,10 @@ key_handler(struct window *window, uint32_t key, uint32_t sym,
|
|||
else if (sym == '/') sym = 0x1F;
|
||||
else if (sym == '8' || sym == '?') sym = 0x7F;
|
||||
} else if ((terminal->mode & MODE_ALT_SENDS_ESC) &&
|
||||
(modifiers & WINDOW_MODIFIER_ALT))
|
||||
(modifiers & XKB_COMMON_MOD1_MASK))
|
||||
{
|
||||
ch[len++] = 0x1b;
|
||||
} else if (modifiers & WINDOW_MODIFIER_ALT) {
|
||||
} else if (modifiers & XKB_COMMON_MOD1_MASK) {
|
||||
sym = sym | 0x80;
|
||||
}
|
||||
|
||||
|
|
@ -2071,6 +2218,50 @@ keyboard_focus_handler(struct window *window,
|
|||
window_schedule_redraw(terminal->window);
|
||||
}
|
||||
|
||||
static void
|
||||
button_handler(struct window *window,
|
||||
struct input *input, uint32_t time,
|
||||
int button, int state, void *data)
|
||||
{
|
||||
struct terminal *terminal = data;
|
||||
|
||||
switch (button) {
|
||||
case 272:
|
||||
if (state) {
|
||||
terminal->dragging = 1;
|
||||
terminal->selection_active = 0;
|
||||
input_get_position(input,
|
||||
&terminal->selection_start_x,
|
||||
&terminal->selection_start_y);
|
||||
terminal->selection_end_x = terminal->selection_start_x;
|
||||
terminal->selection_end_y = terminal->selection_start_y;
|
||||
window_schedule_redraw(window);
|
||||
} else {
|
||||
terminal->dragging = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
motion_handler(struct window *window,
|
||||
struct input *input, uint32_t time,
|
||||
int32_t x, int32_t y,
|
||||
int32_t sx, int32_t sy, void *data)
|
||||
{
|
||||
struct terminal *terminal = data;
|
||||
|
||||
if (terminal->dragging) {
|
||||
terminal->selection_active = 1;
|
||||
input_get_position(input,
|
||||
&terminal->selection_end_x,
|
||||
&terminal->selection_end_y);
|
||||
window_schedule_redraw(window);
|
||||
}
|
||||
|
||||
return POINTER_IBEAM;
|
||||
}
|
||||
|
||||
static struct terminal *
|
||||
terminal_create(struct display *display, int fullscreen)
|
||||
{
|
||||
|
|
@ -2105,6 +2296,8 @@ terminal_create(struct display *display, int fullscreen)
|
|||
window_set_key_handler(terminal->window, key_handler);
|
||||
window_set_keyboard_focus_handler(terminal->window,
|
||||
keyboard_focus_handler);
|
||||
window_set_button_handler(terminal->window, button_handler);
|
||||
window_set_motion_handler(terminal->window, motion_handler);
|
||||
|
||||
surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 0, 0);
|
||||
cr = cairo_create(surface);
|
||||
|
|
|
|||
|
|
@ -110,8 +110,8 @@ redraw_handler(struct window *window, void *data)
|
|||
}
|
||||
|
||||
static void
|
||||
key_handler(struct window *window, uint32_t key, uint32_t unicode,
|
||||
uint32_t state, uint32_t modifiers, void *data)
|
||||
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;
|
||||
|
||||
|
|
|
|||
191
clients/window.c
191
clients/window.c
|
|
@ -43,7 +43,7 @@
|
|||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
|
||||
#ifdef HAVE_CAIRO_GL
|
||||
#ifdef HAVE_CAIRO_EGL
|
||||
#include <cairo-gl.h>
|
||||
#endif
|
||||
|
||||
|
|
@ -79,7 +79,7 @@ struct display {
|
|||
struct xkb_desc *xkb;
|
||||
cairo_surface_t **pointer_surfaces;
|
||||
|
||||
display_drag_offer_handler_t drag_offer_handler;
|
||||
display_global_handler_t global_handler;
|
||||
};
|
||||
|
||||
struct window {
|
||||
|
|
@ -118,6 +118,7 @@ struct input {
|
|||
struct wl_input_device *input_device;
|
||||
struct window *pointer_focus;
|
||||
struct window *keyboard_focus;
|
||||
struct selection_offer *offer;
|
||||
uint32_t current_pointer_image;
|
||||
uint32_t modifiers;
|
||||
int32_t x, y, sx, sy;
|
||||
|
|
@ -181,7 +182,7 @@ struct surface_data {
|
|||
#define MULT(_d,c,a,t) \
|
||||
do { t = c * a + 0x7f; _d = ((t >> 8) + t) >> 8; } while (0)
|
||||
|
||||
#ifdef HAVE_CAIRO_GL
|
||||
#ifdef HAVE_CAIRO_EGL
|
||||
|
||||
struct drm_surface_data {
|
||||
struct surface_data data;
|
||||
|
|
@ -469,7 +470,7 @@ cairo_surface_t *
|
|||
display_create_surface(struct display *display,
|
||||
struct rectangle *rectangle)
|
||||
{
|
||||
#ifdef HAVE_CAIRO_GL
|
||||
#ifdef HAVE_CAIRO_EGL
|
||||
if (display->drm) {
|
||||
return display_create_drm_surface(display, rectangle);
|
||||
}
|
||||
|
|
@ -482,7 +483,7 @@ display_create_surface_from_file(struct display *display,
|
|||
const char *filename,
|
||||
struct rectangle *rectangle)
|
||||
{
|
||||
#ifdef HAVE_CAIRO_GL
|
||||
#ifdef HAVE_CAIRO_EGL
|
||||
if (display->drm) {
|
||||
return display_create_drm_surface_from_file(display, filename, rectangle);
|
||||
}
|
||||
|
|
@ -536,7 +537,7 @@ display_get_pointer_surface(struct display *display, int pointer,
|
|||
cairo_surface_t *surface;
|
||||
|
||||
surface = display->pointer_surfaces[pointer];
|
||||
#if HAVE_CAIRO_GL
|
||||
#if HAVE_CAIRO_EGL
|
||||
*width = cairo_gl_surface_get_width(surface);
|
||||
*height = cairo_gl_surface_get_height(surface);
|
||||
#else
|
||||
|
|
@ -630,7 +631,7 @@ window_create_surface(struct window *window)
|
|||
cairo_surface_t *surface;
|
||||
|
||||
switch (window->buffer_type) {
|
||||
#ifdef HAVE_CAIRO_GL
|
||||
#ifdef HAVE_CAIRO_EGL
|
||||
case WINDOW_BUFFER_TYPE_DRM:
|
||||
surface = display_create_surface(window->display,
|
||||
&window->allocation);
|
||||
|
|
@ -910,7 +911,7 @@ window_handle_key(void *data, struct wl_input_device *input_device,
|
|||
return;
|
||||
|
||||
level = 0;
|
||||
if (input->modifiers & WINDOW_MODIFIER_SHIFT &&
|
||||
if (input->modifiers & XKB_COMMON_SHIFT_MASK &&
|
||||
XkbKeyGroupWidth(d->xkb, code, 0) > 1)
|
||||
level = 1;
|
||||
|
||||
|
|
@ -922,8 +923,8 @@ window_handle_key(void *data, struct wl_input_device *input_device,
|
|||
input->modifiers &= ~d->xkb->map->modmap[code];
|
||||
|
||||
if (window->key_handler)
|
||||
(*window->key_handler)(window, key, sym, state,
|
||||
input->modifiers, window->user_data);
|
||||
(*window->key_handler)(window, input, time, key, sym, state,
|
||||
window->user_data);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -940,6 +941,11 @@ window_handle_pointer_focus(void *data,
|
|||
input->pointer_focus = wl_surface_get_user_data(surface);
|
||||
window = input->pointer_focus;
|
||||
|
||||
input->x = x;
|
||||
input->y = y;
|
||||
input->sx = sx;
|
||||
input->sy = sy;
|
||||
|
||||
pointer = POINTER_LEFT_PTR;
|
||||
if (window->motion_handler)
|
||||
pointer = (*window->motion_handler)(window,
|
||||
|
|
@ -1014,6 +1020,12 @@ input_get_input_device(struct input *input)
|
|||
return input->input_device;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
input_get_modifiers(struct input *input)
|
||||
{
|
||||
return input->modifiers;
|
||||
}
|
||||
|
||||
struct wl_drag *
|
||||
window_create_drag(struct window *window)
|
||||
{
|
||||
|
|
@ -1090,30 +1102,6 @@ window_set_child_size(struct window *window, int32_t width, int32_t height)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
window_copy_image(struct window *window,
|
||||
struct rectangle *rectangle, EGLImageKHR image)
|
||||
{
|
||||
/* set image as read buffer, copy pixels or something... */
|
||||
}
|
||||
|
||||
void
|
||||
window_copy_surface(struct window *window,
|
||||
struct rectangle *rectangle,
|
||||
cairo_surface_t *surface)
|
||||
{
|
||||
cairo_t *cr;
|
||||
|
||||
cr = cairo_create (window->cairo_surface);
|
||||
|
||||
cairo_set_source_surface (cr,
|
||||
surface,
|
||||
rectangle->x, rectangle->y);
|
||||
|
||||
cairo_paint (cr);
|
||||
cairo_destroy (cr);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
idle_redraw(void *data)
|
||||
{
|
||||
|
|
@ -1324,12 +1312,122 @@ display_add_input(struct display *d, uint32_t id)
|
|||
wl_input_device_set_user_data(input->input_device, input);
|
||||
}
|
||||
|
||||
struct selection_offer {
|
||||
struct display *display;
|
||||
struct wl_selection_offer *offer;
|
||||
struct wl_array types;
|
||||
struct input *input;
|
||||
};
|
||||
|
||||
int
|
||||
input_offers_mime_type(struct input *input, const char *type)
|
||||
{
|
||||
struct selection_offer *offer = input->offer;
|
||||
char **p, **end;
|
||||
|
||||
if (offer == NULL)
|
||||
return 0;
|
||||
|
||||
end = offer->types.data + offer->types.size;
|
||||
for (p = offer->types.data; p < end; p++)
|
||||
if (strcmp(*p, type) == 0)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
input_receive_mime_type(struct input *input, const char *type)
|
||||
{
|
||||
struct selection_offer *offer = input->offer;
|
||||
int p[2];
|
||||
|
||||
pipe(p);
|
||||
/* FIXME: A number of things can go wrong here: the object may
|
||||
* not be the current selection offer any more (which could
|
||||
* still work, but the source may have gone away or just
|
||||
* destroyed its wl_selection) or the offer may not have the
|
||||
* requested type after all (programmer/client error,
|
||||
* typically) */
|
||||
wl_selection_offer_receive(offer->offer, type, p[1]);
|
||||
close(p[1]);
|
||||
|
||||
return p[0];
|
||||
}
|
||||
|
||||
static void
|
||||
selection_offer_offer(void *data,
|
||||
struct wl_selection_offer *selection_offer,
|
||||
const char *type)
|
||||
{
|
||||
struct selection_offer *offer = data;
|
||||
|
||||
char **p;
|
||||
|
||||
p = wl_array_add(&offer->types, sizeof *p);
|
||||
if (p)
|
||||
*p = strdup(type);
|
||||
};
|
||||
|
||||
static void
|
||||
selection_offer_keyboard_focus(void *data,
|
||||
struct wl_selection_offer *selection_offer,
|
||||
struct wl_input_device *input_device)
|
||||
{
|
||||
struct selection_offer *offer = data;
|
||||
struct input *input;
|
||||
char **p, **end;
|
||||
|
||||
if (input_device == NULL) {
|
||||
printf("selection offer retracted %p\n", selection_offer);
|
||||
input = offer->input;
|
||||
input->offer = NULL;
|
||||
wl_selection_offer_destroy(selection_offer);
|
||||
wl_array_release(&offer->types);
|
||||
free(offer);
|
||||
return;
|
||||
}
|
||||
|
||||
input = wl_input_device_get_user_data(input_device);
|
||||
printf("new selection offer %p:", selection_offer);
|
||||
|
||||
offer->input = input;
|
||||
input->offer = offer;
|
||||
end = offer->types.data + offer->types.size;
|
||||
for (p = offer->types.data; p < end; p++)
|
||||
printf(" %s", *p);
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
struct wl_selection_offer_listener selection_offer_listener = {
|
||||
selection_offer_offer,
|
||||
selection_offer_keyboard_focus
|
||||
};
|
||||
|
||||
static void
|
||||
add_selection_offer(struct display *d, uint32_t id)
|
||||
{
|
||||
struct selection_offer *offer;
|
||||
|
||||
offer = malloc(sizeof *offer);
|
||||
if (offer == NULL)
|
||||
return;
|
||||
|
||||
offer->offer = wl_selection_offer_create(d->display, id);
|
||||
offer->display = d;
|
||||
wl_array_init(&offer->types);
|
||||
offer->input = NULL;
|
||||
|
||||
wl_selection_offer_add_listener(offer->offer,
|
||||
&selection_offer_listener, offer);
|
||||
}
|
||||
|
||||
static void
|
||||
display_handle_global(struct wl_display *display, uint32_t id,
|
||||
const char *interface, uint32_t version, void *data)
|
||||
{
|
||||
struct display *d = data;
|
||||
struct wl_drag_offer *offer;
|
||||
|
||||
if (strcmp(interface, "compositor") == 0) {
|
||||
d->compositor = wl_compositor_create(display, id);
|
||||
|
|
@ -1346,11 +1444,10 @@ display_handle_global(struct wl_display *display, uint32_t id,
|
|||
wl_drm_add_listener(d->drm, &drm_listener, d);
|
||||
} else if (strcmp(interface, "shm") == 0) {
|
||||
d->shm = wl_shm_create(display, id);
|
||||
} else if (strcmp(interface, "drag_offer") == 0) {
|
||||
if (d->drag_offer_handler) {
|
||||
offer = wl_drag_offer_create(display, id);
|
||||
d->drag_offer_handler(offer, d);
|
||||
}
|
||||
} else if (strcmp(interface, "selection_offer") == 0) {
|
||||
add_selection_offer(d, id);
|
||||
} else if (d->global_handler) {
|
||||
d->global_handler(d, interface, id, version);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1452,7 +1549,7 @@ init_drm(struct display *d)
|
|||
return -1;
|
||||
}
|
||||
|
||||
#ifdef HAVE_CAIRO_GL
|
||||
#ifdef HAVE_CAIRO_EGL
|
||||
d->device = cairo_egl_device_create(d->dpy, d->ctx);
|
||||
if (d->device == NULL) {
|
||||
fprintf(stderr, "failed to get cairo drm device\n");
|
||||
|
|
@ -1545,6 +1642,12 @@ display_get_egl_display(struct display *d)
|
|||
return d->dpy;
|
||||
}
|
||||
|
||||
struct wl_shell *
|
||||
display_get_shell(struct display *display)
|
||||
{
|
||||
return display->shell;
|
||||
}
|
||||
|
||||
void
|
||||
display_run(struct display *d)
|
||||
{
|
||||
|
|
@ -1552,8 +1655,8 @@ display_run(struct display *d)
|
|||
}
|
||||
|
||||
void
|
||||
display_set_drag_offer_handler(struct display *display,
|
||||
display_drag_offer_handler_t handler)
|
||||
display_set_global_handler(struct display *display,
|
||||
display_global_handler_t handler)
|
||||
{
|
||||
display->drag_offer_handler = handler;
|
||||
display->global_handler = handler;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
#ifndef _WINDOW_H_
|
||||
#define _WINDOW_H_
|
||||
|
||||
#include <X11/extensions/XKBcommon.h>
|
||||
#include <glib.h>
|
||||
#include <wayland-client.h>
|
||||
|
||||
|
|
@ -47,11 +48,14 @@ 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_GL
|
||||
#ifdef HAVE_CAIRO_EGL
|
||||
EGLImageKHR
|
||||
display_get_image_for_drm_surface(struct display *display,
|
||||
cairo_surface_t *surface);
|
||||
|
|
@ -82,14 +86,6 @@ display_flush_cairo_device(struct display *display);
|
|||
void
|
||||
display_run(struct display *d);
|
||||
|
||||
enum {
|
||||
WINDOW_MODIFIER_SHIFT = 0x01,
|
||||
WINDOW_MODIFIER_LOCK = 0x02,
|
||||
WINDOW_MODIFIER_CONTROL = 0x04,
|
||||
WINDOW_MODIFIER_ALT = 0x08,
|
||||
WINDOW_MODIFIER_MOD2 = 0x10,
|
||||
};
|
||||
|
||||
enum pointer_type {
|
||||
POINTER_BOTTOM_LEFT,
|
||||
POINTER_BOTTOM_RIGHT,
|
||||
|
|
@ -110,8 +106,9 @@ typedef void (*window_resize_handler_t)(struct window *window,
|
|||
void *data);
|
||||
typedef void (*window_redraw_handler_t)(struct window *window, void *data);
|
||||
typedef void (*window_frame_handler_t)(struct window *window, uint32_t frame, uint32_t timestamp, void *data);
|
||||
typedef void (*window_key_handler_t)(struct window *window, uint32_t key, uint32_t unicode,
|
||||
uint32_t state, uint32_t modifiers, 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);
|
||||
|
||||
|
|
@ -124,8 +121,10 @@ typedef int (*window_motion_handler_t)(struct window *window,
|
|||
int32_t x, int32_t y,
|
||||
int32_t sx, int32_t sy, void *data);
|
||||
|
||||
typedef void (*display_drag_offer_handler_t)(struct wl_drag_offer *offer,
|
||||
struct display *display);
|
||||
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, const char *title,
|
||||
|
|
@ -143,10 +142,6 @@ window_get_child_allocation(struct window *window,
|
|||
void
|
||||
window_set_child_size(struct window *window, int32_t width, int32_t height);
|
||||
void
|
||||
window_copy_image(struct window *window,
|
||||
struct rectangle *rectangle,
|
||||
void *image);
|
||||
void
|
||||
window_schedule_redraw(struct window *window);
|
||||
|
||||
void
|
||||
|
|
@ -156,11 +151,6 @@ window_damage(struct window *window, int32_t x, int32_t y,
|
|||
cairo_surface_t *
|
||||
window_get_surface(struct window *window);
|
||||
|
||||
void
|
||||
window_copy_surface(struct window *window,
|
||||
struct rectangle *rectangle,
|
||||
cairo_surface_t *surface);
|
||||
|
||||
void
|
||||
window_flush(struct window *window);
|
||||
|
||||
|
|
@ -228,8 +218,8 @@ const char *
|
|||
window_get_title(struct window *window);
|
||||
|
||||
void
|
||||
display_set_drag_offer_handler(struct display *display,
|
||||
display_drag_offer_handler_t handler);
|
||||
display_set_global_handler(struct display *display,
|
||||
display_global_handler_t handler);
|
||||
|
||||
struct wl_drag *
|
||||
window_create_drag(struct window *window);
|
||||
|
|
@ -241,7 +231,16 @@ window_activate_drag(struct wl_drag *drag, struct window *window,
|
|||
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);
|
||||
int
|
||||
input_receive_mime_type(struct input *input, const char *type);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue