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/window/window_win.h" | 5 #include "chrome/views/window/window_win.h" |
6 | 6 |
7 #include <shellapi.h> | 7 #include <shellapi.h> |
8 | 8 |
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/gfx/chrome_font.h" | 12 #include "chrome/common/gfx/chrome_font.h" |
13 #include "chrome/common/gfx/icon_util.h" | 13 #include "chrome/common/gfx/icon_util.h" |
14 #include "chrome/common/gfx/path.h" | 14 #include "chrome/common/gfx/path.h" |
15 #include "chrome/common/l10n_util.h" | 15 #include "chrome/common/l10n_util.h" |
16 #include "chrome/common/notification_service.h" | 16 #include "chrome/common/notification_service.h" |
17 #include "chrome/common/pref_service.h" | 17 #include "chrome/common/pref_service.h" |
18 #include "chrome/common/resource_bundle.h" | 18 #include "chrome/common/resource_bundle.h" |
19 #include "chrome/common/win_util.h" | 19 #include "chrome/common/win_util.h" |
20 #include "chrome/views/widget/root_view.h" | 20 #include "chrome/views/widget/root_view.h" |
21 #include "chrome/views/window/client_view.h" | 21 #include "chrome/views/window/client_view.h" |
22 #include "chrome/views/window/custom_frame_view.h" | 22 #include "chrome/views/window/custom_frame_view.h" |
23 #include "chrome/views/window/native_frame_view.h" | 23 #include "chrome/views/window/native_frame_view.h" |
24 #include "chrome/views/window/non_client_view.h" | 24 #include "chrome/views/window/non_client_view.h" |
25 #include "chrome/views/window/window_delegate.h" | 25 #include "chrome/views/window/window_delegate.h" |
26 #include "grit/generated_resources.h" | 26 #include "grit/generated_resources.h" |
27 | 27 |
| 28 namespace { |
| 29 |
| 30 bool GetMonitorAndRects(const RECT& rect, |
| 31 HMONITOR* monitor, |
| 32 gfx::Rect* monitor_rect, |
| 33 gfx::Rect* work_area) { |
| 34 DCHECK(monitor); |
| 35 DCHECK(monitor_rect); |
| 36 DCHECK(work_area); |
| 37 *monitor = MonitorFromRect(&rect, MONITOR_DEFAULTTONULL); |
| 38 if (!*monitor) |
| 39 return false; |
| 40 MONITORINFO monitor_info = { 0 }; |
| 41 monitor_info.cbSize = sizeof(monitor_info); |
| 42 GetMonitorInfo(*monitor, &monitor_info); |
| 43 *monitor_rect = monitor_info.rcMonitor; |
| 44 *work_area = monitor_info.rcWork; |
| 45 return true; |
| 46 } |
| 47 |
| 48 } // namespace |
| 49 |
28 namespace views { | 50 namespace views { |
29 | 51 |
30 // A scoping class that prevents a window from being able to redraw in response | 52 // A scoping class that prevents a window from being able to redraw in response |
31 // to invalidations that may occur within it for the lifetime of the object. | 53 // to invalidations that may occur within it for the lifetime of the object. |
32 // | 54 // |
33 // Why would we want such a thing? Well, it turns out Windows has some | 55 // Why would we want such a thing? Well, it turns out Windows has some |
34 // "unorthodox" behavior when it comes to painting its non-client areas. | 56 // "unorthodox" behavior when it comes to painting its non-client areas. |
35 // Occasionally, Windows will paint portions of the default non-client area | 57 // Occasionally, Windows will paint portions of the default non-client area |
36 // right over the top of the custom frame. This is not simply fixed by handling | 58 // right over the top of the custom frame. This is not simply fixed by handling |
37 // WM_NCPAINT/WM_PAINT, with some investigation it turns out that this | 59 // WM_NCPAINT/WM_PAINT, with some investigation it turns out that this |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
89 window->Init(parent, bounds); | 111 window->Init(parent, bounds); |
90 return window; | 112 return window; |
91 } | 113 } |
92 | 114 |
93 gfx::Rect WindowWin::GetBounds() const { | 115 gfx::Rect WindowWin::GetBounds() const { |
94 gfx::Rect bounds; | 116 gfx::Rect bounds; |
95 WidgetWin::GetBounds(&bounds, true); | 117 WidgetWin::GetBounds(&bounds, true); |
96 return bounds; | 118 return bounds; |
97 } | 119 } |
98 | 120 |
| 121 gfx::Rect WindowWin::GetNormalBounds() const { |
| 122 // If we're in fullscreen mode, we've changed the normal bounds to the monitor |
| 123 // rect, so return the saved bounds instead. |
| 124 if (IsFullscreen()) |
| 125 return gfx::Rect(saved_window_info_.window_rect); |
| 126 |
| 127 WINDOWPLACEMENT wp; |
| 128 wp.length = sizeof(wp); |
| 129 const bool ret = !!GetWindowPlacement(GetNativeView(), &wp); |
| 130 DCHECK(ret); |
| 131 return gfx::Rect(wp.rcNormalPosition); |
| 132 } |
| 133 |
99 void WindowWin::SetBounds(const gfx::Rect& bounds) { | 134 void WindowWin::SetBounds(const gfx::Rect& bounds) { |
100 SetBounds(bounds, NULL); | 135 SetBounds(bounds, NULL); |
101 } | 136 } |
102 | 137 |
103 void WindowWin::SetBounds(const gfx::Rect& bounds, | 138 void WindowWin::SetBounds(const gfx::Rect& bounds, |
104 gfx::NativeWindow other_window) { | 139 gfx::NativeWindow other_window) { |
105 win_util::SetChildBounds(GetNativeView(), GetParent(), other_window, bounds, | 140 win_util::SetChildBounds(GetNativeView(), GetParent(), other_window, bounds, |
106 kMonitorEdgePadding, 0); | 141 kMonitorEdgePadding, 0); |
107 } | 142 } |
108 | 143 |
(...skipping 22 matching lines...) Expand all Loading... |
131 | 166 |
132 int WindowWin::GetShowState() const { | 167 int WindowWin::GetShowState() const { |
133 return SW_SHOWNORMAL; | 168 return SW_SHOWNORMAL; |
134 } | 169 } |
135 | 170 |
136 void WindowWin::ExecuteSystemMenuCommand(int command) { | 171 void WindowWin::ExecuteSystemMenuCommand(int command) { |
137 if (command) | 172 if (command) |
138 SendMessage(GetNativeView(), WM_SYSCOMMAND, command, 0); | 173 SendMessage(GetNativeView(), WM_SYSCOMMAND, command, 0); |
139 } | 174 } |
140 | 175 |
| 176 void WindowWin::PushForceHidden() { |
| 177 if (force_hidden_count_++ == 0) |
| 178 Hide(); |
| 179 } |
| 180 |
| 181 void WindowWin::PopForceHidden() { |
| 182 if (--force_hidden_count_ <= 0) { |
| 183 force_hidden_count_ = 0; |
| 184 ShowWindow(SW_SHOW); |
| 185 } |
| 186 } |
| 187 |
141 // static | 188 // static |
142 int Window::GetLocalizedContentsWidth(int col_resource_id) { | 189 int Window::GetLocalizedContentsWidth(int col_resource_id) { |
143 double chars = _wtof(l10n_util::GetString(col_resource_id).c_str()); | 190 double chars = _wtof(l10n_util::GetString(col_resource_id).c_str()); |
144 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | 191 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
145 ChromeFont font = rb.GetFont(ResourceBundle::BaseFont); | 192 ChromeFont font = rb.GetFont(ResourceBundle::BaseFont); |
146 int width = font.GetExpectedTextWidth(static_cast<int>(chars)); | 193 int width = font.GetExpectedTextWidth(static_cast<int>(chars)); |
147 DCHECK(width > 0); | 194 DCHECK(width > 0); |
148 return width; | 195 return width; |
149 } | 196 } |
150 | 197 |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
228 } | 275 } |
229 | 276 |
230 bool WindowWin::IsMaximized() const { | 277 bool WindowWin::IsMaximized() const { |
231 return !!::IsZoomed(GetNativeView()); | 278 return !!::IsZoomed(GetNativeView()); |
232 } | 279 } |
233 | 280 |
234 bool WindowWin::IsMinimized() const { | 281 bool WindowWin::IsMinimized() const { |
235 return !!::IsIconic(GetNativeView()); | 282 return !!::IsIconic(GetNativeView()); |
236 } | 283 } |
237 | 284 |
| 285 void WindowWin::SetFullscreen(bool fullscreen) { |
| 286 if (fullscreen_ == fullscreen) |
| 287 return; // Nothing to do. |
| 288 |
| 289 // Toggle fullscreen mode. |
| 290 fullscreen_ = fullscreen; |
| 291 |
| 292 // Reduce jankiness during the following position changes by hiding the window |
| 293 // until it's in the final position. |
| 294 PushForceHidden(); |
| 295 |
| 296 // Size/position/style window appropriately. |
| 297 HWND hwnd = GetNativeView(); |
| 298 if (fullscreen_) { |
| 299 // Save current window information. We force the window into restored mode |
| 300 // before going fullscreen because Windows doesn't seem to hide the |
| 301 // taskbar if the window is in the maximized state. |
| 302 saved_window_info_.maximized = IsMaximized(); |
| 303 if (saved_window_info_.maximized) |
| 304 ExecuteSystemMenuCommand(SC_RESTORE); |
| 305 saved_window_info_.style = GetWindowLong(GWL_STYLE); |
| 306 saved_window_info_.ex_style = GetWindowLong(GWL_EXSTYLE); |
| 307 GetWindowRect(&saved_window_info_.window_rect); |
| 308 |
| 309 // Set new window style and size. |
| 310 MONITORINFO monitor_info; |
| 311 monitor_info.cbSize = sizeof(monitor_info); |
| 312 GetMonitorInfo(MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST), |
| 313 &monitor_info); |
| 314 gfx::Rect monitor_rect(monitor_info.rcMonitor); |
| 315 SetWindowLong(GWL_STYLE, |
| 316 saved_window_info_.style & ~(WS_CAPTION | WS_THICKFRAME)); |
| 317 SetWindowLong(GWL_EXSTYLE, |
| 318 saved_window_info_.ex_style & ~(WS_EX_DLGMODALFRAME | |
| 319 WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE)); |
| 320 SetWindowPos(NULL, monitor_rect.x(), monitor_rect.y(), |
| 321 monitor_rect.width(), monitor_rect.height(), |
| 322 SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED); |
| 323 } else { |
| 324 // Reset original window style and size. The multiple window size/moves |
| 325 // here are ugly, but if SetWindowPos() doesn't redraw, the taskbar won't be |
| 326 // repainted. Better-looking methods welcome. |
| 327 gfx::Rect new_rect(saved_window_info_.window_rect); |
| 328 SetWindowLong(GWL_STYLE, saved_window_info_.style); |
| 329 SetWindowLong(GWL_EXSTYLE, saved_window_info_.ex_style); |
| 330 SetWindowPos(NULL, new_rect.x(), new_rect.y(), new_rect.width(), |
| 331 new_rect.height(), |
| 332 SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED); |
| 333 if (saved_window_info_.maximized) |
| 334 ExecuteSystemMenuCommand(SC_MAXIMIZE); |
| 335 } |
| 336 |
| 337 // Undo our anti-jankiness hacks. |
| 338 PopForceHidden(); |
| 339 } |
| 340 |
| 341 bool WindowWin::IsFullscreen() const { |
| 342 return fullscreen_; |
| 343 } |
| 344 |
238 void WindowWin::EnableClose(bool enable) { | 345 void WindowWin::EnableClose(bool enable) { |
239 // If the native frame is rendering its own close button, ask it to disable. | 346 // If the native frame is rendering its own close button, ask it to disable. |
240 non_client_view_->EnableClose(enable); | 347 non_client_view_->EnableClose(enable); |
241 | 348 |
242 // Disable the native frame's close button regardless of whether or not the | 349 // Disable the native frame's close button regardless of whether or not the |
243 // native frame is in use, since this also affects the system menu. | 350 // native frame is in use, since this also affects the system menu. |
244 EnableMenuItem(GetSystemMenu(GetNativeView(), false), | 351 EnableMenuItem(GetSystemMenu(GetNativeView(), false), |
245 SC_CLOSE, enable ? MF_ENABLED : MF_GRAYED); | 352 SC_CLOSE, enable ? MF_ENABLED : MF_GRAYED); |
246 | 353 |
247 // Let the window know the frame changed. | 354 // Let the window know the frame changed. |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
341 WindowWin::WindowWin(WindowDelegate* window_delegate) | 448 WindowWin::WindowWin(WindowDelegate* window_delegate) |
342 : WidgetWin(), | 449 : WidgetWin(), |
343 focus_on_creation_(true), | 450 focus_on_creation_(true), |
344 window_delegate_(window_delegate), | 451 window_delegate_(window_delegate), |
345 non_client_view_(new NonClientView(this)), | 452 non_client_view_(new NonClientView(this)), |
346 owning_hwnd_(NULL), | 453 owning_hwnd_(NULL), |
347 minimum_size_(100, 100), | 454 minimum_size_(100, 100), |
348 is_modal_(false), | 455 is_modal_(false), |
349 restored_enabled_(false), | 456 restored_enabled_(false), |
350 is_always_on_top_(false), | 457 is_always_on_top_(false), |
| 458 fullscreen_(false), |
351 window_closed_(false), | 459 window_closed_(false), |
352 disable_inactive_rendering_(false), | 460 disable_inactive_rendering_(false), |
353 is_active_(false), | 461 is_active_(false), |
354 lock_updates_(false), | 462 lock_updates_(false), |
355 saved_window_style_(0), | 463 saved_window_style_(0), |
356 saved_maximized_state_(0), | 464 saved_maximized_state_(0), |
357 force_hidden_(false) { | 465 ignore_window_pos_changes_(false), |
| 466 ignore_pos_changes_factory_(this), |
| 467 force_hidden_count_(0), |
| 468 last_monitor_(NULL) { |
358 InitClass(); | 469 InitClass(); |
359 DCHECK(window_delegate_); | 470 DCHECK(window_delegate_); |
360 window_delegate_->window_.reset(this); | 471 window_delegate_->window_.reset(this); |
361 // Initialize these values to 0 so that subclasses can override the default | 472 // Initialize these values to 0 so that subclasses can override the default |
362 // behavior before calling Init. | 473 // behavior before calling Init. |
363 set_window_style(0); | 474 set_window_style(0); |
364 set_window_ex_style(0); | 475 set_window_ex_style(0); |
365 } | 476 } |
366 | 477 |
367 void WindowWin::Init(HWND parent, const gfx::Rect& bounds) { | 478 void WindowWin::Init(HWND parent, const gfx::Rect& bounds) { |
(...skipping 18 matching lines...) Expand all Loading... |
386 // Create the ClientView, add it to the NonClientView and add the | 497 // Create the ClientView, add it to the NonClientView and add the |
387 // NonClientView to the RootView. This will cause everything to be parented. | 498 // NonClientView to the RootView. This will cause everything to be parented. |
388 non_client_view_->set_client_view(window_delegate_->CreateClientView(this)); | 499 non_client_view_->set_client_view(window_delegate_->CreateClientView(this)); |
389 WidgetWin::SetContentsView(non_client_view_); | 500 WidgetWin::SetContentsView(non_client_view_); |
390 | 501 |
391 UpdateWindowTitle(); | 502 UpdateWindowTitle(); |
392 | 503 |
393 SetInitialBounds(bounds); | 504 SetInitialBounds(bounds); |
394 InitAlwaysOnTopState(); | 505 InitAlwaysOnTopState(); |
395 | 506 |
| 507 GetMonitorAndRects(bounds.ToRECT(), &last_monitor_, &last_monitor_rect_, |
| 508 &last_work_area_); |
| 509 |
396 if (!IsAppWindow()) { | 510 if (!IsAppWindow()) { |
397 notification_registrar_.Add( | 511 notification_registrar_.Add( |
398 this, | 512 this, |
399 NotificationType::ALL_APPWINDOWS_CLOSED, | 513 NotificationType::ALL_APPWINDOWS_CLOSED, |
400 NotificationService::AllSources()); | 514 NotificationService::AllSources()); |
401 } | 515 } |
402 | 516 |
403 ResetWindowRegion(false); | 517 ResetWindowRegion(false); |
404 | 518 |
405 NotificationService::current()->Notify( | 519 NotificationService::current()->Notify( |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
490 // (now), saving off its placement so it can be properly restored once | 604 // (now), saving off its placement so it can be properly restored once |
491 // everything has settled down. | 605 // everything has settled down. |
492 WINDOWPLACEMENT saved_window_placement; | 606 WINDOWPLACEMENT saved_window_placement; |
493 saved_window_placement.length = sizeof(WINDOWPLACEMENT); | 607 saved_window_placement.length = sizeof(WINDOWPLACEMENT); |
494 GetWindowPlacement(GetNativeView(), &saved_window_placement); | 608 GetWindowPlacement(GetNativeView(), &saved_window_placement); |
495 Hide(); | 609 Hide(); |
496 | 610 |
497 // Important step: restore the window first, since our hiding hack doesn't | 611 // Important step: restore the window first, since our hiding hack doesn't |
498 // work for maximized windows! We tell the frame not to allow itself to be | 612 // work for maximized windows! We tell the frame not to allow itself to be |
499 // made visible though, which removes the brief flicker. | 613 // made visible though, which removes the brief flicker. |
500 force_hidden_ = true; | 614 ++force_hidden_count_; |
501 ::ShowWindow(GetNativeView(), SW_RESTORE); | 615 ::ShowWindow(GetNativeView(), SW_RESTORE); |
502 force_hidden_ = false; | 616 --force_hidden_count_; |
503 | 617 |
504 // We respond to this in response to WM_DWMCOMPOSITIONCHANGED since that is | 618 // We respond to this in response to WM_DWMCOMPOSITIONCHANGED since that is |
505 // the only thing we care about - we don't actually respond to WM_THEMECHANGED | 619 // the only thing we care about - we don't actually respond to WM_THEMECHANGED |
506 // messages. | 620 // messages. |
507 non_client_view_->SetUseNativeFrame(win_util::ShouldUseVistaFrame()); | 621 non_client_view_->SetUseNativeFrame(win_util::ShouldUseVistaFrame()); |
508 | 622 |
509 // Now that we've updated the frame, we'll want to restore our saved placement | 623 // Now that we've updated the frame, we'll want to restore our saved placement |
510 // since the display should have settled down and we can be properly rendered. | 624 // since the display should have settled down and we can be properly rendered. |
511 SetWindowPlacement(GetNativeView(), &saved_window_placement); | 625 SetWindowPlacement(GetNativeView(), &saved_window_placement); |
512 | 626 |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
624 // Make the maximized mode client rect fit the screen exactly, by | 738 // Make the maximized mode client rect fit the screen exactly, by |
625 // subtracting the border Windows automatically adds for maximized mode. | 739 // subtracting the border Windows automatically adds for maximized mode. |
626 int border_thickness = GetSystemMetrics(SM_CXSIZEFRAME); | 740 int border_thickness = GetSystemMetrics(SM_CXSIZEFRAME); |
627 InflateRect(client_rect, -border_thickness, -border_thickness); | 741 InflateRect(client_rect, -border_thickness, -border_thickness); |
628 | 742 |
629 // Find all auto-hide taskbars along the screen edges and adjust in by the | 743 // Find all auto-hide taskbars along the screen edges and adjust in by the |
630 // thickness of the auto-hide taskbar on each such edge, so the window isn't | 744 // thickness of the auto-hide taskbar on each such edge, so the window isn't |
631 // treated as a "fullscreen app", which would cause the taskbars to | 745 // treated as a "fullscreen app", which would cause the taskbars to |
632 // disappear. | 746 // disappear. |
633 HMONITOR monitor = MonitorFromWindow(GetNativeView(), | 747 HMONITOR monitor = MonitorFromWindow(GetNativeView(), |
634 MONITOR_DEFAULTTONEAREST); | 748 MONITOR_DEFAULTTONULL); |
635 if (win_util::EdgeHasTopmostAutoHideTaskbar(ABE_LEFT, monitor)) | 749 if (win_util::EdgeHasTopmostAutoHideTaskbar(ABE_LEFT, monitor)) |
636 client_rect->left += win_util::kAutoHideTaskbarThicknessPx; | 750 client_rect->left += win_util::kAutoHideTaskbarThicknessPx; |
637 if (win_util::EdgeHasTopmostAutoHideTaskbar(ABE_TOP, monitor)) | 751 if (win_util::EdgeHasTopmostAutoHideTaskbar(ABE_TOP, monitor)) |
638 client_rect->top += win_util::kAutoHideTaskbarThicknessPx; | 752 client_rect->top += win_util::kAutoHideTaskbarThicknessPx; |
639 if (win_util::EdgeHasTopmostAutoHideTaskbar(ABE_RIGHT, monitor)) | 753 if (win_util::EdgeHasTopmostAutoHideTaskbar(ABE_RIGHT, monitor)) |
640 client_rect->right -= win_util::kAutoHideTaskbarThicknessPx; | 754 client_rect->right -= win_util::kAutoHideTaskbarThicknessPx; |
641 if (win_util::EdgeHasTopmostAutoHideTaskbar(ABE_BOTTOM, monitor)) | 755 if (win_util::EdgeHasTopmostAutoHideTaskbar(ABE_BOTTOM, monitor)) |
642 client_rect->bottom -= win_util::kAutoHideTaskbarThicknessPx; | 756 client_rect->bottom -= win_util::kAutoHideTaskbarThicknessPx; |
643 | 757 |
644 // We cannot return WVR_REDRAW when there is nonclient area, or Windows | 758 // We cannot return WVR_REDRAW when there is nonclient area, or Windows |
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
898 reinterpret_cast<LPARAM>(new_icon)); | 1012 reinterpret_cast<LPARAM>(new_icon)); |
899 } | 1013 } |
900 | 1014 |
901 LRESULT WindowWin::OnSetText(const wchar_t* text) { | 1015 LRESULT WindowWin::OnSetText(const wchar_t* text) { |
902 // This shouldn't hurt even if we're using the native frame. | 1016 // This shouldn't hurt even if we're using the native frame. |
903 ScopedRedrawLock lock(this); | 1017 ScopedRedrawLock lock(this); |
904 return DefWindowProc(GetNativeView(), WM_SETTEXT, NULL, | 1018 return DefWindowProc(GetNativeView(), WM_SETTEXT, NULL, |
905 reinterpret_cast<LPARAM>(text)); | 1019 reinterpret_cast<LPARAM>(text)); |
906 } | 1020 } |
907 | 1021 |
| 1022 void WindowWin::OnSettingChange(UINT flags, const wchar_t* section) { |
| 1023 if (!GetParent() && (flags == SPI_SETWORKAREA)) { |
| 1024 // Fire a dummy SetWindowPos() call, so we'll trip the code in |
| 1025 // OnWindowPosChanging() below that notices work area changes. |
| 1026 ::SetWindowPos(GetNativeView(), 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | |
| 1027 SWP_NOZORDER | SWP_NOREDRAW | SWP_NOACTIVATE | SWP_NOOWNERZORDER); |
| 1028 SetMsgHandled(TRUE); |
| 1029 } else { |
| 1030 WidgetWin::OnSettingChange(flags, section); |
| 1031 } |
| 1032 } |
| 1033 |
908 void WindowWin::OnSize(UINT size_param, const CSize& new_size) { | 1034 void WindowWin::OnSize(UINT size_param, const CSize& new_size) { |
909 // Don't no-op if the new_size matches current size. If our normal bounds | 1035 // Don't no-op if the new_size matches current size. If our normal bounds |
910 // and maximized bounds are the same, then we need to layout (because we | 1036 // and maximized bounds are the same, then we need to layout (because we |
911 // layout differently when maximized). | 1037 // layout differently when maximized). |
912 SaveWindowPosition(); | 1038 SaveWindowPosition(); |
913 ChangeSize(size_param, new_size); | 1039 ChangeSize(size_param, new_size); |
914 RedrawWindow(GetNativeView(), NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN); | 1040 RedrawWindow(GetNativeView(), NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN); |
915 | 1041 |
916 // ResetWindowRegion is going to trigger WM_NCPAINT. By doing it after we've | 1042 // ResetWindowRegion is going to trigger WM_NCPAINT. By doing it after we've |
917 // invoked OnSize we ensure the RootView has been laid out. | 1043 // invoked OnSize we ensure the RootView has been laid out. |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
964 // Run the system menu at the NonClientView's desired location. | 1090 // Run the system menu at the NonClientView's desired location. |
965 RunSystemMenu(non_client_view_->GetSystemMenuPoint()); | 1091 RunSystemMenu(non_client_view_->GetSystemMenuPoint()); |
966 } else { | 1092 } else { |
967 // Use the default implementation for any other command. | 1093 // Use the default implementation for any other command. |
968 DefWindowProc(GetNativeView(), WM_SYSCOMMAND, notification_code, | 1094 DefWindowProc(GetNativeView(), WM_SYSCOMMAND, notification_code, |
969 MAKELPARAM(click.y, click.x)); | 1095 MAKELPARAM(click.y, click.x)); |
970 } | 1096 } |
971 } | 1097 } |
972 | 1098 |
973 void WindowWin::OnWindowPosChanging(WINDOWPOS* window_pos) { | 1099 void WindowWin::OnWindowPosChanging(WINDOWPOS* window_pos) { |
974 if (force_hidden_) { | 1100 if (force_hidden_count_) { |
975 // Prevent the window from being made visible if we've been asked to do so. | 1101 // Prevent the window from being made visible if we've been asked to do so. |
976 // See comment in header as to why we might want this. | 1102 // See comment in header as to why we might want this. |
977 window_pos->flags &= ~SWP_SHOWWINDOW; | 1103 window_pos->flags &= ~SWP_SHOWWINDOW; |
978 } | 1104 } |
| 1105 |
| 1106 if (ignore_window_pos_changes_) { |
| 1107 // If somebody's trying to toggle our visibility, change the nonclient area, |
| 1108 // change our Z-order, or activate us, we should probably let it go through. |
| 1109 if (!(window_pos->flags & ((IsVisible() ? SWP_HIDEWINDOW : SWP_SHOWWINDOW) | |
| 1110 SWP_FRAMECHANGED)) && |
| 1111 (window_pos->flags & (SWP_NOZORDER | SWP_NOACTIVATE))) { |
| 1112 // Just sizing/moving the window; ignore. |
| 1113 window_pos->flags |= SWP_NOSIZE | SWP_NOMOVE | SWP_NOREDRAW; |
| 1114 window_pos->flags &= ~(SWP_SHOWWINDOW | SWP_HIDEWINDOW); |
| 1115 } |
| 1116 } else if (!GetParent()) { |
| 1117 CRect window_rect; |
| 1118 HMONITOR monitor; |
| 1119 gfx::Rect monitor_rect, work_area; |
| 1120 if (GetWindowRect(&window_rect) && |
| 1121 GetMonitorAndRects(window_rect, &monitor, &monitor_rect, &work_area)) { |
| 1122 if (monitor && (monitor == last_monitor_) && |
| 1123 (IsFullscreen() || ((monitor_rect == last_monitor_rect_) && |
| 1124 (work_area != last_work_area_)))) { |
| 1125 // A rect for the monitor we're on changed. Normally Windows notifies |
| 1126 // us about this (and thus we're reaching here due to the SetWindowPos() |
| 1127 // call in OnSettingChange() above), but with some software (e.g. |
| 1128 // nVidia's nView desktop manager) the work area can change asynchronous |
| 1129 // to any notification, and we're just sent a SetWindowPos() call with a |
| 1130 // new (frequently incorrect) position/size. In either case, the best |
| 1131 // response is to throw away the existing position/size information in |
| 1132 // |window_pos| and recalculate it based on the old window coordinates, |
| 1133 // adjusted for the change in the work area (or, for fullscreen windows, |
| 1134 // to just set it to the monitor rect). |
| 1135 if (IsFullscreen()) { |
| 1136 window_pos->x = monitor_rect.x(); |
| 1137 window_pos->y = monitor_rect.y(); |
| 1138 window_pos->cx = monitor_rect.width(); |
| 1139 window_pos->cy = monitor_rect.height(); |
| 1140 } else if (IsZoomed()) { |
| 1141 window_pos->x = |
| 1142 window_rect.left + work_area.x() - last_work_area_.x(); |
| 1143 window_pos->y = window_rect.top + work_area.y() - last_work_area_.y(); |
| 1144 window_pos->cx = window_rect.Width() + work_area.width() - |
| 1145 last_work_area_.width(); |
| 1146 window_pos->cy = window_rect.Height() + work_area.height() - |
| 1147 last_work_area_.height(); |
| 1148 } else { |
| 1149 gfx::Rect window_gfx_rect(window_rect); |
| 1150 gfx::Rect new_window_rect = window_gfx_rect.AdjustToFit(work_area); |
| 1151 window_pos->x = new_window_rect.x(); |
| 1152 window_pos->y = new_window_rect.y(); |
| 1153 window_pos->cx = new_window_rect.width(); |
| 1154 window_pos->cy = new_window_rect.height(); |
| 1155 } |
| 1156 // WARNING! Don't set SWP_FRAMECHANGED here, it breaks moving the child |
| 1157 // HWNDs for some reason. |
| 1158 window_pos->flags &= ~(SWP_NOSIZE | SWP_NOMOVE | SWP_NOREDRAW); |
| 1159 window_pos->flags |= SWP_NOCOPYBITS; |
| 1160 |
| 1161 // Now ignore all immediately-following SetWindowPos() changes. Windows |
| 1162 // likes to (incorrectly) recalculate what our position/size should be |
| 1163 // and send us further updates. |
| 1164 ignore_window_pos_changes_ = true; |
| 1165 DCHECK(ignore_pos_changes_factory_.empty()); |
| 1166 MessageLoop::current()->PostTask(FROM_HERE, |
| 1167 ignore_pos_changes_factory_.NewRunnableMethod( |
| 1168 &WindowWin::StopIgnoringPosChanges)); |
| 1169 } |
| 1170 last_monitor_ = monitor; |
| 1171 last_monitor_rect_ = monitor_rect; |
| 1172 last_work_area_ = work_area; |
| 1173 } |
| 1174 } |
| 1175 |
979 WidgetWin::OnWindowPosChanging(window_pos); | 1176 WidgetWin::OnWindowPosChanging(window_pos); |
980 } | 1177 } |
981 | 1178 |
982 //////////////////////////////////////////////////////////////////////////////// | 1179 //////////////////////////////////////////////////////////////////////////////// |
983 // WindowWin, private: | 1180 // WindowWin, private: |
984 | 1181 |
985 void WindowWin::BecomeModal() { | 1182 void WindowWin::BecomeModal() { |
986 // We implement modality by crawling up the hierarchy of windows starting | 1183 // We implement modality by crawling up the hierarchy of windows starting |
987 // at the owner, disabling all of them so that they don't receive input | 1184 // at the owner, disabling all of them so that they don't receive input |
988 // messages. | 1185 // messages. |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1160 DCHECK(r); | 1357 DCHECK(r); |
1161 | 1358 |
1162 bool maximized = (win_placement.showCmd == SW_SHOWMAXIMIZED); | 1359 bool maximized = (win_placement.showCmd == SW_SHOWMAXIMIZED); |
1163 CRect window_bounds(win_placement.rcNormalPosition); | 1360 CRect window_bounds(win_placement.rcNormalPosition); |
1164 window_delegate_->SaveWindowPlacement( | 1361 window_delegate_->SaveWindowPlacement( |
1165 gfx::Rect(win_placement.rcNormalPosition), maximized, is_always_on_top_); | 1362 gfx::Rect(win_placement.rcNormalPosition), maximized, is_always_on_top_); |
1166 } | 1363 } |
1167 | 1364 |
1168 void WindowWin::LockUpdates() { | 1365 void WindowWin::LockUpdates() { |
1169 lock_updates_ = true; | 1366 lock_updates_ = true; |
1170 saved_window_style_ = GetWindowLong(GetNativeView(), GWL_STYLE); | 1367 saved_window_style_ = GetWindowLong(GWL_STYLE); |
1171 SetWindowLong(GetNativeView(), GWL_STYLE, saved_window_style_ & ~WS_VISIBLE); | 1368 SetWindowLong(GWL_STYLE, saved_window_style_ & ~WS_VISIBLE); |
1172 } | 1369 } |
1173 | 1370 |
1174 void WindowWin::UnlockUpdates() { | 1371 void WindowWin::UnlockUpdates() { |
1175 SetWindowLong(GetNativeView(), GWL_STYLE, saved_window_style_); | 1372 SetWindowLong(GWL_STYLE, saved_window_style_); |
1176 lock_updates_ = false; | 1373 lock_updates_ = false; |
1177 } | 1374 } |
1178 | 1375 |
1179 void WindowWin::ResetWindowRegion(bool force) { | 1376 void WindowWin::ResetWindowRegion(bool force) { |
1180 // A native frame uses the native window region, and we don't want to mess | 1377 // A native frame uses the native window region, and we don't want to mess |
1181 // with it. | 1378 // with it. |
1182 if (non_client_view_->UseNativeFrame()) { | 1379 if (non_client_view_->UseNativeFrame()) { |
1183 if (force) | 1380 if (force) |
1184 SetWindowRgn(NULL, TRUE); | 1381 SetWindowRgn(NULL, TRUE); |
1185 return; | 1382 return; |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1234 resize_cursors_[RC_NORMAL] = LoadCursor(NULL, IDC_ARROW); | 1431 resize_cursors_[RC_NORMAL] = LoadCursor(NULL, IDC_ARROW); |
1235 resize_cursors_[RC_VERTICAL] = LoadCursor(NULL, IDC_SIZENS); | 1432 resize_cursors_[RC_VERTICAL] = LoadCursor(NULL, IDC_SIZENS); |
1236 resize_cursors_[RC_HORIZONTAL] = LoadCursor(NULL, IDC_SIZEWE); | 1433 resize_cursors_[RC_HORIZONTAL] = LoadCursor(NULL, IDC_SIZEWE); |
1237 resize_cursors_[RC_NESW] = LoadCursor(NULL, IDC_SIZENESW); | 1434 resize_cursors_[RC_NESW] = LoadCursor(NULL, IDC_SIZENESW); |
1238 resize_cursors_[RC_NWSE] = LoadCursor(NULL, IDC_SIZENWSE); | 1435 resize_cursors_[RC_NWSE] = LoadCursor(NULL, IDC_SIZENWSE); |
1239 initialized = true; | 1436 initialized = true; |
1240 } | 1437 } |
1241 } | 1438 } |
1242 | 1439 |
1243 } // namespace views | 1440 } // namespace views |
OLD | NEW |