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.h"
12 #include "ipc/ipc_message.h"
13 #include "ipc/ipc_sender.h"
14 #include "ui/aura/client/capture_client.h"
15 #include "ui/aura/root_window.h"
16 #include "ui/base/cursor/cursor_loader_win.h"
17 #include "ui/base/events/event.h"
18 #include "ui/base/events/event_utils.h"
19 #include "ui/base/keycodes/keyboard_code_conversion_win.h"
20 #include "ui/base/view_prop.h"
21 #include "ui/gfx/insets.h"
22 #include "ui/metro_viewer/metro_viewer_messages.h"
28 const char* kRootWindowHostWinKey
= "__AURA_REMOTE_ROOT_WINDOW_HOST_WIN__";
30 // Sets the keystate for the virtual key passed in to down or up.
31 void SetKeyState(uint8
* key_states
, bool key_down
, uint32 virtual_key_code
) {
35 key_states
[virtual_key_code
] |= 0x80;
37 key_states
[virtual_key_code
] &= 0x7F;
40 // Sets the keyboard states for the Shift/Control/Alt/Caps lock keys.
41 void SetVirtualKeyStates(uint32 flags
) {
42 uint8 keyboard_state
[256] = {0};
43 ::GetKeyboardState(keyboard_state
);
45 SetKeyState(keyboard_state
, !!(flags
& ui::EF_SHIFT_DOWN
), VK_SHIFT
);
46 SetKeyState(keyboard_state
, !!(flags
& ui::EF_CONTROL_DOWN
), VK_CONTROL
);
47 SetKeyState(keyboard_state
, !!(flags
& ui::EF_ALT_DOWN
), VK_MENU
);
48 SetKeyState(keyboard_state
, !!(flags
& ui::EF_CAPS_LOCK_DOWN
), VK_CAPITAL
);
50 ::SetKeyboardState(keyboard_state
);
56 const string16
& title
,
57 const base::FilePath
& default_path
,
58 const string16
& filter
,
59 const OpenFileCompletion
& callback
) {
60 DCHECK(aura::RemoteRootWindowHostWin::Instance());
61 aura::RemoteRootWindowHostWin::Instance()->HandleOpenFile(title
,
67 void HandleOpenMultipleFiles(
68 const string16
& title
,
69 const base::FilePath
& default_path
,
70 const string16
& filter
,
71 const OpenMultipleFilesCompletion
& callback
) {
72 DCHECK(aura::RemoteRootWindowHostWin::Instance());
73 aura::RemoteRootWindowHostWin::Instance()->HandleOpenMultipleFiles(
81 const string16
& title
,
82 const base::FilePath
& default_path
,
83 const string16
& filter
,
85 const string16
& default_extension
,
86 const SaveFileCompletion
& callback
) {
87 DCHECK(aura::RemoteRootWindowHostWin::Instance());
88 aura::RemoteRootWindowHostWin::Instance()->HandleSaveFile(title
,
96 RemoteRootWindowHostWin
* g_instance
= NULL
;
98 RemoteRootWindowHostWin
* RemoteRootWindowHostWin::Instance() {
102 RemoteRootWindowHostWin
* RemoteRootWindowHostWin::Create(
103 const gfx::Rect
& bounds
) {
104 g_instance
= new RemoteRootWindowHostWin(bounds
);
108 RemoteRootWindowHostWin::RemoteRootWindowHostWin(const gfx::Rect
& bounds
)
109 : delegate_(NULL
), host_(NULL
) {
110 prop_
.reset(new ui::ViewProp(NULL
, kRootWindowHostWinKey
, this));
113 RemoteRootWindowHostWin::~RemoteRootWindowHostWin() {
116 void RemoteRootWindowHostWin::Connected(IPC::Sender
* host
) {
117 CHECK(host_
== NULL
);
121 void RemoteRootWindowHostWin::Disconnected() {
122 CHECK(host_
!= NULL
);
126 bool RemoteRootWindowHostWin::OnMessageReceived(const IPC::Message
& message
) {
128 IPC_BEGIN_MESSAGE_MAP(RemoteRootWindowHostWin
, message
)
129 IPC_MESSAGE_HANDLER(MetroViewerHostMsg_MouseMoved
, OnMouseMoved
)
130 IPC_MESSAGE_HANDLER(MetroViewerHostMsg_MouseButton
, OnMouseButton
)
131 IPC_MESSAGE_HANDLER(MetroViewerHostMsg_KeyDown
, OnKeyDown
)
132 IPC_MESSAGE_HANDLER(MetroViewerHostMsg_KeyUp
, OnKeyUp
)
133 IPC_MESSAGE_HANDLER(MetroViewerHostMsg_Character
, OnChar
)
134 IPC_MESSAGE_HANDLER(MetroViewerHostMsg_VisibilityChanged
,
136 IPC_MESSAGE_HANDLER(MetroViewerHostMsg_TouchDown
,
138 IPC_MESSAGE_HANDLER(MetroViewerHostMsg_TouchUp
,
140 IPC_MESSAGE_HANDLER(MetroViewerHostMsg_TouchMoved
,
142 IPC_MESSAGE_HANDLER(MetroViewerHostMsg_FileSaveAsDone
,
144 IPC_MESSAGE_HANDLER(MetroViewerHostMsg_FileOpenDone
,
146 IPC_MESSAGE_HANDLER(MetroViewerHostMsg_MultiFileOpenDone
,
148 IPC_MESSAGE_UNHANDLED(handled
= false)
149 IPC_END_MESSAGE_MAP()
153 void RemoteRootWindowHostWin::HandleOpenFile(
154 const string16
& title
,
155 const base::FilePath
& default_path
,
156 const string16
& filter
,
157 const OpenFileCompletion
& callback
) {
161 // Can only one of these operations in flight.
162 DCHECK(file_open_completion_callback_
.is_null());
163 file_open_completion_callback_
= callback
;
165 host_
->Send(new MetroViewerHostMsg_DisplayFileOpen(title
,
167 default_path
.value(),
171 void RemoteRootWindowHostWin::HandleOpenMultipleFiles(
172 const string16
& title
,
173 const base::FilePath
& default_path
,
174 const string16
& filter
,
175 const OpenMultipleFilesCompletion
& callback
) {
179 // Can only one of these operations in flight.
180 DCHECK(multi_file_open_completion_callback_
.is_null());
181 multi_file_open_completion_callback_
= callback
;
183 host_
->Send(new MetroViewerHostMsg_DisplayFileOpen(title
,
185 default_path
.value(),
189 void RemoteRootWindowHostWin::HandleSaveFile(
190 const string16
& title
,
191 const base::FilePath
& default_path
,
192 const string16
& filter
,
194 const string16
& default_extension
,
195 const SaveFileCompletion
& callback
) {
199 MetroViewerHostMsg_SaveAsDialogParams params
;
200 params
.title
= title
;
201 params
.default_extension
= default_extension
;
202 params
.filter
= filter
;
203 params
.filter_index
= filter_index
;
205 // Can only one of these operations in flight.
206 DCHECK(file_saveas_completion_callback_
.is_null());
207 file_saveas_completion_callback_
= callback
;
209 host_
->Send(new MetroViewerHostMsg_DisplayFileSaveAs(params
));
212 void RemoteRootWindowHostWin::SetDelegate(RootWindowHostDelegate
* delegate
) {
213 delegate_
= delegate
;
216 RootWindow
* RemoteRootWindowHostWin::GetRootWindow() {
217 return delegate_
->AsRootWindow();
220 gfx::AcceleratedWidget
RemoteRootWindowHostWin::GetAcceleratedWidget() {
221 // TODO(cpu): This is bad. Chrome's compositor needs a valid window
222 // initially and then later on we swap it. Since the compositor never
223 // uses this initial window we tell ourselves this hack is ok to get
224 // thing off the ground.
225 return ::GetDesktopWindow();
228 void RemoteRootWindowHostWin::Show() {
231 void RemoteRootWindowHostWin::Hide() {
235 void RemoteRootWindowHostWin::ToggleFullScreen() {
238 gfx::Rect
RemoteRootWindowHostWin::GetBounds() const {
239 gfx::Rect
r(gfx::Point(0, 0), aura::RootWindowHost::GetNativeScreenSize());
243 void RemoteRootWindowHostWin::SetBounds(const gfx::Rect
& bounds
) {
244 delegate_
->OnHostResized(bounds
.size());
247 gfx::Insets
RemoteRootWindowHostWin::GetInsets() const {
248 return gfx::Insets();
251 void RemoteRootWindowHostWin::SetInsets(const gfx::Insets
& insets
) {
254 gfx::Point
RemoteRootWindowHostWin::GetLocationOnNativeScreen() const {
255 return gfx::Point(0, 0);
258 void RemoteRootWindowHostWin::SetCursor(gfx::NativeCursor native_cursor
) {
262 new MetroViewerHostMsg_SetCursor(uint64(native_cursor
.platform())));
265 void RemoteRootWindowHostWin::SetCapture() {
268 void RemoteRootWindowHostWin::ReleaseCapture() {
271 bool RemoteRootWindowHostWin::QueryMouseLocation(gfx::Point
* location_return
) {
275 gfx::Point(static_cast<int>(pt
.x
), static_cast<int>(pt
.y
));
279 bool RemoteRootWindowHostWin::ConfineCursorToRootWindow() {
283 bool RemoteRootWindowHostWin::CopyAreaToSkCanvas(const gfx::Rect
& source_bounds
,
284 const gfx::Point
& dest_offset
,
290 bool RemoteRootWindowHostWin::GrabSnapshot(
291 const gfx::Rect
& snapshot_bounds
,
292 std::vector
<unsigned char>* png_representation
) {
297 void RemoteRootWindowHostWin::UnConfineCursor() {
300 void RemoteRootWindowHostWin::OnCursorVisibilityChanged(bool show
) {
304 void RemoteRootWindowHostWin::MoveCursorTo(const gfx::Point
& location
) {
307 void RemoteRootWindowHostWin::SetFocusWhenShown(bool focus_when_shown
) {
311 void RemoteRootWindowHostWin::PostNativeEvent(
312 const base::NativeEvent
& native_event
) {
315 void RemoteRootWindowHostWin::OnDeviceScaleFactorChanged(
316 float device_scale_factor
) {
320 void RemoteRootWindowHostWin::PrepareForShutdown() {
323 void RemoteRootWindowHostWin::OnMouseMoved(int32 x
, int32 y
, int32 flags
) {
324 gfx::Point
location(x
, y
);
325 ui::MouseEvent
event(ui::ET_MOUSE_MOVED
, location
, location
, flags
);
326 delegate_
->OnHostMouseEvent(&event
);
329 void RemoteRootWindowHostWin::OnMouseButton(
330 int32 x
, int32 y
, int32 extra
, ui::EventType type
, ui::EventFlags flags
) {
331 gfx::Point
location(x
, y
);
332 ui::MouseEvent
mouse_event(type
, location
, location
, 0);
333 mouse_event
.set_flags(flags
);
335 if (type
== ui::ET_MOUSEWHEEL
) {
336 ui::MouseWheelEvent
wheel_event(mouse_event
, extra
);
337 delegate_
->OnHostMouseEvent(&wheel_event
);
339 mouse_event
.SetClickCount(1);
340 delegate_
->OnHostMouseEvent(&mouse_event
);
344 void RemoteRootWindowHostWin::OnKeyDown(uint32 vkey
,
348 DispatchKeyboardMessage(ui::ET_KEY_PRESSED
, vkey
, repeat_count
, scan_code
,
352 void RemoteRootWindowHostWin::OnKeyUp(uint32 vkey
,
356 DispatchKeyboardMessage(ui::ET_KEY_RELEASED
, vkey
, repeat_count
, scan_code
,
360 void RemoteRootWindowHostWin::OnChar(uint32 key_code
,
364 DispatchKeyboardMessage(ui::ET_KEY_PRESSED
, key_code
, repeat_count
,
365 scan_code
, flags
, true);
368 void RemoteRootWindowHostWin::OnVisibilityChanged(bool visible
) {
370 delegate_
->OnHostActivated();
373 void RemoteRootWindowHostWin::OnTouchDown(int32 x
,
377 ui::TouchEvent
event(ui::ET_TOUCH_PRESSED
,
380 base::TimeDelta::FromMicroseconds(timestamp
));
381 delegate_
->OnHostTouchEvent(&event
);
384 void RemoteRootWindowHostWin::OnTouchUp(int32 x
,
388 ui::TouchEvent
event(ui::ET_TOUCH_RELEASED
,
391 base::TimeDelta::FromMicroseconds(timestamp
));
392 delegate_
->OnHostTouchEvent(&event
);
395 void RemoteRootWindowHostWin::OnTouchMoved(int32 x
,
399 ui::TouchEvent
event(ui::ET_TOUCH_MOVED
,
402 base::TimeDelta::FromMicroseconds(timestamp
));
403 delegate_
->OnHostTouchEvent(&event
);
406 void RemoteRootWindowHostWin::OnFileSaveAsDone(bool success
,
410 file_saveas_completion_callback_
.Run(
411 base::FilePath(filename
), filter_index
, NULL
);
413 file_saveas_completion_callback_
.Reset();
417 void RemoteRootWindowHostWin::OnFileOpenDone(bool success
, string16 filename
) {
419 file_open_completion_callback_
.Run(
420 base::FilePath(filename
), 0, NULL
);
422 file_open_completion_callback_
.Reset();
425 void RemoteRootWindowHostWin::OnMultiFileOpenDone(
427 const std::vector
<base::FilePath
>& files
) {
429 multi_file_open_completion_callback_
.Run(files
, NULL
);
431 multi_file_open_completion_callback_
.Reset();
434 void RemoteRootWindowHostWin::DispatchKeyboardMessage(ui::EventType type
,
440 if (MessageLoop::current()->IsNested()) {
441 SetVirtualKeyStates(flags
);
443 uint32 message
= is_character
? WM_CHAR
:
444 (type
== ui::ET_KEY_PRESSED
? WM_KEYDOWN
: WM_KEYUP
);
445 ::PostThreadMessage(::GetCurrentThreadId(),
448 repeat_count
| scan_code
>> 15);
450 ui::KeyEvent
event(type
,
451 ui::KeyboardCodeForWindowsKeyCode(vkey
),
454 delegate_
->OnHostKeyEvent(&event
);