1 /* -*- Mode: C; indent-tabs-mode: t; tab-width: 4 -*-
2 // ---------------------------------------------------------------------------
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
;
21 /* Ignore if no window was specified. */
23 return DefWindowProc(hWnd
, message
, wParam
, lParam
);
25 /* Link back to this window. */
27 inWindow
= (sjme_scritchui_uiWindow
)GetWindowLongPtr(hWnd
,
30 return DefWindowProc(hWnd
, message
, wParam
, lParam
);
33 inState
= inWindow
->component
.common
.state
;
37 inState
->implIntern
->windowProc(inState
,
38 hWnd
, message
, wParam
, lParam
, &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
,
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
,
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
;
109 sjme_jboolean terminated
;
113 state
= (sjme_scritchui
)anything
;
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. */
130 voidWindow
= CreateWindowEx(
131 WS_EX_NOACTIVATE
| WS_EX_NOPARENTNOTIFY
,
134 WS_DISABLED
| WS_OVERLAPPED
,
138 GetModuleHandle(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
;
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);
155 terminated
= SJME_JNI_FALSE
;
158 /* Keep running single executions. */
159 error
= state
->impl
->loopIterate(state
, SJME_JNI_TRUE
,
162 /* Did this error? */
163 if (sjme_error_is(error
))
164 sjme_message("Loop iterate failure: %d", error
);
165 } while (!terminated
);
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.
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. */
195 if (sjme_error_is(error
= sjme_scritchui_core_apiInit(inPool
,
197 &sjme_scritchui_win32Functions
, loopExecute
,
198 initFrontEnd
)) || state
== NULL
)
199 return sjme_error_default(error
);
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
;
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
;
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
);
239 return SJME_ERROR_NONE
;