diff --git a/kauai/src/appb.h b/kauai/src/appb.h index 1068e660..e7e9267a 100644 --- a/kauai/src/appb.h +++ b/kauai/src/appb.h @@ -25,6 +25,10 @@ typedef MSG EVT; #ifdef KAUAI_SDL typedef SDL_Event EVT; + +// Logical size +const uint32_t kdxpLogical = 640; +const uint32_t kdypLogical = 480; #endif // KAUAI_SDL #ifdef MAC diff --git a/kauai/src/appbsdl.cpp b/kauai/src/appbsdl.cpp index 79d2d80e..119ad015 100644 --- a/kauai/src/appbsdl.cpp +++ b/kauai/src/appbsdl.cpp @@ -23,10 +23,6 @@ const uint32_t kdtsIdleTimer = 1; // FUTURE: Get this from the system const uint32_t kdtsDoubleClick = 500; -// Window size -const uint32_t kdxpWindow = 640; -const uint32_t kdypWindow = 480; - static SDL_Cursor *vpsdlcursWait = pvNil; static SDL_Cursor *vpsdlcursArrow = pvNil; @@ -108,17 +104,13 @@ bool APPB::_FInitOS(void) stnApp.GetUtf8Sz(u8szApp); int32_t xpWindow = SDL_WINDOWPOS_UNDEFINED; int32_t ypWindow = SDL_WINDOWPOS_UNDEFINED; - SDL_Window *wnd = SDL_CreateWindow(u8szApp, xpWindow, ypWindow, kdxpWindow, kdypWindow, 0); + SDL_Window *wnd = SDL_CreateWindow(u8szApp, xpWindow, ypWindow, kdxpLogical, kdypLogical, 0); Assert(wnd != pvNil, "no window returned from SDL_CreateWindow"); if (wnd == pvNil) { return fFalse; } - // Create a renderer - SDL_Renderer *rdr = SDL_CreateRenderer(wnd, -1, 0); - Assert(rdr != pvNil, "no renderer created from SDL_CreateRenderer"); - vwig.hwndApp = wnd; // FUTURE: Turn this off when Win32 stuff is removed @@ -222,6 +214,11 @@ void APPB::TrackMouse(PGOB pgob, PT *ppt) { // No mouse move events: just get the current position instead int state = SDL_GetMouseState(&xp, &yp); + SDL_Renderer *rdr = SDL_GetRenderer((SDL_Window *)vwig.hwndApp); + float flx, fly; + SDL_RenderWindowToLogical(rdr, xp, yp, &flx, &fly); + xp = (int)flx; + yp = (int)fly; if (state & SDL_BUTTON(1)) { grfcust |= fcustMouse; @@ -828,9 +825,20 @@ void APPB::ShowCurs(void) ***************************************************************************/ void APPB::PositionCurs(int32_t xpScreen, int32_t ypScreen) { - AssertThis(0); + SDL_Renderer *rdr; + float flxp, flyp; + int xp, yp; + PT pt; - SDL_WarpMouseGlobal(xpScreen, ypScreen); + // Convert coordinates back from screen (global) coordinates to local (window) + // coordinates and use SDL_WarpMouseInWindow() instead of SDL_WarpMouseGlobal() + // so we can apply the logical to window coordinate transformation. + pt.xp = xpScreen; + pt.yp = ypScreen; + GOB::PgobScreen()->MapPt(&pt, cooGlobal, cooLocal); + rdr = SDL_GetRenderer((SDL_Window *)vwig.hwndApp); + SDL_RenderLogicalToWindow(rdr, (float)pt.xp, (float)pt.yp, &xp, &yp); + SDL_WarpMouseInWindow((SDL_Window *)vwig.hwndApp, xp, yp); if (_fFlushCursor) { diff --git a/kauai/src/gfx.h b/kauai/src/gfx.h index 090d0f23..5623863d 100644 --- a/kauai/src/gfx.h +++ b/kauai/src/gfx.h @@ -796,6 +796,8 @@ class GPT : public GPT_PAR void InvalidateTexture(void); // Copy contents of surface to texture void UpdateTexture(void); + // Rebuild texture e.g. due to a change in window size + void RebuildTexture(void); // Save contents of this GPT to a bitmap for debugging void DumpBitmap(STN *stnBmp); diff --git a/kauai/src/gfxsdl.cpp b/kauai/src/gfxsdl.cpp index fdff96b7..a136bc90 100644 --- a/kauai/src/gfxsdl.cpp +++ b/kauai/src/gfxsdl.cpp @@ -142,15 +142,8 @@ PGPT GPT::PgptNew(SDL_Window *wnd, int cbitPixel, bool fOffscreen, int dxp, int return pvNil; pgpt->_wnd = wnd; - pgpt->_renderer = SDL_GetRenderer(wnd); - Assert(pgpt->_renderer != pvNil, "no renderer"); pgpt->_fOffscreen = fOffscreen; - // get drawable size - if (!fOffscreen) - { - AssertDoSDL(SDL_GetRendererOutputSize(pgpt->_renderer, &dxp, &dyp)); - } Assert(dxp != 0, "dxp must be > 0"); Assert(dyp != 0, "dyp must be > 0"); @@ -170,13 +163,6 @@ PGPT GPT::PgptNew(SDL_Window *wnd, int cbitPixel, bool fOffscreen, int dxp, int AssertDoSDL(SDL_SetSurfacePalette(pgpt->_surface, _pal)); } - // Create a texture that is used for rendering - pgpt->_texture = - SDL_CreateTexture(pgpt->_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, dxp, dyp); - Assert(pgpt->_texture, "SDL_CreateTexture failed"); - - pgpt->InvalidateTexture(); - return pgpt; } @@ -188,7 +174,8 @@ PGPT GPT::PgptNewHwnd(KWND hwnd) Assert(kwndNil != hwnd, "Null hwnd"); Assert(pvNil != ((SDL_Window *)hwnd), "Not an SDL window"); PGPT pgpt; - if (pvNil == (pgpt = PgptNew((SDL_Window *)hwnd, 32, fFalse, 0, 0))) + + if (pvNil == (pgpt = PgptNew((SDL_Window *)hwnd, 32, fFalse, kdxpLogical, kdypLogical))) { return pvNil; } @@ -287,6 +274,31 @@ void GPT::UpdateTexture() } } +void GPT::RebuildTexture(void) +{ + // Free the existing texture + if (_texture != pvNil) + SDL_DestroyTexture(_texture); + + // Free the existing renderer + if (_renderer != pvNil) + SDL_DestroyRenderer(_renderer); + + // Create a renderer + _renderer = SDL_CreateRenderer(_wnd, -1, 0); + Assert(_renderer != pvNil, "no renderer created from SDL_CreateRenderer"); + AssertDoSDL(SDL_RenderClear(_renderer)); + AssertDoSDL(SDL_RenderSetLogicalSize(_renderer, kdxpLogical, kdypLogical)); + + // Create a new texture + _texture = + SDL_CreateTexture(_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, kdxpLogical, kdypLogical); + Assert(_texture, "SDL_CreateTexture failed"); + + InvalidateTexture(); + Flip(); +} + void GPT::DumpBitmap(STN *stnBmp) { U8SZ u8szFilePath; @@ -1105,7 +1117,6 @@ void GPT::Flip() Assert(!_fOffscreen, "drawing an offscreen GPT to the screen?"); // Paint the texture - AssertDoSDL(SDL_RenderClear(_renderer)); AssertDoSDL(SDL_RenderCopy(_renderer, _texture, NULL, NULL)); SDL_RenderPresent(_renderer); } diff --git a/kauai/src/gob.cpp b/kauai/src/gob.cpp index 2a674411..2ed1d662 100644 --- a/kauai/src/gob.cpp +++ b/kauai/src/gob.cpp @@ -1030,13 +1030,19 @@ KWND GOB::_HwndGetDptFromCoo(PT *pdpt, int32_t coo) ClientToScreen(hwnd, &pts); #elif defined(KAUAI_SDL) // FIXME MCA: is this correct? + SDL_Renderer *rdr; + float fxp, fyp; int xpWnd, ypWnd; PTS pts; Assert(hwnd == vwig.hwndApp, "We should only have one window"); pts = *pdpt; + rdr = SDL_GetRenderer((SDL_Window *)hwnd); SDL_GetWindowPosition((SDL_Window *)hwnd, &xpWnd, &ypWnd); + SDL_RenderWindowToLogical(rdr, xpWnd, ypWnd, &fxp, &fyp); + xpWnd = (int)fxp; + ypWnd = (int)fyp; pts.xp += xpWnd; pts.yp += ypWnd; @@ -1090,8 +1096,14 @@ PGOB GOB::PgobFromPtGlobal(int32_t xp, int32_t yp, PT *pptLocal) ScreenToClient(hwnd, &pts); #elif defined(KAUAI_SDL) PTS pts; + float fxp, fyp; int xpWnd, ypWnd; + SDL_Renderer *rdr = SDL_GetRenderer((SDL_Window *)vwig.hwndApp); + SDL_GetWindowPosition((SDL_Window *)vwig.hwndApp, &xpWnd, &ypWnd); + SDL_RenderWindowToLogical(rdr, xpWnd, ypWnd, &fxp, &fyp); + xpWnd = (int)fxp; + ypWnd = (int)fyp; pts.xp = xp - xpWnd; pts.yp = yp - ypWnd; @@ -1252,10 +1264,9 @@ void GOB::_SetRcCur(void) GetClientRect(pgob->_hwnd, &rcs); rc = rcs; #elif defined(KAUAI_SDL) - int dxpClient = 0, dypClient = 0; - SDL_GetWindowSize((SDL_Window *)pgob->_hwnd, &dxpClient, &dypClient); - Assert(dxpClient > 0 && dypClient > 0, "SDL_GetWindowSize failed?"); - rc.Set(0, 0, dxpClient, dypClient); + // The rectangle is always the same as that of the logical application + // since logical coordinates are independent of window size + rc.Set(0, 0, kdxpLogical, kdypLogical); #else #error not implemented #endif diff --git a/kauai/src/gobsdl.cpp b/kauai/src/gobsdl.cpp index be58a29c..965b64e6 100644 --- a/kauai/src/gobsdl.cpp +++ b/kauai/src/gobsdl.cpp @@ -54,6 +54,7 @@ bool GOB::FAttachHwnd(KWND hwnd) { if (pvNil == (_pgpt = GPT::PgptNewHwnd(hwnd))) return fFalse; + _pgpt->RebuildTexture(); _hwnd = hwnd; SetRcFromHwnd(); } @@ -126,7 +127,12 @@ void GOB::GetPtMouse(PT *ppt, bool *pfDown) AssertThis(0); int xp = 0, yp = 0; + float fxp, fyp; + SDL_Renderer *rdr = SDL_GetRenderer((SDL_Window *)vwig.hwndApp); int mouseState = SDL_GetMouseState(&xp, &yp); + SDL_RenderWindowToLogical(rdr, xp, yp, &fxp, &fyp); + xp = (int)fxp; + yp = (int)fyp; if (ppt != pvNil) { @@ -194,4 +200,4 @@ bool GOB::FCreateAndAttachMdi(PSTN pstnTitle) // SDL does not support MDI RawRtn(); return fFalse; -} \ No newline at end of file +} diff --git a/src/studio/configini.cpp b/src/studio/configini.cpp index 5bee5c0a..69a4cf50 100644 --- a/src/studio/configini.cpp +++ b/src/studio/configini.cpp @@ -220,6 +220,13 @@ bool FGetSetRegKey(PCSZ pszValueName, void *pvData, int32_t cbData, uint32_t grf grfregNew &= ~fregSetDefault; fRet = FGetSetRegKey(pszValueName, pvData, cbData, grfregNew, pfNoValue); } + else + { + /* If the caller gave us a way to differentiate a genuine registry + failure from simply not having set the value yet, do so */ + if (pfNoValue != pvNil) + fRet = fTrue; + } } if (pfNoValue) diff --git a/src/studio/utest.cpp b/src/studio/utest.cpp index 507a65ad..a46fa795 100644 --- a/src/studio/utest.cpp +++ b/src/studio/utest.cpp @@ -939,7 +939,16 @@ bool APP::_FDisplayIs640480(void) #ifdef WIN return (GetSystemMetrics(SM_CXSCREEN) == 640 && GetSystemMetrics(SM_CYSCREEN) == 480); #else // !WIN - return fFalse; + int w, h; + + if (vwig.hwndApp == pvNil) + return fFalse; + + SDL_GetWindowSize(vwig.hwndApp, &w, &h); + + // This is actually correct, since on Windows the screen upscaling is done by switching + // the video controller into 640x480 mode to fill the screen. + return (w != kdxpLogical && h != kdypLogical); #endif // WIN } @@ -950,6 +959,9 @@ bool APP::_FInitOS(void) { AssertBaseThis(0); + if (_fMainWindowCreated) // If someone else called _FInitOS already, + return fTrue; // we can leave + #if defined(KAUAI_SDL) if (!(FPure(APP_PAR::_FInitOS()))) @@ -967,9 +979,6 @@ bool APP::_FInitOS(void) uint32_t dwStyle = 0; STN stnWindowTitle; - if (_fMainWindowCreated) // If someone else called _FInitOS already, - return fTrue; // we can leave - if (!FGetStnApp(idsWindowTitle, &stnWindowTitle)) return fFalse; @@ -3530,8 +3539,8 @@ bool APP::_FDisplaySwitchSupported(void) // We can no longer compile for Windows platforms that do not support screen resolution changes. return fTrue; #else - // OS doesn't support res-switching - return fFalse; + // SDL does support res-switching via upscaling + return fTrue; #endif // WIN } @@ -3632,8 +3641,39 @@ bool APP::_FSwitch640480(bool fTo640480) LFail: if (0 != hLibrary) FreeLibrary(hLibrary); +#else // KAUAI_WIN32 + PGOB pgobScreen = GOB::PgobScreen(); + int32_t fSwitchRes = !_fRunInWindow; + + if (fTo640480) + { + SDL_SetWindowFullscreen((SDL_Window *)vwig.hwndApp, SDL_WINDOW_FULLSCREEN_DESKTOP); + + if (pgobScreen != pvNil) + { + PGPT pgpt = pgobScreen->Pgpt(); + + pgpt->RebuildTexture(); + } + + _fSwitchedResolution = fTrue; + } + else + { + SDL_SetWindowFullscreen((SDL_Window *)vwig.hwndApp, 0); + + if (pgobScreen != pvNil) + { + PGPT pgpt = pgobScreen->Pgpt(); + + pgpt->RebuildTexture(); + } + } + + FGetSetRegKey(kszSwitchResolutionValue, &fSwitchRes, SIZEOF(fSwitchRes), fregSetKey); + + return fTrue; #endif // KAUAI_WIN32 - return fFalse; } bool APP::_FSetRunInWindow(bool fRunInWindowNew)