From 0be004e8ea42ecf358de396b29e30450f7407d6b Mon Sep 17 00:00:00 2001 From: Xottab-DUTY Date: Mon, 23 Jul 2018 00:08:04 +0500 Subject: [PATCH] Allow window dragging by ALT+WIN combination Console command center_screen that centers game window on execute Dropped support for -draw_borders command line key --- src/xrEngine/Device_Initialize.cpp | 60 +++++++++++++++++++++-- src/xrEngine/Device_create.cpp | 76 ++++++++++-------------------- src/xrEngine/device.cpp | 9 ++-- src/xrEngine/device.h | 9 ++-- src/xrEngine/xr_input.cpp | 7 +-- src/xrEngine/xr_ioc_cmd.cpp | 11 +++++ src/xrGame/MainMenu.cpp | 17 +++++++ src/xrGame/UICursor.cpp | 2 +- 8 files changed, 122 insertions(+), 69 deletions(-) diff --git a/src/xrEngine/Device_Initialize.cpp b/src/xrEngine/Device_Initialize.cpp index ff8b109ca66..2f60fad85cb 100644 --- a/src/xrEngine/Device_Initialize.cpp +++ b/src/xrEngine/Device_Initialize.cpp @@ -8,6 +8,8 @@ #include "PerformanceAlert.hpp" #include "xrCore/ModuleLookup.hpp" +SDL_HitTestResult WindowHitTest(SDL_Window* win, const SDL_Point* area, void* data); + void CRenderDevice::initialize_weather_editor() { m_editor_module = XRay::LoadModule("xrWeatherEditor"); @@ -43,14 +45,14 @@ void CRenderDevice::Initialize() if (!m_sdlWnd) { - Uint32 flags = SDL_WINDOW_BORDERLESS | SDL_WINDOW_HIDDEN | SDL_WINDOW_OPENGL; -#if SDL_VERSION_ATLEAST(2, 0, 5) - flags |= SDL_WINDOW_ALWAYS_ON_TOP; -#endif + const Uint32 flags = SDL_WINDOW_BORDERLESS | SDL_WINDOW_HIDDEN | + SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALWAYS_ON_TOP | SDL_WINDOW_OPENGL; - m_sdlWnd = SDL_CreateWindow("S.T.A.L.K.E.R.: Call of Pripyat", 0, 0, 0, 0, flags); + m_sdlWnd = SDL_CreateWindow("S.T.A.L.K.E.R.: Call of Pripyat", 0, 0, 256, 192, flags); R_ASSERT3(m_sdlWnd, "Unable to create SDL window", SDL_GetError()); + SDL_SetWindowHitTest(m_sdlWnd, WindowHitTest, nullptr); + SDL_SetWindowMinimumSize(m_sdlWnd, 256, 192); } } @@ -62,3 +64,51 @@ void CRenderDevice::DumpStatistics(IGameFont& font, IPerformanceAlert* alert) if (alert && stats.fFPS < 30) alert->Print(font, "FPS < 30: %3.1f", stats.fFPS); } + +SDL_HitTestResult WindowHitTest(SDL_Window* /*window*/, const SDL_Point* area, void* /*data*/) +{ + const auto& rect = Device.m_rcWindowClient; + + // size of additional interactive area (in pixels) + constexpr int hit = 15; + + const bool leftSide = area->x < rect.x + hit; + const bool topSide = area->y < rect.y + hit; + const bool bottomSide = area->y > rect.h - hit; + const bool rightSide = area->x > rect.w - hit; + + if (leftSide && topSide) + return SDL_HITTEST_RESIZE_TOPLEFT; + + if (rightSide && topSide) + return SDL_HITTEST_RESIZE_TOPRIGHT; + + if (rightSide && bottomSide) + return SDL_HITTEST_RESIZE_BOTTOMRIGHT; + + if (leftSide && bottomSide) + return SDL_HITTEST_RESIZE_BOTTOMLEFT; + + if (topSide) + return SDL_HITTEST_RESIZE_TOP; + + if (rightSide) + return SDL_HITTEST_RESIZE_RIGHT; + + if (bottomSide) + return SDL_HITTEST_RESIZE_BOTTOM; + + if (leftSide) + return SDL_HITTEST_RESIZE_LEFT; + + const int centerX = rect.w / 2; + const int centerY = rect.h / 2; + + // Allow drag from any point except window center + // For this case, 'hit' is a size of a square in the center + if ((area->x > centerX + hit || area->x < centerX - hit) + && (area->y > centerY + hit || area->y < centerY - hit)) + return SDL_HITTEST_DRAGGABLE; + + return SDL_HITTEST_NORMAL; +} diff --git a/src/xrEngine/Device_create.cpp b/src/xrEngine/Device_create.cpp index 59aa107b153..e8e3b7b681b 100644 --- a/src/xrEngine/Device_create.cpp +++ b/src/xrEngine/Device_create.cpp @@ -58,7 +58,6 @@ void CRenderDevice::Create() psDeviceFlags.set(rsFullscreen, false); FillVidModesToken(Vid_SelectedMonitor); - SelectResolution(!psDeviceFlags.is(rsFullscreen)); UpdateWindowProps(!psDeviceFlags.is(rsFullscreen)); GEnv.Render->Create(m_sdlWnd, dwWidth, dwHeight, fWidth_2, fHeight_2); @@ -73,49 +72,20 @@ void CRenderDevice::Create() PreCache(0, false, false); } -void CRenderDevice::UpdateWindowProps(bool windowed) +void CRenderDevice::UpdateWindowProps(const bool windowed) { SelectResolution(windowed); SDL_SetWindowFullscreen(m_sdlWnd, windowed ? 0 : SDL_WINDOW_FULLSCREEN); - SDL_Rect rect; // Set window properties depending on what mode were in. if (windowed) - { - const bool drawBorders = strstr(Core.Params, "-draw_borders"); - if (drawBorders) - SDL_SetWindowBordered(m_sdlWnd, SDL_TRUE); - SDL_SetWindowSize(m_sdlWnd, psCurrentVidMode[0], psCurrentVidMode[1]); - - if (GEnv.isDedicatedServer || strstr(Core.Params, "-center_screen")) - SDL_SetWindowPosition(m_sdlWnd, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED); - else - { - SDL_GetDisplayUsableBounds(Vid_SelectedMonitor, &rect); - - int top = 0, left = 0, right = 0, bottom = 0; - // SDL_GetWindowBordersSize(m_sdlWnd, &top, &left, &bottom, &right); -#ifdef WINDOWS - // XXX: Currently SDL_GetWindowBordersSize is supported only on X11 - // For now we must use method below. - if (drawBorders) - top = GetSystemMetrics(SM_CYCAPTION); // size of the window title bar -#else -#pragma TODO("Implement for other platforms") -#endif - SDL_SetWindowPosition(m_sdlWnd, rect.x + left, rect.y + top); - } - - SDL_GetWindowPosition(m_sdlWnd, &m_rcWindowClient.x, &m_rcWindowClient.y); - int w = 0, h = 0; - SDL_GetWindowSize(m_sdlWnd, &w, &h); - m_rcWindowClient.w = m_rcWindowClient.x + w; - m_rcWindowClient.h = m_rcWindowClient.y + h; - } else { + // XXX: fix monitor selection + // it appears to be buggy + SDL_Rect rect; SDL_GetDisplayBounds(Vid_SelectedMonitor, &rect); SDL_SetWindowPosition(m_sdlWnd, rect.x, rect.y); SDL_DisplayMode mode; @@ -126,31 +96,35 @@ void CRenderDevice::UpdateWindowProps(bool windowed) SDL_SetWindowDisplayMode(m_sdlWnd, &mode); } - if (!GEnv.isDedicatedServer) - SDL_SetWindowGrab(m_sdlWnd, SDL_TRUE); - - UpdateWindowRect(); + UpdateWindowRects(); SDL_FlushEvents(SDL_WINDOWEVENT, SDL_SYSWMEVENT); } -void CRenderDevice::UpdateWindowRect() +void CRenderDevice::UpdateWindowRects() { - SDL_GetWindowPosition(m_sdlWnd, &m_rcWindowClient.x, &m_rcWindowClient.y); + m_rcWindowClient.x = 0; + m_rcWindowClient.y = 0; SDL_GetWindowSize(m_sdlWnd, &m_rcWindowClient.w, &m_rcWindowClient.h); - m_rcWindowClient.w += m_rcWindowClient.x; - m_rcWindowClient.h += m_rcWindowClient.y; + + SDL_GetWindowPosition(m_sdlWnd, &m_rcWindowBounds.x, &m_rcWindowBounds.y); + SDL_GetWindowSize(m_sdlWnd, &m_rcWindowBounds.w, &m_rcWindowBounds.h); + m_rcWindowBounds.w += m_rcWindowBounds.x; + m_rcWindowBounds.h += m_rcWindowBounds.y; + + // Do we need code below? + int top, left, bottom, right; + SDL_GetWindowBordersSize(m_sdlWnd, &top, &left, &bottom, &right); + m_rcWindowBounds.x -= left; + m_rcWindowBounds.y -= top; + m_rcWindowBounds.w += right; + m_rcWindowBounds.h += bottom; + // XXX: check if we need this code when SDL_GetWindowBordersSize + // will be available for Windows } -void CRenderDevice::SelectResolution(bool windowed) +void CRenderDevice::SelectResolution(const bool windowed) { - if (GEnv.isDedicatedServer) - { - dwWidth = 640; - dwHeight = 480; - return; - } - if (windowed) { dwWidth = psCurrentVidMode[0]; @@ -172,7 +146,7 @@ void CRenderDevice::SelectResolution(bool windowed) if (SDL_GetClosestDisplayMode(Vid_SelectedMonitor, ¤t, &closest)) xr_sprintf(buff, sizeof(buff), "vid_mode %dx%d", closest.w, closest.h); else - xr_sprintf(buff, sizeof(buff), "vid_mode %s", VidModesToken[0].name); + xr_sprintf(buff, sizeof(buff), "vid_mode %s", VidModesToken.back()); Console->Execute(buff); } diff --git a/src/xrEngine/device.cpp b/src/xrEngine/device.cpp index 765115136be..118fa6a4c9e 100644 --- a/src/xrEngine/device.cpp +++ b/src/xrEngine/device.cpp @@ -348,7 +348,7 @@ void CRenderDevice::message_loop() switch (event.window.event) { case SDL_WINDOWEVENT_MOVED: - UpdateWindowRect(); + UpdateWindowRects(); break; case SDL_WINDOWEVENT_RESIZED: @@ -362,13 +362,12 @@ void CRenderDevice::message_loop() Reset(); } else - UpdateWindowRect(); + UpdateWindowRects(); break; } case SDL_WINDOWEVENT_SHOWN: - case SDL_WINDOWEVENT_ENTER: case SDL_WINDOWEVENT_FOCUS_GAINED: case SDL_WINDOWEVENT_RESTORED: case SDL_WINDOWEVENT_MAXIMIZED: @@ -376,7 +375,6 @@ void CRenderDevice::message_loop() break; case SDL_WINDOWEVENT_HIDDEN: - case SDL_WINDOWEVENT_LEAVE: case SDL_WINDOWEVENT_FOCUS_LOST: case SDL_WINDOWEVENT_MINIMIZED: OnWM_Activate(0, event.window.data2); @@ -418,6 +416,9 @@ void CRenderDevice::Run() seqAppStart.Process(); GEnv.Render->ClearTarget(); splash::hide(); + if (GEnv.isDedicatedServer) + SDL_SetWindowPosition(m_sdlWnd, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED); + SDL_HideWindow(m_sdlWnd); SDL_FlushEvents(SDL_WINDOWEVENT, SDL_SYSWMEVENT); SDL_ShowWindow(m_sdlWnd); SDL_RaiseWindow(m_sdlWnd); diff --git a/src/xrEngine/device.h b/src/xrEngine/device.h index fa048ef79e1..e8ffb6303f9 100644 --- a/src/xrEngine/device.h +++ b/src/xrEngine/device.h @@ -62,6 +62,9 @@ class ENGINE_API CRenderDeviceData u32 dwWidth; u32 dwHeight; + // Real application window resolution + SDL_Rect m_rcWindowBounds; + // Real game window resolution SDL_Rect m_rcWindowClient; @@ -248,9 +251,9 @@ class ENGINE_API CRenderDevice : public CRenderDeviceBase void Destroy(void); void Reset(bool precache = true); - void UpdateWindowProps(bool windowed); - void UpdateWindowRect(); - void SelectResolution(bool windowed); + void UpdateWindowProps(const bool windowed); + void UpdateWindowRects(); + void SelectResolution(const bool windowed); void Initialize(void); void ShutDown(void); diff --git a/src/xrEngine/xr_input.cpp b/src/xrEngine/xr_input.cpp index 4f439331f9d..c0f418ded12 100644 --- a/src/xrEngine/xr_input.cpp +++ b/src/xrEngine/xr_input.cpp @@ -53,8 +53,6 @@ CInput::CInput(bool exclusive, int deviceForInit) //===================== Dummy pack iCapture(&dummyController); - SDL_SetRelativeMouseMode(SDL_TRUE); - xrDebug::SetDialogHandler(on_error_dialog); #ifdef ENGINE_BUILD @@ -66,7 +64,6 @@ CInput::CInput(bool exclusive, int deviceForInit) CInput::~CInput(void) { - SDL_SetRelativeMouseMode(SDL_FALSE); #ifdef ENGINE_BUILD Device.seqFrame.Remove(this); Device.seqAppDeactivate.Remove(this); @@ -232,12 +229,12 @@ void CInput::ClipCursor(bool clip) { if (clip) { - SDL_ShowCursor(SDL_DISABLE); + SDL_SetWindowGrab(Device.m_sdlWnd, SDL_TRUE); SDL_SetRelativeMouseMode(SDL_TRUE); } else { - SDL_ShowCursor(SDL_ENABLE); + SDL_SetWindowGrab(Device.m_sdlWnd, SDL_FALSE); SDL_SetRelativeMouseMode(SDL_FALSE); } } diff --git a/src/xrEngine/xr_ioc_cmd.cpp b/src/xrEngine/xr_ioc_cmd.cpp index 2d06f140c38..f1651a5dda7 100644 --- a/src/xrEngine/xr_ioc_cmd.cpp +++ b/src/xrEngine/xr_ioc_cmd.cpp @@ -657,6 +657,16 @@ class ENGINE_API CCC_HideConsole : public IConsole_Command virtual void Info(TInfo& I) { xr_sprintf(I, sizeof(I), "hide console"); } }; +class CCC_CenterScreen : public IConsole_Command +{ +public: + CCC_CenterScreen(pcstr name) : IConsole_Command(name) { bEmptyArgsHandled = true; } + void Execute(pcstr args) override + { + SDL_SetWindowPosition(Device.m_sdlWnd, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED); + } +}; + ENGINE_API float psHUD_FOV = 0.45f; // extern int psSkeletonUpdate; @@ -787,6 +797,7 @@ void CCC_Register() CMD2(CCC_Float, "cam_inert", &psCamInert); CMD2(CCC_Float, "cam_slide_inert", &psCamSlideInert); + CMD1(CCC_CenterScreen, "center_screen"); CMD4(CCC_Integer, "always_active", &ps_always_active, 0, 1); CMD1(CCC_r2, "renderer"); diff --git a/src/xrGame/MainMenu.cpp b/src/xrGame/MainMenu.cpp index 5690865f629..556ecee9869 100644 --- a/src/xrGame/MainMenu.cpp +++ b/src/xrGame/MainMenu.cpp @@ -36,6 +36,7 @@ #include "profile_store.h" #include "stats_submitter.h" #include "atlas_submit_queue.h" +#include "xrEngine/xr_input.h" // fwd. decl. extern ENGINE_API BOOL bShowPauseString; @@ -335,6 +336,7 @@ void CMainMenu::IR_OnMouseMove(int x, int y) void CMainMenu::IR_OnMouseStop(int x, int y){}; +bool IWantMyMouseBackScreamed = false; void CMainMenu::IR_OnKeyboardPress(int dik) { if (!IsActive()) @@ -345,6 +347,14 @@ void CMainMenu::IR_OnKeyboardPress(int dik) Console->Show(); return; } + + if (pInput->iGetAsyncKeyState(SDL_SCANCODE_LALT) || pInput->iGetAsyncKeyState(SDL_SCANCODE_RALT) + && pInput->iGetAsyncKeyState(SDL_SCANCODE_LGUI) || pInput->iGetAsyncKeyState(SDL_SCANCODE_RGUI)) + { + IWantMyMouseBackScreamed = true; + pInput->ClipCursor(false); + } + if (SDL_SCANCODE_F12 == dik) { GEnv.Render->Screenshot(); @@ -359,6 +369,13 @@ void CMainMenu::IR_OnKeyboardRelease(int dik) if (!IsActive()) return; + if (IWantMyMouseBackScreamed) + { + IWantMyMouseBackScreamed = false; + pInput->ClipCursor(true); + } + + CDialogHolder::IR_UIOnKeyboardRelease(dik); }; diff --git a/src/xrGame/UICursor.cpp b/src/xrGame/UICursor.cpp index cee93e3a70b..6f6c754d70d 100644 --- a/src/xrGame/UICursor.cpp +++ b/src/xrGame/UICursor.cpp @@ -63,7 +63,7 @@ void CUICursor::InitInternal() const u32 screen_size_y = display.h - display.y; m_b_use_win_cursor = screen_size_y >= Device.dwHeight && screen_size_x >= Device.dwWidth; if (m_b_use_win_cursor) // sanity - Device.UpdateWindowRect(); + Device.UpdateWindowRects(); } //--------------------------------------------------------------------