Skip to content

Commit

Permalink
Merge pull request flutter#4 from canonical/multi-window-fix
Browse files Browse the repository at this point in the history
bugfix: making the engine code work
  • Loading branch information
mattkae authored Jul 26, 2024
2 parents 59c26e9 + 17e7f5a commit 6b02329
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 33 deletions.
94 changes: 67 additions & 27 deletions shell/platform/windows/client_wrapper/flutter_window_controller.cc
Original file line number Diff line number Diff line change
Expand Up @@ -356,10 +356,21 @@ void handleCreateRegularWindow(
: flutter::Win32Window::Point{0, 0};
}()};

if (auto const view_id{
if (auto const data{
flutter::FlutterWindowController::instance()
.createRegularWindow(L"regular", origin, size)}) {
result->Success(flutter::EncodableValue(*view_id));
result->Success(flutter::EncodableValue(flutter::EncodableMap{
{flutter::EncodableValue("viewId"),
flutter::EncodableValue(data->view_id)},
{flutter::EncodableValue("parentViewId"),
data->parent_id ? flutter::EncodableValue(*data->parent_id)
: flutter::EncodableValue()},
{flutter::EncodableValue("archetype"),
flutter::EncodableValue(static_cast<int>(data->archetype))},
{flutter::EncodableValue("width"),
flutter::EncodableValue(data->size.width)},
{flutter::EncodableValue("height"),
flutter::EncodableValue((data->size.height))}}));
} else {
result->Error("UNAVAILABLE", "Can't create window.");
}
Expand Down Expand Up @@ -526,10 +537,21 @@ void handleCreatePopupWindow(flutter::MethodCall<> const& call,
auto const& [origin,
new_size]{applyPositioner(positioner, size, *parent)};

if (auto const view_id{
if (auto const data{
flutter::FlutterWindowController::instance().createPopupWindow(
L"popup", origin, new_size, *parent)}) {
result->Success(flutter::EncodableValue(*view_id));
result->Success(flutter::EncodableValue(flutter::EncodableMap{
{flutter::EncodableValue("viewId"),
flutter::EncodableValue(data->view_id)},
{flutter::EncodableValue("parentViewId"),
data->parent_id ? flutter::EncodableValue(*data->parent_id)
: flutter::EncodableValue()},
{flutter::EncodableValue("archetype"),
flutter::EncodableValue(static_cast<int>(data->archetype))},
{flutter::EncodableValue("width"),
flutter::EncodableValue(data->size.width)},
{flutter::EncodableValue("height"),
flutter::EncodableValue((data->size.height))}}));
} else {
result->Error("UNAVAILABLE", "Can't create window.");
}
Expand Down Expand Up @@ -597,12 +619,14 @@ void FlutterWindowController::initializeChannel() {
void FlutterWindowController::setEngine(std::shared_ptr<FlutterEngine> engine) {
std::lock_guard<std::mutex> const lock(mutex_);
engine_ = std::move(engine);
initializeChannel();
}

auto FlutterWindowController::createRegularWindow(
std::wstring const& title,
Win32Window::Point const& origin,
Win32Window::Size const& size) -> std::optional<FlutterViewId> {
Win32Window::Size const& size)
-> std::optional<FlutterWindowCreationResult> {
std::unique_lock lock(mutex_);
if (!engine_) {
std::cerr << "Cannot create window without an engine.\n";
Expand Down Expand Up @@ -631,17 +655,22 @@ auto FlutterWindowController::createRegularWindow(
sendOnWindowCreated(FlutterWindowArchetype::regular, view_id, std::nullopt);

lock.unlock();

FlutterWindowCreationResult result;
result.view_id = view_id;
result.archetype = FlutterWindowArchetype::regular;
result.size = getWindowSize(view_id);
sendOnWindowResized(view_id);

return view_id;
return result;
}

auto FlutterWindowController::createPopupWindow(
std::wstring const& title,
Win32Window::Point const& origin,
Win32Window::Size const& size,
std::optional<FlutterViewId> parent_view_id)
-> std::optional<FlutterViewId> {
-> std::optional<FlutterWindowCreationResult> {
std::unique_lock lock(mutex_);
if (!engine_) {
std::cerr << "Cannot create window without an engine.\n";
Expand Down Expand Up @@ -675,9 +704,15 @@ auto FlutterWindowController::createPopupWindow(
parent_view_id ? *parent_view_id : -1);

lock.unlock();

FlutterWindowCreationResult result;
result.view_id = view_id;
result.archetype = FlutterWindowArchetype::popup;
result.parent_id = parent_view_id;
result.size = getWindowSize(view_id);
sendOnWindowResized(view_id);

return view_id;
return result;
}

auto FlutterWindowController::destroyWindow(FlutterViewId view_id,
Expand Down Expand Up @@ -763,30 +798,35 @@ void FlutterWindowController::sendOnWindowDestroyed(
void FlutterWindowController::sendOnWindowResized(FlutterViewId view_id) const {
std::lock_guard const lock(mutex_);
if (channel_) {
auto* const hwnd{windows_.at(view_id)->GetHandle()};
RECT frame;
if (FAILED(DwmGetWindowAttribute(hwnd, DWMWA_EXTENDED_FRAME_BOUNDS, &frame,
sizeof(frame)))) {
GetWindowRect(hwnd, &frame);
}

// Convert to logical coordinates
auto const dpr{FlutterDesktopGetDpiForHWND(hwnd) / base_dpi};
frame.left = static_cast<LONG>(frame.left / dpr);
frame.top = static_cast<LONG>(frame.top / dpr);
frame.right = static_cast<LONG>(frame.right / dpr);
frame.bottom = static_cast<LONG>(frame.bottom / dpr);

auto const width{frame.right - frame.left};
auto const height{frame.bottom - frame.top};
auto size = getWindowSize(view_id);
channel_->InvokeMethod(
"onWindowResized",
std::make_unique<EncodableValue>(EncodableMap{
{EncodableValue("viewId"), EncodableValue(view_id)},
{EncodableValue("width"), EncodableValue(static_cast<int>(width))},
{EncodableValue("height"),
EncodableValue(static_cast<int>(height))}}));
{EncodableValue("width"), EncodableValue(size.width)},
{EncodableValue("height"), EncodableValue(size.height)}}));
}
}

FlutterWindowSize FlutterWindowController::getWindowSize(
flutter::FlutterViewId view_id) const {
auto* const hwnd{windows_.at(view_id)->GetHandle()};
RECT frame;
if (FAILED(DwmGetWindowAttribute(hwnd, DWMWA_EXTENDED_FRAME_BOUNDS, &frame,
sizeof(frame)))) {
GetWindowRect(hwnd, &frame);
}

// Convert to logical coordinates
auto const dpr{FlutterDesktopGetDpiForHWND(hwnd) / base_dpi};
frame.left = static_cast<LONG>(frame.left / dpr);
frame.top = static_cast<LONG>(frame.top / dpr);
frame.right = static_cast<LONG>(frame.right / dpr);
frame.bottom = static_cast<LONG>(frame.bottom / dpr);

auto const width{frame.right - frame.left};
auto const height{frame.bottom - frame.top};
return {static_cast<int>(width), static_cast<int>(height)};
}

} // namespace flutter
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,18 @@

namespace flutter {

struct FlutterWindowSize {
int width = 0;
int height = 0;
};

struct FlutterWindowCreationResult {
FlutterViewId view_id;
std::optional<FlutterViewId> parent_id = std::nullopt;
FlutterWindowArchetype archetype;
FlutterWindowSize size;
};

// A singleton controller for Flutter windows.
class FlutterWindowController {
public:
Expand All @@ -35,12 +47,13 @@ class FlutterWindowController {
auto createRegularWindow(std::wstring const& title,
Win32Window::Point const& origin,
Win32Window::Size const& size)
-> std::optional<FlutterViewId>;
auto createPopupWindow(std::wstring const& title,
Win32Window::Point const& origin,
Win32Window::Size const& size,
std::optional<FlutterViewId> parent_view_id =
std::nullopt) -> std::optional<FlutterViewId>;
-> std::optional<FlutterWindowCreationResult>;
auto createPopupWindow(
std::wstring const& title,
Win32Window::Point const& origin,
Win32Window::Size const& size,
std::optional<FlutterViewId> parent_view_id = std::nullopt)
-> std::optional<FlutterWindowCreationResult>;
auto destroyWindow(FlutterViewId view_id, bool destroy_native_window) -> bool;
auto windows() const -> ViewWindowMap const&;
auto channel() const -> std::unique_ptr<MethodChannel<>> const&;
Expand All @@ -57,6 +70,7 @@ class FlutterWindowController {
void sendOnWindowDestroyed(FlutterViewId view_id) const;
void sendOnWindowResized(FlutterViewId view_id) const;
void cleanupClosedWindows();
FlutterWindowSize getWindowSize(flutter::FlutterViewId view_id) const;

mutable std::mutex mutex_;
std::unique_ptr<MethodChannel<>> channel_;
Expand Down

0 comments on commit 6b02329

Please sign in to comment.