| Index: ui/views/win/hwnd_message_handler.cc
|
| ===================================================================
|
| --- ui/views/win/hwnd_message_handler.cc (revision 153487)
|
| +++ ui/views/win/hwnd_message_handler.cc (working copy)
|
| @@ -78,6 +78,12 @@
|
| return TRUE;
|
| }
|
|
|
| +// Enables or disables the menu item for the specified command and menu.
|
| +void EnableMenuItemByCommand(HMENU menu, UINT command, bool enabled) {
|
| + UINT flags = MF_BYCOMMAND | (enabled ? MF_ENABLED : MF_DISABLED | MF_GRAYED);
|
| + EnableMenuItem(menu, command, flags);
|
| +}
|
| +
|
| // A custom MSAA object id used to determine if a screen reader is actively
|
| // listening for MSAA events.
|
| const int kCustomObjectID = 1;
|
| @@ -87,6 +93,70 @@
|
|
|
| } // namespace
|
|
|
| +// 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.
|
| +//
|
| +// Why would we want such a thing? Well, it turns out Windows has some
|
| +// "unorthodox" behavior when it comes to painting its non-client areas.
|
| +// Occasionally, Windows will paint portions of the default non-client area
|
| +// right over the top of the custom frame. This is not simply fixed by handling
|
| +// WM_NCPAINT/WM_PAINT, with some investigation it turns out that this
|
| +// rendering is being done *inside* the default implementation of some message
|
| +// handlers and functions:
|
| +// . WM_SETTEXT
|
| +// . WM_SETICON
|
| +// . WM_NCLBUTTONDOWN
|
| +// . EnableMenuItem, called from our WM_INITMENU handler
|
| +// The solution is to handle these messages and call DefWindowProc ourselves,
|
| +// but prevent the window from being able to update itself for the duration of
|
| +// the call. We do this with this class, which automatically calls its
|
| +// associated Window's lock and unlock functions as it is created and destroyed.
|
| +// See documentation in those methods for the technique used.
|
| +//
|
| +// The lock only has an effect if the window was visible upon lock creation, as
|
| +// it doesn't guard against direct visiblility changes, and multiple locks may
|
| +// exist simultaneously to handle certain nested Windows messages.
|
| +//
|
| +// IMPORTANT: Do not use this scoping object for large scopes or periods of
|
| +// time! IT WILL PREVENT THE WINDOW FROM BEING REDRAWN! (duh).
|
| +//
|
| +// I would love to hear Raymond Chen's explanation for all this. And maybe a
|
| +// list of other messages that this applies to ;-)
|
| +class HWNDMessageHandler::ScopedRedrawLock {
|
| + public:
|
| + explicit ScopedRedrawLock(HWNDMessageHandler* owner)
|
| + : owner_(owner),
|
| + hwnd_(owner_->hwnd()),
|
| + was_visible_(owner_->IsVisible()),
|
| + cancel_unlock_(false),
|
| + force_(!(GetWindowLong(hwnd_, GWL_STYLE) & WS_CAPTION)) {
|
| + if (was_visible_ && ::IsWindow(hwnd_))
|
| + owner_->LockUpdates(force_);
|
| + }
|
| +
|
| + ~ScopedRedrawLock() {
|
| + if (!cancel_unlock_ && was_visible_ && ::IsWindow(hwnd_))
|
| + owner_->UnlockUpdates(force_);
|
| + }
|
| +
|
| + // Cancel the unlock operation, call this if the Widget is being destroyed.
|
| + void CancelUnlockOperation() { cancel_unlock_ = true; }
|
| +
|
| + private:
|
| + // The owner having its style changed.
|
| + HWNDMessageHandler* owner_;
|
| + // The owner's HWND, cached to avoid action after window destruction.
|
| + HWND hwnd_;
|
| + // Records the HWND visibility at the time of creation.
|
| + bool was_visible_;
|
| + // A flag indicating that the unlock operation was canceled.
|
| + bool cancel_unlock_;
|
| + // If true, perform the redraw lock regardless of Aero state.
|
| + bool force_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(ScopedRedrawLock);
|
| +};
|
| +
|
| ////////////////////////////////////////////////////////////////////////////////
|
| // HWNDMessageHandler, public:
|
|
|
| @@ -563,12 +633,14 @@
|
| bool is_maximized = IsMaximized();
|
| bool is_restored = !is_fullscreen && !is_minimized && !is_maximized;
|
|
|
| - EnableMenuItem(menu, SC_RESTORE, is_minimized || is_maximized);
|
| - EnableMenuItem(menu, SC_MOVE, is_restored);
|
| - EnableMenuItem(menu, SC_SIZE, delegate_->CanResize() && is_restored);
|
| - EnableMenuItem(menu, SC_MAXIMIZE, delegate_->CanMaximize() &&
|
| - !is_fullscreen && !is_maximized);
|
| - EnableMenuItem(menu, SC_MINIMIZE, delegate_->CanMaximize() && !is_minimized);
|
| + ScopedRedrawLock lock(this);
|
| + EnableMenuItemByCommand(menu, SC_RESTORE, is_minimized || is_maximized);
|
| + EnableMenuItemByCommand(menu, SC_MOVE, is_restored);
|
| + EnableMenuItemByCommand(menu, SC_SIZE, delegate_->CanResize() && is_restored);
|
| + EnableMenuItemByCommand(menu, SC_MAXIMIZE, delegate_->CanMaximize() &&
|
| + !is_fullscreen && !is_maximized);
|
| + EnableMenuItemByCommand(menu, SC_MINIMIZE, delegate_->CanMaximize() &&
|
| + !is_minimized);
|
| }
|
|
|
| void HWNDMessageHandler::OnInitMenuPopup() {
|
| @@ -1288,70 +1360,6 @@
|
| return gfx::Insets(0, 0, fullscreen_handler_->fullscreen() ? 0 : 1, 0);
|
| }
|
|
|
| -// 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.
|
| -//
|
| -// Why would we want such a thing? Well, it turns out Windows has some
|
| -// "unorthodox" behavior when it comes to painting its non-client areas.
|
| -// Occasionally, Windows will paint portions of the default non-client area
|
| -// right over the top of the custom frame. This is not simply fixed by handling
|
| -// WM_NCPAINT/WM_PAINT, with some investigation it turns out that this
|
| -// rendering is being done *inside* the default implementation of some message
|
| -// handlers and functions:
|
| -// . WM_SETTEXT
|
| -// . WM_SETICON
|
| -// . WM_NCLBUTTONDOWN
|
| -// . EnableMenuItem, called from our WM_INITMENU handler
|
| -// The solution is to handle these messages and call DefWindowProc ourselves,
|
| -// but prevent the window from being able to update itself for the duration of
|
| -// the call. We do this with this class, which automatically calls its
|
| -// associated Window's lock and unlock functions as it is created and destroyed.
|
| -// See documentation in those methods for the technique used.
|
| -//
|
| -// The lock only has an effect if the window was visible upon lock creation, as
|
| -// it doesn't guard against direct visiblility changes, and multiple locks may
|
| -// exist simultaneously to handle certain nested Windows messages.
|
| -//
|
| -// IMPORTANT: Do not use this scoping object for large scopes or periods of
|
| -// time! IT WILL PREVENT THE WINDOW FROM BEING REDRAWN! (duh).
|
| -//
|
| -// I would love to hear Raymond Chen's explanation for all this. And maybe a
|
| -// list of other messages that this applies to ;-)
|
| -class HWNDMessageHandler::ScopedRedrawLock {
|
| - public:
|
| - explicit ScopedRedrawLock(HWNDMessageHandler* owner)
|
| - : owner_(owner),
|
| - hwnd_(owner_->hwnd()),
|
| - was_visible_(owner_->IsVisible()),
|
| - cancel_unlock_(false),
|
| - force_(!(GetWindowLong(hwnd_, GWL_STYLE) & WS_CAPTION)) {
|
| - if (was_visible_ && ::IsWindow(hwnd_))
|
| - owner_->LockUpdates(force_);
|
| - }
|
| -
|
| - ~ScopedRedrawLock() {
|
| - if (!cancel_unlock_ && was_visible_ && ::IsWindow(hwnd_))
|
| - owner_->UnlockUpdates(force_);
|
| - }
|
| -
|
| - // Cancel the unlock operation, call this if the Widget is being destroyed.
|
| - void CancelUnlockOperation() { cancel_unlock_ = true; }
|
| -
|
| - private:
|
| - // The owner having its style changed.
|
| - HWNDMessageHandler* owner_;
|
| - // The owner's HWND, cached to avoid action after window destruction.
|
| - HWND hwnd_;
|
| - // Records the HWND visibility at the time of creation.
|
| - bool was_visible_;
|
| - // A flag indicating that the unlock operation was canceled.
|
| - bool cancel_unlock_;
|
| - // If true, perform the redraw lock regardless of Aero state.
|
| - bool force_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(ScopedRedrawLock);
|
| -};
|
| -
|
| LRESULT HWNDMessageHandler::DefWindowProcWithRedrawLock(UINT message,
|
| WPARAM w_param,
|
| LPARAM l_param) {
|
|
|