]> Pileus Git - ~andy/gtk/commitdiff
Merge branch 'master' into broadway
authorAlexander Larsson <alexl@redhat.com>
Sat, 4 Dec 2010 21:31:15 +0000 (22:31 +0100)
committerAlexander Larsson <alexl@redhat.com>
Sat, 4 Dec 2010 21:31:15 +0000 (22:31 +0100)
39 files changed:
configure.ac
gdk/Makefile.am
gdk/broadway/Makefile.am [new file with mode: 0644]
gdk/broadway/broadway-demo.c [new file with mode: 0644]
gdk/broadway/broadway.c [new file with mode: 0644]
gdk/broadway/broadway.h [new file with mode: 0644]
gdk/broadway/broadway.js [new file with mode: 0644]
gdk/broadway/client.html [new file with mode: 0644]
gdk/broadway/gdkapplaunchcontext-broadway.c [new file with mode: 0644]
gdk/broadway/gdkcursor-broadway.c [new file with mode: 0644]
gdk/broadway/gdkdevice-broadway.c [new file with mode: 0644]
gdk/broadway/gdkdevice-broadway.h [new file with mode: 0644]
gdk/broadway/gdkdevicemanager-broadway.c [new file with mode: 0644]
gdk/broadway/gdkdevicemanager-broadway.h [new file with mode: 0644]
gdk/broadway/gdkdisplay-broadway.c [new file with mode: 0644]
gdk/broadway/gdkdisplay-broadway.h [new file with mode: 0644]
gdk/broadway/gdkdnd-broadway.c [new file with mode: 0644]
gdk/broadway/gdkdrawable-broadway.c [new file with mode: 0644]
gdk/broadway/gdkdrawable-broadway.h [new file with mode: 0644]
gdk/broadway/gdkeventsource.c [new file with mode: 0644]
gdk/broadway/gdkeventsource.h [new file with mode: 0644]
gdk/broadway/gdkglobals-broadway.c [new file with mode: 0644]
gdk/broadway/gdkim-broadway.c [new file with mode: 0644]
gdk/broadway/gdkinput.c [new file with mode: 0644]
gdk/broadway/gdkkeys-broadway.c [new file with mode: 0644]
gdk/broadway/gdkmain-broadway.c [new file with mode: 0644]
gdk/broadway/gdkprivate-broadway.h [new file with mode: 0644]
gdk/broadway/gdkproperty-broadway.c [new file with mode: 0644]
gdk/broadway/gdkscreen-broadway.c [new file with mode: 0644]
gdk/broadway/gdkscreen-broadway.h [new file with mode: 0644]
gdk/broadway/gdkselection-broadway.c [new file with mode: 0644]
gdk/broadway/gdkspawn-broadway.c [new file with mode: 0644]
gdk/broadway/gdktestutils-broadway.c [new file with mode: 0644]
gdk/broadway/gdkvisual-broadway.c [new file with mode: 0644]
gdk/broadway/gdkwindow-broadway.c [new file with mode: 0644]
gdk/broadway/gdkwindow-broadway.h [new file with mode: 0644]
gdk/broadway/toarray.pl [new file with mode: 0755]
gtk/Makefile.am
tests/testsocket_common.c

index 477aa7cda8e379e9ad85ecd7da60dac3572be566..0f5ae9e0b45063e9e5511219a8588bd9f299af12 100644 (file)
@@ -258,13 +258,13 @@ else
   gdktarget=x11
 fi
 
-AC_ARG_WITH(gdktarget, [  --with-gdktarget=[[x11/win32/quartz]] select non-default GDK target],
+AC_ARG_WITH(gdktarget, [  --with-gdktarget=[[x11/win32/quartz/broadway]] select non-default GDK target],
        gdktarget=$with_gdktarget)
 
 AC_SUBST(gdktarget)
 case $gdktarget in
-  x11|win32|quartz) ;;
-  *) AC_MSG_ERROR([Invalid target for GDK: use x11, quartz or win32.]);;
+  x11|win32|quartz|broadway) ;;
+  *) AC_MSG_ERROR([Invalid target for GDK: use x11, broadway, quartz or win32.]);;
 esac
 
 gdktargetlib=libgdk-$gdktarget-$GTK_API_VERSION.la
@@ -367,15 +367,18 @@ PKG_CHECK_MODULES(BASE_DEPENDENCIES,
 ## In addition to checking that cairo is present, we also need to
 ## check that the correct cairo backend is there. E.g. if the GDK
 ## target is win32 we need the cairo-win32 backend and so on.
-cairo_backend=$gdktarget
+cairo_backend=cairo-$gdktarget
 
 # GDK calls the xlib backend "x11," cairo calls it "xlib." Other
 # backend names are identical.
-if test "x$cairo_backend" = "xx11"; then
-   cairo_backend=xlib
+if test "x$cairo_backend" = "xcairo-x11"; then
+   cairo_backend=cairo-xlib
+fi
+if test "x$cairo_backend" = "xcairo-broadway"; then
+   cairo_backend=cairo
 fi
 PKG_CHECK_MODULES(CAIRO_BACKEND,
-  [cairo-$cairo_backend >= cairo_required_version])
+  [$cairo_backend >= cairo_required_version])
 
 if test "$os_win32" != yes; then
     # libtool option to control which symbols are exported
@@ -1163,6 +1166,10 @@ else
   AM_CONDITIONAL(USE_QUARTZ, false)
 fi
 
+if test "x$gdktarget" = "xbroadway" ; then
+  GDK_EXTRA_LIBS="$GDK_EXTRA_LIBS -lz"
+fi
+
 # Check for Pango flags
 
 if test "x$gdktarget" = "xwin32"; then
@@ -1201,10 +1208,10 @@ CFLAGS="$saved_cflags"
 LDFLAGS="$saved_ldflags"
 
 # Pull in gio-unix for GDesktopAppInfo usage, see at least gdkapplaunchcontext-x11.c
-if test "x$gdktarget" = "xx11"; then
-  GDK_PACKAGES="$PANGO_PACKAGES gio-unix-2.0 $X_PACKAGES gdk-pixbuf-2.0 cairo-$cairo_backend cairo-gobject"
+if test "x$gdktarget" = "xx11" || test "x$gdktarget" = "xbroadway" ; then
+  GDK_PACKAGES="$PANGO_PACKAGES gio-unix-2.0 $X_PACKAGES gdk-pixbuf-2.0 $cairo_backend cairo-gobject"
 else
-  GDK_PACKAGES="$PANGO_PACKAGES gio-2.0 gdk-pixbuf-2.0 cairo-$cairo_backend cairo-gobject"
+  GDK_PACKAGES="$PANGO_PACKAGES gio-2.0 gdk-pixbuf-2.0 $cairo_backend cairo-gobject"
 fi
 
 GDK_DEP_LIBS="$GDK_EXTRA_LIBS `$PKG_CONFIG --libs $GDK_PACKAGES`"
@@ -1581,6 +1588,9 @@ elif test "x$gdktarget" = "xwin32" ; then
 elif test "x$gdktarget" = "xquartz" ; then
   gdk_windowing='
 #define GDK_WINDOWING_QUARTZ'
+elif test "x$gdktarget" = "xbroadway" ; then
+  gdk_windowing='
+#define GDK_WINDOWING_BROADWAY'
 fi
 
 if test x$gdk_wchar_h = xyes; then
@@ -1650,6 +1660,7 @@ build/Makefile
 build/win32/Makefile
 build/win32/vs9/Makefile
 gdk/Makefile
+gdk/broadway/Makefile
 gdk/x11/Makefile
 gdk/win32/Makefile
 gdk/win32/rc/Makefile
index 987379bc9ced10f249210f8daa54f002b6d2e8d4..eadfc81fe5dd9bf94861c7d7801c5f4a32d02799 100644 (file)
@@ -9,7 +9,7 @@ INTROSPECTION_COMPILER_ARGS = \
    --includedir=.
 
 SUBDIRS = $(gdktarget) . tests
-DIST_SUBDIRS = win32 x11 quartz tests
+DIST_SUBDIRS = win32 x11 quartz broadway tests
 
 CLEANFILES =
 
@@ -147,6 +147,10 @@ common_sources =           \
        gdkmarshalers.c         \
        gdkmarshalers.h
 
+libgdk_broadway_3_0_la_SOURCES = $(common_sources)
+libgdk_broadway_3_0_la_LIBADD = broadway/libgdk-broadway.la $(GDK_DEP_LIBS)
+libgdk_broadway_3_0_la_LDFLAGS = $(LDADD)
+
 libgdk_x11_3_0_la_SOURCES = $(common_sources)
 libgdk_x11_3_0_la_LIBADD = x11/libgdk-x11.la $(GDK_DEP_LIBS)
 libgdk_x11_3_0_la_LDFLAGS = $(LDADD)
@@ -276,7 +280,7 @@ endif
 
 lib_LTLIBRARIES = $(gdktargetlib)
 
-EXTRA_LTLIBRARIES = libgdk-x11-3.0.la libgdk-win32-3.0.la libgdk-quartz-3.0.la
+EXTRA_LTLIBRARIES = libgdk-broadway-3.0.la libgdk-x11-3.0.la libgdk-win32-3.0.la libgdk-quartz-3.0.la
 
 MAINTAINERCLEANFILES = $(gdk_built_sources) stamp-gdkenumtypes.h
 EXTRA_DIST += $(gdk_built_sources)
diff --git a/gdk/broadway/Makefile.am b/gdk/broadway/Makefile.am
new file mode 100644 (file)
index 0000000..1d6df88
--- /dev/null
@@ -0,0 +1,78 @@
+## 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 = libbroadway.la libgdk-broadway.la
+
+libbroadway_la_SOURCES =               \
+       broadway.h                      \
+       broadway.c
+
+clienthtml.h: client.html
+       $(PERL) ./toarray.pl client.html client_html > $@
+
+broadwayjs.h: broadway.js
+       $(PERL) ./toarray.pl broadway.js broadway_js > $@
+
+# built headers that don't get installed
+broadway_built_private_headers =       \
+       clienthtml.h                    \
+       broadwayjs.h
+
+broadway_built_sources =               \
+       ${broadway_built_private_headers}
+
+libgdk_broadway_la_SOURCES =           \
+       ${broadway_built_private_headers}\
+       gdkapplaunchcontext-broadway.c \
+       gdkcursor-broadway.c    \
+       gdkdevice-broadway.h    \
+       gdkdevice-broadway.c    \
+       gdkdevicemanager-broadway.h \
+       gdkdevicemanager-broadway.c \
+       gdkdisplay-broadway.c   \
+       gdkdisplay-broadway.h   \
+       gdkdnd-broadway.c       \
+       gdkdrawable-broadway.c  \
+       gdkdrawable-broadway.h  \
+       gdkeventsource.c        \
+       gdkeventsource.h        \
+       gdkglobals-broadway.c   \
+       gdkim-broadway.c        \
+       gdkinput.c              \
+       gdkkeys-broadway.c      \
+       gdkmain-broadway.c      \
+       gdkproperty-broadway.c  \
+       gdkscreen-broadway.c    \
+       gdkscreen-broadway.h    \
+       gdkselection-broadway.c \
+       gdkspawn-broadway.c     \
+       gdktestutils-broadway.c \
+       gdkvisual-broadway.c    \
+       gdkwindow-broadway.c    \
+       gdkwindow-broadway.h    \
+       gdkprivate-broadway.h
+
+libgdk_broadway_la_LIBADD = libbroadway.la
+
+MAINTAINERCLEANFILES = $(broadway_built_sources)
+EXTRA_DIST += $(broadway_built_sources)
+
+BUILT_SOURCES = $(broadway_built_sources)
+
+noinst_PROGRAMS = broadway-demo
+broadway_demo_LDADD = -lz -lcairo libbroadway.la -lglib-2.0
+
+-include $(top_srcdir)/git.mk
diff --git a/gdk/broadway/broadway-demo.c b/gdk/broadway/broadway-demo.c
new file mode 100644 (file)
index 0000000..96c177b
--- /dev/null
@@ -0,0 +1,230 @@
+/* Build with
+   gcc -lm -lz -O2 -Wall `pkg-config --libs --cflags cairo`  -o broadway broadway.c demo.c
+*/
+
+#include "broadway.h"
+#include <math.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <cairo.h>
+
+static void
+diff_surfaces (cairo_surface_t *surface,
+              cairo_surface_t *old_surface)
+{
+  uint8_t *data, *old_data;
+  uint32_t *line, *old_line;
+  int w, h, stride, old_stride;
+  int x, y;
+
+  data = cairo_image_surface_get_data (surface);
+  old_data = cairo_image_surface_get_data (old_surface);
+
+  w = cairo_image_surface_get_width (surface);
+  h = cairo_image_surface_get_height (surface);
+
+  stride = cairo_image_surface_get_stride (surface);
+  old_stride = cairo_image_surface_get_stride (old_surface);
+
+  for (y = 0; y < h; y++)
+    {
+      line = (uint32_t *)data;
+      old_line = (uint32_t *)old_data;
+
+      for (x = 0; x < w; x++)
+       {
+         if ((*line & 0xffffff) == (*old_line & 0xffffff))
+           *old_line = 0;
+         else
+           *old_line = *line | 0xff000000;
+         line ++;
+         old_line ++;
+       }
+
+      data += stride;
+      old_data += old_stride;
+    }
+}
+
+static void
+snippet(cairo_t *cr, int i)
+{
+  if (1)
+    {
+      cairo_save(cr);
+      cairo_rotate (cr, i * 0.002);
+      /* a custom shape that could be wrapped in a function */
+      double x0      = 25.6,   /* parameters like cairo_rectangle */
+       y0      = 25.6,
+       rect_width  = 204.8,
+       rect_height = 204.8,
+       radius = 102.4;   /* and an approximate curvature radius */
+
+      double x1,y1;
+
+      x1=x0+rect_width;
+      y1=y0+rect_height;
+      if (rect_width/2<radius) {
+       if (rect_height/2<radius) {
+         cairo_move_to  (cr, x0, (y0 + y1)/2);
+         cairo_curve_to (cr, x0 ,y0, x0, y0, (x0 + x1)/2, y0);
+         cairo_curve_to (cr, x1, y0, x1, y0, x1, (y0 + y1)/2);
+         cairo_curve_to (cr, x1, y1, x1, y1, (x1 + x0)/2, y1);
+         cairo_curve_to (cr, x0, y1, x0, y1, x0, (y0 + y1)/2);
+       } else {
+         cairo_move_to  (cr, x0, y0 + radius);
+         cairo_curve_to (cr, x0 ,y0, x0, y0, (x0 + x1)/2, y0);
+         cairo_curve_to (cr, x1, y0, x1, y0, x1, y0 + radius);
+         cairo_line_to (cr, x1 , y1 - radius);
+         cairo_curve_to (cr, x1, y1, x1, y1, (x1 + x0)/2, y1);
+         cairo_curve_to (cr, x0, y1, x0, y1, x0, y1- radius);
+       }
+      } else {
+       if (rect_height/2<radius) {
+         cairo_move_to  (cr, x0, (y0 + y1)/2);
+         cairo_curve_to (cr, x0 , y0, x0 , y0, x0 + radius, y0);
+         cairo_line_to (cr, x1 - radius, y0);
+         cairo_curve_to (cr, x1, y0, x1, y0, x1, (y0 + y1)/2);
+         cairo_curve_to (cr, x1, y1, x1, y1, x1 - radius, y1);
+         cairo_line_to (cr, x0 + radius, y1);
+         cairo_curve_to (cr, x0, y1, x0, y1, x0, (y0 + y1)/2);
+       } else {
+         cairo_move_to  (cr, x0, y0 + radius);
+         cairo_curve_to (cr, x0 , y0, x0 , y0, x0 + radius, y0);
+         cairo_line_to (cr, x1 - radius, y0);
+         cairo_curve_to (cr, x1, y0, x1, y0, x1, y0 + radius);
+         cairo_line_to (cr, x1 , y1 - radius);
+         cairo_curve_to (cr, x1, y1, x1, y1, x1 - radius, y1);
+         cairo_line_to (cr, x0 + radius, y1);
+         cairo_curve_to (cr, x0, y1, x0, y1, x0, y1- radius);
+       }
+      }
+      cairo_close_path (cr);
+
+      cairo_set_source_rgb (cr, 0.5, 0.5, 1);
+      cairo_fill_preserve (cr);
+      cairo_set_source_rgba (cr, 0.5, 0, 0, 0.5);
+      cairo_set_line_width (cr, 10.0);
+      cairo_stroke (cr);
+      cairo_restore(cr);
+    }
+  if (1)
+    {
+      double xc = 128.0;
+      double yc = 128.0;
+      double radius = 100.0;
+      double angle1 = (45.0 + i * 5)  * (M_PI/180.0);  /* angles are specified */
+      double angle2 = (180.0 + i * 5) * (M_PI/180.0);  /* in radians           */
+
+      cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
+
+      cairo_set_line_width (cr, 10.0);
+      cairo_arc (cr, xc, yc, radius, angle1, angle2);
+      cairo_stroke (cr);
+
+      /* draw helping lines */
+      cairo_set_source_rgba (cr, 1, 0.2, 0.2, 0.6);
+      cairo_set_line_width (cr, 6.0);
+
+      cairo_arc (cr, xc, yc, 10.0, 0, 2*M_PI);
+      cairo_fill (cr);
+
+      cairo_arc (cr, xc, yc, radius, angle1, angle1);
+      cairo_line_to (cr, xc, yc);
+      cairo_arc (cr, xc, yc, radius, angle2, angle2);
+      cairo_line_to (cr, xc, yc);
+      cairo_stroke (cr);
+    }
+}
+
+static void
+demo2 (BroadwayOutput *output)
+{
+  cairo_t *cr;
+  cairo_surface_t *surface, *old_surface;
+  BroadwayRect rects[2];
+  double da = 0;
+  int i;
+
+  broadway_output_new_surface(output,  0, 100, 100, 800, 600);
+
+  surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+                                       800, 600);
+  old_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+                                           800, 600);
+
+  cr = cairo_create (old_surface);
+  cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
+  cairo_rectangle (cr, 0, 0, 800, 600);
+  cairo_fill (cr);
+  cairo_destroy (cr);
+
+  for (i = 0; i < 100; i++)
+    {
+      cr = cairo_create (surface);
+
+      cairo_set_source_rgb (cr, 0.8, 0.8, 0.8);
+
+      cairo_rectangle (cr, 0, 0, 800, 600);
+      cairo_fill (cr);
+
+      snippet(cr, i);
+
+      cairo_destroy (cr);
+
+      if (i == 0)
+       {
+         broadway_output_put_rgb (output, 0, 0, 0, 800, 600, 800*4,
+                                  cairo_image_surface_get_data(surface)
+                                  );
+         broadway_output_show_surface (output,  0);
+       }
+      else
+       {
+         diff_surfaces (surface,
+                        old_surface);
+         broadway_output_put_rgba (output, 0, 0, 0, 800, 600, 800*4,
+                                   cairo_image_surface_get_data(old_surface));
+       }
+      broadway_output_move_surface (output, 0, 100 + i, 100 + i);
+
+      rects[0].x = 500;
+      rects[0].y = 0;
+      rects[0].width = 100;
+      rects[0].height = 100;
+      rects[1].x = 600;
+      rects[1].y = 100;
+      rects[1].width = 100;
+      rects[1].height = 100;
+      broadway_output_copy_rectangles (output,
+                                      0,
+                                      rects, 2,
+                                      400, 0);
+
+      broadway_output_flush (output);
+
+      cr = cairo_create (old_surface);
+      cairo_set_source_surface (cr, surface, 0, 0);
+      cairo_paint (cr);
+      cairo_destroy (cr);
+
+      da += 10;
+      usleep (50 * 1000);
+  }
+
+
+  cairo_surface_destroy (surface);
+  broadway_output_destroy_surface(output,  0);
+  broadway_output_flush (output);
+}
+
+int
+main (int argc, char *argv[])
+{
+  BroadwayOutput *output;
+
+  output = broadway_output_new (STDOUT_FILENO);
+  demo2(output);
+
+  return 0;
+}
diff --git a/gdk/broadway/broadway.c b/gdk/broadway/broadway.c
new file mode 100644 (file)
index 0000000..009c481
--- /dev/null
@@ -0,0 +1,993 @@
+#include <glib.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <errno.h>
+#include <zlib.h>
+
+#include "broadway.h"
+
+/************************************************************************
+ *                Base64 functions                                      *
+ ************************************************************************/
+
+static const char base64_alphabet[] =
+       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+#if 0
+static void
+base64_uint8 (guint8 v, char *c)
+{
+  c[0] = base64_alphabet[(v >> 0) & 0x3f];
+  c[1] = base64_alphabet[(v >> 6) & 0x3];
+}
+#endif
+
+static void
+base64_uint16 (guint32 v, char *c)
+{
+  c[0] = base64_alphabet[(v >> 0) & 0x3f];
+  c[1] = base64_alphabet[(v >> 6) & 0x3f];
+  c[2] = base64_alphabet[(v >> 12) & 0xf];
+}
+
+#if 0
+static void
+base64_uint24 (guint32 v, char *c)
+{
+  c[0] = base64_alphabet[(v >> 0) & 0x3f];
+  c[1] = base64_alphabet[(v >> 6) & 0x3f];
+  c[2] = base64_alphabet[(v >> 12) & 0x3f];
+  c[3] = base64_alphabet[(v >> 18) & 0x3f];
+}
+#endif
+
+static void
+base64_uint32 (guint32 v, char *c)
+{
+  c[0] = base64_alphabet[(v >> 0) & 0x3f];
+  c[1] = base64_alphabet[(v >> 6) & 0x3f];
+  c[2] = base64_alphabet[(v >> 12) & 0x3f];
+  c[3] = base64_alphabet[(v >> 18) & 0x3f];
+  c[4] = base64_alphabet[(v >> 24) & 0x3f];
+  c[5] = base64_alphabet[(v >> 30) & 0x2];
+}
+
+/************************************************************************
+ *  conversion of raw image data to uncompressed png data: uris         *
+ ************************************************************************/
+
+/* Table of CRCs of all 8-bit messages. */
+static unsigned long crc_table[256];
+
+/* Flag: has the table been computed? Initially false. */
+static int crc_table_computed = 0;
+
+/* Make the table for a fast CRC. */
+static void
+make_crc_table(void)
+{
+  unsigned long c;
+  int n, k;
+
+  for (n = 0; n < 256; n++) {
+    c = (unsigned long) n;
+    for (k = 0; k < 8; k++) {
+      if (c & 1)
+       c = 0xedb88320L ^ (c >> 1);
+      else
+       c = c >> 1;
+    }
+    crc_table[n] = c;
+  }
+  crc_table_computed = 1;
+}
+
+static unsigned long
+update_crc(unsigned long crc, unsigned char *buf, int len)
+{
+  unsigned long c = crc;
+  int n;
+
+  if (!crc_table_computed)
+    make_crc_table();
+  for (n = 0; n < len; n++) {
+    c = crc_table[(c ^ buf[n]) & 0xff] ^ (c >> 8);
+  }
+  return c;
+}
+
+static unsigned long
+crc(unsigned char *buf, int len)
+{
+  return update_crc(0xffffffffL, buf, len) ^ 0xffffffffL;
+}
+
+#define BASE 65521 /* largest prime smaller than 65536 */
+static unsigned long
+update_adler32(unsigned long adler, unsigned char *buf, int len)
+{
+  unsigned long s1 = adler & 0xffff;
+  unsigned long s2 = (adler >> 16) & 0xffff;
+  int n;
+
+  for (n = 0; n < len; n++) {
+    s1 = (s1 + buf[n]) % BASE;
+    s2 = (s2 + s1)     % BASE;
+  }
+  return (s2 << 16) + s1;
+}
+
+static char *
+to_png_rgb (int w, int h, int byte_stride, guint32 *data)
+{
+  guchar header[] = {137, 80, 78, 71, 13, 10, 26, 10};
+  guchar ihdr[13+12] = {0, 0, 0, 13, 'I', 'H', 'D', 'R',
+                       /* w: */ 0, 0, 0, 0, /* h: */ 0,0,0,0,
+                       /* bpp: */ 8, /* color type: */ 2,
+                       0, 0, 0};
+  guchar idat_start[8] = { /* len: */0, 0, 0, 0,   'I', 'D', 'A', 'T' };
+  guchar iend[12] = {0, 0, 0, 0, 'I', 'E', 'N', 'D', 0xae, 0x42, 0x60, 0x82};
+  gsize data_size, row_size;
+  char row_header[6];
+  guint8 *png, *p, *p_row, *p_idat;
+  guint32 *row;
+  unsigned long adler;
+  guint32 pixel;
+  gsize png_size;
+  int x, y;
+  char *url, *url_base64;
+  int state = 0, outlen;
+  int save = 0;
+
+  *(guint32 *)&ihdr[8] = GUINT32_TO_BE(w);
+  *(guint32 *)&ihdr[12] = GUINT32_TO_BE(h);
+  *(guint32 *)&ihdr[21] = GUINT32_TO_BE(crc(&ihdr[4], 13 + 4));
+
+  row_size = 1 + w * 3;
+  row_header[0] = 0;
+  row_header[1] = row_size & 0xff;
+  row_header[2] = (row_size >> 8) & 0xff;
+  row_header[3] = ~row_header[1];
+  row_header[4] = ~row_header[2];
+  row_header[5] = 0;
+
+  data_size = 2 + (6 + w * 3) * h + 4;
+
+  *(guint32 *)&idat_start[0] = GUINT32_TO_BE(data_size);
+
+  png_size = sizeof(header) + sizeof(ihdr) + 12 + data_size + sizeof(iend);
+  png = g_malloc (png_size);
+
+  p = png;
+  memcpy (p, header, sizeof(header));
+  p += sizeof(header);
+  memcpy (p, ihdr, sizeof(ihdr));
+  p += sizeof(ihdr);
+  memcpy (p, idat_start, sizeof(idat_start));
+  p += sizeof(idat_start);
+
+  /* IDAT data:
+
+     zlib header:  0x78, 0x01 ,
+     h * scanline: row_header[] + width * r,g,b
+     checksum: adler32
+  */
+
+  p_idat = p - 4;
+
+  /* zlib header */
+  *p++ = 0x78;
+  *p++ = 0x01;
+
+  adler = 1;
+
+  /* scanline data */
+  for (y = 0; y < h; y++) {
+    if (y == h - 1)
+      row_header[0] = 1; /* final block */
+    memcpy (p, row_header, sizeof(row_header));
+    p += sizeof(row_header);
+    p_row = p - 1;
+    row = data;
+    data += byte_stride / 4;
+    for (x = 0; x < w; x++) {
+      pixel = *row++;
+      *p++ = (pixel >> 16) & 0xff; /* red */
+      *p++ = (pixel >> 8) & 0xff; /* green */
+      *p++ = (pixel >> 0) & 0xff; /* blue */
+    }
+    adler = update_adler32(adler, p_row, p - p_row);
+  }
+
+  /* adler32 */
+  *(guint32 *)p = GUINT32_TO_BE(adler);
+  p += 4;
+  *(guint32 *)p = GUINT32_TO_BE(crc(p_idat, p - p_idat));
+  p += 4;
+
+  memcpy (p, iend, sizeof(iend));
+  p += sizeof(iend);
+
+  assert(p - png == png_size);
+
+  url = g_malloc (strlen("data:image/png;base64,") +
+                  ((png_size / 3 + 1) * 4 + 4) + 1);
+  strcpy (url, "data:image/png;base64,");
+
+  url_base64 = url + strlen("data:image/png;base64,");
+  outlen = g_base64_encode_step (png, png_size, FALSE, url_base64, &state, &save);
+  outlen += g_base64_encode_close (FALSE, url_base64 + outlen, &state, &save);
+  url_base64[outlen] = 0;
+
+  free (png);
+
+  return url;
+}
+
+static char *
+to_png_rgba (int w, int h, int byte_stride, guint32 *data)
+{
+  guchar header[] = {137, 80, 78, 71, 13, 10, 26, 10};
+  guchar ihdr[13+12] = {0, 0, 0, 13, 'I', 'H', 'D', 'R',
+                       /* w: */ 0, 0, 0, 0, /* h: */ 0,0,0,0,
+                       /* bpp: */ 8, /* color type: */ 6,
+                       0, 0, 0};
+  guchar idat_start[8] = { /* len: */0, 0, 0, 0,   'I', 'D', 'A', 'T' };
+  guchar iend[12] = {0, 0, 0, 0, 'I', 'E', 'N', 'D', 0xae, 0x42, 0x60, 0x82};
+  gsize data_size, row_size;
+  char row_header[6];
+  guint8 *png, *p, *p_row, *p_idat;
+  guint32 *row;
+  unsigned long adler;
+  guint32 pixel;
+  gsize png_size;
+  int x, y;
+  char *url, *url_base64;
+  int state = 0, outlen;
+  int save = 0;
+
+  *(guint32 *)&ihdr[8] = GUINT32_TO_BE(w);
+  *(guint32 *)&ihdr[12] = GUINT32_TO_BE(h);
+  *(guint32 *)&ihdr[21] = GUINT32_TO_BE(crc(&ihdr[4], 13 + 4));
+
+  row_size = 1 + w * 4;
+  row_header[0] = 0;
+  row_header[1] = row_size & 0xff;
+  row_header[2] = (row_size >> 8) & 0xff;
+  row_header[3] = ~row_header[1];
+  row_header[4] = ~row_header[2];
+  row_header[5] = 0;
+
+  data_size = 2 + (6 + w * 4) * h + 4;
+
+  *(guint32 *)&idat_start[0] = GUINT32_TO_BE(data_size);
+
+  png_size = sizeof(header) + sizeof(ihdr) + 12 + data_size + sizeof(iend);
+  png = g_malloc (png_size);
+
+  p = png;
+  memcpy (p, header, sizeof(header));
+  p += sizeof(header);
+  memcpy (p, ihdr, sizeof(ihdr));
+  p += sizeof(ihdr);
+  memcpy (p, idat_start, sizeof(idat_start));
+  p += sizeof(idat_start);
+
+  /* IDAT data:
+
+     zlib header:  0x78, 0x01 ,
+     h * scanline: row_header[] + width * r,g,b,a
+     checksum: adler32
+  */
+
+  p_idat = p - 4;
+
+  /* zlib header */
+  *p++ = 0x78;
+  *p++ = 0x01;
+
+  adler = 1;
+
+  /* scanline data */
+  for (y = 0; y < h; y++) {
+    if (y == h - 1)
+      row_header[0] = 1; /* final block */
+    memcpy (p, row_header, sizeof(row_header));
+    p += sizeof(row_header);
+    p_row = p - 1;
+    row = data;
+    data += byte_stride / 4;
+    for (x = 0; x < w; x++) {
+      pixel = *row++;
+      *p++ = (pixel >> 16) & 0xff; /* red */
+      *p++ = (pixel >> 8) & 0xff; /* green */
+      *p++ = (pixel >> 0) & 0xff; /* blue */
+      *p++ = (pixel >> 24) & 0xff; /* alpha */
+    }
+    adler = update_adler32(adler, p_row, p - p_row);
+  }
+
+  /* adler32 */
+  *(guint32 *)p = GUINT32_TO_BE(adler);
+  p += 4;
+  *(guint32 *)p = GUINT32_TO_BE(crc(p_idat, p - p_idat));
+  p += 4;
+
+  memcpy (p, iend, sizeof(iend));
+  p += sizeof(iend);
+
+  assert(p - png == png_size);
+
+  url = g_malloc (strlen("data:image/png;base64,") +
+                  ((png_size / 3 + 1) * 4 + 4) + 1);
+  strcpy (url, "data:image/png;base64,");
+
+  url_base64 = url + strlen("data:image/png;base64,");
+  outlen = g_base64_encode_step (png, png_size, FALSE, url_base64, &state, &save);
+  outlen += g_base64_encode_close (FALSE, url_base64 + outlen, &state, &save);
+  url_base64[outlen] = 0;
+
+  free (png);
+
+  return url;
+}
+
+#if 0
+static char *
+to_png_a (int w, int h, int byte_stride, guint8 *data)
+{
+  guchar header[] = {137, 80, 78, 71, 13, 10, 26, 10};
+  guchar ihdr[13+12] = {0, 0, 0, 13, 'I', 'H', 'D', 'R',
+                       /* w: */ 0, 0, 0, 0, /* h: */ 0,0,0,0,
+                       /* bpp: */ 8, /* color type: */ 4,
+                       0, 0, 0};
+  guchar idat_start[8] = { /* len: */0, 0, 0, 0,   'I', 'D', 'A', 'T' };
+  guchar iend[12] = {0, 0, 0, 0, 'I', 'E', 'N', 'D', 0xae, 0x42, 0x60, 0x82};
+  gsize data_size, row_size;
+  char row_header[6];
+  guint8 *png, *p, *p_row, *p_idat;
+  guint8 *row;
+  unsigned long adler;
+  guint32 pixel;
+  gsize png_size;
+  int x, y;
+  char *url, *url_base64;
+  int state = 0, outlen;
+  int save = 0;
+
+  *(guint32 *)&ihdr[8] = GUINT32_TO_BE(w);
+  *(guint32 *)&ihdr[12] = GUINT32_TO_BE(h);
+  *(guint32 *)&ihdr[21] = GUINT32_TO_BE(crc(&ihdr[4], 13 + 4));
+
+  row_size = 1 + w * 2;
+  row_header[0] = 0;
+  row_header[1] = row_size & 0xff;
+  row_header[2] = (row_size >> 8) & 0xff;
+  row_header[3] = ~row_header[1];
+  row_header[4] = ~row_header[2];
+  row_header[5] = 0;
+
+  data_size = 2 + (6 + w * 2) * h + 4;
+
+  *(guint32 *)&idat_start[0] = GUINT32_TO_BE(data_size);
+
+  png_size = sizeof(header) + sizeof(ihdr) + 12 + data_size + sizeof(iend);
+  png = g_malloc (png_size);
+
+  p = png;
+  memcpy (p, header, sizeof(header));
+  p += sizeof(header);
+  memcpy (p, ihdr, sizeof(ihdr));
+  p += sizeof(ihdr);
+  memcpy (p, idat_start, sizeof(idat_start));
+  p += sizeof(idat_start);
+
+  /* IDAT data:
+
+     zlib header:  0x78, 0x01 ,
+     h * scanline: row_header[] + width * r,g,b,a
+     checksum: adler32
+  */
+
+  p_idat = p - 4;
+
+  /* zlib header */
+  *p++ = 0x78;
+  *p++ = 0x01;
+
+  adler = 1;
+
+  /* scanline data */
+  for (y = 0; y < h; y++) {
+    if (y == h - 1)
+      row_header[0] = 1; /* final block */
+    memcpy (p, row_header, sizeof(row_header));
+    p += sizeof(row_header);
+    p_row = p - 1;
+    row = data;
+    data += byte_stride / 4;
+    for (x = 0; x < w; x++) {
+      pixel = *row++;
+      *p++ = 0x00; /* gray */
+      *p++ = pixel; /* alpha */
+    }
+    adler = update_adler32(adler, p_row, p - p_row);
+  }
+
+  /* adler32 */
+  *(guint32 *)p = GUINT32_TO_BE(adler);
+  p += 4;
+  *(guint32 *)p = GUINT32_TO_BE(crc(p_idat, p - p_idat));
+  p += 4;
+
+  memcpy (p, iend, sizeof(iend));
+  p += sizeof(iend);
+
+  assert(p - png == png_size);
+
+  url = g_malloc (strlen("data:image/png;base64,") +
+                 ((png_size / 3 + 1) * 4 + 4) + 1);
+  strcpy (url, "data:image/png;base64,");
+
+  url_base64 = url + strlen("data:image/png;base64,");
+  outlen = g_base64_encode_step (png, png_size, FALSE, url_base64, &state, &save);
+  outlen += g_base64_encode_close (FALSE, url_base64 + outlen, &state, &save);
+  url_base64[outlen] = 0;
+
+  free (png);
+
+  return url;
+}
+#endif
+
+/************************************************************************
+ *                Basic I/O primitives                                  *
+ ************************************************************************/
+
+struct BroadwayOutput {
+  int fd;
+  gzFile *zfd;
+  int error;
+};
+
+static void
+broadway_output_write_raw (BroadwayOutput *output,
+                          const void *buf, gsize count)
+{
+  gssize res;
+  int errsave;
+  const char *ptr = (const char *)buf;
+
+  if (output->error)
+    return;
+
+  while (count > 0)
+    {
+      res = write(output->fd, ptr, count);
+      if (res == -1)
+       {
+         errsave = errno;
+         if (errsave == EINTR)
+           continue;
+         output->error = TRUE;
+         return;
+       }
+      if (res == 0)
+       {
+         output->error = TRUE;
+         return;
+       }
+      count -= res;
+      ptr += res;
+    }
+}
+
+static void
+broadway_output_write (BroadwayOutput *output,
+                      const void *buf, gsize count)
+{
+  gssize res;
+  const char *ptr = (const char *)buf;
+
+  if (output->error)
+    return;
+
+  while (count > 0)
+    {
+      res = gzwrite(output->zfd, ptr, count);
+      if (res == -1)
+       {
+         output->error = TRUE;
+         return;
+       }
+      if (res == 0)
+       {
+         output->error = TRUE;
+         return;
+       }
+      count -= res;
+      ptr += res;
+    }
+}
+
+static void
+broadway_output_write_header (BroadwayOutput *output)
+{
+  char *header;
+
+  header =
+    "HTTP/1.1 200 OK\r\n"
+    "Content-type: multipart/x-mixed-replace;boundary=x\r\n"
+    "Content-Encoding: gzip\r\n"
+    "\r\n";
+  broadway_output_write_raw (output,
+                            header, strlen (header));
+}
+
+static void
+send_boundary (BroadwayOutput *output)
+{
+  char *boundary =
+    "--x\r\n"
+    "\r\n";
+
+  broadway_output_write (output, boundary, strlen (boundary));
+}
+
+BroadwayOutput *
+broadway_output_new(int fd)
+{
+  BroadwayOutput *output;
+
+  output = g_new0 (BroadwayOutput, 1);
+
+  output->fd = fd;
+
+  broadway_output_write_header (output);
+
+  output->zfd = gzdopen(fd, "wb");
+
+  /* Need an initial multipart boundary */
+  send_boundary (output);
+
+  return output;
+}
+
+void
+broadway_output_free (BroadwayOutput *output)
+{
+  if (output->zfd)
+    gzclose (output->zfd);
+  else
+    close (output->fd);
+  free (output);
+}
+
+int
+broadway_output_flush (BroadwayOutput *output)
+{
+  send_boundary (output);
+  gzflush (output->zfd, Z_SYNC_FLUSH);
+  return !output->error;
+}
+
+
+/************************************************************************
+ *                     Core rendering operations                        *
+ ************************************************************************/
+
+void
+broadway_output_copy_rectangles (BroadwayOutput *output,  int id,
+                                BroadwayRect *rects, int n_rects,
+                                int dx, int dy)
+{
+  char *buf;
+  int len, i, p;
+
+  len = 1 + 3 + 3 + 3*4*n_rects + 3 + 3;
+
+  buf = g_malloc (len);
+  p = 0;
+  buf[p++] = 'b';
+  base64_uint16(id, &buf[p]); p +=3;
+  base64_uint16(n_rects, &buf[p]); p +=3;
+  for (i = 0; i < n_rects; i++)
+    {
+      base64_uint16(rects[i].x, &buf[p]); p +=3;
+      base64_uint16(rects[i].y, &buf[p]); p +=3;
+      base64_uint16(rects[i].width, &buf[p]); p +=3;
+      base64_uint16(rects[i].height, &buf[p]); p +=3;
+    }
+  base64_uint16(dx, &buf[p]); p +=3;
+  base64_uint16(dy, &buf[p]); p +=3;
+
+  broadway_output_write (output, buf, len);
+  free (buf);
+}
+
+void
+broadway_output_new_surface(BroadwayOutput *output,  int id, int x, int y, int w, int h)
+{
+  char buf[16];
+
+  buf[0] = 's';
+  base64_uint16(id, &buf[1]);
+  base64_uint16(x, &buf[4]);
+  base64_uint16(y, &buf[7]);
+  base64_uint16(w, &buf[10]);
+  base64_uint16(h, &buf[13]);
+
+  broadway_output_write (output, buf, 16);
+}
+
+void
+broadway_output_show_surface(BroadwayOutput *output,  int id)
+{
+  char buf[4];
+
+  buf[0] = 'S';
+  base64_uint16(id, &buf[1]);
+
+  broadway_output_write (output, buf, 4);
+}
+
+void
+broadway_output_hide_surface(BroadwayOutput *output,  int id)
+{
+  char buf[4];
+
+  buf[0] = 'H';
+  base64_uint16(id, &buf[1]);
+
+  broadway_output_write (output, buf, 4);
+}
+
+void
+broadway_output_destroy_surface(BroadwayOutput *output,  int id)
+{
+  char buf[4];
+
+  buf[0] = 'd';
+  base64_uint16(id, &buf[1]);
+
+  broadway_output_write (output, buf, 4);
+}
+
+void
+broadway_output_move_surface(BroadwayOutput *output,  int id, int x, int y)
+{
+  char buf[10];
+
+  buf[0] = 'm';
+  base64_uint16(id, &buf[1]);
+  base64_uint16(x, &buf[4]);
+  base64_uint16(y, &buf[7]);
+
+  broadway_output_write (output, buf, 10);
+}
+
+void
+broadway_output_resize_surface(BroadwayOutput *output,  int id, int w, int h)
+{
+  char buf[10];
+
+  buf[0] = 'r';
+  base64_uint16(id, &buf[1]);
+  base64_uint16(w, &buf[4]);
+  base64_uint16(h, &buf[7]);
+
+  broadway_output_write (output, buf, 10);
+}
+
+void
+broadway_output_put_rgb (BroadwayOutput *output,  int id, int x, int y,
+                        int w, int h, int byte_stride, void *data)
+{
+  char buf[16];
+  gsize len;
+  char *url;
+
+  buf[0] = 'i';
+  base64_uint16(id, &buf[1]);
+  base64_uint16(x, &buf[4]);
+  base64_uint16(y, &buf[7]);
+
+  url = to_png_rgb (w, h, byte_stride, (guint32*)data);
+  len = strlen (url);
+  base64_uint32(len, &buf[10]);
+
+  broadway_output_write (output, buf, 16);
+
+  broadway_output_write (output, url, len);
+
+  free (url);
+}
+
+typedef struct  {
+  int x1, y1;
+  int x2, y2;
+} BroadwayBox;
+
+static int
+is_any_x_set (unsigned char *data,
+             int box_x1, int box_x2,
+             int x1, int x2, int y, int *x_set,
+             int byte_stride)
+{
+  int w ;
+  guint32 *ptr;
+
+  if (x1 < box_x1)
+    x1 = box_x1;
+
+  if (x2 > box_x2)
+    x2 = box_x2;
+
+  w = x2 - x1;
+  if (w > 0)
+    {
+      ptr = (guint32 *)(data + y * byte_stride + x1 * 4);
+      while (w-- > 0)
+       {
+         if (*ptr != 0)
+           {
+             if (x_set)
+               *x_set = x1;
+             return 1;
+           }
+         ptr++;
+         x1++;
+       }
+    }
+  return 0;
+}
+
+
+#define EXTEND_X_FUZZ 10
+#define EXTEND_Y_FUZZ 10
+
+static int
+extend_x_range (unsigned char *data,
+               int box_x1, int box_y1,
+               int box_x2, int box_y2,
+               int *x1, int *x2, int y,
+               int byte_stride)
+{
+  int extended = 0;
+  int new_x;
+
+  while (is_any_x_set (data, box_x1, box_x2, *x1 - EXTEND_X_FUZZ, *x1, y, &new_x, byte_stride))
+    {
+      *x1 = new_x;
+      extended = 1;
+    }
+
+  while (is_any_x_set (data, box_x1, box_x2, *x2, *x2 + EXTEND_X_FUZZ, y, &new_x, byte_stride))
+    {
+      *x2 = new_x + 1;
+      extended = 1;
+    }
+
+  return extended;
+}
+
+static int
+extend_y_range (unsigned char *data,
+               int box_x1, int box_y1,
+               int box_x2, int box_y2,
+               int x1, int x2, int *y,
+               int byte_stride)
+{
+  int extended = 0;
+  int found_set;
+  int yy, y2;
+
+  while (*y < box_y2)
+    {
+      found_set = 0;
+
+      y2 = *y + EXTEND_Y_FUZZ;
+      if (y2 > box_y2)
+       y2 = box_y2;
+
+      for (yy = y2; yy > *y + 1; yy--)
+       {
+         if (is_any_x_set (data, box_x1, box_x2, x1, x2, yy - 1, NULL, byte_stride))
+           {
+             found_set = 1;
+             break;
+           }
+       }
+      if (!found_set)
+       break;
+      *y = yy;
+      extended = 1;
+    }
+
+  return extended;
+}
+
+
+static void
+rgba_find_rects_extents (unsigned char *data,
+                        int box_x1, int box_y1,
+                        int box_x2, int box_y2,
+                        int x, int y,
+                        BroadwayBox *rect,
+                        int byte_stride)
+{
+  int x1, x2, y1, y2, yy;
+  int extended;
+
+  x1 = x;
+  x2 = x + 1;
+  y1 = y;
+  y2 = y + 1;
+
+  do
+    {
+      /* Expand maximally for all known rows */
+      do
+       {
+         extended = 0;
+
+         for (yy = y1; yy < y2; yy++)
+           extended |= extend_x_range (data,
+                                       box_x1, box_y1,
+                                       box_x2, box_y2,
+                                       &x1, &x2, yy,
+                                       byte_stride);
+       }
+      while (extended);
+    }
+  while (extend_y_range(data,
+                       box_x1, box_y1,
+                       box_x2, box_y2,
+                       x1, x2, &y2,
+                       byte_stride));
+
+  rect->x1 = x1;
+  rect->x2 = x2;
+  rect->y1 = y1;
+  rect->y2 = y2;
+}
+
+static void
+rgba_find_rects_sub (unsigned char *data,
+                    int box_x1, int box_y1,
+                    int box_x2, int box_y2,
+                    int byte_stride,
+                    BroadwayBox **rects,
+                    int *n_rects, int *alloc_rects)
+{
+  guint32 *line;
+  BroadwayBox rect;
+  int x, y;
+
+  if (box_x1 == box_x2 || box_y1 == box_y2)
+    return;
+
+  for (y = box_y1; y < box_y2; y++)
+    {
+      line = (guint32 *)(data + y * byte_stride + box_x1 * 4);
+
+      for (x = box_x1; x < box_x2; x++)
+       {
+         if (*line != 0)
+           {
+             rgba_find_rects_extents (data,
+                                      box_x1, box_y1, box_x2, box_y2,
+                                      x, y, &rect, byte_stride);
+             if (*n_rects == *alloc_rects)
+               {
+                 (*alloc_rects) *= 2;
+                 *rects = g_renew (BroadwayBox, *rects, *alloc_rects);
+               }
+             (*rects)[*n_rects] = rect;
+             (*n_rects)++;
+             rgba_find_rects_sub (data,
+                                  box_x1, rect.y1,
+                                  rect.x1, rect.y2,
+                                  byte_stride,
+                                  rects, n_rects, alloc_rects);
+             rgba_find_rects_sub (data,
+                                  rect.x2, rect.y1,
+                                  box_x2, rect.y2,
+                                  byte_stride,
+                                  rects, n_rects, alloc_rects);
+             rgba_find_rects_sub (data,
+                                  box_x1, rect.y2,
+                                  box_x2, box_y2,
+                                  byte_stride,
+                                  rects, n_rects, alloc_rects);
+             return;
+           }
+         line++;
+       }
+    }
+}
+
+static BroadwayBox *
+rgba_find_rects (unsigned char *data,
+                int w, int h, int byte_stride,
+                int *n_rects)
+{
+  BroadwayBox *rects;
+  int alloc_rects;
+
+  alloc_rects = 20;
+  rects = g_new (BroadwayBox, alloc_rects);
+
+  *n_rects = 0;
+  rgba_find_rects_sub (data,
+                      0, 0, w, h, byte_stride,
+                      &rects, n_rects, &alloc_rects);
+
+  return rects;
+}
+
+void
+broadway_output_put_rgba (BroadwayOutput *output,  int id, int x, int y,
+                         int w, int h, int byte_stride, void *data)
+{
+  char buf[16];
+  gsize len;
+  char *url;
+  BroadwayBox *rects;
+  int i, n_rects;
+  guint8 *subdata;
+
+  rects = rgba_find_rects (data, w, h, byte_stride, &n_rects);
+
+  for (i = 0; i < n_rects; i++)
+    {
+      subdata = (guint8 *)data + rects[i].x1 * 4 + rects[i].y1 * byte_stride;
+
+      buf[0] = 'i';
+      base64_uint16(id, &buf[1]);
+      base64_uint16(x + rects[i].x1, &buf[4]);
+      base64_uint16(y + rects[i].y1, &buf[7]);
+
+      url = to_png_rgba (rects[i].x2 - rects[i].x1,
+                        rects[i].y2 - rects[i].y1,
+                        byte_stride, (guint32*)subdata);
+      len = strlen (url);
+      base64_uint32(len, &buf[10]);
+
+      broadway_output_write (output, buf, 16);
+
+      broadway_output_write (output, url, len);
+
+      free (url);
+    }
+
+  free (rects);
+}
+
+#if 0
+static void
+send_image_a (BroadwayOutput *output,  int id, int x, int y,
+             int w, int h, int byte_stride, guint8 *data)
+{
+  char buf[16];
+  gsize len;
+  char *url;
+
+  buf[0] = 'i';
+  base64_uint16(id, &buf[1]);
+  base64_uint16(x, &buf[4]);
+  base64_uint16(y, &buf[7]);
+
+  url = to_png_a (w, h, byte_stride, data);
+  len = strlen (url);
+  base64_uint32(len, &buf[10]);
+
+  broadway_output_write (output, buf, 16);
+
+  broadway_output_write (output, url, len);
+
+  free (url);
+}
+#endif
diff --git a/gdk/broadway/broadway.h b/gdk/broadway/broadway.h
new file mode 100644 (file)
index 0000000..0f7a7eb
--- /dev/null
@@ -0,0 +1,53 @@
+typedef struct BroadwayOutput BroadwayOutput;
+
+typedef struct  {
+    int x, y;
+    int width, height;
+} BroadwayRect;
+
+BroadwayOutput *broadway_output_new             (int             fd);
+void            broadway_output_free            (BroadwayOutput *output);
+int             broadway_output_flush           (BroadwayOutput *output);
+int             broadway_output_has_error       (BroadwayOutput *output);
+void            broadway_output_new_surface     (BroadwayOutput *output,
+                                                int             id,
+                                                int             x,
+                                                int             y,
+                                                int             w,
+                                                int             h);
+void            broadway_output_show_surface    (BroadwayOutput *output,
+                                                int             id);
+void            broadway_output_hide_surface    (BroadwayOutput *output,
+                                                int             id);
+void            broadway_output_destroy_surface (BroadwayOutput *output,
+                                                int             id);
+void            broadway_output_move_surface    (BroadwayOutput *output,
+                                                int             id,
+                                                int             x,
+                                                int             y);
+void            broadway_output_resize_surface  (BroadwayOutput *output,
+                                                int             id,
+                                                int             w,
+                                                int             h);
+void            broadway_output_put_rgb         (BroadwayOutput *output,
+                                                int             id,
+                                                int             x,
+                                                int             y,
+                                                int             w,
+                                                int             h,
+                                                int             byte_stride,
+                                                void           *data);
+void            broadway_output_put_rgba        (BroadwayOutput *output,
+                                                int             id,
+                                                int             x,
+                                                int             y,
+                                                int             w,
+                                                int             h,
+                                                int             byte_stride,
+                                                void           *data);
+void            broadway_output_copy_rectangles (BroadwayOutput *output,
+                                                int             id,
+                                                BroadwayRect   *rects,
+                                                int             n_rects,
+                                                int             dx,
+                                                int             dy);
diff --git a/gdk/broadway/broadway.js b/gdk/broadway/broadway.js
new file mode 100644 (file)
index 0000000..85f5448
--- /dev/null
@@ -0,0 +1,378 @@
+var base64_val = [
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255, 62,255,255,255, 63,
+   52, 53, 54, 55, 56, 57, 58, 59, 60, 61,255,255,255,  0,255,255,
+  255,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
+   15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,255,255,255,255,255,
+  255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+   41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,255,255,255,255,255
+]
+
+function base64_8(str, index) {
+  var v =
+    (base64_val[str.charCodeAt(index)]) +
+    (base64_val[str.charCodeAt(index+1)] << 6);
+  return v;
+}
+
+function base64_16(str, index) {
+  var v =
+    (base64_val[str.charCodeAt(index)]) +
+    (base64_val[str.charCodeAt(index+1)] << 6) +
+    (base64_val[str.charCodeAt(index+2)] << 12);
+  return v;
+}
+
+function base64_16s(str, index) {
+  var v = base64_16(str, index);
+  if (v > 32767)
+    return v - 65536;
+  else
+    return v;
+}
+
+function base64_24(str, index) {
+  var v =
+    (base64_val[str.charCodeAt(index)]) +
+    (base64_val[str.charCodeAt(index+1)] << 6) +
+    (base64_val[str.charCodeAt(index+2)] << 12) +
+    (base64_val[str.charCodeAt(index+3)] << 18);
+  return v;
+}
+
+function base64_32(str, index) {
+  var v =
+    (base64_val[str.charCodeAt(index)]) +
+    (base64_val[str.charCodeAt(index+1)] << 6) +
+    (base64_val[str.charCodeAt(index+2)] << 12) +
+    (base64_val[str.charCodeAt(index+3)] << 18) +
+    (base64_val[str.charCodeAt(index+4)] << 24) +
+    (base64_val[str.charCodeAt(index+5)] << 30);
+  return v;
+}
+
+function createXHR()
+{
+  try { return new XMLHttpRequest(); } catch(e) {}
+  try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); } catch (e) {}
+  try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); } catch (e) {}
+  try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) {}
+  try { return new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) {}
+
+  return null;
+}
+
+var surfaces = {};
+var outstanding_commands = new Array();
+var input_socket = null;
+
+function initContext(canvas, x, y, id)
+{
+  canvas.surface_id = id;
+  canvas.style["position"] = "absolute"
+  canvas.style["left"] = x + "px"
+  canvas.style["top"] = y + "px"
+  canvas.style["display"] = "none"
+  context = canvas.getContext("2d")
+  context.globalCompositeOperation = "src-over"
+  context.fillRect(0, 0, canvas.width, canvas.height);
+  document.body.appendChild(canvas)
+
+  return context
+}
+
+function handleCommands(cmd_obj)
+{
+  var cmd = cmd_obj.data;
+  var i = cmd_obj.pos;
+
+  while (i < cmd.length) {
+    var command = cmd[i++];
+    switch (command) {
+      /* create new surface */
+      case 's':
+        var id = base64_16(cmd, i);
+        i = i + 3;
+        var x = base64_16(cmd, i);
+        i = i + 3;
+        var y = base64_16(cmd, i);
+        i = i + 3;
+        var w = base64_16(cmd, i);
+        i = i + 3;
+        var h = base64_16(cmd, i);
+        i = i + 3;
+        var surface = document.createElement("canvas");
+       surface.width = w;
+       surface.height = h;
+       surfaces[id] = initContext(surface, x, y, id);
+        break;
+
+      /* show a surface */
+      case 'S':
+        var id = base64_16(cmd, i);
+        i = i + 3;
+       surfaces[id].canvas.style["display"] = "inline";
+        break;
+
+      /* hide a surface */
+      case 'H':
+        var id = base64_16(cmd, i);
+        i = i + 3;
+       surfaces[id].canvas.style["display"] = "inline";
+        break;
+
+      /* delete surface */
+      case 'd':
+        var id = base64_16(cmd, i);
+        i = i + 3;
+       var canvas = surfaces[id].canvas
+       delete surfaces[id]
+       canvas.parentNode.removeChild(canvas);
+
+        break;
+
+      /* move a surface */
+      case 'm':
+        var id = base64_16(cmd, i);
+        i = i + 3;
+        var x = base64_16(cmd, i);
+        i = i + 3;
+        var y = base64_16(cmd, i);
+        i = i + 3;
+       surfaces[id].canvas.style["left"] = x + "px";
+       surfaces[id].canvas.style["top"] = y + "px";
+        break;
+
+      /* resize a surface */
+      case 'r':
+        var id = base64_16(cmd, i);
+        i = i + 3;
+        var w = base64_16(cmd, i);
+        i = i + 3;
+        var h = base64_16(cmd, i);
+        i = i + 3;
+       surfaces[id].canvas.width = w;
+       surfaces[id].canvas.height = h;
+        break;
+
+      /* put image data surface */
+      case 'i':
+        var id = base64_16(cmd, i);
+        i = i + 3;
+        var x = base64_16(cmd, i);
+        i = i + 3;
+        var y = base64_16(cmd, i);
+        i = i + 3;
+        var size = base64_32(cmd, i);
+        i = i + 6;
+       var url = cmd.slice(i, i + size);
+       i = i + size;
+        var img = new Image();
+       img.src = url
+       if (img.complete) {
+          surfaces[id].drawImage(img, x, y);
+       } else {
+         cmd_obj.pos = i;
+         img.onload = function() { surfaces[id].drawImage(img, x, y); handleOutstanding(); }
+         return false
+       }
+
+        break;
+
+      /* copy rects */
+      case 'b':
+        var id = base64_16(cmd, i);
+        i = i + 3;
+
+       var nrects = base64_16(cmd, i);
+        i = i + 3;
+
+       var context = surfaces[id];
+       context.save();
+
+       var minx;
+       var miny;
+       var maxx;
+       var maxy;
+       for (var r = 0; r < nrects; r++) {
+         var x = base64_16(cmd, i);
+          i = i + 3;
+          var y = base64_16(cmd, i);
+          i = i + 3;
+          var w = base64_16(cmd, i);
+          i = i + 3;
+          var h = base64_16(cmd, i);
+          i = i + 3;
+         context.rect(x, y, w, h);
+
+         if (r == 0) {
+             minx = x;
+             miny = y;
+             maxx = x + w;
+             maxy = y + h;
+         } else {
+             if (x < minx)
+                 minx = x;
+             if (y < miny)
+                 miny = y;
+             if (x + w > maxx)
+                 maxx = x + w;
+             if (y + h > maxy)
+                 maxy = y + h;
+         }
+       }
+
+       context.clip()
+
+        var dx = base64_16s(cmd, i);
+        i = i + 3;
+        var dy = base64_16s(cmd, i);
+        i = i + 3;
+
+        context.drawImage(context.canvas,
+                         minx - dx, miny - dy, maxx - minx, maxy - miny,
+                         minx, miny, maxx - minx, maxy - miny);
+
+       context.restore();
+        break;
+
+      default:
+        alert("Unknown op " + command);
+    }
+  }
+  return true;
+}
+
+function handleOutstanding()
+{
+  while (outstanding_commands.length > 0) {
+    var cmd = outstanding_commands.shift();
+    if (!handleCommands(cmd)) {
+      outstanding_commands.unshift(cmd);
+      return;
+    }
+  }
+}
+
+function handleLoad(event)
+{
+  var cmd_obj = {};
+  cmd_obj.data = event.target.responseText;
+  cmd_obj.pos = 0;
+
+  outstanding_commands.push(cmd_obj);
+  if (outstanding_commands.length == 1) {
+    handleOutstanding()
+  }
+}
+
+function get_surface_id(ev) {
+  var id = ev.target.surface_id;
+  if (id != undefined)
+    return id;
+  return 0;
+}
+
+function send_input(cmd, args)
+{
+  if (input_socket != null) {
+      input_socket.send(cmd + args.join(","));
+  }
+}
+
+function on_mouse_move (ev) {
+  send_input ("m", [get_surface_id(ev), ev.pageX, ev.pageY, ev.timeStamp])
+}
+
+function on_mouse_down (ev) {
+  send_input ("b", [get_surface_id(ev), ev.pageX, ev.pageY, ev.button, ev.timeStamp])
+}
+
+function on_mouse_up (ev) {
+  send_input ("B", [get_surface_id(ev), ev.pageX, ev.pageY, ev.button, ev.timeStamp])
+}
+
+var last_key_down = 0;
+function on_key_down (ev) {
+  var key_code = ev.keyCode;
+  if (key_code != last_key_down) {
+    send_input ("k", [key_code, ev.timeStamp]);
+    last_key_down = key_code;
+  }
+}
+
+function on_key_up (ev) {
+  var key_code = ev.keyCode;
+  send_input ("K", [key_code, ev.timeStamp]);
+  last_key_down = 0;
+}
+
+function cancel_event(ev)
+{
+  ev = ev ? ev : window.event;
+  if (ev.stopPropagation)
+    ev.stopPropagation();
+  if (ev.preventDefault)
+    ev.preventDefault();
+  ev.cancelBubble = true;
+  ev.cancel = true;
+  ev.returnValue = false;
+  return false;
+}
+
+function on_mouse_wheel(ev)
+{
+  ev = ev ? ev : window.event;
+  var offset = ev.detail ? ev.detail : ev.wheelDelta;
+  var dir = 0
+  if (offset > 0)
+    dir = 1;
+  send_input ("s", [get_surface_id(ev), ev.pageX, ev.pageY, dir, ev.timeStamp])
+
+  return cancel_event(ev);
+}
+
+function connect()
+{
+  var xhr = createXHR();
+  if (xhr) {
+    if (typeof xhr.multipart == 'undefined') {
+      alert("Sorry, this example only works in browsers that support multipart.");
+      return;
+    }
+
+    xhr.multipart = true;
+    xhr.open("GET", "/output", true);
+    xhr.onload = handleLoad;
+    xhr.send(null);
+  }
+
+  if ("WebSocket" in window) {
+    var loc = window.location.toString().replace("http:", "ws:");
+    loc = loc.substr(0, loc.lastIndexOf('/')) + "/input";
+    var ws = new WebSocket(loc, "broadway");
+    ws.onopen = function() {
+      input_socket = ws;
+    };
+    ws.onclose = function() {
+      input_socket = null;
+    };
+  } else {
+     alert("WebSocket not supported, input will not work!");
+  }
+  document.oncontextmenu = function () { return false; }
+  document.onmousemove = on_mouse_move;
+  document.onmousedown = on_mouse_down;
+  document.onmouseup = on_mouse_up;
+  document.onkeydown = on_key_down;
+  document.onkeyup = on_key_up;
+
+  if (document.addEventListener) {
+    document.addEventListener('DOMMouseScroll', on_mouse_wheel, false);
+    document.addEventListener('mousewheel', on_mouse_wheel, false);
+  } else if (document.attachEvent) {
+    element.attachEvent("onmousewheel", on_mouse_wheel);
+  }
+
+}
diff --git a/gdk/broadway/client.html b/gdk/broadway/client.html
new file mode 100644 (file)
index 0000000..e74cdd9
--- /dev/null
@@ -0,0 +1,11 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf8" />
+<title>broadway 2.0</title>
+<script type="text/javascript" src="broadway.js"></script>
+</head>
+
+<body onload="connect()">
+</body>
+</html>
diff --git a/gdk/broadway/gdkapplaunchcontext-broadway.c b/gdk/broadway/gdkapplaunchcontext-broadway.c
new file mode 100644 (file)
index 0000000..23e311f
--- /dev/null
@@ -0,0 +1,50 @@
+/* gdkapplaunchcontext-broadway.c - Gtk+ implementation for GAppLaunchContext
+
+   Copyright (C) 2007 Red Hat, Inc.
+
+   The Gnome 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.
+
+   The Gnome 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 the Gnome Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.
+
+   Author: Alexander Larsson <alexl@redhat.com>
+*/
+
+#include "config.h"
+
+#include "gdkapplaunchcontext.h"
+
+#include "gdkscreen.h"
+#include "gdkinternals.h"
+#include "gdkintl.h"
+
+#include <glib.h>
+#include <gio/gdesktopappinfo.h>
+
+#include <string.h>
+#include <unistd.h>
+
+char *
+_gdk_windowing_get_startup_notify_id (GAppLaunchContext *context,
+                                     GAppInfo          *info,
+                                     GList             *files)
+{
+  return g_strdup ("todo");
+}
+
+
+void
+_gdk_windowing_launch_failed (GAppLaunchContext *context,
+                             const char        *startup_notify_id)
+{
+}
diff --git a/gdk/broadway/gdkcursor-broadway.c b/gdk/broadway/gdkcursor-broadway.c
new file mode 100644 (file)
index 0000000..0e0e617
--- /dev/null
@@ -0,0 +1,198 @@
+/* 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"
+
+/* needs to be first because any header might include gdk-pixbuf.h otherwise */
+#define GDK_PIXBUF_ENABLE_BACKEND
+#include <gdk-pixbuf/gdk-pixbuf.h>
+
+#include "gdkcursor.h"
+
+#include "gdkprivate-broadway.h"
+#include "gdkdisplay-broadway.h"
+
+#include <string.h>
+#include <errno.h>
+
+
+/* Called by gdk_display_broadway_finalize to flush any cached cursors
+ * for a dead display.
+ */
+void
+_gdk_broadway_cursor_display_finalize (GdkDisplay *display)
+{
+}
+
+GdkCursor*
+gdk_cursor_new_for_display (GdkDisplay    *display,
+                           GdkCursorType  cursor_type)
+{
+  GdkCursorPrivate *private;
+  GdkCursor *cursor;
+
+  g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
+
+  private = g_new (GdkCursorPrivate, 1);
+  private->display = display;
+
+  cursor = (GdkCursor *) private;
+  cursor->type = cursor_type;
+  cursor->ref_count = 1;
+
+  return cursor;
+}
+
+void
+_gdk_cursor_destroy (GdkCursor *cursor)
+{
+  GdkCursorPrivate *private;
+
+  g_return_if_fail (cursor != NULL);
+  g_return_if_fail (cursor->ref_count == 0);
+
+  private = (GdkCursorPrivate *) cursor;
+
+  g_free (private);
+}
+
+
+/**
+ * gdk_cursor_get_display:
+ * @cursor: a #GdkCursor.
+ *
+ * Returns the display on which the #GdkCursor is defined.
+ *
+ * Returns: the #GdkDisplay associated to @cursor
+ *
+ * Since: 2.2
+ */
+
+GdkDisplay *
+gdk_cursor_get_display (GdkCursor *cursor)
+{
+  g_return_val_if_fail (cursor != NULL, NULL);
+
+  return ((GdkCursorPrivate *)cursor)->display;
+}
+
+GdkPixbuf*
+gdk_cursor_get_image (GdkCursor *cursor)
+{
+  g_return_val_if_fail (cursor != NULL, NULL);
+
+  return NULL;
+}
+
+void
+gdk_broadway_display_set_cursor_theme (GdkDisplay  *display,
+                                 const gchar *theme,
+                                 const gint   size)
+{
+  g_return_if_fail (GDK_IS_DISPLAY (display));
+}
+
+void
+_gdk_broadway_cursor_update_theme (GdkCursor *cursor)
+{
+  g_return_if_fail (cursor != NULL);
+}
+
+GdkCursor *
+gdk_cursor_new_from_pixbuf (GdkDisplay *display,
+                           GdkPixbuf  *pixbuf,
+                           gint        x,
+                           gint        y)
+{
+  GdkCursorPrivate *private;
+  GdkCursor *cursor;
+
+  g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
+  g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), NULL);
+
+  private = g_new (GdkCursorPrivate, 1);
+  private->display = display;
+
+  cursor = (GdkCursor *) private;
+  cursor->type = GDK_CURSOR_IS_PIXMAP;
+  cursor->ref_count = 1;
+
+  return cursor;
+}
+
+GdkCursor*
+gdk_cursor_new_from_name (GdkDisplay  *display,
+                         const gchar *name)
+{
+  GdkCursorPrivate *private;
+  GdkCursor *cursor;
+
+  g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
+
+  private = g_new (GdkCursorPrivate, 1);
+  private->display = display;
+
+  cursor = (GdkCursor *) private;
+  cursor->type = GDK_CURSOR_IS_PIXMAP;
+  cursor->ref_count = 1;
+
+  return cursor;
+}
+
+gboolean
+gdk_display_supports_cursor_alpha (GdkDisplay *display)
+{
+  g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
+
+  return TRUE;
+}
+
+gboolean
+gdk_display_supports_cursor_color (GdkDisplay *display)
+{
+  g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
+
+  return TRUE;
+}
+
+guint
+gdk_display_get_default_cursor_size (GdkDisplay *display)
+{
+  g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
+
+  return 20;
+}
+
+void
+gdk_display_get_maximal_cursor_size (GdkDisplay *display,
+                                    guint       *width,
+                                    guint       *height)
+{
+  g_return_if_fail (GDK_IS_DISPLAY (display));
+
+  *width = 128;
+  *height = 128;
+}
diff --git a/gdk/broadway/gdkdevice-broadway.c b/gdk/broadway/gdkdevice-broadway.c
new file mode 100644 (file)
index 0000000..17c6901
--- /dev/null
@@ -0,0 +1,191 @@
+/* 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 "gdkdevice-broadway.h"
+
+#include "gdkwindow.h"
+#include "gdkprivate-broadway.h"
+
+static gboolean gdk_device_core_get_history (GdkDevice      *device,
+                                             GdkWindow      *window,
+                                             guint32         start,
+                                             guint32         stop,
+                                             GdkTimeCoord ***events,
+                                             gint           *n_events);
+static void gdk_device_core_get_state (GdkDevice       *device,
+                                       GdkWindow       *window,
+                                       gdouble         *axes,
+                                       GdkModifierType *mask);
+static void gdk_device_core_set_window_cursor (GdkDevice *device,
+                                               GdkWindow *window,
+                                               GdkCursor *cursor);
+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);
+static GdkGrabStatus gdk_device_core_grab   (GdkDevice     *device,
+                                             GdkWindow     *window,
+                                             gboolean       owner_events,
+                                             GdkEventMask   event_mask,
+                                             GdkWindow     *confine_to,
+                                             GdkCursor     *cursor,
+                                             guint32        time_);
+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);
+static void      gdk_device_core_select_window_events (GdkDevice       *device,
+                                                       GdkWindow       *window,
+                                                       GdkEventMask     event_mask);
+
+
+G_DEFINE_TYPE (GdkDeviceCore, gdk_device_core, GDK_TYPE_DEVICE)
+
+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);
+}
+
+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)
+{
+}
+
+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)
+{
+  return FALSE;
+}
+
+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_NOT_VIEWABLE;
+}
+
+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)
+{
+  return NULL;
+}
+
+static void
+gdk_device_core_select_window_events (GdkDevice    *device,
+                                      GdkWindow    *window,
+                                      GdkEventMask  event_mask)
+{
+}
diff --git a/gdk/broadway/gdkdevice-broadway.h b/gdk/broadway/gdkdevice-broadway.h
new file mode 100644 (file)
index 0000000..9ff65c9
--- /dev/null
@@ -0,0 +1,52 @@
+/* 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.
+ */
+
+#ifndef __GDK_DEVICE_BROADWAY_H__
+#define __GDK_DEVICE_BROADWAY_H__
+
+#include <gdk/gdkdeviceprivate.h>
+
+G_BEGIN_DECLS
+
+#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;
+
+struct _GdkDeviceCore
+{
+  GdkDevice parent_instance;
+};
+
+struct _GdkDeviceCoreClass
+{
+  GdkDeviceClass parent_class;
+};
+
+G_GNUC_INTERNAL
+GType gdk_device_core_get_type (void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* __GDK_DEVICE_BROADWAY_H__ */
diff --git a/gdk/broadway/gdkdevicemanager-broadway.c b/gdk/broadway/gdkdevicemanager-broadway.c
new file mode 100644 (file)
index 0000000..42dd200
--- /dev/null
@@ -0,0 +1,150 @@
+/* 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 "gdkdevicemanager-broadway.h"
+
+#include "gdktypes.h"
+#include "gdkdevicemanager.h"
+#include "gdkdevice-broadway.h"
+#include "gdkkeysyms.h"
+#include "gdkprivate-broadway.h"
+
+#define HAS_FOCUS(toplevel)                           \
+  ((toplevel)->has_focus || (toplevel)->has_pointer_focus)
+
+static void    gdk_device_manager_core_finalize    (GObject *object);
+static void    gdk_device_manager_core_constructed (GObject *object);
+
+static GList * gdk_device_manager_core_list_devices (GdkDeviceManager *device_manager,
+                                                     GdkDeviceType     type);
+static GdkDevice * gdk_device_manager_core_get_client_pointer (GdkDeviceManager *device_manager);
+
+G_DEFINE_TYPE (GdkDeviceManagerCore, gdk_device_manager_core, GDK_TYPE_DEVICE_MANAGER)
+
+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;
+  object_class->constructed = gdk_device_manager_core_constructed;
+  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 GdkDevice *
+create_core_pointer (GdkDeviceManager *device_manager,
+                     GdkDisplay       *display)
+{
+  return 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);
+}
+
+static GdkDevice *
+create_core_keyboard (GdkDeviceManager *device_manager,
+                      GdkDisplay       *display)
+{
+  return 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);
+}
+
+static void
+gdk_device_manager_core_init (GdkDeviceManagerCore *device_manager)
+{
+}
+
+static void
+gdk_device_manager_core_finalize (GObject *object)
+{
+  GdkDeviceManagerCore *device_manager_core;
+
+  device_manager_core = GDK_DEVICE_MANAGER_CORE (object);
+
+  g_object_unref (device_manager_core->core_pointer);
+  g_object_unref (device_manager_core->core_keyboard);
+
+  G_OBJECT_CLASS (gdk_device_manager_core_parent_class)->finalize (object);
+}
+
+static void
+gdk_device_manager_core_constructed (GObject *object)
+{
+  GdkDeviceManagerCore *device_manager;
+  GdkDisplay *display;
+
+  device_manager = GDK_DEVICE_MANAGER_CORE (object);
+  display = gdk_device_manager_get_display (GDK_DEVICE_MANAGER (object));
+  device_manager->core_pointer = create_core_pointer (GDK_DEVICE_MANAGER (device_manager), display);
+  device_manager->core_keyboard = create_core_keyboard (GDK_DEVICE_MANAGER (device_manager), display);
+
+  _gdk_device_set_associated_device (device_manager->core_pointer, device_manager->core_keyboard);
+  _gdk_device_set_associated_device (device_manager->core_keyboard, device_manager->core_pointer);
+}
+
+
+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_prepend (devices, device_manager_core->core_keyboard);
+      devices = g_list_prepend (devices, device_manager_core->core_pointer);
+    }
+
+  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->core_pointer;
+}
+
+GdkDeviceManager *
+_gdk_device_manager_new (GdkDisplay *display)
+{
+  return g_object_new (GDK_TYPE_DEVICE_MANAGER_CORE,
+                      "display", display,
+                      NULL);
+}
diff --git a/gdk/broadway/gdkdevicemanager-broadway.h b/gdk/broadway/gdkdevicemanager-broadway.h
new file mode 100644 (file)
index 0000000..50ea91d
--- /dev/null
@@ -0,0 +1,54 @@
+/* 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.
+ */
+
+#ifndef __GDK_DEVICE_MANAGER_BROADWAY_H__
+#define __GDK_DEVICE_MANAGER_BROADWAY_H__
+
+#include <gdk/gdkdevicemanager.h>
+
+G_BEGIN_DECLS
+
+#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;
+};
+
+struct _GdkDeviceManagerCoreClass
+{
+  GdkDeviceManagerClass parent_class;
+};
+
+GType gdk_device_manager_core_get_type (void) G_GNUC_CONST;
+
+
+G_END_DECLS
+
+#endif /* __GDK_DEVICE_MANAGER_BROADWAY_H__ */
diff --git a/gdk/broadway/gdkdisplay-broadway.c b/gdk/broadway/gdkdisplay-broadway.c
new file mode 100644 (file)
index 0000000..4e38048
--- /dev/null
@@ -0,0 +1,784 @@
+/* GDK - The GIMP Drawing Kit
+ * gdkdisplay-broadway.c
+ * 
+ * Copyright 2001 Sun Microsystems Inc.
+ * Copyright (C) 2004 Nokia Corporation
+ *
+ * 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.
+ */
+
+#include "config.h"
+
+#include "gdkdisplay-broadway.h"
+
+#include "gdkdisplay.h"
+#include "gdkeventsource.h"
+#include "gdkscreen.h"
+#include "gdkscreen-broadway.h"
+#include "gdkinternals.h"
+#include "gdkdeviceprivate.h"
+#include "gdkdevicemanager.h"
+
+#include <glib.h>
+#include <glib/gprintf.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+
+static void   gdk_display_broadway_dispose            (GObject            *object);
+static void   gdk_display_broadway_finalize           (GObject            *object);
+
+G_DEFINE_TYPE (GdkDisplayBroadway, _gdk_display_broadway, GDK_TYPE_DISPLAY)
+
+
+static void
+_gdk_display_broadway_class_init (GdkDisplayBroadwayClass * class)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+  object_class->dispose = gdk_display_broadway_dispose;
+  object_class->finalize = gdk_display_broadway_finalize;
+}
+
+static void
+_gdk_display_broadway_init (GdkDisplayBroadway *display)
+{
+  display->id_ht = g_hash_table_new (NULL, NULL);
+}
+
+static void
+_gdk_event_init (GdkDisplay *display)
+{
+  GdkDisplayBroadway *display_broadway;
+
+  display_broadway = GDK_DISPLAY_BROADWAY (display);
+  display_broadway->event_source = gdk_event_source_new (display);
+}
+
+static void
+_gdk_input_init (GdkDisplay *display)
+{
+  GdkDisplayBroadway *display_broadway;
+  GdkDeviceManager *device_manager;
+  GdkDevice *device;
+  GList *list, *l;
+
+  display_broadway = GDK_DISPLAY_BROADWAY (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_broadway->input_devices = g_list_prepend (display_broadway->input_devices,
+                                                   g_object_ref (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_broadway->input_devices = g_list_prepend (display_broadway->input_devices,
+                                               g_object_ref (display->core_pointer));
+
+  g_list_free (list);
+}
+
+struct HttpRequest {
+  GdkDisplay *display;
+  GSocketConnection *connection;
+  GDataInputStream *data;
+  GString *request;
+};
+
+static void
+http_request_free (HttpRequest *request)
+{
+  g_object_unref (request->connection);
+  g_object_unref (request->data);
+  g_string_free (request->request, TRUE);
+  g_free (request);
+}
+
+#include <unistd.h>
+#include <fcntl.h>
+static void
+set_fd_blocking (int fd)
+{
+  glong arg;
+
+  if ((arg = fcntl (fd, F_GETFL, NULL)) < 0)
+    arg = 0;
+
+  arg = arg & ~O_NONBLOCK;
+
+  fcntl (fd, F_SETFL, arg);
+}
+
+static char *
+parse_line (char *line, char *key)
+{
+  char *p;
+
+  if (!g_str_has_prefix (line, key))
+    return NULL;
+  p = line + strlen (key);
+  if (*p != ':')
+    return NULL;
+  p++;
+  /* Skip optional initial space */
+  if (*p == ' ')
+    p++;
+  return p;
+}
+
+static void
+got_input (GInputStream *stream,
+          GAsyncResult *result,
+          HttpRequest *request)
+{
+  GError *error;
+  char *message;
+  gsize len;
+
+  error = NULL;
+  message = g_data_input_stream_read_upto_finish (G_DATA_INPUT_STREAM (stream), result, &len, &error);
+  if (message == NULL)
+    {
+      GDK_DISPLAY_BROADWAY (request->display)->input = NULL;
+      http_request_free (request);
+      return;
+    }
+
+  g_assert (message[0] == 0);
+  _gdk_events_got_input (request->display, message + 1);
+
+  /* Skip past ending 0xff */
+  g_data_input_stream_read_byte (request->data, NULL, NULL);
+  g_data_input_stream_read_upto_async (request->data, "\xff", 1, 0, NULL,
+                                      (GAsyncReadyCallback)got_input, request);
+}
+
+static void
+send_error (HttpRequest *request,
+           int error_code,
+           const char *reason)
+{
+  char *res;
+
+  res = g_strdup_printf ("HTTP/1.0 %d %s\r\n\r\n"
+                        "<html><head><title>%d %s</title></head>"
+                        "<body>%s</body></html>",
+                        error_code, reason,
+                        error_code, reason,
+                        reason);
+  /* TODO: This should really be async */
+  g_output_stream_write_all (g_io_stream_get_output_stream (G_IO_STREAM (request->connection)),
+                            res, strlen (res), NULL, NULL, NULL);
+  g_free (res);
+  http_request_free (request);
+}
+
+static void
+start_input (HttpRequest *request)
+{
+  char **lines;
+  char *p;
+  int num_key1, num_key2;
+  guint64 key1, key2;
+  int num_space;
+  int i;
+  guint8 challenge[16];
+  char *res;
+  gsize len;
+  GChecksum *checksum;
+  char *origin, *host;
+  GdkDisplayBroadway *display_broadway;
+
+  display_broadway = GDK_DISPLAY_BROADWAY (request->display);
+
+  if (display_broadway->input != NULL)
+    {
+      send_error (request, 409, "Input already handled");
+      return;
+    }
+
+  lines = g_strsplit (request->request->str, "\n", 0);
+
+  num_key1 = 0;
+  num_key2 = 0;
+  key1 = 0;
+  key2 = 0;
+  origin = NULL;
+  host = NULL;
+  for (i = 0; lines[i] != NULL; i++)
+    {
+      if ((p = parse_line (lines[i], "Sec-WebSocket-Key1")))
+       {
+         num_space = 0;
+         while (*p != 0)
+           {
+             if (g_ascii_isdigit (*p))
+               key1 = key1 * 10 + g_ascii_digit_value (*p);
+             else if (*p == ' ')
+               num_space++;
+
+             p++;
+           }
+         key1 /= num_space;
+         num_key1++;
+       }
+      else if ((p = parse_line (lines[i], "Sec-WebSocket-Key2")))
+       {
+         num_space = 0;
+         while (*p != 0)
+           {
+             if (g_ascii_isdigit (*p))
+               key2 = key2 * 10 + g_ascii_digit_value (*p);
+             else if (*p == ' ')
+               num_space++;
+
+             p++;
+           }
+         key2 /= num_space;
+         num_key2++;
+       }
+      else if ((p = parse_line (lines[i], "Origin")))
+       {
+         origin = p;
+       }
+      else if ((p = parse_line (lines[i], "Host")))
+       {
+         host = p;
+       }
+    }
+
+  if (num_key1 != 1 || num_key2 != 1 || origin == NULL || host == NULL)
+    {
+      g_strfreev (lines);
+      send_error (request, 400, "Bad websocket request");
+      return;
+    }
+
+  challenge[0] = (key1 >> 24) & 0xff;
+  challenge[1] = (key1 >> 16) & 0xff;
+  challenge[2] = (key1 >>  8) & 0xff;
+  challenge[3] = (key1 >>  0) & 0xff;
+  challenge[4] = (key2 >> 24) & 0xff;
+  challenge[5] = (key2 >> 16) & 0xff;
+  challenge[6] = (key2 >>  8) & 0xff;
+  challenge[7] = (key2 >>  0) & 0xff;
+
+  if (!g_input_stream_read_all (G_INPUT_STREAM (request->data), challenge+8, 8, NULL, NULL, NULL))
+    {
+      g_strfreev (lines);
+      send_error (request, 400, "Bad websocket request");
+      return;
+    }
+
+  checksum = g_checksum_new (G_CHECKSUM_MD5);
+  g_checksum_update (checksum, challenge, 16);
+  len = 16;
+  g_checksum_get_digest (checksum, challenge, &len);
+  g_checksum_free (checksum);
+
+  res = g_strdup_printf ("HTTP/1.1 101 WebSocket Protocol Handshake\r\n"
+                        "Upgrade: WebSocket\r\n"
+                        "Connection: Upgrade\r\n"
+                        "Sec-WebSocket-Origin: %s\r\n"
+                        "Sec-WebSocket-Location: ws://%s/input\r\n"
+                        "Sec-WebSocket-Protocol: broadway\r\n"
+                        "\r\n",
+                        origin, host);
+
+  /* TODO: This should really be async */
+  g_output_stream_write_all (g_io_stream_get_output_stream (G_IO_STREAM (request->connection)),
+                            res, strlen (res), NULL, NULL, NULL);
+  g_free (res);
+  g_output_stream_write_all (g_io_stream_get_output_stream (G_IO_STREAM (request->connection)),
+                            challenge, 16, NULL, NULL, NULL);
+
+  display_broadway->input = request;
+
+  g_data_input_stream_read_upto_async (request->data, "\xff", 1, 0, NULL,
+                                      (GAsyncReadyCallback)got_input, request);
+
+  g_strfreev (lines);
+}
+
+static void
+start_output (HttpRequest *request)
+{
+  GSocket *socket;
+  GdkDisplayBroadway *display_broadway;
+  int fd;
+
+  socket = g_socket_connection_get_socket (request->connection);
+
+  display_broadway = GDK_DISPLAY_BROADWAY (request->display);
+  fd = g_socket_get_fd (socket);
+  set_fd_blocking (fd);
+  /* We dup this because otherwise it'll be closed with the request SocketConnection */
+  display_broadway->output = broadway_output_new (dup(fd));
+  _gdk_broadway_resync_windows ();
+  http_request_free (request);
+}
+
+static void
+send_data (HttpRequest *request,
+            const char *mimetype,
+            const char *data, gsize len)
+{
+  char *res;
+
+  res = g_strdup_printf ("HTTP/1.0 200 OK\r\n"
+                        "Content-Type: %s\r\n"
+                        "Content-Length: %"G_GSIZE_FORMAT"\r\n"
+                        "\r\n",
+                        mimetype, len);
+  /* TODO: This should really be async */
+  g_output_stream_write_all (g_io_stream_get_output_stream (G_IO_STREAM (request->connection)),
+                            res, strlen (res), NULL, NULL, NULL);
+  g_free (res);
+  g_output_stream_write_all (g_io_stream_get_output_stream (G_IO_STREAM (request->connection)),
+                            data, len, NULL, NULL, NULL);
+  http_request_free (request);
+}
+
+#include "clienthtml.h"
+#include "broadwayjs.h"
+
+static void
+got_request (HttpRequest *request)
+{
+  char *start, *escaped, *tmp, *version;
+
+  if (!g_str_has_prefix (request->request->str, "GET "))
+    {
+      send_error (request, 501, "Only GET implemented");
+      return;
+    }
+
+  start = request->request->str + 4; /* Skip "GET " */
+
+  while (*start == ' ')
+    start++;
+
+  for (tmp = start; *tmp != 0 && *tmp != ' ' && *tmp != '\n'; tmp++)
+    ;
+  escaped = g_strndup (start, tmp - start);
+  version = NULL;
+  if (*tmp == ' ')
+    {
+      start = tmp;
+      while (*start == ' ')
+       start++;
+      for (tmp = start; *tmp != 0 && *tmp != ' ' && *tmp != '\n'; tmp++)
+       ;
+      version = g_strndup (start, tmp - start);
+    }
+
+  if (strcmp (escaped, "/client.html") == 0 || strcmp (escaped, "/") == 0)
+    send_data (request, "text/html", client_html, G_N_ELEMENTS(client_html) - 1);
+  else if (strcmp (escaped, "/broadway.js") == 0)
+    send_data (request, "text/javascript", broadway_js, G_N_ELEMENTS(broadway_js) - 1);
+  else if (strcmp (escaped, "/output") == 0)
+    start_output (request);
+  else if (strcmp (escaped, "/input") == 0)
+    start_input (request);
+  else
+    send_error (request, 404, "File not found");
+}
+
+static void
+got_http_request_line (GInputStream *stream,
+                      GAsyncResult *result,
+                      HttpRequest *request)
+{
+  char *line;
+
+  line = g_data_input_stream_read_line_finish (G_DATA_INPUT_STREAM (stream), result, NULL, NULL);
+  if (line == NULL)
+    {
+      http_request_free (request);
+      g_printerr ("Error reading request lines\n");
+      return;
+    }
+  if (strlen (line) == 0)
+    got_request (request);
+  else
+    {
+      /* Protect against overflow in request length */
+      if (request->request->len > 1024 * 5)
+       {
+         send_error (request, 400, "Request to long");
+       }
+      else
+       {
+         g_string_append_printf (request->request, "%s\n", line);
+         g_data_input_stream_read_line_async (request->data, 0, NULL,
+                                              (GAsyncReadyCallback)got_http_request_line, request);
+       }
+    }
+  g_free (line);
+}
+
+static gboolean
+handle_incoming_connection (GSocketService    *service,
+                           GSocketConnection *connection,
+                           GObject           *source_object)
+{
+  HttpRequest *request;
+  GInputStream *in;
+
+  request = g_new0 (HttpRequest, 1);
+  request->connection = g_object_ref (connection);
+  request->display = (GdkDisplay *) source_object;
+  request->request = g_string_new ("");
+
+  in = g_io_stream_get_input_stream (G_IO_STREAM (connection));
+
+  request->data = g_data_input_stream_new (in);
+  g_filter_input_stream_set_close_base_stream (G_FILTER_INPUT_STREAM (request->data), FALSE);
+  /* Be tolerant of input */
+  g_data_input_stream_set_newline_type (request->data, G_DATA_STREAM_NEWLINE_TYPE_ANY);
+
+  g_data_input_stream_read_line_async (request->data, 0, NULL,
+                                      (GAsyncReadyCallback)got_http_request_line, request);
+  return TRUE;
+}
+
+GdkDisplay *
+gdk_display_open (const gchar *display_name)
+{
+  GdkDisplay *display;
+  GdkDisplayBroadway *display_broadway;
+  const char *sm_client_id;
+  GError *error;
+
+  display = g_object_new (GDK_TYPE_DISPLAY_BROADWAY, NULL);
+  display_broadway = GDK_DISPLAY_BROADWAY (display);
+
+  display_broadway->output = NULL;
+
+  /* initialize the display's screens */
+  display_broadway->screens = g_new (GdkScreen *, 1);
+  display_broadway->screens[0] = _gdk_broadway_screen_new (display, 0);
+
+  /* We need to initialize events after we have the screen
+   * structures in places
+   */
+  _gdk_screen_broadway_events_init (display_broadway->screens[0]);
+
+  /*set the default screen */
+  display_broadway->default_screen = display_broadway->screens[0];
+
+  display->device_manager = _gdk_device_manager_new (display);
+
+  _gdk_event_init (display);
+
+  sm_client_id = _gdk_get_sm_client_id ();
+  if (sm_client_id)
+    _gdk_windowing_display_set_sm_client_id (display, sm_client_id);
+
+  _gdk_input_init (display);
+  _gdk_dnd_init (display);
+
+  _gdk_broadway_screen_setup (display_broadway->screens[0]);
+
+  display_broadway->service = g_socket_service_new ();
+  if (!g_socket_listener_add_inet_port (G_SOCKET_LISTENER (display_broadway->service),
+                                       8080,
+                                       G_OBJECT (display),
+                                       &error))
+    {
+      g_printerr ("Unable to listen to port %d: %s\n", 8080, error->message);
+      g_error_free (error);
+      return NULL;
+    }
+  g_signal_connect (display_broadway->service, "incoming", G_CALLBACK (handle_incoming_connection), NULL);
+
+  g_signal_emit_by_name (display, "opened");
+  g_signal_emit_by_name (gdk_display_manager_get (), "display-opened", display);
+
+  return display;
+}
+
+
+G_CONST_RETURN gchar *
+gdk_display_get_name (GdkDisplay *display)
+{
+  g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
+
+  return (gchar *) "Broadway";
+}
+
+gint
+gdk_display_get_n_screens (GdkDisplay *display)
+{
+  g_return_val_if_fail (GDK_IS_DISPLAY (display), 0);
+
+  return 1;
+}
+
+GdkScreen *
+gdk_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_BROADWAY (display)->screens[screen_num];
+}
+
+GdkScreen *
+gdk_display_get_default_screen (GdkDisplay *display)
+{
+  g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
+
+  return GDK_DISPLAY_BROADWAY (display)->default_screen;
+}
+
+void
+gdk_device_ungrab (GdkDevice  *device,
+                   guint32     time_)
+{
+}
+
+void
+gdk_display_beep (GdkDisplay *display)
+{
+  g_return_if_fail (GDK_IS_DISPLAY (display));
+}
+
+void
+gdk_display_sync (GdkDisplay *display)
+{
+  g_return_if_fail (GDK_IS_DISPLAY (display));
+
+}
+
+void
+gdk_display_flush (GdkDisplay *display)
+{
+  g_return_if_fail (GDK_IS_DISPLAY (display));
+
+}
+
+GdkWindow *
+gdk_display_get_default_group (GdkDisplay *display)
+{
+  g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
+
+  return NULL;
+}
+
+void
+gdk_broadway_display_grab (GdkDisplay *display)
+{
+}
+
+void
+gdk_broadway_display_ungrab (GdkDisplay *display)
+{
+}
+
+static void
+gdk_display_broadway_dispose (GObject *object)
+{
+  GdkDisplayBroadway *display_broadway = GDK_DISPLAY_BROADWAY (object);
+
+  g_list_foreach (display_broadway->input_devices, (GFunc) g_object_run_dispose, NULL);
+
+  _gdk_screen_close (display_broadway->screens[0]);
+
+  if (display_broadway->event_source)
+    {
+      g_source_destroy (display_broadway->event_source);
+      g_source_unref (display_broadway->event_source);
+      display_broadway->event_source = NULL;
+    }
+
+  G_OBJECT_CLASS (_gdk_display_broadway_parent_class)->dispose (object);
+}
+
+static void
+gdk_display_broadway_finalize (GObject *object)
+{
+  GdkDisplayBroadway *display_broadway = GDK_DISPLAY_BROADWAY (object);
+
+  /* Keymap */
+  if (display_broadway->keymap)
+    g_object_unref (display_broadway->keymap);
+
+  _gdk_broadway_cursor_display_finalize (GDK_DISPLAY_OBJECT(display_broadway));
+
+  /* Atom Hashtable */
+  g_hash_table_destroy (display_broadway->atom_from_virtual);
+  g_hash_table_destroy (display_broadway->atom_to_virtual);
+
+  /* input GdkDevice list */
+  g_list_foreach (display_broadway->input_devices, (GFunc) g_object_unref, NULL);
+  g_list_free (display_broadway->input_devices);
+  /* Free all GdkScreens */
+  g_object_unref (display_broadway->screens[0]);
+  g_free (display_broadway->screens);
+
+  G_OBJECT_CLASS (_gdk_display_broadway_parent_class)->finalize (object);
+}
+
+void
+_gdk_windowing_set_default_display (GdkDisplay *display)
+{
+}
+
+void
+gdk_notify_startup_complete (void)
+{
+}
+
+void
+gdk_notify_startup_complete_with_id (const gchar* startup_id)
+{
+}
+
+gboolean
+gdk_display_supports_selection_notification (GdkDisplay *display)
+{
+  return FALSE;
+}
+
+gboolean
+gdk_display_request_selection_notification (GdkDisplay *display,
+                                           GdkAtom     selection)
+
+{
+    return FALSE;
+}
+
+gboolean
+gdk_display_supports_clipboard_persistence (GdkDisplay *display)
+{
+  return FALSE;
+}
+
+void
+gdk_display_store_clipboard (GdkDisplay    *display,
+                            GdkWindow     *clipboard_window,
+                            guint32        time_,
+                            const GdkAtom *targets,
+                            gint           n_targets)
+{
+}
+
+guint32
+gdk_broadway_display_get_user_time (GdkDisplay *display)
+{
+  return GDK_DISPLAY_BROADWAY (display)->user_time;
+}
+
+gboolean
+gdk_display_supports_shapes (GdkDisplay *display)
+{
+  return FALSE;
+}
+
+gboolean
+gdk_display_supports_input_shapes (GdkDisplay *display)
+{
+  return FALSE;
+}
+
+gboolean
+gdk_display_supports_composite (GdkDisplay *display)
+{
+  return FALSE;
+}
+
+GList *
+gdk_display_list_devices (GdkDisplay *display)
+{
+  g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
+
+  return GDK_DISPLAY_BROADWAY (display)->input_devices;
+}
+
+gboolean
+gdk_event_send_client_message_for_display (GdkDisplay     *display,
+                                          GdkEvent       *event,
+                                          GdkNativeWindow winid)
+{
+  return FALSE;
+}
+
+void
+gdk_display_add_client_message_filter (GdkDisplay   *display,
+                                      GdkAtom       message_type,
+                                      GdkFilterFunc func,
+                                      gpointer      data)
+{
+}
+
+void
+gdk_add_client_message_filter (GdkAtom       message_type,
+                              GdkFilterFunc func,
+                              gpointer      data)
+{
+}
+
+void
+gdk_flush (void)
+{
+  GSList *tmp_list = _gdk_displays;
+
+  while (tmp_list)
+    {
+      gdk_display_flush (GDK_DISPLAY_OBJECT (tmp_list->data));
+      tmp_list = tmp_list->next;
+    }
+}
+
+gulong
+_gdk_windowing_window_get_next_serial (GdkDisplay *display)
+{
+  return 0;
+}
diff --git a/gdk/broadway/gdkdisplay-broadway.h b/gdk/broadway/gdkdisplay-broadway.h
new file mode 100644 (file)
index 0000000..160416d
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * gdkdisplay-broadway.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_BROADWAY__
+#define __GDK_DISPLAY_BROADWAY__
+
+#include <gdk/gdkdisplay.h>
+#include <gdk/gdkkeys.h>
+#include <gdk/gdkwindow.h>
+#include <gdk/gdkinternals.h>
+#include <gdk/gdkmain.h>
+#include "broadway.h"
+
+G_BEGIN_DECLS
+
+typedef struct _GdkDisplayBroadway GdkDisplayBroadway;
+typedef struct _GdkDisplayBroadwayClass GdkDisplayBroadwayClass;
+
+#define GDK_TYPE_DISPLAY_BROADWAY              (_gdk_display_broadway_get_type())
+#define GDK_DISPLAY_BROADWAY(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_DISPLAY_BROADWAY, GdkDisplayBroadway))
+#define GDK_DISPLAY_BROADWAY_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_DISPLAY_BROADWAY, GdkDisplayBroadwayClass))
+#define GDK_IS_DISPLAY_BROADWAY(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_DISPLAY_BROADWAY))
+#define GDK_IS_DISPLAY_BROADWAY_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_DISPLAY_BROADWAY))
+#define GDK_DISPLAY_BROADWAY_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_DISPLAY_BROADWAY, GdkDisplayBroadwayClass))
+
+typedef  struct HttpRequest HttpRequest;
+
+struct _GdkDisplayBroadway
+{
+  GdkDisplay parent_instance;
+  GdkScreen *default_screen;
+  GdkScreen **screens;
+
+  GHashTable *id_ht;
+  GList *toplevels;
+
+  GSource *event_source;
+  GdkWindow *mouse_in_toplevel;
+  int last_x, last_y;
+
+  gint grab_count;
+
+  /* Keyboard related information */
+  GdkKeymap *keymap;
+
+  /* drag and drop information */
+  GdkDragContext *current_dest_drag;
+
+  /* Mapping to/from virtual atoms */
+
+  GHashTable *atom_from_virtual;
+  GHashTable *atom_to_virtual;
+
+  /* Input device */
+  /* input GdkDevice list */
+  GList *input_devices;
+
+  /* Time of most recent user interaction. */
+  gulong user_time;
+
+  /* The offscreen window that has the pointer in it (if any) */
+  GdkWindow *active_offscreen_window;
+
+  GSocketService *service;
+  BroadwayOutput *output;
+  HttpRequest *input;
+};
+
+struct _GdkDisplayBroadwayClass
+{
+  GdkDisplayClass parent_class;
+};
+
+GType      _gdk_display_broadway_get_type            (void);
+
+G_END_DECLS
+
+#endif                         /* __GDK_DISPLAY_BROADWAY__ */
diff --git a/gdk/broadway/gdkdnd-broadway.c b/gdk/broadway/gdkdnd-broadway.c
new file mode 100644 (file)
index 0000000..14fd172
--- /dev/null
@@ -0,0 +1,229 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1999 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"
+
+#include "gdkdnd.h"
+
+#include "gdkmain.h"
+#include "gdkproperty.h"
+#include "gdkprivate-broadway.h"
+#include "gdkinternals.h"
+#include "gdkscreen-broadway.h"
+#include "gdkdisplay-broadway.h"
+
+#include <string.h>
+
+typedef struct _GdkDragContextPrivateBroadway GdkDragContextPrivateBroadway;
+
+/* Structure that holds information about a drag in progress.
+ * this is used on both source and destination sides.
+ */
+struct _GdkDragContextPrivateBroadway {
+  GdkDragContext context;
+};
+
+#define PRIVATE_DATA(context) ((GdkDragContextPrivateBroadway *) GDK_DRAG_CONTEXT (context)->windowing_data)
+
+static void gdk_drag_context_finalize (GObject *object);
+
+static GList *contexts;
+
+G_DEFINE_TYPE (GdkDragContext, gdk_drag_context, G_TYPE_OBJECT)
+
+static void
+gdk_drag_context_init (GdkDragContext *dragcontext)
+{
+  GdkDragContextPrivateBroadway *private;
+
+  private = G_TYPE_INSTANCE_GET_PRIVATE (dragcontext,
+                                        GDK_TYPE_DRAG_CONTEXT,
+                                        GdkDragContextPrivateBroadway);
+
+  dragcontext->windowing_data = private;
+
+  contexts = g_list_prepend (contexts, dragcontext);
+}
+
+static void
+gdk_drag_context_class_init (GdkDragContextClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = gdk_drag_context_finalize;
+
+  g_type_class_add_private (object_class, sizeof (GdkDragContextPrivateBroadway));
+}
+
+static void
+gdk_drag_context_finalize (GObject *object)
+{
+  GdkDragContext *context = GDK_DRAG_CONTEXT (object);
+
+  contexts = g_list_remove (contexts, context);
+
+  G_OBJECT_CLASS (gdk_drag_context_parent_class)->finalize (object);
+}
+
+/* Drag Contexts */
+
+GdkDragContext *
+gdk_drag_context_new (void)
+{
+  return g_object_new (GDK_TYPE_DRAG_CONTEXT, NULL);
+}
+
+void
+gdk_drag_context_set_device (GdkDragContext *context,
+                             GdkDevice      *device)
+{
+  g_return_if_fail (GDK_IS_DRAG_CONTEXT (context));
+  g_return_if_fail (GDK_IS_DEVICE (device));
+}
+
+GdkDevice *
+gdk_drag_context_get_device (GdkDragContext *context)
+{
+  g_return_val_if_fail (GDK_IS_DRAG_CONTEXT (context), NULL);
+
+  return NULL;
+}
+
+GdkDragContext * 
+gdk_drag_begin (GdkWindow     *window,
+               GList         *targets)
+{
+  GdkDragContext *new_context;
+
+  g_return_val_if_fail (window != NULL, NULL);
+  g_return_val_if_fail (GDK_WINDOW_IS_BROADWAY (window), NULL);
+
+  new_context = gdk_drag_context_new ();
+
+  return new_context;
+}
+
+GdkNativeWindow
+gdk_drag_get_protocol_for_display (GdkDisplay      *display,
+                                  GdkNativeWindow  xid,
+                                  GdkDragProtocol *protocol)
+{
+  return 0;
+}
+
+void
+gdk_drag_find_window_for_screen (GdkDragContext  *context,
+                                GdkWindow       *drag_window,
+                                GdkScreen       *screen,
+                                gint             x_root,
+                                gint             y_root,
+                                GdkWindow      **dest_window,
+                                GdkDragProtocol *protocol)
+{
+  g_return_if_fail (context != NULL);
+}
+
+gboolean
+gdk_drag_motion (GdkDragContext *context,
+                GdkWindow      *dest_window,
+                GdkDragProtocol protocol,
+                gint            x_root,
+                gint            y_root,
+                GdkDragAction   suggested_action,
+                GdkDragAction   possible_actions,
+                guint32         time)
+{
+  g_return_val_if_fail (context != NULL, FALSE);
+  g_return_val_if_fail (dest_window == NULL || GDK_WINDOW_IS_BROADWAY (dest_window), FALSE);
+
+  return FALSE;
+}
+
+void
+gdk_drag_drop (GdkDragContext *context,
+              guint32         time)
+{
+  g_return_if_fail (context != NULL);
+}
+
+void
+gdk_drag_abort (GdkDragContext *context,
+               guint32         time)
+{
+  g_return_if_fail (context != NULL);
+}
+
+/* Destination side */
+
+void
+gdk_drag_status (GdkDragContext   *context,
+                GdkDragAction     action,
+                guint32           time)
+{
+  g_return_if_fail (context != NULL);
+}
+
+void
+gdk_drop_reply (GdkDragContext   *context,
+               gboolean          ok,
+               guint32           time)
+{
+  g_return_if_fail (context != NULL);
+}
+
+void
+gdk_drop_finish (GdkDragContext   *context,
+                gboolean          success,
+                guint32           time)
+{
+  g_return_if_fail (context != NULL);
+}
+
+void
+gdk_window_register_dnd (GdkWindow      *window)
+{
+}
+
+GdkAtom
+gdk_drag_get_selection (GdkDragContext *context)
+{
+  g_return_val_if_fail (context != NULL, GDK_NONE);
+
+  return GDK_NONE;
+}
+
+gboolean
+gdk_drag_drop_succeeded (GdkDragContext *context)
+{
+  g_return_val_if_fail (context != NULL, FALSE);
+
+  return FALSE;
+}
+
+void
+_gdk_dnd_init (GdkDisplay *display)
+{
+}
diff --git a/gdk/broadway/gdkdrawable-broadway.c b/gdk/broadway/gdkdrawable-broadway.c
new file mode 100644 (file)
index 0000000..a07b722
--- /dev/null
@@ -0,0 +1,185 @@
+/* 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"
+
+#include "gdkdrawable-broadway.h"
+
+#include "gdkprivate-broadway.h"
+#include "gdkscreen-broadway.h"
+#include "gdkdisplay-broadway.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+
+static cairo_surface_t *gdk_broadway_ref_cairo_surface (GdkDrawable *drawable);
+
+static const cairo_user_data_key_t gdk_broadway_cairo_key;
+
+G_DEFINE_TYPE (GdkDrawableImplBroadway, _gdk_drawable_impl_broadway, GDK_TYPE_DRAWABLE)
+
+static void
+_gdk_drawable_impl_broadway_class_init (GdkDrawableImplBroadwayClass *klass)
+{
+  GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
+
+  drawable_class->ref_cairo_surface = gdk_broadway_ref_cairo_surface;
+  drawable_class->create_cairo_surface = NULL;
+}
+
+static void
+_gdk_drawable_impl_broadway_init (GdkDrawableImplBroadway *impl)
+{
+}
+
+/**
+ * _gdk_broadway_drawable_finish:
+ * @drawable: a #GdkDrawableImplBroadway.
+ * 
+ * Performs necessary cleanup prior to destroying a window.
+ **/
+void
+_gdk_broadway_drawable_finish (GdkDrawable *drawable)
+{
+  GdkDrawableImplBroadway *impl = GDK_DRAWABLE_IMPL_BROADWAY (drawable);
+
+  if (impl->ref_surface)
+    {
+      cairo_surface_finish (impl->ref_surface);
+      cairo_surface_set_user_data (impl->ref_surface, &gdk_broadway_cairo_key,
+                                  NULL, NULL);
+    }
+
+  if (impl->surface)
+    {
+      cairo_surface_destroy (impl->surface);
+      impl->surface = NULL;
+      cairo_surface_destroy (impl->last_surface);
+      impl->last_surface = NULL;
+    }
+}
+
+/**
+ * _gdk_broadway_drawable_update_size:
+ * @drawable: a #GdkDrawableImplBroadway.
+ *
+ * Updates the state of the drawable (in particular the drawable's
+ * cairo surface) when its size has changed.
+ **/
+void
+_gdk_broadway_drawable_update_size (GdkDrawable *drawable)
+{
+  GdkDrawableImplBroadway *impl = GDK_DRAWABLE_IMPL_BROADWAY (drawable);
+  cairo_surface_t *old, *last_old;
+
+  if (impl->surface)
+    {
+      old = impl->surface;
+      last_old = impl->last_surface;
+
+      impl->surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
+                                                 gdk_window_get_width (impl->wrapper),
+                                                 gdk_window_get_height (impl->wrapper));
+      impl->last_surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
+                                                      gdk_window_get_width (impl->wrapper),
+                                                      gdk_window_get_height (impl->wrapper));
+
+      /* TODO: copy old contents */
+
+      cairo_surface_destroy (old);
+      cairo_surface_destroy (last_old);
+    }
+
+  if (impl->ref_surface)
+    {
+      cairo_surface_set_user_data (impl->ref_surface, &gdk_broadway_cairo_key,
+                                  NULL, NULL);
+      impl->ref_surface = NULL;
+    }
+}
+
+/*****************************************************
+ * Broadway specific implementations of generic functions *
+ *****************************************************/
+
+static void
+gdk_broadway_cairo_surface_destroy (void *data)
+{
+  GdkDrawableImplBroadway *impl = data;
+
+  impl->ref_surface = NULL;
+}
+
+static cairo_surface_t *
+gdk_broadway_ref_cairo_surface (GdkDrawable *drawable)
+{
+  GdkDrawableImplBroadway *impl = GDK_DRAWABLE_IMPL_BROADWAY (drawable);
+  cairo_t *cr;
+  int w, h;
+
+  if (GDK_IS_WINDOW_IMPL_BROADWAY (drawable) &&
+      GDK_WINDOW_DESTROYED (impl->wrapper))
+    return NULL;
+
+  w = gdk_window_get_width (impl->wrapper);
+  h = gdk_window_get_height (impl->wrapper);
+
+  /* Create actual backing store if missing */
+  if (!impl->surface)
+    {
+      impl->surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, w, h);
+      impl->last_surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, w, h);
+
+      cr = cairo_create (impl->surface);
+      cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
+      cairo_rectangle (cr, 0, 0, w, h);
+      cairo_fill (cr);
+      cairo_destroy (cr);
+
+      cr = cairo_create (impl->last_surface);
+      cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
+      cairo_rectangle (cr, 0, 0, w, h);
+      cairo_fill (cr);
+      cairo_destroy (cr);
+    }
+
+  /* Create a destroyable surface referencing the real one */
+  if (!impl->ref_surface)
+    {
+      impl->ref_surface =
+       cairo_surface_create_for_rectangle (impl->surface,
+                                           0, 0,
+                                           w, h);
+      if (impl->ref_surface)
+       cairo_surface_set_user_data (impl->ref_surface, &gdk_broadway_cairo_key,
+                                    drawable, gdk_broadway_cairo_surface_destroy);
+    }
+  else
+    cairo_surface_reference (impl->ref_surface);
+
+  return impl->ref_surface;
+}
diff --git a/gdk/broadway/gdkdrawable-broadway.h b/gdk/broadway/gdkdrawable-broadway.h
new file mode 100644 (file)
index 0000000..2a5b279
--- /dev/null
@@ -0,0 +1,74 @@
+/* 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_DRAWABLE_BROADWAY_H__
+#define __GDK_DRAWABLE_BROADWAY_H__
+
+#include <gdk/gdkdrawable.h>
+
+G_BEGIN_DECLS
+
+/* Drawable implementation for Broadway
+ */
+
+typedef struct _GdkDrawableImplBroadway GdkDrawableImplBroadway;
+typedef struct _GdkDrawableImplBroadwayClass GdkDrawableImplBroadwayClass;
+
+#define GDK_TYPE_DRAWABLE_IMPL_BROADWAY              (_gdk_drawable_impl_broadway_get_type ())
+#define GDK_DRAWABLE_IMPL_BROADWAY(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_DRAWABLE_IMPL_BROADWAY, GdkDrawableImplBroadway))
+#define GDK_DRAWABLE_IMPL_BROADWAY_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_DRAWABLE_IMPL_BROADWAY, GdkDrawableImplBroadwayClass))
+#define GDK_IS_DRAWABLE_IMPL_BROADWAY(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_DRAWABLE_IMPL_BROADWAY))
+#define GDK_IS_DRAWABLE_IMPL_BROADWAY_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_DRAWABLE_IMPL_BROADWAY))
+#define GDK_DRAWABLE_IMPL_BROADWAY_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_DRAWABLE_IMPL_BROADWAY, GdkDrawableImplBroadwayClass))
+
+struct _GdkDrawableImplBroadway
+{
+  GdkDrawable parent_instance;
+
+  GdkDrawable *wrapper;
+
+  GdkScreen *screen;
+  cairo_surface_t *surface;
+  cairo_surface_t *last_surface;
+  cairo_surface_t *ref_surface;
+};
+
+struct _GdkDrawableImplBroadwayClass
+{
+  GdkDrawableClass parent_class;
+
+};
+
+GType _gdk_drawable_impl_broadway_get_type (void);
+
+/* Note that the following take GdkDrawableImplBroadway, not the wrapper drawable */
+void _gdk_broadway_drawable_finish           (GdkDrawable  *drawable);
+void _gdk_broadway_drawable_update_size      (GdkDrawable  *drawable);
+GdkDrawable *gdk_broadway_window_get_drawable_impl (GdkWindow *window);
+
+G_END_DECLS
+
+#endif /* __GDK_DRAWABLE_BROADWAY_H__ */
diff --git a/gdk/broadway/gdkeventsource.c b/gdk/broadway/gdkeventsource.c
new file mode 100644 (file)
index 0000000..548f58b
--- /dev/null
@@ -0,0 +1,367 @@
+/* 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 "gdkeventsource.h"
+
+#include "gdkinternals.h"
+
+#include <stdlib.h>
+
+static gboolean gdk_event_source_prepare  (GSource     *source,
+                                           gint        *timeout);
+static gboolean gdk_event_source_check    (GSource     *source);
+static gboolean gdk_event_source_dispatch (GSource     *source,
+                                           GSourceFunc  callback,
+                                           gpointer     user_data);
+static void     gdk_event_source_finalize (GSource     *source);
+
+#define HAS_FOCUS(toplevel)                           \
+  ((toplevel)->has_focus || (toplevel)->has_pointer_focus)
+
+struct _GdkEventSource
+{
+  GSource source;
+
+  GdkDisplay *display;
+  GPollFD event_poll_fd;
+};
+
+static GSourceFuncs event_funcs = {
+  gdk_event_source_prepare,
+  gdk_event_source_check,
+  gdk_event_source_dispatch,
+  gdk_event_source_finalize
+};
+
+static GList *event_sources = NULL;
+
+static gboolean
+gdk_event_source_prepare (GSource *source,
+                          gint    *timeout)
+{
+  GdkDisplay *display = ((GdkEventSource*) source)->display;
+  gboolean retval;
+
+  GDK_THREADS_ENTER ();
+
+  *timeout = -1;
+  retval = (_gdk_event_queue_find_first (display) != NULL);
+
+  GDK_THREADS_LEAVE ();
+
+  return retval;
+}
+
+static gboolean
+gdk_event_source_check (GSource *source)
+{
+  GdkEventSource *event_source = (GdkEventSource*) source;
+  gboolean retval;
+
+  GDK_THREADS_ENTER ();
+
+  if (event_source->event_poll_fd.revents & G_IO_IN)
+    retval = (_gdk_event_queue_find_first (event_source->display) != NULL);
+  else
+    retval = FALSE;
+
+  GDK_THREADS_LEAVE ();
+
+  return retval;
+}
+
+void
+_gdk_events_got_input (GdkDisplay *display,
+                      const char *message)
+{
+  GdkDisplayBroadway *display_broadway = GDK_DISPLAY_BROADWAY (display);
+  GdkScreen *screen;
+  GdkWindow *root, *window;
+  char *p;
+  int x, y, button, id, dir,key;
+  guint64 time;
+  GdkEvent *event = NULL;
+  char cmd;
+  GList *node;
+
+  screen = gdk_display_get_default_screen (display);
+  root = gdk_screen_get_root_window (screen);
+
+  p = (char *)message;
+  cmd = *p++;
+  switch (cmd) {
+  case 'm':
+    id = strtol(p, &p, 10);
+    p++; /* Skip , */
+    x = strtol(p, &p, 10);
+    p++; /* Skip , */
+    y = strtol(p, &p, 10);
+    p++; /* Skip , */
+    time = strtol(p, &p, 10);
+    display_broadway->last_x = x;
+    display_broadway->last_y = y;
+
+    window = g_hash_table_lookup (display_broadway->id_ht, GINT_TO_POINTER (id));
+
+    if (display_broadway->mouse_in_toplevel != window)
+      {
+       if (display_broadway->mouse_in_toplevel != NULL)
+         {
+           event = gdk_event_new (GDK_LEAVE_NOTIFY);
+           event->crossing.window = g_object_ref (display_broadway->mouse_in_toplevel);
+           event->crossing.time = time;
+           event->crossing.x = x - GDK_WINDOW_OBJECT (display_broadway->mouse_in_toplevel)->x;
+           event->crossing.y = y - GDK_WINDOW_OBJECT (display_broadway->mouse_in_toplevel)->y;
+           event->crossing.x_root = x;
+           event->crossing.y_root = y;
+           event->crossing.mode = GDK_CROSSING_NORMAL;
+           event->crossing.detail = GDK_NOTIFY_ANCESTOR;
+           gdk_event_set_device (event, display->core_pointer);
+
+           node = _gdk_event_queue_append (display, event);
+           _gdk_windowing_got_event (display, node, event, 0);
+
+           event = gdk_event_new (GDK_FOCUS_CHANGE);
+           event->focus_change.window = g_object_ref (display_broadway->mouse_in_toplevel);
+           event->focus_change.in = FALSE;
+           gdk_event_set_device (event, display->core_pointer);
+
+           node = _gdk_event_queue_append (display, event);
+           _gdk_windowing_got_event (display, node, event, 0);
+         }
+
+       /* TODO: Unset when it dies */
+       display_broadway->mouse_in_toplevel = window;
+
+       if (window)
+         {
+           event = gdk_event_new (GDK_ENTER_NOTIFY);
+           event->crossing.window = g_object_ref (window);
+           event->crossing.time = time;
+           event->crossing.x = x - GDK_WINDOW_OBJECT (window)->x;
+           event->crossing.y = y - GDK_WINDOW_OBJECT (window)->y;
+           event->crossing.x_root = x;
+           event->crossing.y_root = y;
+           event->crossing.mode = GDK_CROSSING_NORMAL;
+           event->crossing.detail = GDK_NOTIFY_ANCESTOR;
+           gdk_event_set_device (event, display->core_pointer);
+
+           node = _gdk_event_queue_append (display, event);
+           _gdk_windowing_got_event (display, node, event, 0);
+
+           event = gdk_event_new (GDK_FOCUS_CHANGE);
+           event->focus_change.window = g_object_ref (window);
+           event->focus_change.in = TRUE;
+           gdk_event_set_device (event, display->core_pointer);
+
+           node = _gdk_event_queue_append (display, event);
+           _gdk_windowing_got_event (display, node, event, 0);
+
+         }
+      }
+
+    if (window)
+      {
+       event = gdk_event_new (GDK_MOTION_NOTIFY);
+       event->motion.window = g_object_ref (window);
+       event->motion.time = time;
+       event->motion.x = x - GDK_WINDOW_OBJECT (window)->x;
+       event->motion.y = y - GDK_WINDOW_OBJECT (window)->y;
+       event->motion.x_root = x;
+       event->motion.y_root = y;
+       gdk_event_set_device (event, display->core_pointer);
+
+       node = _gdk_event_queue_append (display, event);
+       _gdk_windowing_got_event (display, node, event, 0);
+      }
+
+    break;
+  case 'b':
+  case 'B':
+    id = strtol(p, &p, 10);
+    p++; /* Skip , */
+    x = strtol(p, &p, 10);
+    p++; /* Skip , */
+    y = strtol(p, &p, 10);
+    p++; /* Skip , */
+    button = strtol(p, &p, 10);
+    p++; /* Skip , */
+    time = strtol(p, &p, 10);
+    display_broadway->last_x = x;
+    display_broadway->last_y = y;
+
+    window = g_hash_table_lookup (display_broadway->id_ht, GINT_TO_POINTER (id));
+
+    if (window)
+      {
+       event = gdk_event_new (cmd == 'b' ? GDK_BUTTON_PRESS : GDK_BUTTON_RELEASE);
+       event->button.window = g_object_ref (window);
+       event->button.time = time;
+       event->button.x = x - GDK_WINDOW_OBJECT (window)->x;
+       event->button.y = y - GDK_WINDOW_OBJECT (window)->y;
+       event->button.x_root = x;
+       event->button.y_root = y;
+       event->button.button = button + 1;
+       gdk_event_set_device (event, display->core_pointer);
+
+       node = _gdk_event_queue_append (display, event);
+       _gdk_windowing_got_event (display, node, event, 0);
+      }
+
+    break;
+  case 's':
+    id = strtol(p, &p, 10);
+    p++; /* Skip , */
+    x = strtol(p, &p, 10);
+    p++; /* Skip , */
+    y = strtol(p, &p, 10);
+    p++; /* Skip , */
+    dir = strtol(p, &p, 10);
+    p++; /* Skip , */
+    time = strtol(p, &p, 10);
+    display_broadway->last_x = x;
+    display_broadway->last_y = y;
+
+    window = g_hash_table_lookup (display_broadway->id_ht, GINT_TO_POINTER (id));
+
+    if (window)
+      {
+       event = gdk_event_new (GDK_SCROLL);
+       event->scroll.window = g_object_ref (window);
+       event->scroll.time = time;
+       event->scroll.x = x - GDK_WINDOW_OBJECT (window)->x;
+       event->scroll.y = y - GDK_WINDOW_OBJECT (window)->y;
+       event->scroll.x_root = x;
+       event->scroll.y_root = y;
+       event->scroll.direction = dir == 0 ? GDK_SCROLL_UP : GDK_SCROLL_DOWN;
+       gdk_event_set_device (event, display->core_pointer);
+
+       node = _gdk_event_queue_append (display, event);
+       _gdk_windowing_got_event (display, node, event, 0);
+      }
+
+    break;
+  case 'k':
+  case 'K':
+    key = strtol(p, &p, 10);
+    p++; /* Skip , */
+    time = strtol(p, &p, 10);
+
+    window = display_broadway->mouse_in_toplevel;
+
+    if (window)
+      {
+       event = gdk_event_new (cmd == 'k' ? GDK_KEY_PRESS : GDK_KEY_RELEASE);
+       event->key.window = g_object_ref (window);
+       event->key.time = time;
+       event->key.keyval = key;
+       event->key.length = 0;
+       gdk_event_set_device (event, display->core_pointer);
+
+       node = _gdk_event_queue_append (display, event);
+       _gdk_windowing_got_event (display, node, event, 0);
+      }
+
+    break;
+  default:
+    g_print ("Unknown input command %s\n", message);
+    break;
+  }
+}
+
+void
+_gdk_events_queue (GdkDisplay *display)
+{
+}
+
+static gboolean
+gdk_event_source_dispatch (GSource     *source,
+                           GSourceFunc  callback,
+                           gpointer     user_data)
+{
+  GdkDisplay *display = ((GdkEventSource*) source)->display;
+  GdkEvent *event;
+
+  GDK_THREADS_ENTER ();
+
+  event = gdk_display_get_event (display);
+
+  if (event)
+    {
+      if (_gdk_event_func)
+       (*_gdk_event_func) (event, _gdk_event_data);
+
+      gdk_event_free (event);
+    }
+
+  GDK_THREADS_LEAVE ();
+
+  return TRUE;
+}
+
+static void
+gdk_event_source_finalize (GSource *source)
+{
+  GdkEventSource *event_source = (GdkEventSource *)source;
+
+  event_sources = g_list_remove (event_sources, event_source);
+}
+
+GSource *
+gdk_event_source_new (GdkDisplay *display)
+{
+  GSource *source;
+  GdkEventSource *event_source;
+  char *name;
+
+  source = g_source_new (&event_funcs, sizeof (GdkEventSource));
+  name = g_strdup_printf ("GDK Broadway Event source (%s)",
+                         gdk_display_get_name (display));
+  g_source_set_name (source, name);
+  g_free (name);
+  event_source = (GdkEventSource *) source;
+  event_source->display = display;
+
+  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;
+}
+
+gboolean
+gdk_events_pending (void)
+{
+  GList *tmp_list;
+
+  for (tmp_list = event_sources; tmp_list; tmp_list = tmp_list->next)
+    {
+      GdkEventSource *tmp_source = tmp_list->data;
+      GdkDisplay *display = tmp_source->display;
+
+      if (_gdk_event_queue_find_first (display))
+       return TRUE;
+    }
+
+  return FALSE;
+}
diff --git a/gdk/broadway/gdkeventsource.h b/gdk/broadway/gdkeventsource.h
new file mode 100644 (file)
index 0000000..ca3b9d6
--- /dev/null
@@ -0,0 +1,34 @@
+/* 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.
+ */
+
+#ifndef __GDK_EVENT_SOURCE_H__
+#define __GDK_EVENT_SOURCE_H__
+
+#include "gdkprivate-broadway.h"
+
+G_BEGIN_DECLS
+
+typedef struct _GdkEventSource GdkEventSource;
+
+G_GNUC_INTERNAL
+GSource * gdk_event_source_new            (GdkDisplay *display);
+
+G_END_DECLS
+
+#endif /* __GDK_EVENT_SOURCE_H__ */
diff --git a/gdk/broadway/gdkglobals-broadway.c b/gdk/broadway/gdkglobals-broadway.c
new file mode 100644 (file)
index 0000000..d2026ea
--- /dev/null
@@ -0,0 +1,33 @@
+/* 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"
+
+#include "gdktypes.h"
+#include "gdkprivate-broadway.h"
+
+#include <stdio.h>
+
diff --git a/gdk/broadway/gdkim-broadway.c b/gdk/broadway/gdkim-broadway.c
new file mode 100644 (file)
index 0000000..9863293
--- /dev/null
@@ -0,0 +1,49 @@
+/* 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"
+
+#include "gdkmain.h"
+#include "gdkinternals.h"
+#include "gdkdisplay-broadway.h"
+
+#include <locale.h>
+#include <stdlib.h>
+#include <string.h>
+
+void
+_gdk_broadway_initialize_locale (void)
+{
+}
+
+gchar*
+gdk_set_locale (void)
+{
+  if (!setlocale (LC_ALL,""))
+    g_warning ("locale not supported by C library");
+
+  return setlocale (LC_ALL, NULL);
+}
diff --git a/gdk/broadway/gdkinput.c b/gdk/broadway/gdkinput.c
new file mode 100644 (file)
index 0000000..ea55157
--- /dev/null
@@ -0,0 +1,69 @@
+/* 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"
+
+#include "gdkscreen-broadway.h"
+#include "gdkdisplay-broadway.h"
+#include "gdkwindow.h"
+
+#include <stdlib.h>
+
+
+/* Addition used for extension_events mask */
+#define GDK_ALL_DEVICES_MASK (1<<30)
+
+struct _GdkInputWindow
+{
+  GList *windows; /* GdkWindow:s with extension_events set */
+
+  /* gdk window */
+  GdkWindow *impl_window; /* an impl window */
+};
+
+
+GList *
+gdk_devices_list (void)
+{
+  return gdk_display_list_devices (gdk_display_get_default ());
+}
+
+void
+gdk_input_set_extension_events (GdkWindow        *window,
+                                gint              mask,
+                               GdkExtensionMode  mode)
+{
+}
+
+void
+_gdk_input_window_destroy (GdkWindow *window)
+{
+}
+
+void
+_gdk_input_check_extension_events (GdkDevice *device)
+{
+}
diff --git a/gdk/broadway/gdkkeys-broadway.c b/gdk/broadway/gdkkeys-broadway.c
new file mode 100644 (file)
index 0000000..b7e4cbb
--- /dev/null
@@ -0,0 +1,236 @@
+/* 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 "gdkprivate-broadway.h"
+#include "gdkinternals.h"
+#include "gdkdisplay-broadway.h"
+#include "gdkkeysyms.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <limits.h>
+#include <errno.h>
+
+typedef struct _GdkKeymapBroadway   GdkKeymapBroadway;
+typedef struct _GdkKeymapClass GdkKeymapBroadwayClass;
+
+#define GDK_TYPE_KEYMAP_BROADWAY          (gdk_keymap_broadway_get_type ())
+#define GDK_KEYMAP_BROADWAY(object)       (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_KEYMAP_BROADWAY, GdkKeymapBroadway))
+#define GDK_IS_KEYMAP_BROADWAY(object)    (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_KEYMAP_BROADWAY))
+
+typedef struct _DirectionCacheEntry DirectionCacheEntry;
+
+struct _GdkKeymapBroadway
+{
+  GdkKeymap     parent_instance;
+
+};
+
+#define KEYMAP_USE_XKB(keymap) GDK_DISPLAY_BROADWAY ((keymap)->display)->use_xkb
+#define KEYMAP_XDISPLAY(keymap) GDK_DISPLAY_XDISPLAY ((keymap)->display)
+
+static GType gdk_keymap_broadway_get_type   (void);
+static void  gdk_keymap_broadway_class_init (GdkKeymapBroadwayClass *klass);
+static void  gdk_keymap_broadway_init       (GdkKeymapBroadway      *keymap);
+static void  gdk_keymap_broadway_finalize   (GObject           *object);
+
+static GdkKeymapClass *parent_class = NULL;
+
+static GType
+gdk_keymap_broadway_get_type (void)
+{
+  static GType object_type = 0;
+
+  if (!object_type)
+    {
+      const GTypeInfo object_info =
+       {
+         sizeof (GdkKeymapClass),
+         (GBaseInitFunc) NULL,
+         (GBaseFinalizeFunc) NULL,
+         (GClassInitFunc) gdk_keymap_broadway_class_init,
+         NULL,           /* class_finalize */
+         NULL,           /* class_data */
+         sizeof (GdkKeymapBroadway),
+         0,              /* n_preallocs */
+         (GInstanceInitFunc) gdk_keymap_broadway_init,
+       };
+      
+      object_type = g_type_register_static (GDK_TYPE_KEYMAP,
+                                            g_intern_static_string ("GdkKeymapBroadway"),
+                                            &object_info, 0);
+    }
+  
+  return object_type;
+}
+
+static void
+gdk_keymap_broadway_class_init (GdkKeymapBroadwayClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  parent_class = g_type_class_peek_parent (klass);
+
+  object_class->finalize = gdk_keymap_broadway_finalize;
+}
+
+static void
+gdk_keymap_broadway_init (GdkKeymapBroadway *keymap)
+{
+}
+
+static void
+gdk_keymap_broadway_finalize (GObject *object)
+{
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+GdkKeymap*
+gdk_keymap_get_for_display (GdkDisplay *display)
+{
+  GdkDisplayBroadway *display_broadway;
+
+  g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
+  display_broadway = GDK_DISPLAY_BROADWAY (display);
+
+  if (!display_broadway->keymap)
+    display_broadway->keymap = g_object_new (gdk_keymap_broadway_get_type (), NULL);
+
+  display_broadway->keymap->display = display;
+
+  return display_broadway->keymap;
+}
+
+PangoDirection
+gdk_keymap_get_direction (GdkKeymap *keymap)
+{
+  return PANGO_DIRECTION_NEUTRAL;
+}
+
+gboolean
+gdk_keymap_have_bidi_layouts (GdkKeymap *keymap)
+{
+  return FALSE;
+}
+
+gboolean
+gdk_keymap_get_caps_lock_state (GdkKeymap *keymap)
+{
+  return FALSE;
+}
+
+gboolean
+gdk_keymap_get_num_lock_state (GdkKeymap *keymap)
+{
+  return FALSE;
+}
+
+gboolean
+gdk_keymap_get_entries_for_keyval (GdkKeymap     *keymap,
+                                   guint          keyval,
+                                   GdkKeymapKey **keys,
+                                   gint          *n_keys)
+{
+  *n_keys = 0;
+  return FALSE;
+}
+
+gboolean
+gdk_keymap_get_entries_for_keycode (GdkKeymap     *keymap,
+                                    guint          hardware_keycode,
+                                    GdkKeymapKey **keys,
+                                    guint        **keyvals,
+                                    gint          *n_entries)
+{
+  *n_entries = 0;
+  return FALSE;
+}
+
+guint
+gdk_keymap_lookup_key (GdkKeymap          *keymap,
+                       const GdkKeymapKey *key)
+{
+  return 0;
+}
+
+
+gboolean
+gdk_keymap_translate_keyboard_state (GdkKeymap       *keymap,
+                                     guint            hardware_keycode,
+                                     GdkModifierType  state,
+                                     gint             group,
+                                     guint           *keyval,
+                                     gint            *effective_group,
+                                     gint            *level,
+                                     GdkModifierType *consumed_modifiers)
+{
+  return FALSE;
+}
+
+
+/* Key handling not part of the keymap */
+gchar*
+gdk_keyval_name (guint       keyval)
+{
+  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";
+    }
+
+  return "TODO";
+}
+
+guint
+gdk_keyval_from_name (const gchar *keyval_name)
+{
+  g_return_val_if_fail (keyval_name != NULL, 0);
+
+  return 0;
+}
+
+void
+gdk_keymap_add_virtual_modifiers (GdkKeymap       *keymap,
+                                 GdkModifierType *state)
+{
+}
+
+gboolean
+gdk_keymap_map_virtual_modifiers (GdkKeymap       *keymap,
+                                 GdkModifierType *state)
+{
+  return FALSE;
+}
diff --git a/gdk/broadway/gdkmain-broadway.c b/gdk/broadway/gdkmain-broadway.c
new file mode 100644 (file)
index 0000000..623379b
--- /dev/null
@@ -0,0 +1,122 @@
+/* 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"
+
+#include "gdkdisplay-broadway.h"
+#include "gdkinternals.h"
+#include "gdkprivate-broadway.h"
+#include "gdkintl.h"
+#include "gdkdeviceprivate.h"
+
+#include <glib/gprintf.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <limits.h>
+#include <errno.h>
+
+typedef struct _GdkPredicate        GdkPredicate;
+typedef struct _GdkGlobalErrorTrap  GdkGlobalErrorTrap;
+
+struct _GdkPredicate
+{
+  GdkEventFunc func;
+  gpointer data;
+};
+
+/* Private variable declarations
+ */
+const GOptionEntry _gdk_windowing_args[] = {
+  { NULL }
+};
+
+void
+_gdk_windowing_init (void)
+{
+  _gdk_broadway_initialize_locale ();
+}
+
+GdkGrabStatus
+_gdk_windowing_device_grab (GdkDevice    *device,
+                            GdkWindow    *window,
+                            GdkWindow    *native,
+                            gboolean      owner_events,
+                            GdkEventMask  event_mask,
+                            GdkWindow    *confine_to,
+                            GdkCursor    *cursor,
+                            guint32       time)
+{
+  return GDK_GRAB_NOT_VIEWABLE;
+}
+
+void
+_gdk_windowing_display_set_sm_client_id (GdkDisplay  *display,
+                                        const gchar *sm_client_id)
+{
+  if (display->closed)
+    return;
+ }
+
+/* Close all open displays
+ */
+void
+_gdk_windowing_exit (void)
+{
+}
+
+void
+gdk_error_trap_push (void)
+{
+}
+
+void
+gdk_error_trap_pop_ignored (void)
+{
+}
+
+gint
+gdk_error_trap_pop (void)
+{
+  return 0;
+}
+
+gchar *
+gdk_get_display (void)
+{
+  return g_strdup (gdk_display_get_name (gdk_display_get_default ()));
+}
+
+void
+_gdk_windowing_event_data_copy (const GdkEvent *src,
+                                GdkEvent       *dst)
+{
+}
+
+void
+_gdk_windowing_event_data_free (GdkEvent *event)
+{
+}
diff --git a/gdk/broadway/gdkprivate-broadway.h b/gdk/broadway/gdkprivate-broadway.h
new file mode 100644 (file)
index 0000000..bf1a3ae
--- /dev/null
@@ -0,0 +1,88 @@
+/* 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_BROADWAY_H__
+#define __GDK_PRIVATE_BROADWAY_H__
+
+#include <gdk/gdkcursor.h>
+#include <gdk/gdkprivate.h>
+#include <gdk/gdkinternals.h>
+#include "gdkwindow-broadway.h"
+#include "gdkdisplay-broadway.h"
+
+typedef struct _GdkCursorPrivate       GdkCursorPrivate;
+
+void _gdk_broadway_resync_windows (void);
+
+struct _GdkCursorPrivate
+{
+  GdkCursor cursor;
+  GdkDisplay *display;
+};
+
+gboolean _gdk_broadway_window_queue_antiexpose  (GdkWindow *window,
+                                                cairo_region_t *area);
+void     _gdk_broadway_window_translate         (GdkWindow *window,
+                                                cairo_region_t *area,
+                                                gint       dx,
+                                                gint       dy);
+
+void     _gdk_selection_window_destroyed   (GdkWindow            *window);
+
+void _gdk_keymap_keys_changed     (GdkDisplay      *display);
+gint _gdk_broadway_get_group_for_state (GdkDisplay      *display,
+                                       GdkModifierType  state);
+void _gdk_keymap_add_virtual_modifiers_compat (GdkKeymap       *keymap,
+                                               GdkModifierType *modifiers);
+gboolean _gdk_keymap_key_is_modifier   (GdkKeymap       *keymap,
+                                       guint            keycode);
+
+void _gdk_broadway_initialize_locale (void);
+
+void _gdk_screen_broadway_events_init   (GdkScreen *screen);
+
+void _gdk_events_init           (GdkDisplay *display);
+void _gdk_events_uninit         (GdkDisplay *display);
+void _gdk_events_got_input      (GdkDisplay *display,
+                                const char *message);
+
+void _gdk_windowing_window_init (GdkScreen *screen);
+void _gdk_visual_init           (GdkScreen *screen);
+void _gdk_dnd_init             (GdkDisplay *display);
+
+void _gdk_broadway_cursor_update_theme (GdkCursor *cursor);
+void _gdk_broadway_cursor_display_finalize (GdkDisplay *display);
+
+#define GDK_SCREEN_DISPLAY(screen)    (GDK_SCREEN_BROADWAY (screen)->display)
+#define GDK_WINDOW_SCREEN(win)       (GDK_DRAWABLE_IMPL_BROADWAY (((GdkWindowObject *)win)->impl)->screen)
+#define GDK_WINDOW_DISPLAY(win)       (GDK_SCREEN_BROADWAY (GDK_WINDOW_SCREEN (win))->display)
+#define GDK_WINDOW_IS_BROADWAY(win)   (GDK_IS_WINDOW_IMPL_BROADWAY (((GdkWindowObject *)win)->impl))
+
+#endif /* __GDK_PRIVATE_BROADWAY_H__ */
diff --git a/gdk/broadway/gdkproperty-broadway.c b/gdk/broadway/gdkproperty-broadway.c
new file mode 100644 (file)
index 0000000..e1eaa3d
--- /dev/null
@@ -0,0 +1,97 @@
+/* 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"
+
+#include "gdkproperty.h"
+
+#include "gdkmain.h"
+#include "gdkprivate.h"
+#include "gdkinternals.h"
+#include "gdkdisplay-broadway.h"
+#include "gdkscreen-broadway.h"
+#include "gdkselection.h"
+
+#include <string.h>
+
+GdkAtom
+gdk_atom_intern (const gchar *atom_name, 
+                gboolean     only_if_exists)
+{
+  return _GDK_MAKE_ATOM (g_quark_from_string (atom_name));
+}
+
+GdkAtom
+gdk_atom_intern_static_string (const gchar *atom_name)
+{
+  return _GDK_MAKE_ATOM (g_quark_from_static_string (atom_name));
+}
+
+static G_CONST_RETURN char *
+get_atom_name (GdkAtom atom)
+{
+  return g_quark_to_string (GPOINTER_TO_UINT(atom));
+}
+
+gchar *
+gdk_atom_name (GdkAtom atom)
+{
+  return g_strdup (get_atom_name (atom));
+}
+
+gboolean
+gdk_property_get (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;
+}
+
+void
+gdk_property_change (GdkWindow    *window,
+                    GdkAtom       property,
+                    GdkAtom       type,
+                    gint          format,
+                    GdkPropMode   mode,
+                    const guchar *data,
+                    gint          nelements)
+{
+  g_return_if_fail (!window || GDK_WINDOW_IS_BROADWAY (window));
+}
+
+void
+gdk_property_delete (GdkWindow *window,
+                    GdkAtom    property)
+{
+  g_return_if_fail (!window || GDK_WINDOW_IS_BROADWAY (window));
+}
diff --git a/gdk/broadway/gdkscreen-broadway.c b/gdk/broadway/gdkscreen-broadway.c
new file mode 100644 (file)
index 0000000..527deb3
--- /dev/null
@@ -0,0 +1,324 @@
+ /*
+ * gdkscreen-broadway.c
+ * 
+ * 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.
+ */
+
+#include "config.h"
+
+#include "gdkscreen-broadway.h"
+
+#include "gdkscreen.h"
+#include "gdkdisplay.h"
+#include "gdkdisplay-broadway.h"
+
+#include <glib.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+static void         gdk_screen_broadway_dispose     (GObject             *object);
+static void         gdk_screen_broadway_finalize    (GObject             *object);
+
+G_DEFINE_TYPE (GdkScreenBroadway, _gdk_screen_broadway, GDK_TYPE_SCREEN)
+
+static void
+_gdk_screen_broadway_class_init (GdkScreenBroadwayClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->dispose = gdk_screen_broadway_dispose;
+  object_class->finalize = gdk_screen_broadway_finalize;
+}
+
+static void
+_gdk_screen_broadway_init (GdkScreenBroadway *screen)
+{
+  screen->width = 1024;
+  screen->height = 768;
+}
+
+GdkDisplay *
+gdk_screen_get_display (GdkScreen *screen)
+{
+  g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
+
+  return GDK_SCREEN_BROADWAY (screen)->display;
+}
+
+gint
+gdk_screen_get_width (GdkScreen *screen)
+{
+  g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
+
+  return GDK_SCREEN_BROADWAY (screen)->width;
+}
+
+gint
+gdk_screen_get_height (GdkScreen *screen)
+{
+  g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
+
+  return GDK_SCREEN_BROADWAY (screen)->height;
+}
+
+gint
+gdk_screen_get_width_mm (GdkScreen *screen)
+{
+  g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
+
+  return gdk_screen_get_width (screen) * 25.4 / 96;
+}
+
+gint
+gdk_screen_get_height_mm (GdkScreen *screen)
+{
+  g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
+
+  return gdk_screen_get_height (screen) * 25.4 / 96;
+}
+
+gint
+gdk_screen_get_number (GdkScreen *screen)
+{
+  g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
+
+  return 0;
+}
+
+GdkWindow *
+gdk_screen_get_root_window (GdkScreen *screen)
+{
+  g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
+
+  return GDK_SCREEN_BROADWAY (screen)->root_window;
+}
+
+static void
+gdk_screen_broadway_dispose (GObject *object)
+{
+  GdkScreenBroadway *screen_broadway = GDK_SCREEN_BROADWAY (object);
+
+  if (screen_broadway->root_window)
+    _gdk_window_destroy (screen_broadway->root_window, TRUE);
+
+  G_OBJECT_CLASS (_gdk_screen_broadway_parent_class)->dispose (object);
+}
+
+static void
+gdk_screen_broadway_finalize (GObject *object)
+{
+  GdkScreenBroadway *screen_broadway = GDK_SCREEN_BROADWAY (object);
+  gint          i;
+
+  if (screen_broadway->root_window)
+    g_object_unref (screen_broadway->root_window);
+
+  /* Visual Part */
+  for (i = 0; i < screen_broadway->nvisuals; i++)
+    g_object_unref (screen_broadway->visuals[i]);
+  g_free (screen_broadway->visuals);
+
+  G_OBJECT_CLASS (_gdk_screen_broadway_parent_class)->finalize (object);
+}
+
+gint
+gdk_screen_get_n_monitors (GdkScreen *screen)
+{
+  g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
+
+  return 1;
+}
+
+gint
+gdk_screen_get_primary_monitor (GdkScreen *screen)
+{
+  g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
+
+  return 0;
+}
+
+gint
+gdk_screen_get_monitor_width_mm        (GdkScreen *screen,
+                                gint       monitor_num)
+{
+  g_return_val_if_fail (GDK_IS_SCREEN (screen), -1);
+  g_return_val_if_fail (monitor_num == 0, -1);
+
+  return gdk_screen_get_width_mm (screen);
+}
+
+gint
+gdk_screen_get_monitor_height_mm (GdkScreen *screen,
+                                 gint       monitor_num)
+{
+  g_return_val_if_fail (GDK_IS_SCREEN (screen), -1);
+  g_return_val_if_fail (monitor_num == 0, -1);
+
+  return gdk_screen_get_height_mm (screen);
+}
+
+gchar *
+gdk_screen_get_monitor_plug_name (GdkScreen *screen,
+                                 gint       monitor_num)
+{
+  g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
+  g_return_val_if_fail (monitor_num == 0, NULL);
+
+  return g_strdup ("browser");
+}
+
+/**
+ * gdk_screen_get_monitor_geometry:
+ * @screen: a #GdkScreen
+ * @monitor_num: the monitor number, between 0 and gdk_screen_get_n_monitors (screen)
+ * @dest: a #GdkRectangle to be filled with the monitor geometry
+ *
+ * Retrieves the #GdkRectangle representing the size and position of
+ * the individual monitor within the entire screen area.
+ *
+ * Note that the size of the entire screen area can be retrieved via
+ * gdk_screen_get_width() and gdk_screen_get_height().
+ *
+ * Since: 2.2
+ */
+void
+gdk_screen_get_monitor_geometry (GdkScreen    *screen,
+                                gint          monitor_num,
+                                GdkRectangle *dest)
+{
+  GdkScreenBroadway *screen_broadway = GDK_SCREEN_BROADWAY (screen);
+
+  g_return_if_fail (GDK_IS_SCREEN (screen));
+  g_return_if_fail (monitor_num == 0);
+
+  if (dest)
+    {
+      dest->x = 0;
+      dest->y = 0;
+      dest->width = screen_broadway->width;
+      dest->height = screen_broadway->height;
+    }
+}
+
+GdkVisual *
+gdk_screen_get_rgba_visual (GdkScreen *screen)
+{
+  GdkScreenBroadway *screen_broadway;
+
+  g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
+
+  screen_broadway = GDK_SCREEN_BROADWAY (screen);
+
+  return screen_broadway->rgba_visual;
+}
+
+GdkScreen *
+_gdk_broadway_screen_new (GdkDisplay *display,
+                    gint        screen_number)
+{
+  GdkScreen *screen;
+  GdkScreenBroadway *screen_broadway;
+
+  screen = g_object_new (GDK_TYPE_SCREEN_BROADWAY, NULL);
+
+  screen_broadway = GDK_SCREEN_BROADWAY (screen);
+  screen_broadway->display = display;
+  _gdk_visual_init (screen);
+  _gdk_windowing_window_init (screen);
+
+  return screen;
+}
+
+/*
+ * It is important that we first request the selection
+ * notification, and then setup the initial state of
+ * is_composited to avoid a race condition here.
+ */
+void
+_gdk_broadway_screen_setup (GdkScreen *screen)
+{
+}
+
+gboolean
+gdk_screen_is_composited (GdkScreen *screen)
+{
+  GdkScreenBroadway *screen_broadway;
+
+  g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE);
+
+  screen_broadway = GDK_SCREEN_BROADWAY (screen);
+
+  return FALSE;
+}
+
+
+gchar *
+gdk_screen_make_display_name (GdkScreen *screen)
+{
+  g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
+
+  return g_strdup ("browser");
+}
+
+GdkWindow *
+gdk_screen_get_active_window (GdkScreen *screen)
+{
+  return NULL;
+}
+
+GList *
+gdk_screen_get_window_stack (GdkScreen *screen)
+{
+  return NULL;
+}
+
+void
+gdk_screen_broadcast_client_message (GdkScreen *screen,
+                                    GdkEvent  *event)
+{
+}
+
+gboolean
+gdk_screen_get_setting (GdkScreen   *screen,
+                       const gchar *name,
+                       GValue      *value)
+{
+  return FALSE;
+}
+
+gboolean
+gdk_net_wm_supports (GdkAtom property)
+{
+  return FALSE;
+}
+
+void
+_gdk_screen_broadway_events_init (GdkScreen *screen)
+{
+}
+
+gchar *
+_gdk_windowing_substitute_screen_number (const gchar *display_name,
+                                        gint         screen_number)
+{
+  return g_strdup ("browser");
+}
+
diff --git a/gdk/broadway/gdkscreen-broadway.h b/gdk/broadway/gdkscreen-broadway.h
new file mode 100644 (file)
index 0000000..d4b730b
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * gdkscreen-broadway.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_SCREEN_BROADWAY_H__
+#define __GDK_SCREEN_BROADWAY_H__
+
+#include <gdk/gdkscreen.h>
+#include <gdk/gdkvisual.h>
+#include "gdkprivate-broadway.h"
+
+G_BEGIN_DECLS
+
+typedef struct _GdkScreenBroadway GdkScreenBroadway;
+typedef struct _GdkScreenBroadwayClass GdkScreenBroadwayClass;
+
+#define GDK_TYPE_SCREEN_BROADWAY              (_gdk_screen_broadway_get_type ())
+#define GDK_SCREEN_BROADWAY(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_SCREEN_BROADWAY, GdkScreenBroadway))
+#define GDK_SCREEN_BROADWAY_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_SCREEN_BROADWAY, GdkScreenBroadwayClass))
+#define GDK_IS_SCREEN_BROADWAY(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_SCREEN_BROADWAY))
+#define GDK_IS_SCREEN_BROADWAY_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_SCREEN_BROADWAY))
+#define GDK_SCREEN_BROADWAY_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_SCREEN_BROADWAY, GdkScreenBroadwayClass))
+
+typedef struct _GdkBroadwayMonitor GdkBroadwayMonitor;
+
+struct _GdkScreenBroadway
+{
+  GdkScreen parent_instance;
+
+  GdkDisplay *display;
+  GdkWindow *root_window;
+
+  int width;
+  int height;
+
+  /* Visual Part */
+  GdkVisual **visuals;
+  gint nvisuals;
+  GdkVisual *system_visual;
+  GdkVisual *rgba_visual;
+  gint available_depths[7];
+  gint navailable_depths;
+  GdkVisualType available_types[6];
+  gint navailable_types;
+};
+
+struct _GdkScreenBroadwayClass
+{
+  GdkScreenClass parent_class;
+
+  void (* window_manager_changed) (GdkScreenBroadway *screen_broadway);
+};
+
+GType       _gdk_screen_broadway_get_type (void);
+GdkScreen * _gdk_broadway_screen_new      (GdkDisplay *display,
+                                          gint   screen_number);
+void _gdk_broadway_screen_setup                  (GdkScreen *screen);
+
+G_END_DECLS
+
+#endif /* __GDK_SCREEN_BROADWAY_H__ */
diff --git a/gdk/broadway/gdkselection-broadway.c b/gdk/broadway/gdkselection-broadway.c
new file mode 100644 (file)
index 0000000..e466e83
--- /dev/null
@@ -0,0 +1,191 @@
+/* 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"
+
+#include "gdkselection.h"
+
+#include "gdkproperty.h"
+#include "gdkprivate.h"
+#include "gdkprivate-broadway.h"
+#include "gdkdisplay-broadway.h"
+
+#include <string.h>
+
+
+typedef struct _OwnerInfo OwnerInfo;
+
+struct _OwnerInfo
+{
+  GdkAtom    selection;
+  GdkWindow *owner;
+  gulong     serial;
+};
+
+static GSList *owner_list;
+
+/* When a window is destroyed we check if it is the owner
+ * of any selections. This is somewhat inefficient, but
+ * owner_list is typically short, and it is a low memory,
+ * low code solution
+ */
+void
+_gdk_selection_window_destroyed (GdkWindow *window)
+{
+  GSList *tmp_list = owner_list;
+  while (tmp_list)
+    {
+      OwnerInfo *info = tmp_list->data;
+      tmp_list = tmp_list->next;
+
+      if (info->owner == window)
+       {
+         owner_list = g_slist_remove (owner_list, info);
+         g_free (info);
+       }
+    }
+}
+
+gboolean
+gdk_selection_owner_set_for_display (GdkDisplay *display,
+                                    GdkWindow  *owner,
+                                    GdkAtom     selection,
+                                    guint32     time,
+                                    gboolean    send_event)
+{
+  return FALSE;
+}
+
+GdkWindow *
+gdk_selection_owner_get_for_display (GdkDisplay *display,
+                                    GdkAtom     selection)
+{
+  return NULL;
+}
+
+void
+gdk_selection_convert (GdkWindow *requestor,
+                      GdkAtom    selection,
+                      GdkAtom    target,
+                      guint32    time)
+{
+}
+
+gint
+gdk_selection_property_get (GdkWindow  *requestor,
+                           guchar    **data,
+                           GdkAtom    *ret_type,
+                           gint       *ret_format)
+{
+  if (ret_type)
+    *ret_type = GDK_NONE;
+  if (ret_format)
+    *ret_format = 0;
+  if (data)
+    *data = NULL;
+
+  return 0;
+}
+
+void
+gdk_selection_send_notify_for_display (GdkDisplay       *display,
+                                      GdkNativeWindow  requestor,
+                                      GdkAtom          selection,
+                                      GdkAtom          target,
+                                      GdkAtom          property, 
+                                      guint32          time)
+{
+  g_return_if_fail (GDK_IS_DISPLAY (display));
+}
+
+gint
+gdk_text_property_to_text_list_for_display (GdkDisplay   *display,
+                                           GdkAtom       encoding,
+                                           gint          format, 
+                                           const guchar *text,
+                                           gint          length,
+                                           gchar      ***list)
+{
+  return 0;
+}
+
+void
+gdk_free_text_list (gchar **list)
+{
+  g_return_if_fail (list != NULL);
+
+  g_strfreev (list);
+}
+
+gint 
+gdk_text_property_to_utf8_list_for_display (GdkDisplay    *display,
+                                           GdkAtom        encoding,
+                                           gint           format,
+                                           const guchar  *text,
+                                           gint           length,
+                                           gchar       ***list)
+{
+  g_return_val_if_fail (text != NULL, 0);
+  g_return_val_if_fail (length >= 0, 0);
+  g_return_val_if_fail (GDK_IS_DISPLAY (display), 0);
+
+  return 0;
+}
+
+gint
+gdk_string_to_compound_text_for_display (GdkDisplay  *display,
+                                        const gchar *str,
+                                        GdkAtom     *encoding,
+                                        gint        *format,
+                                        guchar     **ctext,
+                                        gint        *length)
+{
+  g_return_val_if_fail (GDK_IS_DISPLAY (display), 0);
+
+  return 1;
+}
+
+gchar *
+gdk_utf8_to_string_target (const gchar *str)
+{
+  return g_strdup (str);
+}
+
+gboolean
+gdk_utf8_to_compound_text_for_display (GdkDisplay  *display,
+                                      const gchar *str,
+                                      GdkAtom     *encoding,
+                                      gint        *format,
+                                      guchar     **ctext,
+                                      gint        *length)
+{
+  return FALSE;
+}
+
+void gdk_free_compound_text (guchar *ctext)
+{
+  g_free (ctext);
+}
diff --git a/gdk/broadway/gdkspawn-broadway.c b/gdk/broadway/gdkspawn-broadway.c
new file mode 100644 (file)
index 0000000..17db0d9
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2003 Sun Microsystems Inc.
+ *
+ * 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.
+ *
+ * Authors: Mark McLoughlin <mark@skynet.ie>
+ */
+
+#include "config.h"
+
+#include "gdkspawn.h"
+
+#include <glib.h>
+#include <string.h>
+#include <stdlib.h>
+
+
+typedef struct {
+  char *display;
+  GSpawnChildSetupFunc child_setup;
+  gpointer user_data;
+} UserChildSetup;
+
+static void
+set_environment (gpointer user_data)
+{
+  UserChildSetup *setup = user_data;
+
+  g_setenv ("DISPLAY", setup->display, TRUE);
+
+  if (setup->child_setup)
+    setup->child_setup (setup->user_data);
+}
+
+gboolean
+gdk_spawn_on_screen (GdkScreen             *screen,
+                    const gchar           *working_directory,
+                    gchar                **argv,
+                    gchar                **envp,
+                    GSpawnFlags            flags,
+                    GSpawnChildSetupFunc   child_setup,
+                    gpointer               user_data,
+                    GPid                  *child_pid,
+                    GError               **error)
+{
+  UserChildSetup setup_data;
+
+  g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE);
+
+  setup_data.display = gdk_screen_make_display_name (screen);
+  setup_data.child_setup = child_setup;
+  setup_data.user_data = user_data;
+
+  return g_spawn_async (working_directory,
+                         argv,
+                         envp,
+                         flags,
+                         set_environment,
+                         &setup_data,
+                         child_pid,
+                         error);
+}
+
+gboolean
+gdk_spawn_on_screen_with_pipes (GdkScreen            *screen,
+                               const gchar          *working_directory,
+                               gchar               **argv,
+                               gchar               **envp,
+                               GSpawnFlags           flags,
+                               GSpawnChildSetupFunc  child_setup,
+                               gpointer              user_data,
+                               GPid                 *child_pid,
+                               gint                 *standard_input,
+                               gint                 *standard_output,
+                               gint                 *standard_error,
+                               GError              **error)
+{
+  UserChildSetup setup_data;
+
+  g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE);
+
+  setup_data.display = gdk_screen_make_display_name (screen);
+  setup_data.child_setup = child_setup;
+  setup_data.user_data = user_data;
+
+  return g_spawn_async_with_pipes (working_directory,
+                                    argv,
+                                    envp,
+                                    flags,
+                                    set_environment,
+                                    &setup_data,
+                                    child_pid,
+                                    standard_input,
+                                    standard_output,
+                                    standard_error,
+                                    error);
+
+}
+
+gboolean
+gdk_spawn_command_line_on_screen (GdkScreen    *screen,
+                                 const gchar  *command_line,
+                                 GError      **error)
+{
+  gchar    **argv = NULL;
+  gboolean   retval;
+
+  g_return_val_if_fail (command_line != NULL, FALSE);
+
+  if (!g_shell_parse_argv (command_line,
+                          NULL, &argv,
+                          error))
+    return FALSE;
+
+  retval = gdk_spawn_on_screen (screen,
+                               NULL, argv, NULL,
+                               G_SPAWN_SEARCH_PATH,
+                               NULL, NULL, NULL,
+                               error);
+  g_strfreev (argv);
+
+  return retval;
+}
diff --git a/gdk/broadway/gdktestutils-broadway.c b/gdk/broadway/gdktestutils-broadway.c
new file mode 100644 (file)
index 0000000..ad41d76
--- /dev/null
@@ -0,0 +1,52 @@
+/* Gtk+ testing utilities
+ * Copyright (C) 2007 Imendio AB
+ * Authors: Tim Janik
+ *
+ * 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 "gdktestutils.h"
+
+#include "gdkkeysyms.h"
+
+void
+gdk_test_render_sync (GdkWindow *window)
+{
+}
+
+gboolean
+gdk_test_simulate_key (GdkWindow      *window,
+                       gint            x,
+                       gint            y,
+                       guint           keyval,
+                       GdkModifierType modifiers,
+                       GdkEventType    key_pressrelease)
+{
+  return FALSE;
+}
+
+gboolean
+gdk_test_simulate_button (GdkWindow      *window,
+                          gint            x,
+                          gint            y,
+                          guint           button, /*1..3*/
+                          GdkModifierType modifiers,
+                          GdkEventType    button_pressrelease)
+{
+  return FALSE;
+}
diff --git a/gdk/broadway/gdkvisual-broadway.c b/gdk/broadway/gdkvisual-broadway.c
new file mode 100644 (file)
index 0000000..ff77d3b
--- /dev/null
@@ -0,0 +1,303 @@
+/* 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"
+
+#include "gdkvisual.h"
+
+#include "gdkprivate-broadway.h"
+#include "gdkscreen-broadway.h"
+#include "gdkinternals.h"
+
+struct _GdkVisualPrivate
+{
+  GdkScreen *screen;
+};
+
+struct _GdkVisualClass
+{
+  GObjectClass parent_class;
+};
+
+static void     gdk_visual_decompose_mask (gulong     mask,
+                                          gint      *shift,
+                                          gint      *prec);
+
+
+G_DEFINE_TYPE (GdkVisual, gdk_visual, G_TYPE_OBJECT)
+
+static void
+gdk_visual_finalize (GObject *object)
+{
+  G_OBJECT_CLASS (gdk_visual_parent_class)->finalize (object);
+}
+
+static void
+gdk_visual_class_init (GdkVisualClass *visual_class)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (visual_class);
+
+  g_type_class_add_private (object_class, sizeof (GdkVisualPrivate));
+
+  object_class->finalize = gdk_visual_finalize;
+}
+
+static void
+gdk_visual_init (GdkVisual *visual)
+{
+  visual->priv = G_TYPE_INSTANCE_GET_PRIVATE (visual,
+                                              GDK_TYPE_VISUAL,
+                                              GdkVisualPrivate);
+
+}
+
+void
+_gdk_visual_init (GdkScreen *screen)
+{
+  GdkScreenBroadway *screen_broadway;
+  GdkVisual **visuals;
+  int nvisuals;
+
+  g_return_if_fail (GDK_IS_SCREEN (screen));
+  screen_broadway = GDK_SCREEN_BROADWAY (screen);
+
+  nvisuals = 2;
+  visuals = g_new (GdkVisual *, nvisuals);
+
+  visuals[0] = g_object_new (GDK_TYPE_VISUAL, NULL);
+  visuals[0]->priv->screen = screen;
+  visuals[0]->type = GDK_VISUAL_TRUE_COLOR;
+  visuals[0]->depth = 32;
+  visuals[0]->byte_order = (G_BYTE_ORDER == G_LITTLE_ENDIAN) ? GDK_LSB_FIRST : GDK_MSB_FIRST;
+  visuals[0]->red_mask = 0xff0000;
+  visuals[0]->green_mask = 0xff00;
+  visuals[0]->blue_mask = 0xff;
+  visuals[0]->colormap_size = 256;
+  visuals[0]->bits_per_rgb = 8;
+  gdk_visual_decompose_mask (visuals[0]->red_mask,
+                            &visuals[0]->red_shift,
+                            &visuals[0]->red_prec);
+  gdk_visual_decompose_mask (visuals[0]->green_mask,
+                            &visuals[0]->green_shift,
+                            &visuals[0]->green_prec);
+  gdk_visual_decompose_mask (visuals[0]->blue_mask,
+                            &visuals[0]->blue_shift,
+                            &visuals[0]->blue_prec);
+
+  visuals[1] = g_object_new (GDK_TYPE_VISUAL, NULL);
+  visuals[1]->priv->screen = screen;
+  visuals[1]->type = GDK_VISUAL_TRUE_COLOR;
+  visuals[1]->depth = 24;
+  visuals[1]->byte_order = (G_BYTE_ORDER == G_LITTLE_ENDIAN) ? GDK_LSB_FIRST : GDK_MSB_FIRST;
+  visuals[1]->red_mask = 0xff0000;
+  visuals[1]->green_mask = 0xff00;
+  visuals[1]->blue_mask = 0xff;
+  visuals[1]->colormap_size = 256;
+  visuals[1]->bits_per_rgb = 8;
+  gdk_visual_decompose_mask (visuals[1]->red_mask,
+                            &visuals[1]->red_shift,
+                            &visuals[1]->red_prec);
+  gdk_visual_decompose_mask (visuals[1]->green_mask,
+                            &visuals[1]->green_shift,
+                            &visuals[1]->green_prec);
+  gdk_visual_decompose_mask (visuals[1]->blue_mask,
+                            &visuals[1]->blue_shift,
+                            &visuals[1]->blue_prec);
+
+  screen_broadway->system_visual = visuals[1];
+  screen_broadway->rgba_visual = visuals[0];
+
+  screen_broadway->navailable_depths = 2;
+  screen_broadway->available_depths[0] = 32;
+  screen_broadway->available_depths[1] = 24;
+
+  screen_broadway->navailable_types = 1;
+  screen_broadway->available_types[0] = GDK_VISUAL_TRUE_COLOR;
+
+  screen_broadway->visuals = visuals;
+  screen_broadway->nvisuals = nvisuals;
+}
+
+gint
+gdk_visual_get_best_depth (void)
+{
+  GdkScreen *screen = gdk_screen_get_default();
+
+  return GDK_SCREEN_BROADWAY (screen)->available_depths[0];
+}
+
+GdkVisualType
+gdk_visual_get_best_type (void)
+{
+  GdkScreen *screen = gdk_screen_get_default();
+
+  return GDK_SCREEN_BROADWAY (screen)->available_types[0];
+}
+
+GdkVisual *
+gdk_screen_get_system_visual (GdkScreen * screen)
+{
+  g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
+
+  return ((GdkVisual *) GDK_SCREEN_BROADWAY (screen)->system_visual);
+}
+
+GdkVisual*
+gdk_visual_get_best (void)
+{
+  GdkScreenBroadway *screen_broadway = GDK_SCREEN_BROADWAY (gdk_screen_get_default());
+
+  return (GdkVisual *)screen_broadway->visuals[0];
+}
+
+GdkVisual*
+gdk_visual_get_best_with_depth (gint depth)
+{
+  GdkScreenBroadway *screen_broadway = GDK_SCREEN_BROADWAY (gdk_screen_get_default ());
+  GdkVisual *return_val;
+  int i;
+
+  return_val = NULL;
+  for (i = 0; i < screen_broadway->nvisuals; i++)
+    if (depth == screen_broadway->visuals[i]->depth)
+      {
+       return_val = (GdkVisual *) screen_broadway->visuals[i];
+       break;
+      }
+
+  return return_val;
+}
+
+GdkVisual*
+gdk_visual_get_best_with_type (GdkVisualType visual_type)
+{
+  GdkScreenBroadway *screen_broadway = GDK_SCREEN_BROADWAY (gdk_screen_get_default ());
+  GdkVisual *return_val;
+  int i;
+
+  return_val = NULL;
+  for (i = 0; i < screen_broadway->nvisuals; i++)
+    if (visual_type == screen_broadway->visuals[i]->type)
+      {
+       return_val = (GdkVisual *) screen_broadway->visuals[i];
+       break;
+      }
+
+  return return_val;
+}
+
+GdkVisual*
+gdk_visual_get_best_with_both (gint          depth,
+                              GdkVisualType visual_type)
+{
+  GdkScreenBroadway *screen_broadway = GDK_SCREEN_BROADWAY (gdk_screen_get_default ());
+  GdkVisual *return_val;
+  int i;
+
+  return_val = NULL;
+  for (i = 0; i < screen_broadway->nvisuals; i++)
+    if ((depth == screen_broadway->visuals[i]->depth) &&
+       (visual_type == screen_broadway->visuals[i]->type))
+      {
+       return_val = (GdkVisual *) screen_broadway->visuals[i];
+       break;
+      }
+
+  return return_val;
+}
+
+void
+gdk_query_depths  (gint **depths,
+                  gint  *count)
+{
+  GdkScreenBroadway *screen_broadway = GDK_SCREEN_BROADWAY (gdk_screen_get_default ());
+
+  *count = screen_broadway->navailable_depths;
+  *depths = screen_broadway->available_depths;
+}
+
+void
+gdk_query_visual_types (GdkVisualType **visual_types,
+                       gint           *count)
+{
+  GdkScreenBroadway *screen_broadway = GDK_SCREEN_BROADWAY (gdk_screen_get_default ());
+
+  *count = screen_broadway->navailable_types;
+  *visual_types = screen_broadway->available_types;
+}
+
+GList *
+gdk_screen_list_visuals (GdkScreen *screen)
+{
+  GList *list;
+  GdkScreenBroadway *screen_broadway;
+  guint i;
+
+  g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
+  screen_broadway = GDK_SCREEN_BROADWAY (screen);
+
+  list = NULL;
+
+  for (i = 0; i < screen_broadway->nvisuals; ++i)
+    list = g_list_append (list, screen_broadway->visuals[i]);
+
+  return list;
+}
+
+static void
+gdk_visual_decompose_mask (gulong  mask,
+                          gint   *shift,
+                          gint   *prec)
+{
+  *shift = 0;
+  *prec = 0;
+
+  if (mask == 0)
+    {
+      g_warning ("Mask is 0 in visual. Server bug ?");
+      return;
+    }
+
+  while (!(mask & 0x1))
+    {
+      (*shift)++;
+      mask >>= 1;
+    }
+
+  while (mask & 0x1)
+    {
+      (*prec)++;
+      mask >>= 1;
+    }
+}
+
+GdkScreen *
+gdk_visual_get_screen (GdkVisual *visual)
+{
+  g_return_val_if_fail (GDK_IS_VISUAL (visual), NULL);
+
+  return visual->priv->screen;
+}
diff --git a/gdk/broadway/gdkwindow-broadway.c b/gdk/broadway/gdkwindow-broadway.c
new file mode 100644 (file)
index 0000000..9d6e6d5
--- /dev/null
@@ -0,0 +1,1362 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-2007 Peter Mattis, Spencer Kimball,
+ * Josh MacDonald, Ryan Lortie
+ *
+ * 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 "gdkwindow-broadway.h"
+#include "gdkscreen-broadway.h"
+
+#include "gdkwindow.h"
+#include "gdkwindowimpl.h"
+#include "gdkdisplay-broadway.h"
+#include "gdkprivate-broadway.h"
+#include "gdkinternals.h"
+#include "gdkdeviceprivate.h"
+#include "gdkeventsource.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <unistd.h>
+
+/* Forward declarations */
+static void     gdk_window_broadway_set_background     (GdkWindow      *window,
+                                                   cairo_pattern_t *pattern);
+
+static void        gdk_window_impl_broadway_finalize   (GObject            *object);
+static void        gdk_window_impl_iface_init     (GdkWindowImplIface *iface);
+
+#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 ))     \
+  )
+
+G_DEFINE_TYPE_WITH_CODE (GdkWindowImplBroadway,
+                         gdk_window_impl_broadway,
+                         GDK_TYPE_DRAWABLE_IMPL_BROADWAY,
+                         G_IMPLEMENT_INTERFACE (GDK_TYPE_WINDOW_IMPL,
+                                                gdk_window_impl_iface_init));
+
+GType
+_gdk_window_impl_get_type (void)
+{
+  return gdk_window_impl_broadway_get_type ();
+}
+
+static void
+diff_surfaces (cairo_surface_t *surface,
+              cairo_surface_t *old_surface)
+{
+  guint8 *data, *old_data;
+  guint32 *line, *old_line;
+  int w, h, stride, old_stride;
+  int x, y;
+
+  data = cairo_image_surface_get_data (surface);
+  old_data = cairo_image_surface_get_data (old_surface);
+
+  w = cairo_image_surface_get_width (surface);
+  h = cairo_image_surface_get_height (surface);
+
+  stride = cairo_image_surface_get_stride (surface);
+  old_stride = cairo_image_surface_get_stride (old_surface);
+
+  for (y = 0; y < h; y++)
+    {
+      line = (guint32 *)data;
+      old_line = (guint32 *)old_data;
+
+      for (x = 0; x < w; x++)
+       {
+         if ((*line & 0xffffff) == (*old_line & 0xffffff))
+           *old_line = 0;
+         else
+           *old_line = *line | 0xff000000;
+         line ++;
+         old_line ++;
+       }
+
+      data += stride;
+      old_data += old_stride;
+    }
+}
+
+static guint dirty_flush_id = 0;
+
+static void
+window_data_send (BroadwayOutput *output, GdkWindowImplBroadway *impl)
+{
+  GdkDrawableImplBroadway *drawable_impl = GDK_DRAWABLE_IMPL_BROADWAY (impl);
+  cairo_t *cr;
+
+  if (drawable_impl->surface == NULL)
+    return;
+
+  if (impl->last_synced)
+    {
+      diff_surfaces (drawable_impl->surface,
+                    drawable_impl->last_surface);
+      broadway_output_put_rgba (output, impl->id, 0, 0,
+                               cairo_image_surface_get_width (drawable_impl->last_surface),
+                               cairo_image_surface_get_height (drawable_impl->last_surface),
+                               cairo_image_surface_get_stride (drawable_impl->last_surface),
+                               cairo_image_surface_get_data (drawable_impl->last_surface));
+    }
+  else
+    {
+      impl->last_synced = TRUE;
+      broadway_output_put_rgb (output, impl->id, 0, 0,
+                              cairo_image_surface_get_width (drawable_impl->surface),
+                              cairo_image_surface_get_height (drawable_impl->surface),
+                              cairo_image_surface_get_stride (drawable_impl->surface),
+                              cairo_image_surface_get_data (drawable_impl->surface));
+    }
+
+  cr = cairo_create (drawable_impl->last_surface);
+  cairo_set_source_surface (cr, drawable_impl->surface, 0, 0);
+  cairo_paint (cr);
+  cairo_destroy (cr);
+}
+
+static gboolean
+dirty_flush_idle (gpointer data)
+{
+  GList *l;
+  GdkDisplayBroadway *display;
+  BroadwayOutput *output;
+
+  dirty_flush_id = 0;
+
+  display = GDK_DISPLAY_BROADWAY (gdk_display_get_default ());
+  output = display->output;
+  if (output == NULL)
+    return FALSE;
+
+  for (l = display->toplevels; l != NULL; l = l->next)
+    {
+      GdkWindowImplBroadway *impl = l->data;
+
+      if (impl->dirty)
+       {
+         impl->dirty = FALSE;
+         window_data_send (display->output, impl);
+       }
+    }
+
+  if (!broadway_output_flush (display->output))
+    {
+      broadway_output_free (display->output);
+      display->output = NULL;
+    }
+
+  return FALSE;
+}
+
+static void
+queue_dirty_flush (GdkDisplayBroadway *display)
+{
+  if (dirty_flush_id == 0 && display->output != NULL)
+    dirty_flush_id = gdk_threads_add_idle (dirty_flush_idle, NULL);
+}
+
+void
+_gdk_broadway_resync_windows (void)
+{
+  GdkDisplayBroadway *display;
+  GList *l;
+
+  dirty_flush_id = 0;
+
+  display = GDK_DISPLAY_BROADWAY (gdk_display_get_default ());
+
+  for (l = display->toplevels; l != NULL; l = l->next)
+    {
+      GdkWindowImplBroadway *impl = l->data;
+      GdkWindowObject *private;
+
+      private = (GdkWindowObject*) GDK_DRAWABLE_IMPL_BROADWAY (impl)->wrapper;
+
+      if (impl->id == 0)
+       continue; /* Skip root */
+
+      impl->dirty = FALSE;
+      impl->last_synced = FALSE;
+      broadway_output_new_surface (display->output,
+                                  impl->id,
+                                  private->x,
+                                  private->y,
+                                  private->width,
+                                  private->height);
+      if (GDK_WINDOW_IS_MAPPED (private))
+       {
+         broadway_output_show_surface (display->output, impl->id);
+         window_data_send (display->output, impl);
+       }
+    }
+
+  broadway_output_flush (display->output);
+}
+
+static void
+gdk_window_impl_broadway_init (GdkWindowImplBroadway *impl)
+{
+  impl->toplevel_window_type = -1;
+  impl->device_cursor = g_hash_table_new_full (NULL, NULL, NULL,
+                                               (GDestroyNotify) gdk_cursor_unref);
+}
+
+static void
+gdk_window_impl_broadway_class_init (GdkWindowImplBroadwayClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = gdk_window_impl_broadway_finalize;
+}
+
+static void
+gdk_window_impl_broadway_finalize (GObject *object)
+{
+  GdkWindowObject *wrapper;
+  GdkDrawableImplBroadway *draw_impl;
+  GdkWindowImplBroadway *window_impl;
+  GdkDisplayBroadway *display_broadway;
+
+  g_return_if_fail (GDK_IS_WINDOW_IMPL_BROADWAY (object));
+
+  draw_impl = GDK_DRAWABLE_IMPL_BROADWAY (object);
+  window_impl = GDK_WINDOW_IMPL_BROADWAY (object);
+
+  wrapper = (GdkWindowObject*) draw_impl->wrapper;
+
+  display_broadway = GDK_DISPLAY_BROADWAY (gdk_window_get_display (draw_impl->wrapper));
+
+  if (display_broadway->mouse_in_toplevel == GDK_WINDOW (wrapper))
+    {
+      /* TODO: Send leave + enter event, update cursors, etc */
+      display_broadway->mouse_in_toplevel = NULL;
+    }
+
+  g_hash_table_remove (display_broadway->id_ht, GINT_TO_POINTER(window_impl->id));
+
+  if (window_impl->cursor)
+    gdk_cursor_unref (window_impl->cursor);
+
+  g_hash_table_destroy (window_impl->device_cursor);
+
+  display_broadway->toplevels = g_list_remove (display_broadway->toplevels, window_impl);
+
+  G_OBJECT_CLASS (gdk_window_impl_broadway_parent_class)->finalize (object);
+}
+
+void
+_gdk_windowing_window_init (GdkScreen * screen)
+{
+  GdkWindowObject *private;
+  GdkDrawableImplBroadway *draw_impl;
+  GdkScreenBroadway *screen_broadway;
+
+  screen_broadway = GDK_SCREEN_BROADWAY (screen);
+
+  g_assert (screen_broadway->root_window == NULL);
+
+  screen_broadway->root_window = g_object_new (GDK_TYPE_WINDOW, NULL);
+
+  private = (GdkWindowObject *) screen_broadway->root_window;
+  private->impl = g_object_new (_gdk_window_impl_get_type (), NULL);
+  private->impl_window = private;
+  private->visual = gdk_screen_get_system_visual (screen);
+
+  draw_impl = GDK_DRAWABLE_IMPL_BROADWAY (private->impl);
+
+  draw_impl->screen = screen;
+  draw_impl->wrapper = GDK_DRAWABLE (private);
+
+  private->window_type = GDK_WINDOW_ROOT;
+  private->depth = 24;
+
+  private->x = 0;
+  private->y = 0;
+  private->abs_x = 0;
+  private->abs_y = 0;
+  private->width = gdk_screen_get_width (screen);
+  private->height = gdk_screen_get_height (screen);
+  private->viewable = TRUE;
+
+  _gdk_window_update_size (screen_broadway->root_window);
+}
+
+void
+_gdk_window_impl_new (GdkWindow     *window,
+                     GdkWindow     *real_parent,
+                     GdkScreen     *screen,
+                     GdkEventMask   event_mask,
+                     GdkWindowAttr *attributes,
+                     gint           attributes_mask)
+{
+  GdkWindowObject *private;
+  GdkWindowImplBroadway *impl;
+  GdkDrawableImplBroadway *draw_impl;
+  GdkScreenBroadway *screen_broadway;
+  GdkDisplayBroadway *display_broadway;
+  static int current_id = 1; /* 0 is the root window */
+
+  private = (GdkWindowObject *) window;
+
+  screen_broadway = GDK_SCREEN_BROADWAY (screen);
+  display_broadway = GDK_DISPLAY_BROADWAY (GDK_SCREEN_DISPLAY (screen));
+
+  impl = g_object_new (_gdk_window_impl_get_type (), NULL);
+  private->impl = (GdkDrawable *)impl;
+  impl->id = current_id++;
+  g_hash_table_insert (display_broadway->id_ht, GINT_TO_POINTER(impl->id), window);
+  draw_impl = GDK_DRAWABLE_IMPL_BROADWAY (impl);
+  draw_impl->wrapper = GDK_DRAWABLE (window);
+
+  draw_impl->screen = screen;
+
+  g_assert (private->window_type == GDK_WINDOW_TOPLEVEL ||
+           private->window_type == GDK_WINDOW_TEMP);
+  g_assert (GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT);
+
+  display_broadway->toplevels = g_list_prepend (display_broadway->toplevels, impl);
+
+  /* Instead of window manager placement we have this mini hack
+     so that the main/first window is not covered in the demos. */
+  if (impl->id > 1 && private->window_type == GDK_WINDOW_TOPLEVEL)
+    {
+      private->x = 100;
+      private->y = 20;
+    }
+
+  if (display_broadway->output)
+    broadway_output_new_surface (display_broadway->output,
+                                impl->id,
+                                private->x,
+                                private->y,
+                                private->width,
+                                private->height);
+}
+
+
+GdkWindow *
+gdk_window_foreign_new_for_display (GdkDisplay     *display,
+                                   GdkNativeWindow anid)
+{
+  return NULL;
+}
+
+GdkWindow *
+gdk_window_lookup_for_display (GdkDisplay *display, GdkNativeWindow anid)
+{
+  return NULL;
+}
+
+GdkWindow *
+gdk_window_lookup (GdkNativeWindow anid)
+{
+  return NULL;
+}
+
+static void
+_gdk_broadway_window_destroy (GdkWindow *window,
+                             gboolean   recursing,
+                             gboolean   foreign_destroy)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowImplBroadway *impl;
+  GdkDisplayBroadway *display_broadway;
+
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  private = (GdkWindowObject*) window;
+  impl = GDK_WINDOW_IMPL_BROADWAY (private->impl);
+
+  _gdk_selection_window_destroyed (window);
+
+  _gdk_broadway_drawable_finish (private->impl);
+
+  display_broadway = GDK_DISPLAY_BROADWAY (gdk_window_get_display (window));
+  if (display_broadway->output)
+    broadway_output_destroy_surface (display_broadway->output,
+                                    impl->id);
+}
+
+static cairo_surface_t *
+gdk_window_broadway_resize_cairo_surface (GdkWindow       *window,
+                                         cairo_surface_t *surface,
+                                         gint             width,
+                                         gint             height)
+{
+  /* Image surfaces cannot be resized */
+  cairo_surface_destroy (surface);
+
+  return NULL;
+}
+
+void
+_gdk_windowing_window_destroy_foreign (GdkWindow *window)
+{
+}
+
+/* This function is called when the XWindow is really gone.
+ */
+void
+gdk_window_destroy_notify (GdkWindow *window)
+{
+  GdkWindowImplBroadway *window_impl;
+
+  window_impl = GDK_WINDOW_IMPL_BROADWAY (((GdkWindowObject *)window)->impl);
+
+  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_window_broadway_show (GdkWindow *window, gboolean already_mapped)
+{
+  GdkWindowObject *private;
+  GdkWindowImplBroadway *impl;
+  GdkDisplayBroadway *display_broadway;
+
+  private = (GdkWindowObject*) window;
+  impl = GDK_WINDOW_IMPL_BROADWAY (private->impl);
+
+  if (private->event_mask & GDK_STRUCTURE_MASK)
+    _gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE);
+
+  if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
+    _gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE);
+
+  display_broadway = GDK_DISPLAY_BROADWAY (gdk_window_get_display (window));
+  if (display_broadway->output)
+    {
+      broadway_output_show_surface (display_broadway->output, impl->id);
+      queue_dirty_flush (display_broadway);
+    }
+}
+
+static void
+gdk_window_broadway_hide (GdkWindow *window)
+{
+  GdkWindowObject *private;
+  GdkWindowImplBroadway *impl;
+  GdkDisplayBroadway *display_broadway;
+
+  private = (GdkWindowObject*) window;
+  impl = GDK_WINDOW_IMPL_BROADWAY (private->impl);
+
+  if (private->event_mask & GDK_STRUCTURE_MASK)
+    _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
+
+  if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
+    _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
+
+  display_broadway = GDK_DISPLAY_BROADWAY (gdk_window_get_display (window));
+  if (display_broadway->output)
+    {
+      broadway_output_hide_surface (display_broadway->output, impl->id);
+      queue_dirty_flush (display_broadway);
+    }
+
+  if (display_broadway->mouse_in_toplevel == window)
+    {
+      /* TODO: Send leave + enter event, update cursors, etc */
+      display_broadway->mouse_in_toplevel = NULL;
+    }
+
+  _gdk_window_clear_update_area (window);
+}
+
+static void
+gdk_window_broadway_withdraw (GdkWindow *window)
+{
+  gdk_window_broadway_hide (window);
+}
+
+static void
+gdk_window_broadway_move_resize (GdkWindow *window,
+                                gboolean   with_move,
+                                gint       x,
+                                gint       y,
+                                gint       width,
+                                gint       height)
+{
+  GdkWindowObject *private = (GdkWindowObject *) window;;
+  GdkWindowImplBroadway *impl = GDK_WINDOW_IMPL_BROADWAY (private->impl);
+  GdkDisplayBroadway *display_broadway;
+  gboolean changed;
+
+  changed = FALSE;
+
+  display_broadway = GDK_DISPLAY_BROADWAY (gdk_window_get_display (window));
+  if (with_move)
+    {
+      changed = TRUE;
+      private->x = x;
+      private->y = y;
+      if (display_broadway->output != NULL)
+       {
+         broadway_output_move_surface (display_broadway->output,
+                                       impl->id, x, y);
+         queue_dirty_flush (display_broadway);
+       }
+    }
+
+
+  if (width > 0 || height > 0)
+    {
+      if (width < 1)
+       width = 1;
+
+      if (height < 1)
+       height = 1;
+
+      if (width != private->width ||
+         height != private->height)
+       {
+         changed = TRUE;
+
+         /* Resize clears the content */
+         impl->dirty = TRUE;
+         impl->last_synced = FALSE;
+
+         broadway_output_resize_surface (display_broadway->output,
+                                         impl->id, width, height);
+         queue_dirty_flush (display_broadway);
+
+         private->width = width;
+         private->height = height;
+         _gdk_broadway_drawable_update_size (private->impl);
+         gdk_window_invalidate_rect (window, NULL, TRUE);
+       }
+    }
+
+  if (changed)
+    {
+      GdkEvent *event;
+      GList *node;
+
+      event = gdk_event_new (GDK_CONFIGURE);
+      event->configure.window = g_object_ref (window);
+      event->configure.x = private->x;
+      event->configure.y = private->y;
+      event->configure.width = private->width;
+      event->configure.height = private->height;
+
+      gdk_event_set_device (event, GDK_DISPLAY_OBJECT (display_broadway)->core_pointer);
+
+      node = _gdk_event_queue_append (GDK_DISPLAY_OBJECT (display_broadway), event);
+      _gdk_windowing_got_event (GDK_DISPLAY_OBJECT (display_broadway), node, event, 0);
+    }
+}
+
+static gboolean
+gdk_window_broadway_reparent (GdkWindow *window,
+                         GdkWindow *new_parent,
+                         gint       x,
+                         gint       y)
+{
+  return FALSE;
+}
+
+static void
+gdk_window_broadway_raise (GdkWindow *window)
+{
+}
+
+static void
+gdk_window_broadway_restack_under (GdkWindow *window,
+                             GList *native_siblings /* in requested order, first is bottom-most */)
+{
+}
+
+static void
+gdk_window_broadway_restack_toplevel (GdkWindow *window,
+                                GdkWindow *sibling,
+                                gboolean   above)
+{
+}
+
+static void
+gdk_window_broadway_lower (GdkWindow *window)
+{
+}
+
+
+void
+gdk_window_focus (GdkWindow *window,
+                  guint32    timestamp)
+{
+}
+
+void
+gdk_window_set_type_hint (GdkWindow        *window,
+                         GdkWindowTypeHint hint)
+{
+}
+
+GdkWindowTypeHint
+gdk_window_get_type_hint (GdkWindow *window)
+{
+  return GDK_WINDOW_TYPE_HINT_NORMAL;
+}
+
+void
+gdk_window_set_modal_hint (GdkWindow *window,
+                          gboolean   modal)
+{
+}
+
+void
+gdk_window_set_skip_taskbar_hint (GdkWindow *window,
+                                  gboolean   skips_taskbar)
+{
+}
+
+void
+gdk_window_set_skip_pager_hint (GdkWindow *window,
+                                gboolean   skips_pager)
+{
+}
+
+void
+gdk_window_set_urgency_hint (GdkWindow *window,
+                            gboolean   urgent)
+{
+}
+
+void
+gdk_window_set_geometry_hints (GdkWindow         *window,
+                              const GdkGeometry *geometry,
+                              GdkWindowHints     geom_mask)
+{
+}
+
+void
+gdk_window_set_title (GdkWindow   *window,
+                     const gchar *title)
+{
+}
+
+void
+gdk_window_set_role (GdkWindow   *window,
+                    const gchar *role)
+{
+}
+
+void
+gdk_window_set_startup_id (GdkWindow   *window,
+                          const gchar *startup_id)
+{
+}
+
+void
+gdk_window_set_transient_for (GdkWindow *window,
+                             GdkWindow *parent)
+{
+}
+
+static void
+gdk_window_broadway_set_background (GdkWindow      *window,
+                               cairo_pattern_t *pattern)
+{
+  return;
+}
+
+static void
+gdk_window_broadway_set_device_cursor (GdkWindow *window,
+                                  GdkDevice *device,
+                                  GdkCursor *cursor)
+{
+  GdkWindowObject *private;
+  GdkWindowImplBroadway *impl;
+
+  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (GDK_IS_DEVICE (device));
+
+  private = (GdkWindowObject *) window;
+  impl = GDK_WINDOW_IMPL_BROADWAY (private->impl);
+
+  if (!cursor)
+    g_hash_table_remove (impl->device_cursor, device);
+  else
+    {
+      _gdk_broadway_cursor_update_theme (cursor);
+      g_hash_table_replace (impl->device_cursor,
+                            device, gdk_cursor_ref (cursor));
+    }
+
+  if (!GDK_WINDOW_DESTROYED (window))
+    GDK_DEVICE_GET_CLASS (device)->set_window_cursor (device, window, cursor);
+}
+
+GdkCursor *
+_gdk_broadway_window_get_cursor (GdkWindow *window)
+{
+  GdkWindowObject *private;
+  GdkWindowImplBroadway *impl;
+
+  g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
+
+  private = (GdkWindowObject *)window;
+  impl = GDK_WINDOW_IMPL_BROADWAY (private->impl);
+
+  return impl->cursor;
+}
+
+static void
+gdk_window_broadway_get_geometry (GdkWindow *window,
+                             gint      *x,
+                             gint      *y,
+                             gint      *width,
+                             gint      *height,
+                             gint      *depth)
+{
+}
+
+static gint
+gdk_window_broadway_get_root_coords (GdkWindow *window,
+                               gint       x,
+                               gint       y,
+                               gint      *root_x,
+                               gint      *root_y)
+{
+  if (root_x)
+    *root_x = x;
+  if (root_y)
+    *root_y = y;
+
+  return 1;
+}
+
+void
+gdk_window_get_root_origin (GdkWindow *window,
+                           gint      *x,
+                           gint      *y)
+{
+  if (x)
+    *x = 0;
+
+  if (y)
+    *y = 0;
+}
+
+void
+gdk_window_get_frame_extents (GdkWindow    *window,
+                              GdkRectangle *rect)
+{
+  GdkWindowObject *private;
+
+  g_return_if_fail (rect != NULL);
+
+  private = (GdkWindowObject*) window;
+
+  rect->x = private->x;
+  rect->y = private->y;
+  rect->width = private->width;
+  rect->height = private->height;
+}
+
+void
+_gdk_windowing_get_device_state (GdkDisplay       *display,
+                                 GdkDevice        *device,
+                                 GdkScreen       **screen,
+                                 gint             *x,
+                                 gint             *y,
+                                 GdkModifierType  *mask)
+{
+  if (display->closed)
+    return;
+
+  *screen = gdk_display_get_default_screen (display);
+  *x = 0;
+  *y = 0;
+  *mask = 0;
+}
+
+static gboolean
+gdk_window_broadway_get_device_state (GdkWindow       *window,
+                                     GdkDevice       *device,
+                                     gint            *x,
+                                     gint            *y,
+                                     GdkModifierType *mask)
+{
+  *x = 0;
+  *y = 0;
+  *mask = 0;
+  return FALSE;
+}
+
+void
+gdk_display_warp_pointer (GdkDisplay *display,
+                         GdkScreen  *screen,
+                         gint        x,
+                         gint        y)
+{
+  GdkDevice *device;
+
+  g_return_if_fail (GDK_IS_DISPLAY (display));
+  g_return_if_fail (GDK_IS_SCREEN (screen));
+
+  device = display->core_pointer;
+  GDK_DEVICE_GET_CLASS (device)->warp (device, screen, x, y);
+}
+
+void
+gdk_display_warp_device (GdkDisplay *display,
+                         GdkDevice  *device,
+                         GdkScreen  *screen,
+                         gint        x,
+                         gint        y)
+{
+  g_return_if_fail (GDK_IS_DISPLAY (display));
+  g_return_if_fail (GDK_IS_DEVICE (device));
+  g_return_if_fail (GDK_IS_SCREEN (screen));
+  g_return_if_fail (display == gdk_device_get_display (device));
+
+  GDK_DEVICE_GET_CLASS (device)->warp (device, screen, x, y);
+}
+
+GdkWindow*
+_gdk_windowing_window_at_device_position (GdkDisplay      *display,
+                                          GdkDevice       *device,
+                                          gint            *win_x,
+                                          gint            *win_y,
+                                          GdkModifierType *mask,
+                                          gboolean         get_toplevel)
+{
+  GdkWindow *window;
+  GdkWindowObject *private;
+  GdkDisplayBroadway *display_broadway;
+  GdkScreen *screen;
+
+  display_broadway = GDK_DISPLAY_BROADWAY (display);
+  screen = gdk_display_get_screen (display, 0);
+  window = _gdk_window_find_child_at (gdk_screen_get_root_window (screen),
+                                     display_broadway->last_x,
+                                     display_broadway->last_y);
+
+  if (window != NULL)
+    {
+      private = (GdkWindowObject *)window;
+      *win_x = display_broadway->last_x - private->x;
+      *win_y = display_broadway->last_y - private->y;
+      if (mask)
+       *mask = 0;
+    }
+
+  return window;
+}
+
+static GdkEventMask
+gdk_window_broadway_get_events (GdkWindow *window)
+{
+  if (GDK_WINDOW_DESTROYED (window))
+    return 0;
+
+  return 0;
+}
+static void
+gdk_window_broadway_set_events (GdkWindow    *window,
+                           GdkEventMask  event_mask)
+{
+  if (!GDK_WINDOW_DESTROYED (window))
+    {
+    }
+}
+
+static void
+gdk_window_broadway_shape_combine_region (GdkWindow       *window,
+                                     const cairo_region_t *shape_region,
+                                     gint             offset_x,
+                                     gint             offset_y)
+{
+}
+
+static void
+gdk_window_broadway_input_shape_combine_region (GdkWindow       *window,
+                                          const cairo_region_t *shape_region,
+                                          gint             offset_x,
+                                          gint             offset_y)
+{
+}
+
+
+void
+gdk_window_set_override_redirect (GdkWindow *window,
+                                 gboolean override_redirect)
+{
+}
+
+void
+gdk_window_set_accept_focus (GdkWindow *window,
+                            gboolean accept_focus)
+{
+  GdkWindowObject *private;
+
+  private = (GdkWindowObject *)window;
+
+  accept_focus = accept_focus != FALSE;
+
+  if (private->accept_focus != accept_focus)
+    {
+      private->accept_focus = accept_focus;
+    }
+}
+
+void
+gdk_window_set_focus_on_map (GdkWindow *window,
+                            gboolean focus_on_map)
+{
+  GdkWindowObject *private;
+
+  private = (GdkWindowObject *)window;
+
+  focus_on_map = focus_on_map != FALSE;
+
+  if (private->focus_on_map != focus_on_map)
+    {
+      private->focus_on_map = focus_on_map;
+    }
+}
+
+
+void
+gdk_window_set_icon_list (GdkWindow *window,
+                         GList     *pixbufs)
+{
+}
+
+void
+gdk_window_set_icon_name (GdkWindow   *window, 
+                         const gchar *name)
+{
+  GdkDisplay *display;
+
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
+    return;
+
+  display = gdk_window_get_display (window);
+
+  g_object_set_qdata (G_OBJECT (window), g_quark_from_static_string ("gdk-icon-name-set"),
+                      GUINT_TO_POINTER (name != NULL));
+}
+
+void
+gdk_window_iconify (GdkWindow *window)
+{
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
+    return;
+}
+
+void
+gdk_window_deiconify (GdkWindow *window)
+{
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
+    return;
+}
+
+void
+gdk_window_stick (GdkWindow *window)
+{
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
+    return;
+
+}
+
+void
+gdk_window_unstick (GdkWindow *window)
+{
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
+    return;
+
+}
+
+void
+gdk_window_maximize (GdkWindow *window)
+{
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
+    return;
+
+}
+
+void
+gdk_window_unmaximize (GdkWindow *window)
+{
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
+    return;
+
+}
+
+void
+gdk_window_fullscreen (GdkWindow *window)
+{
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
+    return;
+
+}
+
+void
+gdk_window_unfullscreen (GdkWindow *window)
+{
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
+    return;
+
+}
+
+void
+gdk_window_set_keep_above (GdkWindow *window,
+                           gboolean   setting)
+{
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
+    return;
+
+}
+
+void
+gdk_window_set_keep_below (GdkWindow *window, gboolean setting)
+{
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
+    return;
+
+}
+
+GdkWindow *
+gdk_window_get_group (GdkWindow *window)
+{
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return NULL;
+
+  return window;
+}
+
+void
+gdk_window_set_group (GdkWindow *window,
+                     GdkWindow *leader)
+{
+}
+
+void
+gdk_window_set_decorations (GdkWindow      *window,
+                           GdkWMDecoration decorations)
+{
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
+    return;
+
+}
+
+gboolean
+gdk_window_get_decorations(GdkWindow       *window,
+                          GdkWMDecoration *decorations)
+{
+  gboolean result = FALSE;
+
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
+    return FALSE;
+
+  return result;
+}
+
+void
+gdk_window_set_functions (GdkWindow    *window,
+                         GdkWMFunction functions)
+{
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
+    return;
+}
+
+cairo_region_t *
+_gdk_windowing_window_get_shape (GdkWindow *window)
+{
+  return NULL;
+}
+
+cairo_region_t *
+_gdk_windowing_window_get_input_shape (GdkWindow *window)
+{
+  return NULL;
+}
+
+
+static gboolean
+gdk_window_broadway_set_static_gravities (GdkWindow *window,
+                                     gboolean   use_static)
+{
+  return TRUE;
+}
+
+void
+gdk_window_begin_resize_drag (GdkWindow     *window,
+                              GdkWindowEdge  edge,
+                              gint           button,
+                              gint           root_x,
+                              gint           root_y,
+                              guint32        timestamp)
+{
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
+    return;
+
+}
+
+void
+gdk_window_begin_move_drag (GdkWindow *window,
+                            gint       button,
+                            gint       root_x,
+                            gint       root_y,
+                            guint32    timestamp)
+{
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
+
+}
+
+void
+gdk_window_enable_synchronized_configure (GdkWindow *window)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+
+  if (!GDK_IS_WINDOW_IMPL_BROADWAY (private->impl))
+    return;
+}
+
+void
+gdk_window_configure_finished (GdkWindow *window)
+{
+  if (!WINDOW_IS_TOPLEVEL (window))
+    return;
+}
+
+void
+_gdk_windowing_window_beep (GdkWindow *window)
+{
+  GdkDisplay *display;
+
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  display = GDK_WINDOW_DISPLAY (window);
+
+  gdk_display_beep (display);
+}
+
+void
+gdk_window_set_opacity (GdkWindow *window,
+                       gdouble    opacity)
+{
+  GdkDisplay *display;
+
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
+
+  display = gdk_window_get_display (window);
+
+  if (opacity < 0)
+    opacity = 0;
+  else if (opacity > 1)
+    opacity = 1;
+
+}
+
+void
+_gdk_windowing_window_set_composited (GdkWindow *window,
+                                      gboolean   composited)
+{
+}
+
+void
+_gdk_windowing_window_process_updates_recurse (GdkWindow *window,
+                                               cairo_region_t *region)
+{
+  GdkWindowObject *private;
+  GdkWindowImplBroadway *impl;
+
+  _gdk_window_process_updates_recurse (window, region);
+
+  private = (GdkWindowObject *)window;
+  impl = GDK_WINDOW_IMPL_BROADWAY (private->impl);
+  impl->dirty = TRUE;
+  queue_dirty_flush (GDK_DISPLAY_BROADWAY (gdk_window_get_display (window)));
+}
+
+void
+_gdk_windowing_before_process_all_updates (void)
+{
+}
+
+void
+_gdk_windowing_after_process_all_updates (void)
+{
+}
+
+gboolean
+_gdk_broadway_window_queue_antiexpose (GdkWindow *window,
+                                 cairo_region_t *area)
+{
+  return TRUE;
+}
+
+static void
+copy_region (cairo_surface_t *surface,
+            cairo_region_t *area,
+            gint            dx,
+            gint            dy)
+{
+  cairo_t *cr;
+
+  cr = cairo_create (surface);
+
+  gdk_cairo_region (cr, area);
+  cairo_clip (cr);
+
+  /* NB: This is a self-copy and Cairo doesn't support that yet.
+   * So we do a litle trick.
+   */
+  cairo_push_group (cr);
+
+  cairo_set_source_surface (cr, surface, dx, dy);
+  cairo_paint (cr);
+
+  cairo_pop_group_to_source (cr);
+  cairo_paint (cr);
+
+  cairo_destroy (cr);
+}
+
+void
+_gdk_broadway_window_translate (GdkWindow      *window,
+                               cairo_region_t *area,
+                               gint            dx,
+                               gint            dy)
+{
+  GdkWindowObject *private;
+  GdkDrawableImplBroadway *impl;
+  GdkDisplayBroadway *display_broadway;
+  int n_rects, i;
+  BroadwayRect *rects;
+  cairo_rectangle_int_t rect;
+
+  private = (GdkWindowObject *)window;
+  impl = GDK_DRAWABLE_IMPL_BROADWAY (private->impl);
+
+  if (impl->surface)
+    {
+      copy_region (impl->surface, area, dx, dy);
+      if (GDK_WINDOW_IMPL_BROADWAY (impl)->last_synced)
+       {
+         copy_region (impl->last_surface, area, dx, dy);
+         n_rects = cairo_region_num_rectangles (area);
+         rects = g_new (BroadwayRect, n_rects);
+         for (i = 0; i < n_rects; i++)
+           {
+             cairo_region_get_rectangle (area, i, &rect);
+             rects[i].x = rect.x;
+             rects[i].y = rect.y;
+             rects[i].width = rect.width;
+             rects[i].height = rect.height;
+           }
+         display_broadway = GDK_DISPLAY_BROADWAY (gdk_window_get_display (window));
+         broadway_output_copy_rectangles (display_broadway->output,
+                                          GDK_WINDOW_IMPL_BROADWAY (impl)->id,
+                                          rects, n_rects, dx, dy);
+         queue_dirty_flush (display_broadway);
+         g_free (rects);
+       }
+    }
+}
+
+static void
+gdk_window_impl_iface_init (GdkWindowImplIface *iface)
+{
+  iface->show = gdk_window_broadway_show;
+  iface->hide = gdk_window_broadway_hide;
+  iface->withdraw = gdk_window_broadway_withdraw;
+  iface->set_events = gdk_window_broadway_set_events;
+  iface->get_events = gdk_window_broadway_get_events;
+  iface->raise = gdk_window_broadway_raise;
+  iface->lower = gdk_window_broadway_lower;
+  iface->restack_under = gdk_window_broadway_restack_under;
+  iface->restack_toplevel = gdk_window_broadway_restack_toplevel;
+  iface->move_resize = gdk_window_broadway_move_resize;
+  iface->set_background = gdk_window_broadway_set_background;
+  iface->reparent = gdk_window_broadway_reparent;
+  iface->set_device_cursor = gdk_window_broadway_set_device_cursor;
+  iface->get_geometry = gdk_window_broadway_get_geometry;
+  iface->get_root_coords = gdk_window_broadway_get_root_coords;
+  iface->get_device_state = gdk_window_broadway_get_device_state;
+  iface->shape_combine_region = gdk_window_broadway_shape_combine_region;
+  iface->input_shape_combine_region = gdk_window_broadway_input_shape_combine_region;
+  iface->set_static_gravities = gdk_window_broadway_set_static_gravities;
+  iface->queue_antiexpose = _gdk_broadway_window_queue_antiexpose;
+  iface->translate = _gdk_broadway_window_translate;
+  iface->destroy = _gdk_broadway_window_destroy;
+  iface->resize_cairo_surface = gdk_window_broadway_resize_cairo_surface;
+}
diff --git a/gdk/broadway/gdkwindow-broadway.h b/gdk/broadway/gdkwindow-broadway.h
new file mode 100644 (file)
index 0000000..0871f29
--- /dev/null
@@ -0,0 +1,69 @@
+/* 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_WINDOW_BROADWAY_H__
+#define __GDK_WINDOW_BROADWAY_H__
+
+#include <gdk/broadway/gdkdrawable-broadway.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GdkWindowImplBroadway GdkWindowImplBroadway;
+typedef struct _GdkWindowImplBroadwayClass GdkWindowImplBroadwayClass;
+
+/* Window implementation for Broadway
+ */
+
+#define GDK_TYPE_WINDOW_IMPL_BROADWAY              (gdk_window_impl_broadway_get_type ())
+#define GDK_WINDOW_IMPL_BROADWAY(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_WINDOW_IMPL_BROADWAY, GdkWindowImplBroadway))
+#define GDK_WINDOW_IMPL_BROADWAY_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_WINDOW_IMPL_BROADWAY, GdkWindowImplBroadwayClass))
+#define GDK_IS_WINDOW_IMPL_BROADWAY(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_WINDOW_IMPL_BROADWAY))
+#define GDK_IS_WINDOW_IMPL_BROADWAY_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_WINDOW_IMPL_BROADWAY))
+#define GDK_WINDOW_IMPL_BROADWAY_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_WINDOW_IMPL_BROADWAY, GdkWindowImplBroadwayClass))
+
+struct _GdkWindowImplBroadway
+{
+  GdkDrawableImplBroadway parent_instance;
+
+  int id;
+  GdkCursor *cursor;
+  GHashTable *device_cursor;
+
+  gint8 toplevel_window_type;
+  gboolean dirty;
+  gboolean last_synced;
+};
+
+struct _GdkWindowImplBroadwayClass
+{
+  GdkDrawableImplBroadwayClass parent_class;
+};
+
+GType gdk_window_impl_broadway_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GDK_WINDOW_BROADWAY_H__ */
diff --git a/gdk/broadway/toarray.pl b/gdk/broadway/toarray.pl
new file mode 100755 (executable)
index 0000000..e430885
--- /dev/null
@@ -0,0 +1,15 @@
+#!/usr/bin/perl -w
+
+my $FILENAME = $ARGV[0];
+
+open FILE, $FILENAME or die "Cannot open $FILENAME";
+
+my $ARRAYNAME = $ARGV[1];
+print "static const char $ARRAYNAME\[\] =";
+while (<FILE>) {
+    s@\\@\\\\@g;
+    s@"@\\"@g;
+    chomp ($_);
+    print "\n  \"$_\\n\"";
+}
+print ";\n";
index d95f3de7d65c4efdf34770e3f4827d8fc22b4b95..d740dae1f74ce3a1180a03fa6354e58a392dbf9c 100644 (file)
@@ -867,18 +867,22 @@ gtkinclude_HEADERS = $(gtk_public_h_sources) $(gtk_semi_private_h_sources) $(gtk
 gtkunixprintincludedir = $(includedir)/gtk-3.0/unix-print/gtk
 gtkunixprintinclude_HEADERS = $(gtk_unix_print_public_h_sources)
 
+libgtk_broadway_3_0_la_SOURCES = $(gtk_c_sources)
 libgtk_x11_3_0_la_SOURCES = $(gtk_c_sources)
 libgtk_win32_3_0_la_SOURCES = $(gtk_c_sources)
 libgtk_quartz_3_0_la_SOURCES = $(gtk_c_sources)
 
+libgtk_broadway_3_0_la_LDFLAGS = $(libtool_opts)
 libgtk_x11_3_0_la_LDFLAGS = $(libtool_opts)
 libgtk_win32_3_0_la_LDFLAGS = $(libtool_opts) -Wl,-luuid
 libgtk_quartz_3_0_la_LDFLAGS = $(libtool_opts)
 
+libgtk_broadway_3_0_la_LIBADD = $(libadd)
 libgtk_x11_3_0_la_LIBADD = $(libadd)
 libgtk_win32_3_0_la_LIBADD = $(libadd) -lole32 -lgdi32 -lcomdlg32 -lwinspool -lcomctl32
 libgtk_quartz_3_0_la_LIBADD = $(libadd)
 
+libgtk_broadway_3_0_la_DEPENDENCIES = $(deps)
 libgtk_x11_3_0_la_DEPENDENCIES = $(deps)
 libgtk_win32_3_0_la_DEPENDENCIES = $(gtk_def) $(gtk_win32_res) $(deps)
 libgtk_quartz_3_0_la_DEPENDENCIES = $(deps)
@@ -886,7 +890,7 @@ libgtk_quartz_3_0_la_DEPENDENCIES = $(deps)
 if USE_WIN32
 libgtk_target_ldflags = $(gtk_win32_res_ldflag) $(gtk_win32_symbols)
 endif
-EXTRA_LTLIBRARIES = libgtk-x11-3.0.la libgtk-win32-3.0.la libgtk-quartz-3.0.la
+EXTRA_LTLIBRARIES = libgtk-broadway-3.0.la libgtk-x11-3.0.la libgtk-win32-3.0.la libgtk-quartz-3.0.la
 
 install-exec-hook:
 if DISABLE_EXPLICIT_DEPS
index 995dbf9ee452716f8d6dc53b446955f3ce412746..6dcabb35df5bb2fec8a20560681d1e14f79939a1 100644 (file)
@@ -280,6 +280,8 @@ create_child_plug (guint32  xid,
     return GDK_WINDOW_XID (gtk_widget_get_window (window));
 #elif defined (GDK_WINDOWING_WIN32)
     return (guint32) GDK_WINDOW_HWND (gtk_widget_get_window (window));
+#elif defined (GDK_WINDOWING_BROADWAY)
+    return (guint32) 0; /* Child windows not supported */
 #endif
   else
     return 0;