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 "ui/aura/remote_root_window_host_win.h"
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/root_window.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/events/event_utils.h"
24 #include "ui/events/keycodes/keyboard_code_conversion_win.h"
25 #include "ui/base/view_prop.h"
26 #include "ui/gfx/insets.h"
27 #include "ui/gfx/win/dpi.h"
28 #include "ui/metro_viewer/metro_viewer_messages.h"
34 const char* kRootWindowHostWinKey
= "__AURA_REMOTE_ROOT_WINDOW_HOST_WIN__";
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
) {
41 key_states
[virtual_key_code
] |= 0x80;
43 key_states
[virtual_key_code
] &= 0x7F;
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
);
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
),
58 SetKeyState(keyboard_state
, !!(flags
& ui::EF_MIDDLE_MOUSE_BUTTON
),
61 ::SetKeyboardState(keyboard_state
);
64 void FillCompositionText(
65 const base::string16
& text
,
66 int32 selection_start
,
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
;
85 void 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::RemoteRootWindowHostWin::Instance());
91 aura::RemoteRootWindowHostWin::Instance()->HandleOpenFile(title
,
98 void 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::RemoteRootWindowHostWin::Instance());
104 aura::RemoteRootWindowHostWin::Instance()->HandleOpenMultipleFiles(
112 void HandleSaveFile(const base::string16
& title
,
113 const base::FilePath
& default_path
,
114 const base::string16
& filter
,
116 const base::string16
& default_extension
,
117 const SaveFileCompletion
& on_success
,
118 const FileSelectionCanceled
& on_failure
) {
119 DCHECK(aura::RemoteRootWindowHostWin::Instance());
120 aura::RemoteRootWindowHostWin::Instance()->HandleSaveFile(title
,
129 void HandleSelectFolder(const base::string16
& title
,
130 const SelectFolderCompletion
& on_success
,
131 const FileSelectionCanceled
& on_failure
) {
132 DCHECK(aura::RemoteRootWindowHostWin::Instance());
133 aura::RemoteRootWindowHostWin::Instance()->HandleSelectFolder(title
,
138 void HandleActivateDesktop(const base::FilePath
& shortcut
,
140 DCHECK(aura::RemoteRootWindowHostWin::Instance());
141 aura::RemoteRootWindowHostWin::Instance()->HandleActivateDesktop(shortcut
,
145 RemoteRootWindowHostWin
* g_instance
= NULL
;
147 RemoteRootWindowHostWin
* RemoteRootWindowHostWin::Instance() {
150 return Create(gfx::Rect());
153 RemoteRootWindowHostWin
* RemoteRootWindowHostWin::Create(
154 const gfx::Rect
& bounds
) {
155 g_instance
= g_instance
? g_instance
: new RemoteRootWindowHostWin(bounds
);
159 RemoteRootWindowHostWin::RemoteRootWindowHostWin(const gfx::Rect
& bounds
)
160 : remote_window_(NULL
),
162 ignore_mouse_moves_until_set_cursor_ack_(false),
164 window_size_(aura::RootWindowHost::GetNativeScreenSize()) {
165 prop_
.reset(new ui::ViewProp(NULL
, kRootWindowHostWinKey
, this));
166 CreateCompositor(GetAcceleratedWidget());
169 RemoteRootWindowHostWin::~RemoteRootWindowHostWin() {
173 void RemoteRootWindowHostWin::Connected(IPC::Sender
* host
, HWND remote_window
) {
174 CHECK(host_
== NULL
);
176 remote_window_
= remote_window
;
177 // Recreate the compositor for the target surface represented by the
178 // remote_window HWND.
179 CreateCompositor(remote_window_
);
183 void RemoteRootWindowHostWin::Disconnected() {
184 // Don't CHECK here, Disconnected is called on a channel error which can
185 // happen before we're successfully Connected.
188 ui::RemoteInputMethodPrivateWin
* remote_input_method_private
=
189 GetRemoteInputMethodPrivate();
190 if (remote_input_method_private
)
191 remote_input_method_private
->SetRemoteDelegate(NULL
);
193 remote_window_
= NULL
;
196 bool RemoteRootWindowHostWin::OnMessageReceived(const IPC::Message
& message
) {
198 IPC_BEGIN_MESSAGE_MAP(RemoteRootWindowHostWin
, message
)
199 IPC_MESSAGE_HANDLER(MetroViewerHostMsg_MouseMoved
, OnMouseMoved
)
200 IPC_MESSAGE_HANDLER(MetroViewerHostMsg_MouseButton
, OnMouseButton
)
201 IPC_MESSAGE_HANDLER(MetroViewerHostMsg_KeyDown
, OnKeyDown
)
202 IPC_MESSAGE_HANDLER(MetroViewerHostMsg_KeyUp
, OnKeyUp
)
203 IPC_MESSAGE_HANDLER(MetroViewerHostMsg_Character
, OnChar
)
204 IPC_MESSAGE_HANDLER(MetroViewerHostMsg_WindowActivated
,
206 IPC_MESSAGE_HANDLER(MetroViewerHostMsg_TouchDown
,
208 IPC_MESSAGE_HANDLER(MetroViewerHostMsg_TouchUp
,
210 IPC_MESSAGE_HANDLER(MetroViewerHostMsg_TouchMoved
,
212 IPC_MESSAGE_HANDLER(MetroViewerHostMsg_FileSaveAsDone
,
214 IPC_MESSAGE_HANDLER(MetroViewerHostMsg_FileOpenDone
,
216 IPC_MESSAGE_HANDLER(MetroViewerHostMsg_MultiFileOpenDone
,
218 IPC_MESSAGE_HANDLER(MetroViewerHostMsg_SelectFolderDone
,
220 IPC_MESSAGE_HANDLER(MetroViewerHostMsg_SetCursorPosAck
,
222 IPC_MESSAGE_HANDLER(MetroViewerHostMsg_ImeCandidatePopupChanged
,
223 OnImeCandidatePopupChanged
)
224 IPC_MESSAGE_HANDLER(MetroViewerHostMsg_ImeCompositionChanged
,
225 OnImeCompositionChanged
)
226 IPC_MESSAGE_HANDLER(MetroViewerHostMsg_ImeTextCommitted
,
228 IPC_MESSAGE_HANDLER(MetroViewerHostMsg_ImeInputSourceChanged
,
229 OnImeInputSourceChanged
)
230 IPC_MESSAGE_UNHANDLED(handled
= false)
231 IPC_END_MESSAGE_MAP()
235 void RemoteRootWindowHostWin::HandleOpenURLOnDesktop(
236 const base::FilePath
& shortcut
,
237 const base::string16
& url
) {
240 host_
->Send(new MetroViewerHostMsg_OpenURLOnDesktop(shortcut
, url
));
243 void RemoteRootWindowHostWin::HandleActivateDesktop(
244 const base::FilePath
& shortcut
,
248 host_
->Send(new MetroViewerHostMsg_ActivateDesktop(shortcut
, ash_exit
));
251 void RemoteRootWindowHostWin::HandleOpenFile(
252 const base::string16
& title
,
253 const base::FilePath
& default_path
,
254 const base::string16
& filter
,
255 const OpenFileCompletion
& on_success
,
256 const FileSelectionCanceled
& on_failure
) {
260 // Can only have one of these operations in flight.
261 DCHECK(file_open_completion_callback_
.is_null());
262 DCHECK(failure_callback_
.is_null());
264 file_open_completion_callback_
= on_success
;
265 failure_callback_
= on_failure
;
267 host_
->Send(new MetroViewerHostMsg_DisplayFileOpen(title
,
273 void RemoteRootWindowHostWin::HandleOpenMultipleFiles(
274 const base::string16
& title
,
275 const base::FilePath
& default_path
,
276 const base::string16
& filter
,
277 const OpenMultipleFilesCompletion
& on_success
,
278 const FileSelectionCanceled
& on_failure
) {
282 // Can only have one of these operations in flight.
283 DCHECK(multi_file_open_completion_callback_
.is_null());
284 DCHECK(failure_callback_
.is_null());
285 multi_file_open_completion_callback_
= on_success
;
286 failure_callback_
= on_failure
;
288 host_
->Send(new MetroViewerHostMsg_DisplayFileOpen(title
,
294 void RemoteRootWindowHostWin::HandleSaveFile(
295 const base::string16
& title
,
296 const base::FilePath
& default_path
,
297 const base::string16
& filter
,
299 const base::string16
& default_extension
,
300 const SaveFileCompletion
& on_success
,
301 const FileSelectionCanceled
& on_failure
) {
305 MetroViewerHostMsg_SaveAsDialogParams params
;
306 params
.title
= title
;
307 params
.default_extension
= default_extension
;
308 params
.filter
= filter
;
309 params
.filter_index
= filter_index
;
310 params
.suggested_name
= default_path
;
312 // Can only have one of these operations in flight.
313 DCHECK(file_saveas_completion_callback_
.is_null());
314 DCHECK(failure_callback_
.is_null());
315 file_saveas_completion_callback_
= on_success
;
316 failure_callback_
= on_failure
;
318 host_
->Send(new MetroViewerHostMsg_DisplayFileSaveAs(params
));
321 void RemoteRootWindowHostWin::HandleSelectFolder(
322 const base::string16
& title
,
323 const SelectFolderCompletion
& on_success
,
324 const FileSelectionCanceled
& on_failure
) {
328 // Can only have one of these operations in flight.
329 DCHECK(select_folder_completion_callback_
.is_null());
330 DCHECK(failure_callback_
.is_null());
331 select_folder_completion_callback_
= on_success
;
332 failure_callback_
= on_failure
;
334 host_
->Send(new MetroViewerHostMsg_DisplaySelectFolder(title
));
337 void RemoteRootWindowHostWin::HandleWindowSizeChanged(uint32 width
,
339 SetBounds(gfx::Rect(0, 0, width
, height
));
342 bool RemoteRootWindowHostWin::IsForegroundWindow() {
343 return ::GetForegroundWindow() == remote_window_
;
346 Window
* RemoteRootWindowHostWin::GetAshWindow() {
347 return GetRootWindow()->window();
350 RootWindow
* RemoteRootWindowHostWin::GetRootWindow() {
351 return delegate_
->AsRootWindow();
354 gfx::AcceleratedWidget
RemoteRootWindowHostWin::GetAcceleratedWidget() {
356 return remote_window_
;
357 // Getting here should only happen for ash_unittests.exe and related code.
358 return ::GetDesktopWindow();
361 void RemoteRootWindowHostWin::Show() {
362 ui::RemoteInputMethodPrivateWin
* remote_input_method_private
=
363 GetRemoteInputMethodPrivate();
364 if (remote_input_method_private
)
365 remote_input_method_private
->SetRemoteDelegate(this);
368 void RemoteRootWindowHostWin::Hide() {
372 void RemoteRootWindowHostWin::ToggleFullScreen() {
375 gfx::Rect
RemoteRootWindowHostWin::GetBounds() const {
376 return gfx::Rect(window_size_
);
379 void RemoteRootWindowHostWin::SetBounds(const gfx::Rect
& bounds
) {
380 window_size_
= bounds
.size();
381 NotifyHostResized(bounds
.size());
384 gfx::Insets
RemoteRootWindowHostWin::GetInsets() const {
385 return gfx::Insets();
388 void RemoteRootWindowHostWin::SetInsets(const gfx::Insets
& insets
) {
391 gfx::Point
RemoteRootWindowHostWin::GetLocationOnNativeScreen() const {
392 return gfx::Point(0, 0);
395 void RemoteRootWindowHostWin::SetCursor(gfx::NativeCursor native_cursor
) {
399 new MetroViewerHostMsg_SetCursor(uint64(native_cursor
.platform())));
402 void RemoteRootWindowHostWin::SetCapture() {
405 void RemoteRootWindowHostWin::ReleaseCapture() {
408 bool RemoteRootWindowHostWin::QueryMouseLocation(gfx::Point
* location_return
) {
409 aura::client::CursorClient
* cursor_client
=
410 aura::client::GetCursorClient(GetRootWindow()->window());
411 if (cursor_client
&& !cursor_client
->IsMouseEventsEnabled()) {
412 *location_return
= gfx::Point(0, 0);
418 gfx::Point(static_cast<int>(pt
.x
), static_cast<int>(pt
.y
));
422 bool RemoteRootWindowHostWin::ConfineCursorToRootWindow() {
426 void RemoteRootWindowHostWin::UnConfineCursor() {
429 void RemoteRootWindowHostWin::OnCursorVisibilityChanged(bool show
) {
433 void RemoteRootWindowHostWin::MoveCursorTo(const gfx::Point
& location
) {
434 VLOG(1) << "In MoveCursorTo: " << location
.x() << ", " << location
.y();
438 // This function can be called in cases like when the mouse cursor is
439 // restricted within a viewport (For e.g. LockCursor) which assumes that
440 // subsequent mouse moves would be received starting with the new cursor
441 // coordinates. This is a challenge for Windows ASH for the reasons
443 // Other cases which don't expect this behavior should continue to work
446 // The mouse events are received by the viewer process and sent to the
447 // browser. If we invoke the SetCursor API here we continue to receive
448 // mouse messages from the viewer which were posted before the SetCursor
449 // API executes which messes up the state in the browser. To workaround
450 // this we invoke the SetCursor API in the viewer process and ignore
451 // mouse messages until we received an ACK from the viewer indicating that
452 // the SetCursor operation completed.
453 ignore_mouse_moves_until_set_cursor_ack_
= true;
454 VLOG(1) << "In MoveCursorTo. Sending IPC";
455 host_
->Send(new MetroViewerHostMsg_SetCursorPos(location
.x(), location
.y()));
458 void RemoteRootWindowHostWin::PostNativeEvent(
459 const base::NativeEvent
& native_event
) {
462 void RemoteRootWindowHostWin::OnDeviceScaleFactorChanged(
463 float device_scale_factor
) {
467 void RemoteRootWindowHostWin::PrepareForShutdown() {
470 void RemoteRootWindowHostWin::CancelComposition() {
471 host_
->Send(new MetroViewerHostMsg_ImeCancelComposition
);
474 void RemoteRootWindowHostWin::OnTextInputClientUpdated(
475 const std::vector
<int32
>& input_scopes
,
476 const std::vector
<gfx::Rect
>& composition_character_bounds
) {
477 std::vector
<metro_viewer::CharacterBounds
> character_bounds
;
478 for (size_t i
= 0; i
< composition_character_bounds
.size(); ++i
) {
479 const gfx::Rect
& rect
= composition_character_bounds
[i
];
480 metro_viewer::CharacterBounds bounds
;
481 bounds
.left
= rect
.x();
482 bounds
.top
= rect
.y();
483 bounds
.right
= rect
.right();
484 bounds
.bottom
= rect
.bottom();
485 character_bounds
.push_back(bounds
);
487 host_
->Send(new MetroViewerHostMsg_ImeTextInputClientUpdated(
488 input_scopes
, character_bounds
));
491 gfx::Point
PointFromNativeEvent(int32 x
, int32 y
) {
492 static float scale_factor
= gfx::GetModernUIScale();
493 gfx::Point
result( x
* scale_factor
, y
* scale_factor
);
497 void RemoteRootWindowHostWin::OnMouseMoved(int32 x
, int32 y
, int32 flags
) {
498 if (ignore_mouse_moves_until_set_cursor_ack_
)
501 gfx::Point location
= PointFromNativeEvent(x
, y
);
502 ui::MouseEvent
event(ui::ET_MOUSE_MOVED
, location
, location
, flags
, 0);
503 delegate_
->OnHostMouseEvent(&event
);
506 void RemoteRootWindowHostWin::OnMouseButton(
507 const MetroViewerHostMsg_MouseButtonParams
& params
) {
508 gfx::Point location
= PointFromNativeEvent(params
.x
, params
.y
);
509 ui::MouseEvent
mouse_event(params
.event_type
, location
, location
,
510 static_cast<int>(params
.flags
),
511 static_cast<int>(params
.changed_button
));
513 SetEventFlags(params
.flags
| key_event_flags());
514 if (params
.event_type
== ui::ET_MOUSEWHEEL
) {
515 ui::MouseWheelEvent
wheel_event(mouse_event
, 0, params
.extra
);
516 delegate_
->OnHostMouseEvent(&wheel_event
);
517 } else if (params
.event_type
== ui::ET_MOUSE_PRESSED
) {
518 // TODO(shrikant): Ideally modify code in event.cc by adding automatic
519 // tracking of double clicks in synthetic MouseEvent constructor code.
520 // Non-synthetic MouseEvent constructor code does automatically track
521 // this. Need to use some caution while modifying synthetic constructor
522 // as many tests and other code paths depend on it and apparently
523 // specifically depend on non implicit tracking of previous mouse event.
524 if (last_mouse_click_event_
&&
525 ui::MouseEvent::IsRepeatedClickEvent(mouse_event
,
526 *last_mouse_click_event_
)) {
527 mouse_event
.SetClickCount(2);
529 mouse_event
.SetClickCount(1);
531 last_mouse_click_event_
.reset(new ui::MouseEvent(mouse_event
));
532 delegate_
->OnHostMouseEvent(&mouse_event
);
534 delegate_
->OnHostMouseEvent(&mouse_event
);
538 void RemoteRootWindowHostWin::OnKeyDown(uint32 vkey
,
542 DispatchKeyboardMessage(ui::ET_KEY_PRESSED
, vkey
, repeat_count
, scan_code
,
546 void RemoteRootWindowHostWin::OnKeyUp(uint32 vkey
,
550 DispatchKeyboardMessage(ui::ET_KEY_RELEASED
, vkey
, repeat_count
, scan_code
,
554 void RemoteRootWindowHostWin::OnChar(uint32 key_code
,
558 DispatchKeyboardMessage(ui::ET_KEY_PRESSED
, key_code
, repeat_count
,
559 scan_code
, flags
, true);
562 void RemoteRootWindowHostWin::OnWindowActivated() {
563 delegate_
->OnHostActivated();
566 void RemoteRootWindowHostWin::OnTouchDown(int32 x
,
570 gfx::Point location
= PointFromNativeEvent(x
, y
);
571 ui::TouchEvent
event(ui::ET_TOUCH_PRESSED
,
574 base::TimeDelta::FromMicroseconds(timestamp
));
575 delegate_
->OnHostTouchEvent(&event
);
578 void RemoteRootWindowHostWin::OnTouchUp(int32 x
,
582 gfx::Point location
= PointFromNativeEvent(x
, y
);
583 ui::TouchEvent
event(ui::ET_TOUCH_RELEASED
,
586 base::TimeDelta::FromMicroseconds(timestamp
));
587 delegate_
->OnHostTouchEvent(&event
);
590 void RemoteRootWindowHostWin::OnTouchMoved(int32 x
,
594 gfx::Point location
= PointFromNativeEvent(x
, y
);
595 ui::TouchEvent
event(ui::ET_TOUCH_MOVED
,
598 base::TimeDelta::FromMicroseconds(timestamp
));
599 delegate_
->OnHostTouchEvent(&event
);
602 void RemoteRootWindowHostWin::OnFileSaveAsDone(bool success
,
603 const base::FilePath
& filename
,
606 file_saveas_completion_callback_
.Run(filename
, filter_index
, NULL
);
608 failure_callback_
.Run(NULL
);
609 file_saveas_completion_callback_
.Reset();
610 failure_callback_
.Reset();
614 void RemoteRootWindowHostWin::OnFileOpenDone(bool success
,
615 const base::FilePath
& filename
) {
617 file_open_completion_callback_
.Run(base::FilePath(filename
), 0, NULL
);
619 failure_callback_
.Run(NULL
);
620 file_open_completion_callback_
.Reset();
621 failure_callback_
.Reset();
624 void RemoteRootWindowHostWin::OnMultiFileOpenDone(
626 const std::vector
<base::FilePath
>& files
) {
628 multi_file_open_completion_callback_
.Run(files
, NULL
);
630 failure_callback_
.Run(NULL
);
631 multi_file_open_completion_callback_
.Reset();
632 failure_callback_
.Reset();
635 void RemoteRootWindowHostWin::OnSelectFolderDone(
637 const base::FilePath
& folder
) {
639 select_folder_completion_callback_
.Run(base::FilePath(folder
), 0, NULL
);
641 failure_callback_
.Run(NULL
);
642 select_folder_completion_callback_
.Reset();
643 failure_callback_
.Reset();
646 void RemoteRootWindowHostWin::OnSetCursorPosAck() {
647 DCHECK(ignore_mouse_moves_until_set_cursor_ack_
);
648 ignore_mouse_moves_until_set_cursor_ack_
= false;
651 ui::RemoteInputMethodPrivateWin
*
652 RemoteRootWindowHostWin::GetRemoteInputMethodPrivate() {
653 ui::InputMethod
* input_method
= GetAshWindow()->GetProperty(
654 aura::client::kRootWindowInputMethodKey
);
655 return ui::RemoteInputMethodPrivateWin::Get(input_method
);
658 void RemoteRootWindowHostWin::OnImeCandidatePopupChanged(bool visible
) {
659 ui::RemoteInputMethodPrivateWin
* remote_input_method_private
=
660 GetRemoteInputMethodPrivate();
661 if (!remote_input_method_private
)
663 remote_input_method_private
->OnCandidatePopupChanged(visible
);
666 void RemoteRootWindowHostWin::OnImeCompositionChanged(
667 const base::string16
& text
,
668 int32 selection_start
,
670 const std::vector
<metro_viewer::UnderlineInfo
>& underlines
) {
671 ui::RemoteInputMethodPrivateWin
* remote_input_method_private
=
672 GetRemoteInputMethodPrivate();
673 if (!remote_input_method_private
)
675 ui::CompositionText composition_text
;
677 text
, selection_start
, selection_end
, underlines
, &composition_text
);
678 remote_input_method_private
->OnCompositionChanged(composition_text
);
681 void RemoteRootWindowHostWin::OnImeTextCommitted(const base::string16
& text
) {
682 ui::RemoteInputMethodPrivateWin
* remote_input_method_private
=
683 GetRemoteInputMethodPrivate();
684 if (!remote_input_method_private
)
686 remote_input_method_private
->OnTextCommitted(text
);
689 void RemoteRootWindowHostWin::OnImeInputSourceChanged(uint16 language_id
,
691 ui::RemoteInputMethodPrivateWin
* remote_input_method_private
=
692 GetRemoteInputMethodPrivate();
693 if (!remote_input_method_private
)
695 remote_input_method_private
->OnInputSourceChanged(language_id
, is_ime
);
698 void RemoteRootWindowHostWin::DispatchKeyboardMessage(ui::EventType type
,
704 SetEventFlags(flags
| mouse_event_flags());
705 if (base::MessageLoop::current()->IsNested()) {
706 int index
= (flags
& ui::EF_ALT_DOWN
) ? 1 : 0;
707 const int char_message
[] = {WM_CHAR
, WM_SYSCHAR
};
708 const int keydown_message
[] = {WM_KEYDOWN
, WM_SYSKEYDOWN
};
709 const int keyup_message
[] = {WM_KEYUP
, WM_SYSKEYUP
};
710 uint32 message
= is_character
711 ? char_message
[index
]
712 : (type
== ui::ET_KEY_PRESSED
? keydown_message
[index
]
713 : keyup_message
[index
]);
714 ::PostThreadMessage(::GetCurrentThreadId(),
717 repeat_count
| scan_code
>> 15);
719 ui::KeyEvent
event(type
,
720 ui::KeyboardCodeForWindowsKeyCode(vkey
),
723 delegate_
->OnHostKeyEvent(&event
);
727 void RemoteRootWindowHostWin::SetEventFlags(uint32 flags
) {
728 if (flags
== event_flags_
)
730 event_flags_
= flags
;
731 SetVirtualKeyStates(event_flags_
);