OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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 "chrome/views/widget/widget_win.h" | 5 #include "chrome/views/widget/widget_win.h" |
6 | 6 |
7 #include "base/gfx/native_theme.h" | 7 #include "base/gfx/native_theme.h" |
8 #include "base/string_util.h" | 8 #include "base/string_util.h" |
9 #include "base/win_util.h" | 9 #include "base/win_util.h" |
10 #include "chrome/app/chrome_dll_resource.h" | 10 #include "chrome/app/chrome_dll_resource.h" |
11 #include "chrome/common/gfx/chrome_canvas.h" | 11 #include "chrome/common/gfx/chrome_canvas.h" |
12 #include "chrome/common/notification_service.h" | 12 #include "chrome/common/notification_service.h" |
13 #include "chrome/common/win_util.h" | 13 #include "chrome/common/win_util.h" |
14 #include "chrome/views/accessibility/view_accessibility.h" | 14 #include "chrome/views/accessibility/view_accessibility.h" |
15 #include "chrome/views/controls/native_control_win.h" | 15 #include "chrome/views/controls/native_control_win.h" |
16 #include "chrome/views/fill_layout.h" | 16 #include "chrome/views/fill_layout.h" |
17 #include "chrome/views/focus/focus_util_win.h" | 17 #include "chrome/views/focus/focus_util_win.h" |
18 #include "chrome/views/widget/aero_tooltip_manager.h" | 18 #include "chrome/views/widget/aero_tooltip_manager.h" |
19 #include "chrome/views/widget/hwnd_notification_source.h" | 19 #include "chrome/views/widget/hwnd_notification_source.h" |
20 #include "chrome/views/widget/root_view.h" | 20 #include "chrome/views/widget/root_view.h" |
21 | 21 |
22 namespace { | |
23 | |
24 bool GetMonitorAndWorkAreaForRect(const RECT& rect, | |
25 HMONITOR* monitor, | |
26 gfx::Rect* work_area) { | |
27 DCHECK(monitor); | |
28 DCHECK(work_area); | |
29 *monitor = MonitorFromRect(&rect, MONITOR_DEFAULTTONEAREST); | |
30 if (!*monitor) | |
31 return false; | |
32 MONITORINFO monitor_info = { 0 }; | |
33 monitor_info.cbSize = sizeof(monitor_info); | |
34 GetMonitorInfo(*monitor, &monitor_info); | |
35 *work_area = monitor_info.rcWork; | |
36 return true; | |
37 } | |
38 | |
39 } // namespace | |
40 | |
41 namespace views { | 22 namespace views { |
42 | 23 |
43 static const DWORD kWindowDefaultChildStyle = | 24 static const DWORD kWindowDefaultChildStyle = |
44 WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS; | 25 WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS; |
45 static const DWORD kWindowDefaultStyle = WS_OVERLAPPEDWINDOW; | 26 static const DWORD kWindowDefaultStyle = WS_OVERLAPPEDWINDOW; |
46 static const DWORD kWindowDefaultExStyle = 0; | 27 static const DWORD kWindowDefaultExStyle = 0; |
47 | 28 |
48 // Property used to link the HWND to its RootView. | 29 // Property used to link the HWND to its RootView. |
49 static const wchar_t* const kRootViewWindowProperty = L"__ROOT_VIEW__"; | 30 static const wchar_t* const kRootViewWindowProperty = L"__ROOT_VIEW__"; |
50 | 31 |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
114 | 95 |
115 // The list of registered classes. | 96 // The list of registered classes. |
116 static RegisteredClasses* registered_classes = NULL; | 97 static RegisteredClasses* registered_classes = NULL; |
117 | 98 |
118 | 99 |
119 /////////////////////////////////////////////////////////////////////////////// | 100 /////////////////////////////////////////////////////////////////////////////// |
120 // WidgetWin, public | 101 // WidgetWin, public |
121 | 102 |
122 WidgetWin::WidgetWin() | 103 WidgetWin::WidgetWin() |
123 : close_widget_factory_(this), | 104 : close_widget_factory_(this), |
124 ignore_pos_changes_factory_(this), | |
125 active_mouse_tracking_flags_(0), | 105 active_mouse_tracking_flags_(0), |
126 has_capture_(false), | 106 has_capture_(false), |
127 current_action_(FA_NONE), | 107 current_action_(FA_NONE), |
128 window_style_(0), | 108 window_style_(0), |
129 window_ex_style_(kWindowDefaultExStyle), | 109 window_ex_style_(kWindowDefaultExStyle), |
130 use_layered_buffer_(true), | 110 use_layered_buffer_(true), |
131 layered_alpha_(255), | 111 layered_alpha_(255), |
132 delete_on_destroy_(true), | 112 delete_on_destroy_(true), |
133 can_update_layered_window_(true), | 113 can_update_layered_window_(true), |
134 last_mouse_event_was_move_(false), | 114 last_mouse_event_was_move_(false), |
135 is_mouse_down_(false), | 115 is_mouse_down_(false), |
136 class_style_(CS_DBLCLKS), | 116 class_style_(CS_DBLCLKS), |
137 hwnd_(NULL), | 117 hwnd_(NULL) { |
138 last_monitor_(NULL), | |
139 ignore_window_pos_changes_(false) { | |
140 } | 118 } |
141 | 119 |
142 WidgetWin::~WidgetWin() { | 120 WidgetWin::~WidgetWin() { |
143 MessageLoopForUI::current()->RemoveObserver(this); | 121 MessageLoopForUI::current()->RemoveObserver(this); |
144 } | 122 } |
145 | 123 |
146 void WidgetWin::Init(HWND parent, const gfx::Rect& bounds, | 124 void WidgetWin::Init(HWND parent, const gfx::Rect& bounds, |
147 bool has_own_focus_manager) { | 125 bool has_own_focus_manager) { |
148 if (window_style_ == 0) | 126 if (window_style_ == 0) |
149 window_style_ = parent ? kWindowDefaultChildStyle : kWindowDefaultStyle; | 127 window_style_ = parent ? kWindowDefaultChildStyle : kWindowDefaultStyle; |
(...skipping 13 matching lines...) Expand all Loading... |
163 parent = NULL; | 141 parent = NULL; |
164 } | 142 } |
165 | 143 |
166 hwnd_ = CreateWindowEx(window_ex_style_, GetWindowClassName().c_str(), L"", | 144 hwnd_ = CreateWindowEx(window_ex_style_, GetWindowClassName().c_str(), L"", |
167 window_style_, bounds.x(), bounds.y(), bounds.width(), | 145 window_style_, bounds.x(), bounds.y(), bounds.width(), |
168 bounds.height(), parent, NULL, NULL, this); | 146 bounds.height(), parent, NULL, NULL, this); |
169 DCHECK(hwnd_); | 147 DCHECK(hwnd_); |
170 TRACK_HWND_CREATION(hwnd_); | 148 TRACK_HWND_CREATION(hwnd_); |
171 SetWindowSupportsRerouteMouseWheel(hwnd_); | 149 SetWindowSupportsRerouteMouseWheel(hwnd_); |
172 | 150 |
173 GetMonitorAndWorkAreaForRect(bounds.ToRECT(), &last_monitor_, | |
174 &last_work_area_); | |
175 | |
176 // The window procedure should have set the data for us. | 151 // The window procedure should have set the data for us. |
177 DCHECK(win_util::GetWindowUserData(hwnd_) == this); | 152 DCHECK(win_util::GetWindowUserData(hwnd_) == this); |
178 | 153 |
179 root_view_->OnWidgetCreated(); | 154 root_view_->OnWidgetCreated(); |
180 | 155 |
181 if (has_own_focus_manager) { | 156 if (has_own_focus_manager) { |
182 FocusManager::CreateFocusManager(hwnd_, GetRootView()); | 157 FocusManager::CreateFocusManager(hwnd_, GetRootView()); |
183 } else { | 158 } else { |
184 // Subclass the window so we get the tab key messages when a view with no | 159 // Subclass the window so we get the tab key messages when a view with no |
185 // associated native window is focused. | 160 // associated native window is focused. |
(...skipping 493 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
679 } | 654 } |
680 | 655 |
681 void WidgetWin::OnRButtonUp(UINT flags, const CPoint& point) { | 656 void WidgetWin::OnRButtonUp(UINT flags, const CPoint& point) { |
682 ProcessMouseReleased(point, flags | MK_RBUTTON); | 657 ProcessMouseReleased(point, flags | MK_RBUTTON); |
683 } | 658 } |
684 | 659 |
685 void WidgetWin::OnRButtonDblClk(UINT flags, const CPoint& point) { | 660 void WidgetWin::OnRButtonDblClk(UINT flags, const CPoint& point) { |
686 ProcessMousePressed(point, flags | MK_RBUTTON, true, false); | 661 ProcessMousePressed(point, flags | MK_RBUTTON, true, false); |
687 } | 662 } |
688 | 663 |
689 void WidgetWin::OnSettingChange(UINT flags, const wchar_t* section) { | |
690 if (!GetParent() && (flags == SPI_SETWORKAREA)) { | |
691 // Fire a dummy SetWindowPos() call, so we'll trip the code in | |
692 // OnWindowPosChanging() below that notices work area changes. | |
693 ::SetWindowPos(GetNativeView(), 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | | |
694 SWP_NOZORDER | SWP_NOREDRAW | SWP_NOACTIVATE | SWP_NOOWNERZORDER); | |
695 SetMsgHandled(TRUE); | |
696 } | |
697 } | |
698 | |
699 void WidgetWin::OnSize(UINT param, const CSize& size) { | 664 void WidgetWin::OnSize(UINT param, const CSize& size) { |
700 ChangeSize(param, size); | 665 ChangeSize(param, size); |
701 } | 666 } |
702 | 667 |
703 void WidgetWin::OnThemeChanged() { | 668 void WidgetWin::OnThemeChanged() { |
704 // Notify NativeTheme. | 669 // Notify NativeTheme. |
705 gfx::NativeTheme::instance()->CloseHandles(); | 670 gfx::NativeTheme::instance()->CloseHandles(); |
706 } | 671 } |
707 | 672 |
708 void WidgetWin::OnWindowPosChanging(WINDOWPOS* window_pos) { | |
709 if (ignore_window_pos_changes_) { | |
710 // If somebody's trying to toggle our visibility, change the nonclient area, | |
711 // change our Z-order, or activate us, we should probably let it go through. | |
712 if (!(window_pos->flags & ((IsVisible() ? SWP_HIDEWINDOW : SWP_SHOWWINDOW) | | |
713 SWP_FRAMECHANGED)) && | |
714 (window_pos->flags & (SWP_NOZORDER | SWP_NOACTIVATE))) { | |
715 // Just sizing/moving the window; ignore. | |
716 window_pos->flags |= SWP_NOSIZE | SWP_NOMOVE | SWP_NOREDRAW; | |
717 window_pos->flags &= ~(SWP_SHOWWINDOW | SWP_HIDEWINDOW); | |
718 } | |
719 } else if (!GetParent()) { | |
720 CRect window_rect; | |
721 HMONITOR monitor; | |
722 gfx::Rect work_area; | |
723 if (GetWindowRect(&window_rect) && | |
724 GetMonitorAndWorkAreaForRect(window_rect, &monitor, &work_area)) { | |
725 if ((monitor == last_monitor_) && (work_area != last_work_area_)) { | |
726 // The work area for the monitor we're on changed. Normally Windows | |
727 // notifies us about this (and thus we're reaching here due to the | |
728 // SetWindowPos() call in OnSettingChange() above), but with some | |
729 // software (e.g. nVidia's nView desktop manager) the work area can | |
730 // change asynchronous to any notification, and we're just sent a | |
731 // SetWindowPos() call with a new (frequently incorrect) position/size. | |
732 // In either case, the best response is to throw away the existing | |
733 // position/size information in |window_pos| and recalculate it based on | |
734 // the old window coordinates, adjusted for the change in the work area. | |
735 if (IsZoomed()) { | |
736 window_pos->x = window_rect.left + work_area.x() - last_work_area_.x()
; | |
737 window_pos->y = window_rect.top + work_area.y() - last_work_area_.y(); | |
738 window_pos->cx = window_rect.Width() + work_area.width() - | |
739 last_work_area_.width(); | |
740 window_pos->cy = window_rect.Height() + work_area.height() - | |
741 last_work_area_.height(); | |
742 } else { | |
743 gfx::Rect window_gfx_rect(window_rect); | |
744 gfx::Rect new_window_rect = window_gfx_rect.AdjustToFit(work_area); | |
745 window_pos->x = new_window_rect.x(); | |
746 window_pos->y = new_window_rect.y(); | |
747 window_pos->cx = new_window_rect.width(); | |
748 window_pos->cy = new_window_rect.height(); | |
749 } | |
750 // WARNING! Don't set SWP_FRAMECHANGED here, it breaks moving the child | |
751 // HWNDs for some reason. | |
752 window_pos->flags &= ~(SWP_NOSIZE | SWP_NOMOVE | SWP_NOREDRAW); | |
753 window_pos->flags |= SWP_NOCOPYBITS; | |
754 | |
755 // Now ignore all immediately-following SetWindowPos() changes. Windows | |
756 // likes to (incorrectly) recalculate what our position/size should be | |
757 // and send us further updates. | |
758 ignore_window_pos_changes_ = true; | |
759 DCHECK(ignore_pos_changes_factory_.empty()); | |
760 MessageLoop::current()->PostTask(FROM_HERE, | |
761 ignore_pos_changes_factory_.NewRunnableMethod( | |
762 &WidgetWin::StopIgnoringPosChanges)); | |
763 } | |
764 last_monitor_ = monitor; | |
765 last_work_area_ = work_area; | |
766 } | |
767 } | |
768 | |
769 SetMsgHandled(FALSE); | |
770 } | |
771 | |
772 void WidgetWin::OnFinalMessage(HWND window) { | 673 void WidgetWin::OnFinalMessage(HWND window) { |
773 if (delete_on_destroy_) | 674 if (delete_on_destroy_) |
774 delete this; | 675 delete this; |
775 } | 676 } |
776 | 677 |
777 /////////////////////////////////////////////////////////////////////////////// | 678 /////////////////////////////////////////////////////////////////////////////// |
778 // WidgetWin, protected: | 679 // WidgetWin, protected: |
779 | 680 |
780 void WidgetWin::TrackMouseEvents(DWORD mouse_tracking_flags) { | 681 void WidgetWin::TrackMouseEvents(DWORD mouse_tracking_flags) { |
781 // Begin tracking mouse events for this HWND so that we get WM_MOUSELEAVE | 682 // Begin tracking mouse events for this HWND so that we get WM_MOUSELEAVE |
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1061 result = DefWindowProc(window, message, w_param, l_param); | 962 result = DefWindowProc(window, message, w_param, l_param); |
1062 if (message == WM_NCDESTROY) { | 963 if (message == WM_NCDESTROY) { |
1063 TRACK_HWND_DESTRUCTION(window); | 964 TRACK_HWND_DESTRUCTION(window); |
1064 widget->hwnd_ = NULL; | 965 widget->hwnd_ = NULL; |
1065 widget->OnFinalMessage(window); | 966 widget->OnFinalMessage(window); |
1066 } | 967 } |
1067 return result; | 968 return result; |
1068 } | 969 } |
1069 | 970 |
1070 } // namespace views | 971 } // namespace views |
OLD | NEW |