summaryrefslogtreecommitdiffstats
path: root/app/win
diff options
context:
space:
mode:
authorbrettw@google.com <brettw@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-12-30 22:13:32 +0000
committerbrettw@google.com <brettw@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-12-30 22:13:32 +0000
commitb99603ceb9cbec4a3b1ca9ac535f6b1cbc951bb8 (patch)
tree2f9074d5ad8acf95156fc9c390646eca935d232e /app/win
parent004f2cf5d5eb19764260b1f513738be15ae77d47 (diff)
downloadchromium_src-b99603ceb9cbec4a3b1ca9ac535f6b1cbc951bb8.zip
chromium_src-b99603ceb9cbec4a3b1ca9ac535f6b1cbc951bb8.tar.gz
chromium_src-b99603ceb9cbec4a3b1ca9ac535f6b1cbc951bb8.tar.bz2
Move some functions out of win_util and into hwnd_util, and into a new win/shell file.
This also moves two functions that were only called once from win_util and inwo window_win and download_util, respectively. TEST=it compiles BUG=none Review URL: http://codereview.chromium.org/6035011 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@70321 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'app/win')
-rw-r--r--app/win/hwnd_util.cc124
-rw-r--r--app/win/hwnd_util.h20
-rw-r--r--app/win/shell.cc112
-rw-r--r--app/win/shell.h41
4 files changed, 297 insertions, 0 deletions
diff --git a/app/win/hwnd_util.cc b/app/win/hwnd_util.cc
index b0be404..30b7395 100644
--- a/app/win/hwnd_util.cc
+++ b/app/win/hwnd_util.cc
@@ -4,11 +4,49 @@
#include "app/win/hwnd_util.h"
+#include <dwmapi.h>
+
#include "base/string_util.h"
+#include "base/win/windows_version.h"
+#include "gfx/rect.h"
+#include "gfx/size.h"
+
+#pragma comment(lib, "dwmapi.lib")
namespace app {
namespace win {
+namespace {
+
+// Adjust the window to fit, returning true if the window was resized or moved.
+bool AdjustWindowToFit(HWND hwnd, const RECT& bounds) {
+ // Get the monitor.
+ HMONITOR hmon = MonitorFromRect(&bounds, MONITOR_DEFAULTTONEAREST);
+ if (!hmon) {
+ NOTREACHED() << "Unable to find default monitor";
+ // No monitor available.
+ return false;
+ }
+
+ MONITORINFO mi;
+ mi.cbSize = sizeof(mi);
+ GetMonitorInfo(hmon, &mi);
+ gfx::Rect window_rect(bounds);
+ gfx::Rect monitor_rect(mi.rcWork);
+ gfx::Rect new_window_rect = window_rect.AdjustToFit(monitor_rect);
+ if (!new_window_rect.Equals(window_rect)) {
+ // Window doesn't fit on monitor, move and possibly resize.
+ SetWindowPos(hwnd, 0, new_window_rect.x(), new_window_rect.y(),
+ new_window_rect.width(), new_window_rect.height(),
+ SWP_NOACTIVATE | SWP_NOZORDER);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+} // namespace
+
string16 GetClassName(HWND window) {
// GetClassNameW will return a truncated result (properly null terminated) if
// the given buffer is not large enough. So, it is not possible to determine
@@ -55,5 +93,91 @@ void* GetWindowUserData(HWND hwnd) {
#pragma warning(pop)
+bool DoesWindowBelongToActiveWindow(HWND window) {
+ DCHECK(window);
+ HWND top_window = ::GetAncestor(window, GA_ROOT);
+ if (!top_window)
+ return false;
+
+ HWND active_top_window = ::GetAncestor(::GetForegroundWindow(), GA_ROOT);
+ return (top_window == active_top_window);
+}
+
+void CenterAndSizeWindow(HWND parent,
+ HWND window,
+ const gfx::Size& pref,
+ bool pref_is_client) {
+ DCHECK(window && pref.width() > 0 && pref.height() > 0);
+
+ // Calculate the ideal bounds.
+ RECT window_bounds;
+ RECT center_bounds = {0};
+ if (parent) {
+ // If there is a parent, center over the parents bounds.
+ ::GetWindowRect(parent, &center_bounds);
+ } else {
+ // No parent. Center over the monitor the window is on.
+ HMONITOR monitor = MonitorFromWindow(window, MONITOR_DEFAULTTONEAREST);
+ if (monitor) {
+ MONITORINFO mi = {0};
+ mi.cbSize = sizeof(mi);
+ GetMonitorInfo(monitor, &mi);
+ center_bounds = mi.rcWork;
+ } else {
+ NOTREACHED() << "Unable to get default monitor";
+ }
+ }
+ window_bounds.left = center_bounds.left +
+ (center_bounds.right - center_bounds.left - pref.width()) / 2;
+ window_bounds.right = window_bounds.left + pref.width();
+ window_bounds.top = center_bounds.top +
+ (center_bounds.bottom - center_bounds.top - pref.height()) / 2;
+ window_bounds.bottom = window_bounds.top + pref.height();
+
+ // If we're centering a child window, we are positioning in client
+ // coordinates, and as such we need to offset the target rectangle by the
+ // position of the parent window.
+ if (::GetWindowLong(window, GWL_STYLE) & WS_CHILD) {
+ DCHECK(parent && ::GetParent(window) == parent);
+ POINT topleft = { window_bounds.left, window_bounds.top };
+ ::MapWindowPoints(HWND_DESKTOP, parent, &topleft, 1);
+ window_bounds.left = topleft.x;
+ window_bounds.top = topleft.y;
+ window_bounds.right = window_bounds.left + pref.width();
+ window_bounds.bottom = window_bounds.top + pref.height();
+ }
+
+ // Get the WINDOWINFO for window. We need the style to calculate the size
+ // for the window.
+ WINDOWINFO win_info = {0};
+ win_info.cbSize = sizeof(WINDOWINFO);
+ GetWindowInfo(window, &win_info);
+
+ // Calculate the window size needed for the content size.
+
+ if (!pref_is_client ||
+ AdjustWindowRectEx(&window_bounds, win_info.dwStyle, FALSE,
+ win_info.dwExStyle)) {
+ if (!AdjustWindowToFit(window, window_bounds)) {
+ // The window fits, reset the bounds.
+ SetWindowPos(window, 0, window_bounds.left, window_bounds.top,
+ window_bounds.right - window_bounds.left,
+ window_bounds.bottom - window_bounds.top,
+ SWP_NOACTIVATE | SWP_NOZORDER);
+ } // else case, AdjustWindowToFit set the bounds for us.
+ } else {
+ NOTREACHED() << "Unable to adjust window to fit";
+ }
+}
+
+bool ShouldUseVistaFrame() {
+ if (base::win::GetVersion() < base::win::VERSION_VISTA)
+ return false;
+ // If composition is not enabled, we behave like on XP.
+ BOOL f;
+ DwmIsCompositionEnabled(&f);
+ return !!f;
+}
+
} // namespace win
} // namespace app
diff --git a/app/win/hwnd_util.h b/app/win/hwnd_util.h
index f8ae37e..bace47e 100644
--- a/app/win/hwnd_util.h
+++ b/app/win/hwnd_util.h
@@ -10,6 +10,10 @@
#include "base/string16.h"
+namespace gfx {
+class Size;
+}
+
namespace app {
namespace win {
@@ -25,6 +29,22 @@ WNDPROC SetWindowProc(HWND hwnd, WNDPROC wndproc);
void* SetWindowUserData(HWND hwnd, void* user_data);
void* GetWindowUserData(HWND hwnd);
+// Returns true if the specified window is the current active top window or one
+// of its children.
+bool DoesWindowBelongToActiveWindow(HWND window);
+
+// Sizes the window to have a client or window size (depending on the value of
+// |pref_is_client|) of pref, then centers the window over parent, ensuring the
+// window fits on screen.
+void CenterAndSizeWindow(HWND parent,
+ HWND window,
+ const gfx::Size& pref,
+ bool pref_is_client);
+
+// Returns true if we are on Windows Vista or greater and composition is
+// enabled.
+bool ShouldUseVistaFrame();
+
} // namespace win
} // namespace app
diff --git a/app/win/shell.cc b/app/win/shell.cc
new file mode 100644
index 0000000..a3c7331
--- /dev/null
+++ b/app/win/shell.cc
@@ -0,0 +1,112 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "app/win/shell.h"
+
+#include <shellapi.h>
+#include <shlobj.h>
+
+#include "base/file_path.h"
+#include "base/native_library.h"
+#include "base/string_util.h"
+#include "base/win/scoped_comptr.h"
+#include "base/win/windows_version.h"
+#include "base/win_util.h"
+
+namespace app {
+namespace win {
+
+namespace {
+
+const wchar_t kShell32[] = L"shell32.dll";
+const char kSHGetPropertyStoreForWindow[] = "SHGetPropertyStoreForWindow";
+
+// Define the type of SHGetPropertyStoreForWindow is SHGPSFW.
+typedef DECLSPEC_IMPORT HRESULT (STDAPICALLTYPE *SHGPSFW)(HWND hwnd,
+ REFIID riid,
+ void** ppv);
+
+} // namespace
+
+// Open an item via a shell execute command. Error code checking and casting
+// explanation: http://msdn2.microsoft.com/en-us/library/ms647732.aspx
+bool OpenItemViaShell(const FilePath& full_path) {
+ HINSTANCE h = ::ShellExecuteW(
+ NULL, NULL, full_path.value().c_str(), NULL,
+ full_path.DirName().value().c_str(), SW_SHOWNORMAL);
+
+ LONG_PTR error = reinterpret_cast<LONG_PTR>(h);
+ if (error > 32)
+ return true;
+
+ if ((error == SE_ERR_NOASSOC))
+ return OpenItemWithExternalApp(full_path.value());
+
+ return false;
+}
+
+bool OpenItemViaShellNoZoneCheck(const FilePath& full_path) {
+ SHELLEXECUTEINFO sei = { sizeof(sei) };
+ sei.fMask = SEE_MASK_NOZONECHECKS | SEE_MASK_FLAG_DDEWAIT;
+ sei.nShow = SW_SHOWNORMAL;
+ sei.lpVerb = NULL;
+ sei.lpFile = full_path.value().c_str();
+ if (::ShellExecuteExW(&sei))
+ return true;
+ LONG_PTR error = reinterpret_cast<LONG_PTR>(sei.hInstApp);
+ if ((error == SE_ERR_NOASSOC))
+ return OpenItemWithExternalApp(full_path.value());
+ return false;
+}
+
+// Show the Windows "Open With" dialog box to ask the user to pick an app to
+// open the file with.
+bool OpenItemWithExternalApp(const string16& full_path) {
+ SHELLEXECUTEINFO sei = { sizeof(sei) };
+ sei.fMask = SEE_MASK_FLAG_DDEWAIT;
+ sei.nShow = SW_SHOWNORMAL;
+ sei.lpVerb = L"openas";
+ sei.lpFile = full_path.c_str();
+ return (TRUE == ::ShellExecuteExW(&sei));
+}
+
+void SetAppIdForWindow(const string16& app_id, HWND hwnd) {
+ // This functionality is only available on Win7+.
+ if (base::win::GetVersion() < base::win::VERSION_WIN7)
+ return;
+
+ // Load Shell32.dll into memory.
+ // TODO(brg): Remove this mechanism when the Win7 SDK is available in trunk.
+ std::wstring shell32_filename(kShell32);
+ FilePath shell32_filepath(shell32_filename);
+ base::NativeLibrary shell32_library = base::LoadNativeLibrary(
+ shell32_filepath);
+
+ if (!shell32_library)
+ return;
+
+ // Get the function pointer for SHGetPropertyStoreForWindow.
+ void* function = base::GetFunctionPointerFromNativeLibrary(
+ shell32_library,
+ kSHGetPropertyStoreForWindow);
+
+ if (!function) {
+ base::UnloadNativeLibrary(shell32_library);
+ return;
+ }
+
+ // Set the application's name.
+ base::win::ScopedComPtr<IPropertyStore> pps;
+ SHGPSFW SHGetPropertyStoreForWindow = static_cast<SHGPSFW>(function);
+ HRESULT result = SHGetPropertyStoreForWindow(
+ hwnd, __uuidof(*pps), reinterpret_cast<void**>(pps.Receive()));
+ if (S_OK == result)
+ win_util::SetAppIdForPropertyStore(pps, app_id.c_str());
+
+ // Cleanup.
+ base::UnloadNativeLibrary(shell32_library);
+}
+
+} // namespace win
+} // namespace app
diff --git a/app/win/shell.h b/app/win/shell.h
new file mode 100644
index 0000000..44ee3ba7
--- /dev/null
+++ b/app/win/shell.h
@@ -0,0 +1,41 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef APP_WIN_SHELL_H_
+#define APP_WIN_SHELL_H_
+
+#include <windows.h>
+
+#include "base/string16.h"
+
+class FilePath;
+
+namespace app {
+namespace win {
+
+// Open or run a file via the Windows shell. In the event that there is no
+// default application registered for the file specified by 'full_path',
+// ask the user, via the Windows "Open With" dialog.
+// Returns 'true' on successful open, 'false' otherwise.
+bool OpenItemViaShell(const FilePath& full_path);
+
+// The download manager now writes the alternate data stream with the
+// zone on all downloads. This function is equivalent to OpenItemViaShell
+// without showing the zone warning dialog.
+bool OpenItemViaShellNoZoneCheck(const FilePath& full_path);
+
+// Ask the user, via the Windows "Open With" dialog, for an application to use
+// to open the file specified by 'full_path'.
+// Returns 'true' on successful open, 'false' otherwise.
+bool OpenItemWithExternalApp(const string16& full_path);
+
+// Sets the application id given as the Application Model ID for the window
+// specified. This method is used to insure that different web applications
+// do not group together on the Win7 task bar.
+void SetAppIdForWindow(const string16& app_id, HWND hwnd);
+
+} // namespace win
+} // namespace app
+
+#endif // APP_WIN_SHELL_H_