(module wxwindow mzscheme (require mzlib/class mzlib/class100 (prefix wx: "kernel.ss") "lock.ss" "helper.ss" "wx.ss") (provide (protect wx-make-window% make-window-glue%)) (define wx-make-window% (lambda (% top?) (class100 % args (inherit is-shown-to-root? is-enabled-to-root?) (private-field [top-level #f] [focus? #f] [container this] [visible? #f] [active? #f] [skip-sub-events? #f]) (public [on-visible (lambda () (let ([vis? (is-shown-to-root?)]) (unless (eq? vis? visible?) (set! visible? vis?) (unless skip-sub-events? (as-exit (lambda () (send (wx->proxy this) on-superwindow-show vis?)))))))] [queue-visible (lambda () (parameterize ([wx:current-eventspace (send (get-top-level) get-eventspace)]) (wx:queue-callback (entry-point (lambda () (on-visible))) wx:middle-queue-key)))] [skip-subwindow-events? (case-lambda [() skip-sub-events?] [(skip?) (set! skip-sub-events? skip?)])]) (public [on-active (lambda () (let ([act? (is-enabled-to-root?)]) (unless (eq? act? active?) (set! active? act?) (unless skip-sub-events? (as-exit (lambda () (send (wx->proxy this) on-superwindow-enable act?)))))))] [queue-active (lambda () (parameterize ([wx:current-eventspace (send (get-top-level) get-eventspace)]) (wx:queue-callback (entry-point (lambda () (on-active))) wx:middle-queue-key)))] ;; Needed for radio boxes: [orig-enable (lambda args (super-enable . args))]) (rename [super-enable enable]) (private-field [can-accept-drag? #f] [fake-shown? #f]) (public [accept-drag? (lambda () can-accept-drag?)] [get-container (lambda () container)] [set-container (lambda (c) (set! container c))] [get-window (lambda () this)] [tabbing-position (lambda (x y w h) (list this x y w h))] [has-tabbing-children? (lambda () #f)] [dx (lambda () 0)] [dy (lambda () 0)] [ext-dx (lambda () (dx))] [ext-dy (lambda () (dy))] [handles-key-code (lambda (x alpha? meta?) #f)] [char-to (lambda () (void))] [get-top-level (lambda () (unless top-level (let loop ([window this]) (cond [(or (is-a? window wx:frame%) (is-a? window wx:dialog%)) (set! top-level window)] [else (loop (send window get-parent))]))) top-level)]) (public [really-show (lambda (on?) (set! fake-shown? #f) (super show on?))] [fake-show (lambda (on?) (set! fake-shown? on?))]) (override [show (lambda (on?) (queue-visible) (send (get-top-level) show-control this on?))] [is-shown? (lambda () (or fake-shown? (super is-shown?)))] [enable (lambda (on?) (queue-active) (super enable on?))] [drag-accept-files (lambda (on?) (set! can-accept-drag? (and on? #t)) (super drag-accept-files on?))] [on-set-focus (entry-point (lambda () (send (get-top-level) set-focus-window this) (set! focus? #t) (as-exit (lambda () (super on-set-focus)))))] [on-kill-focus (entry-point (lambda () (send (get-top-level) set-focus-window #f) (set! focus? #f) (as-exit (lambda () (super on-kill-focus)))))]) (public [has-focus? (lambda () focus?)]) (sequence (apply super-init args) (unless top? (set! visible? (is-shown-to-root?)) (set! active? (is-enabled-to-root?))))))) (define (make-window-glue% %) ; implies make-glue% (class100 (make-glue% %) (mred proxy . args) (inherit get-x get-y get-width get-height area-parent get-mred get-proxy skip-subwindow-events?) (private-field [pre-wx->proxy (lambda (orig-w e k) ;; MacOS: w may not be something the user knows ;; Look for a parent, and shift coordinates (let loop ([w orig-w]) (if w (if (is-a? w wx/proxy<%>) (if (eq? w orig-w) (k (wx->proxy w) e) (let ([bx (box (send e get-x))] [by (box (send e get-y))]) (send orig-w client-to-screen bx by) (send w screen-to-client bx by) (let ([new-e (if (e . is-a? . wx:key-event%) (instantiate wx:key-event% () [key-code (send e get-key-code)]) (instantiate wx:mouse-event% () [event-type (send e get-event-type)] [left-down (send e get-left-down)] [right-down (send e get-right-down)] [middle-down (send e get-middle-down)]))]) (when (e . is-a? . wx:key-event%) (send new-e set-key-release-code (send e get-key-release-code))) (send new-e set-time-stamp (send e get-time-stamp)) (send new-e set-alt-down (send e get-alt-down)) (send new-e set-control-down (send e get-control-down)) (send new-e set-meta-down (send e get-meta-down)) (send new-e set-shift-down (send e get-shift-down)) (send new-e set-x (unbox bx)) (send new-e set-y (unbox by)) (k (wx->proxy w) new-e)))) (loop (send w get-parent))) #f)))] [old-w -1] [old-h -1] [old-x -1] [old-y -1]) (override [on-drop-file (entry-point (lambda (f) (as-exit (lambda () (send (get-proxy) on-drop-file f)))))] [on-size (lambda (bad-w bad-h) (super on-size bad-w bad-h) ;; Delay callback to make sure X structures (position) are updated, first. ;; Also, Windows needs a trampoline. (queue-window-callback this (entry-point (lambda () (let ([mred (get-mred)]) (when mred (let* ([w (get-width)] [h (get-height)]) (when (not (and (= w old-w) (= h old-h))) (set! old-w w) (set! old-h h) (as-exit (lambda () (send mred on-size w h))))) (let* ([p (area-parent)] [x (- (get-x) (or (and p (send p dx)) 0))] [y (- (get-y) (or (and p (send p dy)) 0))]) (when (not (and (= x old-x) (= y old-y))) (set! old-x x) (set! old-y y) (as-exit (lambda () (send mred on-move x y)))))))))))] [on-set-focus (entry-point (lambda () ; Windows circumvents the event queue to call on-focus ; when you click on the window's icon in the task bar. (queue-window-callback this (lambda () (send (get-proxy) on-focus #t))) (as-exit (lambda () (super on-set-focus)))))] [on-kill-focus (entry-point (lambda () ; see on-set-focus: (queue-window-callback this (lambda () (send (get-proxy) on-focus #f))) (as-exit (lambda () (super on-kill-focus)))))] [pre-on-char (lambda (w e) (or (super pre-on-char w e) (if (skip-subwindow-events?) #f (as-entry (lambda () (pre-wx->proxy w e (lambda (m e) (as-exit (lambda () (send (get-proxy) on-subwindow-char m e))))))))))] [pre-on-event (entry-point (lambda (w e) (if (skip-subwindow-events?) #f (pre-wx->proxy w e (lambda (m e) (as-exit (lambda () (send (get-proxy) on-subwindow-event m e))))))))]) (sequence (apply super-init mred proxy args)))))