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

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

Issue 7129022: Move last of event handlers down to NativeWidgetWin/Gtk. (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/window.h » ('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>
8 #include <shellapi.h>
9
10 #include "base/i18n/rtl.h" 7 #include "base/i18n/rtl.h"
11 #include "base/win/scoped_gdi_object.h"
12 #include "base/win/win_util.h"
13 #include "base/win/windows_version.h"
14 #include "ui/base/accessibility/accessibility_types.h" 8 #include "ui/base/accessibility/accessibility_types.h"
15 #include "ui/base/keycodes/keyboard_code_conversion_win.h" 9 #include "ui/base/keycodes/keyboard_code_conversion_win.h"
16 #include "ui/base/l10n/l10n_util_win.h" 10 #include "ui/base/l10n/l10n_util_win.h"
17 #include "ui/base/theme_provider.h" 11 #include "ui/base/theme_provider.h"
18 #include "ui/base/win/hwnd_util.h" 12 #include "ui/base/win/hwnd_util.h"
19 #include "ui/gfx/canvas_skia_paint.h"
20 #include "ui/gfx/font.h" 13 #include "ui/gfx/font.h"
21 #include "ui/gfx/path.h" 14 #include "ui/gfx/path.h"
22 #include "views/accessibility/native_view_accessibility_win.h" 15 #include "views/accessibility/native_view_accessibility_win.h"
23 #include "views/window/client_view.h" 16 #include "views/window/client_view.h"
24 #include "views/window/native_window_delegate.h" 17 #include "views/window/native_window_delegate.h"
25 #include "views/window/non_client_view.h" 18 #include "views/window/non_client_view.h"
26 #include "views/window/window_delegate.h" 19 #include "views/window/window_delegate.h"
27 20
28 namespace views { 21 namespace views {
29 namespace {
30
31 // The thickness of an auto-hide taskbar in pixels.
32 static const int kAutoHideTaskbarThicknessPx = 2;
33
34 bool GetMonitorAndRects(const RECT& rect,
35 HMONITOR* monitor,
36 gfx::Rect* monitor_rect,
37 gfx::Rect* work_area) {
38 DCHECK(monitor);
39 DCHECK(monitor_rect);
40 DCHECK(work_area);
41 *monitor = MonitorFromRect(&rect, MONITOR_DEFAULTTONULL);
42 if (!*monitor)
43 return false;
44 MONITORINFO monitor_info = { 0 };
45 monitor_info.cbSize = sizeof(monitor_info);
46 GetMonitorInfo(*monitor, &monitor_info);
47 *monitor_rect = monitor_info.rcMonitor;
48 *work_area = monitor_info.rcWork;
49 return true;
50 }
51
52 // Returns true if edge |edge| (one of ABE_LEFT, TOP, RIGHT, or BOTTOM) of
53 // monitor |monitor| has an auto-hiding taskbar that's always-on-top.
54 bool EdgeHasTopmostAutoHideTaskbar(UINT edge, HMONITOR monitor) {
55 APPBARDATA taskbar_data = { 0 };
56 taskbar_data.cbSize = sizeof APPBARDATA;
57 taskbar_data.uEdge = edge;
58 HWND taskbar = reinterpret_cast<HWND>(SHAppBarMessage(ABM_GETAUTOHIDEBAR,
59 &taskbar_data));
60 return ::IsWindow(taskbar) && (monitor != NULL) &&
61 (MonitorFromWindow(taskbar, MONITOR_DEFAULTTONULL) == monitor) &&
62 (GetWindowLong(taskbar, GWL_EXSTYLE) & WS_EX_TOPMOST);
63 }
64
65 HWND GetOwner(HWND window) {
66 return ::GetWindow(window, GW_OWNER);
67 }
68
69 } // namespace
70
71 namespace internal { 22 namespace internal {
72 23
73 void EnsureRectIsVisibleInRect(const gfx::Rect& parent_rect, 24 void EnsureRectIsVisibleInRect(const gfx::Rect& parent_rect,
74 gfx::Rect* child_rect, 25 gfx::Rect* child_rect,
75 int padding) { 26 int padding) {
76 DCHECK(child_rect); 27 DCHECK(child_rect);
77 28
78 // We use padding here because it allows some of the original web page to 29 // We use padding here because it allows some of the original web page to
79 // bleed through around the edges. 30 // bleed through around the edges.
80 int twice_padding = padding * 2; 31 int twice_padding = padding * 2;
(...skipping 26 matching lines...) Expand all
107 child_rect->set_x(parent_rect.right() - child_rect->width() - padding); 58 child_rect->set_x(parent_rect.right() - child_rect->width() - padding);
108 } 59 }
109 60
110 } // namespace internal 61 } // namespace internal
111 62
112 //////////////////////////////////////////////////////////////////////////////// 63 ////////////////////////////////////////////////////////////////////////////////
113 // NativeWindowWin, public: 64 // NativeWindowWin, public:
114 65
115 NativeWindowWin::NativeWindowWin(internal::NativeWindowDelegate* delegate) 66 NativeWindowWin::NativeWindowWin(internal::NativeWindowDelegate* delegate)
116 : NativeWidgetWin(delegate->AsNativeWidgetDelegate()), 67 : NativeWidgetWin(delegate->AsNativeWidgetDelegate()),
117 delegate_(delegate), 68 delegate_(delegate) {
118 restored_enabled_(false),
119 ignore_window_pos_changes_(false),
120 ignore_pos_changes_factory_(this),
121 is_right_mouse_pressed_on_caption_(false),
122 last_monitor_(NULL) {
123 is_window_ = true; 69 is_window_ = true;
124 // Initialize these values to 0 so that subclasses can override the default 70 // Initialize these values to 0 so that subclasses can override the default
125 // behavior before calling Init. 71 // behavior before calling Init.
126 set_window_style(0); 72 set_window_style(0);
127 set_window_ex_style(0); 73 set_window_ex_style(0);
128 } 74 }
129 75
130 NativeWindowWin::~NativeWindowWin() { 76 NativeWindowWin::~NativeWindowWin() {
131 } 77 }
132 78
133 // static
134 gfx::Font NativeWindowWin::GetWindowTitleFont() {
135 NONCLIENTMETRICS ncm;
136 base::win::GetNonClientMetrics(&ncm);
137 l10n_util::AdjustUIFont(&(ncm.lfCaptionFont));
138 base::win::ScopedHFONT caption_font(CreateFontIndirect(&(ncm.lfCaptionFont)));
139 return gfx::Font(caption_font);
140 }
141
142 ///////////////////////////////////////////////////////////////////////////////
143 // NativeWindowWin, NativeWidgetWin overrides:
144
145 void NativeWindowWin::InitNativeWidget(const Widget::InitParams& params) {
146 if (window_style() == 0)
147 set_window_style(CalculateWindowStyle());
148 if (window_ex_style() == 0)
149 set_window_ex_style(CalculateWindowExStyle());
150
151 GetMonitorAndRects(params.bounds.ToRECT(), &last_monitor_,
152 &last_monitor_rect_, &last_work_area_);
153
154 NativeWidgetWin::InitNativeWidget(params);
155 }
156
157 void NativeWindowWin::OnDestroy() {
158 RestoreEnabledIfNecessary();
159 NativeWidgetWin::OnDestroy();
160 }
161
162 LRESULT NativeWindowWin::OnMouseRange(UINT message,
163 WPARAM w_param,
164 LPARAM l_param) {
165 if (message == WM_RBUTTONUP && is_right_mouse_pressed_on_caption_) {
166 is_right_mouse_pressed_on_caption_ = false;
167 ReleaseCapture();
168 // |point| is in window coordinates, but WM_NCHITTEST and TrackPopupMenu()
169 // expect screen coordinates.
170 CPoint screen_point(l_param);
171 MapWindowPoints(GetNativeView(), HWND_DESKTOP, &screen_point, 1);
172 w_param = SendMessage(GetNativeView(), WM_NCHITTEST, 0,
173 MAKELPARAM(screen_point.x, screen_point.y));
174 if (w_param == HTCAPTION || w_param == HTSYSMENU) {
175 UINT flags = TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_RETURNCMD;
176 if (base::i18n::IsRTL())
177 flags |= TPM_RIGHTALIGN;
178 HMENU system_menu = GetSystemMenu(GetNativeView(), FALSE);
179 int id = TrackPopupMenu(system_menu, flags, screen_point.x,
180 screen_point.y, 0, GetNativeView(), NULL);
181 ExecuteSystemMenuCommand(id);
182 return 0;
183 }
184 } else if (message == WM_NCLBUTTONDOWN &&
185 !GetWindow()->ShouldUseNativeFrame()) {
186 switch (w_param) {
187 case HTCLOSE:
188 case HTMINBUTTON:
189 case HTMAXBUTTON: {
190 // When the mouse is pressed down in these specific non-client areas,
191 // we need to tell the RootView to send the mouse pressed event (which
192 // sets capture, allowing subsequent WM_LBUTTONUP (note, _not_
193 // WM_NCLBUTTONUP) to fire so that the appropriate WM_SYSCOMMAND can be
194 // sent by the applicable button's ButtonListener. We _have_ to do this
195 // way rather than letting Windows just send the syscommand itself (as
196 // would happen if we never did this dance) because for some insane
197 // reason DefWindowProc for WM_NCLBUTTONDOWN also renders the pressed
198 // window control button appearance, in the Windows classic style, over
199 // our view! Ick! By handling this message we prevent Windows from
200 // doing this undesirable thing, but that means we need to roll the
201 // sys-command handling ourselves.
202 // Combine |w_param| with common key state message flags.
203 w_param |= ((GetKeyState(VK_CONTROL) & 0x80) == 0x80)? MK_CONTROL : 0;
204 w_param |= ((GetKeyState(VK_SHIFT) & 0x80) == 0x80)? MK_SHIFT : 0;
205 }
206 }
207 } else if (message == WM_NCRBUTTONDOWN &&
208 (w_param == HTCAPTION || w_param == HTSYSMENU)) {
209 is_right_mouse_pressed_on_caption_ = true;
210 // We SetMouseCapture() to ensure we only show the menu when the button
211 // down and up are both on the caption. Note: this causes the button up to
212 // be WM_RBUTTONUP instead of WM_NCRBUTTONUP.
213 SetMouseCapture();
214 }
215
216 /*
217 TODO(beng): This fixes some situations where the windows-classic appearance
218 non-client area is rendered over our custom frame, however it
219 causes mouse-releases to the non-client area to be eaten, so it
220 can't be enabled.
221 if (message == WM_NCLBUTTONDOWN) {
222 // NativeWindowWin::OnNCLButtonDown set the message as un-handled. This
223 // normally means NativeWidgetWin::ProcessWindowMessage will pass it to
224 // DefWindowProc. Sadly, DefWindowProc for WM_NCLBUTTONDOWN does weird
225 // non-client painting, so we need to call it directly here inside a
226 // scoped update lock.
227 ScopedRedrawLock lock(this);
228 NativeWidgetWin::OnMouseRange(message, w_param, l_param);
229 DefWindowProc(GetNativeView(), WM_NCLBUTTONDOWN, w_param, l_param);
230 SetMsgHandled(TRUE);
231 }
232 */
233
234 NativeWidgetWin::OnMouseRange(message, w_param, l_param);
235 return 0;
236 }
237
238 LRESULT NativeWindowWin::OnNCCalcSize(BOOL mode, LPARAM l_param) {
239 // We only override the default handling if we need to specify a custom
240 // non-client edge width. Note that in most cases "no insets" means no
241 // custom width, but in fullscreen mode we want a custom width of 0.
242 gfx::Insets insets = GetClientAreaInsets();
243 if (insets.empty() && !IsFullscreen())
244 return NativeWidgetWin::OnNCCalcSize(mode, l_param);
245
246 RECT* client_rect = mode ?
247 &reinterpret_cast<NCCALCSIZE_PARAMS*>(l_param)->rgrc[0] :
248 reinterpret_cast<RECT*>(l_param);
249 client_rect->left += insets.left();
250 client_rect->top += insets.top();
251 client_rect->bottom -= insets.bottom();
252 client_rect->right -= insets.right();
253 if (IsMaximized()) {
254 // Find all auto-hide taskbars along the screen edges and adjust in by the
255 // thickness of the auto-hide taskbar on each such edge, so the window isn't
256 // treated as a "fullscreen app", which would cause the taskbars to
257 // disappear.
258 HMONITOR monitor = MonitorFromWindow(GetNativeView(),
259 MONITOR_DEFAULTTONULL);
260 if (!monitor) {
261 // We might end up here if the window was previously minimized and the
262 // user clicks on the taskbar button to restore it in the previously
263 // maximized position. In that case WM_NCCALCSIZE is sent before the
264 // window coordinates are restored to their previous values, so our
265 // (left,top) would probably be (-32000,-32000) like all minimized
266 // windows. So the above MonitorFromWindow call fails, but if we check
267 // the window rect given with WM_NCCALCSIZE (which is our previous
268 // restored window position) we will get the correct monitor handle.
269 monitor = MonitorFromRect(client_rect, MONITOR_DEFAULTTONULL);
270 if (!monitor) {
271 // This is probably an extreme case that we won't hit, but if we don't
272 // intersect any monitor, let us not adjust the client rect since our
273 // window will not be visible anyway.
274 return 0;
275 }
276 }
277 if (EdgeHasTopmostAutoHideTaskbar(ABE_LEFT, monitor))
278 client_rect->left += kAutoHideTaskbarThicknessPx;
279 if (EdgeHasTopmostAutoHideTaskbar(ABE_TOP, monitor)) {
280 if (GetWindow()->ShouldUseNativeFrame()) {
281 // Tricky bit. Due to a bug in DwmDefWindowProc()'s handling of
282 // WM_NCHITTEST, having any nonclient area atop the window causes the
283 // caption buttons to draw onscreen but not respond to mouse
284 // hover/clicks.
285 // So for a taskbar at the screen top, we can't push the
286 // client_rect->top down; instead, we move the bottom up by one pixel,
287 // which is the smallest change we can make and still get a client area
288 // less than the screen size. This is visibly ugly, but there seems to
289 // be no better solution.
290 --client_rect->bottom;
291 } else {
292 client_rect->top += kAutoHideTaskbarThicknessPx;
293 }
294 }
295 if (EdgeHasTopmostAutoHideTaskbar(ABE_RIGHT, monitor))
296 client_rect->right -= kAutoHideTaskbarThicknessPx;
297 if (EdgeHasTopmostAutoHideTaskbar(ABE_BOTTOM, monitor))
298 client_rect->bottom -= kAutoHideTaskbarThicknessPx;
299
300 // We cannot return WVR_REDRAW when there is nonclient area, or Windows
301 // exhibits bugs where client pixels and child HWNDs are mispositioned by
302 // the width/height of the upper-left nonclient area.
303 return 0;
304 }
305
306 // If the window bounds change, we're going to relayout and repaint anyway.
307 // Returning WVR_REDRAW avoids an extra paint before that of the old client
308 // pixels in the (now wrong) location, and thus makes actions like resizing a
309 // window from the left edge look slightly less broken.
310 // We special case when left or top insets are 0, since these conditions
311 // actually require another repaint to correct the layout after glass gets
312 // turned on and off.
313 if (insets.left() == 0 || insets.top() == 0)
314 return 0;
315 return mode ? WVR_REDRAW : 0;
316 }
317
318 namespace {
319 struct ClipState {
320 // The window being painted.
321 HWND parent;
322
323 // DC painting to.
324 HDC dc;
325
326 // Origin of the window in terms of the screen.
327 int x;
328 int y;
329 };
330
331 // See comments in OnNCPaint for details of this function.
332 static BOOL CALLBACK ClipDCToChild(HWND window, LPARAM param) {
333 ClipState* clip_state = reinterpret_cast<ClipState*>(param);
334 if (GetParent(window) == clip_state->parent && IsWindowVisible(window)) {
335 RECT bounds;
336 GetWindowRect(window, &bounds);
337 ExcludeClipRect(clip_state->dc,
338 bounds.left - clip_state->x,
339 bounds.top - clip_state->y,
340 bounds.right - clip_state->x,
341 bounds.bottom - clip_state->y);
342 }
343 return TRUE;
344 }
345 } // namespace
346
347 void NativeWindowWin::OnNCPaint(HRGN rgn) {
348 // We only do non-client painting if we're not using the native frame.
349 // It's required to avoid some native painting artifacts from appearing when
350 // the window is resized.
351 if (GetWindow()->ShouldUseNativeFrame()) {
352 NativeWidgetWin::OnNCPaint(rgn);
353 return;
354 }
355
356 // We have an NC region and need to paint it. We expand the NC region to
357 // include the dirty region of the root view. This is done to minimize
358 // paints.
359 CRect window_rect;
360 GetWindowRect(&window_rect);
361
362 if (window_rect.Width() != GetWidget()->GetRootView()->width() ||
363 window_rect.Height() != GetWidget()->GetRootView()->height()) {
364 // If the size of the window differs from the size of the root view it
365 // means we're being asked to paint before we've gotten a WM_SIZE. This can
366 // happen when the user is interactively resizing the window. To avoid
367 // mass flickering we don't do anything here. Once we get the WM_SIZE we'll
368 // reset the region of the window which triggers another WM_NCPAINT and
369 // all is well.
370 return;
371 }
372
373 CRect dirty_region;
374 // A value of 1 indicates paint all.
375 if (!rgn || rgn == reinterpret_cast<HRGN>(1)) {
376 dirty_region = CRect(0, 0, window_rect.Width(), window_rect.Height());
377 } else {
378 RECT rgn_bounding_box;
379 GetRgnBox(rgn, &rgn_bounding_box);
380 if (!IntersectRect(&dirty_region, &rgn_bounding_box, &window_rect))
381 return; // Dirty region doesn't intersect window bounds, bale.
382
383 // rgn_bounding_box is in screen coordinates. Map it to window coordinates.
384 OffsetRect(&dirty_region, -window_rect.left, -window_rect.top);
385 }
386
387 // In theory GetDCEx should do what we want, but I couldn't get it to work.
388 // In particular the docs mentiond DCX_CLIPCHILDREN, but as far as I can tell
389 // it doesn't work at all. So, instead we get the DC for the window then
390 // manually clip out the children.
391 HDC dc = GetWindowDC(GetNativeView());
392 ClipState clip_state;
393 clip_state.x = window_rect.left;
394 clip_state.y = window_rect.top;
395 clip_state.parent = GetNativeView();
396 clip_state.dc = dc;
397 EnumChildWindows(GetNativeView(), &ClipDCToChild,
398 reinterpret_cast<LPARAM>(&clip_state));
399
400 gfx::Rect old_paint_region = invalid_rect();
401
402 if (!old_paint_region.IsEmpty()) {
403 // The root view has a region that needs to be painted. Include it in the
404 // region we're going to paint.
405
406 CRect old_paint_region_crect = old_paint_region.ToRECT();
407 CRect tmp = dirty_region;
408 UnionRect(&dirty_region, &tmp, &old_paint_region_crect);
409 }
410
411 GetWidget()->GetRootView()->SchedulePaintInRect(gfx::Rect(dirty_region));
412
413 // gfx::CanvasSkiaPaint's destructor does the actual painting. As such, wrap
414 // the following in a block to force paint to occur so that we can release
415 // the dc.
416 {
417 gfx::CanvasSkiaPaint canvas(dc, true, dirty_region.left,
418 dirty_region.top, dirty_region.Width(),
419 dirty_region.Height());
420 delegate_->AsNativeWidgetDelegate()->OnNativeWidgetPaint(&canvas);
421 }
422
423 ReleaseDC(GetNativeView(), dc);
424 // When using a custom frame, we want to avoid calling DefWindowProc() since
425 // that may render artifacts.
426 SetMsgHandled(!GetWindow()->ShouldUseNativeFrame());
427 }
428
429 void NativeWindowWin::OnWindowPosChanging(WINDOWPOS* window_pos) {
430 if (ignore_window_pos_changes_) {
431 // If somebody's trying to toggle our visibility, change the nonclient area,
432 // change our Z-order, or activate us, we should probably let it go through.
433 if (!(window_pos->flags & ((IsVisible() ? SWP_HIDEWINDOW : SWP_SHOWWINDOW) |
434 SWP_FRAMECHANGED)) &&
435 (window_pos->flags & (SWP_NOZORDER | SWP_NOACTIVATE))) {
436 // Just sizing/moving the window; ignore.
437 window_pos->flags |= SWP_NOSIZE | SWP_NOMOVE | SWP_NOREDRAW;
438 window_pos->flags &= ~(SWP_SHOWWINDOW | SWP_HIDEWINDOW);
439 }
440 } else if (!GetParent()) {
441 CRect window_rect;
442 HMONITOR monitor;
443 gfx::Rect monitor_rect, work_area;
444 if (GetWindowRect(&window_rect) &&
445 GetMonitorAndRects(window_rect, &monitor, &monitor_rect, &work_area)) {
446 if (monitor && (monitor == last_monitor_) &&
447 (IsFullscreen() || ((monitor_rect == last_monitor_rect_) &&
448 (work_area != last_work_area_)))) {
449 // A rect for the monitor we're on changed. Normally Windows notifies
450 // us about this (and thus we're reaching here due to the SetWindowPos()
451 // call in OnSettingChange() above), but with some software (e.g.
452 // nVidia's nView desktop manager) the work area can change asynchronous
453 // to any notification, and we're just sent a SetWindowPos() call with a
454 // new (frequently incorrect) position/size. In either case, the best
455 // response is to throw away the existing position/size information in
456 // |window_pos| and recalculate it based on the new work rect.
457 gfx::Rect new_window_rect;
458 if (IsFullscreen()) {
459 new_window_rect = monitor_rect;
460 } else if (IsZoomed()) {
461 new_window_rect = work_area;
462 int border_thickness = GetSystemMetrics(SM_CXSIZEFRAME);
463 new_window_rect.Inset(-border_thickness, -border_thickness);
464 } else {
465 new_window_rect = gfx::Rect(window_rect).AdjustToFit(work_area);
466 }
467 window_pos->x = new_window_rect.x();
468 window_pos->y = new_window_rect.y();
469 window_pos->cx = new_window_rect.width();
470 window_pos->cy = new_window_rect.height();
471 // WARNING! Don't set SWP_FRAMECHANGED here, it breaks moving the child
472 // HWNDs for some reason.
473 window_pos->flags &= ~(SWP_NOSIZE | SWP_NOMOVE | SWP_NOREDRAW);
474 window_pos->flags |= SWP_NOCOPYBITS;
475
476 // Now ignore all immediately-following SetWindowPos() changes. Windows
477 // likes to (incorrectly) recalculate what our position/size should be
478 // and send us further updates.
479 ignore_window_pos_changes_ = true;
480 DCHECK(ignore_pos_changes_factory_.empty());
481 MessageLoop::current()->PostTask(FROM_HERE,
482 ignore_pos_changes_factory_.NewRunnableMethod(
483 &NativeWindowWin::StopIgnoringPosChanges));
484 }
485 last_monitor_ = monitor;
486 last_monitor_rect_ = monitor_rect;
487 last_work_area_ = work_area;
488 }
489 }
490
491 NativeWidgetWin::OnWindowPosChanging(window_pos);
492 }
493
494 //////////////////////////////////////////////////////////////////////////////// 79 ////////////////////////////////////////////////////////////////////////////////
495 // NativeWindowWin, NativeWindow implementation: 80 // NativeWindowWin, NativeWindow implementation:
496 81
497 Window* NativeWindowWin::GetWindow() { 82 Window* NativeWindowWin::GetWindow() {
498 return delegate_->AsWindow(); 83 return delegate_->AsWindow();
499 } 84 }
500 85
501 const Window* NativeWindowWin::GetWindow() const { 86 const Window* NativeWindowWin::GetWindow() const {
502 return delegate_->AsWindow(); 87 return delegate_->AsWindow();
503 } 88 }
504 89
505 NativeWidget* NativeWindowWin::AsNativeWidget() { 90 NativeWidget* NativeWindowWin::AsNativeWidget() {
506 return this; 91 return this;
507 } 92 }
508 93
509 const NativeWidget* NativeWindowWin::AsNativeWidget() const { 94 const NativeWidget* NativeWindowWin::AsNativeWidget() const {
510 return this; 95 return this;
511 } 96 }
512 97
513 void NativeWindowWin::BecomeModal() {
514 // We implement modality by crawling up the hierarchy of windows starting
515 // at the owner, disabling all of them so that they don't receive input
516 // messages.
517 HWND start = GetOwner(GetNativeView());
518 while (start) {
519 ::EnableWindow(start, FALSE);
520 start = ::GetParent(start);
521 }
522 }
523
524 ////////////////////////////////////////////////////////////////////////////////
525 // NativeWindowWin, private:
526
527 void NativeWindowWin::RestoreEnabledIfNecessary() {
528 if (delegate_->IsModal() && !restored_enabled_) {
529 restored_enabled_ = true;
530 // If we were run modally, we need to undo the disabled-ness we inflicted on
531 // the owner's parent hierarchy.
532 HWND start = GetOwner(GetNativeView());
533 while (start) {
534 ::EnableWindow(start, TRUE);
535 start = ::GetParent(start);
536 }
537 }
538 }
539
540 DWORD NativeWindowWin::CalculateWindowStyle() {
541 DWORD window_styles =
542 WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_SYSMENU | WS_CAPTION;
543 bool can_resize = GetWindow()->window_delegate()->CanResize();
544 bool can_maximize = GetWindow()->window_delegate()->CanMaximize();
545 if (can_maximize) {
546 window_styles |= WS_OVERLAPPEDWINDOW;
547 } else if (can_resize) {
548 window_styles |= WS_OVERLAPPED | WS_THICKFRAME;
549 }
550 if (delegate_->IsDialogBox()) {
551 window_styles |= DS_MODALFRAME;
552 // NOTE: Turning this off means we lose the close button, which is bad.
553 // Turning it on though means the user can maximize or size the window
554 // from the system menu, which is worse. We may need to provide our own
555 // menu to get the close button to appear properly.
556 // window_styles &= ~WS_SYSMENU;
557 }
558 return window_styles;
559 }
560
561 DWORD NativeWindowWin::CalculateWindowExStyle() {
562 return delegate_->IsDialogBox() ? WS_EX_DLGMODALFRAME : 0;
563 }
564
565 //////////////////////////////////////////////////////////////////////////////// 98 ////////////////////////////////////////////////////////////////////////////////
566 // NativeWindow, public: 99 // NativeWindow, public:
567 100
568 // static 101 // static
569 NativeWindow* NativeWindow::CreateNativeWindow( 102 NativeWindow* NativeWindow::CreateNativeWindow(
570 internal::NativeWindowDelegate* delegate) { 103 internal::NativeWindowDelegate* delegate) {
571 return new NativeWindowWin(delegate); 104 return new NativeWindowWin(delegate);
572 } 105 }
573 106
574 } // namespace views 107 } // namespace views
OLDNEW
« no previous file with comments | « views/window/native_window_win.h ('k') | views/window/window.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698