@@ -65,17 +65,45 @@ def set_monitor_focus_service(self, service):
6565 if service :
6666 service .monitor_focused .connect (self ._on_monitor_focused )
6767
68+ def _get_gtk_monitor_info (self ) -> List [Dict ]:
69+ """Get monitor information using GTK/GDK including scale factors."""
70+ gtk_monitors = []
71+ try :
72+ display = Gdk .Display .get_default ()
73+ if display and hasattr (display , 'get_n_monitors' ):
74+ n_monitors = display .get_n_monitors ()
75+ for i in range (n_monitors ):
76+ monitor = display .get_monitor (i )
77+ if monitor :
78+ geometry = monitor .get_geometry ()
79+ scale_factor = monitor .get_scale_factor ()
80+ model = monitor .get_model () or f'monitor-{ i } '
81+
82+ gtk_monitors .append ({
83+ 'id' : i ,
84+ 'name' : model ,
85+ 'width' : geometry .width ,
86+ 'height' : geometry .height ,
87+ 'x' : geometry .x ,
88+ 'y' : geometry .y ,
89+ 'scale' : scale_factor
90+ })
91+ except Exception as e :
92+ print (f"Error getting GTK monitor info: { e } " )
93+
94+ return gtk_monitors
95+
6896 def refresh_monitors (self ) -> List [Dict ]:
6997 """
70- Detect monitors using Hyprland API with GTK fallback .
98+ Detect monitors using Hyprland API for accurate info, with GTK for scale detection .
7199
72100 Returns:
73- List of monitor dictionaries with id, name, width, height, x, y
101+ List of monitor dictionaries with id, name, width, height, x, y, scale
74102 """
75103 self ._monitors = []
76104
77105 try :
78- # Try Hyprland first
106+ # Try Hyprland first for primary info (more accurate)
79107 result = subprocess .run (
80108 ["hyprctl" , "monitors" , "-j" ],
81109 capture_output = True ,
@@ -85,14 +113,20 @@ def refresh_monitors(self) -> List[Dict]:
85113 hypr_monitors = json .loads (result .stdout )
86114
87115 for i , monitor in enumerate (hypr_monitors ):
116+ monitor_name = monitor .get ('name' , f'monitor-{ i } ' )
117+
118+ # Get scale directly from Hyprland (more reliable)
119+ hypr_scale = monitor .get ('scale' , 1.0 )
120+
88121 self ._monitors .append ({
89122 'id' : i ,
90- 'name' : monitor . get ( 'name' , f'monitor- { i } ' ) ,
123+ 'name' : monitor_name ,
91124 'width' : monitor .get ('width' , 1920 ),
92125 'height' : monitor .get ('height' , 1080 ),
93126 'x' : monitor .get ('x' , 0 ),
94127 'y' : monitor .get ('y' , 0 ),
95- 'focused' : monitor .get ('focused' , False )
128+ 'focused' : monitor .get ('focused' , False ),
129+ 'scale' : hypr_scale
96130 })
97131
98132 # Initialize states for new monitors
@@ -101,7 +135,7 @@ def refresh_monitors(self) -> List[Dict]:
101135 self ._current_notch_module [i ] = None
102136
103137 except (subprocess .CalledProcessError , json .JSONDecodeError , FileNotFoundError ):
104- # Fallback to GTK
138+ # Fallback to GTK only if Hyprland fails
105139 self ._fallback_to_gtk ()
106140
107141 # Ensure we have at least one monitor
@@ -113,7 +147,8 @@ def refresh_monitors(self) -> List[Dict]:
113147 'height' : 1080 ,
114148 'x' : 0 ,
115149 'y' : 0 ,
116- 'focused' : True
150+ 'focused' : True ,
151+ 'scale' : 1.0
117152 }]
118153 self ._notch_states [0 ] = False
119154 self ._current_notch_module [0 ] = None
@@ -128,14 +163,15 @@ def refresh_monitors(self) -> List[Dict]:
128163 return self ._monitors
129164
130165 def _fallback_to_gtk (self ):
131- """Fallback monitor detection using GTK."""
166+ """Fallback monitor detection using GTK with scale information ."""
132167 try :
133168 display = Gdk .Display .get_default ()
134169 if display and hasattr (display , 'get_n_monitors' ):
135170 n_monitors = display .get_n_monitors ()
136171 for i in range (n_monitors ):
137172 monitor = display .get_monitor (i )
138173 geometry = monitor .get_geometry ()
174+ scale_factor = monitor .get_scale_factor ()
139175
140176 self ._monitors .append ({
141177 'id' : i ,
@@ -144,7 +180,8 @@ def _fallback_to_gtk(self):
144180 'height' : geometry .height ,
145181 'x' : geometry .x ,
146182 'y' : geometry .y ,
147- 'focused' : i == 0 # Assume first monitor is focused
183+ 'focused' : i == 0 , # Assume first monitor is focused
184+ 'scale' : scale_factor
148185 })
149186
150187 if i not in self ._notch_states :
@@ -200,6 +237,19 @@ def get_monitor_for_workspace(self, workspace_id: int) -> int:
200237 return 0
201238 return (workspace_id - 1 ) // 10
202239
240+ def get_monitor_scale (self , monitor_id : int ) -> float :
241+ """
242+ Get scale factor for a monitor.
243+
244+ Args:
245+ monitor_id: Monitor ID
246+
247+ Returns:
248+ Scale factor (default 1.0 if not found)
249+ """
250+ monitor = self .get_monitor_by_id (monitor_id )
251+ return monitor .get ('scale' , 1.0 ) if monitor else 1.0
252+
203253 def is_notch_open (self , monitor_id : int ) -> bool :
204254 """Check if notch is open on a monitor."""
205255 return self ._notch_states .get (monitor_id , False )
0 commit comments