1// Copyright 2013 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 "mojo/services/native_viewport/native_viewport.h" 6 7#include "ui/events/event.h" 8#include "ui/gfx/win/msg_util.h" 9#include "ui/gfx/win/window_impl.h" 10 11namespace mojo { 12namespace services { 13namespace { 14 15gfx::Rect GetWindowBoundsForClientBounds(DWORD style, DWORD ex_style, 16 const gfx::Rect& bounds) { 17 RECT wr; 18 wr.left = bounds.x(); 19 wr.top = bounds.y(); 20 wr.right = bounds.x() + bounds.width(); 21 wr.bottom = bounds.y() + bounds.height(); 22 AdjustWindowRectEx(&wr, style, FALSE, ex_style); 23 24 // Make sure to keep the window onscreen, as AdjustWindowRectEx() may have 25 // moved part of it offscreen. 26 gfx::Rect window_bounds(wr.left, wr.top, 27 wr.right - wr.left, wr.bottom - wr.top); 28 window_bounds.set_x(std::max(0, window_bounds.x())); 29 window_bounds.set_y(std::max(0, window_bounds.y())); 30 return window_bounds; 31} 32 33} 34 35class NativeViewportWin : public gfx::WindowImpl, 36 public NativeViewport { 37 public: 38 explicit NativeViewportWin(NativeViewportDelegate* delegate) 39 : delegate_(delegate) { 40 } 41 virtual ~NativeViewportWin() { 42 if (IsWindow(hwnd())) 43 DestroyWindow(hwnd()); 44 } 45 46 private: 47 // Overridden from NativeViewport: 48 virtual void Init(const gfx::Rect& bounds) OVERRIDE { 49 gfx::Rect window_bounds = GetWindowBoundsForClientBounds( 50 WS_OVERLAPPEDWINDOW, window_ex_style(), bounds); 51 gfx::WindowImpl::Init(NULL, window_bounds); 52 SetWindowText(hwnd(), L"native_viewport::NativeViewportWin!"); 53 } 54 55 virtual void Show() OVERRIDE { 56 ShowWindow(hwnd(), SW_SHOWNORMAL); 57 } 58 59 virtual void Hide() OVERRIDE { 60 ShowWindow(hwnd(), SW_HIDE); 61 } 62 63 virtual void Close() OVERRIDE { 64 DestroyWindow(hwnd()); 65 } 66 67 virtual gfx::Size GetSize() OVERRIDE { 68 RECT cr; 69 GetClientRect(hwnd(), &cr); 70 return gfx::Size(cr.right - cr.left, cr.bottom - cr.top); 71 } 72 73 virtual void SetBounds(const gfx::Rect& bounds) OVERRIDE { 74 gfx::Rect window_bounds = GetWindowBoundsForClientBounds( 75 GetWindowLong(hwnd(), GWL_STYLE), 76 GetWindowLong(hwnd(), GWL_EXSTYLE), 77 bounds); 78 SetWindowPos(hwnd(), NULL, window_bounds.x(), window_bounds.y(), 79 window_bounds.width(), window_bounds.height(), 80 SWP_NOREPOSITION); 81 } 82 83 virtual void SetCapture() OVERRIDE { 84 DCHECK(::GetCapture() != hwnd()); 85 ::SetCapture(hwnd()); 86 } 87 88 virtual void ReleaseCapture() OVERRIDE { 89 if (::GetCapture() == hwnd()) 90 ::ReleaseCapture(); 91 } 92 93 CR_BEGIN_MSG_MAP_EX(NativeViewportWin) 94 CR_MESSAGE_RANGE_HANDLER_EX(WM_MOUSEFIRST, WM_MOUSELAST, OnMouseRange) 95 96 CR_MESSAGE_HANDLER_EX(WM_KEYDOWN, OnKeyEvent) 97 CR_MESSAGE_HANDLER_EX(WM_KEYUP, OnKeyEvent) 98 CR_MESSAGE_HANDLER_EX(WM_SYSKEYDOWN, OnKeyEvent) 99 CR_MESSAGE_HANDLER_EX(WM_SYSKEYUP, OnKeyEvent) 100 CR_MESSAGE_HANDLER_EX(WM_CHAR, OnKeyEvent) 101 CR_MESSAGE_HANDLER_EX(WM_SYSCHAR, OnKeyEvent) 102 CR_MESSAGE_HANDLER_EX(WM_IME_CHAR, OnKeyEvent) 103 104 CR_MSG_WM_CREATE(OnCreate) 105 CR_MSG_WM_DESTROY(OnDestroy) 106 CR_MSG_WM_PAINT(OnPaint) 107 CR_MSG_WM_WINDOWPOSCHANGED(OnWindowPosChanged) 108 CR_END_MSG_MAP() 109 110 LRESULT OnMouseRange(UINT message, WPARAM w_param, LPARAM l_param) { 111 MSG msg = { hwnd(), message, w_param, l_param, 0, 112 { CR_GET_X_LPARAM(l_param), CR_GET_Y_LPARAM(l_param) } }; 113 ui::MouseEvent event(msg); 114 SetMsgHandled(delegate_->OnEvent(&event)); 115 return 0; 116 } 117 LRESULT OnKeyEvent(UINT message, WPARAM w_param, LPARAM l_param) { 118 MSG msg = { hwnd(), message, w_param, l_param }; 119 ui::KeyEvent event(msg, message == WM_CHAR); 120 SetMsgHandled(delegate_->OnEvent(&event)); 121 return 0; 122 } 123 LRESULT OnCreate(CREATESTRUCT* create_struct) { 124 delegate_->OnAcceleratedWidgetAvailable(hwnd()); 125 return 0; 126 } 127 void OnDestroy() { 128 delegate_->OnDestroyed(); 129 } 130 void OnPaint(HDC) { 131 RECT cr; 132 GetClientRect(hwnd(), &cr); 133 134 PAINTSTRUCT ps; 135 HDC dc = BeginPaint(hwnd(), &ps); 136 HBRUSH red_brush = CreateSolidBrush(RGB(255, 0, 0)); 137 HGDIOBJ old_object = SelectObject(dc, red_brush); 138 Rectangle(dc, cr.left, cr.top, cr.right, cr.bottom); 139 SelectObject(dc, old_object); 140 DeleteObject(red_brush); 141 EndPaint(hwnd(), &ps); 142 } 143 void OnWindowPosChanged(WINDOWPOS* window_pos) { 144 if (!(window_pos->flags & SWP_NOSIZE) || 145 !(window_pos->flags & SWP_NOMOVE)) { 146 RECT cr; 147 GetClientRect(hwnd(), &cr); 148 delegate_->OnBoundsChanged( 149 gfx::Rect(window_pos->x, window_pos->y, 150 cr.right - cr.left, cr.bottom - cr.top)); 151 } 152 } 153 154 NativeViewportDelegate* delegate_; 155 156 DISALLOW_COPY_AND_ASSIGN(NativeViewportWin); 157}; 158 159// static 160scoped_ptr<NativeViewport> NativeViewport::Create( 161 shell::Context* context, 162 NativeViewportDelegate* delegate) { 163 return scoped_ptr<NativeViewport>(new NativeViewportWin(delegate)).Pass(); 164} 165 166} // namespace services 167} // namespace mojo 168