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.
5 #include "win8/metro_driver/stdafx.h"
6 #include "win8/metro_driver/chrome_app_view_ash.h"
8 #include <corewindow.h>
10 #include <windows.foundation.h>
12 #include "base/bind.h"
13 #include "base/command_line.h"
14 #include "base/message_loop/message_loop.h"
15 #include "base/path_service.h"
16 #include "base/threading/thread.h"
17 #include "base/win/metro.h"
18 #include "base/win/win_util.h"
19 #include "chrome/common/chrome_switches.h"
20 #include "ipc/ipc_channel.h"
21 #include "ipc/ipc_channel_proxy.h"
22 #include "ipc/ipc_sender.h"
23 #include "ui/base/gestures/gesture_sequence.h"
24 #include "ui/metro_viewer/metro_viewer_messages.h"
25 #include "win8/metro_driver/file_picker_ash.h"
26 #include "win8/metro_driver/metro_driver.h"
27 #include "win8/metro_driver/winrt_utils.h"
28 #include "win8/viewer/metro_viewer_constants.h"
30 typedef winfoundtn::ITypedEventHandler
<
31 winapp::Core::CoreApplicationView
*,
32 winapp::Activation::IActivatedEventArgs
*> ActivatedHandler
;
34 typedef winfoundtn::ITypedEventHandler
<
35 winui::Core::CoreWindow
*,
36 winui::Core::PointerEventArgs
*> PointerEventHandler
;
38 typedef winfoundtn::ITypedEventHandler
<
39 winui::Core::CoreWindow
*,
40 winui::Core::KeyEventArgs
*> KeyEventHandler
;
42 typedef winfoundtn::ITypedEventHandler
<
43 winui::Core::CoreDispatcher
*,
44 winui::Core::AcceleratorKeyEventArgs
*> AcceleratorKeyEventHandler
;
46 typedef winfoundtn::ITypedEventHandler
<
47 winui::Core::CoreWindow
*,
48 winui::Core::CharacterReceivedEventArgs
*> CharEventHandler
;
50 typedef winfoundtn::ITypedEventHandler
<
51 winui::Core::CoreWindow
*,
52 winui::Core::VisibilityChangedEventArgs
*> VisibilityChangedHandler
;
54 typedef winfoundtn::ITypedEventHandler
<
55 winui::Core::CoreWindow
*,
56 winui::Core::WindowActivatedEventArgs
*> WindowActivatedHandler
;
58 typedef winfoundtn::ITypedEventHandler
<
59 winui::Core::CoreWindow
*,
60 winui::Core::WindowSizeChangedEventArgs
*> SizeChangedHandler
;
62 // This function is exported by chrome.exe.
63 typedef int (__cdecl
*BreakpadExceptionHandler
)(EXCEPTION_POINTERS
* info
);
65 // Global information used across the metro driver.
67 winapp::Activation::ApplicationExecutionState previous_state
;
68 winapp::Core::ICoreApplicationExit
* app_exit
;
69 BreakpadExceptionHandler breakpad_exception_handler
;
74 // TODO(robertshield): Share this with chrome_app_view.cc
76 globals
.app_exit
->Exit();
79 class ChromeChannelListener
: public IPC::Listener
{
81 ChromeChannelListener(base::MessageLoop
* ui_loop
, ChromeAppViewAsh
* app_view
)
82 : ui_proxy_(ui_loop
->message_loop_proxy()), app_view_(app_view
) {}
84 virtual bool OnMessageReceived(const IPC::Message
& message
) OVERRIDE
{
85 IPC_BEGIN_MESSAGE_MAP(ChromeChannelListener
, message
)
86 IPC_MESSAGE_HANDLER(MetroViewerHostMsg_SetCursor
, OnSetCursor
)
87 IPC_MESSAGE_HANDLER(MetroViewerHostMsg_DisplayFileOpen
,
88 OnDisplayFileOpenDialog
)
89 IPC_MESSAGE_HANDLER(MetroViewerHostMsg_DisplayFileSaveAs
,
90 OnDisplayFileSaveAsDialog
)
91 IPC_MESSAGE_HANDLER(MetroViewerHostMsg_DisplaySelectFolder
,
92 OnDisplayFolderPicker
)
93 IPC_MESSAGE_HANDLER(MetroViewerHostMsg_SetCursorPos
, OnSetCursorPos
)
94 IPC_MESSAGE_UNHANDLED(__debugbreak())
99 virtual void OnChannelError() OVERRIDE
{
100 DVLOG(1) << "Channel error";
105 void OnSetCursor(int64 cursor
) {
106 ui_proxy_
->PostTask(FROM_HERE
,
107 base::Bind(&ChromeAppViewAsh::OnSetCursor
,
108 base::Unretained(app_view_
),
109 reinterpret_cast<HCURSOR
>(cursor
)));
112 void OnDisplayFileOpenDialog(const string16
& title
,
113 const string16
& filter
,
114 const base::FilePath
& default_path
,
115 bool allow_multiple_files
) {
116 ui_proxy_
->PostTask(FROM_HERE
,
117 base::Bind(&ChromeAppViewAsh::OnDisplayFileOpenDialog
,
118 base::Unretained(app_view_
),
122 allow_multiple_files
));
125 void OnDisplayFileSaveAsDialog(
126 const MetroViewerHostMsg_SaveAsDialogParams
& params
) {
129 base::Bind(&ChromeAppViewAsh::OnDisplayFileSaveAsDialog
,
130 base::Unretained(app_view_
),
134 void OnDisplayFolderPicker(const string16
& title
) {
137 base::Bind(&ChromeAppViewAsh::OnDisplayFolderPicker
,
138 base::Unretained(app_view_
),
142 void OnSetCursorPos(int x
, int y
) {
143 VLOG(1) << "In IPC OnSetCursorPos: " << x
<< ", " << y
;
146 base::Bind(&ChromeAppViewAsh::OnSetCursorPos
,
147 base::Unretained(app_view_
),
152 scoped_refptr
<base::MessageLoopProxy
> ui_proxy_
;
153 ChromeAppViewAsh
* app_view_
;
156 bool WaitForChromeIPCConnection(const std::string
& channel_name
) {
158 while (!IPC::Channel::IsNamedServerInitialized(channel_name
) &&
159 ms_elapsed
< 10000) {
163 return IPC::Channel::IsNamedServerInitialized(channel_name
);
166 // This class helps decoding the pointer properties of an event.
167 class PointerInfoHandler
{
169 PointerInfoHandler() :
173 update_kind_(winui::Input::PointerUpdateKind_Other
),
177 HRESULT
Init(winui::Core::IPointerEventArgs
* args
) {
178 HRESULT hr
= args
->get_CurrentPoint(&pointer_point_
);
182 winfoundtn::Point point
;
183 hr
= pointer_point_
->get_Position(&point
);
187 mswr::ComPtr
<winui::Input::IPointerPointProperties
> properties
;
188 hr
= pointer_point_
->get_Properties(&properties
);
192 hr
= properties
->get_PointerUpdateKind(&update_kind_
);
196 hr
= properties
->get_MouseWheelDelta(&wheel_delta_
);
201 pointer_point_
->get_Timestamp(×tamp_
);
202 pointer_point_
->get_PointerId(&pointer_id_
);
203 // Map the OS touch event id to a range allowed by the gesture recognizer.
205 pointer_id_
%= ui::GestureSequence::kMaxGesturePoints
;
209 bool IsType(windevs::Input::PointerDeviceType type
) const {
210 mswr::ComPtr
<windevs::Input::IPointerDevice
> pointer_device
;
211 CheckHR(pointer_point_
->get_PointerDevice(&pointer_device
));
212 windevs::Input::PointerDeviceType device_type
;
213 CheckHR(pointer_device
->get_PointerDeviceType(&device_type
));
214 return (device_type
== type
);
217 bool IsMouse() const {
218 return IsType(windevs::Input::PointerDeviceType_Mouse
);
221 bool IsTouch() const {
222 return IsType(windevs::Input::PointerDeviceType_Touch
);
225 int32
wheel_delta() const {
229 ui::EventFlags
flags() {
230 switch (update_kind_
) {
231 case winui::Input::PointerUpdateKind_LeftButtonPressed
:
232 return ui::EF_LEFT_MOUSE_BUTTON
;
233 case winui::Input::PointerUpdateKind_LeftButtonReleased
:
234 return ui::EF_LEFT_MOUSE_BUTTON
;
235 case winui::Input::PointerUpdateKind_RightButtonPressed
:
236 return ui::EF_RIGHT_MOUSE_BUTTON
;
237 case winui::Input::PointerUpdateKind_RightButtonReleased
:
238 return ui::EF_RIGHT_MOUSE_BUTTON
;
239 case winui::Input::PointerUpdateKind_MiddleButtonPressed
:
240 return ui::EF_MIDDLE_MOUSE_BUTTON
;
241 case winui::Input::PointerUpdateKind_MiddleButtonReleased
:
242 return ui::EF_MIDDLE_MOUSE_BUTTON
;
248 int x() const { return x_
; }
249 int y() const { return y_
; }
251 uint32
pointer_id() const {
255 uint64
timestamp() const { return timestamp_
; }
262 winui::Input::PointerUpdateKind update_kind_
;
263 mswr::ComPtr
<winui::Input::IPointerPoint
> pointer_point_
;
267 void RunMessageLoop(winui::Core::ICoreDispatcher
* dispatcher
) {
268 // We're entering a nested message loop, let's allow dispatching
269 // tasks while we're in there.
270 base::MessageLoop::current()->SetNestableTasksAllowed(true);
272 // Enter main core message loop. There are several ways to exit it
274 // 1 - User action like ALT-F4.
275 // 2 - Calling ICoreApplicationExit::Exit().
276 // 3- Posting WM_CLOSE to the core window.
277 HRESULT hr
= dispatcher
->ProcessEvents(
278 winui::Core::CoreProcessEventsOption
279 ::CoreProcessEventsOption_ProcessUntilQuit
);
281 // Wind down the thread's chrome message loop.
282 base::MessageLoop::current()->Quit();
285 // Helper to return the state of the shift/control/alt keys.
286 uint32
GetKeyboardEventFlags() {
288 if (base::win::IsShiftPressed())
289 flags
|= ui::EF_SHIFT_DOWN
;
290 if (base::win::IsCtrlPressed())
291 flags
|= ui::EF_CONTROL_DOWN
;
292 if (base::win::IsAltPressed())
293 flags
|= ui::EF_ALT_DOWN
;
299 ChromeAppViewAsh::ChromeAppViewAsh()
300 : mouse_down_flags_(ui::EF_NONE
),
301 ui_channel_(nullptr),
302 core_window_hwnd_(NULL
),
303 ui_loop_(base::MessageLoop::TYPE_UI
) {
304 DVLOG(1) << __FUNCTION__
;
305 globals
.previous_state
=
306 winapp::Activation::ApplicationExecutionState_NotRunning
;
309 ChromeAppViewAsh::~ChromeAppViewAsh() {
310 DVLOG(1) << __FUNCTION__
;
314 ChromeAppViewAsh::Initialize(winapp::Core::ICoreApplicationView
* view
) {
316 DVLOG(1) << __FUNCTION__
;
317 HRESULT hr
= view_
->add_Activated(mswr::Callback
<ActivatedHandler
>(
318 this, &ChromeAppViewAsh::OnActivate
).Get(),
325 ChromeAppViewAsh::SetWindow(winui::Core::ICoreWindow
* window
) {
327 DVLOG(1) << __FUNCTION__
;
329 // Retrieve the native window handle via the interop layer.
330 mswr::ComPtr
<ICoreWindowInterop
> interop
;
331 HRESULT hr
= window
->QueryInterface(interop
.GetAddressOf());
333 hr
= interop
->get_WindowHandle(&core_window_hwnd_
);
336 hr
= window_
->add_SizeChanged(mswr::Callback
<SizeChangedHandler
>(
337 this, &ChromeAppViewAsh::OnSizeChanged
).Get(),
341 // Register for pointer and keyboard notifications. We forward
342 // them to the browser process via IPC.
343 hr
= window_
->add_PointerMoved(mswr::Callback
<PointerEventHandler
>(
344 this, &ChromeAppViewAsh::OnPointerMoved
).Get(),
345 &pointermoved_token_
);
348 hr
= window_
->add_PointerPressed(mswr::Callback
<PointerEventHandler
>(
349 this, &ChromeAppViewAsh::OnPointerPressed
).Get(),
350 &pointerpressed_token_
);
353 hr
= window_
->add_PointerReleased(mswr::Callback
<PointerEventHandler
>(
354 this, &ChromeAppViewAsh::OnPointerReleased
).Get(),
355 &pointerreleased_token_
);
358 hr
= window_
->add_KeyDown(mswr::Callback
<KeyEventHandler
>(
359 this, &ChromeAppViewAsh::OnKeyDown
).Get(),
363 hr
= window_
->add_KeyUp(mswr::Callback
<KeyEventHandler
>(
364 this, &ChromeAppViewAsh::OnKeyUp
).Get(),
368 mswr::ComPtr
<winui::Core::ICoreDispatcher
> dispatcher
;
369 hr
= window_
->get_Dispatcher(&dispatcher
);
370 CheckHR(hr
, "Get Dispatcher failed.");
372 mswr::ComPtr
<winui::Core::ICoreAcceleratorKeys
> accelerator_keys
;
373 hr
= dispatcher
.CopyTo(__uuidof(winui::Core::ICoreAcceleratorKeys
),
374 reinterpret_cast<void**>(
375 accelerator_keys
.GetAddressOf()));
376 CheckHR(hr
, "QI for ICoreAcceleratorKeys failed.");
377 hr
= accelerator_keys
->add_AcceleratorKeyActivated(
378 mswr::Callback
<AcceleratorKeyEventHandler
>(
379 this, &ChromeAppViewAsh::OnAcceleratorKeyDown
).Get(),
380 &accel_keydown_token_
);
383 hr
= window_
->add_PointerWheelChanged(mswr::Callback
<PointerEventHandler
>(
384 this, &ChromeAppViewAsh::OnWheel
).Get(),
388 hr
= window_
->add_CharacterReceived(mswr::Callback
<CharEventHandler
>(
389 this, &ChromeAppViewAsh::OnCharacterReceived
).Get(),
390 &character_received_token_
);
393 hr
= window_
->add_VisibilityChanged(mswr::Callback
<VisibilityChangedHandler
>(
394 this, &ChromeAppViewAsh::OnVisibilityChanged
).Get(),
395 &visibility_changed_token_
);
398 hr
= window_
->add_Activated(mswr::Callback
<WindowActivatedHandler
>(
399 this, &ChromeAppViewAsh::OnWindowActivated
).Get(),
400 &window_activated_token_
);
403 // By initializing the direct 3D swap chain with the corewindow
404 // we can now directly blit to it from the browser process.
405 direct3d_helper_
.Initialize(window
);
406 DVLOG(1) << "Initialized Direct3D.";
411 ChromeAppViewAsh::Load(HSTRING entryPoint
) {
412 DVLOG(1) << __FUNCTION__
;
417 ChromeAppViewAsh::Run() {
418 DVLOG(1) << __FUNCTION__
;
419 mswr::ComPtr
<winui::Core::ICoreDispatcher
> dispatcher
;
420 HRESULT hr
= window_
->get_Dispatcher(&dispatcher
);
421 CheckHR(hr
, "Dispatcher failed.");
423 hr
= window_
->Activate();
425 DLOG(WARNING
) << "activation failed hr=" << hr
;
429 // Create the IPC channel IO thread. It needs to out-live the ChannelProxy.
430 base::Thread
io_thread("metro_IO_thread");
431 base::Thread::Options options
;
432 options
.message_loop_type
= base::MessageLoop::TYPE_IO
;
433 io_thread
.StartWithOptions(options
);
435 // Start up Chrome and wait for the desired IPC server connection to exist.
436 WaitForChromeIPCConnection(win8::kMetroViewerIPCChannelName
);
438 // In Aura mode we create an IPC channel to the browser, then ask it to
440 ChromeChannelListener
ui_channel_listener(&ui_loop_
, this);
441 IPC::ChannelProxy
ui_channel(win8::kMetroViewerIPCChannelName
,
442 IPC::Channel::MODE_NAMED_CLIENT
,
443 &ui_channel_listener
,
444 io_thread
.message_loop_proxy());
445 ui_channel_
= &ui_channel
;
447 // Upon receipt of the MetroViewerHostMsg_SetTargetSurface message the
448 // browser will use D3D from the browser process to present to our Window.
449 ui_channel_
->Send(new MetroViewerHostMsg_SetTargetSurface(
450 gfx::NativeViewId(core_window_hwnd_
)));
451 DVLOG(1) << "ICoreWindow sent " << core_window_hwnd_
;
453 // Send an initial size message so that the Ash root window host gets sized
456 ::GetWindowRect(core_window_hwnd_
, &rect
);
458 new MetroViewerHostMsg_WindowSizeChanged(rect
.right
- rect
.left
,
459 rect
.bottom
- rect
.top
));
461 // And post the task that'll do the inner Metro message pumping to it.
462 ui_loop_
.PostTask(FROM_HERE
, base::Bind(&RunMessageLoop
, dispatcher
.Get()));
465 DVLOG(0) << "ProcessEvents done, hr=" << hr
;
470 ChromeAppViewAsh::Uninitialize() {
471 DVLOG(1) << __FUNCTION__
;
474 core_window_hwnd_
= NULL
;
479 HRESULT
ChromeAppViewAsh::Unsnap() {
480 mswr::ComPtr
<winui::ViewManagement::IApplicationViewStatics
> view_statics
;
481 HRESULT hr
= winrt_utils::CreateActivationFactory(
482 RuntimeClass_Windows_UI_ViewManagement_ApplicationView
,
483 view_statics
.GetAddressOf());
486 winui::ViewManagement::ApplicationViewState state
=
487 winui::ViewManagement::ApplicationViewState_FullScreenLandscape
;
488 hr
= view_statics
->get_Value(&state
);
491 if (state
== winui::ViewManagement::ApplicationViewState_Snapped
) {
492 boolean success
= FALSE
;
493 hr
= view_statics
->TryUnsnap(&success
);
495 if (FAILED(hr
) || !success
) {
496 LOG(ERROR
) << "Failed to unsnap. Error 0x" << hr
;
505 void ChromeAppViewAsh::OnSetCursor(HCURSOR cursor
) {
506 ::SetCursor(HCURSOR(cursor
));
509 void ChromeAppViewAsh::OnDisplayFileOpenDialog(
510 const string16
& title
,
511 const string16
& filter
,
512 const base::FilePath
& default_path
,
513 bool allow_multiple_files
) {
514 DVLOG(1) << __FUNCTION__
;
516 // The OpenFilePickerSession instance is deleted when we receive a
517 // callback from the OpenFilePickerSession class about the completion of the
519 FilePickerSessionBase
* file_picker_
=
520 new OpenFilePickerSession(this,
524 allow_multiple_files
);
528 void ChromeAppViewAsh::OnDisplayFileSaveAsDialog(
529 const MetroViewerHostMsg_SaveAsDialogParams
& params
) {
530 DVLOG(1) << __FUNCTION__
;
532 // The SaveFilePickerSession instance is deleted when we receive a
533 // callback from the SaveFilePickerSession class about the completion of the
535 FilePickerSessionBase
* file_picker_
=
536 new SaveFilePickerSession(this, params
);
540 void ChromeAppViewAsh::OnDisplayFolderPicker(const string16
& title
) {
541 DVLOG(1) << __FUNCTION__
;
542 // The FolderPickerSession instance is deleted when we receive a
543 // callback from the FolderPickerSession class about the completion of the
545 FilePickerSessionBase
* file_picker_
= new FolderPickerSession(this, title
);
549 void ChromeAppViewAsh::OnSetCursorPos(int x
, int y
) {
551 ::SetCursorPos(x
, y
);
552 DVLOG(1) << "In UI OnSetCursorPos: " << x
<< ", " << y
;
553 ui_channel_
->Send(new MetroViewerHostMsg_SetCursorPosAck());
554 // Generate a fake mouse move which matches the SetCursor coordinates as
555 // the browser expects to receive a mouse move for these coordinates.
556 // It is not clear why we don't receive a real mouse move in response to
557 // the SetCursorPos calll above.
558 ui_channel_
->Send(new MetroViewerHostMsg_MouseMoved(x
, y
, 0));
562 void ChromeAppViewAsh::OnOpenFileCompleted(
563 OpenFilePickerSession
* open_file_picker
,
565 DVLOG(1) << __FUNCTION__
;
566 DVLOG(1) << "Success: " << success
;
568 if (open_file_picker
->allow_multi_select()) {
569 ui_channel_
->Send(new MetroViewerHostMsg_MultiFileOpenDone(
570 success
, open_file_picker
->filenames()));
572 ui_channel_
->Send(new MetroViewerHostMsg_FileOpenDone(
573 success
, base::FilePath(open_file_picker
->result())));
576 delete open_file_picker
;
579 void ChromeAppViewAsh::OnSaveFileCompleted(
580 SaveFilePickerSession
* save_file_picker
,
582 DVLOG(1) << __FUNCTION__
;
583 DVLOG(1) << "Success: " << success
;
585 ui_channel_
->Send(new MetroViewerHostMsg_FileSaveAsDone(
587 base::FilePath(save_file_picker
->result()),
588 save_file_picker
->filter_index()));
590 delete save_file_picker
;
593 void ChromeAppViewAsh::OnFolderPickerCompleted(
594 FolderPickerSession
* folder_picker
,
596 DVLOG(1) << __FUNCTION__
;
597 DVLOG(1) << "Success: " << success
;
599 ui_channel_
->Send(new MetroViewerHostMsg_SelectFolderDone(
601 base::FilePath(folder_picker
->result())));
603 delete folder_picker
;
606 HRESULT
ChromeAppViewAsh::OnActivate(
607 winapp::Core::ICoreApplicationView
*,
608 winapp::Activation::IActivatedEventArgs
* args
) {
609 DVLOG(1) << __FUNCTION__
;
610 // Note: If doing more work in this function, you migth need to call
611 // get_PreviousExecutionState() and skip the work if the result is
612 // ApplicationExecutionState_Running and globals.previous_state is too.
613 args
->get_PreviousExecutionState(&globals
.previous_state
);
614 DVLOG(1) << "Previous Execution State: " << globals
.previous_state
;
616 winapp::Activation::ActivationKind activation_kind
;
617 CheckHR(args
->get_Kind(&activation_kind
));
618 if (activation_kind
== winapp::Activation::ActivationKind_Search
)
619 HandleSearchRequest(args
);
620 else if (activation_kind
== winapp::Activation::ActivationKind_Protocol
)
621 HandleProtocolRequest(args
);
622 // We call ICoreWindow::Activate after the handling for the search/protocol
623 // requests because Chrome can be launched to handle a search request which
624 // in turn launches the chrome browser process in desktop mode via
625 // ShellExecute. If we call ICoreWindow::Activate before this, then
626 // Windows kills the metro chrome process when it calls ShellExecute. Seems
632 HRESULT
ChromeAppViewAsh::OnPointerMoved(winui::Core::ICoreWindow
* sender
,
633 winui::Core::IPointerEventArgs
* args
) {
634 PointerInfoHandler pointer
;
635 HRESULT hr
= pointer
.Init(args
);
639 if (pointer
.IsMouse()) {
640 ui_channel_
->Send(new MetroViewerHostMsg_MouseMoved(
643 mouse_down_flags_
| GetKeyboardEventFlags()));
645 DCHECK(pointer
.IsTouch());
646 ui_channel_
->Send(new MetroViewerHostMsg_TouchMoved(pointer
.x(),
649 pointer
.pointer_id()));
654 // NOTE: From experimentation, it seems like Metro only sends a PointerPressed
655 // event for the first button pressed and the last button released in a sequence
657 // For example, a sequence of LEFT_DOWN, RIGHT_DOWN, LEFT_UP, RIGHT_UP results
658 // only in PointerPressed(LEFT)/PointerReleased(RIGHT) events.
659 HRESULT
ChromeAppViewAsh::OnPointerPressed(
660 winui::Core::ICoreWindow
* sender
,
661 winui::Core::IPointerEventArgs
* args
) {
662 PointerInfoHandler pointer
;
663 HRESULT hr
= pointer
.Init(args
);
667 if (pointer
.IsMouse()) {
668 mouse_down_flags_
= pointer
.flags();
669 ui_channel_
->Send(new MetroViewerHostMsg_MouseButton(
673 ui::ET_MOUSE_PRESSED
,
674 static_cast<ui::EventFlags
>(
675 mouse_down_flags_
| GetKeyboardEventFlags())));
677 DCHECK(pointer
.IsTouch());
678 ui_channel_
->Send(new MetroViewerHostMsg_TouchDown(pointer
.x(),
681 pointer
.pointer_id()));
686 HRESULT
ChromeAppViewAsh::OnPointerReleased(
687 winui::Core::ICoreWindow
* sender
,
688 winui::Core::IPointerEventArgs
* args
) {
689 PointerInfoHandler pointer
;
690 HRESULT hr
= pointer
.Init(args
);
694 if (pointer
.IsMouse()) {
695 mouse_down_flags_
= ui::EF_NONE
;
696 ui_channel_
->Send(new MetroViewerHostMsg_MouseButton(
700 ui::ET_MOUSE_RELEASED
,
701 static_cast<ui::EventFlags
>(
702 pointer
.flags() | GetKeyboardEventFlags())));
704 DCHECK(pointer
.IsTouch());
705 ui_channel_
->Send(new MetroViewerHostMsg_TouchUp(pointer
.x(),
708 pointer
.pointer_id()));
713 HRESULT
ChromeAppViewAsh::OnWheel(
714 winui::Core::ICoreWindow
* sender
,
715 winui::Core::IPointerEventArgs
* args
) {
716 PointerInfoHandler pointer
;
717 HRESULT hr
= pointer
.Init(args
);
720 DCHECK(pointer
.IsMouse());
721 ui_channel_
->Send(new MetroViewerHostMsg_MouseButton(pointer
.x(), pointer
.y(),
722 pointer
.wheel_delta(),
728 HRESULT
ChromeAppViewAsh::OnKeyDown(
729 winui::Core::ICoreWindow
* sender
,
730 winui::Core::IKeyEventArgs
* args
) {
731 winsys::VirtualKey virtual_key
;
732 HRESULT hr
= args
->get_VirtualKey(&virtual_key
);
735 winui::Core::CorePhysicalKeyStatus status
;
736 hr
= args
->get_KeyStatus(&status
);
740 ui_channel_
->Send(new MetroViewerHostMsg_KeyDown(virtual_key
,
743 GetKeyboardEventFlags()));
747 HRESULT
ChromeAppViewAsh::OnKeyUp(
748 winui::Core::ICoreWindow
* sender
,
749 winui::Core::IKeyEventArgs
* args
) {
750 winsys::VirtualKey virtual_key
;
751 HRESULT hr
= args
->get_VirtualKey(&virtual_key
);
754 winui::Core::CorePhysicalKeyStatus status
;
755 hr
= args
->get_KeyStatus(&status
);
759 ui_channel_
->Send(new MetroViewerHostMsg_KeyUp(virtual_key
,
762 GetKeyboardEventFlags()));
766 HRESULT
ChromeAppViewAsh::OnAcceleratorKeyDown(
767 winui::Core::ICoreDispatcher
* sender
,
768 winui::Core::IAcceleratorKeyEventArgs
* args
) {
769 winsys::VirtualKey virtual_key
;
770 HRESULT hr
= args
->get_VirtualKey(&virtual_key
);
773 winui::Core::CorePhysicalKeyStatus status
;
774 hr
= args
->get_KeyStatus(&status
);
778 winui::Core::CoreAcceleratorKeyEventType event_type
;
779 hr
= args
->get_EventType(&event_type
);
783 uint32 keyboard_flags
= GetKeyboardEventFlags();
785 switch (event_type
) {
786 case winui::Core::CoreAcceleratorKeyEventType_SystemCharacter
:
787 ui_channel_
->Send(new MetroViewerHostMsg_Character(virtual_key
,
793 case winui::Core::CoreAcceleratorKeyEventType_SystemKeyDown
:
794 ui_channel_
->Send(new MetroViewerHostMsg_KeyDown(virtual_key
,
800 case winui::Core::CoreAcceleratorKeyEventType_SystemKeyUp
:
801 ui_channel_
->Send(new MetroViewerHostMsg_KeyUp(virtual_key
,
813 HRESULT
ChromeAppViewAsh::OnCharacterReceived(
814 winui::Core::ICoreWindow
* sender
,
815 winui::Core::ICharacterReceivedEventArgs
* args
) {
816 unsigned int char_code
= 0;
817 HRESULT hr
= args
->get_KeyCode(&char_code
);
821 winui::Core::CorePhysicalKeyStatus status
;
822 hr
= args
->get_KeyStatus(&status
);
826 ui_channel_
->Send(new MetroViewerHostMsg_Character(char_code
,
829 GetKeyboardEventFlags()));
833 HRESULT
ChromeAppViewAsh::OnVisibilityChanged(
834 winui::Core::ICoreWindow
* sender
,
835 winui::Core::IVisibilityChangedEventArgs
* args
) {
836 boolean visible
= false;
837 HRESULT hr
= args
->get_Visible(&visible
);
841 ui_channel_
->Send(new MetroViewerHostMsg_VisibilityChanged(!!visible
));
845 HRESULT
ChromeAppViewAsh::OnWindowActivated(
846 winui::Core::ICoreWindow
* sender
,
847 winui::Core::IWindowActivatedEventArgs
* args
) {
848 winui::Core::CoreWindowActivationState state
;
849 HRESULT hr
= args
->get_WindowActivationState(&state
);
852 DVLOG(1) << "Window activation state: " << state
;
853 ui_channel_
->Send(new MetroViewerHostMsg_WindowActivated(
854 state
!= winui::Core::CoreWindowActivationState_Deactivated
));
858 HRESULT
ChromeAppViewAsh::HandleSearchRequest(
859 winapp::Activation::IActivatedEventArgs
* args
) {
860 mswr::ComPtr
<winapp::Activation::ISearchActivatedEventArgs
> search_args
;
861 CheckHR(args
->QueryInterface(
862 winapp::Activation::IID_ISearchActivatedEventArgs
, &search_args
));
865 DVLOG(1) << "Launched to handle search request";
866 base::FilePath chrome_exe_path
;
868 if (!PathService::Get(base::FILE_EXE
, &chrome_exe_path
))
871 SHELLEXECUTEINFO sei
= { sizeof(sei
) };
872 sei
.nShow
= SW_SHOWNORMAL
;
873 sei
.lpFile
= chrome_exe_path
.value().c_str();
874 sei
.lpDirectory
= L
"";
876 L
"--silent-launch --viewer-connection=viewer --windows8-search";
877 ::ShellExecuteEx(&sei
);
880 mswrw::HString search_string
;
881 CheckHR(search_args
->get_QueryText(search_string
.GetAddressOf()));
882 string16
search_text(MakeStdWString(search_string
.Get()));
884 ui_loop_
.PostTask(FROM_HERE
,
885 base::Bind(&ChromeAppViewAsh::OnSearchRequest
,
886 base::Unretained(this),
891 HRESULT
ChromeAppViewAsh::HandleProtocolRequest(
892 winapp::Activation::IActivatedEventArgs
* args
) {
893 DVLOG(1) << __FUNCTION__
;
895 DVLOG(1) << "Launched to handle url request";
897 mswr::ComPtr
<winapp::Activation::IProtocolActivatedEventArgs
>
899 CheckHR(args
->QueryInterface(
900 winapp::Activation::IID_IProtocolActivatedEventArgs
,
903 mswr::ComPtr
<winfoundtn::IUriRuntimeClass
> uri
;
904 protocol_args
->get_Uri(&uri
);
906 uri
->get_AbsoluteUri(url
.GetAddressOf());
907 string16
actual_url(MakeStdWString(url
.Get()));
908 DVLOG(1) << "Received url request: " << actual_url
;
910 ui_loop_
.PostTask(FROM_HERE
,
911 base::Bind(&ChromeAppViewAsh::OnNavigateToUrl
,
912 base::Unretained(this),
917 void ChromeAppViewAsh::OnSearchRequest(const string16
& search_string
) {
919 ui_channel_
->Send(new MetroViewerHostMsg_SearchRequest(search_string
));
922 void ChromeAppViewAsh::OnNavigateToUrl(const string16
& url
) {
924 ui_channel_
->Send(new MetroViewerHostMsg_OpenURL(url
));
927 HRESULT
ChromeAppViewAsh::OnSizeChanged(winui::Core::ICoreWindow
* sender
,
928 winui::Core::IWindowSizeChangedEventArgs
* args
) {
933 winfoundtn::Size size
;
934 HRESULT hr
= args
->get_Size(&size
);
938 uint32 cx
= static_cast<uint32
>(size
.Width
);
939 uint32 cy
= static_cast<uint32
>(size
.Height
);
941 DVLOG(1) << "Window size changed: width=" << cx
<< ", height=" << cy
;
942 ui_channel_
->Send(new MetroViewerHostMsg_WindowSizeChanged(cx
, cy
));
946 ///////////////////////////////////////////////////////////////////////////////
948 ChromeAppViewFactory::ChromeAppViewFactory(
949 winapp::Core::ICoreApplication
* icore_app
,
950 LPTHREAD_START_ROUTINE host_main
,
951 void* host_context
) {
952 mswr::ComPtr
<winapp::Core::ICoreApplication
> core_app(icore_app
);
953 mswr::ComPtr
<winapp::Core::ICoreApplicationExit
> app_exit
;
954 CheckHR(core_app
.As(&app_exit
));
955 globals
.app_exit
= app_exit
.Detach();
959 ChromeAppViewFactory::CreateView(winapp::Core::IFrameworkView
** view
) {
960 *view
= mswr::Make
<ChromeAppViewAsh
>().Detach();
961 return (*view
) ? S_OK
: E_OUTOFMEMORY
;