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