Skip to content
This repository was archived by the owner on Dec 3, 2025. It is now read-only.

Conversation

@franciscojma86
Copy link
Contributor

The embedder now provides an API to get the right DPI dynamically, solving crashes caused by unavailable libraries on older versions.

Also, listens to the WM_DPICHANGED message and resizes the window properly.

Fixes flutter/flutter#40855

Depends on flutter/engine#16313

Copy link
Collaborator

@stuartmorgan-g stuartmorgan-g left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just small things.

If you want to also fix up window_size to use the new functions instead of ShellScalingApi directly for window and monitor DPI in this PR, since it's very closely related, that would be great, but if not I can do it in a follow-up.

newWidth, newHeight, SWP_NOZORDER | SWP_NOACTIVATE);

return 0;
break;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't we want to indicate that we've handled the message?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The examples that I've seen still call the DefWindowProc. Is there a reason to stop the propagation?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The docs say "If an application processes this message, it should return zero." It may be that the default handler just doesn't do anything, but absent a specific reason (like, we figure out that the docs are not accurate in this regard) I'd rather we follow what the documentation says the expected contract is.

return 0;

case WM_DPICHANGED: {
// Resize the window only for toplevel windows which have a suggested
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what this comment means. Isn't this class always a top-level window?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, bad copy paste from the engine code.

// limitations under the License.

#include <flutter/flutter_view_controller.h>
#include <flutter_windows.h>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this cruft from an earlier iteration, or fixing a missing include?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cruft :)

case WM_DPICHANGED: {
// Resize the window only for toplevel windows which have a suggested
// size.
auto lprcNewScale = reinterpret_cast<RECT *>(lparam);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use style-compliant variable names, not Windows-style naming, per style guide.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Contributor

@clarkezone clarkezone left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module.
// Appended with FDE to differentiate from the win32 API.
bool FDEEnableNonClientDpiScaling(HWND hwnd) {
HMODULE user32_module_ = LoadLibraryA("User32.dll");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you clean this up somewhere aka release the HMODULE?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn't. Added a FreeLibrary call after using the method.

// Appended with FDE to differentiate from the win32 API.
void EnableFullDpiSupportIfAvailable(HWND hwnd) {
HMODULE user32_module_ = LoadLibraryA("User32.dll");
if (user32_module_) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be if (!user32_module_), no?

// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module.
// Appended with FDE to differentiate from the win32 API.
void EnableFullDpiSupportIfAvailable(HWND hwnd) {
HMODULE user32_module_ = LoadLibraryA("User32.dll");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove trailing _; it's not an ivar.

reinterpret_cast<EnableNonClientDpiScaling_ *>(
GetProcAddress(user32_module_, "EnableNonClientDpiScaling"));

FreeLibrary(user32_module_);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be after calling the function you looked up from the library?

#include <flutter/plugin_registrar_windows.h>
#include <flutter/standard_method_codec.h>
#include <flutter_windows.h>
#include <windows.h>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIRC having windows.h after VersionHelpers.h broke compilation, which is why they are a separate group. I think maybe putting a comment on the group will prevent the autoformatter from reordering it.

GetDpiForMonitor(monitor, MDT_EFFECTIVE_DPI, &dpi_x, &dpi_y);
double scale_factor = dpi_x / kBaseDpi;
// Send a nullptr since the top-level window hasn't been created. This will
// get the neares monitor's DPI.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

primary

But this isn't the right thing to call; we want the DPI for monitor, which is why I had you expose the other function too.

RECT frame;
GetWindowRect(window, &frame);
HMONITOR window_monitor = MonitorFromWindow(window, MONITOR_DEFAULTTOPRIMARY);
// TODO: Support fallback for systems older than Windows 10(1607).
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can remove the TODO now.

// Appended with FDE to differentiate from the win32 API.
void EnableFullDpiSupportIfAvailable(HWND hwnd) {
HMODULE user32_module_ = LoadLibraryA("User32.dll");
if (user32_module_) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remember to mirror all the same fixes here.

#include <flutter_windows.h>

#include "resource.h"
#include "shellscalingapi.h"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Presumably you also need to make a project change to stop linking directly to Shcore.lib?

@franciscojma86
Copy link
Contributor Author

Sorry for the sloppy patch, PTAL!

Copy link
Collaborator

@stuartmorgan-g stuartmorgan-g left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with nits. I think you'll get some collisions with my recent warnings cleanup changes, but I expect they'll all be easily resolvable. If anything seems non-obvious, let me know and I can re-review.

GetDpiForMonitor(monitor, MDT_EFFECTIVE_DPI, &dpi_x, &dpi_y);
double scale_factor = dpi_x / kBaseDpi;
INT dpi = FlutterDesktopGetDpiForMonitor(monitor);
double scale_factor = static_cast<double>(dpi) / kBaseDpi;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You shouldn't need the cast here; kBaseDpi is a double in this file. (We could do the same in the other file so we don't need to explicitly cast, but it's not a big deal either way.)

UINT dpi_x, dpi_y;
GetDpiForMonitor(monitor, MDT_EFFECTIVE_DPI, &dpi_x, &dpi_y);
double scale_factor = dpi_x / kBaseDpi;
INT dpi = FlutterDesktopGetDpiForMonitor(monitor);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The API returns a UINT, not INT.

@stuartmorgan-g
Copy link
Collaborator

See my comment here: 5b2af71#r37243493

There's nothing wrong with the CI.

@franciscojma86
Copy link
Contributor Author

Landing on red since the AppVeyor config has been removed and the build step seems to be an old artifact from the CI changes

@franciscojma86 franciscojma86 merged commit d25b181 into google:master Feb 13, 2020
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Aug 5, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Embedding doesn't run on Windows 7 and crashes with an unclear missing DLL message.

3 participants