Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / ui / aura / remote_window_tree_host_win.cc
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
30 namespace aura {
31
32 namespace {
33
34 const char* kWindowTreeHostWinKey = "__AURA_REMOTE_WINDOW_TREE_HOST_WIN__";
35
36 // Sets the keystate for the virtual key passed in to down or up.
37 void 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.
47 void 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
64 void 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     composition_text->underlines[i].background_color = SK_ColorTRANSPARENT;
81   }
82 }
83
84 }  // namespace
85
86 RemoteWindowTreeHostWin* g_instance = NULL;
87
88 // static
89 RemoteWindowTreeHostWin* RemoteWindowTreeHostWin::Instance() {
90   return g_instance;
91 }
92
93 RemoteWindowTreeHostWin::RemoteWindowTreeHostWin()
94     : remote_window_(NULL),
95       host_(NULL),
96       ignore_mouse_moves_until_set_cursor_ack_(0),
97       event_flags_(0),
98       window_size_(aura::WindowTreeHost::GetNativeScreenSize()) {
99   CHECK(!g_instance);
100   g_instance = this;
101   prop_.reset(new ui::ViewProp(NULL, kWindowTreeHostWinKey, this));
102   CreateCompositor(GetAcceleratedWidget());
103 }
104
105 RemoteWindowTreeHostWin::~RemoteWindowTreeHostWin() {
106   DestroyCompositor();
107   DestroyDispatcher();
108   DCHECK_EQ(g_instance, this);
109   g_instance = NULL;
110 }
111
112 // static
113 bool RemoteWindowTreeHostWin::IsValid() {
114   return Instance()->remote_window_ != NULL;
115 }
116
117 void RemoteWindowTreeHostWin::SetRemoteWindowHandle(HWND remote_window) {
118   remote_window_ = remote_window;
119 }
120
121 void RemoteWindowTreeHostWin::Connected(IPC::Sender* host) {
122   CHECK(host_ == NULL);
123   DCHECK(remote_window_);
124   host_ = host;
125   // Recreate the compositor for the target surface represented by the
126   // remote_window HWND.
127   CreateCompositor(remote_window_);
128   InitCompositor();
129 }
130
131 void RemoteWindowTreeHostWin::Disconnected() {
132   // Don't CHECK here, Disconnected is called on a channel error which can
133   // happen before we're successfully Connected.
134   if (!host_)
135     return;
136   ui::RemoteInputMethodPrivateWin* remote_input_method_private =
137       GetRemoteInputMethodPrivate();
138   if (remote_input_method_private)
139     remote_input_method_private->SetRemoteDelegate(NULL);
140   host_ = NULL;
141   remote_window_ = NULL;
142 }
143
144 bool RemoteWindowTreeHostWin::OnMessageReceived(const IPC::Message& message) {
145   bool handled = true;
146   IPC_BEGIN_MESSAGE_MAP(RemoteWindowTreeHostWin, message)
147     IPC_MESSAGE_HANDLER(MetroViewerHostMsg_MouseMoved, OnMouseMoved)
148     IPC_MESSAGE_HANDLER(MetroViewerHostMsg_MouseButton, OnMouseButton)
149     IPC_MESSAGE_HANDLER(MetroViewerHostMsg_KeyDown, OnKeyDown)
150     IPC_MESSAGE_HANDLER(MetroViewerHostMsg_KeyUp, OnKeyUp)
151     IPC_MESSAGE_HANDLER(MetroViewerHostMsg_Character, OnChar)
152     IPC_MESSAGE_HANDLER(MetroViewerHostMsg_WindowActivated,
153                         OnWindowActivated)
154     IPC_MESSAGE_HANDLER(MetroViewerHostMsg_EdgeGesture, OnEdgeGesture)
155     IPC_MESSAGE_HANDLER(MetroViewerHostMsg_TouchDown,
156                         OnTouchDown)
157     IPC_MESSAGE_HANDLER(MetroViewerHostMsg_TouchUp,
158                         OnTouchUp)
159     IPC_MESSAGE_HANDLER(MetroViewerHostMsg_TouchMoved,
160                         OnTouchMoved)
161     IPC_MESSAGE_HANDLER(MetroViewerHostMsg_SetCursorPosAck,
162                         OnSetCursorPosAck)
163     IPC_MESSAGE_HANDLER(MetroViewerHostMsg_ImeCandidatePopupChanged,
164                         OnImeCandidatePopupChanged)
165     IPC_MESSAGE_HANDLER(MetroViewerHostMsg_ImeCompositionChanged,
166                         OnImeCompositionChanged)
167     IPC_MESSAGE_HANDLER(MetroViewerHostMsg_ImeTextCommitted,
168                         OnImeTextCommitted)
169     IPC_MESSAGE_HANDLER(MetroViewerHostMsg_ImeInputSourceChanged,
170                         OnImeInputSourceChanged)
171     IPC_MESSAGE_UNHANDLED(handled = false)
172   IPC_END_MESSAGE_MAP()
173   return handled;
174 }
175
176 void RemoteWindowTreeHostWin::HandleOpenURLOnDesktop(
177     const base::FilePath& shortcut,
178     const base::string16& url) {
179   if (!host_)
180     return;
181   host_->Send(new MetroViewerHostMsg_OpenURLOnDesktop(shortcut, url));
182 }
183
184 void RemoteWindowTreeHostWin::HandleWindowSizeChanged(uint32 width,
185                                                       uint32 height) {
186   SetBounds(gfx::Rect(0, 0, width, height));
187 }
188
189 bool RemoteWindowTreeHostWin::IsForegroundWindow() {
190   return ::GetForegroundWindow() == remote_window_;
191 }
192
193 Window* RemoteWindowTreeHostWin::GetAshWindow() {
194   return window();
195 }
196
197 ui::EventSource* RemoteWindowTreeHostWin::GetEventSource() {
198   return this;
199 }
200
201 gfx::AcceleratedWidget RemoteWindowTreeHostWin::GetAcceleratedWidget() {
202   if (remote_window_)
203     return remote_window_;
204   // Getting here should only happen for ash_unittests.exe and related code.
205   return ::GetDesktopWindow();
206 }
207
208 void RemoteWindowTreeHostWin::Show() {
209   ui::RemoteInputMethodPrivateWin* remote_input_method_private =
210       GetRemoteInputMethodPrivate();
211   if (remote_input_method_private)
212     remote_input_method_private->SetRemoteDelegate(this);
213 }
214
215 void RemoteWindowTreeHostWin::Hide() {
216   NOTIMPLEMENTED();
217 }
218
219 gfx::Rect RemoteWindowTreeHostWin::GetBounds() const {
220   return gfx::Rect(window_size_);
221 }
222
223 void RemoteWindowTreeHostWin::SetBounds(const gfx::Rect& bounds) {
224   window_size_ = bounds.size();
225   OnHostResized(bounds.size());
226 }
227
228 gfx::Point RemoteWindowTreeHostWin::GetLocationOnNativeScreen() const {
229   return gfx::Point(0, 0);
230 }
231
232 void RemoteWindowTreeHostWin::SetCapture() {
233 }
234
235 void RemoteWindowTreeHostWin::ReleaseCapture() {
236 }
237
238 void RemoteWindowTreeHostWin::SetCursorNative(gfx::NativeCursor native_cursor) {
239   if (!host_)
240     return;
241   host_->Send(
242       new MetroViewerHostMsg_SetCursor(uint64(native_cursor.platform())));
243 }
244
245 void RemoteWindowTreeHostWin::MoveCursorToNative(const gfx::Point& location) {
246   VLOG(1) << "In MoveCursorTo: " << location.x() << ", " << location.y();
247   if (!host_)
248     return;
249
250   // This function can be called in cases like when the mouse cursor is
251   // restricted within a viewport (For e.g. LockCursor) which assumes that
252   // subsequent mouse moves would be received starting with the new cursor
253   // coordinates. This is a challenge for Windows ASH for the reasons
254   // outlined below.
255   // Other cases which don't expect this behavior should continue to work
256   // without issues.
257
258   // The mouse events are received by the viewer process and sent to the
259   // browser. If we invoke the SetCursor API here we continue to receive
260   // mouse messages from the viewer which were posted before the SetCursor
261   // API executes which messes up the state in the browser. To workaround
262   // this we invoke the SetCursor API in the viewer process and ignore
263   // mouse messages until we received an ACK from the viewer indicating that
264   // the SetCursor operation completed.
265   ignore_mouse_moves_until_set_cursor_ack_++;
266   VLOG(1) << "In MoveCursorTo. Sending IPC";
267   host_->Send(new MetroViewerHostMsg_SetCursorPos(location.x(), location.y()));
268 }
269
270 void RemoteWindowTreeHostWin::OnCursorVisibilityChangedNative(bool show) {
271   NOTIMPLEMENTED();
272 }
273
274 ui::EventProcessor* RemoteWindowTreeHostWin::GetEventProcessor() {
275   return dispatcher();
276 }
277
278 void RemoteWindowTreeHostWin::CancelComposition() {
279   if (!host_)
280     return;
281   host_->Send(new MetroViewerHostMsg_ImeCancelComposition);
282 }
283
284 void RemoteWindowTreeHostWin::OnTextInputClientUpdated(
285     const std::vector<int32>& input_scopes,
286     const std::vector<gfx::Rect>& composition_character_bounds) {
287   if (!host_)
288     return;
289   std::vector<metro_viewer::CharacterBounds> character_bounds;
290   for (size_t i = 0; i < composition_character_bounds.size(); ++i) {
291     const gfx::Rect& rect = composition_character_bounds[i];
292     metro_viewer::CharacterBounds bounds;
293     bounds.left = rect.x();
294     bounds.top = rect.y();
295     bounds.right = rect.right();
296     bounds.bottom = rect.bottom();
297     character_bounds.push_back(bounds);
298   }
299   host_->Send(new MetroViewerHostMsg_ImeTextInputClientUpdated(
300       input_scopes, character_bounds));
301 }
302
303 gfx::Point PointFromNativeEvent(int32 x, int32 y) {
304   static float scale_factor = gfx::GetDPIScale();
305   gfx::Point result( x * scale_factor, y * scale_factor);
306   return result;
307 }
308
309 void RemoteWindowTreeHostWin::OnMouseMoved(int32 x, int32 y, int32 flags) {
310   if (ignore_mouse_moves_until_set_cursor_ack_)
311     return;
312
313   gfx::Point location = PointFromNativeEvent(x, y);
314   ui::MouseEvent event(ui::ET_MOUSE_MOVED, location, location, flags, 0);
315   SendEventToProcessor(&event);
316 }
317
318 void RemoteWindowTreeHostWin::OnMouseButton(
319     const MetroViewerHostMsg_MouseButtonParams& params) {
320   gfx::Point location = PointFromNativeEvent(params.x, params.y);
321   ui::MouseEvent mouse_event(params.event_type, location, location,
322                              static_cast<int>(params.flags),
323                              static_cast<int>(params.changed_button));
324
325   SetEventFlags(params.flags | key_event_flags());
326   if (params.event_type == ui::ET_MOUSEWHEEL) {
327     int x_offset = params.is_horizontal_wheel ? params.extra : 0;
328     int y_offset = !params.is_horizontal_wheel ? params.extra : 0;
329     ui::MouseWheelEvent wheel_event(mouse_event, x_offset, y_offset);
330     SendEventToProcessor(&wheel_event);
331   } else if (params.event_type == ui::ET_MOUSE_PRESSED) {
332     // TODO(shrikant): Ideally modify code in event.cc by adding automatic
333     // tracking of double clicks in synthetic MouseEvent constructor code.
334     // Non-synthetic MouseEvent constructor code does automatically track
335     // this. Need to use some caution while modifying synthetic constructor
336     // as many tests and other code paths depend on it and apparently
337     // specifically depend on non implicit tracking of previous mouse event.
338     if (last_mouse_click_event_ &&
339         ui::MouseEvent::IsRepeatedClickEvent(mouse_event,
340                                              *last_mouse_click_event_)) {
341       mouse_event.SetClickCount(2);
342     } else {
343       mouse_event.SetClickCount(1);
344     }
345     last_mouse_click_event_ .reset(new ui::MouseEvent(mouse_event));
346     SendEventToProcessor(&mouse_event);
347   } else {
348     SendEventToProcessor(&mouse_event);
349   }
350 }
351
352 void RemoteWindowTreeHostWin::OnKeyDown(uint32 vkey,
353                                         uint32 repeat_count,
354                                         uint32 scan_code,
355                                         uint32 flags) {
356   DispatchKeyboardMessage(ui::ET_KEY_PRESSED, vkey, repeat_count, scan_code,
357                           flags, false);
358 }
359
360 void RemoteWindowTreeHostWin::OnKeyUp(uint32 vkey,
361                                       uint32 repeat_count,
362                                       uint32 scan_code,
363                                       uint32 flags) {
364   DispatchKeyboardMessage(ui::ET_KEY_RELEASED, vkey, repeat_count, scan_code,
365                           flags, false);
366 }
367
368 void RemoteWindowTreeHostWin::OnChar(uint32 key_code,
369                                      uint32 repeat_count,
370                                      uint32 scan_code,
371                                      uint32 flags) {
372   DispatchKeyboardMessage(ui::ET_KEY_PRESSED, key_code, repeat_count,
373                           scan_code, flags, true);
374 }
375
376 void RemoteWindowTreeHostWin::OnWindowActivated(bool repaint) {
377   OnHostActivated();
378   if (repaint && compositor())
379     compositor()->ScheduleFullRedraw();
380 }
381
382 void RemoteWindowTreeHostWin::OnEdgeGesture() {
383   ui::GestureEvent event(
384       0,
385       0,
386       0,
387       ui::EventTimeForNow(),
388       ui::GestureEventDetails(ui::ET_GESTURE_WIN8_EDGE_SWIPE));
389   SendEventToProcessor(&event);
390 }
391
392 void RemoteWindowTreeHostWin::OnTouchDown(int32 x,
393                                           int32 y,
394                                           uint64 timestamp,
395                                           uint32 pointer_id) {
396   gfx::Point location = PointFromNativeEvent(x, y);
397   ui::TouchEvent event(ui::ET_TOUCH_PRESSED,
398                        location,
399                        pointer_id,
400                        base::TimeDelta::FromMicroseconds(timestamp));
401   SendEventToProcessor(&event);
402 }
403
404 void RemoteWindowTreeHostWin::OnTouchUp(int32 x,
405                                         int32 y,
406                                         uint64 timestamp,
407                                         uint32 pointer_id) {
408   gfx::Point location = PointFromNativeEvent(x, y);
409   ui::TouchEvent event(ui::ET_TOUCH_RELEASED,
410                        location,
411                        pointer_id,
412                        base::TimeDelta::FromMicroseconds(timestamp));
413   SendEventToProcessor(&event);
414 }
415
416 void RemoteWindowTreeHostWin::OnTouchMoved(int32 x,
417                                            int32 y,
418                                            uint64 timestamp,
419                                            uint32 pointer_id) {
420   gfx::Point location = PointFromNativeEvent(x, y);
421   ui::TouchEvent event(ui::ET_TOUCH_MOVED,
422                        location,
423                        pointer_id,
424                        base::TimeDelta::FromMicroseconds(timestamp));
425   SendEventToProcessor(&event);
426 }
427
428 void RemoteWindowTreeHostWin::OnSetCursorPosAck() {
429   DCHECK_GT(ignore_mouse_moves_until_set_cursor_ack_, 0);
430   ignore_mouse_moves_until_set_cursor_ack_--;
431 }
432
433 ui::RemoteInputMethodPrivateWin*
434 RemoteWindowTreeHostWin::GetRemoteInputMethodPrivate() {
435   ui::InputMethod* input_method = GetAshWindow()->GetProperty(
436       aura::client::kRootWindowInputMethodKey);
437   return ui::RemoteInputMethodPrivateWin::Get(input_method);
438 }
439
440 void RemoteWindowTreeHostWin::OnImeCandidatePopupChanged(bool visible) {
441   ui::RemoteInputMethodPrivateWin* remote_input_method_private =
442       GetRemoteInputMethodPrivate();
443   if (!remote_input_method_private)
444     return;
445   remote_input_method_private->OnCandidatePopupChanged(visible);
446 }
447
448 void RemoteWindowTreeHostWin::OnImeCompositionChanged(
449     const base::string16& text,
450     int32 selection_start,
451     int32 selection_end,
452     const std::vector<metro_viewer::UnderlineInfo>& underlines) {
453   ui::RemoteInputMethodPrivateWin* remote_input_method_private =
454       GetRemoteInputMethodPrivate();
455   if (!remote_input_method_private)
456     return;
457   ui::CompositionText composition_text;
458   FillCompositionText(
459       text, selection_start, selection_end, underlines, &composition_text);
460   remote_input_method_private->OnCompositionChanged(composition_text);
461 }
462
463 void RemoteWindowTreeHostWin::OnImeTextCommitted(const base::string16& text) {
464   ui::RemoteInputMethodPrivateWin* remote_input_method_private =
465       GetRemoteInputMethodPrivate();
466   if (!remote_input_method_private)
467     return;
468   remote_input_method_private->OnTextCommitted(text);
469 }
470
471 void RemoteWindowTreeHostWin::OnImeInputSourceChanged(uint16 language_id,
472                                                       bool is_ime) {
473   ui::RemoteInputMethodPrivateWin* remote_input_method_private =
474       GetRemoteInputMethodPrivate();
475   if (!remote_input_method_private)
476     return;
477   remote_input_method_private->OnInputSourceChanged(language_id, is_ime);
478 }
479
480 void RemoteWindowTreeHostWin::DispatchKeyboardMessage(ui::EventType type,
481                                                       uint32 vkey,
482                                                       uint32 repeat_count,
483                                                       uint32 scan_code,
484                                                       uint32 flags,
485                                                       bool is_character) {
486   SetEventFlags(flags | mouse_event_flags());
487   if (base::MessageLoop::current()->IsNested()) {
488     int index = (flags & ui::EF_ALT_DOWN) ? 1 : 0;
489     const int char_message[] = {WM_CHAR, WM_SYSCHAR};
490     const int keydown_message[] = {WM_KEYDOWN, WM_SYSKEYDOWN};
491     const int keyup_message[] = {WM_KEYUP, WM_SYSKEYUP};
492     uint32 message = is_character
493                          ? char_message[index]
494                          : (type == ui::ET_KEY_PRESSED ? keydown_message[index]
495                                                        : keyup_message[index]);
496     ::PostThreadMessage(::GetCurrentThreadId(),
497                         message,
498                         vkey,
499                         repeat_count | scan_code >> 15);
500   } else if (is_character) {
501     ui::KeyEvent event(static_cast<base::char16>(vkey),
502                        ui::KeyboardCodeForWindowsKeyCode(vkey),
503                        flags);
504     SendEventToProcessor(&event);
505   } else {
506     ui::KeyEvent event(type,
507                        ui::KeyboardCodeForWindowsKeyCode(vkey),
508                        flags);
509     SendEventToProcessor(&event);
510   }
511 }
512
513 void RemoteWindowTreeHostWin::SetEventFlags(uint32 flags) {
514   if (flags == event_flags_)
515     return;
516   event_flags_ = flags;
517   SetVirtualKeyStates(event_flags_);
518 }
519
520 }  // namespace aura