11use std:: num:: NonZeroU32 ;
22
33use x11rb:: connection:: RequestConnection ;
4- use x11rb:: protocol:: randr:: { self , ConnectionExt as _} ;
4+ use x11rb:: protocol:: randr:: { self , ConnectionExt as _, Rotation } ;
55use x11rb:: protocol:: xproto;
66
77use super :: { util, X11Error , XConnection } ;
@@ -41,6 +41,8 @@ pub struct MonitorHandle {
4141 pub ( crate ) position : ( i32 , i32 ) ,
4242 /// If the monitor is the primary one
4343 primary : bool ,
44+ /// The physical size of a monitor in millimeters.
45+ pub ( crate ) physical_size : Option < ( NonZeroU32 , NonZeroU32 ) > ,
4446 /// The DPI scale factor
4547 pub ( crate ) scale_factor : f64 ,
4648 /// Used to determine which windows are on this monitor
@@ -66,6 +68,10 @@ impl MonitorHandleProvider for MonitorHandle {
6668 Some ( self . position . into ( ) )
6769 }
6870
71+ fn physical_size ( & self ) -> Option < ( NonZeroU32 , NonZeroU32 ) > {
72+ self . physical_size
73+ }
74+
6975 fn scale_factor ( & self ) -> f64 {
7076 self . scale_factor
7177 }
@@ -125,19 +131,46 @@ impl MonitorHandle {
125131 crtc : & randr:: GetCrtcInfoReply ,
126132 primary : bool ,
127133 ) -> Option < Self > {
128- let ( name, scale_factor, video_modes) = xconn. get_output_info ( resources, crtc) ?;
134+ let ( name, mut physical_size, scale_factor, video_modes) =
135+ xconn. get_output_info ( resources, crtc) ?;
136+
137+ let rotation = xconn
138+ . xcb_connection ( )
139+ . randr_get_crtc_info ( id, x11rb:: CURRENT_TIME )
140+ . ok ( ) ?
141+ . reply ( )
142+ . ok ( ) ?
143+ . rotation ;
144+
145+ // By default, X11 window system is the only that does not
146+ // swap width and height when display is rotated. To match
147+ // behaviour with Windows and MacOS we do this manually.
148+ if matches ! ( rotation, Rotation :: ROTATE90 | Rotation :: ROTATE270 ) {
149+ physical_size = physical_size. map ( |( width_mm, height_mm) | ( height_mm, width_mm) ) ;
150+ }
151+
129152 let dimensions = ( crtc. width as u32 , crtc. height as u32 ) ;
130153 let position = ( crtc. x as i32 , crtc. y as i32 ) ;
131154
132155 let rect = util:: AaRect :: new ( position, dimensions) ;
133156
134- Some ( MonitorHandle { id, name, scale_factor, position, primary, rect, video_modes } )
157+ Some ( MonitorHandle {
158+ id,
159+ name,
160+ physical_size,
161+ scale_factor,
162+ position,
163+ primary,
164+ rect,
165+ video_modes,
166+ } )
135167 }
136168
137169 pub fn dummy ( ) -> Self {
138170 MonitorHandle {
139171 id : 0 ,
140172 name : "<dummy monitor>" . into ( ) ,
173+ physical_size : None ,
141174 scale_factor : 1.0 ,
142175 position : ( 0 , 0 ) ,
143176 primary : true ,
0 commit comments