Started migrating uiWindow on Windows. Oh boy it's UTF-16 time!
This commit is contained in:
parent
d5c06108d6
commit
3f392d04ce
|
@ -71,6 +71,10 @@ bool uiprivSysInit(void *options, uiInitError *err)
|
||||||
if (hr != S_OK)
|
if (hr != S_OK)
|
||||||
return uiprivInitReturnHRESULT(err, "failed to initialize the utility window", hr);
|
return uiprivInitReturnHRESULT(err, "failed to initialize the utility window", hr);
|
||||||
|
|
||||||
|
hr = uiprivRegisterWindowClass(hDefaultIcon, hDefaultCursor);
|
||||||
|
if (hr != S_OK)
|
||||||
|
return uiprivInitReturnHRESULT(err, "failed to register the uiWindow window class", hr);
|
||||||
|
|
||||||
ZeroMemory(&icc, sizeof (INITCOMMONCONTROLSEX));
|
ZeroMemory(&icc, sizeof (INITCOMMONCONTROLSEX));
|
||||||
icc.dwSize = sizeof (INITCOMMONCONTROLSEX);
|
icc.dwSize = sizeof (INITCOMMONCONTROLSEX);
|
||||||
icc.dwICC = wantedICCClasses;
|
icc.dwICC = wantedICCClasses;
|
||||||
|
|
|
@ -16,3 +16,6 @@ enum {
|
||||||
};
|
};
|
||||||
extern HWND uiprivUtilWindow;
|
extern HWND uiprivUtilWindow;
|
||||||
extern HRESULT uiprivInitUtilWindow(HICON hDefaultIcon, HCURSOR hDefaultCursor);
|
extern HRESULT uiprivInitUtilWindow(HICON hDefaultIcon, HCURSOR hDefaultCursor);
|
||||||
|
|
||||||
|
// window.cpp
|
||||||
|
extern HRESULT uiprivRegisterWindowClass(HICON hDefaultIcon, HCURSOR hDefaultCursor);
|
||||||
|
|
|
@ -39,6 +39,7 @@ HRESULT uiprivInitUtilWindow(HICON hDefaultIcon, HCURSOR hDefaultCursor)
|
||||||
return uiprivHrCreateWindowExW(0,
|
return uiprivHrCreateWindowExW(0,
|
||||||
utilWindowClass, L"libui utility window",
|
utilWindowClass, L"libui utility window",
|
||||||
WS_OVERLAPPEDWINDOW,
|
WS_OVERLAPPEDWINDOW,
|
||||||
|
// TODO CW_USEDEFAULT?
|
||||||
0, 0, 100, 100,
|
0, 0, 100, 100,
|
||||||
NULL, NULL, uipriv_hInstance, NULL,
|
NULL, NULL, uipriv_hInstance, NULL,
|
||||||
&uiprivUtilWindow);
|
&uiprivUtilWindow);
|
||||||
|
|
|
@ -3,9 +3,10 @@
|
||||||
|
|
||||||
#define windowClass L"libui_uiWindowClass"
|
#define windowClass L"libui_uiWindowClass"
|
||||||
|
|
||||||
struct uiWindow {
|
struct windowImplData {
|
||||||
uiWindowsControl c;
|
|
||||||
HWND hwnd;
|
HWND hwnd;
|
||||||
|
const char *title;
|
||||||
|
#if 0
|
||||||
HMENU menubar;
|
HMENU menubar;
|
||||||
uiControl *child;
|
uiControl *child;
|
||||||
BOOL shownOnce;
|
BOOL shownOnce;
|
||||||
|
@ -20,8 +21,12 @@ struct uiWindow {
|
||||||
int fullscreen;
|
int fullscreen;
|
||||||
WINDOWPLACEMENT fsPrevPlacement;
|
WINDOWPLACEMENT fsPrevPlacement;
|
||||||
int borderless;
|
int borderless;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// TODO {
|
||||||
|
|
||||||
// from https://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing
|
// from https://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing
|
||||||
#define windowMargin 7
|
#define windowMargin 7
|
||||||
|
|
||||||
|
@ -64,22 +69,11 @@ static void windowRelayout(uiWindow *w)
|
||||||
|
|
||||||
static LRESULT CALLBACK windowWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
static LRESULT CALLBACK windowWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
LONG_PTR ww;
|
|
||||||
uiWindow *w;
|
|
||||||
CREATESTRUCTW *cs = (CREATESTRUCTW *) lParam;
|
|
||||||
WINDOWPOS *wp = (WINDOWPOS *) lParam;
|
WINDOWPOS *wp = (WINDOWPOS *) lParam;
|
||||||
MINMAXINFO *mmi = (MINMAXINFO *) lParam;
|
MINMAXINFO *mmi = (MINMAXINFO *) lParam;
|
||||||
int width, height;
|
int width, height;
|
||||||
LRESULT lResult;
|
LRESULT lResult;
|
||||||
|
|
||||||
ww = GetWindowLongPtrW(hwnd, GWLP_USERDATA);
|
|
||||||
if (ww == 0) {
|
|
||||||
if (uMsg == WM_CREATE)
|
|
||||||
SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONG_PTR) (cs->lpCreateParams));
|
|
||||||
// fall through to DefWindowProc() anyway
|
|
||||||
return DefWindowProcW(hwnd, uMsg, wParam, lParam);
|
|
||||||
}
|
|
||||||
w = uiWindow((void *) ww);
|
|
||||||
if (handleParentMessages(hwnd, uMsg, wParam, lParam, &lResult) != FALSE)
|
if (handleParentMessages(hwnd, uMsg, wParam, lParam, &lResult) != FALSE)
|
||||||
return lResult;
|
return lResult;
|
||||||
switch (uMsg) {
|
switch (uMsg) {
|
||||||
|
@ -124,20 +118,6 @@ static LRESULT CALLBACK windowWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARA
|
||||||
return DefWindowProcW(hwnd, uMsg, wParam, lParam);
|
return DefWindowProcW(hwnd, uMsg, wParam, lParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
ATOM registerWindowClass(HICON hDefaultIcon, HCURSOR hDefaultCursor)
|
|
||||||
{
|
|
||||||
WNDCLASSW wc;
|
|
||||||
|
|
||||||
ZeroMemory(&wc, sizeof (WNDCLASSW));
|
|
||||||
wc.lpszClassName = windowClass;
|
|
||||||
wc.lpfnWndProc = windowWndProc;
|
|
||||||
wc.hInstance = hInstance;
|
|
||||||
wc.hIcon = hDefaultIcon;
|
|
||||||
wc.hCursor = hDefaultCursor;
|
|
||||||
wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1);
|
|
||||||
return RegisterClassW(&wc);
|
|
||||||
}
|
|
||||||
|
|
||||||
void unregisterWindowClass(void)
|
void unregisterWindowClass(void)
|
||||||
{
|
{
|
||||||
if (UnregisterClassW(windowClass, hInstance) == 0)
|
if (UnregisterClassW(windowClass, hInstance) == 0)
|
||||||
|
@ -465,19 +445,7 @@ uiWindow *uiNewWindow(const char *title, int width, int height, int hasMenubar)
|
||||||
hasMenubarBOOL = TRUE;
|
hasMenubarBOOL = TRUE;
|
||||||
w->hasMenubar = hasMenubarBOOL;
|
w->hasMenubar = hasMenubarBOOL;
|
||||||
|
|
||||||
#define style WS_OVERLAPPEDWINDOW
|
|
||||||
#define exstyle 0
|
|
||||||
|
|
||||||
wtitle = toUTF16(title);
|
wtitle = toUTF16(title);
|
||||||
w->hwnd = CreateWindowExW(exstyle,
|
|
||||||
windowClass, wtitle,
|
|
||||||
style,
|
|
||||||
CW_USEDEFAULT, CW_USEDEFAULT,
|
|
||||||
// use the raw width and height for now
|
|
||||||
// this will get CW_USEDEFAULT (hopefully) predicting well
|
|
||||||
// even if it doesn't, we're adjusting it later
|
|
||||||
width, height,
|
|
||||||
NULL, NULL, hInstance, w);
|
|
||||||
if (w->hwnd == NULL)
|
if (w->hwnd == NULL)
|
||||||
logLastError(L"error creating window");
|
logLastError(L"error creating window");
|
||||||
uiprivFree(wtitle);
|
uiprivFree(wtitle);
|
||||||
|
@ -498,6 +466,156 @@ uiWindow *uiNewWindow(const char *title, int width, int height, int hasMenubar)
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// } TODO
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static LRESULT CALLBACK windowWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
LONG_PTR ww;
|
||||||
|
uiWindow *w;
|
||||||
|
struct windowImplData *wi;
|
||||||
|
CREATESTRUCTW *cs = (CREATESTRUCTW *) lParam;
|
||||||
|
|
||||||
|
ww = GetWindowLongPtrW(hwnd, GWLP_USERDATA);
|
||||||
|
if (ww == 0) {
|
||||||
|
if (uMsg == WM_CREATE)
|
||||||
|
SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONG_PTR) (cs->lpCreateParams));
|
||||||
|
// fall through to DefWindowProc() anyway
|
||||||
|
return DefWindowProcW(hwnd, uMsg, wParam, lParam);
|
||||||
|
}
|
||||||
|
w = uiWindow((void *) ww);
|
||||||
|
wi = (struct windowImplData *) uiControlImplData(uiControl(w));
|
||||||
|
switch (uMsg) {
|
||||||
|
case WM_CLOSE:
|
||||||
|
// don't destroy the window on close; programs decide if they should when handling the closing event
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return DefWindowProcW(hwnd, uMsg, wParam, lParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT uiprivRegisterWindowClass(HICON hDefaultIcon, HCURSOR hDefaultCursor)
|
||||||
|
{
|
||||||
|
WNDCLASSW wc;
|
||||||
|
|
||||||
|
ZeroMemory(&wc, sizeof (WNDCLASSW));
|
||||||
|
wc.lpszClassName = windowClass;
|
||||||
|
wc.lpfnWndProc = windowWndProc;
|
||||||
|
wc.hInstance = uipriv_hInstance;
|
||||||
|
wc.hIcon = hDefaultIcon;
|
||||||
|
wc.hCursor = hDefaultCursor;
|
||||||
|
wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1);
|
||||||
|
return uiprivHrRegisterClassW(&wc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool windowInit(uiControl *c, void *implData, void *initData)
|
||||||
|
{
|
||||||
|
struct windowImplData *wi = (struct windowImplData *) implData;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
#define style WS_OVERLAPPEDWINDOW
|
||||||
|
#define exstyle 0
|
||||||
|
hr = uiprivHrCreateWindowExW(exstyle,
|
||||||
|
windowClass, L"",
|
||||||
|
style,
|
||||||
|
CW_USEDEFAULT, CW_USEDEFAULT,
|
||||||
|
CW_USEDEFAULT, CW_USEDEFAULT,
|
||||||
|
NULL, NULL, uipriv_hInstance, c,
|
||||||
|
&(wi->hwnd));
|
||||||
|
if (hr != S_OK) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void windowFree(uiControl *c, void *implData)
|
||||||
|
{
|
||||||
|
struct windowImplData *wi = (struct windowImplData *) implData;
|
||||||
|
|
||||||
|
if (wi->title != NULL) {
|
||||||
|
uiprivFreeUTF8(wi->title);
|
||||||
|
wi->title = NULL;
|
||||||
|
}
|
||||||
|
xxxx
|
||||||
|
}
|
||||||
|
|
||||||
|
static void windowParentChanging(uiControl *c, void *implData, uiControl *oldParent)
|
||||||
|
{
|
||||||
|
uiprivProgrammerErrorCannotHaveWindowsAsChildren();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void windowParentChanged(uiControl *c, void *implData, uiControl *newParent)
|
||||||
|
{
|
||||||
|
uiprivProgrammerErrorCannotHaveWindowsAsChildren();
|
||||||
|
}
|
||||||
|
|
||||||
|
static HWND windowHandle(uiControl *c, void *implData)
|
||||||
|
{
|
||||||
|
struct windowImplData *wi = (struct windowImplData *) implData;
|
||||||
|
|
||||||
|
return wi->hwnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
// gotta do this because of lack of C99-style initializers in C++11
|
||||||
|
// see also https://stackoverflow.com/questions/11516657/c-structure-initialization
|
||||||
|
static const uiControlVtable windowVtable = [](void) {
|
||||||
|
uiControlVtable vt;
|
||||||
|
|
||||||
|
memset(&vt, 0, sizeof (uiControlVtable));
|
||||||
|
vt.Size = sizeof (uiControlVtable);
|
||||||
|
vt.Init = windowInit;
|
||||||
|
vt.Free = windowFree;
|
||||||
|
vt.ParentChanging = windowParentChanging;
|
||||||
|
vt.ParentChanged = windowParentChanged;
|
||||||
|
return vt;
|
||||||
|
}();
|
||||||
|
|
||||||
|
static const uiControlOSVtable windowOSVtable = [](void) {
|
||||||
|
uiControlOSVtable vt;
|
||||||
|
|
||||||
|
memset(&vt, 0, sizeof (uiControlOSVtable));
|
||||||
|
vt.Size = sizeof (uiControlOSVtable);
|
||||||
|
vt.Handle = windowHandle;
|
||||||
|
return vt;
|
||||||
|
}();
|
||||||
|
|
||||||
|
static uint32_t windowType = 0;
|
||||||
|
|
||||||
|
uint32_t uiprivSysWindowType(void)
|
||||||
|
{
|
||||||
|
if (windowType == 0)
|
||||||
|
windowType = uiRegisterControlType("uiWindow", &windowVtable, &windowOSVtable, sizeof (struct windowImplData));
|
||||||
|
return windowType;
|
||||||
|
}
|
||||||
|
|
||||||
|
uiWindow *uiprivSysNewWindow(void)
|
||||||
|
{
|
||||||
|
return (uiWindow *) uiNewControl(uiWindowType(), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *uiprivSysWindowTitle(uiWindow *w)
|
||||||
|
{
|
||||||
|
struct windowImplData *wi = (struct windowImplData *) uiControlImplData(uiControl(w));
|
||||||
|
|
||||||
|
if (wi->title == NULL)
|
||||||
|
// TODO replace this with a dedicated UTF-8 empty string object
|
||||||
|
return "";
|
||||||
|
return wi->title;
|
||||||
|
}
|
||||||
|
|
||||||
|
void uiprivSysWindowSetTitle(uiWindow *w, const char *title)
|
||||||
|
{
|
||||||
|
struct windowImplData *wi = (struct windowImplData *) uiControlImplData(uiControl(w));
|
||||||
|
|
||||||
|
if (wi->title != NULL)
|
||||||
|
uiprivFreeUTF8(wi->title);
|
||||||
|
wi->title = uiprivSanitizeUTF8(title);
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
// this cannot queue a resize because it's called by the resize handler
|
// this cannot queue a resize because it's called by the resize handler
|
||||||
void ensureMinimumWindowSize(uiWindow *w)
|
void ensureMinimumWindowSize(uiWindow *w)
|
||||||
{
|
{
|
||||||
|
@ -534,3 +652,5 @@ void enableAllWindowsExcept(uiWindow *which)
|
||||||
EnableWindow(w.first->hwnd, TRUE);
|
EnableWindow(w.first->hwnd, TRUE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue