summaryrefslogtreecommitdiffstats
path: root/win8/metro_driver
diff options
context:
space:
mode:
authorrobertshield@chromium.org <robertshield@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-09-08 17:50:30 +0000
committerrobertshield@chromium.org <robertshield@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-09-08 17:50:30 +0000
commitd652bfa5646f4abd22b470a88478769c222c2177 (patch)
tree44f25d8b94f5c939df5ee12201ef6367b508ce25 /win8/metro_driver
parenta9e5f04481565af0a3c8dbe770b14899f24b68f7 (diff)
downloadchromium_src-d652bfa5646f4abd22b470a88478769c222c2177.zip
chromium_src-d652bfa5646f4abd22b470a88478769c222c2177.tar.gz
chromium_src-d652bfa5646f4abd22b470a88478769c222c2177.tar.bz2
Manually merging remaining Win8 changes.
BUG=127799 TEST=NONE Review URL: https://chromiumcodereview.appspot.com/10914160 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@155592 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'win8/metro_driver')
-rw-r--r--win8/metro_driver/chrome_app_view.cc135
-rw-r--r--win8/metro_driver/chrome_url_launch_handler.cc26
-rw-r--r--win8/metro_driver/metro_driver.gyp1
-rw-r--r--win8/metro_driver/secondary_tile.cc7
4 files changed, 150 insertions, 19 deletions
diff --git a/win8/metro_driver/chrome_app_view.cc b/win8/metro_driver/chrome_app_view.cc
index 7d5580e..e2ec21a 100644
--- a/win8/metro_driver/chrome_app_view.cc
+++ b/win8/metro_driver/chrome_app_view.cc
@@ -56,8 +56,97 @@ const wchar_t kOSKClassName[] = L"IPTip_Main_Window";
static const int kOSKAdjustmentOffset = 20;
+const wchar_t kChromeSubclassWindowProp[] = L"MetroChromeWindowProc";
+
namespace {
+enum Modifier {
+ NONE,
+ SHIFT = 1,
+ CONTROL = 2,
+ ALT = 4
+};
+
+// Helper function to send keystrokes via the SendInput function.
+// Params:
+// mnemonic_char: The keystroke to be sent.
+// modifiers: Combination with Alt, Ctrl, Shift, etc.
+// extended: whether this is an extended key.
+// unicode: whether this is a unicode key.
+void SendMnemonic(WORD mnemonic_char, Modifier modifiers, bool extended,
+ bool unicode) {
+ INPUT keys[4] = {0}; // Keyboard events
+ int key_count = 0; // Number of generated events
+
+ if (modifiers & SHIFT) {
+ keys[key_count].type = INPUT_KEYBOARD;
+ keys[key_count].ki.wVk = VK_SHIFT;
+ keys[key_count].ki.wScan = MapVirtualKey(VK_SHIFT, 0);
+ key_count++;
+ }
+
+ if (modifiers & CONTROL) {
+ keys[key_count].type = INPUT_KEYBOARD;
+ keys[key_count].ki.wVk = VK_CONTROL;
+ keys[key_count].ki.wScan = MapVirtualKey(VK_CONTROL, 0);
+ key_count++;
+ }
+
+ if (modifiers & ALT) {
+ keys[key_count].type = INPUT_KEYBOARD;
+ keys[key_count].ki.wVk = VK_MENU;
+ keys[key_count].ki.wScan = MapVirtualKey(VK_MENU, 0);
+ key_count++;
+ }
+
+ keys[key_count].type = INPUT_KEYBOARD;
+ keys[key_count].ki.wVk = mnemonic_char;
+ keys[key_count].ki.wScan = MapVirtualKey(mnemonic_char, 0);
+
+ if (extended)
+ keys[key_count].ki.dwFlags |= KEYEVENTF_EXTENDEDKEY;
+ if (unicode)
+ keys[key_count].ki.dwFlags |= KEYEVENTF_UNICODE;
+ key_count++;
+
+ bool should_sleep = key_count > 1;
+
+ // Send key downs
+ for (int i = 0; i < key_count; i++) {
+ SendInput(1, &keys[ i ], sizeof(keys[0]));
+ keys[i].ki.dwFlags |= KEYEVENTF_KEYUP;
+ if (should_sleep) {
+ Sleep(10);
+ }
+ }
+
+ // Now send key ups in reverse order
+ for (int i = key_count; i; i--) {
+ SendInput(1, &keys[ i - 1 ], sizeof(keys[0]));
+ if (should_sleep) {
+ Sleep(10);
+ }
+ }
+}
+
+void MetroExit() {
+ if (globals.core_window == ::GetForegroundWindow()) {
+ DVLOG(1) << "We are in the foreground. Exiting via Alt F4";
+ SendMnemonic(VK_F4, ALT, false, false);
+ DWORD core_window_process_id = 0;
+ DWORD core_window_thread_id = GetWindowThreadProcessId(
+ globals.core_window, &core_window_process_id);
+ if (core_window_thread_id != ::GetCurrentThreadId()) {
+ // Sleep to give time to the core window thread to get this message.
+ Sleep(100);
+ }
+ } else {
+ DVLOG(1) << "We are not in the foreground. Exiting normally";
+ globals.app_exit->Exit();
+ globals.core_window = NULL;
+ }
+}
+
void AdjustToFitWindow(HWND hwnd, int flags) {
RECT rect = {0};
::GetWindowRect(globals.core_window, &rect);
@@ -69,6 +158,35 @@ void AdjustToFitWindow(HWND hwnd, int flags) {
SWP_NOZORDER | flags);
}
+LRESULT CALLBACK ChromeWindowProc(HWND window,
+ UINT message,
+ WPARAM wp,
+ LPARAM lp) {
+ if (message == WM_SETCURSOR) {
+ // Override the WM_SETCURSOR message to avoid showing the resize cursor
+ // as the mouse moves to the edge of the screen.
+ switch (LOWORD(lp)) {
+ case HTBOTTOM:
+ case HTBOTTOMLEFT:
+ case HTBOTTOMRIGHT:
+ case HTLEFT:
+ case HTRIGHT:
+ case HTTOP:
+ case HTTOPLEFT:
+ case HTTOPRIGHT:
+ lp = MAKELPARAM(HTCLIENT, HIWORD(lp));
+ break;
+ default:
+ break;
+ }
+ }
+
+ WNDPROC old_proc = reinterpret_cast<WNDPROC>(
+ ::GetProp(window, kChromeSubclassWindowProp));
+ DCHECK(old_proc);
+ return CallWindowProc(old_proc, window, message, wp, lp);
+}
+
void AdjustFrameWindowStyleForMetro(HWND hwnd) {
DVLOG(1) << __FUNCTION__;
// Ajust the frame so the live preview works and the frame buttons dissapear.
@@ -78,6 +196,14 @@ void AdjustFrameWindowStyleForMetro(HWND hwnd) {
::SetWindowLong(hwnd, GWL_EXSTYLE,
::GetWindowLong(hwnd, GWL_EXSTYLE) & ~(WS_EX_DLGMODALFRAME |
WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE));
+
+ // Subclass the wndproc of the frame window, if it's not already there.
+ if (::GetProp(hwnd, kChromeSubclassWindowProp) == NULL) {
+ WNDPROC old_chrome_proc = reinterpret_cast<WNDPROC>(
+ ::SetWindowLong(hwnd, GWL_WNDPROC,
+ reinterpret_cast<long>(ChromeWindowProc)));
+ ::SetProp(hwnd, kChromeSubclassWindowProp, old_chrome_proc);
+ }
AdjustToFitWindow(hwnd, SWP_FRAMECHANGED | SWP_NOACTIVATE);
}
@@ -117,7 +243,7 @@ void CloseFrameWindowInternal(HWND hwnd) {
} else {
// time to quit
DVLOG(1) << "Last host window closed. Calling Exit().";
- globals.app_exit->Exit();
+ MetroExit();
}
}
@@ -486,8 +612,9 @@ DWORD WINAPI HostMainThreadProc(void*) {
::SetWindowLong(globals.core_window, GWL_WNDPROC,
reinterpret_cast<long>(ChromeAppView::CoreWindowProc)));
DWORD exit_code = globals.host_main(globals.host_context);
+
DVLOG(1) << "host thread done, exit_code=" << exit_code;
- globals.app_exit->Exit();
+ MetroExit();
return exit_code;
}
@@ -696,9 +823,11 @@ ChromeAppView::Run() {
if (wr != WAIT_OBJECT_0) {
DVLOG(1) << "Waiting for host thread failed : " << wr;
}
+
+ DVLOG(1) << "Host thread exited";
+
::CloseHandle(globals.host_thread);
globals.host_thread = NULL;
-
return hr;
}
diff --git a/win8/metro_driver/chrome_url_launch_handler.cc b/win8/metro_driver/chrome_url_launch_handler.cc
index 866bccc..7a9a607 100644
--- a/win8/metro_driver/chrome_url_launch_handler.cc
+++ b/win8/metro_driver/chrome_url_launch_handler.cc
@@ -11,7 +11,7 @@
#include <shlobj.h>
#include <string>
-#include "base/string_tokenizer.h"
+#include "base/command_line.h"
#include "winrt_utils.h"
@@ -97,22 +97,18 @@ void ChromeUrlLaunchHandler::HandleProtocolLaunch(
InitiateNavigationOrSearchRequest(globals.navigation_url.c_str(), 0);
}
-// The LaunchArgs are in a semi-color separated key_name=key_value list. At
-// the moment the only key_name understaood is "url".
+// |launch_args| is an encoded command line, minus the executable name. To
+// find the URL to launch the first argument is used. If any other parameters
+// are encoded in |launch_args| they are ignored.
string16 ChromeUrlLaunchHandler::GetUrlFromLaunchArgs(
const string16& launch_args) {
- WStringTokenizer tokenizer(launch_args, L";=");
- bool next_is_url = false;
- while (tokenizer.GetNext()) {
- if (next_is_url)
- return tokenizer.token();
- if (tokenizer.token() == L"url")
- next_is_url = true;
- }
- if (launch_args == L"opennewwindow") {
- DVLOG(1) << "Returning new tab url";
- return L"chrome://newtab";
- }
+ string16 dummy_command_line(L"dummy.exe ");
+ dummy_command_line.append(launch_args);
+ CommandLine command_line = CommandLine::FromString(dummy_command_line);
+ CommandLine::StringVector args = command_line.GetArgs();
+ if (args.size() > 0)
+ return args[0];
+
return string16();
}
diff --git a/win8/metro_driver/metro_driver.gyp b/win8/metro_driver/metro_driver.gyp
index 186d2bd..94960cdf 100644
--- a/win8/metro_driver/metro_driver.gyp
+++ b/win8/metro_driver/metro_driver.gyp
@@ -31,6 +31,7 @@
'type': 'shared_library',
'dependencies': [
'../../base/base.gyp:base',
+ '../../build/temp_gyp/googleurl.gyp:googleurl',
'../../crypto/crypto.gyp:crypto',
'../../sandbox/sandbox.gyp:sandbox',
'../../google_update/google_update.gyp:google_update',
diff --git a/win8/metro_driver/secondary_tile.cc b/win8/metro_driver/secondary_tile.cc
index 8a54bd7..c784fdc 100644
--- a/win8/metro_driver/secondary_tile.cc
+++ b/win8/metro_driver/secondary_tile.cc
@@ -15,6 +15,7 @@
#include "base/string_number_conversions.h"
#include "base/utf_string_conversions.h"
#include "crypto/sha2.h"
+#include "googleurl/src/gurl.h"
#include "win8/metro_driver/chrome_app_view.h"
#include "win8/metro_driver/winrt_utils.h"
@@ -91,7 +92,11 @@ void CreateTileOnStartScreen(const string16& title_str,
mswrw::HString id;
id.Attach(MakeHString(GenerateTileId(url_str)));
mswrw::HString args;
- args.Attach(MakeHString(string16(L"url=").append(url_str)));
+ // The url is just passed into the tile agruments as is. Metro and desktop
+ // chrome will see the arguments as command line parameters.
+ // A GURL is used to ensure any spaces are properly escaped.
+ GURL url(url_str);
+ args.Attach(MakeHString(UTF8ToUTF16(url.spec())));
mswr::ComPtr<winfoundtn::IUriRuntimeClassFactory> uri_factory;
hr = winrt_utils::CreateActivationFactory(