@@ -30,6 +30,8 @@ typedef struct {
3030
3131 /* Linux virtual terminal (VT) */
3232 int vt_fd ;
33+ bool vt_active ;
34+ struct vt_mode old_vtm ;
3335
3436 /* Linux framebuffer */
3537 int fb_fd ;
@@ -86,22 +88,6 @@ static void twin_fbdev_get_screen_size(twin_fbdev_t *tx,
8688 * height = info .yres ;
8789}
8890
89- static void twin_fbdev_damage (twin_screen_t * screen , twin_fbdev_t * tx )
90- {
91- int width , height ;
92- twin_fbdev_get_screen_size (tx , & width , & height );
93- twin_screen_damage (tx -> screen , 0 , 0 , width , height );
94- }
95-
96- static bool twin_fbdev_work (void * closure )
97- {
98- twin_screen_t * screen = SCREEN (closure );
99-
100- if (twin_screen_damaged (screen ))
101- twin_screen_update (screen );
102- return true;
103- }
104-
10591static inline bool twin_fbdev_is_rgb565 (twin_fbdev_t * tx )
10692{
10793 return tx -> fb_var .red .offset == 11 && tx -> fb_var .red .length == 5 &&
@@ -192,6 +178,50 @@ static bool twin_fbdev_apply_config(twin_fbdev_t *tx)
192178 return true;
193179}
194180
181+ static void twin_fbdev_damage (twin_fbdev_t * tx )
182+ {
183+ int width , height ;
184+ twin_fbdev_get_screen_size (tx , & width , & height );
185+ twin_screen_damage (tx -> screen , 0 , 0 , width , height );
186+ }
187+
188+ static bool twin_fbdev_update_damage (void * closure )
189+ {
190+ twin_fbdev_t * tx = PRIV (closure );
191+ twin_screen_t * screen = SCREEN (closure );
192+
193+ if (!tx -> vt_active && twin_screen_damaged (screen ))
194+ twin_screen_update (screen );
195+
196+ return true;
197+ }
198+
199+ static bool twin_fbdev_work (void * closure )
200+ {
201+ twin_fbdev_t * tx = PRIV (closure );
202+ twin_screen_t * screen = SCREEN (closure );
203+
204+ if (tx -> vt_active && (tx -> fb_base != MAP_FAILED )) {
205+ /* Unmap the fbdev */
206+ munmap (tx -> fb_base , tx -> fb_len );
207+ tx -> fb_base = MAP_FAILED ;
208+ }
209+
210+ if (!tx -> vt_active && (tx -> fb_base == MAP_FAILED )) {
211+ /* Restore the fbdev settings */
212+ if (!twin_fbdev_apply_config (tx ))
213+ log_error ("Failed to apply configurations to the fbdev" );
214+
215+ /* Mark entire screen for refresh */
216+ twin_screen_damage (screen , 0 , 0 , screen -> width , screen -> height );
217+ }
218+
219+ if (!tx -> vt_active && twin_screen_damaged (screen ))
220+ twin_screen_update (screen );
221+
222+ return true;
223+ }
224+
195225twin_context_t * twin_fbdev_init (int width , int height )
196226{
197227 char * fbdev_path = getenv (FBDEV_NAME );
@@ -218,10 +248,13 @@ twin_context_t *twin_fbdev_init(int width, int height)
218248 }
219249
220250 /* Set up virtual terminal environment */
221- if (!twin_vt_setup (& tx -> vt_fd )) {
251+ if (!twin_vt_setup (& tx -> vt_fd , & tx -> old_vtm , & tx -> vt_active )) {
222252 goto bail_fb_fd ;
223253 }
224254
255+ /* Set up signal handlers for switching TTYs */
256+ twin_vt_setup_signal_handler ();
257+
225258 /* Apply configurations to the framebuffer device */
226259 if (!twin_fbdev_apply_config (tx )) {
227260 log_error ("Failed to apply configurations to the framebuffer device" );
@@ -254,6 +287,9 @@ twin_context_t *twin_fbdev_init(int width, int height)
254287 /* Setup file handler and work functions */
255288 twin_set_work (twin_fbdev_work , TWIN_WORK_REDISPLAY , ctx );
256289
290+ /* Register a callback function to handle damaged rendering */
291+ twin_screen_register_damaged (ctx -> screen , twin_fbdev_update_damage , ctx );
292+
257293 return ctx ;
258294
259295bail_screen :
@@ -292,7 +328,6 @@ static void twin_fbdev_exit(twin_context_t *ctx)
292328}
293329
294330/* Register the Linux framebuffer backend */
295-
296331const twin_backend_t g_twin_backend = {
297332 .init = twin_fbdev_init ,
298333 .configure = twin_fbdev_configure ,
0 commit comments