Skip to content

Commit fc04bb6

Browse files
committed
Sync with core 144fca5: title-bar double-click preferences (#48)
FlutterDragToMoveArea performs the system title-bar double-click action.
1 parent 6357367 commit fc04bb6

17 files changed

Lines changed: 170 additions & 36 deletions

File tree

‎bindings/csharp/src/CNativeAPI/generated/Window.cs‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,10 @@ public static partial class Interop
179179
[return: MarshalAs(UnmanagedType.I1)]
180180
public static extern bool native_window_is_window_control_buttons_visible(ulong self);
181181

182+
[DllImport(Libraries.NativeApi, CallingConvention = CallingConvention.Cdecl)]
183+
[return: MarshalAs(UnmanagedType.I1)]
184+
public static extern bool native_window_perform_title_bar_double_click(ulong self);
185+
182186
[DllImport(Libraries.NativeApi, CallingConvention = CallingConvention.Cdecl)]
183187
[return: MarshalAs(UnmanagedType.I1)]
184188
public static extern bool native_window_reset_title_bar_colors(ulong self);

‎bindings/csharp/src/NativeAPI/Window.cs‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -830,6 +830,12 @@ public static bool IsSystemMenuSupported()
830830
return rawResult;
831831
}
832832

833+
public bool PerformTitleBarDoubleClick()
834+
{
835+
var rawResult = Interop.native_window_perform_title_bar_double_click(NativeHandle);
836+
return rawResult;
837+
}
838+
833839
public void StartDragging()
834840
{
835841
Interop.native_window_start_dragging(NativeHandle);

‎bindings/dart/cnativeapi/lib/src/bindings_generated.dart‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2680,6 +2680,9 @@ external void native_window_maximize(int window);
26802680
@ffi.Native<ffi.Void Function(native_window_t)>()
26812681
external void native_window_minimize(int window);
26822682

2683+
@ffi.Native<ffi.Bool Function(native_window_t)>()
2684+
external bool native_window_perform_title_bar_double_click(int window);
2685+
26832686
@ffi.Native<ffi.Bool Function(native_window_t)>()
26842687
external bool native_window_reset_title_bar_colors(int window);
26852688

‎bindings/dart/nativeapi/CHANGELOG.md‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
## 0.4.1
22

3+
* On macOS, empty backgrounds in a hidden window's original title-bar band
4+
perform the preferred double-click action automatically. Controls and custom
5+
mouse handlers keep their gestures. The native Fill action is requested when
6+
the OS provides it.
7+
8+
* Adds `Window.performTitleBarDoubleClick()` for custom title bars, respecting
9+
the macOS Maximize, Minimize and None preferences.
10+
311
* `Window.setIgnoreMouseEvents(ignore, forward)` now returns whether the native
412
policy was applied. Linux implements pass-through and restores input shapes;
513
macOS, Windows and X11 can forward hover movement while clicks pass through.

‎bindings/dart/nativeapi/lib/src/window.dart‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -768,6 +768,10 @@ class Window {
768768
return c.native_window_is_system_menu_supported();
769769
}
770770

771+
bool performTitleBarDoubleClick() {
772+
return c.native_window_perform_title_bar_double_click(nativeHandle);
773+
}
774+
771775
void startDragging() {
772776
c.native_window_start_dragging(nativeHandle);
773777
}

‎bindings/dart/nativeapi_flutter/CHANGELOG.md‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
## 0.4.1
22

3+
* `DragToMoveArea` follows the macOS title-bar double-click preference,
4+
including Minimize and None, through the native window action.
5+
36
* Requires nativeapi 0.4.1.
47
* `DragToMoveArea` opens the native system window menu on a secondary-button
58
press on Windows and supporting Linux window managers.

‎bindings/dart/nativeapi_flutter/lib/src/widgets/drag_to_move_area.dart‎

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ import 'package:nativeapi/nativeapi.dart'
1212
TextField,
1313
View;
1414

15-
/// A custom title-bar region that drags the window and toggles maximization
16-
/// on double tap. A secondary-button press opens the native system window menu
15+
/// A custom title-bar region that drags the window and performs the native
16+
/// title-bar double-click action, including the macOS user preference. A secondary-button press opens the native system window menu
1717
/// where supported (Windows, or a supporting Linux window manager).
1818
class DragToMoveArea extends StatelessWidget {
1919
const DragToMoveArea({super.key, required this.child, this.window});
@@ -36,13 +36,8 @@ class DragToMoveArea extends StatelessWidget {
3636
(window ?? WindowManager.instance.getCurrent())?.startDragging();
3737
},
3838
onDoubleTap: () {
39-
final target = window ?? WindowManager.instance.getCurrent();
40-
if (target == null) return;
41-
if (target.isMaximized) {
42-
target.unmaximize();
43-
} else {
44-
target.maximize();
45-
}
39+
(window ?? WindowManager.instance.getCurrent())
40+
?.performTitleBarDoubleClick();
4641
},
4742
child: child,
4843
);

‎bindings/dart/nativeapi_flutter/test/widgets/window_drag_areas_test.dart‎

Lines changed: 35 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ class _Window extends Window {
88

99
int dragCount = 0;
1010
final edges = <ResizeEdge>[];
11-
bool maximized = false;
11+
int doubleClickCount = 0;
12+
bool doubleClickAccepted = true;
1213
final systemMenuPositions = <Point>[];
1314

1415
@override
@@ -24,13 +25,17 @@ class _Window extends Window {
2425
void startResizing(ResizeEdge edge) => edges.add(edge);
2526

2627
@override
27-
bool get isMaximized => maximized;
28+
bool performTitleBarDoubleClick() {
29+
doubleClickCount++;
30+
return doubleClickAccepted;
31+
}
2832

2933
@override
30-
void maximize() => maximized = true;
34+
void maximize() => throw StateError('must delegate the platform preference');
3135

3236
@override
33-
void unmaximize() => maximized = false;
37+
void unmaximize() =>
38+
throw StateError('must delegate the platform preference');
3439
}
3540

3641
Widget _host(Widget child) => Directionality(
@@ -78,29 +83,33 @@ void main() {
7883
expect(window.systemMenuPositions, hasLength(1));
7984
},
8085
);
81-
testWidgets('move area drags and toggles maximization on double tap', (
82-
tester,
83-
) async {
84-
final window = _Window();
85-
await tester.pumpWidget(
86-
_host(
87-
DragToMoveArea(
88-
window: window,
89-
child: const SizedBox(width: 200, height: 100),
86+
testWidgets(
87+
'move area drags and delegates each double tap without a fallback',
88+
(tester) async {
89+
final window = _Window();
90+
await tester.pumpWidget(
91+
_host(
92+
DragToMoveArea(
93+
window: window,
94+
child: const SizedBox(width: 200, height: 100),
95+
),
9096
),
91-
),
92-
);
93-
final center = tester.getCenter(find.byType(DragToMoveArea));
94-
await _drag(tester, center);
95-
expect(window.dragCount, 1);
96-
for (final expected in [true, false]) {
97-
await tester.tapAt(center);
98-
await tester.pump(const Duration(milliseconds: 50));
99-
await tester.tapAt(center);
100-
await tester.pumpAndSettle();
101-
expect(window.maximized, expected);
102-
}
103-
});
97+
);
98+
final center = tester.getCenter(find.byType(DragToMoveArea));
99+
await _drag(tester, center);
100+
expect(window.dragCount, 1);
101+
for (final accepted in [true, false]) {
102+
window.doubleClickAccepted = accepted;
103+
final previous = window.doubleClickCount;
104+
await tester.tapAt(center);
105+
await tester.pump(const Duration(milliseconds: 50));
106+
await tester.tapAt(center);
107+
await tester.pumpAndSettle();
108+
expect(window.doubleClickCount, previous + 1);
109+
expect(tester.takeException(), isNull);
110+
}
111+
},
112+
);
104113

105114
testWidgets('all eight handles send the correct native resize edge', (
106115
tester,

‎bindings/js/lib/window.ts‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,10 @@ export class Window extends NativeObject {
478478
return native.native_window_is_system_menu_supported();
479479
}
480480

481+
performTitleBarDoubleClick(): boolean {
482+
return native.native_window_perform_title_bar_double_click(this.nativeHandle);
483+
}
484+
481485
startDragging(): void {
482486
native.native_window_start_dragging(this.nativeHandle);
483487
}

‎bindings/js/src/generated/window.cc‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1708,6 +1708,21 @@ napi_value Js_native_window_is_system_menu_supported(napi_env env, napi_callback
17081708
return Value::Bool(result).ToJs(env);
17091709
}
17101710

1711+
napi_value Js_native_window_perform_title_bar_double_click(napi_env env, napi_callback_info info) {
1712+
Args args(env, info);
1713+
if (!args.ok()) {
1714+
return nullptr;
1715+
}
1716+
Arena arena;
1717+
(void)arena;
1718+
uint64_t self = 0;
1719+
if (!GetHandle(env, args[0], &self)) {
1720+
return nullptr;
1721+
}
1722+
auto result = OnMainThread([&] { return native_window_perform_title_bar_double_click(self); });
1723+
return Value::Bool(result).ToJs(env);
1724+
}
1725+
17111726
napi_value Js_native_window_start_dragging(napi_env env, napi_callback_info info) {
17121727
Args args(env, info);
17131728
if (!args.ok()) {
@@ -1849,6 +1864,7 @@ void RegisterWindow(napi_env env, napi_value exports) {
18491864
Export(env, exports, "native_window_is_focusable", Js_native_window_is_focusable);
18501865
Export(env, exports, "native_window_show_system_menu", Js_native_window_show_system_menu);
18511866
Export(env, exports, "native_window_is_system_menu_supported", Js_native_window_is_system_menu_supported);
1867+
Export(env, exports, "native_window_perform_title_bar_double_click", Js_native_window_perform_title_bar_double_click);
18521868
Export(env, exports, "native_window_start_dragging", Js_native_window_start_dragging);
18531869
Export(env, exports, "native_window_start_resizing", Js_native_window_start_resizing);
18541870
}

0 commit comments

Comments
 (0)