Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 45 additions & 7 deletions packages/geastack-windows/targets/win32/main/native/controls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
// stack views arrange their children, anchors pin a child to its parent's
// edges, scroll views size their document to its content.
//
// Layout runs once per frame from the target's frame loop (the callback
// Layout runs on dirty frames from the target's frame loop (the callback
// installed through setNativeLayoutCallback), starting at the root view that
// installRootView handed over, in layout px scaled to the window's DPI.

Expand Down Expand Up @@ -268,16 +268,26 @@ HFONT fontFor(ViewPtr node, int fallbackSize = 13)
return gea::win32::fontForFamily(L"Segoe UI", fallbackSize);
}

void syncClickHandler(ViewPtr node)
{
if (!node || !node->widget) return;
if (!node->onClick) {
node->widget->events.onClick = nullptr;
return;
}
node->widget->events.onClick = [node] {
if (node->onClick && node->onClick->handler) node->onClick->handler();
};
}

void ensureWidget(ViewPtr node, HWND parent)
{
if (!node->widget) {
node->widget = gea::win32::createWidget(widgetKindFor(node->viewKind), parent);
if (!node->widget) return;
if (node->viewKind == ViewKind::Label) node->widget->clickTransparent = node->onClick == nullptr;
syncClickHandler(node);
ViewObject *self = node;
node->widget->events.onClick = [self] {
if (self->onClick && self->onClick->handler) self->onClick->handler();
};
node->widget->events.onTextChanged = [self](const std::wstring &text) {
self->text = text;
if (self->onChange && self->onChange->handler) self->onChange->handler();
Expand Down Expand Up @@ -672,7 +682,23 @@ void installLayout()
{
if (g_layoutInstalled) return;
g_layoutInstalled = true;
gea::win32::setNativeLayoutCallback([](const RECT &area) { layoutRoot(area); });
gea::win32::setNativeLayoutCallback([](const RECT &area) {
static RECT lastArea{};
static double lastScale = 0;
const double currentScale = scale();
if (!g_needsLayout && EqualRect(&lastArea, &area) && currentScale == lastScale) return;
lastArea = area;
lastScale = currentScale;
g_needsLayout = false;
layoutRoot(area);
});
}

void showAttachedTree(ViewPtr node)
{
if (!node || !node->widget) return;
ShowWindow(node->widget->hwnd, node->hidden ? SW_HIDE : SW_SHOWNA);
for (ViewPtr child : node->children) showAttachedTree(child);
}

void attach(ViewPtr parent, ViewPtr child)
Expand All @@ -688,6 +714,12 @@ void attach(ViewPtr parent, ViewPtr child)
if (std::find(parent->children.begin(), parent->children.end(), child) == parent->children.end()) parent->children.push_back(child);
HWND host = parent->widget ? (parent->viewKind == ViewKind::Scroll && parent->widget->document ? parent->widget->document : parent->widget->hwnd) : hostWindow();
if (parent->widget) ensureWidget(child, host);
for (ViewPtr ancestor = parent; ancestor; ancestor = ancestor->parent) {
if (ancestor == g_root) {
showAttachedTree(child);
break;
}
}
g_needsLayout = true;
gea::win32::requestFrame();
}
Expand Down Expand Up @@ -922,8 +954,13 @@ bool WinView_get_hidden(WinView self) { ViewPtr node = view(self); return node ?
void WinView_set_hidden(WinView self, bool value)
{
if (ViewPtr node = view(self)) {
if (node->hidden == value && (!node->widget || node->widget->style.hidden == value)) return;
node->hidden = value;
if (node->widget) ShowWindow(node->widget->hwnd, value ? SW_HIDE : SW_SHOWNA);
if (node->widget) {
// Layout must not repeat the same visibility change.
node->widget->style.hidden = value;
ShowWindow(node->widget->hwnd, value ? SW_HIDE : SW_SHOWNA);
}
markDirty();
}
}
Expand Down Expand Up @@ -1016,7 +1053,8 @@ void WinView_onClick(WinView self, WinCallback handler)
{
if (ViewPtr node = view(self)) {
node->onClick = callback(handler);
if (node->widget) node->widget->clickTransparent = false;
syncClickHandler(node);
if (node->widget && node->viewKind == ViewKind::Label) node->widget->clickTransparent = node->onClick == nullptr;
markDirty();
}
}
Expand Down
9 changes: 9 additions & 0 deletions packages/geastack-windows/targets/win32/main/win32_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -625,6 +625,15 @@ LRESULT CALLBACK mainWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM l
EndPaint(hwnd, &paint);
return 0;
}
case WM_COMMAND:
if (lParam) {
HWND control = reinterpret_cast<HWND>(lParam);
HWND parent = GetParent(control);
// Reparented controls can still notify the window that created them.
if (parent && parent != hwnd && gea::win32::widgetFor(control) && gea::win32::widgetFor(parent))
return SendMessageW(parent, message, wParam, lParam);
}
break;
case WM_SIZE:
if (g_booted && wParam != SIZE_MINIMIZED) {
layoutNativeChrome();
Expand Down
15 changes: 13 additions & 2 deletions packages/geastack-windows/targets/win32/main/win32_widgets.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,9 @@ void notifyCommand(Widget *parent, HWND control, WORD code)
case WidgetKind::TextField:
case WidgetKind::TextArea:
if (code == EN_CHANGE) {
widget->lastText = widgetText(widget);
const std::wstring text = widgetText(widget);
if (text == widget->lastText) break;
widget->lastText = text;
widget->style.text = widget->lastText;
if (widget->events.onTextChanged) widget->events.onTextChanged(widget->lastText);
} else if (code == EN_SETFOCUS) {
Expand Down Expand Up @@ -574,7 +576,16 @@ LRESULT CALLBACK widgetProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPara
POINT point{GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
const bool inside = PtInRect(&client, point) != FALSE;
if (widget->events.onPressUp) widget->events.onPressUp();
if (inside && widget->events.onClick) widget->events.onClick();
if (inside) {
for (HWND current = hwnd; current; current = GetParent(current)) {
Widget *target = widgetFromWindow(current);
if (!target) break;
if (target->events.onClick) {
target->events.onClick();
break;
}
}
}
return 0;
}
case WM_CAPTURECHANGED:
Expand Down
Loading