mirror of
				https://gitlab.freedesktop.org/wayland/wayland.git
				synced 2025-11-03 09:01:42 -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,22 +7,18 @@ noinst_PROGRAMS =				\
 | 
				
			||||||
	$(poppler_programs)			\
 | 
						$(poppler_programs)			\
 | 
				
			||||||
	dnd					\
 | 
						dnd					\
 | 
				
			||||||
	smoke					\
 | 
						smoke					\
 | 
				
			||||||
	resizor
 | 
						resizor					\
 | 
				
			||||||
 | 
						simple-client
 | 
				
			||||||
 | 
					
 | 
				
			||||||
noinst_LTLIBRARIES = libtoytoolkit.la
 | 
					noinst_LTLIBRARIES = libtoytoolkit.la
 | 
				
			||||||
 | 
					
 | 
				
			||||||
INCLUDES =					\
 | 
					AM_CFLAGS = $(GCC_CFLAGS)
 | 
				
			||||||
 | 
					AM_CPPFLAGS =					\
 | 
				
			||||||
 | 
						-DDATADIR='"$(datadir)"'		\
 | 
				
			||||||
	-I$(top_srcdir)/wayland			\
 | 
						-I$(top_srcdir)/wayland			\
 | 
				
			||||||
	-I$(top_builddir)/wayland		\
 | 
						-I$(top_builddir)/wayland		\
 | 
				
			||||||
	$(CLIENT_CFLAGS)
 | 
						$(CLIENT_CFLAGS)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
LDADD = libtoytoolkit.la				\
 | 
					 | 
				
			||||||
	$(top_builddir)/wayland/libwayland-client.la	\
 | 
					 | 
				
			||||||
	$(CLIENT_LIBS) -lrt -lm
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
AM_CFLAGS = $(GCC_CFLAGS)
 | 
					 | 
				
			||||||
AM_CPPFLAGS = -DDATADIR='"$(datadir)"'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
libtoytoolkit_la_SOURCES =			\
 | 
					libtoytoolkit_la_SOURCES =			\
 | 
				
			||||||
	window.c				\
 | 
						window.c				\
 | 
				
			||||||
	window.h				\
 | 
						window.h				\
 | 
				
			||||||
| 
						 | 
					@ -31,14 +27,38 @@ libtoytoolkit_la_SOURCES =			\
 | 
				
			||||||
	cairo-util.c				\
 | 
						cairo-util.c				\
 | 
				
			||||||
	cairo-util.h
 | 
						cairo-util.h
 | 
				
			||||||
 | 
					
 | 
				
			||||||
flower_SOURCES = flower.c
 | 
					toolkit_libs =						\
 | 
				
			||||||
smoke_SOURCES = smoke.c
 | 
						libtoytoolkit.la				\
 | 
				
			||||||
 | 
						$(top_builddir)/wayland/libwayland-client.la	\
 | 
				
			||||||
 | 
						$(CLIENT_LIBS) -lrt -lm
 | 
				
			||||||
 | 
					
 | 
				
			||||||
gears_SOURCES = gears.c
 | 
					gears_SOURCES = gears.c
 | 
				
			||||||
 | 
					gears_LDADD = $(toolkit_libs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					flower_SOURCES = flower.c
 | 
				
			||||||
 | 
					flower_LDADD = $(toolkit_libs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
screenshot_SOURCES = screenshot.c screenshooter-protocol.c
 | 
					screenshot_SOURCES = screenshot.c screenshooter-protocol.c
 | 
				
			||||||
 | 
					screenshot_LDADD = $(toolkit_libs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
terminal_SOURCES = terminal.c
 | 
					terminal_SOURCES = terminal.c
 | 
				
			||||||
 | 
					terminal_LDADD = $(toolkit_libs) -lutil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
image_SOURCES = image.c
 | 
					image_SOURCES = image.c
 | 
				
			||||||
 | 
					image_LDADD = $(toolkit_libs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
dnd_SOURCES = dnd.c
 | 
					dnd_SOURCES = dnd.c
 | 
				
			||||||
 | 
					dnd_LDADD = $(toolkit_libs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					smoke_SOURCES = smoke.c
 | 
				
			||||||
 | 
					smoke_LDADD = $(toolkit_libs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
resizor_SOURCES = resizor.c
 | 
					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 =					\
 | 
					BUILT_SOURCES =					\
 | 
				
			||||||
	screenshooter-client-protocol.h		\
 | 
						screenshooter-client-protocol.h		\
 | 
				
			||||||
| 
						 | 
					@ -48,11 +68,9 @@ CLEANFILES = $(BUILT_SOURCES)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
include $(top_srcdir)/wayland/scanner.mk
 | 
					include $(top_srcdir)/wayland/scanner.mk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
terminal_LDADD = $(LDADD) -lutil
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
if HAVE_POPPLER
 | 
					if HAVE_POPPLER
 | 
				
			||||||
poppler_programs = view
 | 
					poppler_programs = view
 | 
				
			||||||
view_SOURCES = view.c
 | 
					view_SOURCES = view.c
 | 
				
			||||||
view_LDADD = $(LDADD) $(POPPLER_LIBS)
 | 
					view_LDADD = $(toolkit_libs) $(POPPLER_LIBS)
 | 
				
			||||||
view_CPPFLAGS = $(POPPLER_CFLAGS)
 | 
					view_CPPFLAGS = $(AM_CPPFLAGS) $(POPPLER_CFLAGS)
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -171,21 +171,20 @@ dnd_draw(struct dnd *dnd)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct rectangle allocation;
 | 
						struct rectangle allocation;
 | 
				
			||||||
	cairo_t *cr;
 | 
						cairo_t *cr;
 | 
				
			||||||
	cairo_surface_t *wsurface, *surface;
 | 
						cairo_surface_t *surface;
 | 
				
			||||||
	int i;
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	window_draw(dnd->window);
 | 
						window_draw(dnd->window);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	window_get_child_allocation(dnd->window, &allocation);
 | 
						surface = window_get_surface(dnd->window);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	wsurface = window_get_surface(dnd->window);
 | 
					 | 
				
			||||||
	surface = cairo_surface_create_similar(wsurface,
 | 
					 | 
				
			||||||
					       CAIRO_CONTENT_COLOR_ALPHA,
 | 
					 | 
				
			||||||
					       allocation.width,
 | 
					 | 
				
			||||||
					       allocation.height);
 | 
					 | 
				
			||||||
	cairo_surface_destroy(wsurface);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	cr = cairo_create(surface);
 | 
						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_operator(cr, CAIRO_OPERATOR_SOURCE);
 | 
				
			||||||
	cairo_set_source_rgba(cr, 0, 0, 0, 0.8);
 | 
						cairo_set_source_rgba(cr, 0, 0, 0, 0.8);
 | 
				
			||||||
	cairo_paint(cr);
 | 
						cairo_paint(cr);
 | 
				
			||||||
| 
						 | 
					@ -199,9 +198,9 @@ dnd_draw(struct dnd *dnd)
 | 
				
			||||||
		cairo_paint(cr);
 | 
							cairo_paint(cr);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cairo_pop_group_to_source(cr);
 | 
				
			||||||
 | 
						cairo_paint(cr);
 | 
				
			||||||
	cairo_destroy(cr);
 | 
						cairo_destroy(cr);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	window_copy_surface(dnd->window, &allocation, surface);
 | 
					 | 
				
			||||||
	cairo_surface_destroy(surface);
 | 
						cairo_surface_destroy(surface);
 | 
				
			||||||
	window_flush(dnd->window);
 | 
						window_flush(dnd->window);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -487,10 +486,17 @@ static const struct wl_drag_offer_listener drag_offer_listener = {
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					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;
 | 
						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);
 | 
						dnd_offer = malloc(sizeof *dnd_offer);
 | 
				
			||||||
	if (dnd_offer == NULL)
 | 
						if (dnd_offer == NULL)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
| 
						 | 
					@ -681,7 +687,7 @@ main(int argc, char *argv[])
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	display_set_drag_offer_handler(d, drag_offer_handler);
 | 
						display_set_global_handler(d, global_handler);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dnd = dnd_create (d);
 | 
						dnd = dnd_create (d);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -212,7 +212,7 @@ allocate_buffer(struct gears *gears)
 | 
				
			||||||
	window_draw(gears->window);
 | 
						window_draw(gears->window);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	gears->surface[gears->current] = window_get_surface(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,
 | 
						image = display_get_image_for_drm_surface(gears->display,
 | 
				
			||||||
						  gears->surface[gears->current]);
 | 
											  gears->surface[gears->current]);
 | 
				
			||||||
#else /* XXX: hack to make Wayland compile, even if this example doesn't run */
 | 
					#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;
 | 
						struct rectangle allocation;
 | 
				
			||||||
	GdkPixbuf *pb;
 | 
						GdkPixbuf *pb;
 | 
				
			||||||
	cairo_t *cr;
 | 
						cairo_t *cr;
 | 
				
			||||||
	cairo_surface_t *wsurface, *surface;
 | 
						cairo_surface_t *surface;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	window_draw(image->window);
 | 
						window_draw(image->window);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -153,14 +153,15 @@ image_draw(struct image *image)
 | 
				
			||||||
	if (pb == NULL)
 | 
						if (pb == NULL)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wsurface = window_get_surface(image->window);
 | 
						surface = window_get_surface(image->window);
 | 
				
			||||||
	surface = cairo_surface_create_similar(wsurface,
 | 
					 | 
				
			||||||
					       CAIRO_CONTENT_COLOR_ALPHA,
 | 
					 | 
				
			||||||
					       allocation.width,
 | 
					 | 
				
			||||||
					       allocation.height);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	cairo_surface_destroy(wsurface);
 | 
					 | 
				
			||||||
	cr = cairo_create(surface);
 | 
						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_operator(cr, CAIRO_OPERATOR_SOURCE);
 | 
				
			||||||
	cairo_set_source_rgba(cr, 0, 0, 0, 1);
 | 
						cairo_set_source_rgba(cr, 0, 0, 0, 1);
 | 
				
			||||||
	cairo_paint(cr);
 | 
						cairo_paint(cr);
 | 
				
			||||||
| 
						 | 
					@ -169,11 +170,13 @@ image_draw(struct image *image)
 | 
				
			||||||
			  allocation.width, allocation.height);
 | 
								  allocation.width, allocation.height);
 | 
				
			||||||
	cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
 | 
						cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
 | 
				
			||||||
	cairo_paint(cr);
 | 
						cairo_paint(cr);
 | 
				
			||||||
	cairo_destroy(cr);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	g_object_unref(pb);
 | 
						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);
 | 
						window_flush(image->window);
 | 
				
			||||||
	cairo_surface_destroy(surface);
 | 
						cairo_surface_destroy(surface);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -128,8 +128,8 @@ keyboard_focus_handler(struct window *window,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
key_handler(struct window *window, uint32_t key, uint32_t sym,
 | 
					key_handler(struct window *window, struct input *input, uint32_t time,
 | 
				
			||||||
	    uint32_t state, uint32_t modifiers, void *data)
 | 
						    uint32_t key, uint32_t sym, uint32_t state, void *data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct resizor *resizor = 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 mod_num = 0;
 | 
				
			||||||
	int len;
 | 
						int len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (modifiers & WINDOW_MODIFIER_SHIFT) mod_num   |= 1;
 | 
						if (modifiers & XKB_COMMON_SHIFT_MASK) mod_num   |= 1;
 | 
				
			||||||
	if (modifiers & WINDOW_MODIFIER_ALT) mod_num     |= 2;
 | 
						if (modifiers & XKB_COMMON_MOD1_MASK) mod_num    |= 2;
 | 
				
			||||||
	if (modifiers & WINDOW_MODIFIER_CONTROL) mod_num |= 4;
 | 
						if (modifiers & XKB_COMMON_CONTROL_MASK) mod_num |= 4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (mod_num != 0)
 | 
						if (mod_num != 0)
 | 
				
			||||||
		len = snprintf(response, MAX_RESPONSE, "\e[%d;%d%c",
 | 
							len = snprintf(response, MAX_RESPONSE, "\e[%d;%d%c",
 | 
				
			||||||
| 
						 | 
					@ -390,6 +390,14 @@ struct terminal {
 | 
				
			||||||
	struct terminal_color color_table[256];
 | 
						struct terminal_color color_table[256];
 | 
				
			||||||
	cairo_font_extents_t extents;
 | 
						cairo_font_extents_t extents;
 | 
				
			||||||
	cairo_scaled_font_t *font_normal, *font_bold;
 | 
						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 */
 | 
					/* Create default tab stops, every 8 characters */
 | 
				
			||||||
| 
						 | 
					@ -487,16 +495,62 @@ union decoded_attr {
 | 
				
			||||||
	uint32_t key;
 | 
						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
 | 
					static void
 | 
				
			||||||
terminal_decode_attr(struct terminal *terminal, int row, int col,
 | 
					terminal_decode_attr(struct terminal *terminal, int row, int col,
 | 
				
			||||||
		     union decoded_attr *decoded)
 | 
							     union decoded_attr *decoded)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct attr attr;
 | 
						struct attr attr;
 | 
				
			||||||
	int foreground, background, tmp;
 | 
						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 */
 | 
						/* get the attributes for this character cell */
 | 
				
			||||||
	attr = terminal_get_attr_row(terminal, row)[col];
 | 
						attr = terminal_get_attr_row(terminal, row)[col];
 | 
				
			||||||
	if ((attr.a & ATTRMASK_INVERSE) ||
 | 
						if ((attr.a & ATTRMASK_INVERSE) ||
 | 
				
			||||||
 | 
						    inverse ||
 | 
				
			||||||
	    ((terminal->mode & MODE_SHOW_CURSOR) &&
 | 
						    ((terminal->mode & MODE_SHOW_CURSOR) &&
 | 
				
			||||||
	     terminal->focused && terminal->row == row &&
 | 
						     terminal->focused && terminal->row == row &&
 | 
				
			||||||
	     terminal->column == col)) {
 | 
						     terminal->column == col)) {
 | 
				
			||||||
| 
						 | 
					@ -830,7 +884,6 @@ terminal_draw_contents(struct terminal *terminal)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct rectangle allocation;
 | 
						struct rectangle allocation;
 | 
				
			||||||
	cairo_t *cr;
 | 
						cairo_t *cr;
 | 
				
			||||||
	cairo_font_extents_t extents;
 | 
					 | 
				
			||||||
	int top_margin, side_margin;
 | 
						int top_margin, side_margin;
 | 
				
			||||||
	int row, col;
 | 
						int row, col;
 | 
				
			||||||
	union utf8_char *p_row;
 | 
						union utf8_char *p_row;
 | 
				
			||||||
| 
						 | 
					@ -839,23 +892,29 @@ terminal_draw_contents(struct terminal *terminal)
 | 
				
			||||||
	cairo_surface_t *surface;
 | 
						cairo_surface_t *surface;
 | 
				
			||||||
	double d;
 | 
						double d;
 | 
				
			||||||
	struct glyph_run run;
 | 
						struct glyph_run run;
 | 
				
			||||||
 | 
						cairo_font_extents_t extents;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						surface = window_get_surface(terminal->window);
 | 
				
			||||||
	window_get_child_allocation(terminal->window, &allocation);
 | 
						window_get_child_allocation(terminal->window, &allocation);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	surface = display_create_surface(terminal->display, &allocation);
 | 
					 | 
				
			||||||
	cr = cairo_create(surface);
 | 
						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);
 | 
						cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
 | 
				
			||||||
	terminal_set_color(terminal, cr, terminal->color_scheme->border);
 | 
						terminal_set_color(terminal, cr, terminal->color_scheme->border);
 | 
				
			||||||
	cairo_paint(cr);
 | 
						cairo_paint(cr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cairo_set_scaled_font(cr, terminal->font_normal);
 | 
						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;
 | 
						side_margin = (allocation.width - terminal->width * extents.max_x_advance) / 2;
 | 
				
			||||||
	top_margin = (allocation.height - terminal->height * extents.height) / 2;
 | 
						top_margin = (allocation.height - terminal->height * extents.height) / 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cairo_set_line_width(cr, 1.0);
 | 
						cairo_set_line_width(cr, 1.0);
 | 
				
			||||||
 | 
						cairo_translate(cr, allocation.x + side_margin,
 | 
				
			||||||
 | 
								allocation.y + top_margin);
 | 
				
			||||||
	/* paint the background */
 | 
						/* paint the background */
 | 
				
			||||||
	for (row = 0; row < terminal->height; row++) {
 | 
						for (row = 0; row < terminal->height; row++) {
 | 
				
			||||||
		for (col = 0; col < terminal->width; col++) {
 | 
							for (col = 0; col < terminal->width; col++) {
 | 
				
			||||||
| 
						 | 
					@ -866,8 +925,8 @@ terminal_draw_contents(struct terminal *terminal)
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			terminal_set_color(terminal, cr, attr.attr.bg);
 | 
								terminal_set_color(terminal, cr, attr.attr.bg);
 | 
				
			||||||
			cairo_move_to(cr, side_margin + (col * extents.max_x_advance),
 | 
								cairo_move_to(cr, col * extents.max_x_advance,
 | 
				
			||||||
			      top_margin + (row * extents.height));
 | 
									      row * extents.height);
 | 
				
			||||||
			cairo_rel_line_to(cr, extents.max_x_advance, 0);
 | 
								cairo_rel_line_to(cr, extents.max_x_advance, 0);
 | 
				
			||||||
			cairo_rel_line_to(cr, 0, extents.height);
 | 
								cairo_rel_line_to(cr, 0, extents.height);
 | 
				
			||||||
			cairo_rel_line_to(cr, -extents.max_x_advance, 0);
 | 
								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);
 | 
								glyph_run_flush(&run, attr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			text_x = side_margin + col * extents.max_x_advance;
 | 
								text_x = col * extents.max_x_advance;
 | 
				
			||||||
			text_y = top_margin + extents.ascent + row * extents.height;
 | 
								text_y = extents.ascent + row * extents.height;
 | 
				
			||||||
			if (attr.attr.a & ATTRMASK_UNDERLINE) {
 | 
								if (attr.attr.a & ATTRMASK_UNDERLINE) {
 | 
				
			||||||
				terminal_set_color(terminal, cr, attr.attr.fg);
 | 
									terminal_set_color(terminal, cr, attr.attr.fg);
 | 
				
			||||||
				cairo_move_to(cr, text_x, (double)text_y + 1.5);
 | 
									cairo_move_to(cr, text_x, (double)text_y + 1.5);
 | 
				
			||||||
| 
						 | 
					@ -908,8 +967,8 @@ terminal_draw_contents(struct terminal *terminal)
 | 
				
			||||||
		d = 0.5;
 | 
							d = 0.5;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		cairo_set_line_width(cr, 1);
 | 
							cairo_set_line_width(cr, 1);
 | 
				
			||||||
		cairo_move_to(cr, side_margin + terminal->column * extents.max_x_advance + d,
 | 
							cairo_move_to(cr, terminal->column * extents.max_x_advance + d,
 | 
				
			||||||
			      top_margin + terminal->row * extents.height + d);
 | 
								      terminal->row * extents.height + d);
 | 
				
			||||||
		cairo_rel_line_to(cr, extents.max_x_advance - 2 * d, 0);
 | 
							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, 0, extents.height - 2 * d);
 | 
				
			||||||
		cairo_rel_line_to(cr, -extents.max_x_advance + 2 * d, 0);
 | 
							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_stroke(cr);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cairo_pop_group_to_source(cr);
 | 
				
			||||||
 | 
						cairo_paint(cr);
 | 
				
			||||||
	cairo_destroy(cr);
 | 
						cairo_destroy(cr);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	window_copy_surface(terminal->window, &allocation, surface);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	cairo_surface_destroy(surface);
 | 
						cairo_surface_destroy(surface);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1936,13 +1994,102 @@ terminal_data(struct terminal *terminal, const char *data, size_t length)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
key_handler(struct window *window, uint32_t key, uint32_t sym,
 | 
					selection_listener_send(void *data, struct wl_selection *selection,
 | 
				
			||||||
	    uint32_t state, uint32_t modifiers, void *data)
 | 
								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;
 | 
						struct terminal *terminal = data;
 | 
				
			||||||
	char ch[MAX_RESPONSE];
 | 
						char ch[MAX_RESPONSE];
 | 
				
			||||||
 | 
						uint32_t modifiers;
 | 
				
			||||||
	int len = 0;
 | 
						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) {
 | 
						switch (sym) {
 | 
				
			||||||
	case XK_F11:
 | 
						case XK_F11:
 | 
				
			||||||
		if (!state)
 | 
							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);
 | 
							len = apply_key_map(terminal->key_mode, sym, modifiers, ch);
 | 
				
			||||||
		if (len != 0) break;
 | 
							if (len != 0) break;
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		if (modifiers & WINDOW_MODIFIER_CONTROL) {
 | 
							if (modifiers & XKB_COMMON_CONTROL_MASK) {
 | 
				
			||||||
			if (sym >= '3' && sym <= '7')
 | 
								if (sym >= '3' && sym <= '7')
 | 
				
			||||||
				sym = (sym & 0x1f) + 8;
 | 
									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 == '/') sym = 0x1F;
 | 
				
			||||||
			else if (sym == '8' || sym == '?') sym = 0x7F;
 | 
								else if (sym == '8' || sym == '?') sym = 0x7F;
 | 
				
			||||||
		} else if ((terminal->mode & MODE_ALT_SENDS_ESC) && 
 | 
							} else if ((terminal->mode & MODE_ALT_SENDS_ESC) && 
 | 
				
			||||||
			(modifiers & WINDOW_MODIFIER_ALT))
 | 
								   (modifiers & XKB_COMMON_MOD1_MASK))
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			ch[len++] = 0x1b;
 | 
								ch[len++] = 0x1b;
 | 
				
			||||||
		} else if (modifiers & WINDOW_MODIFIER_ALT) {
 | 
							} else if (modifiers & XKB_COMMON_MOD1_MASK) {
 | 
				
			||||||
			sym = sym | 0x80;
 | 
								sym = sym | 0x80;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2071,6 +2218,50 @@ keyboard_focus_handler(struct window *window,
 | 
				
			||||||
	window_schedule_redraw(terminal->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 *
 | 
					static struct terminal *
 | 
				
			||||||
terminal_create(struct display *display, int fullscreen)
 | 
					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_key_handler(terminal->window, key_handler);
 | 
				
			||||||
	window_set_keyboard_focus_handler(terminal->window,
 | 
						window_set_keyboard_focus_handler(terminal->window,
 | 
				
			||||||
					  keyboard_focus_handler);
 | 
										  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);
 | 
						surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 0, 0);
 | 
				
			||||||
	cr = cairo_create(surface);
 | 
						cr = cairo_create(surface);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -110,8 +110,8 @@ redraw_handler(struct window *window, void *data)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
key_handler(struct window *window, uint32_t key, uint32_t unicode,
 | 
					key_handler(struct window *window, struct input *input, uint32_t time,
 | 
				
			||||||
	    uint32_t state, uint32_t modifiers, void *data)
 | 
						    uint32_t key, uint32_t unicode, uint32_t state, void *data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct view *view = data;
 | 
						struct view *view = data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										191
									
								
								clients/window.c
									
										
									
									
									
								
							
							
						
						
									
										191
									
								
								clients/window.c
									
										
									
									
									
								
							| 
						 | 
					@ -43,7 +43,7 @@
 | 
				
			||||||
#include <EGL/egl.h>
 | 
					#include <EGL/egl.h>
 | 
				
			||||||
#include <EGL/eglext.h>
 | 
					#include <EGL/eglext.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef HAVE_CAIRO_GL
 | 
					#ifdef HAVE_CAIRO_EGL
 | 
				
			||||||
#include <cairo-gl.h>
 | 
					#include <cairo-gl.h>
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -79,7 +79,7 @@ struct display {
 | 
				
			||||||
	struct xkb_desc *xkb;
 | 
						struct xkb_desc *xkb;
 | 
				
			||||||
	cairo_surface_t **pointer_surfaces;
 | 
						cairo_surface_t **pointer_surfaces;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	display_drag_offer_handler_t drag_offer_handler;
 | 
						display_global_handler_t global_handler;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct window {
 | 
					struct window {
 | 
				
			||||||
| 
						 | 
					@ -118,6 +118,7 @@ struct input {
 | 
				
			||||||
	struct wl_input_device *input_device;
 | 
						struct wl_input_device *input_device;
 | 
				
			||||||
	struct window *pointer_focus;
 | 
						struct window *pointer_focus;
 | 
				
			||||||
	struct window *keyboard_focus;
 | 
						struct window *keyboard_focus;
 | 
				
			||||||
 | 
						struct selection_offer *offer;
 | 
				
			||||||
	uint32_t current_pointer_image;
 | 
						uint32_t current_pointer_image;
 | 
				
			||||||
	uint32_t modifiers;
 | 
						uint32_t modifiers;
 | 
				
			||||||
	int32_t x, y, sx, sy;
 | 
						int32_t x, y, sx, sy;
 | 
				
			||||||
| 
						 | 
					@ -181,7 +182,7 @@ struct surface_data {
 | 
				
			||||||
#define MULT(_d,c,a,t) \
 | 
					#define MULT(_d,c,a,t) \
 | 
				
			||||||
	do { t = c * a + 0x7f; _d = ((t >> 8) + t) >> 8; } while (0)
 | 
						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 drm_surface_data {
 | 
				
			||||||
	struct surface_data data;
 | 
						struct surface_data data;
 | 
				
			||||||
| 
						 | 
					@ -469,7 +470,7 @@ cairo_surface_t *
 | 
				
			||||||
display_create_surface(struct display *display,
 | 
					display_create_surface(struct display *display,
 | 
				
			||||||
		       struct rectangle *rectangle)
 | 
							       struct rectangle *rectangle)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
#ifdef HAVE_CAIRO_GL
 | 
					#ifdef HAVE_CAIRO_EGL
 | 
				
			||||||
	if (display->drm) {
 | 
						if (display->drm) {
 | 
				
			||||||
		return display_create_drm_surface(display, rectangle);
 | 
							return display_create_drm_surface(display, rectangle);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -482,7 +483,7 @@ display_create_surface_from_file(struct display *display,
 | 
				
			||||||
				 const char *filename,
 | 
									 const char *filename,
 | 
				
			||||||
				 struct rectangle *rectangle)
 | 
									 struct rectangle *rectangle)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
#ifdef HAVE_CAIRO_GL
 | 
					#ifdef HAVE_CAIRO_EGL
 | 
				
			||||||
	if (display->drm) {
 | 
						if (display->drm) {
 | 
				
			||||||
		return display_create_drm_surface_from_file(display, filename, rectangle);
 | 
							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;
 | 
						cairo_surface_t *surface;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	surface = display->pointer_surfaces[pointer];
 | 
						surface = display->pointer_surfaces[pointer];
 | 
				
			||||||
#if HAVE_CAIRO_GL
 | 
					#if HAVE_CAIRO_EGL
 | 
				
			||||||
	*width = cairo_gl_surface_get_width(surface);
 | 
						*width = cairo_gl_surface_get_width(surface);
 | 
				
			||||||
	*height = cairo_gl_surface_get_height(surface);
 | 
						*height = cairo_gl_surface_get_height(surface);
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
| 
						 | 
					@ -630,7 +631,7 @@ window_create_surface(struct window *window)
 | 
				
			||||||
	cairo_surface_t *surface;
 | 
						cairo_surface_t *surface;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch (window->buffer_type) {
 | 
						switch (window->buffer_type) {
 | 
				
			||||||
#ifdef HAVE_CAIRO_GL
 | 
					#ifdef HAVE_CAIRO_EGL
 | 
				
			||||||
	case WINDOW_BUFFER_TYPE_DRM:
 | 
						case WINDOW_BUFFER_TYPE_DRM:
 | 
				
			||||||
		surface = display_create_surface(window->display,
 | 
							surface = display_create_surface(window->display,
 | 
				
			||||||
						 &window->allocation);
 | 
											 &window->allocation);
 | 
				
			||||||
| 
						 | 
					@ -910,7 +911,7 @@ window_handle_key(void *data, struct wl_input_device *input_device,
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	level = 0;
 | 
						level = 0;
 | 
				
			||||||
	if (input->modifiers & WINDOW_MODIFIER_SHIFT &&
 | 
						if (input->modifiers & XKB_COMMON_SHIFT_MASK &&
 | 
				
			||||||
	    XkbKeyGroupWidth(d->xkb, code, 0) > 1)
 | 
						    XkbKeyGroupWidth(d->xkb, code, 0) > 1)
 | 
				
			||||||
		level = 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];
 | 
							input->modifiers &= ~d->xkb->map->modmap[code];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (window->key_handler)
 | 
						if (window->key_handler)
 | 
				
			||||||
		(*window->key_handler)(window, key, sym, state,
 | 
							(*window->key_handler)(window, input, time, key, sym, state,
 | 
				
			||||||
				       input->modifiers, window->user_data);
 | 
									       window->user_data);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
| 
						 | 
					@ -940,6 +941,11 @@ window_handle_pointer_focus(void *data,
 | 
				
			||||||
		input->pointer_focus = wl_surface_get_user_data(surface);
 | 
							input->pointer_focus = wl_surface_get_user_data(surface);
 | 
				
			||||||
		window = input->pointer_focus;
 | 
							window = input->pointer_focus;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							input->x = x;
 | 
				
			||||||
 | 
							input->y = y;
 | 
				
			||||||
 | 
							input->sx = sx;
 | 
				
			||||||
 | 
							input->sy = sy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		pointer = POINTER_LEFT_PTR;
 | 
							pointer = POINTER_LEFT_PTR;
 | 
				
			||||||
		if (window->motion_handler)
 | 
							if (window->motion_handler)
 | 
				
			||||||
			pointer = (*window->motion_handler)(window,
 | 
								pointer = (*window->motion_handler)(window,
 | 
				
			||||||
| 
						 | 
					@ -1014,6 +1020,12 @@ input_get_input_device(struct input *input)
 | 
				
			||||||
	return input->input_device;
 | 
						return input->input_device;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint32_t
 | 
				
			||||||
 | 
					input_get_modifiers(struct input *input)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return input->modifiers;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct wl_drag *
 | 
					struct wl_drag *
 | 
				
			||||||
window_create_drag(struct window *window)
 | 
					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
 | 
					static gboolean
 | 
				
			||||||
idle_redraw(void *data)
 | 
					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);
 | 
						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
 | 
					static void
 | 
				
			||||||
display_handle_global(struct wl_display *display, uint32_t id,
 | 
					display_handle_global(struct wl_display *display, uint32_t id,
 | 
				
			||||||
		      const char *interface, uint32_t version, void *data)
 | 
							      const char *interface, uint32_t version, void *data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct display *d = data;
 | 
						struct display *d = data;
 | 
				
			||||||
	struct wl_drag_offer *offer;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (strcmp(interface, "compositor") == 0) {
 | 
						if (strcmp(interface, "compositor") == 0) {
 | 
				
			||||||
		d->compositor = wl_compositor_create(display, id);
 | 
							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);
 | 
							wl_drm_add_listener(d->drm, &drm_listener, d);
 | 
				
			||||||
	} else if (strcmp(interface, "shm") == 0) {
 | 
						} else if (strcmp(interface, "shm") == 0) {
 | 
				
			||||||
		d->shm = wl_shm_create(display, id);
 | 
							d->shm = wl_shm_create(display, id);
 | 
				
			||||||
	} else if (strcmp(interface, "drag_offer") == 0) {
 | 
						} else if (strcmp(interface, "selection_offer") == 0) {
 | 
				
			||||||
		if (d->drag_offer_handler) {
 | 
							add_selection_offer(d, id);
 | 
				
			||||||
			offer = wl_drag_offer_create(display, id);
 | 
						} else if (d->global_handler) {
 | 
				
			||||||
			d->drag_offer_handler(offer, d);
 | 
							d->global_handler(d, interface, id, version);
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1452,7 +1549,7 @@ init_drm(struct display *d)
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef HAVE_CAIRO_GL
 | 
					#ifdef HAVE_CAIRO_EGL
 | 
				
			||||||
	d->device = cairo_egl_device_create(d->dpy, d->ctx);
 | 
						d->device = cairo_egl_device_create(d->dpy, d->ctx);
 | 
				
			||||||
	if (d->device == NULL) {
 | 
						if (d->device == NULL) {
 | 
				
			||||||
		fprintf(stderr, "failed to get cairo drm device\n");
 | 
							fprintf(stderr, "failed to get cairo drm device\n");
 | 
				
			||||||
| 
						 | 
					@ -1545,6 +1642,12 @@ display_get_egl_display(struct display *d)
 | 
				
			||||||
	return d->dpy;
 | 
						return d->dpy;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wl_shell *
 | 
				
			||||||
 | 
					display_get_shell(struct display *display)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return display->shell;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
display_run(struct display *d)
 | 
					display_run(struct display *d)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -1552,8 +1655,8 @@ display_run(struct display *d)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
display_set_drag_offer_handler(struct display *display,
 | 
					display_set_global_handler(struct display *display,
 | 
				
			||||||
			       display_drag_offer_handler_t handler)
 | 
								   display_global_handler_t handler)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	display->drag_offer_handler = handler;
 | 
						display->global_handler = handler;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,6 +23,7 @@
 | 
				
			||||||
#ifndef _WINDOW_H_
 | 
					#ifndef _WINDOW_H_
 | 
				
			||||||
#define _WINDOW_H_
 | 
					#define _WINDOW_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <X11/extensions/XKBcommon.h>
 | 
				
			||||||
#include <glib.h>
 | 
					#include <glib.h>
 | 
				
			||||||
#include <wayland-client.h>
 | 
					#include <wayland-client.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -47,11 +48,14 @@ display_get_display(struct display *display);
 | 
				
			||||||
struct wl_compositor *
 | 
					struct wl_compositor *
 | 
				
			||||||
display_get_compositor(struct display *display);
 | 
					display_get_compositor(struct display *display);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wl_shell *
 | 
				
			||||||
 | 
					display_get_shell(struct display *display);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef EGL_NO_DISPLAY
 | 
					#ifdef EGL_NO_DISPLAY
 | 
				
			||||||
EGLDisplay
 | 
					EGLDisplay
 | 
				
			||||||
display_get_egl_display(struct display *d);
 | 
					display_get_egl_display(struct display *d);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef HAVE_CAIRO_GL
 | 
					#ifdef HAVE_CAIRO_EGL
 | 
				
			||||||
EGLImageKHR
 | 
					EGLImageKHR
 | 
				
			||||||
display_get_image_for_drm_surface(struct display *display,
 | 
					display_get_image_for_drm_surface(struct display *display,
 | 
				
			||||||
				  cairo_surface_t *surface);
 | 
									  cairo_surface_t *surface);
 | 
				
			||||||
| 
						 | 
					@ -82,14 +86,6 @@ display_flush_cairo_device(struct display *display);
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
display_run(struct display *d);
 | 
					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 {
 | 
					enum pointer_type {
 | 
				
			||||||
	POINTER_BOTTOM_LEFT,
 | 
						POINTER_BOTTOM_LEFT,
 | 
				
			||||||
	POINTER_BOTTOM_RIGHT,
 | 
						POINTER_BOTTOM_RIGHT,
 | 
				
			||||||
| 
						 | 
					@ -110,8 +106,9 @@ typedef void (*window_resize_handler_t)(struct window *window,
 | 
				
			||||||
					void *data);
 | 
										void *data);
 | 
				
			||||||
typedef void (*window_redraw_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_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,
 | 
					typedef void (*window_key_handler_t)(struct window *window, struct input *input,
 | 
				
			||||||
				     uint32_t state, uint32_t modifiers, void *data);
 | 
									     uint32_t time, uint32_t key, uint32_t unicode,
 | 
				
			||||||
 | 
									     uint32_t state, void *data);
 | 
				
			||||||
typedef void (*window_keyboard_focus_handler_t)(struct window *window,
 | 
					typedef void (*window_keyboard_focus_handler_t)(struct window *window,
 | 
				
			||||||
						struct input *device, void *data);
 | 
											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 x, int32_t y,
 | 
				
			||||||
				       int32_t sx, int32_t sy, void *data);
 | 
									       int32_t sx, int32_t sy, void *data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef void (*display_drag_offer_handler_t)(struct wl_drag_offer *offer,
 | 
					typedef void (*display_global_handler_t)(struct display *display,
 | 
				
			||||||
					     struct display *display);
 | 
										 const char *interface,
 | 
				
			||||||
 | 
										 uint32_t id,
 | 
				
			||||||
 | 
										 uint32_t version);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct window *
 | 
					struct window *
 | 
				
			||||||
window_create(struct display *display, const char *title,
 | 
					window_create(struct display *display, const char *title,
 | 
				
			||||||
| 
						 | 
					@ -143,10 +142,6 @@ window_get_child_allocation(struct window *window,
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
window_set_child_size(struct window *window, int32_t width, int32_t height);
 | 
					window_set_child_size(struct window *window, int32_t width, int32_t height);
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
window_copy_image(struct window *window,
 | 
					 | 
				
			||||||
		  struct rectangle *rectangle,
 | 
					 | 
				
			||||||
		  void *image);
 | 
					 | 
				
			||||||
void
 | 
					 | 
				
			||||||
window_schedule_redraw(struct window *window);
 | 
					window_schedule_redraw(struct window *window);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
| 
						 | 
					@ -156,11 +151,6 @@ window_damage(struct window *window, int32_t x, int32_t y,
 | 
				
			||||||
cairo_surface_t *
 | 
					cairo_surface_t *
 | 
				
			||||||
window_get_surface(struct window *window);
 | 
					window_get_surface(struct window *window);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					 | 
				
			||||||
window_copy_surface(struct window *window,
 | 
					 | 
				
			||||||
		    struct rectangle *rectangle,
 | 
					 | 
				
			||||||
		    cairo_surface_t *surface);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
window_flush(struct window *window);
 | 
					window_flush(struct window *window);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -228,8 +218,8 @@ const char *
 | 
				
			||||||
window_get_title(struct window *window);
 | 
					window_get_title(struct window *window);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
display_set_drag_offer_handler(struct display *display,
 | 
					display_set_global_handler(struct display *display,
 | 
				
			||||||
			       display_drag_offer_handler_t handler);
 | 
								   display_global_handler_t handler);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct wl_drag *
 | 
					struct wl_drag *
 | 
				
			||||||
window_create_drag(struct window *window);
 | 
					window_create_drag(struct window *window);
 | 
				
			||||||
| 
						 | 
					@ -241,7 +231,16 @@ window_activate_drag(struct wl_drag *drag, struct window *window,
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
input_get_position(struct input *input, int32_t *x, int32_t *y);
 | 
					input_get_position(struct input *input, int32_t *x, int32_t *y);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint32_t
 | 
				
			||||||
 | 
					input_get_modifiers(struct input *input);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct wl_input_device *
 | 
					struct wl_input_device *
 | 
				
			||||||
input_get_input_device(struct input *input);
 | 
					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
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,5 +2,6 @@ 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_MOUSE}=="1", ENV{WAYLAND_SEAT}="1"
 | 
				
			||||||
KERNEL=="event*", ENV{ID_INPUT_TOUCHPAD}=="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_TOUCHSCREEN}=="1", ENV{WAYLAND_SEAT}="1"
 | 
				
			||||||
 | 
					KERNEL=="event*", ENV{ID_INPUT_TABLET}=="1", ENV{WAYLAND_SEAT}="1"
 | 
				
			||||||
KERNEL=="card0", ENV{WAYLAND_SEAT}="1"
 | 
					KERNEL=="card0", ENV{WAYLAND_SEAT}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,17 +13,33 @@ compositor_LDADD =					\
 | 
				
			||||||
	$(top_builddir)/wayland/libwayland-client.la	\
 | 
						$(top_builddir)/wayland/libwayland-client.la	\
 | 
				
			||||||
	$(COMPOSITOR_LIBS)
 | 
						$(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_SOURCES =				\
 | 
				
			||||||
	compositor.c				\
 | 
						compositor.c				\
 | 
				
			||||||
	compositor.h				\
 | 
						compositor.h				\
 | 
				
			||||||
	compositor-drm.c			\
 | 
						shell.c					\
 | 
				
			||||||
	compositor-x11.c			\
 | 
					 | 
				
			||||||
	compositor-wayland.c			\
 | 
					 | 
				
			||||||
	screenshooter.c				\
 | 
						screenshooter.c				\
 | 
				
			||||||
	screenshooter-protocol.c		\
 | 
						screenshooter-protocol.c		\
 | 
				
			||||||
	screenshooter-server-protocol.h		\
 | 
						screenshooter-server-protocol.h		\
 | 
				
			||||||
	drm.c					\
 | 
						shm.c					\
 | 
				
			||||||
	shm.c
 | 
						$(drm_compositor_sources)		\
 | 
				
			||||||
 | 
						$(x11_compositor_sources)		\
 | 
				
			||||||
 | 
						$(wayland_compositor_sources)		\
 | 
				
			||||||
 | 
						$(drm_sources)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
udevrulesddir = $(sysconfdir)/udev/rules.d
 | 
					udevrulesddir = $(sysconfdir)/udev/rules.d
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,11 +22,6 @@
 | 
				
			||||||
#include <fcntl.h>
 | 
					#include <fcntl.h>
 | 
				
			||||||
#include <unistd.h>
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <signal.h>
 | 
					 | 
				
			||||||
#include <linux/kd.h>
 | 
					 | 
				
			||||||
#include <linux/vt.h>
 | 
					 | 
				
			||||||
#include <linux/input.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define GL_GLEXT_PROTOTYPES
 | 
					#define GL_GLEXT_PROTOTYPES
 | 
				
			||||||
#define EGL_EGLEXT_PROTOTYPES
 | 
					#define EGL_EGLEXT_PROTOTYPES
 | 
				
			||||||
#include <GLES2/gl2.h>
 | 
					#include <GLES2/gl2.h>
 | 
				
			||||||
| 
						 | 
					@ -42,14 +37,7 @@ struct drm_compositor {
 | 
				
			||||||
	struct udev *udev;
 | 
						struct udev *udev;
 | 
				
			||||||
	struct wl_event_source *drm_source;
 | 
						struct wl_event_source *drm_source;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* tty handling state */
 | 
						struct tty *tty;
 | 
				
			||||||
	int tty_fd;
 | 
					 | 
				
			||||||
	uint32_t vt_active : 1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	struct termios terminal_attributes;
 | 
					 | 
				
			||||||
	struct wl_event_source *tty_input_source;
 | 
					 | 
				
			||||||
	struct wl_event_source *enter_vt_source;
 | 
					 | 
				
			||||||
	struct wl_event_source *leave_vt_source;
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct drm_output {
 | 
					struct drm_output {
 | 
				
			||||||
| 
						 | 
					@ -64,199 +52,6 @@ struct drm_output {
 | 
				
			||||||
	uint32_t current;	
 | 
						uint32_t current;	
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct drm_input {
 | 
					 | 
				
			||||||
	struct wlsc_input_device base;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct evdev_input_device {
 | 
					 | 
				
			||||||
	struct drm_input *master;
 | 
					 | 
				
			||||||
	struct wl_event_source *source;
 | 
					 | 
				
			||||||
	int tool, new_x, new_y;
 | 
					 | 
				
			||||||
	int base_x, base_y;
 | 
					 | 
				
			||||||
	int fd;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void evdev_input_device_data(int fd, uint32_t mask, void *data)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct drm_compositor *c;
 | 
					 | 
				
			||||||
	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;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	c = (struct drm_compositor *)
 | 
					 | 
				
			||||||
		device->master->base.input_device.compositor;
 | 
					 | 
				
			||||||
	if (!c->vt_active)
 | 
					 | 
				
			||||||
		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:
 | 
					 | 
				
			||||||
		        absolute_event = 1;
 | 
					 | 
				
			||||||
			switch (e->code) {
 | 
					 | 
				
			||||||
			case ABS_X:
 | 
					 | 
				
			||||||
				if (device->new_x) {
 | 
					 | 
				
			||||||
					device->base_x = x - value;
 | 
					 | 
				
			||||||
					device->new_x = 0;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				x = device->base_x + value;
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
			case ABS_Y:
 | 
					 | 
				
			||||||
				if (device->new_y) {
 | 
					 | 
				
			||||||
					device->base_y = y - value;
 | 
					 | 
				
			||||||
					device->new_y = 0;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				y = device->base_y + value;
 | 
					 | 
				
			||||||
				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:
 | 
					 | 
				
			||||||
				if (device->tool == 0 && value) {
 | 
					 | 
				
			||||||
					device->new_x = 1;
 | 
					 | 
				
			||||||
					device->new_y = 1;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				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 && device->tool)
 | 
					 | 
				
			||||||
		notify_motion(&device->master->base.input_device, time, x, y);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static struct evdev_input_device *
 | 
					 | 
				
			||||||
evdev_input_device_create(struct drm_input *master,
 | 
					 | 
				
			||||||
			  struct wl_display *display, const char *path)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct evdev_input_device *device;
 | 
					 | 
				
			||||||
	struct wl_event_loop *loop;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	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;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	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;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void
 | 
					 | 
				
			||||||
drm_input_create(struct drm_compositor *c)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct drm_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->base);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	e = udev_enumerate_new(c->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(c->udev, path);
 | 
					 | 
				
			||||||
		evdev_input_device_create(input, c->base.wl_display,
 | 
					 | 
				
			||||||
					  udev_device_get_devnode(device));
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
        udev_enumerate_unref(e);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	c->base.input_device = &input->base.input_device;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
drm_compositor_present(struct wlsc_compositor *ec)
 | 
					drm_compositor_present(struct wlsc_compositor *ec)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -498,118 +293,6 @@ create_outputs(struct drm_compositor *ec, int option_connector)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void on_enter_vt(int signal_number, void *data)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct drm_compositor *ec = data;
 | 
					 | 
				
			||||||
	struct drm_output *output;
 | 
					 | 
				
			||||||
	int ret;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ret = drmSetMaster(ec->base.drm.fd);
 | 
					 | 
				
			||||||
	if (ret) {
 | 
					 | 
				
			||||||
		fprintf(stderr, "failed to set drm master\n");
 | 
					 | 
				
			||||||
		kill(0, SIGTERM);
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	fprintf(stderr, "enter vt\n");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ioctl(ec->tty_fd, VT_RELDISP, VT_ACKACQ);
 | 
					 | 
				
			||||||
	ret = ioctl(ec->tty_fd, KDSETMODE, KD_GRAPHICS);
 | 
					 | 
				
			||||||
	if (ret)
 | 
					 | 
				
			||||||
		fprintf(stderr, "failed to set KD_GRAPHICS mode on console: %m\n");
 | 
					 | 
				
			||||||
	ec->vt_active = 1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	wl_list_for_each(output, &ec->base.output_list, base.link) {
 | 
					 | 
				
			||||||
		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 for connector %d: %m\n",
 | 
					 | 
				
			||||||
				output->connector_id);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void on_leave_vt(int signal_number, void *data)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct drm_compositor *ec = data;
 | 
					 | 
				
			||||||
	int ret;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ret = drmDropMaster(ec->base.drm.fd);
 | 
					 | 
				
			||||||
	if (ret) {
 | 
					 | 
				
			||||||
		fprintf(stderr, "failed to drop drm master\n");
 | 
					 | 
				
			||||||
		kill(0, SIGTERM);
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ioctl (ec->tty_fd, VT_RELDISP, 1);
 | 
					 | 
				
			||||||
	ret = ioctl(ec->tty_fd, KDSETMODE, KD_TEXT);
 | 
					 | 
				
			||||||
	if (ret)
 | 
					 | 
				
			||||||
		fprintf(stderr, "failed to set KD_TEXT mode on console: %m\n");
 | 
					 | 
				
			||||||
	ec->vt_active = 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void
 | 
					 | 
				
			||||||
on_tty_input(int fd, uint32_t mask, void *data)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct drm_compositor *ec = data;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Ignore input to tty.  We get keyboard events from evdev
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	tcflush(ec->tty_fd, TCIFLUSH);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int setup_tty(struct drm_compositor *ec, struct wl_event_loop *loop)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct termios raw_attributes;
 | 
					 | 
				
			||||||
	struct vt_mode mode = { 0 };
 | 
					 | 
				
			||||||
	int ret;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ec->tty_fd = open("/dev/tty0", O_RDWR | O_NOCTTY);
 | 
					 | 
				
			||||||
	if (ec->tty_fd <= 0) {
 | 
					 | 
				
			||||||
		fprintf(stderr, "failed to open active tty: %m\n");
 | 
					 | 
				
			||||||
		return -1;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (tcgetattr(ec->tty_fd, &ec->terminal_attributes) < 0) {
 | 
					 | 
				
			||||||
		fprintf(stderr, "could not get terminal attributes: %m\n");
 | 
					 | 
				
			||||||
		return -1;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Ignore control characters and disable echo */
 | 
					 | 
				
			||||||
	raw_attributes = ec->terminal_attributes;
 | 
					 | 
				
			||||||
	cfmakeraw(&raw_attributes);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Fix up line endings to be normal (cfmakeraw hoses them) */
 | 
					 | 
				
			||||||
	raw_attributes.c_oflag |= OPOST | OCRNL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (tcsetattr(ec->tty_fd, TCSANOW, &raw_attributes) < 0)
 | 
					 | 
				
			||||||
		fprintf(stderr, "could not put terminal into raw mode: %m\n");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ec->tty_input_source =
 | 
					 | 
				
			||||||
		wl_event_loop_add_fd(loop, ec->tty_fd,
 | 
					 | 
				
			||||||
				     WL_EVENT_READABLE, on_tty_input, ec);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ret = ioctl(ec->tty_fd, KDSETMODE, KD_GRAPHICS);
 | 
					 | 
				
			||||||
	if (ret)
 | 
					 | 
				
			||||||
		fprintf(stderr, "failed to set KD_GRAPHICS mode on tty: %m\n");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ec->vt_active = 1;
 | 
					 | 
				
			||||||
	mode.mode = VT_PROCESS;
 | 
					 | 
				
			||||||
	mode.relsig = SIGUSR1;
 | 
					 | 
				
			||||||
	mode.acqsig = SIGUSR2;
 | 
					 | 
				
			||||||
	if (!ioctl(ec->tty_fd, VT_SETMODE, &mode) < 0) {
 | 
					 | 
				
			||||||
		fprintf(stderr, "failed to take control of vt handling\n");
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ec->leave_vt_source =
 | 
					 | 
				
			||||||
		wl_event_loop_add_signal(loop, SIGUSR1, on_leave_vt, ec);
 | 
					 | 
				
			||||||
	ec->enter_vt_source =
 | 
					 | 
				
			||||||
		wl_event_loop_add_signal(loop, SIGUSR2, on_enter_vt, ec);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int
 | 
					static int
 | 
				
			||||||
drm_authenticate(struct wlsc_compositor *c, uint32_t id)
 | 
					drm_authenticate(struct wlsc_compositor *c, uint32_t id)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -623,11 +306,9 @@ drm_destroy(struct wlsc_compositor *ec)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct drm_compositor *d = (struct drm_compositor *) ec;
 | 
						struct drm_compositor *d = (struct drm_compositor *) ec;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (tcsetattr(d->tty_fd, TCSANOW, &d->terminal_attributes) < 0)
 | 
						tty_destroy(d->tty);
 | 
				
			||||||
		fprintf(stderr,
 | 
					 | 
				
			||||||
			"could not restore terminal to canonical mode\n");
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	free(ec);
 | 
						free(d);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct wlsc_compositor *
 | 
					struct wlsc_compositor *
 | 
				
			||||||
| 
						 | 
					@ -674,6 +355,12 @@ drm_compositor_create(struct wl_display *display, int connector)
 | 
				
			||||||
		return NULL;
 | 
							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 */
 | 
						/* Can't init base class until we have a current egl context */
 | 
				
			||||||
	if (wlsc_compositor_init(&ec->base, display) < 0)
 | 
						if (wlsc_compositor_init(&ec->base, display) < 0)
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
| 
						 | 
					@ -683,17 +370,13 @@ drm_compositor_create(struct wl_display *display, int connector)
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	drm_input_create(ec);
 | 
						evdev_input_add_devices(&ec->base, ec->udev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	loop = wl_display_get_event_loop(ec->base.wl_display);
 | 
						loop = wl_display_get_event_loop(ec->base.wl_display);
 | 
				
			||||||
	ec->drm_source =
 | 
						ec->drm_source =
 | 
				
			||||||
		wl_event_loop_add_fd(loop, ec->base.drm.fd,
 | 
							wl_event_loop_add_fd(loop, ec->base.drm.fd,
 | 
				
			||||||
				     WL_EVENT_READABLE, on_drm_input, ec);
 | 
									     WL_EVENT_READABLE, on_drm_input, ec);
 | 
				
			||||||
	setup_tty(ec, loop);
 | 
						ec->tty = tty_create(&ec->base);
 | 
				
			||||||
	ec->base.destroy = drm_destroy;
 | 
					 | 
				
			||||||
	ec->base.authenticate = drm_authenticate;
 | 
					 | 
				
			||||||
	ec->base.present = drm_compositor_present;
 | 
					 | 
				
			||||||
	ec->base.focus = 1;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return &ec->base;
 | 
						return &ec->base;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -278,9 +278,7 @@ wayland_compositor_create_output(struct wayland_compositor *c,
 | 
				
			||||||
static struct wl_buffer *
 | 
					static struct wl_buffer *
 | 
				
			||||||
create_invisible_pointer(struct wayland_compositor *c)
 | 
					create_invisible_pointer(struct wayland_compositor *c)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct wlsc_drm_buffer *wlsc_buffer;
 | 
					 | 
				
			||||||
	struct wl_buffer *buffer;
 | 
						struct wl_buffer *buffer;
 | 
				
			||||||
	int name, stride;
 | 
					 | 
				
			||||||
	struct wl_visual *visual;
 | 
						struct wl_visual *visual;
 | 
				
			||||||
	GLuint texture;
 | 
						GLuint texture;
 | 
				
			||||||
	const int width = 1, height = 1;
 | 
						const int width = 1, height = 1;
 | 
				
			||||||
| 
						 | 
					@ -294,18 +292,8 @@ create_invisible_pointer(struct wayland_compositor *c)
 | 
				
			||||||
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 | 
						glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	visual = wl_display_get_premultiplied_argb_visual(c->parent.display);
 | 
						visual = wl_display_get_premultiplied_argb_visual(c->parent.display);
 | 
				
			||||||
	wlsc_buffer = wlsc_drm_buffer_create(&c->base, width, height, visual);
 | 
						buffer = c->base.create_buffer(&c->base, width, height, visual, data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, wlsc_buffer->image);
 | 
					 | 
				
			||||||
	glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height,
 | 
					 | 
				
			||||||
			GL_RGBA, GL_UNSIGNED_BYTE, data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	eglExportDRMImageMESA(c->base.display, wlsc_buffer->image,
 | 
					 | 
				
			||||||
			      &name, NULL, &stride);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	buffer = wl_drm_create_buffer(c->parent.drm, name,
 | 
					 | 
				
			||||||
				      width, height,
 | 
					 | 
				
			||||||
				      stride, visual);
 | 
					 | 
				
			||||||
	return buffer;
 | 
						return buffer;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -542,6 +530,11 @@ wayland_compositor_create(struct wl_display *display, int width, int height)
 | 
				
			||||||
	if (wayland_compositor_init_egl(c) < 0)
 | 
						if (wayland_compositor_init_egl(c) < 0)
 | 
				
			||||||
		return NULL;
 | 
							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 */
 | 
						/* Can't init base class until we have a current egl context */
 | 
				
			||||||
	if (wlsc_compositor_init(&c->base, display) < 0)
 | 
						if (wlsc_compositor_init(&c->base, display) < 0)
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
| 
						 | 
					@ -561,9 +554,5 @@ wayland_compositor_create(struct wl_display *display, int width, int height)
 | 
				
			||||||
	if (c->parent.wl_source == NULL)
 | 
						if (c->parent.wl_source == NULL)
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	c->base.destroy = wayland_destroy;
 | 
					 | 
				
			||||||
	c->base.authenticate = wayland_authenticate;
 | 
					 | 
				
			||||||
	c->base.present = wayland_compositor_present;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return &c->base;
 | 
						return &c->base;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -676,6 +676,11 @@ x11_compositor_create(struct wl_display *display, int width, int height)
 | 
				
			||||||
	if (x11_compositor_init_egl(c) < 0)
 | 
						if (x11_compositor_init_egl(c) < 0)
 | 
				
			||||||
		return NULL;
 | 
							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 */
 | 
						/* Can't init base class until we have a current egl context */
 | 
				
			||||||
	if (wlsc_compositor_init(&c->base, display) < 0)
 | 
						if (wlsc_compositor_init(&c->base, display) < 0)
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
| 
						 | 
					@ -693,9 +698,5 @@ x11_compositor_create(struct wl_display *display, int width, int height)
 | 
				
			||||||
				     WL_EVENT_READABLE,
 | 
									     WL_EVENT_READABLE,
 | 
				
			||||||
				     x11_compositor_handle_event, c);
 | 
									     x11_compositor_handle_event, c);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	c->base.destroy = x11_destroy;
 | 
					 | 
				
			||||||
	c->base.authenticate = x11_authenticate;
 | 
					 | 
				
			||||||
	c->base.present = x11_compositor_present;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return &c->base;
 | 
						return &c->base;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,6 +18,8 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define _GNU_SOURCE
 | 
					#define _GNU_SOURCE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "config.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <stdio.h>
 | 
					#include <stdio.h>
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
| 
						 | 
					@ -30,7 +32,7 @@
 | 
				
			||||||
#include <math.h>
 | 
					#include <math.h>
 | 
				
			||||||
#include <linux/input.h>
 | 
					#include <linux/input.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "wayland-server-protocol.h"
 | 
					#include "wayland-server.h"
 | 
				
			||||||
#include "compositor.h"
 | 
					#include "compositor.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* The plan here is to generate a random anonymous socket name and
 | 
					/* The plan here is to generate a random anonymous socket name and
 | 
				
			||||||
| 
						 | 
					@ -119,7 +121,6 @@ wlsc_matrix_transform(struct wlsc_matrix *matrix, struct wlsc_vector *v)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct wlsc_surface *
 | 
					static struct wlsc_surface *
 | 
				
			||||||
wlsc_surface_create(struct wlsc_compositor *compositor,
 | 
					wlsc_surface_create(struct wlsc_compositor *compositor,
 | 
				
			||||||
		    struct wl_visual *visual,
 | 
					 | 
				
			||||||
		    int32_t x, int32_t y, int32_t width, int32_t height)
 | 
							    int32_t x, int32_t y, int32_t width, int32_t height)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct wlsc_surface *surface;
 | 
						struct wlsc_surface *surface;
 | 
				
			||||||
| 
						 | 
					@ -140,7 +141,7 @@ wlsc_surface_create(struct wlsc_compositor *compositor,
 | 
				
			||||||
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 | 
						glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	surface->compositor = compositor;
 | 
						surface->compositor = compositor;
 | 
				
			||||||
	surface->visual = visual;
 | 
						surface->visual = NULL;
 | 
				
			||||||
	surface->x = x;
 | 
						surface->x = x;
 | 
				
			||||||
	surface->y = y;
 | 
						surface->y = y;
 | 
				
			||||||
	surface->width = width;
 | 
						surface->width = width;
 | 
				
			||||||
| 
						 | 
					@ -156,7 +157,7 @@ wlsc_surface_create(struct wlsc_compositor *compositor,
 | 
				
			||||||
	return surface;
 | 
						return surface;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static uint32_t
 | 
					uint32_t
 | 
				
			||||||
get_time(void)
 | 
					get_time(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct timeval tv;
 | 
						struct timeval tv;
 | 
				
			||||||
| 
						 | 
					@ -188,33 +189,76 @@ destroy_surface(struct wl_resource *resource, struct wl_client *client)
 | 
				
			||||||
	wlsc_compositor_schedule_repaint(compositor);
 | 
						wlsc_compositor_schedule_repaint(compositor);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int
 | 
					static struct wl_buffer *
 | 
				
			||||||
texture_from_png(const char *filename, int width, int height)
 | 
					create_buffer_from_png(struct wlsc_compositor *ec,
 | 
				
			||||||
 | 
							       const char *filename, int width, int height)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	GdkPixbuf *pixbuf;
 | 
						GdkPixbuf *pixbuf;
 | 
				
			||||||
	GError *error = NULL;
 | 
						GError *error = NULL;
 | 
				
			||||||
	void *data;
 | 
						int stride, i, n_channels;
 | 
				
			||||||
	GLenum format;
 | 
						unsigned char *pixels, *end, *argb_pixels, *s, *d;
 | 
				
			||||||
 | 
						struct wl_buffer *buffer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pixbuf = gdk_pixbuf_new_from_file_at_scale(filename,
 | 
						pixbuf = gdk_pixbuf_new_from_file_at_scale(filename,
 | 
				
			||||||
						   width, height,
 | 
											   width, height,
 | 
				
			||||||
						   FALSE, &error);
 | 
											   FALSE, &error);
 | 
				
			||||||
	if (error != NULL)
 | 
						if (error != NULL)
 | 
				
			||||||
		return -1;
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	data = gdk_pixbuf_get_pixels(pixbuf);
 | 
						stride = gdk_pixbuf_get_rowstride(pixbuf);
 | 
				
			||||||
 | 
						pixels = gdk_pixbuf_get_pixels(pixbuf);
 | 
				
			||||||
 | 
						n_channels = gdk_pixbuf_get_n_channels(pixbuf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (gdk_pixbuf_get_has_alpha(pixbuf))
 | 
						argb_pixels = malloc (height * width * 4);
 | 
				
			||||||
		format = GL_RGBA;
 | 
						if (argb_pixels == NULL) {
 | 
				
			||||||
	else
 | 
							gdk_pixbuf_unref(pixbuf);
 | 
				
			||||||
		format = GL_RGB;
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height,
 | 
						if (n_channels == 4) {
 | 
				
			||||||
			format, GL_UNSIGNED_BYTE, data);
 | 
							for (i = 0; i < height; i++) {
 | 
				
			||||||
 | 
								s = pixels + i * stride;
 | 
				
			||||||
 | 
								end = s + width * 4;
 | 
				
			||||||
 | 
								d = argb_pixels + i * width * 4;
 | 
				
			||||||
 | 
								while (s < end) {
 | 
				
			||||||
 | 
									unsigned int t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define MULT(_d,c,a,t) \
 | 
				
			||||||
 | 
						do { t = c * a + 0x7f; _d = ((t >> 8) + t) >> 8; } while (0)
 | 
				
			||||||
 | 
									
 | 
				
			||||||
 | 
									MULT(d[0], s[2], s[3], t);
 | 
				
			||||||
 | 
									MULT(d[1], s[1], s[3], t);
 | 
				
			||||||
 | 
									MULT(d[2], s[0], s[3], t);
 | 
				
			||||||
 | 
									d[3] = s[3];
 | 
				
			||||||
 | 
									s += 4;
 | 
				
			||||||
 | 
									d += 4;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else if (n_channels == 3) {
 | 
				
			||||||
 | 
							for (i = 0; i < height; i++) {
 | 
				
			||||||
 | 
								s = pixels + i * stride;
 | 
				
			||||||
 | 
								end = s + width * 3;
 | 
				
			||||||
 | 
								d = argb_pixels + i * width * 4;
 | 
				
			||||||
 | 
								while (s < end) {
 | 
				
			||||||
 | 
									d[0] = s[2];
 | 
				
			||||||
 | 
									d[1] = s[1];
 | 
				
			||||||
 | 
									d[2] = s[0];
 | 
				
			||||||
 | 
									d[3] = 0xff;
 | 
				
			||||||
 | 
									s += 3;
 | 
				
			||||||
 | 
									d += 4;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	gdk_pixbuf_unref(pixbuf);
 | 
						gdk_pixbuf_unref(pixbuf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						buffer = ec->create_buffer(ec, width, height,
 | 
				
			||||||
 | 
									   &ec->compositor.premultiplied_argb_visual,
 | 
				
			||||||
 | 
									   argb_pixels);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						free(argb_pixels);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return buffer;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const struct {
 | 
					static const struct {
 | 
				
			||||||
| 
						 | 
					@ -238,25 +282,15 @@ static void
 | 
				
			||||||
create_pointer_images(struct wlsc_compositor *ec)
 | 
					create_pointer_images(struct wlsc_compositor *ec)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int i, count;
 | 
						int i, count;
 | 
				
			||||||
	GLuint texture;
 | 
					 | 
				
			||||||
	const int width = 32, height = 32;
 | 
						const int width = 32, height = 32;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	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);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	count = ARRAY_LENGTH(pointer_images);
 | 
						count = ARRAY_LENGTH(pointer_images);
 | 
				
			||||||
	ec->pointer_buffers = malloc(count * sizeof *ec->pointer_buffers);
 | 
						ec->pointer_buffers = malloc(count * sizeof *ec->pointer_buffers);
 | 
				
			||||||
	for (i = 0; i < count; i++) {
 | 
						for (i = 0; i < count; i++) {
 | 
				
			||||||
		ec->pointer_buffers[i] =
 | 
							ec->pointer_buffers[i] =
 | 
				
			||||||
			wlsc_drm_buffer_create(ec, width, height,
 | 
								create_buffer_from_png(ec,
 | 
				
			||||||
					       &ec->compositor.argb_visual);
 | 
										       pointer_images[i].filename,
 | 
				
			||||||
		glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,
 | 
										       width, height);
 | 
				
			||||||
					     ec->pointer_buffers[i]->image);
 | 
					 | 
				
			||||||
		texture_from_png(pointer_images[i].filename, width, height);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -264,37 +298,22 @@ static struct wlsc_surface *
 | 
				
			||||||
background_create(struct wlsc_output *output, const char *filename)
 | 
					background_create(struct wlsc_output *output, const char *filename)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct wlsc_surface *background;
 | 
						struct wlsc_surface *background;
 | 
				
			||||||
	GdkPixbuf *pixbuf;
 | 
						struct wl_buffer *buffer;
 | 
				
			||||||
	GError *error = NULL;
 | 
					 | 
				
			||||||
	void *data;
 | 
					 | 
				
			||||||
	GLenum format;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	background = wlsc_surface_create(output->compositor,
 | 
						background = wlsc_surface_create(output->compositor,
 | 
				
			||||||
					 &output->compositor->compositor.rgb_visual,
 | 
					 | 
				
			||||||
					 output->x, output->y,
 | 
										 output->x, output->y,
 | 
				
			||||||
					 output->width, output->height);
 | 
										 output->width, output->height);
 | 
				
			||||||
	if (background == NULL)
 | 
						if (background == NULL)
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pixbuf = gdk_pixbuf_new_from_file_at_scale(filename,
 | 
						buffer = create_buffer_from_png(output->compositor,
 | 
				
			||||||
						   output->width,
 | 
										filename,
 | 
				
			||||||
						   output->height,
 | 
										output->width, output->height);
 | 
				
			||||||
						   FALSE, &error);
 | 
						if (buffer == NULL) {
 | 
				
			||||||
	if (error != NULL) {
 | 
					 | 
				
			||||||
		free(background);
 | 
							free(background);
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						buffer->attach(buffer, &background->surface);
 | 
				
			||||||
	data = gdk_pixbuf_get_pixels(pixbuf);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (gdk_pixbuf_get_has_alpha(pixbuf))
 | 
					 | 
				
			||||||
		format = GL_RGBA;
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
		format = GL_RGB;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
 | 
					 | 
				
			||||||
		     output->width, output->height, 0,
 | 
					 | 
				
			||||||
		     format, GL_UNSIGNED_BYTE, data);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return background;
 | 
						return background;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -340,7 +359,7 @@ wlsc_surface_raise(struct wlsc_surface *surface)
 | 
				
			||||||
	wl_list_insert(&compositor->surface_list, &surface->link);
 | 
						wl_list_insert(&compositor->surface_list, &surface->link);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					void
 | 
				
			||||||
wlsc_surface_update_matrix(struct wlsc_surface *es)
 | 
					wlsc_surface_update_matrix(struct wlsc_surface *es)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	wlsc_matrix_init(&es->matrix);
 | 
						wlsc_matrix_init(&es->matrix);
 | 
				
			||||||
| 
						 | 
					@ -492,7 +511,7 @@ wlsc_input_device_attach(struct wlsc_input_device *device,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					void
 | 
				
			||||||
wlsc_input_device_set_pointer_image(struct wlsc_input_device *device,
 | 
					wlsc_input_device_set_pointer_image(struct wlsc_input_device *device,
 | 
				
			||||||
				    enum wlsc_pointer_type type)
 | 
									    enum wlsc_pointer_type type)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -500,253 +519,11 @@ wlsc_input_device_set_pointer_image(struct wlsc_input_device *device,
 | 
				
			||||||
		(struct wlsc_compositor *) device->input_device.compositor;
 | 
							(struct wlsc_compositor *) device->input_device.compositor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wlsc_input_device_attach(device,
 | 
						wlsc_input_device_attach(device,
 | 
				
			||||||
				 &compositor->pointer_buffers[type]->buffer,
 | 
									 compositor->pointer_buffers[type],
 | 
				
			||||||
				 pointer_images[type].hotspot_x,
 | 
									 pointer_images[type].hotspot_x,
 | 
				
			||||||
				 pointer_images[type].hotspot_y);
 | 
									 pointer_images[type].hotspot_y);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct wlsc_move_grab {
 | 
					 | 
				
			||||||
	struct wl_grab grab;
 | 
					 | 
				
			||||||
	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 =
 | 
					 | 
				
			||||||
		(struct wlsc_surface *) grab->input_device->pointer_focus;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	es->x = x + move->dx;
 | 
					 | 
				
			||||||
	es->y = y + move->dy;
 | 
					 | 
				
			||||||
	wlsc_surface_update_matrix(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)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	free(grab);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static const struct wl_grab_interface move_grab_interface = {
 | 
					 | 
				
			||||||
	move_grab_motion,
 | 
					 | 
				
			||||||
	move_grab_button,
 | 
					 | 
				
			||||||
	move_grab_end
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static 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;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	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;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	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);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct wlsc_resize_grab {
 | 
					 | 
				
			||||||
	struct wl_grab grab;
 | 
					 | 
				
			||||||
	uint32_t edges;
 | 
					 | 
				
			||||||
	int32_t dx, dy, width, height;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
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 = device->pointer_focus;
 | 
					 | 
				
			||||||
	int32_t width, height;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (resize->edges & WL_GRAB_RESIZE_LEFT) {
 | 
					 | 
				
			||||||
		width = device->grab_x - x + resize->width;
 | 
					 | 
				
			||||||
	} else if (resize->edges & WL_GRAB_RESIZE_RIGHT) {
 | 
					 | 
				
			||||||
		width = x - device->grab_x + resize->width;
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		width = resize->width;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (resize->edges & WL_GRAB_RESIZE_TOP) {
 | 
					 | 
				
			||||||
		height = device->grab_y - y + resize->height;
 | 
					 | 
				
			||||||
	} else if (resize->edges & WL_GRAB_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)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	free(grab);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static const struct wl_grab_interface resize_grab_interface = {
 | 
					 | 
				
			||||||
	resize_grab_motion,
 | 
					 | 
				
			||||||
	resize_grab_button,
 | 
					 | 
				
			||||||
	resize_grab_end
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static 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;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	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;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (edges == 0 || edges > 15 ||
 | 
					 | 
				
			||||||
	    (edges & 3) == 3 || (edges & 12) == 12)
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	switch (edges) {
 | 
					 | 
				
			||||||
	case WL_GRAB_RESIZE_TOP:
 | 
					 | 
				
			||||||
		pointer = WLSC_POINTER_TOP;
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	case WL_GRAB_RESIZE_BOTTOM:
 | 
					 | 
				
			||||||
		pointer = WLSC_POINTER_BOTTOM;
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	case WL_GRAB_RESIZE_LEFT:
 | 
					 | 
				
			||||||
		pointer = WLSC_POINTER_LEFT;
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	case WL_GRAB_RESIZE_TOP_LEFT:
 | 
					 | 
				
			||||||
		pointer = WLSC_POINTER_TOP_LEFT;
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	case WL_GRAB_RESIZE_BOTTOM_LEFT:
 | 
					 | 
				
			||||||
		pointer = WLSC_POINTER_BOTTOM_LEFT;
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	case WL_GRAB_RESIZE_RIGHT:
 | 
					 | 
				
			||||||
		pointer = WLSC_POINTER_RIGHT;
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	case WL_GRAB_RESIZE_TOP_RIGHT:
 | 
					 | 
				
			||||||
		pointer = WLSC_POINTER_TOP_RIGHT;
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	case WL_GRAB_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);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
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);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
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);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const static struct wl_drag_interface drag_interface;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
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);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const static struct wl_shell_interface shell_interface = {
 | 
					 | 
				
			||||||
	shell_move,
 | 
					 | 
				
			||||||
	shell_resize,
 | 
					 | 
				
			||||||
	shell_create_drag
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
compositor_create_surface(struct wl_client *client,
 | 
					compositor_create_surface(struct wl_client *client,
 | 
				
			||||||
			  struct wl_compositor *compositor, uint32_t id)
 | 
								  struct wl_compositor *compositor, uint32_t id)
 | 
				
			||||||
| 
						 | 
					@ -754,7 +531,7 @@ compositor_create_surface(struct wl_client *client,
 | 
				
			||||||
	struct wlsc_compositor *ec = (struct wlsc_compositor *) compositor;
 | 
						struct wlsc_compositor *ec = (struct wlsc_compositor *) compositor;
 | 
				
			||||||
	struct wlsc_surface *surface;
 | 
						struct wlsc_surface *surface;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	surface = wlsc_surface_create(ec, NULL, 0, 0, 0, 0);
 | 
						surface = wlsc_surface_create(ec, 0, 0, 0, 0);
 | 
				
			||||||
	if (surface == NULL) {
 | 
						if (surface == NULL) {
 | 
				
			||||||
		wl_client_post_no_memory(client);
 | 
							wl_client_post_no_memory(client);
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
| 
						 | 
					@ -786,7 +563,7 @@ wlsc_surface_transform(struct wlsc_surface *surface,
 | 
				
			||||||
	*sy = v.f[1] * surface->height;
 | 
						*sy = v.f[1] * surface->height;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct wlsc_surface *
 | 
					struct wlsc_surface *
 | 
				
			||||||
pick_surface(struct wl_input_device *device, int32_t *sx, int32_t *sy)
 | 
					pick_surface(struct wl_input_device *device, int32_t *sx, int32_t *sy)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct wlsc_compositor *ec =
 | 
						struct wlsc_compositor *ec =
 | 
				
			||||||
| 
						 | 
					@ -905,6 +682,10 @@ notify_button(struct wl_input_device *device,
 | 
				
			||||||
	if (state && device->grab == NULL) {
 | 
						if (state && device->grab == NULL) {
 | 
				
			||||||
		wlsc_surface_raise(surface);
 | 
							wlsc_surface_raise(surface);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (wd->selection)
 | 
				
			||||||
 | 
								wlsc_selection_set_focus(wd->selection,
 | 
				
			||||||
 | 
											 &surface->surface, time);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		wl_input_device_start_grab(device,
 | 
							wl_input_device_start_grab(device,
 | 
				
			||||||
					   &device->motion_grab,
 | 
										   &device->motion_grab,
 | 
				
			||||||
					   button, time);
 | 
										   button, time);
 | 
				
			||||||
| 
						 | 
					@ -990,202 +771,6 @@ notify_key(struct wl_input_device *device,
 | 
				
			||||||
				     WL_INPUT_DEVICE_KEY, time, key, state);
 | 
									     WL_INPUT_DEVICE_KEY, time, key, state);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
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);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	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);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
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_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
 | 
					static void
 | 
				
			||||||
input_device_attach(struct wl_client *client,
 | 
					input_device_attach(struct wl_client *client,
 | 
				
			||||||
		    struct wl_input_device *device_base,
 | 
							    struct wl_input_device *device_base,
 | 
				
			||||||
| 
						 | 
					@ -1228,7 +813,7 @@ wlsc_input_device_init(struct wlsc_input_device *device,
 | 
				
			||||||
	wl_display_add_object(ec->wl_display, &device->input_device.object);
 | 
						wl_display_add_object(ec->wl_display, &device->input_device.object);
 | 
				
			||||||
	wl_display_add_global(ec->wl_display, &device->input_device.object, NULL);
 | 
						wl_display_add_global(ec->wl_display, &device->input_device.object, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	device->sprite = wlsc_surface_create(ec, &ec->compositor.argb_visual,
 | 
						device->sprite = wlsc_surface_create(ec,
 | 
				
			||||||
					     device->input_device.x,
 | 
										     device->input_device.x,
 | 
				
			||||||
					     device->input_device.y, 32, 32);
 | 
										     device->input_device.y, 32, 32);
 | 
				
			||||||
	device->hotspot_x = 16;
 | 
						device->hotspot_x = 16;
 | 
				
			||||||
| 
						 | 
					@ -1383,6 +968,7 @@ int
 | 
				
			||||||
wlsc_compositor_init(struct wlsc_compositor *ec, struct wl_display *display)
 | 
					wlsc_compositor_init(struct wlsc_compositor *ec, struct wl_display *display)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct wl_event_loop *loop;
 | 
						struct wl_event_loop *loop;
 | 
				
			||||||
 | 
						const char *extensions;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ec->wl_display = display;
 | 
						ec->wl_display = display;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1390,11 +976,7 @@ wlsc_compositor_init(struct wlsc_compositor *ec, struct wl_display *display)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wlsc_shm_init(ec);
 | 
						wlsc_shm_init(ec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ec->shell.object.interface = &wl_shell_interface;
 | 
						wlsc_shell_init(ec);
 | 
				
			||||||
	ec->shell.object.implementation = (void (**)(void)) &shell_interface;
 | 
					 | 
				
			||||||
	wl_display_add_object(display, &ec->shell.object);
 | 
					 | 
				
			||||||
	if (wl_display_add_global(display, &ec->shell.object, NULL))
 | 
					 | 
				
			||||||
		return -1;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wl_list_init(&ec->surface_list);
 | 
						wl_list_init(&ec->surface_list);
 | 
				
			||||||
	wl_list_init(&ec->input_device_list);
 | 
						wl_list_init(&ec->input_device_list);
 | 
				
			||||||
| 
						 | 
					@ -1404,6 +986,13 @@ wlsc_compositor_init(struct wlsc_compositor *ec, struct wl_display *display)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	screenshooter_create(ec);
 | 
						screenshooter_create(ec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						extensions = (const char *) glGetString(GL_EXTENSIONS);
 | 
				
			||||||
 | 
						if (!strstr(extensions, "GL_EXT_texture_format_BGRA8888")) {
 | 
				
			||||||
 | 
							fprintf(stderr,
 | 
				
			||||||
 | 
								"GL_EXT_texture_format_BGRA8888 not available\n");
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	glGenFramebuffers(1, &ec->fbo);
 | 
						glGenFramebuffers(1, &ec->fbo);
 | 
				
			||||||
	glBindFramebuffer(GL_FRAMEBUFFER, ec->fbo);
 | 
						glBindFramebuffer(GL_FRAMEBUFFER, ec->fbo);
 | 
				
			||||||
	glActiveTexture(GL_TEXTURE0);
 | 
						glActiveTexture(GL_TEXTURE0);
 | 
				
			||||||
| 
						 | 
					@ -1449,12 +1038,22 @@ int main(int argc, char *argv[])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	display = wl_display_create();
 | 
						display = wl_display_create();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ec = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if BUILD_WAYLAND_COMPOSITOR
 | 
				
			||||||
	if (getenv("WAYLAND_DISPLAY"))
 | 
						if (getenv("WAYLAND_DISPLAY"))
 | 
				
			||||||
		ec = wayland_compositor_create(display, width, height);
 | 
							ec = wayland_compositor_create(display, width, height);
 | 
				
			||||||
	else if (getenv("DISPLAY"))
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if BUILD_X11_COMPOSITOR
 | 
				
			||||||
 | 
						if (ec == NULL && getenv("DISPLAY"))
 | 
				
			||||||
		ec = x11_compositor_create(display, width, height);
 | 
							ec = x11_compositor_create(display, width, height);
 | 
				
			||||||
	else
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if BUILD_DRM_COMPOSITOR
 | 
				
			||||||
 | 
						if (ec == NULL)
 | 
				
			||||||
		ec = drm_compositor_create(display, option_connector);
 | 
							ec = drm_compositor_create(display, option_connector);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (ec == NULL) {
 | 
						if (ec == NULL) {
 | 
				
			||||||
		fprintf(stderr, "failed to create compositor\n");
 | 
							fprintf(stderr, "failed to create compositor\n");
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,7 +19,6 @@
 | 
				
			||||||
#ifndef _WAYLAND_SYSTEM_COMPOSITOR_H_
 | 
					#ifndef _WAYLAND_SYSTEM_COMPOSITOR_H_
 | 
				
			||||||
#define _WAYLAND_SYSTEM_COMPOSITOR_H_
 | 
					#define _WAYLAND_SYSTEM_COMPOSITOR_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <termios.h>
 | 
					 | 
				
			||||||
#include <xf86drm.h>
 | 
					#include <xf86drm.h>
 | 
				
			||||||
#include <xf86drmMode.h>
 | 
					#include <xf86drmMode.h>
 | 
				
			||||||
#include <libudev.h>
 | 
					#include <libudev.h>
 | 
				
			||||||
| 
						 | 
					@ -70,6 +69,7 @@ struct wlsc_input_device {
 | 
				
			||||||
	int32_t hotspot_x, hotspot_y;
 | 
						int32_t hotspot_x, hotspot_y;
 | 
				
			||||||
	struct wl_list link;
 | 
						struct wl_list link;
 | 
				
			||||||
	uint32_t modifier_state;
 | 
						uint32_t modifier_state;
 | 
				
			||||||
 | 
						struct wl_selection *selection;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct wlsc_drm {
 | 
					struct wlsc_drm {
 | 
				
			||||||
| 
						 | 
					@ -78,21 +78,10 @@ struct wlsc_drm {
 | 
				
			||||||
	char *filename;
 | 
						char *filename;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct wlsc_drm_buffer {
 | 
					 | 
				
			||||||
	struct wl_buffer buffer;
 | 
					 | 
				
			||||||
	EGLImageKHR image;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct wlsc_shm {
 | 
					struct wlsc_shm {
 | 
				
			||||||
	struct wl_object object;
 | 
						struct wl_object object;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct wlsc_shm_buffer {
 | 
					 | 
				
			||||||
	struct wl_buffer buffer;
 | 
					 | 
				
			||||||
	int32_t stride;
 | 
					 | 
				
			||||||
	void *data;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct wlsc_compositor {
 | 
					struct wlsc_compositor {
 | 
				
			||||||
	struct wl_compositor compositor;
 | 
						struct wl_compositor compositor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -102,7 +91,7 @@ struct wlsc_compositor {
 | 
				
			||||||
	EGLContext context;
 | 
						EGLContext context;
 | 
				
			||||||
	GLuint fbo, vbo;
 | 
						GLuint fbo, vbo;
 | 
				
			||||||
	GLuint proj_uniform, tex_uniform;
 | 
						GLuint proj_uniform, tex_uniform;
 | 
				
			||||||
	struct wlsc_drm_buffer **pointer_buffers;
 | 
						struct wl_buffer **pointer_buffers;
 | 
				
			||||||
	struct wl_display *wl_display;
 | 
						struct wl_display *wl_display;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* We implement the shell interface. */
 | 
						/* We implement the shell interface. */
 | 
				
			||||||
| 
						 | 
					@ -126,6 +115,10 @@ struct wlsc_compositor {
 | 
				
			||||||
	void (*destroy)(struct wlsc_compositor *ec);
 | 
						void (*destroy)(struct wlsc_compositor *ec);
 | 
				
			||||||
	int (*authenticate)(struct wlsc_compositor *c, uint32_t id);
 | 
						int (*authenticate)(struct wlsc_compositor *c, uint32_t id);
 | 
				
			||||||
	void (*present)(struct wlsc_compositor *c);
 | 
						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_CTRL	(1 << 8)
 | 
				
			||||||
| 
						 | 
					@ -149,6 +142,9 @@ struct wlsc_surface {
 | 
				
			||||||
	int mapped;
 | 
						int mapped;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					wlsc_surface_update_matrix(struct wlsc_surface *es);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
notify_motion(struct wl_input_device *device,
 | 
					notify_motion(struct wl_input_device *device,
 | 
				
			||||||
	      uint32_t time, int x, int y);
 | 
						      uint32_t time, int x, int y);
 | 
				
			||||||
| 
						 | 
					@ -164,9 +160,23 @@ wlsc_compositor_finish_frame(struct wlsc_compositor *compositor, int msecs);
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
wlsc_compositor_schedule_repaint(struct wlsc_compositor *compositor);
 | 
					wlsc_compositor_schedule_repaint(struct wlsc_compositor *compositor);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct wlsc_drm_buffer *
 | 
					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,
 | 
					wlsc_drm_buffer_create(struct wlsc_compositor *ec,
 | 
				
			||||||
		       int width, int height, struct wl_visual *visual);
 | 
							       int width, int height,
 | 
				
			||||||
 | 
							       struct wl_visual *visual, const void *data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int
 | 
					int
 | 
				
			||||||
wlsc_compositor_init(struct wlsc_compositor *ec, struct wl_display *display);
 | 
					wlsc_compositor_init(struct wlsc_compositor *ec, struct wl_display *display);
 | 
				
			||||||
| 
						 | 
					@ -182,6 +192,19 @@ wlsc_drm_init(struct wlsc_compositor *ec, int fd, const char *filename);
 | 
				
			||||||
int
 | 
					int
 | 
				
			||||||
wlsc_shm_init(struct wlsc_compositor *ec);
 | 
					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 *
 | 
					struct wl_buffer *
 | 
				
			||||||
wl_buffer_create_drm(struct wlsc_compositor *compositor,
 | 
					wl_buffer_create_drm(struct wlsc_compositor *compositor,
 | 
				
			||||||
		     struct wl_visual *visual);
 | 
							     struct wl_visual *visual);
 | 
				
			||||||
| 
						 | 
					@ -195,6 +218,15 @@ drm_compositor_create(struct wl_display *display, int connector);
 | 
				
			||||||
struct wlsc_compositor *
 | 
					struct wlsc_compositor *
 | 
				
			||||||
wayland_compositor_create(struct wl_display *display, int width, int height);
 | 
					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
 | 
					void
 | 
				
			||||||
screenshooter_create(struct wlsc_compositor *ec);
 | 
					screenshooter_create(struct wlsc_compositor *ec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,6 +22,11 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "compositor.h"
 | 
					#include "compositor.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlsc_drm_buffer {
 | 
				
			||||||
 | 
						struct wl_buffer buffer;
 | 
				
			||||||
 | 
						EGLImageKHR image;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
drm_authenticate(struct wl_client *client,
 | 
					drm_authenticate(struct wl_client *client,
 | 
				
			||||||
		 struct wl_drm *drm_base, uint32_t id)
 | 
							 struct wl_drm *drm_base, uint32_t id)
 | 
				
			||||||
| 
						 | 
					@ -197,12 +202,13 @@ wlsc_drm_init(struct wlsc_compositor *ec, int fd, const char *filename)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct wlsc_drm_buffer *
 | 
					struct wl_buffer *
 | 
				
			||||||
wlsc_drm_buffer_create(struct wlsc_compositor *ec,
 | 
					wlsc_drm_buffer_create(struct wlsc_compositor *ec, int width, int height,
 | 
				
			||||||
		       int width, int height, struct wl_visual *visual)
 | 
							       struct wl_visual *visual, const void *data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct wlsc_drm_buffer *buffer;
 | 
						struct wlsc_drm_buffer *buffer;
 | 
				
			||||||
	EGLImageKHR image;
 | 
						EGLImageKHR image;
 | 
				
			||||||
 | 
						GLuint texture;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	EGLint image_attribs[] = {
 | 
						EGLint image_attribs[] = {
 | 
				
			||||||
		EGL_WIDTH,		0,
 | 
							EGL_WIDTH,		0,
 | 
				
			||||||
| 
						 | 
					@ -222,5 +228,19 @@ wlsc_drm_buffer_create(struct wlsc_compositor *ec,
 | 
				
			||||||
	buffer = wlsc_drm_buffer_create_for_image(ec, image,
 | 
						buffer = wlsc_drm_buffer_create_for_image(ec, image,
 | 
				
			||||||
						  width, height, visual);
 | 
											  width, height, visual);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return buffer;
 | 
						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;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										239
									
								
								compositor/evdev.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										239
									
								
								compositor/evdev.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,239 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * 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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										640
									
								
								compositor/shell.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										640
									
								
								compositor/shell.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,640 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * 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;
 | 
				
			||||||
 | 
						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 =
 | 
				
			||||||
 | 
							(struct wlsc_surface *) grab->input_device->pointer_focus;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						es->x = x + move->dx;
 | 
				
			||||||
 | 
						es->y = y + move->dy;
 | 
				
			||||||
 | 
						wlsc_surface_update_matrix(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)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						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);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlsc_resize_grab {
 | 
				
			||||||
 | 
						struct wl_grab grab;
 | 
				
			||||||
 | 
						uint32_t edges;
 | 
				
			||||||
 | 
						int32_t dx, dy, width, height;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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 = device->pointer_focus;
 | 
				
			||||||
 | 
						int32_t width, height;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (resize->edges & WL_GRAB_RESIZE_LEFT) {
 | 
				
			||||||
 | 
							width = device->grab_x - x + resize->width;
 | 
				
			||||||
 | 
						} else if (resize->edges & WL_GRAB_RESIZE_RIGHT) {
 | 
				
			||||||
 | 
							width = x - device->grab_x + resize->width;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							width = resize->width;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (resize->edges & WL_GRAB_RESIZE_TOP) {
 | 
				
			||||||
 | 
							height = device->grab_y - y + resize->height;
 | 
				
			||||||
 | 
						} else if (resize->edges & WL_GRAB_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)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (edges == 0 || edges > 15 ||
 | 
				
			||||||
 | 
						    (edges & 3) == 3 || (edges & 12) == 12)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (edges) {
 | 
				
			||||||
 | 
						case WL_GRAB_RESIZE_TOP:
 | 
				
			||||||
 | 
							pointer = WLSC_POINTER_TOP;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case WL_GRAB_RESIZE_BOTTOM:
 | 
				
			||||||
 | 
							pointer = WLSC_POINTER_BOTTOM;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case WL_GRAB_RESIZE_LEFT:
 | 
				
			||||||
 | 
							pointer = WLSC_POINTER_LEFT;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case WL_GRAB_RESIZE_TOP_LEFT:
 | 
				
			||||||
 | 
							pointer = WLSC_POINTER_TOP_LEFT;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case WL_GRAB_RESIZE_BOTTOM_LEFT:
 | 
				
			||||||
 | 
							pointer = WLSC_POINTER_BOTTOM_LEFT;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case WL_GRAB_RESIZE_RIGHT:
 | 
				
			||||||
 | 
							pointer = WLSC_POINTER_RIGHT;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case WL_GRAB_RESIZE_TOP_RIGHT:
 | 
				
			||||||
 | 
							pointer = WLSC_POINTER_TOP_RIGHT;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case WL_GRAB_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);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						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);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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_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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -24,6 +24,12 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "compositor.h"
 | 
					#include "compositor.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlsc_shm_buffer {
 | 
				
			||||||
 | 
						struct wl_buffer buffer;
 | 
				
			||||||
 | 
						int32_t stride;
 | 
				
			||||||
 | 
						void *data;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
destroy_buffer(struct wl_resource *resource, struct wl_client *client)
 | 
					destroy_buffer(struct wl_resource *resource, struct wl_client *client)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -57,8 +63,7 @@ shm_buffer_attach(struct wl_buffer *buffer_base, struct wl_surface *surface)
 | 
				
			||||||
	 * overwrite it.*/
 | 
						 * overwrite it.*/
 | 
				
			||||||
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
 | 
						glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
 | 
				
			||||||
		     0, 0, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, NULL);
 | 
							     0, 0, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, NULL);
 | 
				
			||||||
 | 
						glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT,
 | 
				
			||||||
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
 | 
					 | 
				
			||||||
		     buffer->buffer.width, buffer->buffer.height, 0,
 | 
							     buffer->buffer.width, buffer->buffer.height, 0,
 | 
				
			||||||
		     GL_BGRA_EXT, GL_UNSIGNED_BYTE, buffer->data);
 | 
							     GL_BGRA_EXT, GL_UNSIGNED_BYTE, buffer->data);
 | 
				
			||||||
	es->visual = buffer->buffer.visual;
 | 
						es->visual = buffer->buffer.visual;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										163
									
								
								compositor/tty.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										163
									
								
								compositor/tty.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,163 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * 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");
 | 
				
			||||||
 | 
						tty->compositor->focus = 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tty->compositor->focus = 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = ioctl(tty->fd, KDSETMODE, KD_TEXT);
 | 
				
			||||||
 | 
						if (ret)
 | 
				
			||||||
 | 
							fprintf(stderr,
 | 
				
			||||||
 | 
								"failed to set KD_GRAPHICS 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);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										34
									
								
								configure.ac
									
										
									
									
									
								
							
							
						
						
									
										34
									
								
								configure.ac
									
										
									
									
									
								
							| 
						 | 
					@ -24,15 +24,41 @@ PKG_CHECK_MODULES(FFI, [libffi])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PKG_CHECK_MODULES(COMPOSITOR,
 | 
					PKG_CHECK_MODULES(COMPOSITOR,
 | 
				
			||||||
		  [egl glesv2 gdk-pixbuf-2.0 libudev >= 136 libdrm >= 2.4.17] xcb-dri2 xcb-xfixes)
 | 
							  [egl glesv2 gdk-pixbuf-2.0 libudev >= 136 libdrm >= 2.4.17] xcb-dri2 xcb-xfixes)
 | 
				
			||||||
 | 
					PKG_CHECK_MODULES(GLES2, [egl glesv2 libdrm])
 | 
				
			||||||
PKG_CHECK_MODULES(CLIENT, [egl gl cairo gdk-pixbuf-2.0 glib-2.0 gobject-2.0 xkbcommon libdrm])
 | 
					PKG_CHECK_MODULES(CLIENT, [egl gl cairo gdk-pixbuf-2.0 glib-2.0 gobject-2.0 xkbcommon libdrm])
 | 
				
			||||||
PKG_CHECK_MODULES(POPPLER, [poppler-glib gdk-2.0],
 | 
					PKG_CHECK_MODULES(POPPLER, [poppler-glib gdk-2.0],
 | 
				
			||||||
			   [have_poppler=yes], [have_poppler=no])
 | 
								   [have_poppler=yes], [have_poppler=no])
 | 
				
			||||||
AM_CONDITIONAL(HAVE_POPPLER, test "x$have_poppler" = "xyes")
 | 
					AM_CONDITIONAL(HAVE_POPPLER, test "x$have_poppler" = "xyes")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PKG_CHECK_MODULES(CAIRO_GL, [cairo-gl],
 | 
					
 | 
				
			||||||
		  [have_cairo_gl=yes], [have_cairo_gl=no])
 | 
					AC_ARG_ENABLE(x11-compositor, [  --enable-x11-compositor],,
 | 
				
			||||||
AS_IF([test "x$have_cairo_gl" = "xyes"],
 | 
						      enable_x11_compositor=yes)
 | 
				
			||||||
      [AC_DEFINE([HAVE_CAIRO_GL], [1], [Have cairo-gl])])
 | 
					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])
 | 
				
			||||||
 | 
					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])
 | 
				
			||||||
 | 
					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 $CC = gcc; then
 | 
					if test $CC = gcc; then
 | 
				
			||||||
	GCC_CFLAGS="-Wall -g -Wstrict-prototypes -Wmissing-prototypes -fvisibility=hidden"
 | 
						GCC_CFLAGS="-Wall -g -Wstrict-prototypes -Wmissing-prototypes -fvisibility=hidden"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -164,6 +164,10 @@
 | 
				
			||||||
      <arg name="id" type="new_id" interface="drag"/>
 | 
					      <arg name="id" type="new_id" interface="drag"/>
 | 
				
			||||||
    </request>
 | 
					    </request>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <request name="create_selection">
 | 
				
			||||||
 | 
					      <arg name="id" type="new_id" interface="selection"/>
 | 
				
			||||||
 | 
					    </request>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <!-- The configure event asks the client to resize its surface.
 | 
					    <!-- The configure event asks the client to resize its surface.
 | 
				
			||||||
         The size is a hint, in the sense that the client is free to
 | 
					         The size is a hint, in the sense that the client is free to
 | 
				
			||||||
         ignore it if it doesn't resize, pick a smaller size (to
 | 
					         ignore it if it doesn't resize, pick a smaller size (to
 | 
				
			||||||
| 
						 | 
					@ -179,6 +183,53 @@
 | 
				
			||||||
    </event>
 | 
					    </event>
 | 
				
			||||||
  </interface>
 | 
					  </interface>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <interface name="selection" version="1">
 | 
				
			||||||
 | 
					    <!-- Add an offered mime type.  Can be called several times to
 | 
				
			||||||
 | 
					         offer multiple types, but must be called before 'activate'. -->
 | 
				
			||||||
 | 
					    <request name="offer">
 | 
				
			||||||
 | 
					      <arg name="type" type="string"/>
 | 
				
			||||||
 | 
					    </request>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <!-- Can the selection be activated for multiple devices? -->
 | 
				
			||||||
 | 
					    <request name="activate">
 | 
				
			||||||
 | 
					      <arg name="input_device" type="object" interface="input_device"/>
 | 
				
			||||||
 | 
					      <arg name="time" type="uint"/>
 | 
				
			||||||
 | 
					    </request>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <!-- Destroy the selection. -->
 | 
				
			||||||
 | 
					    <request name="destroy" type="destructor"/>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <!-- Another client pasted the selection, send the mime-type over
 | 
				
			||||||
 | 
					         the passed fd. -->
 | 
				
			||||||
 | 
					    <event name="send">
 | 
				
			||||||
 | 
					      <arg name="mime_type" type="string"/>
 | 
				
			||||||
 | 
					      <arg name="fd" type="fd"/>
 | 
				
			||||||
 | 
					    </event>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <!-- Another selection became active. -->
 | 
				
			||||||
 | 
					    <event name="cancelled"/>
 | 
				
			||||||
 | 
					  </interface>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <interface name="selection_offer" version="1">
 | 
				
			||||||
 | 
					    <!-- Called to receive the selection data as the specified type.
 | 
				
			||||||
 | 
					         Sends the pipe fd to the compositor, which forwards it to the
 | 
				
			||||||
 | 
					         source in the 'send' event -->
 | 
				
			||||||
 | 
					    <request name="receive">
 | 
				
			||||||
 | 
					      <arg name="mime_type" type="string"/>
 | 
				
			||||||
 | 
					      <arg name="fd" type="fd"/>
 | 
				
			||||||
 | 
					    </request>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <!-- Sent before the keyboard_focus event to announce the types
 | 
				
			||||||
 | 
					         offered.  One event per offered mime type.  A mime type of
 | 
				
			||||||
 | 
					         NULL means the selection offer is going away.  -->
 | 
				
			||||||
 | 
					    <event name="offer">
 | 
				
			||||||
 | 
					      <arg name="type" type="string"/>
 | 
				
			||||||
 | 
					    </event>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <event name="keyboard_focus">
 | 
				
			||||||
 | 
					      <arg name="input_device" type="object" interface="input_device"/>
 | 
				
			||||||
 | 
					    </event>
 | 
				
			||||||
 | 
					  </interface>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  <interface name="drag" version="1">
 | 
					  <interface name="drag" version="1">
 | 
				
			||||||
    <!-- Add an offered mime type.  Can be called several times to
 | 
					    <!-- Add an offered mime type.  Can be called several times to
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -61,7 +61,7 @@ struct wl_connection {
 | 
				
			||||||
	int fd;
 | 
						int fd;
 | 
				
			||||||
	void *data;
 | 
						void *data;
 | 
				
			||||||
	wl_connection_update_func_t update;
 | 
						wl_connection_update_func_t update;
 | 
				
			||||||
	struct wl_closure closure;
 | 
						struct wl_closure receive_closure, send_closure;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
union wl_value {
 | 
					union wl_value {
 | 
				
			||||||
| 
						 | 
					@ -251,36 +251,6 @@ wl_connection_data(struct wl_connection *connection, uint32_t mask)
 | 
				
			||||||
	char cmsg[128];
 | 
						char cmsg[128];
 | 
				
			||||||
	int len, count, clen;
 | 
						int len, count, clen;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (mask & WL_CONNECTION_READABLE) {
 | 
					 | 
				
			||||||
		wl_buffer_put_iov(&connection->in, iov, &count);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		msg.msg_name = NULL;
 | 
					 | 
				
			||||||
		msg.msg_namelen = 0;
 | 
					 | 
				
			||||||
		msg.msg_iov = iov;
 | 
					 | 
				
			||||||
		msg.msg_iovlen = count;
 | 
					 | 
				
			||||||
		msg.msg_control = cmsg;
 | 
					 | 
				
			||||||
		msg.msg_controllen = sizeof cmsg;
 | 
					 | 
				
			||||||
		msg.msg_flags = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		do {
 | 
					 | 
				
			||||||
			len = recvmsg(connection->fd, &msg, 0);
 | 
					 | 
				
			||||||
		} while (len < 0 && errno == EINTR);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (len < 0) {
 | 
					 | 
				
			||||||
			fprintf(stderr,
 | 
					 | 
				
			||||||
				"read error from connection %p: %m (%d)\n",
 | 
					 | 
				
			||||||
				connection, errno);
 | 
					 | 
				
			||||||
			return -1;
 | 
					 | 
				
			||||||
		} else if (len == 0) {
 | 
					 | 
				
			||||||
			/* FIXME: Handle this better? */
 | 
					 | 
				
			||||||
			return -1;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		decode_cmsg(&connection->fds_in, &msg);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		connection->in.head += len;
 | 
					 | 
				
			||||||
	}	
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (mask & WL_CONNECTION_WRITABLE) {
 | 
						if (mask & WL_CONNECTION_WRITABLE) {
 | 
				
			||||||
		wl_buffer_get_iov(&connection->out, iov, &count);
 | 
							wl_buffer_get_iov(&connection->out, iov, &count);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -314,6 +284,36 @@ wl_connection_data(struct wl_connection *connection, uint32_t mask)
 | 
				
			||||||
					   connection->data);
 | 
										   connection->data);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (mask & WL_CONNECTION_READABLE) {
 | 
				
			||||||
 | 
							wl_buffer_put_iov(&connection->in, iov, &count);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							msg.msg_name = NULL;
 | 
				
			||||||
 | 
							msg.msg_namelen = 0;
 | 
				
			||||||
 | 
							msg.msg_iov = iov;
 | 
				
			||||||
 | 
							msg.msg_iovlen = count;
 | 
				
			||||||
 | 
							msg.msg_control = cmsg;
 | 
				
			||||||
 | 
							msg.msg_controllen = sizeof cmsg;
 | 
				
			||||||
 | 
							msg.msg_flags = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							do {
 | 
				
			||||||
 | 
								len = recvmsg(connection->fd, &msg, 0);
 | 
				
			||||||
 | 
							} while (len < 0 && errno == EINTR);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (len < 0) {
 | 
				
			||||||
 | 
								fprintf(stderr,
 | 
				
			||||||
 | 
									"read error from connection %p: %m (%d)\n",
 | 
				
			||||||
 | 
									connection, errno);
 | 
				
			||||||
 | 
								return -1;
 | 
				
			||||||
 | 
							} else if (len == 0) {
 | 
				
			||||||
 | 
								/* FIXME: Handle this better? */
 | 
				
			||||||
 | 
								return -1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							decode_cmsg(&connection->fds_in, &msg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							connection->in.head += len;
 | 
				
			||||||
 | 
						}	
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return connection->in.head - connection->in.tail;
 | 
						return connection->in.head - connection->in.tail;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -362,14 +362,14 @@ wl_connection_vmarshal(struct wl_connection *connection,
 | 
				
			||||||
		       uint32_t opcode, va_list ap,
 | 
							       uint32_t opcode, va_list ap,
 | 
				
			||||||
		       const struct wl_message *message)
 | 
							       const struct wl_message *message)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct wl_closure *closure = &connection->closure;
 | 
						struct wl_closure *closure = &connection->send_closure;
 | 
				
			||||||
	struct wl_object **objectp, *object;
 | 
						struct wl_object **objectp, *object;
 | 
				
			||||||
	uint32_t length, *p, *start, size;
 | 
						uint32_t length, *p, *start, size;
 | 
				
			||||||
	int dup_fd;
 | 
						int dup_fd;
 | 
				
			||||||
	struct wl_array **arrayp, *array;
 | 
						struct wl_array **arrayp, *array;
 | 
				
			||||||
	const char **sp, *s;
 | 
						const char **sp, *s;
 | 
				
			||||||
	char *extra;
 | 
						char *extra;
 | 
				
			||||||
	int i, count, fd, extra_size;
 | 
						int i, count, fd, extra_size, *fd_ptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	extra_size = wl_message_size_extra(message);
 | 
						extra_size = wl_message_size_extra(message);
 | 
				
			||||||
	count = strlen(message->signature) + 2;
 | 
						count = strlen(message->signature) + 2;
 | 
				
			||||||
| 
						 | 
					@ -449,12 +449,18 @@ wl_connection_vmarshal(struct wl_connection *connection,
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		case 'h':
 | 
							case 'h':
 | 
				
			||||||
 | 
								closure->types[i] = &ffi_type_sint;
 | 
				
			||||||
 | 
								closure->args[i] = extra;
 | 
				
			||||||
 | 
								fd_ptr = (int *) extra;
 | 
				
			||||||
 | 
								extra += sizeof *fd_ptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			fd = va_arg(ap, int);
 | 
								fd = va_arg(ap, int);
 | 
				
			||||||
			dup_fd = dup(fd);
 | 
								dup_fd = dup(fd);
 | 
				
			||||||
			if (dup_fd < 0) {
 | 
								if (dup_fd < 0) {
 | 
				
			||||||
				fprintf(stderr, "dup failed: %m");
 | 
									fprintf(stderr, "dup failed: %m");
 | 
				
			||||||
				abort();
 | 
									abort();
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								*fd_ptr = dup_fd;
 | 
				
			||||||
			wl_buffer_put(&connection->fds_out,
 | 
								wl_buffer_put(&connection->fds_out,
 | 
				
			||||||
				      &dup_fd, sizeof dup_fd);
 | 
									      &dup_fd, sizeof dup_fd);
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
| 
						 | 
					@ -487,7 +493,7 @@ wl_connection_demarshal(struct wl_connection *connection,
 | 
				
			||||||
	int i, count, extra_space;
 | 
						int i, count, extra_space;
 | 
				
			||||||
	struct wl_object **object;
 | 
						struct wl_object **object;
 | 
				
			||||||
	struct wl_array **array;
 | 
						struct wl_array **array;
 | 
				
			||||||
	struct wl_closure *closure = &connection->closure;
 | 
						struct wl_closure *closure = &connection->receive_closure;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	count = strlen(message->signature) + 2;
 | 
						count = strlen(message->signature) + 2;
 | 
				
			||||||
	if (count > ARRAY_LENGTH(closure->types)) {
 | 
						if (count > ARRAY_LENGTH(closure->types)) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -188,6 +188,21 @@ struct wl_drag {
 | 
				
			||||||
	struct wl_listener drag_focus_listener;
 | 
						struct wl_listener drag_focus_listener;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wl_selection_offer {
 | 
				
			||||||
 | 
						struct wl_object object;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wl_selection {
 | 
				
			||||||
 | 
						struct wl_resource resource;
 | 
				
			||||||
 | 
						struct wl_client *client;
 | 
				
			||||||
 | 
						struct wl_input_device *input_device;
 | 
				
			||||||
 | 
						struct wl_selection_offer selection_offer;
 | 
				
			||||||
 | 
						struct wl_surface *selection_focus;
 | 
				
			||||||
 | 
						struct wl_client *target;
 | 
				
			||||||
 | 
						struct wl_array types;
 | 
				
			||||||
 | 
						struct wl_listener selection_focus_listener;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
wl_client_post_event(struct wl_client *client,
 | 
					wl_client_post_event(struct wl_client *client,
 | 
				
			||||||
		      struct wl_object *sender,
 | 
							      struct wl_object *sender,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue