Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(90)

Side by Side Diff: ui/views/win/hwnd_message_handler.cc

Issue 10827454: Move more methods from NWW to HWNDMessageHandler. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ui/views/win/hwnd_message_handler.h ('k') | ui/views/win/hwnd_message_handler_delegate.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/views/win/hwnd_message_handler.h" 5 #include "ui/views/win/hwnd_message_handler.h"
6 6
7 #include <dwmapi.h> 7 #include <dwmapi.h>
8 8
9 #include "base/system_monitor/system_monitor.h" 9 #include "base/system_monitor/system_monitor.h"
10 #include "base/win/windows_version.h" 10 #include "base/win/windows_version.h"
11 #include "ui/gfx/path.h" 11 #include "ui/gfx/path.h"
12 #include "ui/base/event.h"
12 #include "ui/base/native_theme/native_theme_win.h" 13 #include "ui/base/native_theme/native_theme_win.h"
14 #include "ui/base/win/hwnd_util.h"
15 #include "ui/base/win/mouse_wheel_util.h"
16 #include "ui/base/win/shell.h"
13 #include "ui/views/ime/input_method_win.h" 17 #include "ui/views/ime/input_method_win.h"
14 #include "ui/views/widget/native_widget_win.h" 18 #include "ui/views/widget/native_widget_win.h"
19 #include "ui/views/widget/widget_hwnd_utils.h"
15 #include "ui/views/win/hwnd_message_handler_delegate.h" 20 #include "ui/views/win/hwnd_message_handler_delegate.h"
16 21
22 #if !defined(USE_AURA)
23 #include "base/command_line.h"
24 #include "ui/base/ui_base_switches.h"
25 #endif
26
17 namespace views { 27 namespace views {
18 namespace { 28 namespace {
19 29
20 // Called from OnNCActivate. 30 // Called from OnNCActivate.
21 BOOL CALLBACK EnumChildWindowsForRedraw(HWND hwnd, LPARAM lparam) { 31 BOOL CALLBACK EnumChildWindowsForRedraw(HWND hwnd, LPARAM lparam) {
22 DWORD process_id; 32 DWORD process_id;
23 GetWindowThreadProcessId(hwnd, &process_id); 33 GetWindowThreadProcessId(hwnd, &process_id);
24 int flags = RDW_INVALIDATE | RDW_NOCHILDREN | RDW_FRAME; 34 int flags = RDW_INVALIDATE | RDW_NOCHILDREN | RDW_FRAME;
25 if (process_id == GetCurrentProcessId()) 35 if (process_id == GetCurrentProcessId())
26 flags |= RDW_UPDATENOW; 36 flags |= RDW_UPDATENOW;
27 RedrawWindow(hwnd, NULL, NULL, flags); 37 RedrawWindow(hwnd, NULL, NULL, flags);
28 return TRUE; 38 return TRUE;
29 } 39 }
30 40
31 // A custom MSAA object id used to determine if a screen reader is actively 41 // A custom MSAA object id used to determine if a screen reader is actively
32 // listening for MSAA events. 42 // listening for MSAA events.
33 const int kCustomObjectID = 1; 43 const int kCustomObjectID = 1;
34 44
35 } // namespace 45 } // namespace
36 46
37 //////////////////////////////////////////////////////////////////////////////// 47 ////////////////////////////////////////////////////////////////////////////////
38 // HWNDMessageHandler, public: 48 // HWNDMessageHandler, public:
39 49
40 HWNDMessageHandler::HWNDMessageHandler(HWNDMessageHandlerDelegate* delegate) 50 HWNDMessageHandler::HWNDMessageHandler(HWNDMessageHandlerDelegate* delegate)
41 : delegate_(delegate), 51 : delegate_(delegate),
42 remove_standard_frame_(false) { 52 remove_standard_frame_(false),
53 active_mouse_tracking_flags_(0),
54 is_right_mouse_pressed_on_caption_(false),
55 lock_updates_count_(0),
56 destroyed_(NULL) {
43 } 57 }
44 58
45 HWNDMessageHandler::~HWNDMessageHandler() { 59 HWNDMessageHandler::~HWNDMessageHandler() {
60 if (destroyed_ != NULL)
61 *destroyed_ = true;
62 }
63
64 bool HWNDMessageHandler::IsVisible() const {
65 return !!::IsWindowVisible(hwnd());
46 } 66 }
47 67
48 bool HWNDMessageHandler::IsActive() const { 68 bool HWNDMessageHandler::IsActive() const {
49 return GetActiveWindow() == hwnd(); 69 return GetActiveWindow() == hwnd();
50 } 70 }
51 71
52 bool HWNDMessageHandler::IsVisible() const { 72 bool HWNDMessageHandler::IsMinimized() const {
53 return !!::IsWindowVisible(hwnd()); 73 return !!::IsIconic(hwnd());
74 }
75
76 bool HWNDMessageHandler::IsMaximized() const {
77 return !!::IsZoomed(hwnd());
54 } 78 }
55 79
56 void HWNDMessageHandler::SendFrameChanged() { 80 void HWNDMessageHandler::SendFrameChanged() {
57 SetWindowPos(hwnd(), NULL, 0, 0, 0, 0, 81 SetWindowPos(hwnd(), NULL, 0, 0, 0, 0,
58 SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOCOPYBITS | 82 SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOCOPYBITS |
59 SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOREPOSITION | 83 SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOREPOSITION |
60 SWP_NOSENDCHANGING | SWP_NOSIZE | SWP_NOZORDER); 84 SWP_NOSENDCHANGING | SWP_NOSIZE | SWP_NOZORDER);
61 } 85 }
62 86
87 void HWNDMessageHandler::SetCapture() {
88 DCHECK(!HasCapture());
89 ::SetCapture(hwnd());
90 }
91
92 void HWNDMessageHandler::ReleaseCapture() {
93 ::ReleaseCapture();
94 }
95
96 bool HWNDMessageHandler::HasCapture() const {
97 return ::GetCapture() == hwnd();
98 }
99
100 InputMethod* HWNDMessageHandler::CreateInputMethod() {
101 #if !defined(USE_AURA)
102 CommandLine* command_line = CommandLine::ForCurrentProcess();
103 if (!command_line->HasSwitch(switches::kEnableViewsTextfield))
104 return NULL;
105 #endif
106 return new InputMethodWin(this);
107 }
108
63 void HWNDMessageHandler::OnActivate(UINT action, BOOL minimized, HWND window) { 109 void HWNDMessageHandler::OnActivate(UINT action, BOOL minimized, HWND window) {
64 SetMsgHandled(FALSE); 110 SetMsgHandled(FALSE);
65 } 111 }
66 112
67 void HWNDMessageHandler::OnActivateApp(BOOL active, DWORD thread_id) { 113 void HWNDMessageHandler::OnActivateApp(BOOL active, DWORD thread_id) {
68 if (delegate_->IsWidgetWindow() && !active && 114 if (delegate_->IsWidgetWindow() && !active &&
69 thread_id != GetCurrentThreadId()) { 115 thread_id != GetCurrentThreadId()) {
70 delegate_->HandleAppDeactivated(); 116 delegate_->HandleAppDeactivated();
71 // Also update the native frame if it is rendering the non-client area. 117 // Also update the native frame if it is rendering the non-client area.
72 if (!remove_standard_frame_ && !delegate_->IsUsingCustomFrame()) 118 if (!remove_standard_frame_ && !delegate_->IsUsingCustomFrame())
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
127 GetWindowLong(hwnd(), GWL_STYLE) & ~WS_CAPTION); 173 GetWindowLong(hwnd(), GWL_STYLE) & ~WS_CAPTION);
128 SendFrameChanged(); 174 SendFrameChanged();
129 } 175 }
130 176
131 // Get access to a modifiable copy of the system menu. 177 // Get access to a modifiable copy of the system menu.
132 GetSystemMenu(hwnd(), false); 178 GetSystemMenu(hwnd(), false);
133 179
134 if (base::win::GetVersion() >= base::win::VERSION_WIN7) 180 if (base::win::GetVersion() >= base::win::VERSION_WIN7)
135 RegisterTouchWindow(hwnd(), 0); 181 RegisterTouchWindow(hwnd(), 0);
136 182
183 // We need to allow the delegate to size its contents since the window may not
184 // receive a size notification when its initial bounds are specified at window
185 // creation time.
186 ClientAreaSizeChanged();
187
137 delegate_->HandleCreate(); 188 delegate_->HandleCreate();
138 189
139 // TODO(beng): move more of NWW::OnCreate here. 190 // TODO(beng): move more of NWW::OnCreate here.
140 return 0; 191 return 0;
141 } 192 }
142 193
143 void HWNDMessageHandler::OnDestroy() { 194 void HWNDMessageHandler::OnDestroy() {
144 delegate_->HandleDestroy(); 195 delegate_->HandleDestroy();
145 } 196 }
146 197
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 308
258 InputMethodWin* ime_win = static_cast<InputMethodWin*>(input_method); 309 InputMethodWin* ime_win = static_cast<InputMethodWin*>(input_method);
259 BOOL handled = FALSE; 310 BOOL handled = FALSE;
260 LRESULT result = ime_win->OnImeMessages(message, w_param, l_param, &handled); 311 LRESULT result = ime_win->OnImeMessages(message, w_param, l_param, &handled);
261 SetMsgHandled(handled); 312 SetMsgHandled(handled);
262 return result; 313 return result;
263 } 314 }
264 315
265 void HWNDMessageHandler::OnInitMenu(HMENU menu) { 316 void HWNDMessageHandler::OnInitMenu(HMENU menu) {
266 bool is_fullscreen = delegate_->AsNativeWidgetWin()->IsFullscreen(); 317 bool is_fullscreen = delegate_->AsNativeWidgetWin()->IsFullscreen();
267 bool is_minimized = delegate_->AsNativeWidgetWin()->IsMinimized(); 318 bool is_minimized = IsMinimized();
268 bool is_maximized = delegate_->AsNativeWidgetWin()->IsMaximized(); 319 bool is_maximized = IsMaximized();
269 bool is_restored = !is_fullscreen && !is_minimized && !is_maximized; 320 bool is_restored = !is_fullscreen && !is_minimized && !is_maximized;
270 321
271 EnableMenuItem(menu, SC_RESTORE, is_minimized || is_maximized); 322 EnableMenuItem(menu, SC_RESTORE, is_minimized || is_maximized);
272 EnableMenuItem(menu, SC_MOVE, is_restored); 323 EnableMenuItem(menu, SC_MOVE, is_restored);
273 EnableMenuItem(menu, SC_SIZE, delegate_->CanResize() && is_restored); 324 EnableMenuItem(menu, SC_SIZE, delegate_->CanResize() && is_restored);
274 EnableMenuItem(menu, SC_MAXIMIZE, delegate_->CanMaximize() && 325 EnableMenuItem(menu, SC_MAXIMIZE, delegate_->CanMaximize() &&
275 !is_fullscreen && !is_maximized); 326 !is_fullscreen && !is_maximized);
276 EnableMenuItem(menu, SC_MINIMIZE, delegate_->CanMaximize() && !is_minimized); 327 EnableMenuItem(menu, SC_MINIMIZE, delegate_->CanMaximize() && !is_minimized);
277 } 328 }
278 329
(...skipping 12 matching lines...) Expand all
291 342
292 LRESULT HWNDMessageHandler::OnKeyEvent(UINT message, 343 LRESULT HWNDMessageHandler::OnKeyEvent(UINT message,
293 WPARAM w_param, 344 WPARAM w_param,
294 LPARAM l_param) { 345 LPARAM l_param) {
295 MSG msg = { hwnd(), message, w_param, l_param }; 346 MSG msg = { hwnd(), message, w_param, l_param };
296 ui::KeyEvent key(msg, message == WM_CHAR); 347 ui::KeyEvent key(msg, message == WM_CHAR);
297 InputMethod* input_method = delegate_->GetInputMethod(); 348 InputMethod* input_method = delegate_->GetInputMethod();
298 if (input_method) 349 if (input_method)
299 input_method->DispatchKeyEvent(key); 350 input_method->DispatchKeyEvent(key);
300 else 351 else
301 delegate_->AsNativeWidgetWin()->DispatchKeyEventPostIME(key); 352 DispatchKeyEventPostIME(key);
302 return 0; 353 return 0;
303 } 354 }
304 355
305 void HWNDMessageHandler::OnKillFocus(HWND focused_window) { 356 void HWNDMessageHandler::OnKillFocus(HWND focused_window) {
306 delegate_->HandleNativeBlur(focused_window); 357 delegate_->HandleNativeBlur(focused_window);
307 358
308 InputMethod* input_method = delegate_->GetInputMethod(); 359 InputMethod* input_method = delegate_->GetInputMethod();
309 if (input_method) 360 if (input_method)
310 input_method->OnBlur(); 361 input_method->OnBlur();
311 SetMsgHandled(FALSE); 362 SetMsgHandled(FALSE);
312 } 363 }
313 364
314 LRESULT HWNDMessageHandler::OnMouseActivate(UINT message, 365 LRESULT HWNDMessageHandler::OnMouseActivate(UINT message,
315 WPARAM w_param, 366 WPARAM w_param,
316 LPARAM l_param) { 367 LPARAM l_param) {
317 // TODO(beng): resolve this with the GetWindowLong() check on the subsequent 368 // TODO(beng): resolve this with the GetWindowLong() check on the subsequent
318 // line. 369 // line.
319 if (delegate_->IsWidgetWindow()) 370 if (delegate_->IsWidgetWindow())
320 return delegate_->CanActivate() ? MA_ACTIVATE : MA_NOACTIVATEANDEAT; 371 return delegate_->CanActivate() ? MA_ACTIVATE : MA_NOACTIVATEANDEAT;
321 if (GetWindowLong(hwnd(), GWL_EXSTYLE) & WS_EX_NOACTIVATE) 372 if (GetWindowLong(hwnd(), GWL_EXSTYLE) & WS_EX_NOACTIVATE)
322 return MA_NOACTIVATE; 373 return MA_NOACTIVATE;
323 SetMsgHandled(FALSE); 374 SetMsgHandled(FALSE);
324 return MA_ACTIVATE; 375 return MA_ACTIVATE;
325 } 376 }
326 377
378 LRESULT HWNDMessageHandler::OnMouseRange(UINT message,
379 WPARAM w_param,
380 LPARAM l_param) {
381 if (message == WM_RBUTTONUP && is_right_mouse_pressed_on_caption_) {
382 is_right_mouse_pressed_on_caption_ = false;
383 ReleaseCapture();
384 // |point| is in window coordinates, but WM_NCHITTEST and TrackPopupMenu()
385 // expect screen coordinates.
386 CPoint screen_point(l_param);
387 MapWindowPoints(hwnd(), HWND_DESKTOP, &screen_point, 1);
388 w_param = SendMessage(hwnd(), WM_NCHITTEST, 0,
389 MAKELPARAM(screen_point.x, screen_point.y));
390 if (w_param == HTCAPTION || w_param == HTSYSMENU) {
391 ui::ShowSystemMenu(hwnd(), screen_point.x, screen_point.y);
392 return 0;
393 }
394 } else if (message == WM_NCLBUTTONDOWN && delegate_->IsUsingCustomFrame()) {
395 switch (w_param) {
396 case HTCLOSE:
397 case HTMINBUTTON:
398 case HTMAXBUTTON: {
399 // When the mouse is pressed down in these specific non-client areas,
400 // we need to tell the RootView to send the mouse pressed event (which
401 // sets capture, allowing subsequent WM_LBUTTONUP (note, _not_
402 // WM_NCLBUTTONUP) to fire so that the appropriate WM_SYSCOMMAND can be
403 // sent by the applicable button's ButtonListener. We _have_ to do this
404 // way rather than letting Windows just send the syscommand itself (as
405 // would happen if we never did this dance) because for some insane
406 // reason DefWindowProc for WM_NCLBUTTONDOWN also renders the pressed
407 // window control button appearance, in the Windows classic style, over
408 // our view! Ick! By handling this message we prevent Windows from
409 // doing this undesirable thing, but that means we need to roll the
410 // sys-command handling ourselves.
411 // Combine |w_param| with common key state message flags.
412 w_param |= base::win::IsCtrlPressed() ? MK_CONTROL : 0;
413 w_param |= base::win::IsShiftPressed() ? MK_SHIFT : 0;
414 }
415 }
416 } else if (message == WM_NCRBUTTONDOWN &&
417 (w_param == HTCAPTION || w_param == HTSYSMENU)) {
418 is_right_mouse_pressed_on_caption_ = true;
419 // We SetCapture() to ensure we only show the menu when the button
420 // down and up are both on the caption. Note: this causes the button up to
421 // be WM_RBUTTONUP instead of WM_NCRBUTTONUP.
422 SetCapture();
423 }
424
425 MSG msg = { hwnd(), message, w_param, l_param, 0,
426 { GET_X_LPARAM(l_param), GET_Y_LPARAM(l_param) } };
427 ui::MouseEvent event(msg);
428 if (!touch_ids_.empty() || ui::IsMouseEventFromTouch(message))
429 event.set_flags(event.flags() | ui::EF_FROM_TOUCH);
430
431 if (!(event.flags() & ui::EF_IS_NON_CLIENT))
432 delegate_->HandleTooltipMouseMove(message, w_param, l_param);
433
434 if (event.type() == ui::ET_MOUSE_MOVED && !HasCapture()) {
435 // Windows only fires WM_MOUSELEAVE events if the application begins
436 // "tracking" mouse events for a given HWND during WM_MOUSEMOVE events.
437 // We need to call |TrackMouseEvents| to listen for WM_MOUSELEAVE.
438 TrackMouseEvents((message == WM_NCMOUSEMOVE) ?
439 TME_NONCLIENT | TME_LEAVE : TME_LEAVE);
440 } else if (event.type() == ui::ET_MOUSE_EXITED) {
441 // Reset our tracking flags so future mouse movement over this
442 // NativeWidgetWin results in a new tracking session. Fall through for
443 // OnMouseEvent.
444 active_mouse_tracking_flags_ = 0;
445 } else if (event.type() == ui::ET_MOUSEWHEEL) {
446 // Reroute the mouse wheel to the window under the pointer if applicable.
447 return (ui::RerouteMouseWheel(hwnd(), w_param, l_param) ||
448 delegate_->HandleMouseEvent(ui::MouseWheelEvent(msg))) ? 0 : 1;
449 }
450
451 bool handled = delegate_->HandleMouseEvent(event);
452 if (!handled && message == WM_NCLBUTTONDOWN && w_param != HTSYSMENU &&
453 delegate_->IsUsingCustomFrame()) {
454 // TODO(msw): Eliminate undesired painting, or re-evaluate this workaround.
455 // DefWindowProc for WM_NCLBUTTONDOWN does weird non-client painting, so we
456 // need to call it inside a ScopedRedrawLock. This may cause other negative
457 // side-effects (ex/ stifling non-client mouse releases).
458 DefWindowProcWithRedrawLock(message, w_param, l_param);
459 handled = true;
460 }
461
462 SetMsgHandled(handled);
463 return 0;
464 }
465
327 void HWNDMessageHandler::OnMove(const CPoint& point) { 466 void HWNDMessageHandler::OnMove(const CPoint& point) {
328 delegate_->HandleMove(); 467 delegate_->HandleMove();
329 SetMsgHandled(FALSE); 468 SetMsgHandled(FALSE);
330 } 469 }
331 470
332 void HWNDMessageHandler::OnMoving(UINT param, const RECT* new_bounds) { 471 void HWNDMessageHandler::OnMoving(UINT param, const RECT* new_bounds) {
333 delegate_->HandleMove(); 472 delegate_->HandleMove();
334 } 473 }
335 474
336 LRESULT HWNDMessageHandler::OnNCActivate(BOOL active) { 475 LRESULT HWNDMessageHandler::OnNCActivate(BOOL active) {
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
499 RedrawWindow(hwnd(), NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN); 638 RedrawWindow(hwnd(), NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN);
500 // ResetWindowRegion is going to trigger WM_NCPAINT. By doing it after we've 639 // ResetWindowRegion is going to trigger WM_NCPAINT. By doing it after we've
501 // invoked OnSize we ensure the RootView has been laid out. 640 // invoked OnSize we ensure the RootView has been laid out.
502 ResetWindowRegion(false); 641 ResetWindowRegion(false);
503 } 642 }
504 643
505 void HWNDMessageHandler::OnThemeChanged() { 644 void HWNDMessageHandler::OnThemeChanged() {
506 ui::NativeThemeWin::instance()->CloseHandles(); 645 ui::NativeThemeWin::instance()->CloseHandles();
507 } 646 }
508 647
648 LRESULT HWNDMessageHandler::OnTouchEvent(UINT message,
649 WPARAM w_param,
650 LPARAM l_param) {
651 int num_points = LOWORD(w_param);
652 scoped_array<TOUCHINPUT> input(new TOUCHINPUT[num_points]);
653 if (GetTouchInputInfo(reinterpret_cast<HTOUCHINPUT>(l_param),
654 num_points, input.get(), sizeof(TOUCHINPUT))) {
655 for (int i = 0; i < num_points; ++i) {
656 if (input[i].dwFlags & TOUCHEVENTF_DOWN)
657 touch_ids_.insert(input[i].dwID);
658 if (input[i].dwFlags & TOUCHEVENTF_UP)
659 touch_ids_.erase(input[i].dwID);
660 }
661 }
662 CloseTouchInputHandle(reinterpret_cast<HTOUCHINPUT>(l_param));
663 SetMsgHandled(FALSE);
664 return 0;
665 }
666
509 void HWNDMessageHandler::OnVScroll(int scroll_type, 667 void HWNDMessageHandler::OnVScroll(int scroll_type,
510 short position, 668 short position,
511 HWND scrollbar) { 669 HWND scrollbar) {
512 SetMsgHandled(FALSE); 670 SetMsgHandled(FALSE);
513 } 671 }
514 672
673 void HWNDMessageHandler::OnWindowPosChanged(WINDOWPOS* window_pos) {
674 if (DidClientAreaSizeChange(window_pos))
675 ClientAreaSizeChanged();
676 if (remove_standard_frame_ && window_pos->flags & SWP_FRAMECHANGED &&
677 ui::win::IsAeroGlassEnabled()) {
678 MARGINS m = {10, 10, 10, 10};
679 DwmExtendFrameIntoClientArea(hwnd(), &m);
680 }
681 if (window_pos->flags & SWP_SHOWWINDOW)
682 delegate_->HandleVisibilityChanged(true);
683 else if (window_pos->flags & SWP_HIDEWINDOW)
684 delegate_->HandleVisibilityChanged(false);
685 SetMsgHandled(FALSE);
686 }
687
515 void HWNDMessageHandler::ResetWindowRegion(bool force) { 688 void HWNDMessageHandler::ResetWindowRegion(bool force) {
516 // A native frame uses the native window region, and we don't want to mess 689 // A native frame uses the native window region, and we don't want to mess
517 // with it. 690 // with it.
518 if (!delegate_->IsUsingCustomFrame() || !delegate_->IsWidgetWindow()) { 691 if (!delegate_->IsUsingCustomFrame() || !delegate_->IsWidgetWindow()) {
519 if (force) 692 if (force)
520 SetWindowRgn(hwnd(), NULL, TRUE); 693 SetWindowRgn(hwnd(), NULL, TRUE);
521 return; 694 return;
522 } 695 }
523 696
524 // Changing the window region is going to force a paint. Only change the 697 // Changing the window region is going to force a paint. Only change the
525 // window region if the region really differs. 698 // window region if the region really differs.
526 HRGN current_rgn = CreateRectRgn(0, 0, 0, 0); 699 HRGN current_rgn = CreateRectRgn(0, 0, 0, 0);
527 int current_rgn_result = GetWindowRgn(hwnd(), current_rgn); 700 int current_rgn_result = GetWindowRgn(hwnd(), current_rgn);
528 701
529 CRect window_rect; 702 CRect window_rect;
530 GetWindowRect(hwnd(), &window_rect); 703 GetWindowRect(hwnd(), &window_rect);
531 HRGN new_region; 704 HRGN new_region;
532 if (delegate_->AsNativeWidgetWin()->IsMaximized()) { 705 if (IsMaximized()) {
533 HMONITOR monitor = MonitorFromWindow(hwnd(), MONITOR_DEFAULTTONEAREST); 706 HMONITOR monitor = MonitorFromWindow(hwnd(), MONITOR_DEFAULTTONEAREST);
534 MONITORINFO mi; 707 MONITORINFO mi;
535 mi.cbSize = sizeof mi; 708 mi.cbSize = sizeof mi;
536 GetMonitorInfo(monitor, &mi); 709 GetMonitorInfo(monitor, &mi);
537 CRect work_rect = mi.rcWork; 710 CRect work_rect = mi.rcWork;
538 work_rect.OffsetRect(-window_rect.left, -window_rect.top); 711 work_rect.OffsetRect(-window_rect.left, -window_rect.top);
539 new_region = CreateRectRgnIndirect(&work_rect); 712 new_region = CreateRectRgnIndirect(&work_rect);
540 } else { 713 } else {
541 gfx::Path window_mask; 714 gfx::Path window_mask;
542 delegate_->GetWindowMask( 715 delegate_->GetWindowMask(
543 gfx::Size(window_rect.Width(), window_rect.Height()), &window_mask); 716 gfx::Size(window_rect.Width(), window_rect.Height()), &window_mask);
544 new_region = window_mask.CreateNativeRegion(); 717 new_region = window_mask.CreateNativeRegion();
545 } 718 }
546 719
547 if (current_rgn_result == ERROR || !EqualRgn(current_rgn, new_region)) { 720 if (current_rgn_result == ERROR || !EqualRgn(current_rgn, new_region)) {
548 // SetWindowRgn takes ownership of the HRGN created by CreateNativeRegion. 721 // SetWindowRgn takes ownership of the HRGN created by CreateNativeRegion.
549 SetWindowRgn(hwnd(), new_region, TRUE); 722 SetWindowRgn(hwnd(), new_region, TRUE);
550 } else { 723 } else {
551 DeleteObject(new_region); 724 DeleteObject(new_region);
552 } 725 }
553 726
554 DeleteObject(current_rgn); 727 DeleteObject(current_rgn);
555 } 728 }
556 729
557 //////////////////////////////////////////////////////////////////////////////// 730 ////////////////////////////////////////////////////////////////////////////////
731 // HWNDMessageHandler, InputMethodDelegate implementation:
732
733 void HWNDMessageHandler::DispatchKeyEventPostIME(const ui::KeyEvent& key) {
734 SetMsgHandled(delegate_->HandleKeyEvent(key));
735 }
736
737 ////////////////////////////////////////////////////////////////////////////////
558 // HWNDMessageHandler, private: 738 // HWNDMessageHandler, private:
559 739
740 void HWNDMessageHandler::TrackMouseEvents(DWORD mouse_tracking_flags) {
741 // Begin tracking mouse events for this HWND so that we get WM_MOUSELEAVE
742 // when the user moves the mouse outside this HWND's bounds.
743 if (active_mouse_tracking_flags_ == 0 || mouse_tracking_flags & TME_CANCEL) {
744 if (mouse_tracking_flags & TME_CANCEL) {
745 // We're about to cancel active mouse tracking, so empty out the stored
746 // state.
747 active_mouse_tracking_flags_ = 0;
748 } else {
749 active_mouse_tracking_flags_ = mouse_tracking_flags;
750 }
751
752 TRACKMOUSEEVENT tme;
753 tme.cbSize = sizeof(tme);
754 tme.dwFlags = mouse_tracking_flags;
755 tme.hwndTrack = hwnd();
756 tme.dwHoverTime = 0;
757 TrackMouseEvent(&tme);
758 } else if (mouse_tracking_flags != active_mouse_tracking_flags_) {
759 TrackMouseEvents(active_mouse_tracking_flags_ | TME_CANCEL);
760 TrackMouseEvents(mouse_tracking_flags);
761 }
762 }
763
764 void HWNDMessageHandler::ClientAreaSizeChanged() {
765 RECT r = {0, 0, 0, 0};
766 if (delegate_->AsNativeWidgetWin()->WidgetSizeIsClientSize()) {
767 // TODO(beng): investigate whether this could be done
768 // from other branch of if-else.
769 if (!IsMinimized())
770 GetClientRect(hwnd(), &r);
771 } else {
772 GetWindowRect(hwnd(), &r);
773 }
774 gfx::Size s(std::max(0, static_cast<int>(r.right - r.left)),
775 std::max(0, static_cast<int>(r.bottom - r.top)));
776 delegate_->HandleClientSizeChanged(s);
777 }
778
779 // A scoping class that prevents a window from being able to redraw in response
780 // to invalidations that may occur within it for the lifetime of the object.
781 //
782 // Why would we want such a thing? Well, it turns out Windows has some
783 // "unorthodox" behavior when it comes to painting its non-client areas.
784 // Occasionally, Windows will paint portions of the default non-client area
785 // right over the top of the custom frame. This is not simply fixed by handling
786 // WM_NCPAINT/WM_PAINT, with some investigation it turns out that this
787 // rendering is being done *inside* the default implementation of some message
788 // handlers and functions:
789 // . WM_SETTEXT
790 // . WM_SETICON
791 // . WM_NCLBUTTONDOWN
792 // . EnableMenuItem, called from our WM_INITMENU handler
793 // The solution is to handle these messages and call DefWindowProc ourselves,
794 // but prevent the window from being able to update itself for the duration of
795 // the call. We do this with this class, which automatically calls its
796 // associated Window's lock and unlock functions as it is created and destroyed.
797 // See documentation in those methods for the technique used.
798 //
799 // The lock only has an effect if the window was visible upon lock creation, as
800 // it doesn't guard against direct visiblility changes, and multiple locks may
801 // exist simultaneously to handle certain nested Windows messages.
802 //
803 // IMPORTANT: Do not use this scoping object for large scopes or periods of
804 // time! IT WILL PREVENT THE WINDOW FROM BEING REDRAWN! (duh).
805 //
806 // I would love to hear Raymond Chen's explanation for all this. And maybe a
807 // list of other messages that this applies to ;-)
808 class HWNDMessageHandler::ScopedRedrawLock {
809 public:
810 explicit ScopedRedrawLock(HWNDMessageHandler* owner)
811 : owner_(owner),
812 hwnd_(owner_->hwnd()),
813 was_visible_(owner_->IsVisible()),
814 cancel_unlock_(false),
815 force_(!(GetWindowLong(hwnd_, GWL_STYLE) & WS_CAPTION)) {
816 if (was_visible_ && ::IsWindow(hwnd_))
817 owner_->LockUpdates(force_);
818 }
819
820 ~ScopedRedrawLock() {
821 if (!cancel_unlock_ && was_visible_ && ::IsWindow(hwnd_))
822 owner_->UnlockUpdates(force_);
823 }
824
825 // Cancel the unlock operation, call this if the Widget is being destroyed.
826 void CancelUnlockOperation() { cancel_unlock_ = true; }
827
828 private:
829 // The owner having its style changed.
830 HWNDMessageHandler* owner_;
831 // The owner's HWND, cached to avoid action after window destruction.
832 HWND hwnd_;
833 // Records the HWND visibility at the time of creation.
834 bool was_visible_;
835 // A flag indicating that the unlock operation was canceled.
836 bool cancel_unlock_;
837 // If true, perform the redraw lock regardless of Aero state.
838 bool force_;
839
840 DISALLOW_COPY_AND_ASSIGN(ScopedRedrawLock);
841 };
842
843 LRESULT HWNDMessageHandler::DefWindowProcWithRedrawLock(UINT message,
844 WPARAM w_param,
845 LPARAM l_param) {
846 ScopedRedrawLock lock(this);
847 // The Widget and HWND can be destroyed in the call to DefWindowProc, so use
848 // the |destroyed_| flag to avoid unlocking (and crashing) after destruction.
849 bool destroyed = false;
850 destroyed_ = &destroyed;
851 LRESULT result = DefWindowProc(hwnd(), message, w_param, l_param);
852 if (destroyed)
853 lock.CancelUnlockOperation();
854 else
855 destroyed_ = NULL;
856 return result;
857 }
858
859 void HWNDMessageHandler::LockUpdates(bool force) {
860 // We skip locked updates when Aero is on for two reasons:
861 // 1. Because it isn't necessary
862 // 2. Because toggling the WS_VISIBLE flag may occur while the GPU process is
863 // attempting to present a child window's backbuffer onscreen. When these
864 // two actions race with one another, the child window will either flicker
865 // or will simply stop updating entirely.
866 if ((force || !ui::win::IsAeroGlassEnabled()) && ++lock_updates_count_ == 1) {
867 SetWindowLong(hwnd(), GWL_STYLE,
868 GetWindowLong(hwnd(), GWL_STYLE) & ~WS_VISIBLE);
869 }
870 }
871
872 void HWNDMessageHandler::UnlockUpdates(bool force) {
873 if ((force || !ui::win::IsAeroGlassEnabled()) && --lock_updates_count_ <= 0) {
874 SetWindowLong(hwnd(), GWL_STYLE,
875 GetWindowLong(hwnd(), GWL_STYLE) | WS_VISIBLE);
876 lock_updates_count_ = 0;
877 }
878 }
879
560 HWND HWNDMessageHandler::hwnd() { 880 HWND HWNDMessageHandler::hwnd() {
561 return delegate_->AsNativeWidgetWin()->hwnd(); 881 return delegate_->AsNativeWidgetWin()->hwnd();
562 } 882 }
563 883
564 HWND HWNDMessageHandler::hwnd() const { 884 HWND HWNDMessageHandler::hwnd() const {
565 return delegate_->AsNativeWidgetWin()->hwnd(); 885 return delegate_->AsNativeWidgetWin()->hwnd();
566 } 886 }
567 887
568 LRESULT HWNDMessageHandler::DefWindowProcWithRedrawLock(UINT message,
569 WPARAM w_param,
570 LPARAM l_param) {
571 return delegate_->AsNativeWidgetWin()->DefWindowProcWithRedrawLock(message,
572 w_param,
573 l_param);
574 }
575
576 void HWNDMessageHandler::SetMsgHandled(BOOL handled) { 888 void HWNDMessageHandler::SetMsgHandled(BOOL handled) {
577 delegate_->AsNativeWidgetWin()->SetMsgHandled(handled); 889 delegate_->AsNativeWidgetWin()->SetMsgHandled(handled);
578 } 890 }
579 891
580 } // namespace views 892 } // namespace views
581
OLDNEW
« no previous file with comments | « ui/views/win/hwnd_message_handler.h ('k') | ui/views/win/hwnd_message_handler_delegate.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698