Răsfoiți Sursa

Display modes management for SDL and DirectX (#470)

Maurice Doison 3 ani în urmă
părinte
comite
3648e31518
5 a modificat fișierele cu 436 adăugiri și 81 ștergeri
  1. 106 36
      libs/directx/dx/Window.hx
  2. 93 0
      libs/directx/window.c
  3. 104 12
      libs/sdl/sdl.c
  4. 104 24
      libs/sdl/sdl/Sdl.hx
  5. 29 9
      libs/sdl/sdl/Window.hx

+ 106 - 36
libs/directx/dx/Window.hx

@@ -2,15 +2,26 @@ package dx;
 import haxe.EntryPoint;
 
 private typedef WinPtr = hl.Abstract<"dx_window">;
+typedef MonitorHandle = String;
+
+typedef Monitor = {
+	name : MonitorHandle,
+	left : Int,
+	right : Int,
+	top : Int,
+	bottom : Int
+}
+
+typedef DisplaySetting = {
+	width : Int,
+	height : Int,
+	framerate : Int
+}
 
 @:enum abstract DisplayMode(Int) {
 	var Windowed = 0;
 	var Fullscreen = 1;
-	/**
-		Fullscreen not exclusive.
-	**/
 	var Borderless = 2;
-	var FullscreenResize = 3;
 }
 
 @:hlNative("directx")
@@ -24,7 +35,6 @@ class Window {
 	public static inline var RESIZABLE = 0x000002;
 
 	var win : WinPtr;
-	var savedSize : { x : Int, y : Int, width : Int, height : Int };
 	public var title(default, set) : String;
 	public var width(get, never) : Int;
 	public var height(get, never) : Int;
@@ -37,6 +47,8 @@ class Window {
 	public var displayMode(default, set) : DisplayMode;
 	public var visible(default, set) : Bool = true;
 	public var opacity(get, set) : Float;
+	public var displaySetting : DisplaySetting;
+	public var selectedMonitor : MonitorHandle;
 	public var vsync : Bool;
 
 	public function new( title : String, width : Int, height : Int, x : Int = CW_USEDEFAULT, y : Int = CW_USEDEFAULT, windowFlags : Int = RESIZABLE ) {
@@ -52,23 +64,18 @@ class Window {
 	}
 
 	function set_displayMode(mode) {
-		if( mode == displayMode )
-			return mode;
 		displayMode = mode;
-		var fs = mode != Windowed;
-		if( savedSize == null ) {
-			if( !fs ) return mode;
-			savedSize = { x : x, y : y, width : width, height : height };
-			winSetFullscreen(win,true);
-			Driver.fullScreen = mode == Fullscreen;
-		} else {
-			Driver.fullScreen = mode == Fullscreen;
-			if( fs )
-				return mode;
+		if(mode == Windowed) {
+			dx.Window.winChangeDisplaySetting(selectedMonitor != null ? @:privateAccess selectedMonitor.bytes : null, null);
 			winSetFullscreen(win, false);
-			resize(savedSize.width, savedSize.height);
-			setPosition(savedSize.x, savedSize.y);
-			savedSize = null;
+		}
+		else if(mode == Borderless) {
+			dx.Window.winChangeDisplaySetting(selectedMonitor != null ? @:privateAccess selectedMonitor.bytes : null, null);
+			winSetFullscreen(win,true);
+		}
+		else {
+			var r = dx.Window.winChangeDisplaySetting(selectedMonitor != null ? @:privateAccess selectedMonitor.bytes : null, displaySetting);
+			winSetFullscreen(win,true);
 		}
 		return mode;
 	}
@@ -100,6 +107,70 @@ class Window {
 		winCenter(win, centerPrimary);
 	}
 
+	public function destroy() {
+		winDestroy(win);
+		win = null;
+		windows.remove(this);
+	}
+
+	public function maximize() {
+		winResize(win, 0);
+	}
+
+	public function minimize() {
+		winResize(win, 1);
+	}
+
+	public function restore() {
+		winResize(win, 2);
+	}
+
+	public function getNextEvent( e : Event ) : Bool {
+		return winGetNextEvent(win, e);
+	}
+
+	public function clipCursor( enable : Bool ) : Void {
+		winClipCursor(enable ? win : null);
+	}
+
+	public static function getDisplaySettings(monitor : MonitorHandle) : Array<DisplaySetting> {
+		var a : Array<DisplaySetting> = [for(s in winGetDisplaySettings(monitor != null ? @:privateAccess monitor.bytes : null)) s];
+		a.sort((a, b) -> {
+			if(b.width > a.width) 1;
+			else if(b.width < a.width) -1;
+			else if(b.height > a.height) 1;
+			else if(b.height < a.height) -1;
+			else if(b.framerate > a.framerate) 1;
+			else if(b.framerate < a.framerate) -1;
+			else 0;
+		});
+		var last = null;
+		return a.filter(function(e) {
+			if(last == null) {
+				last = e;
+				return true;
+			}
+			else if(last.width == e.width && last.height == e.height && last.framerate == e.framerate) {
+				return false;
+			}
+			last = e;
+			return true;
+		});
+	}
+
+	public static function getCurrentDisplaySetting(monitor : MonitorHandle, registry : Bool = false) : DisplaySetting {
+		return winGetCurrentDisplaySetting(monitor != null ? @:privateAccess monitor.bytes : null, registry);
+	}
+
+	public static function getMonitors() : Array<Monitor> {
+		var last = null;
+		return [for(m in winGetMonitors()) @:privateAccess { name: String.fromUCS2(m.name), left: m.left, right: m.right, top: m.top, bottom: m.bottom } ];
+	}
+
+	public function getCurrentMonitor() : MonitorHandle {
+		return @:privateAccess String.fromUCS2(winGetMonitorFromWindow(win));
+	}
+
 	function get_width() {
 		var w = 0;
 		winGetSize(win, w, null);
@@ -157,30 +228,29 @@ class Window {
 		return v;
 	}
 
-	public function destroy() {
-		winDestroy(win);
-		win = null;
-		windows.remove(this);
-	}
-
-	public function maximize() {
-		winResize(win, 0);
+	@:hlNative("?directx", "win_get_display_settings")
+	static function winGetDisplaySettings(monitor : hl.Bytes) : hl.NativeArray<Dynamic> {
+		return null;
 	}
 
-	public function minimize() {
-		winResize(win, 1);
+	@:hlNative("?directx", "win_get_current_display_setting")
+	static function winGetCurrentDisplaySetting(monitor : hl.Bytes, registry : Bool) : Dynamic {
+		return null;
 	}
 
-	public function restore() {
-		winResize(win, 2);
+	@:hlNative("?directx", "win_change_display_setting")
+	public static function winChangeDisplaySetting(monitor : hl.Bytes, ds : Dynamic) : Int {
+		return 0;
 	}
 
-	public function getNextEvent( e : Event ) : Bool {
-		return winGetNextEvent(win, e);
+	@:hlNative("?directx", "win_get_monitors")
+	static function winGetMonitors() : hl.NativeArray<Dynamic> {
+		return null;
 	}
 
-	public function clipCursor( enable : Bool ) : Void {
-		winClipCursor(enable ? win : null);
+	@:hlNative("?directx", "win_get_monitor_from_window")
+	static function winGetMonitorFromWindow( win : WinPtr ) : hl.Bytes {
+		return null;
 	}
 
 	static function winCreateEx( x : Int, y : Int, width : Int, height : Int, windowFlags : Int ) : WinPtr {

+ 93 - 0
libs/directx/window.c

@@ -575,6 +575,94 @@ HL_PRIM int HL_NAME(get_screen_height)() {
 	return GetSystemMetrics(SM_CYSCREEN);
 }
 
+typedef struct {
+	int idx;
+	varray* arr;
+} get_monitors_data;
+
+BOOL CALLBACK on_get_monitors(HMONITOR monitor, HDC hdc, LPRECT rect, LPARAM param) {
+	get_monitors_data *data = (get_monitors_data*)param;
+	varray* arr = data->arr;
+
+	MONITORINFOEXW info;
+	info.cbSize = sizeof(MONITORINFOEXW);
+	GetMonitorInfoW(monitor, (LPMONITORINFO)&info);
+
+	vdynamic* dynobj = (vdynamic*)hl_alloc_dynobj();
+	hl_dyn_seti(dynobj, hl_hash_utf8("left"), &hlt_i32, rect->left);
+	hl_dyn_seti(dynobj, hl_hash_utf8("right"), &hlt_i32, rect->right);
+	hl_dyn_seti(dynobj, hl_hash_utf8("top"), &hlt_i32, rect->top);
+	hl_dyn_seti(dynobj, hl_hash_utf8("bottom"), &hlt_i32, rect->bottom);
+	hl_dyn_setp(dynobj, hl_hash_utf8("name"), &hlt_bytes, hl_copy_bytes((vbyte*)info.szDevice, (int)(wcslen(info.szDevice)+1)*2));
+	hl_aptr(arr, vdynobj*)[data->idx++] = (vdynobj*)dynobj;
+	return TRUE;
+}
+
+HL_PRIM varray* HL_NAME(win_get_monitors)() {
+	get_monitors_data data;
+	data.idx = 0;
+	data.arr = hl_alloc_array(&hlt_dynobj, 64);
+	EnumDisplayMonitors(NULL, NULL, on_get_monitors, (LPARAM)&data);
+	data.arr->size = data.idx;
+	return data.arr;
+}
+
+HL_PRIM wchar_t* HL_NAME(win_get_monitor_from_window)(HWND wnd) {
+	HMONITOR handle = MonitorFromWindow(wnd, MONITOR_DEFAULTTOPRIMARY);
+
+	MONITORINFOEXW info;
+	info.cbSize = sizeof(MONITORINFOEXW);
+	GetMonitorInfoW(handle, (LPMONITORINFO)&info);
+	return info.szDevice;
+}
+
+HL_PRIM varray* HL_NAME(win_get_display_settings)(wchar_t* device) {
+	DEVMODEW ds;
+	ds.dmSize = sizeof(DEVMODEW);
+	int len = 0;
+	while (EnumDisplaySettingsW(device, len, &ds))
+		len++;
+	varray* arr = hl_alloc_array(&hlt_dynobj, len);
+	for (int i = 0; EnumDisplaySettingsW(device, i, &ds); i++) {
+		vdynamic* dynobj = (vdynamic*) hl_alloc_dynobj();
+		hl_dyn_seti(dynobj, hl_hash_utf8("width"), &hlt_i32, ds.dmPelsWidth);
+		hl_dyn_seti(dynobj, hl_hash_utf8("height"), &hlt_i32, ds.dmPelsHeight);
+		hl_dyn_seti(dynobj, hl_hash_utf8("framerate"), &hlt_i32, ds.dmDisplayFrequency);
+		hl_aptr(arr, vdynobj*)[i] = (vdynobj*) dynobj;
+	}
+	return arr;
+}
+
+HL_PRIM vdynamic* HL_NAME(win_get_current_display_setting)(wchar_t* device, bool registry) {
+	DEVMODEW ds;
+	ds.dmSize = sizeof(DEVMODEW);
+	EnumDisplaySettingsW(device, registry ? ENUM_REGISTRY_SETTINGS : ENUM_CURRENT_SETTINGS, &ds);
+	vdynamic* dynobj = (vdynamic*) hl_alloc_dynobj();
+	hl_dyn_seti(dynobj, hl_hash_utf8("width"), &hlt_i32, ds.dmPelsWidth);
+	hl_dyn_seti(dynobj, hl_hash_utf8("height"), &hlt_i32, ds.dmPelsHeight);
+	hl_dyn_seti(dynobj, hl_hash_utf8("framerate"), &hlt_i32, ds.dmDisplayFrequency);
+	return dynobj;
+}
+
+HL_PRIM int HL_NAME(win_change_display_setting)(wchar_t* device, vdynamic* ds) {
+	bool found = false;
+	DEVMODEW devMode;
+	devMode.dmSize = sizeof(DEVMODEW);
+	if (ds != NULL) {
+		int width = hl_dyn_geti(ds, hl_hash_utf8("width"), &hlt_i32);
+		int height = hl_dyn_geti(ds, hl_hash_utf8("height"), &hlt_i32);
+		int framerate = hl_dyn_geti(ds, hl_hash_utf8("framerate"), &hlt_i32);
+
+		for (int i = 0; EnumDisplaySettingsW(device, i, &devMode); i++) {
+			if (devMode.dmPelsWidth == width && devMode.dmPelsHeight == height && devMode.dmDisplayFrequency == framerate) {
+				found = true;
+				break;
+			}
+		}
+	}
+	return ChangeDisplaySettingsExW(device, found ? &devMode : NULL, NULL, found ? CDS_FULLSCREEN : 0, NULL);
+}
+
 #define TWIN _ABSTRACT(dx_window)
 DEFINE_PRIM(TWIN, win_create_ex, _I32 _I32 _I32 _I32 _I32);
 DEFINE_PRIM(TWIN, win_create, _I32 _I32);
@@ -595,6 +683,11 @@ DEFINE_PRIM(_BOOL, win_set_opacity, TWIN _F64);
 DEFINE_PRIM(_VOID, win_destroy, TWIN);
 DEFINE_PRIM(_BOOL, win_get_next_event, TWIN _DYN);
 DEFINE_PRIM(_VOID, win_clip_cursor, TWIN);
+DEFINE_PRIM(_ARR, win_get_display_settings, _BYTES);
+DEFINE_PRIM(_DYN, win_get_current_display_setting, _BYTES _BOOL);
+DEFINE_PRIM(_I32, win_change_display_setting, _BYTES _DYN);
+DEFINE_PRIM(_ARR, win_get_monitors, _NO_ARG);
+DEFINE_PRIM(_BYTES, win_get_monitor_from_window, TWIN);
 
 DEFINE_PRIM(_I32, get_screen_width, _NO_ARG);
 DEFINE_PRIM(_I32, get_screen_height, _NO_ARG);

+ 104 - 12
libs/sdl/sdl.c

@@ -21,6 +21,9 @@
 #	error "SDL2 SDK not found in hl/include/sdl/"
 #endif
 
+#define TWIN _ABSTRACT(sdl_window)
+#define TGL _ABSTRACT(sdl_gl)
+
 typedef struct {
 	int x;
 	int y;
@@ -362,6 +365,23 @@ HL_PRIM int HL_NAME(get_screen_height)() {
 	return e.h;
 }
 
+HL_PRIM int HL_NAME(get_screen_width_of_window)(SDL_Window* win) {
+	SDL_DisplayMode e;
+	SDL_GetCurrentDisplayMode(win != NULL ? SDL_GetWindowDisplayIndex(win) : 0, &e);
+	return e.w;
+}
+
+HL_PRIM int HL_NAME(get_screen_height_of_window)(SDL_Window* win) {
+	SDL_DisplayMode e;
+	SDL_GetCurrentDisplayMode(win != NULL ? SDL_GetWindowDisplayIndex(win) : 0, &e);
+	return e.h;
+}
+
+HL_PRIM int HL_NAME(get_framerate)(SDL_Window* win) {
+	SDL_DisplayMode e;
+	SDL_GetCurrentDisplayMode(win != NULL ? SDL_GetWindowDisplayIndex(win) : 0, &e);
+	return e.refresh_rate;
+}
 
 HL_PRIM void HL_NAME(message_box)(vbyte *title, vbyte *text, bool error) {
 	hl_blocking(true);
@@ -412,6 +432,9 @@ DEFINE_PRIM(_VOID, quit, _NO_ARG);
 DEFINE_PRIM(_VOID, delay, _I32);
 DEFINE_PRIM(_I32, get_screen_width, _NO_ARG);
 DEFINE_PRIM(_I32, get_screen_height, _NO_ARG);
+DEFINE_PRIM(_I32, get_screen_width_of_window, TWIN);
+DEFINE_PRIM(_I32, get_screen_height_of_window, TWIN);
+DEFINE_PRIM(_I32, get_framerate, TWIN);
 DEFINE_PRIM(_VOID, message_box, _BYTES _BYTES _BOOL);
 DEFINE_PRIM(_VOID, set_vsync, _BOOL);
 DEFINE_PRIM(_BOOL, detect_win32, _NO_ARG);
@@ -423,23 +446,22 @@ DEFINE_PRIM(_BOOL, hint_value, _BYTES _BYTES);
 // Window
 
 HL_PRIM SDL_Window *HL_NAME(win_create_ex)(int x, int y, int width, int height, int sdlFlags) {
-	SDL_Window *w;
 	// force window to match device resolution on mobile
 #ifdef	HL_MOBILE
 	SDL_DisplayMode displayMode;
 	SDL_GetDesktopDisplayMode(0, &displayMode);
-	w = SDL_CreateWindow("", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS | sdlFlags);
+	SDL_Window* win = SDL_CreateWindow("", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS | sdlFlags);
 #else
-	w = SDL_CreateWindow("", x, y, width, height, SDL_WINDOW_OPENGL | sdlFlags);
+	SDL_Window* win = SDL_CreateWindow("", x, y, width, height, SDL_WINDOW_OPENGL | sdlFlags);
 #endif
 #	ifdef HL_WIN
 	// force window to show even if the debugger force process windows to be hidden
-	if( (SDL_GetWindowFlags(w) & SDL_WINDOW_INPUT_FOCUS) == 0 ) {
-		SDL_HideWindow(w);
-		SDL_ShowWindow(w);
+	if( (SDL_GetWindowFlags(win) & SDL_WINDOW_INPUT_FOCUS) == 0 ) {
+		SDL_HideWindow(win);
+		SDL_ShowWindow(win);
 	}
 #	endif
-	return w;
+	return win;
 }
 
 HL_PRIM SDL_Window *HL_NAME(win_create)(int width, int height) {
@@ -472,7 +494,7 @@ HL_PRIM bool HL_NAME(win_set_fullscreen)(SDL_Window *win, int mode) {
 	case 0: // WINDOWED
 		return SDL_SetWindowFullscreen(win, 0) == 0;
 	case 1: // FULLSCREEN
-		return SDL_SetWindowFullscreen(win, SDL_WINDOW_FULLSCREEN_DESKTOP) == 0;
+		return SDL_SetWindowFullscreen(win, SDL_WINDOW_FULLSCREEN) == 0;
 	case 2: // BORDERLESS
 #		ifdef _WIN32
 		{
@@ -496,12 +518,27 @@ HL_PRIM bool HL_NAME(win_set_fullscreen)(SDL_Window *win, int mode) {
 #	else
 		return SDL_SetWindowFullscreen(win, SDL_WINDOW_FULLSCREEN_DESKTOP) == 0;
 #	endif
-	case 3:
-		return SDL_SetWindowFullscreen(win, SDL_WINDOW_FULLSCREEN) == 0;
 	}
 	return false;
 }
 
+HL_PRIM bool HL_NAME(win_set_display_mode)(SDL_Window *win, int width, int height, int framerate) {
+	SDL_DisplayMode mode;
+	int display_idx = SDL_GetWindowDisplayIndex(win);
+	for (int i = 0; i < SDL_GetNumDisplayModes(display_idx); i++) {
+		if (SDL_GetDisplayMode(display_idx, i, &mode) == 0) {
+			if (mode.w == width && mode.h == height && mode.refresh_rate == framerate) {
+				return SDL_SetWindowDisplayMode(win, &mode) >= 0;
+			}
+		}
+	}
+	return false;
+ }
+
+HL_PRIM int HL_NAME(win_display_handle)(SDL_Window *win) {
+	return SDL_GetWindowDisplayIndex(win);
+}
+
 HL_PRIM void HL_NAME(win_set_title)(SDL_Window *win, vbyte *title) {
 	SDL_SetWindowTitle(win, (char*)title);
 }
@@ -592,12 +629,12 @@ HL_PRIM void HL_NAME(win_destroy)(SDL_Window *win, SDL_GLContext gl) {
 	SDL_GL_DeleteContext(gl);
 }
 
-#define TWIN _ABSTRACT(sdl_window)
-#define TGL _ABSTRACT(sdl_gl)
 DEFINE_PRIM(TWIN, win_create_ex, _I32 _I32 _I32 _I32 _I32);
 DEFINE_PRIM(TWIN, win_create, _I32 _I32);
 DEFINE_PRIM(TGL, win_get_glcontext, TWIN);
 DEFINE_PRIM(_BOOL, win_set_fullscreen, TWIN _I32);
+DEFINE_PRIM(_BOOL, win_set_display_mode, TWIN _I32 _I32 _I32);
+DEFINE_PRIM(_I32, win_display_handle, TWIN);
 DEFINE_PRIM(_VOID, win_resize, TWIN _I32);
 DEFINE_PRIM(_VOID, win_set_title, TWIN _BYTES);
 DEFINE_PRIM(_VOID, win_set_position, TWIN _I32 _I32);
@@ -774,6 +811,58 @@ HL_PRIM char* HL_NAME(get_clipboard_text)() {
 	return bytes;
 }
 
+HL_PRIM varray* HL_NAME(get_displays)() {
+	int n = SDL_GetNumVideoDisplays();
+	varray* arr = hl_alloc_array(&hlt_dynobj, n);
+	for (int i = 0; i < n; i++) {
+		vdynamic *obj = (vdynamic*) hl_alloc_dynobj();
+		SDL_Rect rect;
+		SDL_GetDisplayBounds(i, &rect);
+		hl_dyn_seti(obj, hl_hash_utf8("right"), &hlt_i32, rect.x+rect.w);
+		hl_dyn_seti(obj, hl_hash_utf8("bottom"), &hlt_i32, rect.y+rect.h);
+		hl_dyn_seti(obj, hl_hash_utf8("left"), &hlt_i32, rect.x);
+		hl_dyn_seti(obj, hl_hash_utf8("top"), &hlt_i32, rect.y);
+		hl_dyn_seti(obj, hl_hash_utf8("handle"), &hlt_i32, i);
+		const char *name = SDL_GetDisplayName(i);
+		hl_dyn_setp(obj, hl_hash_utf8("name"), &hlt_bytes, hl_copy_bytes(name, (int) strlen(name)+1));
+		hl_aptr(arr, vdynamic*)[i] = obj;
+	}
+	return arr;
+}
+
+HL_PRIM varray* HL_NAME(get_display_modes)(int display_id) {
+	int n = SDL_GetNumDisplayModes(display_id);
+	varray* arr = hl_alloc_array(&hlt_dynobj, n);
+	for (int i = 0; i < n; i++) {
+		SDL_DisplayMode mode;
+		SDL_GetDisplayMode(display_id, i, &mode);
+		vdynamic *obj = (vdynamic*)hl_alloc_dynobj();
+		hl_dyn_seti(obj, hl_hash_utf8("width"), &hlt_i32, mode.w);
+		hl_dyn_seti(obj, hl_hash_utf8("height"), &hlt_i32, mode.h);
+		hl_dyn_seti(obj, hl_hash_utf8("framerate"), &hlt_i32, mode.refresh_rate);
+		hl_aptr(arr, vdynamic*)[i] = obj;
+	}
+	return arr;
+}
+
+HL_PRIM vdynobj* HL_NAME(get_current_display_mode)(int display_id, bool registry) {
+	SDL_DisplayMode mode;
+	int r;
+	if(registry)
+		r = SDL_GetDesktopDisplayMode(display_id, &mode);
+	else
+		r = SDL_GetCurrentDisplayMode(display_id, &mode);
+	if (r < 0) {
+		printf("can't find mode for %d : %d\n", display_id, r);
+		return NULL;
+	}
+	vdynamic* obj = (vdynamic*)hl_alloc_dynobj();
+	hl_dyn_seti(obj, hl_hash_utf8("width"), &hlt_i32, mode.w);
+	hl_dyn_seti(obj, hl_hash_utf8("height"), &hlt_i32, mode.h);
+	hl_dyn_seti(obj, hl_hash_utf8("framerate"), &hlt_i32, mode.refresh_rate);
+	return (vdynobj*) obj;
+}
+
 #define MAX_DEVICES 16
 HL_PRIM varray *HL_NAME(get_devices)() {
 	varray *a = hl_alloc_array(&hlt_bytes, MAX_DEVICES);
@@ -798,4 +887,7 @@ DEFINE_PRIM(_VOID, free_cursor, _CURSOR);
 DEFINE_PRIM(_VOID, set_cursor, _CURSOR);
 DEFINE_PRIM(_BOOL, set_clipboard_text, _BYTES);
 DEFINE_PRIM(_BYTES, get_clipboard_text, _NO_ARG);
+DEFINE_PRIM(_ARR, get_displays, _NO_ARG);
+DEFINE_PRIM(_ARR, get_display_modes, _I32);
+DEFINE_PRIM(_DYN, get_current_display_mode, _I32 _BOOL);
 DEFINE_PRIM(_ARR, get_devices, _NO_ARG);

+ 104 - 24
libs/sdl/sdl/Sdl.hx

@@ -1,5 +1,21 @@
 package sdl;
 
+typedef Display = {
+	var handle : Window.DisplayHandle;
+	var name : String;
+	var left : Int;
+	var top : Int;
+	var right : Int;
+	var bottom : Int;
+};
+
+typedef ScreenMode = {
+	var format : Int;
+	var width : Int;
+	var height : Int;
+	var framerate : Int;
+};
+
 @:hlNative("sdl")
 class Sdl {
 
@@ -70,30 +86,44 @@ class Sdl {
 	public static function delay(time:Int) {
 	}
 
+	public static function getScreenWidth(?win : sdl.Window) : Int {
+		return 
+			if(win == null)
+				get_screen_width();
+			else
+				get_screen_width_of_window(@:privateAccess win.win);
+	}
 
-	public static function getScreenWidth() : Int {
-		return 0;
+	public static function getScreenHeight(?win : sdl.Window) : Int {
+		return
+			if(win == null)
+				get_screen_height();
+			else
+				get_screen_height_of_window(@:privateAccess win.win);
 	}
 
-	public static function getScreenHeight() : Int {
+	@:hlNative("?sdl", "get_framerate")
+	public static function getFramerate(win : sdl.Window.WinPtr) : Int {
 		return 0;
 	}
 
 	public static function message( title : String, text : String, error = false ) {
 		@:privateAccess messageBox(title.toUtf8(), text.toUtf8(), error);
 	}
-
-	static function messageBox( title : hl.Bytes, text : hl.Bytes, error : Bool ) {
+	
+	public static function getDisplayModes(display : Window.DisplayHandle) : Array<ScreenMode> {
+		return [ for(m in get_display_modes(display)) m ];
 	}
 
-	static function detectWin32() {
-		return false;
+	public static function getCurrentDisplayMode(display : Window.DisplayHandle, registry : Bool = false) : ScreenMode {
+		return get_current_display_mode(display, registry);
 	}
 
-	static function get_devices() : hl.NativeArray<hl.Bytes> {
-		return null;
+	public static function getDisplays() : Array<Display> {
+		var i = 0;
+		return [ for(d in get_displays() ) @:privateAccess { handle: d.handle, name: '${String.fromUTF8(d.name)} (${++i})', left: d.left, top: d.top, right: d.right, bottom: d.bottom } ];
 	}
-
+	
 	public static function getDevices() {
 		var a = [];
 		var arr = get_devices();
@@ -111,6 +141,70 @@ class Sdl {
 	public static function setRelativeMouseMode( enable : Bool ) : Int {
 		return 0;
 	}
+	
+	public static function setClipboardText( text : String ) : Bool {
+		if( text == null )
+			return false;
+		return @:privateAccess _setClipboardText( text.toUtf8() );
+	}
+
+	public static function getClipboardText() : String {
+		var t = _getClipboardText();
+		if( t == null )
+			return null;
+		else
+			return @:privateAccess String.fromUTF8(t);
+	}
+
+	@:hlNative("?sdl", "get_screen_width")
+	static function get_screen_width() : Int {
+		return 0;
+	}
+
+	@:hlNative("?sdl", "get_screen_height")
+	static function get_screen_height() : Int {
+		return 0;
+	}
+
+	@:hlNative("?sdl", "get_screen_width_of_window")
+	static function get_screen_width_of_window(win: sdl.Window.WinPtr) : Int {
+		return 0;
+	}
+
+	@:hlNative("?sdl", "get_screen_height_of_display")
+	static function get_screen_height_of_window(win: sdl.Window.WinPtr) : Int {
+		return 0;
+	}
+
+	static function messageBox( title : hl.Bytes, text : hl.Bytes, error : Bool ) {
+	}
+
+	static function detectWin32() {
+		return false;
+	}
+
+	static function get_display_modes(displayId : Int) : hl.NativeArray<Dynamic> {
+		return null;
+	}
+
+	@:hlNative("?sdl", "get_current_display_mode")
+	static function get_current_display_mode(displayId : Int, registry : Bool) : Dynamic {
+		return null;
+	}
+
+
+	@:hlNative("?sdl", "get_desktop_display_mode")
+	static function get_desktop_display_mode(displayId : Int) : Dynamic {
+		return null;
+	}
+
+	static function get_displays() : hl.NativeArray<Dynamic> {
+		return null;
+	}
+
+	static function get_devices() : hl.NativeArray<hl.Bytes> {
+		return null;
+	}
 
 	static function detect_keyboard_layout() : hl.Bytes {
 		return null;
@@ -125,24 +219,10 @@ class Sdl {
 		return false;
 	}
 
-	public static function setClipboardText( text : String ) : Bool {
-		if( text == null )
-			return false;
-		return @:privateAccess _setClipboardText( text.toUtf8() );
-	}
-
 	@:hlNative("?sdl", "get_clipboard_text")
 	private static function _getClipboardText() : hl.Bytes {
 		return null;
 	}
-
-	public static function getClipboardText() : String {
-		var t = _getClipboardText();
-		if( t == null )
-			return null;
-		else
-			return @:privateAccess String.fromUTF8(t);
-	}
 }
 
 @:enum

+ 29 - 9
libs/sdl/sdl/Window.hx

@@ -1,16 +1,19 @@
 package sdl;
 
-private typedef WinPtr = hl.Abstract<"sdl_window">;
+typedef WinPtr = hl.Abstract<"sdl_window">;
 private typedef GLContext = hl.Abstract<"sdl_gl">;
+typedef DisplayHandle = Null<Int>;
 
 @:enum abstract DisplayMode(Int) {
 	var Windowed = 0;
 	var Fullscreen = 1;
-	/**
-		Fullscreen not exclusive.
-	**/
 	var Borderless = 2;
-	var FullscreenResize = 3;
+}
+
+typedef DisplaySetting = {
+	width : Int,
+	height : Int,
+	framerate : Int
 }
 
 @:hlNative("sdl")
@@ -57,6 +60,8 @@ class Window {
 	public var x(get, never) : Int;
 	public var y(get, never) : Int;
 	public var displayMode(default, set) : DisplayMode;
+	public var displaySetting : DisplaySetting;
+	public var currentMonitor(get, default) : Int;
 	public var visible(default, set) : Bool = true;
 	public var opacity(get, set) : Float;
 
@@ -136,10 +141,12 @@ class Window {
 	}
 
 	function set_displayMode(mode) {
-		if( mode == displayMode )
-			return mode;
-		if( winSetFullscreen(win, cast mode) )
+		if( winSetFullscreen(win, mode) ) {
 			displayMode = mode;
+			if(mode == Fullscreen) {
+				try @:privateAccess sdl.Window.winSetDisplayMode(win, displaySetting.width, displaySetting.height, displaySetting.framerate) catch(_) {}
+			}
+		}
 		return displayMode;
 	}
 
@@ -218,6 +225,10 @@ class Window {
 		return y;
 	}
 
+	function get_currentMonitor() {
+		return winDisplayHandle(win);
+	}
+
 	function set_vsync(v) {
 		setVsync(v);
 		return vsync = v;
@@ -297,6 +308,16 @@ class Window {
 		return false;
 	}
 
+	@:hlNative("?sdl", "win_set_display_mode")
+	static function winSetDisplayMode( win : WinPtr, width : Int, height : Int, framerate : Int ) {
+		return false;
+	}
+
+	@:hlNative("?sdl", "win_display_handle")
+	static function winDisplayHandle( win : WinPtr ) : Int {
+		return 0;
+	}
+
 	static function winSetSize( win : WinPtr, width : Int, height : Int ) {
 	}
 
@@ -334,5 +355,4 @@ class Window {
 
 	static function setVsync( b : Bool ) {
 	}
-
 }