88#include < dwmapi.h>
99
1010namespace {
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+ }
1331
1432// Returns the origin point that will center a window of size 'size' within the
1533// client area of the window identified by 'handle'.
@@ -19,7 +37,7 @@ auto calculateCenteredOrigin(flutter::Win32Window::Size size,
1937 POINT const target_point{frame.left , frame.top };
2038 auto * const monitor{
2139 MonitorFromPoint (target_point, MONITOR_DEFAULTTONEAREST)};
22- auto const dpr{FlutterDesktopGetDpiForMonitor (monitor) / base_dpi };
40+ auto const dpr{FlutterDesktopGetDpiForMonitor (monitor) / kBaseDpi };
2341 auto const centered_x{(frame.left + frame.right - size.width * dpr) / 2.0 };
2442 auto const centered_y{(frame.top + frame.bottom - size.height * dpr) / 2.0 };
2543 return {static_cast <unsigned int >(centered_x / dpr),
@@ -35,7 +53,7 @@ applyPositioner(flutter::FlutterWindowPositioner const& positioner,
3553 auto const & windows{flutter::FlutterWindowController::instance ().windows ()};
3654 auto const & parent_window{windows.at (parent_view_id)};
3755 auto const & parent_hwnd{parent_window->GetHandle ()};
38- auto const dpr{FlutterDesktopGetDpiForHWND (parent_hwnd) / base_dpi };
56+ auto const dpr{FlutterDesktopGetDpiForHWND (parent_hwnd) / kBaseDpi };
3957 auto const monitor_rect{[](HWND hwnd) -> RECT {
4058 auto * monitor{MonitorFromWindow (hwnd, MONITOR_DEFAULTTONEAREST)};
4159 MONITORINFO mi;
@@ -347,30 +365,9 @@ void handleCreateRegularWindow(
347365 static_cast <unsigned int >(*width),
348366 static_cast <unsigned int >(*height)};
349367
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 ()));
374371 } else {
375372 result->Error (" UNAVAILABLE" , " Can't create window." );
376373 }
@@ -388,6 +385,68 @@ void handleCreateRegularWindow(
388385 }
389386}
390387
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+
391450void handleCreatePopupWindow (flutter::MethodCall<> const & call,
392451 std::unique_ptr<flutter::MethodResult<>>& result) {
393452 auto const * const arguments{call.arguments ()};
@@ -540,18 +599,7 @@ void handleCreatePopupWindow(flutter::MethodCall<> const& call,
540599 if (auto const data{
541600 flutter::FlutterWindowController::instance ().createPopupWindow (
542601 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 ()));
555603 } else {
556604 result->Error (" UNAVAILABLE" , " Can't create window." );
557605 }
@@ -591,12 +639,14 @@ namespace flutter {
591639void FlutterWindowController::initializeChannel () {
592640 if (!channel_) {
593641 channel_ = std::make_unique<MethodChannel<>>(
594- engine_->messenger (), CHANNEL , &StandardMethodCodec::GetInstance ());
642+ engine_->messenger (), kChannel , &StandardMethodCodec::GetInstance ());
595643 channel_->SetMethodCallHandler (
596644 [this ](MethodCall<> const & call,
597645 std::unique_ptr<MethodResult<>> result) {
598646 if (call.method_name () == " createRegularWindow" ) {
599647 handleCreateRegularWindow (call, result);
648+ } else if (call.method_name () == " createDialogWindow" ) {
649+ handleCreateDialogWindow (call, result);
600650 } else if (call.method_name () == " createPopupWindow" ) {
601651 handleCreatePopupWindow (call, result);
602652 } else if (call.method_name () == " destroyWindow" ) {
@@ -614,22 +664,19 @@ void FlutterWindowController::setEngine(std::shared_ptr<FlutterEngine> engine) {
614664 initializeChannel ();
615665}
616666
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)
621669 -> std::optional<FlutterWindowCreationResult> {
622670 std::unique_lock lock (mutex_);
623671 if (!engine_) {
624- std::cerr << " Cannot create window without an engine.\n " ;
672+ std::cerr << " Cannot create regular window without an engine.\n " ;
625673 return std::nullopt ;
626674 }
627675 auto window{std::make_unique<FlutterWin32Window>(engine_)};
628676
629677 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 )) {
633680 return std::nullopt ;
634681 }
635682 lock.lock ();
@@ -657,32 +704,75 @@ auto FlutterWindowController::createRegularWindow(
657704 return result;
658705}
659706
660- auto FlutterWindowController::createPopupWindow (
707+ auto FlutterWindowController::createDialogWindow (
661708 std::wstring const & title,
662- Win32Window::Point const & origin,
663709 Win32Window::Size const & size,
710+ std::optional<Win32Window::Point> origin,
664711 std::optional<FlutterViewId> parent_view_id)
665712 -> std::optional<FlutterWindowCreationResult> {
666713 std::unique_lock lock (mutex_);
667714 if (!engine_) {
668- std::cerr << " Cannot create window without an engine.\n " ;
715+ std::cerr << " Cannot create dialog without an engine.\n " ;
669716 return std::nullopt ;
670717 }
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 " ;
673760 return std::nullopt ;
674761 }
675762
676763 auto * const parent_hwnd{parent_view_id && windows_.find (*parent_view_id) !=
677764 windows_.end ()
678765 ? windows_[*parent_view_id].get ()->GetHandle ()
679766 : nullptr };
767+ if (!parent_hwnd) {
768+ std::cerr << " Cannot create popup without a parent window.\n " ;
769+ return std::nullopt ;
770+ }
680771 auto window{std::make_unique<FlutterWin32Window>(engine_)};
681772
682773 lock.unlock ();
683- if (!window->Create (title, origin, size, FlutterWindowArchetype::popup,
774+ if (!window->Create (title, size, FlutterWindowArchetype::popup, origin ,
684775 parent_hwnd)) {
685- std::cerr << " Cannot create window due to a Win32 error.\n " ;
686776 return std::nullopt ;
687777 }
688778 lock.lock ();
@@ -808,7 +898,7 @@ FlutterWindowSize FlutterWindowController::getWindowSize(
808898 }
809899
810900 // Convert to logical coordinates
811- auto const dpr{FlutterDesktopGetDpiForHWND (hwnd) / base_dpi };
901+ auto const dpr{FlutterDesktopGetDpiForHWND (hwnd) / kBaseDpi };
812902 frame.left = static_cast <LONG>(frame.left / dpr);
813903 frame.top = static_cast <LONG>(frame.top / dpr);
814904 frame.right = static_cast <LONG>(frame.right / dpr);
0 commit comments