| Index: views/window/window_win.cc
|
| diff --git a/views/window/window_win.cc b/views/window/window_win.cc
|
| index dff452707aa6c225ae0e3afe1419fa801df70bad..64dde6c701e4b31c31efc27acc77ac3f1fb6a72f 100644
|
| --- a/views/window/window_win.cc
|
| +++ b/views/window/window_win.cc
|
| @@ -7,14 +7,16 @@
|
| #include <dwmapi.h>
|
| #include <shellapi.h>
|
|
|
| -#include "app/win/win_util.h"
|
| #include "base/i18n/rtl.h"
|
| +#include "base/win/scoped_gdi_object.h"
|
| +#include "base/win/win_util.h"
|
| #include "base/win/windows_version.h"
|
| #include "gfx/canvas_skia_paint.h"
|
| #include "gfx/font.h"
|
| #include "gfx/icon_util.h"
|
| #include "gfx/path.h"
|
| #include "ui/base/keycodes/keyboard_code_conversion_win.h"
|
| +#include "ui/base/l10n/l10n_util_win.h"
|
| #include "ui/base/theme_provider.h"
|
| #include "ui/base/win/hwnd_util.h"
|
| #include "views/accessibility/view_accessibility.h"
|
| @@ -29,6 +31,9 @@ namespace {
|
|
|
| static const int kDragFrameWindowAlpha = 200;
|
|
|
| +// The thickness of an auto-hide taskbar in pixels.
|
| +static const int kAutoHideTaskbarThicknessPx = 2;
|
| +
|
| bool GetMonitorAndRects(const RECT& rect,
|
| HMONITOR* monitor,
|
| gfx::Rect* monitor_rect,
|
| @@ -88,18 +93,72 @@ void SetChildBounds(HWND child_window, HWND parent_window,
|
| }
|
|
|
| gfx::Rect actual_bounds = bounds;
|
| - app::win::EnsureRectIsVisibleInRect(gfx::Rect(parent_rect), &actual_bounds,
|
| - padding);
|
| + views::internal::EnsureRectIsVisibleInRect(gfx::Rect(parent_rect),
|
| + &actual_bounds, padding);
|
|
|
| SetWindowPos(child_window, insert_after_window, actual_bounds.x(),
|
| actual_bounds.y(), actual_bounds.width(),
|
| actual_bounds.height(), flags);
|
| }
|
|
|
| +// Returns true if edge |edge| (one of ABE_LEFT, TOP, RIGHT, or BOTTOM) of
|
| +// monitor |monitor| has an auto-hiding taskbar that's always-on-top.
|
| +bool EdgeHasTopmostAutoHideTaskbar(UINT edge, HMONITOR monitor) {
|
| + APPBARDATA taskbar_data = { 0 };
|
| + taskbar_data.cbSize = sizeof APPBARDATA;
|
| + taskbar_data.uEdge = edge;
|
| + HWND taskbar = reinterpret_cast<HWND>(SHAppBarMessage(ABM_GETAUTOHIDEBAR,
|
| + &taskbar_data));
|
| + return ::IsWindow(taskbar) && (monitor != NULL) &&
|
| + (MonitorFromWindow(taskbar, MONITOR_DEFAULTTONULL) == monitor) &&
|
| + (GetWindowLong(taskbar, GWL_EXSTYLE) & WS_EX_TOPMOST);
|
| +}
|
| +
|
| } // namespace
|
|
|
| namespace views {
|
|
|
| +namespace internal {
|
| +
|
| +void EnsureRectIsVisibleInRect(const gfx::Rect& parent_rect,
|
| + gfx::Rect* child_rect,
|
| + int padding) {
|
| + DCHECK(child_rect);
|
| +
|
| + // We use padding here because it allows some of the original web page to
|
| + // bleed through around the edges.
|
| + int twice_padding = padding * 2;
|
| +
|
| + // FIRST, clamp width and height so we don't open child windows larger than
|
| + // the containing parent.
|
| + if (child_rect->width() > (parent_rect.width() + twice_padding))
|
| + child_rect->set_width(std::max(0, parent_rect.width() - twice_padding));
|
| + if (child_rect->height() > parent_rect.height() + twice_padding)
|
| + child_rect->set_height(std::max(0, parent_rect.height() - twice_padding));
|
| +
|
| + // SECOND, clamp x,y position to padding,padding so we don't position child
|
| + // windows in hyperspace.
|
| + // TODO(mpcomplete): I don't see what the second check in each 'if' does that
|
| + // isn't handled by the LAST set of 'ifs'. Maybe we can remove it.
|
| + if (child_rect->x() < parent_rect.x() ||
|
| + child_rect->x() > parent_rect.right()) {
|
| + child_rect->set_x(parent_rect.x() + padding);
|
| + }
|
| + if (child_rect->y() < parent_rect.y() ||
|
| + child_rect->y() > parent_rect.bottom()) {
|
| + child_rect->set_y(parent_rect.y() + padding);
|
| + }
|
| +
|
| + // LAST, nudge the window back up into the client area if its x,y position is
|
| + // within the parent bounds but its width/height place it off-screen.
|
| + if (child_rect->bottom() > parent_rect.bottom())
|
| + child_rect->set_y(parent_rect.bottom() - child_rect->height() - padding);
|
| + if (child_rect->right() > parent_rect.right())
|
| + child_rect->set_x(parent_rect.right() - child_rect->width() - padding);
|
| +}
|
| +
|
| +} // namespace internal
|
| +
|
| // A scoping class that prevents a window from being able to redraw in response
|
| // to invalidations that may occur within it for the lifetime of the object.
|
| //
|
| @@ -242,41 +301,6 @@ static BOOL CALLBACK SendDwmCompositionChanged(HWND window, LPARAM param) {
|
| }
|
| } // namespace
|
|
|
| -void WindowWin::FrameTypeChanged() {
|
| - if (base::win::GetVersion() >= base::win::VERSION_VISTA) {
|
| - // We need to toggle the rendering policy of the DWM/glass frame as we
|
| - // change from opaque to glass. "Non client rendering enabled" means that
|
| - // the DWM's glass non-client rendering is enabled, which is why
|
| - // DWMNCRP_ENABLED is used for the native frame case. _DISABLED means the
|
| - // DWM doesn't render glass, and so is used in the custom frame case.
|
| - DWMNCRENDERINGPOLICY policy =
|
| - non_client_view_->UseNativeFrame() ? DWMNCRP_ENABLED
|
| - : DWMNCRP_DISABLED;
|
| - DwmSetWindowAttribute(GetNativeView(), DWMWA_NCRENDERING_POLICY,
|
| - &policy, sizeof(DWMNCRENDERINGPOLICY));
|
| - }
|
| -
|
| - // Send a frame change notification, since the non-client metrics have
|
| - // changed.
|
| - SetWindowPos(NULL, 0, 0, 0, 0,
|
| - SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER |
|
| - SWP_NOOWNERZORDER | SWP_NOACTIVATE);
|
| -
|
| - // The frame type change results in the client rect changing size, but this
|
| - // does not explicitly send a WM_SIZE, so we need to force the root view to
|
| - // be resized now.
|
| - LayoutRootView();
|
| -
|
| - // Update the non-client view with the correct frame view for the active frame
|
| - // type.
|
| - non_client_view_->UpdateFrame();
|
| -
|
| - // WM_DWMCOMPOSITIONCHANGED is only sent to top level windows, however we want
|
| - // to notify our children too, since we can have MDI child windows who need to
|
| - // update their appearance.
|
| - EnumChildWindows(GetNativeView(), &SendDwmCompositionChanged, NULL);
|
| -}
|
| -
|
| ////////////////////////////////////////////////////////////////////////////////
|
| // WindowWin, Window implementation:
|
|
|
| @@ -544,6 +568,53 @@ bool WindowWin::ShouldUseNativeFrame() const {
|
| return tp->ShouldUseNativeFrame();
|
| }
|
|
|
| +void WindowWin::FrameTypeChanged() {
|
| + // Called when the frame type could possibly be changing (theme change or
|
| + // DWM composition change).
|
| + if (base::win::GetVersion() >= base::win::VERSION_VISTA) {
|
| + // We need to toggle the rendering policy of the DWM/glass frame as we
|
| + // change from opaque to glass. "Non client rendering enabled" means that
|
| + // the DWM's glass non-client rendering is enabled, which is why
|
| + // DWMNCRP_ENABLED is used for the native frame case. _DISABLED means the
|
| + // DWM doesn't render glass, and so is used in the custom frame case.
|
| + DWMNCRENDERINGPOLICY policy =
|
| + non_client_view_->UseNativeFrame() ? DWMNCRP_ENABLED
|
| + : DWMNCRP_DISABLED;
|
| + DwmSetWindowAttribute(GetNativeView(), DWMWA_NCRENDERING_POLICY,
|
| + &policy, sizeof(DWMNCRENDERINGPOLICY));
|
| + }
|
| +
|
| + // Send a frame change notification, since the non-client metrics have
|
| + // changed.
|
| + SetWindowPos(NULL, 0, 0, 0, 0,
|
| + SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER |
|
| + SWP_NOOWNERZORDER | SWP_NOACTIVATE);
|
| +
|
| + // The frame type change results in the client rect changing size, but this
|
| + // does not explicitly send a WM_SIZE, so we need to force the root view to
|
| + // be resized now.
|
| + LayoutRootView();
|
| +
|
| + // Update the non-client view with the correct frame view for the active frame
|
| + // type.
|
| + non_client_view_->UpdateFrame();
|
| +
|
| + // WM_DWMCOMPOSITIONCHANGED is only sent to top level windows, however we want
|
| + // to notify our children too, since we can have MDI child windows who need to
|
| + // update their appearance.
|
| + EnumChildWindows(GetNativeView(), &SendDwmCompositionChanged, NULL);
|
| +}
|
| +
|
| +
|
| +// static
|
| +gfx::Font WindowWin::GetWindowTitleFont() {
|
| + NONCLIENTMETRICS ncm;
|
| + base::win::GetNonClientMetrics(&ncm);
|
| + l10n_util::AdjustUIFont(&(ncm.lfCaptionFont));
|
| + base::win::ScopedHFONT caption_font(CreateFontIndirect(&(ncm.lfCaptionFont)));
|
| + return gfx::Font(caption_font);
|
| +}
|
| +
|
| ///////////////////////////////////////////////////////////////////////////////
|
| // WindowWin, protected:
|
|
|
| @@ -843,9 +914,9 @@ LRESULT WindowWin::OnNCCalcSize(BOOL mode, LPARAM l_param) {
|
| return 0;
|
| }
|
| }
|
| - if (app::win::EdgeHasTopmostAutoHideTaskbar(ABE_LEFT, monitor))
|
| - client_rect->left += app::win::kAutoHideTaskbarThicknessPx;
|
| - if (app::win::EdgeHasTopmostAutoHideTaskbar(ABE_TOP, monitor)) {
|
| + if (EdgeHasTopmostAutoHideTaskbar(ABE_LEFT, monitor))
|
| + client_rect->left += kAutoHideTaskbarThicknessPx;
|
| + if (EdgeHasTopmostAutoHideTaskbar(ABE_TOP, monitor)) {
|
| if (GetNonClientView()->UseNativeFrame()) {
|
| // Tricky bit. Due to a bug in DwmDefWindowProc()'s handling of
|
| // WM_NCHITTEST, having any nonclient area atop the window causes the
|
| @@ -858,13 +929,13 @@ LRESULT WindowWin::OnNCCalcSize(BOOL mode, LPARAM l_param) {
|
| // be no better solution.
|
| --client_rect->bottom;
|
| } else {
|
| - client_rect->top += app::win::kAutoHideTaskbarThicknessPx;
|
| + client_rect->top += kAutoHideTaskbarThicknessPx;
|
| }
|
| }
|
| - if (app::win::EdgeHasTopmostAutoHideTaskbar(ABE_RIGHT, monitor))
|
| - client_rect->right -= app::win::kAutoHideTaskbarThicknessPx;
|
| - if (app::win::EdgeHasTopmostAutoHideTaskbar(ABE_BOTTOM, monitor))
|
| - client_rect->bottom -= app::win::kAutoHideTaskbarThicknessPx;
|
| + if (EdgeHasTopmostAutoHideTaskbar(ABE_RIGHT, monitor))
|
| + client_rect->right -= kAutoHideTaskbarThicknessPx;
|
| + if (EdgeHasTopmostAutoHideTaskbar(ABE_BOTTOM, monitor))
|
| + client_rect->bottom -= kAutoHideTaskbarThicknessPx;
|
|
|
| // We cannot return WVR_REDRAW when there is nonclient area, or Windows
|
| // exhibits bugs where client pixels and child HWNDs are mispositioned by
|
|
|