diff --git a/src/conio/bitmap_con.c b/src/conio/bitmap_con.c index eb4e1cc2a7ad652740a2c57bf03ab69966804287..c4496bfede86182889f1b8c4e61d083b825f670a 100644 --- a/src/conio/bitmap_con.c +++ b/src/conio/bitmap_con.c @@ -1,6 +1,8 @@ /* $Id: bitmap_con.c,v 1.148 2020/06/27 00:04:44 deuce Exp $ */ +#include <math.h> #include <stdarg.h> +#include <stdbool.h> #include <stdio.h> /* NULL */ #include <stdlib.h> #include <string.h> @@ -1612,6 +1614,64 @@ static int init_screens(int *width, int *height) /* Called from drivers */ /***********************/ +// Must be called with vstatlock +static void +get_scaled_win_size(int scale, bool wc, int *w, int *h, int maxwidth, int maxheight) +{ + *w = vstat.scrnwidth * scale; + *h = vstat.scrnheight * scale; + if (wc) + *h = INT_MAX; + else + *w = INT_MAX; + if (*w > maxwidth && maxwidth > 0) + *w = maxwidth; + if (*h > maxheight && maxheight > 0) + *h = maxheight; + aspect_fix_wc(w, h, wc, vstat.aspect_width, vstat.aspect_height); +} + +// Must be called with vstatlock +void +bitmap_snap(bool grow, int maxwidth, int maxheight) +{ + int mult; + int wc; + int cw; + int cs; + int w, h; + + w = vstat.winwidth; + h = vstat.winheight; + if (vstat.aspect_width == 0 || vstat.aspect_height == 0) + wc = true; + else + wc = lround((double)(vstat.scrnheight * vstat.aspect_width) / vstat.aspect_height) <= vstat.scrnwidth; + if (wc) { + mult = vstat.winwidth / vstat.scrnwidth; + cw = vstat.winwidth; + cs = vstat.scrnwidth; + } + else { + mult = vstat.winheight / vstat.scrnheight; + cw = vstat.winheight; + cs = vstat.winwidth; + } + if (grow) { + mult++; + } + else { + if (cw % cs == 0) + mult--; + } + if (mult < 1) + mult = 1; + do { + get_scaled_win_size(mult, wc, &vstat.winwidth, &vstat.winheight, maxwidth, maxheight); + mult--; + } while ((vstat.winwidth > maxwidth || vstat.winheight > maxheight) && mult > 1); +} + /* * This function is intended to be called from the driver. * as a result, it cannot block waiting for driver status @@ -1624,9 +1684,16 @@ static int init_screens(int *width, int *height) * out after this and only grab that lock again briefly to update * vstat.scaling. */ -int bitmap_drv_init_mode(int mode, int *width, int *height) +int bitmap_drv_init_mode(int mode, int *width, int *height, int maxwidth, int maxheight) { int i; + int64_t os; + int64_t ls; + int64_t ns; + int64_t bs; + int w, h; + int mult; + bool wc; if(!bitmap_initialized) return(-1); @@ -1635,6 +1702,9 @@ int bitmap_drv_init_mode(int mode, int *width, int *height) return(-1); } + // Save the old diagonal (no point is sqrting here) + os = ((int64_t)vstat.winwidth * vstat.winwidth) + ((int64_t)vstat.winheight * vstat.winheight); + /* Initialize video memory with black background, white foreground */ for (i = 0; i < vstat.cols*vstat.rows; ++i) { if (i > 0) @@ -1674,6 +1744,41 @@ int bitmap_drv_init_mode(int mode, int *width, int *height) cio_textinfo.winright=cio_textinfo.screenwidth; cio_textinfo.winbottom=cio_textinfo.screenheight; + // Now calculate the closest diagonal new size that's smaller than max... + if (vstat.aspect_width == 0 || vstat.aspect_height == 0) + wc = true; + else + wc = lround((double)(vstat.scrnheight * vstat.aspect_width) / vstat.aspect_height) <= vstat.scrnwidth; + mult = 1; + get_scaled_win_size(mult, wc, &w, &h, maxwidth, maxheight); + bs = ((int64_t)w * w) + ((int64_t)h * h); + ls = bs; + ns = bs; + while (ns < os) { + mult++; + get_scaled_win_size(mult, wc, &w, &h, maxwidth, maxheight); + if ((maxwidth > 0) && (w > maxwidth)) { + mult--; + ns = ls; + break; + } + if ((maxheight > 0) && (h > maxheight)) { + mult--; + ns = ls; + break; + } + bs = ((int64_t)w * w) + ((int64_t)h * h); + ls = ns; + ns = bs; + } + if ((os - ls) <= (ns - os)) { + if (mult > 1) + mult--; + } + get_scaled_win_size(mult, wc, &w, &h, maxwidth, maxheight); + vstat.winwidth = w; + vstat.winheight = h; + return(0); } diff --git a/src/conio/bitmap_con.h b/src/conio/bitmap_con.h index 3e104604cd3bdf9316e6816576441c5268972797..4e5c74be7a7f6fb83b3f3c6d219fd1d5962b0869 100644 --- a/src/conio/bitmap_con.h +++ b/src/conio/bitmap_con.h @@ -50,12 +50,13 @@ int bitmap_setpalette(uint32_t index, uint16_t r, uint16_t g, uint16_t b); #ifdef BITMAP_CIOLIB_DRIVER /* Called from drivers */ -int bitmap_drv_init_mode(int mode, int *width, int *height); +int bitmap_drv_init_mode(int mode, int *width, int *height, int maxwidth, int maxheight); int bitmap_drv_init(void (*drawrect_cb) (struct rectlist *data) ,void (*flush) (void)); void bitmap_drv_request_pixels(void); void bitmap_drv_request_some_pixels(int x, int y, int width, int height); void bitmap_drv_free_rect(struct rectlist *rect); +void bitmap_snap(bool grow, int maxwidth, int maxheight); #endif #endif diff --git a/src/conio/scale.c b/src/conio/scale.c index c5fdf2c3bbb62c3f17d18a160745b6f0ab59d2bb..9948c27c6993399b5ee9dcd72b566200f5c3384e 100644 --- a/src/conio/scale.c +++ b/src/conio/scale.c @@ -26,6 +26,32 @@ static struct graphics_buffer *free_list; x = 255; \ } while(0) +/* + * Corrects width/height to have the specified aspect ratio + * any fit inside the specified rectangle + */ +void +aspect_fix_wc(int *x, int *y, bool wc, int aspect_width, int aspect_height) +{ + int bestx, besty; + + if (aspect_width == 0 || aspect_height == 0) + return; + if (r2yptr != NULL && y2rptr != NULL) { + bestx = lround((double)*y * aspect_width / aspect_height); + besty = lround((double)*x * aspect_height / aspect_width); + } + else { + bestx = lround((double)*y * *x / *y); + besty = lround((double)*x * *y / *x); + } + + if (wc) + *y = besty; + else + *x = bestx; +} + /* * Corrects width/height to have the specified aspect ratio * any fit inside the specified rectangle diff --git a/src/conio/scale.h b/src/conio/scale.h index 4ce37c55a0c8fc3279aed44b39e6869184cecd32..3b127a255351312f71f705de56f4f84851e072b9 100644 --- a/src/conio/scale.h +++ b/src/conio/scale.h @@ -1,3 +1,5 @@ +#include <stdbool.h> + #include "bitmap_con.h" struct graphics_buffer { @@ -19,6 +21,7 @@ struct graphics_buffer * do_scale(struct rectlist* rect, int xscale, int yscale, void aspect_correct(int *x, int *y, int aspect_width, int aspect_height); void aspect_reverse(int *x, int *y, int scrnwidth, int scrnheight, int aspect_width, int aspect_height); void aspect_fix(int *x, int *y, int aspect_width, int aspect_height); +void aspect_fix_wc(int *x, int *y, bool wc, int aspect_width, int aspect_height); void aspect_fix_low(int *x, int *y, int aspect_width, int aspect_height); void calc_scaling_factors(int *x, int *y, int winwidth, int winheight, int aspect_width, int aspect_height, int scrnwidth, int scrnheight); void aspect_fix_inside(int *x, int *y, int aspect_width, int aspect_height); diff --git a/src/conio/sdl_con.c b/src/conio/sdl_con.c index fc3791a009c9819048ea0c26825a8b5f24535d9f..bce078d802c539c7f21a619421b35e67a806d0c7 100644 --- a/src/conio/sdl_con.c +++ b/src/conio/sdl_con.c @@ -359,6 +359,8 @@ static int sdl_init_mode(int mode) { int oldcols; int scaling = 1; + int w, h; + SDL_Rect r; if (mode != CIOLIB_MODE_CUSTOM) { pthread_mutex_lock(&vstatlock); @@ -373,37 +375,15 @@ static int sdl_init_mode(int mode) pthread_mutex_lock(&vstatlock); oldcols = vstat.cols; - bitmap_drv_init_mode(mode, &bitmap_width, &bitmap_height); - if (vstat.scrnwidth > 0) { - for (scaling = 1; (scaling + 1) * vstat.scrnwidth < vstat.winwidth; scaling++) - ; + if (sdl.GetDisplayUsableBounds(0, &r) == 0) { + w = r.w; + h = r.h; } - vstat.winwidth = vstat.scrnwidth * scaling; - vstat.winheight = vstat.scrnheight * scaling; - aspect_fix(&vstat.winwidth, &vstat.winheight, vstat.aspect_width, vstat.aspect_height); - if (oldcols != vstat.cols) { - if (oldcols == 0) { - if (ciolib_initial_window_width > 0) - vstat.winwidth = ciolib_initial_window_width; - if (ciolib_initial_window_height > 0) - vstat.winheight = ciolib_initial_window_height; - if (vstat.cols == 40) - oldcols = 40; - } - if (oldcols == 40) { - vstat.winwidth /= 2; - vstat.winheight /= 2; - } - if (vstat.cols == 40) { - vstat.winwidth *= 2; - vstat.winheight *= 2; - } + else { + w = 0; + h = 0; } - if (vstat.winwidth < vstat.scrnwidth) - vstat.winwidth = vstat.scrnwidth; - if (vstat.winheight < vstat.scrnheight) - vstat.winheight = vstat.scrnheight; - + bitmap_drv_init_mode(mode, &bitmap_width, &bitmap_height, w, h); internal_scaling = window_can_scale_internally(&vstat); pthread_mutex_lock(&sdl_mode_mutex); sdl_mode = true; @@ -891,62 +871,22 @@ void sdl_video_event_thread(void *data) if ((ev.key.keysym.mod & KMOD_ALT) && (ev.key.keysym.sym == SDLK_LEFT || ev.key.keysym.sym == SDLK_RIGHT)) { - int w, h; - // Don't allow ALT-DIR to change size when maximized... if ((sdl.GetWindowFlags(win) & SDL_WINDOW_MAXIMIZED) == 0) { - bool wc; - - update_cvstat(&cvstat); - w = cvstat.winwidth; - h = cvstat.winheight; - aspect_fix(&w, &h, cvstat.aspect_width, cvstat.aspect_height); - if (cvstat.aspect_width == 0 || cvstat.aspect_height == 0) - wc = true; - else - wc = lround((double)(h * cvstat.aspect_width) / cvstat.aspect_height * cvstat.scrnwidth / cvstat.scrnheight) > w; - switch(ev.key.keysym.sym) { - case SDLK_LEFT: - if (wc) { - if (w % (cvstat.scrnwidth)) { - w = w - w % cvstat.scrnwidth; - } - else { - w -= cvstat.scrnwidth; - if (w < cvstat.scrnwidth) - w = cvstat.scrnwidth; - } - } - else { - if (h % (cvstat.scrnheight)) { - h = h - h % cvstat.scrnheight; - } - else { - h -= cvstat.scrnheight; - if (h < cvstat.scrnheight) - h = cvstat.scrnheight; - } - } - break; - case SDLK_RIGHT: - if (wc) - w = (w - w % cvstat.scrnwidth) + cvstat.scrnwidth; - else - h = (h - h % cvstat.scrnheight) + cvstat.scrnheight; - break; + int w, h; + SDL_Rect r; + if (sdl.GetDisplayUsableBounds(0, &r) == 0) { + w = r.w; + h = r.h; } - if (wc) - h = INT_MAX; - else - w = INT_MAX; - aspect_fix(&w, &h, cvstat.aspect_width, cvstat.aspect_height); - if (w > 16384 || h > 16384) - beep(); else { - cvstat.winwidth = w; - cvstat.winheight = h; - internal_scaling = window_can_scale_internally(&cvstat); + w = 0; + h = 0; } + pthread_mutex_lock(&vstatlock); + bitmap_snap(ev.key.keysym.sym == SDLK_RIGHT, w, h); + pthread_mutex_unlock(&vstatlock); + update_cvstat(&cvstat); setup_surfaces_locked(&cvstat); } break; diff --git a/src/conio/sdlfuncs.c b/src/conio/sdlfuncs.c index 00e30bfbcde77b6f352720103ba13807a88d5986..4df3beab8c8f61f35df74b2f6116bea1fe1235ef 100644 --- a/src/conio/sdlfuncs.c +++ b/src/conio/sdlfuncs.c @@ -202,6 +202,10 @@ int load_sdl_funcs(struct sdlfuncs *sdlf) xp_dlclose(sdl_dll); return(-1); } + if((sdlf->GetDisplayUsableBounds=xp_dlsym(sdl_dll, SDL_GetDisplayUsableBounds))==NULL) { + xp_dlclose(sdl_dll); + return(-1); + } #ifndef STATIC_SDL { int (HACK_HACK_HACK *ra)(char *name, Uint32 style, void *hInst); diff --git a/src/conio/sdlfuncs.h b/src/conio/sdlfuncs.h index 7dd75bdf9bea504c97fc40e614fd1abd9d55745b..bf52c2b7f705e5811be9197041e478b10e688ae7 100644 --- a/src/conio/sdlfuncs.h +++ b/src/conio/sdlfuncs.h @@ -56,6 +56,7 @@ struct sdlfuncs { void (HACK_HACK_HACK *FreeCursor) (SDL_Cursor *curs); void(HACK_HACK_HACK *free) (void *); Uint32(HACK_HACK_HACK *GetWindowFlags) (SDL_Window * window); + int (HACK_HACK_HACK *GetDisplayUsableBounds) (int, SDL_Rect *); int gotfuncs; }; diff --git a/src/conio/win32gdi.c b/src/conio/win32gdi.c index 001e12d1ffc515a940e61fc796cedd77cc5af203..e6a166faeda0f2bad27b52181e4fdb4e59499697 100644 --- a/src/conio/win32gdi.c +++ b/src/conio/win32gdi.c @@ -197,8 +197,8 @@ UnadjustWindowSize(int *w, int *h) ret = AdjustWindowRect(&r, style, FALSE); if (ret) { - w += r.left - r.right; - h += r.top - r.bottom; + *w += r.left - r.right; + *h += r.top - r.bottom; } return ret; } @@ -222,7 +222,6 @@ gdi_handle_wm_size(WPARAM wParam, LPARAM lParam) return 0; w = lParam & 0xffff; h = (lParam >> 16) & 0xffff; - UnadjustWindowSize(&w, &h); pthread_mutex_lock(&vstatlock); vstat.winwidth = w; vstat.winheight = h; @@ -519,76 +518,34 @@ gdi_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { return DefWindowProcW(hwnd, msg, wParam, lParam); } +static bool +gdi_get_monitor_size(int *w, int *h) +{ + HMONITOR mon; + MONITORINFO mi; + bool ret; + + mon = MonitorFromWindow(win, MONITOR_DEFAULTTOPRIMARY); + mi.cbSize = sizeof(mi); + ret = GetMonitorInfoW(mon, &mi); + *w = mi.rcWork.right - mi.rcWork.left; + *h = mi.rcWork.bottom - mi.rcWork.top; + return ret; +} + static void gdi_snap(bool grow) { - bool wc; - int w, h; int mw, mh; if (maximized) return; - mw = GetSystemMetrics(SM_CXMAXTRACK); - mh = GetSystemMetrics(SM_CYMAXTRACK); + gdi_get_monitor_size(&mw, &mh); UnadjustWindowSize(&mw, &mh); pthread_mutex_lock(&vstatlock); - w = vstat.winwidth; - h = vstat.winheight; - aspect_fix_inside(&w, &h, vstat.aspect_width, vstat.aspect_height); - if (vstat.aspect_width == 0 || vstat.aspect_height == 0) - wc = true; - else - wc = lround((double)(h * vstat.aspect_width) / vstat.aspect_height * vstat.scrnwidth / vstat.scrnheight) > w; - if (wc) - mw = mw - mw % vstat.scrnwidth; - else - mh = mh - mh % vstat.scrnheight; - mh = mw - mw % vstat.scrnwidth; - if (grow) { - if (wc) - w = (w - w % vstat.scrnwidth) + vstat.scrnwidth; - else - h = (h - h % vstat.scrnheight) + vstat.scrnheight; - } - else { - if (wc) { - if (w % (vstat.scrnwidth)) { - w = w - w % vstat.scrnwidth; - } - else { - w -= vstat.scrnwidth; - if (w < vstat.scrnwidth) - w = vstat.scrnwidth; - } - } - else { - if (h % (vstat.scrnheight)) { - h = h - h % vstat.scrnheight; - } - else { - h -= vstat.scrnheight; - if (h < vstat.scrnheight) - h = vstat.scrnheight; - } - } - } - if (wc) - h = INT_MAX; - else - w = INT_MAX; - if (w > mw) - w = mw; - if (h > mh) - h = mh; - aspect_fix_inside(&w, &h, vstat.aspect_width, vstat.aspect_height); - if (w > 16384 || h > 16384) - gdi_beep(); - else { - vstat.winwidth = w; - vstat.winheight = h; - set_ciolib_scaling(); - gdi_setwinsize(w, h); - } + bitmap_snap(grow, mw, mh); + set_ciolib_scaling(); + gdi_setwinsize(vstat.winwidth, vstat.winheight); pthread_mutex_unlock(&vstatlock); } @@ -618,7 +575,6 @@ magic_message(MSG msg) r.left = r.top = 0; r.right = vstat.winwidth = msg.wParam; r.bottom = vstat.winheight = msg.lParam; - set_ciolib_scaling(); pthread_mutex_unlock(&vstatlock); AdjustWindowRect(&r, style, FALSE); SetWindowPos(win, NULL, 0, 0, r.right - r.left, r.bottom - r.top, SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER); @@ -778,8 +734,8 @@ gdi_beep(void) void gdi_textmode(int mode) { - int oldcols; int scaling = 1; + int mw, mh; if (mode != CIOLIB_MODE_CUSTOM) { pthread_mutex_lock(&vstatlock); @@ -791,37 +747,9 @@ gdi_textmode(int mode) } pthread_mutex_lock(&vstatlock); - oldcols = vstat.cols; - bitmap_drv_init_mode(mode, NULL, NULL); - if (vstat.scrnwidth > 0) { - for (scaling = 1; (scaling + 1) * vstat.scrnwidth < vstat.winwidth; scaling++) - ; - } - vstat.winwidth = vstat.scrnwidth * scaling; - vstat.winheight = vstat.scrnheight * scaling; - aspect_fix_inside(&vstat.winwidth, &vstat.winheight, vstat.aspect_width, vstat.aspect_height); - if (oldcols != vstat.cols) { - if (oldcols == 0) { - if (ciolib_initial_window_width > 0) - vstat.winwidth = ciolib_initial_window_width; - if (ciolib_initial_window_height > 0) - vstat.winheight = ciolib_initial_window_height; - if (vstat.cols == 40) - oldcols = 40; - } - if (oldcols == 40) { - vstat.winwidth /= 2; - vstat.winheight /= 2; - } - if (vstat.cols == 40) { - vstat.winwidth *= 2; - vstat.winheight *= 2; - } - } - if (vstat.winwidth < vstat.scrnwidth) - vstat.winwidth = vstat.scrnwidth; - if (vstat.winheight < vstat.scrnheight) - vstat.winheight = vstat.scrnheight; + gdi_get_monitor_size(&mw, &mh); + UnadjustWindowSize(&mw, &mh); + bitmap_drv_init_mode(mode, NULL, NULL, mw, mh); set_ciolib_scaling(); gdi_setwinsize(vstat.winwidth, vstat.winheight); pthread_mutex_unlock(&vstatlock); diff --git a/src/conio/x_events.c b/src/conio/x_events.c index ee5704f40628b8a9eb947e62c704f3ac20d201bc..a7de3d588b2196b82bb9e19a0b029120272bc70a 100644 --- a/src/conio/x_events.c +++ b/src/conio/x_events.c @@ -417,7 +417,7 @@ static void init_mode_internal(int mode) release_buffer(last); last = NULL; } - bitmap_drv_init_mode(mode, &bitmap_width, &bitmap_height); + bitmap_drv_init_mode(mode, &bitmap_width, &bitmap_height, 0, 0); /* Deal with 40 col doubling */ if(oldcols != vstat.cols) {