| OLD | NEW |
| 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 #include <shellapi.h> |
| 9 | 9 |
| 10 #include <algorithm> | 10 #include <algorithm> |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 48 #include "views/widget/root_view.h" | 48 #include "views/widget/root_view.h" |
| 49 #include "views/widget/widget_delegate.h" | 49 #include "views/widget/widget_delegate.h" |
| 50 #include "views/window/native_frame_view.h" | 50 #include "views/window/native_frame_view.h" |
| 51 | 51 |
| 52 #pragma comment(lib, "dwmapi.lib") | 52 #pragma comment(lib, "dwmapi.lib") |
| 53 | 53 |
| 54 using ui::ViewProp; | 54 using ui::ViewProp; |
| 55 | 55 |
| 56 namespace views { | 56 namespace views { |
| 57 | 57 |
| 58 namespace internal { | |
| 59 | |
| 60 void EnsureRectIsVisibleInRect(const gfx::Rect& parent_rect, | |
| 61 gfx::Rect* child_rect, | |
| 62 int padding) { | |
| 63 DCHECK(child_rect); | |
| 64 | |
| 65 // We use padding here because it allows some of the original web page to | |
| 66 // bleed through around the edges. | |
| 67 int twice_padding = padding * 2; | |
| 68 | |
| 69 // FIRST, clamp width and height so we don't open child windows larger than | |
| 70 // the containing parent. | |
| 71 if (child_rect->width() > (parent_rect.width() + twice_padding)) | |
| 72 child_rect->set_width(std::max(0, parent_rect.width() - twice_padding)); | |
| 73 if (child_rect->height() > parent_rect.height() + twice_padding) | |
| 74 child_rect->set_height(std::max(0, parent_rect.height() - twice_padding)); | |
| 75 | |
| 76 // SECOND, clamp x,y position to padding,padding so we don't position child | |
| 77 // windows in hyperspace. | |
| 78 // TODO(mpcomplete): I don't see what the second check in each 'if' does that | |
| 79 // isn't handled by the LAST set of 'ifs'. Maybe we can remove it. | |
| 80 if (child_rect->x() < parent_rect.x() || | |
| 81 child_rect->x() > parent_rect.right()) { | |
| 82 child_rect->set_x(parent_rect.x() + padding); | |
| 83 } | |
| 84 if (child_rect->y() < parent_rect.y() || | |
| 85 child_rect->y() > parent_rect.bottom()) { | |
| 86 child_rect->set_y(parent_rect.y() + padding); | |
| 87 } | |
| 88 | |
| 89 // LAST, nudge the window back up into the client area if its x,y position is | |
| 90 // within the parent bounds but its width/height place it off-screen. | |
| 91 if (child_rect->bottom() > parent_rect.bottom()) | |
| 92 child_rect->set_y(parent_rect.bottom() - child_rect->height() - padding); | |
| 93 if (child_rect->right() > parent_rect.right()) | |
| 94 child_rect->set_x(parent_rect.right() - child_rect->width() - padding); | |
| 95 } | |
| 96 | |
| 97 } // namespace internal | |
| 98 | |
| 99 namespace { | 58 namespace { |
| 100 | 59 |
| 101 // Get the source HWND of the specified message. Depending on the message, the | 60 // Get the source HWND of the specified message. Depending on the message, the |
| 102 // source HWND is encoded in either the WPARAM or the LPARAM value. | 61 // source HWND is encoded in either the WPARAM or the LPARAM value. |
| 103 HWND GetControlHWNDForMessage(UINT message, WPARAM w_param, LPARAM l_param) { | 62 HWND GetControlHWNDForMessage(UINT message, WPARAM w_param, LPARAM l_param) { |
| 104 // Each of the following messages can be sent by a child HWND and must be | 63 // Each of the following messages can be sent by a child HWND and must be |
| 105 // forwarded to its associated NativeControlWin for handling. | 64 // forwarded to its associated NativeControlWin for handling. |
| 106 switch (message) { | 65 switch (message) { |
| 107 case WM_NOTIFY: | 66 case WM_NOTIFY: |
| 108 return reinterpret_cast<NMHDR*>(l_param)->hwndFrom; | 67 return reinterpret_cast<NMHDR*>(l_param)->hwndFrom; |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 154 } | 113 } |
| 155 | 114 |
| 156 // Returns true if the WINDOWPOS data provided indicates the client area of | 115 // Returns true if the WINDOWPOS data provided indicates the client area of |
| 157 // the window may have changed size. This can be caused by the window being | 116 // the window may have changed size. This can be caused by the window being |
| 158 // resized or its frame changing. | 117 // resized or its frame changing. |
| 159 bool DidClientAreaSizeChange(const WINDOWPOS* window_pos) { | 118 bool DidClientAreaSizeChange(const WINDOWPOS* window_pos) { |
| 160 return !(window_pos->flags & SWP_NOSIZE) || | 119 return !(window_pos->flags & SWP_NOSIZE) || |
| 161 window_pos->flags & SWP_FRAMECHANGED; | 120 window_pos->flags & SWP_FRAMECHANGED; |
| 162 } | 121 } |
| 163 | 122 |
| 164 // Ensures that the child window stays within the boundaries of the parent | |
| 165 // before setting its bounds. If |parent_window| is NULL, the bounds of the | |
| 166 // parent are assumed to be the bounds of the monitor that |child_window| is | |
| 167 // nearest to. If |child_window| isn't visible yet and |insert_after_window| | |
| 168 // is non-NULL and visible, the monitor |insert_after_window| is on is used | |
| 169 // as the parent bounds instead. | |
| 170 // TODO(beng): This function could easily not be so windowsy, deal with Widgets | |
| 171 // instead of HWNDs, and move to Widget instead of NativeWidget and | |
| 172 // then miraculously also work on Linux. | |
| 173 void SetChildBounds(HWND child_window, | |
| 174 HWND parent_window, | |
| 175 HWND insert_after_window, | |
| 176 const gfx::Rect& bounds, | |
| 177 int padding, | |
| 178 unsigned long flags) { | |
| 179 DCHECK(IsWindow(child_window)); | |
| 180 | |
| 181 // First figure out the bounds of the parent. | |
| 182 RECT parent_rect = {0}; | |
| 183 if (parent_window) { | |
| 184 GetClientRect(parent_window, &parent_rect); | |
| 185 } else { | |
| 186 // If there is no parent, we consider the bounds of the monitor the window | |
| 187 // is on to be the parent bounds. | |
| 188 | |
| 189 // If the child_window isn't visible yet and we've been given a valid, | |
| 190 // visible insert after window, use that window to locate the correct | |
| 191 // monitor instead. | |
| 192 HWND window = child_window; | |
| 193 if (!IsWindowVisible(window) && IsWindow(insert_after_window) && | |
| 194 IsWindowVisible(insert_after_window)) | |
| 195 window = insert_after_window; | |
| 196 | |
| 197 gfx::Rect work_area = | |
| 198 gfx::Screen::GetMonitorWorkAreaNearestPoint(bounds.origin()); | |
| 199 if (!work_area.IsEmpty()) | |
| 200 parent_rect = work_area.ToRECT(); | |
| 201 } | |
| 202 | |
| 203 gfx::Rect actual_bounds = bounds; | |
| 204 internal::EnsureRectIsVisibleInRect(gfx::Rect(parent_rect), &actual_bounds, | |
| 205 padding); | |
| 206 | |
| 207 SetWindowPos(child_window, insert_after_window, actual_bounds.x(), | |
| 208 actual_bounds.y(), actual_bounds.width(), | |
| 209 actual_bounds.height(), flags); | |
| 210 } | |
| 211 | |
| 212 // Callback used to notify child windows that the top level window received a | 123 // Callback used to notify child windows that the top level window received a |
| 213 // DWMCompositionChanged message. | 124 // DWMCompositionChanged message. |
| 214 BOOL CALLBACK SendDwmCompositionChanged(HWND window, LPARAM param) { | 125 BOOL CALLBACK SendDwmCompositionChanged(HWND window, LPARAM param) { |
| 215 SendMessage(window, WM_DWMCOMPOSITIONCHANGED, 0, 0); | 126 SendMessage(window, WM_DWMCOMPOSITIONCHANGED, 0, 0); |
| 216 return TRUE; | 127 return TRUE; |
| 217 } | 128 } |
| 218 | 129 |
| 219 // Tells the window its frame (non-client area) has changed. | 130 // Tells the window its frame (non-client area) has changed. |
| 220 void SendFrameChanged(HWND window) { | 131 void SendFrameChanged(HWND window) { |
| 221 SetWindowPos(window, NULL, 0, 0, 0, 0, | 132 SetWindowPos(window, NULL, 0, 0, 0, 0, |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 289 return true; | 200 return true; |
| 290 } | 201 } |
| 291 | 202 |
| 292 // Links the HWND to its NativeWidget. | 203 // Links the HWND to its NativeWidget. |
| 293 const char* const kNativeWidgetKey = "__VIEWS_NATIVE_WIDGET__"; | 204 const char* const kNativeWidgetKey = "__VIEWS_NATIVE_WIDGET__"; |
| 294 | 205 |
| 295 // A custom MSAA object id used to determine if a screen reader is actively | 206 // A custom MSAA object id used to determine if a screen reader is actively |
| 296 // listening for MSAA events. | 207 // listening for MSAA events. |
| 297 const int kCustomObjectID = 1; | 208 const int kCustomObjectID = 1; |
| 298 | 209 |
| 299 // If the hung renderer warning doesn't fit on screen, the amount of padding to | |
| 300 // be left between the edge of the window and the edge of the nearest monitor, | |
| 301 // after the window is nudged back on screen. Pixels. | |
| 302 const int kMonitorEdgePadding = 10; | |
| 303 | |
| 304 const int kDragFrameWindowAlpha = 200; | 210 const int kDragFrameWindowAlpha = 200; |
| 305 | 211 |
| 306 } // namespace | 212 } // namespace |
| 307 | 213 |
| 308 // static | 214 // static |
| 309 bool NativeWidgetWin::screen_reader_active_ = false; | 215 bool NativeWidgetWin::screen_reader_active_ = false; |
| 310 | 216 |
| 311 // A scoping class that prevents a window from being able to redraw in response | 217 // A scoping class that prevents a window from being able to redraw in response |
| 312 // to invalidations that may occur within it for the lifetime of the object. | 218 // to invalidations that may occur within it for the lifetime of the object. |
| 313 // | 219 // |
| (...skipping 485 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 799 SetWindowLong(GWL_STYLE, style & ~WS_MAXIMIZE); | 705 SetWindowLong(GWL_STYLE, style & ~WS_MAXIMIZE); |
| 800 SetWindowPos(NULL, bounds.x(), bounds.y(), bounds.width(), bounds.height(), | 706 SetWindowPos(NULL, bounds.x(), bounds.y(), bounds.width(), bounds.height(), |
| 801 SWP_NOACTIVATE | SWP_NOZORDER); | 707 SWP_NOACTIVATE | SWP_NOZORDER); |
| 802 } | 708 } |
| 803 | 709 |
| 804 void NativeWidgetWin::SetSize(const gfx::Size& size) { | 710 void NativeWidgetWin::SetSize(const gfx::Size& size) { |
| 805 SetWindowPos(NULL, 0, 0, size.width(), size.height(), | 711 SetWindowPos(NULL, 0, 0, size.width(), size.height(), |
| 806 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE); | 712 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE); |
| 807 } | 713 } |
| 808 | 714 |
| 809 void NativeWidgetWin::SetBoundsConstrained(const gfx::Rect& bounds, | |
| 810 Widget* other_widget) { | |
| 811 SetChildBounds(GetNativeView(), GetParent(), | |
| 812 other_widget ? other_widget->GetNativeView() : NULL, | |
| 813 bounds, kMonitorEdgePadding, 0); | |
| 814 } | |
| 815 | |
| 816 void NativeWidgetWin::MoveAbove(gfx::NativeView native_view) { | 715 void NativeWidgetWin::MoveAbove(gfx::NativeView native_view) { |
| 817 SetWindowPos(native_view, 0, 0, 0, 0, | 716 SetWindowPos(native_view, 0, 0, 0, 0, |
| 818 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE); | 717 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE); |
| 819 } | 718 } |
| 820 | 719 |
| 821 void NativeWidgetWin::MoveToTop() { | 720 void NativeWidgetWin::MoveToTop() { |
| 822 NOTIMPLEMENTED(); | 721 NOTIMPLEMENTED(); |
| 823 } | 722 } |
| 824 | 723 |
| 825 void NativeWidgetWin::SetShape(gfx::NativeRegion region) { | 724 void NativeWidgetWin::SetShape(gfx::NativeRegion region) { |
| (...skipping 1798 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2624 return (GetKeyState(VK_LBUTTON) & 0x80) || | 2523 return (GetKeyState(VK_LBUTTON) & 0x80) || |
| 2625 (GetKeyState(VK_RBUTTON) & 0x80) || | 2524 (GetKeyState(VK_RBUTTON) & 0x80) || |
| 2626 (GetKeyState(VK_MBUTTON) & 0x80) || | 2525 (GetKeyState(VK_MBUTTON) & 0x80) || |
| 2627 (GetKeyState(VK_XBUTTON1) & 0x80) || | 2526 (GetKeyState(VK_XBUTTON1) & 0x80) || |
| 2628 (GetKeyState(VK_XBUTTON2) & 0x80); | 2527 (GetKeyState(VK_XBUTTON2) & 0x80); |
| 2629 } | 2528 } |
| 2630 | 2529 |
| 2631 } // namespace internal | 2530 } // namespace internal |
| 2632 | 2531 |
| 2633 } // namespace views | 2532 } // namespace views |
| OLD | NEW |