15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/gfx/win/hwnd_util.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/i18n/rtl.h" 87d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/string_util.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/metro.h" 103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/win/win_util.h" 11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/gfx/point.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/rect.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/size.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)namespace gfx { 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Adjust the window to fit. 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AdjustWindowToFit(HWND hwnd, const RECT& bounds, bool fit_to_monitor) { 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (fit_to_monitor) { 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the monitor. 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HMONITOR hmon = MonitorFromRect(&bounds, MONITOR_DEFAULTTONEAREST); 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (hmon) { 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MONITORINFO mi; 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mi.cbSize = sizeof(mi); 275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GetMonitorInfo(hmon, &mi); 28d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) Rect window_rect(bounds); 29d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) Rect monitor_rect(mi.rcWork); 30d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) Rect new_window_rect = window_rect; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_window_rect.AdjustToFit(monitor_rect); 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (new_window_rect != window_rect) { 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Window doesn't fit on monitor, move and possibly resize. 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetWindowPos(hwnd, 0, new_window_rect.x(), new_window_rect.y(), 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_window_rect.width(), new_window_rect.height(), 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SWP_NOACTIVATE | SWP_NOZORDER); 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Else fall through. 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Unable to find default monitor"; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Fall through. 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } // Else fall through. 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The window is not being fit to monitor, or the window fits on the monitor 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // as is, or we have no monitor info; reset the bounds. 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::SetWindowPos(hwnd, 0, bounds.left, bounds.top, 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bounds.right - bounds.left, bounds.bottom - bounds.top, 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SWP_NOACTIVATE | SWP_NOZORDER); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 530f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// Turn off optimizations for these functions so they show up in crash reports. 540f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)MSVC_DISABLE_OPTIMIZE(); 550f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 560f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void CrashOutOfMemory() { 57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PLOG(FATAL); 580f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 590f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 600f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void CrashAccessDenied() { 61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PLOG(FATAL); 620f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 630f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 640f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// Crash isn't one of the ones we commonly see. 650f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void CrashOther() { 66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PLOG(FATAL); 670f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 680f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 690f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)MSVC_ENABLE_OPTIMIZE(); 700f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::string16 GetClassName(HWND window) { 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // GetClassNameW will return a truncated result (properly null terminated) if 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the given buffer is not large enough. So, it is not possible to determine 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that we got the entire class name if the result is exactly equal to the 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // size of the buffer minus one. 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD buffer_size = MAX_PATH; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (true) { 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::wstring output; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD size_ret = 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetClassNameW(window, WriteInto(&output, buffer_size), buffer_size); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (size_ret == 0) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (size_ret < (buffer_size - 1)) { 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output.resize(size_ret); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return output; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer_size *= 2; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return std::wstring(); // error 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma warning(push) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma warning(disable:4312 4244) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WNDPROC SetWindowProc(HWND hwnd, WNDPROC proc) { 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The reason we don't return the SetwindowLongPtr() value is that it returns 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the orignal window procedure and not the current one. I don't know if it is 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a bug or an intended feature. 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WNDPROC oldwindow_proc = 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<WNDPROC>(GetWindowLongPtr(hwnd, GWLP_WNDPROC)); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetWindowLongPtr(hwnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(proc)); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return oldwindow_proc; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* SetWindowUserData(HWND hwnd, void* user_data) { 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<void*>(SetWindowLongPtr(hwnd, GWLP_USERDATA, 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<LONG_PTR>(user_data))); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* GetWindowUserData(HWND hwnd) { 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD process_id = 0; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD thread_id = GetWindowThreadProcessId(hwnd, &process_id); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // A window outside the current process needs to be ignored. 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (process_id != ::GetCurrentProcessId()) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return reinterpret_cast<void*>(GetWindowLongPtr(hwnd, GWLP_USERDATA)); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma warning(pop) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DoesWindowBelongToActiveWindow(HWND window) { 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(window); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HWND top_window = ::GetAncestor(window, GA_ROOT); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!top_window) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HWND active_top_window = ::GetAncestor(::GetForegroundWindow(), GA_ROOT); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (top_window == active_top_window); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CenterAndSizeWindow(HWND parent, 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HWND window, 136d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const Size& pref) { 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(window && pref.width() > 0 && pref.height() > 0); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Calculate the ideal bounds. 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RECT window_bounds; 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RECT center_bounds = {0}; 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (parent) { 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If there is a parent, center over the parents bounds. 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::GetWindowRect(parent, ¢er_bounds); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (::IsRectEmpty(¢er_bounds)) { 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No parent or no parent rect. Center over the monitor the window is on. 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HMONITOR monitor = MonitorFromWindow(window, MONITOR_DEFAULTTONEAREST); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (monitor) { 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MONITORINFO mi = {0}; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mi.cbSize = sizeof(mi); 1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GetMonitorInfo(monitor, &mi); 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) center_bounds = mi.rcWork; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Unable to get default monitor"; 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window_bounds.left = center_bounds.left; 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pref.width() < (center_bounds.right - center_bounds.left)) { 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window_bounds.left += 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (center_bounds.right - center_bounds.left - pref.width()) / 2; 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window_bounds.right = window_bounds.left + pref.width(); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window_bounds.top = center_bounds.top; 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pref.height() < (center_bounds.bottom - center_bounds.top)) { 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window_bounds.top += 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (center_bounds.bottom - center_bounds.top - pref.height()) / 2; 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window_bounds.bottom = window_bounds.top + pref.height(); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we're centering a child window, we are positioning in client 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // coordinates, and as such we need to offset the target rectangle by the 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // position of the parent window. 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (::GetWindowLong(window, GWL_STYLE) & WS_CHILD) { 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(parent && ::GetParent(window) == parent); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) POINT topleft = { window_bounds.left, window_bounds.top }; 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::MapWindowPoints(HWND_DESKTOP, parent, &topleft, 1); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window_bounds.left = topleft.x; 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window_bounds.top = topleft.y; 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window_bounds.right = window_bounds.left + pref.width(); 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window_bounds.bottom = window_bounds.top + pref.height(); 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AdjustWindowToFit(window, window_bounds, !parent); 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CheckWindowCreated(HWND hwnd) { 1910f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (!hwnd) { 1920f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) switch (GetLastError()) { 1930f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) case ERROR_NOT_ENOUGH_MEMORY: 1940f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) CrashOutOfMemory(); 1950f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) break; 1960f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) case ERROR_ACCESS_DENIED: 1970f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) CrashAccessDenied(); 1980f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) break; 1990f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) default: 2000f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) CrashOther(); 2010f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) break; 2020f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 203cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PLOG(FATAL); 2040f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ShowSystemMenu(HWND window) { 208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) RECT rect; 209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) GetWindowRect(window, &rect); 210effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch Point point = Point(base::i18n::IsRTL() ? rect.right : rect.left, rect.top); 211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) static const int kSystemMenuOffset = 10; 212effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch point.Offset(base::i18n::IsRTL() ? -kSystemMenuOffset : kSystemMenuOffset, 213effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch kSystemMenuOffset); 214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ShowSystemMenuAtPoint(window, point); 215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 217d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void ShowSystemMenuAtPoint(HWND window, const Point& point) { 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In the Metro process, we never want to show the system menu. 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (base::win::IsMetroProcess()) 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UINT flags = TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_RETURNCMD; 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (base::i18n::IsRTL()) 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) flags |= TPM_RIGHTALIGN; 224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) HMENU menu = GetSystemMenu(window, FALSE); 225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const int command = 226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) TrackPopupMenu(menu, flags, point.x(), point.y(), 0, window, NULL); 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (command) 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SendMessage(window, WM_SYSCOMMAND, command, 0); 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" { 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef HWND (*RootWindow)(); 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HWND GetWindowToParentTo(bool get_real_hwnd) { 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HMODULE metro = base::win::GetMetroModule(); 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!metro) 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return get_real_hwnd ? ::GetDesktopWindow() : HWND_DESKTOP; 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In windows 8 metro-mode the root window is not the desktop. 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RootWindow root_window = 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<RootWindow>(::GetProcAddress(metro, "GetRootWindow")); 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return root_window(); 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} // namespace gfx 246