From 2d9aa3f7ed0b653c72347469d4861e5b21a23c28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Deuc=D0=B5?= <shurd@sasktel.net> Date: Tue, 6 Jun 2023 02:26:47 -0400 Subject: [PATCH] Add support for starting X11 mode fullscreen. --- src/conio/ciolib.c | 3 +- src/conio/ciolib.h | 1 + src/conio/win32gdi.c | 2 +- src/conio/x_cio.c | 6 ++-- src/conio/x_cio.h | 3 +- src/conio/x_events.c | 68 ++++++++++++++++++++++++++++++----------- src/syncterm/bbslist.c | 2 ++ src/syncterm/syncterm.c | 20 +++++++++--- 8 files changed, 77 insertions(+), 28 deletions(-) diff --git a/src/conio/ciolib.c b/src/conio/ciolib.c index f125994810..220144ffb9 100644 --- a/src/conio/ciolib.c +++ b/src/conio/ciolib.c @@ -281,7 +281,7 @@ static int try_x_init(int mode) } #endif - if(!x_init()) { + if(!x_initciolib(mode)) { cio_api.mode=CIOLIB_MODE_X; cio_api.mouse=1; cio_api.puttext=bitmap_puttext; @@ -502,6 +502,7 @@ CIOLIBEXPORT int initciolib(int mode) break; case CIOLIB_MODE_X: + case CIOLIB_MODE_X_FULLSCREEN: #ifndef NO_X try_x_init(mode); #endif diff --git a/src/conio/ciolib.h b/src/conio/ciolib.h index c4f7442160..9e4e2d2fa5 100644 --- a/src/conio/ciolib.h +++ b/src/conio/ciolib.h @@ -74,6 +74,7 @@ enum { ,CIOLIB_MODE_CURSES_ASCII ,CIOLIB_MODE_ANSI ,CIOLIB_MODE_X + ,CIOLIB_MODE_X_FULLSCREEN ,CIOLIB_MODE_CONIO ,CIOLIB_MODE_CONIO_FULLSCREEN ,CIOLIB_MODE_SDL diff --git a/src/conio/win32gdi.c b/src/conio/win32gdi.c index c3a55e4bd7..c2a0b0a62e 100644 --- a/src/conio/win32gdi.c +++ b/src/conio/win32gdi.c @@ -1077,7 +1077,7 @@ gdi_init(int mode) cio_api.mode=CIOLIB_MODE_GDI; FreeConsole(); - cio_api.options |= CONIO_OPT_PALETTE_SETTING | CONIO_OPT_SET_TITLE | CONIO_OPT_SET_NAME | CONIO_OPT_SET_ICON; + cio_api.options |= CONIO_OPT_SET_TITLE | CONIO_OPT_SET_NAME | CONIO_OPT_SET_ICON | CONIO_OPT_EXTERNAL_SCALING; return(0); } CloseHandle(rch); diff --git a/src/conio/x_cio.c b/src/conio/x_cio.c index d0fed32f67..19ead83a0d 100644 --- a/src/conio/x_cio.c +++ b/src/conio/x_cio.c @@ -211,7 +211,7 @@ void x11_mouse_thread(void *data) } } -int x_init(void) +int x_initciolib(int mode) { dll_handle dl; const char *libnames[]={"X11",NULL}; @@ -716,7 +716,7 @@ int x_init(void) return(-1); } - _beginthread(x11_event_thread,1<<16,NULL); + _beginthread(x11_event_thread,1<<16,(void *)(intptr_t)mode); sem_wait(&init_complete); if(!x11_initialized) { xp_dlclose(dl); @@ -743,7 +743,7 @@ int x_init(void) return(-1); } _beginthread(x11_mouse_thread,1<<16,NULL); - cio_api.options |= CONIO_OPT_SET_TITLE | CONIO_OPT_SET_NAME | CONIO_OPT_SET_ICON; + cio_api.options |= CONIO_OPT_SET_TITLE | CONIO_OPT_SET_NAME | CONIO_OPT_SET_ICON | CONIO_OPT_EXTERNAL_SCALING; return(0); } diff --git a/src/conio/x_cio.h b/src/conio/x_cio.h index 7ea95e80b8..2a259d519a 100644 --- a/src/conio/x_cio.h +++ b/src/conio/x_cio.h @@ -60,8 +60,7 @@ int x_wherey(void); int x_wherex(void); int x_putch(int ch); void x_gotoxy(int x, int y); -int x_init(void); -void x_initciolib(int inmode); +int x_initciolib(int mode); void x_gettextinfo(struct text_info *info); void x_setcursortype(int type); int x_getch(void); diff --git a/src/conio/x_events.c b/src/conio/x_events.c index d52965fc53..5f5b632c5c 100644 --- a/src/conio/x_events.c +++ b/src/conio/x_events.c @@ -33,6 +33,9 @@ #include "x_cio.h" #include "utf8_codepages.h" +static bool send_fullscreen(bool set); +static void resize_window(); + /* * Exported variables */ @@ -175,6 +178,8 @@ static Window parent; static Window root; static char *wm_wm_name; static Atom copy_paste_selection = XA_PRIMARY; +static bool map_pending = true; +static int pending_width, pending_height, pending_xpos, pending_ypos; /* Array of Graphics Contexts */ static GC gc; @@ -756,7 +761,8 @@ static void map_window() if (x11_get_maxsize(&sh->max_width,&sh->max_height)) { pthread_mutex_lock(&vstatlock); - bitmap_get_scaled_win_size(bitmap_double_mult_inside(sh->max_width, sh->max_height), &sh->max_width, &sh->max_height, sh->max_width, sh->max_height); + if (!fullscreen) + bitmap_get_scaled_win_size(bitmap_double_mult_inside(sh->max_width, sh->max_height), &sh->max_width, &sh->max_height, sh->max_width, sh->max_height); } else { pthread_mutex_lock(&vstatlock); @@ -784,7 +790,8 @@ static void map_window() pthread_mutex_lock(&vstatlock); vstat.scaling = x_cvstat.scaling; pthread_mutex_unlock(&vstatlock); - x11.XMapWindow(dpy, win); + if (map_pending) + x11.XMapWindow(dpy, win); x11.XFree(sh); @@ -991,6 +998,9 @@ static int init_window() a = A(_NET_WM_WINDOW_TYPE_NORMAL); if (a != None) set_win_property(ATOM__NET_WM_WINDOW_TYPE, XA_ATOM, 32, PropModeReplace, &a, 1); + a = A(_NET_WM_STATE_FULLSCREEN); + if (a != None) + set_win_property(ATOM__NET_WM_STATE, XA_ATOM, 32, PropModeReplace, &a, 1); im = x11.XOpenIM(dpy, NULL, "CIOLIB", "CIOLIB"); if (im != NULL) { @@ -1069,12 +1079,15 @@ static void resize_window() pthread_mutex_lock(&vstatlock); if (fullscreen && send_fullscreen(true)) { + cio_api.mode = CIOLIB_MODE_X_FULLSCREEN; } else { send_fullscreen(false); fullscreen = false; + cio_api.mode = CIOLIB_MODE_X; new_scaling = x_cvstat.scaling; bitmap_get_scaled_win_size(new_scaling, &width, &height, 0, 0); + // TODO: If we're in fullscreen mode, we don't get the decoration sizes... if (x11_get_maxsize(&max_width, &max_height)) { if (width > max_width || height > max_height) { new_scaling = bitmap_double_mult_inside(max_width, max_height); @@ -1184,7 +1197,6 @@ static int video_init() bitmap_drv_init_mode(vstat.mode, NULL, NULL, 0, 0); x_cvstat = vstat; pthread_mutex_unlock(&vstatlock); - init_mode_internal(x_cvstat.mode); return(0); } @@ -1370,12 +1382,13 @@ local_draw_rect(struct rectlist *rect) last = source; } -static void handle_resize_event(int width, int height) +static void handle_resize_event(int width, int height, bool map) { pthread_mutex_lock(&vstatlock); - if (fullscreen) { + if (fullscreen && !map) { if ((width != x_cvstat.winwidth || height != x_cvstat.winheight)) { fullscreen = false; + cio_api.mode = CIOLIB_MODE_X; } } x_cvstat.winwidth = vstat.winwidth = width; @@ -1518,6 +1531,23 @@ is_maximized(void) return is; } +static void +handle_configuration(int x, int y, int w, int h, bool map) +{ + bool resize = false; + + if ((x11_window_xpos != x || x11_window_ypos != y)) { + x11_window_xpos = x; + x11_window_ypos = y; + } + pthread_mutex_lock(&vstatlock); + if (w != vstat.winwidth || h != vstat.winheight) + resize = true; + pthread_mutex_unlock(&vstatlock); + if (resize) + handle_resize_event(w, h, map); +} + static int x11_event(XEvent *ev) { if (x11.XFilterEvent(ev, win)) @@ -1545,7 +1575,6 @@ static int x11_event(XEvent *ev) break; /* Graphics related events */ case ConfigureNotify: { - bool resize = false; int ax, ay; Window cr; @@ -1558,22 +1587,24 @@ static int x11_event(XEvent *ev) ax = ev->xconfigure.x; ay = ev->xconfigure.y; } - if ((x11_window_xpos != ax || x11_window_ypos != ay)) { - x11_window_xpos = ax; - x11_window_ypos = ay; + if (map_pending) { + pending_xpos = ax; + pending_ypos = ay; + pending_width = ev->xconfigure.width; + pending_height = ev->xconfigure.height; } - pthread_mutex_lock(&vstatlock); - if (ev->xconfigure.width != vstat.winwidth || ev->xconfigure.height != vstat.winheight) { - // XWayland on ChromeOS appears to send a 1x1 resize event early on for unknown reasons... inore it. - if (ev->xconfigure.width != 1 && ev->xconfigure.height != 1) - resize = true; + else { + handle_configuration(ax, ay, ev->xconfigure.width, ev->xconfigure.height, false); } - pthread_mutex_unlock(&vstatlock); - if (resize) - handle_resize_event(ev->xconfigure.width, ev->xconfigure.height); } break; } + case MapNotify: + if (map_pending) { + map_pending = false; + handle_configuration(pending_xpos, pending_ypos, pending_width, pending_height, true); + } + break; case NoExpose: break; case GraphicsExpose: @@ -2040,8 +2071,11 @@ void x11_event_thread(void *args) fd_set fdset; XEvent ev; static struct timeval tv; + int mode = (int)(intptr_t)args; SetThreadName("X11 Events"); + if (mode == CIOLIB_MODE_X_FULLSCREEN) + fullscreen = true; if(video_init()) { sem_post(&init_complete); return; diff --git a/src/syncterm/bbslist.c b/src/syncterm/bbslist.c index 40be50b624..830c8db17c 100644 --- a/src/syncterm/bbslist.c +++ b/src/syncterm/bbslist.c @@ -1927,6 +1927,8 @@ change_settings(int connected) " Uses the Xlib library directly for graphical output. This is\n" " the graphical mode most likely to work when using X11. This\n" " mode supports font changes.\n\n" + "~ X11 Fullscreen ~\n" + " As above, but starts in full-screen mode rather than a window\n\n" #endif #ifdef _WIN32 "~ Win32 Console ~\n" diff --git a/src/syncterm/syncterm.c b/src/syncterm/syncterm.c index 259f765801..fc4cf96992 100644 --- a/src/syncterm/syncterm.c +++ b/src/syncterm/syncterm.c @@ -103,7 +103,7 @@ char *usage = "-iX = set interface mode to X (default=auto) where X is one of:\n" " S[W|F] = SDL surface mode W for windowed and F for fullscreen\n" #ifdef __unix__ - " X = X11 mode\n" + " X[W|F] = X11 mode W for windowed and F for fullscreen\n" " C = Curses mode\n" " I = Curses mode with forced ASCII charset\n" " F = Curses mode with forced IBM charset\n" @@ -759,14 +759,15 @@ char *output_types[] = { , "ANSI" #if defined(__unix__) && !defined(NO_X) , "X11" + , "X11 Fullscreen" #endif #ifdef _WIN32 , "Win32 Console", "Win32 Console Fullscreen" #endif #if defined(WITH_SDL) || defined(WITH_SDL_AUDIO) - , "SDL", - "SDL Fullscreen" + , "SDL" + , "SDL Fullscreen" #endif #if defined(WITH_GDI) , "GDI" @@ -783,6 +784,7 @@ int output_map[] = { , CIOLIB_MODE_ANSI #if defined(__unix__) && !defined(NO_X) , CIOLIB_MODE_X + , CIOLIB_MODE_X_FULLSCREEN #endif #ifdef _WIN32 , CIOLIB_MODE_CONIO, @@ -805,6 +807,7 @@ char *output_descrs[] = { "Curses using US-ASCII", "ANSI", "X11", + "X11 Fullscreen", "Win32 Console", "Win32 Console Fullscreen", "SDL", @@ -820,6 +823,7 @@ char *output_enum[] = { "CursesAscii", "ANSI", "X11", + "X11Fullscreen", "WinConsole", "WinConsoleFullscreen", "SDL", @@ -1628,7 +1632,15 @@ main(int argc, char **argv) ciolib_mode = CIOLIB_MODE_CURSES_ASCII; break; case 'X': - ciolib_mode = CIOLIB_MODE_X; + switch (toupper(argv[i][3])) { + case 0: + case 'W': + ciolib_mode = CIOLIB_MODE_X; + break; + case 'F': + ciolib_mode = CIOLIB_MODE_X_FULLSCREEN; + break; + } break; case 'W': ciolib_mode = CIOLIB_MODE_CONIO; -- GitLab