diff --git a/changelog.txt b/changelog.txt index ab6bb91..dd62c89 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,12 @@ ## v0.01.005 + - Window + - Added bool window.fullscreen + - Added bool window.allow_resize + - Reworked window initialization + Window now starts of invisible and is made visible on first os_update(). + This also gets rid of the weird window resize and reposition at startup. + ## v0.01.004 - Gamepad input, text wrapping, bug fixes - Input diff --git a/oogabooga/examples/minimal_game_loop.c b/oogabooga/examples/minimal_game_loop.c index df11635..b09f51d 100644 --- a/oogabooga/examples/minimal_game_loop.c +++ b/oogabooga/examples/minimal_game_loop.c @@ -7,7 +7,8 @@ int entry(int argc, char **argv) { window.x = 200; window.y = 90; window.clear_color = hex_to_rgba(0x6495EDff); - + window.allow_resize = true; + float64 last_time = os_get_elapsed_seconds(); while (!window.should_close) { reset_temporary_storage(); @@ -29,6 +30,10 @@ int entry(int argc, char **argv) { draw_line(v2(-.75, -.75), v2(mx, my), 0.005, COLOR_WHITE); + if (is_key_just_pressed('F')) { + window.fullscreen = !window.fullscreen; + } + os_update(); gfx_update(); } diff --git a/oogabooga/gfx_impl_d3d11.c b/oogabooga/gfx_impl_d3d11.c index 2401c72..58b8084 100644 --- a/oogabooga/gfx_impl_d3d11.c +++ b/oogabooga/gfx_impl_d3d11.c @@ -231,29 +231,19 @@ void d3d11_update_swapchain() { if (d3d11_window_render_target_view) D3D11Release(d3d11_window_render_target_view); if (d3d11_back_buffer) D3D11Release(d3d11_back_buffer); - RECT client_rect; - bool ok = GetClientRect(window._os_handle, &client_rect); - assert(ok, "GetClientRect failed with error code %lu", GetLastError()); - - u32 window_width = client_rect.right-client_rect.left; - u32 window_height = client_rect.bottom-client_rect.top; - - hr = IDXGISwapChain1_ResizeBuffers(d3d11_swap_chain, d3d11_swap_chain_desc.BufferCount, window_width, window_height, d3d11_swap_chain_desc.Format, d3d11_swap_chain_desc.Flags); + hr = IDXGISwapChain1_ResizeBuffers(d3d11_swap_chain, d3d11_swap_chain_desc.BufferCount, window.pixel_width, window.pixel_height, d3d11_swap_chain_desc.Format, d3d11_swap_chain_desc.Flags); d3d11_check_hr(hr); // update swap chain description hr = IDXGISwapChain1_GetDesc1(d3d11_swap_chain, &d3d11_swap_chain_desc); d3d11_check_hr(hr); - log("Resized swap chain from %dx%d to %dx%d", d3d11_swap_chain_width, d3d11_swap_chain_height, window_width, window_height); + log("Resized swap chain from %dx%d to %dx%d", d3d11_swap_chain_width, d3d11_swap_chain_height, window.pixel_width, window.pixel_height); - d3d11_swap_chain_width = window_width; - d3d11_swap_chain_height = window_height; + d3d11_swap_chain_width = window.pixel_width; + d3d11_swap_chain_height = window.pixel_height; } - - - hr = IDXGISwapChain1_GetBuffer(d3d11_swap_chain, 0, &IID_ID3D11Texture2D, (void**)&d3d11_back_buffer); d3d11_check_hr(hr); hr = ID3D11Device_CreateRenderTargetView(d3d11_device, (ID3D11Resource*)d3d11_back_buffer, 0, &d3d11_window_render_target_view); @@ -858,12 +848,7 @@ void gfx_update() { HRESULT hr; /// // Maybe resize swap chain - RECT client_rect; - bool ok = GetClientRect(window._os_handle, &client_rect); - assert(ok, "GetClientRect failed with error code %lu", GetLastError()); - u32 window_width = client_rect.right-client_rect.left; - u32 window_height = client_rect.bottom-client_rect.top; - if (window_width != d3d11_swap_chain_width || window_height != d3d11_swap_chain_height) { + if (window.pixel_width != d3d11_swap_chain_width || window.pixel_height != d3d11_swap_chain_height) { d3d11_update_swapchain(); } diff --git a/oogabooga/os_impl_windows.c b/oogabooga/os_impl_windows.c index 41a5c56..c524684 100644 --- a/oogabooga/os_impl_windows.c +++ b/oogabooga/os_impl_windows.c @@ -113,6 +113,15 @@ SYSTEM_INFO win32_system_info; LARGE_INTEGER win32_counter_at_start; bool win32_do_handle_raw_input = false; HANDLE win32_xinput = 0; +bool has_os_update_been_called_at_all = false; + +// Used to save windowed state when in fullscreen mode. +DWORD win32_windowed_style = 0; +DWORD win32_windowed_style_ex = 0; +s32 win32_windowed_x = 0; +s32 win32_windowed_y = 0; +s32 win32_windowed_width = 0; +s32 win32_windowed_height = 0; // impl input.c const u64 MAX_NUMBER_OF_GAMEPADS = XUSER_MAX_COUNT; @@ -319,15 +328,15 @@ win32_init_window() { RECT rect = {0, 0, window.width, window.height}; DWORD style = WS_OVERLAPPEDWINDOW; - DWORD ex_style = WS_EX_CLIENTEDGE; - ok = AdjustWindowRectEx(&rect, style, FALSE, ex_style); + DWORD style_ex = WS_EX_CLIENTEDGE; + ok = AdjustWindowRectEx(&rect, style, FALSE, style_ex); assert(ok != 0, "AdjustWindowRectEx failed with error code %lu", GetLastError()); u32 actual_window_width = rect.right - rect.left; u32 actual_window_height = rect.bottom - rect.top; // Create the window window._os_handle = CreateWindowEx( - ex_style, + style_ex, "sigma balls", temp_convert_to_null_terminated_string(window.title), style, @@ -335,8 +344,14 @@ win32_init_window() { 0, 0, instance, 0); assert(window._os_handle != 0, "Window creation failed, error: %lu", GetLastError()); window._initialized = true; - ShowWindow(window._os_handle, SW_SHOWDEFAULT); + window.allow_resize = true; UpdateWindow(window._os_handle); + + ShowWindow(window._os_handle, SW_HIDE); + style = GetWindowLong(window._os_handle, GWL_EXSTYLE); + style &= ~WS_EX_APPWINDOW; // Remove from taskbar + style |= WS_EX_TOOLWINDOW; // Make it a tool window + SetWindowLong(window._os_handle, GWL_EXSTYLE, style); } void @@ -482,15 +497,26 @@ BOOL win32_query_monitors_callback(HMONITOR monitor_handle, HDC dc, LPRECT rect, GetDpiForMonitor(monitor_handle, MDT_EFFECTIVE_DPI, (UINT*)&monitor->dpi, (UINT*)&monitor->dpi_y); + if (monitor_handle == MonitorFromWindow(window._os_handle, MONITOR_DEFAULTTONEAREST)) { + window.monitor = monitor; + } + return TRUE; } void win32_query_monitors() { + + window.monitor = 0; + if (os.monitors) growing_array_clear((void**)&os.monitors); else growing_array_init((void**)&os.monitors, sizeof(Os_Monitor), get_heap_allocator()); EnumDisplayMonitors(0, 0, win32_query_monitors_callback, 0); os.number_of_connected_monitors = growing_array_get_valid_count(os.monitors); + + if (!window.monitor) { + window.monitor = os.primary_monitor; + } } void s64_to_null_terminated_string_reverse(char str[], int length) @@ -1847,26 +1873,51 @@ void set_specific_gamepad_vibration(u64 gamepad_index, float32 left, float32 rig void os_update() { + + // Only show window after first call to os_update + if (!has_os_update_been_called_at_all) { + ShowWindow(window._os_handle, SW_SHOW); + DWORD style = GetWindowLong(window._os_handle, GWL_EXSTYLE); + style &= ~WS_EX_TOOLWINDOW; + style |= WS_EX_APPWINDOW; + SetWindowLong(window._os_handle, GWL_EXSTYLE, style); + } + + has_os_update_been_called_at_all = true; + win32_do_handle_raw_input = true; #ifndef OOGABOOGA_HEADLESS UINT dpi = GetDpiForWindow(window._os_handle); float dpi_scale_factor = dpi / 96.0f; local_persist Os_Window last_window; - + + // + // Window title if (!strings_match(last_window.title, window.title)) { SetWindowText(window._os_handle, temp_convert_to_null_terminated_string(window.title)); } + // + // Window sizing & position + + if (window.fullscreen && last_window.fullscreen) { + window.pixel_width = window.monitor->resolution_x; + window.pixel_height = window.monitor->resolution_y; + window.x = 0; + window.y = 0; + } + + BOOL ok; + DWORD style = (DWORD)GetWindowLong(window._os_handle, GWL_STYLE); + DWORD style_ex = (DWORD)GetWindowLong(window._os_handle, GWL_EXSTYLE); + int screen_height = os.primary_monitor->resolution_y; + if (last_window.scaled_width != window.scaled_width || last_window.scaled_height != window.scaled_height) { window.width = window.scaled_width*dpi_scale_factor; window.height = window.scaled_height*dpi_scale_factor; } - BOOL ok; - int screen_height = GetSystemMetrics(SM_CYSCREEN); - DWORD style = (DWORD)GetWindowLong(window._os_handle, GWL_STYLE); - DWORD ex_style = (DWORD)GetWindowLong(window._os_handle, GWL_EXSTYLE); if (last_window.x != window.x || last_window.y != window.y || last_window.width != window.width || last_window.height != window.height) { RECT update_rect; update_rect.left = window.x; @@ -1874,7 +1925,7 @@ void os_update() { update_rect.top = window.y; update_rect.bottom = window.y + window.height; - BOOL ok = AdjustWindowRectEx(&update_rect, style, FALSE, ex_style); + BOOL ok = AdjustWindowRectEx(&update_rect, style, FALSE, style_ex); assert(ok != 0, "AdjustWindowRectEx failed with error code %lu", GetLastError()); u32 actual_width = update_rect.right - update_rect.left; @@ -1884,13 +1935,12 @@ void os_update() { SetWindowPos(window._os_handle, 0, actual_x, actual_y, actual_width, actual_height, SWP_NOZORDER | SWP_NOACTIVATE); } - RECT client_rect; ok = GetClientRect(window._os_handle, &client_rect); assert(ok, "GetClientRect failed with error code %lu", GetLastError()); RECT adjusted_rect = client_rect; - ok = AdjustWindowRectEx(&adjusted_rect, style, FALSE, ex_style); + ok = AdjustWindowRectEx(&adjusted_rect, style, FALSE, style_ex); assert(ok != 0, "AdjustWindowRectEx failed with error code %lu", GetLastError()); RECT window_rect; @@ -1927,8 +1977,51 @@ void os_update() { window.scaled_width = (u32)((bottom_right.x - top_left.x) * dpi_scale_factor); window.scaled_height = (u32)((bottom_right.y - top_left.y) * dpi_scale_factor); + if (last_window.allow_resize != window.allow_resize) { + if (window.allow_resize) style |= WS_SIZEBOX; + else style &= ~(WS_SIZEBOX); + SetWindowLongW(window._os_handle, GWL_STYLE, style); + } + + bool last_fullscreen = last_window.fullscreen; last_window = window; + // + // Fullscreen + + if (last_fullscreen != window.fullscreen) { + + if (window.fullscreen) { + + // Save windowed state + win32_windowed_style = style; + win32_windowed_style_ex = style_ex; + win32_windowed_x = window.x; + win32_windowed_y = window.y; + win32_windowed_width = window.width; + win32_windowed_height = window.height; + + SetWindowLongW(window._os_handle, GWL_STYLE, style & ~(WS_CAPTION | WS_THICKFRAME)); + SetWindowLongW(window._os_handle, GWL_EXSTYLE, + style_ex & ~(WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE) + ); + + } else { + + // Restore windowed_state + style = win32_windowed_style; + style_ex = win32_windowed_style_ex; + window.x = win32_windowed_x; + window.y = win32_windowed_y; + window.width = win32_windowed_width; + window.height = win32_windowed_height; + + SetWindowLongW(window._os_handle, GWL_STYLE, win32_windowed_style); + SetWindowLongW(window._os_handle, GWL_EXSTYLE, win32_windowed_style_ex); + } + } + + // Reflect what the user layer did to input state before we query for OS inputs memcpy(win32_key_states, input_frame.key_states, sizeof(input_frame.key_states)); diff --git a/oogabooga/os_interface.c b/oogabooga/os_interface.c index ba5344e..6b492a1 100644 --- a/oogabooga/os_interface.c +++ b/oogabooga/os_interface.c @@ -75,6 +75,8 @@ typedef struct Os_Window { s32 y; Vector4 clear_color; bool enable_vsync; + bool fullscreen; + bool allow_resize; bool should_close; @@ -82,6 +84,8 @@ typedef struct Os_Window { bool _initialized; Window_Handle _os_handle; + Os_Monitor *monitor; + } Os_Window; // #Global @@ -90,8 +94,8 @@ ogb_instance Os_Context os; #if !OOGABOOGA_LINK_EXTERNAL_INSTANCE -Os_Context os; -Os_Window window; +Os_Context os = ZERO(Os_Context); +Os_Window window = ZERO(Os_Window); #endif // NOT OOGABOOGA_LINK_EXTERNAL_INSTANCE