135 lines
4.0 KiB
Racket
135 lines
4.0 KiB
Racket
#lang racket/gui
|
|
(require racket/contract/base)
|
|
|
|
(define nnint? exact-nonnegative-integer?)
|
|
(provide
|
|
(contract-out
|
|
[get-mouse-x/y
|
|
(->* ()
|
|
()
|
|
(values nnint? nnint?))]
|
|
[get-display-info
|
|
(->* (nnint?)
|
|
()
|
|
(values nnint? nnint? nnint? nnint?))]
|
|
[find-monitor
|
|
(->* (nnint? nnint?)
|
|
()
|
|
(or/c false/c nnint?))]
|
|
[find-mouse-monitor
|
|
(->* ()
|
|
()
|
|
(or/c false/c nnint?))]
|
|
[find-x/y
|
|
(->* ((or/c nnint? (one-of/c 'left 'center 'right))
|
|
(or/c nnint? (one-of/c 'top 'center 'bottom)))
|
|
(#:width
|
|
nnint?
|
|
#:height
|
|
nnint?
|
|
#:monitor
|
|
(or/c false/c nnint?))
|
|
(values nnint? nnint?))]))
|
|
|
|
|
|
;; Returns the coordinates of the mouse pointer
|
|
(define (get-mouse-x/y)
|
|
(define-values (pt st)
|
|
(get-current-mouse-state))
|
|
(values (send pt get-x)
|
|
(send pt get-y)))
|
|
|
|
;; Returns the position x, y and the sizes w, h of the provided display/monitor number
|
|
(define (get-display-info disp)
|
|
(define-values (-x0 -y0)
|
|
(if (= disp 0)
|
|
(values 0 0) ; to avoid the bars and menus on first monitor
|
|
(get-display-left-top-inset #:monitor disp)))
|
|
(define-values (w h)
|
|
(get-display-size #:monitor disp))
|
|
(values (- -x0) (- -y0) w h))
|
|
|
|
;; Returns the display/monitor that contains the coordinates x,y, or #f if not found
|
|
(define (find-monitor x y)
|
|
(define n-disp (get-display-count))
|
|
(let loop ([disp 0])
|
|
(cond
|
|
[(>= disp n-disp) #f]
|
|
[else
|
|
(define-values (x0 y0 w h)
|
|
(get-display-info disp))
|
|
(if (and (<= x0 x (+ x0 w))
|
|
(<= y0 y (+ y0 h)))
|
|
disp
|
|
(loop (+ disp 1)))])))
|
|
|
|
;; Returns the display/monitor number that contains the mouse pointer
|
|
(define (find-mouse-monitor)
|
|
(define-values (pt st)
|
|
(get-current-mouse-state))
|
|
(find-monitor (send pt get-x) (send pt get-y)))
|
|
|
|
;; Returns the position x, y in pixels for where to place a frame of size fr-w, fr-h
|
|
;; on the specified monitor. If monitor is #f, then the monitor where the mouse
|
|
;; pointer is is used.
|
|
;; pos-x: (or/c non-negative-integer? (one-of 'left 'center 'right))
|
|
;; pos-y: (or/c non-negative-integer?
|
|
(define (find-x/y pos-x pos-y
|
|
#:width [fr-w 0]
|
|
#:height [fr-h 0]
|
|
#:monitor [monitor #f])
|
|
(when (and monitor (not (<= 0 monitor (- (get-display-count) 1))))
|
|
(error "Invalid monitor number" monitor))
|
|
(define disp (or monitor (find-mouse-monitor) 0))
|
|
(define-values (disp-x0 disp-y0 disp-w disp-h)
|
|
(get-display-info disp))
|
|
(define x
|
|
(cond [(eq? pos-x 'left)
|
|
disp-x0]
|
|
[(eq? pos-x 'center)
|
|
(+ disp-x0 (quotient (- disp-w fr-w) 2))]
|
|
[(eq? pos-x 'right)
|
|
(+ disp-x0 disp-w (- fr-w))]
|
|
[else (+ disp-x0 pos-x)]))
|
|
(define y
|
|
(cond [(eq? pos-y 'top)
|
|
disp-y0]
|
|
[(eq? pos-y 'center)
|
|
(+ disp-y0 (quotient (- disp-h fr-h) 2))]
|
|
[(eq? pos-y 'bottom)
|
|
(+ disp-y0 disp-h (- fr-h))]
|
|
[else (+ disp-y0 pos-y)]))
|
|
(values x y))
|
|
|
|
(module+ drracket
|
|
|
|
(define n-displays (get-display-count))
|
|
(for/list ([d (in-range n-displays)])
|
|
(define-values (x y)
|
|
(get-display-left-top-inset #:monitor d))
|
|
(define-values (w h)
|
|
(get-display-size #:monitor d))
|
|
(list d x y w h))
|
|
|
|
(define fr
|
|
(new frame%
|
|
[label "test"]
|
|
[width 400]
|
|
[height 100]))
|
|
(send fr show true)
|
|
(for* ([monitor (in-sequences (in-value #f)
|
|
(in-range (get-display-count)))]
|
|
[xx (in-list '(0 100 300 left center right))]
|
|
[yy (in-list '(0 200 400 top center bottom))])
|
|
(displayln (list monitor xx yy))
|
|
(define-values (x y)
|
|
(find-x/y xx yy
|
|
#:width (send fr get-width)
|
|
#:height (send fr get-height)
|
|
#:monitor monitor))
|
|
(send fr set-label (format "~a, ~a(~a), ~a(~a)" monitor xx x yy y))
|
|
(send fr move x y)
|
|
(sleep/yield 0.25))
|
|
)
|
|
|