aboutsummaryrefslogtreecommitdiff
path: root/src/libui_sdl/libui/windows/window.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libui_sdl/libui/windows/window.cpp')
-rw-r--r--src/libui_sdl/libui/windows/window.cpp665
1 files changed, 0 insertions, 665 deletions
diff --git a/src/libui_sdl/libui/windows/window.cpp b/src/libui_sdl/libui/windows/window.cpp
deleted file mode 100644
index a8f7f23..0000000
--- a/src/libui_sdl/libui/windows/window.cpp
+++ /dev/null
@@ -1,665 +0,0 @@
-// 27 april 2015
-#include "uipriv_windows.hpp"
-
-#define windowClass L"libui_uiWindowClass"
-
-struct uiWindow {
- uiWindowsControl c;
- HWND hwnd;
- HMENU menubar;
- uiControl *child;
- BOOL shownOnce;
- int visible;
- int margined;
- BOOL hasMenubar;
- BOOL changingSize;
- int maximized;
- int fullscreen;
- WINDOWPLACEMENT fsPrevPlacement;
- int borderless;
-
- int (*onClosing)(uiWindow *, void *);
- void *onClosingData;
- void (*onContentSizeChanged)(uiWindow *, void *);
- void *onContentSizeChangedData;
- void (*onDropFile)(uiWindow *, char *, void *);
- void *onDropFileData;
- void (*onGetFocus)(uiWindow *, void *);
- void *onGetFocusData;
- void (*onLoseFocus)(uiWindow *, void *);
- void *onLoseFocusData;
-};
-
-// from https://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing
-#define windowMargin 7
-
-static void windowMargins(uiWindow *w, int *mx, int *my)
-{
- uiWindowsSizing sizing;
-
- *mx = 0;
- *my = 0;
- if (!w->margined)
- return;
- uiWindowsGetSizing(w->hwnd, &sizing);
- *mx = windowMargin;
- *my = windowMargin;
- uiWindowsSizingDlgUnitsToPixels(&sizing, mx, my);
-}
-
-static void windowRelayout(uiWindow *w)
-{
- int x, y, width, height;
- RECT r;
- int mx, my;
- HWND child;
-
- if (w->child == NULL)
- return;
- x = 0;
- y = 0;
- uiWindowsEnsureGetClientRect(w->hwnd, &r);
- width = r.right - r.left;
- height = r.bottom - r.top;
- windowMargins(w, &mx, &my);
- x += mx;
- y += my;
- width -= 2 * mx;
- height -= 2 * my;
- child = (HWND) uiControlHandle(w->child);
- uiWindowsEnsureMoveWindowDuringResize(child, x, y, width, height);
-}
-
-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;
- MINMAXINFO *mmi = (MINMAXINFO *) lParam;
- int width, height;
- 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)
- return lResult;
- switch (uMsg) {
- case WM_COMMAND:
- // not a menu
- if (lParam != 0)
- break;
- if (HIWORD(wParam) != 0 || LOWORD(wParam) <= IDCANCEL)
- break;
- runMenuEvent(LOWORD(wParam), uiWindow(w));
- return 0;
- case WM_WINDOWPOSCHANGED:
- if ((wp->flags & SWP_NOSIZE) != 0)
- break;
- if (w->onContentSizeChanged != NULL) // TODO figure out why this is happening too early
- if (!w->changingSize)
- (*(w->onContentSizeChanged))(w, w->onContentSizeChangedData);
- windowRelayout(w);
- return 0;
- case WM_GETMINMAXINFO:
- // ensure the user cannot resize the window smaller than its minimum size
- lResult = DefWindowProcW(hwnd, uMsg, wParam, lParam);
- uiWindowsControlMinimumSize(uiWindowsControl(w), &width, &height);
- // width and height are in client coordinates; ptMinTrackSize is in window coordinates
- clientSizeToWindowSize(w->hwnd, &width, &height, w->hasMenubar);
- mmi->ptMinTrackSize.x = width;
- mmi->ptMinTrackSize.y = height;
- return lResult;
-
- case WM_DROPFILES:
- if (w->onDropFile)
- {
- HDROP eggdrop = (HDROP)wParam;
- WCHAR filename[1024];
- DragQueryFile(eggdrop, 0, filename, 1024);
-
- char* filename8 = toUTF8(filename);
- w->onDropFile(w, filename8, w->onDropFileData);
- uiFreeText(filename8);
-
- DragFinish(eggdrop);
- }
- break;
-
- case WM_SETFOCUS:
- if (w->onGetFocus)
- {
- w->onGetFocus(w, w->onGetFocusData);
- return 0;
- }
- break;
- case WM_KILLFOCUS:
- if (w->onLoseFocus)
- {
- w->onLoseFocus(w, w->onLoseFocusData);
- return 0;
- }
- break;
-
- case WM_PRINTCLIENT:
- // we do no special painting; just erase the background
- // don't worry about the return value; we let DefWindowProcW() handle this message
- SendMessageW(hwnd, WM_ERASEBKGND, wParam, lParam);
- return 0;
- case WM_CLOSE:
- if ((*(w->onClosing))(w, w->onClosingData))
- uiControlDestroy(uiControl(w));
- return 0; // we destroyed it already
- }
- 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 = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(100));
- wc.hCursor = hDefaultCursor;
- wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1);
- return RegisterClassW(&wc);
-}
-
-void unregisterWindowClass(void)
-{
- if (UnregisterClassW(windowClass, hInstance) == 0)
- logLastError(L"error unregistering uiWindow window class");
-}
-
-static int defaultOnClosing(uiWindow *w, void *data)
-{
- return 0;
-}
-
-static void defaultOnPositionContentSizeChanged(uiWindow *w, void *data)
-{
- // do nothing
-}
-
-static std::map<uiWindow *, bool> windows;
-
-static void uiWindowDestroy(uiControl *c)
-{
- uiWindow *w = uiWindow(c);
-
- // first hide ourselves
- ShowWindow(w->hwnd, SW_HIDE);
- // now destroy the child
- if (w->child != NULL) {
- uiControlSetParent(w->child, NULL);
- uiControlDestroy(w->child);
- }
- // now free the menubar, if any
- if (w->menubar != NULL)
- freeMenubar(w->menubar);
- // and finally free ourselves
- windows.erase(w);
- uiWindowsEnsureDestroyWindow(w->hwnd);
- uiFreeControl(uiControl(w));
-}
-
-uiWindowsControlDefaultHandle(uiWindow)
-
-uiControl *uiWindowParent(uiControl *c)
-{
- return NULL;
-}
-
-void uiWindowSetParent(uiControl *c, uiControl *parent)
-{
- uiUserBugCannotSetParentOnToplevel("uiWindow");
-}
-
-static int uiWindowToplevel(uiControl *c)
-{
- return 1;
-}
-
-// TODO initial state of windows is hidden; ensure this here and make it so on other platforms
-static int uiWindowVisible(uiControl *c)
-{
- uiWindow *w = uiWindow(c);
-
- return w->visible;
-}
-
-static void uiWindowShow(uiControl *c)
-{
- uiWindow *w = uiWindow(c);
-
- w->visible = 1;
- // just in case the window's minimum size wasn't recalculated already
- ensureMinimumWindowSize(w);
- if (w->shownOnce) {
- ShowWindow(w->hwnd, SW_SHOW);
- return;
- }
- w->shownOnce = TRUE;
-
- int cmd;
- if (w->maximized)
- cmd = SW_SHOWMAXIMIZED;
- else
- cmd = SW_SHOWDEFAULT;
-
- // make sure the child is the correct size
- uiWindowsControlMinimumSizeChanged(uiWindowsControl(w));
- ShowWindow(w->hwnd, cmd);//nCmdShow);
- if (UpdateWindow(w->hwnd) == 0)
- logLastError(L"error calling UpdateWindow() after showing uiWindow for the first time");
-}
-
-static void uiWindowHide(uiControl *c)
-{
- uiWindow *w = uiWindow(c);
-
- w->visible = 0;
- ShowWindow(w->hwnd, SW_HIDE);
-}
-
-// TODO we don't want the window to be disabled completely; that would prevent it from being moved! ...would it?
-uiWindowsControlDefaultEnabled(uiWindow)
-uiWindowsControlDefaultEnable(uiWindow)
-uiWindowsControlDefaultDisable(uiWindow)
-uiWindowsControlDefaultSetFocus(uiWindow)
-// TODO we need to do something about undocumented fields in the OS control types
-uiWindowsControlDefaultSyncEnableState(uiWindow)
-// TODO
-uiWindowsControlDefaultSetParentHWND(uiWindow)
-
-static void uiWindowMinimumSize(uiWindowsControl *c, int *width, int *height)
-{
- uiWindow *w = uiWindow(c);
- int mx, my;
-
- *width = 0;
- *height = 0;
- if (w->child != NULL)
- uiWindowsControlMinimumSize(uiWindowsControl(w->child), width, height);
- windowMargins(w, &mx, &my);
- *width += 2 * mx;
- *height += 2 * my;
-}
-
-static void uiWindowMinimumSizeChanged(uiWindowsControl *c)
-{
- uiWindow *w = uiWindow(c);
-
- if (uiWindowsControlTooSmall(uiWindowsControl(w))) {
- // TODO figure out what to do with this function
- // maybe split it into two so WM_GETMINMAXINFO can use it?
- ensureMinimumWindowSize(w);
- return;
- }
- // otherwise we only need to re-layout everything
- windowRelayout(w);
-}
-
-static void uiWindowLayoutRect(uiWindowsControl *c, RECT *r)
-{
- uiWindow *w = uiWindow(c);
-
- // the layout rect is the client rect in this case
- uiWindowsEnsureGetClientRect(w->hwnd, r);
-}
-
-static void uiWindowSetMinSize(uiControl *c, int w, int h)
-{
- // TODO: relayout, eventually
-}
-
-uiWindowsControlDefaultAssignControlIDZOrder(uiWindow)
-
-static void uiWindowChildVisibilityChanged(uiWindowsControl *c)
-{
- // TODO eliminate the redundancy
- uiWindowsControlMinimumSizeChanged(c);
-}
-
-char *uiWindowTitle(uiWindow *w)
-{
- return uiWindowsWindowText(w->hwnd);
-}
-
-void uiWindowSetTitle(uiWindow *w, const char *title)
-{
- uiWindowsSetWindowText(w->hwnd, title);
- // don't queue resize; the caption isn't part of what affects layout and sizing of the client area (it'll be ellipsized if too long)
-}
-
-// this is used for both fullscreening and centering
-// see also https://blogs.msdn.microsoft.com/oldnewthing/20100412-00/?p=14353 and https://blogs.msdn.microsoft.com/oldnewthing/20050505-04/?p=35703
-static void windowMonitorRect(HWND hwnd, RECT *r)
-{
- HMONITOR monitor;
- MONITORINFO mi;
-
- monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY);
- ZeroMemory(&mi, sizeof (MONITORINFO));
- mi.cbSize = sizeof (MONITORINFO);
- if (GetMonitorInfoW(monitor, &mi) == 0) {
- logLastError(L"error getting window monitor rect");
- // default to SM_CXSCREEN x SM_CYSCREEN to be safe
- r->left = 0;
- r->top = 0;
- r->right = GetSystemMetrics(SM_CXSCREEN);
- r->bottom = GetSystemMetrics(SM_CYSCREEN);
- return;
- }
- *r = mi.rcMonitor;
-}
-
-void uiWindowPosition(uiWindow *w, int *x, int *y)
-{
- RECT rect;
- if (GetWindowRect(w->hwnd, &rect) == 0)
- logLastError(L"error getting window position");
- *x = rect.left;
- *y = rect.top;
-}
-
-void uiWindowSetPosition(uiWindow *w, int x, int y)
-{
- if (SetWindowPos(w->hwnd, NULL, x, y, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOOWNERZORDER | SWP_NOZORDER) == 0)
- logLastError(L"error moving window");
-}
-
-void uiWindowContentSize(uiWindow *w, int *width, int *height)
-{
- RECT r;
-
- uiWindowsEnsureGetClientRect(w->hwnd, &r);
- *width = r.right - r.left;
- *height = r.bottom - r.top;
-}
-
-// TODO should this disallow too small?
-void uiWindowSetContentSize(uiWindow *w, int width, int height)
-{
- w->changingSize = TRUE;
- clientSizeToWindowSize(w->hwnd, &width, &height, w->hasMenubar);
- if (SetWindowPos(w->hwnd, NULL, 0, 0, width, height, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER) == 0)
- logLastError(L"error resizing window");
- w->changingSize = FALSE;
-}
-
-int uiWindowMinimized(uiWindow *w)
-{
- return IsIconic(w->hwnd);
-}
-
-void uiWindowSetMinimized(uiWindow *w, int minimized)
-{
- if (minimized)
- ShowWindow(w->hwnd, SW_MINIMIZE);
- else if (w->maximized)
- ShowWindow(w->hwnd, SW_MAXIMIZE);
- else
- ShowWindow(w->hwnd, SW_RESTORE);
-}
-
-int uiWindowMaximized(uiWindow *w)
-{
- return IsZoomed(w->hwnd);
-}
-
-void uiWindowSetMaximized(uiWindow *w, int maximized)
-{
- w->maximized = maximized;
- if (maximized)
- ShowWindow(w->hwnd, SW_MAXIMIZE);
- else
- ShowWindow(w->hwnd, SW_RESTORE);
-}
-
-
-int uiWindowFullscreen(uiWindow *w)
-{
- return w->fullscreen;
-}
-
-void uiWindowSetFullscreen(uiWindow *w, int fullscreen)
-{
- RECT r;
-
- if (w->fullscreen && fullscreen)
- return;
- if (!w->fullscreen && !fullscreen)
- return;
- w->fullscreen = fullscreen;
- w->changingSize = TRUE;
- if (w->fullscreen) {
- ZeroMemory(&(w->fsPrevPlacement), sizeof (WINDOWPLACEMENT));
- w->fsPrevPlacement.length = sizeof (WINDOWPLACEMENT);
- if (GetWindowPlacement(w->hwnd, &(w->fsPrevPlacement)) == 0)
- logLastError(L"error getting old window placement");
- windowMonitorRect(w->hwnd, &r);
- setStyle(w->hwnd, getStyle(w->hwnd) & ~WS_OVERLAPPEDWINDOW);
- if (SetWindowPos(w->hwnd, HWND_TOP,
- r.left, r.top,
- r.right - r.left, r.bottom - r.top,
- SWP_FRAMECHANGED | SWP_NOOWNERZORDER) == 0)
- logLastError(L"error making window fullscreen");
- } else {
- if (!w->borderless) // keep borderless until that is turned off
- setStyle(w->hwnd, getStyle(w->hwnd) | WS_OVERLAPPEDWINDOW);
- if (SetWindowPlacement(w->hwnd, &(w->fsPrevPlacement)) == 0)
- logLastError(L"error leaving fullscreen");
- if (SetWindowPos(w->hwnd, NULL,
- 0, 0, 0, 0,
- SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOSIZE | SWP_NOZORDER) == 0)
- logLastError(L"error restoring window border after fullscreen");
- }
- w->changingSize = FALSE;
-}
-
-void uiWindowOnContentSizeChanged(uiWindow *w, void (*f)(uiWindow *, void *), void *data)
-{
- w->onContentSizeChanged = f;
- w->onContentSizeChangedData = data;
-}
-
-void uiWindowOnClosing(uiWindow *w, int (*f)(uiWindow *, void *), void *data)
-{
- w->onClosing = f;
- w->onClosingData = data;
-}
-
-void uiWindowOnDropFile(uiWindow *w, void (*f)(uiWindow *, char *, void *), void *data)
-{
- w->onDropFile = f;
- w->onDropFileData = data;
-}
-
-void uiWindowOnGetFocus(uiWindow *w, void (*f)(uiWindow *, void *), void *data)
-{
- w->onGetFocus = f;
- w->onGetFocusData = data;
-}
-
-void uiWindowOnLoseFocus(uiWindow *w, void (*f)(uiWindow *, void *), void *data)
-{
- w->onLoseFocus = f;
- w->onLoseFocusData = data;
-}
-
-int uiWindowBorderless(uiWindow *w)
-{
- return w->borderless;
-}
-
-// TODO window should move to the old client position and should not have the extra space the borders left behind
-// TODO extract the relevant styles from WS_OVERLAPPEDWINDOW?
-void uiWindowSetBorderless(uiWindow *w, int borderless)
-{
- w->borderless = borderless;
- if (w->borderless)
- setStyle(w->hwnd, getStyle(w->hwnd) & ~WS_OVERLAPPEDWINDOW);
- else
- if (!w->fullscreen) // keep borderless until leaving fullscreen
- setStyle(w->hwnd, getStyle(w->hwnd) | WS_OVERLAPPEDWINDOW);
-}
-
-void uiWindowSetChild(uiWindow *w, uiControl *child)
-{
- if (w->child != NULL) {
- uiControlSetParent(w->child, NULL);
- uiWindowsControlSetParentHWND(uiWindowsControl(w->child), NULL);
- }
- w->child = child;
- if (w->child != NULL) {
- uiControlSetParent(w->child, uiControl(w));
- uiWindowsControlSetParentHWND(uiWindowsControl(w->child), w->hwnd);
- uiWindowsControlAssignSoleControlIDZOrder(uiWindowsControl(w->child));
- windowRelayout(w);
- }
-}
-
-int uiWindowMargined(uiWindow *w)
-{
- return w->margined;
-}
-
-void uiWindowSetMargined(uiWindow *w, int margined)
-{
- w->margined = margined;
- windowRelayout(w);
-}
-
-
-void uiWindowSetDropTarget(uiWindow* w, int drop)
-{
- DragAcceptFiles(w->hwnd, drop?TRUE:FALSE);
-}
-
-// see http://blogs.msdn.com/b/oldnewthing/archive/2003/09/11/54885.aspx and http://blogs.msdn.com/b/oldnewthing/archive/2003/09/13/54917.aspx
-// TODO use clientSizeToWindowSize()
-static void setClientSize(uiWindow *w, int width, int height, BOOL hasMenubar, DWORD style, DWORD exstyle)
-{
- RECT window;
-
- window.left = 0;
- window.top = 0;
- window.right = width;
- window.bottom = height;
- if (AdjustWindowRectEx(&window, style, hasMenubar, exstyle) == 0)
- logLastError(L"error getting real window coordinates");
- if (hasMenubar) {
- RECT temp;
-
- temp = window;
- temp.bottom = 0x7FFF; // infinite height
- SendMessageW(w->hwnd, WM_NCCALCSIZE, (WPARAM) FALSE, (LPARAM) (&temp));
- window.bottom += temp.top;
- }
- if (SetWindowPos(w->hwnd, NULL, 0, 0, window.right - window.left, window.bottom - window.top, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER) == 0)
- logLastError(L"error resizing window");
-}
-
-uiWindow *uiNewWindow(const char *title, int width, int height, int maximized, int hasMenubar, int resizable)
-{
- uiWindow *w;
- WCHAR *wtitle;
- BOOL hasMenubarBOOL;
-
- if (!resizable) maximized = 0;
-
- uiWindowsNewControl(uiWindow, w);
-
- hasMenubarBOOL = FALSE;
- if (hasMenubar)
- hasMenubarBOOL = TRUE;
- w->hasMenubar = hasMenubarBOOL;
-
- int style = WS_OVERLAPPEDWINDOW;
- int exstyle = 0;
-
- if (!resizable)
- style &= ~(WS_THICKFRAME | WS_MAXIMIZEBOX);
-
- 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)
- logLastError(L"error creating window");
- uiFree(wtitle);
-
- if (hasMenubar) {
- w->menubar = makeMenubar();
- if (SetMenu(w->hwnd, w->menubar) == 0)
- logLastError(L"error giving menu to window");
- }
-
- // and use the proper size
- setClientSize(w, width, height, hasMenubarBOOL, style, exstyle);
-
- w->maximized = maximized;
-
- uiWindowOnClosing(w, defaultOnClosing, NULL);
- uiWindowOnContentSizeChanged(w, defaultOnPositionContentSizeChanged, NULL);
-
- uiWindowOnDropFile(w, NULL, NULL);
- uiWindowOnGetFocus(w, NULL, NULL);
- uiWindowOnLoseFocus(w, NULL, NULL);
-
- windows[w] = true;
- return w;
-}
-
-// this cannot queue a resize because it's called by the resize handler
-void ensureMinimumWindowSize(uiWindow *w)
-{
- int width, height;
- RECT r;
-
- uiWindowsControlMinimumSize(uiWindowsControl(w), &width, &height);
- uiWindowsEnsureGetClientRect(w->hwnd, &r);
- if (width < (r.right - r.left)) // preserve width if larger
- width = r.right - r.left;
- if (height < (r.bottom - r.top)) // preserve height if larger
- height = r.bottom - r.top;
- clientSizeToWindowSize(w->hwnd, &width, &height, w->hasMenubar);
- if (SetWindowPos(w->hwnd, NULL, 0, 0, width, height, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER) == 0)
- logLastError(L"error resizing window");
-}
-
-void disableAllWindowsExcept(uiWindow *which)
-{
- for (auto &w : windows) {
- if (w.first == which)
- continue;
- EnableWindow(w.first->hwnd, FALSE);
- }
-}
-
-void enableAllWindowsExcept(uiWindow *which)
-{
- for (auto &w : windows) {
- if (w.first == which)
- continue;
- if (!uiControlEnabled(uiControl(w.first)))
- continue;
- EnableWindow(w.first->hwnd, TRUE);
- }
-}