Skip to content

Commit

Permalink
Merge pull request #110 from damywise/patch-5
Browse files Browse the repository at this point in the history
[Windows] Remove unnecessary code, implement hasShadow and setHasShadow in frameless mode
  • Loading branch information
lijy91 authored Mar 31, 2022
2 parents 5520f43 + f6c35b7 commit 875a617
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 56 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -653,14 +653,14 @@ Makes the window not show in the taskbar / dock.
Sets progress value in progress bar. Valid range is [0, 1.0].


##### hasShadow `macos`
##### hasShadow `macos` `windows`

Returns `bool` - Whether the window has a shadow.
Returns `bool` - Whether the window has a shadow. On Windows, always returns true unless window is frameless.


##### setHasShadow `macos`
##### setHasShadow `macos` `windows`

Sets whether the window should have a shadow.
Sets whether the window should have a shadow. On Windows, doesn't do anything unless window is frameless.


##### getOpacity `macos` `windows`
Expand Down
8 changes: 4 additions & 4 deletions lib/src/window_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -531,16 +531,16 @@ class WindowManager {
await _channel.invokeMethod('setProgressBar', arguments);
}

/// Returns `bool` - Whether the window has a shadow.
/// Returns `bool` - Whether the window has a shadow. On Windows, always returns true unless window is frameless.
///
/// @platforms macos
/// @platforms macos,windows
Future<bool> hasShadow() async {
return await _channel.invokeMethod('hasShadow');
}

/// Sets whether the window should have a shadow.
/// Sets whether the window should have a shadow. On Windows, doesn't do anything unless window is frameless.
///
/// @platforms macos
/// @platforms macos,windows
Future<void> setHasShadow(bool hasShadow) async {
final Map<String, dynamic> arguments = {
'hasShadow': hasShadow,
Expand Down
57 changes: 22 additions & 35 deletions windows/window_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class WindowManager {

int last_state = STATE_NORMAL;

bool has_shadow_ = false;
bool is_frameless_ = false;
bool is_prevent_close_ = false;
double aspect_ratio_ = 0;
Expand Down Expand Up @@ -127,28 +128,12 @@ void WindowManager::SetAsFrameless() {
HWND hWnd = GetMainWindow();

RECT rect;
MARGINS margins = {0, 0, 0, 0};

GetWindowRect(hWnd, &rect);
SetWindowLong(hWnd, GWL_STYLE,
WS_POPUP | WS_THICKFRAME | WS_CAPTION | WS_SYSMENU |
WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_VISIBLE);
DwmExtendFrameIntoClientArea(hWnd, &margins);
SetWindowPos(hWnd, nullptr, rect.left, rect.top, rect.right - rect.left,
rect.bottom - rect.top,
SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_NOSIZE |
SWP_FRAMECHANGED);

flutter::EncodableMap args = flutter::EncodableMap();
args[flutter::EncodableValue("backgroundColorA")] =
flutter::EncodableValue(0);
args[flutter::EncodableValue("backgroundColorR")] =
flutter::EncodableValue(0);
args[flutter::EncodableValue("backgroundColorG")] =
flutter::EncodableValue(0);
args[flutter::EncodableValue("backgroundColorB")] =
flutter::EncodableValue(0);
SetBackgroundColor(args);
}

void WindowManager::WaitUntilReadyToShow() {
Expand Down Expand Up @@ -569,31 +554,15 @@ void WindowManager::SetTitle(const flutter::EncodableMap& args) {
void WindowManager::SetTitleBarStyle(const flutter::EncodableMap& args) {
title_bar_style_ =
std::get<std::string>(args.at(flutter::EncodableValue("titleBarStyle")));

HWND hWnd = GetMainWindow();
DWORD gwlStyle = GetWindowLong(hWnd, GWL_STYLE);
// Enables the ability to go from setAsFrameless() to
// TitleBarStyle.normal/hidden
is_frameless_ = false;
if (title_bar_style_ == "hidden") {
gwlStyle = WS_POPUP | WS_THICKFRAME | WS_CAPTION | WS_SYSMENU |
WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_VISIBLE;
SetWindowLong(hWnd, GWL_STYLE, gwlStyle);
BOOL composition_enabled = FALSE;
bool success = DwmIsCompositionEnabled(&composition_enabled) == S_OK;
if (composition_enabled && success) {
static const MARGINS shadow_state[2]{{0, 0, 0, 0}, {1, 1, 1, 1}};
DwmExtendFrameIntoClientArea(hWnd, &shadow_state[0]);
ShowWindow(hWnd, SW_SHOW);
}
} else {
gwlStyle = WS_OVERLAPPEDWINDOW | WS_THICKFRAME | WS_CAPTION | WS_SYSMENU |
WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_VISIBLE;
SetWindowLong(hWnd, GWL_STYLE, gwlStyle);
}

MARGINS margins = {0, 0, 0, 0};
HWND hWnd = GetMainWindow();
RECT rect;
GetWindowRect(hWnd, &rect);
DwmExtendFrameIntoClientArea(hWnd, &margins);
SetWindowPos(hWnd, nullptr, rect.left, rect.top, 0, 0,
SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_NOSIZE |
SWP_FRAMECHANGED);
Expand Down Expand Up @@ -653,6 +622,24 @@ void WindowManager::SetProgressBar(const flutter::EncodableMap& args) {
}
}

bool WindowManager::HasShadow() {
if (is_frameless_)
return has_shadow_;
return true;
}

void WindowManager::SetHasShadow(const flutter::EncodableMap& args) {
if (is_frameless_) {
has_shadow_ = std::get<bool>(args.at(flutter::EncodableValue("hasShadow")));

HWND hWnd = GetMainWindow();

MARGINS margins[2]{{0, 0, 0, 0}, {0, 0, 1, 0}};

DwmExtendFrameIntoClientArea(hWnd, &margins[has_shadow_]);
}
}

double WindowManager::GetOpacity() {
return opacity_;
}
Expand Down
37 changes: 24 additions & 13 deletions windows/window_manager_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,48 +109,51 @@ std::optional<LRESULT> WindowManagerPlugin::HandleWindowProc(HWND hWnd,
std::optional<LRESULT> result = std::nullopt;

if (message == WM_NCCALCSIZE) {
// This must always be first or else the one of other two ifs will execute
// when window is in full screen and we don't want that
if (wParam && window_manager->IsFullScreen()) {
NCCALCSIZE_PARAMS* sz = reinterpret_cast<NCCALCSIZE_PARAMS*>(lParam);
sz->rgrc[0].bottom -= 3;
return (WVR_HREDRAW | WVR_VREDRAW);
return 0;
}

// This must always be before handling title_bar_style_ == "hidden" so
// the if TitleBarStyle.hidden doesn't get executed.
if (wParam && window_manager->is_frameless_) {
SetWindowLong(hWnd, 0, 0);
NCCALCSIZE_PARAMS* sz = reinterpret_cast<NCCALCSIZE_PARAMS*>(lParam);
// Add borders when maximized so app doesn't get cut off.
if (window_manager->IsMaximized()) {
sz->rgrc[0].left += 8;
sz->rgrc[0].top += 8;
sz->rgrc[0].right -= 8;
sz->rgrc[0].bottom -= 9;
}
// This cuts the app at the bottom by one pixel but that's necessary to
// prevent jitter when resizing the app
sz->rgrc[0].bottom += 1;
return (WVR_HREDRAW | WVR_VREDRAW);
return 0;
}

// This must always be last.
if (wParam && window_manager->title_bar_style_ == "hidden") {
WINDOWPLACEMENT wPos;
wPos.length = sizeof(wPos);
GetWindowPlacement(hWnd, &wPos);
RECT borderThickness;
SetRectEmpty(&borderThickness);
AdjustWindowRectEx(&borderThickness,
GetWindowLongPtr(hWnd, GWL_STYLE) & WS_POPUP, FALSE,
NULL);
NCCALCSIZE_PARAMS* sz = reinterpret_cast<NCCALCSIZE_PARAMS*>(lParam);

// Add 8 pixel to the top border when maximized so the app isn't cut off
// Top resize border is still not working.
if (window_manager->IsMaximized()) {
sz->rgrc[0].top += 8;
} else {
// on windows 10, if set to 0, there's a white line at the top
// of the app and I've yet to find a way to remove that.
sz->rgrc[0].top += IsWindows11OrGreater() ? 0 : 1;
}
sz->rgrc[0].right -= 8;
sz->rgrc[0].bottom -= 8;
sz->rgrc[0].left -= -8;

return (WVR_HREDRAW | WVR_VREDRAW);
// Previously (WVR_HREDRAW | WVR_VREDRAW), but returning 0 or 1 doesn't
// actually break anything so I've set it to 0. Unless someone pointed a
// problem in the future.
return 0;
}
} else if (message == WM_NCHITTEST) {
if (!window_manager->is_resizable_) {
Expand Down Expand Up @@ -458,6 +461,14 @@ void WindowManagerPlugin::HandleMethodCall(
std::get<flutter::EncodableMap>(*method_call.arguments());
window_manager->SetProgressBar(args);
result->Success(flutter::EncodableValue(true));
} else if (method_name.compare("hasShadow") == 0) {
bool value = window_manager->HasShadow();
result->Success(flutter::EncodableValue(value));
} else if (method_name.compare("setHasShadow") == 0) {
const flutter::EncodableMap& args =
std::get<flutter::EncodableMap>(*method_call.arguments());
window_manager->SetHasShadow(args);
result->Success(flutter::EncodableValue(true));
} else if (method_name.compare("getOpacity") == 0) {
double value = window_manager->GetOpacity();
result->Success(flutter::EncodableValue(value));
Expand Down

0 comments on commit 875a617

Please sign in to comment.