8
8
#include < dwmapi.h>
9
9
10
10
namespace {
11
- auto * const CHANNEL{" flutter/windowing" };
12
- auto const base_dpi{96.0 };
11
+ auto const * const kChannel {" flutter/windowing" };
12
+ auto const kBaseDpi {static_cast <double >(USER_DEFAULT_SCREEN_DPI)};
13
+
14
+ // Encodes the attributes of a FlutterWindowCreationResult into an EncodableMap
15
+ // wrapped in an EncodableValue.
16
+ flutter::EncodableValue encodeWindowCreationResult (
17
+ flutter::FlutterWindowCreationResult const & result) {
18
+ return flutter::EncodableValue (flutter::EncodableMap{
19
+ {flutter::EncodableValue (" viewId" ),
20
+ flutter::EncodableValue (result.view_id )},
21
+ {flutter::EncodableValue (" parentViewId" ),
22
+ result.parent_id ? flutter::EncodableValue (*result.parent_id )
23
+ : flutter::EncodableValue ()},
24
+ {flutter::EncodableValue (" archetype" ),
25
+ flutter::EncodableValue (static_cast <int >(result.archetype ))},
26
+ {flutter::EncodableValue (" width" ),
27
+ flutter::EncodableValue (result.size .width )},
28
+ {flutter::EncodableValue (" height" ),
29
+ flutter::EncodableValue ((result.size .height ))}});
30
+ }
13
31
14
32
// Returns the origin point that will center a window of size 'size' within the
15
33
// client area of the window identified by 'handle'.
@@ -19,7 +37,7 @@ auto calculateCenteredOrigin(flutter::Win32Window::Size size,
19
37
POINT const target_point{frame.left , frame.top };
20
38
auto * const monitor{
21
39
MonitorFromPoint (target_point, MONITOR_DEFAULTTONEAREST)};
22
- auto const dpr{FlutterDesktopGetDpiForMonitor (monitor) / base_dpi };
40
+ auto const dpr{FlutterDesktopGetDpiForMonitor (monitor) / kBaseDpi };
23
41
auto const centered_x{(frame.left + frame.right - size.width * dpr) / 2.0 };
24
42
auto const centered_y{(frame.top + frame.bottom - size.height * dpr) / 2.0 };
25
43
return {static_cast <unsigned int >(centered_x / dpr),
@@ -35,7 +53,7 @@ applyPositioner(flutter::FlutterWindowPositioner const& positioner,
35
53
auto const & windows{flutter::FlutterWindowController::instance ().windows ()};
36
54
auto const & parent_window{windows.at (parent_view_id)};
37
55
auto const & parent_hwnd{parent_window->GetHandle ()};
38
- auto const dpr{FlutterDesktopGetDpiForHWND (parent_hwnd) / base_dpi };
56
+ auto const dpr{FlutterDesktopGetDpiForHWND (parent_hwnd) / kBaseDpi };
39
57
auto const monitor_rect{[](HWND hwnd) -> RECT {
40
58
auto * monitor{MonitorFromWindow (hwnd, MONITOR_DEFAULTTONEAREST)};
41
59
MONITORINFO mi;
@@ -347,30 +365,9 @@ void handleCreateRegularWindow(
347
365
static_cast <unsigned int >(*width),
348
366
static_cast <unsigned int >(*height)};
349
367
350
- // Window will be centered within the 'main window'
351
- auto const origin{[size]() -> flutter::Win32Window::Point {
352
- auto const & windows{
353
- flutter::FlutterWindowController::instance ().windows ()};
354
- return windows.find (0 ) != windows.end ()
355
- ? calculateCenteredOrigin (size, windows.at (0 )->GetHandle ())
356
- : flutter::Win32Window::Point {0 , 0 };
357
- }()};
358
-
359
- if (auto const data{
360
- flutter::FlutterWindowController::instance ()
361
- .createRegularWindow (L" regular" , origin, size)}) {
362
- result->Success (flutter::EncodableValue (flutter::EncodableMap{
363
- {flutter::EncodableValue (" viewId" ),
364
- flutter::EncodableValue (data->view_id )},
365
- {flutter::EncodableValue (" parentViewId" ),
366
- data->parent_id ? flutter::EncodableValue (*data->parent_id )
367
- : flutter::EncodableValue ()},
368
- {flutter::EncodableValue (" archetype" ),
369
- flutter::EncodableValue (static_cast <int >(data->archetype ))},
370
- {flutter::EncodableValue (" width" ),
371
- flutter::EncodableValue (data->size .width )},
372
- {flutter::EncodableValue (" height" ),
373
- flutter::EncodableValue ((data->size .height ))}}));
368
+ if (auto const data{flutter::FlutterWindowController::instance ()
369
+ .createRegularWindow (L" regular" , size)}) {
370
+ result->Success (encodeWindowCreationResult (data.value ()));
374
371
} else {
375
372
result->Error (" UNAVAILABLE" , " Can't create window." );
376
373
}
@@ -388,6 +385,68 @@ void handleCreateRegularWindow(
388
385
}
389
386
}
390
387
388
+ void handleCreateDialogWindow (
389
+ flutter::MethodCall<> const & call,
390
+ std::unique_ptr<flutter::MethodResult<>>& result) {
391
+ auto const * const arguments{call.arguments ()};
392
+ if (auto const * const map{std::get_if<flutter::EncodableMap>(arguments)}) {
393
+ auto const parent_it{map->find (flutter::EncodableValue (" parent" ))};
394
+ auto const size_it{map->find (flutter::EncodableValue (" size" ))};
395
+
396
+ if (parent_it != map->end () && size_it != map->end ()) {
397
+ auto const * const parent{std::get_if<int >(&parent_it->second )};
398
+ if (!parent) {
399
+ result->Error (" INVALID_VALUE" ,
400
+ " Value for 'parent' must be of type int." );
401
+ return ;
402
+ }
403
+
404
+ auto const * const size_list{
405
+ std::get_if<std::vector<flutter::EncodableValue>>(&size_it->second )};
406
+ if (size_list->size () != 2 ||
407
+ !std::holds_alternative<int >(size_list->at (0 )) ||
408
+ !std::holds_alternative<int >(size_list->at (1 ))) {
409
+ result->Error (" INVALID_VALUE" ,
410
+ " Values for 'size' must be of type int." );
411
+ return ;
412
+ }
413
+ auto const width{std::get<int >(size_list->at (0 ))};
414
+ auto const height{std::get<int >(size_list->at (1 ))};
415
+ flutter::Win32Window::Size const size{static_cast <unsigned int >(width),
416
+ static_cast <unsigned int >(height)};
417
+
418
+ auto const origin{
419
+ [&size, &parent]() -> std::optional<flutter::Win32Window::Point > {
420
+ if (parent) {
421
+ auto const & windows{
422
+ flutter::FlutterWindowController::instance ().windows ()};
423
+ if (windows.find (*parent) != windows.end ()) {
424
+ return calculateCenteredOrigin (
425
+ size, windows.at (*parent)->GetHandle ());
426
+ }
427
+ }
428
+ return std::nullopt;
429
+ }()};
430
+
431
+ if (auto const data{
432
+ flutter::FlutterWindowController::instance ().createDialogWindow (
433
+ L" dialog" , size, origin,
434
+ *parent >= 0 ? std::optional<flutter::FlutterViewId>{*parent}
435
+ : std::nullopt)}) {
436
+ result->Success (encodeWindowCreationResult (data.value ()));
437
+ } else {
438
+ result->Error (" UNAVAILABLE" , " Can't create window." );
439
+ }
440
+ } else {
441
+ result->Error (
442
+ " INVALID_VALUE" ,
443
+ " Map does not contain all required keys: {'parent', 'size'}." );
444
+ }
445
+ } else {
446
+ result->Error (" INVALID_VALUE" , " Value argument is not a map." );
447
+ }
448
+ }
449
+
391
450
void handleCreatePopupWindow (flutter::MethodCall<> const & call,
392
451
std::unique_ptr<flutter::MethodResult<>>& result) {
393
452
auto const * const arguments{call.arguments ()};
@@ -540,18 +599,7 @@ void handleCreatePopupWindow(flutter::MethodCall<> const& call,
540
599
if (auto const data{
541
600
flutter::FlutterWindowController::instance ().createPopupWindow (
542
601
L" popup" , origin, new_size, *parent)}) {
543
- result->Success (flutter::EncodableValue (flutter::EncodableMap{
544
- {flutter::EncodableValue (" viewId" ),
545
- flutter::EncodableValue (data->view_id )},
546
- {flutter::EncodableValue (" parentViewId" ),
547
- data->parent_id ? flutter::EncodableValue (*data->parent_id )
548
- : flutter::EncodableValue ()},
549
- {flutter::EncodableValue (" archetype" ),
550
- flutter::EncodableValue (static_cast <int >(data->archetype ))},
551
- {flutter::EncodableValue (" width" ),
552
- flutter::EncodableValue (data->size .width )},
553
- {flutter::EncodableValue (" height" ),
554
- flutter::EncodableValue ((data->size .height ))}}));
602
+ result->Success (encodeWindowCreationResult (data.value ()));
555
603
} else {
556
604
result->Error (" UNAVAILABLE" , " Can't create window." );
557
605
}
@@ -591,12 +639,14 @@ namespace flutter {
591
639
void FlutterWindowController::initializeChannel () {
592
640
if (!channel_) {
593
641
channel_ = std::make_unique<MethodChannel<>>(
594
- engine_->messenger (), CHANNEL , &StandardMethodCodec::GetInstance ());
642
+ engine_->messenger (), kChannel , &StandardMethodCodec::GetInstance ());
595
643
channel_->SetMethodCallHandler (
596
644
[this ](MethodCall<> const & call,
597
645
std::unique_ptr<MethodResult<>> result) {
598
646
if (call.method_name () == " createRegularWindow" ) {
599
647
handleCreateRegularWindow (call, result);
648
+ } else if (call.method_name () == " createDialogWindow" ) {
649
+ handleCreateDialogWindow (call, result);
600
650
} else if (call.method_name () == " createPopupWindow" ) {
601
651
handleCreatePopupWindow (call, result);
602
652
} else if (call.method_name () == " destroyWindow" ) {
@@ -614,22 +664,19 @@ void FlutterWindowController::setEngine(std::shared_ptr<FlutterEngine> engine) {
614
664
initializeChannel ();
615
665
}
616
666
617
- auto FlutterWindowController::createRegularWindow (
618
- std::wstring const & title,
619
- Win32Window::Point const & origin,
620
- Win32Window::Size const & size)
667
+ auto FlutterWindowController::createRegularWindow (std::wstring const & title,
668
+ Win32Window::Size const & size)
621
669
-> std::optional<FlutterWindowCreationResult> {
622
670
std::unique_lock lock (mutex_);
623
671
if (!engine_) {
624
- std::cerr << " Cannot create window without an engine.\n " ;
672
+ std::cerr << " Cannot create regular window without an engine.\n " ;
625
673
return std::nullopt;
626
674
}
627
675
auto window{std::make_unique<FlutterWin32Window>(engine_)};
628
676
629
677
lock.unlock ();
630
- if (!window->Create (title, origin, size, FlutterWindowArchetype::regular,
631
- nullptr )) {
632
- std::cerr << " Cannot create window due to a Win32 error.\n " ;
678
+ if (!window->Create (title, size, FlutterWindowArchetype::regular,
679
+ std::nullopt, std::nullopt)) {
633
680
return std::nullopt;
634
681
}
635
682
lock.lock ();
@@ -657,32 +704,75 @@ auto FlutterWindowController::createRegularWindow(
657
704
return result;
658
705
}
659
706
660
- auto FlutterWindowController::createPopupWindow (
707
+ auto FlutterWindowController::createDialogWindow (
661
708
std::wstring const & title,
662
- Win32Window::Point const & origin,
663
709
Win32Window::Size const & size,
710
+ std::optional<Win32Window::Point > origin,
664
711
std::optional<FlutterViewId> parent_view_id)
665
712
-> std::optional<FlutterWindowCreationResult> {
666
713
std::unique_lock lock (mutex_);
667
714
if (!engine_) {
668
- std::cerr << " Cannot create window without an engine.\n " ;
715
+ std::cerr << " Cannot create dialog without an engine.\n " ;
669
716
return std::nullopt;
670
717
}
671
- if (windows_.empty ()) {
672
- std::cerr << " Cannot create this window as the first window.\n " ;
718
+
719
+ std::optional<HWND> const parent_hwnd{
720
+ parent_view_id && windows_.find (*parent_view_id) != windows_.end ()
721
+ ? std::optional<HWND>{windows_[*parent_view_id].get ()->GetHandle ()}
722
+ : std::nullopt};
723
+ auto window{std::make_unique<FlutterWin32Window>(engine_)};
724
+
725
+ lock.unlock ();
726
+ if (!window->Create (title, size, FlutterWindowArchetype::dialog, origin,
727
+ parent_hwnd)) {
728
+ return std::nullopt;
729
+ }
730
+ lock.lock ();
731
+
732
+ auto const view_id{window->flutter_controller ()->view_id ()};
733
+ windows_[view_id] = std::move (window);
734
+
735
+ cleanupClosedWindows ();
736
+ sendOnWindowCreated (FlutterWindowArchetype::dialog, view_id, parent_view_id);
737
+
738
+ FlutterWindowCreationResult result{
739
+ .view_id = view_id,
740
+ .parent_id = parent_view_id,
741
+ .archetype = FlutterWindowArchetype::dialog,
742
+ .size = getWindowSize (view_id)};
743
+
744
+ lock.unlock ();
745
+
746
+ sendOnWindowResized (view_id);
747
+
748
+ return result;
749
+ }
750
+
751
+ auto FlutterWindowController::createPopupWindow (
752
+ std::wstring const & title,
753
+ Win32Window::Point const & origin,
754
+ Win32Window::Size const & size,
755
+ std::optional<FlutterViewId> parent_view_id)
756
+ -> std::optional<FlutterWindowCreationResult> {
757
+ std::unique_lock lock (mutex_);
758
+ if (!engine_) {
759
+ std::cerr << " Cannot create popup without an engine.\n " ;
673
760
return std::nullopt;
674
761
}
675
762
676
763
auto * const parent_hwnd{parent_view_id && windows_.find (*parent_view_id) !=
677
764
windows_.end ()
678
765
? windows_[*parent_view_id].get ()->GetHandle ()
679
766
: nullptr };
767
+ if (!parent_hwnd) {
768
+ std::cerr << " Cannot create popup without a parent window.\n " ;
769
+ return std::nullopt;
770
+ }
680
771
auto window{std::make_unique<FlutterWin32Window>(engine_)};
681
772
682
773
lock.unlock ();
683
- if (!window->Create (title, origin, size, FlutterWindowArchetype::popup,
774
+ if (!window->Create (title, size, FlutterWindowArchetype::popup, origin ,
684
775
parent_hwnd)) {
685
- std::cerr << " Cannot create window due to a Win32 error.\n " ;
686
776
return std::nullopt;
687
777
}
688
778
lock.lock ();
@@ -808,7 +898,7 @@ FlutterWindowSize FlutterWindowController::getWindowSize(
808
898
}
809
899
810
900
// Convert to logical coordinates
811
- auto const dpr{FlutterDesktopGetDpiForHWND (hwnd) / base_dpi };
901
+ auto const dpr{FlutterDesktopGetDpiForHWND (hwnd) / kBaseDpi };
812
902
frame.left = static_cast <LONG>(frame.left / dpr);
813
903
frame.top = static_cast <LONG>(frame.top / dpr);
814
904
frame.right = static_cast <LONG>(frame.right / dpr);
0 commit comments