OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "ui/base/win/shell.h" | |
6 | |
7 #include <dwmapi.h> | |
8 #include <shlobj.h> // Must be before propkey. | |
9 #include <propkey.h> | |
10 #include <shellapi.h> | |
11 | |
12 #include "base/command_line.h" | |
13 #include "base/files/file_path.h" | |
14 #include "base/native_library.h" | |
15 #include "base/strings/string_util.h" | |
16 #include "base/win/metro.h" | |
17 #include "base/win/scoped_comptr.h" | |
18 #include "base/win/win_util.h" | |
19 #include "base/win/windows_version.h" | |
20 #include "ui/base/ui_base_switches.h" | |
21 | |
22 namespace ui { | |
23 namespace win { | |
24 | |
25 namespace { | |
26 | |
27 // Show the Windows "Open With" dialog box to ask the user to pick an app to | |
28 // open the file with. | |
29 bool OpenItemWithExternalApp(const base::string16& full_path) { | |
30 SHELLEXECUTEINFO sei = { sizeof(sei) }; | |
31 sei.fMask = SEE_MASK_FLAG_DDEWAIT; | |
32 sei.nShow = SW_SHOWNORMAL; | |
33 sei.lpVerb = L"openas"; | |
34 sei.lpFile = full_path.c_str(); | |
35 return (TRUE == ::ShellExecuteExW(&sei)); | |
36 } | |
37 | |
38 } // namespace | |
39 | |
40 bool OpenAnyViaShell(const base::string16& full_path, | |
41 const base::string16& directory, | |
42 const base::string16& args, | |
43 DWORD mask) { | |
44 SHELLEXECUTEINFO sei = { sizeof(sei) }; | |
45 sei.fMask = mask; | |
46 sei.nShow = SW_SHOWNORMAL; | |
47 sei.lpFile = full_path.c_str(); | |
48 sei.lpDirectory = directory.c_str(); | |
49 if (!args.empty()) | |
50 sei.lpParameters = args.c_str(); | |
51 | |
52 if (::ShellExecuteExW(&sei)) | |
53 return true; | |
54 if (::GetLastError() == ERROR_NO_ASSOCIATION) | |
55 return OpenItemWithExternalApp(full_path); | |
56 return false; | |
57 } | |
58 | |
59 bool OpenItemViaShell(const base::FilePath& full_path) { | |
60 return OpenAnyViaShell(full_path.value(), full_path.DirName().value(), | |
61 base::string16(), 0); | |
62 } | |
63 | |
64 bool PreventWindowFromPinning(HWND hwnd) { | |
65 // This functionality is only available on Win7+. It also doesn't make sense | |
66 // to do this for Chrome Metro. | |
67 if (base::win::GetVersion() < base::win::VERSION_WIN7 || | |
68 base::win::IsMetroProcess()) | |
69 return false; | |
70 base::win::ScopedComPtr<IPropertyStore> pps; | |
71 HRESULT result = SHGetPropertyStoreForWindow( | |
72 hwnd, __uuidof(*pps), reinterpret_cast<void**>(pps.Receive())); | |
73 if (FAILED(result)) | |
74 return false; | |
75 | |
76 return base::win::SetBooleanValueForPropertyStore( | |
77 pps.get(), PKEY_AppUserModel_PreventPinning, true); | |
78 } | |
79 | |
80 // TODO(calamity): investigate moving this out of the UI thread as COM | |
81 // operations may spawn nested message loops which can cause issues. | |
82 void SetAppDetailsForWindow(const base::string16& app_id, | |
83 const base::string16& app_icon, | |
84 const base::string16& relaunch_command, | |
85 const base::string16& relaunch_display_name, | |
86 HWND hwnd) { | |
87 // This functionality is only available on Win7+. It also doesn't make sense | |
88 // to do this for Chrome Metro. | |
89 if (base::win::GetVersion() < base::win::VERSION_WIN7 || | |
90 base::win::IsMetroProcess()) | |
91 return; | |
92 base::win::ScopedComPtr<IPropertyStore> pps; | |
93 HRESULT result = SHGetPropertyStoreForWindow( | |
94 hwnd, __uuidof(*pps), reinterpret_cast<void**>(pps.Receive())); | |
95 if (S_OK == result) { | |
96 if (!app_id.empty()) | |
97 base::win::SetAppIdForPropertyStore(pps.get(), app_id.c_str()); | |
98 if (!app_icon.empty()) { | |
99 base::win::SetStringValueForPropertyStore( | |
100 pps.get(), PKEY_AppUserModel_RelaunchIconResource, app_icon.c_str()); | |
101 } | |
102 if (!relaunch_command.empty()) { | |
103 base::win::SetStringValueForPropertyStore( | |
104 pps.get(), PKEY_AppUserModel_RelaunchCommand, relaunch_command.c_str()
); | |
105 } | |
106 if (!relaunch_display_name.empty()) { | |
107 base::win::SetStringValueForPropertyStore( | |
108 pps.get(), PKEY_AppUserModel_RelaunchDisplayNameResource, | |
109 relaunch_display_name.c_str()); | |
110 } | |
111 } | |
112 } | |
113 | |
114 void SetAppIdForWindow(const base::string16& app_id, HWND hwnd) { | |
115 SetAppDetailsForWindow(app_id, | |
116 base::string16(), | |
117 base::string16(), | |
118 base::string16(), | |
119 hwnd); | |
120 } | |
121 | |
122 void SetAppIconForWindow(const base::string16& app_icon, HWND hwnd) { | |
123 SetAppDetailsForWindow(base::string16(), | |
124 app_icon, | |
125 base::string16(), | |
126 base::string16(), | |
127 hwnd); | |
128 } | |
129 | |
130 void SetRelaunchDetailsForWindow(const base::string16& relaunch_command, | |
131 const base::string16& display_name, | |
132 HWND hwnd) { | |
133 SetAppDetailsForWindow(base::string16(), | |
134 base::string16(), | |
135 relaunch_command, | |
136 display_name, | |
137 hwnd); | |
138 } | |
139 | |
140 bool IsAeroGlassEnabled() { | |
141 // For testing in Win8 (where it is not possible to disable composition) the | |
142 // user can specify this command line switch to mimic the behavior. In this | |
143 // mode, cross-HWND transparency is not supported and various types of | |
144 // widgets fallback to more simplified rendering behavior. | |
145 if (CommandLine::ForCurrentProcess()->HasSwitch( | |
146 switches::kDisableDwmComposition)) | |
147 return false; | |
148 | |
149 if (base::win::GetVersion() < base::win::VERSION_VISTA) | |
150 return false; | |
151 // If composition is not enabled, we behave like on XP. | |
152 BOOL enabled = FALSE; | |
153 return SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled; | |
154 } | |
155 | |
156 } // namespace win | |
157 } // namespace ui | |
OLD | NEW |