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

Side by Side Diff: views/widget/native_widget_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/widget/native_widget_win.h ('k') | views/widget/native_widget_win_unittest.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/widget/native_widget_win.h" 5 #include "views/widget/native_widget_win.h"
6 6
7 #include <dwmapi.h> 7 #include <dwmapi.h>
8 #include <shellapi.h>
8 9
9 #include "base/string_util.h" 10 #include "base/string_util.h"
10 #include "base/system_monitor/system_monitor.h" 11 #include "base/system_monitor/system_monitor.h"
12 #include "base/win/scoped_gdi_object.h"
13 #include "base/win/win_util.h"
11 #include "base/win/windows_version.h" 14 #include "base/win/windows_version.h"
12 #include "ui/base/dragdrop/drag_drop_types.h" 15 #include "ui/base/dragdrop/drag_drop_types.h"
13 #include "ui/base/dragdrop/drag_source.h" 16 #include "ui/base/dragdrop/drag_source.h"
14 #include "ui/base/dragdrop/os_exchange_data.h" 17 #include "ui/base/dragdrop/os_exchange_data.h"
15 #include "ui/base/dragdrop/os_exchange_data_provider_win.h" 18 #include "ui/base/dragdrop/os_exchange_data_provider_win.h"
16 #include "ui/base/keycodes/keyboard_code_conversion_win.h" 19 #include "ui/base/keycodes/keyboard_code_conversion_win.h"
17 #include "ui/base/l10n/l10n_util_win.h" 20 #include "ui/base/l10n/l10n_util_win.h"
18 #include "ui/base/theme_provider.h" 21 #include "ui/base/theme_provider.h"
19 #include "ui/base/view_prop.h" 22 #include "ui/base/view_prop.h"
20 #include "ui/base/win/hwnd_util.h" 23 #include "ui/base/win/hwnd_util.h"
21 #include "ui/gfx/canvas_skia.h" 24 #include "ui/gfx/canvas_skia.h"
25 #include "ui/gfx/canvas_skia_paint.h"
22 #include "ui/gfx/icon_util.h" 26 #include "ui/gfx/icon_util.h"
23 #include "ui/gfx/native_theme_win.h" 27 #include "ui/gfx/native_theme_win.h"
24 #include "ui/gfx/path.h" 28 #include "ui/gfx/path.h"
25 #include "views/accessibility/native_view_accessibility_win.h" 29 #include "views/accessibility/native_view_accessibility_win.h"
26 #include "views/controls/native_control_win.h" 30 #include "views/controls/native_control_win.h"
27 #include "views/controls/textfield/native_textfield_views.h" 31 #include "views/controls/textfield/native_textfield_views.h"
28 #include "views/focus/accelerator_handler.h" 32 #include "views/focus/accelerator_handler.h"
29 #include "views/focus/focus_util_win.h" 33 #include "views/focus/focus_util_win.h"
30 #include "views/focus/view_storage.h" 34 #include "views/focus/view_storage.h"
31 #include "views/ime/input_method_win.h" 35 #include "views/ime/input_method_win.h"
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
192 BOOL CALLBACK EnumChildWindowsForRedraw(HWND hwnd, LPARAM lparam) { 196 BOOL CALLBACK EnumChildWindowsForRedraw(HWND hwnd, LPARAM lparam) {
193 DWORD process_id; 197 DWORD process_id;
194 GetWindowThreadProcessId(hwnd, &process_id); 198 GetWindowThreadProcessId(hwnd, &process_id);
195 int flags = RDW_INVALIDATE | RDW_NOCHILDREN | RDW_FRAME; 199 int flags = RDW_INVALIDATE | RDW_NOCHILDREN | RDW_FRAME;
196 if (process_id == GetCurrentProcessId()) 200 if (process_id == GetCurrentProcessId())
197 flags |= RDW_UPDATENOW; 201 flags |= RDW_UPDATENOW;
198 RedrawWindow(hwnd, NULL, NULL, flags); 202 RedrawWindow(hwnd, NULL, NULL, flags);
199 return TRUE; 203 return TRUE;
200 } 204 }
201 205
206 // See comments in OnNCPaint() for details of this struct.
207 struct ClipState {
208 // The window being painted.
209 HWND parent;
210
211 // DC painting to.
212 HDC dc;
213
214 // Origin of the window in terms of the screen.
215 int x;
216 int y;
217 };
218
219 // See comments in OnNCPaint() for details of this function.
220 static BOOL CALLBACK ClipDCToChild(HWND window, LPARAM param) {
221 ClipState* clip_state = reinterpret_cast<ClipState*>(param);
222 if (GetParent(window) == clip_state->parent && IsWindowVisible(window)) {
223 RECT bounds;
224 GetWindowRect(window, &bounds);
225 ExcludeClipRect(clip_state->dc,
226 bounds.left - clip_state->x,
227 bounds.top - clip_state->y,
228 bounds.right - clip_state->x,
229 bounds.bottom - clip_state->y);
230 }
231 return TRUE;
232 }
233
234 // The thickness of an auto-hide taskbar in pixels.
235 static const int kAutoHideTaskbarThicknessPx = 2;
236
237 bool GetMonitorAndRects(const RECT& rect,
238 HMONITOR* monitor,
239 gfx::Rect* monitor_rect,
240 gfx::Rect* work_area) {
241 DCHECK(monitor);
242 DCHECK(monitor_rect);
243 DCHECK(work_area);
244 *monitor = MonitorFromRect(&rect, MONITOR_DEFAULTTONULL);
245 if (!*monitor)
246 return false;
247 MONITORINFO monitor_info = { 0 };
248 monitor_info.cbSize = sizeof(monitor_info);
249 GetMonitorInfo(*monitor, &monitor_info);
250 *monitor_rect = monitor_info.rcMonitor;
251 *work_area = monitor_info.rcWork;
252 return true;
253 }
254
255 // Returns true if edge |edge| (one of ABE_LEFT, TOP, RIGHT, or BOTTOM) of
256 // monitor |monitor| has an auto-hiding taskbar that's always-on-top.
257 bool EdgeHasTopmostAutoHideTaskbar(UINT edge, HMONITOR monitor) {
258 APPBARDATA taskbar_data = { 0 };
259 taskbar_data.cbSize = sizeof APPBARDATA;
260 taskbar_data.uEdge = edge;
261 HWND taskbar = reinterpret_cast<HWND>(SHAppBarMessage(ABM_GETAUTOHIDEBAR,
262 &taskbar_data));
263 return ::IsWindow(taskbar) && (monitor != NULL) &&
264 (MonitorFromWindow(taskbar, MONITOR_DEFAULTTONULL) == monitor) &&
265 (GetWindowLong(taskbar, GWL_EXSTYLE) & WS_EX_TOPMOST);
266 }
267
202 // Links the HWND to its NativeWidget. 268 // Links the HWND to its NativeWidget.
203 const char* const kNativeWidgetKey = "__VIEWS_NATIVE_WIDGET__"; 269 const char* const kNativeWidgetKey = "__VIEWS_NATIVE_WIDGET__";
204 270
205 // A custom MSAA object id used to determine if a screen reader is actively 271 // A custom MSAA object id used to determine if a screen reader is actively
206 // listening for MSAA events. 272 // listening for MSAA events.
207 const int kCustomObjectID = 1; 273 const int kCustomObjectID = 1;
208 274
209 // If the hung renderer warning doesn't fit on screen, the amount of padding to 275 // If the hung renderer warning doesn't fit on screen, the amount of padding to
210 // be left between the edge of the window and the edge of the nearest monitor, 276 // be left between the edge of the window and the edge of the nearest monitor,
211 // after the window is nudged back on screen. Pixels. 277 // after the window is nudged back on screen. Pixels.
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
273 can_update_layered_window_(true), 339 can_update_layered_window_(true),
274 focus_on_creation_(true), 340 focus_on_creation_(true),
275 restore_focus_when_enabled_(false), 341 restore_focus_when_enabled_(false),
276 accessibility_view_events_index_(-1), 342 accessibility_view_events_index_(-1),
277 accessibility_view_events_(kMaxAccessibilityViewEvents), 343 accessibility_view_events_(kMaxAccessibilityViewEvents),
278 previous_cursor_(NULL), 344 previous_cursor_(NULL),
279 is_input_method_win_(false), 345 is_input_method_win_(false),
280 fullscreen_(false), 346 fullscreen_(false),
281 force_hidden_count_(0), 347 force_hidden_count_(0),
282 lock_updates_(false), 348 lock_updates_(false),
283 saved_window_style_(0) { 349 saved_window_style_(0),
350 ignore_window_pos_changes_(false),
351 ignore_pos_changes_factory_(this),
352 last_monitor_(NULL),
353 is_right_mouse_pressed_on_caption_(false),
354 restored_enabled_(false) {
284 } 355 }
285 356
286 NativeWidgetWin::~NativeWidgetWin() { 357 NativeWidgetWin::~NativeWidgetWin() {
287 // We need to delete the input method before calling DestroyRootView(), 358 // We need to delete the input method before calling DestroyRootView(),
288 // because it'll set focus_manager_ to NULL. 359 // because it'll set focus_manager_ to NULL.
289 input_method_.reset(); 360 input_method_.reset();
290 if (ownership_ == Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET) 361 if (ownership_ == Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET)
291 delete delegate_; 362 delete delegate_;
292 } 363 }
293 364
294 // static 365 // static
295 bool NativeWidgetWin::IsAeroGlassEnabled() { 366 bool NativeWidgetWin::IsAeroGlassEnabled() {
296 if (base::win::GetVersion() < base::win::VERSION_VISTA) 367 if (base::win::GetVersion() < base::win::VERSION_VISTA)
297 return false; 368 return false;
298 // If composition is not enabled, we behave like on XP. 369 // If composition is not enabled, we behave like on XP.
299 BOOL enabled = FALSE; 370 BOOL enabled = FALSE;
300 return SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled; 371 return SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled;
301 } 372 }
302 373
374 // static
375 gfx::Font NativeWidgetWin::GetWindowTitleFont() {
376 NONCLIENTMETRICS ncm;
377 base::win::GetNonClientMetrics(&ncm);
378 l10n_util::AdjustUIFont(&(ncm.lfCaptionFont));
379 base::win::ScopedHFONT caption_font(CreateFontIndirect(&(ncm.lfCaptionFont)));
380 return gfx::Font(caption_font);
381 }
382
303 void NativeWidgetWin::Show(int show_state) { 383 void NativeWidgetWin::Show(int show_state) {
304 ShowWindow(show_state); 384 ShowWindow(show_state);
305 // When launched from certain programs like bash and Windows Live Messenger, 385 // When launched from certain programs like bash and Windows Live Messenger,
306 // show_state is set to SW_HIDE, so we need to correct that condition. We 386 // show_state is set to SW_HIDE, so we need to correct that condition. We
307 // don't just change show_state to SW_SHOWNORMAL because MSDN says we must 387 // don't just change show_state to SW_SHOWNORMAL because MSDN says we must
308 // always first call ShowWindow with the specified value from STARTUPINFO, 388 // always first call ShowWindow with the specified value from STARTUPINFO,
309 // otherwise all future ShowWindow calls will be ignored (!!#@@#!). Instead, 389 // otherwise all future ShowWindow calls will be ignored (!!#@@#!). Instead,
310 // we call ShowWindow again in this case. 390 // we call ShowWindow again in this case.
311 if (show_state == SW_HIDE) { 391 if (show_state == SW_HIDE) {
312 show_state = SW_SHOWNORMAL; 392 show_state = SW_SHOWNORMAL;
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
359 ShowWindow(SW_SHOW); 439 ShowWindow(SW_SHOW);
360 } 440 }
361 } 441 }
362 442
363 //////////////////////////////////////////////////////////////////////////////// 443 ////////////////////////////////////////////////////////////////////////////////
364 // NativeWidgetWin, NativeWidget implementation: 444 // NativeWidgetWin, NativeWidget implementation:
365 445
366 void NativeWidgetWin::InitNativeWidget(const Widget::InitParams& params) { 446 void NativeWidgetWin::InitNativeWidget(const Widget::InitParams& params) {
367 SetInitParams(params); 447 SetInitParams(params);
368 448
449 GetMonitorAndRects(params.bounds.ToRECT(), &last_monitor_,
450 &last_monitor_rect_, &last_work_area_);
451
369 // Create the window. 452 // Create the window.
370 gfx::NativeView parent = params.parent_widget ? 453 gfx::NativeView parent = params.parent_widget ?
371 params.parent_widget->GetNativeView() : params.parent; 454 params.parent_widget->GetNativeView() : params.parent;
372 WindowImpl::Init(parent, params.bounds); 455 WindowImpl::Init(parent, params.bounds);
373 } 456 }
374 457
375 NonClientFrameView* NativeWidgetWin::CreateNonClientFrameView() { 458 NonClientFrameView* NativeWidgetWin::CreateNonClientFrameView() {
376 return GetWidget()->ShouldUseNativeFrame() ? 459 return GetWidget()->ShouldUseNativeFrame() ?
377 new NativeFrameView(GetWidget()) : NULL; 460 new NativeFrameView(GetWidget()) : NULL;
378 } 461 }
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after
610 if (SUCCEEDED(hr)) { 693 if (SUCCEEDED(hr)) {
611 VARIANT var; 694 VARIANT var;
612 if (state) { 695 if (state) {
613 var.lVal = NativeViewAccessibilityWin::MSAAState(state); 696 var.lVal = NativeViewAccessibilityWin::MSAAState(state);
614 hr = pAccPropServices->SetHwndProp(GetNativeView(), OBJID_CLIENT, 697 hr = pAccPropServices->SetHwndProp(GetNativeView(), OBJID_CLIENT,
615 CHILDID_SELF, PROPID_ACC_STATE, var); 698 CHILDID_SELF, PROPID_ACC_STATE, var);
616 } 699 }
617 } 700 }
618 } 701 }
619 702
703 void NativeWidgetWin::BecomeModal() {
704 // We implement modality by crawling up the hierarchy of windows starting
705 // at the owner, disabling all of them so that they don't receive input
706 // messages.
707 HWND start = ::GetWindow(GetNativeView(), GW_OWNER);
708 while (start) {
709 ::EnableWindow(start, FALSE);
710 start = ::GetParent(start);
711 }
712 }
713
620 gfx::Rect NativeWidgetWin::GetWindowScreenBounds() const { 714 gfx::Rect NativeWidgetWin::GetWindowScreenBounds() const {
621 RECT r; 715 RECT r;
622 GetWindowRect(&r); 716 GetWindowRect(&r);
623 return gfx::Rect(r); 717 return gfx::Rect(r);
624 } 718 }
625 719
626 gfx::Rect NativeWidgetWin::GetClientAreaScreenBounds() const { 720 gfx::Rect NativeWidgetWin::GetClientAreaScreenBounds() const {
627 RECT r; 721 RECT r;
628 GetClientRect(&r); 722 GetClientRect(&r);
629 POINT point = { r.left, r.top }; 723 POINT point = { r.left, r.top };
(...skipping 460 matching lines...) Expand 10 before | Expand all | Expand 10 after
1090 if (delegate_->HasFocusManager() && 1184 if (delegate_->HasFocusManager() &&
1091 NativeTextfieldViews::IsTextfieldViewsEnabled()) { 1185 NativeTextfieldViews::IsTextfieldViewsEnabled()) {
1092 input_method_.reset(new InputMethodWin(this)); 1186 input_method_.reset(new InputMethodWin(this));
1093 input_method_->Init(GetWidget()); 1187 input_method_->Init(GetWidget());
1094 is_input_method_win_ = true; 1188 is_input_method_win_ = true;
1095 } 1189 }
1096 return 0; 1190 return 0;
1097 } 1191 }
1098 1192
1099 void NativeWidgetWin::OnDestroy() { 1193 void NativeWidgetWin::OnDestroy() {
1194 RestoreEnabledIfNecessary();
1100 delegate_->OnNativeWidgetDestroying(); 1195 delegate_->OnNativeWidgetDestroying();
1101 if (drop_target_.get()) { 1196 if (drop_target_.get()) {
1102 RevokeDragDrop(hwnd()); 1197 RevokeDragDrop(hwnd());
1103 drop_target_ = NULL; 1198 drop_target_ = NULL;
1104 } 1199 }
1105 1200
1106 props_.reset(); 1201 props_.reset();
1107 } 1202 }
1108 1203
1109 void NativeWidgetWin::OnDisplayChange(UINT bits_per_pixel, CSize screen_size) { 1204 void NativeWidgetWin::OnDisplayChange(UINT bits_per_pixel, CSize screen_size) {
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
1302 return delegate_->CanActivate() ? MA_ACTIVATE : MA_NOACTIVATEANDEAT; 1397 return delegate_->CanActivate() ? MA_ACTIVATE : MA_NOACTIVATEANDEAT;
1303 if (GetWindowLong(GWL_EXSTYLE) & WS_EX_NOACTIVATE) 1398 if (GetWindowLong(GWL_EXSTYLE) & WS_EX_NOACTIVATE)
1304 return MA_NOACTIVATE; 1399 return MA_NOACTIVATE;
1305 SetMsgHandled(FALSE); 1400 SetMsgHandled(FALSE);
1306 return MA_ACTIVATE; 1401 return MA_ACTIVATE;
1307 } 1402 }
1308 1403
1309 LRESULT NativeWidgetWin::OnMouseRange(UINT message, 1404 LRESULT NativeWidgetWin::OnMouseRange(UINT message,
1310 WPARAM w_param, 1405 WPARAM w_param,
1311 LPARAM l_param) { 1406 LPARAM l_param) {
1407 if (message == WM_RBUTTONUP && is_right_mouse_pressed_on_caption_) {
1408 is_right_mouse_pressed_on_caption_ = false;
1409 ReleaseCapture();
1410 // |point| is in window coordinates, but WM_NCHITTEST and TrackPopupMenu()
1411 // expect screen coordinates.
1412 CPoint screen_point(l_param);
1413 MapWindowPoints(GetNativeView(), HWND_DESKTOP, &screen_point, 1);
1414 w_param = SendMessage(GetNativeView(), WM_NCHITTEST, 0,
1415 MAKELPARAM(screen_point.x, screen_point.y));
1416 if (w_param == HTCAPTION || w_param == HTSYSMENU) {
1417 UINT flags = TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_RETURNCMD;
1418 if (base::i18n::IsRTL())
1419 flags |= TPM_RIGHTALIGN;
1420 HMENU system_menu = GetSystemMenu(GetNativeView(), FALSE);
1421 int id = TrackPopupMenu(system_menu, flags, screen_point.x,
1422 screen_point.y, 0, GetNativeView(), NULL);
1423 ExecuteSystemMenuCommand(id);
1424 return 0;
1425 }
1426 } else if (message == WM_NCLBUTTONDOWN &&
1427 !GetWidget()->ShouldUseNativeFrame()) {
1428 switch (w_param) {
1429 case HTCLOSE:
1430 case HTMINBUTTON:
1431 case HTMAXBUTTON: {
1432 // When the mouse is pressed down in these specific non-client areas,
1433 // we need to tell the RootView to send the mouse pressed event (which
1434 // sets capture, allowing subsequent WM_LBUTTONUP (note, _not_
1435 // WM_NCLBUTTONUP) to fire so that the appropriate WM_SYSCOMMAND can be
1436 // sent by the applicable button's ButtonListener. We _have_ to do this
1437 // way rather than letting Windows just send the syscommand itself (as
1438 // would happen if we never did this dance) because for some insane
1439 // reason DefWindowProc for WM_NCLBUTTONDOWN also renders the pressed
1440 // window control button appearance, in the Windows classic style, over
1441 // our view! Ick! By handling this message we prevent Windows from
1442 // doing this undesirable thing, but that means we need to roll the
1443 // sys-command handling ourselves.
1444 // Combine |w_param| with common key state message flags.
1445 w_param |= ((GetKeyState(VK_CONTROL) & 0x80) == 0x80)? MK_CONTROL : 0;
1446 w_param |= ((GetKeyState(VK_SHIFT) & 0x80) == 0x80)? MK_SHIFT : 0;
1447 }
1448 }
1449 } else if (message == WM_NCRBUTTONDOWN &&
1450 (w_param == HTCAPTION || w_param == HTSYSMENU)) {
1451 is_right_mouse_pressed_on_caption_ = true;
1452 // We SetMouseCapture() to ensure we only show the menu when the button
1453 // down and up are both on the caption. Note: this causes the button up to
1454 // be WM_RBUTTONUP instead of WM_NCRBUTTONUP.
1455 SetMouseCapture();
1456 }
1457
1458 /*
1459 TODO(beng): This fixes some situations where the windows-classic appearance
1460 non-client area is rendered over our custom frame, however it
1461 causes mouse-releases to the non-client area to be eaten, so it
1462 can't be enabled.
1463 if (message == WM_NCLBUTTONDOWN) {
1464 // NativeWidgetWin::OnNCLButtonDown set the message as un-handled. This
1465 // normally means NativeWidgetWin::ProcessWindowMessage will pass it to
1466 // DefWindowProc. Sadly, DefWindowProc for WM_NCLBUTTONDOWN does weird
1467 // non-client painting, so we need to call it directly here inside a
1468 // scoped update lock.
1469 ScopedRedrawLock lock(this);
1470 NativeWidgetWin::OnMouseRange(message, w_param, l_param);
1471 DefWindowProc(GetNativeView(), WM_NCLBUTTONDOWN, w_param, l_param);
1472 SetMsgHandled(TRUE);
1473 }
1474 */
1475
1312 MSG msg = { hwnd(), message, w_param, l_param, 0, 1476 MSG msg = { hwnd(), message, w_param, l_param, 0,
1313 { GET_X_LPARAM(l_param), GET_Y_LPARAM(l_param) } }; 1477 { GET_X_LPARAM(l_param), GET_Y_LPARAM(l_param) } };
1314 MouseEvent event(msg); 1478 MouseEvent event(msg);
1315 1479
1316 if (!(event.flags() & ui::EF_IS_NON_CLIENT)) 1480 if (!(event.flags() & ui::EF_IS_NON_CLIENT))
1317 tooltip_manager_->OnMouse(message, w_param, l_param); 1481 tooltip_manager_->OnMouse(message, w_param, l_param);
1318 1482
1319 if (event.type() == ui::ET_MOUSE_MOVED && !HasMouseCapture()) { 1483 if (event.type() == ui::ET_MOUSE_MOVED && !HasMouseCapture()) {
1320 // Windows only fires WM_MOUSELEAVE events if the application begins 1484 // Windows only fires WM_MOUSELEAVE events if the application begins
1321 // "tracking" mouse events for a given HWND during WM_MOUSEMOVE events. 1485 // "tracking" mouse events for a given HWND during WM_MOUSEMOVE events.
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
1378 1542
1379 // If we're active again, we should be allowed to render as inactive, so 1543 // If we're active again, we should be allowed to render as inactive, so
1380 // tell the non-client view. 1544 // tell the non-client view.
1381 bool inactive_rendering_disabled = delegate_->IsInactiveRenderingDisabled(); 1545 bool inactive_rendering_disabled = delegate_->IsInactiveRenderingDisabled();
1382 if (IsActive()) 1546 if (IsActive())
1383 delegate_->EnableInactiveRendering(); 1547 delegate_->EnableInactiveRendering();
1384 1548
1385 return CallDefaultNCActivateHandler(inactive_rendering_disabled || active); 1549 return CallDefaultNCActivateHandler(inactive_rendering_disabled || active);
1386 } 1550 }
1387 1551
1388 LRESULT NativeWidgetWin::OnNCCalcSize(BOOL w_param, LPARAM l_param) { 1552 LRESULT NativeWidgetWin::OnNCCalcSize(BOOL mode, LPARAM l_param) {
1389 SetMsgHandled(FALSE); 1553 // We only override the default handling if we need to specify a custom
1390 return 0; 1554 // non-client edge width. Note that in most cases "no insets" means no
1555 // custom width, but in fullscreen mode we want a custom width of 0.
1556 gfx::Insets insets = GetClientAreaInsets();
1557 if (insets.empty() && !IsFullscreen()) {
1558 SetMsgHandled(FALSE);
1559 return 0;
1560 }
1561
1562 RECT* client_rect = mode ?
1563 &reinterpret_cast<NCCALCSIZE_PARAMS*>(l_param)->rgrc[0] :
1564 reinterpret_cast<RECT*>(l_param);
1565 client_rect->left += insets.left();
1566 client_rect->top += insets.top();
1567 client_rect->bottom -= insets.bottom();
1568 client_rect->right -= insets.right();
1569 if (IsMaximized()) {
1570 // Find all auto-hide taskbars along the screen edges and adjust in by the
1571 // thickness of the auto-hide taskbar on each such edge, so the window isn't
1572 // treated as a "fullscreen app", which would cause the taskbars to
1573 // disappear.
1574 HMONITOR monitor = MonitorFromWindow(GetNativeView(),
1575 MONITOR_DEFAULTTONULL);
1576 if (!monitor) {
1577 // We might end up here if the window was previously minimized and the
1578 // user clicks on the taskbar button to restore it in the previously
1579 // maximized position. In that case WM_NCCALCSIZE is sent before the
1580 // window coordinates are restored to their previous values, so our
1581 // (left,top) would probably be (-32000,-32000) like all minimized
1582 // windows. So the above MonitorFromWindow call fails, but if we check
1583 // the window rect given with WM_NCCALCSIZE (which is our previous
1584 // restored window position) we will get the correct monitor handle.
1585 monitor = MonitorFromRect(client_rect, MONITOR_DEFAULTTONULL);
1586 if (!monitor) {
1587 // This is probably an extreme case that we won't hit, but if we don't
1588 // intersect any monitor, let us not adjust the client rect since our
1589 // window will not be visible anyway.
1590 return 0;
1591 }
1592 }
1593 if (EdgeHasTopmostAutoHideTaskbar(ABE_LEFT, monitor))
1594 client_rect->left += kAutoHideTaskbarThicknessPx;
1595 if (EdgeHasTopmostAutoHideTaskbar(ABE_TOP, monitor)) {
1596 if (GetWidget()->ShouldUseNativeFrame()) {
1597 // Tricky bit. Due to a bug in DwmDefWindowProc()'s handling of
1598 // WM_NCHITTEST, having any nonclient area atop the window causes the
1599 // caption buttons to draw onscreen but not respond to mouse
1600 // hover/clicks.
1601 // So for a taskbar at the screen top, we can't push the
1602 // client_rect->top down; instead, we move the bottom up by one pixel,
1603 // which is the smallest change we can make and still get a client area
1604 // less than the screen size. This is visibly ugly, but there seems to
1605 // be no better solution.
1606 --client_rect->bottom;
1607 } else {
1608 client_rect->top += kAutoHideTaskbarThicknessPx;
1609 }
1610 }
1611 if (EdgeHasTopmostAutoHideTaskbar(ABE_RIGHT, monitor))
1612 client_rect->right -= kAutoHideTaskbarThicknessPx;
1613 if (EdgeHasTopmostAutoHideTaskbar(ABE_BOTTOM, monitor))
1614 client_rect->bottom -= kAutoHideTaskbarThicknessPx;
1615
1616 // We cannot return WVR_REDRAW when there is nonclient area, or Windows
1617 // exhibits bugs where client pixels and child HWNDs are mispositioned by
1618 // the width/height of the upper-left nonclient area.
1619 return 0;
1620 }
1621
1622 // If the window bounds change, we're going to relayout and repaint anyway.
1623 // Returning WVR_REDRAW avoids an extra paint before that of the old client
1624 // pixels in the (now wrong) location, and thus makes actions like resizing a
1625 // window from the left edge look slightly less broken.
1626 // We special case when left or top insets are 0, since these conditions
1627 // actually require another repaint to correct the layout after glass gets
1628 // turned on and off.
1629 if (insets.left() == 0 || insets.top() == 0)
1630 return 0;
1631 return mode ? WVR_REDRAW : 0;
1391 } 1632 }
1392 1633
1393 LRESULT NativeWidgetWin::OnNCHitTest(const CPoint& point) { 1634 LRESULT NativeWidgetWin::OnNCHitTest(const CPoint& point) {
1394 if (!GetWidget()->non_client_view()) { 1635 if (!GetWidget()->non_client_view()) {
1395 SetMsgHandled(FALSE); 1636 SetMsgHandled(FALSE);
1396 return 0; 1637 return 0;
1397 } 1638 }
1398 1639
1399 // If the DWM is rendering the window controls, we need to give the DWM's 1640 // If the DWM is rendering the window controls, we need to give the DWM's
1400 // default window procedure first chance to handle hit testing. 1641 // default window procedure first chance to handle hit testing.
(...skipping 13 matching lines...) Expand all
1414 if (component != HTNOWHERE) 1655 if (component != HTNOWHERE)
1415 return component; 1656 return component;
1416 1657
1417 // Otherwise, we let Windows do all the native frame non-client handling for 1658 // Otherwise, we let Windows do all the native frame non-client handling for
1418 // us. 1659 // us.
1419 SetMsgHandled(FALSE); 1660 SetMsgHandled(FALSE);
1420 return 0; 1661 return 0;
1421 } 1662 }
1422 1663
1423 void NativeWidgetWin::OnNCPaint(HRGN rgn) { 1664 void NativeWidgetWin::OnNCPaint(HRGN rgn) {
1424 SetMsgHandled(FALSE); 1665 // We only do non-client painting if we're not using the native frame.
1666 // It's required to avoid some native painting artifacts from appearing when
1667 // the window is resized.
1668 if (!GetWidget()->non_client_view() || GetWidget()->ShouldUseNativeFrame()) {
1669 SetMsgHandled(FALSE);
1670 return;
1671 }
1672
1673 // We have an NC region and need to paint it. We expand the NC region to
1674 // include the dirty region of the root view. This is done to minimize
1675 // paints.
1676 CRect window_rect;
1677 GetWindowRect(&window_rect);
1678
1679 if (window_rect.Width() != GetWidget()->GetRootView()->width() ||
1680 window_rect.Height() != GetWidget()->GetRootView()->height()) {
1681 // If the size of the window differs from the size of the root view it
1682 // means we're being asked to paint before we've gotten a WM_SIZE. This can
1683 // happen when the user is interactively resizing the window. To avoid
1684 // mass flickering we don't do anything here. Once we get the WM_SIZE we'll
1685 // reset the region of the window which triggers another WM_NCPAINT and
1686 // all is well.
1687 return;
1688 }
1689
1690 CRect dirty_region;
1691 // A value of 1 indicates paint all.
1692 if (!rgn || rgn == reinterpret_cast<HRGN>(1)) {
1693 dirty_region = CRect(0, 0, window_rect.Width(), window_rect.Height());
1694 } else {
1695 RECT rgn_bounding_box;
1696 GetRgnBox(rgn, &rgn_bounding_box);
1697 if (!IntersectRect(&dirty_region, &rgn_bounding_box, &window_rect))
1698 return; // Dirty region doesn't intersect window bounds, bale.
1699
1700 // rgn_bounding_box is in screen coordinates. Map it to window coordinates.
1701 OffsetRect(&dirty_region, -window_rect.left, -window_rect.top);
1702 }
1703
1704 // In theory GetDCEx should do what we want, but I couldn't get it to work.
1705 // In particular the docs mentiond DCX_CLIPCHILDREN, but as far as I can tell
1706 // it doesn't work at all. So, instead we get the DC for the window then
1707 // manually clip out the children.
1708 HDC dc = GetWindowDC(GetNativeView());
1709 ClipState clip_state;
1710 clip_state.x = window_rect.left;
1711 clip_state.y = window_rect.top;
1712 clip_state.parent = GetNativeView();
1713 clip_state.dc = dc;
1714 EnumChildWindows(GetNativeView(), &ClipDCToChild,
1715 reinterpret_cast<LPARAM>(&clip_state));
1716
1717 gfx::Rect old_paint_region = invalid_rect();
1718
1719 if (!old_paint_region.IsEmpty()) {
1720 // The root view has a region that needs to be painted. Include it in the
1721 // region we're going to paint.
1722
1723 CRect old_paint_region_crect = old_paint_region.ToRECT();
1724 CRect tmp = dirty_region;
1725 UnionRect(&dirty_region, &tmp, &old_paint_region_crect);
1726 }
1727
1728 GetWidget()->GetRootView()->SchedulePaintInRect(gfx::Rect(dirty_region));
1729
1730 // gfx::CanvasSkiaPaint's destructor does the actual painting. As such, wrap
1731 // the following in a block to force paint to occur so that we can release
1732 // the dc.
1733 {
1734 gfx::CanvasSkiaPaint canvas(dc, true, dirty_region.left,
1735 dirty_region.top, dirty_region.Width(),
1736 dirty_region.Height());
1737 delegate_->OnNativeWidgetPaint(&canvas);
1738 }
1739
1740 ReleaseDC(GetNativeView(), dc);
1741 // When using a custom frame, we want to avoid calling DefWindowProc() since
1742 // that may render artifacts.
1743 SetMsgHandled(!GetWidget()->ShouldUseNativeFrame());
1425 } 1744 }
1426 1745
1427 LRESULT NativeWidgetWin::OnNCUAHDrawCaption(UINT msg, 1746 LRESULT NativeWidgetWin::OnNCUAHDrawCaption(UINT msg,
1428 WPARAM w_param, 1747 WPARAM w_param,
1429 LPARAM l_param) { 1748 LPARAM l_param) {
1430 // See comment in widget_win.h at the definition of WM_NCUAHDRAWCAPTION for 1749 // See comment in widget_win.h at the definition of WM_NCUAHDRAWCAPTION for
1431 // an explanation about why we need to handle this message. 1750 // an explanation about why we need to handle this message.
1432 SetMsgHandled(!GetWidget()->ShouldUseNativeFrame()); 1751 SetMsgHandled(!GetWidget()->ShouldUseNativeFrame());
1433 return 0; 1752 return 0;
1434 } 1753 }
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
1593 gfx::NativeThemeWin::instance()->CloseHandles(); 1912 gfx::NativeThemeWin::instance()->CloseHandles();
1594 } 1913 }
1595 1914
1596 void NativeWidgetWin::OnVScroll(int scroll_type, 1915 void NativeWidgetWin::OnVScroll(int scroll_type,
1597 short position, 1916 short position,
1598 HWND scrollbar) { 1917 HWND scrollbar) {
1599 SetMsgHandled(FALSE); 1918 SetMsgHandled(FALSE);
1600 } 1919 }
1601 1920
1602 void NativeWidgetWin::OnWindowPosChanging(WINDOWPOS* window_pos) { 1921 void NativeWidgetWin::OnWindowPosChanging(WINDOWPOS* window_pos) {
1922 if (ignore_window_pos_changes_) {
1923 // If somebody's trying to toggle our visibility, change the nonclient area,
1924 // change our Z-order, or activate us, we should probably let it go through.
1925 if (!(window_pos->flags & ((IsVisible() ? SWP_HIDEWINDOW : SWP_SHOWWINDOW) |
1926 SWP_FRAMECHANGED)) &&
1927 (window_pos->flags & (SWP_NOZORDER | SWP_NOACTIVATE))) {
1928 // Just sizing/moving the window; ignore.
1929 window_pos->flags |= SWP_NOSIZE | SWP_NOMOVE | SWP_NOREDRAW;
1930 window_pos->flags &= ~(SWP_SHOWWINDOW | SWP_HIDEWINDOW);
1931 }
1932 } else if (!GetParent()) {
1933 CRect window_rect;
1934 HMONITOR monitor;
1935 gfx::Rect monitor_rect, work_area;
1936 if (GetWindowRect(&window_rect) &&
1937 GetMonitorAndRects(window_rect, &monitor, &monitor_rect, &work_area)) {
1938 if (monitor && (monitor == last_monitor_) &&
1939 (IsFullscreen() || ((monitor_rect == last_monitor_rect_) &&
1940 (work_area != last_work_area_)))) {
1941 // A rect for the monitor we're on changed. Normally Windows notifies
1942 // us about this (and thus we're reaching here due to the SetWindowPos()
1943 // call in OnSettingChange() above), but with some software (e.g.
1944 // nVidia's nView desktop manager) the work area can change asynchronous
1945 // to any notification, and we're just sent a SetWindowPos() call with a
1946 // new (frequently incorrect) position/size. In either case, the best
1947 // response is to throw away the existing position/size information in
1948 // |window_pos| and recalculate it based on the new work rect.
1949 gfx::Rect new_window_rect;
1950 if (IsFullscreen()) {
1951 new_window_rect = monitor_rect;
1952 } else if (IsZoomed()) {
1953 new_window_rect = work_area;
1954 int border_thickness = GetSystemMetrics(SM_CXSIZEFRAME);
1955 new_window_rect.Inset(-border_thickness, -border_thickness);
1956 } else {
1957 new_window_rect = gfx::Rect(window_rect).AdjustToFit(work_area);
1958 }
1959 window_pos->x = new_window_rect.x();
1960 window_pos->y = new_window_rect.y();
1961 window_pos->cx = new_window_rect.width();
1962 window_pos->cy = new_window_rect.height();
1963 // WARNING! Don't set SWP_FRAMECHANGED here, it breaks moving the child
1964 // HWNDs for some reason.
1965 window_pos->flags &= ~(SWP_NOSIZE | SWP_NOMOVE | SWP_NOREDRAW);
1966 window_pos->flags |= SWP_NOCOPYBITS;
1967
1968 // Now ignore all immediately-following SetWindowPos() changes. Windows
1969 // likes to (incorrectly) recalculate what our position/size should be
1970 // and send us further updates.
1971 ignore_window_pos_changes_ = true;
1972 DCHECK(ignore_pos_changes_factory_.empty());
1973 MessageLoop::current()->PostTask(FROM_HERE,
1974 ignore_pos_changes_factory_.NewRunnableMethod(
1975 &NativeWidgetWin::StopIgnoringPosChanges));
1976 }
1977 last_monitor_ = monitor;
1978 last_monitor_rect_ = monitor_rect;
1979 last_work_area_ = work_area;
1980 }
1981 }
1982
1603 if (force_hidden_count_) { 1983 if (force_hidden_count_) {
1604 // Prevent the window from being made visible if we've been asked to do so. 1984 // Prevent the window from being made visible if we've been asked to do so.
1605 // See comment in header as to why we might want this. 1985 // See comment in header as to why we might want this.
1606 window_pos->flags &= ~SWP_SHOWWINDOW; 1986 window_pos->flags &= ~SWP_SHOWWINDOW;
1607 } 1987 }
1608 1988
1609 SetMsgHandled(FALSE); 1989 SetMsgHandled(FALSE);
1610 } 1990 }
1611 1991
1612 void NativeWidgetWin::OnWindowPosChanged(WINDOWPOS* window_pos) { 1992 void NativeWidgetWin::OnWindowPosChanged(WINDOWPOS* window_pos) {
(...skipping 11 matching lines...) Expand all
1624 //////////////////////////////////////////////////////////////////////////////// 2004 ////////////////////////////////////////////////////////////////////////////////
1625 // NativeWidgetWin, protected: 2005 // NativeWidgetWin, protected:
1626 2006
1627 int NativeWidgetWin::GetShowState() const { 2007 int NativeWidgetWin::GetShowState() const {
1628 return SW_SHOWNORMAL; 2008 return SW_SHOWNORMAL;
1629 } 2009 }
1630 2010
1631 gfx::Insets NativeWidgetWin::GetClientAreaInsets() const { 2011 gfx::Insets NativeWidgetWin::GetClientAreaInsets() const {
1632 // Returning an empty Insets object causes the default handling in 2012 // Returning an empty Insets object causes the default handling in
1633 // NativeWidgetWin::OnNCCalcSize() to be invoked. 2013 // NativeWidgetWin::OnNCCalcSize() to be invoked.
1634 if (GetWidget()->ShouldUseNativeFrame()) 2014 if (!GetWidget()->non_client_view() || GetWidget()->ShouldUseNativeFrame())
1635 return gfx::Insets(); 2015 return gfx::Insets();
1636 2016
1637 if (IsMaximized()) { 2017 if (IsMaximized()) {
1638 // Windows automatically adds a standard width border to all sides when a 2018 // Windows automatically adds a standard width border to all sides when a
1639 // window is maximized. 2019 // window is maximized.
1640 int border_thickness = GetSystemMetrics(SM_CXSIZEFRAME); 2020 int border_thickness = GetSystemMetrics(SM_CXSIZEFRAME);
1641 return gfx::Insets(border_thickness, border_thickness, border_thickness, 2021 return gfx::Insets(border_thickness, border_thickness, border_thickness,
1642 border_thickness); 2022 border_thickness);
1643 } 2023 }
1644 // This is weird, but highly essential. If we don't offset the bottom edge 2024 // This is weird, but highly essential. If we don't offset the bottom edge
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
1773 ex_style |= l10n_util::GetExtendedTooltipStyles(); 2153 ex_style |= l10n_util::GetExtendedTooltipStyles();
1774 if (params.transparent) 2154 if (params.transparent)
1775 ex_style |= WS_EX_LAYERED; 2155 ex_style |= WS_EX_LAYERED;
1776 if (params.has_dropshadow) { 2156 if (params.has_dropshadow) {
1777 class_style |= (base::win::GetVersion() < base::win::VERSION_XP) ? 2157 class_style |= (base::win::GetVersion() < base::win::VERSION_XP) ?
1778 0 : CS_DROPSHADOW; 2158 0 : CS_DROPSHADOW;
1779 } 2159 }
1780 2160
1781 // Set type-dependent style attributes. 2161 // Set type-dependent style attributes.
1782 switch (params.type) { 2162 switch (params.type) {
1783 case Widget::InitParams::TYPE_WINDOW: 2163 case Widget::InitParams::TYPE_WINDOW: {
2164 style |= WS_SYSMENU | WS_CAPTION;
2165 bool can_resize = GetWidget()->widget_delegate()->CanResize();
2166 bool can_maximize = GetWidget()->widget_delegate()->CanMaximize();
2167 if (can_maximize) {
2168 style |= WS_OVERLAPPEDWINDOW;
2169 } else if (can_resize) {
2170 style |= WS_OVERLAPPED | WS_THICKFRAME;
2171 }
2172 if (delegate_->IsDialogBox()) {
2173 style |= DS_MODALFRAME;
2174 // NOTE: Turning this off means we lose the close button, which is bad.
2175 // Turning it on though means the user can maximize or size the window
2176 // from the system menu, which is worse. We may need to provide our own
2177 // menu to get the close button to appear properly.
2178 // style &= ~WS_SYSMENU;
2179 }
2180 ex_style |= delegate_->IsDialogBox() ? WS_EX_DLGMODALFRAME : 0;
2181 break;
2182 }
1784 case Widget::InitParams::TYPE_CONTROL: 2183 case Widget::InitParams::TYPE_CONTROL:
1785 break; 2184 break;
1786 case Widget::InitParams::TYPE_WINDOW_FRAMELESS: 2185 case Widget::InitParams::TYPE_WINDOW_FRAMELESS:
1787 style |= WS_POPUP; 2186 style |= WS_POPUP;
1788 break; 2187 break;
1789 case Widget::InitParams::TYPE_POPUP: 2188 case Widget::InitParams::TYPE_POPUP:
1790 style |= WS_POPUP; 2189 style |= WS_POPUP;
1791 ex_style |= WS_EX_TOOLWINDOW; 2190 ex_style |= WS_EX_TOOLWINDOW;
1792 break; 2191 break;
1793 case Widget::InitParams::TYPE_MENU: 2192 case Widget::InitParams::TYPE_MENU:
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
1917 } 2316 }
1918 2317
1919 gfx::AcceleratedWidget NativeWidgetWin::GetAcceleratedWidget() { 2318 gfx::AcceleratedWidget NativeWidgetWin::GetAcceleratedWidget() {
1920 #if defined(VIEWS_COMPOSITOR) 2319 #if defined(VIEWS_COMPOSITOR)
1921 return hwnd(); 2320 return hwnd();
1922 #else 2321 #else
1923 return gfx::kNullAcceleratedWidget; 2322 return gfx::kNullAcceleratedWidget;
1924 #endif 2323 #endif
1925 } 2324 }
1926 2325
2326 void NativeWidgetWin::RestoreEnabledIfNecessary() {
2327 if (delegate_->IsModal() && !restored_enabled_) {
2328 restored_enabled_ = true;
2329 // If we were run modally, we need to undo the disabled-ness we inflicted on
2330 // the owner's parent hierarchy.
2331 HWND start = ::GetWindow(GetNativeView(), GW_OWNER);
2332 while (start) {
2333 ::EnableWindow(start, TRUE);
2334 start = ::GetParent(start);
2335 }
2336 }
2337 }
2338
2339
1927 void NativeWidgetWin::DispatchKeyEventPostIME(const KeyEvent& key) { 2340 void NativeWidgetWin::DispatchKeyEventPostIME(const KeyEvent& key) {
1928 SetMsgHandled(delegate_->OnKeyEvent(key)); 2341 SetMsgHandled(delegate_->OnKeyEvent(key));
1929 } 2342 }
1930 2343
1931 //////////////////////////////////////////////////////////////////////////////// 2344 ////////////////////////////////////////////////////////////////////////////////
1932 // Widget, public: 2345 // Widget, public:
1933 2346
1934 // static 2347 // static
1935 void Widget::NotifyLocaleChanged() { 2348 void Widget::NotifyLocaleChanged() {
1936 NOTIMPLEMENTED(); 2349 NOTIMPLEMENTED();
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
2067 2480
2068 // And now, notify them that they have a brand new parent. 2481 // And now, notify them that they have a brand new parent.
2069 for (NativeWidgets::iterator it = widgets.begin(); 2482 for (NativeWidgets::iterator it = widgets.begin();
2070 it != widgets.end(); ++it) { 2483 it != widgets.end(); ++it) {
2071 (*it)->GetWidget()->NotifyNativeViewHierarchyChanged(true, 2484 (*it)->GetWidget()->NotifyNativeViewHierarchyChanged(true,
2072 new_parent); 2485 new_parent);
2073 } 2486 }
2074 } 2487 }
2075 2488
2076 } // namespace views 2489 } // namespace views
OLDNEW
« no previous file with comments | « views/widget/native_widget_win.h ('k') | views/widget/native_widget_win_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698