diff options
author | Kristian Høgsberg <krh@bitplanet.net> | 2011-04-12 09:52:44 -0400 |
---|---|---|
committer | Kristian Høgsberg <krh@bitplanet.net> | 2011-04-12 09:52:44 -0400 |
commit | c7514e8f0d19a833257497caff413bb4dfae6eb4 (patch) | |
tree | 7dc4bbd5b5a162b5b0b0277c68f7b7e3c6dd457b /gdk | |
parent | 85c1c22d04d369529ec4c3b6f608270f4f394cb5 (diff) | |
parent | fcd58b0ffd0935567437b89bb077f60195336764 (diff) | |
download | gtk+-c7514e8f0d19a833257497caff413bb4dfae6eb4.tar.gz |
Merge branch 'gdk-backend-wayland'
Conflicts:
Makefile.am
configure.ac
gdk/Makefile.am
gtk/gtksettings.c
gtk/gtkwindow.c
Diffstat (limited to 'gdk')
-rw-r--r-- | gdk/Makefile.am | 6 | ||||
-rw-r--r-- | gdk/gdkdisplaymanager.c | 9 | ||||
-rw-r--r-- | gdk/wayland/Makefile.am | 40 | ||||
-rw-r--r-- | gdk/wayland/gdkapplaunchcontext-wayland.c | 90 | ||||
-rw-r--r-- | gdk/wayland/gdkcursor-wayland.c | 383 | ||||
-rw-r--r-- | gdk/wayland/gdkdevice-wayland.c | 713 | ||||
-rw-r--r-- | gdk/wayland/gdkdisplay-wayland.c | 643 | ||||
-rw-r--r-- | gdk/wayland/gdkdisplay-wayland.h | 101 | ||||
-rw-r--r-- | gdk/wayland/gdkdisplaymanager-wayland.c | 318 | ||||
-rw-r--r-- | gdk/wayland/gdkdnd-wayland.c | 185 | ||||
-rw-r--r-- | gdk/wayland/gdkeventsource.c | 177 | ||||
-rw-r--r-- | gdk/wayland/gdkkeys-wayland.c | 654 | ||||
-rw-r--r-- | gdk/wayland/gdkprivate-wayland.h | 153 | ||||
-rw-r--r-- | gdk/wayland/gdkscreen-wayland.c | 550 | ||||
-rw-r--r-- | gdk/wayland/gdkselection-wayland.c | 93 | ||||
-rw-r--r-- | gdk/wayland/gdkwayland.h | 38 | ||||
-rw-r--r-- | gdk/wayland/gdkwindow-wayland.c | 1408 |
17 files changed, 5560 insertions, 1 deletions
diff --git a/gdk/Makefile.am b/gdk/Makefile.am index cc5346b0f8..cb1fd545aa 100644 --- a/gdk/Makefile.am +++ b/gdk/Makefile.am @@ -11,7 +11,7 @@ INTROSPECTION_COMPILER_ARGS = \ SUBDIRS = $(GDK_BACKENDS) . tests -DIST_SUBDIRS = win32 x11 quartz broadway tests +DIST_SUBDIRS = win32 x11 quartz broadway wayland tests CLEANFILES = @@ -177,6 +177,10 @@ if USE_BROADWAY libgdk_3_la_LIBADD += broadway/libgdk-broadway.la endif # USE_BROADWAY +if USE_WAYLAND +libgdk_3_la_LIBADD += wayland/libgdk-wayland.la +endif + if HAVE_INTROSPECTION introspection_files = \ diff --git a/gdk/gdkdisplaymanager.c b/gdk/gdkdisplaymanager.c index 11b899ccba..c21ea02c21 100644 --- a/gdk/gdkdisplaymanager.c +++ b/gdk/gdkdisplaymanager.c @@ -52,6 +52,10 @@ #include "win32/gdkwin32.h" #endif +#ifdef GDK_WINDOWING_WAYLAND +#include "wayland/gdkwayland.h" +#endif + /** * SECTION:gdkdisplaymanager * @Short_description: Maintains a list of all open GdkDisplays @@ -239,6 +243,11 @@ gdk_display_manager_get (void) manager = g_object_new (gdk_win32_display_manager_get_type (), NULL); else #endif +#ifdef GDK_WINDOWING_WAYLAND + if (backend == NULL || strcmp (backend, "wayland") == 0) + manager = g_object_new (gdk_wayland_display_manager_get_type (), NULL); + else +#endif #ifdef GDK_WINDOWING_X11 if (backend == NULL || strcmp (backend, "x11") == 0) manager = g_object_new (gdk_x11_display_manager_get_type (), NULL); diff --git a/gdk/wayland/Makefile.am b/gdk/wayland/Makefile.am new file mode 100644 index 0000000000..036856ae88 --- /dev/null +++ b/gdk/wayland/Makefile.am @@ -0,0 +1,40 @@ +## Process this file with automake to produce Makefile.in +include $(top_srcdir)/Makefile.decl + +libgdkincludedir = $(includedir)/gtk-3.0/gdk + +INCLUDES = \ + -DG_LOG_DOMAIN=\"Gdk\" \ + -DGDK_COMPILATION \ + -I$(top_srcdir) \ + -I$(top_srcdir)/gdk \ + -I$(top_builddir)/gdk \ + $(GTK_DEBUG_FLAGS) \ + $(GDK_DEP_CFLAGS) + +LDADDS = $(GDK_DEP_LIBS) + +noinst_LTLIBRARIES = \ + libgdk-wayland.la + +libgdk_wayland_la_SOURCES = \ + gdkapplaunchcontext-wayland.c \ + gdkcursor-wayland.c \ + gdkdevice-wayland.c \ + gdkdisplay-wayland.c \ + gdkdisplay-wayland.h \ + gdkdisplaymanager-wayland.c \ + gdkdnd-wayland.c \ + gdkeventsource.c \ + gdkkeys-wayland.c \ + gdkscreen-wayland.c \ + gdkscreen-wayland.h \ + gdkselection-wayland.c \ + gdkwindow-wayland.c \ + gdkwayland.h \ + gdkprivate-wayland.h + +libgdkinclude_HEADERS = \ + gdkwayland.h + +-include $(top_srcdir)/git.mk diff --git a/gdk/wayland/gdkapplaunchcontext-wayland.c b/gdk/wayland/gdkapplaunchcontext-wayland.c new file mode 100644 index 0000000000..1ff2549c79 --- /dev/null +++ b/gdk/wayland/gdkapplaunchcontext-wayland.c @@ -0,0 +1,90 @@ +/* + * Copyright © 2010 Intel Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include "config.h" + +#include <string.h> +#include <unistd.h> + +#include <glib.h> +#include <gio/gdesktopappinfo.h> + +#include "gdkwayland.h" +#include "gdkprivate-wayland.h" +#include "gdkapplaunchcontextprivate.h" +#include "gdkscreen.h" +#include "gdkinternals.h" +#include "gdkintl.h" + +static char * +gdk_wayland_app_launch_context_get_startup_notify_id (GAppLaunchContext *context, + GAppInfo *info, + GList *files) +{ + return NULL; +} + +static void +gdk_wayland_app_launch_context_launch_failed (GAppLaunchContext *context, + const char *startup_notify_id) +{ +} + +typedef struct _GdkWaylandAppLaunchContext GdkWaylandAppLaunchContext; +typedef struct _GdkWaylandAppLaunchContextClass GdkWaylandAppLaunchContextClass; + +struct _GdkWaylandAppLaunchContext +{ + GdkAppLaunchContext base; + gchar *name; + guint serial; +}; + +struct _GdkWaylandAppLaunchContextClass +{ + GdkAppLaunchContextClass base_class; +}; + +G_DEFINE_TYPE (GdkWaylandAppLaunchContext, gdk_wayland_app_launch_context, GDK_TYPE_APP_LAUNCH_CONTEXT) + +static void +gdk_wayland_app_launch_context_class_init (GdkWaylandAppLaunchContextClass *klass) +{ + GAppLaunchContextClass *ctx_class = G_APP_LAUNCH_CONTEXT_CLASS (klass); + + ctx_class->get_startup_notify_id = gdk_wayland_app_launch_context_get_startup_notify_id; + ctx_class->launch_failed = gdk_wayland_app_launch_context_launch_failed; +} + +static void +gdk_wayland_app_launch_context_init (GdkWaylandAppLaunchContext *ctx) +{ +} + +GdkAppLaunchContext * +_gdk_wayland_display_get_app_launch_context (GdkDisplay *display) +{ + GdkAppLaunchContext *ctx; + + ctx = g_object_new (gdk_wayland_app_launch_context_get_type (), + "display", display, + NULL); + + return ctx; +} diff --git a/gdk/wayland/gdkcursor-wayland.c b/gdk/wayland/gdkcursor-wayland.c new file mode 100644 index 0000000000..e93abc8bb4 --- /dev/null +++ b/gdk/wayland/gdkcursor-wayland.c @@ -0,0 +1,383 @@ +/* GDK - The GIMP Drawing Kit + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GTK+ Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GTK+ at ftp://ftp.gtk.org/pub/gtk/. + */ + +#include "config.h" + +#define GDK_PIXBUF_ENABLE_BACKEND + +#include <string.h> + +#include "gdkprivate-wayland.h" +#include "gdkcursorprivate.h" +#include "gdkdisplay-wayland.h" +#include "gdkwayland.h" +#include <gdk-pixbuf/gdk-pixbuf.h> + +#include <sys/mman.h> + +#define GDK_TYPE_WAYLAND_CURSOR (_gdk_wayland_cursor_get_type ()) +#define GDK_WAYLAND_CURSOR(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_WAYLAND_CURSOR, GdkWaylandCursor)) +#define GDK_WAYLAND_CURSOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_WAYLAND_CURSOR, GdkWaylandCursorClass)) +#define GDK_IS_WAYLAND_CURSOR(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_WAYLAND_CURSOR)) +#define GDK_IS_WAYLAND_CURSOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_WAYLAND_CURSOR)) +#define GDK_WAYLAND_CURSOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_WAYLAND_CURSOR, GdkWaylandCursorClass)) + +typedef struct _GdkWaylandCursor GdkWaylandCursor; +typedef struct _GdkWaylandCursorClass GdkWaylandCursorClass; + +struct _GdkWaylandCursor +{ + GdkCursor cursor; + gchar *name; + guint serial; + int x, y, width, height, size; + void *map; + struct wl_buffer *buffer; +}; + +struct _GdkWaylandCursorClass +{ + GdkCursorClass cursor_class; +}; + +G_DEFINE_TYPE (GdkWaylandCursor, _gdk_wayland_cursor, GDK_TYPE_CURSOR) + +static guint theme_serial = 0; + +static void +gdk_wayland_cursor_finalize (GObject *object) +{ + GdkWaylandCursor *cursor = GDK_WAYLAND_CURSOR (object); + + g_free (cursor->name); + + G_OBJECT_CLASS (_gdk_wayland_cursor_parent_class)->finalize (object); +} + +static GdkPixbuf* +gdk_wayland_cursor_get_image (GdkCursor *cursor) +{ + return NULL; +} + +struct wl_buffer * +_gdk_wayland_cursor_get_buffer (GdkCursor *cursor, int *x, int *y) +{ + GdkWaylandCursor *wayland_cursor = GDK_WAYLAND_CURSOR (cursor); + + *x = wayland_cursor->x; + *y = wayland_cursor->y; + + return wayland_cursor->buffer; +} + +static void +_gdk_wayland_cursor_class_init (GdkWaylandCursorClass *wayland_cursor_class) +{ + GdkCursorClass *cursor_class = GDK_CURSOR_CLASS (wayland_cursor_class); + GObjectClass *object_class = G_OBJECT_CLASS (wayland_cursor_class); + + object_class->finalize = gdk_wayland_cursor_finalize; + + cursor_class->get_image = gdk_wayland_cursor_get_image; +} + +static void +_gdk_wayland_cursor_init (GdkWaylandCursor *cursor) +{ +} + +static void +set_pixbuf (GdkWaylandCursor *cursor, GdkPixbuf *pixbuf) +{ + int stride, i, n_channels; + unsigned char *pixels, *end, *argb_pixels, *s, *d; + + stride = gdk_pixbuf_get_rowstride(pixbuf); + pixels = gdk_pixbuf_get_pixels(pixbuf); + n_channels = gdk_pixbuf_get_n_channels(pixbuf); + argb_pixels = cursor->map; + +#define MULT(_d,c,a,t) \ + do { t = c * a + 0x7f; _d = ((t >> 8) + t) >> 8; } while (0) + + if (n_channels == 4) + { + for (i = 0; i < cursor->height; i++) + { + s = pixels + i * stride; + end = s + cursor->width * 4; + d = argb_pixels + i * cursor->width * 4; + while (s < end) + { + unsigned int t; + + 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 < cursor->height; i++) + { + s = pixels + i * stride; + end = s + cursor->width * 3; + d = argb_pixels + i * cursor->width * 4; + while (s < end) + { + d[0] = s[2]; + d[1] = s[1]; + d[2] = s[0]; + d[3] = 0xff; + s += 3; + d += 4; + } + } + } +} + +static GdkCursor * +create_cursor(GdkDisplayWayland *display, GdkPixbuf *pixbuf, int x, int y) +{ + GdkWaylandCursor *cursor; + struct wl_visual *visual; + int stride, fd; + char *filename; + GError *error = NULL; + + cursor = g_object_new (GDK_TYPE_WAYLAND_CURSOR, + "cursor-type", GDK_CURSOR_IS_PIXMAP, + "display", display, + NULL); + cursor->name = NULL; + cursor->serial = theme_serial; + cursor->x = x; + cursor->y = y; + if (pixbuf) + { + cursor->width = gdk_pixbuf_get_width (pixbuf); + cursor->height = gdk_pixbuf_get_height (pixbuf); + } + else + { + cursor->width = 1; + cursor->height = 1; + } + + stride = cursor->width * 4; + cursor->size = stride * cursor->height; + + fd = g_file_open_tmp("wayland-shm-XXXXXX", &filename, &error); + if (fd < 0) { + fprintf(stderr, "g_file_open_tmp failed: %s\n", error->message); + g_error_free (error); + return NULL; + } + + unlink (filename); + g_free (filename); + + if (ftruncate(fd, cursor->size) < 0) { + fprintf(stderr, "ftruncate failed: %m\n"); + close(fd); + return NULL; + } + + cursor->map = mmap(NULL, cursor->size, + PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (cursor->map == MAP_FAILED) { + fprintf(stderr, "mmap failed: %m\n"); + close(fd); + return NULL; + } + + if (pixbuf) + set_pixbuf (cursor, pixbuf); + else + memset (cursor->map, 0, 4); + + visual = wl_display_get_premultiplied_argb_visual(display->wl_display); + cursor->buffer = wl_shm_create_buffer(display->shm, + fd, + cursor->width, + cursor->height, + stride, visual); + + close(fd); + + return GDK_CURSOR (cursor); +} + +#define DATADIR "/usr/share/wayland" + +static const struct { + GdkCursorType type; + const char *filename; + int hotspot_x, hotspot_y; +} cursor_definitions[] = { + { GDK_BLANK_CURSOR, NULL, 0, 0 }, + { GDK_HAND1, DATADIR "/hand1.png", 18, 11 }, + { GDK_HAND2, DATADIR "/hand2.png", 14, 8 }, + { GDK_LEFT_PTR, DATADIR "/left_ptr.png", 10, 5 }, + { GDK_SB_H_DOUBLE_ARROW, DATADIR "/sb_h_double_arrow.png", 15, 15 }, + { GDK_SB_V_DOUBLE_ARROW, DATADIR "/sb_v_double_arrow.png", 15, 15 }, + { GDK_XTERM, DATADIR "/xterm.png", 15, 15 }, + { GDK_BOTTOM_RIGHT_CORNER, DATADIR "/bottom_right_corner.png", 28, 28 } +}; + +GdkCursor * +_gdk_wayland_display_get_cursor_for_type (GdkDisplay *display, + GdkCursorType cursor_type) +{ + GdkDisplayWayland *wayland_display; + GdkPixbuf *pixbuf; + GError *error = NULL; + int i; + + for (i = 0; i < G_N_ELEMENTS (cursor_definitions); i++) + { + if (cursor_definitions[i].type == cursor_type) + break; + } + + if (i == G_N_ELEMENTS (cursor_definitions)) + { + g_warning("unhandled cursor type %d, falling back to blank\n", + cursor_type); + i = 0; + } + + wayland_display = GDK_DISPLAY_WAYLAND (display); + if (!wayland_display->cursors) + wayland_display->cursors = + g_new0 (GdkCursor *, G_N_ELEMENTS(cursor_definitions)); + if (wayland_display->cursors[i]) + return g_object_ref (wayland_display->cursors[i]); + + GDK_NOTE (CURSOR, + g_message ("creating new cursor for type %d, filename %s", + cursor_type, cursor_definitions[i].filename)); + + if (cursor_type != GDK_BLANK_CURSOR) + pixbuf = gdk_pixbuf_new_from_file(cursor_definitions[i].filename, &error); + else + pixbuf = NULL; + if (error != NULL) + { + GDK_NOTE (CURSOR, + g_message ("failed to load %s: %s", + cursor_definitions[i].filename, error->message)); + g_error_free(error); + return NULL; + } + + wayland_display->cursors[i] = + create_cursor(wayland_display, pixbuf, + cursor_definitions[i].hotspot_x, + cursor_definitions[i].hotspot_y); + if (pixbuf) + g_object_unref (pixbuf); + + return g_object_ref (wayland_display->cursors[i]); +} + +GdkCursor* +_gdk_wayland_display_get_cursor_for_name (GdkDisplay *display, + const gchar *name) +{ + GdkWaylandCursor *private; + + g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL); + + private = g_object_new (GDK_TYPE_WAYLAND_CURSOR, + "cursor-type", GDK_CURSOR_IS_PIXMAP, + "display", display, + NULL); + private->name = g_strdup (name); + private->serial = theme_serial; + + return GDK_CURSOR (private); +} + +GdkCursor * +_gdk_wayland_display_get_cursor_for_pixbuf (GdkDisplay *display, + GdkPixbuf *pixbuf, + gint x, + gint y) +{ + GdkWaylandCursor *private; + + g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL); + g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), NULL); + g_return_val_if_fail (0 <= x && x < gdk_pixbuf_get_width (pixbuf), NULL); + g_return_val_if_fail (0 <= y && y < gdk_pixbuf_get_height (pixbuf), NULL); + + private = g_object_new (GDK_TYPE_WAYLAND_CURSOR, + "cursor-type", GDK_CURSOR_IS_PIXMAP, + "display", display, + NULL); + + private->name = NULL; + private->serial = theme_serial; + + return GDK_CURSOR (private); +} + +void +_gdk_wayland_display_get_default_cursor_size (GdkDisplay *display, + guint *width, + guint *height) +{ + /* FIXME: wayland settings? */ + *width = 64; + *height = 64; +} + +void +_gdk_wayland_display_get_maximal_cursor_size (GdkDisplay *display, + guint *width, + guint *height) +{ + *width = 256; + *height = 256; +} + +gboolean +_gdk_wayland_display_supports_cursor_alpha (GdkDisplay *display) +{ + return TRUE; +} + +gboolean +_gdk_wayland_display_supports_cursor_color (GdkDisplay *display) +{ + return TRUE; +} diff --git a/gdk/wayland/gdkdevice-wayland.c b/gdk/wayland/gdkdevice-wayland.c new file mode 100644 index 0000000000..2a051de4da --- /dev/null +++ b/gdk/wayland/gdkdevice-wayland.c @@ -0,0 +1,713 @@ +/* GDK - The GIMP Drawing Kit + * Copyright (C) 2009 Carlos Garnacho <carlosg@gnome.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include <string.h> +#include <gdk/gdkwindow.h> +#include <gdk/gdktypes.h> +#include "gdkprivate-wayland.h" +#include "gdkwayland.h" +#include "gdkkeysyms.h" +#include "gdkdeviceprivate.h" +#include "gdkdevicemanagerprivate.h" +#include "gdkprivate-wayland.h" + +#include <X11/extensions/XKBcommon.h> +#include <X11/keysym.h> + +#define GDK_TYPE_DEVICE_CORE (gdk_device_core_get_type ()) +#define GDK_DEVICE_CORE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDK_TYPE_DEVICE_CORE, GdkDeviceCore)) +#define GDK_DEVICE_CORE_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), GDK_TYPE_DEVICE_CORE, GdkDeviceCoreClass)) +#define GDK_IS_DEVICE_CORE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDK_TYPE_DEVICE_CORE)) +#define GDK_IS_DEVICE_CORE_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), GDK_TYPE_DEVICE_CORE)) +#define GDK_DEVICE_CORE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDK_TYPE_DEVICE_CORE, GdkDeviceCoreClass)) + +typedef struct _GdkDeviceCore GdkDeviceCore; +typedef struct _GdkDeviceCoreClass GdkDeviceCoreClass; +typedef struct _GdkWaylandDevice GdkWaylandDevice; + +struct _GdkWaylandDevice +{ + GdkDisplay *display; + GdkDevice *pointer; + GdkDevice *keyboard; + GdkModifierType modifiers; + GdkWindow *pointer_focus; + GdkWindow *keyboard_focus; + struct wl_input_device *device; + int32_t x, y, surface_x, surface_y; + uint32_t time; +}; + +struct _GdkDeviceCore +{ + GdkDevice parent_instance; + GdkWaylandDevice *device; +}; + +struct _GdkDeviceCoreClass +{ + GdkDeviceClass parent_class; +}; + +G_DEFINE_TYPE (GdkDeviceCore, gdk_device_core, GDK_TYPE_DEVICE) + +#define GDK_TYPE_DEVICE_MANAGER_CORE (gdk_device_manager_core_get_type ()) +#define GDK_DEVICE_MANAGER_CORE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDK_TYPE_DEVICE_MANAGER_CORE, GdkDeviceManagerCore)) +#define GDK_DEVICE_MANAGER_CORE_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), GDK_TYPE_DEVICE_MANAGER_CORE, GdkDeviceManagerCoreClass)) +#define GDK_IS_DEVICE_MANAGER_CORE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDK_TYPE_DEVICE_MANAGER_CORE)) +#define GDK_IS_DEVICE_MANAGER_CORE_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), GDK_TYPE_DEVICE_MANAGER_CORE)) +#define GDK_DEVICE_MANAGER_CORE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDK_TYPE_DEVICE_MANAGER_CORE, GdkDeviceManagerCoreClass)) + +typedef struct _GdkDeviceManagerCore GdkDeviceManagerCore; +typedef struct _GdkDeviceManagerCoreClass GdkDeviceManagerCoreClass; + +struct _GdkDeviceManagerCore +{ + GdkDeviceManager parent_object; + GdkDevice *core_pointer; + GdkDevice *core_keyboard; + GList *devices; +}; + +struct _GdkDeviceManagerCoreClass +{ + GdkDeviceManagerClass parent_class; +}; + +G_DEFINE_TYPE (GdkDeviceManagerCore, + gdk_device_manager_core, GDK_TYPE_DEVICE_MANAGER) + +static gboolean +gdk_device_core_get_history (GdkDevice *device, + GdkWindow *window, + guint32 start, + guint32 stop, + GdkTimeCoord ***events, + gint *n_events) +{ + return FALSE; +} + +static void +gdk_device_core_get_state (GdkDevice *device, + GdkWindow *window, + gdouble *axes, + GdkModifierType *mask) +{ + gint x_int, y_int; + + gdk_window_get_pointer (window, &x_int, &y_int, mask); + + if (axes) + { + axes[0] = x_int; + axes[1] = y_int; + } +} + +static void +gdk_device_core_set_window_cursor (GdkDevice *device, + GdkWindow *window, + GdkCursor *cursor) +{ + GdkWaylandDevice *wd = GDK_DEVICE_CORE(device)->device; + struct wl_buffer *buffer; + int x, y; + + if (cursor) + { + buffer = _gdk_wayland_cursor_get_buffer(cursor, &x, &y); + wl_input_device_attach(wd->device, wd->time, buffer, x, y); + } + else + { + wl_input_device_attach(wd->device, wd->time, NULL, 0, 0); + } +} + +static void +gdk_device_core_warp (GdkDevice *device, + GdkScreen *screen, + gint x, + gint y) +{ +} + +static gboolean +gdk_device_core_query_state (GdkDevice *device, + GdkWindow *window, + GdkWindow **root_window, + GdkWindow **child_window, + gint *root_x, + gint *root_y, + gint *win_x, + gint *win_y, + GdkModifierType *mask) +{ + GdkWaylandDevice *wd; + GdkScreen *default_screen; + + wd = GDK_DEVICE_CORE(device)->device; + default_screen = gdk_display_get_default_screen (wd->display); + + if (root_window) + *root_window = gdk_screen_get_root_window (default_screen); + if (child_window) + *child_window = wd->pointer_focus; + if (root_x) + *root_x = wd->x; + if (root_y) + *root_y = wd->y; + if (win_x) + *win_x = wd->surface_x; + if (win_y) + *win_y = wd->surface_y; + if (mask) + *mask = wd->modifiers; + + return TRUE; +} + +static GdkGrabStatus +gdk_device_core_grab (GdkDevice *device, + GdkWindow *window, + gboolean owner_events, + GdkEventMask event_mask, + GdkWindow *confine_to, + GdkCursor *cursor, + guint32 time_) +{ + return GDK_GRAB_SUCCESS; +} + +static void +gdk_device_core_ungrab (GdkDevice *device, + guint32 time_) +{ +} + +static GdkWindow * +gdk_device_core_window_at_position (GdkDevice *device, + gint *win_x, + gint *win_y, + GdkModifierType *mask, + gboolean get_toplevel) +{ + GdkWaylandDevice *wd; + + wd = GDK_DEVICE_CORE(device)->device; + if (win_x) + *win_x = wd->surface_x; + if (win_y) + *win_y = wd->surface_y; + if (mask) + *mask = wd->modifiers; + + return wd->pointer_focus; +} + +static void +gdk_device_core_select_window_events (GdkDevice *device, + GdkWindow *window, + GdkEventMask event_mask) +{ +} + +static void +gdk_device_core_class_init (GdkDeviceCoreClass *klass) +{ + GdkDeviceClass *device_class = GDK_DEVICE_CLASS (klass); + + device_class->get_history = gdk_device_core_get_history; + device_class->get_state = gdk_device_core_get_state; + device_class->set_window_cursor = gdk_device_core_set_window_cursor; + device_class->warp = gdk_device_core_warp; + device_class->query_state = gdk_device_core_query_state; + device_class->grab = gdk_device_core_grab; + device_class->ungrab = gdk_device_core_ungrab; + device_class->window_at_position = gdk_device_core_window_at_position; + device_class->select_window_events = gdk_device_core_select_window_events; +} + +static void +gdk_device_core_init (GdkDeviceCore *device_core) +{ + GdkDevice *device; + + device = GDK_DEVICE (device_core); + + _gdk_device_add_axis (device, GDK_NONE, GDK_AXIS_X, 0, 0, 1); + _gdk_device_add_axis (device, GDK_NONE, GDK_AXIS_Y, 0, 0, 1); +} + +struct wl_input_device * +_gdk_wayland_device_get_device (GdkDevice *device) +{ + return GDK_DEVICE_CORE (device)->device->device; +} + +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) +{ + GdkWaylandDevice *device = data; + GdkDisplayWayland *display = GDK_DISPLAY_WAYLAND (device->display); + GdkEvent *event; + + event = gdk_event_new (GDK_NOTHING); + + device->time = time; + device->x = x; + device->y = y; + device->surface_x = sx; + device->surface_y = sy; + + event->motion.type = GDK_MOTION_NOTIFY; + event->motion.window = g_object_ref (device->pointer_focus); + gdk_event_set_device (event, device->pointer); + event->motion.time = time; + event->motion.x = (gdouble) sx; + event->motion.y = (gdouble) sy; + event->motion.x_root = (gdouble) x; + event->motion.y_root = (gdouble) y; + event->motion.axes = NULL; + event->motion.state = device->modifiers; + event->motion.is_hint = 0; + gdk_event_set_screen (event, display->screen); + + GDK_NOTE (EVENTS, + g_message ("motion %d %d, state %d", + sx, sy, event->button.state)); + + _gdk_wayland_display_deliver_event (device->display, event); +} + +static void +input_handle_button(void *data, struct wl_input_device *input_device, + uint32_t time, uint32_t button, uint32_t state) +{ + GdkWaylandDevice *device = data; + GdkDisplayWayland *display = GDK_DISPLAY_WAYLAND (device->display); + GdkEvent *event; + uint32_t modifier; + + device->time = time; + event = gdk_event_new (state ? GDK_BUTTON_PRESS : GDK_BUTTON_RELEASE); + event->button.window = g_object_ref (device->pointer_focus); + gdk_event_set_device (event, device->pointer); + event->button.time = time; + event->button.x = (gdouble) device->surface_x; + event->button.y = (gdouble) device->surface_y; + event->button.x_root = (gdouble) device->x; + event->button.y_root = (gdouble) device->y; + event->button.axes = NULL; + event->button.state = device->modifiers; + event->button.button = button - 271; + gdk_event_set_screen (event, display->screen); + + modifier = 1 << (8 + button - 272); + if (state) + device->modifiers |= modifier; + else + device->modifiers &= ~modifier; + + GDK_NOTE (EVENTS, + g_message ("button %d %s, state %d", + event->button.button, + state ? "press" : "release", event->button.state)); + + _gdk_wayland_display_deliver_event (device->display, event); +} + +static void +translate_keyboard_string (GdkEventKey *event) +{ + gunichar c = 0; + gchar buf[7]; + + /* Fill in event->string crudely, since various programs + * depend on it. + */ + event->string = NULL; + + if (event->keyval != GDK_KEY_VoidSymbol) + c = gdk_keyval_to_unicode (event->keyval); + + if (c) + { + gsize bytes_written; + gint len; + + /* Apply the control key - Taken from Xlib + */ + if (event->state & GDK_CONTROL_MASK) + { + if ((c >= '@' && c < '\177') || c == ' ') c &= 0x1F; + else if (c == '2') + { + event->string = g_memdup ("\0\0", 2); + event->length = 1; + buf[0] = '\0'; + return; + } + else if (c >= '3' && c <= '7') c -= ('3' - '\033'); + else if (c == '8') c = '\177'; + else if (c == '/') c = '_' & 0x1F; + } + + len = g_unichar_to_utf8 (c, buf); + buf[len] = '\0'; + + event->string = g_locale_from_utf8 (buf, len, + NULL, &bytes_written, + NULL); + if (event->string) + event->length = bytes_written; + } + else if (event->keyval == GDK_KEY_Escape) + { + event->length = 1; + event->string = g_strdup ("\033"); + } + else if (event->keyval == GDK_KEY_Return || + event->keyval == GDK_KEY_KP_Enter) + { + event->length = 1; + event->string = g_strdup ("\r"); + } + + if (!event->string) + { + event->length = 0; + event->string = g_strdup (""); + } +} + +static void +input_handle_key(void *data, struct wl_input_device *input_device, + uint32_t time, uint32_t key, uint32_t state) +{ + GdkWaylandDevice *device = data; + GdkEvent *event; + uint32_t code, modifier, level; + struct xkb_desc *xkb; + GdkKeymap *keymap; + + keymap = gdk_keymap_get_for_display (device->display); + xkb = _gdk_wayland_keymap_get_xkb_desc (keymap); + + device->time = time; + event = gdk_event_new (state ? GDK_KEY_PRESS : GDK_KEY_RELEASE); + event->key.window = g_object_ref (device->keyboard_focus); + gdk_event_set_device (event, device->keyboard); + event->button.time = time; + event->key.state = device->modifiers; + event->key.group = 0; + code = key + xkb->min_key_code; + event->key.hardware_keycode = code; + + level = 0; + if (device->modifiers & XKB_COMMON_SHIFT_MASK && + XkbKeyGroupWidth(xkb, code, 0) > 1) + level = 1; + + event->key.keyval = XkbKeySymEntry(xkb, code, level, 0); + + modifier = xkb->map->modmap[code]; + if (state) + device->modifiers |= modifier; + else + device->modifiers &= ~modifier; + + event->key.is_modifier = modifier > 0; + + translate_keyboard_string (&event->key); + + _gdk_wayland_display_deliver_event (device->display, event); + + GDK_NOTE (EVENTS, + g_message ("keyboard event, code %d, sym %d, " + "string %s, mods 0x%x", + code, event->key.keyval, + event->key.string, event->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) +{ + GdkWaylandDevice *device = data; + GdkEvent *event; + + device->time = time; + if (device->pointer_focus) + { + event = gdk_event_new (GDK_LEAVE_NOTIFY); + event->crossing.window = g_object_ref (device->pointer_focus); + gdk_event_set_device (event, device->pointer); + event->crossing.subwindow = NULL; + event->crossing.time = time; + event->crossing.x = (gdouble) device->surface_x; + event->crossing.y = (gdouble) device->surface_y; + event->crossing.x_root = (gdouble) device->x; + event->crossing.y_root = (gdouble) device->y; + + event->crossing.mode = GDK_CROSSING_NORMAL; + event->crossing.detail = GDK_NOTIFY_ANCESTOR; + event->crossing.focus = TRUE; + event->crossing.state = 0; + + _gdk_wayland_display_deliver_event (device->display, event); + + GDK_NOTE (EVENTS, + g_message ("leave, device %p surface %p", + device, device->pointer_focus)); + + g_object_unref(device->pointer_focus); + device->pointer_focus = NULL; + } + + if (surface) + { + device->pointer_focus = wl_surface_get_user_data(surface); + g_object_ref(device->pointer_focus); + + event = gdk_event_new (GDK_ENTER_NOTIFY); + event->crossing.window = g_object_ref (device->pointer_focus); + gdk_event_set_device (event, device->pointer); + event->crossing.subwindow = NULL; + event->crossing.time = time; + event->crossing.x = (gdouble) sx; + event->crossing.y = (gdouble) sy; + event->crossing.x_root = (gdouble) x; + event->crossing.y_root = (gdouble) y; + + event->crossing.mode = GDK_CROSSING_NORMAL; + event->crossing.detail = GDK_NOTIFY_ANCESTOR; + event->crossing.focus = TRUE; + event->crossing.state = 0; + + device->surface_x = sx; + device->surface_y = sy; + device->x = x; + device->y = y; + + _gdk_wayland_display_deliver_event (device->display, event); + + GDK_NOTE (EVENTS, + g_message ("enter, device %p surface %p", + device, device->pointer_focus)); + } +} + +static void +update_modifiers(GdkWaylandDevice *device, struct wl_array *keys) +{ + uint32_t *k, *end; + GdkKeymap *keymap; + struct xkb_desc *xkb; + + keymap = gdk_keymap_get_for_display (device->display); + xkb = _gdk_wayland_keymap_get_xkb_desc (keymap); + + end = keys->data + keys->size; + device->modifiers = 0; + for (k = keys->data; k < end; k++) + device->modifiers |= xkb->map->modmap[*k]; +} + +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) +{ + GdkWaylandDevice *device = data; + GdkEvent *event; + + device->time = time; + if (device->keyboard_focus) + { + event = gdk_event_new (GDK_FOCUS_CHANGE); + event->focus_change.window = g_object_ref (device->keyboard_focus); + event->focus_change.send_event = FALSE; + event->focus_change.in = FALSE; + gdk_event_set_device (event, device->keyboard); + + g_object_unref(device->keyboard_focus); + device->keyboard_focus = NULL; + + GDK_NOTE (EVENTS, + g_message ("focus out, device %p surface %p", + device, device->keyboard_focus)); + + _gdk_wayland_display_deliver_event (device->display, event); + } + + if (surface) + { + device->keyboard_focus = wl_surface_get_user_data(surface); + g_object_ref(device->keyboard_focus); + + event = gdk_event_new (GDK_FOCUS_CHANGE); + event->focus_change.window = g_object_ref (device->keyboard_focus); + event->focus_change.send_event = FALSE; + event->focus_change.in = TRUE; + gdk_event_set_device (event, device->keyboard); + + update_modifiers (device, keys); + + GDK_NOTE (EVENTS, + g_message ("focus int, device %p surface %p", + device, device->keyboard_focus)); + + _gdk_wayland_display_deliver_event (device->display, event); + } +} + +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, +}; + +void +_gdk_wayland_device_manager_add_device (GdkDeviceManager *device_manager, + struct wl_input_device *wl_device) +{ + GdkDisplay *display; + GdkDeviceManagerCore *device_manager_core = + GDK_DEVICE_MANAGER_CORE(device_manager); + GdkWaylandDevice *device; + + device = g_new0 (GdkWaylandDevice, 1); + display = gdk_device_manager_get_display (device_manager); + + device->display = display; + device->pointer = g_object_new (GDK_TYPE_DEVICE_CORE, + "name", "Core Pointer", + "type", GDK_DEVICE_TYPE_MASTER, + "input-source", GDK_SOURCE_MOUSE, + "input-mode", GDK_MODE_SCREEN, + "has-cursor", TRUE, + "display", display, + "device-manager", device_manager, + NULL); + + device->keyboard = g_object_new (GDK_TYPE_DEVICE_CORE, + "name", "Core Keyboard", + "type", GDK_DEVICE_TYPE_MASTER, + "input-source", GDK_SOURCE_KEYBOARD, + "input-mode", GDK_MODE_SCREEN, + "has-cursor", FALSE, + "display", display, + "device-manager", device_manager, + NULL); + + GDK_DEVICE_CORE (device->pointer)->device = device; + GDK_DEVICE_CORE (device->keyboard)->device = device; + device->device = wl_device; + + wl_input_device_add_listener(device->device, + &input_device_listener, device); + + device_manager_core->devices = + g_list_prepend (device_manager_core->devices, device->keyboard); + device_manager_core->devices = + g_list_prepend (device_manager_core->devices, device->pointer); + + _gdk_device_set_associated_device (device->pointer, device->keyboard); + _gdk_device_set_associated_device (device->keyboard, device->pointer); +} + +static void +free_device (void *data, void *user_data) +{ + g_object_unref (data); +} + +static void +gdk_device_manager_core_finalize (GObject *object) +{ + GdkDeviceManagerCore *device_manager_core; + + device_manager_core = GDK_DEVICE_MANAGER_CORE (object); + + g_list_foreach (device_manager_core->devices, free_device, NULL); + g_list_free (device_manager_core->devices); + + G_OBJECT_CLASS (gdk_device_manager_core_parent_class)->finalize (object); +} + +static GList * +gdk_device_manager_core_list_devices (GdkDeviceManager *device_manager, + GdkDeviceType type) +{ + GdkDeviceManagerCore *device_manager_core; + GList *devices = NULL; + + if (type == GDK_DEVICE_TYPE_MASTER) + { + device_manager_core = (GdkDeviceManagerCore *) device_manager; + devices = g_list_copy(device_manager_core->devices); + } + + return devices; +} + +static GdkDevice * +gdk_device_manager_core_get_client_pointer (GdkDeviceManager *device_manager) +{ + GdkDeviceManagerCore *device_manager_core; + + device_manager_core = (GdkDeviceManagerCore *) device_manager; + return device_manager_core->devices->data; +} + +static void +gdk_device_manager_core_class_init (GdkDeviceManagerCoreClass *klass) +{ + GdkDeviceManagerClass *device_manager_class = GDK_DEVICE_MANAGER_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = gdk_device_manager_core_finalize; + device_manager_class->list_devices = gdk_device_manager_core_list_devices; + device_manager_class->get_client_pointer = gdk_device_manager_core_get_client_pointer; +} + +static void +gdk_device_manager_core_init (GdkDeviceManagerCore *device_manager) +{ +} + +GdkDeviceManager * +_gdk_wayland_device_manager_new (GdkDisplay *display) +{ + return g_object_new (GDK_TYPE_DEVICE_MANAGER_CORE, + "display", display, + NULL); +} diff --git a/gdk/wayland/gdkdisplay-wayland.c b/gdk/wayland/gdkdisplay-wayland.c new file mode 100644 index 0000000000..cb447d659f --- /dev/null +++ b/gdk/wayland/gdkdisplay-wayland.c @@ -0,0 +1,643 @@ +/* + * Copyright © 2010 Intel Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include <wayland-egl.h> + +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <fcntl.h> + +#include <glib.h> +#include "gdkwayland.h" +#include "gdkdisplay.h" +#include "gdkdisplay-wayland.h" +#include "gdkscreen.h" +#include "gdkinternals.h" +#include "gdkdeviceprivate.h" +#include "gdkdevicemanager.h" +#include "gdkkeysprivate.h" +#include "gdkprivate-wayland.h" + +G_DEFINE_TYPE (GdkDisplayWayland, _gdk_display_wayland, GDK_TYPE_DISPLAY) + +static void +gdk_input_init (GdkDisplay *display) +{ + GdkDisplayWayland *display_wayland; + GdkDeviceManager *device_manager; + GdkDevice *device; + GList *list, *l; + + display_wayland = GDK_DISPLAY_WAYLAND (display); + device_manager = gdk_display_get_device_manager (display); + + /* For backwards compatibility, just add + * floating devices that are not keyboards. + */ + list = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING); + + for (l = list; l; l = l->next) + { + device = l->data; + + if (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD) + continue; + + display_wayland->input_devices = g_list_prepend (display_wayland->input_devices, l->data); + } + + g_list_free (list); + + /* Now set "core" pointer to the first + * master device that is a pointer. + */ + list = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER); + + for (l = list; l; l = l->next) + { + device = list->data; + + if (gdk_device_get_source (device) != GDK_SOURCE_MOUSE) + continue; + + display->core_pointer = device; + break; + } + + /* Add the core pointer to the devices list */ + display_wayland->input_devices = g_list_prepend (display_wayland->input_devices, display->core_pointer); + + g_list_free (list); +} + +static void +shell_handle_configure(void *data, struct wl_shell *shell, + uint32_t time, uint32_t edges, + struct wl_surface *surface, + int32_t width, int32_t height) +{ + GdkWindow *window; + GdkDisplay *display; + GdkEvent *event; + + window = wl_surface_get_user_data(surface); + + display = gdk_window_get_display (window); + + event = gdk_event_new (GDK_CONFIGURE); + event->configure.window = window; + event->configure.send_event = FALSE; + event->configure.width = width; + event->configure.height = height; + + _gdk_window_update_size (window); + _gdk_wayland_window_update_size (window, width, height, edges); + + g_object_ref(window); + + _gdk_wayland_display_deliver_event (display, event); +} + +static const struct wl_shell_listener shell_listener = { + shell_handle_configure, +}; + +static void +output_handle_geometry(void *data, + struct wl_output *output, + int32_t x, int32_t y, int32_t width, int32_t height) +{ + /* + g_signal_emit_by_name (screen, "monitors-changed"); + g_signal_emit_by_name (screen, "size-changed"); + */ +} + +static const struct wl_output_listener output_listener = { + output_handle_geometry, +}; + +static void +gdk_display_handle_global(struct wl_display *display, uint32_t id, + const char *interface, uint32_t version, void *data) +{ + GdkDisplayWayland *display_wayland = data; + GdkDisplay *gdk_display = GDK_DISPLAY_OBJECT (data); + struct wl_input_device *input; + + if (strcmp(interface, "compositor") == 0) { + display_wayland->compositor = wl_compositor_create(display, id); + } else if (strcmp(interface, "shm") == 0) { + display_wayland->shm = wl_shm_create(display, id); + } else if (strcmp(interface, "shell") == 0) { + display_wayland->shell = wl_shell_create(display, id); + wl_shell_add_listener(display_wayland->shell, + &shell_listener, display_wayland); + } else if (strcmp(interface, "output") == 0) { + display_wayland->output = wl_output_create(display, id); + wl_output_add_listener(display_wayland->output, + &output_listener, display_wayland); + } else if (strcmp(interface, "input_device") == 0) { + input = wl_input_device_create(display, id); + _gdk_wayland_device_manager_add_device (gdk_display->device_manager, + input); + } +} + +static gboolean +gdk_display_init_egl(GdkDisplay *display) +{ + GdkDisplayWayland *display_wayland = GDK_DISPLAY_WAYLAND (display); + EGLint major, minor, i; + void *p; + + static const struct { const char *f; unsigned int offset; } + extension_functions[] = { + { "glEGLImageTargetTexture2DOES", offsetof(GdkDisplayWayland, image_target_texture_2d) }, + { "eglCreateImageKHR", offsetof(GdkDisplayWayland, create_image) }, + { "eglDestroyImageKHR", offsetof(GdkDisplayWayland, destroy_image) } + }; + + display_wayland->egl_display = + eglGetDisplay(display_wayland->native_display); + if (!eglInitialize(display_wayland->egl_display, &major, &minor)) { + fprintf(stderr, "failed to initialize display\n"); + return FALSE; + } + + eglBindAPI(EGL_OPENGL_API); + + display_wayland->egl_context = + eglCreateContext(display_wayland->egl_display, NULL, EGL_NO_CONTEXT, NULL); + if (display_wayland->egl_context == NULL) { + fprintf(stderr, "failed to create context\n"); + return FALSE; + } + + if (!eglMakeCurrent(display_wayland->egl_display, + NULL, NULL, display_wayland->egl_context)) { + fprintf(stderr, "faile to make context current\n"); + return FALSE; + } + + display_wayland->cairo_device = + cairo_egl_device_create(display_wayland->egl_display, + display_wayland->egl_context); + if (cairo_device_status (display_wayland->cairo_device) != CAIRO_STATUS_SUCCESS) { + fprintf(stderr, "failed to get cairo drm device\n"); + return FALSE; + } + + for (i = 0; i < G_N_ELEMENTS(extension_functions); i++) { + p = eglGetProcAddress(extension_functions[i].f); + *(void **) ((char *) display_wayland + extension_functions[i].offset) = p; + if (p == NULL) { + fprintf(stderr, "failed to look up %s\n", extension_functions[i].f); + return FALSE; + } + } + + return TRUE; +} + +GdkDisplay * +_gdk_wayland_display_open (const gchar *display_name) +{ + struct wl_display *wl_display; + GdkDisplay *display; + GdkDisplayWayland *display_wayland; + + wl_display = wl_display_connect(display_name); + if (!wl_display) + return NULL; + + display = g_object_new (GDK_TYPE_DISPLAY_WAYLAND, NULL); + display_wayland = GDK_DISPLAY_WAYLAND (display); + + display_wayland->wl_display = wl_display; + + display_wayland->native_display = wl_egl_display_create(wl_display); + if (display_wayland->native_display == NULL) { + wl_display_destroy(wl_display); + return NULL; + } + + display_wayland->screen = _gdk_wayland_screen_new (display); + + display->device_manager = _gdk_wayland_device_manager_new (display); + + /* Set up listener so we'll catch all events. */ + wl_display_add_global_listener(display_wayland->wl_display, + gdk_display_handle_global, display_wayland); + + gdk_display_init_egl(display); + + display_wayland->event_source = _gdk_wayland_display_event_source_new (display); + + gdk_input_init (display); + + g_signal_emit_by_name (display, "opened"); + g_signal_emit_by_name (gdk_display_manager_get(), "display_opened", display); + + return display; +} + +static void +gdk_wayland_display_dispose (GObject *object) +{ + GdkDisplayWayland *display_wayland = GDK_DISPLAY_WAYLAND (object); + + _gdk_wayland_display_manager_remove_display (gdk_display_manager_get (), + GDK_DISPLAY (display_wayland)); + g_list_foreach (display_wayland->input_devices, + (GFunc) g_object_run_dispose, NULL); + + _gdk_screen_close (display_wayland->screen); + + if (display_wayland->event_source) + { + g_source_destroy (display_wayland->event_source); + g_source_unref (display_wayland->event_source); + display_wayland->event_source = NULL; + } + + eglTerminate(display_wayland->egl_display); + wl_egl_display_destroy(display_wayland->native_display); + + G_OBJECT_CLASS (_gdk_display_wayland_parent_class)->dispose (object); +} + +static void +gdk_wayland_display_finalize (GObject *object) +{ + GdkDisplayWayland *display_wayland = GDK_DISPLAY_WAYLAND (object); + + /* Keymap */ + if (display_wayland->keymap) + g_object_unref (display_wayland->keymap); + + /* input GdkDevice list */ + g_list_foreach (display_wayland->input_devices, (GFunc) g_object_unref, NULL); + g_list_free (display_wayland->input_devices); + + g_object_unref (display_wayland->screen); + + g_free (display_wayland->startup_notification_id); + + G_OBJECT_CLASS (_gdk_display_wayland_parent_class)->finalize (object); +} + +static G_CONST_RETURN gchar * +gdk_wayland_display_get_name (GdkDisplay *display) +{ + return "Wayland"; +} + +static gint +gdk_wayland_display_get_n_screens (GdkDisplay *display) +{ + return 1; +} + +static GdkScreen * +gdk_wayland_display_get_screen (GdkDisplay *display, + gint screen_num) +{ + g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL); + g_return_val_if_fail (screen_num == 0, NULL); + + return GDK_DISPLAY_WAYLAND (display)->screen; +} + +static GdkScreen * +gdk_wayland_display_get_default_screen (GdkDisplay *display) +{ + g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL); + + return GDK_DISPLAY_WAYLAND (display)->screen; +} + +static void +gdk_wayland_display_beep (GdkDisplay *display) +{ + g_return_if_fail (GDK_IS_DISPLAY (display)); +} + +static void +sync_callback(void *data) +{ + gboolean *done = data; + + *done = TRUE; +} + +static void +gdk_wayland_display_sync (GdkDisplay *display) +{ + GdkDisplayWayland *display_wayland; + gboolean done; + + g_return_if_fail (GDK_IS_DISPLAY (display)); + + display_wayland = GDK_DISPLAY_WAYLAND (display); + + wl_display_sync_callback(display_wayland->wl_display, sync_callback, &done); + wl_display_iterate(display_wayland->wl_display, WL_DISPLAY_WRITABLE); + while (!done) + wl_display_iterate(display_wayland->wl_display, WL_DISPLAY_READABLE); +} + +static void +gdk_wayland_display_flush (GdkDisplay *display) +{ + g_return_if_fail (GDK_IS_DISPLAY (display)); + + if (!display->closed) + _gdk_wayland_display_flush (display, + GDK_DISPLAY_WAYLAND (display)->event_source); +} + +static gboolean +gdk_wayland_display_has_pending (GdkDisplay *display) +{ + return FALSE; +} + +static GdkWindow * +gdk_wayland_display_get_default_group (GdkDisplay *display) +{ + g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL); + + return NULL; +} + + +static gboolean +gdk_wayland_display_supports_selection_notification (GdkDisplay *display) +{ + return TRUE; +} + +static gboolean +gdk_wayland_display_request_selection_notification (GdkDisplay *display, + GdkAtom selection) + +{ + return FALSE; +} + +static gboolean +gdk_wayland_display_supports_clipboard_persistence (GdkDisplay *display) +{ + return FALSE; +} + +static void +gdk_wayland_display_store_clipboard (GdkDisplay *display, + GdkWindow *clipboard_window, + guint32 time_, + const GdkAtom *targets, + gint n_targets) +{ +} + +static gboolean +gdk_wayland_display_supports_shapes (GdkDisplay *display) +{ + return TRUE; +} + +static gboolean +gdk_wayland_display_supports_input_shapes (GdkDisplay *display) +{ + return TRUE; +} + +static gboolean +gdk_wayland_display_supports_composite (GdkDisplay *display) +{ + return TRUE; +} + +static GList * +gdk_wayland_display_list_devices (GdkDisplay *display) +{ + g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL); + + return GDK_DISPLAY_WAYLAND (display)->input_devices; +} + +static void +gdk_wayland_display_before_process_all_updates (GdkDisplay *display) +{ +} + +static void +gdk_wayland_display_after_process_all_updates (GdkDisplay *display) +{ + /* Post the damage here instead? */ +} + +static gulong +gdk_wayland_display_get_next_serial (GdkDisplay *display) +{ + return 0; +} + +void +_gdk_wayland_display_make_default (GdkDisplay *display) +{ +} + +/** + * gdk_wayland_display_broadcast_startup_message: + * @display: a #GdkDisplay + * @message_type: startup notification message type ("new", "change", + * or "remove") + * @...: a list of key/value pairs (as strings), terminated by a + * %NULL key. (A %NULL value for a key will cause that key to be + * skipped in the output.) + * + * Sends a startup notification message of type @message_type to + * @display. + * + * This is a convenience function for use by code that implements the + * freedesktop startup notification specification. Applications should + * not normally need to call it directly. See the <ulink + * url="http://standards.freedesktop.org/startup-notification-spec/startup-notification-latest.txt">Startup + * Notification Protocol specification</ulink> for + * definitions of the message types and keys that can be used. + * + * Since: 2.12 + **/ +void +gdk_wayland_display_broadcast_startup_message (GdkDisplay *display, + const char *message_type, + ...) +{ + GString *message; + va_list ap; + const char *key, *value, *p; + + message = g_string_new (message_type); + g_string_append_c (message, ':'); + + va_start (ap, message_type); + while ((key = va_arg (ap, const char *))) + { + value = va_arg (ap, const char *); + if (!value) + continue; + + g_string_append_printf (message, " %s=\"", key); + for (p = value; *p; p++) + { + switch (*p) + { + case ' ': + case '"': + case '\\': + g_string_append_c (message, '\\'); + break; + } + + g_string_append_c (message, *p); + } + g_string_append_c (message, '\"'); + } + va_end (ap); + + printf ("startup message: %s\n", message->str); + + g_string_free (message, TRUE); +} + +static void +gdk_wayland_display_notify_startup_complete (GdkDisplay *display, + const gchar *startup_id) +{ + gdk_wayland_display_broadcast_startup_message (display, "remove", + "ID", startup_id, + NULL); +} + +static void +gdk_wayland_display_event_data_copy (GdkDisplay *display, + const GdkEvent *src, + GdkEvent *dst) +{ +} + +static void +gdk_wayland_display_event_data_free (GdkDisplay *display, + GdkEvent *event) +{ +} + +static GdkKeymap * +gdk_wayland_display_get_keymap (GdkDisplay *display) +{ + GdkDisplayWayland *display_wayland; + + g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL); + display_wayland = GDK_DISPLAY_WAYLAND (display); + + if (!display_wayland->keymap) + display_wayland->keymap = _gdk_wayland_keymap_new (display); + + return display_wayland->keymap; +} + +static void +gdk_wayland_display_push_error_trap (GdkDisplay *display) +{ +} + +static gint +gdk_wayland_display_pop_error_trap (GdkDisplay *display, + gboolean ignored) +{ + return 0; +} + +static void +_gdk_display_wayland_class_init (GdkDisplayWaylandClass * class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + GdkDisplayClass *display_class = GDK_DISPLAY_CLASS (class); + + object_class->dispose = gdk_wayland_display_dispose; + object_class->finalize = gdk_wayland_display_finalize; + + display_class->window_type = _gdk_wayland_window_get_type (); + display_class->get_name = gdk_wayland_display_get_name; + display_class->get_n_screens = gdk_wayland_display_get_n_screens; + display_class->get_screen = gdk_wayland_display_get_screen; + display_class->get_default_screen = gdk_wayland_display_get_default_screen; + display_class->beep = gdk_wayland_display_beep; + display_class->sync = gdk_wayland_display_sync; + display_class->flush = gdk_wayland_display_flush; + display_class->has_pending = gdk_wayland_display_has_pending; + display_class->queue_events = _gdk_wayland_display_queue_events; + display_class->get_default_group = gdk_wayland_display_get_default_group; + display_class->supports_selection_notification = gdk_wayland_display_supports_selection_notification; + display_class->request_selection_notification = gdk_wayland_display_request_selection_notification; + display_class->supports_clipboard_persistence = gdk_wayland_display_supports_clipboard_persistence; + display_class->store_clipboard = gdk_wayland_display_store_clipboard; + display_class->supports_shapes = gdk_wayland_display_supports_shapes; + display_class->supports_input_shapes = gdk_wayland_display_supports_input_shapes; + display_class->supports_composite = gdk_wayland_display_supports_composite; + display_class->list_devices = gdk_wayland_display_list_devices; + display_class->get_app_launch_context = _gdk_wayland_display_get_app_launch_context; + display_class->get_default_cursor_size = _gdk_wayland_display_get_default_cursor_size; + display_class->get_maximal_cursor_size = _gdk_wayland_display_get_maximal_cursor_size; + display_class->get_cursor_for_type = _gdk_wayland_display_get_cursor_for_type; + display_class->get_cursor_for_name = _gdk_wayland_display_get_cursor_for_name; + display_class->get_cursor_for_pixbuf = _gdk_wayland_display_get_cursor_for_pixbuf; + display_class->supports_cursor_alpha = _gdk_wayland_display_supports_cursor_alpha; + display_class->supports_cursor_color = _gdk_wayland_display_supports_cursor_color; + display_class->before_process_all_updates = gdk_wayland_display_before_process_all_updates; + display_class->after_process_all_updates = gdk_wayland_display_after_process_all_updates; + display_class->get_next_serial = gdk_wayland_display_get_next_serial; + display_class->notify_startup_complete = gdk_wayland_display_notify_startup_complete; + display_class->event_data_copy = gdk_wayland_display_event_data_copy; + display_class->event_data_free = gdk_wayland_display_event_data_free; + display_class->create_window_impl = _gdk_wayland_display_create_window_impl; + display_class->get_keymap = gdk_wayland_display_get_keymap; + display_class->push_error_trap = gdk_wayland_display_push_error_trap; + display_class->pop_error_trap = gdk_wayland_display_pop_error_trap; + display_class->get_selection_owner = _gdk_wayland_display_get_selection_owner; + display_class->set_selection_owner = _gdk_wayland_display_set_selection_owner; + display_class->send_selection_notify = _gdk_wayland_display_send_selection_notify; + display_class->get_selection_property = _gdk_wayland_display_get_selection_property; + display_class->convert_selection = _gdk_wayland_display_convert_selection; + display_class->text_property_to_utf8_list = _gdk_wayland_display_text_property_to_utf8_list; + display_class->utf8_to_string_target = _gdk_wayland_display_utf8_to_string_target; +} + +static void +_gdk_display_wayland_init (GdkDisplayWayland *display) +{ + _gdk_wayland_display_manager_add_display (gdk_display_manager_get (), + GDK_DISPLAY (display)); +} diff --git a/gdk/wayland/gdkdisplay-wayland.h b/gdk/wayland/gdkdisplay-wayland.h new file mode 100644 index 0000000000..87be6bb8ac --- /dev/null +++ b/gdk/wayland/gdkdisplay-wayland.h @@ -0,0 +1,101 @@ +/* + * gdkdisplay-wayland.h + * + * Copyright 2001 Sun Microsystems Inc. + * + * Erwann Chenede <erwann.chenede@sun.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GDK_DISPLAY_WAYLAND__ +#define __GDK_DISPLAY_WAYLAND__ + +#include <stdint.h> +#include <wayland-client.h> +#include <wayland-egl.h> +#include <EGL/egl.h> +#include <EGL/eglext.h> +#include <GL/gl.h> +#include <GL/glext.h> +#include <cairo-gl.h> +#include <glib.h> +#include <gdk/gdkkeys.h> +#include <gdk/gdkwindow.h> +#include <gdk/gdkinternals.h> +#include <gdk/gdk.h> /* For gdk_get_program_class() */ + +#include "gdkdisplayprivate.h" + +G_BEGIN_DECLS + +typedef struct _GdkDisplayWayland GdkDisplayWayland; +typedef struct _GdkDisplayWaylandClass GdkDisplayWaylandClass; + +#define GDK_TYPE_DISPLAY_WAYLAND (_gdk_display_wayland_get_type()) +#define GDK_DISPLAY_WAYLAND(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_DISPLAY_WAYLAND, GdkDisplayWayland)) +#define GDK_DISPLAY_WAYLAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_DISPLAY_WAYLAND, GdkDisplayWaylandClass)) +#define GDK_IS_DISPLAY_WAYLAND(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_DISPLAY_WAYLAND)) +#define GDK_IS_DISPLAY_WAYLAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_DISPLAY_WAYLAND)) +#define GDK_DISPLAY_WAYLAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_DISPLAY_WAYLAND, GdkDisplayWaylandClass)) + +struct _GdkDisplayWayland +{ + GdkDisplay parent_instance; + GdkScreen *screen; + + /* Keyboard related information */ + GdkKeymap *keymap; + + /* input GdkDevice list */ + GList *input_devices; + + /* Startup notification */ + gchar *startup_notification_id; + + /* Time of most recent user interaction. */ + gulong user_time; + + /* Wayland fields below */ + struct wl_display *wl_display; + struct wl_egl_display *native_display; + struct wl_compositor *compositor; + struct wl_shm *shm; + struct wl_shell *shell; + struct wl_output *output; + struct wl_input_device *input_device; + GSource *event_source; + EGLDisplay egl_display; + EGLContext egl_context; + cairo_device_t *cairo_device; + + GdkCursor **cursors; + + PFNGLEGLIMAGETARGETTEXTURE2DOESPROC image_target_texture_2d; + PFNEGLCREATEIMAGEKHRPROC create_image; + PFNEGLDESTROYIMAGEKHRPROC destroy_image; +}; + +struct _GdkDisplayWaylandClass +{ + GdkDisplayClass parent_class; +}; + +GType _gdk_display_wayland_get_type (void); + +G_END_DECLS + +#endif /* __GDK_DISPLAY_WAYLAND__ */ diff --git a/gdk/wayland/gdkdisplaymanager-wayland.c b/gdk/wayland/gdkdisplaymanager-wayland.c new file mode 100644 index 0000000000..25aa6fb989 --- /dev/null +++ b/gdk/wayland/gdkdisplaymanager-wayland.c @@ -0,0 +1,318 @@ +/* GDK - The GIMP Drawing Kit + * gdkdisplaymanager-wayland.c + * + * Copyright 2010 Red Hat, Inc. + * + * Author: Matthias clasen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include "gdkdisplaymanagerprivate.h" +#include "gdkdisplay-wayland.h" +#include "gdkprivate-wayland.h" + +#include "gdkinternals.h" + +#include <X11/extensions/XKBcommon.h> + +typedef struct _GdkWaylandDisplayManager GdkWaylandDisplayManager; +typedef struct _GdkWaylandDisplayManagerClass GdkWaylandDisplayManagerClass; + +#define GDK_TYPE_WAYLAND_DISPLAY_MANAGER (gdk_wayland_display_manager_get_type()) +#define GDK_WAYLAND_DISPLAY_MANAGER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_WAYLAND_DISPLAY_MANAGER, GdkWaylandDisplayManager)) +#define GDK_WAYLAND_DISPLAY_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_WAYLAND_DISPLAY_MANAGER, GdkWaylandDisplayManagerClass)) +#define GDK_IS_WAYLAND_DISPLAY_MANAGER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_WAYLAND_DISPLAY_MANAGER)) +#define GDK_IS_WAYLAND_DISPLAY_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_WAYLAND_DISPLAY_MANAGER)) +#define GDK_WAYLAND_DISPLAY_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_WAYLAND_DISPLAY_MANAGER, GdkWaylandDisplayManagerClass)) + +struct _GdkWaylandDisplayManager +{ + GdkDisplayManager parent; + + GdkDisplay *default_display; + GSList *displays; +}; + +struct _GdkWaylandDisplayManagerClass +{ + GdkDisplayManagerClass parent_class; +}; + +G_DEFINE_TYPE (GdkWaylandDisplayManager, gdk_wayland_display_manager, GDK_TYPE_DISPLAY_MANAGER) + +static void +gdk_wayland_display_manager_finalize (GObject *object) +{ + g_error ("A GdkWaylandDisplayManager object was finalized. This should not happen"); + G_OBJECT_CLASS (gdk_wayland_display_manager_parent_class)->finalize (object); +} + +static GdkDisplay * +gdk_wayland_display_manager_open_display (GdkDisplayManager *manager, + const gchar *name) +{ + return _gdk_wayland_display_open (name); +} + +static GSList * +gdk_wayland_display_manager_list_displays (GdkDisplayManager *manager) +{ + return g_slist_copy (GDK_WAYLAND_DISPLAY_MANAGER (manager)->displays); +} + +static void +gdk_wayland_display_manager_set_default_display (GdkDisplayManager *manager, + GdkDisplay *display) +{ + GDK_WAYLAND_DISPLAY_MANAGER (manager)->default_display = display; + + _gdk_wayland_display_make_default (display); +} + +static GdkDisplay * +gdk_wayland_display_manager_get_default_display (GdkDisplayManager *manager) +{ + return GDK_WAYLAND_DISPLAY_MANAGER (manager)->default_display; +} + +static GdkAtom +gdk_wayland_display_manager_atom_intern (GdkDisplayManager *manager, + const gchar *atom_name, + gboolean dup) +{ + return 0; +} + +static gchar * +gdk_wayland_display_manager_get_atom_name (GdkDisplayManager *manager, + GdkAtom atom) +{ + return 0; +} + +static guint +gdk_wayland_display_manager_lookup_keyval (GdkDisplayManager *manager, + const gchar *keyval_name) +{ + g_return_val_if_fail (keyval_name != NULL, 0); + + return xkb_string_to_keysym(keyval_name); +} + +static gchar * +gdk_wayland_display_manager_get_keyval_name (GdkDisplayManager *manager, + guint keyval) +{ + static char buf[128]; + + switch (keyval) + { + case GDK_KEY_Page_Up: + return "Page_Up"; + case GDK_KEY_Page_Down: + return "Page_Down"; + case GDK_KEY_KP_Page_Up: + return "KP_Page_Up"; + case GDK_KEY_KP_Page_Down: + return "KP_Page_Down"; + } + + xkb_keysym_to_string(keyval, buf, sizeof buf); + + return buf; +} + +static void +gdk_wayland_display_manager_keyval_convert_case (GdkDisplayManager *manager, + guint symbol, + guint *lower, + guint *upper) +{ + guint xlower = symbol; + guint xupper = symbol; + + /* Check for directly encoded 24-bit UCS characters: */ + if ((symbol & 0xff000000) == 0x01000000) + { + if (lower) + *lower = gdk_unicode_to_keyval (g_unichar_tolower (symbol & 0x00ffffff)); + if (upper) + *upper = gdk_unicode_to_keyval (g_unichar_toupper (symbol & 0x00ffffff)); + return; + } + + switch (symbol >> 8) + { + case 0: /* Latin 1 */ + if ((symbol >= GDK_KEY_A) && (symbol <= GDK_KEY_Z)) + xlower += (GDK_KEY_a - GDK_KEY_A); + else if ((symbol >= GDK_KEY_a) && (symbol <= GDK_KEY_z)) + xupper -= (GDK_KEY_a - GDK_KEY_A); + else if ((symbol >= GDK_KEY_Agrave) && (symbol <= GDK_KEY_Odiaeresis)) + xlower += (GDK_KEY_agrave - GDK_KEY_Agrave); + else if ((symbol >= GDK_KEY_agrave) && (symbol <= GDK_KEY_odiaeresis)) + xupper -= (GDK_KEY_agrave - GDK_KEY_Agrave); + else if ((symbol >= GDK_KEY_Ooblique) && (symbol <= GDK_KEY_Thorn)) + xlower += (GDK_KEY_oslash - GDK_KEY_Ooblique); + else if ((symbol >= GDK_KEY_oslash) && (symbol <= GDK_KEY_thorn)) + xupper -= (GDK_KEY_oslash - GDK_KEY_Ooblique); + break; + + case 1: /* Latin 2 */ + /* Assume the KeySym is a legal value (ignore discontinuities) */ + if (symbol == GDK_KEY_Aogonek) + xlower = GDK_KEY_aogonek; + else if (symbol >= GDK_KEY_Lstroke && symbol <= GDK_KEY_Sacute) + xlower += (GDK_KEY_lstroke - GDK_KEY_Lstroke); + else if (symbol >= GDK_KEY_Scaron && symbol <= GDK_KEY_Zacute) + xlower += (GDK_KEY_scaron - GDK_KEY_Scaron); + else if (symbol >= GDK_KEY_Zcaron && symbol <= GDK_KEY_Zabovedot) + xlower += (GDK_KEY_zcaron - GDK_KEY_Zcaron); + else if (symbol == GDK_KEY_aogonek) + xupper = GDK_KEY_Aogonek; + else if (symbol >= GDK_KEY_lstroke && symbol <= GDK_KEY_sacute) + xupper -= (GDK_KEY_lstroke - GDK_KEY_Lstroke); + else if (symbol >= GDK_KEY_scaron && symbol <= GDK_KEY_zacute) + xupper -= (GDK_KEY_scaron - GDK_KEY_Scaron); + else if (symbol >= GDK_KEY_zcaron && symbol <= GDK_KEY_zabovedot) + xupper -= (GDK_KEY_zcaron - GDK_KEY_Zcaron); + else if (symbol >= GDK_KEY_Racute && symbol <= GDK_KEY_Tcedilla) + xlower += (GDK_KEY_racute - GDK_KEY_Racute); + else if (symbol >= GDK_KEY_racute && symbol <= GDK_KEY_tcedilla) + xupper -= (GDK_KEY_racute - GDK_KEY_Racute); + break; + + case 2: /* Latin 3 */ + /* Assume the KeySym is a legal value (ignore discontinuities) */ + if (symbol >= GDK_KEY_Hstroke && symbol <= GDK_KEY_Hcircumflex) + xlower += (GDK_KEY_hstroke - GDK_KEY_Hstroke); + else if (symbol >= GDK_KEY_Gbreve && symbol <= GDK_KEY_Jcircumflex) + xlower += (GDK_KEY_gbreve - GDK_KEY_Gbreve); + else if (symbol >= GDK_KEY_hstroke && symbol <= GDK_KEY_hcircumflex) + xupper -= (GDK_KEY_hstroke - GDK_KEY_Hstroke); + else if (symbol >= GDK_KEY_gbreve && symbol <= GDK_KEY_jcircumflex) + xupper -= (GDK_KEY_gbreve - GDK_KEY_Gbreve); + else if (symbol >= GDK_KEY_Cabovedot && symbol <= GDK_KEY_Scircumflex) + xlower += (GDK_KEY_cabovedot - GDK_KEY_Cabovedot); + else if (symbol >= GDK_KEY_cabovedot && symbol <= GDK_KEY_scircumflex) + xupper -= (GDK_KEY_cabovedot - GDK_KEY_Cabovedot); + break; + + case 3: /* Latin 4 */ + /* Assume the KeySym is a legal value (ignore discontinuities) */ + if (symbol >= GDK_KEY_Rcedilla && symbol <= GDK_KEY_Tslash) + xlower += (GDK_KEY_rcedilla - GDK_KEY_Rcedilla); + else if (symbol >= GDK_KEY_rcedilla && symbol <= GDK_KEY_tslash) + xupper -= (GDK_KEY_rcedilla - GDK_KEY_Rcedilla); + else if (symbol == GDK_KEY_ENG) + xlower = GDK_KEY_eng; + else if (symbol == GDK_KEY_eng) + xupper = GDK_KEY_ENG; + else if (symbol >= GDK_KEY_Amacron && symbol <= GDK_KEY_Umacron) + xlower += (GDK_KEY_amacron - GDK_KEY_Amacron); + else if (symbol >= GDK_KEY_amacron && symbol <= GDK_KEY_umacron) + xupper -= (GDK_KEY_amacron - GDK_KEY_Amacron); + break; + + case 6: /* Cyrillic */ + /* Assume the KeySym is a legal value (ignore discontinuities) */ + if (symbol >= GDK_KEY_Serbian_DJE && symbol <= GDK_KEY_Serbian_DZE) + xlower -= (GDK_KEY_Serbian_DJE - GDK_KEY_Serbian_dje); + else if (symbol >= GDK_KEY_Serbian_dje && symbol <= GDK_KEY_Serbian_dze) + xupper += (GDK_KEY_Serbian_DJE - GDK_KEY_Serbian_dje); + else if (symbol >= GDK_KEY_Cyrillic_YU && symbol <= GDK_KEY_Cyrillic_HARDSIGN) + xlower -= (GDK_KEY_Cyrillic_YU - GDK_KEY_Cyrillic_yu); + else if (symbol >= GDK_KEY_Cyrillic_yu && symbol <= GDK_KEY_Cyrillic_hardsign) + xupper += (GDK_KEY_Cyrillic_YU - GDK_KEY_Cyrillic_yu); + break; + + case 7: /* Greek */ + /* Assume the KeySym is a legal value (ignore discontinuities) */ + if (symbol >= GDK_KEY_Greek_ALPHAaccent && symbol <= GDK_KEY_Greek_OMEGAaccent) + xlower += (GDK_KEY_Greek_alphaaccent - GDK_KEY_Greek_ALPHAaccent); + else if (symbol >= GDK_KEY_Greek_alphaaccent && symbol <= GDK_KEY_Greek_omegaaccent && + symbol != GDK_KEY_Greek_iotaaccentdieresis && + symbol != GDK_KEY_Greek_upsilonaccentdieresis) + xupper -= (GDK_KEY_Greek_alphaaccent - GDK_KEY_Greek_ALPHAaccent); + else if (symbol >= GDK_KEY_Greek_ALPHA && symbol <= GDK_KEY_Greek_OMEGA) + xlower += (GDK_KEY_Greek_alpha - GDK_KEY_Greek_ALPHA); + else if (symbol >= GDK_KEY_Greek_alpha && symbol <= GDK_KEY_Greek_omega && + symbol != GDK_KEY_Greek_finalsmallsigma) + xupper -= (GDK_KEY_Greek_alpha - GDK_KEY_Greek_ALPHA); + break; + } + + if (lower) + *lower = xlower; + if (upper) + *upper = xupper; +} + +static void +gdk_wayland_display_manager_class_init (GdkWaylandDisplayManagerClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + GdkDisplayManagerClass *manager_class = GDK_DISPLAY_MANAGER_CLASS (class); + + object_class->finalize = gdk_wayland_display_manager_finalize; + + manager_class->open_display = gdk_wayland_display_manager_open_display; + manager_class->list_displays = gdk_wayland_display_manager_list_displays; + manager_class->set_default_display = gdk_wayland_display_manager_set_default_display; + manager_class->get_default_display = gdk_wayland_display_manager_get_default_display; + manager_class->atom_intern = gdk_wayland_display_manager_atom_intern; + manager_class->get_atom_name = gdk_wayland_display_manager_get_atom_name; + manager_class->lookup_keyval = gdk_wayland_display_manager_lookup_keyval; + manager_class->get_keyval_name = gdk_wayland_display_manager_get_keyval_name; + manager_class->keyval_convert_case = gdk_wayland_display_manager_keyval_convert_case; +} + +static void +gdk_wayland_display_manager_init (GdkWaylandDisplayManager *manager) +{ +} + +void +_gdk_wayland_display_manager_add_display (GdkDisplayManager *manager, + GdkDisplay *display) +{ + GdkWaylandDisplayManager *manager_wayland = GDK_WAYLAND_DISPLAY_MANAGER (manager); + + if (manager_wayland->displays == NULL) + gdk_display_manager_set_default_display (manager, display); + + manager_wayland->displays = g_slist_prepend (manager_wayland->displays, display); +} + +void +_gdk_wayland_display_manager_remove_display (GdkDisplayManager *manager, + GdkDisplay *display) +{ + GdkWaylandDisplayManager *manager_wayland = GDK_WAYLAND_DISPLAY_MANAGER (manager); + + manager_wayland->displays = g_slist_remove (manager_wayland->displays, display); + + if (manager_wayland->default_display == display) + { + if (manager_wayland->displays) + gdk_display_manager_set_default_display (manager, manager_wayland->displays->data); + else + gdk_display_manager_set_default_display (manager, NULL); + } +} diff --git a/gdk/wayland/gdkdnd-wayland.c b/gdk/wayland/gdkdnd-wayland.c new file mode 100644 index 0000000000..62c79759b5 --- /dev/null +++ b/gdk/wayland/gdkdnd-wayland.c @@ -0,0 +1,185 @@ +/* + * Copyright © 2010 Intel Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include "gdkdndprivate.h" + +#include "gdkmain.h" +#include "gdkinternals.h" +#include "gdkproperty.h" +#include "gdkprivate-wayland.h" +#include "gdkdisplay-wayland.h" + +#include <string.h> + +#define GDK_TYPE_WAYLAND_DRAG_CONTEXT (gdk_wayland_drag_context_get_type ()) +#define GDK_WAYLAND_DRAG_CONTEXT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_WAYLAND_DRAG_CONTEXT, GdkWaylandDragContext)) +#define GDK_WAYLAND_DRAG_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_WAYLAND_DRAG_CONTEXT, GdkWaylandDragContextClass)) +#define GDK_IS_WAYLAND_DRAG_CONTEXT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_WAYLAND_DRAG_CONTEXT)) +#define GDK_IS_WAYLAND_DRAG_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_WAYLAND_DRAG_CONTEXT)) +#define GDK_WAYLAND_DRAG_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_WAYLAND_DRAG_CONTEXT, GdkWaylandDragContextClass)) + +typedef struct _GdkWaylandDragContext GdkWaylandDragContext; +typedef struct _GdkWaylandDragContextClass GdkWaylandDragContextClass; + +struct _GdkWaylandDragContext +{ + GdkDragContext context; +}; + +struct _GdkWaylandDragContextClass +{ + GdkDragContextClass parent_class; +}; + +static GList *contexts; + +G_DEFINE_TYPE (GdkWaylandDragContext, gdk_wayland_drag_context, GDK_TYPE_DRAG_CONTEXT) + +static void +gdk_wayland_drag_context_finalize (GObject *object) +{ + GdkDragContext *context = GDK_DRAG_CONTEXT (object); + + contexts = g_list_remove (contexts, context); + + G_OBJECT_CLASS (gdk_wayland_drag_context_parent_class)->finalize (object); +} + +static GdkWindow * +gdk_wayland_drag_context_find_window (GdkDragContext *context, + GdkWindow *drag_window, + GdkScreen *screen, + gint x_root, + gint y_root, + GdkDragProtocol *protocol) +{ + return NULL; +} + +static gboolean +gdk_wayland_drag_context_drag_motion (GdkDragContext *context, + GdkWindow *dest_window, + GdkDragProtocol protocol, + gint x_root, + gint y_root, + GdkDragAction suggested_action, + GdkDragAction possible_actions, + guint32 time) +{ + return FALSE; +} + +static void +gdk_wayland_drag_context_drag_abort (GdkDragContext *context, + guint32 time) +{ +} + +static void +gdk_wayland_drag_context_drag_drop (GdkDragContext *context, + guint32 time) +{ +} + +/* Destination side */ + +static void +gdk_wayland_drag_context_drag_status (GdkDragContext *context, + GdkDragAction action, + guint32 time_) +{ +} + +static void +gdk_wayland_drag_context_drop_reply (GdkDragContext *context, + gboolean accepted, + guint32 time_) +{ +} + +static void +gdk_wayland_drag_context_drop_finish (GdkDragContext *context, + gboolean success, + guint32 time) +{ +} + +static gboolean +gdk_wayland_drag_context_drop_status (GdkDragContext *context) +{ + return FALSE; +} + +static GdkAtom +gdk_wayland_drag_context_get_selection (GdkDragContext *context) +{ + return GDK_NONE; +} + +static void +gdk_wayland_drag_context_init (GdkWaylandDragContext *context) +{ + contexts = g_list_prepend (contexts, context); +} + +static void +gdk_wayland_drag_context_class_init (GdkWaylandDragContextClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GdkDragContextClass *context_class = GDK_DRAG_CONTEXT_CLASS (klass); + + object_class->finalize = gdk_wayland_drag_context_finalize; + + context_class->find_window = gdk_wayland_drag_context_find_window; + context_class->drag_status = gdk_wayland_drag_context_drag_status; + context_class->drag_motion = gdk_wayland_drag_context_drag_motion; + context_class->drag_abort = gdk_wayland_drag_context_drag_abort; + context_class->drag_drop = gdk_wayland_drag_context_drag_drop; + context_class->drop_reply = gdk_wayland_drag_context_drop_reply; + context_class->drop_finish = gdk_wayland_drag_context_drop_finish; + context_class->drop_status = gdk_wayland_drag_context_drop_status; + context_class->get_selection = gdk_wayland_drag_context_get_selection; +} + +GdkDragProtocol +_gdk_wayland_window_get_drag_protocol (GdkWindow *window, GdkWindow **target) +{ + return 0; +} + +void +_gdk_wayland_window_register_dnd (GdkWindow *window) +{ +} + +GdkDragContext * +_gdk_wayland_window_drag_begin (GdkWindow *window, + GdkDevice *device, + GList *targets) +{ + GdkDragContext *context; + + context = (GdkDragContext *) g_object_new (GDK_TYPE_WAYLAND_DRAG_CONTEXT, NULL); + + gdk_drag_context_set_device (context, device); + + return context; +} diff --git a/gdk/wayland/gdkeventsource.c b/gdk/wayland/gdkeventsource.c new file mode 100644 index 0000000000..b48e880107 --- /dev/null +++ b/gdk/wayland/gdkeventsource.c @@ -0,0 +1,177 @@ +/* GDK - The GIMP Drawing Kit + * Copyright (C) 2009 Carlos Garnacho <carlosg@gnome.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include "gdkinternals.h" +#include "gdkprivate-wayland.h" + +typedef struct _GdkWaylandEventSource { + GSource source; + GPollFD pfd; + uint32_t mask; + GdkDisplay *display; +} GdkWaylandEventSource; + +static GList *event_sources = NULL; + +static gboolean +gdk_event_source_prepare(GSource *base, gint *timeout) +{ + GdkWaylandEventSource *source = (GdkWaylandEventSource *) base; + GdkDisplayWayland *display = (GdkDisplayWayland *) source->display; + + *timeout = -1; + + /* We have to add/remove the GPollFD if we want to update our + * poll event mask dynamically. Instead, let's just flush all + * write on idle instead, which is what this amounts to. */ + + if (_gdk_event_queue_find_first (source->display) != NULL) + return TRUE; + + while (source->mask & WL_DISPLAY_WRITABLE) + wl_display_iterate(display->wl_display, WL_DISPLAY_WRITABLE); + + return FALSE; +} + +static gboolean +gdk_event_source_check(GSource *base) +{ + GdkWaylandEventSource *source = (GdkWaylandEventSource *) base; + + return _gdk_event_queue_find_first (source->display) != NULL || + source->pfd.revents; +} + +static gboolean +gdk_event_source_dispatch(GSource *base, + GSourceFunc callback, + gpointer data) +{ + GdkWaylandEventSource *source = (GdkWaylandEventSource *) base; + GdkDisplay *display = source->display; + GdkEvent *event; + + GDK_THREADS_ENTER (); + + event = gdk_display_get_event (display); + + if (event) + { + _gdk_event_emit (event); + + gdk_event_free (event); + } + + GDK_THREADS_LEAVE (); + + return TRUE; +} + +static void +gdk_event_source_finalize (GSource *source) +{ + event_sources = g_list_remove (event_sources, source); +} + +static GSourceFuncs wl_glib_source_funcs = { + gdk_event_source_prepare, + gdk_event_source_check, + gdk_event_source_dispatch, + gdk_event_source_finalize +}; + +static int +gdk_event_source_update(uint32_t mask, void *data) +{ + GdkWaylandEventSource *source = data; + + source->mask = mask; + + return 0; +} + +void +_gdk_wayland_display_deliver_event (GdkDisplay *display, GdkEvent *event) +{ + GList *node; + static int serial; + + node = _gdk_event_queue_append (display, event); + _gdk_windowing_got_event (display, node, event, serial++); +} + +GSource * +_gdk_wayland_display_event_source_new (GdkDisplay *display) +{ + GSource *source; + GdkWaylandEventSource *wl_source; + GdkDisplayWayland *display_wayland; + char *name; + + source = g_source_new (&wl_glib_source_funcs, + sizeof (GdkWaylandEventSource)); + name = g_strdup_printf ("GDK Wayland Event source (%s)", "display name"); + g_source_set_name (source, name); + g_free (name); + wl_source = (GdkWaylandEventSource *) source; + + display_wayland = GDK_DISPLAY_WAYLAND (display); + wl_source->display = display; + wl_source->pfd.fd = wl_display_get_fd(display_wayland->wl_display, + gdk_event_source_update, source); + wl_source->pfd.events = G_IO_IN | G_IO_ERR; + g_source_add_poll(source, &wl_source->pfd); + + g_source_set_priority (source, GDK_PRIORITY_EVENTS); + g_source_set_can_recurse (source, TRUE); + g_source_attach (source, NULL); + + event_sources = g_list_prepend (event_sources, source); + + return source; +} + +void +_gdk_wayland_display_flush (GdkDisplay *display, GSource *source) +{ + GdkWaylandEventSource *wayland_source = (GdkWaylandEventSource *) source; + + while (wayland_source->mask & WL_DISPLAY_WRITABLE) + wl_display_iterate(GDK_DISPLAY_WAYLAND (display)->wl_display, + WL_DISPLAY_WRITABLE); +} + +void +_gdk_wayland_display_queue_events (GdkDisplay *display) +{ + GdkDisplayWayland *display_wayland; + GdkWaylandEventSource *source; + + display_wayland = GDK_DISPLAY_WAYLAND (display); + source = (GdkWaylandEventSource *) display_wayland->event_source; + + if (source->pfd.revents) + { + wl_display_iterate(display_wayland->wl_display, WL_DISPLAY_READABLE); + source->pfd.revents = 0; + } +} diff --git a/gdk/wayland/gdkkeys-wayland.c b/gdk/wayland/gdkkeys-wayland.c new file mode 100644 index 0000000000..55c95e35dc --- /dev/null +++ b/gdk/wayland/gdkkeys-wayland.c @@ -0,0 +1,654 @@ +/* GDK - The GIMP Drawing Kit + * Copyright (C) 2000 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GTK+ Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GTK+ at ftp://ftp.gtk.org/pub/gtk/. + */ + +#include "config.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <limits.h> +#include <errno.h> + +#include "gdk.h" +#include "gdkwayland.h" + +#include "gdkprivate-wayland.h" +#include "gdkinternals.h" +#include "gdkdisplay-wayland.h" +#include "gdkkeysprivate.h" + +#include <X11/extensions/XKBcommon.h> + +typedef struct _GdkWaylandKeymap GdkWaylandKeymap; +typedef struct _GdkWaylandKeymapClass GdkWaylandKeymapClass; + +struct _GdkWaylandKeymap +{ + GdkKeymap parent_instance; + GdkModifierType modmap[8]; + struct xkb_desc *xkb; +}; + +struct _GdkWaylandKeymapClass +{ + GdkKeymapClass parent_class; +}; + +#define GDK_TYPE_WAYLAND_KEYMAP (_gdk_wayland_keymap_get_type ()) +#define GDK_WAYLAND_KEYMAP(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_WAYLAND_KEYMAP, GdkWaylandKeymap)) +#define GDK_IS_WAYLAND_KEYMAP(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_WAYLAND_KEYMAP)) + +G_DEFINE_TYPE (GdkWaylandKeymap, _gdk_wayland_keymap, GDK_TYPE_KEYMAP) + +static void +gdk_wayland_keymap_finalize (GObject *object) +{ + G_OBJECT_CLASS (_gdk_wayland_keymap_parent_class)->finalize (object); +} + +static PangoDirection +gdk_wayland_keymap_get_direction (GdkKeymap *keymap) +{ + return PANGO_DIRECTION_NEUTRAL; +} + +static gboolean +gdk_wayland_keymap_have_bidi_layouts (GdkKeymap *keymap) +{ + return FALSE; +} + +static gboolean +gdk_wayland_keymap_get_caps_lock_state (GdkKeymap *keymap) +{ + return FALSE; +} + +static gboolean +gdk_wayland_keymap_get_num_lock_state (GdkKeymap *keymap) +{ + return FALSE; +} + +static gboolean +gdk_wayland_keymap_get_entries_for_keyval (GdkKeymap *keymap, + guint keyval, + GdkKeymapKey **keys, + gint *n_keys) +{ + GArray *retval; + uint32_t keycode; + struct xkb_desc *xkb; + + xkb = GDK_WAYLAND_KEYMAP (keymap)->xkb; + keycode = xkb->min_key_code; + + retval = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey)); + + for (keycode = xkb->min_key_code; keycode <= xkb->max_key_code; keycode++) + { + gint max_shift_levels = XkbKeyGroupsWidth (xkb, keycode); + + gint group = 0; + gint level = 0; + gint total_syms = XkbKeyNumSyms (xkb, keycode); + gint i = 0; + uint32_t *entry; + + /* entry is an array with all syms for group 0, all + * syms for group 1, etc. and for each group the + * shift level syms are in order + */ + entry = XkbKeySymsPtr (xkb, keycode); + + for (i = 0; i < total_syms; i++) + { + /* check out our cool loop invariant */ + g_assert (i == (group * max_shift_levels + level)); + + if (entry[i] == keyval) + { + /* Found a match */ + GdkKeymapKey key; + + key.keycode = keycode; + key.group = group; + key.level = level; + + g_array_append_val (retval, key); + + g_assert (XkbKeySymEntry (xkb, keycode, level, group) == + keyval); + } + + level++; + + if (level == max_shift_levels) + { + level = 0; + group++; + } + } + } + + *n_keys = retval->len; + *keys = (GdkKeymapKey *) g_array_free (retval, FALSE); + + return *n_keys > 0; +} + +static gboolean +gdk_wayland_keymap_get_entries_for_keycode (GdkKeymap *keymap, + guint hardware_keycode, + GdkKeymapKey **keys, + guint **keyvals, + gint *n_entries) +{ + GArray *key_array; + GArray *keyval_array; + struct xkb_desc *xkb; + gint max_shift_levels; + gint group = 0; + gint level = 0; + gint total_syms; + gint i; + uint32_t *entry; + + g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE); + g_return_val_if_fail (n_entries != NULL, FALSE); + + xkb = GDK_WAYLAND_KEYMAP (keymap)->xkb; + + if (hardware_keycode < xkb->min_key_code || + hardware_keycode > xkb->max_key_code) + { + if (keys) + *keys = NULL; + if (keyvals) + *keyvals = NULL; + + *n_entries = 0; + return FALSE; + } + + if (keys) + key_array = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey)); + else + key_array = NULL; + + if (keyvals) + keyval_array = g_array_new (FALSE, FALSE, sizeof (guint)); + else + keyval_array = NULL; + + /* See sec 15.3.4 in XKB docs */ + max_shift_levels = XkbKeyGroupsWidth (xkb, hardware_keycode); + total_syms = XkbKeyNumSyms (xkb, hardware_keycode); + + /* entry is an array with all syms for group 0, all + * syms for group 1, etc. and for each group the + * shift level syms are in order + */ + entry = XkbKeySymsPtr (xkb, hardware_keycode); + + for (i = 0; i < total_syms; i++) + { + /* check out our cool loop invariant */ + g_assert (i == (group * max_shift_levels + level)); + + if (key_array) + { + GdkKeymapKey key; + + key.keycode = hardware_keycode; + key.group = group; + key.level = level; + + g_array_append_val (key_array, key); + } + + if (keyval_array) + g_array_append_val (keyval_array, entry[i]); + + ++level; + + if (level == max_shift_levels) + { + level = 0; + ++group; + } + } + + *n_entries = 0; + + if (keys) + { + *n_entries = key_array->len; + *keys = (GdkKeymapKey*) g_array_free (key_array, FALSE); + } + + if (keyvals) + { + *n_entries = keyval_array->len; + *keyvals = (guint*) g_array_free (keyval_array, FALSE); + } + + return *n_entries > 0; +} + +static guint +gdk_wayland_keymap_lookup_key (GdkKeymap *keymap, + const GdkKeymapKey *key) +{ + struct xkb_desc *xkb; + + xkb = GDK_WAYLAND_KEYMAP (keymap)->xkb; + + return XkbKeySymEntry (xkb, key->keycode, key->level, key->group); +} + +/* This is copied straight from XFree86 Xlib, to: + * - add the group and level return. + * - change the interpretation of mods_rtrn as described + * in the docs for gdk_keymap_translate_keyboard_state() + * It's unchanged for ease of diff against the Xlib sources; don't + * reformat it. + */ +static int +MyEnhancedXkbTranslateKeyCode(struct xkb_desc * xkb, + KeyCode key, + unsigned int mods, + unsigned int * mods_rtrn, + uint32_t * keysym_rtrn, + int * group_rtrn, + int * level_rtrn) +{ + struct xkb_key_type *type; + int col,nKeyGroups; + unsigned preserve,effectiveGroup; + uint32_t *syms; + + if (mods_rtrn!=NULL) + *mods_rtrn = 0; + + nKeyGroups= XkbKeyNumGroups(xkb,key); + if ((!XkbKeycodeInRange(xkb,key))||(nKeyGroups==0)) { + if (keysym_rtrn!=NULL) + *keysym_rtrn = 0; + return 0; + } + + syms = XkbKeySymsPtr(xkb,key); + + /* find the offset of the effective group */ + col = 0; + effectiveGroup= XkbGroupForCoreState(mods); + if ( effectiveGroup>=nKeyGroups ) { + unsigned groupInfo= XkbKeyGroupInfo(xkb,key); + switch (XkbOutOfRangeGroupAction(groupInfo)) { + default: + effectiveGroup %= nKeyGroups; + break; + case XkbClampIntoRange: + effectiveGroup = nKeyGroups-1; + break; + case XkbRedirectIntoRange: + effectiveGroup = XkbOutOfRangeGroupNumber(groupInfo); + if (effectiveGroup>=nKeyGroups) + effectiveGroup= 0; + break; + } + } + col= effectiveGroup*XkbKeyGroupsWidth(xkb,key); + type = XkbKeyKeyType(xkb,key,effectiveGroup); + + preserve= 0; + if (type->map) { /* find the column (shift level) within the group */ + register int i; + struct xkb_kt_map_entry *entry; + /* ---- Begin section modified for GDK ---- */ + int found = 0; + + for (i=0,entry=type->map;i<type->map_count;i++,entry++) { + if (mods_rtrn) { + int bits = 0; + unsigned long tmp = entry->mods.mask; + while (tmp) { + if ((tmp & 1) == 1) + bits++; + tmp >>= 1; + } + /* We always add one-modifiers levels to mods_rtrn since + * they can't wipe out bits in the state unless the + * level would be triggered. But return other modifiers + * + */ + if (bits == 1 || (mods&type->mods.mask)==entry->mods.mask) + *mods_rtrn |= entry->mods.mask; + } + + if (!found&&entry->active&&((mods&type->mods.mask)==entry->mods.mask)) { + col+= entry->level; + if (type->preserve) + preserve= type->preserve[i].mask; + + if (level_rtrn) + *level_rtrn = entry->level; + + found = 1; + } + } + /* ---- End section modified for GDK ---- */ + } + + if (keysym_rtrn!=NULL) + *keysym_rtrn= syms[col]; + if (mods_rtrn) { + /* ---- Begin section modified for GDK ---- */ + *mods_rtrn &= ~preserve; + /* ---- End section modified for GDK ---- */ + + /* ---- Begin stuff GDK comments out of the original Xlib version ---- */ + /* This is commented out because xkb_info is a private struct */ + +#if 0 + /* The Motif VTS doesn't get the help callback called if help + * is bound to Shift+<whatever>, and it appears as though it + * is XkbTranslateKeyCode that is causing the problem. The + * core X version of XTranslateKey always OR's in ShiftMask + * and LockMask for mods_rtrn, so this "fix" keeps this behavior + * and solves the VTS problem. + */ + if ((xkb->dpy)&&(xkb->dpy->xkb_info)&& + (xkb->dpy->xkb_info->xlib_ctrls&XkbLC_AlwaysConsumeShiftAndLock)) { *mods_rtrn|= (ShiftMask|LockMask); + } +#endif + + /* ---- End stuff GDK comments out of the original Xlib version ---- */ + } + + /* ---- Begin stuff GDK adds to the original Xlib version ---- */ + + if (group_rtrn) + *group_rtrn = effectiveGroup; + + /* ---- End stuff GDK adds to the original Xlib version ---- */ + + return (syms[col] != 0); +} + +static gboolean +gdk_wayland_keymap_translate_keyboard_state (GdkKeymap *keymap, + guint hardware_keycode, + GdkModifierType state, + gint group, + guint *keyval, + gint *effective_group, + gint *level, + GdkModifierType *consumed_modifiers) +{ + GdkWaylandKeymap *wayland_keymap; + uint32_t tmp_keyval = 0; + guint tmp_modifiers; + struct xkb_desc *xkb; + + g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE); + g_return_val_if_fail (group < 4, FALSE); + + wayland_keymap = GDK_WAYLAND_KEYMAP (keymap); + xkb = wayland_keymap->xkb; + + if (keyval) + *keyval = 0; + if (effective_group) + *effective_group = 0; + if (level) + *level = 0; + if (consumed_modifiers) + *consumed_modifiers = 0; + + if (hardware_keycode < xkb->min_key_code || + hardware_keycode > xkb->max_key_code) + return FALSE; + + + /* replace bits 13 and 14 with the provided group */ + state &= ~(1 << 13 | 1 << 14); + state |= group << 13; + + MyEnhancedXkbTranslateKeyCode (xkb, + hardware_keycode, + state, + &tmp_modifiers, + &tmp_keyval, + effective_group, + level); + + if (state & ~tmp_modifiers & XKB_COMMON_LOCK_MASK) + tmp_keyval = gdk_keyval_to_upper (tmp_keyval); + + /* We need to augment the consumed modifiers with LockMask, since + * we handle that ourselves, and also with the group bits + */ + tmp_modifiers |= XKB_COMMON_LOCK_MASK | 1 << 13 | 1 << 14; + + + if (consumed_modifiers) + *consumed_modifiers = tmp_modifiers; + + if (keyval) + *keyval = tmp_keyval; + + return tmp_keyval != 0; +} + + +static void +update_modmap (GdkWaylandKeymap *wayland_keymap) +{ + static struct { + const gchar *name; + uint32_t atom; + GdkModifierType mask; + } vmods[] = { + { "Meta", 0, GDK_META_MASK }, + { "Super", 0, GDK_SUPER_MASK }, + { "Hyper", 0, GDK_HYPER_MASK }, + { NULL, 0, 0 } + }; + + gint i, j, k; + + if (!vmods[0].atom) + for (i = 0; vmods[i].name; i++) + vmods[i].atom = xkb_intern_atom(vmods[i].name); + + for (i = 0; i < 8; i++) + wayland_keymap->modmap[i] = 1 << i; + + for (i = 0; i < XkbNumVirtualMods; i++) + { + for (j = 0; vmods[j].atom; j++) + { + if (wayland_keymap->xkb->names->vmods[i] == vmods[j].atom) + { + for (k = 0; k < 8; k++) + { + if (wayland_keymap->xkb->server->vmods[i] & (1 << k)) + wayland_keymap->modmap[k] |= vmods[j].mask; + } + } + } + } +} + +static void +gdk_wayland_keymap_add_virtual_modifiers (GdkKeymap *keymap, + GdkModifierType *state) +{ + GdkWaylandKeymap *wayland_keymap; + int i; + + wayland_keymap = GDK_WAYLAND_KEYMAP (keymap); + + for (i = 3; i < 8; i++) + { + if ((1 << i) & *state) + { + if (wayland_keymap->modmap[i] & GDK_MOD1_MASK) + *state |= GDK_MOD1_MASK; + if (wayland_keymap->modmap[i] & GDK_SUPER_MASK) + *state |= GDK_SUPER_MASK; + if (wayland_keymap->modmap[i] & GDK_HYPER_MASK) + *state |= GDK_HYPER_MASK; + if (wayland_keymap->modmap[i] & GDK_META_MASK) + *state |= GDK_META_MASK; + } + } +} + +static gboolean +gdk_wayland_keymap_map_virtual_modifiers (GdkKeymap *keymap, + GdkModifierType *state) +{ + const guint vmods[] = { + GDK_SUPER_MASK, GDK_HYPER_MASK, GDK_META_MASK + }; + int i, j; + GdkWaylandKeymap *wayland_keymap; + gboolean retval; + + wayland_keymap = GDK_WAYLAND_KEYMAP (keymap); + + for (j = 0; j < 3; j++) + { + if (*state & vmods[j]) + { + for (i = 3; i < 8; i++) + { + if (wayland_keymap->modmap[i] & vmods[j]) + { + if (*state & (1 << i)) + retval = FALSE; + else + *state |= 1 << i; + } + } + } + } + + return retval; +} + +static void +_gdk_wayland_keymap_class_init (GdkWaylandKeymapClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GdkKeymapClass *keymap_class = GDK_KEYMAP_CLASS (klass); + + object_class->finalize = gdk_wayland_keymap_finalize; + + keymap_class->get_direction = gdk_wayland_keymap_get_direction; + keymap_class->have_bidi_layouts = gdk_wayland_keymap_have_bidi_layouts; + keymap_class->get_caps_lock_state = gdk_wayland_keymap_get_caps_lock_state; + keymap_class->get_num_lock_state = gdk_wayland_keymap_get_num_lock_state; + keymap_class->get_entries_for_keyval = gdk_wayland_keymap_get_entries_for_keyval; + keymap_class->get_entries_for_keycode = gdk_wayland_keymap_get_entries_for_keycode; + keymap_class->lookup_key = gdk_wayland_keymap_lookup_key; + keymap_class->translate_keyboard_state = gdk_wayland_keymap_translate_keyboard_state; + keymap_class->add_virtual_modifiers = gdk_wayland_keymap_add_virtual_modifiers; + keymap_class->map_virtual_modifiers = gdk_wayland_keymap_map_virtual_modifiers; +} + +static void +_gdk_wayland_keymap_init (GdkWaylandKeymap *keymap) +{ +} + +static void +update_keymaps (GdkWaylandKeymap *keymap) +{ + struct xkb_desc *xkb = keymap->xkb; + gint keycode, total_syms, i, modifier; + uint32_t *entry; + guint mask; + + for (keycode = xkb->min_key_code; keycode <= xkb->max_key_code; keycode++) + { + total_syms = XkbKeyNumSyms (xkb, keycode); + + entry = XkbKeySymsPtr (xkb, keycode); + mask = 0; + for (i = 0; i < total_syms; i++) + { + switch (entry[i]) { + case GDK_KEY_Meta_L: + case GDK_KEY_Meta_R: + mask |= GDK_META_MASK; + break; + case GDK_KEY_Hyper_L: + case GDK_KEY_Hyper_R: + mask |= GDK_HYPER_MASK; + break; + case GDK_KEY_Super_L: + case GDK_KEY_Super_R: + mask |= GDK_SUPER_MASK; + break; + } + } + + modifier = g_bit_nth_lsf(xkb->map->modmap[keycode], -1); + keymap->modmap[modifier] |= mask; + } +} + +GdkKeymap * +_gdk_wayland_keymap_new (GdkDisplay *display) +{ + GdkWaylandKeymap *keymap; + struct xkb_rule_names names; + + keymap = g_object_new (_gdk_wayland_keymap_get_type(), NULL); + GDK_KEYMAP (keymap)->display = display; + + names.rules = "evdev"; + names.model = "pc105"; + names.layout = "us"; + names.variant = ""; + names.options = ""; + keymap->xkb = xkb_compile_keymap_from_rules(&names); + + update_modmap (keymap); + update_keymaps (keymap); + + return GDK_KEYMAP (keymap); +} + +struct xkb_desc *_gdk_wayland_keymap_get_xkb_desc (GdkKeymap *keymap) +{ + return GDK_WAYLAND_KEYMAP (keymap)->xkb; +} diff --git a/gdk/wayland/gdkprivate-wayland.h b/gdk/wayland/gdkprivate-wayland.h new file mode 100644 index 0000000000..e876494017 --- /dev/null +++ b/gdk/wayland/gdkprivate-wayland.h @@ -0,0 +1,153 @@ +/* GDK - The GIMP Drawing Kit + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GTK+ Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GTK+ at ftp://ftp.gtk.org/pub/gtk/. + */ + +/* + * Private uninstalled header defining things local to X windowing code + */ + +#ifndef __GDK_PRIVATE_WAYLAND_H__ +#define __GDK_PRIVATE_WAYLAND_H__ + +#include <gdk/gdkcursor.h> +#include <gdk/gdkprivate.h> +#include <gdk/wayland/gdkdisplay-wayland.h> + +#include "gdkinternals.h" + +#include "config.h" + +#define GDK_SCREEN_DISPLAY(screen) (GDK_SCREEN_WAYLAND (screen)->display) +#define GDK_WINDOW_SCREEN(win) (gdk_window_get_screen (win)) +#define GDK_WINDOW_DISPLAY(win) (GDK_SCREEN_WAYLAND (GDK_WINDOW_SCREEN (win))->display) +#define GDK_WINDOW_IS_WAYLAND(win) (GDK_IS_WINDOW_IMPL_WAYLAND (((GdkWindow *)win)->impl)) + +GType _gdk_wayland_window_get_type (void); +void _gdk_wayland_window_update_size (GdkWindow *window, + int32_t width, + int32_t height, + uint32_t edges); + +GdkKeymap *_gdk_wayland_keymap_new (GdkDisplay *display); +struct xkb_desc *_gdk_wayland_keymap_get_xkb_desc (GdkKeymap *keymap); + +GdkCursor *_gdk_wayland_display_get_cursor_for_type (GdkDisplay *display, + GdkCursorType cursor_type); +GdkCursor *_gdk_wayland_display_get_cursor_for_name (GdkDisplay *display, + const gchar *name); +GdkCursor *_gdk_wayland_display_get_cursor_for_pixbuf (GdkDisplay *display, + GdkPixbuf *pixbuf, + gint x, + gint y); +void _gdk_wayland_display_get_default_cursor_size (GdkDisplay *display, + guint *width, + guint *height); +void _gdk_wayland_display_get_maximal_cursor_size (GdkDisplay *display, + guint *width, + guint *height); +gboolean _gdk_wayland_display_supports_cursor_alpha (GdkDisplay *display); +gboolean _gdk_wayland_display_supports_cursor_color (GdkDisplay *display); + +struct wl_buffer *_gdk_wayland_cursor_get_buffer (GdkCursor *cursor, + int *x, + int *y); + +GdkDragProtocol _gdk_wayland_window_get_drag_protocol (GdkWindow *window, + GdkWindow **target); + +void _gdk_wayland_window_register_dnd (GdkWindow *window); +GdkDragContext *_gdk_wayland_window_drag_begin (GdkWindow *window, + GdkDevice *device, + GList *targets); + +void _gdk_wayland_display_create_window_impl (GdkDisplay *display, + GdkWindow *window, + GdkWindow *real_parent, + GdkScreen *screen, + GdkEventMask event_mask, + GdkWindowAttr *attributes, + gint attributes_mask); + +GdkKeymap *_gdk_wayland_display_get_keymap (GdkDisplay *display); + +GdkWindow *_gdk_wayland_display_get_selection_owner (GdkDisplay *display, + GdkAtom selection); +gboolean _gdk_wayland_display_set_selection_owner (GdkDisplay *display, + GdkWindow *owner, + GdkAtom selection, + guint32 time, + gboolean send_event); +void _gdk_wayland_display_send_selection_notify (GdkDisplay *dispay, + GdkWindow *requestor, + GdkAtom selection, + GdkAtom target, + GdkAtom property, + guint32 time); +gint _gdk_wayland_display_get_selection_property (GdkDisplay *display, + GdkWindow *requestor, + guchar **data, + GdkAtom *ret_type, + gint *ret_format); +void _gdk_wayland_display_convert_selection (GdkDisplay *display, + GdkWindow *requestor, + GdkAtom selection, + GdkAtom target, + guint32 time); +gint _gdk_wayland_display_text_property_to_utf8_list (GdkDisplay *display, + GdkAtom encoding, + gint format, + const guchar *text, + gint length, + gchar ***list); +gchar * _gdk_wayland_display_utf8_to_string_target (GdkDisplay *display, + const gchar *str); + +GdkDeviceManager *_gdk_wayland_device_manager_new (GdkDisplay *display); +void _gdk_wayland_device_manager_add_device (GdkDeviceManager *device_manager, + struct wl_input_device *device); +struct wl_input_device *_gdk_wayland_device_get_device (GdkDevice *device); + +void _gdk_wayland_display_deliver_event (GdkDisplay *display, GdkEvent *event); +GSource *_gdk_wayland_display_event_source_new (GdkDisplay *display); +void _gdk_wayland_display_queue_events (GdkDisplay *display); +void _gdk_wayland_display_flush (GdkDisplay *display, GSource *source); + +GdkAppLaunchContext *_gdk_wayland_display_get_app_launch_context (GdkDisplay *display); + +GdkDisplay *_gdk_wayland_display_open (const gchar *display_name); +void _gdk_wayland_display_make_default (GdkDisplay *display); + +GdkWindow *_gdk_wayland_screen_create_root_window (GdkScreen *screen, + int width, + int height); + +GdkScreen *_gdk_wayland_screen_new (GdkDisplay *display); + +void _gdk_wayland_display_manager_add_display (GdkDisplayManager *manager, + GdkDisplay *display); +void _gdk_wayland_display_manager_remove_display (GdkDisplayManager *manager, + GdkDisplay *display); + +#endif /* __GDK_PRIVATE_WAYLAND_H__ */ diff --git a/gdk/wayland/gdkscreen-wayland.c b/gdk/wayland/gdkscreen-wayland.c new file mode 100644 index 0000000000..b1cb479179 --- /dev/null +++ b/gdk/wayland/gdkscreen-wayland.c @@ -0,0 +1,550 @@ +/* + * Copyright © 2010 Intel Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include <stdlib.h> +#include <string.h> + +#include <glib.h> +#include "gdkscreenprivate.h" +#include "gdkvisualprivate.h" +#include "gdkdisplay.h" +#include "gdkdisplay-wayland.h" +#include "gdkwayland.h" +#include "gdkprivate-wayland.h" + +typedef struct _GdkScreenWayland GdkScreenWayland; +typedef struct _GdkScreenWaylandClass GdkScreenWaylandClass; + +#define GDK_TYPE_SCREEN_WAYLAND (_gdk_screen_wayland_get_type ()) +#define GDK_SCREEN_WAYLAND(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_SCREEN_WAYLAND, GdkScreenWayland)) +#define GDK_SCREEN_WAYLAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_SCREEN_WAYLAND, GdkScreenWaylandClass)) +#define GDK_IS_SCREEN_WAYLAND(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_SCREEN_WAYLAND)) +#define GDK_IS_SCREEN_WAYLAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_SCREEN_WAYLAND)) +#define GDK_SCREEN_WAYLAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_SCREEN_WAYLAND, GdkScreenWaylandClass)) + +typedef struct _GdkWaylandMonitor GdkWaylandMonitor; + +struct _GdkScreenWayland +{ + GdkScreen parent_instance; + + GdkDisplay *display; + GdkWindow *root_window; + + int width, height; + int width_mm, height_mm; + + /* Visual Part */ + GdkVisual *argb_visual; + GdkVisual *premultiplied_argb_visual; + GdkVisual *rgb_visual; + + /* Xinerama/RandR 1.2 */ + gint n_monitors; + GdkWaylandMonitor *monitors; + gint primary_monitor; +}; + +struct _GdkScreenWaylandClass +{ + GdkScreenClass parent_class; + + void (* window_manager_changed) (GdkScreenWayland *screen_wayland); +}; + +struct _GdkWaylandMonitor +{ + GdkRectangle geometry; + int width_mm; + int height_mm; + char * output_name; + char * manufacturer; +}; + +G_DEFINE_TYPE (GdkScreenWayland, _gdk_screen_wayland, GDK_TYPE_SCREEN) + +static void +init_monitor_geometry (GdkWaylandMonitor *monitor, + int x, int y, int width, int height) +{ + monitor->geometry.x = x; + monitor->geometry.y = y; + monitor->geometry.width = width; + monitor->geometry.height = height; + + monitor->width_mm = -1; + monitor->height_mm = -1; + monitor->output_name = NULL; + monitor->manufacturer = NULL; +} + +static void +free_monitors (GdkWaylandMonitor *monitors, + gint n_monitors) +{ + int i; + + for (i = 0; i < n_monitors; ++i) + { + g_free (monitors[i].output_name); + g_free (monitors[i].manufacturer); + } + + g_free (monitors); +} + +static void +deinit_multihead (GdkScreen *screen) +{ + GdkScreenWayland *screen_wayland = GDK_SCREEN_WAYLAND (screen); + + free_monitors (screen_wayland->monitors, screen_wayland->n_monitors); + + screen_wayland->n_monitors = 0; + screen_wayland->monitors = NULL; +} + +static void +init_multihead (GdkScreen *screen) +{ + GdkScreenWayland *screen_wayland = GDK_SCREEN_WAYLAND (screen); + + /* No multihead support of any kind for this screen */ + screen_wayland->n_monitors = 1; + screen_wayland->monitors = g_new0 (GdkWaylandMonitor, 1); + screen_wayland->primary_monitor = 0; + + init_monitor_geometry (screen_wayland->monitors, 0, 0, + screen_wayland->width, screen_wayland->height); +} + +static void +gdk_wayland_screen_dispose (GObject *object) +{ + GdkScreenWayland *screen_wayland = GDK_SCREEN_WAYLAND (object); + + if (screen_wayland->root_window) + _gdk_window_destroy (screen_wayland->root_window, TRUE); + + G_OBJECT_CLASS (_gdk_screen_wayland_parent_class)->dispose (object); +} + +static void +gdk_wayland_screen_finalize (GObject *object) +{ + GdkScreenWayland *screen_wayland = GDK_SCREEN_WAYLAND (object); + + if (screen_wayland->root_window) + g_object_unref (screen_wayland->root_window); + + /* Visual Part */ + g_object_unref (screen_wayland->argb_visual); + g_object_unref (screen_wayland->premultiplied_argb_visual); + g_object_unref (screen_wayland->rgb_visual); + + deinit_multihead (GDK_SCREEN (object)); + + G_OBJECT_CLASS (_gdk_screen_wayland_parent_class)->finalize (object); +} + +static GdkDisplay * +gdk_wayland_screen_get_display (GdkScreen *screen) +{ + g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL); + + return GDK_SCREEN_WAYLAND (screen)->display; +} + +static gint +gdk_wayland_screen_get_width (GdkScreen *screen) +{ + g_return_val_if_fail (GDK_IS_SCREEN (screen), 0); + + return GDK_SCREEN_WAYLAND (screen)->width; +} + +static gint +gdk_wayland_screen_get_height (GdkScreen *screen) +{ + g_return_val_if_fail (GDK_IS_SCREEN (screen), 0); + + return GDK_SCREEN_WAYLAND (screen)->height; +} + +static gint +gdk_wayland_screen_get_width_mm (GdkScreen *screen) +{ + g_return_val_if_fail (GDK_IS_SCREEN (screen), 0); + + return GDK_SCREEN_WAYLAND (screen)->width_mm; +} + +static gint +gdk_wayland_screen_get_height_mm (GdkScreen *screen) +{ + g_return_val_if_fail (GDK_IS_SCREEN (screen), 0); + + return GDK_SCREEN_WAYLAND (screen)->height_mm; +} + +static gint +gdk_wayland_screen_get_number (GdkScreen *screen) +{ + g_return_val_if_fail (GDK_IS_SCREEN (screen), 0); + + return 0; +} + +static GdkWindow * +gdk_wayland_screen_get_root_window (GdkScreen *screen) +{ + g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL); + + return GDK_SCREEN_WAYLAND (screen)->root_window; +} + +static gint +gdk_wayland_screen_get_n_monitors (GdkScreen *screen) +{ + g_return_val_if_fail (GDK_IS_SCREEN (screen), 0); + + return GDK_SCREEN_WAYLAND (screen)->n_monitors; +} + +static gint +gdk_wayland_screen_get_primary_monitor (GdkScreen *screen) +{ + g_return_val_if_fail (GDK_IS_SCREEN (screen), 0); + + return GDK_SCREEN_WAYLAND (screen)->primary_monitor; +} + +static gint +gdk_wayland_screen_get_monitor_width_mm (GdkScreen *screen, + gint monitor_num) +{ + GdkScreenWayland *screen_wayland = GDK_SCREEN_WAYLAND (screen); + + g_return_val_if_fail (GDK_IS_SCREEN (screen), -1); + g_return_val_if_fail (monitor_num >= 0, -1); + g_return_val_if_fail (monitor_num < screen_wayland->n_monitors, -1); + + return screen_wayland->monitors[monitor_num].width_mm; +} + +static gint +gdk_wayland_screen_get_monitor_height_mm (GdkScreen *screen, + gint monitor_num) +{ + GdkScreenWayland *screen_wayland = GDK_SCREEN_WAYLAND (screen); + + g_return_val_if_fail (GDK_IS_SCREEN (screen), -1); + g_return_val_if_fail (monitor_num >= 0, -1); + g_return_val_if_fail (monitor_num < screen_wayland->n_monitors, -1); + + return screen_wayland->monitors[monitor_num].height_mm; +} + +static gchar * +gdk_wayland_screen_get_monitor_plug_name (GdkScreen *screen, + gint monitor_num) +{ + GdkScreenWayland *screen_wayland = GDK_SCREEN_WAYLAND (screen); + + g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL); + g_return_val_if_fail (monitor_num >= 0, NULL); + g_return_val_if_fail (monitor_num < screen_wayland->n_monitors, NULL); + + return g_strdup (screen_wayland->monitors[monitor_num].output_name); +} + +static void +gdk_wayland_screen_get_monitor_geometry (GdkScreen *screen, + gint monitor_num, + GdkRectangle *dest) +{ + GdkScreenWayland *screen_wayland = GDK_SCREEN_WAYLAND (screen); + + g_return_if_fail (GDK_IS_SCREEN (screen)); + g_return_if_fail (monitor_num >= 0); + g_return_if_fail (monitor_num < screen_wayland->n_monitors); + + if (dest) + *dest = screen_wayland->monitors[monitor_num].geometry; +} + +static GdkVisual * +gdk_wayland_screen_get_system_visual (GdkScreen * screen) +{ + return (GdkVisual *) GDK_SCREEN_WAYLAND (screen)->argb_visual; +} + +static GdkVisual * +gdk_wayland_screen_get_rgba_visual (GdkScreen *screen) +{ + return (GdkVisual *) GDK_SCREEN_WAYLAND (screen)->argb_visual; +} + +static gboolean +gdk_wayland_screen_is_composited (GdkScreen *screen) +{ + return TRUE; +} + +static gchar * +gdk_wayland_screen_make_display_name (GdkScreen *screen) +{ + return NULL; +} + +static GdkWindow * +gdk_wayland_screen_get_active_window (GdkScreen *screen) +{ + g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL); + + return NULL; +} + +static GList * +gdk_wayland_screen_get_window_stack (GdkScreen *screen) +{ + return NULL; +} + +static void +gdk_wayland_screen_broadcast_client_message (GdkScreen *screen, + GdkEvent *event) +{ +} + +static gboolean +gdk_wayland_screen_get_setting (GdkScreen *screen, + const gchar *name, + GValue *value) +{ + return FALSE; +} + +typedef struct _GdkWaylandVisual GdkWaylandVisual; +typedef struct _GdkWaylandVisualClass GdkWaylandVisualClass; + +struct _GdkWaylandVisual +{ + GdkVisual visual; + struct wl_visual *wl_visual; +}; + +struct _GdkWaylandVisualClass +{ + GdkVisualClass parent_class; +}; + +G_DEFINE_TYPE (GdkWaylandVisual, _gdk_wayland_visual, GDK_TYPE_VISUAL) + +static void +_gdk_wayland_visual_class_init (GdkWaylandVisualClass *klass) +{ +} + +static void +_gdk_wayland_visual_init (GdkWaylandVisual *visual) +{ +} + +static gint +gdk_wayland_screen_visual_get_best_depth (GdkScreen *screen) +{ + return 32; +} + +static GdkVisualType +gdk_wayland_screen_visual_get_best_type (GdkScreen *screen) +{ + return GDK_VISUAL_TRUE_COLOR; +} + +static GdkVisual* +gdk_wayland_screen_visual_get_best (GdkScreen *screen) +{ + return GDK_SCREEN_WAYLAND (screen)->argb_visual; +} + +static GdkVisual* +gdk_wayland_screen_visual_get_best_with_depth (GdkScreen *screen, + gint depth) +{ + return GDK_SCREEN_WAYLAND (screen)->argb_visual; +} + +static GdkVisual* +gdk_wayland_screen_visual_get_best_with_type (GdkScreen *screen, + GdkVisualType visual_type) +{ + return GDK_SCREEN_WAYLAND (screen)->argb_visual; +} + +static GdkVisual* +gdk_wayland_screen_visual_get_best_with_both (GdkScreen *screen, + gint depth, + GdkVisualType visual_type) +{ + return GDK_SCREEN_WAYLAND (screen)->argb_visual; +} + +static void +gdk_wayland_screen_query_depths (GdkScreen *screen, + gint **depths, + gint *count) +{ + static gint static_depths[] = { 32 }; + + *count = G_N_ELEMENTS(static_depths); + *depths = static_depths; +} + +static void +gdk_wayland_screen_query_visual_types (GdkScreen *screen, + GdkVisualType **visual_types, + gint *count) +{ + static GdkVisualType static_visual_types[] = { GDK_VISUAL_TRUE_COLOR }; + + *count = G_N_ELEMENTS(static_visual_types); + *visual_types = static_visual_types; +} + +static GList * +gdk_wayland_screen_list_visuals (GdkScreen *screen) +{ + GList *list; + GdkScreenWayland *screen_wayland; + + g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL); + screen_wayland = GDK_SCREEN_WAYLAND (screen); + + list = g_list_append (NULL, screen_wayland->argb_visual); + list = g_list_append (NULL, screen_wayland->premultiplied_argb_visual); + list = g_list_append (NULL, screen_wayland->rgb_visual); + + return list; +} + +#define GDK_TYPE_WAYLAND_VISUAL (_gdk_wayland_visual_get_type ()) +#define GDK_WAYLAND_VISUAL(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_WAYLAND_VISUAL, GdkWaylandVisual)) + +static GdkVisual * +gdk_wayland_visual_new (GdkScreen *screen, struct wl_visual *wl_visual) +{ + GdkVisual *visual; + + visual = g_object_new (GDK_TYPE_WAYLAND_VISUAL, NULL); + visual->screen = GDK_SCREEN (screen); + visual->type = GDK_VISUAL_TRUE_COLOR; + visual->depth = 32; + + GDK_WAYLAND_VISUAL (visual)->wl_visual = wl_visual; + + return visual; +} + +GdkScreen * +_gdk_wayland_screen_new (GdkDisplay *display) +{ + GdkScreen *screen; + GdkScreenWayland *screen_wayland; + GdkDisplayWayland *display_wayland; + struct wl_visual *visual; + + display_wayland = GDK_DISPLAY_WAYLAND (display); + + screen = g_object_new (GDK_TYPE_SCREEN_WAYLAND, NULL); + + screen_wayland = GDK_SCREEN_WAYLAND (screen); + screen_wayland->display = display; + screen_wayland->width = 8192; + screen_wayland->height = 8192; + + visual = wl_display_get_argb_visual(display_wayland->wl_display); + screen_wayland->argb_visual = gdk_wayland_visual_new (screen, visual); + + visual = + wl_display_get_premultiplied_argb_visual(display_wayland->wl_display); + screen_wayland->premultiplied_argb_visual = + gdk_wayland_visual_new (screen, visual); + + visual = wl_display_get_rgb_visual(display_wayland->wl_display); + screen_wayland->rgb_visual = gdk_wayland_visual_new (screen, visual); + + screen_wayland->root_window = + _gdk_wayland_screen_create_root_window (screen, + screen_wayland->width, + screen_wayland->height); + + init_multihead (screen); + + return screen; +} + +static void +_gdk_screen_wayland_class_init (GdkScreenWaylandClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GdkScreenClass *screen_class = GDK_SCREEN_CLASS (klass); + + object_class->dispose = gdk_wayland_screen_dispose; + object_class->finalize = gdk_wayland_screen_finalize; + + screen_class->get_display = gdk_wayland_screen_get_display; + screen_class->get_width = gdk_wayland_screen_get_width; + screen_class->get_height = gdk_wayland_screen_get_height; + screen_class->get_width_mm = gdk_wayland_screen_get_width_mm; + screen_class->get_height_mm = gdk_wayland_screen_get_height_mm; + screen_class->get_number = gdk_wayland_screen_get_number; + screen_class->get_root_window = gdk_wayland_screen_get_root_window; + screen_class->get_n_monitors = gdk_wayland_screen_get_n_monitors; + screen_class->get_primary_monitor = gdk_wayland_screen_get_primary_monitor; + screen_class->get_monitor_width_mm = gdk_wayland_screen_get_monitor_width_mm; + screen_class->get_monitor_height_mm = gdk_wayland_screen_get_monitor_height_mm; + screen_class->get_monitor_plug_name = gdk_wayland_screen_get_monitor_plug_name; + screen_class->get_monitor_geometry = gdk_wayland_screen_get_monitor_geometry; + screen_class->get_system_visual = gdk_wayland_screen_get_system_visual; + screen_class->get_rgba_visual = gdk_wayland_screen_get_rgba_visual; + screen_class->is_composited = gdk_wayland_screen_is_composited; + screen_class->make_display_name = gdk_wayland_screen_make_display_name; + screen_class->get_active_window = gdk_wayland_screen_get_active_window; + screen_class->get_window_stack = gdk_wayland_screen_get_window_stack; + screen_class->broadcast_client_message = gdk_wayland_screen_broadcast_client_message; + screen_class->get_setting = gdk_wayland_screen_get_setting; + screen_class->visual_get_best_depth = gdk_wayland_screen_visual_get_best_depth; + screen_class->visual_get_best_type = gdk_wayland_screen_visual_get_best_type; + screen_class->visual_get_best = gdk_wayland_screen_visual_get_best; + screen_class->visual_get_best_with_depth = gdk_wayland_screen_visual_get_best_with_depth; + screen_class->visual_get_best_with_type = gdk_wayland_screen_visual_get_best_with_type; + screen_class->visual_get_best_with_both = gdk_wayland_screen_visual_get_best_with_both; + screen_class->query_depths = gdk_wayland_screen_query_depths; + screen_class->query_visual_types = gdk_wayland_screen_query_visual_types; + screen_class->list_visuals = gdk_wayland_screen_list_visuals; +} + +static void +_gdk_screen_wayland_init (GdkScreenWayland *screen_wayland) +{ +} diff --git a/gdk/wayland/gdkselection-wayland.c b/gdk/wayland/gdkselection-wayland.c new file mode 100644 index 0000000000..6c904a17a4 --- /dev/null +++ b/gdk/wayland/gdkselection-wayland.c @@ -0,0 +1,93 @@ +/* + * Copyright © 2010 Intel Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include "gdkselection.h" +#include "gdkproperty.h" +#include "gdkprivate.h" + +#include <string.h> + +GdkWindow * +_gdk_wayland_display_get_selection_owner (GdkDisplay *display, + GdkAtom selection) +{ + return NULL; +} + +gboolean +_gdk_wayland_display_set_selection_owner (GdkDisplay *display, + GdkWindow *owner, + GdkAtom selection, + guint32 time, + gboolean send_event) +{ + fprintf(stderr, "set selection owner: atom %ld, owner %p\n", + selection, owner); + + return TRUE; +} + +void +_gdk_wayland_display_send_selection_notify (GdkDisplay *dispay, + GdkWindow *requestor, + GdkAtom selection, + GdkAtom target, + GdkAtom property, + guint32 time) +{ +} + +gint +_gdk_wayland_display_get_selection_property (GdkDisplay *display, + GdkWindow *requestor, + guchar **data, + GdkAtom *ret_type, + gint *ret_format) +{ + return 0; +} + +void +_gdk_wayland_display_convert_selection (GdkDisplay *display, + GdkWindow *requestor, + GdkAtom selection, + GdkAtom target, + guint32 time) +{ +} + +gint +_gdk_wayland_display_text_property_to_utf8_list (GdkDisplay *display, + GdkAtom encoding, + gint format, + const guchar *text, + gint length, + gchar ***list) +{ + return 0; +} + +gchar * +_gdk_wayland_display_utf8_to_string_target (GdkDisplay *display, + const gchar *str) +{ + return NULL; +} diff --git a/gdk/wayland/gdkwayland.h b/gdk/wayland/gdkwayland.h new file mode 100644 index 0000000000..c9e9f6e14d --- /dev/null +++ b/gdk/wayland/gdkwayland.h @@ -0,0 +1,38 @@ +/* GDK - The GIMP Drawing Kit + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GTK+ Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GTK+ at ftp://ftp.gtk.org/pub/gtk/. + */ + +#ifndef __GDK_WAYLAND_H__ +#define __GDK_WAYLAND_H__ + +#include <gdk/gdk.h> + +G_BEGIN_DECLS + +GType gdk_wayland_display_manager_get_type (void); + +G_END_DECLS + +#endif /* __GDK_WAYLAND_H__ */ diff --git a/gdk/wayland/gdkwindow-wayland.c b/gdk/wayland/gdkwindow-wayland.c new file mode 100644 index 0000000000..2fbcab991f --- /dev/null +++ b/gdk/wayland/gdkwindow-wayland.c @@ -0,0 +1,1408 @@ +/* + * Copyright © 2010 Intel Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include "config.h" + +#include <netinet/in.h> +#include <unistd.h> + +#include "gdk.h" +#include "gdkwayland.h" + +#include "gdkwindow.h" +#include "gdkwindowimpl.h" +#include "gdkdisplay-wayland.h" +#include "gdkprivate-wayland.h" +#include "gdkinternals.h" +#include "gdkdeviceprivate.h" + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include <wayland-egl.h> + +#define WINDOW_IS_TOPLEVEL_OR_FOREIGN(window) \ + (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \ + GDK_WINDOW_TYPE (window) != GDK_WINDOW_OFFSCREEN) + +#define WINDOW_IS_TOPLEVEL(window) \ + (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \ + GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN && \ + GDK_WINDOW_TYPE (window) != GDK_WINDOW_OFFSCREEN) + +/* Return whether time1 is considered later than time2 as far as xserver + * time is concerned. Accounts for wraparound. + */ +#define XSERVER_TIME_IS_LATER(time1, time2) \ + ( (( time1 > time2 ) && ( time1 - time2 < ((guint32)-1)/2 )) || \ + (( time1 < time2 ) && ( time2 - time1 > ((guint32)-1)/2 )) \ + ) + +typedef struct _GdkWaylandWindow GdkWaylandWindow; +typedef struct _GdkWaylandWindowClass GdkWaylandWindowClass; + +struct _GdkWaylandWindow { + GdkWindow parent; +}; + +struct _GdkWaylandWindowClass { + GdkWindowClass parent_class; +}; + +G_DEFINE_TYPE (GdkWaylandWindow, _gdk_wayland_window, GDK_TYPE_WINDOW) + +static void +_gdk_wayland_window_class_init (GdkWaylandWindowClass *wayland_window_class) +{ +} + +static void +_gdk_wayland_window_init (GdkWaylandWindow *wayland_window) +{ +} + +#define GDK_TYPE_WINDOW_IMPL_WAYLAND (_gdk_window_impl_wayland_get_type ()) +#define GDK_WINDOW_IMPL_WAYLAND(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_WINDOW_IMPL_WAYLAND, GdkWindowImplWayland)) +#define GDK_WINDOW_IMPL_WAYLAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_WINDOW_IMPL_WAYLAND, GdkWindowImplWaylandClass)) +#define GDK_IS_WINDOW_IMPL_WAYLAND(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_WINDOW_IMPL_WAYLAND)) +#define GDK_IS_WINDOW_IMPL_WAYLAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_WINDOW_IMPL_WAYLAND)) +#define GDK_WINDOW_IMPL_WAYLAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_WINDOW_IMPL_WAYLAND, GdkWindowImplWaylandClass)) + +typedef struct _GdkWindowImplWayland GdkWindowImplWayland; +typedef struct _GdkWindowImplWaylandClass GdkWindowImplWaylandClass; + +struct _GdkWindowImplWayland +{ + GdkWindowImpl parent_instance; + + GdkWindow *wrapper; + + GdkCursor *cursor; + + gint8 toplevel_window_type; + + struct wl_surface *surface; + unsigned int mapped : 1; + GdkWindow *transient_for; + + cairo_surface_t *cairo_surface; + cairo_surface_t *server_surface; + GLuint texture; + uint32_t resize_edges; + + /* Set if the window, or any descendent of it, is the server's focus window + */ + guint has_focus_window : 1; + + /* Set if window->has_focus_window and the focus isn't grabbed elsewhere. + */ + guint has_focus : 1; + + /* Set if the pointer is inside this window. (This is needed for + * for focus tracking) + */ + guint has_pointer : 1; + + /* Set if the window is a descendent of the focus window and the pointer is + * inside it. (This is the case where the window will receive keystroke + * events even window->has_focus_window is FALSE) + */ + guint has_pointer_focus : 1; + + /* Set if we are requesting these hints */ + guint skip_taskbar_hint : 1; + guint skip_pager_hint : 1; + guint urgency_hint : 1; + + guint on_all_desktops : 1; /* _NET_WM_STICKY == 0xFFFFFFFF */ + + guint have_sticky : 1; /* _NET_WM_STATE_STICKY */ + guint have_maxvert : 1; /* _NET_WM_STATE_MAXIMIZED_VERT */ + guint have_maxhorz : 1; /* _NET_WM_STATE_MAXIMIZED_HORZ */ + guint have_fullscreen : 1; /* _NET_WM_STATE_FULLSCREEN */ + + gulong map_serial; /* Serial of last transition from unmapped */ + + cairo_surface_t *icon_pixmap; + cairo_surface_t *icon_mask; + + /* Time of most recent user interaction. */ + gulong user_time; +}; + +struct _GdkWindowImplWaylandClass +{ + GdkWindowImplClass parent_class; +}; + +G_DEFINE_TYPE (GdkWindowImplWayland, _gdk_window_impl_wayland, GDK_TYPE_WINDOW_IMPL) + +static void +_gdk_window_impl_wayland_init (GdkWindowImplWayland *impl) +{ + impl->toplevel_window_type = -1; +} + +/** + * _gdk_wayland_window_update_size: + * @drawable: a #GdkDrawableImplWayland. + * + * Updates the state of the drawable (in particular the drawable's + * cairo surface) when its size has changed. + **/ +void +_gdk_wayland_window_update_size (GdkWindow *window, + int32_t width, int32_t height, uint32_t edges) +{ + GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl); + GdkRectangle area; + cairo_region_t *region; + + if (impl->cairo_surface) + { + cairo_surface_destroy (impl->cairo_surface); + impl->cairo_surface = NULL; + } + + window->width = width; + window->height = height; + impl->resize_edges = edges; + + area.x = 0; + area.y = 0; + area.width = window->width; + area.height = window->height; + + region = cairo_region_create_rectangle (&area); + _gdk_window_invalidate_for_expose (window, region); + cairo_region_destroy (region); +} + +GdkWindow * +_gdk_wayland_screen_create_root_window (GdkScreen *screen, + int width, int height) +{ + GdkWindow *window; + GdkWindowImplWayland *impl; + + window = _gdk_display_create_window (gdk_screen_get_display (screen)); + window->impl = g_object_new (GDK_TYPE_WINDOW_IMPL_WAYLAND, NULL); + window->impl_window = window; + window->visual = gdk_screen_get_system_visual (screen); + + impl = GDK_WINDOW_IMPL_WAYLAND (window->impl); + + impl->wrapper = GDK_WINDOW (window); + + window->window_type = GDK_WINDOW_ROOT; + window->depth = 32; + + window->x = 0; + window->y = 0; + window->abs_x = 0; + window->abs_y = 0; + window->width = width; + window->height = height; + window->viewable = TRUE; + + /* see init_randr_support() in gdkscreen-wayland.c */ + window->event_mask = GDK_STRUCTURE_MASK; + + return window; +} + +static const gchar * +get_default_title (void) +{ + const char *title; + + title = g_get_application_name (); + if (!title) + title = g_get_prgname (); + if (!title) + title = ""; + + return title; +} + +void +_gdk_wayland_display_create_window_impl (GdkDisplay *display, + GdkWindow *window, + GdkWindow *real_parent, + GdkScreen *screen, + GdkEventMask event_mask, + GdkWindowAttr *attributes, + gint attributes_mask) +{ + GdkWindowImplWayland *impl; + const char *title; + + impl = g_object_new (GDK_TYPE_WINDOW_IMPL_WAYLAND, NULL); + window->impl = GDK_WINDOW_IMPL (impl); + impl->wrapper = GDK_WINDOW (window); + + if (window->width > 65535 || + window->height > 65535) + { + g_warning ("Native Windows wider or taller than 65535 pixels are not supported"); + + if (window->width > 65535) + window->width = 65535; + if (window->height > 65535) + window->height = 65535; + } + + g_object_ref (window); + + switch (GDK_WINDOW_TYPE (window)) + { + case GDK_WINDOW_TOPLEVEL: + case GDK_WINDOW_TEMP: + if (attributes_mask & GDK_WA_TITLE) + title = attributes->title; + else + title = get_default_title (); + + gdk_window_set_title (window, title); + break; + + case GDK_WINDOW_CHILD: + default: + break; + } + + if (attributes_mask & GDK_WA_TYPE_HINT) + gdk_window_set_type_hint (window, attributes->type_hint); +} + +static const cairo_user_data_key_t gdk_wayland_cairo_key; + +typedef struct _GdkWaylandCairoSurfaceData { + EGLImageKHR image; + GLuint texture; + struct wl_egl_pixmap *pixmap; + struct wl_buffer *buffer; + GdkDisplayWayland *display; + int32_t width, height; +} GdkWaylandCairoSurfaceData; + +static void +gdk_wayland_window_attach_image (GdkWindow *window) +{ + GdkDisplayWayland *display = + GDK_DISPLAY_WAYLAND (gdk_window_get_display (window)); + GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl); + GdkWaylandCairoSurfaceData *data; + int32_t server_width, server_height, dx, dy; + + if (GDK_WINDOW_DESTROYED (window)) + return; + + if (impl->server_surface == impl->cairo_surface) + return; + + if (impl->server_surface) + { + data = cairo_surface_get_user_data (impl->server_surface, + &gdk_wayland_cairo_key); + server_width = data->width; + server_height = data->height; + cairo_surface_destroy (impl->server_surface); + } + else + { + server_width = 0; + server_height = 0; + } + + impl->server_surface = cairo_surface_reference (impl->cairo_surface); + data = cairo_surface_get_user_data (impl->cairo_surface, + &gdk_wayland_cairo_key); + if (!data->buffer) + data->buffer = + wl_egl_pixmap_create_buffer(display->native_display, data->pixmap); + + if (impl->resize_edges & WL_SHELL_RESIZE_LEFT) + dx = server_width - data->width; + else + dx = 0; + + if (impl->resize_edges & WL_SHELL_RESIZE_TOP) + dy = server_height - data->height; + else + dy = 0; + + wl_surface_attach (impl->surface, data->buffer, dx, dy); +} + +static void +gdk_window_impl_wayland_finalize (GObject *object) +{ + GdkWindowImplWayland *impl; + + g_return_if_fail (GDK_IS_WINDOW_IMPL_WAYLAND (object)); + + impl = GDK_WINDOW_IMPL_WAYLAND (object); + + if (impl->cursor) + gdk_cursor_unref (impl->cursor); + if (impl->server_surface) + cairo_surface_destroy (impl->server_surface); + + G_OBJECT_CLASS (_gdk_window_impl_wayland_parent_class)->finalize (object); +} + +static void +gdk_wayland_cairo_surface_destroy (void *p) +{ + GdkWaylandCairoSurfaceData *data = p; + + data->display->destroy_image (data->display->egl_display, data->image); + cairo_device_acquire(data->display->cairo_device); + glDeleteTextures(1, &data->texture); + cairo_device_release(data->display->cairo_device); + if (data->buffer) + wl_buffer_destroy(data->buffer); + g_free(data); +} + +static cairo_surface_t * +gdk_wayland_create_cairo_surface (GdkDisplayWayland *display, + int width, int height) +{ + GdkWaylandCairoSurfaceData *data; + cairo_surface_t *surface; + struct wl_visual *visual; + + data = g_new (GdkWaylandCairoSurfaceData, 1); + data->display = display; + data->buffer = NULL; + visual = wl_display_get_premultiplied_argb_visual(display->wl_display); + data->width = width; + data->height = height; + data->pixmap = + wl_egl_pixmap_create(display->native_display, width, height, visual, 0); + data->image = + display->create_image(display->egl_display, NULL, EGL_NATIVE_PIXMAP_KHR, + (EGLClientBuffer) data->pixmap, NULL); + + glGenTextures(1, &data->texture); + glBindTexture(GL_TEXTURE_2D, data->texture); + display->image_target_texture_2d(GL_TEXTURE_2D, data->image); + + surface = cairo_gl_surface_create_for_texture(display->cairo_device, + CAIRO_CONTENT_COLOR_ALPHA, + data->texture, width, height); + + cairo_surface_set_user_data (surface, &gdk_wayland_cairo_key, + data, gdk_wayland_cairo_surface_destroy); + + if (cairo_surface_status (surface) != CAIRO_STATUS_SUCCESS) + fprintf (stderr, "create gl surface failed\n"); + + return surface; +} + +static cairo_surface_t * +gdk_wayland_window_ref_cairo_surface (GdkWindow *window) +{ + GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl); + GdkDisplayWayland *display_wayland = + GDK_DISPLAY_WAYLAND (gdk_window_get_display (impl->wrapper)); + + if (GDK_WINDOW_DESTROYED (impl->wrapper)) + return NULL; + + if (!impl->cairo_surface) + { + impl->cairo_surface = + gdk_wayland_create_cairo_surface (display_wayland, + impl->wrapper->width, + impl->wrapper->height); + } + + cairo_surface_reference (impl->cairo_surface); + + return impl->cairo_surface; +} + +static void +gdk_wayland_window_set_user_time (GdkWindow *window, guint32 user_time) +{ +} + +static void +gdk_wayland_window_map (GdkWindow *window) +{ + GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl); + GdkWindowImplWayland *parent; + + if (!impl->mapped) + { + if (impl->transient_for) + { + fprintf(stderr, "parent surface: %d, %d, transient surface %d, %d\n", + impl->transient_for->x, + impl->transient_for->y, + window->x, + window->y); + + parent = GDK_WINDOW_IMPL_WAYLAND (impl->transient_for->impl); + wl_surface_map_transient (impl->surface, parent->surface, + window->x, window->y, 0); + } + else + wl_surface_map_toplevel (impl->surface); + impl->mapped = TRUE; + } +} + +static void +gdk_wayland_window_show (GdkWindow *window, gboolean already_mapped) +{ + GdkDisplay *display; + GdkDisplayWayland *display_wayland; + GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl); + GdkEvent *event; + + display = gdk_window_get_display (window); + display_wayland = GDK_DISPLAY_WAYLAND (display); + + if (impl->user_time != 0 && + display_wayland->user_time != 0 && + XSERVER_TIME_IS_LATER (display_wayland->user_time, impl->user_time)) + gdk_wayland_window_set_user_time (window, impl->user_time); + + impl->surface = wl_compositor_create_surface(display_wayland->compositor); + wl_surface_set_user_data(impl->surface, window); + + _gdk_make_event (window, GDK_MAP, NULL, FALSE); + event = _gdk_make_event (window, GDK_VISIBILITY_NOTIFY, NULL, FALSE); + event->visibility.state = GDK_VISIBILITY_UNOBSCURED; + + if (impl->cairo_surface) + gdk_wayland_window_attach_image (window); +} + +static void +gdk_wayland_window_hide (GdkWindow *window) +{ + GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl); + + if (impl->surface) + { + wl_surface_destroy(impl->surface); + impl->surface = NULL; + cairo_surface_destroy(impl->server_surface); + impl->server_surface = NULL; + impl->mapped = FALSE; + } + + _gdk_window_clear_update_area (window); +} + +static void +gdk_window_wayland_withdraw (GdkWindow *window) +{ + GdkWindowImplWayland *impl; + + if (!window->destroyed) + { + if (GDK_WINDOW_IS_MAPPED (window)) + gdk_synthesize_window_state (window, 0, GDK_WINDOW_STATE_WITHDRAWN); + + g_assert (!GDK_WINDOW_IS_MAPPED (window)); + + impl = GDK_WINDOW_IMPL_WAYLAND (window->impl); + if (impl->surface) + { + wl_surface_destroy(impl->surface); + impl->surface = NULL; + cairo_surface_destroy(impl->server_surface); + impl->server_surface = NULL; + impl->mapped = FALSE; + } + } +} + +static void +gdk_window_wayland_set_events (GdkWindow *window, + GdkEventMask event_mask) +{ + GDK_WINDOW (window)->event_mask = event_mask; +} + +static GdkEventMask +gdk_window_wayland_get_events (GdkWindow *window) +{ + if (GDK_WINDOW_DESTROYED (window)) + return 0; + else + return GDK_WINDOW (window)->event_mask; +} + +static void +gdk_window_wayland_raise (GdkWindow *window) +{ + /* FIXME: wl_shell_raise() */ +} + +static void +gdk_window_wayland_lower (GdkWindow *window) +{ + /* FIXME: wl_shell_lower() */ +} + +static void +gdk_window_wayland_restack_under (GdkWindow *window, + GList *native_siblings) +{ +} + +static void +gdk_window_wayland_restack_toplevel (GdkWindow *window, + GdkWindow *sibling, + gboolean above) +{ +} + +static void +gdk_window_wayland_move_resize (GdkWindow *window, + gboolean with_move, + gint x, + gint y, + gint width, + gint height) +{ + window->x = x; + window->y = y; + + _gdk_wayland_window_update_size (window, width, height, 0); +} + +static void +gdk_window_wayland_set_background (GdkWindow *window, + cairo_pattern_t *pattern) +{ +} + +static gboolean +gdk_window_wayland_reparent (GdkWindow *window, + GdkWindow *new_parent, + gint x, + gint y) +{ + return FALSE; +} + +static void +gdk_window_wayland_set_device_cursor (GdkWindow *window, + GdkDevice *device, + GdkCursor *cursor) +{ + g_return_if_fail (GDK_IS_WINDOW (window)); + g_return_if_fail (GDK_IS_DEVICE (device)); + + if (!GDK_WINDOW_DESTROYED (window)) + GDK_DEVICE_GET_CLASS (device)->set_window_cursor (device, window, cursor); +} + +static void +gdk_window_wayland_get_geometry (GdkWindow *window, + gint *x, + gint *y, + gint *width, + gint *height) +{ + if (!GDK_WINDOW_DESTROYED (window)) + { + if (x) + *x = window->x; + if (y) + *y = window->y; + if (width) + *width = window->width; + if (height) + *height = window->height; + } +} + +static gint +gdk_window_wayland_get_root_coords (GdkWindow *window, + gint x, + gint y, + gint *root_x, + gint *root_y) +{ + /* We can't do this. */ + if (root_x) + *root_x = 0; + if (root_y) + *root_y = 0; + + return 1; +} + +static gboolean +gdk_window_wayland_get_device_state (GdkWindow *window, + GdkDevice *device, + gint *x, + gint *y, + GdkModifierType *mask) +{ + gboolean return_val; + + g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), FALSE); + + return_val = TRUE; + + if (!GDK_WINDOW_DESTROYED (window)) + { + GdkWindow *child; + + GDK_DEVICE_GET_CLASS (device)->query_state (device, window, + NULL, &child, + NULL, NULL, + x, y, mask); + return_val = (child != NULL); + } + + return return_val; +} + +static void +gdk_window_wayland_shape_combine_region (GdkWindow *window, + const cairo_region_t *shape_region, + gint offset_x, + gint offset_y) +{ +} + +static void +gdk_window_wayland_input_shape_combine_region (GdkWindow *window, + const cairo_region_t *shape_region, + gint offset_x, + gint offset_y) +{ +} + +static gboolean +gdk_window_wayland_set_static_gravities (GdkWindow *window, + gboolean use_static) +{ + return TRUE; +} + +static gboolean +gdk_wayland_window_queue_antiexpose (GdkWindow *window, + cairo_region_t *area) +{ + return FALSE; +} + +static void +gdk_wayland_window_translate (GdkWindow *window, + cairo_region_t *area, + gint dx, + gint dy) +{ + cairo_surface_t *surface; + cairo_t *cr; + + surface = gdk_wayland_window_ref_cairo_surface (window->impl_window); + cr = cairo_create (surface); + cairo_surface_destroy (surface); + + gdk_cairo_region (cr, area); + cairo_clip (cr); + cairo_set_source_surface (cr, cairo_get_target (cr), dx, dy); + cairo_push_group (cr); + cairo_paint (cr); + cairo_pop_group_to_source (cr); + cairo_paint (cr); + cairo_destroy (cr); +} + +static void +gdk_wayland_window_destroy (GdkWindow *window, + gboolean recursing, + gboolean foreign_destroy) +{ + GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl); + + g_return_if_fail (GDK_IS_WINDOW (window)); + + if (impl->cairo_surface) + { + cairo_surface_finish (impl->cairo_surface); + cairo_surface_set_user_data (impl->cairo_surface, &gdk_wayland_cairo_key, + NULL, NULL); + } + + if (impl->texture) + glDeleteTextures(1, &impl->texture); + + if (!recursing && !foreign_destroy) + { + if (GDK_WINDOW_IMPL_WAYLAND (window->impl)->surface) + wl_surface_destroy(GDK_WINDOW_IMPL_WAYLAND (window->impl)->surface); + } +} + +static void +gdk_window_wayland_destroy_foreign (GdkWindow *window) +{ +} + +static cairo_surface_t * +gdk_window_wayland_resize_cairo_surface (GdkWindow *window, + cairo_surface_t *surface, + gint width, + gint height) +{ + return surface; +} + +static cairo_region_t * +gdk_wayland_window_get_shape (GdkWindow *window) +{ + return NULL; +} + +static cairo_region_t * +gdk_wayland_window_get_input_shape (GdkWindow *window) +{ + return NULL; +} + +static void +gdk_wayland_window_focus (GdkWindow *window, + guint32 timestamp) +{ + /* FIXME: wl_shell_focus() */ +} + +static void +gdk_wayland_window_set_type_hint (GdkWindow *window, + GdkWindowTypeHint hint) +{ + if (GDK_WINDOW_DESTROYED (window)) + return; + + switch (hint) + { + case GDK_WINDOW_TYPE_HINT_DIALOG: + case GDK_WINDOW_TYPE_HINT_MENU: + case GDK_WINDOW_TYPE_HINT_TOOLBAR: + case GDK_WINDOW_TYPE_HINT_UTILITY: + case GDK_WINDOW_TYPE_HINT_SPLASHSCREEN: + case GDK_WINDOW_TYPE_HINT_DOCK: + case GDK_WINDOW_TYPE_HINT_DESKTOP: + case GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU: + case GDK_WINDOW_TYPE_HINT_POPUP_MENU: + case GDK_WINDOW_TYPE_HINT_TOOLTIP: + case GDK_WINDOW_TYPE_HINT_NOTIFICATION: + case GDK_WINDOW_TYPE_HINT_COMBO: + case GDK_WINDOW_TYPE_HINT_DND: + break; + default: + g_warning ("Unknown hint %d passed to gdk_window_set_type_hint", hint); + /* Fall thru */ + case GDK_WINDOW_TYPE_HINT_NORMAL: + break; + } +} + +static GdkWindowTypeHint +gdk_wayland_window_get_type_hint (GdkWindow *window) +{ + return GDK_WINDOW_TYPE_HINT_NORMAL; +} + +void +gdk_wayland_window_set_modal_hint (GdkWindow *window, + gboolean modal) +{ +} + +static void +gdk_wayland_window_set_skip_taskbar_hint (GdkWindow *window, + gboolean skips_taskbar) +{ +} + +static void +gdk_wayland_window_set_skip_pager_hint (GdkWindow *window, + gboolean skips_pager) +{ +} + +static void +gdk_wayland_window_set_urgency_hint (GdkWindow *window, + gboolean urgent) +{ +} + +static void +gdk_wayland_window_set_geometry_hints (GdkWindow *window, + const GdkGeometry *geometry, + GdkWindowHints geom_mask) +{ + if (GDK_WINDOW_DESTROYED (window) || + !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window)) + return; + + /* + * GDK_HINT_POS + * GDK_HINT_USER_POS + * GDK_HINT_USER_SIZE + * GDK_HINT_MIN_SIZE + * GDK_HINT_MAX_SIZE + * GDK_HINT_BASE_SIZE + * GDK_HINT_RESIZE_INC + * GDK_HINT_ASPECT + * GDK_HINT_WIN_GRAVITY + */ +} + +static void +gdk_wayland_window_set_title (GdkWindow *window, + const gchar *title) +{ + g_return_if_fail (title != NULL); + + if (GDK_WINDOW_DESTROYED (window)) + return; +} + +static void +gdk_wayland_window_set_role (GdkWindow *window, + const gchar *role) +{ +} + +static void +gdk_wayland_window_set_startup_id (GdkWindow *window, + const gchar *startup_id) +{ +} + +static void +gdk_wayland_window_set_transient_for (GdkWindow *window, + GdkWindow *parent) +{ + GdkWindowImplWayland *impl; + + impl = GDK_WINDOW_IMPL_WAYLAND (window->impl); + impl->transient_for = parent; +} + +static void +gdk_wayland_window_get_root_origin (GdkWindow *window, + gint *x, + gint *y) +{ + if (x) + *x = 0; + + if (y) + *y = 0; +} + +static void +gdk_wayland_window_get_frame_extents (GdkWindow *window, + GdkRectangle *rect) +{ + rect->x = window->x; + rect->y = window->y; + rect->width = window->width; + rect->height = window->height; +} + +static void +gdk_wayland_window_set_override_redirect (GdkWindow *window, + gboolean override_redirect) +{ +} + +static void +gdk_wayland_window_set_accept_focus (GdkWindow *window, + gboolean accept_focus) +{ +} + +static void +gdk_wayland_window_set_focus_on_map (GdkWindow *window, + gboolean focus_on_map) +{ + focus_on_map = focus_on_map != FALSE; + + if (window->focus_on_map != focus_on_map) + { + window->focus_on_map = focus_on_map; + + if ((!GDK_WINDOW_DESTROYED (window)) && + (!window->focus_on_map) && + WINDOW_IS_TOPLEVEL_OR_FOREIGN (window)) + gdk_wayland_window_set_user_time (window, 0); + } +} + +static void +gdk_wayland_window_set_icon_list (GdkWindow *window, + GList *pixbufs) +{ +} + +static void +gdk_wayland_window_set_icon_name (GdkWindow *window, + const gchar *name) +{ + if (GDK_WINDOW_DESTROYED (window)) + return; +} + +static void +gdk_wayland_window_iconify (GdkWindow *window) +{ +} + +static void +gdk_wayland_window_deiconify (GdkWindow *window) +{ + if (GDK_WINDOW_DESTROYED (window) || + !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window)) + return; + + if (GDK_WINDOW_IS_MAPPED (window)) + { + gdk_window_show (window); + } + else + { + /* Flip our client side flag, the real work happens on map. */ + gdk_synthesize_window_state (window, GDK_WINDOW_STATE_ICONIFIED, 0); + } +} + +static void +gdk_wayland_window_stick (GdkWindow *window) +{ + if (GDK_WINDOW_DESTROYED (window)) + return; +} + +static void +gdk_wayland_window_unstick (GdkWindow *window) +{ + if (GDK_WINDOW_DESTROYED (window)) + return; +} + +static void +gdk_wayland_window_maximize (GdkWindow *window) +{ + if (GDK_WINDOW_DESTROYED (window)) + return; +} + +static void +gdk_wayland_window_unmaximize (GdkWindow *window) +{ + if (GDK_WINDOW_DESTROYED (window)) + return; +} + +static void +gdk_wayland_window_fullscreen (GdkWindow *window) +{ + if (GDK_WINDOW_DESTROYED (window)) + return; +} + +static void +gdk_wayland_window_unfullscreen (GdkWindow *window) +{ + if (GDK_WINDOW_DESTROYED (window)) + return; +} + +static void +gdk_wayland_window_set_keep_above (GdkWindow *window, + gboolean setting) +{ + g_return_if_fail (GDK_IS_WINDOW (window)); + + if (GDK_WINDOW_DESTROYED (window)) + return; +} + +static void +gdk_wayland_window_set_keep_below (GdkWindow *window, gboolean setting) +{ + g_return_if_fail (GDK_IS_WINDOW (window)); + + if (GDK_WINDOW_DESTROYED (window)) + return; +} + +static GdkWindow * +gdk_wayland_window_get_group (GdkWindow *window) +{ + if (GDK_WINDOW_DESTROYED (window) || + !WINDOW_IS_TOPLEVEL (window)) + return NULL; + + return NULL; +} + +static void +gdk_wayland_window_set_group (GdkWindow *window, + GdkWindow *leader) +{ + g_return_if_fail (GDK_IS_WINDOW (window)); + g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD); + g_return_if_fail (leader == NULL || GDK_IS_WINDOW (leader)); +} + +static void +gdk_wayland_window_set_decorations (GdkWindow *window, + GdkWMDecoration decorations) +{ +} + +static gboolean +gdk_wayland_window_get_decorations (GdkWindow *window, + GdkWMDecoration *decorations) +{ + return FALSE; +} + +static void +gdk_wayland_window_set_functions (GdkWindow *window, + GdkWMFunction functions) +{ +} + +static void +gdk_wayland_window_begin_resize_drag (GdkWindow *window, + GdkWindowEdge edge, + gint button, + gint root_x, + gint root_y, + guint32 timestamp) +{ + GdkDisplay *display = gdk_window_get_display (window); + GdkDeviceManager *dm; + GdkWindowImplWayland *impl; + GdkDevice *device; + uint32_t grab_type; + + if (GDK_WINDOW_DESTROYED (window) || + !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window)) + return; + + switch (edge) + { + case GDK_WINDOW_EDGE_NORTH_WEST: + grab_type = WL_SHELL_RESIZE_TOP_LEFT; + break; + + case GDK_WINDOW_EDGE_NORTH: + grab_type = WL_SHELL_RESIZE_TOP; + break; + + case GDK_WINDOW_EDGE_NORTH_EAST: + grab_type = WL_SHELL_RESIZE_RIGHT; + break; + + case GDK_WINDOW_EDGE_WEST: + grab_type = WL_SHELL_RESIZE_LEFT; + break; + + case GDK_WINDOW_EDGE_EAST: + grab_type = WL_SHELL_RESIZE_RIGHT; + break; + + case GDK_WINDOW_EDGE_SOUTH_WEST: + grab_type = WL_SHELL_RESIZE_BOTTOM_LEFT; + break; + + case GDK_WINDOW_EDGE_SOUTH: + grab_type = WL_SHELL_RESIZE_BOTTOM; + break; + + case GDK_WINDOW_EDGE_SOUTH_EAST: + grab_type = WL_SHELL_RESIZE_BOTTOM_RIGHT; + break; + + default: + g_warning ("gdk_window_begin_resize_drag: bad resize edge %d!", + edge); + return; + } + + impl = GDK_WINDOW_IMPL_WAYLAND (window->impl); + dm = gdk_display_get_device_manager (display); + device = gdk_device_manager_get_client_pointer (dm); + + wl_shell_resize(GDK_DISPLAY_WAYLAND (display)->shell, impl->surface, + _gdk_wayland_device_get_device (device), + timestamp, grab_type); +} + +static void +gdk_wayland_window_begin_move_drag (GdkWindow *window, + gint button, + gint root_x, + gint root_y, + guint32 timestamp) +{ + GdkDisplay *display = gdk_window_get_display (window); + GdkDeviceManager *dm; + GdkWindowImplWayland *impl; + GdkDevice *device; + + if (GDK_WINDOW_DESTROYED (window) || + !WINDOW_IS_TOPLEVEL (window)) + return; + + impl = GDK_WINDOW_IMPL_WAYLAND (window->impl); + + dm = gdk_display_get_device_manager (display); + device = gdk_device_manager_get_client_pointer (dm); + + wl_shell_move(GDK_DISPLAY_WAYLAND (display)->shell, impl->surface, + _gdk_wayland_device_get_device (device), timestamp); +} + +static void +gdk_wayland_window_enable_synchronized_configure (GdkWindow *window) +{ +} + +static void +gdk_wayland_window_configure_finished (GdkWindow *window) +{ + if (!WINDOW_IS_TOPLEVEL (window)) + return; + + if (!GDK_IS_WINDOW_IMPL_WAYLAND (window->impl)) + return; +} + +static void +gdk_wayland_window_set_opacity (GdkWindow *window, + gdouble opacity) +{ +} + +static void +gdk_wayland_window_set_composited (GdkWindow *window, + gboolean composited) +{ +} + +static void +gdk_wayland_window_destroy_notify (GdkWindow *window) +{ + if (!GDK_WINDOW_DESTROYED (window)) + { + if (GDK_WINDOW_TYPE(window) != GDK_WINDOW_FOREIGN) + g_warning ("GdkWindow %p unexpectedly destroyed", window); + + _gdk_window_destroy (window, TRUE); + } + + g_object_unref (window); +} + +static void +gdk_wayland_window_process_updates_recurse (GdkWindow *window, + cairo_region_t *region) +{ + GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl); + cairo_rectangle_int_t rect; + int i, n; + + if (impl->cairo_surface) + gdk_wayland_window_attach_image (window); + + gdk_wayland_window_map (window); + + n = cairo_region_num_rectangles(region); + for (i = 0; i < n; i++) + { + cairo_region_get_rectangle (region, i, &rect); + wl_surface_damage (impl->surface, + rect.x, rect.y, rect.width, rect.height); + } + + _gdk_window_process_updates_recurse (window, region); +} + +static void +gdk_wayland_window_sync_rendering (GdkWindow *window) +{ +} + +static gboolean +gdk_wayland_window_simulate_key (GdkWindow *window, + gint x, + gint y, + guint keyval, + GdkModifierType modifiers, + GdkEventType key_pressrelease) +{ + return FALSE; +} + +static gboolean +gdk_wayland_window_simulate_button (GdkWindow *window, + gint x, + gint y, + guint button, /*1..3*/ + GdkModifierType modifiers, + GdkEventType button_pressrelease) +{ + return FALSE; +} + +static gboolean +gdk_wayland_window_get_property (GdkWindow *window, + GdkAtom property, + GdkAtom type, + gulong offset, + gulong length, + gint pdelete, + GdkAtom *actual_property_type, + gint *actual_format_type, + gint *actual_length, + guchar **data) +{ + return FALSE; +} + +static void +gdk_wayland_window_change_property (GdkWindow *window, + GdkAtom property, + GdkAtom type, + gint format, + GdkPropMode mode, + const guchar *data, + gint nelements) +{ +} + +static void +gdk_wayland_window_delete_property (GdkWindow *window, + GdkAtom property) +{ +} + +static void +_gdk_window_impl_wayland_class_init (GdkWindowImplWaylandClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GdkWindowImplClass *impl_class = GDK_WINDOW_IMPL_CLASS (klass); + + object_class->finalize = gdk_window_impl_wayland_finalize; + + impl_class->ref_cairo_surface = gdk_wayland_window_ref_cairo_surface; + impl_class->show = gdk_wayland_window_show; + impl_class->hide = gdk_wayland_window_hide; + impl_class->withdraw = gdk_window_wayland_withdraw; + impl_class->set_events = gdk_window_wayland_set_events; + impl_class->get_events = gdk_window_wayland_get_events; + impl_class->raise = gdk_window_wayland_raise; + impl_class->lower = gdk_window_wayland_lower; + impl_class->restack_under = gdk_window_wayland_restack_under; + impl_class->restack_toplevel = gdk_window_wayland_restack_toplevel; + impl_class->move_resize = gdk_window_wayland_move_resize; + impl_class->set_background = gdk_window_wayland_set_background; + impl_class->reparent = gdk_window_wayland_reparent; + impl_class->set_device_cursor = gdk_window_wayland_set_device_cursor; + impl_class->get_geometry = gdk_window_wayland_get_geometry; + impl_class->get_root_coords = gdk_window_wayland_get_root_coords; + impl_class->get_device_state = gdk_window_wayland_get_device_state; + impl_class->shape_combine_region = gdk_window_wayland_shape_combine_region; + impl_class->input_shape_combine_region = gdk_window_wayland_input_shape_combine_region; + impl_class->set_static_gravities = gdk_window_wayland_set_static_gravities; + impl_class->queue_antiexpose = gdk_wayland_window_queue_antiexpose; + impl_class->translate = gdk_wayland_window_translate; + impl_class->destroy = gdk_wayland_window_destroy; + impl_class->destroy_foreign = gdk_window_wayland_destroy_foreign; + impl_class->resize_cairo_surface = gdk_window_wayland_resize_cairo_surface; + impl_class->get_shape = gdk_wayland_window_get_shape; + impl_class->get_input_shape = gdk_wayland_window_get_input_shape; + /* impl_class->beep */ + + impl_class->focus = gdk_wayland_window_focus; + impl_class->set_type_hint = gdk_wayland_window_set_type_hint; + impl_class->get_type_hint = gdk_wayland_window_get_type_hint; + impl_class->set_modal_hint = gdk_wayland_window_set_modal_hint; + impl_class->set_skip_taskbar_hint = gdk_wayland_window_set_skip_taskbar_hint; + impl_class->set_skip_pager_hint = gdk_wayland_window_set_skip_pager_hint; + impl_class->set_urgency_hint = gdk_wayland_window_set_urgency_hint; + impl_class->set_geometry_hints = gdk_wayland_window_set_geometry_hints; + impl_class->set_title = gdk_wayland_window_set_title; + impl_class->set_role = gdk_wayland_window_set_role; + impl_class->set_startup_id = gdk_wayland_window_set_startup_id; + impl_class->set_transient_for = gdk_wayland_window_set_transient_for; + impl_class->get_root_origin = gdk_wayland_window_get_root_origin; + impl_class->get_frame_extents = gdk_wayland_window_get_frame_extents; + impl_class->set_override_redirect = gdk_wayland_window_set_override_redirect; + impl_class->set_accept_focus = gdk_wayland_window_set_accept_focus; + impl_class->set_focus_on_map = gdk_wayland_window_set_focus_on_map; + impl_class->set_icon_list = gdk_wayland_window_set_icon_list; + impl_class->set_icon_name = gdk_wayland_window_set_icon_name; + impl_class->iconify = gdk_wayland_window_iconify; + impl_class->deiconify = gdk_wayland_window_deiconify; + impl_class->stick = gdk_wayland_window_stick; + impl_class->unstick = gdk_wayland_window_unstick; + impl_class->maximize = gdk_wayland_window_maximize; + impl_class->unmaximize = gdk_wayland_window_unmaximize; + impl_class->fullscreen = gdk_wayland_window_fullscreen; + impl_class->unfullscreen = gdk_wayland_window_unfullscreen; + impl_class->set_keep_above = gdk_wayland_window_set_keep_above; + impl_class->set_keep_below = gdk_wayland_window_set_keep_below; + impl_class->get_group = gdk_wayland_window_get_group; + impl_class->set_group = gdk_wayland_window_set_group; + impl_class->set_decorations = gdk_wayland_window_set_decorations; + impl_class->get_decorations = gdk_wayland_window_get_decorations; + impl_class->set_functions = gdk_wayland_window_set_functions; + impl_class->begin_resize_drag = gdk_wayland_window_begin_resize_drag; + impl_class->begin_move_drag = gdk_wayland_window_begin_move_drag; + impl_class->enable_synchronized_configure = gdk_wayland_window_enable_synchronized_configure; + impl_class->configure_finished = gdk_wayland_window_configure_finished; + impl_class->set_opacity = gdk_wayland_window_set_opacity; + impl_class->set_composited = gdk_wayland_window_set_composited; + impl_class->destroy_notify = gdk_wayland_window_destroy_notify; + impl_class->get_drag_protocol = _gdk_wayland_window_get_drag_protocol; + impl_class->register_dnd = _gdk_wayland_window_register_dnd; + impl_class->drag_begin = _gdk_wayland_window_drag_begin; + impl_class->process_updates_recurse = gdk_wayland_window_process_updates_recurse; + impl_class->sync_rendering = gdk_wayland_window_sync_rendering; + impl_class->simulate_key = gdk_wayland_window_simulate_key; + impl_class->simulate_button = gdk_wayland_window_simulate_button; + impl_class->get_property = gdk_wayland_window_get_property; + impl_class->change_property = gdk_wayland_window_change_property; + impl_class->delete_property = gdk_wayland_window_delete_property; +} |