| Index: views/widget/native_widget_win.cc
|
| ===================================================================
|
| --- views/widget/native_widget_win.cc (revision 88384)
|
| +++ views/widget/native_widget_win.cc (working copy)
|
| @@ -5,9 +5,12 @@
|
| #include "views/widget/native_widget_win.h"
|
|
|
| #include <dwmapi.h>
|
| +#include <shellapi.h>
|
|
|
| #include "base/string_util.h"
|
| #include "base/system_monitor/system_monitor.h"
|
| +#include "base/win/scoped_gdi_object.h"
|
| +#include "base/win/win_util.h"
|
| #include "base/win/windows_version.h"
|
| #include "ui/base/dragdrop/drag_drop_types.h"
|
| #include "ui/base/dragdrop/drag_source.h"
|
| @@ -19,6 +22,7 @@
|
| #include "ui/base/view_prop.h"
|
| #include "ui/base/win/hwnd_util.h"
|
| #include "ui/gfx/canvas_skia.h"
|
| +#include "ui/gfx/canvas_skia_paint.h"
|
| #include "ui/gfx/icon_util.h"
|
| #include "ui/gfx/native_theme_win.h"
|
| #include "ui/gfx/path.h"
|
| @@ -199,6 +203,68 @@
|
| return TRUE;
|
| }
|
|
|
| +// See comments in OnNCPaint() for details of this struct.
|
| +struct ClipState {
|
| + // The window being painted.
|
| + HWND parent;
|
| +
|
| + // DC painting to.
|
| + HDC dc;
|
| +
|
| + // Origin of the window in terms of the screen.
|
| + int x;
|
| + int y;
|
| +};
|
| +
|
| +// See comments in OnNCPaint() for details of this function.
|
| +static BOOL CALLBACK ClipDCToChild(HWND window, LPARAM param) {
|
| + ClipState* clip_state = reinterpret_cast<ClipState*>(param);
|
| + if (GetParent(window) == clip_state->parent && IsWindowVisible(window)) {
|
| + RECT bounds;
|
| + GetWindowRect(window, &bounds);
|
| + ExcludeClipRect(clip_state->dc,
|
| + bounds.left - clip_state->x,
|
| + bounds.top - clip_state->y,
|
| + bounds.right - clip_state->x,
|
| + bounds.bottom - clip_state->y);
|
| + }
|
| + return TRUE;
|
| +}
|
| +
|
| +// 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,
|
| + gfx::Rect* work_area) {
|
| + DCHECK(monitor);
|
| + DCHECK(monitor_rect);
|
| + DCHECK(work_area);
|
| + *monitor = MonitorFromRect(&rect, MONITOR_DEFAULTTONULL);
|
| + if (!*monitor)
|
| + return false;
|
| + MONITORINFO monitor_info = { 0 };
|
| + monitor_info.cbSize = sizeof(monitor_info);
|
| + GetMonitorInfo(*monitor, &monitor_info);
|
| + *monitor_rect = monitor_info.rcMonitor;
|
| + *work_area = monitor_info.rcWork;
|
| + return true;
|
| +}
|
| +
|
| +// 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);
|
| +}
|
| +
|
| // Links the HWND to its NativeWidget.
|
| const char* const kNativeWidgetKey = "__VIEWS_NATIVE_WIDGET__";
|
|
|
| @@ -280,7 +346,12 @@
|
| fullscreen_(false),
|
| force_hidden_count_(0),
|
| lock_updates_(false),
|
| - saved_window_style_(0) {
|
| + saved_window_style_(0),
|
| + ignore_window_pos_changes_(false),
|
| + ignore_pos_changes_factory_(this),
|
| + last_monitor_(NULL),
|
| + is_right_mouse_pressed_on_caption_(false),
|
| + restored_enabled_(false) {
|
| }
|
|
|
| NativeWidgetWin::~NativeWidgetWin() {
|
| @@ -300,6 +371,15 @@
|
| return SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled;
|
| }
|
|
|
| +// static
|
| +gfx::Font NativeWidgetWin::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);
|
| +}
|
| +
|
| void NativeWidgetWin::Show(int show_state) {
|
| ShowWindow(show_state);
|
| // When launched from certain programs like bash and Windows Live Messenger,
|
| @@ -366,6 +446,9 @@
|
| void NativeWidgetWin::InitNativeWidget(const Widget::InitParams& params) {
|
| SetInitParams(params);
|
|
|
| + GetMonitorAndRects(params.bounds.ToRECT(), &last_monitor_,
|
| + &last_monitor_rect_, &last_work_area_);
|
| +
|
| // Create the window.
|
| gfx::NativeView parent = params.parent_widget ?
|
| params.parent_widget->GetNativeView() : params.parent;
|
| @@ -617,6 +700,17 @@
|
| }
|
| }
|
|
|
| +void NativeWidgetWin::BecomeModal() {
|
| + // We implement modality by crawling up the hierarchy of windows starting
|
| + // at the owner, disabling all of them so that they don't receive input
|
| + // messages.
|
| + HWND start = ::GetWindow(GetNativeView(), GW_OWNER);
|
| + while (start) {
|
| + ::EnableWindow(start, FALSE);
|
| + start = ::GetParent(start);
|
| + }
|
| +}
|
| +
|
| gfx::Rect NativeWidgetWin::GetWindowScreenBounds() const {
|
| RECT r;
|
| GetWindowRect(&r);
|
| @@ -1083,7 +1177,10 @@
|
| // creation time.
|
| ClientAreaSizeChanged();
|
|
|
| - delegate_->OnNativeWidgetCreated();
|
| + delegate_->OnNativeWidgetCreated(gfx::Rect(create_struct->x,
|
| + create_struct->y,
|
| + create_struct->cx,
|
| + create_struct->cy));
|
|
|
| // delegate_->OnNativeWidgetCreated() creates the focus manager for top-level
|
| // widget. Only top-level widget should have an input method.
|
| @@ -1097,6 +1194,7 @@
|
| }
|
|
|
| void NativeWidgetWin::OnDestroy() {
|
| + RestoreEnabledIfNecessary();
|
| delegate_->OnNativeWidgetDestroying();
|
| if (drop_target_.get()) {
|
| RevokeDragDrop(hwnd());
|
| @@ -1309,6 +1407,75 @@
|
| LRESULT NativeWidgetWin::OnMouseRange(UINT message,
|
| WPARAM w_param,
|
| LPARAM l_param) {
|
| + if (message == WM_RBUTTONUP && is_right_mouse_pressed_on_caption_) {
|
| + is_right_mouse_pressed_on_caption_ = false;
|
| + ReleaseCapture();
|
| + // |point| is in window coordinates, but WM_NCHITTEST and TrackPopupMenu()
|
| + // expect screen coordinates.
|
| + CPoint screen_point(l_param);
|
| + MapWindowPoints(GetNativeView(), HWND_DESKTOP, &screen_point, 1);
|
| + w_param = SendMessage(GetNativeView(), WM_NCHITTEST, 0,
|
| + MAKELPARAM(screen_point.x, screen_point.y));
|
| + if (w_param == HTCAPTION || w_param == HTSYSMENU) {
|
| + UINT flags = TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_RETURNCMD;
|
| + if (base::i18n::IsRTL())
|
| + flags |= TPM_RIGHTALIGN;
|
| + HMENU system_menu = GetSystemMenu(GetNativeView(), FALSE);
|
| + int id = TrackPopupMenu(system_menu, flags, screen_point.x,
|
| + screen_point.y, 0, GetNativeView(), NULL);
|
| + ExecuteSystemMenuCommand(id);
|
| + return 0;
|
| + }
|
| + } else if (message == WM_NCLBUTTONDOWN &&
|
| + !GetWidget()->ShouldUseNativeFrame()) {
|
| + switch (w_param) {
|
| + case HTCLOSE:
|
| + case HTMINBUTTON:
|
| + case HTMAXBUTTON: {
|
| + // When the mouse is pressed down in these specific non-client areas,
|
| + // we need to tell the RootView to send the mouse pressed event (which
|
| + // sets capture, allowing subsequent WM_LBUTTONUP (note, _not_
|
| + // WM_NCLBUTTONUP) to fire so that the appropriate WM_SYSCOMMAND can be
|
| + // sent by the applicable button's ButtonListener. We _have_ to do this
|
| + // way rather than letting Windows just send the syscommand itself (as
|
| + // would happen if we never did this dance) because for some insane
|
| + // reason DefWindowProc for WM_NCLBUTTONDOWN also renders the pressed
|
| + // window control button appearance, in the Windows classic style, over
|
| + // our view! Ick! By handling this message we prevent Windows from
|
| + // doing this undesirable thing, but that means we need to roll the
|
| + // sys-command handling ourselves.
|
| + // Combine |w_param| with common key state message flags.
|
| + w_param |= ((GetKeyState(VK_CONTROL) & 0x80) == 0x80)? MK_CONTROL : 0;
|
| + w_param |= ((GetKeyState(VK_SHIFT) & 0x80) == 0x80)? MK_SHIFT : 0;
|
| + }
|
| + }
|
| + } else if (message == WM_NCRBUTTONDOWN &&
|
| + (w_param == HTCAPTION || w_param == HTSYSMENU)) {
|
| + is_right_mouse_pressed_on_caption_ = true;
|
| + // We SetMouseCapture() to ensure we only show the menu when the button
|
| + // down and up are both on the caption. Note: this causes the button up to
|
| + // be WM_RBUTTONUP instead of WM_NCRBUTTONUP.
|
| + SetMouseCapture();
|
| + }
|
| +
|
| + /*
|
| + TODO(beng): This fixes some situations where the windows-classic appearance
|
| + non-client area is rendered over our custom frame, however it
|
| + causes mouse-releases to the non-client area to be eaten, so it
|
| + can't be enabled.
|
| + if (message == WM_NCLBUTTONDOWN) {
|
| + // NativeWidgetWin::OnNCLButtonDown set the message as un-handled. This
|
| + // normally means NativeWidgetWin::ProcessWindowMessage will pass it to
|
| + // DefWindowProc. Sadly, DefWindowProc for WM_NCLBUTTONDOWN does weird
|
| + // non-client painting, so we need to call it directly here inside a
|
| + // scoped update lock.
|
| + ScopedRedrawLock lock(this);
|
| + NativeWidgetWin::OnMouseRange(message, w_param, l_param);
|
| + DefWindowProc(GetNativeView(), WM_NCLBUTTONDOWN, w_param, l_param);
|
| + SetMsgHandled(TRUE);
|
| + }
|
| + */
|
| +
|
| MSG msg = { hwnd(), message, w_param, l_param, 0,
|
| { GET_X_LPARAM(l_param), GET_Y_LPARAM(l_param) } };
|
| MouseEvent event(msg);
|
| @@ -1385,9 +1552,86 @@
|
| return CallDefaultNCActivateHandler(inactive_rendering_disabled || active);
|
| }
|
|
|
| -LRESULT NativeWidgetWin::OnNCCalcSize(BOOL w_param, LPARAM l_param) {
|
| - SetMsgHandled(FALSE);
|
| - return 0;
|
| +LRESULT NativeWidgetWin::OnNCCalcSize(BOOL mode, LPARAM l_param) {
|
| + // We only override the default handling if we need to specify a custom
|
| + // non-client edge width. Note that in most cases "no insets" means no
|
| + // custom width, but in fullscreen mode we want a custom width of 0.
|
| + gfx::Insets insets = GetClientAreaInsets();
|
| + if (insets.empty() && !IsFullscreen()) {
|
| + SetMsgHandled(FALSE);
|
| + return 0;
|
| + }
|
| +
|
| + RECT* client_rect = mode ?
|
| + &reinterpret_cast<NCCALCSIZE_PARAMS*>(l_param)->rgrc[0] :
|
| + reinterpret_cast<RECT*>(l_param);
|
| + client_rect->left += insets.left();
|
| + client_rect->top += insets.top();
|
| + client_rect->bottom -= insets.bottom();
|
| + client_rect->right -= insets.right();
|
| + if (IsMaximized()) {
|
| + // Find all auto-hide taskbars along the screen edges and adjust in by the
|
| + // thickness of the auto-hide taskbar on each such edge, so the window isn't
|
| + // treated as a "fullscreen app", which would cause the taskbars to
|
| + // disappear.
|
| + HMONITOR monitor = MonitorFromWindow(GetNativeView(),
|
| + MONITOR_DEFAULTTONULL);
|
| + if (!monitor) {
|
| + // We might end up here if the window was previously minimized and the
|
| + // user clicks on the taskbar button to restore it in the previously
|
| + // maximized position. In that case WM_NCCALCSIZE is sent before the
|
| + // window coordinates are restored to their previous values, so our
|
| + // (left,top) would probably be (-32000,-32000) like all minimized
|
| + // windows. So the above MonitorFromWindow call fails, but if we check
|
| + // the window rect given with WM_NCCALCSIZE (which is our previous
|
| + // restored window position) we will get the correct monitor handle.
|
| + monitor = MonitorFromRect(client_rect, MONITOR_DEFAULTTONULL);
|
| + if (!monitor) {
|
| + // This is probably an extreme case that we won't hit, but if we don't
|
| + // intersect any monitor, let us not adjust the client rect since our
|
| + // window will not be visible anyway.
|
| + return 0;
|
| + }
|
| + }
|
| + if (EdgeHasTopmostAutoHideTaskbar(ABE_LEFT, monitor))
|
| + client_rect->left += kAutoHideTaskbarThicknessPx;
|
| + if (EdgeHasTopmostAutoHideTaskbar(ABE_TOP, monitor)) {
|
| + if (GetWidget()->ShouldUseNativeFrame()) {
|
| + // Tricky bit. Due to a bug in DwmDefWindowProc()'s handling of
|
| + // WM_NCHITTEST, having any nonclient area atop the window causes the
|
| + // caption buttons to draw onscreen but not respond to mouse
|
| + // hover/clicks.
|
| + // So for a taskbar at the screen top, we can't push the
|
| + // client_rect->top down; instead, we move the bottom up by one pixel,
|
| + // which is the smallest change we can make and still get a client area
|
| + // less than the screen size. This is visibly ugly, but there seems to
|
| + // be no better solution.
|
| + --client_rect->bottom;
|
| + } else {
|
| + client_rect->top += 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
|
| + // the width/height of the upper-left nonclient area.
|
| + return 0;
|
| + }
|
| +
|
| + // If the window bounds change, we're going to relayout and repaint anyway.
|
| + // Returning WVR_REDRAW avoids an extra paint before that of the old client
|
| + // pixels in the (now wrong) location, and thus makes actions like resizing a
|
| + // window from the left edge look slightly less broken.
|
| + // We special case when left or top insets are 0, since these conditions
|
| + // actually require another repaint to correct the layout after glass gets
|
| + // turned on and off.
|
| + if (insets.left() == 0 || insets.top() == 0)
|
| + return 0;
|
| + return mode ? WVR_REDRAW : 0;
|
| }
|
|
|
| LRESULT NativeWidgetWin::OnNCHitTest(const CPoint& point) {
|
| @@ -1421,7 +1665,85 @@
|
| }
|
|
|
| void NativeWidgetWin::OnNCPaint(HRGN rgn) {
|
| - SetMsgHandled(FALSE);
|
| + // We only do non-client painting if we're not using the native frame.
|
| + // It's required to avoid some native painting artifacts from appearing when
|
| + // the window is resized.
|
| + if (!GetWidget()->non_client_view() || GetWidget()->ShouldUseNativeFrame()) {
|
| + SetMsgHandled(FALSE);
|
| + return;
|
| + }
|
| +
|
| + // We have an NC region and need to paint it. We expand the NC region to
|
| + // include the dirty region of the root view. This is done to minimize
|
| + // paints.
|
| + CRect window_rect;
|
| + GetWindowRect(&window_rect);
|
| +
|
| + if (window_rect.Width() != GetWidget()->GetRootView()->width() ||
|
| + window_rect.Height() != GetWidget()->GetRootView()->height()) {
|
| + // If the size of the window differs from the size of the root view it
|
| + // means we're being asked to paint before we've gotten a WM_SIZE. This can
|
| + // happen when the user is interactively resizing the window. To avoid
|
| + // mass flickering we don't do anything here. Once we get the WM_SIZE we'll
|
| + // reset the region of the window which triggers another WM_NCPAINT and
|
| + // all is well.
|
| + return;
|
| + }
|
| +
|
| + CRect dirty_region;
|
| + // A value of 1 indicates paint all.
|
| + if (!rgn || rgn == reinterpret_cast<HRGN>(1)) {
|
| + dirty_region = CRect(0, 0, window_rect.Width(), window_rect.Height());
|
| + } else {
|
| + RECT rgn_bounding_box;
|
| + GetRgnBox(rgn, &rgn_bounding_box);
|
| + if (!IntersectRect(&dirty_region, &rgn_bounding_box, &window_rect))
|
| + return; // Dirty region doesn't intersect window bounds, bale.
|
| +
|
| + // rgn_bounding_box is in screen coordinates. Map it to window coordinates.
|
| + OffsetRect(&dirty_region, -window_rect.left, -window_rect.top);
|
| + }
|
| +
|
| + // In theory GetDCEx should do what we want, but I couldn't get it to work.
|
| + // In particular the docs mentiond DCX_CLIPCHILDREN, but as far as I can tell
|
| + // it doesn't work at all. So, instead we get the DC for the window then
|
| + // manually clip out the children.
|
| + HDC dc = GetWindowDC(GetNativeView());
|
| + ClipState clip_state;
|
| + clip_state.x = window_rect.left;
|
| + clip_state.y = window_rect.top;
|
| + clip_state.parent = GetNativeView();
|
| + clip_state.dc = dc;
|
| + EnumChildWindows(GetNativeView(), &ClipDCToChild,
|
| + reinterpret_cast<LPARAM>(&clip_state));
|
| +
|
| + gfx::Rect old_paint_region = invalid_rect();
|
| +
|
| + if (!old_paint_region.IsEmpty()) {
|
| + // The root view has a region that needs to be painted. Include it in the
|
| + // region we're going to paint.
|
| +
|
| + CRect old_paint_region_crect = old_paint_region.ToRECT();
|
| + CRect tmp = dirty_region;
|
| + UnionRect(&dirty_region, &tmp, &old_paint_region_crect);
|
| + }
|
| +
|
| + GetWidget()->GetRootView()->SchedulePaintInRect(gfx::Rect(dirty_region));
|
| +
|
| + // gfx::CanvasSkiaPaint's destructor does the actual painting. As such, wrap
|
| + // the following in a block to force paint to occur so that we can release
|
| + // the dc.
|
| + {
|
| + gfx::CanvasSkiaPaint canvas(dc, true, dirty_region.left,
|
| + dirty_region.top, dirty_region.Width(),
|
| + dirty_region.Height());
|
| + delegate_->OnNativeWidgetPaint(&canvas);
|
| + }
|
| +
|
| + ReleaseDC(GetNativeView(), dc);
|
| + // When using a custom frame, we want to avoid calling DefWindowProc() since
|
| + // that may render artifacts.
|
| + SetMsgHandled(!GetWidget()->ShouldUseNativeFrame());
|
| }
|
|
|
| LRESULT NativeWidgetWin::OnNCUAHDrawCaption(UINT msg,
|
| @@ -1600,6 +1922,67 @@
|
| }
|
|
|
| void NativeWidgetWin::OnWindowPosChanging(WINDOWPOS* window_pos) {
|
| + if (ignore_window_pos_changes_) {
|
| + // If somebody's trying to toggle our visibility, change the nonclient area,
|
| + // change our Z-order, or activate us, we should probably let it go through.
|
| + if (!(window_pos->flags & ((IsVisible() ? SWP_HIDEWINDOW : SWP_SHOWWINDOW) |
|
| + SWP_FRAMECHANGED)) &&
|
| + (window_pos->flags & (SWP_NOZORDER | SWP_NOACTIVATE))) {
|
| + // Just sizing/moving the window; ignore.
|
| + window_pos->flags |= SWP_NOSIZE | SWP_NOMOVE | SWP_NOREDRAW;
|
| + window_pos->flags &= ~(SWP_SHOWWINDOW | SWP_HIDEWINDOW);
|
| + }
|
| + } else if (!GetParent()) {
|
| + CRect window_rect;
|
| + HMONITOR monitor;
|
| + gfx::Rect monitor_rect, work_area;
|
| + if (GetWindowRect(&window_rect) &&
|
| + GetMonitorAndRects(window_rect, &monitor, &monitor_rect, &work_area)) {
|
| + if (monitor && (monitor == last_monitor_) &&
|
| + (IsFullscreen() || ((monitor_rect == last_monitor_rect_) &&
|
| + (work_area != last_work_area_)))) {
|
| + // A rect for the monitor we're on changed. Normally Windows notifies
|
| + // us about this (and thus we're reaching here due to the SetWindowPos()
|
| + // call in OnSettingChange() above), but with some software (e.g.
|
| + // nVidia's nView desktop manager) the work area can change asynchronous
|
| + // to any notification, and we're just sent a SetWindowPos() call with a
|
| + // new (frequently incorrect) position/size. In either case, the best
|
| + // response is to throw away the existing position/size information in
|
| + // |window_pos| and recalculate it based on the new work rect.
|
| + gfx::Rect new_window_rect;
|
| + if (IsFullscreen()) {
|
| + new_window_rect = monitor_rect;
|
| + } else if (IsZoomed()) {
|
| + new_window_rect = work_area;
|
| + int border_thickness = GetSystemMetrics(SM_CXSIZEFRAME);
|
| + new_window_rect.Inset(-border_thickness, -border_thickness);
|
| + } else {
|
| + new_window_rect = gfx::Rect(window_rect).AdjustToFit(work_area);
|
| + }
|
| + window_pos->x = new_window_rect.x();
|
| + window_pos->y = new_window_rect.y();
|
| + window_pos->cx = new_window_rect.width();
|
| + window_pos->cy = new_window_rect.height();
|
| + // WARNING! Don't set SWP_FRAMECHANGED here, it breaks moving the child
|
| + // HWNDs for some reason.
|
| + window_pos->flags &= ~(SWP_NOSIZE | SWP_NOMOVE | SWP_NOREDRAW);
|
| + window_pos->flags |= SWP_NOCOPYBITS;
|
| +
|
| + // Now ignore all immediately-following SetWindowPos() changes. Windows
|
| + // likes to (incorrectly) recalculate what our position/size should be
|
| + // and send us further updates.
|
| + ignore_window_pos_changes_ = true;
|
| + DCHECK(ignore_pos_changes_factory_.empty());
|
| + MessageLoop::current()->PostTask(FROM_HERE,
|
| + ignore_pos_changes_factory_.NewRunnableMethod(
|
| + &NativeWidgetWin::StopIgnoringPosChanges));
|
| + }
|
| + last_monitor_ = monitor;
|
| + last_monitor_rect_ = monitor_rect;
|
| + last_work_area_ = work_area;
|
| + }
|
| + }
|
| +
|
| if (force_hidden_count_) {
|
| // Prevent the window from being made visible if we've been asked to do so.
|
| // See comment in header as to why we might want this.
|
| @@ -1631,7 +2014,7 @@
|
| gfx::Insets NativeWidgetWin::GetClientAreaInsets() const {
|
| // Returning an empty Insets object causes the default handling in
|
| // NativeWidgetWin::OnNCCalcSize() to be invoked.
|
| - if (GetWidget()->ShouldUseNativeFrame())
|
| + if (!GetWidget()->non_client_view() || GetWidget()->ShouldUseNativeFrame())
|
| return gfx::Insets();
|
|
|
| if (IsMaximized()) {
|
| @@ -1780,7 +2163,26 @@
|
|
|
| // Set type-dependent style attributes.
|
| switch (params.type) {
|
| - case Widget::InitParams::TYPE_WINDOW:
|
| + case Widget::InitParams::TYPE_WINDOW: {
|
| + style |= WS_SYSMENU | WS_CAPTION;
|
| + bool can_resize = GetWidget()->widget_delegate()->CanResize();
|
| + bool can_maximize = GetWidget()->widget_delegate()->CanMaximize();
|
| + if (can_maximize) {
|
| + style |= WS_OVERLAPPEDWINDOW;
|
| + } else if (can_resize) {
|
| + style |= WS_OVERLAPPED | WS_THICKFRAME;
|
| + }
|
| + if (delegate_->IsDialogBox()) {
|
| + style |= DS_MODALFRAME;
|
| + // NOTE: Turning this off means we lose the close button, which is bad.
|
| + // Turning it on though means the user can maximize or size the window
|
| + // from the system menu, which is worse. We may need to provide our own
|
| + // menu to get the close button to appear properly.
|
| + // style &= ~WS_SYSMENU;
|
| + }
|
| + ex_style |= delegate_->IsDialogBox() ? WS_EX_DLGMODALFRAME : 0;
|
| + break;
|
| + }
|
| case Widget::InitParams::TYPE_CONTROL:
|
| break;
|
| case Widget::InitParams::TYPE_POPUP:
|
| @@ -1921,6 +2323,20 @@
|
| #endif
|
| }
|
|
|
| +void NativeWidgetWin::RestoreEnabledIfNecessary() {
|
| + if (delegate_->IsModal() && !restored_enabled_) {
|
| + restored_enabled_ = true;
|
| + // If we were run modally, we need to undo the disabled-ness we inflicted on
|
| + // the owner's parent hierarchy.
|
| + HWND start = ::GetWindow(GetNativeView(), GW_OWNER);
|
| + while (start) {
|
| + ::EnableWindow(start, TRUE);
|
| + start = ::GetParent(start);
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| void NativeWidgetWin::DispatchKeyEventPostIME(const KeyEvent& key) {
|
| SetMsgHandled(delegate_->OnKeyEvent(key));
|
| }
|
|
|