Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
81ef505
pie: open at a point
concprog Nov 8, 2026
92340fd
kit: public hit test
concprog Nov 8, 2026
006e313
pie: pick on key release
concprog Nov 8, 2026
abeac81
pie: sub-pies and the More level
concprog Nov 8, 2026
297b278
window: focus callback and hiding on Linux
concprog Nov 8, 2026
2a54944
raster: optional frame alpha
concprog Nov 8, 2026
096288e
window: transparent windows on Linux
concprog Nov 8, 2026
9fd8a6a
window: frameless and topmost on Linux
concprog Nov 8, 2026
d880a93
window: layer-shell windows on Wayland
concprog Nov 8, 2026
aff3a5d
pie: number keys are numpad directions
concprog Nov 8, 2026
3b3e480
pie: accelerator keys
concprog Nov 8, 2026
2c5b5c0
pie: open animation
concprog Nov 8, 2026
de0ce2e
rust: on_focus in BKWindowCallbacks
concprog Nov 8, 2026
ba7c244
wayland: wait for the first configure
concprog Nov 8, 2026
57ad36a
imgui: recover the frame after a Python error
concprog Nov 8, 2026
634de0c
tk test: Tk 9's default tearoff
concprog Nov 8, 2026
3a48261
docs: window requests, focus, hit test, raster alpha, imgui abandon
concprog Nov 8, 2026
0d2ac56
docs: drop imgui abandon and lua context from tutorials
concprog Nov 8, 2026
7bc4ffc
rust: window activation hook and transparent background
concprog Nov 8, 2026
313d8b9
python: drop X11 autorepeat key releases in the Tk host
concprog Nov 8, 2026
ca2869d
docs: rust window activation and transparent background
concprog Nov 8, 2026
0141607
wayland: cursor-shape cursors, as GHOST
concprog Nov 8, 2026
e5aa0e7
docs: wayland cursor-shape
concprog Nov 8, 2026
37ab058
wayland: copy only the damage after a full frame
concprog Nov 8, 2026
3ec5a5e
kit: no relayout or redraw for unchanged values and canvas items
concprog Nov 8, 2026
37d5ced
js: transparent windows, focus and blur events
concprog Nov 8, 2026
0ca786a
Revert "tk test: Tk 9's default tearoff"
concprog Nov 8, 2026
fd14f61
Merge upstream/main into pie-overlay
concprog Nov 8, 2026
d7dde3f
changelog: Linux windows, hit test, focus, pies
concprog Nov 8, 2026
5284347
Merge remote-tracking branch 'upstream/main' into pie-overlay
concprog Nov 8, 2026
b584c6d
kit: text shadow switch, off in python
concprog Nov 8, 2026
9080f51
kit: forget a popup's animations when it closes
concprog Nov 8, 2026
feb61c8
win32: transparent windows through UpdateLayeredWindow
concprog Nov 9, 2026
a64f598
cocoa: transparent windows
concprog Nov 9, 2026
2fb5168
docs: transparent windows on windows and macos
concprog Nov 9, 2026
d26fb49
gpu: transparent frames in the OpenGL renderer
concprog Nov 9, 2026
f660180
win32: transparent windows with the Direct3D 11 renderer
concprog Nov 9, 2026
af2bb5d
merge: upstream main
concprog Nov 9, 2026
d478976
docs: transparent window options on every platform
concprog Nov 9, 2026
1b84b7c
d3d11: declare the DirectComposition interfaces for C
concprog Nov 9, 2026
5cea7a6
win32: transparent GPU windows through DWM blur-behind
concprog Nov 9, 2026
84170af
gpu: test for alpha once per readback
concprog Nov 9, 2026
7af1a95
rust: window kind, decorations and layer shell options
concprog Nov 9, 2026
586dd18
js: always on top, frame and layer shell window options
concprog Nov 9, 2026
cc111ce
rust: test window kind requests
concprog Nov 9, 2026
0a1c91e
docs: window kind options in rust and javascript
concprog Nov 9, 2026
7d32cc3
rust: window kind cleanups from review
concprog Nov 9, 2026
5cc2167
changelog: gpu header changes, transparent windows on every platform
concprog Nov 9, 2026
718472b
tests: send tk quit from the run loop
concprog Nov 10, 2026
c8dc4e8
python: answer a close that arrives mid-callback right after it
concprog Nov 10, 2026
15c4198
tests: quit from the timer callback again, python defers the close
concprog Nov 10, 2026
1cfe940
merge upstream/main into pie-overlay
concprog Nov 10, 2026
5a4c004
gpu: blend skips the alpha byte in opaque frames
concprog Nov 10, 2026
c28ac4e
win32: timers follow the window when it is made again
concprog Nov 10, 2026
7e698bf
gpu: opaque image and paint paths skip the alpha byte
concprog Nov 10, 2026
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
72 changes: 72 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,90 @@ All notable changes to **blenderui** (BUI). The format follows
### Added
- **Rust:** `<input live>` (and `<textarea live>`): the field reports every keystroke to `on_input` / `on_change`, not only on Enter or blur,
so a view can follow the typing (a search box, a date field that lights up a calendar).
- **Linux window requests** that Win32 and Cocoa already had, through `BK_window_wm` (Python `Window.wm`):
`"state"` 2 and 0 hide and show a window on X11 and Wayland; `"override"` removes the frame (`_MOTIF_WM_HINTS`
on X11, client-side decorations on Wayland) and `"topmost"` keeps an X11 window above others
(`_NET_WM_STATE_ABOVE`), both ported from `GHOST_WindowX11`.
- **Transparent windows on Linux:** `wm "transparent"` before `show` gives per-pixel alpha, with no region
background, through a 32-bit ARGB visual on X11 and ARGB8888 buffers on Wayland. The software raster can keep
premultiplied alpha (`BUI_raster_set_alpha`, `BUI_raster_alpha`, `BUI_raster_clear`); opaque frames are
unchanged byte for byte and draw as fast as before. The OpenGL renderer draws transparent windows too: a GLX config for the
32-bit visual, frames cleared to alpha 0 and `BUI_raster_clear` as a GPU clear of the redrawn rect (`ROP`: premultiplied
`ONE, ONE_MINUS_SRC_ALPHA` for colour and alpha, as in Blender's `GPU_BLEND_ALPHA_PREMULT`).
- **Transparent windows on Windows and macOS:** `wm "transparent"` gives per-pixel alpha with the software
raster. Windows shows the premultiplied frame through a layered window (`UpdateLayeredWindow`, `AC_SRC_ALPHA`; the
window has no frame and `"alpha"` scales the whole window); macOS draws it in a non-opaque window with a clear
background. Rust `WindowBackgroundAppearance::Transparent` and JavaScript `transparent: true` use it there too.
With the Direct3D 11 renderer the window uses DWM blur-behind (`DwmEnableBlurBehindWindow` over the client area, the
surface cleared to zero alpha) and a bitblt-model swap chain, as SDL does (no copy to the CPU, `ClearView` for the
redrawn rect); without the device it falls back to `UpdateLayeredWindow`. A window that is not transparent keeps the
flip-model swap chain with `DXGI_ALPHA_MODE_IGNORE`.
- **Layer-shell windows on Wayland:** `wm "layer"` (layer 0 background to 3 overlay, keyboard interactivity) and
`"anchor"` (edges, exclusive zone) make a wlr-layer-shell surface, on KDE Plasma, wlroots compositors and
COSMIC (not GNOME). `wm_get("layer")` says whether the compositor has it. The protocol file (MIT) is in
`kit/extern/wayland_protocols`.
- **Focus callback:** `BKWindowCallbacks.on_focus` reports when a window gets or loses the keyboard focus, on
Win32, Cocoa, X11 and Wayland (Python `Window.on_focus`). Losing it cancels an open pie, as Blender's
`WINDEACTIVATE` does. In Python the callback is queued behind a running callback, like the timers.
- **Hit test:** `BK_hit_at(ctx, x, y)` gives the interactive node under a point (Python `ctx.hit`, Lua `ctx:hit`).
- **Pie menus as in Blender** (`pie_handler`, `pie_menu_begin`): opened while a key is held, releasing the key
picks the item in the pointer's direction, and a quick tap keeps the pie open for a click; an item with a
submenu opens a sub-pie at the pointer; past 8 items, the 8th is "More" with the rest
(`pie_menu_level_create`); items get underlined accelerator letters (`menu_block_set_keyaccels`); and the
items grow out of the center over 60 ms (`pie_animation_timeout`, off with reduced motion).
- **Rust:** `App::on_window_activation(|id, active, cx| ...)` reports keyboard focus, and `WindowOptions.window_background =
WindowBackgroundAppearance::Transparent` opens a transparent window on Linux, Windows and macOS.
- **JavaScript** (Node, Bun and `bui build` apps): `app.window({ transparent: true })` and the window events `focus` and
`blur`.
- **Window kinds in Rust and JavaScript:** Rust `WindowOptions.kind` (`WindowKind::Floating`, `PopUp` and
`LayerShell(LayerShellOptions)`) and `window_decorations` (`WindowDecorations::Client`), and JavaScript
`app.window({ alwaysOnTop, frame: false, layerShell: { layer, anchor, exclusiveZone, keyboard } })`, send the
`topmost`, `override`, `layer` and `anchor` window requests that Python reaches through `Window.wm`. Topmost works on
Windows, macOS and X11; a Wayland toplevel cannot ask for it, so use the layer shell there.
- **Dear ImGui:** `ImGui_ImplBUI_AbandonFrame()` (C: `cImGui_ImplBUI_AbandonFrame`) ends a frame that a binding's
callback left early on an error, with Dear ImGui's error recovery.

### Changed
- **Text fields:** in the HTML look (browser-style inputs and text areas) the caret blinks like a browser's (about every 530 ms, solid right after it
moves or the text changes); Blender's own fields keep Blender's solid caret. The window wakes only for the next toggle, so an idle window still sleeps.
- `BK_open_pie` takes the pie's center (`at_x`, `at_y`; `-100000` for the pointer, as in `BK_open_menu`).
Python `PieMenu.show(..., at=(x, y))` and `ctx.open_pie(..., at=)`, Lua `ctx:open_pie(items, title, x, y)`.
- Pie number keys are directions on the numpad (8 north, 6 east, 2 south, 4 west, the diagonals on 7, 9, 1 and 3),
as in Blender. They were item positions.
- **Python text has no shadow:** Blender's UI text shadow made small text look soft. The Python binding turns it off at import;
`buipy.kit_set_text_shadow(True)` brings it back. Other bindings keep it. The switch is `BK_set_text_shadow(on)` in C.
- **Wayland cursors** go through the cursor-shape protocol when the compositor has it (KDE, wlroots, GNOME 46+), as in
Blender's GHOST: the compositor draws the cursor and no cursor theme is loaded. Elsewhere the theme loads on the first
cursor change, not at start-up. Builds with wayland-protocols older than 1.32 keep the theme.
- `BKWindowCallbacks` has the new `on_focus` member, and so has the Rust `blenderui-sys` struct.
- **GPU renderer header:** `BuiGpuX11Window` has the new `visual` member (the window's VisualID, 0 for the default one),
and `BUI_raster_clear` clears on a GPU raster too. Call `BUI_raster_set_alpha` before attaching a GPU renderer: it
reads the setting when it starts.

### Fixed
- **Closing a pie during its open animation** freed it while the animation still pointed at it, so the next render read freed
memory (`bui_lua_context` crashed in CI). Closing a popup now clears everything that refers into it through `bk_forget`.
- **Wayland frames copied the whole window every frame** after the first full one: the double-buffer copy kept
its own full copy as the next frame's damage. It copies and reports only what changed now.
- **Setting a node's geometry or a flag property** (`visible`, `enabled` ...) **to the value it already has** relaid out
and redrew the whole window. Unchanged values do nothing now. The Rust binding sets every widget's place each frame,
so each Rust frame was a full redraw: 2.7 ms of CPU per frame at 941x982 on Wayland, 0.43 ms now.
- **`BK_canvas_put_item` / `BK_canvas_truncate`** (display lists rebuilt each frame) redrew the whole canvas. Only items
that changed, moved or went away are redrawn now.
- **Python Tk host on X11:** a held key no longer sends a release on each auto-repeat, so holding a pie key keeps the pie open
until the key is up (the native X11 host already did this).
- **Lua bindings** set_menus on menubar fix; ctx:free() no-ops fix; widget tests
- **Browser-look text fields** take the CSS `color` and `font-size` the field itself is given (one that differs from its parent's); without them they keep Chrome's black 13.33px, as before.
- **Browser-look form controls** drew their text with Blender's UI drop shadow, which made it look heavy next to the page's text. They draw none now, as in a browser.
- **macOS:** the npm `bui-runtime` (and the release build of the addon) failed to link with `Undefined symbols: ___isPlatformVersionAtLeast`: the
Cocoa host asked for ProMotion with `@available`, which needs a symbol from clang's runtime that a Rust binary linked with
`-nodefaultlibs` does not have. It asks by selector now.
- **Wayland:** a new window drew nothing until a later turn of the event loop, because the host did not wait for
the compositor's first configure. It waits now, as `GHOST_WindowWayland` does (`buipy_render` failed on
Wayland sessions).
- **Dear ImGui from Python:** an exception after `Begin()` in a frame callback aborted the process in builds with
asserts ("Missing End()"). The frame is unwound now and the exception reaches Python.
- Pies with more than 8 items dropped the rest; they now get Blender's "More" item.

## [0.5.0] - 2026-11-08

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ If you're starting fresh in Python, the Blender components are the friendliest.
- **Math in number fields**, with Blender's own expression evaluator: `2*pi`, `min(4, 3)`, `round(1.7)`, `x if c else y`.
- Ctrl+Wheel steps values, Ctrl+C / Ctrl+V copy values, Backspace resets.
- **Drag across checkboxes** to set them all.
- Press-drag-release menus, pie menus, and **Blender's fuzzy menu search**: "ad cu" finds "Add Cube", typos are forgiven, recent picks rank first.
- Press-drag-release menus, pie menus that pick on key release as in Blender (sub-pies, a "More" level, numpad directions, underlined letters), and **Blender's fuzzy menu search**: "ad cu" finds "Add Cube", typos are forgiven, recent picks rank first.
- **Ctrl+Z / Ctrl+Shift+Z** on every UI edit, and inside a text field while you type; Tab between fields.
- Blender's float display precision, multi-field vertical drags, and panels that collapse with Blender's animation.
- The HSV color wheel, color ramps, curves, trees, lists, text areas, canvases, a node editor and Blender's File Browser.
Expand Down
32 changes: 32 additions & 0 deletions THIRD_PARTY_NOTICES.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ and their licenses. It is generated by `tools/gen_notices.py`: do not edit it by
| NanoSVG, as edited by Blender | Rasterizing Blender's SVG icons (kit/extern/nanosvg) | zlib | https://github.com/memononen/nanosvg |
| Slug reference shaders | GPU glyph coverage (gpu/intern/gpu_gl.c, gpu_d3d11.c) | MIT | https://github.com/EricLengyel/Slug |
| Tailwind CSS v4 theme values | The default theme behind the Tailwind support (blenderui-tailwind) | MIT | https://tailwindcss.com |
| wlr-layer-shell-unstable-v1 (version 5) | Layer-shell windows on Wayland (kit/extern/wayland_protocols) | MIT | https://gitlab.freedesktop.org/wlroots/wlr-protocols |
| Lua 5.4.7 | The Lua runtime embedded in bui-lua (bindings/lua, fetched from lua.org) | MIT | https://www.lua.org |
| linenoise 1.0 | REPL line editing (bindings/lua/extern/linenoise) | BSD-2-Clause | https://github.com/antirez/linenoise |

Expand Down Expand Up @@ -722,6 +723,37 @@ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
````

### wlr-layer-shell-unstable-v1 (version 5)

License: MIT

````text
SPDX-License-Identifier: MIT

Copyright © 2017 Drew DeVault

Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that copyright notice and this permission
notice appear in supporting documentation, and that the name of
the copyright holders not be used in advertising or publicity
pertaining to distribution of the software without specific,
written prior permission. The copyright holders make no
representations about the suitability of this software for any
purpose. It is provided "as is" without express or implied
warranty.

THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.
````

### Lua 5.4.7

License: MIT
Expand Down
1 change: 1 addition & 0 deletions bindings/imgui/c/cimgui_impl_bui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ CIMGUI_API bool cImGui_ImplBUI_Init(BKNode* node, cImGui_ImplBUI_FrameFn frame,
CIMGUI_API void cImGui_ImplBUI_Shutdown(void) { ImGui_ImplBUI_Shutdown(); }
CIMGUI_API BKNode* cImGui_ImplBUI_GetNode(void) { return reinterpret_cast<BKNode*>(ImGui_ImplBUI_GetNode()); }
CIMGUI_API void cImGui_ImplBUI_RequestFrames(int n) { ImGui_ImplBUI_RequestFrames(n); }
CIMGUI_API void cImGui_ImplBUI_AbandonFrame(void) { ImGui_ImplBUI_AbandonFrame(); }
CIMGUI_API void cImGui_ImplBUI_RequestFrameIn(int ms) { ImGui_ImplBUI_RequestFrameIn(ms); }
CIMGUI_API int cImGui_ImplBUI_FrameCount(void) { return ImGui_ImplBUI_FrameCount(); }

Expand Down
1 change: 1 addition & 0 deletions bindings/imgui/c/cimgui_impl_bui.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ CIMGUI_API bool cImGui_ImplBUI_Init(BKNode* node, cImGui_ImplBUI_FrameFn fram
CIMGUI_API void cImGui_ImplBUI_Shutdown(void);
CIMGUI_API BKNode* cImGui_ImplBUI_GetNode(void);
CIMGUI_API void cImGui_ImplBUI_RequestFrames(int n);
CIMGUI_API void cImGui_ImplBUI_AbandonFrame(void); /* a frame callback stopped on an error */
CIMGUI_API void cImGui_ImplBUI_RequestFrameIn(int ms);
CIMGUI_API int cImGui_ImplBUI_FrameCount(void);

Expand Down
16 changes: 16 additions & 0 deletions bindings/imgui/imgui_impl_bui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ struct ImGui_ImplBUI_Data
bool SuperDown = false;
char* ClipboardText = nullptr;
bool InFrame = false;
ImGuiErrorRecoveryState FrameState; // before the user's frame, for AbandonFrame
};

static double now_seconds()
Expand Down Expand Up @@ -520,6 +521,7 @@ static void Bui_Frame(void* data, BKNode* node)

bd->InFrame = true;
ImGui::NewFrame();
ImGui::ErrorRecoveryStoreState(&bd->FrameState);
if (bd->Frame)
bd->Frame(bd->User);
ImGui::Render();
Expand Down Expand Up @@ -676,6 +678,20 @@ bool ImGui_ImplBUI_Init(BKNode* node, ImGui_ImplBUI_FrameFn frame, void* user, c
return true;
}

void ImGui_ImplBUI_AbandonFrame()
{
// Dear ImGui's recovery for scripting languages: unwind to the state before the user's frame,
// without the assert (the caller reports the error)
ImGui_ImplBUI_Data* bd = GetBackendData();
if (bd == nullptr || !bd->InFrame)
return;
ImGuiIO& io = ImGui::GetIO();
const bool assert_on = io.ConfigErrorRecoveryEnableAssert;
io.ConfigErrorRecoveryEnableAssert = false;
ImGui::ErrorRecoveryTryToRecoverState(&bd->FrameState);
io.ConfigErrorRecoveryEnableAssert = assert_on;
}

void ImGui_ImplBUI_Shutdown()
{
ImGui_ImplBUI_Data* bd = GetBackendData();
Expand Down
3 changes: 3 additions & 0 deletions bindings/imgui/imgui_impl_bui.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ IMGUI_IMPL_API BKNode* ImGui_ImplBUI_GetNode();
// Ask for frames: e.g. after the application changed state shown by the UI. n frames
// back to back (paced to the display in a window), or one frame after `ms` milliseconds.
IMGUI_IMPL_API void ImGui_ImplBUI_RequestFrames(int n = 1);
// Call from a frame callback that stops early on an error (an exception in a scripting
// language): closes what the frame opened (Begin() without End() ...) so the frame can end.
IMGUI_IMPL_API void ImGui_ImplBUI_AbandonFrame();
IMGUI_IMPL_API void ImGui_ImplBUI_RequestFrameIn(int ms);
// Frames run since Init (tests, profiling) and whether the last frame changed the output.
IMGUI_IMPL_API int ImGui_ImplBUI_FrameCount();
Expand Down
36 changes: 20 additions & 16 deletions bindings/lua/src/bui_context.c
Original file line number Diff line number Diff line change
Expand Up @@ -380,10 +380,8 @@ static int l_ctx_close_popups(lua_State *L) {
return 0;
}

static int l_ctx_focus(lua_State *L) {
luabui_Context *cud = CHECK_CTX(L, 1);
if (!cud->ctx) return 0;
BKNode *n = BK_focus(cud->ctx);
/* Push the node's userdata (made on first use), or nothing for NULL. */
static int push_node(lua_State *L, BKNode *n) {
if (!n) return 0;
if (luabui_lookup_node(L, n)) return 1;
luabui_Node *ud = (luabui_Node *)lua_newuserdata(L, sizeof(luabui_Node));
Expand All @@ -396,20 +394,23 @@ static int l_ctx_focus(lua_State *L) {
return 1;
}

static int l_ctx_focus(lua_State *L) {
luabui_Context *cud = CHECK_CTX(L, 1);
if (!cud->ctx) return 0;
return push_node(L, BK_focus(cud->ctx));
}

static int l_ctx_hover(lua_State *L) {
luabui_Context *cud = CHECK_CTX(L, 1);
if (!cud->ctx) return 0;
BKNode *n = BK_hover(cud->ctx);
if (!n) return 0;
if (luabui_lookup_node(L, n)) return 1;
luabui_Node *ud = (luabui_Node *)lua_newuserdata(L, sizeof(luabui_Node));
ud->node = n;
luaL_getmetatable(L, LUABUI_NODE_MT);
lua_setmetatable(L, -2);
lua_newtable(L);
lua_setuservalue(L, -2);
luabui_map_node(L, n, -1);
return 1;
return push_node(L, BK_hover(cud->ctx));
}

static int l_ctx_hit(lua_State *L) {
luabui_Context *cud = CHECK_CTX(L, 1);
if (!cud->ctx) return 0;
return push_node(L, BK_hit_at(cud->ctx, (int)luaL_checkinteger(L, 2),
(int)luaL_checkinteger(L, 3)));
}

static int l_ctx_cursor(lua_State *L) {
Expand Down Expand Up @@ -591,7 +592,9 @@ static int l_ctx_open_pie(lua_State *L) {
BKMenuSpec *specs;
int n = luabui_build_menuspec(L, 2, &specs);
const char *title = luaL_optstring(L, 3, NULL);
if (specs) BK_open_pie(cud->ctx, specs, n, title);
int ax = (int)luaL_optinteger(L, 4, -100000);
int ay = (int)luaL_optinteger(L, 5, -100000);
if (specs) BK_open_pie(cud->ctx, specs, n, title, ax, ay);
return 0;
}

Expand Down Expand Up @@ -665,6 +668,7 @@ static const luaL_Reg ctx_methods[] = {
{"focus", l_ctx_focus},
{"focus_node", l_ctx_focus_node},
{"hover", l_ctx_hover},
{"hit", l_ctx_hit},
{"cursor", l_ctx_cursor},
{"set_pointer", l_ctx_set_pointer},
{"modal", l_ctx_modal},
Expand Down
8 changes: 7 additions & 1 deletion bindings/lua/tests/test_context.lua
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ ctx:open_pie({
{text="South", icon=1},
{text="East", icon=2},
{text="West", icon=3},
}, "Direction")
}, "Direction", 160, 100)

-- Close popups after open_menu/open_pie
ctx:close_popups()
Expand All @@ -235,6 +235,12 @@ for i = 1, 3 do
check(rh == 200, "render " .. i .. " height")
end

-- ── Hit ───────────────────────────────────────────────────────────────

local bx, by, bw, bh = btn:rect()
assert(ctx:hit(bx + bw // 2, by + bh // 2) == btn, "hit over the button")
assert(ctx:hit(-5, -5) == nil, "hit outside the window")

-- ── Context tostring ─────────────────────────────────────────────────

local s = tostring(ctx)
Expand Down
23 changes: 22 additions & 1 deletion bindings/node/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,26 @@ export interface WindowOptions {
height?: number
resizable?: boolean
gpu?: boolean
/** Per-pixel alpha: only the elements show (no frame on Windows). */
transparent?: boolean
/** Stay above other windows: Windows, macOS and X11. A Wayland toplevel cannot; use `layerShell`. */
alwaysOnTop?: boolean
/** `false`: no frame (Electron's `frame`). */
frame?: boolean
/** A wlr-layer-shell surface (Wayland compositors with layer shell: KDE Plasma, wlroots);
* a normal window elsewhere. */
layerShell?: LayerShellOptions
}

export interface LayerShellOptions {
/** Default `'overlay'`. */
layer?: 'background' | 'bottom' | 'top' | 'overlay'
/** Edges the surface sticks to; both edges of an axis fill it. */
anchor?: Array<'top' | 'bottom' | 'left' | 'right'>
/** Space the compositor keeps free for the surface (a panel), in pixels. */
exclusiveZone?: number
/** Default `'none'`. */
keyboard?: 'none' | 'exclusive' | 'on-demand'
}

export type EventType = 'click' | 'mousedown' | 'mouseup' | 'mousemove' | 'mouseenter' | 'mouseleave' |
Expand Down Expand Up @@ -199,7 +219,8 @@ export class Window {
screenshot (): Promise<{ width: number, height: number, data: Buffer }>
click (x: number, y: number): void
close (): void
on (event: 'close', listener: () => void): this
/** `focus` / `blur`: the window got or lost the keyboard focus. */
on (event: 'close' | 'focus' | 'blur', listener: () => void): this
}

export class App {
Expand Down
Loading
Loading