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

Side by Side Diff: chrome/views/widget/widget_win.cc

Issue 67023: Fix various problems with work area change notifications so that we now (hope... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 11 years, 8 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 | « chrome/views/widget/widget_win.h ('k') | no next file » | 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) 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
22 namespace views { 41 namespace views {
23 42
24 static const DWORD kWindowDefaultChildStyle = 43 static const DWORD kWindowDefaultChildStyle =
25 WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS; 44 WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
26 static const DWORD kWindowDefaultStyle = WS_OVERLAPPEDWINDOW; 45 static const DWORD kWindowDefaultStyle = WS_OVERLAPPEDWINDOW;
27 static const DWORD kWindowDefaultExStyle = 0; 46 static const DWORD kWindowDefaultExStyle = 0;
28 47
29 // Property used to link the HWND to its RootView. 48 // Property used to link the HWND to its RootView.
30 static const wchar_t* const kRootViewWindowProperty = L"__ROOT_VIEW__"; 49 static const wchar_t* const kRootViewWindowProperty = L"__ROOT_VIEW__";
31 50
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
94 typedef std::list<RegisteredClass> RegisteredClasses; 113 typedef std::list<RegisteredClass> RegisteredClasses;
95 114
96 // The list of registered classes. 115 // The list of registered classes.
97 static RegisteredClasses* registered_classes = NULL; 116 static RegisteredClasses* registered_classes = NULL;
98 117
99 118
100 /////////////////////////////////////////////////////////////////////////////// 119 ///////////////////////////////////////////////////////////////////////////////
101 // WidgetWin, public 120 // WidgetWin, public
102 121
103 WidgetWin::WidgetWin() 122 WidgetWin::WidgetWin()
104 : active_mouse_tracking_flags_(0), 123 : close_widget_factory_(this),
124 ignore_pos_changes_factory_(this),
125 active_mouse_tracking_flags_(0),
105 has_capture_(false), 126 has_capture_(false),
106 current_action_(FA_NONE), 127 current_action_(FA_NONE),
107 toplevel_(false), 128 toplevel_(false),
108 window_style_(0), 129 window_style_(0),
109 window_ex_style_(kWindowDefaultExStyle), 130 window_ex_style_(kWindowDefaultExStyle),
110 use_layered_buffer_(true), 131 use_layered_buffer_(true),
111 layered_alpha_(255), 132 layered_alpha_(255),
112 delete_on_destroy_(true), 133 delete_on_destroy_(true),
113 can_update_layered_window_(true), 134 can_update_layered_window_(true),
114 last_mouse_event_was_move_(false), 135 last_mouse_event_was_move_(false),
115 is_mouse_down_(false), 136 is_mouse_down_(false),
116 class_style_(CS_DBLCLKS), 137 class_style_(CS_DBLCLKS),
117 hwnd_(NULL), 138 hwnd_(NULL),
118 close_widget_factory_(this) { 139 last_monitor_(NULL),
140 ignore_window_pos_changes_(false) {
119 } 141 }
120 142
121 WidgetWin::~WidgetWin() { 143 WidgetWin::~WidgetWin() {
122 MessageLoopForUI::current()->RemoveObserver(this); 144 MessageLoopForUI::current()->RemoveObserver(this);
123 } 145 }
124 146
125 void WidgetWin::Init(HWND parent, const gfx::Rect& bounds, 147 void WidgetWin::Init(HWND parent, const gfx::Rect& bounds,
126 bool has_own_focus_manager) { 148 bool has_own_focus_manager) {
127 toplevel_ = parent == NULL; 149 toplevel_ = parent == NULL;
128 150
(...skipping 15 matching lines...) Expand all
144 parent = NULL; 166 parent = NULL;
145 } 167 }
146 168
147 hwnd_ = CreateWindowEx(window_ex_style_, GetWindowClassName().c_str(), L"", 169 hwnd_ = CreateWindowEx(window_ex_style_, GetWindowClassName().c_str(), L"",
148 window_style_, bounds.x(), bounds.y(), bounds.width(), 170 window_style_, bounds.x(), bounds.y(), bounds.width(),
149 bounds.height(), parent, NULL, NULL, this); 171 bounds.height(), parent, NULL, NULL, this);
150 DCHECK(hwnd_); 172 DCHECK(hwnd_);
151 TRACK_HWND_CREATION(hwnd_); 173 TRACK_HWND_CREATION(hwnd_);
152 SetWindowSupportsRerouteMouseWheel(hwnd_); 174 SetWindowSupportsRerouteMouseWheel(hwnd_);
153 175
176 GetMonitorAndWorkAreaForRect(bounds.ToRECT(), &last_monitor_,
177 &last_work_area_);
178
154 // The window procedure should have set the data for us. 179 // The window procedure should have set the data for us.
155 DCHECK(win_util::GetWindowUserData(hwnd_) == this); 180 DCHECK(win_util::GetWindowUserData(hwnd_) == this);
156 181
157 root_view_->OnWidgetCreated(); 182 root_view_->OnWidgetCreated();
158 183
159 if (has_own_focus_manager) { 184 if (has_own_focus_manager) {
160 FocusManager::CreateFocusManager(hwnd_, GetRootView()); 185 FocusManager::CreateFocusManager(hwnd_, GetRootView());
161 } else { 186 } else {
162 // Subclass the window so we get the tab key messages when a view with no 187 // Subclass the window so we get the tab key messages when a view with no
163 // associated native window is focused. 188 // associated native window is focused.
(...skipping 495 matching lines...) Expand 10 before | Expand all | Expand 10 after
659 void WidgetWin::OnRButtonUp(UINT flags, const CPoint& point) { 684 void WidgetWin::OnRButtonUp(UINT flags, const CPoint& point) {
660 ProcessMouseReleased(point, flags | MK_RBUTTON); 685 ProcessMouseReleased(point, flags | MK_RBUTTON);
661 } 686 }
662 687
663 void WidgetWin::OnRButtonDblClk(UINT flags, const CPoint& point) { 688 void WidgetWin::OnRButtonDblClk(UINT flags, const CPoint& point) {
664 ProcessMousePressed(point, flags | MK_RBUTTON, true, false); 689 ProcessMousePressed(point, flags | MK_RBUTTON, true, false);
665 } 690 }
666 691
667 void WidgetWin::OnSettingChange(UINT flags, const wchar_t* section) { 692 void WidgetWin::OnSettingChange(UINT flags, const wchar_t* section) {
668 if (toplevel_ && (flags == SPI_SETWORKAREA)) { 693 if (toplevel_ && (flags == SPI_SETWORKAREA)) {
669 AdjustWindowToFitScreenSize(); 694 // Fire a dummy SetWindowPos() call, so we'll trip the code in
695 // OnWindowPosChanging() below that notices work area changes.
696 ::SetWindowPos(GetNativeView(), 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
697 SWP_NOZORDER | SWP_NOREDRAW | SWP_NOACTIVATE | SWP_NOOWNERZORDER);
670 SetMsgHandled(TRUE); 698 SetMsgHandled(TRUE);
671 } 699 }
672 } 700 }
673 701
674 void WidgetWin::OnSize(UINT param, const CSize& size) { 702 void WidgetWin::OnSize(UINT param, const CSize& size) {
675 ChangeSize(param, size); 703 ChangeSize(param, size);
676 } 704 }
677 705
678 void WidgetWin::OnThemeChanged() { 706 void WidgetWin::OnThemeChanged() {
679 // Notify NativeTheme. 707 // Notify NativeTheme.
680 gfx::NativeTheme::instance()->CloseHandles(); 708 gfx::NativeTheme::instance()->CloseHandles();
681 } 709 }
682 710
711 void WidgetWin::OnWindowPosChanging(WINDOWPOS* window_pos) {
712 if (ignore_window_pos_changes_) {
713 // If somebody's trying to toggle our visibility, change the nonclient area,
714 // change our Z-order, or activate us, we should probably let it go through.
715 if (!(window_pos->flags & ((IsVisible() ? SWP_HIDEWINDOW : SWP_SHOWWINDOW) |
716 SWP_FRAMECHANGED)) &&
717 (window_pos->flags & (SWP_NOZORDER | SWP_NOACTIVATE))) {
718 // Just sizing/moving the window; ignore.
719 window_pos->flags |= SWP_NOSIZE | SWP_NOMOVE | SWP_NOREDRAW;
720 window_pos->flags &= ~(SWP_SHOWWINDOW | SWP_HIDEWINDOW);
721 }
722 } else if (toplevel_) {
Ben Goodger (Google) 2009/04/10 19:59:03 Can you just use !GetParent() here instead? I want
Peter Kasting 2009/04/10 20:05:02 Yep, and I can just remove toplevel_ entirely, goi
723 CRect window_rect;
724 HMONITOR monitor;
725 gfx::Rect work_area;
726 if (GetWindowRect(&window_rect) &&
727 GetMonitorAndWorkAreaForRect(window_rect, &monitor, &work_area)) {
728 if ((monitor == last_monitor_) && (work_area != last_work_area_)) {
729 // The work area for the monitor we're on changed. Normally Windows
730 // notifies us about this (and thus we're reaching here due to the
731 // SetWindowPos() call in OnSettingChange() above), but with some
732 // software (e.g. nVidia's nView desktop manager) the work area can
733 // change asynchronous to any notification, and we're just sent a
734 // SetWindowPos() call with a new (frequently incorrect) position/size.
735 // In either case, the best response is to throw away the existing
736 // position/size information in |window_pos| and recalculate it based on
737 // the old window coordinates, adjusted for the change in the work area.
738 if (IsZoomed()) {
739 window_pos->x = window_rect.left + work_area.x() - last_work_area_.x() ;
740 window_pos->y = window_rect.top + work_area.y() - last_work_area_.y();
741 window_pos->cx = window_rect.Width() + work_area.width() -
742 last_work_area_.width();
743 window_pos->cy = window_rect.Height() + work_area.height() -
744 last_work_area_.height();
745 } else {
746 gfx::Rect window_gfx_rect(window_rect);
747 gfx::Rect new_window_rect = window_gfx_rect.AdjustToFit(work_area);
748 window_pos->x = new_window_rect.x();
749 window_pos->y = new_window_rect.y();
750 window_pos->cx = new_window_rect.width();
751 window_pos->cy = new_window_rect.height();
752 }
753 // WARNING! Don't set SWP_FRAMECHANGED here, it breaks moving the child
754 // HWNDs for some reason.
755 window_pos->flags &= ~(SWP_NOSIZE | SWP_NOMOVE | SWP_NOREDRAW);
756 window_pos->flags |= SWP_NOCOPYBITS;
757
758 // Now ignore all immediately-following SetWindowPos() changes. Windows
759 // likes to (incorrectly) recalculate what our position/size should be
760 // and send us further updates.
761 ignore_window_pos_changes_ = true;
762 DCHECK(ignore_pos_changes_factory_.empty());
763 MessageLoop::current()->PostTask(FROM_HERE,
764 ignore_pos_changes_factory_.NewRunnableMethod(
765 &WidgetWin::StopIgnoringPosChanges));
766 }
767 last_monitor_ = monitor;
768 last_work_area_ = work_area;
769 }
770 }
771
772 SetMsgHandled(FALSE);
773 }
774
683 void WidgetWin::OnFinalMessage(HWND window) { 775 void WidgetWin::OnFinalMessage(HWND window) {
684 if (delete_on_destroy_) 776 if (delete_on_destroy_)
685 delete this; 777 delete this;
686 } 778 }
687 779
688 /////////////////////////////////////////////////////////////////////////////// 780 ///////////////////////////////////////////////////////////////////////////////
689 // WidgetWin, protected: 781 // WidgetWin, protected:
690 782
691 void WidgetWin::TrackMouseEvents(DWORD mouse_tracking_flags) { 783 void WidgetWin::TrackMouseEvents(DWORD mouse_tracking_flags) {
692 // Begin tracking mouse events for this HWND so that we get WM_MOUSELEAVE 784 // Begin tracking mouse events for this HWND so that we get WM_MOUSELEAVE
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
795 } 887 }
796 888
797 void WidgetWin::ProcessMouseExited() { 889 void WidgetWin::ProcessMouseExited() {
798 last_mouse_event_was_move_ = false; 890 last_mouse_event_was_move_ = false;
799 root_view_->ProcessOnMouseExited(); 891 root_view_->ProcessOnMouseExited();
800 // Reset our tracking flag so that future mouse movement over this WidgetWin 892 // Reset our tracking flag so that future mouse movement over this WidgetWin
801 // results in a new tracking session. 893 // results in a new tracking session.
802 active_mouse_tracking_flags_ = 0; 894 active_mouse_tracking_flags_ = 0;
803 } 895 }
804 896
805 void WidgetWin::AdjustWindowToFitScreenSize() {
806 // Desktop size has changed. Make sure we're still on screen.
807 CRect wr;
808 GetWindowRect(&wr);
809 HMONITOR hmon = MonitorFromRect(&wr, MONITOR_DEFAULTTONEAREST);
810 if (!hmon) {
811 // No monitor available.
812 return;
813 }
814
815 MONITORINFO mi;
816 mi.cbSize = sizeof(mi);
817 GetMonitorInfo(hmon, &mi);
818 gfx::Rect window_rect(wr);
819 gfx::Rect monitor_rect(mi.rcWork);
820 gfx::Rect new_window_rect = window_rect.AdjustToFit(monitor_rect);
821 if (!new_window_rect.Equals(window_rect)) {
822 // New position differs from last, resize window.
823 ::SetWindowPos(GetNativeView(),
824 0,
825 new_window_rect.x(),
826 new_window_rect.y(),
827 new_window_rect.width(),
828 new_window_rect.height(),
829 SWP_NOACTIVATE | SWP_NOZORDER);
830 }
831 }
832
833 void WidgetWin::ChangeSize(UINT size_param, const CSize& size) { 897 void WidgetWin::ChangeSize(UINT size_param, const CSize& size) {
834 CRect rect; 898 CRect rect;
835 if (use_layered_buffer_) { 899 if (use_layered_buffer_) {
836 GetWindowRect(&rect); 900 GetWindowRect(&rect);
837 SizeContents(rect); 901 SizeContents(rect);
838 } else { 902 } else {
839 GetClientRect(&rect); 903 GetClientRect(&rect);
840 } 904 }
841 905
842 // Resizing changes the size of the view hierarchy and thus forces a 906 // Resizing changes the size of the view hierarchy and thus forces a
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
1000 result = DefWindowProc(window, message, w_param, l_param); 1064 result = DefWindowProc(window, message, w_param, l_param);
1001 if (message == WM_NCDESTROY) { 1065 if (message == WM_NCDESTROY) {
1002 TRACK_HWND_DESTRUCTION(window); 1066 TRACK_HWND_DESTRUCTION(window);
1003 widget->hwnd_ = NULL; 1067 widget->hwnd_ = NULL;
1004 widget->OnFinalMessage(window); 1068 widget->OnFinalMessage(window);
1005 } 1069 }
1006 return result; 1070 return result;
1007 } 1071 }
1008 1072
1009 } // namespace views 1073 } // namespace views
OLDNEW
« no previous file with comments | « chrome/views/widget/widget_win.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698