Windows/Linux: avoid relying on hidden win_handle global

This commit is contained in:
UnknownShadow200 2024-07-12 19:15:39 +10:00
parent 202e67c3dd
commit e28603c66c
3 changed files with 117 additions and 75 deletions

View File

@ -673,7 +673,7 @@ static void DrawColouredTriangles(int verticesCount, int startVertex) {
static void DrawTriangles(int verticesCount, int startVertex) { static void DrawTriangles(int verticesCount, int startVertex) {
if (stateDirty) UpdateState(0); if (stateDirty) UpdateState(0);
if (formatDirty) UpdateFormat(); if (formatDirty) UpdateFormat(0);
if ((q - current->data) > 45000) { if ((q - current->data) > 45000) {
DMATAG_END(dma_tag, (q - current->data) - 1, 0, 0, 0); DMATAG_END(dma_tag, (q - current->data) - 1, 0, 0, 0);

View File

@ -108,10 +108,11 @@ static int MapNativeKey(WPARAM vk_key, LPARAM meta) {
} }
static cc_bool RefreshWindowDimensions(void) { static cc_bool RefreshWindowDimensions(void) {
HWND hwnd = Window_Main.Handle.ptr;
RECT rect; RECT rect;
int width = Window_Main.Width, height = Window_Main.Height; int width = Window_Main.Width, height = Window_Main.Height;
GetClientRect(win_handle, &rect); GetClientRect(hwnd, &rect);
Window_Main.Width = Rect_Width(rect); Window_Main.Width = Rect_Width(rect);
Window_Main.Height = Rect_Height(rect); Window_Main.Height = Rect_Height(rect);
@ -119,23 +120,26 @@ static cc_bool RefreshWindowDimensions(void) {
} }
static void RefreshWindowPosition(void) { static void RefreshWindowPosition(void) {
HWND hwnd = Window_Main.Handle.ptr;
POINT topLeft = { 0, 0 }; POINT topLeft = { 0, 0 };
/* GetClientRect always returns 0,0 for left,top (see MSDN) */ /* GetClientRect always returns 0,0 for left,top (see MSDN) */
ClientToScreen(win_handle, &topLeft); ClientToScreen(hwnd, &topLeft);
windowX = topLeft.x; windowY = topLeft.y; windowX = topLeft.x; windowY = topLeft.y;
} }
static void GrabCursor(void) { static void GrabCursor(void) {
HWND hwnd = Window_Main.Handle.ptr;
RECT rect; RECT rect;
if (!grabCursor || !Input.RawMode) return; if (!grabCursor || !Input.RawMode) return;
GetWindowRect(win_handle, &rect); GetWindowRect(hwnd, &rect);
ClipCursor(&rect); ClipCursor(&rect);
} }
static LRESULT CALLBACK Window_Procedure(HWND handle, UINT message, WPARAM wParam, LPARAM lParam) { static LRESULT CALLBACK Window_Procedure(HWND handle, UINT message, WPARAM wParam, LPARAM lParam) {
float wheelDelta; float wheelDelta;
cc_bool sized; cc_bool sized;
HWND hwnd;
switch (message) { switch (message) {
case WM_ACTIVATE: case WM_ACTIVATE:
@ -147,7 +151,8 @@ static LRESULT CALLBACK Window_Procedure(HWND handle, UINT message, WPARAM wPara
return 1; /* Avoid flickering */ return 1; /* Avoid flickering */
case WM_PAINT: case WM_PAINT:
ValidateRect(win_handle, NULL); hwnd = Window_Main.Handle.ptr;
ValidateRect(hwnd, NULL);
Event_RaiseVoid(&WindowEvents.RedrawNeeded); Event_RaiseVoid(&WindowEvents.RedrawNeeded);
return 0; return 0;
@ -356,45 +361,49 @@ static ATOM DoRegisterClass(void) {
return RegisterClassExA((const WNDCLASSEXA*)&wc); return RegisterClassExA((const WNDCLASSEXA*)&wc);
} }
static void CreateWindowHandle(ATOM atom, int width, int height) { static HWND CreateWindowHandle(ATOM atom, int width, int height) {
cc_result res; cc_result res;
HWND hwnd;
RECT r; RECT r;
/* Calculate final window rectangle after window decorations are added (titlebar, borders etc) */ /* Calculate final window rectangle after window decorations are added (titlebar, borders etc) */
r.left = Display_CentreX(width); r.right = r.left + width; r.left = Display_CentreX(width); r.right = r.left + width;
r.top = Display_CentreY(height); r.bottom = r.top + height; r.top = Display_CentreY(height); r.bottom = r.top + height;
AdjustWindowRect(&r, CC_WIN_STYLE, false); AdjustWindowRect(&r, CC_WIN_STYLE, false);
if ((win_handle = CreateWindowExW(0, MAKEINTATOM(atom), NULL, CC_WIN_STYLE, if ((hwnd = CreateWindowExW(0, MAKEINTATOM(atom), NULL, CC_WIN_STYLE,
r.left, r.top, Rect_Width(r), Rect_Height(r), NULL, NULL, win_instance, NULL))) return; r.left, r.top, Rect_Width(r), Rect_Height(r), NULL, NULL, win_instance, NULL))) return hwnd;
res = GetLastError(); res = GetLastError();
/* Windows 9x does not support W API functions */ /* Windows 9x does not support W API functions */
if (res == ERROR_CALL_NOT_IMPLEMENTED) { if (res == ERROR_CALL_NOT_IMPLEMENTED) {
is_ansiWindow = true; is_ansiWindow = true;
if ((win_handle = CreateWindowExA(0, (LPCSTR)MAKEINTATOM(atom), NULL, CC_WIN_STYLE, if ((hwnd = CreateWindowExA(0, (LPCSTR)MAKEINTATOM(atom), NULL, CC_WIN_STYLE,
r.left, r.top, Rect_Width(r), Rect_Height(r), NULL, NULL, win_instance, NULL))) return; r.left, r.top, Rect_Width(r), Rect_Height(r), NULL, NULL, win_instance, NULL))) return hwnd;
res = GetLastError(); res = GetLastError();
} }
Logger_Abort2(res, "Failed to create window"); Logger_Abort2(res, "Failed to create window");
return NULL;
} }
static void DoCreateWindow(int width, int height) { static void DoCreateWindow(int width, int height) {
ATOM atom; ATOM atom;
HWND hwnd;
win_instance = GetModuleHandleA(NULL); win_instance = GetModuleHandleA(NULL);
/* TODO: UngroupFromTaskbar(); */ /* TODO: UngroupFromTaskbar(); */
width = Display_ScaleX(width); width = Display_ScaleX(width);
height = Display_ScaleY(height); height = Display_ScaleY(height);
atom = DoRegisterClass(); atom = DoRegisterClass();
CreateWindowHandle(atom, width, height); hwnd = CreateWindowHandle(atom, width, height);
RefreshWindowDimensions(); RefreshWindowDimensions();
RefreshWindowPosition(); RefreshWindowPosition();
win_DC = GetDC(win_handle); win_DC = GetDC(hwnd);
if (!win_DC) Logger_Abort2(GetLastError(), "Failed to get device context"); if (!win_DC) Logger_Abort2(GetLastError(), "Failed to get device context");
Window_Main.Exists = true; Window_Main.Exists = true;
Window_Main.Handle.ptr = win_handle; Window_Main.Handle.ptr = hwnd;
Window_Main.UIScaleX = DEFAULT_UI_SCALE_X; Window_Main.UIScaleX = DEFAULT_UI_SCALE_X;
Window_Main.UIScaleY = DEFAULT_UI_SCALE_Y; Window_Main.UIScaleY = DEFAULT_UI_SCALE_Y;
@ -404,20 +413,23 @@ void Window_Create2D(int width, int height) { DoCreateWindow(width, height); }
void Window_Create3D(int width, int height) { DoCreateWindow(width, height); } void Window_Create3D(int width, int height) { DoCreateWindow(width, height); }
void Window_Destroy(void) { void Window_Destroy(void) {
if (win_DC) ReleaseDC(win_handle, win_DC); HWND hwnd = Window_Main.Handle.ptr;
DestroyWindow(win_handle); if (win_DC) ReleaseDC(hwnd, win_DC);
DestroyWindow(hwnd);
} }
void Window_SetTitle(const cc_string* title) { void Window_SetTitle(const cc_string* title) {
HWND hwnd = Window_Main.Handle.ptr;
cc_winstring str; cc_winstring str;
Platform_EncodeString(&str, title); Platform_EncodeString(&str, title);
if (SetWindowTextW(win_handle, str.uni)) return; if (SetWindowTextW(hwnd, str.uni)) return;
/* Windows 9x does not support W API functions */ /* Windows 9x does not support W API functions */
SetWindowTextA(win_handle, str.ansi); SetWindowTextA(hwnd, str.ansi);
} }
void Clipboard_GetText(cc_string* value) { void Clipboard_GetText(cc_string* value) {
HWND hwnd = Window_Main.Handle.ptr;
cc_bool unicode; cc_bool unicode;
HANDLE hGlobal; HANDLE hGlobal;
LPVOID src; LPVOID src;
@ -426,7 +438,7 @@ void Clipboard_GetText(cc_string* value) {
/* retry up to 50 times */ /* retry up to 50 times */
for (i = 0; i < 50; i++) { for (i = 0; i < 50; i++) {
if (!OpenClipboard(win_handle)) { if (!OpenClipboard(hwnd)) {
Thread_Sleep(10); Thread_Sleep(10);
continue; continue;
} }
@ -457,13 +469,14 @@ void Clipboard_GetText(cc_string* value) {
} }
void Clipboard_SetText(const cc_string* value) { void Clipboard_SetText(const cc_string* value) {
HWND hwnd = Window_Main.Handle.ptr;
cc_unichar* text; cc_unichar* text;
HANDLE hGlobal; HANDLE hGlobal;
int i; int i;
/* retry up to 10 times */ /* retry up to 10 times */
for (i = 0; i < 10; i++) { for (i = 0; i < 10; i++) {
if (!OpenClipboard(win_handle)) { if (!OpenClipboard(hwnd)) {
Thread_Sleep(100); Thread_Sleep(100);
continue; continue;
} }
@ -486,23 +499,24 @@ void Clipboard_SetText(const cc_string* value) {
} }
int Window_GetWindowState(void) { int Window_GetWindowState(void) {
DWORD s = GetWindowLongA(win_handle, GWL_STYLE); HWND hwnd = Window_Main.Handle.ptr;
DWORD s = GetWindowLongA(hwnd, GWL_STYLE);
if ((s & WS_MINIMIZE)) return WINDOW_STATE_MINIMISED; if ((s & WS_MINIMIZE)) return WINDOW_STATE_MINIMISED;
if ((s & WS_MAXIMIZE) && (s & WS_POPUP)) return WINDOW_STATE_FULLSCREEN; if ((s & WS_MAXIMIZE) && (s & WS_POPUP)) return WINDOW_STATE_FULLSCREEN;
return WINDOW_STATE_NORMAL; return WINDOW_STATE_NORMAL;
} }
static void ToggleFullscreen(cc_bool fullscreen, UINT finalShow) { static void ToggleFullscreen(HWND hwnd, cc_bool fullscreen, UINT finalShow) {
DWORD style = WS_CLIPCHILDREN | WS_CLIPSIBLINGS; DWORD style = WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
style |= (fullscreen ? WS_POPUP : WS_OVERLAPPEDWINDOW); style |= (fullscreen ? WS_POPUP : WS_OVERLAPPEDWINDOW);
suppress_resize = true; suppress_resize = true;
{ {
ShowWindow(win_handle, SW_RESTORE); /* reset maximised state */ ShowWindow(hwnd, SW_RESTORE); /* reset maximised state */
SetWindowLongA(win_handle, GWL_STYLE, style); SetWindowLongA(hwnd, GWL_STYLE, style);
SetWindowPos(win_handle, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
ShowWindow(win_handle, finalShow); ShowWindow(hwnd, finalShow);
Window_ProcessEvents(0.0); Window_ProcessEvents(0.0);
} }
suppress_resize = false; suppress_resize = false;
@ -514,34 +528,38 @@ static void ToggleFullscreen(cc_bool fullscreen, UINT finalShow) {
static UINT win_show; static UINT win_show;
cc_result Window_EnterFullscreen(void) { cc_result Window_EnterFullscreen(void) {
HWND hwnd = Window_Main.Handle.ptr;
WINDOWPLACEMENT w = { 0 }; WINDOWPLACEMENT w = { 0 };
w.length = sizeof(WINDOWPLACEMENT); w.length = sizeof(WINDOWPLACEMENT);
GetWindowPlacement(win_handle, &w); GetWindowPlacement(hwnd, &w);
win_show = w.showCmd; win_show = w.showCmd;
ToggleFullscreen(true, SW_MAXIMIZE); ToggleFullscreen(hwnd, true, SW_MAXIMIZE);
return 0; return 0;
} }
cc_result Window_ExitFullscreen(void) { cc_result Window_ExitFullscreen(void) {
ToggleFullscreen(false, win_show); HWND hwnd = Window_Main.Handle.ptr;
ToggleFullscreen(hwnd, false, win_show);
return 0; return 0;
} }
int Window_IsObscured(void) { return 0; } int Window_IsObscured(void) { return 0; }
void Window_Show(void) { void Window_Show(void) {
ShowWindow(win_handle, SW_SHOW); HWND hwnd = Window_Main.Handle.ptr;
BringWindowToTop(win_handle); ShowWindow(hwnd, SW_SHOW);
SetForegroundWindow(win_handle); BringWindowToTop(hwnd);
SetForegroundWindow(hwnd);
} }
void Window_SetSize(int width, int height) { void Window_SetSize(int width, int height) {
DWORD style = GetWindowLongA(win_handle, GWL_STYLE); HWND hwnd = Window_Main.Handle.ptr;
DWORD style = GetWindowLongA(hwnd, GWL_STYLE);
RECT rect = { 0, 0, width, height }; RECT rect = { 0, 0, width, height };
AdjustWindowRect(&rect, style, false); AdjustWindowRect(&rect, style, false);
SetWindowPos(win_handle, NULL, 0, 0, SetWindowPos(hwnd, NULL, 0, 0,
Rect_Width(rect), Rect_Height(rect), SWP_NOMOVE); Rect_Width(rect), Rect_Height(rect), SWP_NOMOVE);
} }
@ -551,6 +569,7 @@ void Window_RequestClose(void) {
void Window_ProcessEvents(float delta) { void Window_ProcessEvents(float delta) {
HWND foreground; HWND foreground;
HWND hwnd;
MSG msg; MSG msg;
if (is_ansiWindow) { if (is_ansiWindow) {
@ -565,7 +584,8 @@ void Window_ProcessEvents(float delta) {
foreground = GetForegroundWindow(); foreground = GetForegroundWindow();
if (foreground) { if (foreground) {
Window_Main.Focused = foreground == win_handle; hwnd = Window_Main.Handle.ptr;
Window_Main.Focused = foreground == hwnd;
} }
} }
@ -597,7 +617,8 @@ static void Cursor_DoSetVisible(cc_bool visible) {
} }
static void ShowDialogCore(const char* title, const char* msg) { static void ShowDialogCore(const char* title, const char* msg) {
MessageBoxA(win_handle, msg, title, 0); HWND hwnd = Window_Main.Handle.ptr;
MessageBoxA(hwnd, msg, title, 0);
} }
static cc_result OpenSaveFileDialog(const cc_string* filters, FileDialogCallback callback, cc_bool load, static cc_result OpenSaveFileDialog(const cc_string* filters, FileDialogCallback callback, cc_bool load,
@ -606,6 +627,7 @@ static cc_result OpenSaveFileDialog(const cc_string* filters, FileDialogCallback
OPENFILENAMEW wide; OPENFILENAMEW wide;
OPENFILENAMEA ansi; OPENFILENAMEA ansi;
} ofn = { 0 }; // less compiler warnings this way } ofn = { 0 }; // less compiler warnings this way
HWND hwnd = Window_Main.Handle.ptr;
cc_string path; char pathBuffer[NATIVE_STR_LEN]; cc_string path; char pathBuffer[NATIVE_STR_LEN];
cc_winstring str = { 0 }; cc_winstring str = { 0 };
@ -624,7 +646,7 @@ static cc_result OpenSaveFileDialog(const cc_string* filters, FileDialogCallback
/* on modern Windows versions the dialogs are altered to show an old Win 9x style appearance */ /* on modern Windows versions the dialogs are altered to show an old Win 9x style appearance */
/* (see https://github.com/geany/geany/issues/578 for example of this problem) */ /* (see https://github.com/geany/geany/issues/578 for example of this problem) */
ofn.wide.hwndOwner = win_handle; ofn.wide.hwndOwner = hwnd;
ofn.wide.lpstrFile = str.uni; ofn.wide.lpstrFile = str.uni;
ofn.wide.nMaxFile = MAX_PATH; ofn.wide.nMaxFile = MAX_PATH;
ofn.wide.lpstrFilter = filter.uni; ofn.wide.lpstrFilter = filter.uni;
@ -739,6 +761,7 @@ void Window_FreeFramebuffer(struct Bitmap* bmp) {
static cc_bool rawMouseInited, rawMouseSupported; static cc_bool rawMouseInited, rawMouseSupported;
static void InitRawMouse(void) { static void InitRawMouse(void) {
HWND hwnd = Window_Main.Handle.ptr;
RAWINPUTDEVICE rid; RAWINPUTDEVICE rid;
rawMouseSupported = _RegisterRawInputDevices && _GetRawInputData; rawMouseSupported = _RegisterRawInputDevices && _GetRawInputData;
@ -748,7 +771,7 @@ static void InitRawMouse(void) {
rid.usUsagePage = 1; /* HID_USAGE_PAGE_GENERIC; */ rid.usUsagePage = 1; /* HID_USAGE_PAGE_GENERIC; */
rid.usUsage = 2; /* HID_USAGE_GENERIC_MOUSE; */ rid.usUsage = 2; /* HID_USAGE_GENERIC_MOUSE; */
rid.dwFlags = RIDEV_INPUTSINK; rid.dwFlags = RIDEV_INPUTSINK;
rid.hwndTarget = win_handle; rid.hwndTarget = hwnd;
if (_RegisterRawInputDevices(&rid, 1, sizeof(rid))) return; if (_RegisterRawInputDevices(&rid, 1, sizeof(rid))) return;
Logger_SysWarn(GetLastError(), "initing raw mouse"); Logger_SysWarn(GetLastError(), "initing raw mouse");

View File

@ -35,7 +35,7 @@
#define _NET_WM_STATE_TOGGLE 2 #define _NET_WM_STATE_TOGGLE 2
static Display* win_display; static Display* win_display;
static Window win_rootWin, win_handle; static Window win_rootWin;
static XVisualInfo win_visual; static XVisualInfo win_visual;
#ifdef CC_BUILD_XIM #ifdef CC_BUILD_XIM
static XIM win_xim; static XIM win_xim;
@ -324,15 +324,15 @@ void Window_Free(void) { }
/* See misc/x11/x11_icon_gen.cs for how to generate this file */ /* See misc/x11/x11_icon_gen.cs for how to generate this file */
#include "../misc/x11/CCIcon_X11.h" #include "../misc/x11/CCIcon_X11.h"
static void ApplyIcon(void) { static void ApplyIcon(Window win) {
Atom net_wm_icon = XInternAtom(win_display, "_NET_WM_ICON", false); Atom net_wm_icon = XInternAtom(win_display, "_NET_WM_ICON", false);
Atom xa_cardinal = XInternAtom(win_display, "CARDINAL", false); Atom xa_cardinal = XInternAtom(win_display, "CARDINAL", false);
XChangeProperty(win_display, win_handle, net_wm_icon, xa_cardinal, 32, PropModeReplace, XChangeProperty(win_display, win, net_wm_icon, xa_cardinal, 32, PropModeReplace,
(unsigned char*)CCIcon_Data, CCIcon_Size); (unsigned char*)CCIcon_Data, CCIcon_Size);
} }
#else #else
static void ApplyIcon(void) { } static void ApplyIcon(Window win) { }
#endif #endif
static void DoCreateWindow(int width, int height) { static void DoCreateWindow(int width, int height) {
@ -352,7 +352,7 @@ static void DoCreateWindow(int width, int height) {
attributes.colormap = XCreateColormap(win_display, win_rootWin, win_visual.visual, AllocNone); attributes.colormap = XCreateColormap(win_display, win_rootWin, win_visual.visual, AllocNone);
attributes.event_mask = win_eventMask; attributes.event_mask = win_eventMask;
win_handle = XCreateWindow(win_display, win_rootWin, x, y, width, height, Window win = XCreateWindow(win_display, win_rootWin, x, y, width, height,
0, win_visual.depth /* CopyFromParent*/, InputOutput, win_visual.visual, 0, win_visual.depth /* CopyFromParent*/, InputOutput, win_visual.visual,
#ifdef CC_BUILD_IRIX #ifdef CC_BUILD_IRIX
CWColormap | CWEventMask | CWBlackPixel | CWBorderPixel, &attributes); CWColormap | CWEventMask | CWBlackPixel | CWBorderPixel, &attributes);
@ -361,12 +361,12 @@ static void DoCreateWindow(int width, int height) {
CWColormap | CWEventMask, &attributes); CWColormap | CWEventMask, &attributes);
#endif #endif
if (!win_handle) Logger_Abort("XCreateWindow failed"); if (!win) Logger_Abort("XCreateWindow failed");
#ifdef CC_BUILD_XIM #ifdef CC_BUILD_XIM
win_xim = XOpenIM(win_display, NULL, NULL, NULL); win_xim = XOpenIM(win_display, NULL, NULL, NULL);
win_xic = XCreateIC(win_xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, win_xic = XCreateIC(win_xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
XNClientWindow, win_handle, NULL); XNClientWindow, win, NULL);
#endif #endif
/* Set hints to try to force WM to create window at requested x,y */ /* Set hints to try to force WM to create window at requested x,y */
@ -374,12 +374,12 @@ static void DoCreateWindow(int width, int height) {
hints.base_width = width; hints.base_width = width;
hints.base_height = height; hints.base_height = height;
hints.flags = PSize | PPosition; hints.flags = PSize | PPosition;
XSetWMNormalHints(win_display, win_handle, &hints); XSetWMNormalHints(win_display, win, &hints);
/* Register for window destroy notification */ /* Register for window destroy notification */
protocols[0] = wm_destroy; protocols[0] = wm_destroy;
protocols[1] = net_wm_ping; protocols[1] = net_wm_ping;
XSetWMProtocols(win_display, win_handle, protocols, 2); XSetWMProtocols(win_display, win, protocols, 2);
/* Request that auto-repeat is only set on devices that support it physically. /* Request that auto-repeat is only set on devices that support it physically.
This typically means that it's turned off for keyboards (which is what we want). This typically means that it's turned off for keyboards (which is what we want).
@ -389,7 +389,7 @@ static void DoCreateWindow(int width, int height) {
RefreshWindowBounds(width, height); RefreshWindowBounds(width, height);
Window_Main.Exists = true; Window_Main.Exists = true;
Window_Main.Handle.val = win_handle; Window_Main.Handle.val = win;
Window_Main.UIScaleX = DEFAULT_UI_SCALE_X; Window_Main.UIScaleX = DEFAULT_UI_SCALE_X;
Window_Main.UIScaleY = DEFAULT_UI_SCALE_Y; Window_Main.UIScaleY = DEFAULT_UI_SCALE_Y;
grabCursor = Options_GetBool(OPT_GRAB_CURSOR, false); grabCursor = Options_GetBool(OPT_GRAB_CURSOR, false);
@ -403,27 +403,29 @@ static void DoCreateWindow(int width, int height) {
hint.res_name = GAME_APP_TITLE; hint.res_name = GAME_APP_TITLE;
hint.res_class = GAME_APP_TITLE; hint.res_class = GAME_APP_TITLE;
#endif #endif
XSetClassHint(win_display, win_handle, &hint); XSetClassHint(win_display, win, &hint);
ApplyIcon(); ApplyIcon(win);
/* Check for focus initially, in case WM doesn't send a FocusIn event */ /* Check for focus initially, in case WM doesn't send a FocusIn event */
XGetInputFocus(win_display, &focus, &focusRevert); XGetInputFocus(win_display, &focus, &focusRevert);
if (focus == win_handle) Window_Main.Focused = true; if (focus == win) Window_Main.Focused = true;
} }
void Window_Create2D(int width, int height) { DoCreateWindow(width, height); } void Window_Create2D(int width, int height) { DoCreateWindow(width, height); }
void Window_Create3D(int width, int height) { DoCreateWindow(width, height); } void Window_Create3D(int width, int height) { DoCreateWindow(width, height); }
void Window_Destroy(void) { void Window_Destroy(void) {
Window win = Window_Main.Handle.val;
/* sync and discard all events queued */ /* sync and discard all events queued */
XSync(win_display, true); XSync(win_display, true);
XDestroyWindow(win_display, win_handle); XDestroyWindow(win_display, win);
Window_Main.Exists = false; Window_Main.Exists = false;
} }
void Window_SetTitle(const cc_string* title) { void Window_SetTitle(const cc_string* title) {
Window win = Window_Main.Handle.val;
char str[NATIVE_STR_LEN]; char str[NATIVE_STR_LEN];
String_EncodeUtf8(str, title); String_EncodeUtf8(str, title);
XStoreName(win_display, win_handle, str); XStoreName(win_display, win, str);
} }
static char clipboard_copy_buffer[256]; static char clipboard_copy_buffer[256];
@ -433,11 +435,12 @@ static cc_string clipboard_paste_text = String_FromArray(clipboard_paste_buffer)
static cc_bool clipboard_paste_received; static cc_bool clipboard_paste_received;
void Clipboard_GetText(cc_string* value) { void Clipboard_GetText(cc_string* value) {
Window win = Window_Main.Handle.val;
Window owner = XGetSelectionOwner(win_display, xa_clipboard); Window owner = XGetSelectionOwner(win_display, xa_clipboard);
int i; int i;
if (!owner) return; /* no window owner */ if (!owner) return; /* no window owner */
XConvertSelection(win_display, xa_clipboard, xa_utf8_string, xa_data_sel, win_handle, 0); XConvertSelection(win_display, xa_clipboard, xa_utf8_string, xa_data_sel, win, 0);
clipboard_paste_received = false; clipboard_paste_received = false;
clipboard_paste_text.length = 0; clipboard_paste_text.length = 0;
@ -454,19 +457,21 @@ void Clipboard_GetText(cc_string* value) {
} }
void Clipboard_SetText(const cc_string* value) { void Clipboard_SetText(const cc_string* value) {
Window win = Window_Main.Handle.val;
String_Copy(&clipboard_copy_text, value); String_Copy(&clipboard_copy_text, value);
XSetSelectionOwner(win_display, xa_clipboard, win_handle, 0); XSetSelectionOwner(win_display, xa_clipboard, win, 0);
} }
int Window_GetWindowState(void) { int Window_GetWindowState(void) {
cc_bool fullscreen = false, minimised = false; cc_bool fullscreen = false, minimised = false;
Window win = Window_Main.Handle.val;
Atom prop_type; Atom prop_type;
unsigned long items, after; unsigned long items, after;
unsigned char* data = NULL; unsigned char* data = NULL;
int i, prop_format; int i, prop_format;
Atom* list; Atom* list;
XGetWindowProperty(win_display, win_handle, XGetWindowProperty(win_display, win,
net_wm_state, 0, 256, false, xa_atom, &prop_type, net_wm_state, 0, 256, false, xa_atom, &prop_type,
&prop_format, &items, &after, &data); &prop_format, &items, &after, &data);
@ -490,9 +495,10 @@ int Window_GetWindowState(void) {
} }
static void ToggleFullscreen(long op) { static void ToggleFullscreen(long op) {
Window win = Window_Main.Handle.val;
XEvent ev = { 0 }; XEvent ev = { 0 };
ev.xclient.type = ClientMessage; ev.xclient.type = ClientMessage;
ev.xclient.window = win_handle; ev.xclient.window = win;
ev.xclient.message_type = net_wm_state; ev.xclient.message_type = net_wm_state;
ev.xclient.format = 32; ev.xclient.format = 32;
ev.xclient.data.l[0] = op; ev.xclient.data.l[0] = op;
@ -501,7 +507,7 @@ static void ToggleFullscreen(long op) {
XSendEvent(win_display, win_rootWin, false, XSendEvent(win_display, win_rootWin, false,
SubstructureRedirectMask | SubstructureNotifyMask, &ev); SubstructureRedirectMask | SubstructureNotifyMask, &ev);
XSync(win_display, false); XSync(win_display, false);
XRaiseWindow(win_display, win_handle); XRaiseWindow(win_display, win);
Window_ProcessEvents(0.0); Window_ProcessEvents(0.0);
} }
@ -514,10 +520,14 @@ cc_result Window_ExitFullscreen(void) {
int Window_IsObscured(void) { return 0; } int Window_IsObscured(void) { return 0; }
void Window_Show(void) { XMapWindow(win_display, win_handle); } void Window_Show(void) {
Window win = Window_Main.Handle.val;
XMapWindow(win_display, win);
}
void Window_SetSize(int width, int height) { void Window_SetSize(int width, int height) {
XResizeWindow(win_display, win_handle, width, height); Window win = Window_Main.Handle.val;
XResizeWindow(win_display, win, width, height);
Window_ProcessEvents(0.0); Window_ProcessEvents(0.0);
} }
@ -586,13 +596,14 @@ static void HandleWMPing(XEvent* e) {
static void HandleGenericEvent(XEvent* e); static void HandleGenericEvent(XEvent* e);
void Window_ProcessEvents(float delta) { void Window_ProcessEvents(float delta) {
Window win = Window_Main.Handle.val;
XEvent e; XEvent e;
Window focus; Window focus;
int focusRevert; int focusRevert;
int i, btn, key, status; int i, btn, key, status;
while (Window_Main.Exists) { while (Window_Main.Exists) {
if (!XCheckIfEvent(win_display, &e, FilterEvent, (XPointer)win_handle)) break; if (!XCheckIfEvent(win_display, &e, FilterEvent, (XPointer)win)) break;
if (XFilterEvent(&e, None) == True) continue; if (XFilterEvent(&e, None) == True) continue;
switch (e.type) { switch (e.type) {
@ -716,9 +727,9 @@ void Window_ProcessEvents(float delta) {
unsigned long items, after; unsigned long items, after;
cc_uint8* data = NULL; cc_uint8* data = NULL;
XGetWindowProperty(win_display, win_handle, xa_data_sel, 0, 1024, false, 0, XGetWindowProperty(win_display, win, xa_data_sel, 0, 1024, false, 0,
&prop_type, &prop_format, &items, &after, &data); &prop_type, &prop_format, &items, &after, &data);
XDeleteProperty(win_display, win_handle, xa_data_sel); XDeleteProperty(win_display, win, xa_data_sel);
if (data && items && prop_type == xa_utf8_string) { if (data && items && prop_type == xa_utf8_string) {
clipboard_paste_received = true; clipboard_paste_received = true;
@ -775,23 +786,25 @@ static void Cursor_GetRawPos(int* x, int* y) {
} }
void Cursor_SetPosition(int x, int y) { void Cursor_SetPosition(int x, int y) {
XWarpPointer(win_display, None, win_handle, 0, 0, 0, 0, x, y); Window win = Window_Main.Handle.val;
XWarpPointer(win_display, None, win, 0, 0, 0, 0, x, y);
XFlush(win_display); /* TODO: not sure if XFlush call is necessary */ XFlush(win_display); /* TODO: not sure if XFlush call is necessary */
} }
static Cursor blankCursor; static Cursor blankCursor;
static void Cursor_DoSetVisible(cc_bool visible) { static void Cursor_DoSetVisible(cc_bool visible) {
Window win = Window_Main.Handle.val;
if (visible) { if (visible) {
XUndefineCursor(win_display, win_handle); XUndefineCursor(win_display, win);
} else { } else {
if (!blankCursor) { if (!blankCursor) {
char data = 0; char data = 0;
XColor col = { 0 }; XColor col = { 0 };
Pixmap pixmap = XCreateBitmapFromData(win_display, win_handle, &data, 1, 1); Pixmap pixmap = XCreateBitmapFromData(win_display, win, &data, 1, 1);
blankCursor = XCreatePixmapCursor(win_display, pixmap, pixmap, &col, &col, 0, 0); blankCursor = XCreatePixmapCursor(win_display, pixmap, pixmap, &col, &col, 0, 0);
XFreePixmap(win_display, pixmap); XFreePixmap(win_display, pixmap);
} }
XDefineCursor(win_display, win_handle, blankCursor); XDefineCursor(win_display, win, blankCursor);
} }
} }
@ -931,6 +944,7 @@ static Bool X11_FilterEvent(Display* d, XEvent* e, XPointer w) { return e->xany.
static void X11_MessageBox(const char* title, const char* text, struct X11MessageBox* m) { static void X11_MessageBox(const char* title, const char* text, struct X11MessageBox* m) {
struct X11Button ok = { 0 }; struct X11Button ok = { 0 };
struct X11Textbox body = { 0 }; struct X11Textbox body = { 0 };
Window win = Window_Main.Handle.val;
Atom protocols[2]; Atom protocols[2];
XFontStruct* font; XFontStruct* font;
@ -973,7 +987,7 @@ static void X11_MessageBox(const char* title, const char* text, struct X11Messag
/* This marks the window as popup window of the main window */ /* This marks the window as popup window of the main window */
/* http://tronche.com/gui/x/icccm/sec-4.html#WM_TRANSIENT_FOR */ /* http://tronche.com/gui/x/icccm/sec-4.html#WM_TRANSIENT_FOR */
/* Depending on WM, removes minimise and doesn't show in taskbar */ /* Depending on WM, removes minimise and doesn't show in taskbar */
if (win_handle) XSetTransientForHint(m->dpy, m->win, win_handle); if (win) XSetTransientForHint(m->dpy, m->win, win);
XFreeFontInfo(NULL, font, 1); XFreeFontInfo(NULL, font, 1);
XUnmapWindow(m->dpy, m->win); /* Make window non resizeable */ XUnmapWindow(m->dpy, m->win); /* Make window non resizeable */
@ -1132,7 +1146,8 @@ static void* fb_data;
static int fb_fast; static int fb_fast;
void Window_AllocFramebuffer(struct Bitmap* bmp, int width, int height) { void Window_AllocFramebuffer(struct Bitmap* bmp, int width, int height) {
if (!fb_gc) fb_gc = XCreateGC(win_display, win_handle, 0, NULL); Window win = Window_Main.Handle.val;
if (!fb_gc) fb_gc = XCreateGC(win_display, win, 0, NULL);
bmp->scan0 = (BitmapCol*)Mem_Alloc(width * height, BITMAPCOLOR_SIZE, "window pixels"); bmp->scan0 = (BitmapCol*)Mem_Alloc(width * height, BITMAPCOLOR_SIZE, "window pixels");
bmp->width = width; bmp->width = width;
@ -1192,10 +1207,11 @@ static void BlitFramebuffer(int x1, int y1, int width, int height, struct Bitmap
} }
void Window_DrawFramebuffer(Rect2D r, struct Bitmap* bmp) { void Window_DrawFramebuffer(Rect2D r, struct Bitmap* bmp) {
Window win = Window_Main.Handle.val;
/* Convert 32 bit depth to window depth when required */ /* Convert 32 bit depth to window depth when required */
if (!fb_fast) BlitFramebuffer(r.x, r.y, r.width, r.height, bmp); if (!fb_fast) BlitFramebuffer(r.x, r.y, r.width, r.height, bmp);
XPutImage(win_display, win_handle, fb_gc, fb_image, XPutImage(win_display, win, fb_gc, fb_image,
r.x, r.y, r.x, r.y, r.width, r.height); r.x, r.y, r.x, r.y, r.width, r.height);
} }
@ -1300,13 +1316,14 @@ static void InitRawMouse(void) { }
#endif #endif
void Window_EnableRawMouse(void) { void Window_EnableRawMouse(void) {
Window win = Window_Main.Handle.val;
DefaultEnableRawMouse(); DefaultEnableRawMouse();
if (!rawMouseInited) InitRawMouse(); if (!rawMouseInited) InitRawMouse();
rawMouseInited = true; rawMouseInited = true;
if (!grabCursor) return; if (!grabCursor) return;
XGrabPointer(win_display, win_handle, True, ButtonPressMask | ButtonReleaseMask | PointerMotionMask, XGrabPointer(win_display, win, True, ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
GrabModeAsync, GrabModeAsync, win_handle, blankCursor, CurrentTime); GrabModeAsync, GrabModeAsync, win, blankCursor, CurrentTime);
} }
void Window_UpdateRawMouse(void) { void Window_UpdateRawMouse(void) {
@ -1342,6 +1359,7 @@ void GLContext_Create(void) {
static const cc_string vsync_mesa = String_FromConst("GLX_MESA_swap_control"); static const cc_string vsync_mesa = String_FromConst("GLX_MESA_swap_control");
static const cc_string vsync_sgi = String_FromConst("GLX_SGI_swap_control"); static const cc_string vsync_sgi = String_FromConst("GLX_SGI_swap_control");
static const cc_string info_mesa = String_FromConst("GLX_MESA_query_renderer"); static const cc_string info_mesa = String_FromConst("GLX_MESA_query_renderer");
Window win = Window_Main.Handle.val;
const char* raw_exts; const char* raw_exts;
cc_string exts; cc_string exts;
@ -1356,7 +1374,7 @@ void GLContext_Create(void) {
if (!glXIsDirect(win_display, ctx_handle)) { if (!glXIsDirect(win_display, ctx_handle)) {
Platform_LogConst("== WARNING: Context is not direct =="); Platform_LogConst("== WARNING: Context is not direct ==");
} }
if (!glXMakeCurrent(win_display, win_handle, ctx_handle)) { if (!glXMakeCurrent(win_display, win, ctx_handle)) {
Logger_Abort("Failed to make OpenGL context current."); Logger_Abort("Failed to make OpenGL context current.");
} }
@ -1390,7 +1408,8 @@ void* GLContext_GetAddress(const char* function) {
} }
cc_bool GLContext_SwapBuffers(void) { cc_bool GLContext_SwapBuffers(void) {
glXSwapBuffers(win_display, win_handle); Window win = Window_Main.Handle.val;
glXSwapBuffers(win_display, win);
return true; return true;
} }