diff options
author | pkasting@chromium.org <pkasting@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-04-17 00:24:43 +0000 |
---|---|---|
committer | pkasting@chromium.org <pkasting@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-04-17 00:24:43 +0000 |
commit | 4eaa87f37d0fd5af2487f60aee9323882c39f2e9 (patch) | |
tree | 2a0947a5c4df4a6fdefd7769616b83f6b53c6aa2 | |
parent | 78590369cbb7a30a248d3d037b0088275cd4616b (diff) | |
download | chromium_src-4eaa87f37d0fd5af2487f60aee9323882c39f2e9.zip chromium_src-4eaa87f37d0fd5af2487f60aee9323882c39f2e9.tar.gz chromium_src-4eaa87f37d0fd5af2487f60aee9323882c39f2e9.tar.bz2 |
Reorganize fullscreen mode handling. Now nearly everything is in WindowWin. This also includes work area change notifications, which only really apply to Windows (and not pure Widgets) anyway. Some parts (namely, the browser-specific things) are still in BrowserView.This allows me to fix the bug where unlocking your screen resized fullscreen mode windows incorrectly.There are probably one or two other small bits tangled in here -- this got a bit messy. I moved the exit bubble out of browser/ because it wasn't browser-specific; in theory, any WindowWin can now go into fullscreen mode.BUG=8159
Review URL: http://codereview.chromium.org/78002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@13908 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/views/frame/browser_frame.cc | 4 | ||||
-rw-r--r-- | chrome/browser/views/frame/browser_view.cc | 138 | ||||
-rw-r--r-- | chrome/browser/views/frame/browser_view.h | 20 | ||||
-rw-r--r-- | chrome/browser/views/frame/glass_browser_frame_view.cc | 14 | ||||
-rw-r--r-- | chrome/browser/views/frame/opaque_browser_frame_view.cc | 17 | ||||
-rw-r--r-- | chrome/browser/window_sizer.cc | 10 | ||||
-rw-r--r-- | chrome/common/win_util.cc | 2 | ||||
-rw-r--r-- | chrome/views/widget/widget_win.cc | 101 | ||||
-rw-r--r-- | chrome/views/widget/widget_win.h | 35 | ||||
-rw-r--r-- | chrome/views/window/window.h | 7 | ||||
-rw-r--r-- | chrome/views/window/window_win.cc | 213 | ||||
-rw-r--r-- | chrome/views/window/window_win.h | 55 |
12 files changed, 344 insertions, 272 deletions
diff --git a/chrome/browser/views/frame/browser_frame.cc b/chrome/browser/views/frame/browser_frame.cc index 2973f5c..235fedc 100644 --- a/chrome/browser/views/frame/browser_frame.cc +++ b/chrome/browser/views/frame/browser_frame.cc @@ -146,7 +146,7 @@ LRESULT BrowserFrame::OnNCCalcSize(BOOL mode, LPARAM l_param) { // treated as a "fullscreen app", which would cause the taskbars to // disappear. HMONITOR monitor = MonitorFromWindow(GetNativeView(), - MONITOR_DEFAULTTONEAREST); + MONITOR_DEFAULTTONULL); if (win_util::EdgeHasTopmostAutoHideTaskbar(ABE_LEFT, monitor)) client_rect->left += win_util::kAutoHideTaskbarThicknessPx; if (win_util::EdgeHasTopmostAutoHideTaskbar(ABE_RIGHT, monitor)) @@ -238,7 +238,7 @@ void BrowserFrame::UpdateDWMFrame() { // because the GDI-drawn text in the web content composited over it will // become semi-transparent over any glass area. MARGINS margins = { 0 }; - if (browser_view_->CanCurrentlyResize()) { + if (!IsMaximized() && !IsFullscreen()) { margins.cxLeftWidth = kClientEdgeThickness + 1; margins.cxRightWidth = kClientEdgeThickness + 1; margins.cyBottomHeight = kClientEdgeThickness + 1; diff --git a/chrome/browser/views/frame/browser_view.cc b/chrome/browser/views/frame/browser_view.cc index 2a00dc3..2505ff8 100644 --- a/chrome/browser/views/frame/browser_view.cc +++ b/chrome/browser/views/frame/browser_view.cc @@ -59,7 +59,7 @@ #include "chrome/views/widget/hwnd_notification_source.h" #include "chrome/views/widget/root_view.h" #include "chrome/views/window/non_client_view.h" -#include "chrome/views/window/window.h" +#include "chrome/views/window/window_win.h" #include "grit/chromium_strings.h" #include "grit/generated_resources.h" #include "grit/theme_resources.h" @@ -136,8 +136,8 @@ class ResizeCorner : public views::View { ResizeCorner() { } virtual void Paint(ChromeCanvas* canvas) { - BrowserView* browser = GetBrowserView(); - if (browser && !browser->CanCurrentlyResize()) + views::WindowWin* window = GetWindow(); + if (!window || (window->IsMaximized() || window->IsFullscreen())) return; SkBitmap* bitmap = ResourceBundle::GetSharedInstance().GetBitmapNamed( @@ -164,8 +164,8 @@ class ResizeCorner : public views::View { } virtual gfx::Size GetPreferredSize() { - BrowserView* browser = GetBrowserView(); - return (browser && !browser->CanCurrentlyResize()) ? + views::WindowWin* window = GetWindow(); + return (!window || window->IsMaximized() || window->IsFullscreen()) ? gfx::Size() : GetSize(); } @@ -181,11 +181,11 @@ class ResizeCorner : public views::View { } private: - // Returns the BrowserView we're displayed in. Returns NULL if we're not - // currently in a browser view. - BrowserView* GetBrowserView() { - View* browser = GetAncestorWithClassName(kBrowserViewClassName); - return browser ? static_cast<BrowserView*>(browser) : NULL; + // Returns the WindowWin we're displayed in. Returns NULL if we're not + // currently in a window. + views::WindowWin* GetWindow() { + views::Widget* widget = GetWidget(); + return widget ? static_cast<views::WindowWin*>(widget) : NULL; } DISALLOW_COPY_AND_ASSIGN(ResizeCorner); @@ -277,7 +277,6 @@ BrowserView::BrowserView(Browser* browser) find_bar_y_(0), contents_container_(NULL), initialized_(false), - fullscreen_(false), ignore_layout_(false), hung_window_detector_(&hung_plugin_action_), ticker_(0) @@ -340,10 +339,6 @@ void BrowserView::WindowMoveOrResizeStarted() { tab_contents->AsWebContents()->WindowMoveOrResizeStarted(); } -bool BrowserView::CanCurrentlyResize() const { - return !IsMaximized() && !IsFullscreen(); -} - gfx::Rect BrowserView::GetToolbarBounds() const { return toolbar_->bounds(); } @@ -603,16 +598,7 @@ void BrowserView::SetStarredState(bool is_starred) { } gfx::Rect BrowserView::GetNormalBounds() const { - // If we're in fullscreen mode, we've changed the normal bounds to the monitor - // rect, so return the saved bounds instead. - if (fullscreen_) - return gfx::Rect(saved_window_info_.window_rect); - - WINDOWPLACEMENT wp; - wp.length = sizeof(wp); - const bool ret = !!GetWindowPlacement(frame_->GetNativeView(), &wp); - DCHECK(ret); - return gfx::Rect(wp.rcNormalPosition); + return frame_->GetNormalBounds(); } bool BrowserView::IsMaximized() const { @@ -620,30 +606,28 @@ bool BrowserView::IsMaximized() const { } void BrowserView::SetFullscreen(bool fullscreen) { - if (fullscreen_ == fullscreen) + if (IsFullscreen() == fullscreen) return; // Nothing to do. - // Move focus out of the location bar if necessary. + // Reduce jankiness during the following position changes by: + // * Hiding the window until it's in the final position + // * Ignoring all intervening Layout() calls, which resize the webpage and + // thus are slow and look ugly + ignore_layout_ = true; LocationBarView* location_bar = toolbar_->GetLocationBarView(); - if (!fullscreen_) { + AutocompleteEditViewWin* edit_view = + static_cast<AutocompleteEditViewWin*>(location_bar->location_entry()); + if (IsFullscreen()) { + // Hide the fullscreen bubble as soon as possible, since the mode toggle can + // take enough time for the user to notice. + fullscreen_bubble_.reset(); + } else { + // Move focus out of the location bar if necessary. views::FocusManager* focus_manager = GetFocusManager(); DCHECK(focus_manager); if (focus_manager->GetFocusedView() == location_bar) focus_manager->ClearFocus(); - } - AutocompleteEditViewWin* edit_view = - static_cast<AutocompleteEditViewWin*>(location_bar->location_entry()); - - // Toggle fullscreen mode. - fullscreen_ = fullscreen; - // Reduce jankiness during the following position changes by: - // * Hiding the window until it's in the final position - // * Ignoring all intervening Layout() calls, which resize the webpage and - // thus are slow and look ugly - ignore_layout_ = true; - frame_->set_force_hidden(true); - if (fullscreen_) { // If we don't hide the edit and force it to not show until we come out of // fullscreen, then if the user was on the New Tab Page, the edit contents // will appear atop the web contents once we go into fullscreen mode. This @@ -652,59 +636,18 @@ void BrowserView::SetFullscreen(bool fullscreen) { edit_view->set_force_hidden(true); ShowWindow(edit_view->m_hWnd, SW_HIDE); } - frame_->Hide(); + frame_->PushForceHidden(); // Notify bookmark bar, so it can set itself to the appropriate drawing state. if (bookmark_bar_view_.get()) - bookmark_bar_view_->OnFullscreenToggled(fullscreen_); - - // Size/position/style window appropriately. - views::Widget* widget = GetWidget(); - HWND hwnd = widget->GetNativeView(); - MONITORINFO monitor_info; - monitor_info.cbSize = sizeof(monitor_info); - GetMonitorInfo(MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY), - &monitor_info); - gfx::Rect monitor_rect(monitor_info.rcMonitor); - if (fullscreen_) { - // Save current window information. We force the window into restored mode - // before going fullscreen because Windows doesn't seem to hide the - // taskbar if the window is in the maximized state. - saved_window_info_.maximized = IsMaximized(); - if (saved_window_info_.maximized) - frame_->ExecuteSystemMenuCommand(SC_RESTORE); - saved_window_info_.style = GetWindowLong(hwnd, GWL_STYLE); - saved_window_info_.ex_style = GetWindowLong(hwnd, GWL_EXSTYLE); - GetWindowRect(hwnd, &saved_window_info_.window_rect); - - // Set new window style and size. - SetWindowLong(hwnd, GWL_STYLE, - saved_window_info_.style & ~(WS_CAPTION | WS_THICKFRAME)); - SetWindowLong(hwnd, GWL_EXSTYLE, - saved_window_info_.ex_style & ~(WS_EX_DLGMODALFRAME | - WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE)); - SetWindowPos(hwnd, NULL, monitor_rect.x(), monitor_rect.y(), - monitor_rect.width(), monitor_rect.height(), - SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED); - - fullscreen_bubble_.reset(new FullscreenExitBubble(widget, browser_.get())); - } else { - // Hide the fullscreen bubble as soon as possible, since the calls below can - // take enough time for the user to notice. - fullscreen_bubble_.reset(); + bookmark_bar_view_->OnFullscreenToggled(fullscreen); - // Reset original window style and size. The multiple window size/moves - // here are ugly, but if SetWindowPos() doesn't redraw, the taskbar won't be - // repainted. Better-looking methods welcome. - gfx::Rect new_rect(saved_window_info_.window_rect); - SetWindowLong(hwnd, GWL_STYLE, saved_window_info_.style); - SetWindowLong(hwnd, GWL_EXSTYLE, saved_window_info_.ex_style); - SetWindowPos(hwnd, NULL, new_rect.x(), new_rect.y(), new_rect.width(), - new_rect.height(), - SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED); - if (saved_window_info_.maximized) - frame_->ExecuteSystemMenuCommand(SC_MAXIMIZE); + // Toggle fullscreen mode. + frame_->SetFullscreen(fullscreen); + if (IsFullscreen()) { + fullscreen_bubble_.reset(new FullscreenExitBubble(frame_, browser_.get())); + } else { // Show the edit again since we're no longer in fullscreen mode. edit_view->set_force_hidden(false); ShowWindow(edit_view->m_hWnd, SW_SHOW); @@ -714,12 +657,11 @@ void BrowserView::SetFullscreen(bool fullscreen) { // it's in its final position. ignore_layout_ = false; Layout(); - frame_->set_force_hidden(false); - ShowWindow(hwnd, SW_SHOW); + frame_->PopForceHidden(); } bool BrowserView::IsFullscreen() const { - return fullscreen_; + return frame_->IsFullscreen(); } LocationBar* BrowserView::GetLocationBar() const { @@ -772,7 +714,7 @@ bool BrowserView::IsBookmarkBarVisible() const { } gfx::Rect BrowserView::GetRootWindowResizerRect() const { - if (!CanCurrentlyResize()) + if (frame_->IsMaximized() || frame_->IsFullscreen()) return gfx::Rect(); // We don't specify a resize corner size if we have a bottom shelf either. @@ -1051,10 +993,10 @@ std::wstring BrowserView::GetWindowName() const { void BrowserView::SaveWindowPlacement(const gfx::Rect& bounds, bool maximized, bool always_on_top) { - // If fullscreen_ is true, we've just changed into fullscreen mode, and we're - // catching the going-into-fullscreen sizing and positioning calls, which we - // want to ignore. - if (!fullscreen_ && browser_->ShouldSaveWindowPlacement()) { + // If IsFullscreen() is true, we've just changed into fullscreen mode, and + // we're catching the going-into-fullscreen sizing and positioning calls, + // which we want to ignore. + if (!IsFullscreen() && browser_->ShouldSaveWindowPlacement()) { WindowDelegate::SaveWindowPlacement(bounds, maximized, always_on_top); browser_->SaveWindowPlacement(bounds, maximized); } @@ -1150,7 +1092,7 @@ int BrowserView::NonClientHitTest(const gfx::Point& point) { // area of the window. So we need to treat hit-tests in these regions as // hit-tests of the titlebar. - if (CanCurrentlyResize()) { + if (!frame_->IsMaximized() && !frame_->IsFullscreen()) { CRect client_rect; ::GetClientRect(frame_->GetNativeView(), &client_rect); gfx::Size resize_corner_size = ResizeCorner::GetSize(); diff --git a/chrome/browser/views/frame/browser_view.h b/chrome/browser/views/frame/browser_view.h index 89aad2a..30b5aaf6 100644 --- a/chrome/browser/views/frame/browser_view.h +++ b/chrome/browser/views/frame/browser_view.h @@ -72,11 +72,6 @@ class BrowserView : public BrowserWindow, // initiated. void WindowMoveOrResizeStarted(); - // Returns whether the browser can be resized _now_. This differs from - // CanResize() below, which returns whether the window is ever resizable in - // principle. - bool CanCurrentlyResize() const; - // Returns the bounds of the toolbar, in BrowserView coordinates. gfx::Rect GetToolbarBounds() const; @@ -269,15 +264,6 @@ class BrowserView : public BrowserWindow, views::View* parent, views::View* child); private: - // Information saved before going into fullscreen mode, used to restore the - // window afterwards. - struct SavedWindowInfo { - bool maximized; - LONG style; - LONG ex_style; - RECT window_rect; - }; - // Browser window related initializations. void Init(); @@ -391,16 +377,10 @@ class BrowserView : public BrowserWindow, // True if we have already been initialized. bool initialized_; - // True if we're in fullscreen mode. - bool fullscreen_; - // True if we should ignore requests to layout. This is set while toggling // fullscreen mode on and off to reduce jankiness. bool ignore_layout_; - // Saved window information from before entering fullscreen mode. - SavedWindowInfo saved_window_info_; - scoped_ptr<FullscreenExitBubble> fullscreen_bubble_; // Lazily created representation of the system menu. diff --git a/chrome/browser/views/frame/glass_browser_frame_view.cc b/chrome/browser/views/frame/glass_browser_frame_view.cc index d170a72..770245f 100644 --- a/chrome/browser/views/frame/glass_browser_frame_view.cc +++ b/chrome/browser/views/frame/glass_browser_frame_view.cc @@ -184,9 +184,10 @@ gfx::Point GlassBrowserFrameView::GetSystemMenuPoint() const { // (where we don't do this trick) maximized windows have no client edge and // only the frame edge is offscreen. system_menu_point.SetPoint(NonClientBorderThickness() - - (browser_view_->CanCurrentlyResize() ? kClientEdgeThickness : 0), + ((frame_->IsMaximized() || frame_->IsFullscreen()) ? + 0 : kClientEdgeThickness), NonClientTopBorderHeight() + browser_view_->GetTabStripHeight() - - (browser_view_->IsFullscreen() ? 0 : kClientEdgeThickness)); + (frame_->IsFullscreen() ? 0 : kClientEdgeThickness)); } else { system_menu_point.SetPoint(0, -kFrameShadowThickness); } @@ -239,16 +240,17 @@ void GlassBrowserFrameView::Layout() { // GlassBrowserFrameView, private: int GlassBrowserFrameView::FrameBorderThickness() const { - return browser_view_->CanCurrentlyResize() ? - GetSystemMetrics(SM_CXSIZEFRAME) : 0; + return (frame_->IsMaximized() || frame_->IsFullscreen()) ? + 0 : GetSystemMetrics(SM_CXSIZEFRAME); } int GlassBrowserFrameView::NonClientBorderThickness() const { - return browser_view_->CanCurrentlyResize() ? kNonClientBorderThickness : 0; + return (frame_->IsMaximized() || frame_->IsFullscreen()) ? + 0 : kNonClientBorderThickness; } int GlassBrowserFrameView::NonClientTopBorderHeight() const { - if (browser_view_->IsFullscreen()) + if (frame_->IsFullscreen()) return 0; // We'd like to use FrameBorderThickness() here, but the maximized Aero glass // frame has a 0 frame border around most edges and a CXSIZEFRAME-thick border diff --git a/chrome/browser/views/frame/opaque_browser_frame_view.cc b/chrome/browser/views/frame/opaque_browser_frame_view.cc index 9e8692b..ef80018 100644 --- a/chrome/browser/views/frame/opaque_browser_frame_view.cc +++ b/chrome/browser/views/frame/opaque_browser_frame_view.cc @@ -463,7 +463,7 @@ gfx::Point OpaqueBrowserFrameView::GetSystemMenuPoint() const { gfx::Point system_menu_point( MirroredXCoordinateInsideView(FrameBorderThickness()), NonClientTopBorderHeight() + browser_view_->GetTabStripHeight() - - (browser_view_->IsFullscreen() ? 0 : kClientEdgeThickness)); + (frame_->IsFullscreen() ? 0 : kClientEdgeThickness)); ConvertPointToScreen(this, &system_menu_point); return system_menu_point; } @@ -503,7 +503,7 @@ void OpaqueBrowserFrameView::GetWindowMask(const gfx::Size& size, gfx::Path* window_mask) { DCHECK(window_mask); - if (!browser_view_->CanCurrentlyResize()) + if (frame_->IsMaximized() || frame_->IsFullscreen()) return; // Redefine the window visible region for the new size. @@ -540,7 +540,7 @@ void OpaqueBrowserFrameView::ResetWindowControls() { // OpaqueBrowserFrameView, views::View overrides: void OpaqueBrowserFrameView::Paint(ChromeCanvas* canvas) { - if (browser_view_->IsFullscreen()) + if (frame_->IsFullscreen()) return; // Nothing is visible, so don't bother to paint. if (frame_->IsMaximized()) @@ -647,7 +647,8 @@ SkBitmap OpaqueBrowserFrameView::GetFavIconForTabIconView() { // OpaqueBrowserFrameView, private: int OpaqueBrowserFrameView::FrameBorderThickness() const { - return browser_view_->CanCurrentlyResize() ? kFrameBorderThickness : 0; + return (frame_->IsMaximized() || frame_->IsFullscreen()) ? + 0 : kFrameBorderThickness; } int OpaqueBrowserFrameView::TopResizeHeight() const { @@ -657,7 +658,8 @@ int OpaqueBrowserFrameView::TopResizeHeight() const { int OpaqueBrowserFrameView::NonClientBorderThickness() const { // When we fill the screen, we don't show a client edge. return FrameBorderThickness() + - (browser_view_->CanCurrentlyResize() ? kClientEdgeThickness : 0); + ((frame_->IsMaximized() || frame_->IsFullscreen()) ? + 0 : kClientEdgeThickness); } int OpaqueBrowserFrameView::NonClientTopBorderHeight() const { @@ -666,8 +668,9 @@ int OpaqueBrowserFrameView::NonClientTopBorderHeight() const { return TitleCoordinates(&title_top_spacing, &title_thickness); } - return FrameBorderThickness() + (browser_view_->CanCurrentlyResize() ? - kNonClientRestoredExtraThickness : 0); + return FrameBorderThickness() + + ((frame_->IsMaximized() || frame_->IsFullscreen()) ? + 0 : kNonClientRestoredExtraThickness); } int OpaqueBrowserFrameView::UnavailablePixelsAtBottomOfNonClientHeight() const { diff --git a/chrome/browser/window_sizer.cc b/chrome/browser/window_sizer.cc index dfee295..a3ec88d 100644 --- a/chrome/browser/window_sizer.cc +++ b/chrome/browser/window_sizer.cc @@ -41,7 +41,7 @@ class DefaultMonitorInfoProvider : public WindowSizer::MonitorInfoProvider { const gfx::Rect& match_rect) const { CRect other_bounds_crect = match_rect.ToRECT(); MONITORINFO monitor_info = GetMonitorInfoForMonitor(MonitorFromRect( - &other_bounds_crect, MONITOR_DEFAULTTOPRIMARY)); + &other_bounds_crect, MONITOR_DEFAULTTONEAREST)); return gfx::Rect(monitor_info.rcWork); } @@ -49,7 +49,7 @@ class DefaultMonitorInfoProvider : public WindowSizer::MonitorInfoProvider { const gfx::Rect& match_rect) const { CRect other_bounds_crect = match_rect.ToRECT(); MONITORINFO monitor_info = GetMonitorInfoForMonitor(MonitorFromRect( - &other_bounds_crect, MONITOR_DEFAULTTOPRIMARY)); + &other_bounds_crect, MONITOR_DEFAULTTONEAREST)); return gfx::Point(monitor_info.rcWork.left - monitor_info.rcMonitor.left, monitor_info.rcWork.top - monitor_info.rcMonitor.top); } @@ -130,9 +130,9 @@ class DefaultStateProvider : public WindowSizer::StateProvider { for (; it != end; ++it) { Browser* last_active = *it; if (last_active && last_active->type() == Browser::TYPE_NORMAL) { - BrowserWindow* frame = last_active->window(); - DCHECK(frame); - *bounds = frame->GetNormalBounds(); + BrowserWindow* window = last_active->window(); + DCHECK(window); + *bounds = window->GetNormalBounds(); return true; } } diff --git a/chrome/common/win_util.cc b/chrome/common/win_util.cc index 98d0c48..692aeca 100644 --- a/chrome/common/win_util.cc +++ b/chrome/common/win_util.cc @@ -531,7 +531,7 @@ bool EdgeHasTopmostAutoHideTaskbar(UINT edge, HMONITOR monitor) { taskbar_data.uEdge = edge; HWND taskbar = reinterpret_cast<HWND>(SHAppBarMessage(ABM_GETAUTOHIDEBAR, &taskbar_data)); - return ::IsWindow(taskbar) && + return ::IsWindow(taskbar) && (monitor != NULL) && (MonitorFromWindow(taskbar, MONITOR_DEFAULTTONULL) == monitor) && (GetWindowLong(taskbar, GWL_EXSTYLE) & WS_EX_TOPMOST); } diff --git a/chrome/views/widget/widget_win.cc b/chrome/views/widget/widget_win.cc index ddf8db8..a362f21 100644 --- a/chrome/views/widget/widget_win.cc +++ b/chrome/views/widget/widget_win.cc @@ -19,25 +19,6 @@ #include "chrome/views/widget/hwnd_notification_source.h" #include "chrome/views/widget/root_view.h" -namespace { - -bool GetMonitorAndWorkAreaForRect(const RECT& rect, - HMONITOR* monitor, - gfx::Rect* work_area) { - DCHECK(monitor); - DCHECK(work_area); - *monitor = MonitorFromRect(&rect, MONITOR_DEFAULTTONEAREST); - if (!*monitor) - return false; - MONITORINFO monitor_info = { 0 }; - monitor_info.cbSize = sizeof(monitor_info); - GetMonitorInfo(*monitor, &monitor_info); - *work_area = monitor_info.rcWork; - return true; -} - -} // namespace - namespace views { static const DWORD kWindowDefaultChildStyle = @@ -121,7 +102,6 @@ static RegisteredClasses* registered_classes = NULL; WidgetWin::WidgetWin() : close_widget_factory_(this), - ignore_pos_changes_factory_(this), active_mouse_tracking_flags_(0), has_capture_(false), current_action_(FA_NONE), @@ -134,9 +114,7 @@ WidgetWin::WidgetWin() last_mouse_event_was_move_(false), is_mouse_down_(false), class_style_(CS_DBLCLKS), - hwnd_(NULL), - last_monitor_(NULL), - ignore_window_pos_changes_(false) { + hwnd_(NULL) { } WidgetWin::~WidgetWin() { @@ -170,9 +148,6 @@ void WidgetWin::Init(HWND parent, const gfx::Rect& bounds, TRACK_HWND_CREATION(hwnd_); SetWindowSupportsRerouteMouseWheel(hwnd_); - GetMonitorAndWorkAreaForRect(bounds.ToRECT(), &last_monitor_, - &last_work_area_); - // The window procedure should have set the data for us. DCHECK(win_util::GetWindowUserData(hwnd_) == this); @@ -686,16 +661,6 @@ void WidgetWin::OnRButtonDblClk(UINT flags, const CPoint& point) { ProcessMousePressed(point, flags | MK_RBUTTON, true, false); } -void WidgetWin::OnSettingChange(UINT flags, const wchar_t* section) { - if (!GetParent() && (flags == SPI_SETWORKAREA)) { - // Fire a dummy SetWindowPos() call, so we'll trip the code in - // OnWindowPosChanging() below that notices work area changes. - ::SetWindowPos(GetNativeView(), 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | - SWP_NOZORDER | SWP_NOREDRAW | SWP_NOACTIVATE | SWP_NOOWNERZORDER); - SetMsgHandled(TRUE); - } -} - void WidgetWin::OnSize(UINT param, const CSize& size) { ChangeSize(param, size); } @@ -705,70 +670,6 @@ void WidgetWin::OnThemeChanged() { gfx::NativeTheme::instance()->CloseHandles(); } -void WidgetWin::OnWindowPosChanging(WINDOWPOS* window_pos) { - if (ignore_window_pos_changes_) { - // If somebody's trying to toggle our visibility, change the nonclient area, - // change our Z-order, or activate us, we should probably let it go through. - if (!(window_pos->flags & ((IsVisible() ? SWP_HIDEWINDOW : SWP_SHOWWINDOW) | - SWP_FRAMECHANGED)) && - (window_pos->flags & (SWP_NOZORDER | SWP_NOACTIVATE))) { - // Just sizing/moving the window; ignore. - window_pos->flags |= SWP_NOSIZE | SWP_NOMOVE | SWP_NOREDRAW; - window_pos->flags &= ~(SWP_SHOWWINDOW | SWP_HIDEWINDOW); - } - } else if (!GetParent()) { - CRect window_rect; - HMONITOR monitor; - gfx::Rect work_area; - if (GetWindowRect(&window_rect) && - GetMonitorAndWorkAreaForRect(window_rect, &monitor, &work_area)) { - if ((monitor == last_monitor_) && (work_area != last_work_area_)) { - // The work area for the monitor we're on changed. Normally Windows - // notifies us about this (and thus we're reaching here due to the - // SetWindowPos() call in OnSettingChange() above), but with some - // software (e.g. nVidia's nView desktop manager) the work area can - // change asynchronous to any notification, and we're just sent a - // SetWindowPos() call with a new (frequently incorrect) position/size. - // In either case, the best response is to throw away the existing - // position/size information in |window_pos| and recalculate it based on - // the old window coordinates, adjusted for the change in the work area. - if (IsZoomed()) { - window_pos->x = window_rect.left + work_area.x() - last_work_area_.x(); - window_pos->y = window_rect.top + work_area.y() - last_work_area_.y(); - window_pos->cx = window_rect.Width() + work_area.width() - - last_work_area_.width(); - window_pos->cy = window_rect.Height() + work_area.height() - - last_work_area_.height(); - } else { - gfx::Rect window_gfx_rect(window_rect); - gfx::Rect new_window_rect = window_gfx_rect.AdjustToFit(work_area); - window_pos->x = new_window_rect.x(); - window_pos->y = new_window_rect.y(); - window_pos->cx = new_window_rect.width(); - window_pos->cy = new_window_rect.height(); - } - // WARNING! Don't set SWP_FRAMECHANGED here, it breaks moving the child - // HWNDs for some reason. - window_pos->flags &= ~(SWP_NOSIZE | SWP_NOMOVE | SWP_NOREDRAW); - window_pos->flags |= SWP_NOCOPYBITS; - - // Now ignore all immediately-following SetWindowPos() changes. Windows - // likes to (incorrectly) recalculate what our position/size should be - // and send us further updates. - ignore_window_pos_changes_ = true; - DCHECK(ignore_pos_changes_factory_.empty()); - MessageLoop::current()->PostTask(FROM_HERE, - ignore_pos_changes_factory_.NewRunnableMethod( - &WidgetWin::StopIgnoringPosChanges)); - } - last_monitor_ = monitor; - last_work_area_ = work_area; - } - } - - SetMsgHandled(FALSE); -} - void WidgetWin::OnFinalMessage(HWND window) { if (delete_on_destroy_) delete this; diff --git a/chrome/views/widget/widget_win.h b/chrome/views/widget/widget_win.h index 264e9f9..ede4252 100644 --- a/chrome/views/widget/widget_win.h +++ b/chrome/views/widget/widget_win.h @@ -282,10 +282,20 @@ class WidgetWin : public Widget, return ::GetParent(GetNativeView()); } + LONG GetWindowLong(int index) { + DCHECK(::IsWindow(GetNativeView())); + return ::GetWindowLong(GetNativeView(), index); + } + BOOL GetWindowRect(RECT* rect) const { return ::GetWindowRect(GetNativeView(), rect); } + LONG SetWindowLong(int index, LONG new_long) { + DCHECK(::IsWindow(GetNativeView())); + return ::SetWindowLong(GetNativeView(), index, new_long); + } + BOOL SetWindowPos(HWND hwnd_after, int x, int y, int cx, int cy, UINT flags) { DCHECK(::IsWindow(GetNativeView())); return ::SetWindowPos(GetNativeView(), hwnd_after, x, y, cx, cy, flags); @@ -450,14 +460,18 @@ class WidgetWin : public Widget, SetMsgHandled(FALSE); return 0; } - virtual void OnSettingChange(UINT flags, const wchar_t* section); + virtual void OnSettingChange(UINT flags, const wchar_t* section) { + SetMsgHandled(FALSE); + } virtual void OnSize(UINT param, const CSize& size); virtual void OnSysCommand(UINT notification_code, CPoint click) { } virtual void OnThemeChanged(); virtual void OnVScroll(int scroll_type, short position, HWND scrollbar) { SetMsgHandled(FALSE); } - virtual void OnWindowPosChanging(WINDOWPOS* window_pos); + virtual void OnWindowPosChanging(WINDOWPOS* window_pos) { + SetMsgHandled(FALSE); + } virtual void OnWindowPosChanged(WINDOWPOS* window_pos) { SetMsgHandled(FALSE); } @@ -537,17 +551,10 @@ class WidgetWin : public Widget, // If necessary, this registers the window class. std::wstring GetWindowClassName(); - // Stops ignoring SetWindowPos() requests (see below). - void StopIgnoringPosChanges() { ignore_window_pos_changes_ = false; } - // The following factory is used for calls to close the WidgetWin // instance. ScopedRunnableMethodFactory<WidgetWin> close_widget_factory_; - // The following factory is used to ignore SetWindowPos() calls for short time - // periods. - ScopedRunnableMethodFactory<WidgetWin> ignore_pos_changes_factory_; - // The flags currently being used with TrackMouseEvent to track mouse // messages. 0 if there is no active tracking. The value of this member is // used when tracking is canceled. @@ -609,16 +616,6 @@ class WidgetWin : public Widget, // Our hwnd. HWND hwnd_; - - // The last-seen monitor containing us, and its work area. These are used to - // catch updates to the work area and react accordingly. - HMONITOR last_monitor_; - gfx::Rect last_work_area_; - - // When true, this flag makes us discard incoming SetWindowPos() requests that - // only change our position/size. (We still allow changes to Z-order, - // activation, etc.) - bool ignore_window_pos_changes_; }; } // namespace views diff --git a/chrome/views/window/window.h b/chrome/views/window/window.h index 48c1ad8..fe820da 100644 --- a/chrome/views/window/window.h +++ b/chrome/views/window/window.h @@ -42,6 +42,9 @@ class Window { // Retrieves the window's bounds, including its frame. virtual gfx::Rect GetBounds() const = 0; + // Retrieves the restored bounds for the window. + virtual gfx::Rect GetNormalBounds() const = 0; + // Sizes and/or places the window to the specified bounds, size or position. virtual void SetBounds(const gfx::Rect& bounds) = 0; @@ -78,6 +81,10 @@ class Window { virtual bool IsMaximized() const = 0; virtual bool IsMinimized() const = 0; + // Accessors for fullscreen state. + virtual void SetFullscreen(bool fullscreen) = 0; + virtual bool IsFullscreen() const = 0; + // Toggles the enable state for the Close button (and the Close menu item in // the system menu). virtual void EnableClose(bool enable) = 0; diff --git a/chrome/views/window/window_win.cc b/chrome/views/window/window_win.cc index e046180c..3c75b9d 100644 --- a/chrome/views/window/window_win.cc +++ b/chrome/views/window/window_win.cc @@ -25,6 +25,28 @@ #include "chrome/views/window/window_delegate.h" #include "grit/generated_resources.h" +namespace { + +bool GetMonitorAndRects(const RECT& rect, + HMONITOR* monitor, + gfx::Rect* monitor_rect, + gfx::Rect* work_area) { + DCHECK(monitor); + DCHECK(monitor_rect); + DCHECK(work_area); + *monitor = MonitorFromRect(&rect, MONITOR_DEFAULTTONULL); + if (!*monitor) + return false; + MONITORINFO monitor_info = { 0 }; + monitor_info.cbSize = sizeof(monitor_info); + GetMonitorInfo(*monitor, &monitor_info); + *monitor_rect = monitor_info.rcMonitor; + *work_area = monitor_info.rcWork; + return true; +} + +} // namespace + namespace views { // A scoping class that prevents a window from being able to redraw in response @@ -96,6 +118,19 @@ gfx::Rect WindowWin::GetBounds() const { return bounds; } +gfx::Rect WindowWin::GetNormalBounds() const { + // If we're in fullscreen mode, we've changed the normal bounds to the monitor + // rect, so return the saved bounds instead. + if (IsFullscreen()) + return gfx::Rect(saved_window_info_.window_rect); + + WINDOWPLACEMENT wp; + wp.length = sizeof(wp); + const bool ret = !!GetWindowPlacement(GetNativeView(), &wp); + DCHECK(ret); + return gfx::Rect(wp.rcNormalPosition); +} + void WindowWin::SetBounds(const gfx::Rect& bounds) { SetBounds(bounds, NULL); } @@ -138,6 +173,18 @@ void WindowWin::ExecuteSystemMenuCommand(int command) { SendMessage(GetNativeView(), WM_SYSCOMMAND, command, 0); } +void WindowWin::PushForceHidden() { + if (force_hidden_count_++ == 0) + Hide(); +} + +void WindowWin::PopForceHidden() { + if (--force_hidden_count_ <= 0) { + force_hidden_count_ = 0; + ShowWindow(SW_SHOW); + } +} + // static int Window::GetLocalizedContentsWidth(int col_resource_id) { double chars = _wtof(l10n_util::GetString(col_resource_id).c_str()); @@ -235,6 +282,66 @@ bool WindowWin::IsMinimized() const { return !!::IsIconic(GetNativeView()); } +void WindowWin::SetFullscreen(bool fullscreen) { + if (fullscreen_ == fullscreen) + return; // Nothing to do. + + // Toggle fullscreen mode. + fullscreen_ = fullscreen; + + // Reduce jankiness during the following position changes by hiding the window + // until it's in the final position. + PushForceHidden(); + + // Size/position/style window appropriately. + HWND hwnd = GetNativeView(); + if (fullscreen_) { + // Save current window information. We force the window into restored mode + // before going fullscreen because Windows doesn't seem to hide the + // taskbar if the window is in the maximized state. + saved_window_info_.maximized = IsMaximized(); + if (saved_window_info_.maximized) + ExecuteSystemMenuCommand(SC_RESTORE); + saved_window_info_.style = GetWindowLong(GWL_STYLE); + saved_window_info_.ex_style = GetWindowLong(GWL_EXSTYLE); + GetWindowRect(&saved_window_info_.window_rect); + + // Set new window style and size. + MONITORINFO monitor_info; + monitor_info.cbSize = sizeof(monitor_info); + GetMonitorInfo(MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST), + &monitor_info); + gfx::Rect monitor_rect(monitor_info.rcMonitor); + SetWindowLong(GWL_STYLE, + saved_window_info_.style & ~(WS_CAPTION | WS_THICKFRAME)); + SetWindowLong(GWL_EXSTYLE, + saved_window_info_.ex_style & ~(WS_EX_DLGMODALFRAME | + WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE)); + SetWindowPos(NULL, monitor_rect.x(), monitor_rect.y(), + monitor_rect.width(), monitor_rect.height(), + SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED); + } else { + // Reset original window style and size. The multiple window size/moves + // here are ugly, but if SetWindowPos() doesn't redraw, the taskbar won't be + // repainted. Better-looking methods welcome. + gfx::Rect new_rect(saved_window_info_.window_rect); + SetWindowLong(GWL_STYLE, saved_window_info_.style); + SetWindowLong(GWL_EXSTYLE, saved_window_info_.ex_style); + SetWindowPos(NULL, new_rect.x(), new_rect.y(), new_rect.width(), + new_rect.height(), + SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED); + if (saved_window_info_.maximized) + ExecuteSystemMenuCommand(SC_MAXIMIZE); + } + + // Undo our anti-jankiness hacks. + PopForceHidden(); +} + +bool WindowWin::IsFullscreen() const { + return fullscreen_; +} + void WindowWin::EnableClose(bool enable) { // If the native frame is rendering its own close button, ask it to disable. non_client_view_->EnableClose(enable); @@ -348,13 +455,17 @@ WindowWin::WindowWin(WindowDelegate* window_delegate) is_modal_(false), restored_enabled_(false), is_always_on_top_(false), + fullscreen_(false), window_closed_(false), disable_inactive_rendering_(false), is_active_(false), lock_updates_(false), saved_window_style_(0), saved_maximized_state_(0), - force_hidden_(false) { + ignore_window_pos_changes_(false), + ignore_pos_changes_factory_(this), + force_hidden_count_(0), + last_monitor_(NULL) { InitClass(); DCHECK(window_delegate_); window_delegate_->window_.reset(this); @@ -393,6 +504,9 @@ void WindowWin::Init(HWND parent, const gfx::Rect& bounds) { SetInitialBounds(bounds); InitAlwaysOnTopState(); + GetMonitorAndRects(bounds.ToRECT(), &last_monitor_, &last_monitor_rect_, + &last_work_area_); + if (!IsAppWindow()) { notification_registrar_.Add( this, @@ -497,9 +611,9 @@ LRESULT WindowWin::OnDwmCompositionChanged(UINT msg, WPARAM w_param, // Important step: restore the window first, since our hiding hack doesn't // work for maximized windows! We tell the frame not to allow itself to be // made visible though, which removes the brief flicker. - force_hidden_ = true; + ++force_hidden_count_; ::ShowWindow(GetNativeView(), SW_RESTORE); - force_hidden_ = false; + --force_hidden_count_; // We respond to this in response to WM_DWMCOMPOSITIONCHANGED since that is // the only thing we care about - we don't actually respond to WM_THEMECHANGED @@ -631,7 +745,7 @@ LRESULT WindowWin::OnNCCalcSize(BOOL mode, LPARAM l_param) { // treated as a "fullscreen app", which would cause the taskbars to // disappear. HMONITOR monitor = MonitorFromWindow(GetNativeView(), - MONITOR_DEFAULTTONEAREST); + MONITOR_DEFAULTTONULL); if (win_util::EdgeHasTopmostAutoHideTaskbar(ABE_LEFT, monitor)) client_rect->left += win_util::kAutoHideTaskbarThicknessPx; if (win_util::EdgeHasTopmostAutoHideTaskbar(ABE_TOP, monitor)) @@ -905,6 +1019,18 @@ LRESULT WindowWin::OnSetText(const wchar_t* text) { reinterpret_cast<LPARAM>(text)); } +void WindowWin::OnSettingChange(UINT flags, const wchar_t* section) { + if (!GetParent() && (flags == SPI_SETWORKAREA)) { + // Fire a dummy SetWindowPos() call, so we'll trip the code in + // OnWindowPosChanging() below that notices work area changes. + ::SetWindowPos(GetNativeView(), 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | + SWP_NOZORDER | SWP_NOREDRAW | SWP_NOACTIVATE | SWP_NOOWNERZORDER); + SetMsgHandled(TRUE); + } else { + WidgetWin::OnSettingChange(flags, section); + } +} + void WindowWin::OnSize(UINT size_param, const CSize& new_size) { // Don't no-op if the new_size matches current size. If our normal bounds // and maximized bounds are the same, then we need to layout (because we @@ -971,11 +1097,82 @@ void WindowWin::OnSysCommand(UINT notification_code, CPoint click) { } void WindowWin::OnWindowPosChanging(WINDOWPOS* window_pos) { - if (force_hidden_) { + if (force_hidden_count_) { // Prevent the window from being made visible if we've been asked to do so. // See comment in header as to why we might want this. window_pos->flags &= ~SWP_SHOWWINDOW; } + + if (ignore_window_pos_changes_) { + // If somebody's trying to toggle our visibility, change the nonclient area, + // change our Z-order, or activate us, we should probably let it go through. + if (!(window_pos->flags & ((IsVisible() ? SWP_HIDEWINDOW : SWP_SHOWWINDOW) | + SWP_FRAMECHANGED)) && + (window_pos->flags & (SWP_NOZORDER | SWP_NOACTIVATE))) { + // Just sizing/moving the window; ignore. + window_pos->flags |= SWP_NOSIZE | SWP_NOMOVE | SWP_NOREDRAW; + window_pos->flags &= ~(SWP_SHOWWINDOW | SWP_HIDEWINDOW); + } + } else if (!GetParent()) { + CRect window_rect; + HMONITOR monitor; + gfx::Rect monitor_rect, work_area; + if (GetWindowRect(&window_rect) && + GetMonitorAndRects(window_rect, &monitor, &monitor_rect, &work_area)) { + if (monitor && (monitor == last_monitor_) && + (IsFullscreen() || ((monitor_rect == last_monitor_rect_) && + (work_area != last_work_area_)))) { + // A rect for the monitor we're on changed. Normally Windows notifies + // us about this (and thus we're reaching here due to the SetWindowPos() + // call in OnSettingChange() above), but with some software (e.g. + // nVidia's nView desktop manager) the work area can change asynchronous + // to any notification, and we're just sent a SetWindowPos() call with a + // new (frequently incorrect) position/size. In either case, the best + // response is to throw away the existing position/size information in + // |window_pos| and recalculate it based on the old window coordinates, + // adjusted for the change in the work area (or, for fullscreen windows, + // to just set it to the monitor rect). + if (IsFullscreen()) { + window_pos->x = monitor_rect.x(); + window_pos->y = monitor_rect.y(); + window_pos->cx = monitor_rect.width(); + window_pos->cy = monitor_rect.height(); + } else if (IsZoomed()) { + window_pos->x = + window_rect.left + work_area.x() - last_work_area_.x(); + window_pos->y = window_rect.top + work_area.y() - last_work_area_.y(); + window_pos->cx = window_rect.Width() + work_area.width() - + last_work_area_.width(); + window_pos->cy = window_rect.Height() + work_area.height() - + last_work_area_.height(); + } else { + gfx::Rect window_gfx_rect(window_rect); + gfx::Rect new_window_rect = window_gfx_rect.AdjustToFit(work_area); + window_pos->x = new_window_rect.x(); + window_pos->y = new_window_rect.y(); + window_pos->cx = new_window_rect.width(); + window_pos->cy = new_window_rect.height(); + } + // WARNING! Don't set SWP_FRAMECHANGED here, it breaks moving the child + // HWNDs for some reason. + window_pos->flags &= ~(SWP_NOSIZE | SWP_NOMOVE | SWP_NOREDRAW); + window_pos->flags |= SWP_NOCOPYBITS; + + // Now ignore all immediately-following SetWindowPos() changes. Windows + // likes to (incorrectly) recalculate what our position/size should be + // and send us further updates. + ignore_window_pos_changes_ = true; + DCHECK(ignore_pos_changes_factory_.empty()); + MessageLoop::current()->PostTask(FROM_HERE, + ignore_pos_changes_factory_.NewRunnableMethod( + &WindowWin::StopIgnoringPosChanges)); + } + last_monitor_ = monitor; + last_monitor_rect_ = monitor_rect; + last_work_area_ = work_area; + } + } + WidgetWin::OnWindowPosChanging(window_pos); } @@ -1167,12 +1364,12 @@ void WindowWin::SaveWindowPosition() { void WindowWin::LockUpdates() { lock_updates_ = true; - saved_window_style_ = GetWindowLong(GetNativeView(), GWL_STYLE); - SetWindowLong(GetNativeView(), GWL_STYLE, saved_window_style_ & ~WS_VISIBLE); + saved_window_style_ = GetWindowLong(GWL_STYLE); + SetWindowLong(GWL_STYLE, saved_window_style_ & ~WS_VISIBLE); } void WindowWin::UnlockUpdates() { - SetWindowLong(GetNativeView(), GWL_STYLE, saved_window_style_); + SetWindowLong(GWL_STYLE, saved_window_style_); lock_updates_ = false; } diff --git a/chrome/views/window/window_win.h b/chrome/views/window/window_win.h index 6c33093..cd7bd50 100644 --- a/chrome/views/window/window_win.h +++ b/chrome/views/window/window_win.h @@ -48,15 +48,23 @@ class WindowWin : public WidgetWin, // Executes the specified SC_command. void ExecuteSystemMenuCommand(int command); + // Hides the window if it hasn't already been force-hidden, then increments + // |force_hidden_count_| to prevent it from being shown again until + // PopForceHidden()) is called. + void PushForceHidden(); + + // Decrements |force_hidden_count_| and, if it is now zero, shows the window. + void PopForceHidden(); + // Accessors and setters for various properties. HWND owning_window() const { return owning_hwnd_; } void set_focus_on_creation(bool focus_on_creation) { focus_on_creation_ = focus_on_creation; } - void set_force_hidden(bool force_hidden) { force_hidden_ = force_hidden; } // Window overrides: virtual gfx::Rect GetBounds() const; + virtual gfx::Rect GetNormalBounds() const; virtual void SetBounds(const gfx::Rect& bounds); virtual void SetBounds(const gfx::Rect& bounds, gfx::NativeWindow other_window); @@ -70,6 +78,8 @@ class WindowWin : public WidgetWin, virtual bool IsVisible() const; virtual bool IsMaximized() const; virtual bool IsMinimized() const; + virtual void SetFullscreen(bool fullscreen); + virtual bool IsFullscreen() const; virtual void EnableClose(bool enable); virtual void DisableInactiveRendering(); virtual void UpdateWindowTitle(); @@ -132,6 +142,7 @@ class WindowWin : public WidgetWin, virtual LRESULT OnSetCursor(HWND window, UINT hittest_code, UINT message); virtual LRESULT OnSetIcon(UINT size_type, HICON new_icon); virtual LRESULT OnSetText(const wchar_t* text); + virtual void OnSettingChange(UINT flags, const wchar_t* section); virtual void OnSize(UINT size_param, const CSize& new_size); virtual void OnSysCommand(UINT notification_code, CPoint click); virtual void OnWindowPosChanging(WINDOWPOS* window_pos); @@ -144,6 +155,15 @@ class WindowWin : public WidgetWin, } private: + // Information saved before going into fullscreen mode, used to restore the + // window afterwards. + struct SavedWindowInfo { + bool maximized; + LONG style; + LONG ex_style; + RECT window_rect; + }; + // Set the window as modal (by disabling all the other windows). void BecomeModal(); @@ -182,6 +202,9 @@ class WindowWin : public WidgetWin, void LockUpdates(); void UnlockUpdates(); + // Stops ignoring SetWindowPos() requests (see below). + void StopIgnoringPosChanges() { ignore_window_pos_changes_ = false; } + // Resets the window region for the current window bounds if necessary. // If |force| is true, the window region is reset to NULL even for native // frame windows. @@ -241,6 +264,12 @@ class WindowWin : public WidgetWin, // We need to own the text of the menu, the Windows API does not copy it. std::wstring always_on_top_menu_text_; + // True if we're in fullscreen mode. + bool fullscreen_; + + // Saved window information from before entering fullscreen mode. + SavedWindowInfo saved_window_info_; + // Set to true if the window is in the process of closing . bool window_closed_; @@ -261,11 +290,25 @@ class WindowWin : public WidgetWin, // that explains why we save this. bool saved_maximized_state_; - // True if we should prevent attempts to make the window visible when we - // handle WM_WINDOWPOSCHANGING. Some calls like ShowWindow(SW_RESTORE) make - // the window visible in addition to restoring it, when all we want to do is - // restore it. - bool force_hidden_; + // When true, this flag makes us discard incoming SetWindowPos() requests that + // only change our position/size. (We still allow changes to Z-order, + // activation, etc.) + bool ignore_window_pos_changes_; + + // The following factory is used to ignore SetWindowPos() calls for short time + // periods. + ScopedRunnableMethodFactory<WindowWin> ignore_pos_changes_factory_; + + // If this is greater than zero, we should prevent attempts to make the window + // visible when we handle WM_WINDOWPOSCHANGING. Some calls like + // ShowWindow(SW_RESTORE) make the window visible in addition to restoring it, + // when all we want to do is restore it. + int force_hidden_count_; + + // The last-seen monitor containing us, and its rect and work area. These are + // used to catch updates to the rect and work area and react accordingly. + HMONITOR last_monitor_; + gfx::Rect last_monitor_rect_, last_work_area_; // Hold onto notifications. NotificationRegistrar notification_registrar_; |