#include "win32.h"
#include "../application/win32.h"
#include "../assert.h"
#include "../debug.h"
#include "../win32.h"
#include "../window.h"
#include <stdio.h>
#include <stdlib.h>
typedef struct {
const bw_Window* window;
bool all_dropped;
} bw_Window_DropCheckData;
LRESULT CALLBACK bw_Window_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp);
void bw_WindowWin32_calculatePositionCentered( int width, int height, int* x, int* y );
bw_Dims2D bw_Window_getContentDimensions( bw_Window* window ) {
bw_Dims2D dims;
RECT rect;
GetClientRect( window->impl.handle, &rect );
dims.width = (uint16_t)(rect.right - rect.left);
dims.height = (uint16_t)(rect.bottom - rect.top);
return dims;
}
uint8_t bw_Window_getOpacity( bw_Window* window ) {
return window->impl.opacity;
}
bw_Pos2D bw_Window_getPosition( bw_Window* window ) {
bw_Pos2D pos;
RECT rect;
GetWindowRect( window->impl.handle, &rect );
pos.x = (uint16_t)rect.left;
pos.y = (uint16_t)rect.top;
return pos;
}
size_t bw_Window_getTitle( bw_Window* window, bw_StrSlice title ) {
int length = GetWindowTextLengthW( window->impl.handle );
BW_WIN32_ASSERT_SUCCESS;
if ( length > 0 && title.len > 0 ) {
WCHAR* buffer = (WCHAR*)malloc( sizeof(WCHAR) * (length + 1) );
int copied = GetWindowTextW( window->impl.handle, (LPWSTR)buffer, length + 1 );
if ( copied == 0 ) {
free( buffer );
BW_WIN32_PANIC_LAST_ERROR;
}
char* utf8_str;
bw_win32_copyAsNewUtf8Str( buffer, &utf8_str );
memcpy( title.data, utf8_str, length );
free( utf8_str );
}
return length;
}
bw_Dims2D bw_Window_getWindowDimensions( bw_Window* window ) {
bw_Dims2D dims;
RECT rect;
GetWindowRect( window->impl.handle, &rect );
dims.width = (uint16_t)(rect.right - rect.left);
dims.height = (uint16_t)(rect.bottom - rect.top);
return dims;
}
void bw_Window_setContentDimensions( bw_Window* window, bw_Dims2D dimensions ) {
RECT rect;
rect.left = 0; rect.right = dimensions.width;
rect.top = 0; rect.bottom = dimensions.height;
if ( !AdjustWindowRect( &rect, window->impl.style, FALSE ) )
BW_WIN32_PANIC_LAST_ERROR
LONG actual_width = rect.right - rect.left;
LONG actual_height = rect.bottom - rect.top;
if ( !SetWindowPos( window->impl.handle, 0, rect.left, rect.top, actual_width, actual_height, SWP_NOMOVE ) )
BW_WIN32_PANIC_LAST_ERROR
}
void bw_Window_setOpacity( bw_Window* window, uint8_t opacity ) {
if ( !SetLayeredWindowAttributes( window->impl.handle, 0, opacity, LWA_ALPHA ) )
BW_WIN32_PANIC_LAST_ERROR
window->impl.opacity = opacity;
}
void bw_Window_setPosition( bw_Window* window, bw_Pos2D position ) {
if ( !SetWindowPos( window->impl.handle, 0, position.x, position.y, 0, 0, SWP_NOSIZE ) )
BW_WIN32_PANIC_LAST_ERROR
}
void bw_Window_setTitle( bw_Window* window, bw_CStrSlice _title ) {
WCHAR* title = bw_win32_copyAsNewWstr( _title );
SetWindowTextW( window->impl.handle, title );
free( title );
}
void bw_Window_setWindowDimensions( bw_Window* window, bw_Dims2D dimensions ) {
if ( !SetWindowPos( window->impl.handle, 0, 0, 0, dimensions.width, dimensions.height, SWP_NOMOVE ) )
BW_WIN32_PANIC_LAST_ERROR
}
void bw_WindowImpl_destroy( bw_WindowImpl* window ) {
DestroyWindow( window->handle );
}
void bw_WindowImpl_hide( bw_WindowImpl* window ) {
ShowWindow( window->handle, SW_HIDE );
}
bw_WindowImpl bw_WindowImpl_new(
const bw_Window* window,
bw_CStrSlice _title,
int width, int height,
const bw_WindowOptions* options
) {
bw_WindowImpl impl;
impl.style = WS_OVERLAPPEDWINDOW;
if ( !options->borders )
impl.style ^= WS_BORDER;
if ( !options->resizable )
impl.style ^= WS_SIZEBOX & WS_MAXIMIZEBOX;
if ( !options->minimizable )
impl.style ^= WS_MINIMIZEBOX;
if ( width == -1 && height == -1 )
width = CW_USEDEFAULT;
wchar_t* title = bw_win32_copyAsNewWstr( _title );
impl.handle = CreateWindowExW(
WS_EX_LAYERED,
L"bw-window",
title,
impl.style,
CW_USEDEFAULT, 0,
width,
height,
HWND_DESKTOP, NULL,
window->app->impl.handle,
(void*)window
);
free( title );
if ( impl.handle == NULL ) {
BW_WIN32_PANIC_LAST_ERROR;
}
SetWindowLongPtrW( impl.handle, GWLP_USERDATA, (LONG_PTR)window );
BW_WIN32_ASSERT_SUCCESS;
impl.opacity = 255;
if ( !SetLayeredWindowAttributes( impl.handle, 0, impl.opacity, LWA_ALPHA ) )
BW_WIN32_PANIC_LAST_ERROR
window->app->windows_alive += 1;
return impl;
}
LRESULT CALLBACK bw_Window_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
bw_Window* window = (bw_Window*)GetWindowLongPtrW( hwnd, GWLP_USERDATA );
switch (msg) {
case WM_SIZE:
BW_ASSERT( window != 0, "Invalid window pointer during WM_SIZE" );
RECT rect;
GetClientRect( window->impl.handle, &rect );
unsigned int width = rect.right - rect.left;
unsigned int height = rect.bottom - rect.top;
if ( window->callbacks.on_resize != 0 )
window->callbacks.on_resize( window, width, height );
break;
case WM_CLOSE:
bw_Window_triggerClose( window );
break;
default:
return DefWindowProcW(hwnd, msg, wp, lp);
}
return 0;
}
void bw_WindowImpl_show( bw_WindowImpl* window ) {
ShowWindow( window->handle, SW_SHOW );
}
void bw_WindowWin32_calculatePositionCentered( int width, int height, int* x, int* y ) {
RECT rect;
GetClientRect( GetDesktopWindow(), &rect );
int desktop_width = rect.right - rect.left;
int desktop_height = rect.bottom - rect.top;
*x = ( desktop_width - width ) / 2;
*y = ( desktop_height - height ) / 2;
}
BOOL CALLBACK _bw_Window_closeChild( HWND handle, LPARAM _window ) {
bw_Window* window = (bw_Window*)_window;
bw_Window* enum_window = (bw_Window*)GetWindowLongPtrW( handle, GWLP_USERDATA );
if ( enum_window != 0 ) {
wchar_t class_name[11];
int class_name_len = GetClassNameW( handle, class_name, 11 );
wchar_t* bw_class = L"bw-window";
if ( class_name_len == 9 && memcmp( class_name, bw_class, 9*sizeof(wchar_t) ) == 0 ) {
if ( enum_window->parent == window ) {
bw_Window_triggerClose( enum_window );
}
}
}
return true;
}