Skip to content
Snippets Groups Projects
Commit 85aa5b03 authored by Deucе's avatar Deucе :ok_hand_tone4:
Browse files

Some more GDI cleanup stuff...

Create a proper aspect fix function
Centre bitmap in window with correct aspect ratio
Fix cursor at resize points
Explicitly set high DPI awareness
Don't snap window larger than allowed

Since this is the newest/simplest display driver, I'm going to use
this to decide how to do scaling in general so I can abstract that
into shared code to ensure all drivers have the same scaling
behaviour.

I haven't tested mouse on windows with black bars yet though, so I
assume that's broken...
parent b9e5efac
No related branches found
No related tags found
1 merge request!463MRC mods by Codefenix (2024-10-20)
Pipeline #4163 passed
...@@ -27,6 +27,29 @@ static struct graphics_buffer *free_list; ...@@ -27,6 +27,29 @@ static struct graphics_buffer *free_list;
x = 255; \ x = 255; \
} while(0) } while(0)
/*
* Corrects width/height to have the specified aspect ratio
* any fit inside the specified rectangle
*/
void
aspect_fix_inside(int *x, int *y, int aspect_width, int aspect_height)
{
int bestx, besty;
if (aspect_width == 0 || aspect_height == 0)
return;
bestx = lround((double)*y * aspect_width / aspect_height);
besty = lround((double)*x * aspect_height / aspect_width);
if (besty <= *y)
*y = besty;
else if (bestx <= *x)
*x = bestx;
else {
fprintf(stderr, "Unable to fix %dx%d at ratio %d:%d (best %d, %d)\n", *x, *y, aspect_width, aspect_height, bestx, besty);
}
}
/* /*
* Corrects width/height to have the specified aspect ratio * Corrects width/height to have the specified aspect ratio
*/ */
......
...@@ -21,3 +21,4 @@ void aspect_reverse(int *x, int *y, int scrnwidth, int scrnheight, int aspect_wi ...@@ -21,3 +21,4 @@ void aspect_reverse(int *x, int *y, int scrnwidth, int scrnheight, int aspect_wi
void aspect_fix(int *x, int *y, int aspect_width, int aspect_height); void aspect_fix(int *x, int *y, int aspect_width, int aspect_height);
void aspect_fix_low(int *x, int *y, 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 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);
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <xp_dl.h>
#define BITMAP_CIOLIB_DRIVER #define BITMAP_CIOLIB_DRIVER
#include "win32gdi.h" #include "win32gdi.h"
#include "bitmap_con.h" #include "bitmap_con.h"
...@@ -169,7 +171,7 @@ set_ciolib_scaling(void) ...@@ -169,7 +171,7 @@ set_ciolib_scaling(void)
w = vstat.winwidth; w = vstat.winwidth;
h = vstat.winheight; h = vstat.winheight;
aspect_fix_low(&w, &h, vstat.aspect_width, vstat.aspect_height); aspect_fix_inside(&w, &h, vstat.aspect_width, vstat.aspect_height);
fw = w; fw = w;
fh = h; fh = h;
aspect_reverse(&w, &h, vstat.scrnwidth, vstat.scrnheight, vstat.aspect_width, vstat.aspect_height); aspect_reverse(&w, &h, vstat.scrnwidth, vstat.scrnheight, vstat.aspect_width, vstat.aspect_height);
...@@ -231,7 +233,9 @@ gdi_handle_wm_paint(HWND hwnd) ...@@ -231,7 +233,9 @@ gdi_handle_wm_paint(HWND hwnd)
{ {
static HDC memDC = NULL; static HDC memDC = NULL;
static HBITMAP di = NULL; static HBITMAP di = NULL;
static int diw, dih; static int diw = -1, dih = -1;
static int sww = -1, swh = -1;
static int lww = -1, lwh = -1;
PAINTSTRUCT ps; PAINTSTRUCT ps;
struct rectlist *list; struct rectlist *list;
...@@ -279,24 +283,28 @@ gdi_handle_wm_paint(HWND hwnd) ...@@ -279,24 +283,28 @@ gdi_handle_wm_paint(HWND hwnd)
b5hdr.bV5Height = -list->rect.height; b5hdr.bV5Height = -list->rect.height;
b5hdr.bV5SizeImage = list->rect.width * list->rect.height * 4; b5hdr.bV5SizeImage = list->rect.width * list->rect.height * 4;
data = list->data; data = list->data;
if (lww != w || lwh != h) {
sww = w;
swh = h;
aspect_fix_inside(&sww, &swh, aw, ah);
}
} }
winDC = BeginPaint(hwnd, &ps); winDC = BeginPaint(hwnd, &ps);
if (memDC == NULL) { if (memDC == NULL) {
memDC = CreateCompatibleDC(winDC); memDC = CreateCompatibleDC(winDC);
SetPixel(memDC, 0, 0, RGB(0, 0, 0));
} }
if (di == NULL) if (di == NULL)
di = CreateDIBitmap(winDC, (BITMAPINFOHEADER *)&b5hdr, CBM_INIT, data, (BITMAPINFO *)&b5hdr, DIB_RGB_COLORS); di = CreateDIBitmap(winDC, (BITMAPINFOHEADER *)&b5hdr, CBM_INIT, data, (BITMAPINFO *)&b5hdr, DIB_RGB_COLORS);
else else
SetDIBits(winDC, di, 0, dih, data, (BITMAPINFO *)&b5hdr, DIB_RGB_COLORS); SetDIBits(winDC, di, 0, dih, data, (BITMAPINFO *)&b5hdr, DIB_RGB_COLORS);
// Clear to black first // Clear to black first
StretchBlt(winDC, 0, 0, w, h, memDC, 0, 0, 1, 1, SRCCOPY); StretchBlt(winDC, 0, 0, w, h, memDC, 0, 0, 1, 1, BLACKNESS);
di = SelectObject(memDC, di); di = SelectObject(memDC, di);
if (ciolib_scaling) { if (ciolib_scaling) {
BitBlt(winDC, 0, 0, w, h, memDC, 0, 0, SRCCOPY); BitBlt(winDC, (w - diw) / 2, (h - dih) / 2, diw, dih, memDC, 0, 0, SRCCOPY);
} }
else { else {
StretchBlt(winDC, 0, 0, w, h, memDC, 0, 0, list->rect.width, list->rect.height, SRCCOPY); StretchBlt(winDC, (w - sww) / 2, (h - swh) / 2, sww, swh, memDC, 0, 0, diw, dih, SRCCOPY);
} }
EndPaint(hwnd, &ps); EndPaint(hwnd, &ps);
di = SelectObject(memDC, di); di = SelectObject(memDC, di);
...@@ -352,6 +360,8 @@ win_to_pos(LPARAM lParam, struct gdi_mouse_pos *p) ...@@ -352,6 +360,8 @@ win_to_pos(LPARAM lParam, struct gdi_mouse_pos *p)
cx = lParam & 0xffff; cx = lParam & 0xffff;
cy = (lParam >> 16) & 0xffff; cy = (lParam >> 16) & 0xffff;
// TODO: Fix up to work with windows that have black bars...
pthread_mutex_lock(&vstatlock); pthread_mutex_lock(&vstatlock);
p->tx = cx / (((float)vstat.winwidth) / vstat.cols) + 1; p->tx = cx / (((float)vstat.winwidth) / vstat.cols) + 1;
if (p->tx > vstat.cols) if (p->tx > vstat.cols)
...@@ -398,13 +408,14 @@ gdi_handle_activate(HWND hwnd, WPARAM wParam) ...@@ -398,13 +408,14 @@ gdi_handle_activate(HWND hwnd, WPARAM wParam)
uint16_t lw = wParam & 0xffff; uint16_t lw = wParam & 0xffff;
// TODO: We may need to read the state of CTRL and SHIFT keys for extended key input... // TODO: We may need to read the state of CTRL and SHIFT keys for extended key input...
if (lw != 0)
SetCursor(cursor);
return 0; return 0;
} }
static LRESULT CALLBACK static LRESULT CALLBACK
gdi_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { gdi_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
POINT p;
RECT r;
switch(msg) { switch(msg) {
case WM_PAINT: case WM_PAINT:
return gdi_handle_wm_paint(hwnd); return gdi_handle_wm_paint(hwnd);
...@@ -439,11 +450,24 @@ gdi_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { ...@@ -439,11 +450,24 @@ gdi_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
return gdi_handle_mouse_button(lParam, CIOLIB_BUTTON_RELEASE(3)); return gdi_handle_mouse_button(lParam, CIOLIB_BUTTON_RELEASE(3));
case WM_ACTIVATE: case WM_ACTIVATE:
return gdi_handle_activate(hwnd, wParam); return gdi_handle_activate(hwnd, wParam);
case WM_SETCURSOR:
case WM_USER_SETCURSOR: case WM_USER_SETCURSOR:
if (!GetClientRect(hwnd, &r))
break;
if (!GetCursorPos(&p))
break;
if (!ScreenToClient(hwnd, &p))
break;
if (p.x < 0 || p.y < 0 || p.x > (r.right - r.left) || p.y > (r.bottom - r.top))
break;
SetCursor(cursor);
break;
case WM_SETCURSOR:
if ((lParam & 0xffff) == HTCLIENT) {
SetCursor(cursor); SetCursor(cursor);
return 0; return 0;
} }
break;
}
return DefWindowProcW(hwnd, msg, wParam, lParam); return DefWindowProcW(hwnd, msg, wParam, lParam);
} }
...@@ -453,17 +477,26 @@ gdi_snap(bool grow) ...@@ -453,17 +477,26 @@ gdi_snap(bool grow)
{ {
bool wc; bool wc;
int w, h; int w, h;
int mw, mh;
if (maximized) if (maximized)
return; return;
mw = GetSystemMetrics(SM_CXMAXTRACK);
mh = GetSystemMetrics(SM_CYMAXTRACK);
UnadjustWindowSize(&mw, &mh);
pthread_mutex_lock(&vstatlock); pthread_mutex_lock(&vstatlock);
w = vstat.winwidth; w = vstat.winwidth;
h = vstat.winheight; h = vstat.winheight;
aspect_fix(&w, &h, vstat.aspect_width, vstat.aspect_height); aspect_fix_inside(&w, &h, vstat.aspect_width, vstat.aspect_height);
if (vstat.aspect_width == 0 || vstat.aspect_height == 0) if (vstat.aspect_width == 0 || vstat.aspect_height == 0)
wc = true; wc = true;
else else
wc = lround((double)(h * vstat.aspect_width) / vstat.aspect_height * vstat.scrnwidth / vstat.scrnheight) > w; 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 (grow) {
if (wc) if (wc)
w = (w - w % vstat.scrnwidth) + vstat.scrnwidth; w = (w - w % vstat.scrnwidth) + vstat.scrnwidth;
...@@ -496,7 +529,11 @@ gdi_snap(bool grow) ...@@ -496,7 +529,11 @@ gdi_snap(bool grow)
h = INT_MAX; h = INT_MAX;
else else
w = INT_MAX; w = INT_MAX;
aspect_fix(&w, &h, vstat.aspect_width, vstat.aspect_height); 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) if (w > 16384 || h > 16384)
gdi_beep(); gdi_beep();
else { else {
...@@ -715,7 +752,7 @@ gdi_textmode(int mode) ...@@ -715,7 +752,7 @@ gdi_textmode(int mode)
} }
vstat.winwidth = vstat.scrnwidth * scaling; vstat.winwidth = vstat.scrnwidth * scaling;
vstat.winheight = vstat.scrnheight * scaling; vstat.winheight = vstat.scrnheight * scaling;
aspect_fix(&vstat.winwidth, &vstat.winheight, vstat.aspect_width, vstat.aspect_height); aspect_fix_inside(&vstat.winwidth, &vstat.winheight, vstat.aspect_width, vstat.aspect_height);
if (oldcols != vstat.cols) { if (oldcols != vstat.cols) {
if (oldcols == 0) { if (oldcols == 0) {
if (ciolib_initial_window_width > 0) if (ciolib_initial_window_width > 0)
...@@ -891,6 +928,43 @@ gdi_init(int mode) ...@@ -891,6 +928,43 @@ gdi_init(int mode)
bitmap_drv_init(gdi_drawrect, gdi_flush); bitmap_drv_init(gdi_drawrect, gdi_flush);
gdi_textmode(mode); gdi_textmode(mode);
// code that tells windows we're High DPI aware so it doesn't scale our windows
// taken from Yamagi Quake II
typedef enum D3_PROCESS_DPI_AWARENESS {
D3_PROCESS_DPI_UNAWARE = 0,
D3_PROCESS_SYSTEM_DPI_AWARE = 1,
D3_PROCESS_PER_MONITOR_DPI_AWARE = 2
} YQ2_PROCESS_DPI_AWARENESS;
/* For Vista, Win7 and Win8 */
BOOL(WINAPI *SetProcessDPIAware)(void) = NULL;
/* Win8.1 and later */
HRESULT(WINAPI *SetProcessDpiAwareness)(enum D3_PROCESS_DPI_AWARENESS dpiAwareness) = NULL;
const char* user32dll[] = {"User32", NULL};
dll_handle userDLL = xp_dlopen(user32dll, RTLD_LAZY, 0);
if (userDLL)
{
SetProcessDPIAware = xp_dlsym(userDLL, SetProcessDPIAware);
}
const char* shcoredll[] = {"SHCore", NULL};
dll_handle shcoreDLL = xp_dlopen(shcoredll, RTLD_LAZY, 0);
if (shcoreDLL)
{
SetProcessDpiAwareness = xp_dlsym(shcoreDLL, SetProcessDpiAwareness);
}
if (SetProcessDpiAwareness) {
SetProcessDpiAwareness(D3_PROCESS_PER_MONITOR_DPI_AWARE);
}
else if (SetProcessDPIAware) {
SetProcessDPIAware();
}
_beginthread(gdi_mouse_thread, 0, NULL); _beginthread(gdi_mouse_thread, 0, NULL);
_beginthread(gdi_thread, 0, NULL); _beginthread(gdi_thread, 0, NULL);
WaitForSingleObject(init_sem, INFINITE); WaitForSingleObject(init_sem, INFINITE);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment