#include "ui/views/win/hwnd_message_handler.h"
#include <dwmapi.h>
+#include <oleacc.h>
#include <shellapi.h>
#include <wtsapi32.h>
#pragma comment(lib, "wtsapi32.lib")
#include "ui/native_theme/native_theme_win.h"
#include "ui/views/views_delegate.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/appbar.h"
#include "ui/views/win/fullscreen_handler.h"
// Create the window.
WindowImpl::Init(parent, bounds);
-
-#if defined(USE_AURA)
+ // TODO(ananta)
+ // Remove the scrolling hack code once we have scrolling working well.
+#if defined(ENABLE_SCROLL_HACK)
// Certain trackpad drivers on Windows have bugs where in they don't generate
// WM_MOUSEWHEEL messages for the trackpoint and trackpad scrolling gestures
// unless there is an entry for Chrome with the class name of the Window.
void HWNDMessageHandler::FrameTypeChanged() {
// Called when the frame type could possibly be changing (theme change or
// DWM composition change).
+ UpdateDwmNcRenderingPolicy();
// Don't redraw the window here, because we need to hide and show the window
// which will also trigger a redraw.
UINT flags = SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER;
SetWindowPos(hwnd(), NULL, 0, 0, 0, 0, flags | SWP_HIDEWINDOW);
SetWindowPos(hwnd(), NULL, 0, 0, 0, 0, flags | SWP_SHOWWINDOW);
-
- UpdateWindow(hwnd());
+ // Invalidate the window to force a paint. There may be child windows which
+ // could resize in this context. Don't paint right away.
+ ::InvalidateRect(hwnd(), NULL, FALSE);
}
// WM_DWMCOMPOSITIONCHANGED is only sent to top level windows, however we want
if (delegate_ && delegate_->PreHandleMSG(message, w_param, l_param, &result))
return result;
-#if !defined(USE_AURA)
- // First allow messages sent by child controls to be processed directly by
- // their associated views. If such a view is present, it will handle the
- // message *instead of* this NativeWidgetWin.
- if (ProcessChildWindowMessage(message, w_param, l_param, &result))
- return result;
-#endif
-
// Otherwise we handle everything else.
// NOTE: We inline ProcessWindowMessage() as 'this' may be destroyed during
// dispatch and ProcessWindowMessage() doesn't deal with that well.
if (delegate_)
delegate_->PostHandleMSG(message, w_param, l_param);
if (message == WM_NCDESTROY) {
-#if !defined(USE_AURA)
- base::MessageLoopForUI::current()->RemoveObserver(this);
-#endif
if (delegate_)
delegate_->HandleDestroyed();
}
}
////////////////////////////////////////////////////////////////////////////////
-// HWNDMessageHandler, MessageLoopForUI::Observer implementation:
-
-base::EventStatus HWNDMessageHandler::WillProcessEvent(
- const base::NativeEvent& event) {
- return base::EVENT_CONTINUE;
-}
-
-void HWNDMessageHandler::DidProcessEvent(const base::NativeEvent& event) {
- RedrawInvalidRect();
-}
-
-////////////////////////////////////////////////////////////////////////////////
// HWNDMessageHandler, private:
int HWNDMessageHandler::GetAppbarAutohideEdges(HMONITOR monitor) {
HRGN current_rgn = CreateRectRgn(0, 0, 0, 0);
int current_rgn_result = GetWindowRgn(hwnd(), current_rgn);
- CRect window_rect;
+ RECT window_rect;
GetWindowRect(hwnd(), &window_rect);
HRGN new_region;
if (custom_window_region_) {
MONITORINFO mi;
mi.cbSize = sizeof mi;
GetMonitorInfo(monitor, &mi);
- CRect work_rect = mi.rcWork;
- work_rect.OffsetRect(-window_rect.left, -window_rect.top);
+ RECT work_rect = mi.rcWork;
+ OffsetRect(&work_rect, -window_rect.left, -window_rect.top);
new_region = CreateRectRgnIndirect(&work_rect);
} else {
gfx::Path window_mask;
- delegate_->GetWindowMask(
- gfx::Size(window_rect.Width(), window_rect.Height()), &window_mask);
+ delegate_->GetWindowMask(gfx::Size(window_rect.right - window_rect.left,
+ window_rect.bottom - window_rect.top),
+ &window_mask);
new_region = gfx::CreateHRGNFromSkPath(window_mask);
}
void HWNDMessageHandler::UpdateDwmNcRenderingPolicy() {
if (base::win::GetVersion() < base::win::VERSION_VISTA)
return;
- DWMNCRENDERINGPOLICY policy = custom_window_region_ ? DWMNCRP_DISABLED
- : DWMNCRP_USEWINDOWSTYLE;
+
+ DWMNCRENDERINGPOLICY policy =
+ custom_window_region_ || delegate_->IsUsingCustomFrame() ?
+ DWMNCRP_DISABLED : DWMNCRP_ENABLED;
+
DwmSetWindowAttribute(hwnd(), DWMWA_NCRENDERING_POLICY,
&policy, sizeof(DWMNCRENDERINGPOLICY));
}
}
}
-void HWNDMessageHandler::RedrawInvalidRect() {
-// TODO(cpu): Remove the caller and this class as a message loop observer
-// because we don't need agressive repaints via RDW_UPDATENOW in Aura. The
-// general tracking bug for repaint issues is 177115.
-#if !defined(USE_AURA)
- if (!use_layered_buffer_) {
- RECT r = { 0, 0, 0, 0 };
- if (GetUpdateRect(hwnd(), &r, FALSE) && !IsRectEmpty(&r)) {
- RedrawWindow(hwnd(), &r, NULL,
- RDW_INVALIDATE | RDW_UPDATENOW | RDW_NOCHILDREN);
- }
- }
-#endif
-}
-
void HWNDMessageHandler::RedrawLayeredWindowContents() {
waiting_for_redraw_layered_window_contents_ = false;
if (invalid_rect_.IsEmpty())
// creation time.
ClientAreaSizeChanged();
-#if !defined(USE_AURA)
- // We need to add ourselves as a message loop observer so that we can repaint
- // aggressively if the contents of our window become invalid. Unfortunately
- // WM_PAINT messages are starved and we get flickery redrawing when resizing
- // if we do not do this.
- base::MessageLoopForUI::current()->AddObserver(this);
-#endif
-
delegate_->HandleCreate();
WTSRegisterSessionNotification(hwnd(), NOTIFY_FOR_THIS_SESSION);
}
void HWNDMessageHandler::OnDisplayChange(UINT bits_per_pixel,
- const CSize& screen_size) {
+ const gfx::Size& screen_size) {
delegate_->HandleDisplayChange();
}
// Add the native frame border size to the minimum and maximum size if the
// view reports its size as the client size.
if (delegate_->WidgetSizeIsClientSize()) {
- CRect client_rect, window_rect;
+ RECT client_rect, window_rect;
GetClientRect(hwnd(), &client_rect);
GetWindowRect(hwnd(), &window_rect);
- window_rect -= client_rect;
- min_window_size.Enlarge(window_rect.Width(), window_rect.Height());
- if (!max_window_size.IsEmpty())
- max_window_size.Enlarge(window_rect.Width(), window_rect.Height());
+ CR_DEFLATE_RECT(&window_rect, &client_rect);
+ min_window_size.Enlarge(window_rect.right - window_rect.left,
+ window_rect.bottom - window_rect.top);
+ if (!max_window_size.IsEmpty()) {
+ max_window_size.Enlarge(window_rect.right - window_rect.left,
+ window_rect.bottom - window_rect.top);
+ }
}
minmax_info->ptMinTrackSize.x = min_window_size.width();
minmax_info->ptMinTrackSize.y = min_window_size.height();
EnableMenuItemByCommand(menu, SC_SIZE, delegate_->CanResize() && is_restored);
EnableMenuItemByCommand(menu, SC_MAXIMIZE, delegate_->CanMaximize() &&
!is_fullscreen && !is_maximized);
- EnableMenuItemByCommand(menu, SC_MINIMIZE, !is_minimized);
+ // TODO: unfortunately, WidgetDelegate does not declare CanMinimize() and some
+ // code depends on this check, see http://crbug.com/341010.
+ EnableMenuItemByCommand(menu, SC_MINIMIZE, delegate_->CanMaximize() &&
+ !is_minimized);
if (is_maximized && delegate_->CanResize())
::SetMenuDefaultItem(menu, SC_RESTORE, FALSE);
// For mouse events (except wheel events), location is in window coordinates
// and should be converted to screen coordinates for WM_NCHITTEST.
if (message != WM_MOUSEWHEEL && message != WM_MOUSEHWHEEL) {
- CPoint screen_point(l_param_ht);
+ POINT screen_point = CR_POINT_INITIALIZER_FROM_LPARAM(l_param_ht);
MapWindowPoints(hwnd(), HWND_DESKTOP, &screen_point, 1);
l_param_ht = MAKELPARAM(screen_point.x, screen_point.y);
}
ReleaseCapture();
// |point| is in window coordinates, but WM_NCHITTEST and TrackPopupMenu()
// expect screen coordinates.
- CPoint screen_point(l_param);
+ POINT screen_point = CR_POINT_INITIALIZER_FROM_LPARAM(l_param);
MapWindowPoints(hwnd(), HWND_DESKTOP, &screen_point, 1);
w_param = SendMessage(hwnd(), WM_NCHITTEST, 0,
MAKELPARAM(screen_point.x, screen_point.y));
// be WM_RBUTTONUP instead of WM_NCRBUTTONUP.
SetCapture();
}
-
MSG msg = { hwnd(), message, w_param, l_param, GetMessageTime(),
- { GET_X_LPARAM(l_param), GET_Y_LPARAM(l_param) } };
+ { CR_GET_X_LPARAM(l_param), CR_GET_Y_LPARAM(l_param) } };
ui::MouseEvent event(msg);
if (!touch_ids_.empty() || ui::IsMouseEventFromTouch(message))
event.set_flags(event.flags() | ui::EF_FROM_TOUCH);
if (!(event.flags() & ui::EF_IS_NON_CLIENT))
delegate_->HandleTooltipMouseMove(message, w_param, l_param);
- if (event.type() == ui::ET_MOUSE_MOVED && !HasCapture()) {
+ // Certain child windows forward mouse events to us. We don't want to track
+ // these mouse moves as the child window will also send us a WM_MOUSELEAVE.
+ if (event.type() == ui::ET_MOUSE_MOVED && !HasCapture() &&
+ HIWORD(w_param) != SPECIAL_MOUSEMOVE_NOT_TO_BE_TRACKED) {
// Windows only fires WM_MOUSELEAVE events if the application begins
// "tracking" mouse events for a given HWND during WM_MOUSEMOVE events.
// We need to call |TrackMouseEvents| to listen for WM_MOUSELEAVE.
return 0;
}
-void HWNDMessageHandler::OnMove(const CPoint& point) {
+void HWNDMessageHandler::OnMove(const gfx::Point& point) {
delegate_->HandleMove();
SetMsgHandled(FALSE);
}
return mode ? WVR_REDRAW : 0;
}
-LRESULT HWNDMessageHandler::OnNCHitTest(const CPoint& point) {
+LRESULT HWNDMessageHandler::OnNCHitTest(const gfx::Point& point) {
if (!delegate_->IsWidgetWindow()) {
SetMsgHandled(FALSE);
return 0;
if (!remove_standard_frame_ && !delegate_->IsUsingCustomFrame()) {
LRESULT result;
if (DwmDefWindowProc(hwnd(), WM_NCHITTEST, 0,
- MAKELPARAM(point.x, point.y), &result)) {
+ MAKELPARAM(point.x(), point.y()), &result)) {
return result;
}
}
// First, give the NonClientView a chance to test the point to see if it
// provides any of the non-client area.
- POINT temp = point;
+ POINT temp = { point.x(), point.y() };
MapWindowPoints(HWND_DESKTOP, hwnd(), &temp, 1);
int component = delegate_->GetNonClientComponent(gfx::Point(temp));
if (component != HTNOWHERE)
// us.
#if defined(USE_AURA)
LRESULT hit_test_code = DefWindowProc(hwnd(), WM_NCHITTEST, 0,
- MAKELPARAM(point.x, point.y));
- // If we faked the WS_VSCROLL and WS_HSCROLL styles for this window, then
- // Windows returns the HTVSCROLL or HTHSCROLL hit test codes if we hover or
- // click on the non client portions of the window where the OS scrollbars
- // would be drawn. These hittest codes are returned even when the scrollbars
- // are hidden, which is the case in Aura. We fake the hittest code as
- // HTCLIENT in this case to ensure that we receive client mouse messages as
- // opposed to non client mouse messages.
- if (needs_scroll_styles_ && (hit_test_code == HTVSCROLL ||
- hit_test_code == HTHSCROLL))
- hit_test_code = HTCLIENT;
+ MAKELPARAM(point.x(), point.y()));
+ if (needs_scroll_styles_) {
+ switch (hit_test_code) {
+ // If we faked the WS_VSCROLL and WS_HSCROLL styles for this window, then
+ // Windows returns the HTVSCROLL or HTHSCROLL hit test codes if we hover
+ // or click on the non client portions of the window where the OS
+ // scrollbars would be drawn. These hittest codes are returned even when
+ // the scrollbars are hidden, which is the case in Aura. We fake the
+ // hittest code as HTCLIENT in this case to ensure that we receive client
+ // mouse messages as opposed to non client mouse messages.
+ case HTVSCROLL:
+ case HTHSCROLL:
+ hit_test_code = HTCLIENT;
+ break;
+
+ case HTBOTTOMRIGHT: {
+ // Normally the HTBOTTOMRIGHT hittest code is received when we hover
+ // near the bottom right of the window. However due to our fake scroll
+ // styles, we get this code even when we hover around the area where
+ // the vertical scrollar down arrow would be drawn.
+ // We check if the hittest coordinates lie in this region and if yes
+ // we return HTCLIENT.
+ int border_width = ::GetSystemMetrics(SM_CXSIZEFRAME);
+ int border_height = ::GetSystemMetrics(SM_CYSIZEFRAME);
+ int scroll_width = ::GetSystemMetrics(SM_CXVSCROLL);
+ int scroll_height = ::GetSystemMetrics(SM_CYVSCROLL);
+ RECT window_rect;
+ ::GetWindowRect(hwnd(), &window_rect);
+ window_rect.bottom -= border_height;
+ window_rect.right -= border_width;
+ window_rect.left = window_rect.right - scroll_width;
+ window_rect.top = window_rect.bottom - scroll_height;
+ POINT pt;
+ pt.x = point.x();
+ pt.y = point.y();
+ if (::PtInRect(&window_rect, pt))
+ hit_test_code = HTCLIENT;
+ break;
+ }
+
+ default:
+ break;
+ }
+ }
return hit_test_code;
#else
SetMsgHandled(FALSE);
// 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;
+ RECT window_rect;
GetWindowRect(hwnd(), &window_rect);
gfx::Size root_view_size = delegate_->GetRootViewSize();
- if (gfx::Size(window_rect.Width(), window_rect.Height()) != root_view_size) {
+ if (gfx::Size(window_rect.right - window_rect.left,
+ window_rect.bottom - window_rect.top) != root_view_size) {
// 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
return;
}
- CRect dirty_region;
+ RECT 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());
+ dirty_region.left = 0;
+ dirty_region.top = 0;
+ dirty_region.right = window_rect.right - window_rect.left;
+ dirty_region.bottom = window_rect.bottom - window_rect.top;
} else {
RECT rgn_bounding_box;
GetRgnBox(rgn, &rgn_bounding_box);
// 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;
+ RECT old_paint_region_crect = old_paint_region.ToRECT();
+ RECT tmp = dirty_region;
UnionRect(&dirty_region, &tmp, &old_paint_region_crect);
}
// the following in a block to force paint to occur so that we can release
// the dc.
if (!delegate_->HandlePaintAccelerated(gfx::Rect(dirty_region))) {
- gfx::CanvasSkiaPaint canvas(dc, true, dirty_region.left,
- dirty_region.top, dirty_region.Width(),
- dirty_region.Height());
+ gfx::CanvasSkiaPaint canvas(dc,
+ true,
+ dirty_region.left,
+ dirty_region.top,
+ dirty_region.right - dirty_region.left,
+ dirty_region.bottom - dirty_region.top);
delegate_->HandlePaint(&canvas);
}
}
}
-void HWNDMessageHandler::OnSize(UINT param, const CSize& size) {
+void HWNDMessageHandler::OnSize(UINT param, const gfx::Size& size) {
RedrawWindow(hwnd(), NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN);
// ResetWindowRegion is going to trigger WM_NCPAINT. By doing it after we've
// invoked OnSize we ensure the RootView has been laid out.
}
void HWNDMessageHandler::OnSysCommand(UINT notification_code,
- const CPoint& point) {
+ const gfx::Point& point) {
if (!delegate_->ShouldHandleSystemCommands())
return;
// 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) {
+ 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 ((notification_code & sc_mask) == SC_SIZE)
in_size_loop_ = true;
DefWindowProc(hwnd(), WM_SYSCOMMAND, notification_code,
- MAKELPARAM(point.x, point.y));
+ MAKELPARAM(point.x(), point.y()));
in_size_loop_ = false;
}
}
window_pos->flags &= ~(SWP_SHOWWINDOW | SWP_HIDEWINDOW);
}
} else if (!GetParent(hwnd())) {
- CRect window_rect;
+ RECT window_rect;
HMONITOR monitor;
gfx::Rect monitor_rect, work_area;
if (GetWindowRect(hwnd(), &window_rect) &&