Subject: Re: bug#23568: 25.0.94; Mode line menus appear incorrectly in some monitor configurations

From: Alex <[email-masked]>
Date: Wed, 31 May 2017 15:18:57 -0600

martin rudalics <[email-masked]> writes:

>> Martin, since you were involved with bug#22549, what do you think? Does
>> this seem reasonable, and should this functionality (window dimensions
>> of the current position's monitor) be extracted into its own procedure?
>
> I think so.
>
> But in addition I would like two functions, say display_monitor_geometry
> and display_monitor_workarea (maybe in frame.c), so we can avoid the
> Fx_display_monitor_attributes_list detour when we want the dimensions of
> the dominating monitor for a particular frame only.
>
> martin

That makes sense. What do you think of the following proposal? I made a
quick Lisp implementation for easy testing. The
`display-monitor-attribute' function allows access to any arbitrary
attribute of the "current" monitor, which can either be determined by
the selected frame or an explicit (x, y) coordinate.

(defun display-monitor-geometry (&optional frame x y)
  (display-monitor-attribute 'geometry frame x y))

(defun display-monitor-workarea (&optional frame x y)
  (display-monitor-attribute 'workarea frame x y))

(defun display-monitor-attribute (attribute &optional frame x y)
  "Return the value of the attribute of the 'current' monitor.
By default, use the frame info to determine the current monitor,
but if x and y are non-nil then use the given coordinates to
determine it."
  (let ((attributes (display-monitor-attributes-list))
        (frame (or frame (selected-frame))))
    (if (and x y)
        (cl-loop for monitor in attributes do
                 (let* ((geometry (assq 'geometry monitor))
                        (min-x (nth 1 geometry))
                        (min-y (nth 2 geometry))
                        (max-x (+ min-x (nth 3 geometry)))
                        (max-y (+ min-y (nth 4 geometry))))
                   (when (and (<= min-x x max-x)
                              (<= min-y y max-y))
                     (cl-return (alist-get attribute monitor)))))
      (cl-loop for monitor in attributes do
               (when (memq frame (alist-get 'frames monitor))
                 (cl-return (alist-get attribute monitor)))))))