diff options
| author | Kristian Høgsberg <krh@bitplanet.net> | 2011-02-14 22:17:41 -0500 |
|---|---|---|
| committer | Kristian Høgsberg <krh@bitplanet.net> | 2011-02-14 22:21:13 -0500 |
| commit | fcfb4e30a47a4cd2416dac210521594b489c8bfd (patch) | |
| tree | e940236740627c99898ad726246226977c9d7af8 /compositor | |
| parent | compositor: Clip repaint to the damage region (diff) | |
| download | wayland-fcfb4e30a47a4cd2416dac210521594b489c8bfd.tar wayland-fcfb4e30a47a4cd2416dac210521594b489c8bfd.tar.gz wayland-fcfb4e30a47a4cd2416dac210521594b489c8bfd.tar.bz2 wayland-fcfb4e30a47a4cd2416dac210521594b489c8bfd.tar.lz wayland-fcfb4e30a47a4cd2416dac210521594b489c8bfd.tar.xz wayland-fcfb4e30a47a4cd2416dac210521594b489c8bfd.tar.zst wayland-fcfb4e30a47a4cd2416dac210521594b489c8bfd.zip | |
Split into a core repository that only holds the core Wayland libraries
Diffstat (limited to 'compositor')
| -rw-r--r-- | compositor/.gitignore | 3 | ||||
| -rw-r--r-- | compositor/70-wayland.rules | 7 | ||||
| -rw-r--r-- | compositor/Makefile.am | 55 | ||||
| -rw-r--r-- | compositor/compositor-drm.c | 383 | ||||
| -rw-r--r-- | compositor/compositor-wayland.c | 542 | ||||
| -rw-r--r-- | compositor/compositor-x11.c | 795 | ||||
| -rw-r--r-- | compositor/compositor.c | 1411 | ||||
| -rw-r--r-- | compositor/compositor.h | 269 | ||||
| -rw-r--r-- | compositor/drm.c | 246 | ||||
| -rw-r--r-- | compositor/evdev.c | 239 | ||||
| -rw-r--r-- | compositor/screenshooter.c | 88 | ||||
| -rw-r--r-- | compositor/shell.c | 676 | ||||
| -rw-r--r-- | compositor/shm.c | 174 | ||||
| -rw-r--r-- | compositor/tty.c | 160 |
14 files changed, 0 insertions, 5048 deletions
diff --git a/compositor/.gitignore b/compositor/.gitignore deleted file mode 100644 index dc926c1..0000000 --- a/compositor/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -compositor -screenshooter-protocol.c -screenshooter-server-protocol.h diff --git a/compositor/70-wayland.rules b/compositor/70-wayland.rules deleted file mode 100644 index 1b7ca66..0000000 --- a/compositor/70-wayland.rules +++ /dev/null @@ -1,7 +0,0 @@ -KERNEL=="event*", ENV{ID_INPUT_KEYBOARD}=="1", ENV{WAYLAND_SEAT}="1" -KERNEL=="event*", ENV{ID_INPUT_MOUSE}=="1", ENV{WAYLAND_SEAT}="1" -KERNEL=="event*", ENV{ID_INPUT_TOUCHPAD}=="1", ENV{WAYLAND_SEAT}="1" -KERNEL=="event*", ENV{ID_INPUT_TOUCHSCREEN}=="1", ENV{WAYLAND_SEAT}="1" -KERNEL=="event*", ENV{ID_INPUT_TABLET}=="1", ENV{WAYLAND_SEAT}="1" -KERNEL=="card0", ENV{WAYLAND_SEAT}="1" - diff --git a/compositor/Makefile.am b/compositor/Makefile.am deleted file mode 100644 index d2baa43..0000000 --- a/compositor/Makefile.am +++ /dev/null @@ -1,55 +0,0 @@ -noinst_PROGRAMS = compositor - -AM_CPPFLAGS = \ - -DDATADIR='"$(datadir)"' \ - -I$(top_builddir)/wayland \ - -I$(top_srcdir)/wayland \ - $(COMPOSITOR_CFLAGS) - -AM_CFLAGS = $(GCC_CFLAGS) - -compositor_LDADD = \ - $(top_builddir)/wayland/libwayland-server.la \ - $(top_builddir)/wayland/libwayland-client.la \ - $(COMPOSITOR_LIBS) - -if ENABLE_DRM_COMPOSITOR -drm_compositor_sources = compositor-drm.c tty.c evdev.c -drm_sources = drm.c -endif - -if ENABLE_X11_COMPOSITOR -x11_compositor_sources = compositor-x11.c -drm_sources = drm.c -endif - -if ENABLE_WAYLAND_COMPOSITOR -wayland_compositor_sources = compositor-wayland.c -drm_sources = drm.c -endif - -compositor_SOURCES = \ - compositor.c \ - compositor.h \ - shell.c \ - screenshooter.c \ - screenshooter-protocol.c \ - screenshooter-server-protocol.h \ - shm.c \ - $(drm_compositor_sources) \ - $(x11_compositor_sources) \ - $(wayland_compositor_sources) \ - $(drm_sources) - -udevrulesddir = $(sysconfdir)/udev/rules.d - -dist_udevrulesd_DATA = \ - 70-wayland.rules - -BUILT_SOURCES = \ - screenshooter-server-protocol.h \ - screenshooter-protocol.c - -CLEANFILES = $(BUILT_SOURCES) - -include $(top_srcdir)/wayland/scanner.mk diff --git a/compositor/compositor-drm.c b/compositor/compositor-drm.c deleted file mode 100644 index 50f353b..0000000 --- a/compositor/compositor-drm.c +++ /dev/null @@ -1,383 +0,0 @@ -/* - * Copyright © 2008-2010 Kristian Høgsberg - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <fcntl.h> -#include <unistd.h> - -#define GL_GLEXT_PROTOTYPES -#define EGL_EGLEXT_PROTOTYPES -#include <GLES2/gl2.h> -#include <GLES2/gl2ext.h> -#include <EGL/egl.h> -#include <EGL/eglext.h> - -#include "compositor.h" - -struct drm_compositor { - struct wlsc_compositor base; - - struct udev *udev; - struct wl_event_source *drm_source; - - struct tty *tty; -}; - -struct drm_output { - struct wlsc_output base; - - drmModeModeInfo mode; - uint32_t crtc_id; - uint32_t connector_id; - GLuint rbo[2]; - uint32_t fb_id[2]; - EGLImageKHR image[2]; - uint32_t current; -}; - -static void -drm_compositor_present(struct wlsc_compositor *ec) -{ - struct drm_compositor *c = (struct drm_compositor *) ec; - struct drm_output *output; - - wl_list_for_each(output, &ec->output_list, base.link) { - output->current ^= 1; - - glFramebufferRenderbuffer(GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_RENDERBUFFER, - output->rbo[output->current]); - glFlush(); - - drmModePageFlip(c->base.drm.fd, output->crtc_id, - output->fb_id[output->current ^ 1], - DRM_MODE_PAGE_FLIP_EVENT, output); - } -} - -static void -page_flip_handler(int fd, unsigned int frame, - unsigned int sec, unsigned int usec, void *data) -{ - struct wlsc_output *output = data; - struct wlsc_compositor *compositor = output->compositor; - uint32_t msecs; - - msecs = sec * 1000 + usec / 1000; - wlsc_compositor_finish_frame(compositor, msecs); -} - -static void -on_drm_input(int fd, uint32_t mask, void *data) -{ - drmEventContext evctx; - - memset(&evctx, 0, sizeof evctx); - evctx.version = DRM_EVENT_CONTEXT_VERSION; - evctx.page_flip_handler = page_flip_handler; - drmHandleEvent(fd, &evctx); -} - -static int -init_egl(struct drm_compositor *ec, struct udev_device *device) -{ - EGLint major, minor; - const char *extensions, *filename; - int fd; - static const EGLint context_attribs[] = { - EGL_CONTEXT_CLIENT_VERSION, 2, - EGL_NONE - }; - - filename = udev_device_get_devnode(device); - fd = open(filename, O_RDWR); - if (fd < 0) { - /* Probably permissions error */ - fprintf(stderr, "couldn't open %s, skipping\n", - udev_device_get_devnode(device)); - return -1; - } - - wlsc_drm_init(&ec->base, fd, filename); - - ec->base.display = eglGetDRMDisplayMESA(ec->base.drm.fd); - if (ec->base.display == NULL) { - fprintf(stderr, "failed to create display\n"); - return -1; - } - - if (!eglInitialize(ec->base.display, &major, &minor)) { - fprintf(stderr, "failed to initialize display\n"); - return -1; - } - - extensions = eglQueryString(ec->base.display, EGL_EXTENSIONS); - if (!strstr(extensions, "EGL_KHR_surfaceless_opengl")) { - fprintf(stderr, "EGL_KHR_surfaceless_opengl not available\n"); - return -1; - } - - if (!eglBindAPI(EGL_OPENGL_ES_API)) { - fprintf(stderr, "failed to bind api EGL_OPENGL_ES_API\n"); - return -1; - } - - ec->base.context = eglCreateContext(ec->base.display, NULL, - EGL_NO_CONTEXT, context_attribs); - if (ec->base.context == NULL) { - fprintf(stderr, "failed to create context\n"); - return -1; - } - - if (!eglMakeCurrent(ec->base.display, EGL_NO_SURFACE, - EGL_NO_SURFACE, ec->base.context)) { - fprintf(stderr, "failed to make context current\n"); - return -1; - } - - return 0; -} - -static drmModeModeInfo builtin_1024x768 = { - 63500, /* clock */ - 1024, 1072, 1176, 1328, 0, - 768, 771, 775, 798, 0, - 59920, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC, - 0, - "1024x768" -}; - -static int -create_output_for_connector(struct drm_compositor *ec, - drmModeRes *resources, - drmModeConnector *connector) -{ - struct drm_output *output; - drmModeEncoder *encoder; - drmModeModeInfo *mode; - int i, ret; - EGLint handle, stride, attribs[] = { - EGL_WIDTH, 0, - EGL_HEIGHT, 0, - EGL_DRM_BUFFER_FORMAT_MESA, EGL_DRM_BUFFER_FORMAT_ARGB32_MESA, - EGL_DRM_BUFFER_USE_MESA, EGL_DRM_BUFFER_USE_SCANOUT_MESA, - EGL_NONE - }; - - output = malloc(sizeof *output); - if (output == NULL) - return -1; - - if (connector->count_modes > 0) - mode = &connector->modes[0]; - else - mode = &builtin_1024x768; - - encoder = drmModeGetEncoder(ec->base.drm.fd, connector->encoders[0]); - if (encoder == NULL) { - fprintf(stderr, "No encoder for connector.\n"); - return -1; - } - - for (i = 0; i < resources->count_crtcs; i++) { - if (encoder->possible_crtcs & (1 << i)) - break; - } - if (i == resources->count_crtcs) { - fprintf(stderr, "No usable crtc for encoder.\n"); - return -1; - } - - memset(output, 0, sizeof *output); - wlsc_output_init(&output->base, &ec->base, 0, 0, - mode->hdisplay, mode->vdisplay); - - output->crtc_id = resources->crtcs[i]; - output->connector_id = connector->connector_id; - output->mode = *mode; - - drmModeFreeEncoder(encoder); - - glGenRenderbuffers(2, output->rbo); - for (i = 0; i < 2; i++) { - glBindRenderbuffer(GL_RENDERBUFFER, output->rbo[i]); - - attribs[1] = output->base.width; - attribs[3] = output->base.height; - output->image[i] = - eglCreateDRMImageMESA(ec->base.display, attribs); - glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, - output->image[i]); - eglExportDRMImageMESA(ec->base.display, output->image[i], - NULL, &handle, &stride); - - ret = drmModeAddFB(ec->base.drm.fd, - output->base.width, output->base.height, - 32, 32, stride, handle, &output->fb_id[i]); - if (ret) { - fprintf(stderr, "failed to add fb %d: %m\n", i); - return -1; - } - } - - output->current = 0; - glFramebufferRenderbuffer(GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_RENDERBUFFER, - output->rbo[output->current]); - ret = drmModeSetCrtc(ec->base.drm.fd, output->crtc_id, - output->fb_id[output->current ^ 1], 0, 0, - &output->connector_id, 1, &output->mode); - if (ret) { - fprintf(stderr, "failed to set mode: %m\n"); - return -1; - } - - wl_list_insert(ec->base.output_list.prev, &output->base.link); - - return 0; -} - -static int -create_outputs(struct drm_compositor *ec, int option_connector) -{ - drmModeConnector *connector; - drmModeRes *resources; - int i; - - resources = drmModeGetResources(ec->base.drm.fd); - if (!resources) { - fprintf(stderr, "drmModeGetResources failed\n"); - return -1; - } - - for (i = 0; i < resources->count_connectors; i++) { - connector = drmModeGetConnector(ec->base.drm.fd, resources->connectors[i]); - if (connector == NULL) - continue; - - if (connector->connection == DRM_MODE_CONNECTED && - (option_connector == 0 || - connector->connector_id == option_connector)) - if (create_output_for_connector(ec, resources, connector) < 0) - return -1; - - drmModeFreeConnector(connector); - } - - if (wl_list_empty(&ec->base.output_list)) { - fprintf(stderr, "No currently active connector found.\n"); - return -1; - } - - drmModeFreeResources(resources); - - return 0; -} - -static int -drm_authenticate(struct wlsc_compositor *c, uint32_t id) -{ - struct drm_compositor *ec = (struct drm_compositor *) c; - - return drmAuthMagic(ec->base.drm.fd, id); -} - -static void -drm_destroy(struct wlsc_compositor *ec) -{ - struct drm_compositor *d = (struct drm_compositor *) ec; - - tty_destroy(d->tty); - - free(d); -} - -struct wlsc_compositor * -drm_compositor_create(struct wl_display *display, int connector) -{ - struct drm_compositor *ec; - struct udev_enumerate *e; - struct udev_list_entry *entry; - struct udev_device *device; - const char *path; - struct wl_event_loop *loop; - - ec = malloc(sizeof *ec); - if (ec == NULL) - return NULL; - - memset(ec, 0, sizeof *ec); - ec->udev = udev_new(); - if (ec->udev == NULL) { - fprintf(stderr, "failed to initialize udev context\n"); - return NULL; - } - - e = udev_enumerate_new(ec->udev); - udev_enumerate_add_match_subsystem(e, "drm"); - udev_enumerate_add_match_property(e, "WAYLAND_SEAT", "1"); - udev_enumerate_scan_devices(e); - device = NULL; - udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) { - path = udev_list_entry_get_name(entry); - device = udev_device_new_from_syspath(ec->udev, path); - break; - } - udev_enumerate_unref(e); - - if (device == NULL) { - fprintf(stderr, "no drm device found\n"); - return NULL; - } - - ec->base.wl_display = display; - if (init_egl(ec, device) < 0) { - fprintf(stderr, "failed to initialize egl\n"); - return NULL; - } - - ec->base.destroy = drm_destroy; - ec->base.authenticate = drm_authenticate; - ec->base.present = drm_compositor_present; - ec->base.create_buffer = wlsc_drm_buffer_create; - ec->base.focus = 1; - - /* Can't init base class until we have a current egl context */ - if (wlsc_compositor_init(&ec->base, display) < 0) - return NULL; - - if (create_outputs(ec, connector) < 0) { - fprintf(stderr, "failed to create output for %s\n", path); - return NULL; - } - - evdev_input_add_devices(&ec->base, ec->udev); - - loop = wl_display_get_event_loop(ec->base.wl_display); - ec->drm_source = - wl_event_loop_add_fd(loop, ec->base.drm.fd, - WL_EVENT_READABLE, on_drm_input, ec); - ec->tty = tty_create(&ec->base); - - return &ec->base; -} diff --git a/compositor/compositor-wayland.c b/compositor/compositor-wayland.c deleted file mode 100644 index 11320d8..0000000 --- a/compositor/compositor-wayland.c +++ /dev/null @@ -1,542 +0,0 @@ -/* - * Copyright © 2010 Benjamin Franzke - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stddef.h> -#define _GNU_SOURCE -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <fcntl.h> -#include <unistd.h> - -#include "wayland-client.h" - -#define GL_GLEXT_PROTOTYPES -#define EGL_EGLEXT_PROTOTYPES -#include <GLES2/gl2.h> -#include <GLES2/gl2ext.h> -#include <EGL/egl.h> -#include <EGL/eglext.h> - -#include "compositor.h" - -struct wayland_compositor { - struct wlsc_compositor base; - - struct { - struct wl_display *display; - struct wl_compositor *compositor; - struct wl_shell *shell; - struct wl_drm *drm; - struct wl_output *output; - - struct { - int32_t x, y, width, height; - } screen_allocation; - - char *device_name; - int authenticated; - - struct wl_event_source *wl_source; - uint32_t event_mask; - } parent; - - struct wl_list input_list; -}; - -struct wayland_output { - struct wlsc_output base; - - struct { - struct wl_surface *surface; - struct wl_buffer *buffer[2]; - } parent; - EGLImageKHR image[2]; - GLuint rbo[2]; - uint32_t fb_id[2]; - uint32_t current; -}; - -struct wayland_input { - struct wayland_compositor *compositor; - struct wl_input_device *input_device; - struct wl_list link; -}; - -static int -wayland_input_create(struct wayland_compositor *c) -{ - struct wlsc_input_device *input; - - input = malloc(sizeof *input); - if (input == NULL) - return -1; - - memset(input, 0, sizeof *input); - wlsc_input_device_init(input, &c->base); - - c->base.input_device = &input->input_device; - - return 0; -} - -static int -wayland_compositor_init_egl(struct wayland_compositor *c) -{ - EGLint major, minor; - const char *extensions; - drm_magic_t magic; - int fd; - static const EGLint context_attribs[] = { - EGL_CONTEXT_CLIENT_VERSION, 2, - EGL_NONE - }; - - fd = open(c->parent.device_name, O_RDWR); - if (fd < 0) { - fprintf(stderr, "drm open failed: %m\n"); - return -1; - } - - wlsc_drm_init(&c->base, fd, c->parent.device_name); - - if (drmGetMagic(fd, &magic)) { - fprintf(stderr, "DRI2: failed to get drm magic"); - return -1; - } - - wl_drm_authenticate(c->parent.drm, magic); - wl_display_iterate(c->parent.display, WL_DISPLAY_WRITABLE); - while (!c->parent.authenticated) - wl_display_iterate(c->parent.display, WL_DISPLAY_READABLE); - - c->base.display = eglGetDRMDisplayMESA(fd); - if (c->base.display == NULL) { - fprintf(stderr, "failed to create display\n"); - return -1; - } - - if (!eglInitialize(c->base.display, &major, &minor)) { - fprintf(stderr, "failed to initialize display\n"); - return -1; - } - - extensions = eglQueryString(c->base.display, EGL_EXTENSIONS); - if (!strstr(extensions, "EGL_KHR_surfaceless_opengl")) { - fprintf(stderr, "EGL_KHR_surfaceless_opengl not available\n"); - return -1; - } - - if (!eglBindAPI(EGL_OPENGL_ES_API)) { - fprintf(stderr, "failed to bind EGL_OPENGL_ES_API\n"); - return -1; - } - - c->base.context = eglCreateContext(c->base.display, NULL, - EGL_NO_CONTEXT, context_attribs); - if (c->base.context == NULL) { - fprintf(stderr, "failed to create context\n"); - return -1; - } - - if (!eglMakeCurrent(c->base.display, EGL_NO_SURFACE, - EGL_NO_SURFACE, c->base.context)) { - fprintf(stderr, "failed to make context current\n"); - return -1; - } - - return 0; -} - -static void -frame_callback(void *data, uint32_t time) -{ - struct wayland_compositor *c = (struct wayland_compositor *) data; - - wlsc_compositor_finish_frame(&c->base, time); -} - -static void -wayland_compositor_present(struct wlsc_compositor *base) -{ - struct wayland_compositor *c = (struct wayland_compositor *) base; - struct wayland_output *output; - - glFlush(); - - wl_list_for_each(output, &base->output_list, base.link) { - output->current ^= 1; - - glFramebufferRenderbuffer(GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_RENDERBUFFER, - output->rbo[output->current]); - - wl_surface_attach(output->parent.surface, - output->parent.buffer[output->current ^ 1], - 0, 0); - wl_surface_damage(output->parent.surface, 0, 0, - output->base.width, output->base.height); - } - - wl_display_frame_callback(c->parent.display, frame_callback, c); -} - -static int -wayland_authenticate(struct wlsc_compositor *ec, uint32_t id) -{ - struct wayland_compositor *c = (struct wayland_compositor *) ec; - - wl_drm_authenticate(c->parent.drm, id); - /* FIXME: recv drm_authenticated event from parent? */ - wl_display_iterate(c->parent.display, WL_DISPLAY_WRITABLE); - - return 0; -} - -static int -wayland_compositor_create_output(struct wayland_compositor *c, - int width, int height) -{ - struct wayland_output *output; - struct wl_visual *visual; - int i; - EGLint name, stride, attribs[] = { - EGL_WIDTH, 0, - EGL_HEIGHT, 0, - EGL_DRM_BUFFER_FORMAT_MESA, EGL_DRM_BUFFER_FORMAT_ARGB32_MESA, - EGL_DRM_BUFFER_USE_MESA, EGL_DRM_BUFFER_USE_SCANOUT_MESA, - EGL_NONE - }; - - output = malloc(sizeof *output); - if (output == NULL) - return -1; - memset(output, 0, sizeof *output); - - wlsc_output_init(&output->base, &c->base, 0, 0, width, height); - output->parent.surface = - wl_compositor_create_surface(c->parent.compositor); - wl_surface_set_user_data(output->parent.surface, output); - - glGenRenderbuffers(2, output->rbo); - visual = wl_display_get_premultiplied_argb_visual(c->parent.display); - for (i = 0; i < 2; i++) { - glBindRenderbuffer(GL_RENDERBUFFER, output->rbo[i]); - - attribs[1] = width; - attribs[3] = height; - output->image[i] = - eglCreateDRMImageMESA(c->base.display, attribs); - glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, - output->image[i]); - eglExportDRMImageMESA(c->base.display, output->image[i], - &name, NULL, &stride); - output->parent.buffer[i] = - wl_drm_create_buffer(c->parent.drm, name, - width, height, - stride, visual); - } - - output->current = 0; - glFramebufferRenderbuffer(GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_RENDERBUFFER, - output->rbo[output->current]); - - wl_surface_attach(output->parent.surface, - output->parent.buffer[output->current], 0, 0); - wl_surface_map_toplevel(output->parent.surface); - - glClearColor(0, 0, 0, 0.5); - - wl_list_insert(c->base.output_list.prev, &output->base.link); - - return 0; -} - -/* Events received from the wayland-server this compositor is client of: */ - -/* parent output interface */ -static void -display_handle_geometry(void *data, - struct wl_output *output, - int32_t x, int32_t y, - int32_t width, int32_t height) -{ - struct wayland_compositor *c = data; - - c->parent.screen_allocation.x = x; - c->parent.screen_allocation.y = y; - c->parent.screen_allocation.width = width; - c->parent.screen_allocation.height = height; -} - -static const struct wl_output_listener output_listener = { - display_handle_geometry, -}; - -/* parent shell interface */ -static void -handle_configure(void *data, struct wl_shell *shell, - uint32_t time, uint32_t edges, - struct wl_surface *surface, int32_t width, int32_t height) -{ -#if 0 - struct output *output = wl_surface_get_user_data(surface); - - /* FIXME: add resize? */ -#endif -} - -static const struct wl_shell_listener shell_listener = { - handle_configure, -}; - -/* parent drm interface */ -static void -drm_handle_device(void *data, struct wl_drm *drm, const char *device) -{ - struct wayland_compositor *c = data; - - c->parent.device_name = strdup(device); -} - -static void drm_handle_authenticated(void *data, struct wl_drm *drm) -{ - struct wayland_compositor *c = data; - - c->parent.authenticated = 1; -} - -static const struct wl_drm_listener drm_listener = { - drm_handle_device, - drm_handle_authenticated -}; - -/* parent input interface */ -static void -input_handle_motion(void *data, struct wl_input_device *input_device, - uint32_t time, - int32_t x, int32_t y, int32_t sx, int32_t sy) -{ - struct wayland_input *input = data; - struct wayland_compositor *c = input->compositor; - - notify_motion(c->base.input_device, time, sx, sy); -} - -static void -input_handle_button(void *data, - struct wl_input_device *input_device, - uint32_t time, uint32_t button, uint32_t state) -{ - struct wayland_input *input = data; - struct wayland_compositor *c = input->compositor; - - notify_button(c->base.input_device, time, button, state); -} - -static void -input_handle_key(void *data, struct wl_input_device *input_device, - uint32_t time, uint32_t key, uint32_t state) -{ - struct wayland_input *input = data; - struct wayland_compositor *c = input->compositor; - - notify_key(c->base.input_device, time, key, state); -} - -static void -input_handle_pointer_focus(void *data, - struct wl_input_device *input_device, - uint32_t time, struct wl_surface *surface, - int32_t x, int32_t y, int32_t sx, int32_t sy) -{ - struct wayland_input *input = data; - struct wayland_output *output; - struct wayland_compositor *c = input->compositor; - - if (surface) { - output = wl_surface_get_user_data(surface); - notify_pointer_focus(c->base.input_device, - time, &output->base, sx, sy); - } else { - notify_pointer_focus(c->base.input_device, time, NULL, 0, 0); - } -} - -static void -input_handle_keyboard_focus(void *data, - struct wl_input_device *input_device, - uint32_t time, - struct wl_surface *surface, - struct wl_array *keys) -{ - struct wayland_input *input = data; - struct wayland_compositor *c = input->compositor; - struct wayland_output *output; - - if (surface) { - output = wl_surface_get_user_data(surface); - notify_keyboard_focus(c->base.input_device, - time, &output->base, keys); - } else { - notify_keyboard_focus(c->base.input_device, time, NULL, NULL); - } -} - -static const struct wl_input_device_listener input_device_listener = { - input_handle_motion, - input_handle_button, - input_handle_key, - input_handle_pointer_focus, - input_handle_keyboard_focus, -}; - -static void -display_add_input(struct wayland_compositor *c, uint32_t id) -{ - struct wayland_input *input; - - input = malloc(sizeof *input); - if (input == NULL) - return; - - memset(input, 0, sizeof *input); - - input->compositor = c; - input->input_device = wl_input_device_create(c->parent.display, id); - wl_list_insert(c->input_list.prev, &input->link); - - wl_input_device_add_listener(input->input_device, - &input_device_listener, input); - wl_input_device_set_user_data(input->input_device, input); -} - -static void -display_handle_global(struct wl_display *display, uint32_t id, - const char *interface, uint32_t version, void *data) -{ - struct wayland_compositor *c = data; - - if (strcmp(interface, "compositor") == 0) { - c->parent.compositor = wl_compositor_create(display, id); - } else if (strcmp(interface, "output") == 0) { - c->parent.output = wl_output_create(display, id); - wl_output_add_listener(c->parent.output, &output_listener, c); - } else if (strcmp(interface, "input_device") == 0) { - display_add_input(c, id); - } else if (strcmp(interface, "shell") == 0) { - c->parent.shell = wl_shell_create(display, id); - wl_shell_add_listener(c->parent.shell, &shell_listener, c); - } else if (strcmp(interface, "drm") == 0) { - c->parent.drm = wl_drm_create(display, id); - wl_drm_add_listener(c->parent.drm, &drm_listener, c); - } -} - -static int -update_event_mask(uint32_t mask, void *data) -{ - struct wayland_compositor *c = data; - - c->parent.event_mask = mask; - if (c->parent.wl_source) - wl_event_source_fd_update(c->parent.wl_source, mask); - - return 0; -} - -static void -wayland_compositor_handle_event(int fd, uint32_t mask, void *data) -{ - struct wayland_compositor *c = data; - - if (mask & WL_EVENT_READABLE) - wl_display_iterate(c->parent.display, WL_DISPLAY_READABLE); - if (mask & WL_EVENT_WRITEABLE) - wl_display_iterate(c->parent.display, WL_DISPLAY_WRITABLE); -} - -static void -wayland_destroy(struct wlsc_compositor *ec) -{ - free(ec); -} - -struct wlsc_compositor * -wayland_compositor_create(struct wl_display *display, int width, int height) -{ - struct wayland_compositor *c; - struct wl_event_loop *loop; - int fd; - - c = malloc(sizeof *c); - if (c == NULL) - return NULL; - - memset(c, 0, sizeof *c); - - c->parent.display = wl_display_connect(NULL); - - if (c->parent.display == NULL) { - fprintf(stderr, "failed to create display: %m\n"); - return NULL; - } - - wl_list_init(&c->input_list); - wl_display_add_global_listener(c->parent.display, - display_handle_global, c); - - wl_display_iterate(c->parent.display, WL_DISPLAY_READABLE); - - c->base.wl_display = display; - if (wayland_compositor_init_egl(c) < 0) - return NULL; - - c->base.destroy = wayland_destroy; - c->base.authenticate = wayland_authenticate; - c->base.present = wayland_compositor_present; - c->base.create_buffer = wlsc_drm_buffer_create; - - /* Can't init base class until we have a current egl context */ - if (wlsc_compositor_init(&c->base, display) < 0) - return NULL; - - if (wayland_compositor_create_output(c, width, height) < 0) - return NULL; - - if (wayland_input_create(c) < 0) - return NULL; - - loop = wl_display_get_event_loop(c->base.wl_display); - - fd = wl_display_get_fd(c->parent.display, update_event_mask, c); - c->parent.wl_source = - wl_event_loop_add_fd(loop, fd, c->parent.event_mask, - wayland_compositor_handle_event, c); - if (c->parent.wl_source == NULL) - return NULL; - - return &c->base; -} diff --git a/compositor/compositor-x11.c b/compositor/compositor-x11.c deleted file mode 100644 index 4365c0a..0000000 --- a/compositor/compositor-x11.c +++ /dev/null @@ -1,795 +0,0 @@ -/* - * Copyright © 2008-2010 Kristian Høgsberg - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stddef.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <fcntl.h> -#include <unistd.h> -#include <errno.h> -#include <sys/time.h> -#include <linux/input.h> - -#include <xcb/xcb.h> -#include <xcb/dri2.h> -#include <xcb/xfixes.h> - -#define GL_GLEXT_PROTOTYPES -#define EGL_EGLEXT_PROTOTYPES -#include <GLES2/gl2.h> -#include <GLES2/gl2ext.h> -#include <EGL/egl.h> -#include <EGL/eglext.h> - -#include "compositor.h" - -#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0])) - -struct x11_compositor { - struct wlsc_compositor base; - - xcb_connection_t *conn; - xcb_screen_t *screen; - xcb_cursor_t null_cursor; - int dri2_major; - int dri2_minor; - struct wl_array keys; - struct wl_event_source *xcb_source; - struct { - xcb_atom_t wm_protocols; - xcb_atom_t wm_normal_hints; - xcb_atom_t wm_size_hints; - xcb_atom_t wm_delete_window; - xcb_atom_t wm_class; - xcb_atom_t net_wm_name; - xcb_atom_t net_wm_icon; - xcb_atom_t string; - xcb_atom_t utf8_string; - xcb_atom_t cardinal; - } atom; -}; - -struct x11_output { - struct wlsc_output base; - - xcb_xfixes_region_t region; - xcb_window_t window; - GLuint rbo; - EGLImageKHR image; - xcb_rectangle_t damage[16]; - int damage_count; -}; - -struct x11_input { - struct wlsc_input_device base; -}; - - -static int -x11_input_create(struct x11_compositor *c) -{ - struct x11_input *input; - - input = malloc(sizeof *input); - if (input == NULL) - return -1; - - memset(input, 0, sizeof *input); - wlsc_input_device_init(&input->base, &c->base); - - c->base.input_device = &input->base.input_device; - - return 0; -} - - -static int -dri2_connect(struct x11_compositor *c) -{ - xcb_xfixes_query_version_reply_t *xfixes_query; - xcb_xfixes_query_version_cookie_t xfixes_query_cookie; - xcb_dri2_query_version_reply_t *dri2_query; - xcb_dri2_query_version_cookie_t dri2_query_cookie; - xcb_dri2_connect_reply_t *connect; - xcb_dri2_connect_cookie_t connect_cookie; - xcb_generic_error_t *error; - char path[256]; - int fd; - - xcb_prefetch_extension_data (c->conn, &xcb_xfixes_id); - xcb_prefetch_extension_data (c->conn, &xcb_dri2_id); - - xfixes_query_cookie = - xcb_xfixes_query_version(c->conn, - XCB_XFIXES_MAJOR_VERSION, - XCB_XFIXES_MINOR_VERSION); - - dri2_query_cookie = - xcb_dri2_query_version (c->conn, - XCB_DRI2_MAJOR_VERSION, - XCB_DRI2_MINOR_VERSION); - - connect_cookie = xcb_dri2_connect_unchecked (c->conn, - c->screen->root, - XCB_DRI2_DRIVER_TYPE_DRI); - - xfixes_query = - xcb_xfixes_query_version_reply (c->conn, - xfixes_query_cookie, &error); - if (xfixes_query == NULL || - error != NULL || xfixes_query->major_version < 2) { - free(error); - return -1; - } - free(xfixes_query); - - dri2_query = - xcb_dri2_query_version_reply (c->conn, - dri2_query_cookie, &error); - if (dri2_query == NULL || error != NULL) { - fprintf(stderr, "DRI2: failed to query version\n"); - free(error); - return EGL_FALSE; - } - c->dri2_major = dri2_query->major_version; - c->dri2_minor = dri2_query->minor_version; - free(dri2_query); - - connect = xcb_dri2_connect_reply (c->conn, - connect_cookie, NULL); - if (connect == NULL || - connect->driver_name_length + connect->device_name_length == 0) { - fprintf(stderr, "DRI2: failed to connect, DRI2 version: %u.%u\n", - c->dri2_major, c->dri2_minor); - return -1; - } - -#ifdef XCB_DRI2_CONNECT_DEVICE_NAME_BROKEN - { - char *driver_name, *device_name; - - driver_name = xcb_dri2_connect_driver_name (connect); - device_name = driver_name + - ((connect->driver_name_length + 3) & ~3); - snprintf(path, sizeof path, "%.*s", - xcb_dri2_connect_device_name_length (connect), - device_name); - } -#else - snprintf(path, sizeof path, "%.*s", - xcb_dri2_connect_device_name_length (connect), - xcb_dri2_connect_device_name (connect)); -#endif - free(connect); - - fd = open(path, O_RDWR); - if (fd < 0) { - fprintf(stderr, - "DRI2: could not open %s (%s)\n", path, strerror(errno)); - return -1; - } - - return wlsc_drm_init(&c->base, fd, path); -} - -static int -dri2_authenticate(struct x11_compositor *c, uint32_t magic) -{ - xcb_dri2_authenticate_reply_t *authenticate; - xcb_dri2_authenticate_cookie_t authenticate_cookie; - - authenticate_cookie = - xcb_dri2_authenticate_unchecked(c->conn, - c->screen->root, magic); - authenticate = - xcb_dri2_authenticate_reply(c->conn, - authenticate_cookie, NULL); - if (authenticate == NULL || !authenticate->authenticated) { - fprintf(stderr, "DRI2: failed to authenticate\n"); - free(authenticate); - return -1; - } - - free(authenticate); - - return 0; -} - -static int -x11_compositor_init_egl(struct x11_compositor *c) -{ - EGLint major, minor; - const char *extensions; - drm_magic_t magic; - static const EGLint context_attribs[] = { - EGL_CONTEXT_CLIENT_VERSION, 2, - EGL_NONE - }; - - if (dri2_connect(c) < 0) - return -1; - - if (drmGetMagic(c->base.drm.fd, &magic)) { - fprintf(stderr, "DRI2: failed to get drm magic\n"); - return -1; - } - - if (dri2_authenticate(c, magic) < 0) - return -1; - - c->base.display = eglGetDRMDisplayMESA(c->base.drm.fd); - if (c->base.display == NULL) { - fprintf(stderr, "failed to create display\n"); - return -1; - } - - if (!eglInitialize(c->base.display, &major, &minor)) { - fprintf(stderr, "failed to initialize display\n"); - return -1; - } - - extensions = eglQueryString(c->base.display, EGL_EXTENSIONS); - if (!strstr(extensions, "EGL_KHR_surfaceless_opengl")) { - fprintf(stderr, "EGL_KHR_surfaceless_opengl not available\n"); - return -1; - } - - if (!eglBindAPI(EGL_OPENGL_ES_API)) { - fprintf(stderr, "failed to bind EGL_OPENGL_ES_API\n"); - return -1; - } - - c->base.context = eglCreateContext(c->base.display, NULL, - EGL_NO_CONTEXT, context_attribs); - if (c->base.context == NULL) { - fprintf(stderr, "failed to create context\n"); - return -1; - } - - if (!eglMakeCurrent(c->base.display, EGL_NO_SURFACE, - EGL_NO_SURFACE, c->base.context)) { - fprintf(stderr, "failed to make context current\n"); - return -1; - } - - return 0; -} - -static void -x11_compositor_present(struct wlsc_compositor *base) -{ - struct x11_compositor *c = (struct x11_compositor *) base; - struct x11_output *output; - xcb_dri2_copy_region_cookie_t cookie; - struct timeval tv; - uint32_t msec; - - glFlush(); - - wl_list_for_each(output, &c->base.output_list, base.link) { - cookie = xcb_dri2_copy_region_unchecked(c->conn, - output->window, - output->region, - XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT, - XCB_DRI2_ATTACHMENT_BUFFER_BACK_LEFT); - free(xcb_dri2_copy_region_reply(c->conn, cookie, NULL)); - } - - gettimeofday(&tv, NULL); - msec = tv.tv_sec * 1000 + tv.tv_usec / 1000; - wlsc_compositor_finish_frame(&c->base, msec); -} - -static void -x11_output_set_wm_protocols(struct x11_output *output) -{ - xcb_atom_t list[1]; - struct x11_compositor *c = - (struct x11_compositor *) output->base.compositor; - - list[0] = c->atom.wm_delete_window; - xcb_change_property (c->conn, - XCB_PROP_MODE_REPLACE, - output->window, - c->atom.wm_protocols, - XCB_ATOM_ATOM, - 32, - ARRAY_SIZE(list), - list); -} - -struct wm_normal_hints { - uint32_t flags; - uint32_t pad[4]; - int32_t min_width, min_height; - int32_t max_width, max_height; - int32_t width_inc, height_inc; - int32_t min_aspect_x, min_aspect_y; - int32_t max_aspect_x, max_aspect_y; - int32_t base_width, base_height; - int32_t win_gravity; -}; - -#define WM_NORMAL_HINTS_MIN_SIZE 16 -#define WM_NORMAL_HINTS_MAX_SIZE 32 - -static void -x11_output_set_icon(struct x11_compositor *c, struct x11_output *output, - const char *filename, int width, int height) -{ - uint32_t *icon, *pixels; - - pixels = wlsc_load_image(filename, width, height); - if (!pixels) - return; - icon = malloc(width * height * 4 + 8); - if (!icon) { - free(pixels); - return; - } - - icon[0] = width; - icon[1] = height; - memcpy(icon + 2, pixels, width * height * 4); - xcb_change_property(c->conn, XCB_PROP_MODE_REPLACE, output->window, - c->atom.net_wm_icon, c->atom.cardinal, 32, - width * height + 2, icon); - free(icon); - free(pixels); -} - -static int -x11_compositor_create_output(struct x11_compositor *c, int width, int height) -{ - static const char name[] = "Wayland Compositor"; - static const char class[] = "wayland-1\0Wayland Compositor"; - struct x11_output *output; - xcb_dri2_dri2_buffer_t *buffers; - xcb_dri2_get_buffers_reply_t *reply; - xcb_dri2_get_buffers_cookie_t cookie; - xcb_screen_iterator_t iter; - xcb_rectangle_t rectangle; - struct wm_normal_hints normal_hints; - unsigned int attachments[] = - { XCB_DRI2_ATTACHMENT_BUFFER_BACK_LEFT}; - uint32_t mask = XCB_CW_EVENT_MASK | XCB_CW_CURSOR; - uint32_t values[2] = { - XCB_EVENT_MASK_KEY_PRESS | - XCB_EVENT_MASK_KEY_RELEASE | - XCB_EVENT_MASK_BUTTON_PRESS | - XCB_EVENT_MASK_BUTTON_RELEASE | - XCB_EVENT_MASK_POINTER_MOTION | - XCB_EVENT_MASK_EXPOSURE | - XCB_EVENT_MASK_STRUCTURE_NOTIFY | - XCB_EVENT_MASK_ENTER_WINDOW | - XCB_EVENT_MASK_LEAVE_WINDOW | - XCB_EVENT_MASK_KEYMAP_STATE | - XCB_EVENT_MASK_FOCUS_CHANGE, - 0 - }; - - EGLint attribs[] = { - EGL_WIDTH, 0, - EGL_HEIGHT, 0, - EGL_DRM_BUFFER_STRIDE_MESA, 0, - EGL_DRM_BUFFER_FORMAT_MESA, EGL_DRM_BUFFER_FORMAT_ARGB32_MESA, - EGL_NONE - }; - - output = malloc(sizeof *output); - if (output == NULL) - return -1; - - memset(output, 0, sizeof *output); - wlsc_output_init(&output->base, &c->base, 0, 0, width, height); - - values[1] = c->null_cursor; - output->window = xcb_generate_id(c->conn); - iter = xcb_setup_roots_iterator(xcb_get_setup(c->conn)); - xcb_create_window(c->conn, - XCB_COPY_FROM_PARENT, - output->window, - iter.data->root, - 0, 0, - width, height, - 0, - XCB_WINDOW_CLASS_INPUT_OUTPUT, - iter.data->root_visual, - mask, values); - - /* Don't resize me. */ - memset(&normal_hints, 0, sizeof normal_hints); - normal_hints.flags = - WM_NORMAL_HINTS_MAX_SIZE | WM_NORMAL_HINTS_MIN_SIZE; - normal_hints.min_width = width; - normal_hints.min_height = height; - normal_hints.max_width = width; - normal_hints.max_height = height; - xcb_change_property (c->conn, XCB_PROP_MODE_REPLACE, output->window, - c->atom.wm_normal_hints, - c->atom.wm_size_hints, 32, - sizeof normal_hints / 4, - (uint8_t *) &normal_hints); - - /* Set window name. Don't bother with non-EWMH WMs. */ - xcb_change_property(c->conn, XCB_PROP_MODE_REPLACE, output->window, - c->atom.net_wm_name, c->atom.utf8_string, 8, - strlen(name), name); - xcb_change_property(c->conn, XCB_PROP_MODE_REPLACE, output->window, - c->atom.wm_class, c->atom.string, 8, - sizeof class, class); - - x11_output_set_icon(c, output, - DATADIR "/wayland/wayland.png", 128, 128); - - xcb_map_window(c->conn, output->window); - - rectangle.x = 0; - rectangle.y = 0; - rectangle.width = width; - rectangle.height = height; - output->region = xcb_generate_id(c->conn); - xcb_xfixes_create_region(c->conn, output->region, 1, &rectangle); - - xcb_dri2_create_drawable (c->conn, output->window); - - x11_output_set_wm_protocols(output); - - cookie = xcb_dri2_get_buffers_unchecked (c->conn, - output->window, - 1, 1, attachments); - reply = xcb_dri2_get_buffers_reply (c->conn, cookie, NULL); - if (reply == NULL) - return -1; - buffers = xcb_dri2_get_buffers_buffers (reply); - if (buffers == NULL) - return -1; - - if (reply->count != 1) { - fprintf(stderr, - "got wrong number of buffers (%d)\n", reply->count); - return -1; - } - - attribs[1] = reply->width; - attribs[3] = reply->height; - attribs[5] = buffers[0].pitch / 4; - output->image = - eglCreateImageKHR(c->base.display, - EGL_NO_CONTEXT, - EGL_DRM_BUFFER_MESA, - (EGLClientBuffer) buffers[0].name, - attribs); - free(reply); - - glGenRenderbuffers(1, &output->rbo); - glBindRenderbuffer(GL_RENDERBUFFER, output->rbo); - - glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, - output->image); - - glFramebufferRenderbuffer(GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_RENDERBUFFER, - output->rbo); - - wl_list_insert(c->base.output_list.prev, &output->base.link); - - return 0; -} - -static void -idle_repaint(void *data) -{ - struct x11_output *output = data; - struct x11_compositor *c = - (struct x11_compositor *) output->base.compositor; - xcb_xfixes_region_t region; - xcb_dri2_copy_region_cookie_t cookie; - - if (output->damage_count <= ARRAY_SIZE(output->damage)) { - region = xcb_generate_id(c->conn); - xcb_xfixes_create_region(c->conn, region, - output->damage_count, output->damage); - } else { - region = output->region; - } - - cookie = xcb_dri2_copy_region_unchecked(c->conn, - output->window, - region, - XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT, - XCB_DRI2_ATTACHMENT_BUFFER_BACK_LEFT); - - if (region != output->region) - xcb_xfixes_destroy_region(c->conn, region); - - free(xcb_dri2_copy_region_reply(c->conn, cookie, NULL)); - output->damage_count = 0; -} - -static struct x11_output * -x11_compositor_find_output(struct x11_compositor *c, xcb_window_t window) -{ - struct x11_output *output; - - wl_list_for_each(output, &c->base.output_list, base.link) { - if (output->window == window) - return output; - } - - return NULL; -} - -static void -x11_compositor_handle_event(int fd, uint32_t mask, void *data) -{ - struct x11_compositor *c = data; - struct x11_output *output; - xcb_generic_event_t *event; - struct wl_event_loop *loop; - xcb_client_message_event_t *client_message; - xcb_motion_notify_event_t *motion_notify; - xcb_enter_notify_event_t *enter_notify; - xcb_key_press_event_t *key_press; - xcb_button_press_event_t *button_press; - xcb_keymap_notify_event_t *keymap_notify; - xcb_focus_in_event_t *focus_in; - xcb_expose_event_t *expose; - xcb_rectangle_t *r; - xcb_atom_t atom; - uint32_t *k; - int i, set; - - loop = wl_display_get_event_loop(c->base.wl_display); - while (event = xcb_poll_for_event (c->conn), event != NULL) { - switch (event->response_type & ~0x80) { - - case XCB_KEY_PRESS: - key_press = (xcb_key_press_event_t *) event; - notify_key(c->base.input_device, - key_press->time, key_press->detail - 8, 1); - break; - case XCB_KEY_RELEASE: - key_press = (xcb_key_press_event_t *) event; - notify_key(c->base.input_device, - key_press->time, key_press->detail - 8, 0); - break; - case XCB_BUTTON_PRESS: - button_press = (xcb_button_press_event_t *) event; - notify_button(c->base.input_device, - button_press->time, - button_press->detail + BTN_LEFT - 1, 1); - break; - case XCB_BUTTON_RELEASE: - button_press = (xcb_button_press_event_t *) event; - notify_button(c->base.input_device, - button_press->time, - button_press->detail + BTN_LEFT - 1, 0); - break; - - case XCB_MOTION_NOTIFY: - motion_notify = (xcb_motion_notify_event_t *) event; - notify_motion(c->base.input_device, - motion_notify->time, - motion_notify->event_x, - motion_notify->event_y); - break; - - case XCB_EXPOSE: - expose = (xcb_expose_event_t *) event; - output = x11_compositor_find_output(c, expose->window); - if (output->damage_count == 0) - wl_event_loop_add_idle(loop, - idle_repaint, output); - - r = &output->damage[output->damage_count++]; - if (output->damage_count > 16) - break; - r->x = expose->x; - r->y = expose->y; - r->width = expose->width; - r->height = expose->height; - break; - - case XCB_ENTER_NOTIFY: - enter_notify = (xcb_enter_notify_event_t *) event; - if (enter_notify->state >= Button1Mask) - break; - output = x11_compositor_find_output(c, enter_notify->event); - notify_pointer_focus(c->base.input_device, - enter_notify->time, - &output->base, - enter_notify->event_x, - enter_notify->event_y); - break; - - case XCB_LEAVE_NOTIFY: - enter_notify = (xcb_enter_notify_event_t *) event; - if (enter_notify->state >= Button1Mask) - break; - notify_pointer_focus(c->base.input_device, - enter_notify->time, - NULL, - enter_notify->event_x, - enter_notify->event_y); - break; - - case XCB_CLIENT_MESSAGE: - client_message = (xcb_client_message_event_t *) event; - atom = client_message->data.data32[0]; - if (atom == c->atom.wm_delete_window) - wl_display_terminate(c->base.wl_display); - break; - - case XCB_FOCUS_IN: - focus_in = (xcb_focus_in_event_t *) event; - if (focus_in->mode == XCB_NOTIFY_MODE_WHILE_GRABBED) - break; - - output = x11_compositor_find_output(c, focus_in->event); - notify_keyboard_focus(c->base.input_device, - get_time(), - &output->base, &c->keys); - break; - - case XCB_FOCUS_OUT: - focus_in = (xcb_focus_in_event_t *) event; - if (focus_in->mode == XCB_NOTIFY_MODE_WHILE_GRABBED) - break; - notify_keyboard_focus(c->base.input_device, - get_time(), NULL, NULL); - break; - - case XCB_KEYMAP_NOTIFY: - keymap_notify = (xcb_keymap_notify_event_t *) event; - c->keys.size = 0; - for (i = 0; i < ARRAY_LENGTH(keymap_notify->keys) * 8; i++) { - set = keymap_notify->keys[i >> 3] & - (1 << (i & 7)); - if (set) { - k = wl_array_add(&c->keys, sizeof *k); - *k = i; - } - } - break; - default: - break; - } - - free (event); - } -} - -#define F(field) offsetof(struct x11_compositor, field) - -static void -x11_compositor_get_resources(struct x11_compositor *c) -{ - static const struct { const char *name; int offset; } atoms[] = { - { "WM_PROTOCOLS", F(atom.wm_protocols) }, - { "WM_NORMAL_HINTS", F(atom.wm_normal_hints) }, - { "WM_SIZE_HINTS", F(atom.wm_size_hints) }, - { "WM_DELETE_WINDOW", F(atom.wm_delete_window) }, - { "WM_CLASS", F(atom.wm_class) }, - { "_NET_WM_NAME", F(atom.net_wm_name) }, - { "_NET_WM_ICON", F(atom.net_wm_icon) }, - { "STRING", F(atom.string) }, - { "UTF8_STRING", F(atom.utf8_string) }, - { "CARDINAL", F(atom.cardinal) }, - }; - - xcb_intern_atom_cookie_t cookies[ARRAY_SIZE(atoms)]; - xcb_intern_atom_reply_t *reply; - xcb_pixmap_t pixmap; - xcb_gc_t gc; - int i; - uint8_t data[] = { 0, 0, 0, 0 }; - - for (i = 0; i < ARRAY_SIZE(atoms); i++) - cookies[i] = xcb_intern_atom (c->conn, 0, - strlen(atoms[i].name), - atoms[i].name); - - for (i = 0; i < ARRAY_SIZE(atoms); i++) { - reply = xcb_intern_atom_reply (c->conn, cookies[i], NULL); - *(xcb_atom_t *) ((char *) c + atoms[i].offset) = reply->atom; - free(reply); - } - - pixmap = xcb_generate_id(c->conn); - gc = xcb_generate_id(c->conn); - xcb_create_pixmap(c->conn, 1, pixmap, c->screen->root, 1, 1); - xcb_create_gc(c->conn, gc, pixmap, 0, NULL); - xcb_put_image(c->conn, XCB_IMAGE_FORMAT_XY_PIXMAP, - pixmap, gc, 1, 1, 0, 0, 0, 32, sizeof data, data); - c->null_cursor = xcb_generate_id(c->conn); - xcb_create_cursor (c->conn, c->null_cursor, - pixmap, pixmap, 0, 0, 0, 0, 0, 0, 1, 1); - xcb_free_gc(c->conn, gc); - xcb_free_pixmap(c->conn, pixmap); -} - -static int -x11_authenticate(struct wlsc_compositor *c, uint32_t id) -{ - return dri2_authenticate((struct x11_compositor *) c, id); -} - -static void -x11_destroy(struct wlsc_compositor *ec) -{ - free(ec); -} - -struct wlsc_compositor * -x11_compositor_create(struct wl_display *display, int width, int height) -{ - struct x11_compositor *c; - struct wl_event_loop *loop; - xcb_screen_iterator_t s; - - c = malloc(sizeof *c); - if (c == NULL) - return NULL; - - memset(c, 0, sizeof *c); - c->conn = xcb_connect(0, 0); - - if (xcb_connection_has_error(c->conn)) - return NULL; - - s = xcb_setup_roots_iterator(xcb_get_setup(c->conn)); - c->screen = s.data; - wl_array_init(&c->keys); - - x11_compositor_get_resources(c); - - c->base.wl_display = display; - if (x11_compositor_init_egl(c) < 0) - return NULL; - - c->base.destroy = x11_destroy; - c->base.authenticate = x11_authenticate; - c->base.present = x11_compositor_present; - c->base.create_buffer = wlsc_drm_buffer_create; - - /* Can't init base class until we have a current egl context */ - if (wlsc_compositor_init(&c->base, display) < 0) - return NULL; - - if (x11_compositor_create_output(c, width, height) < 0) - return NULL; - - if (x11_input_create(c) < 0) - return NULL; - - loop = wl_display_get_event_loop(c->base.wl_display); - - c->xcb_source = - wl_event_loop_add_fd(loop, xcb_get_file_descriptor(c->conn), - WL_EVENT_READABLE, - x11_compositor_handle_event, c); - - return &c->base; -} diff --git a/compositor/compositor.c b/compositor/compositor.c deleted file mode 100644 index afff961..0000000 --- a/compositor/compositor.c +++ /dev/null @@ -1,1411 +0,0 @@ -/* - * Copyright © 2008 Kristian Høgsberg - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#define _GNU_SOURCE - -#include "config.h" - -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <stdint.h> -#include <stdarg.h> -#include <sys/ioctl.h> -#include <fcntl.h> -#include <unistd.h> -#include <gdk-pixbuf/gdk-pixbuf.h> -#include <math.h> -#include <linux/input.h> - -#include "wayland-server.h" -#include "compositor.h" - -struct wlsc_switcher { - struct wlsc_compositor *compositor; - struct wlsc_surface *current; - struct wl_listener listener; -}; - -/* The plan here is to generate a random anonymous socket name and - * advertise that through a service on the session dbus. - */ -static const char *option_socket_name = NULL; -static const char *option_background = "background.jpg"; -static const char *option_geometry = "1024x640"; -static int option_connector = 0; - -static const GOptionEntry option_entries[] = { - { "background", 'b', 0, G_OPTION_ARG_STRING, - &option_background, "Background image" }, - { "connector", 'c', 0, G_OPTION_ARG_INT, - &option_connector, "KMS connector" }, - { "geometry", 'g', 0, G_OPTION_ARG_STRING, - &option_geometry, "Geometry" }, - { "socket", 's', 0, G_OPTION_ARG_STRING, - &option_socket_name, "Socket Name" }, - { NULL } -}; - -static void -wlsc_matrix_init(struct wlsc_matrix *matrix) -{ - static const struct wlsc_matrix identity = { - { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 } - }; - - memcpy(matrix, &identity, sizeof identity); -} - -static void -wlsc_matrix_multiply(struct wlsc_matrix *m, const struct wlsc_matrix *n) -{ - struct wlsc_matrix tmp; - const GLfloat *row, *column; - div_t d; - int i, j; - - for (i = 0; i < 16; i++) { - tmp.d[i] = 0; - d = div(i, 4); - row = m->d + d.quot * 4; - column = n->d + d.rem; - for (j = 0; j < 4; j++) - tmp.d[i] += row[j] * column[j * 4]; - } - memcpy(m, &tmp, sizeof tmp); -} - -static void -wlsc_matrix_translate(struct wlsc_matrix *matrix, GLfloat x, GLfloat y, GLfloat z) -{ - struct wlsc_matrix translate = { - { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, x, y, z, 1 } - }; - - wlsc_matrix_multiply(matrix, &translate); -} - -static void -wlsc_matrix_scale(struct wlsc_matrix *matrix, GLfloat x, GLfloat y, GLfloat z) -{ - struct wlsc_matrix scale = { - { x, 0, 0, 0, 0, y, 0, 0, 0, 0, z, 0, 0, 0, 0, 1 } - }; - - wlsc_matrix_multiply(matrix, &scale); -} - -static void -wlsc_matrix_transform(struct wlsc_matrix *matrix, struct wlsc_vector *v) -{ - int i, j; - struct wlsc_vector t; - - for (i = 0; i < 4; i++) { - t.f[i] = 0; - for (j = 0; j < 4; j++) - t.f[i] += v->f[j] * matrix->d[i + j * 4]; - } - - *v = t; -} - -static struct wlsc_surface * -wlsc_surface_create(struct wlsc_compositor *compositor, - int32_t x, int32_t y, int32_t width, int32_t height) -{ - struct wlsc_surface *surface; - - surface = malloc(sizeof *surface); - if (surface == NULL) - return NULL; - - wl_list_init(&surface->surface.destroy_listener_list); - wl_list_init(&surface->link); - surface->map_type = WLSC_SURFACE_MAP_UNMAPPED; - - glGenTextures(1, &surface->texture); - glBindTexture(GL_TEXTURE_2D, surface->texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - surface->compositor = compositor; - surface->visual = NULL; - surface->x = x; - surface->y = y; - surface->width = width; - surface->height = height; - wlsc_matrix_init(&surface->matrix); - wlsc_matrix_scale(&surface->matrix, width, height, 1); - wlsc_matrix_translate(&surface->matrix, x, y, 0); - - wlsc_matrix_init(&surface->matrix_inv); - wlsc_matrix_translate(&surface->matrix_inv, -x, -y, 0); - wlsc_matrix_scale(&surface->matrix_inv, 1.0 / width, 1.0 / height, 1); - - return surface; -} - -void -wlsc_surface_damage_rectangle(struct wlsc_surface *surface, - int32_t x, int32_t y, - int32_t width, int32_t height) -{ - struct wlsc_compositor *compositor = surface->compositor; - - pixman_region32_union_rect(&compositor->damage_region, - &compositor->damage_region, - surface->x + x, surface->y + y, - width, height); - wlsc_compositor_schedule_repaint(compositor); -} - -void -wlsc_surface_damage(struct wlsc_surface *surface) -{ - wlsc_surface_damage_rectangle(surface, 0, 0, - surface->width, surface->height); -} - -uint32_t -get_time(void) -{ - struct timeval tv; - - gettimeofday(&tv, NULL); - - return tv.tv_sec * 1000 + tv.tv_usec / 1000; -} - -static void -destroy_surface(struct wl_resource *resource, struct wl_client *client) -{ - struct wlsc_surface *surface = - container_of(resource, struct wlsc_surface, surface.resource); - struct wl_listener *l, *next; - uint32_t time; - - wlsc_surface_damage(surface); - - wl_list_remove(&surface->link); - glDeleteTextures(1, &surface->texture); - - time = get_time(); - wl_list_for_each_safe(l, next, - &surface->surface.destroy_listener_list, link) - l->func(l, &surface->surface, time); - - free(surface); -} - -uint32_t * -wlsc_load_image(const char *filename, int width, int height) -{ - GdkPixbuf *pixbuf; - GError *error = NULL; - int stride, i, n_channels; - unsigned char *pixels, *end, *argb_pixels, *s, *d; - - pixbuf = gdk_pixbuf_new_from_file_at_scale(filename, - width, height, - FALSE, &error); - if (error != NULL) { - fprintf(stderr, "failed to load image: %s\n", error->message); - g_error_free(error); - return NULL; - } - - stride = gdk_pixbuf_get_rowstride(pixbuf); - pixels = gdk_pixbuf_get_pixels(pixbuf); - n_channels = gdk_pixbuf_get_n_channels(pixbuf); - - argb_pixels = malloc (height * width * 4); - if (argb_pixels == NULL) { - g_object_unref(pixbuf); - return NULL; - } - - if (n_channels == 4) { - for (i = 0; i < height; i++) { - s = pixels + i * stride; - end = s + width * 4; - d = argb_pixels + i * width * 4; - while (s < end) { - unsigned int t; - -#define MULT(_d,c,a,t) \ - do { t = c * a + 0x7f; _d = ((t >> 8) + t) >> 8; } while (0) - - MULT(d[0], s[2], s[3], t); - MULT(d[1], s[1], s[3], t); - MULT(d[2], s[0], s[3], t); - d[3] = s[3]; - s += 4; - d += 4; - } - } - } else if (n_channels == 3) { - for (i = 0; i < height; i++) { - s = pixels + i * stride; - end = s + width * 3; - d = argb_pixels + i * width * 4; - while (s < end) { - d[0] = s[2]; - d[1] = s[1]; - d[2] = s[0]; - d[3] = 0xff; - s += 3; - d += 4; - } - } - } - - g_object_unref(pixbuf); - - return (uint32_t *) argb_pixels; -} - -static struct wl_buffer * -create_buffer_from_png(struct wlsc_compositor *ec, - const char *filename, int width, int height) -{ - uint32_t *pixels; - struct wl_buffer *buffer; - - pixels = wlsc_load_image(filename, width, height); - if(pixels == NULL) - return NULL; - - buffer = ec->create_buffer(ec, width, height, - &ec->compositor.premultiplied_argb_visual, - pixels); - - free(pixels); - - return buffer; -} - -static const struct { - const char *filename; - int hotspot_x, hotspot_y; -} pointer_images[] = { - { DATADIR "/wayland/bottom_left_corner.png", 6, 30 }, - { DATADIR "/wayland/bottom_right_corner.png", 28, 28 }, - { DATADIR "/wayland/bottom_side.png", 16, 20 }, - { DATADIR "/wayland/grabbing.png", 20, 17 }, - { DATADIR "/wayland/left_ptr.png", 10, 5 }, - { DATADIR "/wayland/left_side.png", 10, 20 }, - { DATADIR "/wayland/right_side.png", 30, 19 }, - { DATADIR "/wayland/top_left_corner.png", 8, 8 }, - { DATADIR "/wayland/top_right_corner.png", 26, 8 }, - { DATADIR "/wayland/top_side.png", 18, 8 }, - { DATADIR "/wayland/xterm.png", 15, 15 } -}; - -static void -create_pointer_images(struct wlsc_compositor *ec) -{ - int i, count; - const int width = 32, height = 32; - - count = ARRAY_LENGTH(pointer_images); - ec->pointer_buffers = malloc(count * sizeof *ec->pointer_buffers); - for (i = 0; i < count; i++) { - ec->pointer_buffers[i] = - create_buffer_from_png(ec, - pointer_images[i].filename, - width, height); - } -} - -static struct wlsc_surface * -background_create(struct wlsc_output *output, const char *filename) -{ - struct wlsc_surface *background; - struct wl_buffer *buffer; - - background = wlsc_surface_create(output->compositor, - output->x, output->y, - output->width, output->height); - if (background == NULL) - return NULL; - - buffer = create_buffer_from_png(output->compositor, - filename, - output->width, output->height); - if (buffer == NULL) { - free(background); - return NULL; - } - buffer->attach(buffer, &background->surface); - - return background; -} - -static void -wlsc_surface_draw(struct wlsc_surface *es, - struct wlsc_output *output, pixman_region32_t *clip) -{ - struct wlsc_compositor *ec = es->compositor; - GLfloat *v, inv_width, inv_height; - unsigned int *p; - pixman_region32_t repaint; - pixman_box32_t *rectangles; - int i, n; - - pixman_region32_init_rect(&repaint, - es->x, es->y, es->width, es->height); - pixman_region32_intersect(&repaint, &repaint, clip); - if (!pixman_region32_not_empty(&repaint)) - return; - - if (es->visual == &ec->compositor.argb_visual) { - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_BLEND); - } else if (es->visual == &ec->compositor.premultiplied_argb_visual) { - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_BLEND); - } else { - glDisable(GL_BLEND); - } - - rectangles = pixman_region32_rectangles(&repaint, &n); - v = wl_array_add(&ec->vertices, n * 16 * sizeof *v); - p = wl_array_add(&ec->indices, n * 6 * sizeof *p); - inv_width = 1.0 / es->width; - inv_height = 1.0 / es->height; - for (i = 0; i < n; i++, v += 16, p += 6) { - v[ 0] = rectangles[i].x1; - v[ 1] = rectangles[i].y1; - v[ 2] = (GLfloat) (rectangles[i].x1 - es->x) * inv_width; - v[ 3] = (GLfloat) (rectangles[i].y1 - es->y) * inv_height; - - v[ 4] = rectangles[i].x1; - v[ 5] = rectangles[i].y2; - v[ 6] = v[ 2]; - v[ 7] = (GLfloat) (rectangles[i].y2 - es->y) * inv_height; - - v[ 8] = rectangles[i].x2; - v[ 9] = rectangles[i].y1; - v[10] = (GLfloat) (rectangles[i].x2 - es->x) * inv_width; - v[11] = v[ 3]; - - v[12] = rectangles[i].x2; - v[13] = rectangles[i].y2; - v[14] = v[10]; - v[15] = v[ 7]; - - p[0] = i * 4 + 0; - p[1] = i * 4 + 1; - p[2] = i * 4 + 2; - p[3] = i * 4 + 2; - p[4] = i * 4 + 1; - p[5] = i * 4 + 3; - } - - glBindTexture(GL_TEXTURE_2D, es->texture); - v = ec->vertices.data; - glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[0]); - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[2]); - glEnableVertexAttribArray(0); - glEnableVertexAttribArray(1); - glDrawElements(GL_TRIANGLES, n * 6, GL_UNSIGNED_INT, ec->indices.data); - - ec->vertices.size = 0; - ec->indices.size = 0; - pixman_region32_fini(&repaint); -} - -static void -wlsc_surface_raise(struct wlsc_surface *surface) -{ - struct wlsc_compositor *compositor = surface->compositor; - - wl_list_remove(&surface->link); - wl_list_insert(&compositor->surface_list, &surface->link); -} - -void -wlsc_surface_update_matrix(struct wlsc_surface *es) -{ - wlsc_matrix_init(&es->matrix); - wlsc_matrix_scale(&es->matrix, es->width, es->height, 1); - wlsc_matrix_translate(&es->matrix, es->x, es->y, 0); - - wlsc_matrix_init(&es->matrix_inv); - wlsc_matrix_translate(&es->matrix_inv, -es->x, -es->y, 0); - wlsc_matrix_scale(&es->matrix_inv, - 1.0 / es->width, 1.0 / es->height, 1); -} - -void -wlsc_compositor_finish_frame(struct wlsc_compositor *compositor, int msecs) -{ - wl_display_post_frame(compositor->wl_display, msecs); - wl_event_source_timer_update(compositor->timer_source, 5); - compositor->repaint_on_timeout = 1; -} - -static void -wlsc_output_repaint(struct wlsc_output *output) -{ - struct wlsc_compositor *ec = output->compositor; - struct wlsc_surface *es; - struct wlsc_input_device *eid; - pixman_region32_t new_damage, total_damage; - - glViewport(0, 0, output->width, output->height); - - glUniformMatrix4fv(ec->proj_uniform, 1, GL_FALSE, output->matrix.d); - glUniform1i(ec->tex_uniform, 0); - - pixman_region32_init(&new_damage); - pixman_region32_init(&total_damage); - pixman_region32_intersect_rect(&new_damage, - &ec->damage_region, - output->x, output->y, - output->width, output->height); - pixman_region32_subtract(&ec->damage_region, - &ec->damage_region, &new_damage); - pixman_region32_union(&total_damage, &new_damage, - &output->previous_damage_region); - pixman_region32_copy(&output->previous_damage_region, &new_damage); - - es = container_of(ec->surface_list.next, struct wlsc_surface, link); - if (es->map_type == WLSC_SURFACE_MAP_FULLSCREEN && - es->fullscreen_output == output) { - if (es->width < output->width || es->height < output->height) - glClear(GL_COLOR_BUFFER_BIT); - wlsc_surface_draw(es, output, &total_damage); - } else { - if (output->background) - wlsc_surface_draw(output->background, - output, &total_damage); - else - glClear(GL_COLOR_BUFFER_BIT); - - wl_list_for_each_reverse(es, &ec->surface_list, link) { - if (ec->switcher && - ec->switcher->current == es) - continue; - - wlsc_surface_draw(es, output, &total_damage); - } - } - - if (ec->switcher) - wlsc_surface_draw(ec->switcher->current, - output, &total_damage); - - if (ec->focus) - wl_list_for_each(eid, &ec->input_device_list, link) - wlsc_surface_draw(eid->sprite, output, &total_damage); -} - -static void -repaint(void *data) -{ - struct wlsc_compositor *ec = data; - struct wlsc_output *output; - - if (!ec->repaint_needed) { - ec->repaint_on_timeout = 0; - return; - } - - wl_list_for_each(output, &ec->output_list, link) - wlsc_output_repaint(output); - - ec->present(ec); - - ec->repaint_needed = 0; -} - -void -wlsc_compositor_schedule_repaint(struct wlsc_compositor *compositor) -{ - compositor->repaint_needed = 1; - if (compositor->repaint_on_timeout) - return; - - wl_event_source_timer_update(compositor->timer_source, 1); - compositor->repaint_on_timeout = 1; -} - -static void -surface_destroy(struct wl_client *client, - struct wl_surface *surface) -{ - wl_resource_destroy(&surface->resource, client); -} - -static void -surface_attach(struct wl_client *client, - struct wl_surface *surface, struct wl_buffer *buffer, - int32_t x, int32_t y) -{ - struct wlsc_surface *es = (struct wlsc_surface *) surface; - - /* FIXME: This damages the entire old surface, but we should - * really just damage the part that's no longer covered by the - * surface. Anything covered by the new surface will be - * damaged by the client. */ - wlsc_surface_damage(es); - - buffer->attach(buffer, surface); - es->buffer = buffer; - es->x += x; - es->y += y; - es->width = buffer->width; - es->height = buffer->height; - wlsc_surface_update_matrix(es); -} - -static void -surface_map_toplevel(struct wl_client *client, - struct wl_surface *surface) -{ - struct wlsc_surface *es = (struct wlsc_surface *) surface; - - switch (es->map_type) { - case WLSC_SURFACE_MAP_UNMAPPED: - es->x = 10 + random() % 400; - es->y = 10 + random() % 400; - wlsc_surface_update_matrix(es); - wl_list_insert(&es->compositor->surface_list, &es->link); - break; - case WLSC_SURFACE_MAP_TOPLEVEL: - return; - case WLSC_SURFACE_MAP_FULLSCREEN: - es->fullscreen_output = NULL; - es->x = es->saved_x; - es->y = es->saved_y; - wlsc_surface_update_matrix(es); - break; - default: - break; - } - - wlsc_surface_damage(es); - es->map_type = WLSC_SURFACE_MAP_TOPLEVEL; -} - -static void -surface_map_transient(struct wl_client *client, - struct wl_surface *surface, struct wl_surface *parent, - int x, int y, uint32_t flags) -{ - struct wlsc_surface *es = (struct wlsc_surface *) surface; - struct wlsc_surface *pes = (struct wlsc_surface *) parent; - - switch (es->map_type) { - case WLSC_SURFACE_MAP_UNMAPPED: - wl_list_insert(&es->compositor->surface_list, &es->link); - break; - case WLSC_SURFACE_MAP_FULLSCREEN: - es->fullscreen_output = NULL; - break; - default: - break; - } - - es->x = pes->x + x; - es->y = pes->y + y; - - wlsc_surface_update_matrix(es); - wlsc_surface_damage(es); - es->map_type = WLSC_SURFACE_MAP_TRANSIENT; -} - -static void -surface_map_fullscreen(struct wl_client *client, struct wl_surface *surface) -{ - struct wlsc_surface *es = (struct wlsc_surface *) surface; - struct wlsc_output *output; - - switch (es->map_type) { - case WLSC_SURFACE_MAP_UNMAPPED: - es->x = 10 + random() % 400; - es->y = 10 + random() % 400; - wl_list_insert(&es->compositor->surface_list, &es->link); - break; - case WLSC_SURFACE_MAP_FULLSCREEN: - return; - default: - break; - } - - /* FIXME: Fullscreen on first output */ - /* FIXME: Handle output going away */ - output = container_of(es->compositor->output_list.next, - struct wlsc_output, link); - - es->saved_x = es->x; - es->saved_y = es->y; - es->x = (output->width - es->width) / 2; - es->y = (output->height - es->height) / 2; - es->fullscreen_output = output; - wlsc_surface_update_matrix(es); - wlsc_surface_damage(es); - es->map_type = WLSC_SURFACE_MAP_FULLSCREEN; -} - -static void -surface_damage(struct wl_client *client, - struct wl_surface *surface, - int32_t x, int32_t y, int32_t width, int32_t height) -{ - struct wlsc_surface *es = (struct wlsc_surface *) surface; - - es->buffer->damage(es->buffer, surface, x, y, width, height); - - wlsc_surface_damage_rectangle(es, x, y, width, height); -} - -const static struct wl_surface_interface surface_interface = { - surface_destroy, - surface_attach, - surface_map_toplevel, - surface_map_transient, - surface_map_fullscreen, - surface_damage -}; - -static void -wlsc_input_device_attach(struct wlsc_input_device *device, - struct wl_buffer *buffer, int x, int y) -{ - wlsc_surface_damage(device->sprite); - - buffer->attach(buffer, &device->sprite->surface); - device->hotspot_x = x; - device->hotspot_y = y; - - device->sprite->x = device->input_device.x - device->hotspot_x; - device->sprite->y = device->input_device.y - device->hotspot_y; - device->sprite->width = buffer->width; - device->sprite->height = buffer->height; - wlsc_surface_update_matrix(device->sprite); - - wlsc_surface_damage(device->sprite); -} - - -void -wlsc_input_device_set_pointer_image(struct wlsc_input_device *device, - enum wlsc_pointer_type type) -{ - struct wlsc_compositor *compositor = - (struct wlsc_compositor *) device->input_device.compositor; - - wlsc_input_device_attach(device, - compositor->pointer_buffers[type], - pointer_images[type].hotspot_x, - pointer_images[type].hotspot_y); -} - -static void -compositor_create_surface(struct wl_client *client, - struct wl_compositor *compositor, uint32_t id) -{ - struct wlsc_compositor *ec = (struct wlsc_compositor *) compositor; - struct wlsc_surface *surface; - - surface = wlsc_surface_create(ec, 0, 0, 0, 0); - if (surface == NULL) { - wl_client_post_no_memory(client); - return; - } - - surface->surface.resource.destroy = destroy_surface; - - surface->surface.resource.object.id = id; - surface->surface.resource.object.interface = &wl_surface_interface; - surface->surface.resource.object.implementation = - (void (**)(void)) &surface_interface; - surface->surface.client = client; - - wl_client_add_resource(client, &surface->surface.resource); -} - -const static struct wl_compositor_interface compositor_interface = { - compositor_create_surface, -}; - -static void -wlsc_surface_transform(struct wlsc_surface *surface, - int32_t x, int32_t y, int32_t *sx, int32_t *sy) -{ - struct wlsc_vector v = { { x, y, 0, 1 } }; - - wlsc_matrix_transform(&surface->matrix_inv, &v); - *sx = v.f[0] * surface->width; - *sy = v.f[1] * surface->height; -} - -struct wlsc_surface * -pick_surface(struct wl_input_device *device, int32_t *sx, int32_t *sy) -{ - struct wlsc_compositor *ec = - (struct wlsc_compositor *) device->compositor; - struct wlsc_surface *es; - - wl_list_for_each(es, &ec->surface_list, link) { - wlsc_surface_transform(es, device->x, device->y, sx, sy); - if (0 <= *sx && *sx < es->width && - 0 <= *sy && *sy < es->height) - return es; - } - - return NULL; -} - - -static void -motion_grab_motion(struct wl_grab *grab, - uint32_t time, int32_t x, int32_t y) -{ - struct wlsc_input_device *device = - (struct wlsc_input_device *) grab->input_device; - struct wlsc_surface *es = - (struct wlsc_surface *) device->input_device.pointer_focus; - int32_t sx, sy; - - wlsc_surface_transform(es, x, y, &sx, &sy); - wl_client_post_event(es->surface.client, - &device->input_device.object, - WL_INPUT_DEVICE_MOTION, - time, x, y, sx, sy); -} - -static void -motion_grab_button(struct wl_grab *grab, - uint32_t time, int32_t button, int32_t state) -{ - wl_client_post_event(grab->input_device->pointer_focus->client, - &grab->input_device->object, - WL_INPUT_DEVICE_BUTTON, - time, button, state); -} - -static void -motion_grab_end(struct wl_grab *grab, uint32_t time) -{ -} - -static const struct wl_grab_interface motion_grab_interface = { - motion_grab_motion, - motion_grab_button, - motion_grab_end -}; - -void -notify_motion(struct wl_input_device *device, uint32_t time, int x, int y) -{ - struct wlsc_surface *es; - struct wlsc_compositor *ec = - (struct wlsc_compositor *) device->compositor; - struct wlsc_output *output; - const struct wl_grab_interface *interface; - struct wlsc_input_device *wd = (struct wlsc_input_device *) device; - int32_t sx, sy; - - /* FIXME: We need some multi head love here. */ - output = container_of(ec->output_list.next, struct wlsc_output, link); - if (x < output->x) - x = 0; - if (y < output->y) - y = 0; - if (x >= output->x + output->width) - x = output->x + output->width - 1; - if (y >= output->y + output->height) - y = output->y + output->height - 1; - - device->x = x; - device->y = y; - - if (device->grab) { - interface = device->grab->interface; - interface->motion(device->grab, time, x, y); - } else { - es = pick_surface(device, &sx, &sy); - wl_input_device_set_pointer_focus(device, - &es->surface, - time, x, y, sx, sy); - if (es) - wl_client_post_event(es->surface.client, - &device->object, - WL_INPUT_DEVICE_MOTION, - time, x, y, sx, sy); - } - - wlsc_surface_damage(wd->sprite); - - wd->sprite->x = device->x - wd->hotspot_x; - wd->sprite->y = device->y - wd->hotspot_y; - wlsc_surface_update_matrix(wd->sprite); - - wlsc_surface_damage(wd->sprite); -} - -static void -wlsc_surface_activate(struct wlsc_surface *surface, - struct wlsc_input_device *device, uint32_t time) -{ - wlsc_surface_raise(surface); - if (device->selection) - wlsc_selection_set_focus(device->selection, - &surface->surface, time); - - wl_input_device_set_keyboard_focus(&device->input_device, - &surface->surface, - time); -} - -void -notify_button(struct wl_input_device *device, - uint32_t time, int32_t button, int32_t state) -{ - struct wlsc_input_device *wd = (struct wlsc_input_device *) device; - struct wlsc_surface *surface; - struct wlsc_compositor *compositor = - (struct wlsc_compositor *) device->compositor; - - surface = (struct wlsc_surface *) device->pointer_focus; - uint32_t edges = 0; - int32_t x, y; - - if (state && surface && device->grab == NULL) { - wlsc_surface_activate(surface, wd, time); - wl_input_device_start_grab(device, - &device->motion_grab, - button, time); - } - - if (state && surface && button == BTN_LEFT && - (wd->modifier_state & MODIFIER_SUPER)) - shell_move(NULL, - (struct wl_shell *) &compositor->shell, - &surface->surface, device, time); - else if (state && surface && button == BTN_MIDDLE && - (wd->modifier_state & MODIFIER_SUPER)) { - - x = device->grab_x - surface->x; - y = device->grab_y - surface->y; - - if (x < surface->width / 3) - edges |= WL_SHELL_RESIZE_LEFT; - else if (x < 2 * surface->width / 3) - edges |= 0; - else - edges |= WL_SHELL_RESIZE_RIGHT; - - if (y < surface->height / 3) - edges |= WL_SHELL_RESIZE_TOP; - else if (y < 2 * surface->height / 3) - edges |= 0; - else - edges |= WL_SHELL_RESIZE_BOTTOM; - - shell_resize(NULL, - (struct wl_shell *) &compositor->shell, - &surface->surface, device, time, edges); - } - - if (device->grab) - device->grab->interface->button(device->grab, time, - button, state); - - if (!state && device->grab && device->grab_button == button) - wl_input_device_end_grab(device, time); -} - -static void -wlsc_switcher_next(struct wlsc_switcher *switcher) -{ - struct wl_list *l; - - wlsc_surface_damage(switcher->current); - l = switcher->current->link.next; - if (l == &switcher->compositor->surface_list) - l = switcher->compositor->surface_list.next; - switcher->current = container_of(l, struct wlsc_surface, link); - wl_list_remove(&switcher->listener.link); - wl_list_insert(switcher->current->surface.destroy_listener_list.prev, - &switcher->listener.link); - wlsc_surface_damage(switcher->current); -} - -static void -switcher_handle_surface_destroy(struct wl_listener *listener, - struct wl_surface *surface, uint32_t time) -{ - struct wlsc_switcher *switcher = - container_of(listener, struct wlsc_switcher, listener); - - wlsc_switcher_next(switcher); -} - -static struct wlsc_switcher * -wlsc_switcher_create(struct wlsc_compositor *compositor) -{ - struct wlsc_switcher *switcher; - - switcher = malloc(sizeof *switcher); - switcher->compositor = compositor; - switcher->current = container_of(compositor->surface_list.next, - struct wlsc_surface, link); - switcher->listener.func = switcher_handle_surface_destroy; - wl_list_init(&switcher->listener.link); - - return switcher; -} - -static void -wlsc_switcher_destroy(struct wlsc_switcher *switcher) -{ - wl_list_remove(&switcher->listener.link); - free(switcher); -} - -void -notify_key(struct wl_input_device *device, - uint32_t time, uint32_t key, uint32_t state) -{ - struct wlsc_input_device *wd = (struct wlsc_input_device *) device; - struct wlsc_compositor *compositor = - (struct wlsc_compositor *) device->compositor; - uint32_t *k, *end; - uint32_t modifier; - - switch (key | wd->modifier_state) { - case KEY_BACKSPACE | MODIFIER_CTRL | MODIFIER_ALT: - wl_display_terminate(compositor->wl_display); - return; - - case KEY_TAB | MODIFIER_SUPER: - if (!state) - return; - if (wl_list_empty(&compositor->surface_list)) - return; - if (compositor->switcher == NULL) - compositor->switcher = wlsc_switcher_create(compositor); - - wlsc_switcher_next(compositor->switcher); - return; - - case KEY_LEFTMETA | MODIFIER_SUPER: - case KEY_RIGHTMETA | MODIFIER_SUPER: - if (compositor->switcher && !state) { - wlsc_surface_activate(compositor->switcher->current, - wd, time); - wlsc_switcher_destroy(compositor->switcher); - compositor->switcher = NULL; - } - break; - } - - switch (key) { - case KEY_LEFTCTRL: - case KEY_RIGHTCTRL: - modifier = MODIFIER_CTRL; - break; - - case KEY_LEFTALT: - case KEY_RIGHTALT: - modifier = MODIFIER_ALT; - break; - - case KEY_LEFTMETA: - case KEY_RIGHTMETA: - modifier = MODIFIER_SUPER; - break; - - default: - modifier = 0; - break; - } - - if (state) - wd->modifier_state |= modifier; - else - wd->modifier_state &= ~modifier; - - end = device->keys.data + device->keys.size; - for (k = device->keys.data; k < end; k++) { - if (*k == key) - *k = *--end; - } - device->keys.size = (void *) end - device->keys.data; - if (state) { - k = wl_array_add(&device->keys, sizeof *k); - *k = key; - } - - if (device->keyboard_focus != NULL) - wl_client_post_event(device->keyboard_focus->client, - &device->object, - WL_INPUT_DEVICE_KEY, time, key, state); -} - -void -notify_pointer_focus(struct wl_input_device *device, - uint32_t time, struct wlsc_output *output, - int32_t x, int32_t y) -{ - struct wlsc_input_device *wd = (struct wlsc_input_device *) device; - struct wlsc_compositor *compositor = - (struct wlsc_compositor *) device->compositor; - struct wlsc_surface *es; - int32_t sx, sy; - - if (output) { - device->x = x; - device->y = y; - es = pick_surface(device, &sx, &sy); - wl_input_device_set_pointer_focus(device, - &es->surface, - time, x, y, sx, sy); - - compositor->focus = 1; - - wd->sprite->x = device->x - wd->hotspot_x; - wd->sprite->y = device->y - wd->hotspot_y; - wlsc_surface_update_matrix(wd->sprite); - } else { - wl_input_device_set_pointer_focus(device, NULL, - time, 0, 0, 0, 0); - compositor->focus = 0; - } - - wlsc_surface_damage(wd->sprite); -} - -void -notify_keyboard_focus(struct wl_input_device *device, - uint32_t time, struct wlsc_output *output, - struct wl_array *keys) -{ - struct wlsc_input_device *wd = - (struct wlsc_input_device *) device; - struct wlsc_compositor *compositor = - (struct wlsc_compositor *) device->compositor; - struct wlsc_surface *es; - - if (!wl_list_empty(&compositor->surface_list)) - es = container_of(compositor->surface_list.next, - struct wlsc_surface, link); - else - es = NULL; - - if (output) { - wl_array_copy(&wd->input_device.keys, keys); - wl_input_device_set_keyboard_focus(&wd->input_device, - &es->surface, time); - } else { - wl_input_device_set_keyboard_focus(&wd->input_device, - NULL, time); - } -} - - -static void -input_device_attach(struct wl_client *client, - struct wl_input_device *device_base, - uint32_t time, - struct wl_buffer *buffer, int32_t x, int32_t y) -{ - struct wlsc_input_device *device = - (struct wlsc_input_device *) device_base; - - if (time < device->input_device.pointer_focus_time) - return; - if (device->input_device.pointer_focus == NULL) - return; - if (device->input_device.pointer_focus->client != client) - return; - - if (buffer == NULL) { - wlsc_input_device_set_pointer_image(device, - WLSC_POINTER_LEFT_PTR); - return; - } - - wlsc_input_device_attach(device, buffer, x, y); -} - -const static struct wl_input_device_interface input_device_interface = { - input_device_attach, -}; - -void -wlsc_input_device_init(struct wlsc_input_device *device, - struct wlsc_compositor *ec) -{ - wl_input_device_init(&device->input_device, &ec->compositor); - - device->input_device.object.interface = &wl_input_device_interface; - device->input_device.object.implementation = - (void (**)(void)) &input_device_interface; - wl_display_add_object(ec->wl_display, &device->input_device.object); - wl_display_add_global(ec->wl_display, &device->input_device.object, NULL); - - device->sprite = wlsc_surface_create(ec, - device->input_device.x, - device->input_device.y, 32, 32); - device->hotspot_x = 16; - device->hotspot_y = 16; - - device->input_device.motion_grab.interface = &motion_grab_interface; - - wl_list_insert(ec->input_device_list.prev, &device->link); - - wlsc_input_device_set_pointer_image(device, WLSC_POINTER_LEFT_PTR); -} - -static void -wlsc_output_post_geometry(struct wl_client *client, struct wl_object *global) -{ - struct wlsc_output *output = - container_of(global, struct wlsc_output, object); - - wl_client_post_event(client, global, - WL_OUTPUT_GEOMETRY, - output->x, output->y, - output->width, output->height); -} - -static const char vertex_shader[] = - "uniform mat4 proj;\n" - "attribute vec2 position;\n" - "attribute vec2 texcoord;\n" - "varying vec2 v_texcoord;\n" - "void main()\n" - "{\n" - " gl_Position = proj * vec4(position, 0.0, 1.0);\n" - " v_texcoord = texcoord;\n" - "}\n"; - -static const char fragment_shader[] = - "precision mediump float;\n" - "varying vec2 v_texcoord;\n" - "uniform sampler2D tex;\n" - "void main()\n" - "{\n" - " gl_FragColor = texture2D(tex, v_texcoord)\n;" - "}\n"; - -static int -init_shaders(struct wlsc_compositor *ec) -{ - GLuint v, f, program; - const char *p; - char msg[512]; - GLint status; - - p = vertex_shader; - v = glCreateShader(GL_VERTEX_SHADER); - glShaderSource(v, 1, &p, NULL); - glCompileShader(v); - glGetShaderiv(v, GL_COMPILE_STATUS, &status); - if (!status) { - glGetShaderInfoLog(v, sizeof msg, NULL, msg); - fprintf(stderr, "vertex shader info: %s\n", msg); - return -1; - } - - p = fragment_shader; - f = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(f, 1, &p, NULL); - glCompileShader(f); - glGetShaderiv(f, GL_COMPILE_STATUS, &status); - if (!status) { - glGetShaderInfoLog(f, sizeof msg, NULL, msg); - fprintf(stderr, "fragment shader info: %s\n", msg); - return -1; - } - - program = glCreateProgram(); - glAttachShader(program, v); - glAttachShader(program, f); - glBindAttribLocation(program, 0, "position"); - glBindAttribLocation(program, 1, "texcoord"); - - glLinkProgram(program); - glGetProgramiv(program, GL_LINK_STATUS, &status); - if (!status) { - glGetProgramInfoLog(program, sizeof msg, NULL, msg); - fprintf(stderr, "link info: %s\n", msg); - return -1; - } - - glUseProgram(program); - ec->proj_uniform = glGetUniformLocation(program, "proj"); - ec->tex_uniform = glGetUniformLocation(program, "tex"); - - return 0; -} - -void -wlsc_output_init(struct wlsc_output *output, struct wlsc_compositor *c, - int x, int y, int width, int height) -{ - output->compositor = c; - output->x = x; - output->y = y; - output->width = width; - output->height = height; - - pixman_region32_init(&output->previous_damage_region); - - output->background = - background_create(output, option_background); - - wlsc_matrix_init(&output->matrix); - wlsc_matrix_translate(&output->matrix, - -output->x - output->width / 2.0, - -output->y - output->height / 2.0, 0); - wlsc_matrix_scale(&output->matrix, - 2.0 / output->width, 2.0 / output->height, 1); - - output->object.interface = &wl_output_interface; - wl_display_add_object(c->wl_display, &output->object); - wl_display_add_global(c->wl_display, &output->object, - wlsc_output_post_geometry); - - pixman_region32_union_rect(&c->damage_region, - &c->damage_region, - x, y, width, height); -} - -int -wlsc_compositor_init(struct wlsc_compositor *ec, struct wl_display *display) -{ - struct wl_event_loop *loop; - const char *extensions; - - ec->wl_display = display; - - wl_compositor_init(&ec->compositor, &compositor_interface, display); - - wlsc_shm_init(ec); - - wlsc_shell_init(ec); - - wl_list_init(&ec->surface_list); - wl_list_init(&ec->input_device_list); - wl_list_init(&ec->output_list); - - create_pointer_images(ec); - - screenshooter_create(ec); - - extensions = (const char *) glGetString(GL_EXTENSIONS); - if (!strstr(extensions, "GL_EXT_texture_format_BGRA8888")) { - fprintf(stderr, - "GL_EXT_texture_format_BGRA8888 not available\n"); - return -1; - } - - glGenFramebuffers(1, &ec->fbo); - glBindFramebuffer(GL_FRAMEBUFFER, ec->fbo); - glActiveTexture(GL_TEXTURE0); - if (init_shaders(ec) < 0) - return -1; - - loop = wl_display_get_event_loop(ec->wl_display); - ec->timer_source = wl_event_loop_add_timer(loop, repaint, ec); - pixman_region32_init(&ec->damage_region); - wlsc_compositor_schedule_repaint(ec); - - return 0; -} - -static void on_term_signal(int signal_number, void *data) -{ - struct wlsc_compositor *ec = data; - - wl_display_terminate(ec->wl_display); -} - -int main(int argc, char *argv[]) -{ - struct wl_display *display; - struct wlsc_compositor *ec; - struct wl_event_loop *loop; - GError *error = NULL; - GOptionContext *context; - int width, height; - - g_type_init(); /* GdkPixbuf needs this, it seems. */ - - context = g_option_context_new(NULL); - g_option_context_add_main_entries(context, option_entries, "Wayland"); - if (!g_option_context_parse(context, &argc, &argv, &error)) { - fprintf(stderr, "option parsing failed: %s\n", error->message); - exit(EXIT_FAILURE); - } - if (sscanf(option_geometry, "%dx%d", &width, &height) != 2) { - fprintf(stderr, "invalid geometry option: %s \n", - option_geometry); - exit(EXIT_FAILURE); - } - - display = wl_display_create(); - - ec = NULL; - -#if BUILD_WAYLAND_COMPOSITOR - if (getenv("WAYLAND_DISPLAY")) - ec = wayland_compositor_create(display, width, height); -#endif - -#if BUILD_X11_COMPOSITOR - if (ec == NULL && getenv("DISPLAY")) - ec = x11_compositor_create(display, width, height); -#endif - -#if BUILD_DRM_COMPOSITOR - if (ec == NULL) - ec = drm_compositor_create(display, option_connector); -#endif - - if (ec == NULL) { - fprintf(stderr, "failed to create compositor\n"); - exit(EXIT_FAILURE); - } - - if (wl_display_add_socket(display, option_socket_name)) { - fprintf(stderr, "failed to add socket: %m\n"); - exit(EXIT_FAILURE); - } - - loop = wl_display_get_event_loop(ec->wl_display); - wl_event_loop_add_signal(loop, SIGTERM, on_term_signal, ec); - wl_event_loop_add_signal(loop, SIGINT, on_term_signal, ec); - - wl_display_run(display); - - wl_display_destroy(display); - - ec->destroy(ec); - - return 0; -} diff --git a/compositor/compositor.h b/compositor/compositor.h deleted file mode 100644 index b0901e8..0000000 --- a/compositor/compositor.h +++ /dev/null @@ -1,269 +0,0 @@ -/* - * Copyright © 2008 Kristian Høgsberg - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef _WAYLAND_SYSTEM_COMPOSITOR_H_ -#define _WAYLAND_SYSTEM_COMPOSITOR_H_ - -#include <xf86drm.h> -#include <xf86drmMode.h> -#include <libudev.h> -#include <pixman.h> -#include "wayland-server.h" -#include "wayland-util.h" - -#define GL_GLEXT_PROTOTYPES -#define EGL_EGLEXT_PROTOTYPES -#include <GLES2/gl2.h> -#include <GLES2/gl2ext.h> -#include <EGL/egl.h> -#include <EGL/eglext.h> - -#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0]) - -struct wlsc_matrix { - GLfloat d[16]; -}; - -struct wlsc_surface; - -struct wlsc_output { - struct wl_object object; - struct wl_list link; - struct wlsc_compositor *compositor; - struct wlsc_surface *background; - struct wlsc_matrix matrix; - int32_t x, y, width, height; - pixman_region32_t previous_damage_region; -}; - -enum wlsc_pointer_type { - WLSC_POINTER_BOTTOM_LEFT, - WLSC_POINTER_BOTTOM_RIGHT, - WLSC_POINTER_BOTTOM, - WLSC_POINTER_DRAGGING, - WLSC_POINTER_LEFT_PTR, - WLSC_POINTER_LEFT, - WLSC_POINTER_RIGHT, - WLSC_POINTER_TOP_LEFT, - WLSC_POINTER_TOP_RIGHT, - WLSC_POINTER_TOP, - WLSC_POINTER_IBEAM, -}; - -struct wlsc_input_device { - struct wl_input_device input_device; - struct wlsc_surface *sprite; - int32_t hotspot_x, hotspot_y; - struct wl_list link; - uint32_t modifier_state; - struct wl_selection *selection; -}; - -struct wlsc_drm { - struct wl_object object; - int fd; - char *filename; -}; - -struct wlsc_shm { - struct wl_object object; -}; - -struct wlsc_compositor { - struct wl_compositor compositor; - - struct wlsc_drm drm; - struct wlsc_shm shm; - EGLDisplay display; - EGLContext context; - GLuint fbo; - GLuint proj_uniform, tex_uniform; - struct wl_buffer **pointer_buffers; - struct wl_display *wl_display; - - /* We implement the shell interface. */ - struct wl_shell shell; - - /* There can be more than one, but not right now... */ - struct wl_input_device *input_device; - - struct wl_list output_list; - struct wl_list input_device_list; - struct wl_list surface_list; - - /* Repaint state. */ - struct wl_event_source *timer_source; - int repaint_needed; - int repaint_on_timeout; - struct timespec previous_swap; - pixman_region32_t damage_region; - struct wl_array vertices, indices; - - struct wlsc_switcher *switcher; - uint32_t focus; - - void (*destroy)(struct wlsc_compositor *ec); - int (*authenticate)(struct wlsc_compositor *c, uint32_t id); - void (*present)(struct wlsc_compositor *c); - struct wl_buffer *(*create_buffer)(struct wlsc_compositor *c, - int32_t width, int32_t height, - struct wl_visual *visual, - const void *data); -}; - -#define MODIFIER_CTRL (1 << 8) -#define MODIFIER_ALT (1 << 9) -#define MODIFIER_SUPER (1 << 10) - -struct wlsc_vector { - GLfloat f[4]; -}; - -enum wlsc_surface_map_type { - WLSC_SURFACE_MAP_UNMAPPED, - WLSC_SURFACE_MAP_TOPLEVEL, - WLSC_SURFACE_MAP_TRANSIENT, - WLSC_SURFACE_MAP_FULLSCREEN -}; - -struct wlsc_surface { - struct wl_surface surface; - struct wlsc_compositor *compositor; - GLuint texture; - int32_t x, y, width, height; - int32_t saved_x, saved_y; - struct wl_list link; - struct wlsc_matrix matrix; - struct wlsc_matrix matrix_inv; - struct wl_visual *visual; - struct wl_buffer *buffer; - enum wlsc_surface_map_type map_type; - struct wlsc_output *fullscreen_output; -}; - -void -wlsc_surface_update_matrix(struct wlsc_surface *es); - -void -notify_motion(struct wl_input_device *device, - uint32_t time, int x, int y); -void -notify_button(struct wl_input_device *device, - uint32_t time, int32_t button, int32_t state); -void -notify_key(struct wl_input_device *device, - uint32_t time, uint32_t key, uint32_t state); - -void -notify_pointer_focus(struct wl_input_device *device, - uint32_t time, - struct wlsc_output *output, - int32_t x, int32_t y); - -void -notify_keyboard_focus(struct wl_input_device *device, - uint32_t time, struct wlsc_output *output, - struct wl_array *keys); - -void -wlsc_compositor_finish_frame(struct wlsc_compositor *compositor, int msecs); -void -wlsc_compositor_schedule_repaint(struct wlsc_compositor *compositor); - -void -wlsc_surface_damage(struct wlsc_surface *surface); - -void -wlsc_surface_damage_rectangle(struct wlsc_surface *surface, - int32_t x, int32_t y, - int32_t width, int32_t height); - -void -wlsc_input_device_set_pointer_image(struct wlsc_input_device *device, - enum wlsc_pointer_type type); -struct wlsc_surface * -pick_surface(struct wl_input_device *device, int32_t *sx, int32_t *sy); - -void -wlsc_selection_set_focus(struct wl_selection *selection, - struct wl_surface *surface, uint32_t time); - -uint32_t -get_time(void); - -struct wl_buffer * -wlsc_drm_buffer_create(struct wlsc_compositor *ec, - int width, int height, - struct wl_visual *visual, const void *data); - -int -wlsc_compositor_init(struct wlsc_compositor *ec, struct wl_display *display); -void -wlsc_output_init(struct wlsc_output *output, struct wlsc_compositor *c, - int x, int y, int width, int height); -void -wlsc_input_device_init(struct wlsc_input_device *device, - struct wlsc_compositor *ec); -int -wlsc_drm_init(struct wlsc_compositor *ec, int fd, const char *filename); - -int -wlsc_shm_init(struct wlsc_compositor *ec); - -int -wlsc_shell_init(struct wlsc_compositor *ec); - -void -shell_move(struct wl_client *client, struct wl_shell *shell, - struct wl_surface *surface, - struct wl_input_device *device, uint32_t time); - -void -shell_resize(struct wl_client *client, struct wl_shell *shell, - struct wl_surface *surface, - struct wl_input_device *device, uint32_t time, uint32_t edges); - -struct wl_buffer * -wl_buffer_create_drm(struct wlsc_compositor *compositor, - struct wl_visual *visual); - -struct wlsc_compositor * -x11_compositor_create(struct wl_display *display, int width, int height); - -struct wlsc_compositor * -drm_compositor_create(struct wl_display *display, int connector); - -struct wlsc_compositor * -wayland_compositor_create(struct wl_display *display, int width, int height); - -void -evdev_input_add_devices(struct wlsc_compositor *c, struct udev *udev); - -struct tty * -tty_create(struct wlsc_compositor *compositor); - -void -tty_destroy(struct tty *tty); - -void -screenshooter_create(struct wlsc_compositor *ec); - -uint32_t * -wlsc_load_image(const char *filename, int width, int height); - -#endif diff --git a/compositor/drm.c b/compositor/drm.c deleted file mode 100644 index 9e25d33..0000000 --- a/compositor/drm.c +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Copyright © 2010 Kristian Høgsberg - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "compositor.h" - -struct wlsc_drm_buffer { - struct wl_buffer buffer; - EGLImageKHR image; -}; - -static void -drm_authenticate(struct wl_client *client, - struct wl_drm *drm_base, uint32_t id) -{ - struct wlsc_drm *drm = (struct wlsc_drm *) drm_base; - struct wlsc_compositor *compositor = - container_of(drm, struct wlsc_compositor, drm); - - if (compositor->authenticate(compositor, id) < 0) - wl_client_post_event(client, - (struct wl_object *) compositor->wl_display, - WL_DISPLAY_INVALID_OBJECT, 0); - else - wl_client_post_event(client, &drm->object, - WL_DRM_AUTHENTICATED); -} - -static void -destroy_buffer(struct wl_resource *resource, struct wl_client *client) -{ - struct wlsc_drm_buffer *buffer = - container_of(resource, struct wlsc_drm_buffer, buffer.resource); - struct wlsc_compositor *compositor = - (struct wlsc_compositor *) buffer->buffer.compositor; - - eglDestroyImageKHR(compositor->display, buffer->image); - free(buffer); -} - -static void -buffer_destroy(struct wl_client *client, struct wl_buffer *buffer) -{ - wl_resource_destroy(&buffer->resource, client); -} - -const static struct wl_buffer_interface buffer_interface = { - buffer_destroy -}; - -static void -drm_buffer_attach(struct wl_buffer *buffer_base, struct wl_surface *surface) -{ - struct wlsc_surface *es = (struct wlsc_surface *) surface; - struct wlsc_drm_buffer *buffer = - (struct wlsc_drm_buffer *) buffer_base; - - glBindTexture(GL_TEXTURE_2D, es->texture); - glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, buffer->image); - es->visual = buffer->buffer.visual; -} - -static void -drm_buffer_damage(struct wl_buffer *buffer, - struct wl_surface *surface, - int32_t x, int32_t y, int32_t width, int32_t height) -{ -} - -static struct wlsc_drm_buffer * -wlsc_drm_buffer_create_for_image(struct wlsc_compositor *compositor, - EGLImageKHR *image, - int32_t width, int32_t height, - struct wl_visual *visual) -{ - struct wlsc_drm_buffer *buffer; - - buffer = malloc(sizeof *buffer); - if (buffer == NULL) - return NULL; - - buffer->buffer.compositor = &compositor->compositor; - buffer->buffer.width = width; - buffer->buffer.height = height; - buffer->buffer.visual = visual; - buffer->buffer.attach = drm_buffer_attach; - buffer->buffer.damage = drm_buffer_damage; - buffer->image = image; - - return buffer; -} - -static void -drm_create_buffer(struct wl_client *client, struct wl_drm *drm_base, - uint32_t id, uint32_t name, int32_t width, int32_t height, - uint32_t stride, struct wl_visual *visual) -{ - struct wlsc_drm *drm = (struct wlsc_drm *) drm_base; - struct wlsc_compositor *compositor = - container_of(drm, struct wlsc_compositor, drm); - struct wlsc_drm_buffer *buffer; - EGLImageKHR image; - EGLint attribs[] = { - EGL_WIDTH, 0, - EGL_HEIGHT, 0, - EGL_DRM_BUFFER_STRIDE_MESA, 0, - EGL_DRM_BUFFER_FORMAT_MESA, EGL_DRM_BUFFER_FORMAT_ARGB32_MESA, - EGL_NONE - }; - - if (visual->object.interface != &wl_visual_interface) { - /* FIXME: Define a real exception event instead of - * abusing this one */ - wl_client_post_event(client, - (struct wl_object *) compositor->wl_display, - WL_DISPLAY_INVALID_OBJECT, 0); - fprintf(stderr, "invalid visual in create_buffer\n"); - return; - } - - attribs[1] = width; - attribs[3] = height; - attribs[5] = stride / 4; - image = eglCreateImageKHR(compositor->display, - EGL_NO_CONTEXT, - EGL_DRM_BUFFER_MESA, - (EGLClientBuffer) name, attribs); - if (image == NULL) { - /* FIXME: Define a real exception event instead of - * abusing this one */ - wl_client_post_event(client, - (struct wl_object *) compositor->wl_display, - WL_DISPLAY_INVALID_OBJECT, 0); - fprintf(stderr, "failed to create image for name %d\n", name); - return; - } - - buffer = wlsc_drm_buffer_create_for_image(compositor, image, - width, height, visual); - if (buffer == NULL) { - eglDestroyImageKHR(compositor->display, image); - wl_client_post_no_memory(client); - return; - } - - buffer->buffer.resource.object.id = id; - buffer->buffer.resource.object.interface = &wl_buffer_interface; - buffer->buffer.resource.object.implementation = (void (**)(void)) - &buffer_interface; - - buffer->buffer.resource.destroy = destroy_buffer; - - wl_client_add_resource(client, &buffer->buffer.resource); -} - -const static struct wl_drm_interface drm_interface = { - drm_authenticate, - drm_create_buffer -}; - -static void -post_drm_device(struct wl_client *client, struct wl_object *global) -{ - struct wlsc_drm *drm = container_of(global, struct wlsc_drm, object); - - wl_client_post_event(client, global, WL_DRM_DEVICE, drm->filename); -} - -int -wlsc_drm_init(struct wlsc_compositor *ec, int fd, const char *filename) -{ - struct wlsc_drm *drm = &ec->drm; - - drm->fd = fd; - drm->filename = strdup(filename); - if (drm->filename == NULL) - return -1; - - drm->object.interface = &wl_drm_interface; - drm->object.implementation = (void (**)(void)) &drm_interface; - wl_display_add_object(ec->wl_display, &drm->object); - wl_display_add_global(ec->wl_display, &drm->object, post_drm_device); - - return 0; -} - -struct wl_buffer * -wlsc_drm_buffer_create(struct wlsc_compositor *ec, int width, int height, - struct wl_visual *visual, const void *data) -{ - struct wlsc_drm_buffer *buffer; - EGLImageKHR image; - GLuint texture; - - EGLint image_attribs[] = { - EGL_WIDTH, 0, - EGL_HEIGHT, 0, - EGL_DRM_BUFFER_FORMAT_MESA, EGL_DRM_BUFFER_FORMAT_ARGB32_MESA, - EGL_DRM_BUFFER_USE_MESA, EGL_DRM_BUFFER_USE_SCANOUT_MESA, - EGL_NONE - }; - - image_attribs[1] = width; - image_attribs[3] = height; - - image = eglCreateDRMImageMESA(ec->display, image_attribs); - if (image == NULL) - return NULL; - - buffer = wlsc_drm_buffer_create_for_image(ec, image, - width, height, visual); - - glGenTextures(1, &texture); - glBindTexture(GL_TEXTURE_2D, texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, buffer->image); - - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, - GL_BGRA_EXT, GL_UNSIGNED_BYTE, data); - - glDeleteTextures(1, &texture); - - return &buffer->buffer; -} diff --git a/compositor/evdev.c b/compositor/evdev.c deleted file mode 100644 index 6ff7b69..0000000 --- a/compositor/evdev.c +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Copyright © 2010 Intel Corporation - * - * Permission to use, copy, modify, distribute, and sell this software and - * its documentation for any purpose is hereby granted without fee, provided - * that the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of the copyright holders not be used in - * advertising or publicity pertaining to distribution of the software - * without specific, written prior permission. The copyright holders make - * no representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER - * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF - * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <linux/input.h> -#include <unistd.h> -#include <fcntl.h> - -#include "compositor.h" - -struct evdev_input { - struct wlsc_input_device base; -}; - -struct evdev_input_device { - struct evdev_input *master; - struct wl_event_source *source; - int tool, new_x, new_y; - int base_x, base_y; - int fd; - int min_x, max_x, min_y, max_y; -}; - -static void evdev_input_device_data(int fd, uint32_t mask, void *data) -{ - struct wlsc_compositor *ec; - struct evdev_input_device *device = data; - struct input_event ev[8], *e, *end; - int len, value, dx, dy, absolute_event; - int x, y; - uint32_t time; - - /* FIXME: Obviously we need to not hardcode these here, but - * instead get the values from the output it's associated with. */ - const int screen_width = 1024, screen_height = 600; - - ec = (struct wlsc_compositor *) - device->master->base.input_device.compositor; - if (!ec->focus) - return; - - dx = 0; - dy = 0; - absolute_event = 0; - x = device->master->base.input_device.x; - y = device->master->base.input_device.y; - - len = read(fd, &ev, sizeof ev); - if (len < 0 || len % sizeof e[0] != 0) { - /* FIXME: handle error... reopen device? */; - return; - } - - e = ev; - end = (void *) ev + len; - for (e = ev; e < end; e++) { - /* Get the signed value, earlier kernels had this as unsigned */ - value = e->value; - time = e->time.tv_sec * 1000 + e->time.tv_usec / 1000; - - switch (e->type) { - case EV_REL: - switch (e->code) { - case REL_X: - dx += value; - break; - - case REL_Y: - dy += value; - break; - } - break; - - case EV_ABS: - switch (e->code) { - case ABS_X: - absolute_event = device->tool; - x = (value - device->min_x) * screen_width / - (device->max_x - device->min_x); - break; - case ABS_Y: - absolute_event = device->tool; - y = (value - device->min_y) * screen_height / - (device->max_y - device->min_y); - break; - } - break; - - case EV_KEY: - if (value == 2) - break; - - switch (e->code) { - case BTN_TOUCH: - case BTN_TOOL_PEN: - case BTN_TOOL_RUBBER: - case BTN_TOOL_BRUSH: - case BTN_TOOL_PENCIL: - case BTN_TOOL_AIRBRUSH: - case BTN_TOOL_FINGER: - case BTN_TOOL_MOUSE: - case BTN_TOOL_LENS: - device->tool = value ? e->code : 0; - break; - - case BTN_LEFT: - case BTN_RIGHT: - case BTN_MIDDLE: - case BTN_SIDE: - case BTN_EXTRA: - case BTN_FORWARD: - case BTN_BACK: - case BTN_TASK: - notify_button(&device->master->base.input_device, - time, e->code, value); - break; - - default: - notify_key(&device->master->base.input_device, - time, e->code, value); - break; - } - } - } - - if (dx != 0 || dy != 0) - notify_motion(&device->master->base.input_device, - time, x + dx, y + dy); - if (absolute_event) - notify_motion(&device->master->base.input_device, time, x, y); -} - -#define TEST_BIT(b, i) (b[(i) / 32] & (1 << (i & 31))) - -static struct evdev_input_device * -evdev_input_device_create(struct evdev_input *master, - struct wl_display *display, const char *path) -{ - struct evdev_input_device *device; - struct wl_event_loop *loop; - struct input_absinfo absinfo; - uint32_t ev_bits[EV_MAX]; - uint32_t key_bits[KEY_MAX]; - - device = malloc(sizeof *device); - if (device == NULL) - return NULL; - - device->tool = 1; - device->new_x = 1; - device->new_y = 1; - device->master = master; - - device->fd = open(path, O_RDONLY); - if (device->fd < 0) { - free(device); - fprintf(stderr, "couldn't create pointer for %s: %m\n", path); - return NULL; - } - - ioctl(device->fd, EVIOCGBIT(0, EV_MAX), ev_bits); - if (TEST_BIT(ev_bits, EV_ABS)) { - ioctl(device->fd, EVIOCGBIT(EV_ABS, EV_MAX), key_bits); - if (TEST_BIT(key_bits, ABS_X)) { - ioctl(device->fd, EVIOCGABS(ABS_X), &absinfo); - device->min_x = absinfo.minimum; - device->max_x = absinfo.maximum; - } - if (TEST_BIT(key_bits, ABS_Y)) { - ioctl(device->fd, EVIOCGABS(ABS_Y), &absinfo); - device->min_y = absinfo.minimum; - device->max_y = absinfo.maximum; - } - } - - loop = wl_display_get_event_loop(display); - device->source = wl_event_loop_add_fd(loop, device->fd, - WL_EVENT_READABLE, - evdev_input_device_data, device); - if (device->source == NULL) { - close(device->fd); - free(device); - return NULL; - } - - return device; -} - -void -evdev_input_add_devices(struct wlsc_compositor *c, struct udev *udev) -{ - struct evdev_input *input; - struct udev_enumerate *e; - struct udev_list_entry *entry; - struct udev_device *device; - const char *path; - - input = malloc(sizeof *input); - if (input == NULL) - return; - - memset(input, 0, sizeof *input); - wlsc_input_device_init(&input->base, c); - - e = udev_enumerate_new(udev); - udev_enumerate_add_match_subsystem(e, "input"); - udev_enumerate_add_match_property(e, "WAYLAND_SEAT", "1"); - udev_enumerate_scan_devices(e); - udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) { - path = udev_list_entry_get_name(entry); - device = udev_device_new_from_syspath(udev, path); - evdev_input_device_create(input, c->wl_display, - udev_device_get_devnode(device)); - } - udev_enumerate_unref(e); - - c->input_device = &input->base.input_device; -} diff --git a/compositor/screenshooter.c b/compositor/screenshooter.c deleted file mode 100644 index 53ed931..0000000 --- a/compositor/screenshooter.c +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright © 2008 Kristian Høgsberg - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include <stdlib.h> -#include <GLES2/gl2.h> -#include <gdk-pixbuf/gdk-pixbuf.h> - -#include "compositor.h" -#include "screenshooter-server-protocol.h" - -struct wl_screenshooter { - struct wl_object base; - struct wlsc_compositor *ec; -}; - -static void -screenshooter_shoot(struct wl_client *client, struct wl_screenshooter *shooter) -{ - struct wlsc_compositor *ec = shooter->ec; - struct wlsc_output *output; - char buffer[256]; - GdkPixbuf *pixbuf; - GError *error = NULL; - unsigned char *data; - int i, j; - - i = 0; - wl_list_for_each(output, &ec->output_list, link) { - snprintf(buffer, sizeof buffer, "wayland-screenshot-%d.png", i++); - data = malloc(output->width * output->height * 4); - if (data == NULL) { - fprintf(stderr, "couldn't allocate image buffer\n"); - continue; - } - - glPixelStorei(GL_PACK_ALIGNMENT, 1); - glReadPixels(0, 0, output->width, output->height, - GL_RGBA, GL_UNSIGNED_BYTE, data); - - /* FIXME: We should just use a RGB visual for the frontbuffer. */ - for (j = 3; j < output->width * output->height * 4; j += 4) - data[j] = 0xff; - - pixbuf = gdk_pixbuf_new_from_data(data, GDK_COLORSPACE_RGB, TRUE, - 8, output->width, output->height, output->width * 4, - NULL, NULL); - gdk_pixbuf_save(pixbuf, buffer, "png", &error, NULL); - g_object_unref(pixbuf); - free(data); - } -} - -struct wl_screenshooter_interface screenshooter_implementation = { - screenshooter_shoot -}; - -void -screenshooter_create(struct wlsc_compositor *ec) -{ - struct wl_screenshooter *shooter; - - shooter = malloc(sizeof *shooter); - if (shooter == NULL) - return; - - shooter->base.interface = &wl_screenshooter_interface; - shooter->base.implementation = - (void(**)(void)) &screenshooter_implementation; - shooter->ec = ec; - - wl_display_add_object(ec->wl_display, &shooter->base); - wl_display_add_global(ec->wl_display, &shooter->base, NULL); -}; diff --git a/compositor/shell.c b/compositor/shell.c deleted file mode 100644 index a19d3db..0000000 --- a/compositor/shell.c +++ /dev/null @@ -1,676 +0,0 @@ -/* - * Copyright © 2010 Intel Corporation - * - * Permission to use, copy, modify, distribute, and sell this software and - * its documentation for any purpose is hereby granted without fee, provided - * that the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of the copyright holders not be used in - * advertising or publicity pertaining to distribution of the software - * without specific, written prior permission. The copyright holders make - * no representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER - * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF - * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include "wayland-server.h" -#include "compositor.h" - -struct wlsc_move_grab { - struct wl_grab grab; - struct wlsc_surface *surface; - int32_t dx, dy; -}; - -static void -move_grab_motion(struct wl_grab *grab, - uint32_t time, int32_t x, int32_t y) -{ - struct wlsc_move_grab *move = (struct wlsc_move_grab *) grab; - struct wlsc_surface *es = move->surface; - - wlsc_surface_damage(es); - es->x = x + move->dx; - es->y = y + move->dy; - wlsc_surface_update_matrix(es); - wlsc_surface_damage(es); -} - -static void -move_grab_button(struct wl_grab *grab, - uint32_t time, int32_t button, int32_t state) -{ -} - -static void -move_grab_end(struct wl_grab *grab, uint32_t time) -{ - struct wlsc_surface *es; - struct wl_input_device *device = grab->input_device; - int32_t sx, sy; - - es = pick_surface(grab->input_device, &sx, &sy); - wl_input_device_set_pointer_focus(device, - &es->surface, time, - device->x, device->y, sx, sy); - free(grab); -} - -static const struct wl_grab_interface move_grab_interface = { - move_grab_motion, - move_grab_button, - move_grab_end -}; - -void -shell_move(struct wl_client *client, struct wl_shell *shell, - struct wl_surface *surface, - struct wl_input_device *device, uint32_t time) -{ - struct wlsc_input_device *wd = (struct wlsc_input_device *) device; - struct wlsc_surface *es = (struct wlsc_surface *) surface; - struct wlsc_move_grab *move; - - /* FIXME: Reject if fullscreen */ - - move = malloc(sizeof *move); - if (!move) { - wl_client_post_no_memory(client); - return; - } - - move->grab.interface = &move_grab_interface; - move->dx = es->x - wd->input_device.grab_x; - move->dy = es->y - wd->input_device.grab_y; - move->surface = es; - - if (wl_input_device_update_grab(&wd->input_device, - &move->grab, surface, time) < 0) - return; - - wlsc_input_device_set_pointer_image(wd, WLSC_POINTER_DRAGGING); - wl_input_device_set_pointer_focus(device, NULL, time, 0, 0, 0, 0); -} - -struct wlsc_resize_grab { - struct wl_grab grab; - uint32_t edges; - int32_t dx, dy, width, height; - struct wlsc_surface *surface; -}; - -static void -resize_grab_motion(struct wl_grab *grab, - uint32_t time, int32_t x, int32_t y) -{ - struct wlsc_resize_grab *resize = (struct wlsc_resize_grab *) grab; - struct wl_input_device *device = grab->input_device; - struct wlsc_compositor *ec = - (struct wlsc_compositor *) device->compositor; - struct wl_surface *surface = &resize->surface->surface; - int32_t width, height; - - if (resize->edges & WL_SHELL_RESIZE_LEFT) { - width = device->grab_x - x + resize->width; - } else if (resize->edges & WL_SHELL_RESIZE_RIGHT) { - width = x - device->grab_x + resize->width; - } else { - width = resize->width; - } - - if (resize->edges & WL_SHELL_RESIZE_TOP) { - height = device->grab_y - y + resize->height; - } else if (resize->edges & WL_SHELL_RESIZE_BOTTOM) { - height = y - device->grab_y + resize->height; - } else { - height = resize->height; - } - - wl_client_post_event(surface->client, &ec->shell.object, - WL_SHELL_CONFIGURE, time, resize->edges, - surface, width, height); -} - -static void -resize_grab_button(struct wl_grab *grab, - uint32_t time, int32_t button, int32_t state) -{ -} - -static void -resize_grab_end(struct wl_grab *grab, uint32_t time) -{ - struct wlsc_surface *es; - struct wl_input_device *device = grab->input_device; - int32_t sx, sy; - - es = pick_surface(grab->input_device, &sx, &sy); - wl_input_device_set_pointer_focus(device, - &es->surface, time, - device->x, device->y, sx, sy); - free(grab); -} - -static const struct wl_grab_interface resize_grab_interface = { - resize_grab_motion, - resize_grab_button, - resize_grab_end -}; - -void -shell_resize(struct wl_client *client, struct wl_shell *shell, - struct wl_surface *surface, - struct wl_input_device *device, uint32_t time, uint32_t edges) -{ - struct wlsc_input_device *wd = (struct wlsc_input_device *) device; - struct wlsc_resize_grab *resize; - enum wlsc_pointer_type pointer = WLSC_POINTER_LEFT_PTR; - struct wlsc_surface *es = (struct wlsc_surface *) surface; - - /* FIXME: Reject if fullscreen */ - - resize = malloc(sizeof *resize); - if (!resize) { - wl_client_post_no_memory(client); - return; - } - - resize->grab.interface = &resize_grab_interface; - resize->edges = edges; - resize->dx = es->x - wd->input_device.grab_x; - resize->dy = es->y - wd->input_device.grab_y; - resize->width = es->width; - resize->height = es->height; - resize->surface = es; - - if (edges == 0 || edges > 15 || - (edges & 3) == 3 || (edges & 12) == 12) - return; - - switch (edges) { - case WL_SHELL_RESIZE_TOP: - pointer = WLSC_POINTER_TOP; - break; - case WL_SHELL_RESIZE_BOTTOM: - pointer = WLSC_POINTER_BOTTOM; - break; - case WL_SHELL_RESIZE_LEFT: - pointer = WLSC_POINTER_LEFT; - break; - case WL_SHELL_RESIZE_TOP_LEFT: - pointer = WLSC_POINTER_TOP_LEFT; - break; - case WL_SHELL_RESIZE_BOTTOM_LEFT: - pointer = WLSC_POINTER_BOTTOM_LEFT; - break; - case WL_SHELL_RESIZE_RIGHT: - pointer = WLSC_POINTER_RIGHT; - break; - case WL_SHELL_RESIZE_TOP_RIGHT: - pointer = WLSC_POINTER_TOP_RIGHT; - break; - case WL_SHELL_RESIZE_BOTTOM_RIGHT: - pointer = WLSC_POINTER_BOTTOM_RIGHT; - break; - } - - if (wl_input_device_update_grab(&wd->input_device, - &resize->grab, surface, time) < 0) - return; - - wlsc_input_device_set_pointer_image(wd, pointer); - wl_input_device_set_pointer_focus(device, NULL, time, 0, 0, 0, 0); -} - -static void -destroy_drag(struct wl_resource *resource, struct wl_client *client) -{ - struct wl_drag *drag = - container_of(resource, struct wl_drag, resource); - - wl_list_remove(&drag->drag_focus_listener.link); - if (drag->grab.input_device) - wl_input_device_end_grab(drag->grab.input_device, get_time()); - - free(drag); -} - - -static void -wl_drag_set_pointer_focus(struct wl_drag *drag, - struct wl_surface *surface, uint32_t time, - int32_t x, int32_t y, int32_t sx, int32_t sy) -{ - char **p, **end; - - if (drag->drag_focus == surface) - return; - - if (drag->drag_focus && - (!surface || drag->drag_focus->client != surface->client)) - wl_client_post_event(drag->drag_focus->client, - &drag->drag_offer.object, - WL_DRAG_OFFER_POINTER_FOCUS, - time, NULL, 0, 0, 0, 0); - - if (surface && - (!drag->drag_focus || - drag->drag_focus->client != surface->client)) { - wl_client_post_global(surface->client, - &drag->drag_offer.object); - - end = drag->types.data + drag->types.size; - for (p = drag->types.data; p < end; p++) - wl_client_post_event(surface->client, - &drag->drag_offer.object, - WL_DRAG_OFFER_OFFER, *p); - } - - if (surface) { - wl_client_post_event(surface->client, - &drag->drag_offer.object, - WL_DRAG_OFFER_POINTER_FOCUS, - time, surface, - x, y, sx, sy); - - } - - drag->drag_focus = surface; - drag->pointer_focus_time = time; - drag->target = NULL; - - wl_list_remove(&drag->drag_focus_listener.link); - if (surface) - wl_list_insert(surface->destroy_listener_list.prev, - &drag->drag_focus_listener.link); -} - -static void -drag_offer_accept(struct wl_client *client, - struct wl_drag_offer *offer, uint32_t time, const char *type) -{ - struct wl_drag *drag = container_of(offer, struct wl_drag, drag_offer); - char **p, **end; - - /* If the client responds to drag pointer_focus or motion - * events after the pointer has left the surface, we just - * discard the accept requests. The drag source just won't - * get the corresponding 'target' events and eventually the - * next surface/root will start sending events. */ - if (time < drag->pointer_focus_time) - return; - - drag->target = client; - drag->type = NULL; - end = drag->types.data + drag->types.size; - for (p = drag->types.data; p < end; p++) - if (type && strcmp(*p, type) == 0) - drag->type = *p; - - wl_client_post_event(drag->source->client, &drag->resource.object, - WL_DRAG_TARGET, drag->type); -} - -static void -drag_offer_receive(struct wl_client *client, - struct wl_drag_offer *offer, int fd) -{ - struct wl_drag *drag = container_of(offer, struct wl_drag, drag_offer); - - wl_client_post_event(drag->source->client, &drag->resource.object, - WL_DRAG_FINISH, fd); - close(fd); -} - -static void -drag_offer_reject(struct wl_client *client, struct wl_drag_offer *offer) -{ - struct wl_drag *drag = container_of(offer, struct wl_drag, drag_offer); - - wl_client_post_event(drag->source->client, &drag->resource.object, - WL_DRAG_REJECT); -} - -static const struct wl_drag_offer_interface drag_offer_interface = { - drag_offer_accept, - drag_offer_receive, - drag_offer_reject -}; - -static void -drag_offer(struct wl_client *client, struct wl_drag *drag, const char *type) -{ - char **p; - - p = wl_array_add(&drag->types, sizeof *p); - if (p) - *p = strdup(type); - if (!p || !*p) - wl_client_post_no_memory(client); -} - -static void -drag_grab_motion(struct wl_grab *grab, - uint32_t time, int32_t x, int32_t y) -{ - struct wl_drag *drag = container_of(grab, struct wl_drag, grab); - struct wlsc_surface *es; - int32_t sx, sy; - - es = pick_surface(grab->input_device, &sx, &sy); - wl_drag_set_pointer_focus(drag, &es->surface, time, x, y, sx, sy); - if (es) - wl_client_post_event(es->surface.client, - &drag->drag_offer.object, - WL_DRAG_OFFER_MOTION, - time, x, y, sx, sy); -} - -static void -drag_grab_button(struct wl_grab *grab, - uint32_t time, int32_t button, int32_t state) -{ -} - -static void -drag_grab_end(struct wl_grab *grab, uint32_t time) -{ - struct wl_drag *drag = container_of(grab, struct wl_drag, grab); - struct wlsc_surface *es; - struct wl_input_device *device = grab->input_device; - int32_t sx, sy; - - if (drag->target) - wl_client_post_event(drag->target, - &drag->drag_offer.object, - WL_DRAG_OFFER_DROP); - - wl_drag_set_pointer_focus(drag, NULL, time, 0, 0, 0, 0); - - es = pick_surface(grab->input_device, &sx, &sy); - wl_input_device_set_pointer_focus(device, - &es->surface, time, - device->x, device->y, sx, sy); -} - -static const struct wl_grab_interface drag_grab_interface = { - drag_grab_motion, - drag_grab_button, - drag_grab_end -}; - -static void -drag_activate(struct wl_client *client, - struct wl_drag *drag, - struct wl_surface *surface, - struct wl_input_device *device, uint32_t time) -{ - struct wl_display *display = wl_client_get_display (client); - struct wlsc_surface *target; - int32_t sx, sy; - - if (wl_input_device_update_grab(device, - &drag->grab, surface, time) < 0) - return; - - drag->grab.interface = &drag_grab_interface; - - drag->source = surface; - - drag->drag_offer.object.interface = &wl_drag_offer_interface; - drag->drag_offer.object.implementation = - (void (**)(void)) &drag_offer_interface; - - wl_display_add_object(display, &drag->drag_offer.object); - - target = pick_surface(device, &sx, &sy); - wl_input_device_set_pointer_focus(device, NULL, time, 0, 0, 0, 0); - wl_drag_set_pointer_focus(drag, &target->surface, time, - device->x, device->y, sx, sy); -} - -static void -drag_destroy(struct wl_client *client, struct wl_drag *drag) -{ - wl_resource_destroy(&drag->resource, client); -} - -static const struct wl_drag_interface drag_interface = { - drag_offer, - drag_activate, - drag_destroy, -}; - -static void -drag_handle_surface_destroy(struct wl_listener *listener, - struct wl_surface *surface, uint32_t time) -{ - struct wl_drag *drag = - container_of(listener, struct wl_drag, drag_focus_listener); - - if (drag->drag_focus == surface) - wl_drag_set_pointer_focus(drag, NULL, time, 0, 0, 0, 0); -} - -static void -shell_create_drag(struct wl_client *client, - struct wl_shell *shell, uint32_t id) -{ - struct wl_drag *drag; - - drag = malloc(sizeof *drag); - if (drag == NULL) { - wl_client_post_no_memory(client); - return; - } - - memset(drag, 0, sizeof *drag); - drag->resource.object.id = id; - drag->resource.object.interface = &wl_drag_interface; - drag->resource.object.implementation = - (void (**)(void)) &drag_interface; - - drag->resource.destroy = destroy_drag; - - drag->drag_focus_listener.func = drag_handle_surface_destroy; - wl_list_init(&drag->drag_focus_listener.link); - - wl_client_add_resource(client, &drag->resource); -} - -void -wlsc_selection_set_focus(struct wl_selection *selection, - struct wl_surface *surface, uint32_t time) -{ - char **p, **end; - - if (selection->selection_focus == surface) - return; - - if (selection->selection_focus != NULL) - wl_client_post_event(selection->selection_focus->client, - &selection->selection_offer.object, - WL_SELECTION_OFFER_KEYBOARD_FOCUS, - NULL); - - if (surface) { - wl_client_post_global(surface->client, - &selection->selection_offer.object); - - end = selection->types.data + selection->types.size; - for (p = selection->types.data; p < end; p++) - wl_client_post_event(surface->client, - &selection->selection_offer.object, - WL_SELECTION_OFFER_OFFER, *p); - - wl_list_remove(&selection->selection_focus_listener.link); - wl_list_insert(surface->destroy_listener_list.prev, - &selection->selection_focus_listener.link); - - wl_client_post_event(surface->client, - &selection->selection_offer.object, - WL_SELECTION_OFFER_KEYBOARD_FOCUS, - selection->input_device); - } - - selection->selection_focus = surface; - - wl_list_remove(&selection->selection_focus_listener.link); - if (surface) - wl_list_insert(surface->destroy_listener_list.prev, - &selection->selection_focus_listener.link); -} - -static void -selection_offer_receive(struct wl_client *client, - struct wl_selection_offer *offer, - const char *mime_type, int fd) -{ - struct wl_selection *selection = - container_of(offer, struct wl_selection, selection_offer); - - wl_client_post_event(selection->client, - &selection->resource.object, - WL_SELECTION_SEND, mime_type, fd); - close(fd); -} - -static const struct wl_selection_offer_interface selection_offer_interface = { - selection_offer_receive -}; - -static void -selection_offer(struct wl_client *client, - struct wl_selection *selection, const char *type) -{ - char **p; - - p = wl_array_add(&selection->types, sizeof *p); - if (p) - *p = strdup(type); - if (!p || !*p) - wl_client_post_no_memory(client); -} - -static void -selection_activate(struct wl_client *client, - struct wl_selection *selection, - struct wl_input_device *device, uint32_t time) -{ - struct wlsc_input_device *wd = (struct wlsc_input_device *) device; - struct wl_display *display = wl_client_get_display (client); - - selection->input_device = device; - - selection->selection_offer.object.interface = - &wl_selection_offer_interface; - selection->selection_offer.object.implementation = - (void (**)(void)) &selection_offer_interface; - - wl_display_add_object(display, &selection->selection_offer.object); - - if (wd->selection) { - wl_client_post_event(wd->selection->client, - &wd->selection->resource.object, - WL_SELECTION_CANCELLED); - } - wd->selection = selection; - - wlsc_selection_set_focus(selection, device->keyboard_focus, time); -} - -static void -selection_destroy(struct wl_client *client, struct wl_selection *selection) -{ - wl_resource_destroy(&selection->resource, client); -} - -static const struct wl_selection_interface selection_interface = { - selection_offer, - selection_activate, - selection_destroy -}; - -static void -destroy_selection(struct wl_resource *resource, struct wl_client *client) -{ - struct wl_selection *selection = - container_of(resource, struct wl_selection, resource); - struct wlsc_input_device *wd = - (struct wlsc_input_device *) selection->input_device; - - if (wd && wd->selection == selection) { - wd->selection = NULL; - wlsc_selection_set_focus(selection, NULL, get_time()); - } - - wl_list_remove(&selection->selection_focus_listener.link); - free(selection); -} - -static void -selection_handle_surface_destroy(struct wl_listener *listener, - struct wl_surface *surface, uint32_t time) -{ -} - -static void -shell_create_selection(struct wl_client *client, - struct wl_shell *shell, uint32_t id) -{ - struct wl_selection *selection; - - selection = malloc(sizeof *selection); - if (selection == NULL) { - wl_client_post_no_memory(client); - return; - } - - memset(selection, 0, sizeof *selection); - selection->resource.object.id = id; - selection->resource.object.interface = &wl_selection_interface; - selection->resource.object.implementation = - (void (**)(void)) &selection_interface; - - selection->client = client; - selection->resource.destroy = destroy_selection; - selection->selection_focus = NULL; - - selection->selection_focus_listener.func = - selection_handle_surface_destroy; - wl_list_init(&selection->selection_focus_listener.link); - - wl_client_add_resource(client, &selection->resource); -} - -const static struct wl_shell_interface shell_interface = { - shell_move, - shell_resize, - shell_create_drag, - shell_create_selection -}; - -int -wlsc_shell_init(struct wlsc_compositor *ec) -{ - struct wl_shell *shell = &ec->shell; - - shell->object.interface = &wl_shell_interface; - shell->object.implementation = (void (**)(void)) &shell_interface; - wl_display_add_object(ec->wl_display, &shell->object); - if (wl_display_add_global(ec->wl_display, &shell->object, NULL)) - return -1; - - return 0; -} diff --git a/compositor/shm.c b/compositor/shm.c deleted file mode 100644 index 389eeaa..0000000 --- a/compositor/shm.c +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright © 2010 Kristian Høgsberg - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/mman.h> -#include <unistd.h> - -#include "compositor.h" - -struct wlsc_shm_buffer { - struct wl_buffer buffer; - int32_t stride; - void *data; -}; - -static void -destroy_buffer(struct wl_resource *resource, struct wl_client *client) -{ - struct wlsc_shm_buffer *buffer = - container_of(resource, struct wlsc_shm_buffer, buffer.resource); - - munmap(buffer->data, buffer->stride * buffer->buffer.height); - free(buffer); -} - -static void -buffer_destroy(struct wl_client *client, struct wl_buffer *buffer) -{ - // wl_resource_destroy(&buffer->base, client); -} - -const static struct wl_buffer_interface buffer_interface = { - buffer_destroy -}; - -static void -shm_buffer_attach(struct wl_buffer *buffer_base, struct wl_surface *surface) -{ - struct wlsc_surface *es = (struct wlsc_surface *) surface; - struct wlsc_shm_buffer *buffer = - (struct wlsc_shm_buffer *) buffer_base; - - glBindTexture(GL_TEXTURE_2D, es->texture); - - /* Unbind any EGLImage texture that may be bound, so we don't - * overwrite it.*/ - glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, - 0, 0, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, NULL); - glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, - buffer->buffer.width, buffer->buffer.height, 0, - GL_BGRA_EXT, GL_UNSIGNED_BYTE, buffer->data); - es->visual = buffer->buffer.visual; -} - -static void -shm_buffer_damage(struct wl_buffer *buffer_base, - struct wl_surface *surface, - int32_t x, int32_t y, int32_t width, int32_t height) -{ - struct wlsc_surface *es = (struct wlsc_surface *) surface; - struct wlsc_shm_buffer *buffer = - (struct wlsc_shm_buffer *) buffer_base; - - glBindTexture(GL_TEXTURE_2D, es->texture); - glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, - buffer->buffer.width, buffer->buffer.height, 0, - GL_BGRA_EXT, GL_UNSIGNED_BYTE, buffer->data); - - /* Hmm, should use glTexSubImage2D() here but GLES2 doesn't - * support any unpack attributes except GL_UNPACK_ALIGNMENT. */ -} - -static void -shm_create_buffer(struct wl_client *client, struct wl_shm *shm, - uint32_t id, int fd, int32_t width, int32_t height, - uint32_t stride, struct wl_visual *visual) -{ - struct wlsc_compositor *compositor = - container_of((struct wlsc_shm *) shm, - struct wlsc_compositor, shm); - struct wlsc_shm_buffer *buffer; - - /* FIXME: Define a real exception event instead of abusing the - * display.invalid_object error */ - if (visual->object.interface != &wl_visual_interface) { - wl_client_post_event(client, - (struct wl_object *) compositor->wl_display, - WL_DISPLAY_INVALID_OBJECT, 0); - fprintf(stderr, "invalid visual in create_buffer\n"); - close(fd); - return; - } - - if (width < 0 || height < 0 || stride < width) { - wl_client_post_event(client, - (struct wl_object *) compositor->wl_display, - WL_DISPLAY_INVALID_OBJECT, 0); - fprintf(stderr, - "invalid width, height or stride in create_buffer\n"); - close(fd); - return; - } - - buffer = malloc(sizeof *buffer); - if (buffer == NULL) { - close(fd); - wl_client_post_no_memory(client); - return; - } - - buffer->buffer.compositor = (struct wl_compositor *) compositor; - buffer->buffer.width = width; - buffer->buffer.height = height; - buffer->buffer.visual = visual; - buffer->buffer.attach = shm_buffer_attach; - buffer->buffer.damage = shm_buffer_damage; - buffer->stride = stride; - buffer->data = - mmap(NULL, stride * height, PROT_READ, MAP_SHARED, fd, 0); - close(fd); - if (buffer->data == MAP_FAILED) { - /* FIXME: Define a real exception event instead of - * abusing this one */ - free(buffer); - wl_client_post_event(client, - (struct wl_object *) compositor->wl_display, - WL_DISPLAY_INVALID_OBJECT, 0); - fprintf(stderr, "failed to create image for fd %d\n", fd); - return; - } - - buffer->buffer.resource.object.id = id; - buffer->buffer.resource.object.interface = &wl_buffer_interface; - buffer->buffer.resource.object.implementation = (void (**)(void)) - &buffer_interface; - - buffer->buffer.resource.destroy = destroy_buffer; - - wl_client_add_resource(client, &buffer->buffer.resource); -} - -const static struct wl_shm_interface shm_interface = { - shm_create_buffer -}; - -int -wlsc_shm_init(struct wlsc_compositor *ec) -{ - struct wlsc_shm *shm = &ec->shm; - - shm->object.interface = &wl_shm_interface; - shm->object.implementation = (void (**)(void)) &shm_interface; - wl_display_add_object(ec->wl_display, &shm->object); - wl_display_add_global(ec->wl_display, &shm->object, NULL); - - return 0; -} diff --git a/compositor/tty.c b/compositor/tty.c deleted file mode 100644 index 0de7584..0000000 --- a/compositor/tty.c +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright © 2010 Intel Corporation - * - * Permission to use, copy, modify, distribute, and sell this software and - * its documentation for any purpose is hereby granted without fee, provided - * that the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of the copyright holders not be used in - * advertising or publicity pertaining to distribution of the software - * without specific, written prior permission. The copyright holders make - * no representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER - * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF - * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <termios.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <fcntl.h> -#include <signal.h> -#include <linux/kd.h> -#include <linux/vt.h> -#include <sys/ioctl.h> - -#include "compositor.h" - -struct tty { - struct wlsc_compositor *compositor; - int fd; - struct termios terminal_attributes; - - struct wl_event_source *input_source; - struct wl_event_source *enter_vt_source; - struct wl_event_source *leave_vt_source; -}; - -static void on_enter_vt(int signal_number, void *data) -{ - struct tty *tty = data; - int ret; - - fprintf(stderr, "enter vt\n"); - - ioctl(tty->fd, VT_RELDISP, VT_ACKACQ); - ret = ioctl(tty->fd, KDSETMODE, KD_GRAPHICS); - if (ret) - fprintf(stderr, "failed to set KD_GRAPHICS mode on console: %m\n"); -} - -static void on_leave_vt(int signal_number, void *data) -{ - struct tty *tty = data; - int ret; - - ioctl (tty->fd, VT_RELDISP, 1); - ret = ioctl(tty->fd, KDSETMODE, KD_TEXT); - if (ret) - fprintf(stderr, - "failed to set KD_TEXT mode on console: %m\n"); -} - -static void -on_tty_input(int fd, uint32_t mask, void *data) -{ - struct tty *tty = data; - - /* Ignore input to tty. We get keyboard events from evdev - */ - tcflush(tty->fd, TCIFLUSH); -} - -struct tty * -tty_create(struct wlsc_compositor *compositor) -{ - struct termios raw_attributes; - struct vt_mode mode = { 0 }; - int ret; - struct tty *tty; - struct wl_event_loop *loop; - - tty = malloc(sizeof *tty); - if (tty == NULL) - return NULL; - - memset(tty, 0, sizeof *tty); - tty->compositor = compositor; - tty->fd = open("/dev/tty0", O_RDWR | O_NOCTTY); - if (tty->fd <= 0) { - fprintf(stderr, "failed to open active tty: %m\n"); - return NULL; - } - - if (tcgetattr(tty->fd, &tty->terminal_attributes) < 0) { - fprintf(stderr, "could not get terminal attributes: %m\n"); - return NULL; - } - - /* Ignore control characters and disable echo */ - raw_attributes = tty->terminal_attributes; - cfmakeraw(&raw_attributes); - - /* Fix up line endings to be normal (cfmakeraw hoses them) */ - raw_attributes.c_oflag |= OPOST | OCRNL; - - if (tcsetattr(tty->fd, TCSANOW, &raw_attributes) < 0) - fprintf(stderr, "could not put terminal into raw mode: %m\n"); - - loop = wl_display_get_event_loop(compositor->wl_display); - tty->input_source = - wl_event_loop_add_fd(loop, tty->fd, - WL_EVENT_READABLE, on_tty_input, tty); - - ret = ioctl(tty->fd, KDSETMODE, KD_GRAPHICS); - if (ret) { - fprintf(stderr, "failed to set KD_GRAPHICS mode on tty: %m\n"); - return NULL; - } - - tty->compositor->focus = 1; - mode.mode = VT_PROCESS; - mode.relsig = SIGUSR1; - mode.acqsig = SIGUSR2; - if (!ioctl(tty->fd, VT_SETMODE, &mode) < 0) { - fprintf(stderr, "failed to take control of vt handling\n"); - return NULL; - } - - tty->leave_vt_source = - wl_event_loop_add_signal(loop, SIGUSR1, on_leave_vt, tty); - tty->enter_vt_source = - wl_event_loop_add_signal(loop, SIGUSR2, on_enter_vt, tty); - - return tty; -} - -void -tty_destroy(struct tty *tty) -{ - if(!tty) - return; - - if (ioctl(tty->fd, KDSETMODE, KD_TEXT)) - fprintf(stderr, - "failed to set KD_TEXT mode on tty: %m\n"); - - if (tcsetattr(tty->fd, TCSANOW, &tty->terminal_attributes) < 0) - fprintf(stderr, - "could not restore terminal to canonical mode\n"); - - free(tty); -} |
