Skip to content

Conversation

@jserv
Copy link
Contributor

@jserv jserv commented Oct 20, 2025

Previous design had widget-specific callback mechanisms (button signals, scroll signals) with duplicated closure management code.

This commit introduces two complementary callback patterns:

  1. Widget-level dispatch (for custom widgets and complex event handling)
    • Added twin_widget_proc_t with (widget, event, closure) signature
    • Unified closure storage in twin_widget_t
    • Used by custom widgets and applications needing full event access
  2. Button-specific API (for simple click handling)
    • Added twin_button_on_clicked(button, callback, data)
    • Simplified signature: void (*)(twin_button_t*, void*)
    • Direct callback invocation on button click
    • Used by calc, image, spline demos

Button signals promoted to standard events (TwinEventButtonSignal*). Removed obsolete scroll signal typedefs and button-specific fields.


Summary by cubic

Unifies widget event handling with a closure-based API and adds a simple button click callback to replace widget-specific signal plumbing. This standardizes callbacks across widgets and simplifies demo apps.

  • New Features

    • Added twin_widget_proc_t(widget, event, closure) and closure storage on twin_widget_t.
    • Added twin_widget_set_callback(widget, callback, data) for app-level event callbacks.
    • Added twin_button_on_clicked(button, callback, data) for straightforward click handling.
    • Standardized button signals as events: TwinEventButtonSignalDown/Up.
  • Migration

    • Replace dispatch with handler everywhere; use twin_widget_create_with_handler(...) and update function signatures to include void *closure.
    • For custom widgets, pass a handler to twin_custom_widget_create(...).
    • Stop using button signal callbacks; use twin_button_on_clicked(...).
    • Removed scroll signal typedefs and button-specific signal fields.

Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 issues found across 14 files

Prompt for AI agents (all 3 issues)

Understand the root cause of the following 3 issues and fix them.


<file name="src/widget.c">

<violation number="1" location="src/widget.c:91">
Forward the closure you received when calling the copy widget’s handler; otherwise its user data is lost and the new closure-based API breaks for geometry-copy scenarios.</violation>

<violation number="2" location="src/widget.c:354">
Pass the closure argument to the user’s custom widget handler; dropping it to NULL means their registered user data never reaches the handler in the destroy path.</violation>

<violation number="3" location="src/widget.c:378">
Return the user dispatch with the closure you were passed; otherwise custom widget handlers cannot access their user data during normal event handling.</violation>
</file>

React with 👍 or 👎 to teach cubic. Mention @cubic-dev-ai to give feedback, ask questions, or re-run the review.

@sysprog21 sysprog21 deleted a comment from cubic-dev-ai bot Oct 20, 2025
Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

4 issues found across 14 files

Prompt for AI agents (all 4 issues)

Understand the root cause of the following 4 issues and fix them.


<file name="src/box.c">

<violation number="1" location="src/box.c:44">
Passing NULL as the closure when dispatching to a child widget discards its callback_data, so widgets relying on per-instance state stop receiving their context. Please forward the child’s stored closure instead.</violation>

<violation number="2" location="src/box.c:191">
Pointer events forwarded to the pressed child must pass its callback_data; returning with a NULL closure prevents handlers from seeing their per-instance context.</violation>

<violation number="3" location="src/box.c:198">
Keyboard events sent to the focused child need to include its callback_data; passing NULL strips away the closure context and breaks stateful handlers.</violation>

<violation number="4" location="src/box.c:217">
Paint callbacks must receive the widget’s callback_data closure; forwarding NULL causes stateful renderers to lose their context.</violation>
</file>

React with 👍 or 👎 to teach cubic. Mention @cubic-dev-ai to give feedback, ask questions, or re-run the review.

Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

6 issues found across 14 files

Prompt for AI agents (all 6 issues)

Understand the root cause of the following 6 issues and fix them.


<file name="src/button.c">

<violation number="1" location="src/button.c:69">
The new click dispatch emits TwinEventButtonSignalDown from the TwinEventButtonUp handler, so button release events are misreported and the matching TwinEventButtonSignalUp is never sent. This breaks release handlers and mislabels clicks.</violation>
</file>

<file name="src/widget.c">

<violation number="1" location="src/widget.c:91">
Forward the incoming closure when delegating QueryGeometry to the copy widget; replacing it with callback_data loses the caller-provided context and breaks custom handlers.</violation>
</file>

<file name="src/box.c">

<violation number="1" location="src/box.c:44">
Forward the widget’s closure when dispatching to children; passing NULL drops application state for QueryGeometry handlers.</violation>

<violation number="2" location="src/box.c:191">
Propagate the child widget’s closure when sending pointer events; NULL strips the handler’s state.</violation>

<violation number="3" location="src/box.c:198">
Return the focused child with its closure so key handlers can access state; passing NULL breaks them.</violation>

<violation number="4" location="src/box.c:217">
Forward the child’s closure when invoking its paint handler; NULL removes the required state.</violation>
</file>

React with 👍 or 👎 to teach cubic. Mention @cubic-dev-ai to give feedback, ask questions, or re-run the review.

twin_widget_t *copy = widget->copy_geom;
if (copy->layout)
(*copy->dispatch)(copy, event);
copy->handler(copy, event, copy->callback_data);
Copy link

@cubic-dev-ai cubic-dev-ai bot Oct 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Forward the incoming closure when delegating QueryGeometry to the copy widget; replacing it with callback_data loses the caller-provided context and breaks custom handlers.

Prompt for AI agents
Address the following comment on src/widget.c at line 91:

<comment>Forward the incoming closure when delegating QueryGeometry to the copy widget; replacing it with callback_data loses the caller-provided context and breaks custom handlers.</comment>

<file context>
@@ -75,16 +75,20 @@ static void _twin_widget_paint(twin_widget_t *widget)
             twin_widget_t *copy = widget-&gt;copy_geom;
             if (copy-&gt;layout)
-                (*copy-&gt;dispatch)(copy, event);
+                copy-&gt;handler(copy, event, copy-&gt;callback_data);
             widget-&gt;preferred = copy-&gt;preferred;
             return TwinDispatchDone;
</file context>
Suggested change
copy->handler(copy, event, copy->callback_data);
copy->handler(copy, event, closure);
Fix with Cubic

@sysprog21 sysprog21 deleted a comment from cubic-dev-ai bot Oct 20, 2025
@sysprog21 sysprog21 deleted a comment from cubic-dev-ai bot Oct 20, 2025
@sysprog21 sysprog21 deleted a comment from cubic-dev-ai bot Oct 20, 2025
cubic-dev-ai[bot]

This comment was marked as resolved.

Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 14 files

Prompt for AI agents (all 1 issues)

Understand the root cause of the following 1 issues and fix them.


<file name="src/box.c">

<violation number="1" location="src/box.c:132">
Passing NULL here discards the widget&#39;s callback_data, so configure handlers that rely on their closure will now be called with NULL and malfunction. Forward the stored closure instead.</violation>
</file>

React with 👍 or 👎 to teach cubic. Mention @cubic-dev-ai to give feedback, ask questions, or re-run the review.

Previous design had widget-specific callbacks (button signals, scroll
signals) scattered across different widgets, each managing its own
closure storage.

Now all widgets use a unified callback mechanism:
- Single callback signature: (widget, event, closure) → result
- Closure stored in twin_widget_t.callback_data
- Button clicks emit TwinEventButtonSignalDown event
- Applications register callbacks via twin_widget_set_callback()

Removed obsolete scroll signal typedefs and widget-specific callback
fields. Custom widgets and button handlers now use the same dispatch
pattern.

Button event types now correctly reflect their semantics:
- TwinEventButtonSignalDown: emitted on button press
- TwinEventButtonSignalUp: emitted on button release (click completion)

Applications updated to listen for ButtonSignalUp instead of Down,
matching the GTK convention where click callbacks trigger on release.
@jserv jserv merged commit b2008b0 into main Oct 20, 2025
8 checks passed
@jserv jserv deleted the refine-callback branch October 20, 2025 14:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants