diff options
author | cpu@chromium.org <cpu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-11-09 05:26:48 +0000 |
---|---|---|
committer | cpu@chromium.org <cpu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-11-09 05:26:48 +0000 |
commit | 9c9c0311de14421b09efcef7f2c920135583534f (patch) | |
tree | aec20b8b410a5f65851f88e3cdf97aed3dfac1b0 /win8 | |
parent | a0fcb684c965ef62d44247683aba922f3f29caaa (diff) | |
download | chromium_src-9c9c0311de14421b09efcef7f2c920135583534f.zip chromium_src-9c9c0311de14421b09efcef7f2c920135583534f.tar.gz chromium_src-9c9c0311de14421b09efcef7f2c920135583534f.tar.bz2 |
Exit metro mode without leaving a ghost
This basically brings the code we have for m28 chrome that
uses alt-f4 trick to kill the metro viewer without leaving
the strange thumbnail window in the desktop left corner.
BUG=315919
TEST=see bug
Review URL: https://codereview.chromium.org/67633002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@234113 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'win8')
-rw-r--r-- | win8/metro_driver/chrome_app_view_ash.cc | 87 | ||||
-rw-r--r-- | win8/metro_driver/chrome_app_view_ash.h | 2 |
2 files changed, 84 insertions, 5 deletions
diff --git a/win8/metro_driver/chrome_app_view_ash.cc b/win8/metro_driver/chrome_app_view_ash.cc index 6152d22..654e82d 100644 --- a/win8/metro_driver/chrome_app_view_ash.cc +++ b/win8/metro_driver/chrome_app_view_ash.cc @@ -68,9 +68,76 @@ struct Globals { namespace { -// TODO(robertshield): Share this with chrome_app_view.cc -void MetroExit() { - globals.app_exit->Exit(); +enum KeyModifier { + NONE, + SHIFT = 1, + CONTROL = 2, + ALT = 4 +}; + +// Helper function to send keystrokes via the SendInput function. +// mnemonic_char: The keystroke to be sent. +// modifiers: Combination with Alt, Ctrl, Shift, etc. +void SendMnemonic( + WORD mnemonic_char, KeyModifier modifiers) { + 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); + 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); + } +} + +// Helper function to Exit metro chrome cleanly. If we are in the foreground +// then we try and exit by sending an Alt+F4 key combination to the core +// window which ensures that the chrome application tile does not show up in +// the running metro apps list on the top left corner. +void MetroExit(HWND core_window) { + if ((core_window != NULL) && (core_window == ::GetForegroundWindow())) { + DVLOG(1) << "We are in the foreground. Exiting via Alt F4"; + SendMnemonic(VK_F4, ALT); + } else { + globals.app_exit->Exit(); + } } class ChromeChannelListener : public IPC::Listener { @@ -99,8 +166,13 @@ class ChromeChannelListener : public IPC::Listener { } virtual void OnChannelError() OVERRIDE { - DVLOG(1) << "Channel error"; - MetroExit(); + DVLOG(1) << "Channel error. Exiting."; + MetroExit(app_view_->core_window_hwnd()); + // In early Windows 8 versions the code above sometimes fails so we call + // it a second time with a NULL window which just calls Exit(). + ui_proxy_->PostDelayedTask(FROM_HERE, + base::Bind(&MetroExit, HWND(NULL)), + base::TimeDelta::FromMilliseconds(100)); } private: @@ -561,6 +633,11 @@ HRESULT ChromeAppViewAsh::Unsnap() { void ChromeAppViewAsh::OnActivateDesktop(const base::FilePath& file_path) { DLOG(INFO) << "ChannelAppViewAsh::OnActivateDesktop\n"; + + // As we are the top level window, the exiting is done async so we manage + // to execute the entire function including the final Send(). + MetroExit(core_window_hwnd()); + // We are just executing delegate_execute here without parameters. Assumption // here is that this process will be reused by shell when asking for // IExecuteCommand interface. diff --git a/win8/metro_driver/chrome_app_view_ash.h b/win8/metro_driver/chrome_app_view_ash.h index b301b3a..a393365 100644 --- a/win8/metro_driver/chrome_app_view_ash.h +++ b/win8/metro_driver/chrome_app_view_ash.h @@ -82,6 +82,8 @@ class ChromeAppViewAsh void OnFolderPickerCompleted(FolderPickerSession* folder_picker, bool success); + HWND core_window_hwnd() const { return core_window_hwnd_; } + private: HRESULT OnActivate(winapp::Core::ICoreApplicationView* view, winapp::Activation::IActivatedEventArgs* args); |