diff --git a/gui-lib/mred/private/wx/gtk/canvas.rkt b/gui-lib/mred/private/wx/gtk/canvas.rkt index 1607721b..378d0f22 100644 --- a/gui-lib/mred/private/wx/gtk/canvas.rkt +++ b/gui-lib/mred/private/wx/gtk/canvas.rkt @@ -17,6 +17,7 @@ "const.rkt" "types.rkt" "window.rkt" + "queue.rkt" "client-window.rkt" "widget.rkt" "dc.rkt" @@ -613,7 +614,7 @@ ;; A transparent canvas can't have a native window, so we ;; need to release any freezes befre the window implementation ;; might change. - (when transparentish? (unrealize))) + (when (or transparentish? wayland?) (unrealize))) (define/public (begin-refresh-sequence) (send dc suspend-flush)) diff --git a/gui-lib/mred/private/wx/gtk/dc.rkt b/gui-lib/mred/private/wx/gtk/dc.rkt index 49cc1222..45e8ca85 100644 --- a/gui-lib/mred/private/wx/gtk/dc.rkt +++ b/gui-lib/mred/private/wx/gtk/dc.rkt @@ -4,6 +4,7 @@ racket/class "utils.rkt" "types.rkt" + "queue.rkt" "window.rkt" "frame.rkt" "x11.rkt" @@ -195,9 +196,11 @@ (define/override (make-backing-bitmap w h) (cond [(and (not is-transparentish?) + (not wayland?) (eq? 'unix (system-type))) (make-object x11-bitmap% w h (send canvas get-client-gtk))] [(and (not is-transparentish?) + (not wayland?) (eq? 'windows (system-type))) (make-object win32-bitmap% w h (widget-window (send canvas get-client-gtk)))] [else diff --git a/gui-lib/mred/private/wx/gtk/frame.rkt b/gui-lib/mred/private/wx/gtk/frame.rkt index 18750e0c..9e6f3160 100644 --- a/gui-lib/mred/private/wx/gtk/frame.rkt +++ b/gui-lib/mred/private/wx/gtk/frame.rkt @@ -16,6 +16,7 @@ "cursor.rkt" "pixbuf.rkt" "resolution.rkt" + "queue.rkt" "../common/queue.rkt") (provide @@ -88,6 +89,8 @@ [max_aspect _double] [win_gravity _int])) (define-gtk gtk_window_set_geometry_hints (_fun _GtkWindow _GtkWidget _GdkGeometry-pointer _int -> _void)) +(define-gtk gtk_widget_get_allocated_width (_fun _GtkWidget -> _int)) +(define-gtk gtk_widget_get_allocated_height (_fun _GtkWidget -> _int)) (define-gtk gtk_layout_new (_fun (_pointer = #f) (_pointer = #f) -> _GtkWidget)) (define-gtk gtk_layout_put (_fun _GtkWidget _GtkWidget _int _int -> _void)) @@ -107,11 +110,15 @@ (lambda (gtk a) (let ([wx (gtk->wx gtk)]) (when wx + (define-values (w h) (if gtk3? + (gtk_window_get_size gtk) + (values (GdkEventConfigure-width a) + (GdkEventConfigure-height a)))) (send wx remember-size (->normal (GdkEventConfigure-x a)) (->normal (GdkEventConfigure-y a)) - (->normal (GdkEventConfigure-width a)) - (->normal (GdkEventConfigure-height a))))) + (->normal w) + (->normal h)))) #f)) (define-cstruct _GdkEventWindowState ([type _int] @@ -266,9 +273,18 @@ (define/public (enforce-size min-x min-y max-x max-y inc-x inc-y) (define (to-max v) (if (= v -1) #x3FFFFF (->screen v))) (set! saved-enforcements (vector min-x min-y max-x max-y)) + (define-values (dx dy) + (if wayland? + ;; Hints work at a layer of geometry below some offset that + ;; `gtk_window_get_size` works but above where allocations + ;; work: + (let-values ([(w h) (gtk_window_get_size gtk)]) + (values (- (gtk_widget_get_allocated_width gtk) w) + (- (gtk_widget_get_allocated_height gtk) h))) + (values 0 0))) (gtk_window_set_geometry_hints gtk gtk (make-GdkGeometry (->screen min-x) (->screen min-y) - (to-max max-x) (to-max max-y) + (+ dx (to-max max-x)) (+ dy (to-max max-y)) 0 0 (->screen inc-x) (->screen inc-y) 0.0 0.0 diff --git a/gui-lib/mred/private/wx/gtk/gcwin.rkt b/gui-lib/mred/private/wx/gtk/gcwin.rkt index 87dbcfa3..94395723 100644 --- a/gui-lib/mred/private/wx/gtk/gcwin.rkt +++ b/gui-lib/mred/private/wx/gtk/gcwin.rkt @@ -6,6 +6,7 @@ "utils.rkt" "types.rkt" "window.rkt" + "queue.rkt" "pixbuf.rkt" "x11.rkt") @@ -19,7 +20,7 @@ bitmap->gc-bitmap)) ;; Gtk2, only: -(define-cstruct _GdkWindowAttr +(define-cstruct _GdkWindowAttr2 ([title _string] [event_mask _int] [x _int] @@ -36,6 +37,29 @@ [override_redirect _gboolean] [type_hint _int])) +;; Gtk3, only: +(define-cstruct _GdkWindowAttr3 + ([title _string] + [event_mask _int] + [x _int] + [y _int] + [width _int] + [height _int] + [wclass _int] ; GDK_INPUT_OUTPUT + [visual _pointer] + [window_type _int] ; GDK_WINDOW_CHILD + [cursor _pointer] + [wmclass_name _string] + [wmclass_class _string] + [override_redirect _gboolean] + [type_hint _int])) + +(define make-GdkWindowAttr + (if gtk3? + (lambda (t e x y w h wc vis cm wt c wmc_n wmc_c o th) + (make-GdkWindowAttr3 t e x y w h wc vis wt c wmc_n wmc_c o th)) + make-GdkWindowAttr2)) + (define << arithmetic-shift) (define GDK_WA_TITLE (1 . << . 1)) @@ -52,12 +76,19 @@ (define GDK_WINDOW_CHILD 2) -(define-gdk gdk_window_new (_fun _GdkWindow _GdkWindowAttr-pointer _uint -> _GdkWindow)) +(define-gdk gdk_window_new (_fun _GdkWindow + (if gtk3? + _GdkWindowAttr3-pointer + _GdkWindowAttr2-pointer) + _uint -> _GdkWindow)) -(define-gdk gdk_window_show _fpointer) +(define-gdk gdk_window_show-p _fpointer + #:c-id gdk_window_show) (define-gdk gdk_window_hide _fpointer) (define-gdk gdk_display_flush _fpointer) +(define-gdk gdk_window_show (_fun _GdkWindow -> _void)) + ;; Gtk2 (define-gdk gdk_draw_pixbuf _fpointer #:make-fail make-not-available) @@ -69,9 +100,11 @@ (define-x11 XMapRaised _fpointer #:fail (lambda () #f)) (define-x11 XUnmapWindow _fpointer #:fail (lambda () #f)) +(define use-x11? (and gtk3? (not wayland?))) + (define (bitmap->gc-bitmap bm client-gtk) (cond - [gtk3? + [use-x11? ; Generate an X11 Pixmap (define gwin (widget-window client-gtk)) (define display (gdk_x11_display_get_xdisplay (gdk_window_get_display gwin))) @@ -109,7 +142,7 @@ (define (create-gc-window client-gtk x y w h) (define cwin (widget-window client-gtk)) (cond - [gtk3? + [use-x11? ;; 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)) @@ -132,51 +165,61 @@ (define (free-gc-window win) (cond - [gtk3? (XDestroyWindow (car win) (cdr win))] + [use-x11? (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)])) + [use-x11? (vector + (vector 'ptr_ptr_ptr->void + XSetWindowBackgroundPixmap + (car win) + (cdr win) + gc-bitmap))] + [gtk3? (vector)] + [else (vector + (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)) + (vector + (vector 'ptr_ptr_ptr->void gdk_display_flush (gdk_display_get_default) #f #f))) + +(define (vector* . l) + (for*/vector ([v (in-list l)] [e (in-vector v)]) e)) (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) + [use-x11? (vector* + (make-draw win gc-bitmap w h) + (vector + (vector 'ptr_ptr_ptr->void + XMapRaised + (car win) + (cdr win) + #f)) + (make-flush))] + [else (vector* + (vector + (vector 'ptr_ptr_ptr->void gdk_window_show-p win #f #f)) (make-draw win gc-bitmap w h) (make-flush))])) (define (make-gc-hide-desc win gc-bitmap w h) - (vector + (vector* ;; draw the ``off'' bitmap so we can flush immediately (make-draw win gc-bitmap w h) (make-flush) - ;; hide the window; it may take a while for the underlying canvas - ;; to refresh: - (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)))) + (vector + ;; hide the window; it may take a while for the underlying canvas + ;; to refresh: + (if use-x11? + (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/procs.rkt b/gui-lib/mred/private/wx/gtk/procs.rkt index db6bd448..bf8ab4f8 100644 --- a/gui-lib/mred/private/wx/gtk/procs.rkt +++ b/gui-lib/mred/private/wx/gtk/procs.rkt @@ -156,9 +156,10 @@ (define/top (make-screen-bitmap [exact-positive-integer? w] [exact-positive-integer? h]) - (if (eq? 'unix (system-type)) + (if (and (eq? 'unix (system-type)) + (not wayland?)) (make-object x11-bitmap% w h #f) - (make-object bitmap% w h #f #t))) + (make-object bitmap% w h #f #t (display-bitmap-resolution 0 (lambda () 1.0))))) (define/top (make-gl-bitmap [exact-positive-integer? w] [exact-positive-integer? h] diff --git a/gui-lib/mred/private/wx/gtk/queue.rkt b/gui-lib/mred/private/wx/gtk/queue.rkt index 8c4e0c71..9cf5ee3f 100644 --- a/gui-lib/mred/private/wx/gtk/queue.rkt +++ b/gui-lib/mred/private/wx/gtk/queue.rkt @@ -16,6 +16,7 @@ try-to-sync-refresh set-widget-hook! x11-display) + wayland? ;; from common/queue: current-eventspace queue-event @@ -90,6 +91,19 @@ (gdk_set_program_class (cast v _pointer _string)))) display)))) + +;; ---------------------------------------- +;; Check for Wayland vs. X11 + +(define-gdk gdk_display_get_default (_fun -> _GdkDisplay)) +(define-gdk gdk_display_get_name (_fun _GdkDisplay -> _string)) + +(define wayland? + (and gtk3? + (regexp-match? #rx"^wayland" + (gdk_display_get_name + (gdk_display_get_default))))) + ;; ------------------------------------------------------------ ;; Gtk event pump diff --git a/gui-lib/mred/private/wx/gtk/window.rkt b/gui-lib/mred/private/wx/gtk/window.rkt index 03624193..8d0ee892 100644 --- a/gui-lib/mred/private/wx/gtk/window.rkt +++ b/gui-lib/mred/private/wx/gtk/window.rkt @@ -916,7 +916,7 @@ ;; windows; that means we have to be extra careful that ;; the underlying window doesn't change while a freeze is ;; in effect; the `reset-child-freezes` helps with that. - (unless (and transparentish? gtk3?) + (unless (or (and transparentish? gtk3?) wayland?) (gdk_window_ensure_native win)) (begin (gdk_window_freeze_updates win)