Skip to content

feat: add SetWillCloseHook to WindowManager - #51

Open
brennodewinter wants to merge 1 commit into
libnativeapi:mainfrom
brennodewinter:feat/window-will-close-hook
Open

feat: add SetWillCloseHook to WindowManager#51
brennodewinter wants to merge 1 commit into
libnativeapi:mainfrom
brennodewinter:feat/window-will-close-hook

Conversation

@brennodewinter

Copy link
Copy Markdown

Summary

Adds WindowWillCloseHook to WindowManager, following the exact same pattern as the existing WindowWillShowHook and WindowWillHideHook. This allows FFI consumers (notably Flutter apps via nativeapi-flutter) to intercept window close and decide whether to proceed — needed for "unsaved changes" dialogs before closing.

Changes per layer

  • window_manager.h: WindowWillCloseHook typedef, SetWillCloseHook, HasWillCloseHook, HandleWillClose, CallOriginalClose declarations.
  • macOS: swizzles performClose: on NSWindow (same pattern as makeKeyAndOrderFront: and orderOut:). CallOriginalClose calls the swizzled original.
  • Linux: adds a delete-event emission hook alongside show/hide. CallOriginalClose destroys the toplevel GtkWidget.
  • Windows: stores the hook; CallOriginalClose posts WM_CLOSE. Full WM_CLOSE interception (WH_CBT or window subclassing) is left as a follow-up — noted with a ponytail: comment naming the ceiling and upgrade path.
  • C API: native_window_manager_set_will_close_hook, has_will_close_hook, handle_will_close, call_original_close.
  • Tests: window_manager_hook_test — verifies set/clear, dispatch with correct ID, no-hook safety, and coexistence with show/hide hooks.

How the hook works

The pattern is identical to will-show/will-hide:

  1. Consumer calls SetWillCloseHook(callback) — platform installs swizzle/emission hook.
  2. When the user closes a window, the swizzled method calls HandleWillClose(id) and returns without calling the original.
  3. The hook decides: call CallOriginalClose(id) to proceed, or do nothing to prevent close.

Test plan

  • window_manager_hook_test — 4 tests, all pass on macOS
  • Full test suite: 6/6 tests pass on macOS
  • Build verified on macOS (CMake + make, 0 errors)
  • Build verified on Windows (CI)
  • Build verified on Linux (CI)

Use case

OciDeck (a LibreKAT presentation tool) needs setPreventClose to show an "unsaved changes" dialog before the window closes. The current workaround uses window_manager's setPreventClose, but OciDeck is migrating to nativeapi. This hook is the missing piece.

Adds a WindowWillCloseHook following the same pattern as the existing
WindowWillShowHook and WindowWillHideHook. This allows FFI consumers
(notably Flutter apps via nativeapi-flutter) to intercept window close
and decide whether to proceed — needed for "unsaved changes" dialogs.

Changes per layer:

- window_manager.h: WindowWillCloseHook typedef, SetWillCloseHook,
  HasWillCloseHook, HandleWillClose, CallOriginalClose declarations.
- macOS: swizzles performClose: on NSWindow (same pattern as
  makeKeyAndOrderFront: and orderOut:). CallOriginalClose calls the
  swizzled original.
- Linux: adds a delete-event emission hook alongside show/hide.
  CallOriginalClose destroys the toplevel GtkWidget.
- Windows: stores the hook; CallOriginalClose posts WM_CLOSE. Full
  WM_CLOSE interception (WH_CBT or window subclassing) is left as a
  follow-up — noted with a ponytail: comment.
- C API: native_window_manager_set_will_close_hook,
  has_will_close_hook, handle_will_close, call_original_close.
- Tests: window_manager_hook_test — verifies set/clear, dispatch,
  no-hook safety, and coexistence with show/hide hooks.

All 6 tests pass on macOS. Build verified on macOS (CMake + make).
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.

1 participant