diff --git a/gui-doc/scribblings/gui/libs.scrbl b/gui-doc/scribblings/gui/libs.scrbl index f75a28ae..8688ace9 100644 --- a/gui-doc/scribblings/gui/libs.scrbl +++ b/gui-doc/scribblings/gui/libs.scrbl @@ -7,14 +7,17 @@ See @secref[#:doc draw-doc "libs"] in @other-manual[draw-doc] for information on platform library dependencies for -@racketmodname[racket/draw]. On Unix, the following additional -system libraries must be installed for @racketmodname[racket/gui/base]: +@racketmodname[racket/draw]. On Unix, GTK+ 3 is used if its libraries +can be found and the @indexed-envvar{PLT_GTK2} environment is not +defined. Otherwise, GTK+ 2 is used. The following additional system +libraries must be installed for @racketmodname[racket/gui/base] in +either case: @itemlist[ - @item{@filepath{libgdk-x11-2.0[.0]}} - @item{@filepath{libgdk_pixbuf-2.0[.0]}} - @item{@filepath{libgtk-x11-2.0[.0]}} + @item{@filepath{libgdk-3.0[.0]} (GTK+ 3) or @filepath{libgdk-x11-2.0[.0]} (GTK+ 2)} + @item{@filepath{libgdk_pixbuf-2.0[.0]} (GTK+ 2)} + @item{@filepath{libgtk-3.0[.0]} (GTK+ 3) or @filepath{libgtk-x11-2.0[.0]} (GTK+ 2)} @item{@filepath{libgio-2.0[.0]} --- optional, for detecting interface scaling} - @item{@filepath{libGL} --- optional, for OpenGL support} + @item{@filepath{libGL[.1]} --- optional, for OpenGL support} @item{@filepath{libunique-1.0[.0]} --- optional, for single-instance support} ] diff --git a/gui-doc/scribblings/gui/miscwin-funcs.scrbl b/gui-doc/scribblings/gui/miscwin-funcs.scrbl index b625d0c4..0f492c7d 100644 --- a/gui-doc/scribblings/gui/miscwin-funcs.scrbl +++ b/gui-doc/scribblings/gui/miscwin-funcs.scrbl @@ -186,6 +186,28 @@ The keymap for the read-eval-print loop's editor is initialized by @racket[current-text-keymap-initializer] parameter. } + +@defproc[(graphical-system-type) symbol?]{ + +Returns a symbol indicating the platform native GUI layer on which +@racket[racket/gui] is running. The current possible values are as +follows: + +@itemlist[ + + @item{@racket['win32] (Windows)} + + @item{@racket['cocoa] (Mac OS X)} + + @item{@racket['gtk2] --- GTK+ version 2} + + @item{@racket['gtk3] --- GTK+ version 3} + +] + +@history[#:added "1.15"]} + + @defproc[(textual-read-eval-print-loop) void?]{ Similar to @racket[read-eval-print-loop], except that evaluation uses diff --git a/gui-lib/info.rkt b/gui-lib/info.rkt index 6e229835..e64074a2 100644 --- a/gui-lib/info.rkt +++ b/gui-lib/info.rkt @@ -6,7 +6,7 @@ "data-lib" "base" "syntax-color-lib" - ("draw-lib" #:version "1.5") + ("draw-lib" #:version "1.6") "snip-lib" "wxme-lib" "pict-lib" @@ -30,4 +30,4 @@ (define pkg-authors '(mflatt robby)) -(define version "1.14") +(define version "1.15") diff --git a/gui-lib/mred/mred-sig.rkt b/gui-lib/mred/mred-sig.rkt index d071cafa..a2d237aa 100644 --- a/gui-lib/mred/mred-sig.rkt +++ b/gui-lib/mred/mred-sig.rkt @@ -108,6 +108,7 @@ get-window-text-extent gl-config% gl-context<%> graphical-read-eval-print-loop +graphical-system-type group-box-panel% grow-box-spacer-pane% hide-cursor-until-moved diff --git a/gui-lib/mred/private/mred.rkt b/gui-lib/mred/private/mred.rkt index 54f5e53c..655868b7 100644 --- a/gui-lib/mred/private/mred.rkt +++ b/gui-lib/mred/private/mred.rkt @@ -153,6 +153,7 @@ eventspace-shutdown? eventspace-event-evt get-panel-background + graphical-system-type the-editor-wordbreak-map make-screen-bitmap diff --git a/gui-lib/mred/private/wx/cocoa/platform.rkt b/gui-lib/mred/private/wx/cocoa/platform.rkt index 99d3b54d..c4594814 100644 --- a/gui-lib/mred/private/wx/cocoa/platform.rkt +++ b/gui-lib/mred/private/wx/cocoa/platform.rkt @@ -91,4 +91,5 @@ make-gl-bitmap check-for-break key-symbol-to-menu-key - needs-grow-box-spacer?)) + needs-grow-box-spacer? + graphical-system-type)) diff --git a/gui-lib/mred/private/wx/cocoa/procs.rkt b/gui-lib/mred/private/wx/cocoa/procs.rkt index dc318f97..5731d013 100644 --- a/gui-lib/mred/private/wx/cocoa/procs.rkt +++ b/gui-lib/mred/private/wx/cocoa/procs.rkt @@ -66,7 +66,8 @@ file-selector key-symbol-to-menu-key needs-grow-box-spacer? - get-current-mouse-state) + get-current-mouse-state + graphical-system-type) (import-class NSScreen NSCursor NSMenu NSEvent) @@ -198,6 +199,8 @@ (define (needs-grow-box-spacer?) (not (version-10.7-or-later?))) +(define (graphical-system-type) 'cocoa) + ;; ------------------------------------------------------------ ;; Mouse and modifier-key state diff --git a/gui-lib/mred/private/wx/common/backing-dc.rkt b/gui-lib/mred/private/wx/common/backing-dc.rkt index 5bc6ef6c..2724a9f5 100644 --- a/gui-lib/mred/private/wx/common/backing-dc.rkt +++ b/gui-lib/mred/private/wx/common/backing-dc.rkt @@ -204,11 +204,13 @@ (define cr #f) (define w 0) (define h 0) + (define mx (make-cairo_matrix_t 0.0 0.0 0.0 0.0 0.0 0.0)) (super-new) (define/public (set-cr new-cr new-w new-h) (set! cr new-cr) + (when cr (cairo_get_matrix cr mx)) (set! w new-w) (set! h new-h) (when cr @@ -216,6 +218,9 @@ (define/override (get-cr) cr) + (define/override (init-cr-matrix cr) + (cairo_set_matrix cr mx)) + (define/override (reset-clip cr) (super reset-clip cr) (cairo_rectangle cr 0 0 w h) diff --git a/gui-lib/mred/private/wx/gtk/button.rkt b/gui-lib/mred/private/wx/gtk/button.rkt index 090b4ea0..bd55c3f6 100644 --- a/gui-lib/mred/private/wx/gtk/button.rkt +++ b/gui-lib/mred/private/wx/gtk/button.rkt @@ -97,8 +97,7 @@ (define both-labels? (pair? label)) (when (eq? event-type 'button) - (set-gtk-object-flags! gtk (bitwise-ior (get-gtk-object-flags gtk) - GTK_CAN_DEFAULT))) + (gtk_widget_set_can_default gtk #t)) (set-auto-size) diff --git a/gui-lib/mred/private/wx/gtk/canvas.rkt b/gui-lib/mred/private/wx/gtk/canvas.rkt index 3f0dadc2..6032568a 100644 --- a/gui-lib/mred/private/wx/gtk/canvas.rkt +++ b/gui-lib/mred/private/wx/gtk/canvas.rkt @@ -1,11 +1,13 @@ #lang racket/base (require ffi/unsafe + ffi/unsafe/define racket/class racket/draw ffi/unsafe/alloc (except-in racket/draw/private/color color% make-color) racket/draw/private/local + racket/draw/unsafe/cairo "../common/backing-dc.rkt" "../common/canvas-mixin.rkt" "../../syntax.rkt" @@ -20,7 +22,6 @@ "dc.rkt" "gl-context.rkt" "combo.rkt" - "pixbuf.rkt" "gcwin.rkt" "panel.rkt") @@ -41,14 +42,29 @@ (define-gtk gtk_drawing_area_new (_fun -> _GtkWidget)) -(define-gtk gtk_combo_box_entry_new_text (_fun -> _GtkWidget)) -(define-gtk gtk_combo_box_append_text (_fun _GtkWidget _string -> _void)) -(define-gtk gtk_combo_box_remove_text (_fun _GtkWidget _int -> _void)) +(define-gtk gtk_combo_box_text_new (_fun -> _GtkWidget) + #:make-fail make-not-available) +(define-gtk gtk_combo_box_entry_new_text (_fun -> _GtkWidget) + #:fail (lambda () gtk_combo_box_text_new)) + +(define-gtk gtk_combo_box_text_append_text (_fun _GtkWidget _string -> _void) + #:make-fail make-not-available) +(define-gtk gtk_combo_box_append_text (_fun _GtkWidget _string -> _void) + #:fail (lambda () gtk_combo_box_text_append_text)) + +(define-gtk gtk_combo_box_text_remove (_fun _GtkWidget _int -> _void) + #:make-fail make-not-available) +(define-gtk gtk_combo_box_remove_text (_fun _GtkWidget _int -> _void) + #:fail (lambda () gtk_combo_box_text_remove)) + (define-gtk gtk_combo_box_popup (_fun _GtkWidget -> _void)) (define-gtk gtk_widget_queue_draw (_fun _GtkWidget -> _void)) -(define-gtk gtk_fixed_set_has_window (_fun _GtkWidget _gboolean -> _void)) +(define-gtk gtk_widget_set_has_window (_fun _GtkWidget _gboolean -> _void) + #:make-fail make-not-available) +(define-gtk gtk_fixed_set_has_window (_fun _GtkWidget _gboolean -> _void) + #:fail (lambda () gtk_widget_set_has_window)) (define-gtk gtk_hscrollbar_new (_fun _pointer -> _GtkWidget)) (define-gtk gtk_vscrollbar_new (_fun _pointer -> _GtkWidget)) @@ -184,7 +200,7 @@ (let ([wx (gtk->wx gtk)]) (if wx (begin - (unless (send wx paint-or-queue-paint) + (unless (send wx paint-or-queue-paint #f) (let ([gc (send wx get-canvas-background-for-clearing)]) (when gc (gdk_draw_rectangle (widget-window gtk) gc #t @@ -193,6 +209,33 @@ (not (send wx is-panel?))) #f)))) +(define-gdk gdk_window_get_background_pattern (_fun _GdkWindow -> (_or-null _cairo_pattern_t))) +(define-gdk gdk_window_get_effective_parent (_fun _GdkWindow -> _GdkWindow)) +(define-signal-handler connect-draw "draw" + (_fun _GtkWidget _cairo_t -> _gboolean) + (lambda (gtk cr) + (let ([wx (gtk->wx gtk)]) + (if wx + (let ([col (send wx get-canvas-background-for-backing)] + [win (widget-window gtk)]) + (when (and win (not col)) + ;; Before transparent drawing, we need to install the + ;; parent window's pattern. + (cairo_set_source cr (gdk_window_get_background_pattern + (gdk_window_get_effective_parent win))) + (cairo_rectangle cr 0 0 32000 32000) + (cairo_fill cr)) + (unless (send wx paint-or-queue-paint cr) + (when col + (cairo_set_source_rgb cr + (color-red col) + (color-green col) + (color-blue col)) + (cairo_rectangle cr 0 0 32000 32000) + (cairo_fill cr))) + (not (send wx is-panel?))) + #f)))) + (define-signal-handler connect-value-changed-h "value-changed" (_fun _GtkWidget -> _void) (lambda (gtk) @@ -244,7 +287,8 @@ refresh-for-autoscroll refresh-all-children reset-auto-scroll get-eventspace - register-extra-gtk) + register-extra-gtk + call-pre-on-event set-focus on-event) (define is-combo? (memq 'combo style)) (define has-border? (or (memq 'border style) @@ -252,7 +296,9 @@ (define margin (if has-border? 1 0)) - (define-values (client-gtk container-gtk gtk + (define flush-win-box (mcons #f 0)) + + (define-values (client-gtk container-gtk gtk hscroll-adj vscroll-adj hscroll-gtk vscroll-gtk resize-box combo-button-gtk scroll-width) @@ -274,7 +320,11 @@ (memq 'auto-hscroll style))] [vs? (or (memq 'vscroll style) (memq 'auto-vscroll style))]) - (let ([h (as-gtk-allocation (gtk_hbox_new #f 0))] + (let ([border (and has-border? + (as-gtk-allocation (gtk_hbox_new #f 0)))] + [h (if has-border? + (gtk_hbox_new #f 0) + (as-gtk-allocation (gtk_hbox_new #f 0)))] [v (gtk_vbox_new #f 0)] [v2 (gtk_vbox_new #f 0)] [h2 (gtk_vbox_new #f 0)] @@ -292,7 +342,8 @@ (gtk_fixed_set_has_window client-gtk #t)) ; imposes clipping (when has-border? (gtk_container_set_border_width h margin) - (connect-expose-border h)) + (connect-expose/draw-border border h)) + (when border (gtk_box_pack_start border h #t #t 0)) (gtk_box_pack_start h v #t #t 0) (gtk_box_pack_start v client-gtk #t #t 0) (gtk_box_pack_start h v2 #f #f 0) @@ -303,7 +354,8 @@ (when hs? (gtk_widget_show hscroll)) (gtk_widget_show vscroll) - (gtk_widget_show h) + (when border + (gtk_widget_show h)) (gtk_widget_show v) (when vs? (gtk_widget_show v2)) @@ -316,7 +368,7 @@ (gtk_widget_show container-gtk)) (let ([req (make-GtkRequisition 0 0)]) (gtk_widget_size_request vscroll req) - (values client-gtk container-gtk h hadj vadj + (values client-gtk container-gtk (or border h) hadj vadj (and hs? h2) (and vs? v2) (and hs? vs? resize-box) @@ -329,12 +381,15 @@ (values orig-entry gtk gtk #f #f #f #f #f (extract-combo-button gtk) 0))] [has-border? (let ([client-gtk (gtk_drawing_area_new)] - [h (as-gtk-allocation (gtk_hbox_new #f 0))]) + [h (gtk_hbox_new #f 0)] + [border (as-gtk-allocation (gtk_hbox_new #f 0))]) + (gtk_box_pack_start border h #t #t 0) (gtk_box_pack_start h client-gtk #t #t 0) (gtk_container_set_border_width h margin) - (connect-expose-border h) + (connect-expose/draw-border border h) + (gtk_widget_show h) (gtk_widget_show client-gtk) - (values client-gtk client-gtk h #f #f #f #f #f #f 0))] + (values client-gtk client-gtk border #f #f #f #f #f #f 0))] [else (let ([client-gtk (as-gtk-allocation (gtk_drawing_area_new))]) (values client-gtk client-gtk client-gtk #f #f #f #f #f #f 0))]))) @@ -387,7 +442,9 @@ (GtkRequisition-height r) (GtkRequisition-height r)))) - (connect-expose client-gtk) + (if gtk3? + (connect-draw client-gtk) + (connect-expose client-gtk)) #;(gtk_widget_set_double_buffered client-gtk #f) (connect-key-and-mouse client-gtk) (connect-focus client-gtk) @@ -401,8 +458,7 @@ GDK_LEAVE_NOTIFY_MASK)) (unless (or (memq 'no-focus style) (is-panel?)) - (set-gtk-object-flags! client-gtk (bitwise-ior (get-gtk-object-flags client-gtk) - GTK_CAN_FOCUS))) + (gtk_widget_set_can_focus client-gtk #t)) (check-combo) (when combo-button-gtk (connect-combo-key-and-mouse combo-button-gtk)) @@ -412,6 +468,20 @@ (when hscroll-adj (connect-value-changed-h hscroll-adj)) (when vscroll-adj (connect-value-changed-v vscroll-adj)) + (when (and gtk3? (or hscroll-gtk vscroll-gtk)) + ;; Need to get scroll size now that the control is shown + (let ([req (make-GtkRequisition 0 0)]) + (gtk_widget_show gtk) + (gtk_widget_get_preferred_size (or vscroll-gtk hscroll-gtk) req #f) + (set! scroll-width (if vscroll-gtk + (GtkRequisition-width req) + (GtkRequisition-height req))) + (gtk_widget_hide gtk))) + + (when (and gtk3? is-combo?) + ;; Needed for sizing: + (gtk_combo_box_append_text gtk (make-string 10 #\X))) + (set-auto-size) (adjust-client-delta (+ (* 2 margin) (if (or (memq 'vscroll style) @@ -423,6 +493,9 @@ (memq 'auto-hscroll style)) scroll-width 0))) + (when (and gtk3? is-combo?) + (infer-client-delta #:inside client-gtk) + (gtk_combo_box_text_remove gtk 0)) (define/public (is-panel?) #f) @@ -447,11 +520,19 @@ (define/override (handles-events? gtk) (not (ptr-equal? gtk combo-button-gtk))) (define/override (internal-pre-on-event gtk e) - (if (and (ptr-equal? gtk combo-button-gtk) - (send e button-down?)) - (begin - (on-popup) - #t) + (if (ptr-equal? gtk combo-button-gtk) + (cond + [gtk3? + (queue-window-event this (lambda () + (unless (call-pre-on-event this e) + (when (send e button-down?) + (set-focus)) + (on-event e)))) + #t] + [(send e button-down?) + (on-popup) + #t] + [else #f]) #f)) (define/public (popup-combo) ;; Unfortunately, the user has to hold the mouse @@ -475,11 +556,11 @@ (queue-window-refresh-event this thunk)) (define/public (skip-pre-paint?) #f) - (define/public (paint-or-queue-paint) + (define/public (paint-or-queue-paint cr) ;; in atomic mode (if for-gl? (queue-paint) - (or (do-canvas-backing-flush #f) + (or (do-canvas-backing-flush cr) (begin (queue-paint) #f)))) @@ -487,18 +568,18 @@ ;; overridden to extend for scheduled periodic flushes: (define/public (schedule-periodic-backing-flush) (void)) - (define/public (do-canvas-backing-flush ctx) - (do-backing-flush this dc (if is-combo? - (get-subwindow client-gtk) - (widget-window client-gtk)))) + (define/public (do-canvas-backing-flush cr) + (do-backing-flush this dc (if gtk3? + cr + (if is-combo? + (get-subwindow client-gtk) + (widget-window client-gtk))))) (define/public (on-paint) (void)) - (define flush-win-box (mcons #f 0)) (define/public (get-flush-window) (atomically - (if (zero? (bitwise-and (get-gtk-object-flags client-gtk) - GTK_MAPPED)) + (if (not (gtk_widget_get_mapped client-gtk)) (mcons #f #f) (if (win-box-valid? flush-win-box) flush-win-box @@ -570,8 +651,9 @@ [(and v? (not h?)) ;; remove corner (gtk_widget_hide resize-box)])) - (adjust-client-delta (+ (* 2 margin) (if v? scroll-width 0)) - (+ (* 2 margin) (if h? scroll-width 0)))) + (unless is-combo? + (adjust-client-delta (+ (* 2 margin) (if v? scroll-width 0)) + (+ (* 2 margin) (if h? scroll-width 0))))) (define suspend-scroll-callbacks? #f) (define/public (deliver-scroll-callbacks?) (not suspend-scroll-callbacks?)) @@ -653,7 +735,7 @@ (->long (dispatch which gtk_adjustment_get_value 0)))) (define clear-bg? - (and (not (memq 'transparent style)) + (and (not (memq 'transparent style)) (not (memq 'no-autoclear style)))) (define transparent? (memq 'transparent style)) @@ -678,7 +760,7 @@ #f)) (when is-combo? - (connect-changed client-gtk)) + (connect-changed (if gtk3? gtk client-gtk))) (define combo-count 0) (define/public (clear-combo-items) @@ -786,30 +868,29 @@ (define reg-blits null) - (define/private (register-one-blit x y w h on-pixbuf off-pixbuf) - (let* ([cwin (widget-window client-gtk)]) - (atomically - (let ([win (create-gc-window cwin x y w h)]) - (let ([r (scheme_add_gc_callback - (make-gc-show-desc win on-pixbuf w h) - (make-gc-hide-desc win off-pixbuf w h))]) - (cons win r)))))) - + (define/private (register-one-blit x y w h on-gc-bitmap off-gc-bitmap) + (atomically + (let ([win (create-gc-window client-gtk x y w h)]) + (let ([r (scheme_add_gc_callback + (make-gc-show-desc win on-gc-bitmap w h) + (make-gc-hide-desc win off-gc-bitmap w h))]) + (cons win r))))) + (define/public (register-collecting-blit x y w h on off on-x on-y off-x off-y) (let ([on (fix-bitmap-size on w h on-x on-y)] [off (fix-bitmap-size off w h off-x off-y)]) - (let ([on-pixbuf (bitmap->pixbuf on (->screen 1.0))] - [off-pixbuf (bitmap->pixbuf off (->screen 1.0))]) + (let ([on-gc-bitmap (bitmap->gc-bitmap on client-gtk)] + [off-gc-bitmap (bitmap->gc-bitmap off client-gtk)]) (atomically (set! reg-blits (cons (register-one-blit (->screen x) (->screen y) (->screen w) (->screen h) - on-pixbuf off-pixbuf) + on-gc-bitmap off-gc-bitmap) reg-blits)))))) (define/public (unregister-collecting-blits) (atomically (for ([r (in-list reg-blits)]) - (g_object_unref (car r)) + (free-gc-window (car r)) (scheme_remove_gc_callback (cdr r))) (set! reg-blits null)))))) diff --git a/gui-lib/mred/private/wx/gtk/choice.rkt b/gui-lib/mred/private/wx/gtk/choice.rkt index c36da477..22eacb51 100644 --- a/gui-lib/mred/private/wx/gtk/choice.rkt +++ b/gui-lib/mred/private/wx/gtk/choice.rkt @@ -1,5 +1,6 @@ #lang racket/base (require ffi/unsafe + ffi/unsafe/define racket/class "../../syntax.rkt" "../../lock.rkt" @@ -16,9 +17,21 @@ ;; ---------------------------------------- -(define-gtk gtk_combo_box_new_text (_fun -> _GtkWidget)) -(define-gtk gtk_combo_box_append_text (_fun _GtkWidget _string -> _void)) -(define-gtk gtk_combo_box_remove_text (_fun _GtkWidget _int -> _void)) +(define-gtk gtk_combo_box_text_new (_fun -> _GtkWidget) + #:make-fail make-not-available) +(define-gtk gtk_combo_box_new_text (_fun -> _GtkWidget) + #:fail (lambda () gtk_combo_box_text_new)) + +(define-gtk gtk_combo_box_text_append_text (_fun _GtkWidget _string -> _void) + #:make-fail make-not-available) +(define-gtk gtk_combo_box_append_text (_fun _GtkWidget _string -> _void) + #:fail (lambda () gtk_combo_box_text_append_text)) + +(define-gtk gtk_combo_box_text_remove (_fun _GtkWidget _int -> _void) + #:make-fail make-not-available) +(define-gtk gtk_combo_box_remove_text (_fun _GtkWidget _int -> _void) + #:fail (lambda () gtk_combo_box_text_remove)) + (define-gtk gtk_combo_box_set_active (_fun _GtkWidget _int -> _void)) (define-gtk gtk_combo_box_get_active (_fun _GtkWidget -> _int)) (define-gtk gtk_bin_get_child (_fun _GtkWidget -> _GtkWidget)) diff --git a/gui-lib/mred/private/wx/gtk/clipboard.rkt b/gui-lib/mred/private/wx/gtk/clipboard.rkt index 2da85840..fb817987 100644 --- a/gui-lib/mred/private/wx/gtk/clipboard.rkt +++ b/gui-lib/mred/private/wx/gtk/clipboard.rkt @@ -1,5 +1,6 @@ #lang racket/base (require racket/class + racket/promise ffi/unsafe ffi/unsafe/alloc racket/draw/unsafe/bstr @@ -18,7 +19,7 @@ _GtkSelectionData gtk_selection_data_get_length gtk_selection_data_get_data - primary-atom + get-primary-atom get-selection-eventspace)) (define (has-x-selection?) #t) @@ -72,8 +73,10 @@ (define clear_owner (function-ptr clear-owner (_fun #:atomic? #t _GtkClipboard _pointer -> _void))) -(define primary-atom (gdk_atom_intern "PRIMARY" #t)) -(define clipboard-atom (gdk_atom_intern "CLIPBOARD" #t)) +(define primary-atom (delay (gdk_atom_intern "PRIMARY" #t))) +(define clipboard-atom (delay (gdk_atom_intern "CLIPBOARD" #t))) + +(define (get-primary-atom) (force primary-atom)) (define the-x-selection-driver #f) @@ -145,8 +148,8 @@ (define cb (gtk_clipboard_get (if x-selection? - primary-atom - clipboard-atom))) + (force primary-atom) + (force clipboard-atom)))) (define self-box #f) (define/public (get-client) client) diff --git a/gui-lib/mred/private/wx/gtk/combo.rkt b/gui-lib/mred/private/wx/gtk/combo.rkt index 4bd0aee6..b0e2d8c7 100644 --- a/gui-lib/mred/private/wx/gtk/combo.rkt +++ b/gui-lib/mred/private/wx/gtk/combo.rkt @@ -4,6 +4,7 @@ "../../syntax.rkt" "types.rkt" "utils.rkt" + "const.rkt" "window.rkt") ;; Hacks for working with GtkComboBox[Entry] @@ -144,4 +145,13 @@ hand-id))))]) (connect-key-and-mouse button-gtk (and hand-id #t)) (when hand-id - (connect-reorder-button-press button-gtk (cast hand-id _long _pointer))))) + (connect-reorder-button-press button-gtk (cast hand-id _long _pointer))) + (when gtk3? + (gtk_widget_add_events button-gtk (bitwise-ior GDK_KEY_PRESS_MASK + GDK_KEY_RELEASE_MASK + GDK_BUTTON_PRESS_MASK + GDK_BUTTON_RELEASE_MASK + GDK_POINTER_MOTION_MASK + GDK_FOCUS_CHANGE_MASK + GDK_ENTER_NOTIFY_MASK + GDK_LEAVE_NOTIFY_MASK))))) diff --git a/gui-lib/mred/private/wx/gtk/dc.rkt b/gui-lib/mred/private/wx/gtk/dc.rkt index ec339160..872182a5 100644 --- a/gui-lib/mred/private/wx/gtk/dc.rkt +++ b/gui-lib/mred/private/wx/gtk/dc.rkt @@ -1,9 +1,11 @@ #lang racket/base (require ffi/unsafe + ffi/unsafe/define racket/class "utils.rkt" "types.rkt" "window.rkt" + "frame.rkt" "x11.rkt" "win32.rkt" "gl-context.rkt" @@ -23,17 +25,24 @@ gdk_gc_new gdk_gc_unref gdk_gc_set_rgb_fg_color + gdk_gc_set_line_attributes gdk_draw_rectangle)) (define-gdk gdk_cairo_create (_fun _pointer -> _cairo_t) #:wrap (allocator cairo_destroy)) (define-gdk gdk_gc_unref (_fun _pointer -> _void) - #:wrap (deallocator)) + #:wrap (deallocator) + #:make-fail make-not-available) (define-gdk gdk_gc_new (_fun _GdkWindow -> _pointer) - #:wrap (allocator gdk_gc_unref)) -(define-gdk gdk_gc_set_rgb_fg_color (_fun _pointer _GdkColor-pointer -> _void)) -(define-gdk gdk_draw_rectangle (_fun _GdkWindow _pointer _gboolean _int _int _int _int -> _void)) + #:wrap (allocator gdk_gc_unref) + #:make-fail make-not-available) +(define-gdk gdk_gc_set_rgb_fg_color (_fun _pointer _GdkColor-pointer -> _void) + #:make-fail make-not-available) +(define-gdk gdk_gc_set_line_attributes (_fun _pointer _int _int _int _int -> _void) + #:make-fail make-not-available) +(define-gdk gdk_draw_rectangle (_fun _GdkWindow _pointer _gboolean _int _int _int _int -> _void) + #:make-fail make-not-available) (define-cstruct _GdkVisual-rec ([type-instance _pointer] [ref_count _uint] @@ -42,18 +51,20 @@ [depth _int])) (define-gdk gdk_visual_get_system (_fun -> _GdkVisual-rec-pointer)) -(define x11-bitmap% +(define x11-bitmap%/gtk2 (class bitmap% - (init w h gdk-win) + (init w h gtk) (super-make-object (make-alternate-bitmap-kind w h (->screen 1.0))) - (define pixmap (gdk_pixmap_new gdk-win - (min (max 1 (->screen w)) 32000) - (min (max 1 (->screen h)) 32000) - (if gdk-win - -1 - (GdkVisual-rec-depth - (gdk_visual_get_system))))) + (define pixmap + (let ([gdk-win (and gtk (widget-window gtk))]) + (gdk_pixmap_new gdk-win + (min (max 1 (->screen w)) 32000) + (min (max 1 (->screen h)) 32000) + (if gdk-win + -1 + (GdkVisual-rec-depth + (gdk_visual_get_system)))))) (define s (cairo_xlib_surface_create (gdk_x11_display_get_xdisplay (gdk_drawable_get_display pixmap)) @@ -89,6 +100,18 @@ (gobject-unref pixmap) (set! s #f))))) +(define x11-bitmap%/gtk3 + (class bitmap% + (init w h gtk) + (super-make-object w h #f #t (if gtk + (->screen (gtk_widget_get_scale_factor gtk)) + (display-bitmap-resolution 0 (lambda () 1.0)))))) + +(define x11-bitmap% + (if gtk3? + x11-bitmap%/gtk3 + x11-bitmap%/gtk2)) + (define win32-bitmap% (class bitmap% (init w h gdk-win) @@ -134,8 +157,8 @@ (define/override (make-backing-bitmap w h) (cond [(and (eq? 'unix (system-type)) - (send canvas get-canvas-background)) - (make-object x11-bitmap% w h (widget-window (send canvas get-client-gtk)))] + (or gtk3? (send canvas get-canvas-background))) + (make-object x11-bitmap% w h (send canvas get-client-gtk))] [(and (eq? 'windows (system-type)) (send canvas get-canvas-background)) (make-object win32-bitmap% w h (widget-window (send canvas get-client-gtk)))] @@ -165,13 +188,16 @@ (define/override (cancel-delay req) (cancel-flush-delay req)))) -(define (do-backing-flush canvas dc win) +(define (do-backing-flush canvas dc win-or-cr) (send dc on-backing-flush (lambda (bm) (let ([w (box 0)] [h (box 0)]) (send canvas get-client-size w h) - (let ([cr (gdk_cairo_create win)]) + (let ([cr (if gtk3? + win-or-cr + (gdk_cairo_create win-or-cr))]) (cairo_scale cr (->screen 1.0) (->screen 1.0)) (backing-draw-bm bm cr (unbox w) (unbox h) 0 0 (->screen 1.0)) - (cairo_destroy cr)))))) + (unless gtk3? + (cairo_destroy cr))))))) diff --git a/gui-lib/mred/private/wx/gtk/frame.rkt b/gui-lib/mred/private/wx/gtk/frame.rkt index 94ebcc14..2ccd2f94 100644 --- a/gui-lib/mred/private/wx/gtk/frame.rkt +++ b/gui-lib/mred/private/wx/gtk/frame.rkt @@ -48,7 +48,9 @@ (define-gtk gtk_window_set_focus_on_map (_fun _GtkWidget _gboolean -> _void)) (define-gtk gtk_window_maximize (_fun _GtkWidget -> _void)) (define-gtk gtk_window_unmaximize (_fun _GtkWidget -> _void)) -(define-gtk gtk_widget_set_uposition (_fun _GtkWidget _int _int -> _void)) +(define-gtk gtk_window_move (_fun _GtkWidget _int _int -> _void)) +(define-gtk gtk_widget_set_uposition (_fun _GtkWidget _int _int -> _void) + #:fail (lambda () (lambda (w x y) (gtk_window_move w x y)))) (define-gtk gtk_window_get_position (_fun _GtkWidget (x : (_ptr o _int)) (y : (_ptr o _int)) -> _void -> (values x y))) @@ -62,6 +64,8 @@ (define-gdk gdk_window_set_cursor (_fun _GdkWindow _pointer -> _void)) (define-gdk gdk_screen_get_root_window (_fun _GdkScreen -> _GdkWindow)) +(define-gdk gdk_screen_get_monitor_scale_factor (_fun _GdkScreen _int -> _int) + #:fail (lambda () (lambda (s n) 1))) (define-gdk gdk_window_get_pointer (_fun _GdkWindow (x : (_ptr o _int)) (y : (_ptr o _int)) @@ -85,6 +89,8 @@ [win_gravity _int])) (define-gtk gtk_window_set_geometry_hints (_fun _GtkWindow _GtkWidget _GdkGeometry-pointer _int -> _void)) +(define-gtk gtk_layout_new (_fun (_pointer = #f) (_pointer = #f) -> _GtkWidget)) +(define-gtk gtk_layout_put (_fun _GtkWidget _GtkWidget _int _int -> _void)) (define-signal-handler connect-delete "delete-event" (_fun _GtkWidget -> _gboolean) @@ -173,22 +179,24 @@ (when floating? (gtk_window_set_keep_above gtk #t) (gtk_window_set_focus_on_map gtk #f)) - (define-values (vbox-gtk panel-gtk) + (define-values (vbox-gtk layout-gtk panel-gtk) (atomically (let ([vbox-gtk (gtk_vbox_new #f 0)] + [layout-gtk (and gtk3? (gtk_layout_new))] [panel-gtk (gtk_fixed_new)]) (gtk_container_add gtk vbox-gtk) - (gtk_box_pack_end vbox-gtk panel-gtk #t #t 0) - (values vbox-gtk panel-gtk)))) + (gtk_box_pack_end vbox-gtk (or layout-gtk panel-gtk) #t #t 0) + (when layout-gtk + (gtk_layout_put layout-gtk panel-gtk 0 0)) + (values vbox-gtk layout-gtk panel-gtk)))) (gtk_widget_show vbox-gtk) + (when layout-gtk (gtk_widget_show layout-gtk)) (gtk_widget_show panel-gtk) (connect-enter-and-leave gtk) ;; Enable key events on the panel to catch events ;; that would otherwise go undelivered: - (set-gtk-object-flags! panel-gtk - (bitwise-ior (get-gtk-object-flags panel-gtk) - GTK_CAN_FOCUS)) + (gtk_widget_set_can_focus panel-gtk #t) (gtk_widget_add_events panel-gtk (bitwise-ior GDK_KEY_PRESS_MASK GDK_KEY_RELEASE_MASK)) (connect-key panel-gtk) @@ -235,7 +243,7 @@ (define/public (set-menu-bar mb) (let ([mb-gtk (send mb get-gtk)]) - (gtk_box_pack_start vbox-gtk mb-gtk #t #t 0) + (gtk_box_pack_start vbox-gtk mb-gtk #f #f 0) (gtk_widget_show mb-gtk)) (let ([h (send mb set-top-window this)]) ;; adjust client delta right away, so that we make @@ -444,8 +452,7 @@ (let ([f-gtk (gtk_window_get_focus gtk)]) (and f-gtk (or even-if-not-active? - (positive? (bitwise-and (get-gtk-object-flags f-gtk) - GTK_HAS_FOCUS))) + (gtk_widget_has_focus f-gtk)) (gtk->wx f-gtk)))) (define/override (call-pre-on-event w e) @@ -576,8 +583,11 @@ (gdk_screen_get_n_monitors (gdk_screen_get_default))) (define (display-bitmap-resolution num fail) - (define (get) (or (get-interface-scale-factor num) - 1.0)) + (define (get) (* (or (get-interface-scale-factor num) + 1.0) + (gdk_screen_get_monitor_scale_factor + (gdk_screen_get_default) + num))) (if (zero? num) (get) (if (num . < . (gdk_screen_get_n_monitors (gdk_screen_get_default))) diff --git a/gui-lib/mred/private/wx/gtk/gauge.rkt b/gui-lib/mred/private/wx/gtk/gauge.rkt index dda1a9a5..e6130aa2 100644 --- a/gui-lib/mred/private/wx/gtk/gauge.rkt +++ b/gui-lib/mred/private/wx/gtk/gauge.rkt @@ -1,5 +1,6 @@ #lang racket/base (require ffi/unsafe + ffi/unsafe/define racket/class "../../syntax.rkt" "item.rkt" @@ -15,9 +16,18 @@ (define-gtk gtk_progress_bar_new (_fun _pointer -> _GtkWidget)) (define-gtk gtk_progress_bar_set_fraction (_fun _GtkWidget _double* -> _void)) -(define-gtk gtk_progress_bar_set_orientation (_fun _GtkWidget _int -> _void)) +(define-gtk gtk_orientable_set_orientation (_fun _GtkWidget _int -> _void) + #:make-fail make-not-available) +(define-gtk gtk_progress_bar_set_inverted (_fun _GtkWidget _gboolean -> _void) + #:make-fail make-not-available) +(define-gtk gtk_progress_bar_set_orientation (_fun _GtkWidget _int -> _void) + #:fail (lambda () + (lambda (w o) + (gtk_orientable_set_orientation w GTK_ORIENTATION_VERTICAL) + (gtk_progress_bar_set_inverted w #t)))) (define GTK_PROGRESS_BOTTOM_TO_TOP 2) +(define GTK_ORIENTATION_VERTICAL 1) (defclass gauge% item% (init parent diff --git a/gui-lib/mred/private/wx/gtk/gcwin.rkt b/gui-lib/mred/private/wx/gtk/gcwin.rkt index d017aeba..e13a6760 100644 --- a/gui-lib/mred/private/wx/gtk/gcwin.rkt +++ b/gui-lib/mred/private/wx/gtk/gcwin.rkt @@ -1,16 +1,24 @@ #lang racket/base (require ffi/unsafe + ffi/unsafe/define + racket/draw/unsafe/cairo + racket/class "utils.rkt" "types.rkt" - "window.rkt") + "window.rkt" + "pixbuf.rkt" + "x11.rkt") (provide (protect-out scheme_add_gc_callback scheme_remove_gc_callback create-gc-window + free-gc-window make-gc-show-desc - make-gc-hide-desc)) + make-gc-hide-desc + bitmap->gc-bitmap)) +;; Gtk2, only: (define-cstruct _GdkWindowAttr ([title _string] [event_mask _int] @@ -20,7 +28,7 @@ [height _int] [wclass _int] ; GDK_INPUT_OUTPUT [visual _pointer] - [colormap _pointer] + [colormap _pointer] ; this field is absent in Gtk3 [window_type _int] ; GDK_WINDOW_CHILD [cursor _pointer] [wmclass_name _string] @@ -44,52 +52,136 @@ (define GDK_WINDOW_CHILD 2) -(define-gdk gdk_window_new (_fun _GdkWindow _GdkWindowAttr-pointer _uint - -> _GdkWindow)) +(define-gdk gdk_window_new (_fun _GdkWindow _GdkWindowAttr-pointer _uint -> _GdkWindow)) (define-gdk gdk_window_show _fpointer) (define-gdk gdk_window_hide _fpointer) (define-gdk gdk_display_flush _fpointer) -(define-gdk gdk_draw_pixbuf _fpointer) + +;; Gtk2 +(define-gdk gdk_draw_pixbuf _fpointer + #:make-fail make-not-available) (define-mz scheme_add_gc_callback (_fun _racket _racket -> _racket)) (define-mz scheme_remove_gc_callback (_fun _racket -> _void)) -(define (create-gc-window cwin x y w h) - (let ([win (gdk_window_new cwin (make-GdkWindowAttr - "" - 0 - x y w h - GDK_INPUT_OUTPUT - #f #f - GDK_WINDOW_CHILD - #f - "" "" #f 0) - (bitwise-ior GDK_WA_X - GDK_WA_Y))]) - win)) +(define-x11 XSetWindowBackgroundPixmap _fpointer #:fail (lambda () #f)) +(define-x11 XMapRaised _fpointer #:fail (lambda () #f)) +(define-x11 XUnmapWindow _fpointer #:fail (lambda () #f)) -(define (make-draw win pixbuf w h) - (vector 'ptr_ptr_ptr_int_int_int_int_int_int_int_int_int->void - gdk_draw_pixbuf - win #f pixbuf - 0 0 0 0 w h - 0 0 0)) +(define _GdkVisual (_cpointer 'GdkVisual)) +(define-gdk gdk_window_get_visual (_fun _GdkWindow -> _GdkVisual)) +(define-gdk gdk_visual_get_depth (_fun _GdkVisual -> _int)) + +(define (bitmap->gc-bitmap bm client-gtk) + (cond + [gtk3? + ; Generate an X11 Pixmap + (define gwin (widget-window client-gtk)) + (define display (gdk_x11_display_get_xdisplay (gdk_window_get_display gwin))) + (define sf (->screen (gtk_widget_get_scale_factor client-gtk))) + (define w (send bm get-width)) + (define h (send bm get-height)) + (define bms (send bm get-backing-scale)) + (define cw (inexact->exact (ceiling (* sf w)))) + (define ch (inexact->exact (ceiling (* sf h)))) + (define visual (gdk_window_get_visual gwin)) + (define pixmap (XCreatePixmap display + (gdk_x11_window_get_xid gwin) + cw ch + (gdk_visual_get_depth visual))) + (define s (cairo_xlib_surface_create display + (cast pixmap _pointer _ulong) + (gdk_x11_visual_get_xvisual visual) + cw ch)) + (define cr (cairo_create s)) + (define pat (cairo_pattern_create_for_surface (send bm get-handle))) + (cairo_pattern_set_matrix pat (make-cairo_matrix_t (/ bms sf) 0.0 + 0.0 (/ bms sf) + 0.0 0.0)) + (cairo_set_source cr pat) + (cairo_pattern_destroy pat) + (cairo_rectangle cr 0 0 cw ch) + (cairo_fill cr) + (cairo_destroy cr) + (cairo_surface_destroy s) + pixmap] + [else + ;; Generate a Gdk Pixbuf + (bitmap->pixbuf bm (->screen 1.0))])) + +(define (create-gc-window client-gtk x y w h) + (define cwin (widget-window client-gtk)) + (cond + [gtk3? + ;; Work at the level of X11 to change the screen without an event loop + (define display (gdk_x11_display_get_xdisplay (gdk_window_get_display cwin))) + (define s (gtk_widget_get_scale_factor client-gtk)) + (cons display + (XCreateSimpleWindow display + (gdk_x11_window_get_xid cwin) + (* s x) (* s y) (* s w) (* s h) 0 0 0))] + [else + (as-gtk-window-allocation + (gdk_window_new cwin (make-GdkWindowAttr + "" + 0 + x y w h + GDK_INPUT_OUTPUT + #f #f + GDK_WINDOW_CHILD + #f + "" "" #f 0) + (bitwise-ior GDK_WA_X + GDK_WA_Y)))])) + +(define (free-gc-window win) + (cond + [gtk3? (XDestroyWindow (car win) (cdr win))] + [else (g_object_unref win)])) + +(define (make-draw win gc-bitmap w h) + (cond + [gtk3? (vector 'ptr_ptr_ptr->void + XSetWindowBackgroundPixmap + (car win) + (cdr win) + gc-bitmap)] + [else (vector 'ptr_ptr_ptr_int_int_int_int_int_int_int_int_int->void + gdk_draw_pixbuf + win #f gc-bitmap + 0 0 0 0 w h + 0 0 0)])) (define (make-flush) (vector 'ptr_ptr_ptr->void gdk_display_flush (gdk_display_get_default) #f #f)) -(define (make-gc-show-desc win pixbuf w h) - (vector - (vector 'ptr_ptr_ptr->void gdk_window_show win #f #f) - (make-draw win pixbuf w h) - (make-flush))) +(define (make-gc-show-desc win gc-bitmap w h) + (cond + [gtk3? (vector + (make-draw win gc-bitmap w h) + (vector 'ptr_ptr_ptr->void + XMapRaised + (car win) + (cdr win) + #f) + (make-flush))] + [else (vector + (vector 'ptr_ptr_ptr->void gdk_window_show win #f #f) + (make-draw win gc-bitmap w h) + (make-flush))])) -(define (make-gc-hide-desc win pixbuf w h) +(define (make-gc-hide-desc win gc-bitmap w h) (vector ;; draw the ``off'' bitmap so we can flush immediately - (make-draw win pixbuf w h) + (make-draw win gc-bitmap w h) (make-flush) ;; hide the window; it may take a while for the underlying canvas ;; to refresh: - (vector 'ptr_ptr_ptr->void gdk_window_hide win #f #f))) + (if gtk3? + (vector 'ptr_ptr_ptr->void + XUnmapWindow + (car win) + (cast (cdr win) _Window _pointer) + #f) + (vector 'ptr_ptr_ptr->void gdk_window_hide win #f #f)))) diff --git a/gui-lib/mred/private/wx/gtk/gl-context.rkt b/gui-lib/mred/private/wx/gtk/gl-context.rkt index e210fc8a..6210ead8 100644 --- a/gui-lib/mred/private/wx/gtk/gl-context.rkt +++ b/gui-lib/mred/private/wx/gtk/gl-context.rkt @@ -32,12 +32,8 @@ ;; =================================================================================================== ;; X11/GLX FFI -(define x-lib (ffi-lib/complaint-on-failure "libX11" '(""))) (define gl-lib (ffi-lib/complaint-on-failure "libGL" '("1" ""))) -(define-ffi-definer define-x x-lib - #:default-make-fail make-not-available) - (define-ffi-definer define-glx gl-lib #:default-make-fail make-not-available) @@ -81,14 +77,14 @@ (define GLX_CONTEXT_CORE_PROFILE_BIT_ARB #x1) (define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB #x2) -(define-x XFree (_fun _pointer -> _int) +(define-x11 XFree (_fun _pointer -> _int) #:wrap (deallocator)) -(define-x XSetErrorHandler +(define-x11 XSetErrorHandler (_fun (_fun _Display _XErrorEvent -> _int) -> (_fun _Display _XErrorEvent -> _int))) -(define-x XSync +(define-x11 XSync (_fun _Display _int -> _void)) (define-glx glXQueryVersion diff --git a/gui-lib/mred/private/wx/gtk/gtk3.rkt b/gui-lib/mred/private/wx/gtk/gtk3.rkt new file mode 100644 index 00000000..b8d5b195 --- /dev/null +++ b/gui-lib/mred/private/wx/gtk/gtk3.rkt @@ -0,0 +1,16 @@ +#lang racket/base +(require ffi/unsafe) + +(provide gtk3? + get-gdk3-lib + get-gtk3-lib) + +(define (get-gdk3-lib) + (ffi-lib "libgdk-3" '("0" ""))) +(define (get-gtk3-lib) + (ffi-lib "libgtk-3" '("0" ""))) + +(define gtk3? + (and (not (getenv "PLT_GTK2")) + (get-gdk3-lib) + (get-gtk3-lib))) diff --git a/gui-lib/mred/private/wx/gtk/item.rkt b/gui-lib/mred/private/wx/gtk/item.rkt index d5155174..f38d8074 100644 --- a/gui-lib/mred/private/wx/gtk/item.rkt +++ b/gui-lib/mred/private/wx/gtk/item.rkt @@ -1,7 +1,11 @@ #lang racket/base (require ffi/unsafe + ffi/unsafe/define racket/class racket/draw/private/local + (only-in racket/draw/unsafe/pango + pango_cairo_font_map_get_resolution + pango_cairo_font_map_get_default) (only-in racket/draw make-font) "../../syntax.rkt" "window.rkt" @@ -13,14 +17,27 @@ install-control-font)) (define _PangoFontDescription _pointer) -(define-gtk gtk_widget_modify_font (_fun _GtkWidget _PangoFontDescription -> _void)) +(define-gtk gtk_widget_override_font (_fun _GtkWidget _PangoFontDescription -> _void) + #:make-fail make-not-available) +(define-gtk gtk_widget_modify_font (_fun _GtkWidget _PangoFontDescription -> _void) + #:fail (lambda () gtk_widget_override_font)) (define (install-control-font gtk font) (when font - (let* ([s (->screen 1)] - [font (if (= s 1) + (let* ([target-size + (cond + [gtk3? + ;; Gtk3 ignores the "size-in-pixels" part of a + ;; font spec, so we have to adjust the text size + ;; to compensate. + (* (send font get-size) + (/ 72.0 + (pango_cairo_font_map_get_resolution + (pango_cairo_font_map_get_default))))] + [else (->screen (send font get-size))])] + [font (if (= target-size (send font get-size)) font - (make-font #:size (->screen (send font get-size)) + (make-font #:size target-size #:face (send font get-face) #:family (send font get-family) #:style (send font get-style) diff --git a/gui-lib/mred/private/wx/gtk/menu-bar.rkt b/gui-lib/mred/private/wx/gtk/menu-bar.rkt index 29dac48a..3bb1ec76 100644 --- a/gui-lib/mred/private/wx/gtk/menu-bar.rkt +++ b/gui-lib/mred/private/wx/gtk/menu-bar.rkt @@ -24,7 +24,8 @@ (define-gtk gtk_label_set_text_with_mnemonic (_fun _GtkWidget _string -> _void)) (define-gtk gtk_bin_get_child (_fun _GtkWidget -> _GtkWidget)) -(define-gtk gtk_widget_set_usize (_fun _GtkWidget _int _int -> _void)) +(define-gtk gtk_widget_set_usize (_fun _GtkWidget _int _int -> _void) + #:fail (lambda () gtk_widget_set_size_request)) (define-gtk ubuntu_menu_proxy_get _fpointer #:fail (lambda () #f)) @@ -101,7 +102,7 @@ (fix-menu-height)) (define/public (reset-menu-height) - (when top-wx + (when (and (not gtk3?) top-wx) (send top-wx reset-menu-height (fix-menu-height)))) (define/private (fix-menu-height) diff --git a/gui-lib/mred/private/wx/gtk/panel.rkt b/gui-lib/mred/private/wx/gtk/panel.rkt index 3f89c701..ec197c0e 100644 --- a/gui-lib/mred/private/wx/gtk/panel.rkt +++ b/gui-lib/mred/private/wx/gtk/panel.rkt @@ -1,6 +1,8 @@ #lang racket/base (require racket/class ffi/unsafe + ffi/unsafe/define + racket/draw/unsafe/cairo "../../syntax.rkt" "../../lock.rkt" "window.rkt" @@ -18,7 +20,7 @@ gtk_fixed_move gtk_container_set_border_width - connect-expose-border)) + connect-expose/draw-border)) (define-gtk gtk_fixed_new (_fun -> _GtkWidget)) (define-gtk gtk_event_box_new (_fun -> _GtkWidget)) @@ -35,12 +37,14 @@ [gray #x8000]) (when gc (gdk_gc_set_rgb_fg_color gc (make-GdkColor 0 gray gray gray)) + (unless (= 1 (->screen 1)) + (gdk_gc_set_line_attributes gc (->screen 1) 0 0 0)) (let* ([a (widget-allocation gtk)] [w (sub1 (GtkAllocation-width a))] [h (sub1 (GtkAllocation-height a))]) (let loop ([gtk gtk] [x 0] [y 0] [can-super? #t]) (if (and can-super? - (not (zero? (bitwise-and (get-gtk-object-flags gtk) GTK_NO_WINDOW)))) + (not (gtk_widget_get_has_window gtk))) ;; no window: (let ([a (widget-allocation gtk)]) (loop (widget-parent gtk) (+ x (GtkAllocation-x a)) (+ y (GtkAllocation-y a)) @@ -52,6 +56,28 @@ (gdk_gc_unref gc))) #f)) +(define-gtk gtk_widget_get_allocated_width (_fun _GtkWidget -> _int) + #:make-fail make-not-available) +(define-gtk gtk_widget_get_allocated_height (_fun _GtkWidget -> _int) + #:make-fail make-not-available) + +(define-signal-handler connect-draw-border "draw" + (_fun _GtkWidget _cairo_t -> _gboolean) + (lambda (gtk cr) + (cairo_set_source_rgba cr 0.5 0.5 0.5 1.0) + (cairo_set_line_width cr 1.0) + (cairo_rectangle cr + 0.5 0.5 + (- (gtk_widget_get_allocated_width gtk) 1) + (- (gtk_widget_get_allocated_height gtk) 1)) + (cairo_stroke cr) + #f)) + +(define (connect-expose/draw-border gtk border-gtk) + (if gtk3? + (connect-draw-border gtk #:after? #t) + (connect-expose-border border-gtk))) + (define (panel-mixin %) (class % @@ -121,7 +147,7 @@ (let ([border-gtk (gtk_fixed_new)]) (gtk_container_add gtk border-gtk) (gtk_container_set_border_width border-gtk 1) - (connect-expose-border border-gtk) + (connect-expose/draw-border gtk border-gtk) (gtk_widget_show border-gtk) border-gtk)))) (define client-gtk (atomically diff --git a/gui-lib/mred/private/wx/gtk/platform.rkt b/gui-lib/mred/private/wx/gtk/platform.rkt index 12574439..56a50a1a 100644 --- a/gui-lib/mred/private/wx/gtk/platform.rkt +++ b/gui-lib/mred/private/wx/gtk/platform.rkt @@ -92,4 +92,5 @@ make-gl-bitmap check-for-break key-symbol-to-menu-key - needs-grow-box-spacer?)) + needs-grow-box-spacer? + graphical-system-type)) diff --git a/gui-lib/mred/private/wx/gtk/procs.rkt b/gui-lib/mred/private/wx/gtk/procs.rkt index c9f84e17..972d32ea 100644 --- a/gui-lib/mred/private/wx/gtk/procs.rkt +++ b/gui-lib/mred/private/wx/gtk/procs.rkt @@ -60,7 +60,8 @@ fill-private-color get-color-from-user key-symbol-to-menu-key - needs-grow-box-spacer?) + needs-grow-box-spacer? + graphical-system-type) (define (find-graphical-system-path what) (case what @@ -159,3 +160,8 @@ (define (check-for-break) #f) (define (needs-grow-box-spacer?) #f) + +(define (graphical-system-type) + (cond + [gtk3? 'gtk3] + [else 'gtk2])) diff --git a/gui-lib/mred/private/wx/gtk/queue.rkt b/gui-lib/mred/private/wx/gtk/queue.rkt index 9e2d28c0..8c4e0c71 100644 --- a/gui-lib/mred/private/wx/gtk/queue.rkt +++ b/gui-lib/mred/private/wx/gtk/queue.rkt @@ -187,7 +187,7 @@ (and (= (ptr-ref evt _GdkEventType) GDK_SELECTION_REQUEST) (let ([s (cast evt _pointer _GdkEventSelection-pointer)]) (= (GdkEventSelection-selection s) - primary-atom)) + (get-primary-atom))) (get-selection-eventspace))) => (lambda (e) (let ([evt (gdk_event_copy evt)]) diff --git a/gui-lib/mred/private/wx/gtk/resolution.rkt b/gui-lib/mred/private/wx/gtk/resolution.rkt index ab22f615..21ff8296 100644 --- a/gui-lib/mred/private/wx/gtk/resolution.rkt +++ b/gui-lib/mred/private/wx/gtk/resolution.rkt @@ -1,7 +1,8 @@ #lang racket/base (require racket/promise ffi/unsafe - "gsettings.rkt") + "gsettings.rkt" + "gtk3.rkt") (provide get-interface-scale-factor) @@ -38,11 +39,17 @@ (with-handlers ([exn:fail? (lambda (exn) #f)]) (define gs (force interface-settings)) (define v - (* (g_variant_get_uint32 - (g_settings_get_value gs "scaling-factor")) + (* (if gtk3? + ;; For Gtk3, toolbox handles this scaling: + 1 + ;; For Gtk2, we can handle explicit settings, + ;; but we don't try to infer a scale if the + ;; setting is 0: + (max 1 + (g_variant_get_uint32 + (g_settings_get_value gs "scaling-factor")))) (g_variant_get_double (g_settings_get_value gs "text-scaling-factor")))) - (g_object_unref gs) (and (rational? v) (positive? v) v))) diff --git a/gui-lib/mred/private/wx/gtk/tab-panel.rkt b/gui-lib/mred/private/wx/gtk/tab-panel.rkt index 345bb9c4..5c434a16 100644 --- a/gui-lib/mred/private/wx/gtk/tab-panel.rkt +++ b/gui-lib/mred/private/wx/gtk/tab-panel.rkt @@ -26,8 +26,10 @@ (define-gtk gtk_container_remove (_fun _GtkWidget _GtkWidget -> _void)) -(define-gtk gtk_widget_ref (_fun _GtkWidget -> _void)) -(define-gtk gtk_widget_unref (_fun _GtkWidget -> _void)) +(define-gtk gtk_widget_ref (_fun _GtkWidget -> _void) + #:fail (lambda () g_object_ref)) +(define-gtk gtk_widget_unref (_fun _GtkWidget -> _void) + #:fail (lambda () g_object_unref)) (define-struct page (bin-gtk label-gtk)) diff --git a/gui-lib/mred/private/wx/gtk/utils.rkt b/gui-lib/mred/private/wx/gtk/utils.rkt index f2b19a9b..85dc57d8 100644 --- a/gui-lib/mred/private/wx/gtk/utils.rkt +++ b/gui-lib/mred/private/wx/gtk/utils.rkt @@ -6,11 +6,13 @@ racket/string racket/draw/unsafe/glib (only-in '#%foreign ctype-c->scheme) + "gtk3.rkt" "../common/utils.rkt" "types.rkt" "resolution.rkt") -(provide +(provide + gtk3? define-mz define-gobj define-glib @@ -58,24 +60,30 @@ (define gdk-lib (case (system-type) - [(windows) + [(windows) (ffi-lib "libatk-1.0-0") (ffi-lib "libgio-2.0-0") (ffi-lib "libgdk_pixbuf-2.0-0") (ffi-lib "libgdk-win32-2.0-0")] - [else (ffi-lib "libgdk-x11-2.0" '("0" ""))])) + [else (if gtk3? + (get-gdk3-lib) + (ffi-lib "libgdk-x11-2.0" '("0" "")))])) (define gdk_pixbuf-lib (case (system-type) [(windows) (ffi-lib "libgdk_pixbuf-2.0-0")] [(unix) - (ffi-lib "libgdk_pixbuf-2.0" '("0" ""))] + (if gtk3? + #f + (ffi-lib "libgdk_pixbuf-2.0" '("0" "")))] [else gdk-lib])) (define gtk-lib (case (system-type) [(windows) (ffi-lib "libgtk-win32-2.0-0")] - [else (ffi-lib "libgtk-x11-2.0" '("0" ""))])) + [else (if gtk3? + (get-gtk3-lib) + (ffi-lib "libgtk-x11-2.0" '("0" "")))])) (define-ffi-definer define-gtk gtk-lib) (define-ffi-definer define-gdk gdk-lib) @@ -119,8 +127,9 @@ (define-gobj g_object_get_data (_fun _GtkWidget _string -> _pointer)) (define-gobj g_signal_connect_data (_fun _gpointer _string _fpointer _pointer _fnpointer _int -> _ulong)) -(define (g_signal_connect obj s proc user-data) - (g_signal_connect_data obj s proc user-data #f 0)) +(define G_CONNECT_AFTER 1) +(define (g_signal_connect obj s proc user-data after?) + (g_signal_connect_data obj s proc user-data #f (if after? G_CONNECT_AFTER 0))) (define-gobj g_object_get (_fun _GtkWidget (_string = "window") [w : (_ptr o _GdkWindow)] @@ -138,7 +147,8 @@ (define (get-gtk-object-flags gtk) (GtkObject-flags (cast gtk _pointer _GtkObject-pointer))) (define (set-gtk-object-flags! gtk v) - (set-GtkObject-flags! (cast gtk _pointer _GtkObject-pointer) v)) + (unless gtk3? + (set-GtkObject-flags! (cast gtk _pointer _GtkObject-pointer) v))) (define-gmodule g_module_open (_fun _path _int -> _pointer)) @@ -151,8 +161,8 @@ (define handler-proc proc) (define handler_function (function-ptr handler-proc (_fun #:atomic? #t . args))) - (define (connect-name gtk [user-data #f]) - (g_signal_connect gtk signal-name handler_function user-data)))) + (define (connect-name gtk [user-data #f] #:after? [after? #f]) + (g_signal_connect gtk signal-name handler_function user-data after?)))) (define _gpath/free diff --git a/gui-lib/mred/private/wx/gtk/window.rkt b/gui-lib/mred/private/wx/gtk/window.rkt index dda963a8..4c94c18c 100644 --- a/gui-lib/mred/private/wx/gtk/window.rkt +++ b/gui-lib/mred/private/wx/gtk/window.rkt @@ -30,8 +30,16 @@ gtk_widget_add_events gtk_widget_size_request gtk_widget_set_size_request + gtk_widget_size_allocate + gtk_widget_get_preferred_size gtk_widget_grab_focus + gtk_widget_has_focus + gtk_widget_get_mapped + gtk_widget_get_has_window + gtk_widget_set_can_default + gtk_widget_set_can_focus gtk_widget_set_sensitive + gtk_widget_get_scale_factor connect-focus connect-key @@ -88,6 +96,10 @@ (define-gtk gtk_widget_grab_focus (_fun _GtkWidget -> _void)) (define-gtk gtk_widget_is_focus (_fun _GtkWidget -> _gboolean)) (define-gtk gtk_widget_set_sensitive (_fun _GtkWidget _gboolean -> _void)) +(define-gtk gtk_widget_get_preferred_size (_fun _GtkWidget _GtkRequisition-pointer/null _GtkRequisition-pointer/null -> _void) + #:fail (lambda () #f)) +(define-gtk gtk_widget_get_scale_factor (_fun _GtkWidget -> _int) + #:fail (lambda () (lambda (gtk) 1))) (define-gdk gdk_keyboard_grab (_fun _GdkWindow _gboolean _int -> _void)) (define-gdk gdk_keyboard_ungrab (_fun _int -> _void)) @@ -99,6 +111,7 @@ (define the-accelerator-group (gtk_accel_group_new)) +;; Only for Gtk2 (define-cstruct _GtkWidgetT ([obj _GtkObject] [private_flags _uint16] [state _byte] @@ -110,14 +123,45 @@ [window _GdkWindow] [parent _GtkWidget])) -(define (widget-window gtk) - (GtkWidgetT-window (cast gtk _GtkWidget _GtkWidgetT-pointer))) +(define-gtk widget-window (_fun _GtkWidget -> _GdkWindow) + #:c-id gtk_widget_get_window + #:fail (lambda () + (lambda (gtk) + (GtkWidgetT-window (cast gtk _GtkWidget _GtkWidgetT-pointer))))) -(define (widget-parent gtk) - (GtkWidgetT-parent (cast gtk _GtkWidget _GtkWidgetT-pointer))) +(define-gtk widget-parent (_fun _GtkWidget -> _GdkWindow) + #:c-id gtk_widget_get_parent + #:fail (lambda () + (lambda (gtk) + (GtkWidgetT-parent (cast gtk _GtkWidget _GtkWidgetT-pointer))))) -(define (widget-allocation gtk) - (GtkWidgetT-alloc (cast gtk _GtkWidget _GtkWidgetT-pointer))) +(define-gtk widget-allocation (_fun _GtkWidget (o : (_ptr o _GtkAllocation)) -> _void -> o) + #:c-id gtk_widget_get_allocation + #:fail (lambda () + (lambda (gtk) + (GtkWidgetT-alloc (cast gtk _GtkWidget _GtkWidgetT-pointer))))) + +;; Fallbacks for old Gtk2 versions: +(define ((get-one-flag flag [wrap values]) gtk) + (wrap (positive? (bitwise-and (get-gtk-object-flags gtk) + flag)))) +(define ((set-one-flag! flag) gtk on?) + (define v (get-gtk-object-flags gtk)) + (set-gtk-object-flags! gtk + (if on? + (bitwise-ior v flag) + (bitwise-and v (bitwise-not flag))))) + +(define-gtk gtk_widget_has_focus (_fun _GtkWidget -> _gboolean) + #:fail (lambda () (get-one-flag GTK_HAS_FOCUS))) +(define-gtk gtk_widget_get_mapped (_fun _GtkWidget -> _gboolean) + #:fail (lambda () (get-one-flag GTK_MAPPED))) +(define-gtk gtk_widget_get_has_window (_fun _GtkWidget -> _gboolean) + #:fail (lambda () (get-one-flag GTK_NO_WINDOW not))) +(define-gtk gtk_widget_set_can_default (_fun _GtkWidget _gboolean -> _void) + #:fail (lambda () (set-one-flag! GTK_CAN_DEFAULT))) +(define-gtk gtk_widget_set_can_focus (_fun _GtkWidget _gboolean -> _void) + #:fail (lambda () (set-one-flag! GTK_CAN_FOCUS))) (define-gtk gtk_drag_dest_add_uri_targets (_fun _GtkWidget -> _void)) (define-gtk gtk_drag_dest_set (_fun _GtkWidget _int (_pointer = #f) (_int = 0) _int -> _void)) @@ -532,12 +576,14 @@ (set! client-delta-w dw) (set! client-delta-h dh)) - (define/public (infer-client-delta [w? #t] [h? #t] [sub-h-gtk #f]) + (define/public (infer-client-delta [w? #t] [h? #t] [sub-h-gtk #f] + #:inside [inside-gtk (get-container-gtk)]) (let ([req (make-GtkRequisition 0 0)] [creq (make-GtkRequisition 0 0)] [hreq (make-GtkRequisition 0 0)]) + (when gtk3? (gtk_widget_show gtk)) (gtk_widget_size_request gtk req) - (gtk_widget_size_request (get-container-gtk) creq) + (gtk_widget_size_request inside-gtk creq) (when sub-h-gtk (gtk_widget_size_request sub-h-gtk hreq)) (when w? @@ -548,11 +594,17 @@ (when h? (set! client-delta-h (->normal (- (GtkRequisition-height req) - (GtkRequisition-height creq))))))) + (GtkRequisition-height creq))))) + (when gtk3? (gtk_widget_show gtk)))) (define/public (set-auto-size [dw 0] [dh 0]) (let ([req (make-GtkRequisition 0 0)]) - (gtk_widget_size_request gtk req) + (cond + [gtk3? + (gtk_widget_show gtk) + (gtk_widget_get_preferred_size gtk req #f) + (gtk_widget_hide gtk)] + [else (gtk_widget_size_request gtk req)]) (set-size #f #f (+ (->normal (GtkRequisition-width req)) dw) diff --git a/gui-lib/mred/private/wx/gtk/x11.rkt b/gui-lib/mred/private/wx/gtk/x11.rkt index d069e8ce..2d4d44ab 100644 --- a/gui-lib/mred/private/wx/gtk/x11.rkt +++ b/gui-lib/mred/private/wx/gtk/x11.rkt @@ -5,16 +5,33 @@ "utils.rkt") (provide - (protect-out gdk_pixmap_new + (protect-out define-x11 + + gdk_pixmap_new + gdk_window_get_display gdk_drawable_get_display gdk_drawable_get_visual gdk_x11_drawable_get_xid gdk_x11_display_get_xdisplay gdk_x11_visual_get_xvisual - gdk_x11_screen_get_screen_number)) + gdk_x11_screen_get_screen_number + gdk_x11_window_get_xid + + _Display + _Window + _Pixmap + XCreatePixmap + XCreateSimpleWindow + XDestroyWindow)) + +(define x11-lib (ffi-lib "libX11" '("6" "5" ""))) + +(define-ffi-definer define-x11 x11-lib + #:default-make-fail make-not-available) (define _GdkDrawable _pointer) (define _GdkDisplay (_cpointer 'GdkDisplay)) +(define _GdkWindow (_cpointer 'GdkWindow)) (define _GdkScreen (_cpointer 'GdkScreen)) (define _GdkVisual (_cpointer 'GdkVisual)) (define _GdkPixmap (_cpointer 'GdkPixmap)) @@ -22,15 +39,31 @@ (define _Display (_cpointer 'Display)) (define _Drawable _ulong) +;; This should be `_ulong`, but we use pointers for various +;; reasons, including support for dealloctaors: +(define _Window (_cpointer 'Window)) +(define _Pixmap (_cpointer 'Pixmap)) + (define-gdk gdk_pixmap_new (_fun _GdkDrawable _int _int _int -> _GdkPixmap) - #:wrap (allocator gobject-unref)) - -(define-gdk gdk_drawable_get_display (_fun _GdkDrawable -> _GdkDisplay)) -(define-gdk gdk_drawable_get_visual (_fun _GdkDrawable -> _GdkVisual)) - -(define-gdk gdk_x11_drawable_get_xid (_fun _GdkDrawable -> _Drawable) + #:wrap (allocator gobject-unref) #:make-fail make-not-available) +(define-gdk gdk_drawable_get_display (_fun _GdkDrawable -> _GdkDisplay) + #:make-fail make-not-available) +(define-gdk gdk_window_get_display (_fun _GdkWindow -> _GdkDisplay) + #:make-fail make-not-available) +(define-gdk gdk_drawable_get_visual (_fun _GdkDrawable -> _GdkVisual) + #:make-fail make-not-available) + +(define-gtk gdk_x11_window_get_xid (_fun _GdkWindow -> _Window) + #:make-fail make-not-available) +(define-gdk gdk_x11_drawable_get_xid (_fun _GdkDrawable -> _Drawable) + #:fail (lambda () (lambda (d) + (cast + (gdk_x11_window_get_xid (cast d _GdkDrawable _GdkWindow)) + _pointer + _ulong)))) + (define-gdk gdk_x11_display_get_xdisplay (_fun _GdkDisplay -> _Display) #:make-fail make-not-available) @@ -39,3 +72,26 @@ (define-gdk gdk_x11_screen_get_screen_number (_fun _GdkScreen -> _int) #:make-fail make-not-available) + +(define-x11 XFreePixmap (_fun _Display _Pixmap -> _void)) +(define-x11 XCreatePixmap (_fun _Display _Window _int _int _int -> _Pixmap) + #:wrap (lambda (proc) + (lambda (dpy win w h d) + (((allocator ((deallocator) + (lambda (pixmap) + (XFreePixmap dpy pixmap)))) + (lambda () + (proc dpy win w h d))))))) +(define-x11 XDestroyWindow (_fun _Display _Window -> _void) + #:wrap (deallocator cadr)) +(define-x11 XCreateSimpleWindow (_fun _Display _Window + _int _int _int _int + _int _long _long + -> _Window) + #:wrap (lambda (proc) + (lambda (dpy win x y w h bw b bg) + (((allocator (lambda (win) + (XDestroyWindow dpy win))) + (lambda () + (proc dpy win x y w h bw b bg))))))) + diff --git a/gui-lib/mred/private/wx/platform.rkt b/gui-lib/mred/private/wx/platform.rkt index 8029396a..9c640fd9 100644 --- a/gui-lib/mred/private/wx/platform.rkt +++ b/gui-lib/mred/private/wx/platform.rkt @@ -78,5 +78,6 @@ make-gl-bitmap check-for-break key-symbol-to-menu-key - needs-grow-box-spacer?) + needs-grow-box-spacer? + graphical-system-type) ((dynamic-require platform-lib 'platform-values))) diff --git a/gui-lib/mred/private/wx/win32/procs.rkt b/gui-lib/mred/private/wx/win32/procs.rkt index 8851fb8d..e6234533 100644 --- a/gui-lib/mred/private/wx/win32/procs.rkt +++ b/gui-lib/mred/private/wx/win32/procs.rkt @@ -60,7 +60,8 @@ special-option-key get-color-from-user key-symbol-to-menu-key - needs-grow-box-spacer?) + needs-grow-box-spacer? + graphical-system-type) (define (find-graphical-system-path what) #f) @@ -119,6 +120,8 @@ (define (needs-grow-box-spacer?) #f) +(define (graphical-system-type) 'win32) + (define-user32 GetCursorPos (_wfun (p : (_ptr o _POINT)) -> (r : _BOOL) -> (if r p