summaryrefslogtreecommitdiffstats
path: root/ui/views/win/hwnd_message_handler.cc
diff options
context:
space:
mode:
Diffstat (limited to 'ui/views/win/hwnd_message_handler.cc')
-rw-r--r--ui/views/win/hwnd_message_handler.cc345
1 files changed, 1 insertions, 344 deletions
diff --git a/ui/views/win/hwnd_message_handler.cc b/ui/views/win/hwnd_message_handler.cc
index fa28e3c..5c8641c 100644
--- a/ui/views/win/hwnd_message_handler.cc
+++ b/ui/views/win/hwnd_message_handler.cc
@@ -5,26 +5,19 @@
#include "ui/views/win/hwnd_message_handler.h"
#include <dwmapi.h>
-#include <shellapi.h>
-#include "base/bind.h"
#include "base/system_monitor/system_monitor.h"
#include "base/win/windows_version.h"
-#include "ui/gfx/insets.h"
#include "ui/gfx/path.h"
#include "ui/base/event.h"
-#include "ui/base/keycodes/keyboard_code_conversion_win.h"
#include "ui/base/native_theme/native_theme_win.h"
#include "ui/base/win/hwnd_util.h"
#include "ui/base/win/mouse_wheel_util.h"
#include "ui/base/win/shell.h"
#include "ui/views/ime/input_method_win.h"
-#include "ui/views/widget/monitor_win.h"
#include "ui/views/widget/native_widget_win.h"
#include "ui/views/widget/widget_hwnd_utils.h"
-#include "ui/views/win/fullscreen_handler.h"
#include "ui/views/win/hwnd_message_handler_delegate.h"
-#include "ui/views/win/scoped_fullscreen_visibility.h"
#if !defined(USE_AURA)
#include "base/command_line.h"
@@ -45,31 +38,10 @@ BOOL CALLBACK EnumChildWindowsForRedraw(HWND hwnd, LPARAM lparam) {
return TRUE;
}
-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;
-}
-
// A custom MSAA object id used to determine if a screen reader is actively
// listening for MSAA events.
const int kCustomObjectID = 1;
-// The thickness of an auto-hide taskbar in pixels.
-const int kAutoHideTaskbarThicknessPx = 2;
-
} // namespace
////////////////////////////////////////////////////////////////////////////////
@@ -77,16 +49,11 @@ const int kAutoHideTaskbarThicknessPx = 2;
HWNDMessageHandler::HWNDMessageHandler(HWNDMessageHandlerDelegate* delegate)
: delegate_(delegate),
- ALLOW_THIS_IN_INITIALIZER_LIST(fullscreen_handler_(new FullscreenHandler(
- delegate->AsNativeWidgetWin()->GetWidget()))),
remove_standard_frame_(false),
active_mouse_tracking_flags_(0),
is_right_mouse_pressed_on_caption_(false),
lock_updates_count_(0),
- destroyed_(NULL),
- ignore_window_pos_changes_(false),
- ALLOW_THIS_IN_INITIALIZER_LIST(ignore_pos_changes_factory_(this)),
- last_monitor_(NULL) {
+ destroyed_(NULL) {
}
HWNDMessageHandler::~HWNDMessageHandler() {
@@ -94,53 +61,6 @@ HWNDMessageHandler::~HWNDMessageHandler() {
*destroyed_ = true;
}
-void HWNDMessageHandler::Init(const gfx::Rect& bounds) {
- GetMonitorAndRects(bounds.ToRECT(), &last_monitor_, &last_monitor_rect_,
- &last_work_area_);
-}
-
-gfx::Rect HWNDMessageHandler::GetRestoredBounds() const {
- // If we're in fullscreen mode, we've changed the normal bounds to the monitor
- // rect, so return the saved bounds instead.
- if (fullscreen_handler_->fullscreen())
- return fullscreen_handler_->GetRestoreBounds();
-
- gfx::Rect bounds;
- GetWindowPlacement(&bounds, NULL);
- return bounds;
-}
-
-void HWNDMessageHandler::GetWindowPlacement(
- gfx::Rect* bounds,
- ui::WindowShowState* show_state) const {
- WINDOWPLACEMENT wp;
- wp.length = sizeof(wp);
- const bool succeeded = !!::GetWindowPlacement(hwnd(), &wp);
- DCHECK(succeeded);
-
- if (bounds != NULL) {
- MONITORINFO mi;
- mi.cbSize = sizeof(mi);
- const bool succeeded = !!GetMonitorInfo(
- MonitorFromWindow(hwnd(), MONITOR_DEFAULTTONEAREST), &mi);
- DCHECK(succeeded);
- *bounds = gfx::Rect(wp.rcNormalPosition);
- // Convert normal position from workarea coordinates to screen coordinates.
- bounds->Offset(mi.rcWork.left - mi.rcMonitor.left,
- mi.rcWork.top - mi.rcMonitor.top);
- }
-
- if (show_state) {
- if (wp.showCmd == SW_SHOWMAXIMIZED)
- *show_state = ui::SHOW_STATE_MAXIMIZED;
- else if (wp.showCmd == SW_SHOWMINIMIZED)
- *show_state = ui::SHOW_STATE_MINIMIZED;
- else
- *show_state = ui::SHOW_STATE_NORMAL;
- }
-}
-
-
bool HWNDMessageHandler::IsVisible() const {
return !!::IsWindowVisible(hwnd());
}
@@ -599,89 +519,6 @@ LRESULT HWNDMessageHandler::OnNCActivate(BOOL active) {
WM_NCACTIVATE, inactive_rendering_disabled || active, 0);
}
-LRESULT HWNDMessageHandler::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 or when the NonClientFrameView
- // requests it, we want a custom width of 0.
- gfx::Insets insets = GetClientAreaInsets();
- if (insets.empty() && !fullscreen_handler_->fullscreen() &&
- !(mode && remove_standard_frame_)) {
- 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(hwnd(), 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 (GetTopmostAutoHideTaskbarForEdge(ABE_LEFT, monitor))
- client_rect->left += kAutoHideTaskbarThicknessPx;
- if (GetTopmostAutoHideTaskbarForEdge(ABE_TOP, monitor)) {
- if (!delegate_->IsUsingCustomFrame()) {
- // 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 (GetTopmostAutoHideTaskbarForEdge(ABE_RIGHT, monitor))
- client_rect->right -= kAutoHideTaskbarThicknessPx;
- if (GetTopmostAutoHideTaskbarForEdge(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 HWNDMessageHandler::OnNCHitTest(const CPoint& point) {
if (!delegate_->IsWidgetWindow()) {
SetMsgHandled(FALSE);
@@ -804,59 +641,6 @@ void HWNDMessageHandler::OnSize(UINT param, const CSize& size) {
ResetWindowRegion(false);
}
-void HWNDMessageHandler::OnSysCommand(UINT notification_code,
- const CPoint& point) {
- if (!delegate_->IsWidgetWindow())
- return;
-
- // Windows uses the 4 lower order bits of |notification_code| for type-
- // specific information so we must exclude this when comparing.
- static const int sc_mask = 0xFFF0;
- // Ignore size/move/maximize in fullscreen mode.
- if (fullscreen_handler_->fullscreen() &&
- (((notification_code & sc_mask) == SC_SIZE) ||
- ((notification_code & sc_mask) == SC_MOVE) ||
- ((notification_code & sc_mask) == SC_MAXIMIZE)))
- return;
- if (delegate_->IsUsingCustomFrame()) {
- if ((notification_code & sc_mask) == SC_MINIMIZE ||
- (notification_code & sc_mask) == SC_MAXIMIZE ||
- (notification_code & sc_mask) == SC_RESTORE) {
- delegate_->ResetWindowControls();
- } else if ((notification_code & sc_mask) == SC_MOVE ||
- (notification_code & sc_mask) == SC_SIZE) {
- if (!IsVisible()) {
- // Circumvent ScopedRedrawLocks and force visibility before entering a
- // resize or move modal loop to get continuous sizing/moving feedback.
- SetWindowLong(hwnd(), GWL_STYLE,
- GetWindowLong(hwnd(), GWL_STYLE) | WS_VISIBLE);
- }
- }
- }
-
- // Handle SC_KEYMENU, which means that the user has pressed the ALT
- // key and released it, so we should focus the menu bar.
- if ((notification_code & sc_mask) == SC_KEYMENU && point.x == 0) {
- int modifiers = ui::EF_NONE;
- if (base::win::IsShiftPressed())
- modifiers |= ui::EF_SHIFT_DOWN;
- if (base::win::IsCtrlPressed())
- modifiers |= ui::EF_CONTROL_DOWN;
- // Retrieve the status of shift and control keys to prevent consuming
- // shift+alt keys, which are used by Windows to change input languages.
- ui::Accelerator accelerator(ui::KeyboardCodeForWindowsKeyCode(VK_MENU),
- modifiers);
- delegate_->HandleAccelerator(accelerator);
- return;
- }
-
- // If the delegate can't handle it, the system implementation will be called.
- if (!delegate_->HandleCommand(notification_code)) {
- DefWindowProc(hwnd(), WM_SYSCOMMAND, notification_code,
- MAKELPARAM(point.x, point.y));
- }
-}
-
void HWNDMessageHandler::OnThemeChanged() {
ui::NativeThemeWin::instance()->CloseHandles();
}
@@ -886,94 +670,6 @@ void HWNDMessageHandler::OnVScroll(int scroll_type,
SetMsgHandled(FALSE);
}
-void HWNDMessageHandler::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(hwnd())) {
- CRect window_rect;
- HMONITOR monitor;
- gfx::Rect monitor_rect, work_area;
- if (GetWindowRect(hwnd(), &window_rect) &&
- GetMonitorAndRects(window_rect, &monitor, &monitor_rect, &work_area)) {
- bool work_area_changed = (monitor_rect == last_monitor_rect_) &&
- (work_area != last_work_area_);
- if (monitor && (monitor == last_monitor_) &&
- ((fullscreen_handler_->fullscreen() &&
- !fullscreen_handler_->metro_snap()) ||
- work_area_changed)) {
- // 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 (fullscreen_handler_->fullscreen()) {
- new_window_rect = monitor_rect;
- } else if (IsMaximized()) {
- 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_.HasWeakPtrs());
- MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(&HWNDMessageHandler::StopIgnoringPosChanges,
- ignore_pos_changes_factory_.GetWeakPtr()));
- }
- last_monitor_ = monitor;
- last_monitor_rect_ = monitor_rect;
- last_work_area_ = work_area;
- }
- }
-
- if (ScopedFullscreenVisibility::IsHiddenForFullscreen(hwnd())) {
- // 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.
- window_pos->flags &= ~SWP_SHOWWINDOW;
- }
-
- // When WM_WINDOWPOSCHANGING message is handled by DefWindowProc, it will
- // enforce (cx, cy) not to be smaller than (6, 6) for any non-popup window.
- // We work around this by changing cy back to our intended value.
- if (!GetParent(hwnd()) && !(window_pos->flags & SWP_NOSIZE) &&
- window_pos->cy < 6) {
- LONG old_cy = window_pos->cy;
- DefWindowProc(hwnd(), WM_WINDOWPOSCHANGING, 0,
- reinterpret_cast<LPARAM>(window_pos));
- window_pos->cy = old_cy;
- SetMsgHandled(TRUE);
- return;
- }
-
- SetMsgHandled(FALSE);
-}
-
void HWNDMessageHandler::OnWindowPosChanged(WINDOWPOS* window_pos) {
if (DidClientAreaSizeChange(window_pos))
ClientAreaSizeChanged();
@@ -1080,45 +776,6 @@ void HWNDMessageHandler::ClientAreaSizeChanged() {
delegate_->HandleClientSizeChanged(s);
}
-gfx::Insets HWNDMessageHandler::GetClientAreaInsets() const {
- gfx::Insets insets;
- if (delegate_->GetClientAreaInsets(&insets))
- return insets;
- DCHECK(insets.empty());
-
- // Returning an empty Insets object causes the default handling in
- // NativeWidgetWin::OnNCCalcSize() to be invoked.
- if (!delegate_->IsWidgetWindow() ||
- (!delegate_->IsUsingCustomFrame() && !remove_standard_frame_)) {
- return insets;
- }
-
- if (IsMaximized()) {
- // Windows automatically adds a standard width border to all sides when a
- // window is maximized.
- int border_thickness = GetSystemMetrics(SM_CXSIZEFRAME);
- return gfx::Insets(border_thickness, border_thickness, border_thickness,
- border_thickness);
- }
-
- // The hack below doesn't seem to be necessary when the standard frame is
- // removed.
- if (remove_standard_frame_)
- return insets;
- // This is weird, but highly essential. If we don't offset the bottom edge
- // of the client rect, the window client area and window area will match,
- // and when returning to glass rendering mode from non-glass, the client
- // area will not paint black as transparent. This is because (and I don't
- // know why) the client area goes from matching the window rect to being
- // something else. If the client area is not the window rect in both
- // modes, the blackness doesn't occur. Because of this, we need to tell
- // the RootView to lay out to fit the window rect, rather than the client
- // rect when using the opaque frame.
- // Note: this is only required for non-fullscreen windows. Note that
- // fullscreen windows are in restored state, not maximized.
- 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.
//