From ff20e067cf837c9446d5f2bf6daa372946162219 Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Thu, 24 Apr 2014 16:38:39 -0600 Subject: [PATCH] racket/gui Gtk: `choice%` and `combo%` repair for some Gtk variants Finishes repair started in 8cbcba8ed so that mouse events can be intercepted for `combo%` and `choice%` objects. DrRacket's font preference choice relies on intercepting mouse events to populate the menu, for example. Reference counting doesn't seem to work, probably because the relevant widgets are supposed to be private. original commit: 310df9e9cf4607260a64308182088cf40533a0e4 --- .../gui-lib/mred/private/wx/gtk/canvas.rkt | 8 +++- .../gui-lib/mred/private/wx/gtk/choice.rkt | 1 + .../gui-lib/mred/private/wx/gtk/combo.rkt | 37 ++++++++++++++++--- .../gui-lib/mred/private/wx/gtk/widget.rkt | 4 ++ 4 files changed, 43 insertions(+), 7 deletions(-) diff --git a/pkgs/gui-pkgs/gui-lib/mred/private/wx/gtk/canvas.rkt b/pkgs/gui-pkgs/gui-lib/mred/private/wx/gtk/canvas.rkt index 51858bc6..cea95bd7 100644 --- a/pkgs/gui-pkgs/gui-lib/mred/private/wx/gtk/canvas.rkt +++ b/pkgs/gui-pkgs/gui-lib/mred/private/wx/gtk/canvas.rkt @@ -242,7 +242,8 @@ is-auto-scroll? is-disabled-scroll? get-virtual-width get-virtual-height refresh-for-autoscroll refresh-all-children - get-eventspace) + get-eventspace + register-extra-gtk) (define is-combo? (memq 'combo style)) (define has-border? (or (memq 'border style) @@ -359,6 +360,10 @@ (list client-gtk combo-button-gtk) (list client-gtk)))))]) + (define/private (check-combo) + (when is-combo? + (set! combo-button-gtk (re-extract-combo-button gtk combo-button-gtk this)))) + (set-size x y w h) (define/override (set-size x y w h) @@ -393,6 +398,7 @@ (is-panel?)) (set-gtk-object-flags! client-gtk (bitwise-ior (get-gtk-object-flags client-gtk) GTK_CAN_FOCUS))) + (check-combo) (when combo-button-gtk (connect-combo-key-and-mouse combo-button-gtk)) (connect-unrealize client-gtk) diff --git a/pkgs/gui-pkgs/gui-lib/mred/private/wx/gtk/choice.rkt b/pkgs/gui-pkgs/gui-lib/mred/private/wx/gtk/choice.rkt index b5c9d9ef..c36da477 100644 --- a/pkgs/gui-pkgs/gui-lib/mred/private/wx/gtk/choice.rkt +++ b/pkgs/gui-pkgs/gui-lib/mred/private/wx/gtk/choice.rkt @@ -59,6 +59,7 @@ (set-auto-size) (connect-changed gtk) + (set! button-gtk (re-extract-combo-button gtk button-gtk this)) (connect-focus button-gtk) (connect-combo-key-and-mouse button-gtk) diff --git a/pkgs/gui-pkgs/gui-lib/mred/private/wx/gtk/combo.rkt b/pkgs/gui-pkgs/gui-lib/mred/private/wx/gtk/combo.rkt index e2da3b06..988344b7 100644 --- a/pkgs/gui-pkgs/gui-lib/mred/private/wx/gtk/combo.rkt +++ b/pkgs/gui-pkgs/gui-lib/mred/private/wx/gtk/combo.rkt @@ -10,6 +10,7 @@ (provide (protect-out extract-combo-button + re-extract-combo-button connect-combo-key-and-mouse)) ;; ---------------------------------------- @@ -17,6 +18,8 @@ (define-gtk gtk_container_foreach (_fun _GtkWidget (_fun _GtkWidget -> _void) _pointer -> _void)) (define-gtk gtk_container_forall (_fun _GtkWidget (_fun _GtkWidget -> _void) _pointer -> _void)) +(define-gtk gtk_widget_get_name (_fun _GtkWidget -> _string)) + (define-gobj g_signal_parse_name (_fun _string _GType (id : (_ptr o _uint)) @@ -80,17 +83,39 @@ (gtk_container_forall gtk (lambda (c) (set! all (cons c all))) #f) (gtk_container_foreach gtk (lambda (c) (set! ext (cons c ext))) #f) (for-each (lambda (e) - (set! all (filter (lambda (a) (not (ptr-equal? a e))) + (set! all (filter (lambda (a) + (not (ptr-equal? a e))) all))) ext) - (unless (= 1 (length all)) - (error "expected Gtk combobox to have one private child")) - (define combo-gtk (car all)) - (gobject-ref combo-gtk) + (define combo-gtk + (cond + [(= 1 (length all)) + ;; most common case: + (car all)] + [(and (= 2 (length all)) + (equal? '("GtkFrame" "GtkToggleButton") + (map gtk_widget_get_name all))) + (define inner null) + (gtk_container_forall (car all) (lambda (c) (set! inner (cons c inner))) #f) + (and (= 1 (length inner)) + (car inner))] + [else #f])) + (unless combo-gtk + (error "unrecognized Gtk combobox implementation")) combo-gtk)) +(define (re-extract-combo-button gtk combo-button-gtk win) + (define c-gtk (extract-combo-button gtk)) + (cond + [(ptr-equal? c-gtk combo-button-gtk) + ;; combo button hasn't changed: + combo-button-gtk] + [else + (send win register-extra-gtk gtk c-gtk) + c-gtk])) + ;; More dependence on the implemenation of GtkComboBox: -;; The memnu-popup action is implemented by seeting a button-press-event +;; The menu-popup action is implemented by seeting a button-press-event ;; signal handler on `button-gtk'. Since Gtk calls signal handlers in the ;; order that they're registered, our button-press-event handler doesn't ;; get called first, so it can't cancel the button press due to modality diff --git a/pkgs/gui-pkgs/gui-lib/mred/private/wx/gtk/widget.rkt b/pkgs/gui-pkgs/gui-lib/mred/private/wx/gtk/widget.rkt index ed9e5327..0b44df28 100644 --- a/pkgs/gui-pkgs/gui-lib/mred/private/wx/gtk/widget.rkt +++ b/pkgs/gui-pkgs/gui-lib/mred/private/wx/gtk/widget.rkt @@ -57,6 +57,10 @@ (super-new) + (define/public (register-extra-gtk gtk extra-gtk) + (define cell (g_object_get_data gtk "wx")) + (g_object_set_data extra-gtk "wx" cell)) + (atomically (let ([cell (malloc-immobile-cell (make-weak-box this))]) (g_object_set_data gtk "wx" cell)