remote_window_tree_host_win.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
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/aura/remote_window_tree_host_win.h"
6
7#include <windows.h>
8
9#include <algorithm>
10
11#include "base/message_loop/message_loop.h"
12#include "ipc/ipc_message.h"
13#include "ipc/ipc_sender.h"
14#include "ui/aura/client/aura_constants.h"
15#include "ui/aura/client/cursor_client.h"
16#include "ui/aura/window_event_dispatcher.h"
17#include "ui/aura/window_property.h"
18#include "ui/base/cursor/cursor_loader_win.h"
19#include "ui/base/ime/composition_text.h"
20#include "ui/base/ime/input_method.h"
21#include "ui/base/ime/remote_input_method_win.h"
22#include "ui/base/ime/text_input_client.h"
23#include "ui/base/view_prop.h"
24#include "ui/events/event_utils.h"
25#include "ui/events/keycodes/keyboard_code_conversion_win.h"
26#include "ui/gfx/insets.h"
27#include "ui/gfx/win/dpi.h"
28#include "ui/metro_viewer/metro_viewer_messages.h"
29
30namespace aura {
31
32namespace {
33
34const char* kWindowTreeHostWinKey = "__AURA_REMOTE_WINDOW_TREE_HOST_WIN__";
35
36// Sets the keystate for the virtual key passed in to down or up.
37void SetKeyState(uint8* key_states, bool key_down, uint32 virtual_key_code) {
38  DCHECK(key_states);
39
40  if (key_down)
41    key_states[virtual_key_code] |= 0x80;
42  else
43    key_states[virtual_key_code] &= 0x7F;
44}
45
46// Sets the keyboard states for the Shift/Control/Alt/Caps lock keys.
47void SetVirtualKeyStates(uint32 flags) {
48  uint8 keyboard_state[256] = {0};
49  ::GetKeyboardState(keyboard_state);
50
51  SetKeyState(keyboard_state, !!(flags & ui::EF_SHIFT_DOWN), VK_SHIFT);
52  SetKeyState(keyboard_state, !!(flags & ui::EF_CONTROL_DOWN), VK_CONTROL);
53  SetKeyState(keyboard_state, !!(flags & ui::EF_ALT_DOWN), VK_MENU);
54  SetKeyState(keyboard_state, !!(flags & ui::EF_CAPS_LOCK_DOWN), VK_CAPITAL);
55  SetKeyState(keyboard_state, !!(flags & ui::EF_LEFT_MOUSE_BUTTON), VK_LBUTTON);
56  SetKeyState(keyboard_state, !!(flags & ui::EF_RIGHT_MOUSE_BUTTON),
57              VK_RBUTTON);
58  SetKeyState(keyboard_state, !!(flags & ui::EF_MIDDLE_MOUSE_BUTTON),
59              VK_MBUTTON);
60
61  ::SetKeyboardState(keyboard_state);
62}
63
64void FillCompositionText(
65    const base::string16& text,
66    int32 selection_start,
67    int32 selection_end,
68    const std::vector<metro_viewer::UnderlineInfo>& underlines,
69    ui::CompositionText* composition_text) {
70  composition_text->Clear();
71  composition_text->text = text;
72  composition_text->selection.set_start(selection_start);
73  composition_text->selection.set_end(selection_end);
74  composition_text->underlines.resize(underlines.size());
75  for (size_t i = 0; i < underlines.size(); ++i) {
76    composition_text->underlines[i].start_offset = underlines[i].start_offset;
77    composition_text->underlines[i].end_offset = underlines[i].end_offset;
78    composition_text->underlines[i].color = SK_ColorBLACK;
79    composition_text->underlines[i].thick = underlines[i].thick;
80  }
81}
82
83}  // namespace
84
85void HandleOpenFile(const base::string16& title,
86                    const base::FilePath& default_path,
87                    const base::string16& filter,
88                    const OpenFileCompletion& on_success,
89                    const FileSelectionCanceled& on_failure) {
90  DCHECK(aura::RemoteWindowTreeHostWin::Instance());
91  aura::RemoteWindowTreeHostWin::Instance()->HandleOpenFile(title,
92                                                            default_path,
93                                                            filter,
94                                                            on_success,
95                                                            on_failure);
96}
97
98void HandleOpenMultipleFiles(const base::string16& title,
99                             const base::FilePath& default_path,
100                             const base::string16& filter,
101                             const OpenMultipleFilesCompletion& on_success,
102                             const FileSelectionCanceled& on_failure) {
103  DCHECK(aura::RemoteWindowTreeHostWin::Instance());
104  aura::RemoteWindowTreeHostWin::Instance()->HandleOpenMultipleFiles(
105      title,
106      default_path,
107      filter,
108      on_success,
109      on_failure);
110}
111
112void HandleSaveFile(const base::string16& title,
113                    const base::FilePath& default_path,
114                    const base::string16& filter,
115                    int filter_index,
116                    const base::string16& default_extension,
117                    const SaveFileCompletion& on_success,
118                    const FileSelectionCanceled& on_failure) {
119  DCHECK(aura::RemoteWindowTreeHostWin::Instance());
120  aura::RemoteWindowTreeHostWin::Instance()->HandleSaveFile(title,
121                                                            default_path,
122                                                            filter,
123                                                            filter_index,
124                                                            default_extension,
125                                                            on_success,
126                                                            on_failure);
127}
128
129void HandleSelectFolder(const base::string16& title,
130                        const SelectFolderCompletion& on_success,
131                        const FileSelectionCanceled& on_failure) {
132  DCHECK(aura::RemoteWindowTreeHostWin::Instance());
133  aura::RemoteWindowTreeHostWin::Instance()->HandleSelectFolder(title,
134                                                                on_success,
135                                                                on_failure);
136}
137
138void HandleActivateDesktop(const base::FilePath& shortcut,
139                           bool ash_exit) {
140  DCHECK(aura::RemoteWindowTreeHostWin::Instance());
141  aura::RemoteWindowTreeHostWin::Instance()->HandleActivateDesktop(shortcut,
142                                                                   ash_exit);
143}
144
145void HandleMetroExit() {
146  DCHECK(aura::RemoteWindowTreeHostWin::Instance());
147  aura::RemoteWindowTreeHostWin::Instance()->HandleMetroExit();
148}
149
150RemoteWindowTreeHostWin* g_instance = NULL;
151
152RemoteWindowTreeHostWin* RemoteWindowTreeHostWin::Instance() {
153  if (g_instance)
154    return g_instance;
155  return Create(gfx::Rect());
156}
157
158RemoteWindowTreeHostWin* RemoteWindowTreeHostWin::Create(
159    const gfx::Rect& bounds) {
160  g_instance = g_instance ? g_instance : new RemoteWindowTreeHostWin(bounds);
161  return g_instance;
162}
163
164RemoteWindowTreeHostWin::RemoteWindowTreeHostWin(const gfx::Rect& bounds)
165    : remote_window_(NULL),
166      host_(NULL),
167      ignore_mouse_moves_until_set_cursor_ack_(false),
168      event_flags_(0),
169      window_size_(aura::WindowTreeHost::GetNativeScreenSize()) {
170  prop_.reset(new ui::ViewProp(NULL, kWindowTreeHostWinKey, this));
171  CreateCompositor(GetAcceleratedWidget());
172}
173
174RemoteWindowTreeHostWin::~RemoteWindowTreeHostWin() {
175  DestroyCompositor();
176  DestroyDispatcher();
177  g_instance = NULL;
178}
179
180// static
181bool RemoteWindowTreeHostWin::IsValid() {
182  return Instance()->remote_window_ != NULL;
183}
184
185void RemoteWindowTreeHostWin::SetRemoteWindowHandle(HWND remote_window) {
186  remote_window_ = remote_window;
187  // Do not create compositor here, but in Connected() below.
188  // See http://crbug.com/330179 and http://crbug.com/334380.
189}
190
191void RemoteWindowTreeHostWin::Connected(IPC::Sender* host) {
192  CHECK(host_ == NULL);
193  DCHECK(remote_window_);
194  host_ = host;
195  // Recreate the compositor for the target surface represented by the
196  // remote_window HWND.
197  CreateCompositor(remote_window_);
198  InitCompositor();
199}
200
201void RemoteWindowTreeHostWin::Disconnected() {
202  // Don't CHECK here, Disconnected is called on a channel error which can
203  // happen before we're successfully Connected.
204  if (!host_)
205    return;
206  ui::RemoteInputMethodPrivateWin* remote_input_method_private =
207      GetRemoteInputMethodPrivate();
208  if (remote_input_method_private)
209    remote_input_method_private->SetRemoteDelegate(NULL);
210  host_ = NULL;
211  remote_window_ = NULL;
212}
213
214bool RemoteWindowTreeHostWin::OnMessageReceived(const IPC::Message& message) {
215  bool handled = true;
216  IPC_BEGIN_MESSAGE_MAP(RemoteWindowTreeHostWin, message)
217    IPC_MESSAGE_HANDLER(MetroViewerHostMsg_MouseMoved, OnMouseMoved)
218    IPC_MESSAGE_HANDLER(MetroViewerHostMsg_MouseButton, OnMouseButton)
219    IPC_MESSAGE_HANDLER(MetroViewerHostMsg_KeyDown, OnKeyDown)
220    IPC_MESSAGE_HANDLER(MetroViewerHostMsg_KeyUp, OnKeyUp)
221    IPC_MESSAGE_HANDLER(MetroViewerHostMsg_Character, OnChar)
222    IPC_MESSAGE_HANDLER(MetroViewerHostMsg_WindowActivated,
223                        OnWindowActivated)
224    IPC_MESSAGE_HANDLER(MetroViewerHostMsg_EdgeGesture, OnEdgeGesture)
225    IPC_MESSAGE_HANDLER(MetroViewerHostMsg_TouchDown,
226                        OnTouchDown)
227    IPC_MESSAGE_HANDLER(MetroViewerHostMsg_TouchUp,
228                        OnTouchUp)
229    IPC_MESSAGE_HANDLER(MetroViewerHostMsg_TouchMoved,
230                        OnTouchMoved)
231    IPC_MESSAGE_HANDLER(MetroViewerHostMsg_FileSaveAsDone,
232                        OnFileSaveAsDone)
233    IPC_MESSAGE_HANDLER(MetroViewerHostMsg_FileOpenDone,
234                        OnFileOpenDone)
235    IPC_MESSAGE_HANDLER(MetroViewerHostMsg_MultiFileOpenDone,
236                        OnMultiFileOpenDone)
237    IPC_MESSAGE_HANDLER(MetroViewerHostMsg_SelectFolderDone,
238                        OnSelectFolderDone)
239    IPC_MESSAGE_HANDLER(MetroViewerHostMsg_SetCursorPosAck,
240                        OnSetCursorPosAck)
241    IPC_MESSAGE_HANDLER(MetroViewerHostMsg_ImeCandidatePopupChanged,
242                        OnImeCandidatePopupChanged)
243    IPC_MESSAGE_HANDLER(MetroViewerHostMsg_ImeCompositionChanged,
244                        OnImeCompositionChanged)
245    IPC_MESSAGE_HANDLER(MetroViewerHostMsg_ImeTextCommitted,
246                        OnImeTextCommitted)
247    IPC_MESSAGE_HANDLER(MetroViewerHostMsg_ImeInputSourceChanged,
248                        OnImeInputSourceChanged)
249    IPC_MESSAGE_UNHANDLED(handled = false)
250  IPC_END_MESSAGE_MAP()
251  return handled;
252}
253
254void RemoteWindowTreeHostWin::HandleOpenURLOnDesktop(
255    const base::FilePath& shortcut,
256    const base::string16& url) {
257  if (!host_)
258    return;
259  host_->Send(new MetroViewerHostMsg_OpenURLOnDesktop(shortcut, url));
260}
261
262void RemoteWindowTreeHostWin::HandleActivateDesktop(
263    const base::FilePath& shortcut,
264    bool ash_exit) {
265  if (!host_)
266    return;
267  host_->Send(new MetroViewerHostMsg_ActivateDesktop(shortcut, ash_exit));
268}
269
270void RemoteWindowTreeHostWin::HandleMetroExit() {
271  if (!host_)
272    return;
273  host_->Send(new MetroViewerHostMsg_MetroExit());
274}
275
276void RemoteWindowTreeHostWin::HandleOpenFile(
277    const base::string16& title,
278    const base::FilePath& default_path,
279    const base::string16& filter,
280    const OpenFileCompletion& on_success,
281    const FileSelectionCanceled& on_failure) {
282  if (!host_)
283    return;
284
285  // Can only have one of these operations in flight.
286  DCHECK(file_open_completion_callback_.is_null());
287  DCHECK(failure_callback_.is_null());
288
289  file_open_completion_callback_ = on_success;
290  failure_callback_ = on_failure;
291
292  host_->Send(new MetroViewerHostMsg_DisplayFileOpen(title,
293                                                     filter,
294                                                     default_path,
295                                                     false));
296}
297
298void RemoteWindowTreeHostWin::HandleOpenMultipleFiles(
299    const base::string16& title,
300    const base::FilePath& default_path,
301    const base::string16& filter,
302    const OpenMultipleFilesCompletion& on_success,
303    const FileSelectionCanceled& on_failure) {
304  if (!host_)
305    return;
306
307  // Can only have one of these operations in flight.
308  DCHECK(multi_file_open_completion_callback_.is_null());
309  DCHECK(failure_callback_.is_null());
310  multi_file_open_completion_callback_ = on_success;
311  failure_callback_ = on_failure;
312
313  host_->Send(new MetroViewerHostMsg_DisplayFileOpen(title,
314                                                     filter,
315                                                     default_path,
316                                                     true));
317}
318
319void RemoteWindowTreeHostWin::HandleSaveFile(
320    const base::string16& title,
321    const base::FilePath& default_path,
322    const base::string16& filter,
323    int filter_index,
324    const base::string16& default_extension,
325    const SaveFileCompletion& on_success,
326    const FileSelectionCanceled& on_failure) {
327  if (!host_)
328    return;
329
330  MetroViewerHostMsg_SaveAsDialogParams params;
331  params.title = title;
332  params.default_extension = default_extension;
333  params.filter = filter;
334  params.filter_index = filter_index;
335  params.suggested_name = default_path;
336
337  // Can only have one of these operations in flight.
338  DCHECK(file_saveas_completion_callback_.is_null());
339  DCHECK(failure_callback_.is_null());
340  file_saveas_completion_callback_ = on_success;
341  failure_callback_ = on_failure;
342
343  host_->Send(new MetroViewerHostMsg_DisplayFileSaveAs(params));
344}
345
346void RemoteWindowTreeHostWin::HandleSelectFolder(
347    const base::string16& title,
348    const SelectFolderCompletion& on_success,
349    const FileSelectionCanceled& on_failure) {
350  if (!host_)
351    return;
352
353  // Can only have one of these operations in flight.
354  DCHECK(select_folder_completion_callback_.is_null());
355  DCHECK(failure_callback_.is_null());
356  select_folder_completion_callback_ = on_success;
357  failure_callback_ = on_failure;
358
359  host_->Send(new MetroViewerHostMsg_DisplaySelectFolder(title));
360}
361
362void RemoteWindowTreeHostWin::HandleWindowSizeChanged(uint32 width,
363                                                      uint32 height) {
364  SetBounds(gfx::Rect(0, 0, width, height));
365}
366
367bool RemoteWindowTreeHostWin::IsForegroundWindow() {
368  return ::GetForegroundWindow() == remote_window_;
369}
370
371Window* RemoteWindowTreeHostWin::GetAshWindow() {
372  return window();
373}
374
375gfx::AcceleratedWidget RemoteWindowTreeHostWin::GetAcceleratedWidget() {
376  if (remote_window_)
377    return remote_window_;
378  // Getting here should only happen for ash_unittests.exe and related code.
379  return ::GetDesktopWindow();
380}
381
382void RemoteWindowTreeHostWin::Show() {
383  ui::RemoteInputMethodPrivateWin* remote_input_method_private =
384      GetRemoteInputMethodPrivate();
385  if (remote_input_method_private)
386    remote_input_method_private->SetRemoteDelegate(this);
387}
388
389void RemoteWindowTreeHostWin::Hide() {
390  NOTIMPLEMENTED();
391}
392
393void RemoteWindowTreeHostWin::ToggleFullScreen() {
394}
395
396gfx::Rect RemoteWindowTreeHostWin::GetBounds() const {
397  return gfx::Rect(window_size_);
398}
399
400void RemoteWindowTreeHostWin::SetBounds(const gfx::Rect& bounds) {
401  window_size_ = bounds.size();
402  OnHostResized(bounds.size());
403}
404
405gfx::Insets RemoteWindowTreeHostWin::GetInsets() const {
406  return gfx::Insets();
407}
408
409void RemoteWindowTreeHostWin::SetInsets(const gfx::Insets& insets) {
410}
411
412gfx::Point RemoteWindowTreeHostWin::GetLocationOnNativeScreen() const {
413  return gfx::Point(0, 0);
414}
415
416void RemoteWindowTreeHostWin::SetCapture() {
417}
418
419void RemoteWindowTreeHostWin::ReleaseCapture() {
420}
421
422bool RemoteWindowTreeHostWin::QueryMouseLocation(gfx::Point* location_return) {
423  aura::client::CursorClient* cursor_client =
424      aura::client::GetCursorClient(window());
425  if (cursor_client && !cursor_client->IsMouseEventsEnabled()) {
426    *location_return = gfx::Point(0, 0);
427    return false;
428  }
429  POINT pt;
430  GetCursorPos(&pt);
431  *location_return =
432      gfx::Point(static_cast<int>(pt.x), static_cast<int>(pt.y));
433  return true;
434}
435
436bool RemoteWindowTreeHostWin::ConfineCursorToRootWindow() {
437  return true;
438}
439
440void RemoteWindowTreeHostWin::UnConfineCursor() {
441}
442
443void RemoteWindowTreeHostWin::SetCursorNative(gfx::NativeCursor native_cursor) {
444  if (!host_)
445    return;
446  host_->Send(
447    new MetroViewerHostMsg_SetCursor(uint64(native_cursor.platform())));
448}
449
450void RemoteWindowTreeHostWin::MoveCursorToNative(const gfx::Point& location) {
451  VLOG(1) << "In MoveCursorTo: " << location.x() << ", " << location.y();
452  if (!host_)
453    return;
454
455  // This function can be called in cases like when the mouse cursor is
456  // restricted within a viewport (For e.g. LockCursor) which assumes that
457  // subsequent mouse moves would be received starting with the new cursor
458  // coordinates. This is a challenge for Windows ASH for the reasons
459  // outlined below.
460  // Other cases which don't expect this behavior should continue to work
461  // without issues.
462
463  // The mouse events are received by the viewer process and sent to the
464  // browser. If we invoke the SetCursor API here we continue to receive
465  // mouse messages from the viewer which were posted before the SetCursor
466  // API executes which messes up the state in the browser. To workaround
467  // this we invoke the SetCursor API in the viewer process and ignore
468  // mouse messages until we received an ACK from the viewer indicating that
469  // the SetCursor operation completed.
470  ignore_mouse_moves_until_set_cursor_ack_ = true;
471  VLOG(1) << "In MoveCursorTo. Sending IPC";
472  host_->Send(new MetroViewerHostMsg_SetCursorPos(location.x(), location.y()));
473}
474
475void RemoteWindowTreeHostWin::OnCursorVisibilityChangedNative(bool show) {
476  NOTIMPLEMENTED();
477}
478
479void RemoteWindowTreeHostWin::PostNativeEvent(
480    const base::NativeEvent& native_event) {
481}
482
483void RemoteWindowTreeHostWin::OnDeviceScaleFactorChanged(
484    float device_scale_factor) {
485  NOTIMPLEMENTED();
486}
487
488void RemoteWindowTreeHostWin::PrepareForShutdown() {
489}
490
491ui::EventProcessor* RemoteWindowTreeHostWin::GetEventProcessor() {
492  return dispatcher();
493}
494
495void RemoteWindowTreeHostWin::CancelComposition() {
496  if (!host_)
497    return;
498  host_->Send(new MetroViewerHostMsg_ImeCancelComposition);
499}
500
501void RemoteWindowTreeHostWin::OnTextInputClientUpdated(
502    const std::vector<int32>& input_scopes,
503    const std::vector<gfx::Rect>& composition_character_bounds) {
504  if (!host_)
505    return;
506  std::vector<metro_viewer::CharacterBounds> character_bounds;
507  for (size_t i = 0; i < composition_character_bounds.size(); ++i) {
508    const gfx::Rect& rect = composition_character_bounds[i];
509    metro_viewer::CharacterBounds bounds;
510    bounds.left = rect.x();
511    bounds.top = rect.y();
512    bounds.right = rect.right();
513    bounds.bottom = rect.bottom();
514    character_bounds.push_back(bounds);
515  }
516  host_->Send(new MetroViewerHostMsg_ImeTextInputClientUpdated(
517      input_scopes, character_bounds));
518}
519
520gfx::Point PointFromNativeEvent(int32 x, int32 y) {
521  static float scale_factor = gfx::GetModernUIScale();
522  gfx::Point result( x * scale_factor, y * scale_factor);
523  return result;
524}
525
526void RemoteWindowTreeHostWin::OnMouseMoved(int32 x, int32 y, int32 flags) {
527  if (ignore_mouse_moves_until_set_cursor_ack_)
528    return;
529
530  gfx::Point location = PointFromNativeEvent(x, y);
531  ui::MouseEvent event(ui::ET_MOUSE_MOVED, location, location, flags, 0);
532  SendEventToProcessor(&event);
533}
534
535void RemoteWindowTreeHostWin::OnMouseButton(
536    const MetroViewerHostMsg_MouseButtonParams& params) {
537  gfx::Point location = PointFromNativeEvent(params.x, params.y);
538  ui::MouseEvent mouse_event(params.event_type, location, location,
539                             static_cast<int>(params.flags),
540                             static_cast<int>(params.changed_button));
541
542  SetEventFlags(params.flags | key_event_flags());
543  if (params.event_type == ui::ET_MOUSEWHEEL) {
544    int x_offset = params.is_horizontal_wheel ? params.extra : 0;
545    int y_offset = !params.is_horizontal_wheel ? params.extra : 0;
546    ui::MouseWheelEvent wheel_event(mouse_event, x_offset, y_offset);
547    SendEventToProcessor(&wheel_event);
548  } else if (params.event_type == ui::ET_MOUSE_PRESSED) {
549    // TODO(shrikant): Ideally modify code in event.cc by adding automatic
550    // tracking of double clicks in synthetic MouseEvent constructor code.
551    // Non-synthetic MouseEvent constructor code does automatically track
552    // this. Need to use some caution while modifying synthetic constructor
553    // as many tests and other code paths depend on it and apparently
554    // specifically depend on non implicit tracking of previous mouse event.
555    if (last_mouse_click_event_ &&
556        ui::MouseEvent::IsRepeatedClickEvent(mouse_event,
557                                             *last_mouse_click_event_)) {
558      mouse_event.SetClickCount(2);
559    } else {
560      mouse_event.SetClickCount(1);
561    }
562    last_mouse_click_event_ .reset(new ui::MouseEvent(mouse_event));
563    SendEventToProcessor(&mouse_event);
564  } else {
565    SendEventToProcessor(&mouse_event);
566  }
567}
568
569void RemoteWindowTreeHostWin::OnKeyDown(uint32 vkey,
570                                        uint32 repeat_count,
571                                        uint32 scan_code,
572                                        uint32 flags) {
573  DispatchKeyboardMessage(ui::ET_KEY_PRESSED, vkey, repeat_count, scan_code,
574                          flags, false);
575}
576
577void RemoteWindowTreeHostWin::OnKeyUp(uint32 vkey,
578                                      uint32 repeat_count,
579                                      uint32 scan_code,
580                                      uint32 flags) {
581  DispatchKeyboardMessage(ui::ET_KEY_RELEASED, vkey, repeat_count, scan_code,
582                          flags, false);
583}
584
585void RemoteWindowTreeHostWin::OnChar(uint32 key_code,
586                                     uint32 repeat_count,
587                                     uint32 scan_code,
588                                     uint32 flags) {
589  DispatchKeyboardMessage(ui::ET_KEY_PRESSED, key_code, repeat_count,
590                          scan_code, flags, true);
591}
592
593void RemoteWindowTreeHostWin::OnWindowActivated() {
594  OnHostActivated();
595}
596
597void RemoteWindowTreeHostWin::OnEdgeGesture() {
598  ui::GestureEvent event(
599      ui::ET_GESTURE_WIN8_EDGE_SWIPE,
600      0,
601      0,
602      0,
603      ui::EventTimeForNow(),
604      ui::GestureEventDetails(ui::ET_GESTURE_WIN8_EDGE_SWIPE, 0, 0),
605      0);
606  SendEventToProcessor(&event);
607}
608
609void RemoteWindowTreeHostWin::OnTouchDown(int32 x,
610                                          int32 y,
611                                          uint64 timestamp,
612                                          uint32 pointer_id) {
613  gfx::Point location = PointFromNativeEvent(x, y);
614  ui::TouchEvent event(ui::ET_TOUCH_PRESSED,
615                       location,
616                       pointer_id,
617                       base::TimeDelta::FromMicroseconds(timestamp));
618  SendEventToProcessor(&event);
619}
620
621void RemoteWindowTreeHostWin::OnTouchUp(int32 x,
622                                        int32 y,
623                                        uint64 timestamp,
624                                        uint32 pointer_id) {
625  gfx::Point location = PointFromNativeEvent(x, y);
626  ui::TouchEvent event(ui::ET_TOUCH_RELEASED,
627                       location,
628                       pointer_id,
629                       base::TimeDelta::FromMicroseconds(timestamp));
630  SendEventToProcessor(&event);
631}
632
633void RemoteWindowTreeHostWin::OnTouchMoved(int32 x,
634                                           int32 y,
635                                           uint64 timestamp,
636                                           uint32 pointer_id) {
637  gfx::Point location = PointFromNativeEvent(x, y);
638  ui::TouchEvent event(ui::ET_TOUCH_MOVED,
639                       location,
640                       pointer_id,
641                       base::TimeDelta::FromMicroseconds(timestamp));
642  SendEventToProcessor(&event);
643}
644
645void RemoteWindowTreeHostWin::OnFileSaveAsDone(bool success,
646                                               const base::FilePath& filename,
647                                               int filter_index) {
648  if (success)
649    file_saveas_completion_callback_.Run(filename, filter_index, NULL);
650  else
651    failure_callback_.Run(NULL);
652  file_saveas_completion_callback_.Reset();
653  failure_callback_.Reset();
654}
655
656
657void RemoteWindowTreeHostWin::OnFileOpenDone(bool success,
658                                             const base::FilePath& filename) {
659  if (success)
660    file_open_completion_callback_.Run(base::FilePath(filename), 0, NULL);
661  else
662    failure_callback_.Run(NULL);
663  file_open_completion_callback_.Reset();
664  failure_callback_.Reset();
665}
666
667void RemoteWindowTreeHostWin::OnMultiFileOpenDone(
668    bool success,
669    const std::vector<base::FilePath>& files) {
670  if (success)
671    multi_file_open_completion_callback_.Run(files, NULL);
672  else
673    failure_callback_.Run(NULL);
674  multi_file_open_completion_callback_.Reset();
675  failure_callback_.Reset();
676}
677
678void RemoteWindowTreeHostWin::OnSelectFolderDone(
679    bool success,
680    const base::FilePath& folder) {
681  if (success)
682    select_folder_completion_callback_.Run(base::FilePath(folder), 0, NULL);
683  else
684    failure_callback_.Run(NULL);
685  select_folder_completion_callback_.Reset();
686  failure_callback_.Reset();
687}
688
689void RemoteWindowTreeHostWin::OnSetCursorPosAck() {
690  DCHECK(ignore_mouse_moves_until_set_cursor_ack_);
691  ignore_mouse_moves_until_set_cursor_ack_ = false;
692}
693
694ui::RemoteInputMethodPrivateWin*
695RemoteWindowTreeHostWin::GetRemoteInputMethodPrivate() {
696  ui::InputMethod* input_method = GetAshWindow()->GetProperty(
697      aura::client::kRootWindowInputMethodKey);
698  return ui::RemoteInputMethodPrivateWin::Get(input_method);
699}
700
701void RemoteWindowTreeHostWin::OnImeCandidatePopupChanged(bool visible) {
702  ui::RemoteInputMethodPrivateWin* remote_input_method_private =
703      GetRemoteInputMethodPrivate();
704  if (!remote_input_method_private)
705    return;
706  remote_input_method_private->OnCandidatePopupChanged(visible);
707}
708
709void RemoteWindowTreeHostWin::OnImeCompositionChanged(
710    const base::string16& text,
711    int32 selection_start,
712    int32 selection_end,
713    const std::vector<metro_viewer::UnderlineInfo>& underlines) {
714  ui::RemoteInputMethodPrivateWin* remote_input_method_private =
715      GetRemoteInputMethodPrivate();
716  if (!remote_input_method_private)
717    return;
718  ui::CompositionText composition_text;
719  FillCompositionText(
720      text, selection_start, selection_end, underlines, &composition_text);
721  remote_input_method_private->OnCompositionChanged(composition_text);
722}
723
724void RemoteWindowTreeHostWin::OnImeTextCommitted(const base::string16& text) {
725  ui::RemoteInputMethodPrivateWin* remote_input_method_private =
726      GetRemoteInputMethodPrivate();
727  if (!remote_input_method_private)
728    return;
729  remote_input_method_private->OnTextCommitted(text);
730}
731
732void RemoteWindowTreeHostWin::OnImeInputSourceChanged(uint16 language_id,
733                                                      bool is_ime) {
734  ui::RemoteInputMethodPrivateWin* remote_input_method_private =
735      GetRemoteInputMethodPrivate();
736  if (!remote_input_method_private)
737    return;
738  remote_input_method_private->OnInputSourceChanged(language_id, is_ime);
739}
740
741void RemoteWindowTreeHostWin::DispatchKeyboardMessage(ui::EventType type,
742                                                      uint32 vkey,
743                                                      uint32 repeat_count,
744                                                      uint32 scan_code,
745                                                      uint32 flags,
746                                                      bool is_character) {
747  SetEventFlags(flags | mouse_event_flags());
748  if (base::MessageLoop::current()->IsNested()) {
749    int index = (flags & ui::EF_ALT_DOWN) ? 1 : 0;
750    const int char_message[] = {WM_CHAR, WM_SYSCHAR};
751    const int keydown_message[] = {WM_KEYDOWN, WM_SYSKEYDOWN};
752    const int keyup_message[] = {WM_KEYUP, WM_SYSKEYUP};
753    uint32 message = is_character
754                         ? char_message[index]
755                         : (type == ui::ET_KEY_PRESSED ? keydown_message[index]
756                                                       : keyup_message[index]);
757    ::PostThreadMessage(::GetCurrentThreadId(),
758                        message,
759                        vkey,
760                        repeat_count | scan_code >> 15);
761  } else {
762    ui::KeyEvent event(type,
763                       ui::KeyboardCodeForWindowsKeyCode(vkey),
764                       flags,
765                       is_character);
766    SendEventToProcessor(&event);
767  }
768}
769
770void RemoteWindowTreeHostWin::SetEventFlags(uint32 flags) {
771  if (flags == event_flags_)
772    return;
773  event_flags_ = flags;
774  SetVirtualKeyStates(event_flags_);
775}
776
777}  // namespace aura
778