Skip to content

Commit d72f437

Browse files
committed
[win]frameless window'height can be sized under 38px
relate to nwjs#419
1 parent 12fb385 commit d72f437

File tree

2 files changed

+82
-0
lines changed

2 files changed

+82
-0
lines changed

src/browser/native_window_win.cc

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
#include "base/utf_string_conversions.h"
2424
#include "base/values.h"
25+
#include "base/logging.h"
2526
#include "base/win/wrapped_window_proc.h"
2627
#include "chrome/browser/platform_util.h"
2728
#include "chrome/common/extensions/draggable_region.h"
@@ -317,7 +318,79 @@ bool NativeWindowWin::IsFullscreen() {
317318
return is_fullscreen_;
318319
}
319320

321+
void NativeWindowWin::UpdateWindowAttribute(int attribute_index,
322+
int attribute_value_to_set,
323+
int attribute_value_to_reset,
324+
bool update_frame) {
325+
HWND native_window = window_->GetNativeWindow();
326+
int value = ::GetWindowLong(native_window, attribute_index);
327+
int expected_value = value;
328+
if (attribute_value_to_set)
329+
expected_value |= attribute_value_to_set;
330+
if (attribute_value_to_reset)
331+
expected_value &= ~attribute_value_to_reset;
332+
if (value != expected_value)
333+
::SetWindowLong(native_window, attribute_index, expected_value);
334+
335+
// Per MSDN, if any of the frame styles is changed, SetWindowPos with the
336+
// SWP_FRAMECHANGED flag must be called in order for the cached window data
337+
// to be updated properly.
338+
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms633591(v=vs.85).aspx
339+
if (update_frame) {
340+
::SetWindowPos(native_window, NULL, 0, 0, 0, 0,
341+
SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE |
342+
SWP_NOZORDER | SWP_NOACTIVATE);
343+
}
344+
}
345+
320346
void NativeWindowWin::SetSize(const gfx::Size& size) {
347+
348+
349+
if (!this->has_frame()) {
350+
// An overlapped window is a top-level window that has a titlebar, border,
351+
// and client area. The Windows system will automatically put the shadow
352+
// around the whole window. Also the system will enforce the minimum height
353+
// (38 pixels based on observation) for the overlapped window such that it
354+
// will always has the space for the titlebar.
355+
//
356+
// On contrast, a popup window is a bare minimum window without border and
357+
// titlebar by default. It is often used for the popup menu and the window
358+
// with short life. The Windows system does not add the shadow around the
359+
// whole window though CS_DROPSHADOW class style could be passed to add the
360+
// drop shadow which is only around the right and bottom edges.
361+
//
362+
// The height of the title-only or minimized panel is smaller than the minimum
363+
// overlapped window height. If the panel still uses the overlapped window
364+
// style, Windows system will automatically increase the window height. To
365+
// work around this limitation, we temporarily change the window style to
366+
// popup when the height to set is smaller than the minimum overlapped window
367+
// height and then restore the window style to overlapped when the height
368+
// grows.
369+
370+
static const int kMinimumOverlappedWindowHeight = 38;
371+
gfx::Rect old_bounds = GetWidget()->GetRestoredBounds();
372+
gfx::Rect new_bounds(size);
373+
if (old_bounds.height() > kMinimumOverlappedWindowHeight &&
374+
new_bounds.height() <= kMinimumOverlappedWindowHeight) {
375+
// When the panel height shrinks below the minimum overlapped window height,
376+
// change the window style to popup such that we can show the title-only
377+
// and minimized panel without additional height being added by the system.
378+
UpdateWindowAttribute(GWL_STYLE,
379+
WS_POPUP,
380+
WS_OVERLAPPED | WS_THICKFRAME | WS_SYSMENU,
381+
true);
382+
} else if (old_bounds.height() <= kMinimumOverlappedWindowHeight &&
383+
new_bounds.height() > kMinimumOverlappedWindowHeight) {
384+
// Change the window style back to overlappped when the panel height grow
385+
// taller than the minimum overlapped window height.
386+
UpdateWindowAttribute(GWL_STYLE,
387+
WS_OVERLAPPED | WS_THICKFRAME | WS_SYSMENU,
388+
WS_POPUP,
389+
true);
390+
}
391+
392+
}
393+
321394
window_->SetSize(size);
322395
}
323396

src/browser/native_window_win.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,15 @@ class NativeWindowWin : public NativeWindow,
125125
private:
126126
void OnViewWasResized();
127127

128+
129+
// Sets |attribute_value_to_set| and/or clears |attribute_value_to_reset| for
130+
// the attibute denoted by |attribute_index|. This is used to update the style
131+
// or extended style for the native window.
132+
void UpdateWindowAttribute(int attribute_index,
133+
int attribute_value_to_set,
134+
int attribute_value_to_reset,
135+
bool update_frame);
136+
128137
NativeWindowToolbarWin* toolbar_;
129138
views::WebView* web_view_;
130139
views::Widget* window_;

0 commit comments

Comments
 (0)