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

Side by Side Diff: views/window/native_window_win.cc

Issue 7054052: Move more from Window onto Widget. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « views/window/native_window_win.h ('k') | views/window/non_client_view.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 "views/window/native_window_win.h" 5 #include "views/window/native_window_win.h"
6 6
7 #include <dwmapi.h> 7 #include <dwmapi.h>
8 #include <shellapi.h> 8 #include <shellapi.h>
9 9
10 #include "base/i18n/rtl.h" 10 #include "base/i18n/rtl.h"
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
59 &taskbar_data)); 59 &taskbar_data));
60 return ::IsWindow(taskbar) && (monitor != NULL) && 60 return ::IsWindow(taskbar) && (monitor != NULL) &&
61 (MonitorFromWindow(taskbar, MONITOR_DEFAULTTONULL) == monitor) && 61 (MonitorFromWindow(taskbar, MONITOR_DEFAULTTONULL) == monitor) &&
62 (GetWindowLong(taskbar, GWL_EXSTYLE) & WS_EX_TOPMOST); 62 (GetWindowLong(taskbar, GWL_EXSTYLE) & WS_EX_TOPMOST);
63 } 63 }
64 64
65 HWND GetOwner(HWND window) { 65 HWND GetOwner(HWND window) {
66 return ::GetWindow(window, GW_OWNER); 66 return ::GetWindow(window, GW_OWNER);
67 } 67 }
68 68
69 // Tells the window its frame (non-client area) has changed.
70 void SendFrameChanged(HWND window) {
71 SetWindowPos(window, NULL, 0, 0, 0, 0,
72 SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOCOPYBITS |
73 SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOREPOSITION |
74 SWP_NOSENDCHANGING | SWP_NOSIZE | SWP_NOZORDER);
75 }
76
77 // Enables or disables the menu item for the specified command and menu.
78 void EnableMenuItem(HMENU menu, UINT command, bool enabled) {
79 UINT flags = MF_BYCOMMAND | (enabled ? MF_ENABLED : MF_DISABLED | MF_GRAYED);
80 EnableMenuItem(menu, command, flags);
81 }
82
83 } // namespace 69 } // namespace
84 70
85 namespace internal { 71 namespace internal {
86 72
87 void EnsureRectIsVisibleInRect(const gfx::Rect& parent_rect, 73 void EnsureRectIsVisibleInRect(const gfx::Rect& parent_rect,
88 gfx::Rect* child_rect, 74 gfx::Rect* child_rect,
89 int padding) { 75 int padding) {
90 DCHECK(child_rect); 76 DCHECK(child_rect);
91 77
92 // We use padding here because it allows some of the original web page to 78 // We use padding here because it allows some of the original web page to
(...skipping 23 matching lines...) Expand all
116 // LAST, nudge the window back up into the client area if its x,y position is 102 // LAST, nudge the window back up into the client area if its x,y position is
117 // within the parent bounds but its width/height place it off-screen. 103 // within the parent bounds but its width/height place it off-screen.
118 if (child_rect->bottom() > parent_rect.bottom()) 104 if (child_rect->bottom() > parent_rect.bottom())
119 child_rect->set_y(parent_rect.bottom() - child_rect->height() - padding); 105 child_rect->set_y(parent_rect.bottom() - child_rect->height() - padding);
120 if (child_rect->right() > parent_rect.right()) 106 if (child_rect->right() > parent_rect.right())
121 child_rect->set_x(parent_rect.right() - child_rect->width() - padding); 107 child_rect->set_x(parent_rect.right() - child_rect->width() - padding);
122 } 108 }
123 109
124 } // namespace internal 110 } // namespace internal
125 111
126 // A scoping class that prevents a window from being able to redraw in response
127 // to invalidations that may occur within it for the lifetime of the object.
128 //
129 // Why would we want such a thing? Well, it turns out Windows has some
130 // "unorthodox" behavior when it comes to painting its non-client areas.
131 // Occasionally, Windows will paint portions of the default non-client area
132 // right over the top of the custom frame. This is not simply fixed by handling
133 // WM_NCPAINT/WM_PAINT, with some investigation it turns out that this
134 // rendering is being done *inside* the default implementation of some message
135 // handlers and functions:
136 // . WM_SETTEXT
137 // . WM_SETICON
138 // . WM_NCLBUTTONDOWN
139 // . EnableMenuItem, called from our WM_INITMENU handler
140 // The solution is to handle these messages and call DefWindowProc ourselves,
141 // but prevent the window from being able to update itself for the duration of
142 // the call. We do this with this class, which automatically calls its
143 // associated Window's lock and unlock functions as it is created and destroyed.
144 // See documentation in those methods for the technique used.
145 //
146 // IMPORTANT: Do not use this scoping object for large scopes or periods of
147 // time! IT WILL PREVENT THE WINDOW FROM BEING REDRAWN! (duh).
148 //
149 // I would love to hear Raymond Chen's explanation for all this. And maybe a
150 // list of other messages that this applies to ;-)
151 class NativeWindowWin::ScopedRedrawLock {
152 public:
153 explicit ScopedRedrawLock(NativeWindowWin* window) : window_(window) {
154 window_->LockUpdates();
155 }
156
157 ~ScopedRedrawLock() {
158 window_->UnlockUpdates();
159 }
160
161 private:
162 // The window having its style changed.
163 NativeWindowWin* window_;
164 };
165
166 //////////////////////////////////////////////////////////////////////////////// 112 ////////////////////////////////////////////////////////////////////////////////
167 // NativeWindowWin, public: 113 // NativeWindowWin, public:
168 114
169 NativeWindowWin::NativeWindowWin(internal::NativeWindowDelegate* delegate) 115 NativeWindowWin::NativeWindowWin(internal::NativeWindowDelegate* delegate)
170 : NativeWidgetWin(delegate->AsNativeWidgetDelegate()), 116 : NativeWidgetWin(delegate->AsNativeWidgetDelegate()),
171 delegate_(delegate), 117 delegate_(delegate),
172 restored_enabled_(false), 118 restored_enabled_(false),
173 is_active_(false),
174 lock_updates_(false),
175 saved_window_style_(0),
176 ignore_window_pos_changes_(false), 119 ignore_window_pos_changes_(false),
177 ignore_pos_changes_factory_(this), 120 ignore_pos_changes_factory_(this),
178 is_right_mouse_pressed_on_caption_(false), 121 is_right_mouse_pressed_on_caption_(false),
179 last_monitor_(NULL) { 122 last_monitor_(NULL) {
180 is_window_ = true; 123 is_window_ = true;
181 // Initialize these values to 0 so that subclasses can override the default 124 // Initialize these values to 0 so that subclasses can override the default
182 // behavior before calling Init. 125 // behavior before calling Init.
183 set_window_style(0); 126 set_window_style(0);
184 set_window_ex_style(0); 127 set_window_ex_style(0);
185 } 128 }
186 129
187 NativeWindowWin::~NativeWindowWin() { 130 NativeWindowWin::~NativeWindowWin() {
188 } 131 }
189 132
190 void NativeWindowWin::Show(int show_state) {
191 ShowWindow(show_state);
192 // When launched from certain programs like bash and Windows Live Messenger,
193 // show_state is set to SW_HIDE, so we need to correct that condition. We
194 // don't just change show_state to SW_SHOWNORMAL because MSDN says we must
195 // always first call ShowWindow with the specified value from STARTUPINFO,
196 // otherwise all future ShowWindow calls will be ignored (!!#@@#!). Instead,
197 // we call ShowWindow again in this case.
198 if (show_state == SW_HIDE) {
199 show_state = SW_SHOWNORMAL;
200 ShowWindow(show_state);
201 }
202
203 // We need to explicitly activate the window if we've been shown with a state
204 // that should activate, because if we're opened from a desktop shortcut while
205 // an existing window is already running it doesn't seem to be enough to use
206 // one of these flags to activate the window.
207 if (show_state == SW_SHOWNORMAL || show_state == SW_SHOWMAXIMIZED)
208 Activate();
209
210 SetInitialFocus();
211 }
212
213 // static 133 // static
214 gfx::Font NativeWindowWin::GetWindowTitleFont() { 134 gfx::Font NativeWindowWin::GetWindowTitleFont() {
215 NONCLIENTMETRICS ncm; 135 NONCLIENTMETRICS ncm;
216 base::win::GetNonClientMetrics(&ncm); 136 base::win::GetNonClientMetrics(&ncm);
217 l10n_util::AdjustUIFont(&(ncm.lfCaptionFont)); 137 l10n_util::AdjustUIFont(&(ncm.lfCaptionFont));
218 base::win::ScopedHFONT caption_font(CreateFontIndirect(&(ncm.lfCaptionFont))); 138 base::win::ScopedHFONT caption_font(CreateFontIndirect(&(ncm.lfCaptionFont)));
219 return gfx::Font(caption_font); 139 return gfx::Font(caption_font);
220 } 140 }
221 141
222 /////////////////////////////////////////////////////////////////////////////// 142 ///////////////////////////////////////////////////////////////////////////////
223 // NativeWindowWin, protected:
224
225 gfx::Insets NativeWindowWin::GetClientAreaInsets() const {
226 // Returning an empty Insets object causes the default handling in
227 // NativeWidgetWin::OnNCCalcSize() to be invoked.
228 if (GetWindow()->ShouldUseNativeFrame())
229 return gfx::Insets();
230
231 if (IsMaximized()) {
232 // Windows automatically adds a standard width border to all sides when a
233 // window is maximized.
234 int border_thickness = GetSystemMetrics(SM_CXSIZEFRAME);
235 return gfx::Insets(border_thickness, border_thickness, border_thickness,
236 border_thickness);
237 }
238 // This is weird, but highly essential. If we don't offset the bottom edge
239 // of the client rect, the window client area and window area will match,
240 // and when returning to glass rendering mode from non-glass, the client
241 // area will not paint black as transparent. This is because (and I don't
242 // know why) the client area goes from matching the window rect to being
243 // something else. If the client area is not the window rect in both
244 // modes, the blackness doesn't occur. Because of this, we need to tell
245 // the RootView to lay out to fit the window rect, rather than the client
246 // rect when using the opaque frame.
247 // Note: this is only required for non-fullscreen windows. Note that
248 // fullscreen windows are in restored state, not maximized.
249 return gfx::Insets(0, 0, IsFullscreen() ? 0 : 1, 0);
250 }
251
252 int NativeWindowWin::GetShowState() const {
253 return SW_SHOWNORMAL;
254 }
255
256 ///////////////////////////////////////////////////////////////////////////////
257 // NativeWindowWin, NativeWidgetWin overrides: 143 // NativeWindowWin, NativeWidgetWin overrides:
258 144
259 void NativeWindowWin::InitNativeWidget(const Widget::InitParams& params) { 145 void NativeWindowWin::InitNativeWidget(const Widget::InitParams& params) {
260 if (window_style() == 0) 146 if (window_style() == 0)
261 set_window_style(CalculateWindowStyle()); 147 set_window_style(CalculateWindowStyle());
262 if (window_ex_style() == 0) 148 if (window_ex_style() == 0)
263 set_window_ex_style(CalculateWindowExStyle()); 149 set_window_ex_style(CalculateWindowExStyle());
264 150
265 GetMonitorAndRects(params.bounds.ToRECT(), &last_monitor_, 151 GetMonitorAndRects(params.bounds.ToRECT(), &last_monitor_,
266 &last_monitor_rect_, &last_work_area_); 152 &last_monitor_rect_, &last_work_area_);
267 153
268 NativeWidgetWin::InitNativeWidget(params); 154 NativeWidgetWin::InitNativeWidget(params);
269 } 155 }
270 156
271 void NativeWindowWin::OnActivateApp(BOOL active, DWORD thread_id) {
272 if (!active && thread_id != GetCurrentThreadId()) {
273 // Another application was activated, we should reset any state that
274 // disables inactive rendering now.
275 delegate_->EnableInactiveRendering();
276 // Update the native frame too, since it could be rendering the non-client
277 // area.
278 CallDefaultNCActivateHandler(FALSE);
279 }
280 }
281
282 void NativeWindowWin::OnDestroy() { 157 void NativeWindowWin::OnDestroy() {
283 delegate_->OnNativeWindowDestroying();
284 RestoreEnabledIfNecessary(); 158 RestoreEnabledIfNecessary();
285 NativeWidgetWin::OnDestroy(); 159 NativeWidgetWin::OnDestroy();
286 } 160 }
287 161
288 LRESULT NativeWindowWin::OnDwmCompositionChanged(UINT msg,
289 WPARAM w_param,
290 LPARAM l_param) {
291 // For some reason, we need to hide the window while we're changing the frame
292 // type only when we're changing it in response to WM_DWMCOMPOSITIONCHANGED.
293 // If we don't, the client area will be filled with black. I'm suspecting
294 // something skia-ey.
295 // Frame type toggling caused by the user (e.g. switching theme) doesn't seem
296 // to have this requirement.
297 FrameTypeChanged();
298 return 0;
299 }
300
301 void NativeWindowWin::OnEnterSizeMove() {
302 NativeWidgetWin::OnEnterSizeMove();
303 delegate_->OnNativeWindowBeginUserBoundsChange();
304 }
305
306 void NativeWindowWin::OnExitSizeMove() {
307 NativeWidgetWin::OnExitSizeMove();
308 delegate_->OnNativeWindowEndUserBoundsChange();
309 }
310
311 void NativeWindowWin::OnGetMinMaxInfo(MINMAXINFO* minmax_info) {
312 gfx::Size min_window_size(delegate_->GetMinimumSize());
313 minmax_info->ptMinTrackSize.x = min_window_size.width();
314 minmax_info->ptMinTrackSize.y = min_window_size.height();
315 NativeWidgetWin::OnGetMinMaxInfo(minmax_info);
316 }
317
318 void NativeWindowWin::OnInitMenu(HMENU menu) {
319 // We only need to manually enable the system menu if we're not using a native
320 // frame.
321 if (GetWindow()->ShouldUseNativeFrame())
322 NativeWidgetWin::OnInitMenu(menu);
323
324 bool is_fullscreen = IsFullscreen();
325 bool is_minimized = IsMinimized();
326 bool is_maximized = IsMaximized();
327 bool is_restored = !is_fullscreen && !is_minimized && !is_maximized;
328
329 ScopedRedrawLock lock(this);
330 EnableMenuItem(menu, SC_RESTORE, is_minimized || is_maximized);
331 EnableMenuItem(menu, SC_MOVE, is_restored);
332 EnableMenuItem(menu, SC_SIZE,
333 GetWindow()->window_delegate()->CanResize() && is_restored);
334 EnableMenuItem(menu, SC_MAXIMIZE,
335 GetWindow()->window_delegate()->CanMaximize() &&
336 !is_fullscreen && !is_maximized);
337 EnableMenuItem(menu, SC_MINIMIZE,
338 GetWindow()->window_delegate()->CanMaximize() &&
339 !is_minimized);
340 }
341
342 LRESULT NativeWindowWin::OnMouseActivate(UINT message,
343 WPARAM w_param,
344 LPARAM l_param) {
345 return delegate_->CanActivate() ? MA_ACTIVATE : MA_NOACTIVATEANDEAT;
346 }
347
348 LRESULT NativeWindowWin::OnMouseRange(UINT message, 162 LRESULT NativeWindowWin::OnMouseRange(UINT message,
349 WPARAM w_param, 163 WPARAM w_param,
350 LPARAM l_param) { 164 LPARAM l_param) {
351 if (message == WM_RBUTTONUP && is_right_mouse_pressed_on_caption_) { 165 if (message == WM_RBUTTONUP && is_right_mouse_pressed_on_caption_) {
352 is_right_mouse_pressed_on_caption_ = false; 166 is_right_mouse_pressed_on_caption_ = false;
353 ReleaseCapture(); 167 ReleaseCapture();
354 // |point| is in window coordinates, but WM_NCHITTEST and TrackPopupMenu() 168 // |point| is in window coordinates, but WM_NCHITTEST and TrackPopupMenu()
355 // expect screen coordinates. 169 // expect screen coordinates.
356 CPoint screen_point(l_param); 170 CPoint screen_point(l_param);
357 MapWindowPoints(GetNativeView(), HWND_DESKTOP, &screen_point, 1); 171 MapWindowPoints(GetNativeView(), HWND_DESKTOP, &screen_point, 1);
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
414 NativeWidgetWin::OnMouseRange(message, w_param, l_param); 228 NativeWidgetWin::OnMouseRange(message, w_param, l_param);
415 DefWindowProc(GetNativeView(), WM_NCLBUTTONDOWN, w_param, l_param); 229 DefWindowProc(GetNativeView(), WM_NCLBUTTONDOWN, w_param, l_param);
416 SetMsgHandled(TRUE); 230 SetMsgHandled(TRUE);
417 } 231 }
418 */ 232 */
419 233
420 NativeWidgetWin::OnMouseRange(message, w_param, l_param); 234 NativeWidgetWin::OnMouseRange(message, w_param, l_param);
421 return 0; 235 return 0;
422 } 236 }
423 237
424 namespace {
425 BOOL CALLBACK EnumChildWindowsForRedraw(HWND hwnd, LPARAM lparam) {
426 DWORD process_id;
427 GetWindowThreadProcessId(hwnd, &process_id);
428 int flags = RDW_INVALIDATE | RDW_NOCHILDREN | RDW_FRAME;
429 if (process_id == GetCurrentProcessId())
430 flags |= RDW_UPDATENOW;
431 RedrawWindow(hwnd, NULL, NULL, flags);
432 return TRUE;
433 }
434 } // namespace
435
436 LRESULT NativeWindowWin::OnNCActivate(BOOL active) {
437 if (!delegate_->CanActivate())
438 return TRUE;
439
440 is_active_ = !!active;
441 delegate_->OnNativeWindowActivationChanged(is_active_);
442
443 // The frame may need to redraw as a result of the activation change.
444 // We can get WM_NCACTIVATE before we're actually visible. If we're not
445 // visible, no need to paint.
446 if (IsVisible())
447 GetWindow()->non_client_view()->SchedulePaint();
448
449 if (!GetWindow()->ShouldUseNativeFrame()) {
450 // TODO(beng, et al): Hack to redraw this window and child windows
451 // synchronously upon activation. Not all child windows are redrawing
452 // themselves leading to issues like http://crbug.com/74604
453 // We redraw out-of-process HWNDs asynchronously to avoid hanging the
454 // whole app if a child HWND belonging to a hung plugin is encountered.
455 RedrawWindow(GetNativeView(), NULL, NULL,
456 RDW_NOCHILDREN | RDW_INVALIDATE | RDW_UPDATENOW);
457 EnumChildWindows(GetNativeView(), EnumChildWindowsForRedraw, NULL);
458 }
459
460 // If we're active again, we should be allowed to render as inactive, so
461 // tell the non-client view.
462 bool inactive_rendering_disabled = delegate_->IsInactiveRenderingDisabled();
463 if (IsActive())
464 delegate_->EnableInactiveRendering();
465
466 return CallDefaultNCActivateHandler(inactive_rendering_disabled || active);
467 }
468
469 LRESULT NativeWindowWin::OnNCCalcSize(BOOL mode, LPARAM l_param) { 238 LRESULT NativeWindowWin::OnNCCalcSize(BOOL mode, LPARAM l_param) {
470 // We only override the default handling if we need to specify a custom 239 // We only override the default handling if we need to specify a custom
471 // non-client edge width. Note that in most cases "no insets" means no 240 // non-client edge width. Note that in most cases "no insets" means no
472 // custom width, but in fullscreen mode we want a custom width of 0. 241 // custom width, but in fullscreen mode we want a custom width of 0.
473 gfx::Insets insets = GetClientAreaInsets(); 242 gfx::Insets insets = GetClientAreaInsets();
474 if (insets.empty() && !IsFullscreen()) 243 if (insets.empty() && !IsFullscreen())
475 return NativeWidgetWin::OnNCCalcSize(mode, l_param); 244 return NativeWidgetWin::OnNCCalcSize(mode, l_param);
476 245
477 RECT* client_rect = mode ? 246 RECT* client_rect = mode ?
478 &reinterpret_cast<NCCALCSIZE_PARAMS*>(l_param)->rgrc[0] : 247 &reinterpret_cast<NCCALCSIZE_PARAMS*>(l_param)->rgrc[0] :
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
539 // pixels in the (now wrong) location, and thus makes actions like resizing a 308 // pixels in the (now wrong) location, and thus makes actions like resizing a
540 // window from the left edge look slightly less broken. 309 // window from the left edge look slightly less broken.
541 // We special case when left or top insets are 0, since these conditions 310 // We special case when left or top insets are 0, since these conditions
542 // actually require another repaint to correct the layout after glass gets 311 // actually require another repaint to correct the layout after glass gets
543 // turned on and off. 312 // turned on and off.
544 if (insets.left() == 0 || insets.top() == 0) 313 if (insets.left() == 0 || insets.top() == 0)
545 return 0; 314 return 0;
546 return mode ? WVR_REDRAW : 0; 315 return mode ? WVR_REDRAW : 0;
547 } 316 }
548 317
549 LRESULT NativeWindowWin::OnNCHitTest(const CPoint& point) {
550 // If the DWM is rendering the window controls, we need to give the DWM's
551 // default window procedure first chance to handle hit testing.
552 if (GetWindow()->ShouldUseNativeFrame()) {
553 LRESULT result;
554 if (DwmDefWindowProc(GetNativeView(), WM_NCHITTEST, 0,
555 MAKELPARAM(point.x, point.y), &result)) {
556 return result;
557 }
558 }
559
560 // First, give the NonClientView a chance to test the point to see if it
561 // provides any of the non-client area.
562 POINT temp = point;
563 MapWindowPoints(HWND_DESKTOP, GetNativeView(), &temp, 1);
564 int component = delegate_->GetNonClientComponent(gfx::Point(temp));
565 if (component != HTNOWHERE)
566 return component;
567
568 // Otherwise, we let Windows do all the native frame non-client handling for
569 // us.
570 return NativeWidgetWin::OnNCHitTest(point);
571 }
572
573 namespace { 318 namespace {
574 struct ClipState { 319 struct ClipState {
575 // The window being painted. 320 // The window being painted.
576 HWND parent; 321 HWND parent;
577 322
578 // DC painting to. 323 // DC painting to.
579 HDC dc; 324 HDC dc;
580 325
581 // Origin of the window in terms of the screen. 326 // Origin of the window in terms of the screen.
582 int x; 327 int x;
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
674 dirty_region.Height()); 419 dirty_region.Height());
675 delegate_->AsNativeWidgetDelegate()->OnNativeWidgetPaint(&canvas); 420 delegate_->AsNativeWidgetDelegate()->OnNativeWidgetPaint(&canvas);
676 } 421 }
677 422
678 ReleaseDC(GetNativeView(), dc); 423 ReleaseDC(GetNativeView(), dc);
679 // When using a custom frame, we want to avoid calling DefWindowProc() since 424 // When using a custom frame, we want to avoid calling DefWindowProc() since
680 // that may render artifacts. 425 // that may render artifacts.
681 SetMsgHandled(!GetWindow()->ShouldUseNativeFrame()); 426 SetMsgHandled(!GetWindow()->ShouldUseNativeFrame());
682 } 427 }
683 428
684 LRESULT NativeWindowWin::OnNCUAHDrawCaption(UINT msg,
685 WPARAM w_param,
686 LPARAM l_param) {
687 // See comment in widget_win.h at the definition of WM_NCUAHDRAWCAPTION for
688 // an explanation about why we need to handle this message.
689 SetMsgHandled(!GetWindow()->ShouldUseNativeFrame());
690 return 0;
691 }
692
693 LRESULT NativeWindowWin::OnNCUAHDrawFrame(UINT msg,
694 WPARAM w_param,
695 LPARAM l_param) {
696 // See comment in widget_win.h at the definition of WM_NCUAHDRAWCAPTION for
697 // an explanation about why we need to handle this message.
698 SetMsgHandled(!GetWindow()->ShouldUseNativeFrame());
699 return 0;
700 }
701
702 LRESULT NativeWindowWin::OnSetCursor(UINT msg,
703 WPARAM w_param,
704 LPARAM l_param) {
705 // This shouldn't hurt even if we're using the native frame.
706 ScopedRedrawLock lock(this);
707 return DefWindowProc(GetNativeView(), msg, w_param, l_param);
708 }
709
710 LRESULT NativeWindowWin::OnSetIcon(UINT size_type, HICON new_icon) {
711 // This shouldn't hurt even if we're using the native frame.
712 ScopedRedrawLock lock(this);
713 return DefWindowProc(GetNativeView(), WM_SETICON, size_type,
714 reinterpret_cast<LPARAM>(new_icon));
715 }
716
717 LRESULT NativeWindowWin::OnSetText(const wchar_t* text) {
718 // This shouldn't hurt even if we're using the native frame.
719 ScopedRedrawLock lock(this);
720 return DefWindowProc(GetNativeView(), WM_SETTEXT, NULL,
721 reinterpret_cast<LPARAM>(text));
722 }
723
724 void NativeWindowWin::OnSize(UINT size_param, const CSize& new_size) {
725 delegate_->OnNativeWindowBoundsChanged();
726 RedrawWindow(GetNativeView(), NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN);
727 NativeWidgetWin::OnSize(size_param, new_size);
728 }
729
730 void NativeWindowWin::OnSysCommand(UINT notification_code, CPoint click) {
731 // Windows uses the 4 lower order bits of |notification_code| for type-
732 // specific information so we must exclude this when comparing.
733 static const int sc_mask = 0xFFF0;
734 // Ignore size/move/maximize in fullscreen mode.
735 if (IsFullscreen() &&
736 (((notification_code & sc_mask) == SC_SIZE) ||
737 ((notification_code & sc_mask) == SC_MOVE) ||
738 ((notification_code & sc_mask) == SC_MAXIMIZE)))
739 return;
740 if (!GetWindow()->ShouldUseNativeFrame()) {
741 if ((notification_code & sc_mask) == SC_MINIMIZE ||
742 (notification_code & sc_mask) == SC_MAXIMIZE ||
743 (notification_code & sc_mask) == SC_RESTORE) {
744 GetWindow()->non_client_view()->ResetWindowControls();
745 } else if ((notification_code & sc_mask) == SC_MOVE ||
746 (notification_code & sc_mask) == SC_SIZE) {
747 if (lock_updates_) {
748 // We were locked, before entering a resize or move modal loop. Now that
749 // we've begun to move the window, we need to unlock updates so that the
750 // sizing/moving feedback can be continuous.
751 UnlockUpdates();
752 }
753 }
754 }
755
756 // Handle SC_KEYMENU, which means that the user has pressed the ALT
757 // key and released it, so we should focus the menu bar.
758 if ((notification_code & sc_mask) == SC_KEYMENU && click.x == 0) {
759 // Retrieve the status of shift and control keys to prevent consuming
760 // shift+alt keys, which are used by Windows to change input languages.
761 Accelerator accelerator(ui::KeyboardCodeForWindowsKeyCode(VK_MENU),
762 !!(GetKeyState(VK_SHIFT) & 0x8000),
763 !!(GetKeyState(VK_CONTROL) & 0x8000),
764 false);
765 AsNativeWidget()->GetWidget()->GetFocusManager()->
766 ProcessAccelerator(accelerator);
767 return;
768 }
769
770 // If the delegate can't handle it, the system implementation will be called.
771 if (!delegate_->ExecuteCommand(notification_code)) {
772 DefWindowProc(GetNativeView(), WM_SYSCOMMAND, notification_code,
773 MAKELPARAM(click.x, click.y));
774 }
775 }
776
777 void NativeWindowWin::OnWindowPosChanging(WINDOWPOS* window_pos) { 429 void NativeWindowWin::OnWindowPosChanging(WINDOWPOS* window_pos) {
778 if (ignore_window_pos_changes_) { 430 if (ignore_window_pos_changes_) {
779 // If somebody's trying to toggle our visibility, change the nonclient area, 431 // If somebody's trying to toggle our visibility, change the nonclient area,
780 // change our Z-order, or activate us, we should probably let it go through. 432 // change our Z-order, or activate us, we should probably let it go through.
781 if (!(window_pos->flags & ((IsVisible() ? SWP_HIDEWINDOW : SWP_SHOWWINDOW) | 433 if (!(window_pos->flags & ((IsVisible() ? SWP_HIDEWINDOW : SWP_SHOWWINDOW) |
782 SWP_FRAMECHANGED)) && 434 SWP_FRAMECHANGED)) &&
783 (window_pos->flags & (SWP_NOZORDER | SWP_NOACTIVATE))) { 435 (window_pos->flags & (SWP_NOZORDER | SWP_NOACTIVATE))) {
784 // Just sizing/moving the window; ignore. 436 // Just sizing/moving the window; ignore.
785 window_pos->flags |= SWP_NOSIZE | SWP_NOMOVE | SWP_NOREDRAW; 437 window_pos->flags |= SWP_NOSIZE | SWP_NOMOVE | SWP_NOREDRAW;
786 window_pos->flags &= ~(SWP_SHOWWINDOW | SWP_HIDEWINDOW); 438 window_pos->flags &= ~(SWP_SHOWWINDOW | SWP_HIDEWINDOW);
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
851 } 503 }
852 504
853 NativeWidget* NativeWindowWin::AsNativeWidget() { 505 NativeWidget* NativeWindowWin::AsNativeWidget() {
854 return this; 506 return this;
855 } 507 }
856 508
857 const NativeWidget* NativeWindowWin::AsNativeWidget() const { 509 const NativeWidget* NativeWindowWin::AsNativeWidget() const {
858 return this; 510 return this;
859 } 511 }
860 512
861 gfx::Rect NativeWindowWin::GetRestoredBounds() const {
862 // If we're in fullscreen mode, we've changed the normal bounds to the monitor
863 // rect, so return the saved bounds instead.
864 if (IsFullscreen())
865 return gfx::Rect(saved_window_info_.window_rect);
866
867 gfx::Rect bounds;
868 GetWindowBoundsAndMaximizedState(&bounds, NULL);
869 return bounds;
870 }
871
872 void NativeWindowWin::ShowNativeWindow(ShowState state) {
873 DWORD native_show_state;
874 switch (state) {
875 case SHOW_INACTIVE:
876 native_show_state = SW_SHOWNOACTIVATE;
877 break;
878 case SHOW_MAXIMIZED:
879 native_show_state = SW_SHOWMAXIMIZED;
880 break;
881 default:
882 native_show_state = GetShowState();
883 break;
884 }
885 Show(native_show_state);
886 }
887
888 void NativeWindowWin::BecomeModal() { 513 void NativeWindowWin::BecomeModal() {
889 // We implement modality by crawling up the hierarchy of windows starting 514 // We implement modality by crawling up the hierarchy of windows starting
890 // at the owner, disabling all of them so that they don't receive input 515 // at the owner, disabling all of them so that they don't receive input
891 // messages. 516 // messages.
892 HWND start = GetOwner(GetNativeView()); 517 HWND start = GetOwner(GetNativeView());
893 while (start) { 518 while (start) {
894 ::EnableWindow(start, FALSE); 519 ::EnableWindow(start, FALSE);
895 start = ::GetParent(start); 520 start = ::GetParent(start);
896 } 521 }
897 } 522 }
898 523
899 void NativeWindowWin::EnableClose(bool enable) {
900 // Disable the native frame's close button regardless of whether or not the
901 // native frame is in use, since this also affects the system menu.
902 EnableMenuItem(GetSystemMenu(GetNativeView(), false), SC_CLOSE, enable);
903 SendFrameChanged(GetNativeView());
904 }
905
906 ////////////////////////////////////////////////////////////////////////////////
907 // NativeWindowWin, NativeWidgetWin overrides:
908
909 bool NativeWindowWin::IsActive() const {
910 // TODO(beng): evaluate whether or not this is needed. NativeWidgetWin checks
911 // active-state with the OS using GetWindowInfo().
912 return is_active_;
913 }
914
915 //////////////////////////////////////////////////////////////////////////////// 524 ////////////////////////////////////////////////////////////////////////////////
916 // NativeWindowWin, private: 525 // NativeWindowWin, private:
917 526
918 void NativeWindowWin::RestoreEnabledIfNecessary() { 527 void NativeWindowWin::RestoreEnabledIfNecessary() {
919 if (delegate_->IsModal() && !restored_enabled_) { 528 if (delegate_->IsModal() && !restored_enabled_) {
920 restored_enabled_ = true; 529 restored_enabled_ = true;
921 // If we were run modally, we need to undo the disabled-ness we inflicted on 530 // If we were run modally, we need to undo the disabled-ness we inflicted on
922 // the owner's parent hierarchy. 531 // the owner's parent hierarchy.
923 HWND start = GetOwner(GetNativeView()); 532 HWND start = GetOwner(GetNativeView());
924 while (start) { 533 while (start) {
(...skipping 21 matching lines...) Expand all
946 // menu to get the close button to appear properly. 555 // menu to get the close button to appear properly.
947 // window_styles &= ~WS_SYSMENU; 556 // window_styles &= ~WS_SYSMENU;
948 } 557 }
949 return window_styles; 558 return window_styles;
950 } 559 }
951 560
952 DWORD NativeWindowWin::CalculateWindowExStyle() { 561 DWORD NativeWindowWin::CalculateWindowExStyle() {
953 return delegate_->IsDialogBox() ? WS_EX_DLGMODALFRAME : 0; 562 return delegate_->IsDialogBox() ? WS_EX_DLGMODALFRAME : 0;
954 } 563 }
955 564
956 void NativeWindowWin::LockUpdates() {
957 lock_updates_ = true;
958 saved_window_style_ = GetWindowLong(GWL_STYLE);
959 SetWindowLong(GWL_STYLE, saved_window_style_ & ~WS_VISIBLE);
960 }
961
962 void NativeWindowWin::UnlockUpdates() {
963 SetWindowLong(GWL_STYLE, saved_window_style_);
964 lock_updates_ = false;
965 }
966
967 LRESULT NativeWindowWin::CallDefaultNCActivateHandler(BOOL active) {
968 // The DefWindowProc handling for WM_NCACTIVATE renders the classic-look
969 // window title bar directly, so we need to use a redraw lock here to prevent
970 // it from doing so.
971 ScopedRedrawLock lock(this);
972 return DefWindowProc(GetNativeView(), WM_NCACTIVATE, active, 0);
973 }
974
975 //////////////////////////////////////////////////////////////////////////////// 565 ////////////////////////////////////////////////////////////////////////////////
976 // NativeWindow, public: 566 // NativeWindow, public:
977 567
978 // static 568 // static
979 NativeWindow* NativeWindow::CreateNativeWindow( 569 NativeWindow* NativeWindow::CreateNativeWindow(
980 internal::NativeWindowDelegate* delegate) { 570 internal::NativeWindowDelegate* delegate) {
981 return new NativeWindowWin(delegate); 571 return new NativeWindowWin(delegate);
982 } 572 }
983 573
984 } // namespace views 574 } // namespace views
OLDNEW
« no previous file with comments | « views/window/native_window_win.h ('k') | views/window/non_client_view.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698