1#lang racket/base
2(require ffi/unsafe
3	 ffi/unsafe/define
4         racket/class
5         racket/promise
6         racket/runtime-path
7         racket/draw
8         (for-syntax (only-in racket/base quote))
9         "../../syntax.rkt"
10         "../../lock.rkt"
11         "utils.rkt"
12         "const.rkt"
13         "types.rkt"
14         "window.rkt"
15         "client-window.rkt"
16         "widget.rkt"
17         "cursor.rkt"
18         "pixbuf.rkt"
19	 "resolution.rkt"
20	 "queue.rkt"
21         "../common/queue.rkt")
22
23(provide
24 (protect-out frame%
25              display-origin
26              display-size
27	      display-count
28              display-bitmap-resolution
29              location->window
30              get-current-mouse-state))
31
32;; ----------------------------------------
33
34(define GDK_GRAVITY_NORTH_WEST 1)
35(define GDK_GRAVITY_STATIC 10)
36
37(define _GList (_cpointer/null 'GList))
38(define-glib g_list_insert (_fun _GList _pointer _int -> _GList))
39(define-glib g_list_free (_fun _GList -> _void))
40
41(define-gtk gtk_window_new (_fun _int -> _GtkWidget))
42(define-gtk gtk_window_set_title (_fun _GtkWindow _string -> _void))
43(define-gtk gtk_fixed_new (_fun -> _GtkWidget))
44(define-gtk gtk_fixed_move (_fun _GtkWidget _GtkWidget _int _int -> _void))
45(define-gtk gtk_window_get_size (_fun _GtkWidget (w : (_ptr o _int)) (h : (_ptr o _int))
46                                      -> _void
47                                      -> (values w h)))
48(define-gtk gtk_window_set_decorated (_fun _GtkWidget _gboolean -> _void))
49(define-gtk gtk_window_set_keep_above (_fun _GtkWidget _gboolean -> _void))
50(define-gtk gtk_window_set_focus_on_map (_fun _GtkWidget _gboolean -> _void))
51(define-gtk gtk_window_maximize (_fun _GtkWidget -> _void))
52(define-gtk gtk_window_unmaximize (_fun _GtkWidget -> _void))
53(define-gtk gtk_window_move (_fun _GtkWidget _int _int -> _void))
54(define-gtk gtk_widget_set_uposition (_fun _GtkWidget _int _int -> _void)
55  #:fail (lambda () (lambda (w x y) (gtk_window_move w x y))))
56(define-gtk gtk_window_get_position (_fun _GtkWidget (x : (_ptr o _int)) (y : (_ptr o _int))
57                                          -> _void
58                                          -> (values x y)))
59(define-gtk gtk_window_set_gravity (_fun _GtkWindow _int -> _void))
60(define-gtk gtk_window_set_icon_list (_fun _GtkWindow _GList -> _void))
61(define-gtk gtk_window_fullscreen (_fun _GtkWindow -> _void))
62(define-gtk gtk_window_unfullscreen (_fun _GtkWindow -> _void))
63(define-gtk gtk_window_get_focus (_fun _GtkWindow -> (_or-null _GtkWidget)))
64
65(define-gtk gtk_window_resize (_fun _GtkWidget _int _int -> _void))
66
67(define-gdk gdk_window_set_cursor (_fun _GdkWindow _pointer -> _void))
68(define-gdk gdk_screen_get_root_window (_fun _GdkScreen -> _GdkWindow))
69(define-gdk gdk_screen_get_monitor_scale_factor (_fun _GdkScreen _int -> _int)
70  #:fail (lambda () (lambda (s n) 1)))
71(define-gdk gdk_window_get_pointer (_fun _GdkWindow
72                                         (x : (_ptr o _int))
73                                         (y : (_ptr o _int))
74                                         (mods : (_ptr o _uint))
75                                         -> _GdkWindow
76                                         -> (values x y mods)))
77
78(define-gtk gtk_window_iconify (_fun _GtkWindow -> _void))
79(define-gtk gtk_window_deiconify (_fun _GtkWindow -> _void))
80
81(define-cstruct _GdkGeometry ([min_width _int]
82                              [min_height _int]
83                              [max_width _int]
84                              [max_height _int]
85                              [base_width _int]
86                              [base_height _int]
87                              [width_inc _int]
88                              [height_inc _int]
89                              [min_aspect _double]
90                              [max_aspect _double]
91                              [win_gravity _int]))
92(define-gtk gtk_window_set_geometry_hints (_fun _GtkWindow _pointer _GdkGeometry-pointer _int -> _void))
93(define-gtk gtk_widget_get_allocated_width (_fun _GtkWidget -> _int)
94  #:make-fail make-not-available)
95(define-gtk gtk_widget_get_allocated_height (_fun _GtkWidget -> _int)
96  #:make-fail make-not-available)
97
98(define-gtk gtk_layout_new (_fun (_pointer = #f) (_pointer = #f) -> _GtkWidget))
99(define-gtk gtk_layout_put (_fun _GtkWidget _GtkWidget _int _int -> _void))
100
101(define-signal-handler connect-delete "delete-event"
102  (_fun _GtkWidget -> _gboolean)
103  (lambda (gtk)
104    (let ([wx (gtk->wx gtk)])
105      (when wx
106        (queue-window-event wx (lambda ()
107                                 (unless (other-modal? wx)
108                                   (when (send wx on-close)
109                                     (send wx direct-show #f)))))))))
110
111(define-signal-handler connect-configure "configure-event"
112  (_fun _GtkWidget _GdkEventConfigure-pointer -> _gboolean)
113  (lambda (gtk a)
114    (let ([wx (gtk->wx gtk)])
115      (when wx
116        (define-values (w h) (if gtk3?
117				 (gtk_window_get_size gtk)
118				 (values (GdkEventConfigure-width a)
119					 (GdkEventConfigure-height a))))
120        (send wx remember-size
121              (->normal (GdkEventConfigure-x a))
122              (->normal (GdkEventConfigure-y a))
123              (->normal w)
124              (->normal h))))
125    #f))
126
127(define-cstruct _GdkEventWindowState ([type _int]
128                                      [window _GtkWindow]
129                                      [send_event _int8]
130                                      [changed_mask _int]
131                                      [new_window_state _int]))
132
133
134(define-signal-handler connect-window-state "window-state-event"
135  (_fun _GtkWidget _GdkEventWindowState-pointer -> _gboolean)
136  (lambda (gtk evt)
137    (let ([wx (gtk->wx gtk)])
138      (when wx
139        (send wx on-window-state
140              (GdkEventWindowState-changed_mask evt)
141              (GdkEventWindowState-new_window_state evt))))
142    #f))
143
144(define-runtime-path plt-16x16-file '(lib "icons/plt-icon-16x16.png"))
145(define-runtime-path plt-32x32-file '(lib "icons/plt-icon-32x32.png"))
146(define-runtime-path plt-48x48-file '(lib "icons/plt-icon-48x48.png"))
147
148(define icon-pixbufs+glist
149  (delay
150    (let ([icons (map
151                  (lambda (fn)
152                    (bitmap->pixbuf (make-object bitmap% fn 'png/alpha)))
153                  (list plt-16x16-file
154                        plt-32x32-file
155                        plt-48x48-file))])
156      (cons
157       ;; keep pixbuf pointers to avoid GC:
158       icons
159       ;; a glist:
160       (for/fold ([l #f]) ([i (in-list icons)])
161	 (g_list_insert l i -1))))))
162
163;; used for location->window
164(define all-frames (make-weak-hasheq))
165
166(define frame%
167  (class (client-size-mixin window%)
168    (init parent
169          label
170          x y w h
171          style)
172    (init [is-dialog? #f])
173
174    (inherit get-gtk set-size
175             pre-on-char pre-on-event
176             get-stored-client-delta get-size
177             get-parent get-eventspace
178             adjust-client-delta
179             queue-on-size)
180
181    (define floating? (memq 'float style))
182
183    (define gtk (as-gtk-window-allocation
184                 (gtk_window_new (if floating?
185				     GTK_WINDOW_POPUP
186				     GTK_WINDOW_TOPLEVEL))))
187    (when (memq 'no-caption style)
188      (gtk_window_set_decorated gtk #f))
189    (when floating?
190      (gtk_window_set_keep_above gtk #t)
191      (gtk_window_set_focus_on_map gtk #f))
192    (define-values (vbox-gtk layout-gtk panel-gtk)
193      (atomically
194       (let ([vbox-gtk (gtk_vbox_new #f 0)]
195             [layout-gtk (and gtk3? (gtk_layout_new))]
196             [panel-gtk (gtk_fixed_new)])
197         (gtk_container_add gtk vbox-gtk)
198         (gtk_box_pack_end vbox-gtk (or layout-gtk panel-gtk) #t #t 0)
199	 (when layout-gtk
200	   (gtk_layout_put layout-gtk panel-gtk 0 0))
201         (values vbox-gtk layout-gtk panel-gtk))))
202    (gtk_widget_show vbox-gtk)
203    (when layout-gtk (gtk_widget_show layout-gtk))
204    (gtk_widget_show panel-gtk)
205    (connect-enter-and-leave gtk)
206
207    ;; Enable key events on the panel to catch events
208    ;; that would otherwise go undelivered:
209    (gtk_widget_set_can_focus panel-gtk #t)
210    (gtk_widget_add_events panel-gtk (bitwise-ior GDK_KEY_PRESS_MASK
211						  GDK_KEY_RELEASE_MASK))
212    (connect-key panel-gtk)
213
214    (unless is-dialog?
215      (gtk_window_set_icon_list gtk (cdr (force icon-pixbufs+glist))))
216
217    (define/override (get-client-gtk) panel-gtk)
218    (define/override (get-window-gtk) gtk)
219
220    (define/override (in-floating?) floating?)
221
222    (super-new [parent parent]
223               [gtk gtk]
224               [client-gtk panel-gtk]
225               [no-show? #t]
226               [add-to-parent? #f]
227               [extra-gtks (list panel-gtk)]
228               [connect-size-allocate? #f])
229
230    (set-size x y w h)
231
232    (when (memq 'hide-menu-bar style)
233      (gtk_window_fullscreen gtk))
234
235    (connect-delete gtk)
236    (connect-configure gtk)
237    (connect-focus gtk)
238    (connect-window-state gtk)
239
240    (define saved-title (or label ""))
241    (define is-modified? #f)
242
243    (when label
244      (gtk_window_set_title gtk label))
245
246    ;(gtk_window_add_accel_group (widget-window gtk) the-accelerator-group)
247
248    (define/override (set-child-size child-gtk x y w h)
249      (gtk_fixed_move panel-gtk child-gtk (->screen x) (->screen y))
250      ;; gtk3: we expect a panel in a frame to be always visible, so
251      ;; this size request should work
252      (avoid-preferred-size-warning child-gtk)
253      (gtk_widget_set_size_request child-gtk (->screen w) (->screen h)))
254
255    (define/public (on-close) #t)
256
257    (define/public (set-menu-bar mb)
258      (let ([mb-gtk (send mb get-gtk)])
259	(gtk_box_pack_start vbox-gtk mb-gtk #f #f 0)
260        (gtk_widget_show mb-gtk))
261      (let ([h (send mb set-top-window this)])
262        ;; adjust client delta right away, so that we make
263        ;; better assumptions about the client size and more
264        ;; quickly converge to the right size of the frame
265        ;; based on its content
266        (adjust-client-delta 0 h))
267      ;; Hack: calls back into the mred layer to re-compute
268      ;;  sizes. By calling this early enough, the frame won't
269      ;;  grow if it doesn't have to grow to accommodate the menu bar.
270      (send this resized))
271
272    (define/public (reset-menu-height h)
273      (adjust-client-delta 0 h))
274
275    (define saved-enforcements (vector 0 0 -1 -1))
276
277    (define/public (enforce-size min-x min-y max-x max-y inc-x inc-y)
278      (define (to-max v) (if (= v -1) #x3FFFFF (->screen v)))
279      (set! saved-enforcements (vector min-x min-y max-x max-y))
280      (define-values (dx dy)
281	(if wayland?
282	    ;; Hints work at a layer of geometry below some offset that
283	    ;; `gtk_window_get_size` works but above where allocations
284	    ;; work:
285	    (let-values ([(w h) (gtk_window_get_size gtk)])
286	      (values (- (gtk_widget_get_allocated_width gtk) w)
287		      (- (gtk_widget_get_allocated_height gtk) h)))
288	    (values 0 0)))
289      (gtk_window_set_geometry_hints gtk #f
290                                     (make-GdkGeometry (->screen min-x) (->screen min-y)
291                                                       (+ dx (to-max max-x)) (+ dy (to-max max-y))
292                                                       0 0
293                                                       (->screen inc-x) (->screen inc-y)
294                                                       0.0 0.0
295                                                       0)
296                                     (bitwise-ior GDK_HINT_MIN_SIZE
297                                                  GDK_HINT_MAX_SIZE
298                                                  GDK_HINT_RESIZE_INC)))
299
300    (define/override (get-top-win) this)
301
302    (define dc-lock (and (eq? 'windows (system-type)) (make-semaphore 1)))
303    (define/public (get-dc-lock) dc-lock)
304
305    (define/override (get-dialog-level) 0)
306    (define/public (frame-relative-dialog-status win) #f)
307
308    (define/override (get-unset-pos) #f)
309
310    (define/override (center dir wrt)
311      (let ([w-box (box 0)]
312            [h-box (box 0)]
313            [sx-box (box 0)]
314            [sy-box (box 0)]
315            [sw-box (box 0)]
316            [sh-box (box 0)])
317        (get-size w-box h-box)
318        (let ([p (get-parent)])
319          (if p
320              (begin
321                (send p get-size sw-box sh-box)
322                (set-box! sx-box (send p get-x))
323                (set-box! sy-box (send p get-y)))
324              (display-size sw-box sh-box #t 0 void)))
325        (let* ([sw (unbox sw-box)]
326               [sh (unbox sh-box)]
327               [fw (unbox w-box)]
328               [fh (unbox h-box)])
329          (set-top-position (if (or (eq? dir 'both)
330                                    (eq? dir 'horizontal))
331                                (+ (unbox sx-box) (quotient (- sw fw) 2))
332                                #f)
333                            (if (or (eq? dir 'both)
334                                    (eq? dir 'vertical))
335                                (+ (unbox sy-box) (quotient (- sh fh) 2))
336                                #f)))))
337
338    (define/public (set-top-position x y)
339      (unless (and (not x) (not y))
340        (gtk_widget_set_uposition gtk
341                                  (or (and x (->screen x)) -2)
342                                  (or (and y (->screen y)) -2))))
343
344    (define/override (really-set-size gtk x y processed-x processed-y w h)
345      (set-top-position x y)
346      (gtk_window_resize gtk (max 1 (->screen w)) (max 1 (->screen h))))
347
348    (define/override (show on?)
349      (let ([es (get-eventspace)])
350        (when (and on?
351                   (eventspace-shutdown? es))
352          (error (string->symbol
353                  (format "show method in ~a"
354                          (if (frame-relative-dialog-status this)
355                              'dialog%
356                              'frame%)))
357                 "eventspace has been shutdown")
358          (when saved-child
359            (if (eq? (current-thread) (eventspace-handler-thread es))
360                (send saved-child paint-children)
361                (let ([s (make-semaphore)])
362                  (queue-callback (lambda ()
363                                    (when saved-child
364                                      (send saved-child paint-children))
365                                    (semaphore-post s)))
366                  (sync/timeout 1 s))))))
367      (super show on?))
368
369    (define saved-child #f)
370    (define/override (register-child child on?)
371      (unless on? (error 'register-child-in-frame "did not expect #f"))
372      (unless (or (not saved-child) (eq? child saved-child))
373        (error 'register-child-in-frame "expected only one child"))
374      (set! saved-child child))
375    (define/override (register-child-in-parent on?)
376      (void))
377
378    (define/override (refresh-all-children)
379      (when saved-child
380        (send saved-child refresh)))
381
382    (define/override (direct-show on?)
383      ;; atomic mode
384      (if on?
385          (hash-set! all-frames this #t)
386          (hash-remove! all-frames this))
387      (super direct-show on?)
388      (when on? (gtk_window_deiconify gtk))
389      (register-frame-shown this on?))
390
391    (define/public (destroy)
392      ;; atomic mode
393      (direct-show #f))
394
395    (define/override (on-client-size w h)
396      (void))
397
398    (define/augment (is-enabled-to-root?) #t)
399
400    (define big-icon #f)
401    (define small-icon #f)
402    (define/public (set-icon bm [mask #f] [mode 'both])
403      (let ([bm (if mask
404		    (let* ([nbm (make-object bitmap%
405					     (send bm get-width)
406					     (send bm get-height)
407					     #f
408					     #t)]
409			   [dc (make-object bitmap-dc% nbm)])
410		      (send dc draw-bitmap bm 0 0
411			    'solid (make-object color% "black")
412			    mask)
413		      (send dc set-bitmap #f)
414		      nbm)
415		    bm)])
416	(case mode
417	  [(small) (set! small-icon bm)]
418	  [(big) (set! big-icon bm)]
419	  [(both)
420	   (set! small-icon bm)
421	   (set! big-icon bm)])
422	(let ([small-pixbuf
423	       (if small-icon
424		   (bitmap->pixbuf small-icon)
425		   (car (car (force icon-pixbufs+glist))))]
426	      [big-pixbufs
427	       (if big-icon
428		   (list (bitmap->pixbuf big-icon))
429		   (cdr (car (force icon-pixbufs+glist))))])
430          (atomically
431           (let ([l (for/fold ([l #f]) ([i (cons small-pixbuf big-pixbufs)])
432                      (g_list_insert l i -1))])
433             (gtk_window_set_icon_list gtk l)
434             (g_list_free l))))))
435
436    (define child-has-focus? #f)
437    (define reported-activate #f)
438    (define queued-active? #f)
439    (define/public (on-focus-child on?)
440      ;; atomic mode
441      (set! child-has-focus? on?)
442      (unless queued-active?
443	(set! queued-active? #t)
444	(queue-window-event this
445			    (lambda ()
446			      (let ([on? child-has-focus?])
447				(set! queued-active? #f)
448				(unless (eq? on? reported-activate)
449				  (set! reported-activate on?)
450				  (on-activate on?)))))))
451
452    (define treat-focus-out-as-menu-click? #f)
453    (define/public (treat-focus-out-as-menu-click)
454      (set! treat-focus-out-as-menu-click? #t))
455
456    (define focus-here? #f)
457    (define/override (on-focus? on?)
458      (when (and (not on?) treat-focus-out-as-menu-click?)
459        (on-menu-click))
460      (on-focus-child on?)
461      (cond
462       [on?
463	(if (ptr-equal? (gtk_window_get_focus gtk) gtk)
464	    (begin
465	      (set! focus-here? #t)
466	      (super on-focus? on?))
467	    #f)]
468       [focus-here?
469	(set! focus-here? #f)
470	(super on-focus? on?)]
471       [else #f]))
472
473    (define/public (get-focus-window [even-if-not-active? #f])
474      (let ([f-gtk (gtk_window_get_focus gtk)])
475        (and f-gtk
476             (or even-if-not-active?
477		 (gtk_widget_has_focus f-gtk))
478             (gtk->wx f-gtk))))
479
480    (define/override (call-pre-on-event w e)
481      (pre-on-event w e))
482    (define/override (call-pre-on-char w e)
483      (pre-on-char w e))
484
485    (define/override (internal-client-to-screen x y)
486      (gtk_window_set_gravity gtk GDK_GRAVITY_STATIC)
487      (let-values ([(dx dy) (gtk_window_get_position gtk)]
488                   [(cdx cdy) (get-stored-client-delta)])
489        (gtk_window_set_gravity gtk GDK_GRAVITY_NORTH_WEST)
490        (set-box! x (+ (unbox x) (->normal (+ dx cdx))))
491        (set-box! y (+ (unbox y) (->normal (+ dy cdy))))))
492
493    (define/public (on-toolbar-click) (void))
494    (define/public (on-menu-click) (void))
495
496    (define/public (on-menu-command c) (void))
497
498    (def/public-unimplemented on-mdi-activate)
499
500    (define/public (on-activate on?) (void))
501
502    (define/public (designate-root-frame) (void))
503
504    (def/public-unimplemented system-menu)
505
506    (define/public (set-modified mod?)
507      (unless (eq? is-modified? (and mod? #t))
508        (set! is-modified? (and mod? #t))
509        (set-title saved-title)))
510
511    (define waiting-cursor? #f)
512    (define/public (set-wait-cursor-mode on?)
513      (set! waiting-cursor? on?)
514      (when in-window
515        (send in-window enter-window)))
516
517    (define current-cursor-handle #f)
518    (define in-window #f)
519    (define/override (set-parent-window-cursor in-win c)
520      (set! in-window in-win)
521      (let ([c (if waiting-cursor?
522                   (get-watch-cursor-handle)
523                   c)])
524        (unless (eq? c current-cursor-handle)
525          (atomically
526           (set! current-cursor-handle c)
527           (gdk_window_set_cursor (widget-window (get-gtk)) (if (eq? c (get-arrow-cursor-handle))
528                                                                #f
529                                                                c))))))
530    (define/override (enter-window) (void))
531    (define/override (leave-window) (void))
532
533    (define/override (check-window-cursor win)
534      (when in-window
535        (send in-window enter-window)))
536
537    (define maximized? #f)
538    (define is-iconized? #f)
539    (define fullscreen? #f)
540
541    (define/public (is-maximized?)
542      maximized?)
543    (define/public (maximize on?)
544      ((if on? gtk_window_maximize gtk_window_unmaximize) gtk))
545
546    (define/public (on-window-state changed value)
547      (when (positive? (bitwise-and changed GDK_WINDOW_STATE_MAXIMIZED))
548        (set! maximized? (positive? (bitwise-and value GDK_WINDOW_STATE_MAXIMIZED))))
549      (when (positive? (bitwise-and changed GDK_WINDOW_STATE_FULLSCREEN))
550	(set! fullscreen? (positive? (bitwise-and value GDK_WINDOW_STATE_FULLSCREEN))))
551      (when (positive? (bitwise-and changed GDK_WINDOW_STATE_ICONIFIED))
552        (set! is-iconized? (positive? (bitwise-and value GDK_WINDOW_STATE_ICONIFIED)))))
553
554    (define/public (iconized?)
555      is-iconized?)
556    (define/public (iconize on?)
557      (if on?
558          (gtk_window_iconify gtk)
559          (gtk_window_deiconify gtk)))
560
561    (define/public (fullscreened?)
562      fullscreen?)
563    (define/public (fullscreen on?)
564      (if on?
565	  (gtk_window_fullscreen gtk)
566	  (gtk_window_unfullscreen gtk)))
567
568    (def/public-unimplemented get-menu-bar)
569
570    (define/public (set-title s)
571      (set! saved-title s)
572      (gtk_window_set_title gtk (if is-modified?
573                                    (string-append s "*")
574                                    s)))
575
576    (define/public (display-changed) (void))))
577
578;; ----------------------------------------
579
580(define-gdk gdk_screen_get_width (_fun _GdkScreen -> _int))
581(define-gdk gdk_screen_get_height (_fun _GdkScreen -> _int))
582
583(define-gdk gdk_screen_get_monitor_geometry (_fun _GdkScreen _int _GdkRectangle-pointer -> _void))
584(define-gdk gdk_screen_get_n_monitors (_fun _GdkScreen -> _int))
585
586(define (monitor-rect num fail)
587  (let ([s (gdk_screen_get_default)]
588	[r (make-GdkRectangle 0 0 0 0)])
589    (unless (num . < . (gdk_screen_get_n_monitors s))
590      (fail))
591    (gdk_screen_get_monitor_geometry s num r)
592    r))
593
594(define (display-origin x y all? num fail)
595  (let ([r (monitor-rect num fail)])
596    (set-box! x (->normal (- (GdkRectangle-x r))))
597    (set-box! y (->normal (- (GdkRectangle-y r))))))
598
599(define (display-size w h all? num fail)
600  (let ([r (monitor-rect num fail)])
601    (set-box! w (->normal (GdkRectangle-width r)))
602    (set-box! h (->normal (GdkRectangle-height r)))))
603
604(define (display-count)
605  (gdk_screen_get_n_monitors (gdk_screen_get_default)))
606
607(define (display-bitmap-resolution num fail)
608  (define (get) (* (or (get-interface-scale-factor num)
609		       1.0)
610		   (gdk_screen_get_monitor_scale_factor
611		    (gdk_screen_get_default)
612		    num)))
613  (if (zero? num)
614      (get)
615      (if (num . < . (gdk_screen_get_n_monitors (gdk_screen_get_default)))
616          (get)
617          (fail))))
618
619(define (location->window x y)
620  (for/or ([f (in-hash-keys all-frames)])
621    (let ([fx (send f get-x)]
622          [fw (send f get-width)])
623      (and (<= fx x (+ fx fw))
624           (let ([fy (send f get-y)]
625                 [fh (send f get-height)])
626             (<= fy y (+ fy fh)))
627           f))))
628
629;; ----------------------------------------
630
631(define (get-current-mouse-state)
632  (define-values (x y mods) (gdk_window_get_pointer
633                             (gdk_screen_get_root_window
634                              (gdk_screen_get_default))))
635  (define (maybe mask sym)
636    (if (zero? (bitwise-and mods mask))
637        null
638        (list sym)))
639  (values (make-object point% x y)
640          (append
641           (maybe GDK_BUTTON1_MASK 'left)
642           (maybe GDK_BUTTON2_MASK 'middle)
643           (maybe GDK_BUTTON3_MASK 'right)
644           (maybe GDK_SHIFT_MASK 'shift)
645           (maybe GDK_LOCK_MASK 'caps)
646           (maybe GDK_CONTROL_MASK 'control)
647           (maybe GDK_MOD1_MASK 'alt)
648           (maybe GDK_META_MASK 'meta))))
649
650(define (tell-all-frames-signal-changed n)
651  (define frames (for/list ([f (in-hash-keys all-frames)]) f))
652  (for ([f (in-hash-keys all-frames)])
653    (define e (send f get-eventspace))
654    (unless (eventspace-shutdown? e)
655      (parameterize ([current-eventspace e])
656        (queue-callback
657         (λ ()
658           (send f display-changed)))))))
659
660(define-signal-handler
661  connect-monitor-changed-signal
662  "monitors-changed"
663  (_fun _GdkScreen -> _void)
664  (λ (screen) (tell-all-frames-signal-changed 1)))
665
666(define-signal-handler
667  connect-size-changed-signal
668  "size-changed"
669  (_fun _GdkScreen -> _void)
670  (λ (screen) (tell-all-frames-signal-changed 2)))
671
672(define-signal-handler
673  connect-composited-changed-signal
674  "composited-changed"
675  (_fun _GdkScreen -> _void)
676  (λ (screen) (tell-all-frames-signal-changed 3)))
677
678(define (screen-size-signal-connect connect-signal)
679  (void (connect-signal (cast (gdk_screen_get_default) _GdkScreen _GtkWidget))))
680(screen-size-signal-connect connect-monitor-changed-signal)
681(screen-size-signal-connect connect-size-changed-signal)
682(screen-size-signal-connect connect-composited-changed-signal)
683