From: Matt Birkholz <matt@birkholz.chandler.az.us>
Date: Thu, 8 Jul 2010 22:06:07 +0000 (-0700)
Subject: Added scm-layout event handlers and gdk-key support.
X-Git-Tag: 20100708-Gtk
X-Git-Url: https://birchwood-abbey.net/git?a=commitdiff_plain;h=ad8dd99c75397146ed7939b9950c89b88d1eda9f;p=mit-scheme.git

Added scm-layout event handlers and gdk-key support.

A more complete wrapping eliminates the need for c-includes in the
"Hello, World!" example and scm-layout demo.

* doc/gtk/gtk.texinfo: The FFI syntax is no longer used in hello.scm.

* src/gtk/Tags.sh: Fixed the exuberant ctags commandline to avoid
wiping out the Scheme file extensions list, thus punting *.scm.

* src/gtk/demo.scm: Use new callback and event wrappers.

* src/gtk/gtk-object.scm: Use integrate-operator where a parameter is
referenced multiple times.

(gtk-widget-font): Return a PangoFontDescription alien.

(set-gtk-button-clicked-callback!)
(set-gtk-window-delete-event-callback!): More wrapping, to get
C-callback syntax out of hello.scm and demo.scm.

* src/gtk/gtk.pkg: Added keys.scm.  Export new callback and event
wrappers to (gtk).

* src/gtk/gtk.sf: Added keys.scm.

* src/gtk/gtk-ev.scm: Punt impish delete_event callback from hello.

* src/gtk/hello.scm: Simplify.  Use new wrappers.

* src/gtk/keys.scm: New.

* src/gtk/scm-layout.scm: Punted null-alien in favor of 0.  Added an
"event-handlers" vector per widget.  Provide specific event handler
setters, which can translate from toolkit to Scheme constants, so the
provided handlers do not need C- syntax.

(scm-layout-event-handler): Handle expose events directly.  Lookup the
rest in the event-handlers vector.
---

diff --git a/doc/gtk/gtk.texinfo b/doc/gtk/gtk.texinfo
index 2fd3a6306..9dfefa14d 100644
--- a/doc/gtk/gtk.texinfo
+++ b/doc/gtk/gtk.texinfo
@@ -240,7 +240,6 @@ command lines in the @file{src/gtk} directory of your build tree.
 
 @smallexample
   ../microcode/scheme --library ../lib
-  (load-option 'FFI)
   (load-option 'Gtk)
   (ge '(gtk))
   (load "hello")
diff --git a/src/gtk/Tags.sh b/src/gtk/Tags.sh
index 266b054bf..2f95f74b5 100755
--- a/src/gtk/Tags.sh
+++ b/src/gtk/Tags.sh
@@ -3,5 +3,5 @@
 # Utility to make TAGS file for the gtk build directory.
 # The working directory must be the build directory.
 
-etags gtk-shim.h scmwidget.c.stay --langmap=scheme:.cdecl \
+etags gtk-shim.h scmwidget.c.stay --langmap=scheme:+.cdecl \
 	`echo *.scm | sed 's/ gtk-const.scm//'` Includes/*.cdecl
diff --git a/src/gtk/demo.scm b/src/gtk/demo.scm
index 21227d412..c2fc847b8 100644
--- a/src/gtk/demo.scm
+++ b/src/gtk/demo.scm
@@ -24,18 +24,17 @@ USA.
 ;;;; A small drawing in two scm-layout widgets.
 ;;; package: (gtk demo)
 
-
-(c-include "gtk")
-
 (define (scm-layout-demo)
   (let* ((window (gtk-window-new 'toplevel))
 	 (vbox (gtk-vbox-new #t 0))
 	 (scroller1 (gtk-scrolled-window-new))
 	 (scroller2 (gtk-scrolled-window-new))
-	 (layout1 (scm-layout-new 200 200))
-	 (layout2 (scm-layout-new 200 200)))
+	 (layout1 (demo-layout-new 200 200))
+	 (layout2 (demo-layout-new 200 200)))
     (gtk-window-set-title window "scm-layout-demo")
     (gtk-window-set-default-size window 200 400)
+    (set-gtk-window-delete-event-callback!
+     window (lambda () (outf-console "; Closed "window".\n") 0))
     (gtk-container-set-border-width window 10)
     (gtk-container-add scroller1 layout1)
     (gtk-container-add vbox scroller1)
@@ -43,22 +42,14 @@ USA.
     (gtk-container-add vbox scroller2)
     (gtk-container-add window vbox)
     (gtk-widget-show-all window)
-    (g-signal-connect window (C-callback "delete_event")
-      (lambda (w e)
-	w e ;;Ignored.
-	(outf-console "; Closed "window".\n")
-	0))
+
     (let ((drawing (demo-drawing layout1)))
 
       (set-scm-layout-drawing! layout1 drawing)
       (set-scm-layout-scroll-pos! layout1 175 150)
-      (set-scm-widget-event!
-       layout1 (demo-event-handler layout1 (scm-layout-event-handler layout1)))
 
       (set-scm-layout-drawing! layout2 drawing)
       (set-scm-layout-scroll-pos! layout2 175 150)
-      (set-scm-widget-event!
-       layout2 (demo-event-handler layout2 (scm-layout-event-handler layout2)))
 
       (let ((cursor1 (add-box-item drawing 'BOTTOM))
 	    (cursor2 (add-box-item drawing 'BOTTOM)))
@@ -70,6 +61,13 @@ USA.
     (outf-console "; Created "layout1" and "layout2"\n"))
   unspecific)
 
+(define (demo-layout-new width height)
+  (let ((layout (scm-layout-new width height)))
+    (set-scm-layout-motion-handler! layout demo-motion-handler)
+    (set-scm-layout-button-release-handler! layout demo-button-release-handler)
+    (set-scm-layout-key-press-handler! layout demo-key-press-handler)
+    layout))
+
 (define (demo-drawing device)
   ;; DEVICE can (must, at the moment) be a scm-layout.
   (let ((drawing (make-demo-drawing device)))
@@ -100,81 +98,64 @@ USA.
   ;; and mouse motion handler.
   (cursor-items define standard initial-value '()))
 
-(define (demo-event-handler widget old-handler)
-  (named-lambda (scm-layout-demo::handle-event GtkWidget GdkEvent)
-
-    (trace2 ";(scm-layout-demo::event "GtkWidget" "GdkEvent")\n")
-    (let ((type (C-> GdkEvent "GdkEvent any type")))
-      (cond
-       ((fix:= type (C-enum "GDK_MOTION_NOTIFY"))
-	(let* ((drawing (scm-layout-drawing widget))
-	       ;; pointer coords
-	       (xP (floor->exact (C-> GdkEvent "GdkEventMotion x")))
-	       (yP (floor->exact (C-> GdkEvent "GdkEventMotion y")))
-	       ;; scroll offset
-	       (scroll (scm-layout-on-screen-area widget))
-	       (xO (rect-x scroll))
-	       (yO (rect-y scroll))
-	       ;; drawing coords
-	       (x (int:+ xP xO))
-	       (y (int:+ yP yO)))
-	  (trace2 "; Pointer moved to ("x","y") in "widget".\n")
-	  (for-each
-	   (lambda (item)
-	     (if (not (text-item? item))
-		 (trace "; Picked: "item"\n")
-		 (let ((index (text-item-xy-to-index item x y))
-		       (text-area (drawn-item-area item)))
-		   (trace "; Picked: "index" in "(text-item-text item)"\n")
-		   (call-with-text-item-grapheme-rect
-		    item index
-		    (lambda (xG yG widthG heightG)
-		      (for-each
-		       (lambda (cursor.widgets)
-			 (if (memq widget (cdr cursor.widgets))
-			     (begin
-			       (set-box-item-pos-size!
-				(car cursor.widgets)
-				(int:+ xG (rect-x text-area))
-				(int:+ yG (rect-y text-area))
-				widthG heightG)
-			       ;; Keep the cursor on while tracking the mouse.
-			       (set-drawn-item-widgets!
-				(car cursor.widgets)
-				(cdr cursor.widgets)))))
-		       (demo-drawing-cursor-items drawing)))))))
-	   (drawing-pick-list drawing widget x y)))
-	(C-call "gdk_window_get_pointer" #f
-		(C-> GdkEvent "GdkEventMotion window")
-		null-alien null-alien null-alien)
-	1 ;;Handled.
-	)
-
-       ((fix:= type (C-enum "GDK_BUTTON_RELEASE"))
-	(let ((scroll (scm-layout-on-screen-area widget))
-	      (drawing (scm-layout-drawing widget))
-	      (xp (floor->exact (C-> GdkEvent "GdkEventButton x")))
-	      (yp (floor->exact (C-> GdkEvent "GdkEventButton y"))))
-	  (let ((x (int:+ xp (rect-x scroll)))
-		(y (int:+ yp (rect-y scroll))))
-	    (outf-console "; Pointer release at ("x","y").\n")
-	    (for-each
-	     (lambda (item)
-	       (if (not (text-item? item))
-		   (outf-console "; Picked: "item"\n")
-		   (let ((index (text-item-xy-to-index item x y)))
-		     (outf-console "; Picked: "item" (char "index")\n"))))
-	     (drawing-pick-list drawing widget x y))))
-	1 ;;Handled.
-	)
-
-       ((and (= type (C-enum "GDK_KEY_PRESS"))
-	     (= (C-> GdkEvent "GdkEvent key keyval") (C-enum "GDK_D")))
-	(bkpt 'Test)
-	(old-handler GtkWidget GdkEvent))
-
-       (else
-	(old-handler GtkWidget GdkEvent))))))
+(define (demo-motion-handler layout window-x window-y)
+  (trace2 ";(demo-motion-handler "layout" "window-x" "window-y")\n")
+  (let* ((drawing (scm-layout-drawing layout))
+	 (scroll (scm-layout-on-screen-area layout))
+	 (x (int:+ window-x (rect-x scroll)))
+	 (y (int:+ window-y (rect-y scroll))))
+    (trace2 "; Pointer moved to ("x","y") in "layout".\n")
+    (for-each
+      (lambda (item)
+	(if (not (text-item? item))
+	    (trace "; Picked: "item"\n")
+	    (let ((index (text-item-xy-to-index item x y))
+		  (text-area (drawn-item-area item)))
+	      (trace "; Picked: "index" in "(text-item-text item)"\n")
+	      (call-with-text-item-grapheme-rect
+	       item index
+	       (lambda (xG yG widthG heightG)
+		 (for-each
+		   (lambda (cursor.widgets)
+		     (if (memq layout (cdr cursor.widgets))
+			 (begin
+			   (set-box-item-pos-size!
+			    (car cursor.widgets)
+			    (int:+ xG (rect-x text-area))
+			    (int:+ yG (rect-y text-area))
+			    widthG heightG)
+			   ;; Keep the cursor on while tracking the mouse.
+			   (set-drawn-item-widgets!
+			    (car cursor.widgets)
+			    (cdr cursor.widgets)))))
+		   (demo-drawing-cursor-items drawing)))))))
+      (drawing-pick-list drawing layout x y)))
+  1 ;;Handled.
+  )
+
+(define (demo-button-release-handler layout window-x window-y)
+  (trace2 ";(demo-button-release-handler "layout" "window-x" "window-y")\n")
+  (let* ((drawing (scm-layout-drawing layout))
+	 (scroll (scm-layout-on-screen-area layout))
+	 (x (int:+ window-x (rect-x scroll)))
+	 (y (int:+ window-y (rect-y scroll))))
+    (outf-console "; Pointer release at ("x","y").\n")
+    (for-each
+      (lambda (item)
+	(if (not (text-item? item))
+	    (outf-console "; Picked: "item"\n")
+	    (let ((index (text-item-xy-to-index item x y)))
+	      (outf-console "; Picked: "item" (char "index")\n"))))
+      (drawing-pick-list drawing layout x y)))
+  1 ;;Handled.
+  )
+
+(define (demo-key-press-handler layout keyval char-bits)
+  (trace2 ";(demo-key-press-handler "layout" "keyval" "char-bits")\n")
+  (if (and (char? keyval) (char=? keyval #\D))
+      (bkpt 'Test)
+      0 ;;NOT handled.
+      ))
 
 (define (start-blinking drawing)
   (create-thread
diff --git a/src/gtk/gtk-ev.scm b/src/gtk/gtk-ev.scm
index b07b20f68..1aed2ec00 100644
--- a/src/gtk/gtk-ev.scm
+++ b/src/gtk/gtk-ev.scm
@@ -35,16 +35,6 @@ USA.
     (gtk-container-add window gtk-ev)
     (gtk-window-set-title window "gtk-event-viewer")
     (gtk-container-set-border-width window 10)
-    (g-signal-connect window (C-callback "delete_event")
-      (let ((counter 0))
-	(named-lambda (gtk-event-viewer::delete-event w e)
-	  (trace2 ";(gtk-event-viewer::delete_event "w" "e")\n")
-	  (let ((num (number->string (- 2 counter))))
-	    (push-text gtk-ev (list (string-append "Delete me "num" times."))))
-	  (outf-console ";Delete me "(- 2 counter)" times.\n")
-	  (set! counter (1+ counter))
-	  ;; Three or more is the charm.
-	  (if (> counter 2) 0 1))))
     (gtk-widget-show-all window)
     gtk-ev))
 
diff --git a/src/gtk/gtk-object.scm b/src/gtk/gtk-object.scm
index 2ce5da720..23374f29c 100644
--- a/src/gtk/gtk-object.scm
+++ b/src/gtk/gtk-object.scm
@@ -75,7 +75,8 @@ USA.
   (let ((alien (gobject-alien (check-gtk-object gtkobject))))
     (C-> alien "GtkObject flags")))
 
-(define-integrable (check-gtk-object object)
+(declare (integrate-operator check-gtk-object))
+(define (check-gtk-object object)
   (if (gtk-object? object) object
       (error:wrong-type-argument object "<gtk-object>" 'check-gtk-object)))
 
@@ -154,7 +155,8 @@ USA.
      (C-> alien "GtkAdjustment step_increment")
      (C-> alien "GtkAdjustment page_increment"))))
 
-(define-integrable (check-real object)
+(declare (integrate-operator check-real))
+(define (check-real object)
   (if (real? object) object
       (error:wrong-type-argument object "real number" 'check-real)))
 
@@ -214,7 +216,7 @@ USA.
 	(desc (make-alien '|PangoFontDescription|)))
     (C-> alien "GtkWidget style" desc)
     (C-> desc "GtkStyle font_desc" desc)
-    (pango-font-description-to-string desc)))
+    desc))
 
 (define (set-gtk-widget-font! widget desc)
   (let ((font (->PangoFontDescription desc)))
@@ -412,11 +414,13 @@ USA.
 (define-integrable (check-gtk-widget-alien object)
   (gobject-alien (check-gtk-widget object)))
 
-(define-integrable (check-gtk-widget object)
+(declare (integrate-operator check-gtk-widget))
+(define (check-gtk-widget object)
   (if (gtk-widget? object) object
       (error:wrong-type-argument object "<gtk-widget>" 'check-gtk-widget)))
 
-(define-integrable (check-gtk-container object)
+(declare (integrate-operator check-gtk-container))
+(define (check-gtk-container object)
   (if (gtk-container? object) object
       (error:wrong-type-argument object "<gtk-container>"
 				 'check-gtk-container)))
@@ -456,6 +460,19 @@ USA.
     (C-call "gtk_button_new" a)
     (if (alien-null? a) (ferror "Could not create button."))
     b))
+
+(declare (integrate-operator check-gtk-button))
+(define (check-gtk-button object)
+  (if (gtk-button? object) object
+      (error:wrong-type-argument object "<gtk-button>" 'check-gtk-button)))
+
+(define (set-gtk-button-clicked-callback! button handler)
+  (let ((b (check-gtk-button button)))
+    (g-signal-connect
+     b (C-callback "clicked")
+     (lambda (GtkButton)
+       GtkButton			;ignore
+       (handler)))))
 
 
 ;;; GtkVBox
@@ -517,12 +534,14 @@ USA.
 	(p (check-scrolled-window-placement placement)))
     (C-call "gtk_scrolled_window_set_placement" (gobject-alien w) p)))
 
-(define-integrable (check-scrolled-window object)
+(declare (integrate-operator check-scrolled-window))
+(define (check-scrolled-window object)
   (if (gtk-scrolled-window? object) object
       (error:wrong-type-argument object "<gtk-scrolled-window>"
 				 'check-scrolled-window)))
 
-(define-integrable (check-scrollbar-policy object)
+(declare (integrate-operator check-scrollbar-policy))
+(define (check-scrollbar-policy object)
   (case object
     ((ALWAYS)	(C-enum "GTK_POLICY_ALWAYS"))
     ((AUTO)	(C-enum "GTK_POLICY_AUTOMATIC"))
@@ -530,7 +549,8 @@ USA.
     (else (error:wrong-type-argument object "symbol: ALWAYS, AUTO or NEVER"
 				     'check-scrollbar-policy))))
 
-(define-integrable (check-scrolled-window-placement object)
+(declare (integrate-operator check-scrolled-window-placement))
+(define (check-scrolled-window-placement object)
   (case object
     ((TOP-LEFT) (C-enum "GTK_CORNER_TOP_LEFT"))
     ((BOTTOM-LEFT) (C-enum "GTK_CORNER_BOTTOM_LEFT"))
@@ -564,14 +584,16 @@ USA.
     (C-call "gtk_window_set_default_size" alien -1 -1)
     window))
 
-(define-integrable (check-window-type type)
+(declare (integrate-operator check-window-type))
+(define (check-window-type type)
   (case type
     ((TOPLEVEL POPUP) type)
     (else
      (error:wrong-type-argument type "symbol: TOPLEVEL or POPUP"
 				'check-window-type))))
 
-(define-integrable (check-gtk-window object)
+(declare (integrate-operator check-gtk-window))
+(define (check-gtk-window object)
   (if (gtk-window? object) object
       (error:wrong-type-argument object "<gtk-window>" 'check-gtk-window)))
 
@@ -613,6 +635,13 @@ USA.
   (let ((alien (gobject-alien (check-gtk-window window))))
     (C-call "gtk_window_present" alien)))
 
+(define (set-gtk-window-delete-event-callback! window handler)
+  (let ((w (check-gtk-window window)))
+    (g-signal-connect
+     w (C-callback "delete_event")
+     (lambda (GtkWidget GdkEvent)
+       GtkWidget GdkEvent		;ignore
+       (handler)))))
 
 (define trace? #f)
 
diff --git a/src/gtk/gtk.pkg b/src/gtk/gtk.pkg
index 333a604c6..c285c9531 100644
--- a/src/gtk/gtk.pkg
+++ b/src/gtk/gtk.pkg
@@ -81,7 +81,9 @@ USA.
 	  gtk-window-parse-geometry
 	  gtk-window-resize
 	  gtk-window-present
+	  set-gtk-window-delete-event-callback!
 	  <gtk-button> gtk-button-new
+	  set-gtk-button-clicked-callback!
 	  <gtk-label> gtk-label-new
 	  gtk-label-get-text gtk-label-set-text
 	  <gtk-vbox> gtk-vbox-new gtk-box-pack-start gtk-box-pack-end
@@ -112,6 +114,14 @@ USA.
 	  scm-layout-on-screen-area set-scm-layout-scroll-pos!
 	  scm-layout-scroll-step set-scm-layout-scroll-step!
 
+	  set-scm-layout-map-handler!
+	  set-scm-layout-unmap-handler!
+	  set-scm-layout-focus-change-handler!
+	  set-scm-layout-visibility-notify-handler!
+	  set-scm-layout-key-press-handler!
+	  set-scm-layout-motion-handler!
+	  set-scm-layout-button-release-handler!
+
 	  <drawing> make-drawing drawing-widgets
 	  set-drawing-size! drawing-pick-list
 
@@ -157,6 +167,13 @@ USA.
 	  pangos->pixels
 	  pixels->pangos))
 
+(define-package (gtk keys)
+  (parent (gtk))
+  (files "keys")
+  (export (gtk)
+	  gdk-key-state->char-bits
+	  gdk-keyval->name))
+
 (define-package (gtk thread)
   (parent (runtime thread))
   (files "thread")
@@ -193,7 +210,5 @@ USA.
 (define-package (gtk demo)
   (parent (gtk))
   (files "demo")
-  (import (gtk layout)
-	  scm-layout-event-handler)
   (export ()
 	  scm-layout-demo))
\ No newline at end of file
diff --git a/src/gtk/gtk.sf b/src/gtk/gtk.sf
index e38a2ddee..33846a1b4 100644
--- a/src/gtk/gtk.sf
+++ b/src/gtk/gtk.sf
@@ -32,6 +32,7 @@ USA.
   (lambda ()
     (let* ((files.packages
 	    '(("gtk"        . (gtk))
+	      ("keys"	    . (gtk keys))
 	      ("main"       . (gtk main))
 	      ("gobject"    . (gtk gobject))
 	      ("gtk-object" . (gtk gtk-object))
@@ -80,7 +81,7 @@ USA.
 
       ;; These core files depend only on the constants behind the C-
       ;; syntax.
-      (sf+ '("gtk" "main" "gobject" "gtk-object" "pango" "scm-widget")
+      (sf+ '("gtk" "keys" "main" "gobject" "gtk-object" "pango" "scm-widget")
 	   '("gtk-const"))
 
       ;; These files will want the latest rect(angle) and
diff --git a/src/gtk/hello.scm b/src/gtk/hello.scm
index e888dc7b7..debba9b92 100644
--- a/src/gtk/hello.scm
+++ b/src/gtk/hello.scm
@@ -2,10 +2,6 @@
 
 This is Havoc Pennington's Hello World example from GGAD, wrapped in Scheme. |#
 
-(declare (usual-integrations))
-
-(C-include "gtk")
-
 (define (hello)
   (let ((window (gtk-window-new 'toplevel))
 	(button (gtk-button-new))
@@ -15,19 +11,19 @@ This is Havoc Pennington's Hello World example from GGAD, wrapped in Scheme. |#
     (gtk-window-set-title window "Hello")
     (gtk-container-set-border-width button 10)
     (let ((counter 0))
-      (g-signal-connect window (C-callback "delete_event")
-	(lambda (w e)
-	  w e ;ignore
-	  (outf-console ";Bite me "(- 2 counter)" times.\n")
-	  (set! counter (1+ counter))
-	  ;; Three or more is the charm.
-	  (if (> counter 2) 0 1)))
-      (g-signal-connect button (C-callback "clicked")
-	(lambda (w)
-	  w ;ignore
-	  (let ((text (gtk-label-get-text label)))
-	    (gtk-label-set-text
-	     label (list->string (reverse! (string->list text)))))
-	  unspecific)))
+      (set-gtk-window-delete-event-callback!
+       window
+       (lambda ()
+	 (outf-console ";Bite me "(- 2 counter)" times.\n")
+	 (set! counter (1+ counter))
+	 ;; Three or more is the charm.
+	 (if (> counter 2) 0 1)))
+      (set-gtk-button-clicked-callback!
+       button
+       (lambda ()
+	 (let ((text (gtk-label-get-text label)))
+	   (gtk-label-set-text
+	    label (list->string (reverse! (string->list text)))))
+	 unspecific)))
     (gtk-widget-show-all window)
     window))
\ No newline at end of file
diff --git a/src/gtk/keys.scm b/src/gtk/keys.scm
new file mode 100644
index 000000000..7189ceb96
--- /dev/null
+++ b/src/gtk/keys.scm
@@ -0,0 +1,919 @@
+#| -*-Scheme-*-
+
+Copyright (C) 2009, 2010  Matthew Birkholz
+
+This file is part of MIT/GNU Scheme.
+
+MIT/GNU Scheme is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+MIT/GNU Scheme is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with MIT/GNU Scheme; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301,
+USA.
+
+|#
+
+;;;; Gtk Keys
+;;; Package: (gtk keys)
+
+(c-include "gtk")
+
+(define (gdk-key-state->char-bits modifier-state)
+  ;; Given a Gdk modifier-state, returns a bitmap (sum) of
+  ;; char-bit:control, :meta, :super, :hyper.
+  (fix:+
+   (if (zero? (bit-and (C-enum "GDK_CONTROL_MASK") modifier-state))
+       0 char-bit:control)
+   (fix:+
+    (if (zero? (bit-and (C-enum "GDK_META_MASK") modifier-state))
+	0 char-bit:meta)
+    (fix:+
+     (if (zero? (bit-and (C-enum "GDK_SUPER_MASK") modifier-state))
+	 0 char-bit:super)
+     (if (zero? (bit-and (C-enum "GDK_HYPER_MASK") modifier-state))
+	 0 char-bit:hyper)))))
+
+(define (gdk-keyval->name keyval)
+  (let ((entry
+	 (vector-binary-search gtk-key-translation-table
+			       (lambda (u v) (< u v))
+			       (lambda (pair) (car pair))
+			       keyval)))
+    (and entry (cdr entry))))
+
+(define gtk-key-translation-table
+  (sort!
+   (vector
+    (cons (C-enum "GDK_braceleft") 'braceleft)
+    (cons (C-enum "GDK_bar") 'bar)
+    (cons (C-enum "GDK_braceright") 'braceright)
+    (cons (C-enum "GDK_asciitilde") 'asciitilde)
+    (cons (C-enum "GDK_nobreakspace") 'nobreakspace)
+    (cons (C-enum "GDK_exclamdown") 'exclamdown)
+    (cons (C-enum "GDK_cent") 'cent)
+    (cons (C-enum "GDK_sterling") 'sterling)
+    (cons (C-enum "GDK_currency") 'currency)
+    (cons (C-enum "GDK_yen") 'yen)
+    (cons (C-enum "GDK_brokenbar") 'brokenbar)
+    (cons (C-enum "GDK_section") 'section)
+    (cons (C-enum "GDK_diaeresis") 'diaeresis)
+    (cons (C-enum "GDK_copyright") 'copyright)
+    (cons (C-enum "GDK_ordfeminine") 'ordfeminine)
+    (cons (C-enum "GDK_guillemotleft") 'guillemotleft)
+    (cons (C-enum "GDK_notsign") 'notsign)
+    (cons (C-enum "GDK_hyphen") 'hyphen)
+    (cons (C-enum "GDK_registered") 'registered)
+    (cons (C-enum "GDK_macron") 'macron)
+    (cons (C-enum "GDK_degree") 'degree)
+    (cons (C-enum "GDK_plusminus") 'plusminus)
+    (cons (C-enum "GDK_twosuperior") 'twosuperior)
+    (cons (C-enum "GDK_threesuperior") 'threesuperior)
+    (cons (C-enum "GDK_acute") 'acute)
+    (cons (C-enum "GDK_mu") 'mu)
+    (cons (C-enum "GDK_paragraph") 'paragraph)
+    (cons (C-enum "GDK_periodcentered") 'periodcentered)
+    (cons (C-enum "GDK_cedilla") 'cedilla)
+    (cons (C-enum "GDK_onesuperior") 'onesuperior)
+    (cons (C-enum "GDK_masculine") 'masculine)
+    (cons (C-enum "GDK_guillemotright") 'guillemotright)
+    (cons (C-enum "GDK_onequarter") 'onequarter)
+    (cons (C-enum "GDK_onehalf") 'onehalf)
+    (cons (C-enum "GDK_threequarters") 'threequarters)
+    (cons (C-enum "GDK_questiondown") 'questiondown)
+    (cons (C-enum "GDK_Agrave") 'Agrave)
+    (cons (C-enum "GDK_Aacute") 'Aacute)
+    (cons (C-enum "GDK_Acircumflex") 'Acircumflex)
+    (cons (C-enum "GDK_Atilde") 'Atilde)
+    (cons (C-enum "GDK_Adiaeresis") 'Adiaeresis)
+    (cons (C-enum "GDK_Aring") 'Aring)
+    (cons (C-enum "GDK_AE") 'AE)
+    (cons (C-enum "GDK_Ccedilla") 'Ccedilla)
+    (cons (C-enum "GDK_Egrave") 'Egrave)
+    (cons (C-enum "GDK_Eacute") 'Eacute)
+    (cons (C-enum "GDK_Ecircumflex") 'Ecircumflex)
+    (cons (C-enum "GDK_Ediaeresis") 'Ediaeresis)
+    (cons (C-enum "GDK_Igrave") 'Igrave)
+    (cons (C-enum "GDK_Iacute") 'Iacute)
+    (cons (C-enum "GDK_Icircumflex") 'Icircumflex)
+    (cons (C-enum "GDK_Idiaeresis") 'Idiaeresis)
+    (cons (C-enum "GDK_Eth") 'Eth)
+    (cons (C-enum "GDK_Ntilde") 'Ntilde)
+    (cons (C-enum "GDK_Ograve") 'Ograve)
+    (cons (C-enum "GDK_Oacute") 'Oacute)
+    (cons (C-enum "GDK_Ocircumflex") 'Ocircumflex)
+    (cons (C-enum "GDK_Otilde") 'Otilde)
+    (cons (C-enum "GDK_Odiaeresis") 'Odiaeresis)
+    (cons (C-enum "GDK_multiply") 'multiply)
+    (cons (C-enum "GDK_Ooblique") 'Ooblique)
+    (cons (C-enum "GDK_Ugrave") 'Ugrave)
+    (cons (C-enum "GDK_Uacute") 'Uacute)
+    (cons (C-enum "GDK_Ucircumflex") 'Ucircumflex)
+    (cons (C-enum "GDK_Udiaeresis") 'Udiaeresis)
+    (cons (C-enum "GDK_Yacute") 'Yacute)
+    (cons (C-enum "GDK_Thorn") 'Thorn)
+    (cons (C-enum "GDK_ssharp") 'ssharp)
+    (cons (C-enum "GDK_agrave") 'agrave)
+    (cons (C-enum "GDK_aacute") 'aacute)
+    (cons (C-enum "GDK_acircumflex") 'acircumflex)
+    (cons (C-enum "GDK_atilde") 'atilde)
+    (cons (C-enum "GDK_adiaeresis") 'adiaeresis)
+    (cons (C-enum "GDK_aring") 'aring)
+    (cons (C-enum "GDK_ae") 'ae)
+    (cons (C-enum "GDK_ccedilla") 'ccedilla)
+    (cons (C-enum "GDK_egrave") 'egrave)
+    (cons (C-enum "GDK_eacute") 'eacute)
+    (cons (C-enum "GDK_ecircumflex") 'ecircumflex)
+    (cons (C-enum "GDK_ediaeresis") 'ediaeresis)
+    (cons (C-enum "GDK_igrave") 'igrave)
+    (cons (C-enum "GDK_iacute") 'iacute)
+    (cons (C-enum "GDK_icircumflex") 'icircumflex)
+    (cons (C-enum "GDK_idiaeresis") 'idiaeresis)
+    (cons (C-enum "GDK_eth") 'eth)
+    (cons (C-enum "GDK_ntilde") 'ntilde)
+    (cons (C-enum "GDK_ograve") 'ograve)
+    (cons (C-enum "GDK_oacute") 'oacute)
+    (cons (C-enum "GDK_ocircumflex") 'ocircumflex)
+    (cons (C-enum "GDK_otilde") 'otilde)
+    (cons (C-enum "GDK_odiaeresis") 'odiaeresis)
+    (cons (C-enum "GDK_division") 'division)
+    (cons (C-enum "GDK_oslash") 'oslash)
+    (cons (C-enum "GDK_ugrave") 'ugrave)
+    (cons (C-enum "GDK_uacute") 'uacute)
+    (cons (C-enum "GDK_ucircumflex") 'ucircumflex)
+    (cons (C-enum "GDK_udiaeresis") 'udiaeresis)
+    (cons (C-enum "GDK_yacute") 'yacute)
+    (cons (C-enum "GDK_thorn") 'thorn)
+    (cons (C-enum "GDK_ydiaeresis") 'ydiaeresis)
+    (cons (C-enum "GDK_Aogonek") 'Aogonek)
+    (cons (C-enum "GDK_breve") 'breve)
+    (cons (C-enum "GDK_Lstroke") 'Lstroke)
+    (cons (C-enum "GDK_Lcaron") 'Lcaron)
+    (cons (C-enum "GDK_Sacute") 'Sacute)
+    (cons (C-enum "GDK_Scaron") 'Scaron)
+    (cons (C-enum "GDK_Scedilla") 'Scedilla)
+    (cons (C-enum "GDK_Tcaron") 'Tcaron)
+    (cons (C-enum "GDK_Zacute") 'Zacute)
+    (cons (C-enum "GDK_Zcaron") 'Zcaron)
+    (cons (C-enum "GDK_Zabovedot") 'Zabovedot)
+    (cons (C-enum "GDK_aogonek") 'aogonek)
+    (cons (C-enum "GDK_ogonek") 'ogonek)
+    (cons (C-enum "GDK_lstroke") 'lstroke)
+    (cons (C-enum "GDK_lcaron") 'lcaron)
+    (cons (C-enum "GDK_sacute") 'sacute)
+    (cons (C-enum "GDK_caron") 'caron)
+    (cons (C-enum "GDK_scaron") 'scaron)
+    (cons (C-enum "GDK_scedilla") 'scedilla)
+    (cons (C-enum "GDK_tcaron") 'tcaron)
+    (cons (C-enum "GDK_zacute") 'zacute)
+    (cons (C-enum "GDK_doubleacute") 'doubleacute)
+    (cons (C-enum "GDK_zcaron") 'zcaron)
+    (cons (C-enum "GDK_zabovedot") 'zabovedot)
+    (cons (C-enum "GDK_Racute") 'Racute)
+    (cons (C-enum "GDK_Abreve") 'Abreve)
+    (cons (C-enum "GDK_Lacute") 'Lacute)
+    (cons (C-enum "GDK_Cacute") 'Cacute)
+    (cons (C-enum "GDK_Ccaron") 'Ccaron)
+    (cons (C-enum "GDK_Eogonek") 'Eogonek)
+    (cons (C-enum "GDK_Ecaron") 'Ecaron)
+    (cons (C-enum "GDK_Dcaron") 'Dcaron)
+    (cons (C-enum "GDK_Dstroke") 'Dstroke)
+    (cons (C-enum "GDK_Nacute") 'Nacute)
+    (cons (C-enum "GDK_Ncaron") 'Ncaron)
+    (cons (C-enum "GDK_Odoubleacute") 'Odoubleacute)
+    (cons (C-enum "GDK_Rcaron") 'Rcaron)
+    (cons (C-enum "GDK_Uring") 'Uring)
+    (cons (C-enum "GDK_Udoubleacute") 'Udoubleacute)
+    (cons (C-enum "GDK_Tcedilla") 'Tcedilla)
+    (cons (C-enum "GDK_racute") 'racute)
+    (cons (C-enum "GDK_abreve") 'abreve)
+    (cons (C-enum "GDK_lacute") 'lacute)
+    (cons (C-enum "GDK_cacute") 'cacute)
+    (cons (C-enum "GDK_ccaron") 'ccaron)
+    (cons (C-enum "GDK_eogonek") 'eogonek)
+    (cons (C-enum "GDK_ecaron") 'ecaron)
+    (cons (C-enum "GDK_dcaron") 'dcaron)
+    (cons (C-enum "GDK_dstroke") 'dstroke)
+    (cons (C-enum "GDK_nacute") 'nacute)
+    (cons (C-enum "GDK_ncaron") 'ncaron)
+    (cons (C-enum "GDK_odoubleacute") 'odoubleacute)
+    (cons (C-enum "GDK_rcaron") 'rcaron)
+    (cons (C-enum "GDK_uring") 'uring)
+    (cons (C-enum "GDK_udoubleacute") 'udoubleacute)
+    (cons (C-enum "GDK_tcedilla") 'tcedilla)
+    (cons (C-enum "GDK_abovedot") 'abovedot)
+    (cons (C-enum "GDK_Hstroke") 'Hstroke)
+    (cons (C-enum "GDK_Hcircumflex") 'Hcircumflex)
+    (cons (C-enum "GDK_Iabovedot") 'Iabovedot)
+    (cons (C-enum "GDK_Gbreve") 'Gbreve)
+    (cons (C-enum "GDK_Jcircumflex") 'Jcircumflex)
+    (cons (C-enum "GDK_hstroke") 'hstroke)
+    (cons (C-enum "GDK_hcircumflex") 'hcircumflex)
+    (cons (C-enum "GDK_idotless") 'idotless)
+    (cons (C-enum "GDK_gbreve") 'gbreve)
+    (cons (C-enum "GDK_jcircumflex") 'jcircumflex)
+    (cons (C-enum "GDK_Cabovedot") 'Cabovedot)
+    (cons (C-enum "GDK_Ccircumflex") 'Ccircumflex)
+    (cons (C-enum "GDK_Gabovedot") 'Gabovedot)
+    (cons (C-enum "GDK_Gcircumflex") 'Gcircumflex)
+    (cons (C-enum "GDK_Ubreve") 'Ubreve)
+    (cons (C-enum "GDK_Scircumflex") 'Scircumflex)
+    (cons (C-enum "GDK_cabovedot") 'cabovedot)
+    (cons (C-enum "GDK_ccircumflex") 'ccircumflex)
+    (cons (C-enum "GDK_gabovedot") 'gabovedot)
+    (cons (C-enum "GDK_gcircumflex") 'gcircumflex)
+    (cons (C-enum "GDK_ubreve") 'ubreve)
+    (cons (C-enum "GDK_scircumflex") 'scircumflex)
+    (cons (C-enum "GDK_kappa") 'kappa)
+    (cons (C-enum "GDK_Rcedilla") 'Rcedilla)
+    (cons (C-enum "GDK_Itilde") 'Itilde)
+    (cons (C-enum "GDK_Lcedilla") 'Lcedilla)
+    (cons (C-enum "GDK_Emacron") 'Emacron)
+    (cons (C-enum "GDK_Gcedilla") 'Gcedilla)
+    (cons (C-enum "GDK_Tslash") 'Tslash)
+    (cons (C-enum "GDK_rcedilla") 'rcedilla)
+    (cons (C-enum "GDK_itilde") 'itilde)
+    (cons (C-enum "GDK_lcedilla") 'lcedilla)
+    (cons (C-enum "GDK_emacron") 'emacron)
+    (cons (C-enum "GDK_gcedilla") 'gcedilla)
+    (cons (C-enum "GDK_tslash") 'tslash)
+    (cons (C-enum "GDK_ENG") 'ENG)
+    (cons (C-enum "GDK_eng") 'eng)
+    (cons (C-enum "GDK_Amacron") 'Amacron)
+    (cons (C-enum "GDK_Iogonek") 'Iogonek)
+    (cons (C-enum "GDK_Eabovedot") 'Eabovedot)
+    (cons (C-enum "GDK_Imacron") 'Imacron)
+    (cons (C-enum "GDK_Ncedilla") 'Ncedilla)
+    (cons (C-enum "GDK_Omacron") 'Omacron)
+    (cons (C-enum "GDK_Kcedilla") 'Kcedilla)
+    (cons (C-enum "GDK_Uogonek") 'Uogonek)
+    (cons (C-enum "GDK_Utilde") 'Utilde)
+    (cons (C-enum "GDK_Umacron") 'Umacron)
+    (cons (C-enum "GDK_amacron") 'amacron)
+    (cons (C-enum "GDK_iogonek") 'iogonek)
+    (cons (C-enum "GDK_eabovedot") 'eabovedot)
+    (cons (C-enum "GDK_imacron") 'imacron)
+    (cons (C-enum "GDK_ncedilla") 'ncedilla)
+    (cons (C-enum "GDK_omacron") 'omacron)
+    (cons (C-enum "GDK_kcedilla") 'kcedilla)
+    (cons (C-enum "GDK_uogonek") 'uogonek)
+    (cons (C-enum "GDK_utilde") 'utilde)
+    (cons (C-enum "GDK_umacron") 'umacron)
+    (cons (C-enum "GDK_overline") 'overline)
+    (cons (C-enum "GDK_kana_fullstop") 'kana-fullstop)
+    (cons (C-enum "GDK_kana_openingbracket") 'kana-openingbracket)
+    (cons (C-enum "GDK_kana_closingbracket") 'kana-closingbracket)
+    (cons (C-enum "GDK_kana_comma") 'kana-comma)
+    (cons (C-enum "GDK_kana_conjunctive") 'kana-conjunctive)
+    (cons (C-enum "GDK_kana_WO") 'kana-WO)
+    (cons (C-enum "GDK_kana_a") 'kana-a)
+    (cons (C-enum "GDK_kana_i") 'kana-i)
+    (cons (C-enum "GDK_kana_u") 'kana-u)
+    (cons (C-enum "GDK_kana_e") 'kana-e)
+    (cons (C-enum "GDK_kana_o") 'kana-o)
+    (cons (C-enum "GDK_kana_ya") 'kana-ya)
+    (cons (C-enum "GDK_kana_yu") 'kana-yu)
+    (cons (C-enum "GDK_kana_yo") 'kana-yo)
+    (cons (C-enum "GDK_kana_tu") 'kana-tu)
+    (cons (C-enum "GDK_prolongedsound") 'prolongedsound)
+    (cons (C-enum "GDK_kana_A") 'kana-A)
+    (cons (C-enum "GDK_kana_I") 'kana-I)
+    (cons (C-enum "GDK_kana_U") 'kana-U)
+    (cons (C-enum "GDK_kana_E") 'kana-E)
+    (cons (C-enum "GDK_kana_O") 'kana-O)
+    (cons (C-enum "GDK_kana_KA") 'kana-KA)
+    (cons (C-enum "GDK_kana_KI") 'kana-KI)
+    (cons (C-enum "GDK_kana_KU") 'kana-KU)
+    (cons (C-enum "GDK_kana_KE") 'kana-KE)
+    (cons (C-enum "GDK_kana_KO") 'kana-KO)
+    (cons (C-enum "GDK_kana_SA") 'kana-SA)
+    (cons (C-enum "GDK_kana_SHI") 'kana-SHI)
+    (cons (C-enum "GDK_kana_SU") 'kana-SU)
+    (cons (C-enum "GDK_kana_SE") 'kana-SE)
+    (cons (C-enum "GDK_kana_SO") 'kana-SO)
+    (cons (C-enum "GDK_kana_TA") 'kana-TA)
+    (cons (C-enum "GDK_kana_TI") 'kana-TI)
+    (cons (C-enum "GDK_kana_TU") 'kana-TU)
+    (cons (C-enum "GDK_kana_TE") 'kana-TE)
+    (cons (C-enum "GDK_kana_TO") 'kana-TO)
+    (cons (C-enum "GDK_kana_NA") 'kana-NA)
+    (cons (C-enum "GDK_kana_NI") 'kana-NI)
+    (cons (C-enum "GDK_kana_NU") 'kana-NU)
+    (cons (C-enum "GDK_kana_NE") 'kana-NE)
+    (cons (C-enum "GDK_kana_NO") 'kana-NO)
+    (cons (C-enum "GDK_kana_HA") 'kana-HA)
+    (cons (C-enum "GDK_kana_HI") 'kana-HI)
+    (cons (C-enum "GDK_kana_HU") 'kana-HU)
+    (cons (C-enum "GDK_kana_HE") 'kana-HE)
+    (cons (C-enum "GDK_kana_HO") 'kana-HO)
+    (cons (C-enum "GDK_kana_MA") 'kana-MA)
+    (cons (C-enum "GDK_kana_MI") 'kana-MI)
+    (cons (C-enum "GDK_kana_MU") 'kana-MU)
+    (cons (C-enum "GDK_kana_ME") 'kana-ME)
+    (cons (C-enum "GDK_kana_MO") 'kana-MO)
+    (cons (C-enum "GDK_kana_YA") 'kana-YA)
+    (cons (C-enum "GDK_kana_YU") 'kana-YU)
+    (cons (C-enum "GDK_kana_YO") 'kana-YO)
+    (cons (C-enum "GDK_kana_RA") 'kana-RA)
+    (cons (C-enum "GDK_kana_RI") 'kana-RI)
+    (cons (C-enum "GDK_kana_RU") 'kana-RU)
+    (cons (C-enum "GDK_kana_RE") 'kana-RE)
+    (cons (C-enum "GDK_kana_RO") 'kana-RO)
+    (cons (C-enum "GDK_kana_WA") 'kana-WA)
+    (cons (C-enum "GDK_kana_N") 'kana-N)
+    (cons (C-enum "GDK_voicedsound") 'voicedsound)
+    (cons (C-enum "GDK_semivoicedsound") 'semivoicedsound)
+    (cons (C-enum "GDK_Arabic_comma") 'Arabic-comma)
+    (cons (C-enum "GDK_Arabic_semicolon") 'Arabic-semicolon)
+    (cons (C-enum "GDK_Arabic_question_mark") 'Arabic-question-mark)
+    (cons (C-enum "GDK_Arabic_hamza") 'Arabic-hamza)
+    (cons (C-enum "GDK_Arabic_maddaonalef") 'Arabic-maddaonalef)
+    (cons (C-enum "GDK_Arabic_hamzaonalef") 'Arabic-hamzaonalef)
+    (cons (C-enum "GDK_Arabic_hamzaonwaw") 'Arabic-hamzaonwaw)
+    (cons (C-enum "GDK_Arabic_hamzaunderalef") 'Arabic-hamzaunderalef)
+    (cons (C-enum "GDK_Arabic_hamzaonyeh") 'Arabic-hamzaonyeh)
+    (cons (C-enum "GDK_Arabic_alef") 'Arabic-alef)
+    (cons (C-enum "GDK_Arabic_beh") 'Arabic-beh)
+    (cons (C-enum "GDK_Arabic_tehmarbuta") 'Arabic-tehmarbuta)
+    (cons (C-enum "GDK_Arabic_teh") 'Arabic-teh)
+    (cons (C-enum "GDK_Arabic_theh") 'Arabic-theh)
+    (cons (C-enum "GDK_Arabic_jeem") 'Arabic-jeem)
+    (cons (C-enum "GDK_Arabic_hah") 'Arabic-hah)
+    (cons (C-enum "GDK_Arabic_khah") 'Arabic-khah)
+    (cons (C-enum "GDK_Arabic_dal") 'Arabic-dal)
+    (cons (C-enum "GDK_Arabic_thal") 'Arabic-thal)
+    (cons (C-enum "GDK_Arabic_ra") 'Arabic-ra)
+    (cons (C-enum "GDK_Arabic_zain") 'Arabic-zain)
+    (cons (C-enum "GDK_Arabic_seen") 'Arabic-seen)
+    (cons (C-enum "GDK_Arabic_sheen") 'Arabic-sheen)
+    (cons (C-enum "GDK_Arabic_sad") 'Arabic-sad)
+    (cons (C-enum "GDK_Arabic_dad") 'Arabic-dad)
+    (cons (C-enum "GDK_Arabic_tah") 'Arabic-tah)
+    (cons (C-enum "GDK_Arabic_zah") 'Arabic-zah)
+    (cons (C-enum "GDK_Arabic_ain") 'Arabic-ain)
+    (cons (C-enum "GDK_Arabic_ghain") 'Arabic-ghain)
+    (cons (C-enum "GDK_Arabic_tatweel") 'Arabic-tatweel)
+    (cons (C-enum "GDK_Arabic_feh") 'Arabic-feh)
+    (cons (C-enum "GDK_Arabic_qaf") 'Arabic-qaf)
+    (cons (C-enum "GDK_Arabic_kaf") 'Arabic-kaf)
+    (cons (C-enum "GDK_Arabic_lam") 'Arabic-lam)
+    (cons (C-enum "GDK_Arabic_meem") 'Arabic-meem)
+    (cons (C-enum "GDK_Arabic_noon") 'Arabic-noon)
+    (cons (C-enum "GDK_Arabic_heh") 'Arabic-heh)
+    (cons (C-enum "GDK_Arabic_waw") 'Arabic-waw)
+    (cons (C-enum "GDK_Arabic_alefmaksura") 'Arabic-alefmaksura)
+    (cons (C-enum "GDK_Arabic_yeh") 'Arabic-yeh)
+    (cons (C-enum "GDK_Arabic_fathatan") 'Arabic-fathatan)
+    (cons (C-enum "GDK_Arabic_dammatan") 'Arabic-dammatan)
+    (cons (C-enum "GDK_Arabic_kasratan") 'Arabic-kasratan)
+    (cons (C-enum "GDK_Arabic_fatha") 'Arabic-fatha)
+    (cons (C-enum "GDK_Arabic_damma") 'Arabic-damma)
+    (cons (C-enum "GDK_Arabic_kasra") 'Arabic-kasra)
+    (cons (C-enum "GDK_Arabic_shadda") 'Arabic-shadda)
+    (cons (C-enum "GDK_Arabic_sukun") 'Arabic-sukun)
+    (cons (C-enum "GDK_Serbian_dje") 'Serbian-dje)
+    (cons (C-enum "GDK_Macedonia_gje") 'Macedonia-gje)
+    (cons (C-enum "GDK_Cyrillic_io") 'Cyrillic-io)
+    (cons (C-enum "GDK_Ukranian_je") 'Ukranian-je)
+    (cons (C-enum "GDK_Macedonia_dse") 'Macedonia-dse)
+    (cons (C-enum "GDK_Ukranian_i") 'Ukranian-i)
+    (cons (C-enum "GDK_Ukranian_yi") 'Ukranian-yi)
+    (cons (C-enum "GDK_Cyrillic_je") 'Cyrillic-je)
+    (cons (C-enum "GDK_Cyrillic_lje") 'Cyrillic-lje)
+    (cons (C-enum "GDK_Cyrillic_nje") 'Cyrillic-nje)
+    (cons (C-enum "GDK_Serbian_tshe") 'Serbian-tshe)
+    (cons (C-enum "GDK_Macedonia_kje") 'Macedonia-kje)
+    (cons (C-enum "GDK_Byelorussian_shortu") 'Byelorussian-shortu)
+    (cons (C-enum "GDK_Cyrillic_dzhe") 'Cyrillic-dzhe)
+    (cons (C-enum "GDK_numerosign") 'numerosign)
+    (cons (C-enum "GDK_Serbian_DJE") 'Serbian-DJE)
+    (cons (C-enum "GDK_Macedonia_GJE") 'Macedonia-GJE)
+    (cons (C-enum "GDK_Cyrillic_IO") 'Cyrillic-IO)
+    (cons (C-enum "GDK_Ukranian_JE") 'Ukranian-JE)
+    (cons (C-enum "GDK_Macedonia_DSE") 'Macedonia-DSE)
+    (cons (C-enum "GDK_Ukranian_I") 'Ukranian-I)
+    (cons (C-enum "GDK_Ukrainian_YI") 'Ukrainian-YI)
+    (cons (C-enum "GDK_Cyrillic_JE") 'Cyrillic-JE)
+    (cons (C-enum "GDK_Cyrillic_LJE") 'Cyrillic-LJE)
+    (cons (C-enum "GDK_Cyrillic_NJE") 'Cyrillic-NJE)
+    (cons (C-enum "GDK_Serbian_TSHE") 'Serbian-TSHE)
+    (cons (C-enum "GDK_Macedonia_KJE") 'Macedonia-KJE)
+    (cons (C-enum "GDK_Byelorussian_SHORTU") 'Byelorussian-SHORTU)
+    (cons (C-enum "GDK_Cyrillic_DZHE") 'Cyrillic-DZHE)
+    (cons (C-enum "GDK_Cyrillic_yu") 'Cyrillic-yu)
+    (cons (C-enum "GDK_Cyrillic_a") 'Cyrillic-a)
+    (cons (C-enum "GDK_Cyrillic_be") 'Cyrillic-be)
+    (cons (C-enum "GDK_Cyrillic_tse") 'Cyrillic-tse)
+    (cons (C-enum "GDK_Cyrillic_de") 'Cyrillic-de)
+    (cons (C-enum "GDK_Cyrillic_ie") 'Cyrillic-ie)
+    (cons (C-enum "GDK_Cyrillic_ef") 'Cyrillic-ef)
+    (cons (C-enum "GDK_Cyrillic_ghe") 'Cyrillic-ghe)
+    (cons (C-enum "GDK_Cyrillic_ha") 'Cyrillic-ha)
+    (cons (C-enum "GDK_Cyrillic_i") 'Cyrillic-i)
+    (cons (C-enum "GDK_Cyrillic_shorti") 'Cyrillic-shorti)
+    (cons (C-enum "GDK_Cyrillic_ka") 'Cyrillic-ka)
+    (cons (C-enum "GDK_Cyrillic_el") 'Cyrillic-el)
+    (cons (C-enum "GDK_Cyrillic_em") 'Cyrillic-em)
+    (cons (C-enum "GDK_Cyrillic_en") 'Cyrillic-en)
+    (cons (C-enum "GDK_Cyrillic_o") 'Cyrillic-o)
+    (cons (C-enum "GDK_Cyrillic_pe") 'Cyrillic-pe)
+    (cons (C-enum "GDK_Cyrillic_ya") 'Cyrillic-ya)
+    (cons (C-enum "GDK_Cyrillic_er") 'Cyrillic-er)
+    (cons (C-enum "GDK_Cyrillic_es") 'Cyrillic-es)
+    (cons (C-enum "GDK_Cyrillic_te") 'Cyrillic-te)
+    (cons (C-enum "GDK_Cyrillic_u") 'Cyrillic-u)
+    (cons (C-enum "GDK_Cyrillic_zhe") 'Cyrillic-zhe)
+    (cons (C-enum "GDK_Cyrillic_ve") 'Cyrillic-ve)
+    (cons (C-enum "GDK_Cyrillic_softsign") 'Cyrillic-softsign)
+    (cons (C-enum "GDK_Cyrillic_yeru") 'Cyrillic-yeru)
+    (cons (C-enum "GDK_Cyrillic_ze") 'Cyrillic-ze)
+    (cons (C-enum "GDK_Cyrillic_sha") 'Cyrillic-sha)
+    (cons (C-enum "GDK_Cyrillic_e") 'Cyrillic-e)
+    (cons (C-enum "GDK_Cyrillic_shcha") 'Cyrillic-shcha)
+    (cons (C-enum "GDK_Cyrillic_che") 'Cyrillic-che)
+    (cons (C-enum "GDK_Cyrillic_hardsign") 'Cyrillic-hardsign)
+    (cons (C-enum "GDK_Cyrillic_YU") 'Cyrillic-YU)
+    (cons (C-enum "GDK_Cyrillic_A") 'Cyrillic-A)
+    (cons (C-enum "GDK_Cyrillic_BE") 'Cyrillic-BE)
+    (cons (C-enum "GDK_Cyrillic_TSE") 'Cyrillic-TSE)
+    (cons (C-enum "GDK_Cyrillic_DE") 'Cyrillic-DE)
+    (cons (C-enum "GDK_Cyrillic_IE") 'Cyrillic-IE)
+    (cons (C-enum "GDK_Cyrillic_EF") 'Cyrillic-EF)
+    (cons (C-enum "GDK_Cyrillic_GHE") 'Cyrillic-GHE)
+    (cons (C-enum "GDK_Cyrillic_HA") 'Cyrillic-HA)
+    (cons (C-enum "GDK_Cyrillic_I") 'Cyrillic-I)
+    (cons (C-enum "GDK_Cyrillic_SHORTI") 'Cyrillic-SHORTI)
+    (cons (C-enum "GDK_Cyrillic_KA") 'Cyrillic-KA)
+    (cons (C-enum "GDK_Cyrillic_EL") 'Cyrillic-EL)
+    (cons (C-enum "GDK_Cyrillic_EM") 'Cyrillic-EM)
+    (cons (C-enum "GDK_Cyrillic_EN") 'Cyrillic-EN)
+    (cons (C-enum "GDK_Cyrillic_O") 'Cyrillic-O)
+    (cons (C-enum "GDK_Cyrillic_PE") 'Cyrillic-PE)
+    (cons (C-enum "GDK_Cyrillic_YA") 'Cyrillic-YA)
+    (cons (C-enum "GDK_Cyrillic_ER") 'Cyrillic-ER)
+    (cons (C-enum "GDK_Cyrillic_ES") 'Cyrillic-ES)
+    (cons (C-enum "GDK_Cyrillic_TE") 'Cyrillic-TE)
+    (cons (C-enum "GDK_Cyrillic_U") 'Cyrillic-U)
+    (cons (C-enum "GDK_Cyrillic_ZHE") 'Cyrillic-ZHE)
+    (cons (C-enum "GDK_Cyrillic_VE") 'Cyrillic-VE)
+    (cons (C-enum "GDK_Cyrillic_SOFTSIGN") 'Cyrillic-SOFTSIGN)
+    (cons (C-enum "GDK_Cyrillic_YERU") 'Cyrillic-YERU)
+    (cons (C-enum "GDK_Cyrillic_ZE") 'Cyrillic-ZE)
+    (cons (C-enum "GDK_Cyrillic_SHA") 'Cyrillic-SHA)
+    (cons (C-enum "GDK_Cyrillic_E") 'Cyrillic-E)
+    (cons (C-enum "GDK_Cyrillic_SHCHA") 'Cyrillic-SHCHA)
+    (cons (C-enum "GDK_Cyrillic_CHE") 'Cyrillic-CHE)
+    (cons (C-enum "GDK_Cyrillic_HARDSIGN") 'Cyrillic-HARDSIGN)
+    (cons (C-enum "GDK_Greek_ALPHAaccent") 'Greek-ALPHAaccent)
+    (cons (C-enum "GDK_Greek_EPSILONaccent") 'Greek-EPSILONaccent)
+    (cons (C-enum "GDK_Greek_ETAaccent") 'Greek-ETAaccent)
+    (cons (C-enum "GDK_Greek_IOTAaccent") 'Greek-IOTAaccent)
+    (cons (C-enum "GDK_Greek_IOTAdiaeresis") 'Greek-IOTAdiaeresis)
+    (cons (C-enum "GDK_Greek_OMICRONaccent") 'Greek-OMICRONaccent)
+    (cons (C-enum "GDK_Greek_UPSILONaccent") 'Greek-UPSILONaccent)
+    (cons (C-enum "GDK_Greek_UPSILONdieresis") 'Greek-UPSILONdieresis)
+    (cons (C-enum "GDK_Greek_OMEGAaccent") 'Greek-OMEGAaccent)
+    (cons (C-enum "GDK_Greek_accentdieresis") 'Greek-accentdieresis)
+    (cons (C-enum "GDK_Greek_horizbar") 'Greek-horizbar)
+    (cons (C-enum "GDK_Greek_alphaaccent") 'Greek-alphaaccent)
+    (cons (C-enum "GDK_Greek_epsilonaccent") 'Greek-epsilonaccent)
+    (cons (C-enum "GDK_Greek_etaaccent") 'Greek-etaaccent)
+    (cons (C-enum "GDK_Greek_iotaaccent") 'Greek-iotaaccent)
+    (cons (C-enum "GDK_Greek_iotadieresis") 'Greek-iotadieresis)
+    (cons (C-enum "GDK_Greek_iotaaccentdieresis") 'Greek-iotaaccentdieresis)
+    (cons (C-enum "GDK_Greek_omicronaccent") 'Greek-omicronaccent)
+    (cons (C-enum "GDK_Greek_upsilonaccent") 'Greek-upsilonaccent)
+    (cons (C-enum "GDK_Greek_upsilondieresis") 'Greek-upsilondieresis)
+    (cons (C-enum "GDK_Greek_upsilonaccentdieresis") 'Greek-upsilonaccentdieresis)
+    (cons (C-enum "GDK_Greek_omegaaccent") 'Greek-omegaaccent)
+    (cons (C-enum "GDK_Greek_ALPHA") 'Greek-ALPHA)
+    (cons (C-enum "GDK_Greek_BETA") 'Greek-BETA)
+    (cons (C-enum "GDK_Greek_GAMMA") 'Greek-GAMMA)
+    (cons (C-enum "GDK_Greek_DELTA") 'Greek-DELTA)
+    (cons (C-enum "GDK_Greek_EPSILON") 'Greek-EPSILON)
+    (cons (C-enum "GDK_Greek_ZETA") 'Greek-ZETA)
+    (cons (C-enum "GDK_Greek_ETA") 'Greek-ETA)
+    (cons (C-enum "GDK_Greek_THETA") 'Greek-THETA)
+    (cons (C-enum "GDK_Greek_IOTA") 'Greek-IOTA)
+    (cons (C-enum "GDK_Greek_KAPPA") 'Greek-KAPPA)
+    (cons (C-enum "GDK_Greek_LAMBDA") 'Greek-LAMBDA)
+    (cons (C-enum "GDK_Greek_MU") 'Greek-MU)
+    (cons (C-enum "GDK_Greek_NU") 'Greek-NU)
+    (cons (C-enum "GDK_Greek_XI") 'Greek-XI)
+    (cons (C-enum "GDK_Greek_OMICRON") 'Greek-OMICRON)
+    (cons (C-enum "GDK_Greek_PI") 'Greek-PI)
+    (cons (C-enum "GDK_Greek_RHO") 'Greek-RHO)
+    (cons (C-enum "GDK_Greek_SIGMA") 'Greek-SIGMA)
+    (cons (C-enum "GDK_Greek_TAU") 'Greek-TAU)
+    (cons (C-enum "GDK_Greek_UPSILON") 'Greek-UPSILON)
+    (cons (C-enum "GDK_Greek_PHI") 'Greek-PHI)
+    (cons (C-enum "GDK_Greek_CHI") 'Greek-CHI)
+    (cons (C-enum "GDK_Greek_PSI") 'Greek-PSI)
+    (cons (C-enum "GDK_Greek_OMEGA") 'Greek-OMEGA)
+    (cons (C-enum "GDK_Greek_alpha") 'Greek-alpha)
+    (cons (C-enum "GDK_Greek_beta") 'Greek-beta)
+    (cons (C-enum "GDK_Greek_gamma") 'Greek-gamma)
+    (cons (C-enum "GDK_Greek_delta") 'Greek-delta)
+    (cons (C-enum "GDK_Greek_epsilon") 'Greek-epsilon)
+    (cons (C-enum "GDK_Greek_zeta") 'Greek-zeta)
+    (cons (C-enum "GDK_Greek_eta") 'Greek-eta)
+    (cons (C-enum "GDK_Greek_theta") 'Greek-theta)
+    (cons (C-enum "GDK_Greek_iota") 'Greek-iota)
+    (cons (C-enum "GDK_Greek_kappa") 'Greek-kappa)
+    (cons (C-enum "GDK_Greek_lambda") 'Greek-lambda)
+    (cons (C-enum "GDK_Greek_mu") 'Greek-mu)
+    (cons (C-enum "GDK_Greek_nu") 'Greek-nu)
+    (cons (C-enum "GDK_Greek_xi") 'Greek-xi)
+    (cons (C-enum "GDK_Greek_omicron") 'Greek-omicron)
+    (cons (C-enum "GDK_Greek_pi") 'Greek-pi)
+    (cons (C-enum "GDK_Greek_rho") 'Greek-rho)
+    (cons (C-enum "GDK_Greek_sigma") 'Greek-sigma)
+    (cons (C-enum "GDK_Greek_finalsmallsigma") 'Greek-finalsmallsigma)
+    (cons (C-enum "GDK_Greek_tau") 'Greek-tau)
+    (cons (C-enum "GDK_Greek_upsilon") 'Greek-upsilon)
+    (cons (C-enum "GDK_Greek_phi") 'Greek-phi)
+    (cons (C-enum "GDK_Greek_chi") 'Greek-chi)
+    (cons (C-enum "GDK_Greek_psi") 'Greek-psi)
+    (cons (C-enum "GDK_Greek_omega") 'Greek-omega)
+    (cons (C-enum "GDK_leftradical") 'leftradical)
+    (cons (C-enum "GDK_topleftradical") 'topleftradical)
+    (cons (C-enum "GDK_horizconnector") 'horizconnector)
+    (cons (C-enum "GDK_topintegral") 'topintegral)
+    (cons (C-enum "GDK_botintegral") 'botintegral)
+    (cons (C-enum "GDK_vertconnector") 'vertconnector)
+    (cons (C-enum "GDK_topleftsqbracket") 'topleftsqbracket)
+    (cons (C-enum "GDK_botleftsqbracket") 'botleftsqbracket)
+    (cons (C-enum "GDK_toprightsqbracket") 'toprightsqbracket)
+    (cons (C-enum "GDK_botrightsqbracket") 'botrightsqbracket)
+    (cons (C-enum "GDK_topleftparens") 'topleftparens)
+    (cons (C-enum "GDK_botleftparens") 'botleftparens)
+    (cons (C-enum "GDK_toprightparens") 'toprightparens)
+    (cons (C-enum "GDK_botrightparens") 'botrightparens)
+    (cons (C-enum "GDK_leftmiddlecurlybrace") 'leftmiddlecurlybrace)
+    (cons (C-enum "GDK_rightmiddlecurlybrace") 'rightmiddlecurlybrace)
+    (cons (C-enum "GDK_topleftsummation") 'topleftsummation)
+    (cons (C-enum "GDK_botleftsummation") 'botleftsummation)
+    (cons (C-enum "GDK_topvertsummationconnector") 'topvertsummationconnector)
+    (cons (C-enum "GDK_botvertsummationconnector") 'botvertsummationconnector)
+    (cons (C-enum "GDK_toprightsummation") 'toprightsummation)
+    (cons (C-enum "GDK_botrightsummation") 'botrightsummation)
+    (cons (C-enum "GDK_rightmiddlesummation") 'rightmiddlesummation)
+    (cons (C-enum "GDK_lessthanequal") 'lessthanequal)
+    (cons (C-enum "GDK_notequal") 'notequal)
+    (cons (C-enum "GDK_greaterthanequal") 'greaterthanequal)
+    (cons (C-enum "GDK_integral") 'integral)
+    (cons (C-enum "GDK_therefore") 'therefore)
+    (cons (C-enum "GDK_variation") 'variation)
+    (cons (C-enum "GDK_infinity") 'infinity)
+    (cons (C-enum "GDK_nabla") 'nabla)
+    (cons (C-enum "GDK_approximate") 'approximate)
+    (cons (C-enum "GDK_similarequal") 'similarequal)
+    (cons (C-enum "GDK_ifonlyif") 'ifonlyif)
+    (cons (C-enum "GDK_implies") 'implies)
+    (cons (C-enum "GDK_identical") 'identical)
+    (cons (C-enum "GDK_radical") 'radical)
+    (cons (C-enum "GDK_includedin") 'includedin)
+    (cons (C-enum "GDK_includes") 'includes)
+    (cons (C-enum "GDK_intersection") 'intersection)
+    (cons (C-enum "GDK_union") 'union)
+    (cons (C-enum "GDK_logicaland") 'logicaland)
+    (cons (C-enum "GDK_logicalor") 'logicalor)
+    (cons (C-enum "GDK_partialderivative") 'partialderivative)
+    (cons (C-enum "GDK_function") 'function)
+    (cons (C-enum "GDK_leftarrow") 'leftarrow)
+    (cons (C-enum "GDK_uparrow") 'uparrow)
+    (cons (C-enum "GDK_rightarrow") 'rightarrow)
+    (cons (C-enum "GDK_downarrow") 'downarrow)
+    (cons (C-enum "GDK_blank") 'blank)
+    (cons (C-enum "GDK_soliddiamond") 'soliddiamond)
+    (cons (C-enum "GDK_checkerboard") 'checkerboard)
+    (cons (C-enum "GDK_ht") 'ht)
+    (cons (C-enum "GDK_ff") 'ff)
+    (cons (C-enum "GDK_cr") 'cr)
+    (cons (C-enum "GDK_lf") 'lf)
+    (cons (C-enum "GDK_nl") 'nl)
+    (cons (C-enum "GDK_vt") 'vt)
+    (cons (C-enum "GDK_lowrightcorner") 'lowrightcorner)
+    (cons (C-enum "GDK_uprightcorner") 'uprightcorner)
+    (cons (C-enum "GDK_upleftcorner") 'upleftcorner)
+    (cons (C-enum "GDK_lowleftcorner") 'lowleftcorner)
+    (cons (C-enum "GDK_crossinglines") 'crossinglines)
+    (cons (C-enum "GDK_horizlinescan1") 'horizlinescan1)
+    (cons (C-enum "GDK_horizlinescan3") 'horizlinescan3)
+    (cons (C-enum "GDK_horizlinescan5") 'horizlinescan5)
+    (cons (C-enum "GDK_horizlinescan7") 'horizlinescan7)
+    (cons (C-enum "GDK_horizlinescan9") 'horizlinescan9)
+    (cons (C-enum "GDK_leftt") 'leftt)
+    (cons (C-enum "GDK_rightt") 'rightt)
+    (cons (C-enum "GDK_bott") 'bott)
+    (cons (C-enum "GDK_topt") 'topt)
+    (cons (C-enum "GDK_vertbar") 'vertbar)
+    (cons (C-enum "GDK_emspace") 'emspace)
+    (cons (C-enum "GDK_enspace") 'enspace)
+    (cons (C-enum "GDK_em3space") 'em3space)
+    (cons (C-enum "GDK_em4space") 'em4space)
+    (cons (C-enum "GDK_digitspace") 'digitspace)
+    (cons (C-enum "GDK_punctspace") 'punctspace)
+    (cons (C-enum "GDK_thinspace") 'thinspace)
+    (cons (C-enum "GDK_hairspace") 'hairspace)
+    (cons (C-enum "GDK_emdash") 'emdash)
+    (cons (C-enum "GDK_endash") 'endash)
+    (cons (C-enum "GDK_signifblank") 'signifblank)
+    (cons (C-enum "GDK_ellipsis") 'ellipsis)
+    (cons (C-enum "GDK_doubbaselinedot") 'doubbaselinedot)
+    (cons (C-enum "GDK_onethird") 'onethird)
+    (cons (C-enum "GDK_twothirds") 'twothirds)
+    (cons (C-enum "GDK_onefifth") 'onefifth)
+    (cons (C-enum "GDK_twofifths") 'twofifths)
+    (cons (C-enum "GDK_threefifths") 'threefifths)
+    (cons (C-enum "GDK_fourfifths") 'fourfifths)
+    (cons (C-enum "GDK_onesixth") 'onesixth)
+    (cons (C-enum "GDK_fivesixths") 'fivesixths)
+    (cons (C-enum "GDK_careof") 'careof)
+    (cons (C-enum "GDK_figdash") 'figdash)
+    (cons (C-enum "GDK_leftanglebracket") 'leftanglebracket)
+    (cons (C-enum "GDK_decimalpoint") 'decimalpoint)
+    (cons (C-enum "GDK_rightanglebracket") 'rightanglebracket)
+    (cons (C-enum "GDK_marker") 'marker)
+    (cons (C-enum "GDK_oneeighth") 'oneeighth)
+    (cons (C-enum "GDK_threeeighths") 'threeeighths)
+    (cons (C-enum "GDK_fiveeighths") 'fiveeighths)
+    (cons (C-enum "GDK_seveneighths") 'seveneighths)
+    (cons (C-enum "GDK_trademark") 'trademark)
+    (cons (C-enum "GDK_signaturemark") 'signaturemark)
+    (cons (C-enum "GDK_trademarkincircle") 'trademarkincircle)
+    (cons (C-enum "GDK_leftopentriangle") 'leftopentriangle)
+    (cons (C-enum "GDK_rightopentriangle") 'rightopentriangle)
+    (cons (C-enum "GDK_emopencircle") 'emopencircle)
+    (cons (C-enum "GDK_emopenrectangle") 'emopenrectangle)
+    (cons (C-enum "GDK_leftsinglequotemark") 'leftsinglequotemark)
+    (cons (C-enum "GDK_rightsinglequotemark") 'rightsinglequotemark)
+    (cons (C-enum "GDK_leftdoublequotemark") 'leftdoublequotemark)
+    (cons (C-enum "GDK_rightdoublequotemark") 'rightdoublequotemark)
+    (cons (C-enum "GDK_prescription") 'prescription)
+    (cons (C-enum "GDK_minutes") 'minutes)
+    (cons (C-enum "GDK_seconds") 'seconds)
+    (cons (C-enum "GDK_latincross") 'latincross)
+    (cons (C-enum "GDK_hexagram") 'hexagram)
+    (cons (C-enum "GDK_filledrectbullet") 'filledrectbullet)
+    (cons (C-enum "GDK_filledlefttribullet") 'filledlefttribullet)
+    (cons (C-enum "GDK_filledrighttribullet") 'filledrighttribullet)
+    (cons (C-enum "GDK_emfilledcircle") 'emfilledcircle)
+    (cons (C-enum "GDK_emfilledrect") 'emfilledrect)
+    (cons (C-enum "GDK_enopencircbullet") 'enopencircbullet)
+    (cons (C-enum "GDK_enopensquarebullet") 'enopensquarebullet)
+    (cons (C-enum "GDK_openrectbullet") 'openrectbullet)
+    (cons (C-enum "GDK_opentribulletup") 'opentribulletup)
+    (cons (C-enum "GDK_opentribulletdown") 'opentribulletdown)
+    (cons (C-enum "GDK_openstar") 'openstar)
+    (cons (C-enum "GDK_enfilledcircbullet") 'enfilledcircbullet)
+    (cons (C-enum "GDK_enfilledsqbullet") 'enfilledsqbullet)
+    (cons (C-enum "GDK_filledtribulletup") 'filledtribulletup)
+    (cons (C-enum "GDK_filledtribulletdown") 'filledtribulletdown)
+    (cons (C-enum "GDK_leftpointer") 'leftpointer)
+    (cons (C-enum "GDK_rightpointer") 'rightpointer)
+    (cons (C-enum "GDK_club") 'club)
+    (cons (C-enum "GDK_diamond") 'diamond)
+    (cons (C-enum "GDK_heart") 'heart)
+    (cons (C-enum "GDK_maltesecross") 'maltesecross)
+    (cons (C-enum "GDK_dagger") 'dagger)
+    (cons (C-enum "GDK_doubledagger") 'doubledagger)
+    (cons (C-enum "GDK_checkmark") 'checkmark)
+    (cons (C-enum "GDK_ballotcross") 'ballotcross)
+    (cons (C-enum "GDK_musicalsharp") 'musicalsharp)
+    (cons (C-enum "GDK_musicalflat") 'musicalflat)
+    (cons (C-enum "GDK_malesymbol") 'malesymbol)
+    (cons (C-enum "GDK_femalesymbol") 'femalesymbol)
+    (cons (C-enum "GDK_telephone") 'telephone)
+    (cons (C-enum "GDK_telephonerecorder") 'telephonerecorder)
+    (cons (C-enum "GDK_phonographcopyright") 'phonographcopyright)
+    (cons (C-enum "GDK_caret") 'caret)
+    (cons (C-enum "GDK_singlelowquotemark") 'singlelowquotemark)
+    (cons (C-enum "GDK_doublelowquotemark") 'doublelowquotemark)
+    (cons (C-enum "GDK_cursor") 'cursor)
+    (cons (C-enum "GDK_leftcaret") 'leftcaret)
+    (cons (C-enum "GDK_rightcaret") 'rightcaret)
+    (cons (C-enum "GDK_downcaret") 'downcaret)
+    (cons (C-enum "GDK_upcaret") 'upcaret)
+    (cons (C-enum "GDK_overbar") 'overbar)
+    (cons (C-enum "GDK_downtack") 'downtack)
+    (cons (C-enum "GDK_upshoe") 'upshoe)
+    (cons (C-enum "GDK_downstile") 'downstile)
+    (cons (C-enum "GDK_underbar") 'underbar)
+    (cons (C-enum "GDK_jot") 'jot)
+    (cons (C-enum "GDK_quad") 'quad)
+    (cons (C-enum "GDK_uptack") 'uptack)
+    (cons (C-enum "GDK_circle") 'circle)
+    (cons (C-enum "GDK_upstile") 'upstile)
+    (cons (C-enum "GDK_downshoe") 'downshoe)
+    (cons (C-enum "GDK_rightshoe") 'rightshoe)
+    (cons (C-enum "GDK_leftshoe") 'leftshoe)
+    (cons (C-enum "GDK_lefttack") 'lefttack)
+    (cons (C-enum "GDK_righttack") 'righttack)
+    (cons (C-enum "GDK_hebrew_doublelowline") 'hebrew-doublelowline)
+    (cons (C-enum "GDK_hebrew_aleph") 'hebrew-aleph)
+    (cons (C-enum "GDK_hebrew_beth") 'hebrew-beth)
+    (cons (C-enum "GDK_hebrew_gimmel") 'hebrew-gimmel)
+    (cons (C-enum "GDK_hebrew_daleth") 'hebrew-daleth)
+    (cons (C-enum "GDK_hebrew_he") 'hebrew-he)
+    (cons (C-enum "GDK_hebrew_waw") 'hebrew-waw)
+    (cons (C-enum "GDK_hebrew_zayin") 'hebrew-zayin)
+    (cons (C-enum "GDK_hebrew_het") 'hebrew-het)
+    (cons (C-enum "GDK_hebrew_teth") 'hebrew-teth)
+    (cons (C-enum "GDK_hebrew_yod") 'hebrew-yod)
+    (cons (C-enum "GDK_hebrew_finalkaph") 'hebrew-finalkaph)
+    (cons (C-enum "GDK_hebrew_kaph") 'hebrew-kaph)
+    (cons (C-enum "GDK_hebrew_lamed") 'hebrew-lamed)
+    (cons (C-enum "GDK_hebrew_finalmem") 'hebrew-finalmem)
+    (cons (C-enum "GDK_hebrew_mem") 'hebrew-mem)
+    (cons (C-enum "GDK_hebrew_finalnun") 'hebrew-finalnun)
+    (cons (C-enum "GDK_hebrew_nun") 'hebrew-nun)
+    (cons (C-enum "GDK_hebrew_samekh") 'hebrew-samekh)
+    (cons (C-enum "GDK_hebrew_ayin") 'hebrew-ayin)
+    (cons (C-enum "GDK_hebrew_finalpe") 'hebrew-finalpe)
+    (cons (C-enum "GDK_hebrew_pe") 'hebrew-pe)
+    (cons (C-enum "GDK_hebrew_finalzadi") 'hebrew-finalzadi)
+    (cons (C-enum "GDK_hebrew_zadi") 'hebrew-zadi)
+    (cons (C-enum "GDK_hebrew_qoph") 'hebrew-qoph)
+    (cons (C-enum "GDK_hebrew_resh") 'hebrew-resh)
+    (cons (C-enum "GDK_hebrew_shin") 'hebrew-shin)
+    (cons (C-enum "GDK_hebrew_taf") 'hebrew-taf)
+    (cons (C-enum "GDK_BackSpace") 'BackSpace)
+    (cons (C-enum "GDK_Tab") 'Tab)
+    (cons (C-enum "GDK_Linefeed") 'Linefeed)
+    (cons (C-enum "GDK_Clear") 'Clear)
+    (cons (C-enum "GDK_Return") 'Return)
+    (cons (C-enum "GDK_Pause") 'Pause)
+    (cons (C-enum "GDK_Scroll_Lock") 'Scroll-Lock)
+    (cons (C-enum "GDK_Escape") 'Escape)
+    (cons (C-enum "GDK_Multi_key") 'Multi-key)
+    (cons (C-enum "GDK_Kanji") 'Kanji)
+    (cons (C-enum "GDK_Muhenkan") 'Muhenkan)
+    (cons (C-enum "GDK_Henkan") 'Henkan)
+    (cons (C-enum "GDK_Romaji") 'Romaji)
+    (cons (C-enum "GDK_Hiragana") 'Hiragana)
+    (cons (C-enum "GDK_Katakana") 'Katakana)
+    (cons (C-enum "GDK_Hiragana_Katakana") 'Hiragana-Katakana)
+    (cons (C-enum "GDK_Zenkaku") 'Zenkaku)
+    (cons (C-enum "GDK_Hankaku") 'Hankaku)
+    (cons (C-enum "GDK_Zenkaku_Hankaku") 'Zenkaku-Hankaku)
+    (cons (C-enum "GDK_Touroku") 'Touroku)
+    (cons (C-enum "GDK_Massyo") 'Massyo)
+    (cons (C-enum "GDK_Kana_Lock") 'Kana-Lock)
+    (cons (C-enum "GDK_Kana_Shift") 'Kana-Shift)
+    (cons (C-enum "GDK_Eisu_Shift") 'Eisu-Shift)
+    (cons (C-enum "GDK_Eisu_toggle") 'Eisu-toggle)
+    (cons (C-enum "GDK_Home") 'Home)
+    (cons (C-enum "GDK_Left") 'Left)
+    (cons (C-enum "GDK_Up") 'Up)
+    (cons (C-enum "GDK_Right") 'Right)
+    (cons (C-enum "GDK_Down") 'Down)
+    (cons (C-enum "GDK_Prior") 'Prior)
+    (cons (C-enum "GDK_Next") 'Next)
+    (cons (C-enum "GDK_End") 'End)
+    (cons (C-enum "GDK_Begin") 'Begin)
+    (cons (C-enum "GDK_Select") 'Select)
+    (cons (C-enum "GDK_Print") 'Print)
+    (cons (C-enum "GDK_Execute") 'Execute)
+    (cons (C-enum "GDK_Insert") 'Insert)
+    (cons (C-enum "GDK_Undo") 'Undo)
+    (cons (C-enum "GDK_Redo") 'Redo)
+    (cons (C-enum "GDK_Menu") 'Menu)
+    (cons (C-enum "GDK_Find") 'Find)
+    (cons (C-enum "GDK_Cancel") 'Stop)	;originally called Cancel
+    (cons (C-enum "GDK_Help") 'Help)
+    (cons (C-enum "GDK_Break") 'Break)
+    (cons (C-enum "GDK_script_switch") 'script-switch)
+    (cons (C-enum "GDK_Num_Lock") 'Num-Lock)
+    (cons (C-enum "GDK_KP_Space") 'KP-Space)
+    (cons (C-enum "GDK_KP_Tab") 'KP-Tab)
+    (cons (C-enum "GDK_KP_Enter") 'KP-Enter)
+    (cons (C-enum "GDK_KP_F1") 'KP-F1)
+    (cons (C-enum "GDK_KP_F2") 'KP-F2)
+    (cons (C-enum "GDK_KP_F3") 'KP-F3)
+    (cons (C-enum "GDK_KP_F4") 'KP-F4)
+    (cons (C-enum "GDK_KP_Multiply") 'KP-Multiply)
+    (cons (C-enum "GDK_KP_Add") 'KP-Add)
+    (cons (C-enum "GDK_KP_Separator") 'KP-Separator)
+    (cons (C-enum "GDK_KP_Subtract") 'KP-Subtract)
+    (cons (C-enum "GDK_KP_Decimal") 'KP-Decimal)
+    (cons (C-enum "GDK_KP_Divide") 'KP-Divide)
+    (cons (C-enum "GDK_KP_0") 'KP-0)
+    (cons (C-enum "GDK_KP_1") 'KP-1)
+    (cons (C-enum "GDK_KP_2") 'KP-2)
+    (cons (C-enum "GDK_KP_3") 'KP-3)
+    (cons (C-enum "GDK_KP_4") 'KP-4)
+    (cons (C-enum "GDK_KP_5") 'KP-5)
+    (cons (C-enum "GDK_KP_6") 'KP-6)
+    (cons (C-enum "GDK_KP_7") 'KP-7)
+    (cons (C-enum "GDK_KP_8") 'KP-8)
+    (cons (C-enum "GDK_KP_9") 'KP-9)
+    (cons (C-enum "GDK_KP_Equal") 'KP-Equal)
+    (cons (C-enum "GDK_F1") 'F1)
+    (cons (C-enum "GDK_F2") 'F2)
+    (cons (C-enum "GDK_F3") 'F3)
+    (cons (C-enum "GDK_F4") 'F4)
+    (cons (C-enum "GDK_F5") 'F5)
+    (cons (C-enum "GDK_F6") 'F6)
+    (cons (C-enum "GDK_F7") 'F7)
+    (cons (C-enum "GDK_F8") 'F8)
+    (cons (C-enum "GDK_F9") 'F9)
+    (cons (C-enum "GDK_F10") 'F10)
+    (cons (C-enum "GDK_F11") 'F11)
+    (cons (C-enum "GDK_F12") 'F12)
+    (cons (C-enum "GDK_F13") 'F13)
+    (cons (C-enum "GDK_F14") 'F14)
+    (cons (C-enum "GDK_F15") 'F15)
+    (cons (C-enum "GDK_F16") 'F16)
+    (cons (C-enum "GDK_F17") 'F17)
+    (cons (C-enum "GDK_F18") 'F18)
+    (cons (C-enum "GDK_F19") 'F19)
+    (cons (C-enum "GDK_F20") 'F20)
+    (cons (C-enum "GDK_F21") 'F21)
+    (cons (C-enum "GDK_F22") 'F22)
+    (cons (C-enum "GDK_F23") 'F23)
+    (cons (C-enum "GDK_F24") 'F24)
+    (cons (C-enum "GDK_F25") 'F25)
+    (cons (C-enum "GDK_F26") 'F26)
+    (cons (C-enum "GDK_F27") 'F27)
+    (cons (C-enum "GDK_F28") 'F28)
+    (cons (C-enum "GDK_F29") 'F29)
+    (cons (C-enum "GDK_F30") 'F30)
+    (cons (C-enum "GDK_F31") 'F31)
+    (cons (C-enum "GDK_F32") 'F32)
+    (cons (C-enum "GDK_F33") 'F33)
+    (cons (C-enum "GDK_F34") 'F34)
+    (cons (C-enum "GDK_F35") 'F35)
+    (cons (C-enum "GDK_Shift_L") 'Shift-L)
+    (cons (C-enum "GDK_Shift_R") 'Shift-R)
+    (cons (C-enum "GDK_Control_L") 'Control-L)
+    (cons (C-enum "GDK_Control_R") 'Control-R)
+    (cons (C-enum "GDK_Caps_Lock") 'Caps-Lock)
+    (cons (C-enum "GDK_Shift_Lock") 'Shift-Lock)
+    (cons (C-enum "GDK_Meta_L") 'Meta-L)
+    (cons (C-enum "GDK_Meta_R") 'Meta-R)
+    (cons (C-enum "GDK_Alt_L") 'Alt-L)
+    (cons (C-enum "GDK_Alt_R") 'Alt-R)
+    (cons (C-enum "GDK_Super_L") 'Super-L)
+    (cons (C-enum "GDK_Super_R") 'Super-R)
+    (cons (C-enum "GDK_Hyper_L") 'Hyper-L)
+    (cons (C-enum "GDK_Hyper_R") 'Hyper-R)
+    (cons (C-enum "GDK_Delete") 'Delete)
+    (cons (C-enum "GDK_dead_acute") 'mute-acute)
+    (cons (C-enum "GDK_dead_grave") 'mute-grave)
+    (cons (C-enum "GDK_dead_circumflex") 'mute-asciicircum)
+    (cons (C-enum "GDK_dead_diaeresis") 'mute-diaeresis)
+    (cons (C-enum "GDK_dead_tilde") 'mute-asciitilde)
+    (cons (C-enum "GDK_LiraSign") 'lira)
+    ;; '(#x8000BE . guilder)
+    (cons (C-enum "GDK_Ydiaeresis") 'Ydiaeresis)
+    ;; '(#x8000F6 . longminus)
+    ;; '(#x8000FC . block)
+    ;; '(#x80FF48 . hpModelock1)
+    ;; '(#x80FF49 . hpModelock2)
+    ;; '(#x80FF6C . Reset)
+    ;; '(#x80FF6D . System)
+    ;; '(#x80FF6E . User)
+    ;; '(#x80FF6F . ClearLine)
+    ;; '(#x80FF70 . InsertLine)
+    ;; '(#x80FF71 . DeleteLine)
+    ;; '(#x80FF72 . InsertChar)
+    ;; '(#x80FF73 . DeleteChar)
+    ;; '(#x80FF74 . BackTab)
+    ;; '(#x80FF75 . KP-BackTab)
+    ;; '(#x80FF76 . Ext16bit-L)
+    ;; '(#x80FF77 . Ext16bit-R)
+    ;; '(#x84FF02 . osfCopy)
+    ;; '(#x84FF03 . osfCut)
+    ;; '(#x84FF04 . osfPaste)
+    ;; '(#x84FF08 . osfBackSpace)
+    ;; '(#x84FF0B . osfClear)
+    ;; '(#x84FF31 . osfAddMode)
+    ;; '(#x84FF32 . osfPrimaryPaste)
+    ;; '(#x84FF33 . osfQuickPaste)
+    ;; '(#x84FF41 . osfPageUp)
+    ;; '(#x84FF42 . osfPageDown)
+    ;; '(#x84FF44 . osfActivate)
+    ;; '(#x84FF45 . osfMenuBar)
+    ;; '(#x84FF51 . osfLeft)
+    ;; '(#x84FF52 . osfUp)
+    ;; '(#x84FF53 . osfRight)
+    ;; '(#x84FF54 . osfDown)
+    ;; '(#x84FF57 . osfEndLine)
+    ;; '(#x84FF58 . osfBeginLine)
+    ;; '(#x84FF60 . osfSelect)
+    ;; '(#x84FF63 . osfInsert)
+    ;; '(#x84FF65 . osfUndo)
+    ;; '(#x84FF67 . osfMenu)
+    ;; '(#x84FF69 . osfCancel)
+    ;; '(#x84FF6A . osfHelp)
+    ;; '(#x84FFFF . osfDelete)
+    (cons (C-enum "GDK_VoidSymbol") 'VoidSymbol))
+   (lambda (a b) (< (car a) (car b)))))
\ No newline at end of file
diff --git a/src/gtk/scm-layout.scm b/src/gtk/scm-layout.scm
index 175492d31..36edc555b 100644
--- a/src/gtk/scm-layout.scm
+++ b/src/gtk/scm-layout.scm
@@ -48,15 +48,17 @@ USA.
   (scrollable-area define accessor
 		   initializer (lambda () (make-rect 0 0 100 100)))
 
-  ;; Scroll offset and window size (on-screen area).
-  ;; The width and height should match the window geometry.
+  ;; Scroll offset (and window size) in logical device coordinates.
+  ;; (The size should match the window geometry.)
   (on-screen-area define accessor
 		  initializer (lambda () (make-rect 0 0)))
 
-  ;; The drawing.
   (drawing define standard
 	   modifier %set-scm-layout-drawing!
-	   initial-value #f))
+	   initial-value #f)
+
+  (event-handlers define accessor initializer
+		  (lambda () (make-vector (C-enum "GDK_DAMAGE") #f))))
 
 (define (scm-layout-new width height)
   (let ((w (check-non-negative-integer width))
@@ -268,39 +270,6 @@ USA.
       (adjust-adjustments widget)
       unspecific)))
 
-(define (scm-layout-event-handler widget)
-  (named-lambda (scm-layout-handle-event GtkWidget GdkEvent)
-    (trace2 ";((scm-layout-handle-event "widget") "GtkWidget" "GdkEvent")\n")
-
-    (let ((type (C-> GdkEvent "GdkEvent any type")))
-
-      (cond ((int:= type (C-enum "GDK_EXPOSE"))
-	     (let ((window (C-> GdkEvent "GdkEvent any window"))
-		   (x (C-> GdkEvent "GdkEventExpose area x"))
-		   (y (C-> GdkEvent "GdkEventExpose area y"))
-		   (width (C-> GdkEvent "GdkEventExpose area width"))
-		   (height (C-> GdkEvent "GdkEventExpose area height"))
-		   ;;(count (C-> GdkEvent "GdkEventExpose count"))
-		   (drawing (scm-layout-drawing widget))
-		   (widget-window (scm-layout-window widget)))
-	       (cond ((not (alien=? window widget-window))
-		      (trace "; Expose a strange window "window
-			      " (not "widget-window").\n"))
-		     (drawing
-		      (let* ((scroll (scm-layout-on-screen-area widget))
-			     (offx (rect-x scroll))
-			     (offy (rect-y scroll)))
-			(trace "; Expose area "width"x"height"+"x"+"y
-				" of "widget".\n")
-			(drawing-expose drawing widget window
-					(make-rect (int:+ x offx) (int:+ y offy)
-						   width height)))))))
-
-	    (else
-	     (trace "; "(C-enum "GdkEventType" type)" on "widget"\n"))))
-    1 ;;TRUE -- "handled" -- done.
-    ))
-
 (define (scm-layout-set-scroll-adjustments widget)
   (named-lambda (scm-layout::set-scroll-adjustments
 		 GtkWidget hGtkAdjustment vGtkAdjustment)
@@ -395,6 +364,142 @@ USA.
 			       page-size step-incr page-incr)))))
 
 
+;;;; Event Handlers
+
+(define (scm-layout-event-handler layout)
+  (named-lambda (scm-layout-handle-event GtkWidget GdkEvent)
+    (trace2 ";((scm-layout-handle-event "layout") "GtkWidget" "GdkEvent")\n")
+
+    (let ((type (C-> GdkEvent "GdkEvent any type")))
+      (if (int:= type (C-enum "GDK_EXPOSE"))
+	  (let ((window (C-> GdkEvent "GdkEvent any window"))
+		(x (C-> GdkEvent "GdkEventExpose area x"))
+		(y (C-> GdkEvent "GdkEventExpose area y"))
+		(width (C-> GdkEvent "GdkEventExpose area width"))
+		(height (C-> GdkEvent "GdkEventExpose area height"))
+		;;(count (C-> GdkEvent "GdkEventExpose count"))
+		(drawing (scm-layout-drawing layout))
+		(widget-window (scm-layout-window layout)))
+	    (cond ((not (alien=? window widget-window))
+		   (trace "; Expose a strange window "window
+			  " (not "widget-window").\n"))
+		  (drawing
+		   (let* ((scroll (scm-layout-on-screen-area layout))
+			  (offx (rect-x scroll))
+			  (offy (rect-y scroll)))
+		     (trace "; Expose area "width"x"height"+"x"+"y
+			    " of "layout".\n")
+		     (drawing-expose drawing layout window
+				     (make-rect (int:+ x offx) (int:+ y offy)
+						width height)))))
+	    1 ;;TRUE -- "handled" -- done.
+	    )
+	  (let ((handler (vector-ref (scm-layout-event-handlers layout) type)))
+	    (if handler
+		(handler GtkWidget GdkEvent)
+		;; Unhandled
+		0))))))
+
+(define (set-scm-layout-map-handler! layout handler)
+  (let ((handler (check-procedure-arity handler 1)))
+    (vector-set!
+     (scm-layout-event-handlers layout) (C-enum "GDK_MAP")
+     (named-lambda (scm-layout-unmap-handler GtkWidget GdkEvent)
+       GtkWidget GdkEvent			;ignore
+       (handler layout)))))
+
+(define (set-scm-layout-unmap-handler! layout handler)
+  (let ((handler (check-procedure-arity handler 1)))
+    (vector-set!
+     (scm-layout-event-handlers layout) (C-enum "GDK_UNMAP")
+     (named-lambda (scm-layout-unmap-handler GtkWidget GdkEvent)
+       GtkWidget GdkEvent			;ignore
+       (handler layout)))))
+
+(define (set-scm-layout-focus-change-handler! layout handler)
+  (let ((handler (check-procedure-arity handler 2)))
+    (vector-set!
+     (scm-layout-event-handlers layout) (C-enum "GDK_FOCUS_CHANGE")
+     (named-lambda (scm-layout-unmap-handler GtkWidget GdkEvent)
+       GtkWidget			;ignore
+       (let ((in? (not (zero? (C-> GdkEvent "GdkEventFocus in")))))
+	 (handler layout in?))))))
+
+(define (set-scm-layout-visibility-notify-handler! layout handler)
+  (let ((handler (check-procedure-arity handler 2)))
+    (vector-set!
+     (scm-layout-event-handlers layout) (C-enum "GDK_VISIBILITY_NOTIFY")
+     (named-lambda (scm-layout-visibility-notify-handler GtkWidget GdkEvent)
+       GtkWidget			;ignore
+       (let ((state (C-> GdkEvent "GdkEventVisibility state")))
+	 (handler
+	  layout
+	  (cond
+	   ((int:= state (C-enum "GDK_VISIBILITY_UNOBSCURED")) 'VISIBLE)
+	   ((int:= state (C-enum "GDK_VISIBILITY_PARTIAL")) 'PARTIALLY-OBSCURED)
+	   ((int:= state (C-enum "GDK_VISIBILITY_FULLY_OBSCURED")) 'OBSCURED)
+	   (else (C-enum "GdkVisibilityState" state)))))))))
+
+(define (set-scm-layout-key-press-handler! layout handler)
+  (let ((handler (check-procedure-arity handler 3)))
+    (vector-set!
+     (scm-layout-event-handlers layout) (C-enum "GDK_KEY_PRESS")
+     (named-lambda (scm-layout-key-press-handler GtkWidget GdkEvent)
+       GtkWidget			;ignore
+       (let ((alien (C-> GdkEvent "GdkEvent key string"))
+	     (length (C-> GdkEvent "GdkEvent key length"))
+	     (state (C-> GdkEvent "GdkEvent key state"))
+	     (keyval (C-> GdkEvent "GdkEvent key keyval")))
+	 (let ((string (c-peek-cstring alien))
+	       (char-bits (gdk-key-state->char-bits state)))
+	   (if (zero? (string-length string))
+	       (cond ((int:= length 1)
+		      (handler layout #\NUL char-bits))
+		     ((int:= length 0)
+		      (handler layout (gdk-keyval->name keyval) char-bits))
+		     (else (error "Unexpected length in GdkEventKey.")))
+	       (let ((l (string-length string)))
+		 (let loop ((i 0))
+		   (if (int:< i l)
+		       (if (zero? (handler layout
+					   (string-ref string i) char-bits))
+			   0 ;;NOT handled.
+			   (loop (int:1+ i)))
+		       1 ;;Handled.
+		       ))))))))))
+
+(define (set-scm-layout-motion-handler! layout handler)
+  (let ((handler (check-procedure-arity handler 3)))
+    (vector-set!
+     (scm-layout-event-handlers layout) (C-enum "GDK_MOTION_NOTIFY")
+     (named-lambda (scm-layout-motion-handler GtkWidget GdkEvent)
+       GtkWidget			;ignore
+       (let ((handled?
+	      (handler layout
+		       (floor->exact (C-> GdkEvent "GdkEventMotion x"))
+		       (floor->exact (C-> GdkEvent "GdkEventMotion y")))))
+	 (C-call "gdk_window_get_pointer" #f
+		 (C-> GdkEvent "GdkEventMotion window") 0 0 0)
+	 handled?)))))
+
+(define (set-scm-layout-button-release-handler! layout handler)
+  (let ((handler (check-procedure-arity handler 3)))
+    (vector-set!
+     (scm-layout-event-handlers layout) (C-enum "GDK_BUTTON_RELEASE")
+     (named-lambda (scm-layout-button-release-handler GtkWidget GdkEvent)
+       GtkWidget			;ignore
+       (let ((x (floor->exact (C-> GdkEvent "GdkEventButton x")))
+	     (y (floor->exact (C-> GdkEvent "GdkEventButton y"))))
+	 (handler layout x y))))))
+
+(define-integrable (check-procedure-arity object arity)
+  (cond ((not (procedure? object))
+	 (error:wrong-type-argument object "procedure" 'check-procedure-arity))
+	((not (procedure-arity-valid? object arity))
+	 (error:bad-range-argument object 'check-procedure-arity))
+	(else object)))
+
+
 ;;;; Drawings
 
 (define-class (<drawing> (constructor () 1))
@@ -624,7 +729,7 @@ USA.
 		(area (drawn-item-area item)))
 	    (C-call "gtk_paint_box"
 		    style window state (%box-item-shadow item)
-		    null-alien alien null-alien ;area widget detail
+		    0 alien 0 ;area widget detail
 		    (int:- (rect-x area) scroll-x)
 		    (int:- (rect-y area) scroll-y)
 		    (rect-width area)
@@ -689,7 +794,7 @@ USA.
 		(area (drawn-item-area item)))
 	    (C-call "gtk_paint_hline"
 		    style window state
-		    null-alien alien null-alien ;area widget detail
+		    0 alien 0 ;area widget detail
 		    (int:- (rect-min-x area) scroll-x)
 		    (int:- (rect-max-x area) scroll-x)
 		    (int:- (rect-y area) scroll-y)))))))
@@ -722,7 +827,7 @@ USA.
 		(area (drawn-item-area item)))
 	    (C-call "gtk_paint_vline"
 		    style window state
-		    null-alien alien null-alien ;area widget detail
+		    0 alien 0 ;area widget detail
 		    (int:- (rect-min-y area) scroll-y)
 		    (int:- (rect-max-y area) scroll-y)
 		    (int:- (rect-x area) scroll-x)))))))
@@ -781,7 +886,7 @@ USA.
 	    (if (not (alien-null? layout))
 		(C-call "gtk_paint_layout"
 			style window state 1
-			null-alien alien null-alien ;area widget detail
+			0 alien 0 ;area widget detail
 			(int:- (rect-x area) scroll-x)
 			(int:- (rect-y area) scroll-y)
 			layout)))))))
@@ -796,7 +901,7 @@ USA.
 	(begin
 	  (C-call "pango_layout_set_text" layout text -1)))
     (let ((log-extent (pango-rectangle))
-	  (ink-extent null-alien))
+	  (ink-extent 0))
       (C-call "pango_layout_get_pixel_extents" layout ink-extent log-extent)
 
       (without-interrupts
@@ -820,7 +925,7 @@ USA.
 		(yL (int:- y (rect-y area))))
 	    (if (fix:= 0 (C-call "pango_layout_xy_to_index" layout
 				 (pixels->pangos xL) (pixels->pangos yL)
-				 index-alien null-alien))
+				 index-alien 0))
 		(begin
 		  (free index-alien)
 		  #f)