488 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			488 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| 
								 | 
							
								#include <kinc/display.h>
							 | 
						||
| 
								 | 
							
								#include <kinc/graphics4/graphics.h>
							 | 
						||
| 
								 | 
							
								#include <kinc/window.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <kinc/backend/Windows.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef KINC_VR
							 | 
						||
| 
								 | 
							
								#include <kinc/vr/vrinterface.h>
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#undef CreateWindow
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								struct HWND__;
							 | 
						||
| 
								 | 
							
								typedef unsigned long DWORD;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								typedef struct {
							 | 
						||
| 
								 | 
							
									struct HWND__ *handle;
							 | 
						||
| 
								 | 
							
									int display_index;
							 | 
						||
| 
								 | 
							
									bool mouseInside;
							 | 
						||
| 
								 | 
							
									int index;
							 | 
						||
| 
								 | 
							
									int x, y, mode, bpp, frequency, features;
							 | 
						||
| 
								 | 
							
									int manualWidth, manualHeight;
							 | 
						||
| 
								 | 
							
									void (*resizeCallback)(int x, int y, void *data);
							 | 
						||
| 
								 | 
							
									void *resizeCallbackData;
							 | 
						||
| 
								 | 
							
									void (*ppiCallback)(int ppi, void *data);
							 | 
						||
| 
								 | 
							
									void *ppiCallbackData;
							 | 
						||
| 
								 | 
							
									bool (*closeCallback)(void *data);
							 | 
						||
| 
								 | 
							
									void *closeCallbackData;
							 | 
						||
| 
								 | 
							
								} WindowData;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								LRESULT WINAPI KoreWindowsMessageProcedure(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define MAXIMUM_WINDOWS 16
							 | 
						||
| 
								 | 
							
								static WindowData windows[MAXIMUM_WINDOWS] = {0};
							 | 
						||
| 
								 | 
							
								static int window_counter = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef KINC_OCULUS
							 | 
						||
| 
								 | 
							
								const wchar_t *windowClassName = L"ORT";
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								const wchar_t *windowClassName = L"KoreWindow";
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef KINC_VULKAN
							 | 
						||
| 
								 | 
							
								#include <vulkan/vulkan_core.h>
							 | 
						||
| 
								 | 
							
								#include <vulkan/vulkan_win32.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								VkResult kinc_vulkan_create_surface(VkInstance instance, int window_index, VkSurfaceKHR *surface) {
							 | 
						||
| 
								 | 
							
									VkWin32SurfaceCreateInfoKHR createInfo = {0};
							 | 
						||
| 
								 | 
							
									createInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
							 | 
						||
| 
								 | 
							
									createInfo.pNext = NULL;
							 | 
						||
| 
								 | 
							
									createInfo.flags = 0;
							 | 
						||
| 
								 | 
							
									createInfo.hinstance = GetModuleHandle(NULL);
							 | 
						||
| 
								 | 
							
									createInfo.hwnd = windows[window_index].handle;
							 | 
						||
| 
								 | 
							
									return vkCreateWin32SurfaceKHR(instance, &createInfo, NULL, surface);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <assert.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void kinc_vulkan_get_instance_extensions(const char **names, int *index, int max) {
							 | 
						||
| 
								 | 
							
									assert(*index + 1 < max);
							 | 
						||
| 
								 | 
							
									names[(*index)++] = VK_KHR_WIN32_SURFACE_EXTENSION_NAME;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								VkBool32 kinc_vulkan_get_physical_device_presentation_support(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex) {
							 | 
						||
| 
								 | 
							
									return vkGetPhysicalDeviceWin32PresentationSupportKHR(physicalDevice, queueFamilyIndex);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void RegisterWindowClass(HINSTANCE hInstance, const wchar_t *className) {
							 | 
						||
| 
								 | 
							
									WNDCLASSEXW wc = {sizeof(WNDCLASSEXA),
							 | 
						||
| 
								 | 
							
									                  CS_OWNDC /*CS_CLASSDC*/,
							 | 
						||
| 
								 | 
							
									                  KoreWindowsMessageProcedure,
							 | 
						||
| 
								 | 
							
									                  0L,
							 | 
						||
| 
								 | 
							
									                  0L,
							 | 
						||
| 
								 | 
							
									                  hInstance,
							 | 
						||
| 
								 | 
							
									                  LoadIconW(hInstance, MAKEINTRESOURCEW(107)),
							 | 
						||
| 
								 | 
							
									                  LoadCursor(NULL, IDC_ARROW),
							 | 
						||
| 
								 | 
							
									                  0,
							 | 
						||
| 
								 | 
							
									                  0,
							 | 
						||
| 
								 | 
							
									                  className,
							 | 
						||
| 
								 | 
							
									                  0};
							 | 
						||
| 
								 | 
							
									RegisterClassExW(&wc);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static DWORD getStyle(int features) {
							 | 
						||
| 
								 | 
							
									DWORD style = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_POPUP;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if ((features & KINC_WINDOW_FEATURE_RESIZEABLE) && ((features & KINC_WINDOW_FEATURE_BORDERLESS) == 0)) {
							 | 
						||
| 
								 | 
							
										style |= WS_SIZEBOX;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (features & KINC_WINDOW_FEATURE_MAXIMIZABLE) {
							 | 
						||
| 
								 | 
							
										style |= WS_MAXIMIZEBOX;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (features & KINC_WINDOW_FEATURE_MINIMIZABLE) {
							 | 
						||
| 
								 | 
							
										style |= WS_MINIMIZEBOX;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if ((features & KINC_WINDOW_FEATURE_BORDERLESS) == 0) {
							 | 
						||
| 
								 | 
							
										style |= WS_CAPTION | WS_SYSMENU;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return style;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static DWORD getExStyle(int features) {
							 | 
						||
| 
								 | 
							
									DWORD exStyle = WS_EX_APPWINDOW;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if ((features & KINC_WINDOW_FEATURE_BORDERLESS) == 0) {
							 | 
						||
| 
								 | 
							
										exStyle |= WS_EX_WINDOWEDGE;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (features & KINC_WINDOW_FEATURE_ON_TOP) {
							 | 
						||
| 
								 | 
							
										exStyle |= WS_EX_TOPMOST;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return exStyle;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int kinc_windows_window_index_from_hwnd(struct HWND__ *handle) {
							 | 
						||
| 
								 | 
							
									for (int i = 0; i < MAXIMUM_WINDOWS; ++i) {
							 | 
						||
| 
								 | 
							
										if (windows[i].handle == handle) {
							 | 
						||
| 
								 | 
							
											return i;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									return -1;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int kinc_count_windows() {
							 | 
						||
| 
								 | 
							
									return window_counter;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int kinc_window_x(int window_index) {
							 | 
						||
| 
								 | 
							
									RECT rect;
							 | 
						||
| 
								 | 
							
									GetWindowRect(windows[window_index].handle, &rect);
							 | 
						||
| 
								 | 
							
									windows[window_index].x = rect.left;
							 | 
						||
| 
								 | 
							
									return windows[window_index].x;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int kinc_window_y(int window_index) {
							 | 
						||
| 
								 | 
							
									RECT rect;
							 | 
						||
| 
								 | 
							
									GetWindowRect(windows[window_index].handle, &rect);
							 | 
						||
| 
								 | 
							
									windows[window_index].y = rect.top;
							 | 
						||
| 
								 | 
							
									return windows[window_index].y;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int kinc_window_width(int window_index) {
							 | 
						||
| 
								 | 
							
									RECT rect;
							 | 
						||
| 
								 | 
							
									GetClientRect(windows[window_index].handle, &rect);
							 | 
						||
| 
								 | 
							
									return rect.right;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int kinc_window_height(int window_index) {
							 | 
						||
| 
								 | 
							
									RECT rect;
							 | 
						||
| 
								 | 
							
									GetClientRect(windows[window_index].handle, &rect);
							 | 
						||
| 
								 | 
							
									return rect.bottom;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static DWORD getDwStyle(kinc_window_mode_t mode, int features) {
							 | 
						||
| 
								 | 
							
									switch (mode) {
							 | 
						||
| 
								 | 
							
									case KINC_WINDOW_MODE_EXCLUSIVE_FULLSCREEN: {
							 | 
						||
| 
								 | 
							
										return WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_POPUP;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									case KINC_WINDOW_MODE_FULLSCREEN:
							 | 
						||
| 
								 | 
							
										return WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_POPUP;
							 | 
						||
| 
								 | 
							
									case KINC_WINDOW_MODE_WINDOW:
							 | 
						||
| 
								 | 
							
									default:
							 | 
						||
| 
								 | 
							
										return getStyle(features);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static DWORD getDwExStyle(kinc_window_mode_t mode, int features) {
							 | 
						||
| 
								 | 
							
									switch (mode) {
							 | 
						||
| 
								 | 
							
									case KINC_WINDOW_MODE_EXCLUSIVE_FULLSCREEN: {
							 | 
						||
| 
								 | 
							
										return WS_EX_APPWINDOW;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									case KINC_WINDOW_MODE_FULLSCREEN:
							 | 
						||
| 
								 | 
							
										return WS_EX_APPWINDOW;
							 | 
						||
| 
								 | 
							
									case KINC_WINDOW_MODE_WINDOW:
							 | 
						||
| 
								 | 
							
									default:
							 | 
						||
| 
								 | 
							
										return getExStyle(features);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static int createWindow(const wchar_t *title, int x, int y, int width, int height, int bpp, int frequency, int features, kinc_window_mode_t windowMode,
							 | 
						||
| 
								 | 
							
								                        int target_display_index) {
							 | 
						||
| 
								 | 
							
									HINSTANCE inst = GetModuleHandleW(NULL);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (window_counter == 0) {
							 | 
						||
| 
								 | 
							
										RegisterWindowClass(inst, windowClassName);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									int display_index = target_display_index == -1 ? kinc_primary_display() : target_display_index;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef KINC_VR
							 | 
						||
| 
								 | 
							
									int dstx = 0;
							 | 
						||
| 
								 | 
							
									int dsty = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									char titleutf8[1024];
							 | 
						||
| 
								 | 
							
									char classNameutf8[1024];
							 | 
						||
| 
								 | 
							
									WideCharToMultiByte(CP_UTF8, 0, title, -1, titleutf8, 1024 - 1, NULL, NULL);
							 | 
						||
| 
								 | 
							
									WideCharToMultiByte(CP_UTF8, 0, windowClassName, -1, classNameutf8, 1024 - 1, NULL, NULL);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									HWND hwnd = (HWND)kinc_vr_interface_init(inst, titleutf8, classNameutf8);
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
									RECT WindowRect;
							 | 
						||
| 
								 | 
							
									WindowRect.left = 0;
							 | 
						||
| 
								 | 
							
									WindowRect.right = width;
							 | 
						||
| 
								 | 
							
									WindowRect.top = 0;
							 | 
						||
| 
								 | 
							
									WindowRect.bottom = height;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (windowMode == KINC_WINDOW_MODE_EXCLUSIVE_FULLSCREEN) {
							 | 
						||
| 
								 | 
							
										kinc_windows_set_display_mode(display_index, width, height, bpp, frequency);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									AdjustWindowRectEx(&WindowRect, getDwStyle(windowMode, features), FALSE, getDwExStyle(windowMode, features));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									kinc_display_mode_t display_mode = kinc_display_current_mode(display_index);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									int dstx = display_mode.x;
							 | 
						||
| 
								 | 
							
									int dsty = display_mode.y;
							 | 
						||
| 
								 | 
							
									int dstw = width;
							 | 
						||
| 
								 | 
							
									int dsth = height;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									switch (windowMode) {
							 | 
						||
| 
								 | 
							
									case KINC_WINDOW_MODE_WINDOW:
							 | 
						||
| 
								 | 
							
										dstx += x < 0 ? (display_mode.width - width) / 2 : x;
							 | 
						||
| 
								 | 
							
										dsty += y < 0 ? (display_mode.height - height) / 2 : y;
							 | 
						||
| 
								 | 
							
										dstw = WindowRect.right - WindowRect.left;
							 | 
						||
| 
								 | 
							
										dsth = WindowRect.bottom - WindowRect.top;
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									case KINC_WINDOW_MODE_FULLSCREEN:
							 | 
						||
| 
								 | 
							
										dstw = display_mode.width;
							 | 
						||
| 
								 | 
							
										dsth = display_mode.height;
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									case KINC_WINDOW_MODE_EXCLUSIVE_FULLSCREEN:
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									HWND hwnd = CreateWindowExW(getDwExStyle(windowMode, features), windowClassName, title, getDwStyle(windowMode, features), dstx, dsty, dstw, dsth, NULL, NULL,
							 | 
						||
| 
								 | 
							
									                            inst, NULL);
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									SetCursor(LoadCursor(NULL, IDC_ARROW));
							 | 
						||
| 
								 | 
							
									DragAcceptFiles(hwnd, true);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									windows[window_counter].handle = hwnd;
							 | 
						||
| 
								 | 
							
									windows[window_counter].x = dstx;
							 | 
						||
| 
								 | 
							
									windows[window_counter].y = dsty;
							 | 
						||
| 
								 | 
							
									windows[window_counter].mode = windowMode;
							 | 
						||
| 
								 | 
							
									windows[window_counter].display_index = display_index;
							 | 
						||
| 
								 | 
							
									windows[window_counter].bpp = bpp;
							 | 
						||
| 
								 | 
							
									windows[window_counter].frequency = frequency;
							 | 
						||
| 
								 | 
							
									windows[window_counter].features = features;
							 | 
						||
| 
								 | 
							
									windows[window_counter].manualWidth = width;
							 | 
						||
| 
								 | 
							
									windows[window_counter].manualHeight = height;
							 | 
						||
| 
								 | 
							
									windows[window_counter].index = window_counter;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return window_counter++;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void kinc_window_resize(int window_index, int width, int height) {
							 | 
						||
| 
								 | 
							
									WindowData *win = &windows[window_index];
							 | 
						||
| 
								 | 
							
									win->manualWidth = width;
							 | 
						||
| 
								 | 
							
									win->manualHeight = height;
							 | 
						||
| 
								 | 
							
									switch (win->mode) {
							 | 
						||
| 
								 | 
							
									case KINC_WINDOW_MODE_WINDOW: {
							 | 
						||
| 
								 | 
							
										RECT rect;
							 | 
						||
| 
								 | 
							
										rect.left = 0;
							 | 
						||
| 
								 | 
							
										rect.top = 0;
							 | 
						||
| 
								 | 
							
										rect.right = width;
							 | 
						||
| 
								 | 
							
										rect.bottom = height;
							 | 
						||
| 
								 | 
							
										AdjustWindowRectEx(&rect, getDwStyle((kinc_window_mode_t)win->mode, win->features), FALSE, getDwExStyle((kinc_window_mode_t)win->mode, win->features));
							 | 
						||
| 
								 | 
							
										SetWindowPos(win->handle, NULL, kinc_window_x(window_index), kinc_window_y(window_index), rect.right - rect.left, rect.bottom - rect.top, 0);
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									case KINC_WINDOW_MODE_EXCLUSIVE_FULLSCREEN: {
							 | 
						||
| 
								 | 
							
										int display_index = kinc_window_display(window_index);
							 | 
						||
| 
								 | 
							
										kinc_display_mode_t display_mode = kinc_display_current_mode(display_index);
							 | 
						||
| 
								 | 
							
										kinc_windows_set_display_mode(display_index, width, height, win->bpp, win->frequency);
							 | 
						||
| 
								 | 
							
										SetWindowPos(win->handle, NULL, display_mode.x, display_mode.y, display_mode.width, display_mode.height, 0);
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void kinc_window_move(int window_index, int x, int y) {
							 | 
						||
| 
								 | 
							
									WindowData *win = &windows[window_index];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (win->mode != 0) {
							 | 
						||
| 
								 | 
							
										return;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									win->x = x;
							 | 
						||
| 
								 | 
							
									win->y = y;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									RECT rect;
							 | 
						||
| 
								 | 
							
									rect.left = 0;
							 | 
						||
| 
								 | 
							
									rect.top = 0;
							 | 
						||
| 
								 | 
							
									rect.right = kinc_window_width(window_index);
							 | 
						||
| 
								 | 
							
									rect.bottom = kinc_window_height(window_index);
							 | 
						||
| 
								 | 
							
									AdjustWindowRectEx(&rect, getDwStyle((kinc_window_mode_t)win->mode, win->features), FALSE, getDwExStyle((kinc_window_mode_t)win->mode, win->features));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									SetWindowPos(win->handle, NULL, x, y, rect.right - rect.left, rect.bottom - rect.top, 0);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void kinc_internal_change_framebuffer(int window, struct kinc_framebuffer_options *frame);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void kinc_window_change_framebuffer(int window, kinc_framebuffer_options_t *frame) {
							 | 
						||
| 
								 | 
							
									kinc_internal_change_framebuffer(window, frame);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void kinc_window_change_features(int window_index, int features) {
							 | 
						||
| 
								 | 
							
									WindowData *win = &windows[window_index];
							 | 
						||
| 
								 | 
							
									win->features = features;
							 | 
						||
| 
								 | 
							
									SetWindowLongW(win->handle, GWL_STYLE, getStyle(features));
							 | 
						||
| 
								 | 
							
									SetWindowLongW(win->handle, GWL_EXSTYLE, getExStyle(features));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									HWND on_top = (features & KINC_WINDOW_FEATURE_ON_TOP) ? HWND_TOPMOST : HWND_NOTOPMOST;
							 | 
						||
| 
								 | 
							
									SetWindowPos(win->handle, on_top, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									kinc_window_show(window_index);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void kinc_window_change_mode(int window_index, kinc_window_mode_t mode) {
							 | 
						||
| 
								 | 
							
									WindowData *win = &windows[window_index];
							 | 
						||
| 
								 | 
							
									int display_index = kinc_window_display(window_index);
							 | 
						||
| 
								 | 
							
									kinc_display_mode_t display_mode = kinc_display_current_mode(display_index);
							 | 
						||
| 
								 | 
							
									switch (mode) {
							 | 
						||
| 
								 | 
							
									case KINC_WINDOW_MODE_WINDOW:
							 | 
						||
| 
								 | 
							
										kinc_windows_restore_display(display_index);
							 | 
						||
| 
								 | 
							
										kinc_window_change_features(window_index, win->features);
							 | 
						||
| 
								 | 
							
										kinc_window_show(window_index);
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									case KINC_WINDOW_MODE_FULLSCREEN: {
							 | 
						||
| 
								 | 
							
										kinc_windows_restore_display(display_index);
							 | 
						||
| 
								 | 
							
										SetWindowLongW(win->handle, GWL_STYLE, WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_POPUP);
							 | 
						||
| 
								 | 
							
										SetWindowLongW(win->handle, GWL_EXSTYLE, WS_EX_APPWINDOW);
							 | 
						||
| 
								 | 
							
										SetWindowPos(win->handle, NULL, display_mode.x, display_mode.y, display_mode.width, display_mode.height, 0);
							 | 
						||
| 
								 | 
							
										kinc_window_show(window_index);
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									case KINC_WINDOW_MODE_EXCLUSIVE_FULLSCREEN:
							 | 
						||
| 
								 | 
							
										kinc_windows_set_display_mode(display_index, win->manualWidth, win->manualHeight, win->bpp, win->frequency);
							 | 
						||
| 
								 | 
							
										SetWindowLongW(win->handle, GWL_STYLE, WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_POPUP);
							 | 
						||
| 
								 | 
							
										SetWindowLongW(win->handle, GWL_EXSTYLE, WS_EX_APPWINDOW);
							 | 
						||
| 
								 | 
							
										SetWindowPos(win->handle, NULL, display_mode.x, display_mode.y, display_mode.width, display_mode.height, 0);
							 | 
						||
| 
								 | 
							
										kinc_window_show(window_index);
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									win->mode = mode;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								kinc_window_mode_t kinc_window_get_mode(int window_index) {
							 | 
						||
| 
								 | 
							
									return (kinc_window_mode_t)windows[window_index].mode;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void kinc_window_destroy(int window_index) {
							 | 
						||
| 
								 | 
							
									WindowData *win = &windows[window_index];
							 | 
						||
| 
								 | 
							
									if (win->handle != NULL) {
							 | 
						||
| 
								 | 
							
										kinc_g4_internal_destroy_window(window_index);
							 | 
						||
| 
								 | 
							
										DestroyWindow(win->handle);
							 | 
						||
| 
								 | 
							
										win->handle = NULL;
							 | 
						||
| 
								 | 
							
										--window_counter;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void kinc_windows_hide_windows(void) {
							 | 
						||
| 
								 | 
							
									for (int i = 0; i < MAXIMUM_WINDOWS; ++i) {
							 | 
						||
| 
								 | 
							
										if (windows[i].handle != NULL) {
							 | 
						||
| 
								 | 
							
											ShowWindow(windows[i].handle, SW_HIDE);
							 | 
						||
| 
								 | 
							
											UpdateWindow(windows[i].handle);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void kinc_windows_destroy_windows(void) {
							 | 
						||
| 
								 | 
							
									for (int i = 0; i < MAXIMUM_WINDOWS; ++i) {
							 | 
						||
| 
								 | 
							
										kinc_window_destroy(i);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									UnregisterClassW(windowClassName, GetModuleHandleW(NULL));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void kinc_window_show(int window_index) {
							 | 
						||
| 
								 | 
							
									ShowWindow(windows[window_index].handle, SW_SHOWDEFAULT);
							 | 
						||
| 
								 | 
							
									UpdateWindow(windows[window_index].handle);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void kinc_window_hide(int window_index) {
							 | 
						||
| 
								 | 
							
									ShowWindow(windows[window_index].handle, SW_HIDE);
							 | 
						||
| 
								 | 
							
									UpdateWindow(windows[window_index].handle);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void kinc_window_set_title(int window_index, const char *title) {
							 | 
						||
| 
								 | 
							
									wchar_t buffer[1024];
							 | 
						||
| 
								 | 
							
									MultiByteToWideChar(CP_UTF8, 0, title, -1, buffer, 1024);
							 | 
						||
| 
								 | 
							
									SetWindowTextW(windows[window_index].handle, buffer);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int kinc_window_create(kinc_window_options_t *win, kinc_framebuffer_options_t *frame) {
							 | 
						||
| 
								 | 
							
									kinc_window_options_t defaultWin;
							 | 
						||
| 
								 | 
							
									kinc_framebuffer_options_t defaultFrame;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (win == NULL) {
							 | 
						||
| 
								 | 
							
										kinc_window_options_set_defaults(&defaultWin);
							 | 
						||
| 
								 | 
							
										win = &defaultWin;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (frame == NULL) {
							 | 
						||
| 
								 | 
							
										kinc_framebuffer_options_set_defaults(&defaultFrame);
							 | 
						||
| 
								 | 
							
										frame = &defaultFrame;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (win->title == NULL) {
							 | 
						||
| 
								 | 
							
										win->title = "";
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									wchar_t wbuffer[1024];
							 | 
						||
| 
								 | 
							
									MultiByteToWideChar(CP_UTF8, 0, win->title, -1, wbuffer, 1024);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									int windowId = createWindow(wbuffer, win->x, win->y, win->width, win->height, frame->color_bits, frame->frequency, win->window_features, win->mode,
							 | 
						||
| 
								 | 
							
									                            win->display_index);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									kinc_g4_set_antialiasing_samples(frame->samples_per_pixel);
							 | 
						||
| 
								 | 
							
									bool vsync = frame->vertical_sync;
							 | 
						||
| 
								 | 
							
								#ifdef KINC_OCULUS
							 | 
						||
| 
								 | 
							
									vsync = false;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
									kinc_g4_internal_init_window(windowId, frame->depth_bits, frame->stencil_bits, vsync);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (win->visible) {
							 | 
						||
| 
								 | 
							
										kinc_window_show(windowId);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return windowId;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void kinc_window_set_resize_callback(int window_index, void (*callback)(int x, int y, void *data), void *data) {
							 | 
						||
| 
								 | 
							
									windows[window_index].resizeCallback = callback;
							 | 
						||
| 
								 | 
							
									windows[window_index].resizeCallbackData = data;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void kinc_window_set_ppi_changed_callback(int window_index, void (*callback)(int ppi, void *data), void *data) {
							 | 
						||
| 
								 | 
							
									windows[window_index].ppiCallback = callback;
							 | 
						||
| 
								 | 
							
									windows[window_index].ppiCallbackData = data;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void kinc_window_set_close_callback(int window_index, bool (*callback)(void *data), void *data) {
							 | 
						||
| 
								 | 
							
									windows[window_index].closeCallback = callback;
							 | 
						||
| 
								 | 
							
									windows[window_index].closeCallbackData = data;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int kinc_window_display(int window_index) {
							 | 
						||
| 
								 | 
							
									return kinc_windows_get_display_for_monitor(MonitorFromWindow(windows[window_index].handle, MONITOR_DEFAULTTOPRIMARY));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								struct HWND__ *kinc_windows_window_handle(int window_index) {
							 | 
						||
| 
								 | 
							
									return windows[window_index].handle;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int kinc_windows_manual_width(int window) {
							 | 
						||
| 
								 | 
							
									return windows[window].manualWidth;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int kinc_windows_manual_height(int window) {
							 | 
						||
| 
								 | 
							
									return windows[window].manualHeight;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void kinc_internal_call_resize_callback(int window_index, int width, int height) {
							 | 
						||
| 
								 | 
							
									if (windows[window_index].resizeCallback != NULL) {
							 | 
						||
| 
								 | 
							
										windows[window_index].resizeCallback(width, height, windows[window_index].resizeCallbackData);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void kinc_internal_call_ppi_changed_callback(int window_index, int ppi) {
							 | 
						||
| 
								 | 
							
									if (windows[window_index].ppiCallback != NULL) {
							 | 
						||
| 
								 | 
							
										windows[window_index].ppiCallback(ppi, windows[window_index].ppiCallbackData);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								bool kinc_internal_call_close_callback(int window_index) {
							 | 
						||
| 
								 | 
							
									if (windows[window_index].closeCallback != NULL) {
							 | 
						||
| 
								 | 
							
										return windows[window_index].closeCallback(windows[window_index].closeCallbackData);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									return true;
							 | 
						||
| 
								 | 
							
								}
							 |