Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 12 additions & 6 deletions libs/directx/dx/Window.hx
Original file line number Diff line number Diff line change
Expand Up @@ -73,17 +73,18 @@ class Window {

function set_displayMode(mode) {
displayMode = mode;
var monitor = selectedMonitor != null ? @:privateAccess selectedMonitor.bytes : null;
if(mode == Windowed) {
dx.Window.winChangeDisplaySetting(selectedMonitor != null ? @:privateAccess selectedMonitor.bytes : null, null);
winSetFullscreen(win, false);
dx.Window.winChangeDisplaySetting(monitor, null);
winSetFullscreenOn(win, false, monitor);
}
else if(mode == Borderless) {
dx.Window.winChangeDisplaySetting(selectedMonitor != null ? @:privateAccess selectedMonitor.bytes : null, null);
winSetFullscreen(win,true);
dx.Window.winChangeDisplaySetting(monitor, null);
winSetFullscreenOn(win, true, monitor);
}
else {
var r = dx.Window.winChangeDisplaySetting(selectedMonitor != null ? @:privateAccess selectedMonitor.bytes : null, displaySetting);
winSetFullscreen(win,true);
var r = dx.Window.winChangeDisplaySetting(monitor, displaySetting);
winSetFullscreenOn(win, true, monitor);
}
return mode;
}
Expand Down Expand Up @@ -339,6 +340,11 @@ class Window {
static function winSetFullscreen( win : WinPtr, fs : Bool ) {
}

@:hlNative("?directx", "win_set_fullscreen_on")
static function winSetFullscreenOn( win : WinPtr, fs : Bool, monitor : hl.Bytes ) {
winSetFullscreen(win, fs);
}

static function winSetSize( win : WinPtr, width : Int, height : Int ) {
}

Expand Down
116 changes: 110 additions & 6 deletions libs/directx/window.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ typedef struct {
int next_event;
bool is_over;
bool is_focused;
bool fullscreen;
RECT fullscreen_rect;
WCHAR fullscreen_device[CCHDEVICENAME];
} dx_events;

typedef struct HWND__ dx_window;
Expand Down Expand Up @@ -107,6 +110,58 @@ static dx_events *get_events(HWND wnd) {
return (dx_events*)GetWindowLongPtr(wnd,GWLP_USERDATA);
}

#ifndef WM_DPICHANGED
# define WM_DPICHANGED 0x02E0
#endif

typedef struct {
const WCHAR *name;
HMONITOR result;
} find_monitor_data;

static BOOL CALLBACK on_find_monitor( HMONITOR monitor, HDC hdc, LPRECT rect, LPARAM param ) {
find_monitor_data *d = (find_monitor_data*)param;
MONITORINFOEXW info;
info.cbSize = sizeof(info);
if( GetMonitorInfoW(monitor,(LPMONITORINFO)&info) && wcscmp(info.szDevice,d->name) == 0 ) {
d->result = monitor;
return FALSE;
}
return TRUE;
}

static bool get_fullscreen_rect( HWND wnd, RECT *out ) {
dx_events *buf = get_events(wnd);
HMONITOR mon = NULL;
MONITORINFO mi;
if( buf != NULL && buf->fullscreen_device[0] ) {
find_monitor_data d;
d.name = buf->fullscreen_device;
d.result = NULL;
EnumDisplayMonitors(NULL,NULL,on_find_monitor,(LPARAM)&d);
mon = d.result;
}
if( mon == NULL )
mon = MonitorFromWindow(wnd,MONITOR_DEFAULTTOPRIMARY);
mi.cbSize = sizeof(mi);
// never fall back on the zeroed rect : that would move the window to 0,0 and size it 0x0
if( !GetMonitorInfo(mon,&mi) || IsRectEmpty(&mi.rcMonitor) )
return false;
*out = mi.rcMonitor;
return true;
}

static void apply_fullscreen_rect( HWND wnd, bool force ) {
dx_events *buf = get_events(wnd);
RECT r, cur;
if( buf == NULL || !buf->fullscreen || !get_fullscreen_rect(wnd,&r) )
return;
buf->fullscreen_rect = r;
if( !force && GetWindowRect(wnd,&cur) && EqualRect(&cur,&r) )
return;
SetWindowPos(wnd,NULL,r.left,r.top,r.right - r.left,r.bottom - r.top,SWP_NOOWNERZORDER|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_SHOWWINDOW);
}

static void updateClipCursor(HWND wnd) {
if ( disable_capture ) {
ClipCursor(NULL);
Expand Down Expand Up @@ -402,6 +457,28 @@ static LRESULT CALLBACK WndProc( HWND wnd, UINT umsg, WPARAM wparam, LPARAM lpar
get_events(wnd)->is_focused = false;
addState(Blur);
break;
case WM_WINDOWPOSCHANGING:
{
// While fullscreen, veto any move/resize we didn't ask for.
dx_events *buf = get_events(wnd);
WINDOWPOS *wp = (WINDOWPOS*)lparam;
if( buf != NULL && buf->fullscreen && !IsRectEmpty(&buf->fullscreen_rect) ) {
// let minimize through, else alt-tab would be broken
bool minimizing = (wp->flags & SWP_HIDEWINDOW) != 0 || wp->x <= -30000 || wp->y <= -30000;
if( !minimizing && !IsIconic(wnd) ) {
wp->x = buf->fullscreen_rect.left;
wp->y = buf->fullscreen_rect.top;
wp->cx = buf->fullscreen_rect.right - buf->fullscreen_rect.left;
wp->cy = buf->fullscreen_rect.bottom - buf->fullscreen_rect.top;
wp->flags &= ~(SWP_NOMOVE | SWP_NOSIZE);
}
}
break;
}
case WM_DISPLAYCHANGE:
case WM_DPICHANGED:
apply_fullscreen_rect(wnd,true);
break;
case WM_WINDOWPOSCHANGED:
{
HWND wndFg = GetForegroundWindow();
Expand Down Expand Up @@ -732,19 +809,45 @@ HL_PRIM void HL_NAME(win_set_focus)(dx_window* win) {
SetFocus(win);
}

HL_PRIM void HL_NAME(win_set_fullscreen)(dx_window *win, bool fs) {
HL_PRIM void HL_NAME(win_set_fullscreen_on)(dx_window *win, bool fs, vbyte *monitor) {
dx_events *buf = get_events(win);
if( buf == NULL )
return;
if( fs ) {
MONITORINFO mi = { sizeof(mi) };
GetMonitorInfo(MonitorFromWindow(win,MONITOR_DEFAULTTOPRIMARY), &mi);
SetWindowLong(win,GWL_STYLE,WS_POPUP | WS_VISIBLE);
SetWindowPos(win,NULL,mi.rcMonitor.left,mi.rcMonitor.top,mi.rcMonitor.right - mi.rcMonitor.left,mi.rcMonitor.bottom - mi.rcMonitor.top,SWP_NOOWNERZORDER|SWP_FRAMECHANGED|SWP_SHOWWINDOW);
if( IsIconic(win) || IsZoomed(win) )
ShowWindow(win,SW_RESTORE);
buf->fullscreen_device[0] = 0;
if( monitor != NULL ) {
const WCHAR *name = (const WCHAR*)monitor;
int i = 0;
while( i < CCHDEVICENAME - 1 && name[i] ) {
buf->fullscreen_device[i] = name[i];
i++;
}
buf->fullscreen_device[i] = 0;
} else {
MONITORINFOEXW info;
info.cbSize = sizeof(info);
if( GetMonitorInfoW(MonitorFromWindow(win,MONITOR_DEFAULTTOPRIMARY),(LPMONITORINFO)&info) )
memcpy(buf->fullscreen_device,info.szDevice,sizeof(info.szDevice));
}
buf->fullscreen = true;
SetRectEmpty(&buf->fullscreen_rect);
SetWindowLong(win,GWL_STYLE,(buf->normal_style & (WS_CLIPSIBLINGS|WS_CLIPCHILDREN)) | WS_POPUP | WS_VISIBLE);
apply_fullscreen_rect(win,true);
} else {
dx_events *buf = get_events(win);
buf->fullscreen = false;
SetRectEmpty(&buf->fullscreen_rect);
buf->fullscreen_device[0] = 0;
SetWindowLong(win,GWL_STYLE,buf->normal_style);
SetWindowPos(win,NULL,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOOWNERZORDER|SWP_FRAMECHANGED|SWP_SHOWWINDOW);
}
}

HL_PRIM void HL_NAME(win_set_fullscreen)(dx_window *win, bool fs) {
HL_NAME(win_set_fullscreen_on)(win,fs,NULL);
}

HL_PRIM double HL_NAME(win_get_opacity)(dx_window *win) {
dx_events *buf = get_events(win);
return buf->opacity;
Expand Down Expand Up @@ -982,6 +1085,7 @@ HL_PRIM void HL_NAME(win_set_icon)(HWND wnd, dx_icon icon) {
DEFINE_PRIM(TWIN, win_create_ex, _I32 _I32 _I32 _I32 _I32);
DEFINE_PRIM(TWIN, win_create, _I32 _I32);
DEFINE_PRIM(_VOID, win_set_fullscreen, TWIN _BOOL);
DEFINE_PRIM(_VOID, win_set_fullscreen_on, TWIN _BOOL _BYTES);
DEFINE_PRIM(_VOID, win_resize, TWIN _I32);
DEFINE_PRIM(_VOID, win_set_focus, TWIN);
DEFINE_PRIM(_VOID, win_set_title, TWIN _BYTES);
Expand Down
Loading