Getting of Win32 colors.
[SquirrelJME.git] / nanocoat / lib / scritchui / win32 / win32Core.c
blob337d1039ea5db2d8b60e187c21d884c26fcc8df3
1 /* -*- Mode: C; indent-tabs-mode: t; tab-width: 4 -*-
2 // ---------------------------------------------------------------------------
3 // SquirrelJME
4 // Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
5 // ---------------------------------------------------------------------------
6 // SquirrelJME is under the Mozilla Public License Version 2.0.
7 // See license.mkd for licensing and copyright information.
8 // -------------------------------------------------------------------------*/
10 #include "lib/scritchui/core/core.h"
11 #include "lib/scritchui/win32/win32.h"
12 #include "lib/scritchui/win32/win32Intern.h"
14 static LRESULT sjme_scritchui_win32_windowProcForward(
15 HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
17 sjme_scritchui inState;
18 sjme_scritchui_uiWindow inWindow;
19 LRESULT result;
21 /* Ignore if no window was specified. */
22 if (hWnd == NULL)
23 return DefWindowProc(hWnd, message, wParam, lParam);
25 /* Link back to this window. */
26 SetLastError(0);
27 inWindow = (sjme_scritchui_uiWindow)GetWindowLongPtr(hWnd,
28 GWLP_USERDATA);
29 if (inWindow == NULL)
30 return DefWindowProc(hWnd, message, wParam, lParam);
32 /* Recover state. */
33 inState = inWindow->component.common.state;
35 /* Handle message. */
36 result = 0;
37 inState->implIntern->windowProc(inState,
38 hWnd, message, wParam, lParam, &result);
39 return result;
42 static const sjme_scritchui_implFunctions sjme_scritchui_win32Functions =
44 .apiInit = sjme_scritchui_win32_apiInit,
45 .choiceItemInsert = NULL,
46 .choiceItemRemove = NULL,
47 .choiceItemSetEnabled = NULL,
48 .choiceItemSetImage = NULL,
49 .choiceItemSetSelected = NULL,
50 .choiceItemSetString = NULL,
51 .componentFocusGrab = NULL,
52 .componentFocusHas = NULL,
53 .componentPosition = sjme_scritchui_win32_componentPosition,
54 .componentRepaint = sjme_scritchui_win32_componentRepaint,
55 .componentRevalidate = sjme_scritchui_win32_componentRevalidate,
56 .componentSetActivateListener = NULL,
57 .componentSetInputListener = NULL,
58 .componentSetPaintListener =
59 sjme_scritchui_win32_componentSetPaintListener,
60 .componentSetSizeListener = NULL,
61 .componentSetVisibleListener = NULL,
62 .componentSize = sjme_scritchui_win32_componentSize,
63 .containerAdd = sjme_scritchui_win32_containerAdd,
64 .containerRemove = NULL,
65 .containerSetBounds = sjme_scritchui_win32_containerSetBounds,
66 .hardwareGraphics = NULL,
67 .labelSetString = NULL,
68 .lafElementColor = sjme_scritchui_win32_lafElementColor,
69 .listNew = NULL,
70 .loopExecute = NULL,
71 .loopExecuteLater = sjme_scritchui_win32_loopExecuteLater,
72 .loopExecuteWait = NULL,
73 .loopIterate = sjme_scritchui_win32_loopIterate,
74 .menuBarNew = sjme_scritchui_win32_menuBarNew,
75 .menuInsert = sjme_scritchui_win32_menuInsert,
76 .menuItemNew = sjme_scritchui_win32_menuItemNew,
77 .menuNew = sjme_scritchui_win32_menuNew,
78 .menuRemove = sjme_scritchui_win32_menuRemove,
79 .panelEnableFocus = sjme_scritchui_win32_panelEnableFocus,
80 .panelNew = sjme_scritchui_win32_panelNew,
81 .screens = sjme_scritchui_win32_screens,
82 .scrollPanelNew = NULL,
83 .viewGetView = NULL,
84 .viewSetArea = NULL,
85 .viewSetView = NULL,
86 .viewSetViewListener = NULL,
87 .windowContentMinimumSize = sjme_scritchui_win32_windowContentMinimumSize,
88 .windowNew = sjme_scritchui_win32_windowNew,
89 .windowSetCloseListener = NULL,
90 .windowSetMenuBar = sjme_scritchui_win32_windowSetMenuBar,
91 .windowSetVisible = sjme_scritchui_win32_windowSetVisible,
94 static const sjme_scritchui_implInternFunctions
95 sjme_scritchui_win32InternFunctions =
97 .getLastError = sjme_scritchui_win32_intern_getLastError,
98 .recoverComponent = sjme_scritchui_win32_intern_recoverComponent,
99 .windowProc = sjme_scritchui_win32_intern_windowProc,
100 .windowProcWin32 = sjme_scritchui_win32_windowProcForward,
103 static sjme_thread_result sjme_scritchui_win32_loopMain(
104 sjme_attrInNullable sjme_thread_parameter anything)
106 sjme_errorCode error;
107 sjme_scritchui state;
108 MSG message;
109 sjme_jboolean terminated;
110 HWND voidWindow;
112 /* Restore state. */
113 state = (sjme_scritchui)anything;
114 if (state == NULL)
115 return SJME_THREAD_RESULT(SJME_ERROR_NULL_ARGUMENTS);
117 /* By calling this, we are forcing the event queue to be created. */
118 memset(&message, 0, sizeof(message));
119 PeekMessage(&message, NULL,
120 WM_USER, WM_USER, PM_NOREMOVE);
122 /* Past Windows 98, we can use a specific message window. */
123 if (!state->common.intVals[SJME_SUI_WIN32_V_WIN9X])
124 voidWindow = HWND_MESSAGE;
126 /* Because all child windows need a parent, we need somewhere to store */
127 /* them before reparenting. */
128 else
130 voidWindow = CreateWindowEx(
131 WS_EX_NOACTIVATE | WS_EX_NOPARENTNOTIFY,
132 "Static",
133 "SquirrelJME Void",
134 WS_DISABLED | WS_OVERLAPPED,
135 0, 0, 1, 1,
136 NULL,
137 NULL,
138 GetModuleHandle(NULL),
139 NULL);
140 if (voidWindow == NULL)
141 return SJME_THREAD_RESULT(state->implIntern->getLastError(
142 state, SJME_ERROR_NATIVE_WIDGET_CREATE_FAILED));
145 /* Store the handle for later. */
146 state->common.handle[SJME_SUI_WIN32_H_VOID] = voidWindow;
148 /* Debug. */
149 sjme_message("Void Window: %p", voidWindow);
151 /* Before we go into the main loop, signal it is ready. */
152 sjme_atomic_sjme_jint_set(&state->loopThreadReady, 1);
154 /* Message loop. */
155 terminated = SJME_JNI_FALSE;
158 /* Keep running single executions. */
159 error = state->impl->loopIterate(state, SJME_JNI_TRUE,
160 &terminated);
162 /* Did this error? */
163 if (sjme_error_is(error))
164 sjme_message("Loop iterate failure: %d", error);
165 } while (!terminated);
167 /* Success?? */
168 return SJME_THREAD_RESULT(SJME_ERROR_NONE);
172 * Returns the Win32 ScritchUI interface.
174 * @param inPool The allocation pool used.
175 * @param loopExecute The loop execution to run after init.
176 * @param initFrontEnd Optional initial frontend data.
177 * @param outState The newly created state.
178 * @return The library interface.
179 * @since 2024/07/16
181 sjme_errorCode SJME_DYLIB_EXPORT SJME_SCRITCHUI_DYLIB_SYMBOL(win32)(
182 sjme_attrInNotNull sjme_alloc_pool* inPool,
183 sjme_attrInNullable sjme_thread_mainFunc loopExecute,
184 sjme_attrInNullable sjme_frontEnd* initFrontEnd,
185 sjme_attrInOutNotNull sjme_scritchui* outState)
187 sjme_errorCode error;
188 sjme_scritchui state;
190 if (outState == NULL)
191 return SJME_ERROR_NULL_ARGUMENTS;
193 /* Forward to core call. */
194 state = NULL;
195 if (sjme_error_is(error = sjme_scritchui_core_apiInit(inPool,
196 &state,
197 &sjme_scritchui_win32Functions, loopExecute,
198 initFrontEnd)) || state == NULL)
199 return sjme_error_default(error);
201 /* Success! */
202 *outState = state;
203 return SJME_ERROR_NONE;
206 sjme_errorCode sjme_scritchui_win32_apiInit(
207 sjme_attrInNotNull sjme_scritchui inState)
209 sjme_errorCode error;
210 OSVERSIONINFOEX winVer;
212 if (inState == NULL)
213 return SJME_ERROR_NULL_ARGUMENTS;
215 /* Internal functions to use specifically for Win32. */
216 inState->implIntern = &sjme_scritchui_win32InternFunctions;
218 /* This is a standard desktop. */
219 inState->wmType = SJME_SCRITCHUI_WM_TYPE_STANDARD_DESKTOP;
221 /* Are we on Windows 9x? */
222 memset(&winVer, 0, sizeof(winVer));
223 GetVersionEx((LPOSVERSIONINFOA)&winVer);
224 if ((winVer.dwMajorVersion == 4 && (winVer.dwMinorVersion == 0 ||
225 winVer.dwMinorVersion == 10 || winVer.dwMinorVersion == 90)) ||
226 winVer.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
227 inState->common.intVals[SJME_SUI_WIN32_V_WIN9X] = SJME_JNI_TRUE;
228 else
229 inState->common.intVals[SJME_SUI_WIN32_V_WIN9X] = SJME_JNI_FALSE;
231 /* Start main Win32 thread. */
232 if (sjme_error_is(error = sjme_thread_new(
233 &inState->loopThread,
234 sjme_scritchui_win32_loopMain, inState)) ||
235 inState->loopThread == SJME_THREAD_NULL)
236 return sjme_error_default(error);
238 /* Success! */
239 return SJME_ERROR_NONE;