@@ -15,7 +15,10 @@ use cosmic::{
15
15
iced:: { self , Subscription } ,
16
16
iced_futures:: stream,
17
17
} ;
18
- use drm:: control:: Device as ControlDevice ;
18
+ use drm:: control:: {
19
+ Device as ControlDevice ,
20
+ connector:: { Info as ConnectorInfo , Interface } ,
21
+ } ;
19
22
use futures:: { FutureExt , SinkExt } ;
20
23
use tokio:: {
21
24
io:: unix:: AsyncFd ,
@@ -57,6 +60,7 @@ impl Debug for GpuMonitor {
57
60
struct Gpu {
58
61
path : PathBuf ,
59
62
name : String ,
63
+ boot_vga : bool ,
60
64
primary : bool ,
61
65
enabled : bool ,
62
66
driver : Option < OsString > ,
@@ -147,26 +151,32 @@ pub struct RunningApp {
147
151
executable_name : String ,
148
152
}
149
153
154
+ fn connectors ( path : & impl AsRef < Path > ) -> Option < impl Iterator < Item = ConnectorInfo > > {
155
+ struct Device ( std:: fs:: File ) ;
156
+ impl AsFd for Device {
157
+ fn as_fd ( & self ) -> std:: os:: unix:: prelude:: BorrowedFd < ' _ > {
158
+ self . 0 . as_fd ( )
159
+ }
160
+ }
161
+ impl drm:: Device for Device { }
162
+ impl ControlDevice for Device { }
163
+
164
+ let device = Device ( std:: fs:: File :: open ( path) . ok ( ) ?) ;
165
+ let resources = device. resource_handles ( ) . ok ( ) ?;
166
+
167
+ Some (
168
+ resources
169
+ . connectors
170
+ . into_iter ( )
171
+ . filter_map ( move |conn| device. get_connector ( conn, false ) . ok ( ) ) ,
172
+ )
173
+ }
174
+
150
175
impl Gpu {
151
176
async fn connected_outputs ( & self ) -> Option < Vec < Entry > > {
152
177
let path = self . path . clone ( ) ;
153
178
spawn_blocking ( move || {
154
- struct Device ( std:: fs:: File ) ;
155
- impl AsFd for Device {
156
- fn as_fd ( & self ) -> std:: os:: unix:: prelude:: BorrowedFd < ' _ > {
157
- self . 0 . as_fd ( )
158
- }
159
- }
160
- impl drm:: Device for Device { }
161
- impl ControlDevice for Device { }
162
-
163
- let device = Device ( std:: fs:: File :: open ( path) . ok ( ) ?) ;
164
- let resources = device. resource_handles ( ) . ok ( ) ?;
165
-
166
- let outputs = resources
167
- . connectors
168
- . into_iter ( )
169
- . filter_map ( |conn| device. get_connector ( conn, false ) . ok ( ) )
179
+ let outputs = connectors ( & path) ?
170
180
. filter ( |info| info. state ( ) == drm:: control:: connector:: State :: Connected )
171
181
. map ( |info| Entry {
172
182
name : format ! (
@@ -178,6 +188,7 @@ impl Gpu {
178
188
secondary : String :: new ( ) ,
179
189
} )
180
190
. collect ( ) ;
191
+
181
192
// TODO read and parse edid with libdisplay-info and display output manufacture/model
182
193
183
194
Some ( outputs)
@@ -309,7 +320,7 @@ fn all_gpus<S: AsRef<str>>(seat: S) -> io::Result<Vec<Gpu>> {
309
320
let mut enumerator = udev:: Enumerator :: new ( ) ?;
310
321
enumerator. match_subsystem ( "drm" ) ?;
311
322
enumerator. match_sysname ( "card[0-9]*" ) ?;
312
- Ok ( enumerator
323
+ let mut gpus = enumerator
313
324
. scan_devices ( ) ?
314
325
. filter ( |device| {
315
326
device
@@ -370,13 +381,34 @@ fn all_gpus<S: AsRef<str>>(seat: S) -> io::Result<Vec<Gpu>> {
370
381
Some ( Gpu {
371
382
path,
372
383
name,
373
- primary : boot_vga,
384
+ boot_vga,
385
+ primary : false ,
374
386
enabled : false ,
375
387
driver,
376
388
interval,
377
389
} )
378
390
} )
379
- . collect ( ) )
391
+ . collect :: < Vec < _ > > ( ) ;
392
+
393
+ if let Some ( primary_idx) = gpus
394
+ . iter ( )
395
+ . position ( |gpu| {
396
+ connectors ( & gpu. path ) . is_some_and ( |mut conns| {
397
+ conns. any ( |info| {
398
+ let i = info. interface ( ) ;
399
+ i == Interface :: EmbeddedDisplayPort
400
+ || i == Interface :: LVDS
401
+ || i == Interface :: DSI
402
+ } )
403
+ } )
404
+ } )
405
+ . or_else ( || gpus. iter ( ) . position ( |gpu| gpu. boot_vga ) )
406
+ . or_else ( || ( gpus. len ( ) == 1 ) . then_some ( 0 ) )
407
+ {
408
+ gpus[ primary_idx] . primary = true ;
409
+ }
410
+
411
+ Ok ( gpus)
380
412
}
381
413
382
414
pub fn dgpu_subscription < I : ' static + Hash + Copy + Send + Sync + Debug > (
@@ -481,6 +513,7 @@ async fn start_listening(
481
513
monitor. gpus. push( Gpu {
482
514
path: path. to_path_buf( ) ,
483
515
name,
516
+ boot_vga: false ,
484
517
primary: false ,
485
518
enabled: false ,
486
519
driver,
0 commit comments