OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "ui/views/widget/native_widget_win.h" |
| 6 |
| 7 #include "base/scoped_ptr.h" |
| 8 #include "gfx/canvas_skia.h" |
| 9 #include "gfx/path.h" |
| 10 #include "gfx/native_theme_win.h" |
| 11 #include "ui/base/system_monitor/system_monitor.h" |
| 12 #include "ui/base/view_prop.h" |
| 13 #include "ui/views/view.h" |
| 14 #include "ui/views/widget/native_widget_listener.h" |
| 15 #include "ui/views/widget/widget.h" |
| 16 |
| 17 namespace ui { |
| 18 namespace internal { |
| 19 |
| 20 namespace { |
| 21 |
| 22 // Called from NativeWidgetWin::Paint() to asynchronously redraw child windows. |
| 23 BOOL CALLBACK EnumChildProcForRedraw(HWND hwnd, LPARAM lparam) { |
| 24 DWORD process_id; |
| 25 GetWindowThreadProcessId(hwnd, &process_id); |
| 26 gfx::Rect invalid_rect = *reinterpret_cast<gfx::Rect*>(lparam); |
| 27 |
| 28 RECT window_rect; |
| 29 GetWindowRect(hwnd, &window_rect); |
| 30 invalid_rect.Offset(-window_rect.left, -window_rect.top); |
| 31 |
| 32 int flags = RDW_INVALIDATE | RDW_NOCHILDREN | RDW_FRAME; |
| 33 if (process_id == GetCurrentProcessId()) |
| 34 flags |= RDW_UPDATENOW; |
| 35 RedrawWindow(hwnd, &invalid_rect.ToRECT(), NULL, flags); |
| 36 return TRUE; |
| 37 } |
| 38 |
| 39 // Links the HWND to its Widget. |
| 40 const char* const kNativeWidgetKey = "__VIEWS_NATIVE_WIDGET__"; |
| 41 |
| 42 // A custom MSAA object id used to determine if a screen reader is actively |
| 43 // listening for MSAA events. |
| 44 const int kMSAAObjectID = 1; |
| 45 |
| 46 } |
| 47 |
| 48 //////////////////////////////////////////////////////////////////////////////// |
| 49 // NativeWidgetWin, public: |
| 50 |
| 51 NativeWidgetWin::NativeWidgetWin(NativeWidgetListener* listener) |
| 52 : listener_(listener), |
| 53 active_mouse_tracking_flags_(0), |
| 54 has_capture_(false) { |
| 55 } |
| 56 |
| 57 NativeWidgetWin::~NativeWidgetWin() { |
| 58 } |
| 59 |
| 60 //////////////////////////////////////////////////////////////////////////////// |
| 61 // NativeWidgetWin, NativeWidget implementation: |
| 62 |
| 63 void NativeWidgetWin::InitWithNativeViewParent(gfx::NativeView parent, |
| 64 const gfx::Rect& bounds) { |
| 65 WindowImpl::Init(parent, bounds); |
| 66 } |
| 67 |
| 68 void NativeWidgetWin::InitWithWidgetParent(Widget* parent, |
| 69 const gfx::Rect& bounds) { |
| 70 InitWithNativeViewParent(parent->native_widget()->GetNativeView(), bounds); |
| 71 } |
| 72 |
| 73 void NativeWidgetWin::InitWithViewParent(View* parent, |
| 74 const gfx::Rect& bounds) { |
| 75 InitWithWidgetParent(parent->GetWidget(), bounds); |
| 76 } |
| 77 |
| 78 void NativeWidgetWin::SetNativeWindowProperty(const char* name, void* value) { |
| 79 // Remove the existing property (if any). |
| 80 for (ViewProps::iterator i = props_.begin(); i != props_.end(); ++i) { |
| 81 if ((*i)->Key() == name) { |
| 82 props_.erase(i); |
| 83 break; |
| 84 } |
| 85 } |
| 86 |
| 87 if (value) |
| 88 props_.push_back(new ViewProp(hwnd(), name, value)); |
| 89 } |
| 90 |
| 91 void* NativeWidgetWin::GetNativeWindowProperty(const char* name) const { |
| 92 return ViewProp::GetValue(hwnd(), name); |
| 93 } |
| 94 |
| 95 gfx::Rect NativeWidgetWin::GetWindowScreenBounds() const { |
| 96 RECT r; |
| 97 GetWindowRect(hwnd(), &r); |
| 98 return gfx::Rect(r); |
| 99 } |
| 100 |
| 101 gfx::Rect NativeWidgetWin::GetClientAreaScreenBounds() const { |
| 102 RECT r; |
| 103 GetClientRect(hwnd(), &r); |
| 104 POINT point = { r.left, r.top }; |
| 105 ClientToScreen(hwnd(), &point); |
| 106 return gfx::Rect(point.x, point.y, r.right - r.left, r.bottom - r.top); |
| 107 } |
| 108 |
| 109 void NativeWidgetWin::SetBounds(const gfx::Rect& bounds) { |
| 110 SetWindowPos(hwnd(), NULL, bounds.x(), bounds.y(), bounds.width(), |
| 111 bounds.height(), SWP_NOACTIVATE | SWP_NOZORDER); |
| 112 } |
| 113 |
| 114 void NativeWidgetWin::SetShape(const gfx::Path& shape) { |
| 115 SetWindowRgn(hwnd(), shape.CreateNativeRegion(), TRUE); |
| 116 } |
| 117 |
| 118 gfx::NativeView NativeWidgetWin::GetNativeView() const { |
| 119 return hwnd(); |
| 120 } |
| 121 |
| 122 void NativeWidgetWin::Show() { |
| 123 if (IsWindow(hwnd())) |
| 124 ShowWindow(hwnd(), SW_SHOWNOACTIVATE); |
| 125 // TODO(beng): move to windowposchanging to trap visibility changes instead. |
| 126 if (IsLayeredWindow()) |
| 127 Invalidate(); |
| 128 } |
| 129 |
| 130 void NativeWidgetWin::Hide() { |
| 131 if (IsWindow(hwnd())) { |
| 132 // NOTE: Be careful not to activate any windows here (for example, calling |
| 133 // ShowWindow(SW_HIDE) will automatically activate another window). This |
| 134 // code can be called while a window is being deactivated, and activating |
| 135 // another window will screw up the activation that is already in progress. |
| 136 SetWindowPos(hwnd(), NULL, 0, 0, 0, 0, |
| 137 SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOMOVE | |
| 138 SWP_NOREPOSITION | SWP_NOSIZE | SWP_NOZORDER); |
| 139 } |
| 140 } |
| 141 |
| 142 void NativeWidgetWin::Close() { |
| 143 DestroyWindow(hwnd()); |
| 144 } |
| 145 |
| 146 void NativeWidgetWin::MoveAbove(NativeWidget* other) { |
| 147 SetWindowPos(hwnd(), other->GetNativeView(), 0, 0, 0, 0, |
| 148 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE); |
| 149 } |
| 150 |
| 151 void NativeWidgetWin::SetAlwaysOnTop(bool always_on_top) { |
| 152 DWORD style = always_on_top ? window_ex_style() | WS_EX_TOPMOST |
| 153 : window_ex_style() & ~WS_EX_TOPMOST; |
| 154 set_window_ex_style(style); |
| 155 SetWindowLong(hwnd(), GWL_EXSTYLE, window_ex_style()); |
| 156 } |
| 157 |
| 158 bool NativeWidgetWin::IsVisible() const { |
| 159 return !!IsWindowVisible(hwnd()); |
| 160 } |
| 161 |
| 162 bool NativeWidgetWin::IsActive() const { |
| 163 WINDOWINFO info; |
| 164 return ::GetWindowInfo(hwnd(), &info) && |
| 165 ((info.dwWindowStatus & WS_ACTIVECAPTION) != 0); |
| 166 } |
| 167 |
| 168 void NativeWidgetWin::SetMouseCapture() { |
| 169 SetCapture(hwnd()); |
| 170 has_capture_ = true; |
| 171 } |
| 172 |
| 173 void NativeWidgetWin::ReleaseMouseCapture() { |
| 174 ReleaseCapture(); |
| 175 has_capture_ = false; |
| 176 } |
| 177 |
| 178 bool NativeWidgetWin::HasMouseCapture() const { |
| 179 return has_capture_; |
| 180 } |
| 181 |
| 182 bool NativeWidgetWin::ShouldReleaseCaptureOnMouseReleased() const { |
| 183 return true; |
| 184 } |
| 185 |
| 186 void NativeWidgetWin::Invalidate() { |
| 187 ::InvalidateRect(hwnd(), NULL, FALSE); |
| 188 } |
| 189 |
| 190 void NativeWidgetWin::InvalidateRect(const gfx::Rect& invalid_rect) { |
| 191 // InvalidateRect() expects client coordinates. |
| 192 RECT r = invalid_rect.ToRECT(); |
| 193 ::InvalidateRect(hwnd(), &r, FALSE); |
| 194 } |
| 195 |
| 196 void NativeWidgetWin::Paint() { |
| 197 RECT r; |
| 198 GetUpdateRect(hwnd(), &r, FALSE); |
| 199 if (!IsRectEmpty(&r)) { |
| 200 // TODO(beng): WS_EX_TRANSPARENT windows (see WidgetWin::opaque_) |
| 201 // Paint child windows that are in a different process asynchronously. |
| 202 // This prevents a hang in other processes from blocking this process. |
| 203 |
| 204 // Calculate the invalid rect in screen coordinates before the first |
| 205 // RedrawWindow() call to the parent HWND, since that will empty update_rect |
| 206 // (which comes from a member variable) in the OnPaint call. |
| 207 gfx::Rect screen_rect = GetWindowScreenBounds(); |
| 208 gfx::Rect invalid_screen_rect(r); |
| 209 invalid_screen_rect.Offset(screen_rect.x(), screen_rect.y()); |
| 210 |
| 211 RedrawWindow(hwnd(), &r, NULL, |
| 212 RDW_INVALIDATE | RDW_UPDATENOW | RDW_NOCHILDREN); |
| 213 |
| 214 LPARAM lparam = reinterpret_cast<LPARAM>(&invalid_screen_rect); |
| 215 EnumChildWindows(hwnd(), EnumChildProcForRedraw, lparam); |
| 216 } |
| 217 } |
| 218 |
| 219 //////////////////////////////////////////////////////////////////////////////// |
| 220 // NativeWidetWin, MessageLoopForUI::Observer implementation |
| 221 |
| 222 void NativeWidgetWin::WillProcessMessage(const MSG& msg) { |
| 223 } |
| 224 |
| 225 void NativeWidgetWin::DidProcessMessage(const MSG& msg) { |
| 226 // We need to add ourselves as a message loop observer so that we can repaint |
| 227 // aggressively if the contents of our window become invalid. Unfortunately |
| 228 // WM_PAINT messages are starved and we get flickery redrawing when resizing |
| 229 // if we do not do this. |
| 230 Paint(); |
| 231 } |
| 232 |
| 233 //////////////////////////////////////////////////////////////////////////////// |
| 234 // NativeWidgetWin, message handlers: |
| 235 |
| 236 void NativeWidgetWin::OnActivate(UINT action, BOOL minimized, HWND window) { |
| 237 SetMsgHandled(FALSE); |
| 238 } |
| 239 |
| 240 void NativeWidgetWin::OnActivateApp(BOOL active, DWORD thread_id) { |
| 241 SetMsgHandled(FALSE); |
| 242 } |
| 243 |
| 244 LRESULT NativeWidgetWin::OnAppCommand(HWND window, short app_command, |
| 245 WORD device, int keystate) { |
| 246 SetMsgHandled(FALSE); |
| 247 return 0; |
| 248 } |
| 249 |
| 250 void NativeWidgetWin::OnCancelMode() { |
| 251 } |
| 252 |
| 253 void NativeWidgetWin::OnCaptureChanged(HWND hwnd) { |
| 254 has_capture_ = false; |
| 255 listener_->OnMouseCaptureLost(); |
| 256 } |
| 257 |
| 258 void NativeWidgetWin::OnClose() { |
| 259 listener_->OnClose(); |
| 260 } |
| 261 |
| 262 void NativeWidgetWin::OnCommand(UINT notification_code, int command_id, |
| 263 HWND window) { |
| 264 SetMsgHandled(FALSE); |
| 265 } |
| 266 |
| 267 LRESULT NativeWidgetWin::OnCreate(CREATESTRUCT* create_struct) { |
| 268 MessageLoopForUI::current()->AddObserver(this); |
| 269 return 0; |
| 270 } |
| 271 |
| 272 void NativeWidgetWin::OnDestroy() { |
| 273 // TODO(beng): drop_target_ |
| 274 props_.reset(); |
| 275 } |
| 276 |
| 277 void NativeWidgetWin::OnDisplayChange(UINT bits_per_pixel, CSize screen_size) { |
| 278 listener_->OnDisplayChanged(); |
| 279 } |
| 280 |
| 281 LRESULT NativeWidgetWin::OnDwmCompositionChanged(UINT message, |
| 282 WPARAM w_param, |
| 283 LPARAM l_param) { |
| 284 SetMsgHandled(FALSE); |
| 285 return 0; |
| 286 } |
| 287 |
| 288 void NativeWidgetWin::OnEndSession(BOOL ending, UINT logoff) { |
| 289 SetMsgHandled(FALSE); |
| 290 } |
| 291 |
| 292 void NativeWidgetWin::OnEnterSizeMove() { |
| 293 SetMsgHandled(FALSE); |
| 294 } |
| 295 |
| 296 LRESULT NativeWidgetWin::OnEraseBkgnd(HDC dc) { |
| 297 // This is needed for magical win32 flicker ju-ju |
| 298 return 1; |
| 299 } |
| 300 |
| 301 void NativeWidgetWin::OnExitMenuLoop(BOOL is_track_popup_menu) { |
| 302 SetMsgHandled(FALSE); |
| 303 } |
| 304 |
| 305 void NativeWidgetWin::OnExitSizeMove() { |
| 306 SetMsgHandled(FALSE); |
| 307 } |
| 308 |
| 309 LRESULT NativeWidgetWin::OnGetObject(UINT message, WPARAM w_param, |
| 310 LPARAM l_param) { |
| 311 return static_cast<LRESULT>(0L); |
| 312 } |
| 313 |
| 314 void NativeWidgetWin::OnGetMinMaxInfo(MINMAXINFO* minmax_info) { |
| 315 SetMsgHandled(FALSE); |
| 316 } |
| 317 |
| 318 void NativeWidgetWin::OnHScroll(int scroll_type, short position, |
| 319 HWND scrollbar) { |
| 320 SetMsgHandled(FALSE); |
| 321 } |
| 322 |
| 323 void NativeWidgetWin::OnInitMenu(HMENU menu) { |
| 324 SetMsgHandled(FALSE); |
| 325 } |
| 326 |
| 327 void NativeWidgetWin::OnInitMenuPopup(HMENU menu, UINT position, |
| 328 BOOL is_system_menu) { |
| 329 SetMsgHandled(FALSE); |
| 330 } |
| 331 |
| 332 LRESULT NativeWidgetWin::OnKeyDown(UINT message, WPARAM w_param, |
| 333 LPARAM l_param) { |
| 334 MSG msg; |
| 335 MakeMSG(&msg, message, w_param, l_param); |
| 336 SetMsgHandled(listener_->OnKeyEvent(KeyEvent(msg))); |
| 337 return 0; |
| 338 } |
| 339 |
| 340 LRESULT NativeWidgetWin::OnKeyUp(UINT message, WPARAM w_param, LPARAM l_param) { |
| 341 MSG msg; |
| 342 MakeMSG(&msg, message, w_param, l_param); |
| 343 SetMsgHandled(listener_->OnKeyEvent(KeyEvent(msg))); |
| 344 return 0; |
| 345 } |
| 346 |
| 347 void NativeWidgetWin::OnKillFocus(HWND focused_window) { |
| 348 // TODO(beng): focus |
| 349 SetMsgHandled(FALSE); |
| 350 } |
| 351 |
| 352 LRESULT NativeWidgetWin::OnMouseActivate(HWND window, UINT hittest_code, |
| 353 UINT message) { |
| 354 SetMsgHandled(FALSE); |
| 355 return MA_ACTIVATE; |
| 356 } |
| 357 |
| 358 LRESULT NativeWidgetWin::OnMouseLeave(UINT message, WPARAM w_param, |
| 359 LPARAM l_param) { |
| 360 // TODO(beng): tooltip |
| 361 MSG msg; |
| 362 MakeMSG(&msg, message, w_param, l_param); |
| 363 SetMsgHandled(listener_->OnMouseEvent(MouseEvent(msg))); |
| 364 |
| 365 // Reset our tracking flag so that future mouse movement over this WidgetWin |
| 366 // results in a new tracking session. |
| 367 active_mouse_tracking_flags_ = 0; |
| 368 |
| 369 return 0; |
| 370 } |
| 371 |
| 372 void NativeWidgetWin::OnMove(const CPoint& point) { |
| 373 SetMsgHandled(FALSE); |
| 374 } |
| 375 |
| 376 void NativeWidgetWin::OnMoving(UINT param, LPRECT new_bounds) { |
| 377 } |
| 378 |
| 379 LRESULT NativeWidgetWin::OnMouseRange(UINT message, WPARAM w_param, |
| 380 LPARAM l_param) { |
| 381 // TODO(beng): tooltips |
| 382 ProcessMouseRange(message, w_param, l_param, false); |
| 383 return 0; |
| 384 } |
| 385 |
| 386 LRESULT NativeWidgetWin::OnNCActivate(BOOL active) { |
| 387 SetMsgHandled(FALSE); |
| 388 return 0; |
| 389 } |
| 390 |
| 391 LRESULT NativeWidgetWin::OnNCCalcSize(BOOL w_param, LPARAM l_param) { |
| 392 SetMsgHandled(FALSE); |
| 393 return 0; |
| 394 } |
| 395 |
| 396 LRESULT NativeWidgetWin::OnNCHitTest(UINT message, WPARAM w_param, |
| 397 LPARAM l_param) { |
| 398 LRESULT lr = DefWindowProc(hwnd(), message, w_param, l_param); |
| 399 return lr; |
| 400 } |
| 401 |
| 402 LRESULT NativeWidgetWin::OnNCMouseRange(UINT message, WPARAM w_param, |
| 403 LPARAM l_param) { |
| 404 bool processed = ProcessMouseRange(message, w_param, l_param, true); |
| 405 SetMsgHandled(FALSE); |
| 406 return 0; |
| 407 } |
| 408 |
| 409 void NativeWidgetWin::OnNCPaint(HRGN rgn) { |
| 410 SetMsgHandled(FALSE); |
| 411 } |
| 412 |
| 413 LRESULT NativeWidgetWin::OnNCUAHDrawCaption(UINT message, |
| 414 WPARAM w_param, |
| 415 LPARAM l_param) { |
| 416 SetMsgHandled(FALSE); |
| 417 return 0; |
| 418 } |
| 419 |
| 420 LRESULT NativeWidgetWin::OnNCUAHDrawFrame(UINT message, |
| 421 WPARAM w_param, |
| 422 LPARAM l_param) { |
| 423 SetMsgHandled(FALSE); |
| 424 return 0; |
| 425 } |
| 426 |
| 427 LRESULT NativeWidgetWin::OnNotify(int w_param, NMHDR* l_param) { |
| 428 // TODO(beng): tooltips |
| 429 SetMsgHandled(FALSE); |
| 430 return 0; |
| 431 } |
| 432 |
| 433 void NativeWidgetWin::OnPaint(HDC dc) { |
| 434 if (IsLayeredWindow()) { |
| 435 // We need to clip to the dirty rect ourselves. |
| 436 window_contents_->save(SkCanvas::kClip_SaveFlag); |
| 437 RECT r; |
| 438 GetUpdateRect(hwnd(), &r, FALSE); |
| 439 window_contents_->ClipRectInt(r.left, r.top, r.right - r.left, |
| 440 r.bottom - r.top); |
| 441 listener_->OnPaint(window_contents_.get()); |
| 442 window_contents_->restore(); |
| 443 |
| 444 RECT wr; |
| 445 GetWindowRect(hwnd(), &wr); |
| 446 SIZE size = {wr.right - wr.left, wr.bottom - wr.top}; |
| 447 POINT position = {wr.left, wr.top}; |
| 448 HDC dib_dc = window_contents_->getTopPlatformDevice().getBitmapDC(); |
| 449 POINT zero = {0, 0}; |
| 450 BLENDFUNCTION blend = {AC_SRC_OVER, 0, 125, AC_SRC_ALPHA}; |
| 451 UpdateLayeredWindow(hwnd(), NULL, &position, &size, dib_dc, &zero, |
| 452 RGB(0xFF, 0xFF, 0xFF), &blend, ULW_ALPHA); |
| 453 } else { |
| 454 scoped_ptr<gfx::CanvasPaint> canvas( |
| 455 gfx::CanvasPaint::CreateCanvasPaint(hwnd())); |
| 456 listener_->OnPaint(canvas->AsCanvas()); |
| 457 } |
| 458 } |
| 459 |
| 460 LRESULT NativeWidgetWin::OnPowerBroadcast(DWORD power_event, DWORD data) { |
| 461 SystemMonitor* monitor = SystemMonitor::Get(); |
| 462 if (monitor) |
| 463 monitor->ProcessWmPowerBroadcastMessage(power_event); |
| 464 SetMsgHandled(FALSE); |
| 465 return 0; |
| 466 } |
| 467 |
| 468 LRESULT NativeWidgetWin::OnReflectedMessage(UINT message, WPARAM w_param, |
| 469 LPARAM l_param) { |
| 470 SetMsgHandled(FALSE); |
| 471 return 0; |
| 472 } |
| 473 |
| 474 void NativeWidgetWin::OnSetFocus(HWND focused_window) { |
| 475 // TODO(beng): focus |
| 476 SetMsgHandled(FALSE); |
| 477 } |
| 478 |
| 479 LRESULT NativeWidgetWin::OnSetIcon(UINT size_type, HICON new_icon) { |
| 480 SetMsgHandled(FALSE); |
| 481 return 0; |
| 482 } |
| 483 |
| 484 LRESULT NativeWidgetWin::OnSetText(const wchar_t* text) { |
| 485 SetMsgHandled(FALSE); |
| 486 return 0; |
| 487 } |
| 488 |
| 489 void NativeWidgetWin::OnSettingChange(UINT flags, const wchar_t* section) { |
| 490 if (flags == SPI_SETWORKAREA) |
| 491 listener_->OnWorkAreaChanged(); |
| 492 SetMsgHandled(FALSE); |
| 493 } |
| 494 |
| 495 void NativeWidgetWin::OnSize(UINT param, const CSize& size) { |
| 496 gfx::Size s(size.cx, size.cy); |
| 497 listener_->OnSizeChanged(s); |
| 498 if (IsLayeredWindow()) { |
| 499 window_contents_.reset( |
| 500 new gfx::CanvasSkia(s.width(), s.height(), false)); |
| 501 } |
| 502 } |
| 503 |
| 504 void NativeWidgetWin::OnSysCommand(UINT notification_code, CPoint click) { |
| 505 SetMsgHandled(FALSE); |
| 506 } |
| 507 |
| 508 void NativeWidgetWin::OnThemeChanged() { |
| 509 gfx::NativeTheme::instance()->CloseHandles(); |
| 510 } |
| 511 |
| 512 void NativeWidgetWin::OnVScroll(int scroll_type, short position, |
| 513 HWND scrollbar) { |
| 514 SetMsgHandled(FALSE); |
| 515 } |
| 516 |
| 517 void NativeWidgetWin::OnWindowPosChanging(WINDOWPOS* window_pos) { |
| 518 SetMsgHandled(FALSE); |
| 519 } |
| 520 |
| 521 void NativeWidgetWin::OnWindowPosChanged(WINDOWPOS* window_pos) { |
| 522 SetMsgHandled(FALSE); |
| 523 } |
| 524 |
| 525 void NativeWidgetWin::OnFinalMessage(HWND window) { |
| 526 delete this; |
| 527 } |
| 528 |
| 529 //////////////////////////////////////////////////////////////////////////////// |
| 530 // NativeWidgetWin, WindowImpl overrides: |
| 531 |
| 532 HICON NativeWidgetWin::GetDefaultWindowIcon() const { |
| 533 return NULL; |
| 534 } |
| 535 |
| 536 LRESULT NativeWidgetWin::OnWndProc(UINT message, WPARAM w_param, |
| 537 LPARAM l_param) { |
| 538 LRESULT result = 0; |
| 539 |
| 540 // Otherwise we handle everything else. |
| 541 if (!ProcessWindowMessage(hwnd(), message, w_param, l_param, result)) |
| 542 result = DefWindowProc(hwnd(), message, w_param, l_param); |
| 543 if (message == WM_NCDESTROY) { |
| 544 MessageLoopForUI::current()->RemoveObserver(this); |
| 545 OnFinalMessage(hwnd()); |
| 546 } |
| 547 return result; |
| 548 } |
| 549 |
| 550 //////////////////////////////////////////////////////////////////////////////// |
| 551 // NativeWidgetWin, private: |
| 552 |
| 553 void NativeWidgetWin::TrackMouseEvents(DWORD mouse_tracking_flags) { |
| 554 // Begin tracking mouse events for this HWND so that we get WM_MOUSELEAVE |
| 555 // when the user moves the mouse outside this HWND's bounds. |
| 556 if (active_mouse_tracking_flags_ == 0 || mouse_tracking_flags & TME_CANCEL) { |
| 557 if (mouse_tracking_flags & TME_CANCEL) { |
| 558 // We're about to cancel active mouse tracking, so empty out the stored |
| 559 // state. |
| 560 active_mouse_tracking_flags_ = 0; |
| 561 } else { |
| 562 active_mouse_tracking_flags_ = mouse_tracking_flags; |
| 563 } |
| 564 |
| 565 TRACKMOUSEEVENT tme; |
| 566 tme.cbSize = sizeof(tme); |
| 567 tme.dwFlags = mouse_tracking_flags; |
| 568 tme.hwndTrack = hwnd(); |
| 569 tme.dwHoverTime = 0; |
| 570 TrackMouseEvent(&tme); |
| 571 } else if (mouse_tracking_flags != active_mouse_tracking_flags_) { |
| 572 TrackMouseEvents(active_mouse_tracking_flags_ | TME_CANCEL); |
| 573 TrackMouseEvents(mouse_tracking_flags); |
| 574 } |
| 575 } |
| 576 |
| 577 bool NativeWidgetWin::ProcessMouseRange(UINT message, WPARAM w_param, |
| 578 LPARAM l_param, bool non_client) { |
| 579 MSG msg; |
| 580 MakeMSG(&msg, message, w_param, l_param); |
| 581 if (message == WM_MOUSEWHEEL) { |
| 582 // Reroute the mouse-wheel to the window under the mouse pointer if |
| 583 // applicable. |
| 584 // TODO(beng): |
| 585 //if (views::RerouteMouseWheel(hwnd(), w_param, l_param)) |
| 586 // return 0; |
| 587 return listener_->OnMouseWheelEvent(MouseWheelEvent(msg)); |
| 588 } |
| 589 // Windows only fires WM_MOUSELEAVE events if the application begins |
| 590 // "tracking" mouse events for a given HWND during WM_MOUSEMOVE events. |
| 591 // We need to call |TrackMouseEvents| to listen for WM_MOUSELEAVE. |
| 592 if (!has_capture_) |
| 593 TrackMouseEvents(non_client ? TME_NONCLIENT | TME_LEAVE : TME_LEAVE); |
| 594 return listener_->OnMouseEvent(MouseEvent(msg)); |
| 595 } |
| 596 |
| 597 void NativeWidgetWin::MakeMSG(MSG* msg, UINT message, WPARAM w_param, |
| 598 LPARAM l_param) const { |
| 599 msg->hwnd = hwnd(); |
| 600 msg->message = message; |
| 601 msg->wParam = w_param; |
| 602 msg->lParam = l_param; |
| 603 msg->time = 0; |
| 604 msg->pt.x = msg->pt.y = 0; |
| 605 } |
| 606 |
| 607 void NativeWidgetWin::CloseNow() { |
| 608 DestroyWindow(hwnd()); |
| 609 } |
| 610 |
| 611 bool NativeWidgetWin::IsLayeredWindow() const { |
| 612 return !!(window_ex_style() & WS_EX_LAYERED); |
| 613 } |
| 614 |
| 615 } // namespace internal |
| 616 |
| 617 //////////////////////////////////////////////////////////////////////////////// |
| 618 // NativeWidget, public: |
| 619 |
| 620 // static |
| 621 NativeWidget* NativeWidget::CreateNativeWidget( |
| 622 internal::NativeWidgetListener* listener) { |
| 623 return new internal::NativeWidgetWin(listener); |
| 624 } |
| 625 |
| 626 } // namespace ui |
OLD | NEW |