11use crate :: injector:: { self , WindowInfo } ;
22use eframe:: {
33 Renderer ,
4- egui:: { self , IconData } ,
4+ egui:: { self , ColorImage , IconData } ,
55} ;
66use image:: { GenericImageView , ImageFormat , ImageReader } ;
77use std:: sync:: { Arc , Mutex } ;
88use std:: thread;
99use std:: { io:: Cursor , mem} ;
10+ use windows_capture:: capture:: { Context , GraphicsCaptureApiHandler } ;
11+ use windows_capture:: frame:: Frame ;
12+ use windows_capture:: monitor:: Monitor ;
13+ use windows_capture:: settings:: {
14+ ColorFormat , CursorCaptureSettings , DirtyRegionSettings , DrawBorderSettings ,
15+ MinimumUpdateIntervalSettings , SecondaryWindowSettings , Settings ,
16+ } ;
17+
18+ struct ScreenCapture {
19+ capture_sender : crossbeam_channel:: Sender < ColorImage > ,
20+ }
21+
22+ impl GraphicsCaptureApiHandler for ScreenCapture {
23+ type Flags = crossbeam_channel:: Sender < ColorImage > ;
24+
25+ type Error = Box < dyn std:: error:: Error + Send + Sync > ;
26+
27+ fn new ( ctx : Context < Self :: Flags > ) -> Result < Self , Self :: Error > {
28+ Ok ( ScreenCapture {
29+ capture_sender : ctx. flags ,
30+ } )
31+ }
32+
33+ fn on_frame_arrived (
34+ & mut self ,
35+ frame : & mut Frame ,
36+ _capture_control : windows_capture:: graphics_capture_api:: InternalCaptureControl ,
37+ ) -> Result < ( ) , Self :: Error > {
38+ let width = frame. width ( ) ;
39+ let height = frame. height ( ) ;
40+ if let Ok ( mut buffer) = frame. buffer ( ) {
41+ if let Ok ( no_pad_buffer) = buffer. as_nopadding_buffer ( ) {
42+ let img = ColorImage :: from_rgba_unmultiplied (
43+ [ width as usize , height as usize ] ,
44+ & no_pad_buffer,
45+ ) ;
46+ let _ = self . capture_sender . try_send ( img) ;
47+ }
48+ }
49+ Ok ( ( ) )
50+ }
51+ }
1052
1153#[ derive( Debug ) ]
1254enum WorkerEvents {
@@ -15,11 +57,12 @@ enum WorkerEvents {
1557 SHOW ( u32 , u32 , bool ) ,
1658}
1759
18- #[ derive( Debug ) ]
1960struct Gui {
2061 windows : Arc < Mutex < Vec < WindowInfo > > > ,
21- sender : crossbeam_channel:: Sender < WorkerEvents > ,
22- hide_taskbar_icons : bool ,
62+ event_sender : crossbeam_channel:: Sender < WorkerEvents > ,
63+ capture_receiver : crossbeam_channel:: Receiver < ColorImage > ,
64+ hide_from_taskbar : bool ,
65+ capture_tex : Option < egui:: TextureHandle > ,
2366}
2467
2568impl Gui {
@@ -50,10 +93,39 @@ impl Gui {
5093 }
5194 } ) ;
5295
96+ let ( capture_sender, capture_receiver) = crossbeam_channel:: bounded ( 1 ) ;
97+
98+ thread:: spawn ( move || {
99+ let primary_monitor = Monitor :: primary ( ) . expect ( "There is no primary monitor" ) ;
100+
101+ let settings = Settings :: new (
102+ // Item to capture
103+ primary_monitor,
104+ // Capture cursor settings
105+ CursorCaptureSettings :: Default ,
106+ // Draw border settings
107+ DrawBorderSettings :: Default ,
108+ // Secondary window settings, if you want to include secondary windows in the capture
109+ SecondaryWindowSettings :: Default ,
110+ // Minimum update interval, if you want to change the frame rate limit (default is 60 FPS or 16.67 ms)
111+ MinimumUpdateIntervalSettings :: Default ,
112+ // Dirty region settings,
113+ DirtyRegionSettings :: Default ,
114+ // The desired color format for the captured frame.
115+ ColorFormat :: Rgba8 ,
116+ // Additional flags for the capture settings that will be passed to the user-defined `new` function.
117+ capture_sender,
118+ ) ;
119+
120+ ScreenCapture :: start ( settings) . expect ( "screen capture failed" ) ;
121+ } ) ;
122+
53123 Gui {
54124 windows,
55- sender,
56- hide_taskbar_icons : false ,
125+ event_sender : sender,
126+ capture_receiver,
127+ hide_from_taskbar : false ,
128+ capture_tex : None ,
57129 }
58130 }
59131}
@@ -67,17 +139,39 @@ impl eframe::App for Gui {
67139 // `focused` is a bool: true=gained focus, false=lost focus
68140 if focused {
69141 println ! ( "focused" ) ;
70- self . sender . send ( WorkerEvents :: UPDATE ) . unwrap ( ) ;
142+ self . event_sender . send ( WorkerEvents :: UPDATE ) . unwrap ( ) ;
71143 } else {
72144 println ! ( "unfocused" ) ;
73145 }
74146 }
75147 }
76148 egui:: CentralPanel :: default ( ) . show ( ctx, |ui| {
77- ui. heading ( "Hide applications" ) ;
78- ui. add_space ( 4.0 ) ;
79-
80149 egui:: ScrollArea :: vertical ( ) . show ( ui, |ui| {
150+ ui. heading ( "Desktop Preview" ) ;
151+ ui. add_space ( 4.0 ) ;
152+
153+ if let Ok ( img) = self . capture_receiver . try_recv ( ) {
154+ if let Some ( texture_handle) = & mut self . capture_tex {
155+ texture_handle. set ( img, egui:: TextureOptions :: default ( ) ) ;
156+ } else {
157+ self . capture_tex = Some ( ctx. load_texture (
158+ "screen_capture" ,
159+ img,
160+ egui:: TextureOptions :: LINEAR , // or NEAREST if you want crisp pixels
161+ ) ) ;
162+ }
163+ }
164+
165+ if let Some ( tex) = & self . capture_tex {
166+ // Show at native size:
167+ ui. add ( egui:: Image :: from_texture ( tex) . shrink_to_fit ( ) ) ;
168+ // or force a size (e.g. scale to 512x512):
169+ // ui.image((tex.id(), egui::vec2(512.0, 512.0)));
170+ }
171+ ui. add_space ( 8.0 ) ;
172+
173+ ui. heading ( "Hide applications" ) ;
174+ ui. add_space ( 4.0 ) ;
81175 for window_info in self . windows . lock ( ) . unwrap ( ) . iter_mut ( ) {
82176 ui. style_mut ( ) . wrap_mode = Some ( egui:: TextWrapMode :: Truncate ) ; // elide with "…"
83177 let checkbox_response =
@@ -87,24 +181,21 @@ impl eframe::App for Gui {
87181 WorkerEvents :: HIDE (
88182 window_info. pid ,
89183 window_info. hwnd ,
90- ! self . hide_taskbar_icons ,
184+ self . hide_from_taskbar ,
91185 )
92186 } else {
93187 WorkerEvents :: SHOW (
94188 window_info. pid ,
95189 window_info. hwnd ,
96- ! self . hide_taskbar_icons ,
190+ self . hide_from_taskbar ,
97191 )
98192 } ;
99- self . sender . send ( event) . unwrap ( ) ;
193+ self . event_sender . send ( event) . unwrap ( ) ;
100194 }
101195 }
102196 ui. add_space ( 10.0 ) ;
103197 ui. collapsing ( "Advanced settings" , |ui| {
104- ui. checkbox (
105- & mut self . hide_taskbar_icons ,
106- "Hide from Alt+Tab and Taskbar" ,
107- )
198+ ui. checkbox ( & mut self . hide_from_taskbar , "Hide from Alt+Tab and Taskbar" )
108199 } ) ;
109200 } ) ;
110201 } ) ;
0 commit comments