Take a look at display-monitor-attribute-list
:
(display-monitor-attributes-list &optional DISPLAY)
Return a list of physical monitor attributes on DISPLAY. Each element
of the list represents the attributes of each physical monitor. The
first element corresponds to the primary monitor.
Attributes for a physical monitor is represented as an alist of
attribute keys and values as follows:
geometry -- Position and size in pixels in the form of
(X Y WIDTH HEIGHT) workarea -- Position and size of the workarea in pixels in the
form of (X Y WIDTH HEIGHT) mm-size -- Width and height in millimeters in the form of
(WIDTH HEIGHT) frames -- List of frames dominated by the physical monitor name (*) -- Name of the physical monitor as a string
where X, Y, WIDTH, and HEIGHT are integers. Keys labeled with (*) are
optional.
A frame is dominated by a physical monitor when either the largest
area of the frame resides in the monitor, or the monitor is the
closest to the frame if the frame does not intersect any physical
monitors. Every non-tip frame (including invisible one) in a
graphical display is dominated by exactly one physical monitor at a
time, though it can span multiple (or no) physical monitors. If
DISPLAY is omitted or nil, it defaults to the selected frame's
display.
For example, to find the width of the first monitor, you could use:
(nth 4 (assq 'geometry (car (display-monitor-attributes-list))))