diff options
Diffstat (limited to 'chrome/views')
-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 |
5 files changed, 278 insertions, 133 deletions
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_; |