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

Fix issue 138

Weird stuff happened when dragging a GDI window between monitors
with different zoom (DPI) settings.  The following changes were
all done to clean up this stuff:

Window position is signed
Do some type casting for warnings
Fix return times of GetDpiFor*() pointers
Fix fallback to GetDpiForSystem() (could never be used)
Handle WM_DPICHANGED correctly
Move some copy/pasted code into a function
Fix return value for WM_GETDPISCALEDSIZE
Fix return value for WM_USER_SETCURSOR
parent 9b13ae0f
No related branches found
No related tags found
No related merge requests found
Pipeline #6707 passed
...@@ -84,15 +84,28 @@ Foreground colour ...@@ -84,15 +84,28 @@ Foreground colour
Background colour Background colour
Font Font
Flags Flags
- Fast Blink
- Slow Blink
- Bold - Bold
- Increased intensity
- Faint
- decreased intensity
- second colour
- Italic - Italic
- Underline
- Slow Blink (< 150/min)
- Fast Blink (> 150/min)
- Negative - Negative
- Concealed - Concealed
- Underline - crossed-out (Overstrike)
- Overstrike - Fraktur (Gothic)
- Double underline - Double underline
- Framed
- Encircled
- Overlined
- Ideogram underline (right)
- Ideogram double underline (right)
- Ideogram overline (left)
- Ideogram double overline (left)
- Ideogram stress
- Double overstrike - Double overstrike
- Double-wide - Double-wide
- Double-high - Double-high
......
...@@ -23,7 +23,7 @@ static HWND win; ...@@ -23,7 +23,7 @@ static HWND win;
static HANDLE rch; static HANDLE rch;
static HANDLE wch; static HANDLE wch;
static bool maximized = false; static bool maximized = false;
static uint16_t winxpos, winypos; static int16_t winxpos, winypos;
static const DWORD style = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_VISIBLE; static const DWORD style = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_VISIBLE;
static const DWORD fs_style = WS_POPUP | WS_VISIBLE; static const DWORD fs_style = WS_POPUP | WS_VISIBLE;
#define STYLE (fullscreen ? fs_style : style) #define STYLE (fullscreen ? fs_style : style)
...@@ -87,11 +87,11 @@ utf8_to_utf16(const uint8_t *str8, int buflen) ...@@ -87,11 +87,11 @@ utf8_to_utf16(const uint8_t *str8, int buflen)
LPWSTR ret; LPWSTR ret;
// First, get the size required for the conversion... // First, get the size required for the conversion...
sz = MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, str8, buflen, NULL, 0); sz = MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, (LPCCH)str8, buflen, NULL, 0);
if (sz == 0) if (sz == 0)
return NULL; return NULL;
ret = (LPWSTR)malloc((sz + 1) * sizeof(*ret)); ret = (LPWSTR)malloc((sz + 1) * sizeof(*ret));
if (sz == MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, str8, buflen, ret, sz)) { if (sz == MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, (LPCCH)str8, buflen, (LPWSTR)ret, sz)) {
ret[sz] = 0; ret[sz] = 0;
return ret; return ret;
} }
...@@ -110,7 +110,7 @@ utf16_to_utf8(const LPWSTR str16) ...@@ -110,7 +110,7 @@ utf16_to_utf8(const LPWSTR str16)
if (sz == 0) if (sz == 0)
return NULL; return NULL;
ret = (uint8_t *)malloc(sz * sizeof(*ret)); ret = (uint8_t *)malloc(sz * sizeof(*ret));
if (sz == WideCharToMultiByte(CP_UTF8, 0, str16, -1, ret, sz * sizeof(*ret), NULL, NULL)) { if (sz == WideCharToMultiByte(CP_UTF8, 0, str16, -1, (LPSTR)ret, sz * sizeof(*ret), NULL, NULL)) {
return ret; return ret;
} }
free(ret); free(ret);
...@@ -195,9 +195,9 @@ static BOOL ...@@ -195,9 +195,9 @@ static BOOL
gdiAdjustWindowRect(LPRECT r, DWORD style, BOOL menu, UINT dpi) gdiAdjustWindowRect(LPRECT r, DWORD style, BOOL menu, UINT dpi)
{ {
static bool gotPtr = false; static bool gotPtr = false;
static BOOL (__stdcall *AWREFD)(LPRECT, DWORD, BOOL, DWORD, UINT); static BOOL (__stdcall *AWREFD)(LPRECT, DWORD, BOOL, DWORD, UINT) = NULL;
static BOOL (__stdcall *GDFW)(HWND); static UINT (__stdcall *GDFW)(HWND) = NULL;
static BOOL (__stdcall *GDFS)(void); static UINT (__stdcall *GDFS)(void) = NULL;
if (!gotPtr) { if (!gotPtr) {
const char* user32dll[] = {"User32", NULL}; const char* user32dll[] = {"User32", NULL};
...@@ -211,13 +211,15 @@ gdiAdjustWindowRect(LPRECT r, DWORD style, BOOL menu, UINT dpi) ...@@ -211,13 +211,15 @@ gdiAdjustWindowRect(LPRECT r, DWORD style, BOOL menu, UINT dpi)
gotPtr = true; gotPtr = true;
} }
if (win && AWREFD && GDFW && GDFS) { if (AWREFD && GDFW && GDFS) {
if (dpi == 0) { if (dpi == 0) {
if (win == NULL) if (win == NULL || GDFW == NULL) {
dpi = GDFS(); dpi = GDFS();
else }
else {
dpi = GDFW(win); dpi = GDFW(win);
} }
}
return AWREFD(r, style, menu, 0, dpi); return AWREFD(r, style, menu, 0, dpi);
} }
return AdjustWindowRect(r, style, menu); return AdjustWindowRect(r, style, menu);
...@@ -269,38 +271,6 @@ gdi_handle_wm_size(WPARAM wParam, LPARAM lParam) ...@@ -269,38 +271,6 @@ gdi_handle_wm_size(WPARAM wParam, LPARAM lParam)
return 0; return 0;
} }
static LRESULT
gdi_handle_wm_sizing(WPARAM wParam, RECT *rect)
{
int w, h;
double mult;
mult = bitmap_double_mult_inside(w, h);
bitmap_get_scaled_win_size(mult, &w, &h, 0, 0);
switch(wParam) {
case WMSZ_BOTTOM:
case WMSZ_BOTTOMLEFT:
case WMSZ_LEFT:
rect->bottom = rect->top + h - 1;
rect->left = rect->right - w + 1;
break;
case WMSZ_BOTTOMRIGHT:
case WMSZ_RIGHT:
rect->bottom = rect->top + h - 1;
rect->right = rect->left + w - 1;
break;
case WMSZ_TOP:
case WMSZ_TOPLEFT:
rect->top = rect->bottom - h + 1;
rect->left = rect->right - w + 1;
break;
case WMSZ_TOPRIGHT:
rect->right = rect->left + w - 1;
break;
}
return TRUE;
}
static LRESULT static LRESULT
gdi_handle_wm_paint(HWND hwnd) gdi_handle_wm_paint(HWND hwnd)
{ {
...@@ -611,20 +581,50 @@ handle_wm_getminmaxinfo(MINMAXINFO *inf) ...@@ -611,20 +581,50 @@ handle_wm_getminmaxinfo(MINMAXINFO *inf)
return 0; return 0;
} }
static LRESULT static void
gdi_handle_getdpiscaledsize(WPARAM wParam, LPSIZE sz) gdi_get_windowsize_at_dpi(bool screen, LONG *w, LONG *h, WORD dpi)
{ {
RECT r; RECT r;
r.left = r.top = 0;
pthread_mutex_lock(&vstatlock); pthread_mutex_lock(&vstatlock);
// Now make the inside of the window the size we want (sigh) // Now make the inside of the window the size we want (sigh)
r.left = r.top = 0; if (screen) {
r.right = vstat.scrnwidth - 1; r.right = vstat.scrnwidth - 1;
r.bottom = vstat.scrnheight - 1; r.bottom = vstat.scrnheight - 1;
} else {
r.right = vstat.winwidth - 1;
r.bottom = vstat.winheight - 1;
}
pthread_mutex_unlock(&vstatlock); pthread_mutex_unlock(&vstatlock);
gdiAdjustWindowRect(&r, STYLE, FALSE, HIWORD(wParam)); gdiAdjustWindowRect(&r, STYLE, FALSE, dpi);
sz->cx = r.right - r.left + 1; if (w)
sz->cy = r.bottom - r.top + 1; *w = r.right - r.left + 1;
pthread_mutex_unlock(&vstatlock); if (h)
*h = r.bottom - r.top + 1;
}
static LRESULT
gdi_handle_getdpiscaledsize(WORD dpi, LPSIZE sz)
{
LONG w, h;
gdi_get_windowsize_at_dpi(true, &w, &h, dpi);
sz->cx = w;
sz->cy = h;
return TRUE;
}
static LRESULT CALLBACK
gdi_handle_wm_dpichanged(WPARAM wParam, RECT *r)
{
WORD dpi;
LONG w, h;
// The high and low words have the X and Y DPI respectively, and they're always the same
dpi = HIWORD(wParam);
// Now make the inside of the window the size we want (sigh)
gdi_get_windowsize_at_dpi(false, &w, &h, dpi);
SetWindowPos(win, NULL, 0, 0, w, h, SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER|SWP_NOACTIVATE);
return 0; return 0;
} }
...@@ -640,14 +640,12 @@ gdi_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { ...@@ -640,14 +640,12 @@ gdi_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
return gdi_handle_wm_char(wParam, lParam); return gdi_handle_wm_char(wParam, lParam);
case WM_MOVE: case WM_MOVE:
pthread_mutex_lock(&winpos_lock); pthread_mutex_lock(&winpos_lock);
winxpos = lParam & 0xffff; winxpos = (WORD)(lParam & 0xffff);
winypos = (lParam >> 16) & 0xffff; winypos = (WORD)((lParam >> 16) & 0xffff);
pthread_mutex_unlock(&winpos_lock); pthread_mutex_unlock(&winpos_lock);
return 0; return 0;
case WM_SIZE: case WM_SIZE:
return gdi_handle_wm_size(wParam, lParam); return gdi_handle_wm_size(wParam, lParam);
//case WM_SIZING:
// return gdi_handle_wm_sizing(wParam, (RECT *)lParam);
case WM_CLOSE: case WM_CLOSE:
case WM_DESTROY: case WM_DESTROY:
PostQuitMessage(0); PostQuitMessage(0);
...@@ -675,21 +673,13 @@ gdi_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { ...@@ -675,21 +673,13 @@ gdi_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
case WM_SETCURSOR: case WM_SETCURSOR:
if ((lParam & 0xffff) == HTCLIENT) { if ((lParam & 0xffff) == HTCLIENT) {
SetCursor(cursor); SetCursor(cursor);
return 0; return TRUE;
} }
break; return FALSE;
case WM_GETDPISCALEDSIZE: case WM_GETDPISCALEDSIZE:
return gdi_handle_getdpiscaledsize(wParam, (LPSIZE)lParam); return gdi_handle_getdpiscaledsize(HIWORD(wParam), (LPSIZE)lParam);
case WM_DPICHANGED: case WM_DPICHANGED:
// The rect is the suggested position and size for the window... return gdi_handle_wm_dpichanged(wParam, (RECT*)lParam);
//r = *((RECT*)lParam);
// The high and low words have the X and Y DPI respectively, and they're always the same
//WORD dpi = HIWORD(wParam);
// For now, just say "We've got this!" and ignore it.
// TODO: In the future, maybe resize so the window stays "the same"?
// Problem is that this is still imaginary DPI, so unlikely to work properly.
return 0;
break;
case WM_USER_SETCURSOR: case WM_USER_SETCURSOR:
if (!GetClientRect(hwnd, &r)) if (!GetClientRect(hwnd, &r))
break; break;
...@@ -700,17 +690,15 @@ gdi_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { ...@@ -700,17 +690,15 @@ gdi_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
if (p.x < 0 || p.y < 0 || p.x > (r.right - r.left) || p.y > (r.bottom - r.top)) if (p.x < 0 || p.y < 0 || p.x > (r.right - r.left) || p.y > (r.bottom - r.top))
break; break;
SetCursor(cursor); SetCursor(cursor);
break; return true;
case WM_USER_INVALIDATE: case WM_USER_INVALIDATE:
InvalidateRect(win, NULL, FALSE); InvalidateRect(win, NULL, FALSE);
return true; return true;
case WM_USER_SETSIZE: case WM_USER_SETSIZE:
pthread_mutex_lock(&vstatlock);
// Now make the inside of the window the size we want (sigh) // Now make the inside of the window the size we want (sigh)
r.left = r.top = 0; r.left = r.top = 0;
r.right = wParam - 1; r.right = wParam - 1;
r.bottom = lParam - 1; r.bottom = lParam - 1;
pthread_mutex_unlock(&vstatlock);
gdiAdjustWindowRect(&r, STYLE, FALSE, 0); gdiAdjustWindowRect(&r, STYLE, FALSE, 0);
SetWindowPos(win, NULL, 0, 0, r.right - r.left + 1, r.bottom - r.top + 1, SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER); SetWindowPos(win, NULL, 0, 0, r.right - r.left + 1, r.bottom - r.top + 1, SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER);
return true; return true;
...@@ -874,8 +862,8 @@ gdi_thread(void *arg) ...@@ -874,8 +862,8 @@ gdi_thread(void *arg)
{ {
WNDCLASSW wc = {0}; WNDCLASSW wc = {0};
MSG msg; MSG msg;
RECT r;
ATOM cl; ATOM cl;
LONG w, h;
int wx = CW_USEDEFAULT; int wx = CW_USEDEFAULT;
int wy = CW_USEDEFAULT; int wy = CW_USEDEFAULT;
int mode = (int)arg; int mode = (int)arg;
...@@ -924,13 +912,9 @@ gdi_thread(void *arg) ...@@ -924,13 +912,9 @@ gdi_thread(void *arg)
fullscreen = false; fullscreen = false;
} }
stype = ciolib_initial_scaling_type; stype = ciolib_initial_scaling_type;
// Now make the inside of the window the size we want (sigh)
r.left = r.top = 0;
r.right = vstat.winwidth - 1;
r.bottom = vstat.winheight - 1;
pthread_mutex_unlock(&vstatlock); pthread_mutex_unlock(&vstatlock);
gdiAdjustWindowRect(&r, STYLE, FALSE, 0); gdi_get_windowsize_at_dpi(false, &w, &h, 0);
win = CreateWindowW(wc.lpszClassName, L"SyncConsole", STYLE, wx, wy, r.right - r.left + 1, r.bottom - r.top + 1, NULL, NULL, NULL, NULL); win = CreateWindowW(wc.lpszClassName, L"SyncConsole", STYLE, wx, wy, w, h, NULL, NULL, NULL, NULL);
if (win == NULL) if (win == NULL)
goto fail; goto fail;
if (cio_api.options & CONIO_OPT_DISABLE_CLOSE) if (cio_api.options & CONIO_OPT_DISABLE_CLOSE)
...@@ -1026,7 +1010,7 @@ gdi_settitle(const char *newTitle) ...@@ -1026,7 +1010,7 @@ gdi_settitle(const char *newTitle)
{ {
LPWSTR utf16; LPWSTR utf16;
utf16 = utf8_to_utf16(newTitle, -1); utf16 = utf8_to_utf16((const uint8_t *)newTitle, -1);
if (utf16 != NULL) { if (utf16 != NULL) {
SetWindowTextW(win, utf16); SetWindowTextW(win, utf16);
free(utf16); free(utf16);
...@@ -1097,7 +1081,7 @@ gdi_copytext(const char *text, size_t buflen) ...@@ -1097,7 +1081,7 @@ gdi_copytext(const char *text, size_t buflen)
LPWSTR clipStr; LPWSTR clipStr;
HGLOBAL clipBuf; HGLOBAL clipBuf;
utf16 = utf8_to_utf16(text, buflen); utf16 = utf8_to_utf16((const uint8_t *)text, buflen);
if (utf16 != NULL) { if (utf16 != NULL) {
if (OpenClipboard(NULL)) { if (OpenClipboard(NULL)) {
EmptyClipboard(); EmptyClipboard();
...@@ -1129,7 +1113,7 @@ gdi_getcliptext(void) ...@@ -1129,7 +1113,7 @@ gdi_getcliptext(void)
if (dat != NULL) { if (dat != NULL) {
datstr = GlobalLock(dat); datstr = GlobalLock(dat);
if (datstr != NULL) { if (datstr != NULL) {
ret = utf16_to_utf8(datstr); ret = (char *)utf16_to_utf8(datstr);
GlobalUnlock(dat); GlobalUnlock(dat);
} }
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment