From 4f99fdd90fb3828d02cc3e37968b590bd37f1295 Mon Sep 17 00:00:00 2001 From: Pietro Gagliardi Date: Mon, 27 Apr 2015 18:04:41 -0400 Subject: [PATCH] Started working on the new uiWindow. --- new/ui.idl | 6 +- new/windows/GNUmakeinc.mk | 3 +- new/windows/OLDwindow.c | 218 ++++++++++++++++++++++++++++++++ new/windows/window.c | 256 ++++++++------------------------------ 4 files changed, 270 insertions(+), 213 deletions(-) create mode 100644 new/windows/OLDwindow.c diff --git a/new/ui.idl b/new/ui.idl index b67c9392..7b463bfa 100644 --- a/new/ui.idl +++ b/new/ui.idl @@ -62,13 +62,9 @@ interface Container from Control { }; func MakeContainer(c *Container); -interface Window { - func Destroy(void); - func Handle(void) uintptr_t; +interface Window from Control { func Title(void) *char; func SetTitle(title *const char); - func Show(void); - func Hide(void); // TODO really return int? func OnClosing(f *func(w *Window, data *void) int, data *void); func SetChild(c *Control); diff --git a/new/windows/GNUmakeinc.mk b/new/windows/GNUmakeinc.mk index 7ced11d0..ea31145a 100644 --- a/new/windows/GNUmakeinc.mk +++ b/new/windows/GNUmakeinc.mk @@ -2,12 +2,13 @@ osCFILES = \ windows/alloc.c \ + windows/bin.c \ windows/comctl32.c \ + windows/container.c \ windows/debug.c \ windows/init.c \ windows/main.c \ windows/menu.c \ - windows/oscontainer.c \ windows/text.c \ windows/util.c \ windows/window.c diff --git a/new/windows/OLDwindow.c b/new/windows/OLDwindow.c new file mode 100644 index 00000000..1000523b --- /dev/null +++ b/new/windows/OLDwindow.c @@ -0,0 +1,218 @@ +// 6 april 2015 +#include "uipriv_windows.h" + +struct window { + uiWindow w; + HWND hwnd; + uiOSContainer *content; + BOOL shownOnce; + int (*onClosing)(uiWindow *, void *); + void *onClosingData; + int margined; + BOOL canDestroy; +}; + +#define uiWindowClass L"uiWindowClass" + +static LRESULT CALLBACK uiWindowWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + struct window *w; + CREATESTRUCTW *cs = (CREATESTRUCTW *) lParam; + WINDOWPOS *wp = (WINDOWPOS *) lParam; + RECT r; + HWND contenthwnd; + + w = (struct window *) GetWindowLongPtrW(hwnd, GWLP_USERDATA); + if (w == NULL) { + if (uMsg == WM_CREATE) + SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONG_PTR) (cs->lpCreateParams)); + // fall through to DefWindowProc() anyway + return DefWindowProcW(hwnd, uMsg, wParam, lParam); + } + switch (uMsg) { + case WM_COMMAND: + // not a menu + if (lParam != 0) + break; + if (HIWORD(wParam) != 0) + break; + runMenuEvent(LOWORD(wParam), uiWindow(w)); + return 0; + case WM_WINDOWPOSCHANGED: + if ((wp->flags & SWP_NOSIZE) != 0) + break; + // fall through + case msgUpdateChild: + if (GetClientRect(w->hwnd, &r) == 0) + logLastError("error getting window client rect for resize in uiWindowWndProc()"); + contenthwnd = uiOSContainerHWND(w->content); + if (MoveWindow(contenthwnd, r.left, r.top, r.right - r.left, r.bottom - r.top, TRUE) == 0) + logLastError("error resizing window content parent in uiWindowWndProc()"); + return 0; + case WM_CLOSE: + if (!(*(w->onClosing))(uiWindow(w), w->onClosingData)) + uiWindowDestroy(uiWindow(w)); + return 0; // we destroyed it already + case WM_DESTROY: + if (!w->canDestroy) + complain("attempt to destroy uiWindow at %p before uiWindowDestroy()", w); + uiFree(w); + break; // fall through to DefWindowProcW() + } + return DefWindowProcW(hwnd, uMsg, wParam, lParam); +} + +ATOM registerWindowClass(HICON hDefaultIcon, HCURSOR hDefaultCursor) +{ + WNDCLASSW wc; + + ZeroMemory(&wc, sizeof (WNDCLASSW)); + wc.lpszClassName = uiWindowClass; + wc.lpfnWndProc = uiWindowWndProc; + wc.hInstance = hInstance; + wc.hIcon = hDefaultIcon; + wc.hCursor = hDefaultCursor; + wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1); + return RegisterClassW(&wc); +} + +#define exstyle 0 +#define style WS_OVERLAPPEDWINDOW + +static int defaultOnClosing(uiWindow *w, void *data) +{ + return 1; +} + +static char *windowTitle(uiWindow *ww) +{ + struct window *w = (struct window *) ww; + WCHAR *wtext; + char *text; + + wtext = windowText(w->hwnd); + text = toUTF8(wtext); + uiFree(wtext); + return text; +} + +static void windowSetTitle(uiWindow *ww, const char *text) +{ + struct window *w = (struct window *) ww; + WCHAR *wtext; + + wtext = toUTF16(text); + if (SetWindowTextW(w->hwnd, wtext) == 0) + logLastError("error setting window title in uiWindowSetTitle()"); + uiFree(wtext); +} + +static void windowShow(uiWindow *ww) +{ + struct window *w = (struct window *) ww; + + if (w->shownOnce) { + ShowWindow(w->hwnd, SW_SHOW); + return; + } + w->shownOnce = TRUE; + ShowWindow(w->hwnd, nCmdShow); + if (UpdateWindow(w->hwnd) == 0) + logLastError("error calling UpdateWindow() after showing uiWindow for the first time"); +} + +static void windowOnClosing(uiWindow *ww, int (*f)(uiWindow *, void *), void *data) +{ + struct window *w = (struct window *) ww; + + w->onClosing = f; + w->onClosingData = data; +} + +static void windowSetChild(uiWindow *ww, uiControl *c) +{ + struct window *w = (struct window *) ww; + + uiOSContainerSetMainControl(w->content, c); + // don't call uiOSContainerUpdate(); instead, synthesize a resize + // otherwise, we'll have a 0x0 content area at first + SendMessageW(w->hwnd, msgUpdateChild, 0, 0); +} + +static int windowMargined(uiWindow *ww) +{ + struct window *w = (struct window *) ww; + + return w->margined; +} + +// from https://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing +#define windowMargin 7 + +static void windowSetMargined(uiWindow *ww, int margined) +{ + struct window *w = (struct window *) ww; + + w->margined = margined; + if (w->margined) + uiOSContainerSetMargins(w->content, windowMargin, windowMargin, windowMargin, windowMargin); + else + uiOSContainerSetMargins(w->content, 0, 0, 0, 0); + uiOSContainerUpdate(w->content); +} + +uiWindow *uiNewWindow(const char *title, int width, int height, int hasMenubar) +{ + struct window *w; + RECT adjust; + WCHAR *wtitle; + BOOL hasMenubarBOOL; + HMENU hmenu; + + w = uiNew(struct window); + w->onClosing = defaultOnClosing; + + hasMenubarBOOL = FALSE; + if (hasMenubar) + hasMenubarBOOL = TRUE; + + adjust.left = 0; + adjust.top = 0; + adjust.right = width; + adjust.bottom = height; + // TODO does not handle menu wrapping; see http://blogs.msdn.com/b/oldnewthing/archive/2003/09/11/54885.aspx + if (AdjustWindowRectEx(&adjust, style, hasMenubarBOOL, exstyle) == 0) + logLastError("error getting real window coordinates in uiWindow()"); + + wtitle = toUTF16(title); + w->hwnd = CreateWindowExW(exstyle, + uiWindowClass, wtitle, + style, + CW_USEDEFAULT, CW_USEDEFAULT, + adjust.right - adjust.left, adjust.bottom - adjust.top, + NULL, NULL, hInstance, w); + if (w->hwnd == NULL) + logLastError("error creating window in uiWindow()"); + uiFree(wtitle); + + w->content = uiNewOSContainer((uintptr_t) (w->hwnd)); + + if (hasMenubar) { + hmenu = makeMenubar(); + if (SetMenu(w->hwnd, hmenu) == 0) + logLastError("error giving menu to window in uiNewWindow()"); + } + + uiWindow(w)->Destroy = windowDestroy; + uiWindow(w)->Handle = windowHandle; + uiWindow(w)->Title = windowTitle; + uiWindow(w)->SetTitle = windowSetTitle; + uiWindow(w)->Show = windowShow; + uiWindow(w)->Hide = windowHide; + uiWindow(w)->OnClosing = windowOnClosing; + uiWindow(w)->SetChild = windowSetChild; + uiWindow(w)->Margined = windowMargined; + uiWindow(w)->SetMargined = windowSetMargined; + + return uiWindow(w); +} diff --git a/new/windows/window.c b/new/windows/window.c index eec40223..340ee6d8 100644 --- a/new/windows/window.c +++ b/new/windows/window.c @@ -1,246 +1,88 @@ -// 6 april 2015 +// 27 april 2015 #include "uipriv_windows.h" struct window { uiWindow w; HWND hwnd; - uiOSContainer *content; - BOOL shownOnce; - int (*onClosing)(uiWindow *, void *); - void *onClosingData; + uiContainer *bin; + int hidden; int margined; - BOOL canDestroy; }; -#define uiWindowClass L"uiWindowClass" +// TODO window class and init functions -static LRESULT CALLBACK uiWindowWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +static void windowDestroy(uiControl *c) { - struct window *w; - CREATESTRUCTW *cs = (CREATESTRUCTW *) lParam; - WINDOWPOS *wp = (WINDOWPOS *) lParam; - RECT r; - HWND contenthwnd; + struct window *w = (struct window *) c; - w = (struct window *) GetWindowLongPtrW(hwnd, GWLP_USERDATA); - if (w == NULL) { - if (uMsg == WM_CREATE) - SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONG_PTR) (cs->lpCreateParams)); - // fall through to DefWindowProc() anyway - return DefWindowProcW(hwnd, uMsg, wParam, lParam); - } - switch (uMsg) { - case WM_COMMAND: - // not a menu - if (lParam != 0) - break; - if (HIWORD(wParam) != 0) - break; - runMenuEvent(LOWORD(wParam), uiWindow(w)); - return 0; - case WM_WINDOWPOSCHANGED: - if ((wp->flags & SWP_NOSIZE) != 0) - break; - // fall through - case msgUpdateChild: - if (GetClientRect(w->hwnd, &r) == 0) - logLastError("error getting window client rect for resize in uiWindowWndProc()"); - contenthwnd = uiOSContainerHWND(w->content); - if (MoveWindow(contenthwnd, r.left, r.top, r.right - r.left, r.bottom - r.top, TRUE) == 0) - logLastError("error resizing window content parent in uiWindowWndProc()"); - return 0; - case WM_CLOSE: - if (!(*(w->onClosing))(uiWindow(w), w->onClosingData)) - uiWindowDestroy(uiWindow(w)); - return 0; // we destroyed it already - case WM_DESTROY: - if (!w->canDestroy) - complain("attempt to destroy uiWindow at %p before uiWindowDestroy()", w); - uiFree(w); - break; // fall through to DefWindowProcW() - } - return DefWindowProcW(hwnd, uMsg, wParam, lParam); + // first hide ourselves + ShowWindow(w->hwnd, SW_HIDE); + // now destroy the bin + // the bin has no parent, so we can just call uiControlDestroy() + uiControlDestroy(uiControl(w->bin)); + // TODO menus + // now destroy ourselves + if (DestroyWindow(w->hwnd) == 0) + logLastError("error destroying uiWindow in windowDestroy()"); + uiFree(w); } -ATOM registerWindowClass(HICON hDefaultIcon, HCURSOR hDefaultCursor) +static uintptr_t windowHandle(uiControl *c) { - WNDCLASSW wc; - - ZeroMemory(&wc, sizeof (WNDCLASSW)); - wc.lpszClassName = uiWindowClass; - wc.lpfnWndProc = uiWindowWndProc; - wc.hInstance = hInstance; - wc.hIcon = hDefaultIcon; - wc.hCursor = hDefaultCursor; - wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1); - return RegisterClassW(&wc); -} - -#define exstyle 0 -#define style WS_OVERLAPPEDWINDOW - -static int defaultOnClosing(uiWindow *w, void *data) -{ - return 1; -} - -static void windowDestroy(uiWindow *ww) -{ - struct window *w = (struct window *) ww; - - // first destroy the content - uiOSContainerDestroy(w->content); - // then mark that we're ready to destroy - w->canDestroy = TRUE; - // and finally destroy - // TODO check for errors - DestroyWindow(w->hwnd); - // no need to explicitly destroy the menubar, if any; that's done automatically during window destruction -} - -static uintptr_t windowHandle(uiWindow *ww) -{ - struct window *w = (struct window *) ww; + struct window *w = (struct window *) c; return (uintptr_t) (w->hwnd); } -static char *windowTitle(uiWindow *ww) +static void windowSetParent(uiControl *c) { - struct window *w = (struct window *) ww; - WCHAR *wtext; - char *text; - - wtext = windowText(w->hwnd); - text = toUTF8(wtext); - uiFree(wtext); - return text; + complain("attempt to give the uiWindow at %p a parent", c); } -static void windowSetTitle(uiWindow *ww, const char *text) +static void windowPreferredSize(uiControl *c, uiSizing *d, intmax_t *width, intmax_t *height) { - struct window *w = (struct window *) ww; - WCHAR *wtext; - - wtext = toUTF16(text); - if (SetWindowTextW(w->hwnd, wtext) == 0) - logLastError("error setting window title in uiWindowSetTitle()"); - uiFree(wtext); + complain("attempt to get the preferred size of the uiWindow at %p", c); } -static void windowShow(uiWindow *ww) +static void windowResize(uiControl *c, intmax_t x, intmax_t y, intmax_t width, intmax_t height, uiSizing *d) { - struct window *w = (struct window *) ww; - - if (w->shownOnce) { - ShowWindow(w->hwnd, SW_SHOW); - return; - } - w->shownOnce = TRUE; - ShowWindow(w->hwnd, nCmdShow); - if (UpdateWindow(w->hwnd) == 0) - logLastError("error calling UpdateWindow() after showing uiWindow for the first time"); + complain("attempt to resize the uiWindow at %p", c); } -static void windowHide(uiWindow *ww) +static int windowVisible(uiControl *c) { - struct window *w = (struct window *) ww; + struct window *w = (struct window *) c; + + return !w->hidden; +} + +static void windowShow(uiControl *w) +{ + struct window *w = (struct window *) c; + + // TODO first show logic + ShowWindow(w->hwnd, SW_SHOW); + w->hidden = 0; +} + +static void windowHide(uiControl *w) +{ + struct window *w = (struct window *) c; ShowWindow(w->hwnd, SW_HIDE); + w->hidden = 1; } -static void windowOnClosing(uiWindow *ww, int (*f)(uiWindow *, void *), void *data) +static void windowEnable(uiControl *c) { - struct window *w = (struct window *) ww; + struct window *w = (struct window *) c; - w->onClosing = f; - w->onClosingData = data; + EnableWindow(w->hwnd, TRUE); } -static void windowSetChild(uiWindow *ww, uiControl *c) +static void windowDisable(uiControl *c) { - struct window *w = (struct window *) ww; + struct window *w = (struct window *) c; - uiOSContainerSetMainControl(w->content, c); - // don't call uiOSContainerUpdate(); instead, synthesize a resize - // otherwise, we'll have a 0x0 content area at first - SendMessageW(w->hwnd, msgUpdateChild, 0, 0); -} - -static int windowMargined(uiWindow *ww) -{ - struct window *w = (struct window *) ww; - - return w->margined; -} - -// from https://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing -#define windowMargin 7 - -static void windowSetMargined(uiWindow *ww, int margined) -{ - struct window *w = (struct window *) ww; - - w->margined = margined; - if (w->margined) - uiOSContainerSetMargins(w->content, windowMargin, windowMargin, windowMargin, windowMargin); - else - uiOSContainerSetMargins(w->content, 0, 0, 0, 0); - uiOSContainerUpdate(w->content); -} - -uiWindow *uiNewWindow(const char *title, int width, int height, int hasMenubar) -{ - struct window *w; - RECT adjust; - WCHAR *wtitle; - BOOL hasMenubarBOOL; - HMENU hmenu; - - w = uiNew(struct window); - w->onClosing = defaultOnClosing; - - hasMenubarBOOL = FALSE; - if (hasMenubar) - hasMenubarBOOL = TRUE; - - adjust.left = 0; - adjust.top = 0; - adjust.right = width; - adjust.bottom = height; - // TODO does not handle menu wrapping; see http://blogs.msdn.com/b/oldnewthing/archive/2003/09/11/54885.aspx - if (AdjustWindowRectEx(&adjust, style, hasMenubarBOOL, exstyle) == 0) - logLastError("error getting real window coordinates in uiWindow()"); - - wtitle = toUTF16(title); - w->hwnd = CreateWindowExW(exstyle, - uiWindowClass, wtitle, - style, - CW_USEDEFAULT, CW_USEDEFAULT, - adjust.right - adjust.left, adjust.bottom - adjust.top, - NULL, NULL, hInstance, w); - if (w->hwnd == NULL) - logLastError("error creating window in uiWindow()"); - uiFree(wtitle); - - w->content = uiNewOSContainer((uintptr_t) (w->hwnd)); - - if (hasMenubar) { - hmenu = makeMenubar(); - if (SetMenu(w->hwnd, hmenu) == 0) - logLastError("error giving menu to window in uiNewWindow()"); - } - - uiWindow(w)->Destroy = windowDestroy; - uiWindow(w)->Handle = windowHandle; - uiWindow(w)->Title = windowTitle; - uiWindow(w)->SetTitle = windowSetTitle; - uiWindow(w)->Show = windowShow; - uiWindow(w)->Hide = windowHide; - uiWindow(w)->OnClosing = windowOnClosing; - uiWindow(w)->SetChild = windowSetChild; - uiWindow(w)->Margined = windowMargined; - uiWindow(w)->SetMargined = windowSetMargined; - - return uiWindow(w); + EnableWindow(w->hwnd, FALSE); }