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

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

Issue 577018: Support app menu and double-click close on upper left corner of window, part ... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 10 years, 10 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/window_win.h ('k') | no next file » | 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) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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/window_win.h" 5 #include "views/window/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 "app/gfx/canvas_paint.h" 10 #include "app/gfx/canvas_paint.h"
11 #include "app/gfx/font.h" 11 #include "app/gfx/font.h"
(...skipping 480 matching lines...) Expand 10 before | Expand all | Expand 10 after
492 window_closed_(false), 492 window_closed_(false),
493 disable_inactive_rendering_(false), 493 disable_inactive_rendering_(false),
494 is_active_(false), 494 is_active_(false),
495 lock_updates_(false), 495 lock_updates_(false),
496 saved_window_style_(0), 496 saved_window_style_(0),
497 saved_maximized_state_(0), 497 saved_maximized_state_(0),
498 ignore_window_pos_changes_(false), 498 ignore_window_pos_changes_(false),
499 ignore_pos_changes_factory_(this), 499 ignore_pos_changes_factory_(this),
500 force_hidden_count_(0), 500 force_hidden_count_(0),
501 is_right_mouse_pressed_on_caption_(false), 501 is_right_mouse_pressed_on_caption_(false),
502 last_time_system_menu_clicked_(0),
503 last_monitor_(NULL) { 502 last_monitor_(NULL) {
504 is_window_ = true; 503 is_window_ = true;
505 InitClass(); 504 InitClass();
506 DCHECK(window_delegate_); 505 DCHECK(window_delegate_);
507 window_delegate_->window_.reset(this); 506 window_delegate_->window_.reset(this);
508 // Initialize these values to 0 so that subclasses can override the default 507 // Initialize these values to 0 so that subclasses can override the default
509 // behavior before calling Init. 508 // behavior before calling Init.
510 set_window_style(0); 509 set_window_style(0);
511 set_window_ex_style(0); 510 set_window_ex_style(0);
512 } 511 }
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
569 // know why) the client area goes from matching the window rect to being 568 // know why) the client area goes from matching the window rect to being
570 // something else. If the client area is not the window rect in both 569 // something else. If the client area is not the window rect in both
571 // modes, the blackness doesn't occur. Because of this, we need to tell 570 // modes, the blackness doesn't occur. Because of this, we need to tell
572 // the RootView to lay out to fit the window rect, rather than the client 571 // the RootView to lay out to fit the window rect, rather than the client
573 // rect when using the opaque frame. See GetRootViewSize. 572 // rect when using the opaque frame. See GetRootViewSize.
574 // Note: this is only required for non-fullscreen windows. Note that 573 // Note: this is only required for non-fullscreen windows. Note that
575 // fullscreen windows are in restored state, not maximized. 574 // fullscreen windows are in restored state, not maximized.
576 return gfx::Insets(0, 0, IsFullscreen() ? 0 : 1, 0); 575 return gfx::Insets(0, 0, IsFullscreen() ? 0 : 1, 0);
577 } 576 }
578 577
579 void WindowWin::RunSystemMenu(const gfx::Point& point) {
580 // We need to reset and clean up any currently created system menu objects.
581 // We need to call this otherwise there's a small chance that we aren't going
582 // to get a system menu. We also can't take the return value of this
583 // function. We need to call it *again* to get a valid HMENU.
584 //::GetSystemMenu(GetNativeView(), TRUE);
585 UINT flags = TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_RETURNCMD;
586 if (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT)
587 flags |= TPM_RIGHTALIGN;
588 HMENU system_menu = ::GetSystemMenu(GetNativeView(), FALSE);
589 int id = ::TrackPopupMenu(system_menu, flags,
590 point.x(), point.y(), 0, GetNativeView(), NULL);
591 ExecuteSystemMenuCommand(id);
592 if (id) // something was selected
593 last_time_system_menu_clicked_ = 0;
594 }
595
596 /////////////////////////////////////////////////////////////////////////////// 578 ///////////////////////////////////////////////////////////////////////////////
597 // WindowWin, WidgetWin overrides: 579 // WindowWin, WidgetWin overrides:
598 580
599 void WindowWin::OnActivate(UINT action, BOOL minimized, HWND window) { 581 void WindowWin::OnActivate(UINT action, BOOL minimized, HWND window) {
600 if (action == WA_INACTIVE) 582 if (action == WA_INACTIVE)
601 SaveWindowPosition(); 583 SaveWindowPosition();
602 } 584 }
603 585
604 void WindowWin::OnActivateApp(BOOL active, DWORD thread_id) { 586 void WindowWin::OnActivateApp(BOOL active, DWORD thread_id) {
605 if (!active && thread_id != GetCurrentThreadId()) { 587 if (!active && thread_id != GetCurrentThreadId()) {
(...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after
955 // window control button appearance, in the Windows classic style, over 937 // window control button appearance, in the Windows classic style, over
956 // our view! Ick! By handling this message we prevent Windows from 938 // our view! Ick! By handling this message we prevent Windows from
957 // doing this undesirable thing, but that means we need to roll the 939 // doing this undesirable thing, but that means we need to roll the
958 // sys-command handling ourselves. 940 // sys-command handling ourselves.
959 ProcessNCMousePress(point, MK_LBUTTON); 941 ProcessNCMousePress(point, MK_LBUTTON);
960 return; 942 return;
961 } 943 }
962 } 944 }
963 } 945 }
964 946
965 // TODO(beng): figure out why we need to run the system menu manually 947 WidgetWin::OnNCLButtonDown(ht_component, point);
966 // ourselves. This is wrong and causes many subtle bugs.
967 // From my initial research, it looks like DefWindowProc tries
968 // to run it but fails before sending the initial WM_MENUSELECT
969 // for the sysmenu.
970 // TODO(georgey): Remove the fix for double click when we figure out why
971 // system menu does not open automatically and pass it to
972 // default processing.
973 if (ht_component == HTSYSMENU) {
974 // We use 0 as a special value. If user is "lucky" and double clicks on
975 // system icon exactly 49.7x days after PC was started we ignore that
976 // click.
977 last_time_system_menu_clicked_ = GetTickCount();
978 RunSystemMenu(non_client_view_->GetSystemMenuPoint());
979 } else {
980 WidgetWin::OnNCLButtonDown(ht_component, point);
981 }
982 948
983 /* TODO(beng): Fix the standard non-client over-painting bug. This code 949 /* TODO(beng): Fix the standard non-client over-painting bug. This code
984 doesn't work but identifies the problem. 950 doesn't work but identifies the problem.
985 if (!IsMsgHandled()) { 951 if (!IsMsgHandled()) {
986 // WindowWin::OnNCLButtonDown set the message as unhandled. This normally 952 // WindowWin::OnNCLButtonDown set the message as unhandled. This normally
987 // means WidgetWin::ProcessWindowMessage will pass it to 953 // means WidgetWin::ProcessWindowMessage will pass it to
988 // DefWindowProc. Sadly, DefWindowProc for WM_NCLBUTTONDOWN does weird 954 // DefWindowProc. Sadly, DefWindowProc for WM_NCLBUTTONDOWN does weird
989 // non-client painting, so we need to call it directly here inside a 955 // non-client painting, so we need to call it directly here inside a
990 // scoped update lock. 956 // scoped update lock.
991 ScopedRedrawLock lock(this); 957 ScopedRedrawLock lock(this);
992 DefWindowProc(GetNativeView(), WM_NCLBUTTONDOWN, ht_component, 958 DefWindowProc(GetNativeView(), WM_NCLBUTTONDOWN, ht_component,
993 MAKELPARAM(point.x, point.y)); 959 MAKELPARAM(point.x, point.y));
994 SetMsgHandled(TRUE); 960 SetMsgHandled(TRUE);
995 } 961 }
996 */ 962 */
997 } 963 }
998 964
999 void WindowWin::OnNCLButtonUp(UINT ht_component, const CPoint& point) {
1000 // georgey : fix for double click on system icon not working
1001 // As we do track on system menu, the following sequence occurs, when user
1002 // double clicks:
1003 // 1. Window gets WM_NCLBUTTONDOWN with ht_component == HTSYSMENU
1004 // 2. We call TrackPopupMenu, that captures the mouse
1005 // 3. Menu, not window, gets WM_NCLBUTTONUP
1006 // 4. Menu gets WM_NCLBUTTONDOWN and closes returning 0 (canceled) from
1007 // TrackPopupMenu.
1008 // 5. Window gets WM_NCLBUTTONUP with ht_component == HTSYSMENU
1009 if (ht_component == HTSYSMENU) {
1010 if (last_time_system_menu_clicked_) {
1011 if ((GetTickCount() - last_time_system_menu_clicked_) <=
1012 GetDoubleClickTime()) {
1013 // User double clicked left mouse button on system menu - close
1014 // window
1015 ExecuteSystemMenuCommand(SC_CLOSE);
1016 }
1017 last_time_system_menu_clicked_ = 0;
1018 }
1019 }
1020
1021 WidgetWin::OnNCLButtonUp(ht_component, point);
1022 }
1023
1024 void WindowWin::OnNCRButtonDown(UINT ht_component, const CPoint& point) { 965 void WindowWin::OnNCRButtonDown(UINT ht_component, const CPoint& point) {
1025 if (ht_component == HTCAPTION || ht_component == HTSYSMENU) { 966 if (ht_component == HTCAPTION || ht_component == HTSYSMENU) {
1026 is_right_mouse_pressed_on_caption_ = true; 967 is_right_mouse_pressed_on_caption_ = true;
1027 // Using SetCapture() here matches Windows native behavior for right-clicks 968 // We SetCapture() to ensure we only show the menu when the button down and
1028 // on the title bar. It's not obvious why Windows does this. 969 // up are both on the caption. Note: this causes the button up to be
970 // WM_RBUTTONUP instead of WM_NCRBUTTONUP.
1029 SetCapture(); 971 SetCapture();
1030 } 972 }
1031 973
1032 WidgetWin::OnNCRButtonDown(ht_component, point); 974 WidgetWin::OnNCRButtonDown(ht_component, point);
1033 } 975 }
1034 976
1035 void WindowWin::OnNCRButtonUp(UINT ht_component, const CPoint& point) {
1036 if (is_right_mouse_pressed_on_caption_)
1037 is_right_mouse_pressed_on_caption_ = false;
1038
1039 WidgetWin::OnNCRButtonUp(ht_component, point);
1040 }
1041
1042 void WindowWin::OnRButtonUp(UINT ht_component, const CPoint& point) { 977 void WindowWin::OnRButtonUp(UINT ht_component, const CPoint& point) {
1043 // We handle running the system menu on mouseup here because calling
1044 // SetCapture() on mousedown makes the mouseup generate WM_RBUTTONUP instead
1045 // of WM_NCRBUTTONUP.
1046 if (is_right_mouse_pressed_on_caption_) { 978 if (is_right_mouse_pressed_on_caption_) {
1047 is_right_mouse_pressed_on_caption_ = false; 979 is_right_mouse_pressed_on_caption_ = false;
1048 ReleaseCapture(); 980 ReleaseCapture();
1049 // |point| is in window coordinates, but WM_NCHITTEST and RunSystemMenu() 981 // |point| is in window coordinates, but WM_NCHITTEST and TrackPopupMenu()
1050 // expect screen coordinates. 982 // expect screen coordinates.
1051 CPoint screen_point(point); 983 CPoint screen_point(point);
1052 MapWindowPoints(GetNativeView(), HWND_DESKTOP, &screen_point, 1); 984 MapWindowPoints(GetNativeView(), HWND_DESKTOP, &screen_point, 1);
1053 ht_component = ::SendMessage(GetNativeView(), WM_NCHITTEST, 0, 985 ht_component = SendMessage(GetNativeView(), WM_NCHITTEST, 0,
1054 MAKELPARAM(screen_point.x, screen_point.y)); 986 MAKELPARAM(screen_point.x, screen_point.y));
1055 if (ht_component == HTCAPTION || ht_component == HTSYSMENU) { 987 if (ht_component == HTCAPTION || ht_component == HTSYSMENU) {
1056 RunSystemMenu(gfx::Point(screen_point)); 988 UINT flags = TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_RETURNCMD;
989 if (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT)
990 flags |= TPM_RIGHTALIGN;
991 HMENU system_menu = GetSystemMenu(GetNativeView(), FALSE);
992 int id = TrackPopupMenu(system_menu, flags, screen_point.x,
993 screen_point.y, 0, GetNativeView(), NULL);
994 ExecuteSystemMenuCommand(id);
Ben Goodger (Google) 2010/02/05 03:27:25 This is all because we called SetCapture right? i.
Peter Kasting 2010/02/05 05:01:06 Sadly, no. I tried this, and then I tried making
1057 return; 995 return;
1058 } 996 }
1059 } 997 }
1060 998
1061 WidgetWin::OnRButtonUp(ht_component, point); 999 WidgetWin::OnRButtonUp(ht_component, point);
1062 } 1000 }
1063 1001
1064 LRESULT WindowWin::OnNCUAHDrawCaption(UINT msg, WPARAM w_param, 1002 LRESULT WindowWin::OnNCUAHDrawCaption(UINT msg, WPARAM w_param,
1065 LPARAM l_param) { 1003 LPARAM l_param) {
1066 // See comment in widget_win.h at the definition of WM_NCUAHDRAWCAPTION for 1004 // See comment in widget_win.h at the definition of WM_NCUAHDRAWCAPTION for
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
1139 // sizing/moving feedback can be continuous. 1077 // sizing/moving feedback can be continuous.
1140 UnlockUpdates(); 1078 UnlockUpdates();
1141 } 1079 }
1142 } 1080 }
1143 } 1081 }
1144 1082
1145 // First see if the delegate can handle it. 1083 // First see if the delegate can handle it.
1146 if (window_delegate_->ExecuteWindowsCommand(notification_code)) 1084 if (window_delegate_->ExecuteWindowsCommand(notification_code))
1147 return; 1085 return;
1148 1086
1149 if ((notification_code == SC_KEYMENU) && (click.x == VK_SPACE)) { 1087 // Use the default implementation for any other command.
1150 // Run the system menu at the NonClientView's desired location. 1088 DefWindowProc(GetNativeView(), WM_SYSCOMMAND, notification_code,
1151 RunSystemMenu(non_client_view_->GetSystemMenuPoint()); 1089 MAKELPARAM(click.x, click.y));
1152 } else {
1153 // Use the default implementation for any other command.
1154 DefWindowProc(GetNativeView(), WM_SYSCOMMAND, notification_code,
1155 MAKELPARAM(click.y, click.x));
1156 }
1157 } 1090 }
1158 1091
1159 void WindowWin::OnWindowPosChanging(WINDOWPOS* window_pos) { 1092 void WindowWin::OnWindowPosChanging(WINDOWPOS* window_pos) {
1160 if (force_hidden_count_) { 1093 if (force_hidden_count_) {
1161 // Prevent the window from being made visible if we've been asked to do so. 1094 // Prevent the window from being made visible if we've been asked to do so.
1162 // See comment in header as to why we might want this. 1095 // See comment in header as to why we might want this.
1163 window_pos->flags &= ~SWP_SHOWWINDOW; 1096 window_pos->flags &= ~SWP_SHOWWINDOW;
1164 } 1097 }
1165 1098
1166 if (ignore_window_pos_changes_) { 1099 if (ignore_window_pos_changes_) {
(...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after
1491 Window::CloseSecondaryWidget(root_view->GetWidget()); 1424 Window::CloseSecondaryWidget(root_view->GetWidget());
1492 return TRUE; 1425 return TRUE;
1493 } 1426 }
1494 } // namespace 1427 } // namespace
1495 1428
1496 void Window::CloseAllSecondaryWindows() { 1429 void Window::CloseAllSecondaryWindows() {
1497 EnumThreadWindows(GetCurrentThreadId(), WindowCallbackProc, 0); 1430 EnumThreadWindows(GetCurrentThreadId(), WindowCallbackProc, 0);
1498 } 1431 }
1499 1432
1500 } // namespace views 1433 } // namespace views
OLDNEW
« no previous file with comments | « views/window/window_win.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698