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; intmax_t 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) break; runMenuEvent(LOWORD(wParam), uiWindow(w)); return 0; case WM_WINDOWPOSCHANGED: if ((wp->flags & SWP_NOSIZE) != 0) break; 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_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); }
bool Button::leftClick(float x, float y) { UNUSED(x); UNUSED(y); if(uiWindow().ctrlPressed()) this->triggerCtrl(); else if(uiWindow().shiftPressed()) this->triggerShift(); else this->trigger(); return true; }
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 uiWindowHide(uiControl *c) { uiWindow *w = uiWindow(c); w->visible = 0; ShowWindow(w->hwnd, SW_HIDE); }
SpaceSheet::SpaceSheet(SpaceViewport& viewport) : RootSheet(viewport.uiWindow(), nullptr, false) , mViewport(viewport) , mTarget(uiWindow().inkWindow().as<GorillaWindow>().spaceTarget(mViewport.ogreCamera()->getParentSceneNode()->getCreator(), 0, 0).as<GorillaSpaceTarget>()) { mStyle = &cls(); mFrame = make_unique<Layer3D>(*this, 0, &mTarget); mOgreCamera = mViewport.ogreCamera(); mSceneNode = mTarget.spaceScreen().getParentSceneNode(); mSceneNode->getUserObjectBindings().setUserAny(Ogre::Any(static_cast<Object*>(this))); mDummyRect = mSceneNode->getCreator()->createManualObject(); mSceneNode->attachObject(mDummyRect); mDummyRect->setQueryFlags(SPACESHEET_OGRE_MASK); mDummyRect->begin("debug_invisible"); mDummyRect->position(Ogre::Vector3::ZERO); mDummyRect->normal(Ogre::Vector3::ZERO); mDummyRect->textureCoord(Ogre::Vector2::ZERO); mDummyRect->index(0); mDummyRect->end(); mTarget.spaceScreen().ratio() = 0.01f; //this->updateSize(); }
static void onSizeAllocate(GtkWidget *widget, GdkRectangle *allocation, gpointer data) { uiWindow *w = uiWindow(data); // TODO deal with spurious size-allocates (*(w->onContentSizeChanged))(w, w->onContentSizeChangedData); }
void setFullscreen(uiCheckbox *cb, void *data) { uiWindow *w = uiWindow(data); uiWindowSetFullscreen(w, uiCheckboxChecked(fullscreen)); updatesize(w); }
static void sizeHeight(uiSpinbox *s, void *data) { uiWindow *w = uiWindow(data); int xp, yp; uiWindowContentSize(w, &xp, &yp); yp = uiSpinboxValue(height); uiWindowSetContentSize(w, xp, yp); }
static void uiWindowShow(uiControl *c) { uiWindow *w = uiWindow(c); // don't use gtk_widget_show_all() as that will show all children, regardless of user settings // don't use gtk_widget_show(); that doesn't bring to front or give keyboard focus // (gtk_window_present() does call gtk_widget_show() though) gtk_window_present(w->window); }
static void onSizeAllocate(GtkWidget *widget, GdkRectangle *allocation, gpointer data) { uiWindow *w = uiWindow(data); if (w->changingSize) w->changingSize = FALSE; else (*(w->onContentSizeChanged))(w, w->onContentSizeChangedData); }
static void sizeWidth(uiSpinbox *s, void *data) { uiWindow *w = uiWindow(data); int xp, yp; uiWindowContentSize(w, &xp, &yp); xp = uiSpinboxValue(width); uiWindowSetContentSize(w, xp, yp); }
static gboolean onClosing(GtkWidget *win, GdkEvent *e, gpointer data) { uiWindow *w = uiWindow(data); // manually destroy the window ourselves; don't let the delete-event handler do it if ((*(w->onClosing))(w, w->onClosingData)) uiControlDestroy(uiControl(w)); // don't continue to the default delete-event handler; we destroyed the window by now return TRUE; }
static gboolean onConfigure(GtkWidget *win, GdkEvent *e, gpointer data) { uiWindow *w = uiWindow(data); // there doesn't seem to be a way to determine if only moving or only resizing is happening :/ if (w->changingPosition) w->changingPosition = FALSE; else (*(w->onPositionChanged))(w, w->onPositionChangedData); // always continue handling return FALSE; }
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); }
uiWindow *uiNewWindow(const char *title, int width, int height, int hasMenubar) { uiWindow *w; uiUnixNewControl(uiWindow, w); w->widget = gtk_window_new(GTK_WINDOW_TOPLEVEL); w->container = GTK_CONTAINER(w->widget); w->window = GTK_WINDOW(w->widget); gtk_window_set_title(w->window, title); gtk_window_resize(w->window, width, height); w->vboxWidget = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); w->vboxContainer = GTK_CONTAINER(w->vboxWidget); w->vbox = GTK_BOX(w->vboxWidget); // set the vbox as the GtkWindow child gtk_container_add(w->container, w->vboxWidget); if (hasMenubar) { w->menubar = makeMenubar(uiWindow(w)); gtk_container_add(w->vboxContainer, w->menubar); } w->childHolderWidget = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); w->childHolderContainer = GTK_CONTAINER(w->childHolderWidget); gtk_widget_set_hexpand(w->childHolderWidget, TRUE); gtk_widget_set_halign(w->childHolderWidget, GTK_ALIGN_FILL); gtk_widget_set_vexpand(w->childHolderWidget, TRUE); gtk_widget_set_valign(w->childHolderWidget, GTK_ALIGN_FILL); gtk_container_add(w->vboxContainer, w->childHolderWidget); // show everything in the vbox, but not the GtkWindow itself gtk_widget_show_all(w->vboxWidget); // and connect our events g_signal_connect(w->widget, "delete-event", G_CALLBACK(onClosing), w); g_signal_connect(w->widget, "configure-event", G_CALLBACK(onConfigure), w); g_signal_connect(w->childHolderWidget, "size-allocate", G_CALLBACK(onSizeAllocate), w); uiWindowOnClosing(w, defaultOnClosing, NULL); uiWindowOnPositionChanged(w, defaultOnPositionContentSizeChanged, NULL); uiWindowOnContentSizeChanged(w, defaultOnPositionContentSizeChanged, NULL); // normally it's SetParent() that does this, but we can't call SetParent() on a uiWindow // TODO we really need to clean this up, especially since see uiWindowDestroy() above g_object_ref(w->widget); return w; }
static void uiWindowMinimumSize(uiWindowsControl *c, intmax_t *width, intmax_t *height) { uiWindow *w = uiWindow(c); uiWindowsSizing sizing; 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 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; // make sure the child is the correct size uiWindowsControlMinimumSizeChanged(uiWindowsControl(w)); ShowWindow(w->hwnd, nCmdShow); if (UpdateWindow(w->hwnd) == 0) logLastError(L"error calling UpdateWindow() after showing uiWindow for the first time"); }
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)); }
void doResizes(void) { uiWindowsControl *w; HWND hwnd; RECT r; while (resizes->len != 0) { w = ptrArrayIndex(resizes, uiWindowsControl *, 0); ptrArrayDelete(resizes, 0); // don't clip content if content dynamically changed (tab page changed, etc.) ensureMinimumWindowSize(uiWindow(w)); hwnd = (HWND) uiControlHandle(uiControl(w)); if (GetClientRect(hwnd, &r) == 0) logLastError("error getting uiWindow client rect in doResizes()"); (*(w->Relayout))(w, r.left, r.top, r.right - r.left, r.bottom - r.top); // we used SWP_NOREDRAW; we need to queue a redraw ourselves // force all controls to be redrawn; this fixes things like the date-time picker's up-down not showing up until hovered over (and bypasses complications caused by WS_CLIPCHILDREN and WS_CLIPSIBLINGS, which we don't use but other controls might) if (RedrawWindow(hwnd, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN) == 0) logLastError("error redrawing controls after a resize in doResizes()"); } }
static void uiWindowDestroy(uiControl *c) { uiWindow *w = uiWindow(c); // first hide ourselves gtk_widget_hide(w->widget); // now destroy the child if (w->child != NULL) { uiControlSetParent(w->child, NULL); uiUnixControlSetContainer(uiUnixControl(w->child), w->childHolderContainer, TRUE); uiControlDestroy(w->child); } // now destroy the menus, if any if (w->menubar != NULL) freeMenubar(w->menubar); gtk_widget_destroy(w->childHolderWidget); gtk_widget_destroy(w->vboxWidget); // and finally free ourselves // use gtk_widget_destroy() instead of g_object_unref() because GTK+ has internal references (see #165) gtk_widget_destroy(w->widget); uiFreeControl(uiControl(w)); }
static void borderless(uiCheckbox *c, void *data) { uiWindow *w = uiWindow(data); uiWindowSetBorderless(w, uiCheckboxChecked(c)); }
// 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; }