diff options
author | robertshield@chromium.org <robertshield@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-09-08 17:50:30 +0000 |
---|---|---|
committer | robertshield@chromium.org <robertshield@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-09-08 17:50:30 +0000 |
commit | d652bfa5646f4abd22b470a88478769c222c2177 (patch) | |
tree | 44f25d8b94f5c939df5ee12201ef6367b508ce25 /win8/metro_driver | |
parent | a9e5f04481565af0a3c8dbe770b14899f24b68f7 (diff) | |
download | chromium_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.cc | 135 | ||||
-rw-r--r-- | win8/metro_driver/chrome_url_launch_handler.cc | 26 | ||||
-rw-r--r-- | win8/metro_driver/metro_driver.gyp | 1 | ||||
-rw-r--r-- | win8/metro_driver/secondary_tile.cc | 7 |
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( |