• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2015 The Chromium Embedded Framework Authors. All rights
2 // reserved. Use of this source code is governed by a BSD-style license that
3 // can be found in the LICENSE file.
4 
5 #include "tests/cefclient/browser/osr_window_win.h"
6 
7 #include <windowsx.h>
8 #if defined(CEF_USE_ATL)
9 #include <oleacc.h>
10 #endif
11 
12 #include "include/base/cef_build.h"
13 #include "tests/cefclient/browser/main_context.h"
14 #include "tests/cefclient/browser/osr_accessibility_helper.h"
15 #include "tests/cefclient/browser/osr_accessibility_node.h"
16 #include "tests/cefclient/browser/osr_ime_handler_win.h"
17 #include "tests/cefclient/browser/osr_render_handler_win_d3d11.h"
18 #include "tests/cefclient/browser/osr_render_handler_win_gl.h"
19 #include "tests/cefclient/browser/resource.h"
20 #include "tests/shared/browser/geometry_util.h"
21 #include "tests/shared/browser/main_message_loop.h"
22 #include "tests/shared/browser/util_win.h"
23 
24 namespace client {
25 
26 namespace {
27 
28 const wchar_t kWndClass[] = L"Client_OsrWindow";
29 
30 // Helper funtion to check if it is Windows8 or greater.
31 // https://msdn.microsoft.com/en-us/library/ms724833(v=vs.85).aspx
IsWindows_8_Or_Newer()32 inline BOOL IsWindows_8_Or_Newer() {
33   OSVERSIONINFOEX osvi = {0};
34   osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
35   osvi.dwMajorVersion = 6;
36   osvi.dwMinorVersion = 2;
37   DWORDLONG dwlConditionMask = 0;
38   VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL);
39   VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, VER_GREATER_EQUAL);
40   return ::VerifyVersionInfo(&osvi, VER_MAJORVERSION | VER_MINORVERSION,
41                              dwlConditionMask);
42 }
43 
44 // Helper function to detect mouse messages coming from emulation of touch
45 // events. These should be ignored.
IsMouseEventFromTouch(UINT message)46 bool IsMouseEventFromTouch(UINT message) {
47 #define MOUSEEVENTF_FROMTOUCH 0xFF515700
48   return (message >= WM_MOUSEFIRST) && (message <= WM_MOUSELAST) &&
49          (GetMessageExtraInfo() & MOUSEEVENTF_FROMTOUCH) ==
50              MOUSEEVENTF_FROMTOUCH;
51 }
52 
53 class CreateBrowserHelper {
54  public:
CreateBrowserHelper(HWND hwnd,const RECT & rect,CefRefPtr<CefClient> handler,const std::string & url,const CefBrowserSettings & settings,CefRefPtr<CefDictionaryValue> extra_info,CefRefPtr<CefRequestContext> request_context,OsrWindowWin * osr_window_win)55   CreateBrowserHelper(HWND hwnd,
56                       const RECT& rect,
57                       CefRefPtr<CefClient> handler,
58                       const std::string& url,
59                       const CefBrowserSettings& settings,
60                       CefRefPtr<CefDictionaryValue> extra_info,
61                       CefRefPtr<CefRequestContext> request_context,
62                       OsrWindowWin* osr_window_win)
63       : hwnd_(hwnd),
64         rect_(rect),
65         handler_(handler),
66         url_(url),
67         settings_(settings),
68         extra_info_(extra_info),
69         request_context_(request_context),
70         osr_window_win_(osr_window_win) {}
71 
72   HWND hwnd_;
73   RECT rect_;
74   CefRefPtr<CefClient> handler_;
75   std::string url_;
76   CefBrowserSettings settings_;
77   CefRefPtr<CefDictionaryValue> extra_info_;
78   CefRefPtr<CefRequestContext> request_context_;
79   OsrWindowWin* osr_window_win_;
80 };
81 
82 }  // namespace
83 
OsrWindowWin(Delegate * delegate,const OsrRendererSettings & settings)84 OsrWindowWin::OsrWindowWin(Delegate* delegate,
85                            const OsrRendererSettings& settings)
86     : delegate_(delegate),
87       settings_(settings),
88       hwnd_(NULL),
89       device_scale_factor_(0),
90       hidden_(false),
91       last_mouse_pos_(),
92       current_mouse_pos_(),
93       mouse_rotation_(false),
94       mouse_tracking_(false),
95       last_click_x_(0),
96       last_click_y_(0),
97       last_click_button_(MBT_LEFT),
98       last_click_count_(1),
99       last_click_time_(0),
100       last_mouse_down_on_view_(false) {
101   DCHECK(delegate_);
102   client_rect_ = {0};
103 }
104 
~OsrWindowWin()105 OsrWindowWin::~OsrWindowWin() {
106   CEF_REQUIRE_UI_THREAD();
107   // The native window should have already been destroyed.
108   DCHECK(!hwnd_ && !render_handler_.get());
109 }
110 
CreateBrowserWithHelper(CreateBrowserHelper * helper)111 void CreateBrowserWithHelper(CreateBrowserHelper* helper) {
112   helper->osr_window_win_->CreateBrowser(
113       helper->hwnd_, helper->rect_, helper->handler_, helper->settings_,
114       helper->extra_info_, helper->request_context_, helper->url_);
115   delete helper;
116 }
117 
CreateBrowser(HWND parent_hwnd,const RECT & rect,CefRefPtr<CefClient> handler,const CefBrowserSettings & settings,CefRefPtr<CefDictionaryValue> extra_info,CefRefPtr<CefRequestContext> request_context,const std::string & startup_url)118 void OsrWindowWin::CreateBrowser(HWND parent_hwnd,
119                                  const RECT& rect,
120                                  CefRefPtr<CefClient> handler,
121                                  const CefBrowserSettings& settings,
122                                  CefRefPtr<CefDictionaryValue> extra_info,
123                                  CefRefPtr<CefRequestContext> request_context,
124                                  const std::string& startup_url) {
125   if (!CefCurrentlyOn(TID_UI)) {
126     // Execute this method on the UI thread.
127     CreateBrowserHelper* helper =
128         new CreateBrowserHelper(parent_hwnd, rect, handler, startup_url,
129                                 settings, extra_info, request_context, this);
130     CefPostTask(TID_UI, base::Bind(CreateBrowserWithHelper, helper));
131     return;
132   }
133 
134   // Create the native window.
135   Create(parent_hwnd, rect);
136 
137   CefWindowInfo window_info;
138   window_info.SetAsWindowless(hwnd_);
139 
140   if (GetWindowLongPtr(parent_hwnd, GWL_EXSTYLE) & WS_EX_NOACTIVATE) {
141     // Don't activate the browser window on creation.
142     window_info.ex_style |= WS_EX_NOACTIVATE;
143   }
144 
145   window_info.shared_texture_enabled = settings_.shared_texture_enabled;
146   window_info.external_begin_frame_enabled =
147       settings_.external_begin_frame_enabled;
148 
149   // Create the browser asynchronously.
150   CefBrowserHost::CreateBrowser(window_info, handler, startup_url, settings,
151                                 extra_info, request_context);
152 }
153 
ShowPopup(HWND parent_hwnd,int x,int y,size_t width,size_t height)154 void OsrWindowWin::ShowPopup(HWND parent_hwnd,
155                              int x,
156                              int y,
157                              size_t width,
158                              size_t height) {
159   if (!CefCurrentlyOn(TID_UI)) {
160     // Execute this method on the UI thread.
161     CefPostTask(TID_UI, base::Bind(&OsrWindowWin::ShowPopup, this, parent_hwnd,
162                                    x, y, width, height));
163     return;
164   }
165 
166   DCHECK(browser_.get());
167 
168   // Create the native window.
169   const RECT rect = {x, y, x + static_cast<int>(width),
170                      y + static_cast<int>(height)};
171   Create(parent_hwnd, rect);
172 
173   // Create the render handler.
174   EnsureRenderHandler();
175   render_handler_->SetBrowser(browser_);
176 
177   // Send resize notification so the compositor is assigned the correct
178   // viewport size and begins rendering.
179   browser_->GetHost()->WasResized();
180 
181   Show();
182 }
183 
Show()184 void OsrWindowWin::Show() {
185   if (!CefCurrentlyOn(TID_UI)) {
186     // Execute this method on the UI thread.
187     CefPostTask(TID_UI, base::Bind(&OsrWindowWin::Show, this));
188     return;
189   }
190 
191   if (!browser_)
192     return;
193 
194   // Show the native window if not currently visible.
195   if (hwnd_ && !::IsWindowVisible(hwnd_))
196     ShowWindow(hwnd_, SW_SHOW);
197 
198   if (hidden_) {
199     // Set the browser as visible.
200     browser_->GetHost()->WasHidden(false);
201     hidden_ = false;
202   }
203 
204   // Give focus to the browser.
205   browser_->GetHost()->SendFocusEvent(true);
206 }
207 
Hide()208 void OsrWindowWin::Hide() {
209   if (!CefCurrentlyOn(TID_UI)) {
210     // Execute this method on the UI thread.
211     CefPostTask(TID_UI, base::Bind(&OsrWindowWin::Hide, this));
212     return;
213   }
214 
215   if (!browser_)
216     return;
217 
218   // Remove focus from the browser.
219   browser_->GetHost()->SendFocusEvent(false);
220 
221   if (!hidden_) {
222     // Set the browser as hidden.
223     browser_->GetHost()->WasHidden(true);
224     hidden_ = true;
225   }
226 }
227 
SetBounds(int x,int y,size_t width,size_t height)228 void OsrWindowWin::SetBounds(int x, int y, size_t width, size_t height) {
229   if (!CefCurrentlyOn(TID_UI)) {
230     // Execute this method on the UI thread.
231     CefPostTask(TID_UI, base::Bind(&OsrWindowWin::SetBounds, this, x, y, width,
232                                    height));
233     return;
234   }
235 
236   if (hwnd_) {
237     // Set the browser window bounds.
238     ::SetWindowPos(hwnd_, NULL, x, y, static_cast<int>(width),
239                    static_cast<int>(height), SWP_NOZORDER);
240   }
241 }
242 
SetFocus()243 void OsrWindowWin::SetFocus() {
244   if (!CefCurrentlyOn(TID_UI)) {
245     // Execute this method on the UI thread.
246     CefPostTask(TID_UI, base::Bind(&OsrWindowWin::SetFocus, this));
247     return;
248   }
249 
250   if (hwnd_) {
251     // Give focus to the native window.
252     ::SetFocus(hwnd_);
253   }
254 }
255 
SetDeviceScaleFactor(float device_scale_factor)256 void OsrWindowWin::SetDeviceScaleFactor(float device_scale_factor) {
257   if (!CefCurrentlyOn(TID_UI)) {
258     // Execute this method on the UI thread.
259     CefPostTask(TID_UI, base::Bind(&OsrWindowWin::SetDeviceScaleFactor, this,
260                                    device_scale_factor));
261     return;
262   }
263 
264   if (device_scale_factor == device_scale_factor_)
265     return;
266 
267   device_scale_factor_ = device_scale_factor;
268   if (browser_) {
269     browser_->GetHost()->NotifyScreenInfoChanged();
270     browser_->GetHost()->WasResized();
271   }
272 }
273 
Create(HWND parent_hwnd,const RECT & rect)274 void OsrWindowWin::Create(HWND parent_hwnd, const RECT& rect) {
275   CEF_REQUIRE_UI_THREAD();
276   DCHECK(!hwnd_ && !render_handler_.get());
277   DCHECK(parent_hwnd);
278   DCHECK(!::IsRectEmpty(&rect));
279 
280   HINSTANCE hInst = ::GetModuleHandle(NULL);
281 
282   const cef_color_t background_color = MainContext::Get()->GetBackgroundColor();
283   const HBRUSH background_brush = CreateSolidBrush(
284       RGB(CefColorGetR(background_color), CefColorGetG(background_color),
285           CefColorGetB(background_color)));
286 
287   RegisterOsrClass(hInst, background_brush);
288 
289   DWORD ex_style = 0;
290   if (GetWindowLongPtr(parent_hwnd, GWL_EXSTYLE) & WS_EX_NOACTIVATE) {
291     // Don't activate the browser window on creation.
292     ex_style |= WS_EX_NOACTIVATE;
293   }
294 
295   // Create the native window with a border so it's easier to visually identify
296   // OSR windows.
297   hwnd_ = ::CreateWindowEx(
298       ex_style, kWndClass, 0,
299       WS_BORDER | WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE,
300       rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
301       parent_hwnd, 0, hInst, 0);
302   CHECK(hwnd_);
303 
304   client_rect_ = rect;
305 
306   // Associate |this| with the window.
307   SetUserDataPtr(hwnd_, this);
308 
309 #if defined(CEF_USE_ATL)
310   accessibility_root_ = nullptr;
311 
312   // Create/register the drag&drop handler.
313   drop_target_ = DropTargetWin::Create(this, hwnd_);
314   HRESULT register_res = RegisterDragDrop(hwnd_, drop_target_);
315   DCHECK_EQ(register_res, S_OK);
316 #endif
317 
318   ime_handler_.reset(new OsrImeHandlerWin(hwnd_));
319 
320   // Enable Touch Events if requested
321   if (client::MainContext::Get()->TouchEventsEnabled())
322     RegisterTouchWindow(hwnd_, 0);
323 
324   // Notify the window owner.
325   NotifyNativeWindowCreated(hwnd_);
326 }
327 
Destroy()328 void OsrWindowWin::Destroy() {
329   CEF_REQUIRE_UI_THREAD();
330   DCHECK(hwnd_ != NULL);
331 
332 #if defined(CEF_USE_ATL)
333   // Revoke/delete the drag&drop handler.
334   RevokeDragDrop(hwnd_);
335   drop_target_ = nullptr;
336 #endif
337 
338   render_handler_.reset();
339 
340   // Destroy the native window.
341   ::DestroyWindow(hwnd_);
342   ime_handler_.reset();
343   hwnd_ = NULL;
344 }
345 
NotifyNativeWindowCreated(HWND hwnd)346 void OsrWindowWin::NotifyNativeWindowCreated(HWND hwnd) {
347   if (!CURRENTLY_ON_MAIN_THREAD()) {
348     // Execute this method on the main thread.
349     MAIN_POST_CLOSURE(
350         base::Bind(&OsrWindowWin::NotifyNativeWindowCreated, this, hwnd));
351     return;
352   }
353 
354   delegate_->OnOsrNativeWindowCreated(hwnd);
355 }
356 
357 // static
RegisterOsrClass(HINSTANCE hInstance,HBRUSH background_brush)358 void OsrWindowWin::RegisterOsrClass(HINSTANCE hInstance,
359                                     HBRUSH background_brush) {
360   // Only register the class one time.
361   static bool class_registered = false;
362   if (class_registered)
363     return;
364   class_registered = true;
365 
366   WNDCLASSEX wcex;
367 
368   wcex.cbSize = sizeof(WNDCLASSEX);
369   wcex.style = CS_OWNDC;
370   wcex.lpfnWndProc = OsrWndProc;
371   wcex.cbClsExtra = 0;
372   wcex.cbWndExtra = 0;
373   wcex.hInstance = hInstance;
374   wcex.hIcon = NULL;
375   wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
376   wcex.hbrBackground = background_brush;
377   wcex.lpszMenuName = NULL;
378   wcex.lpszClassName = kWndClass;
379   wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
380 
381   RegisterClassEx(&wcex);
382 }
383 
OnIMESetContext(UINT message,WPARAM wParam,LPARAM lParam)384 void OsrWindowWin::OnIMESetContext(UINT message, WPARAM wParam, LPARAM lParam) {
385   // We handle the IME Composition Window ourselves (but let the IME Candidates
386   // Window be handled by IME through DefWindowProc()), so clear the
387   // ISC_SHOWUICOMPOSITIONWINDOW flag:
388   lParam &= ~ISC_SHOWUICOMPOSITIONWINDOW;
389   ::DefWindowProc(hwnd_, message, wParam, lParam);
390 
391   // Create Caret Window if required
392   if (ime_handler_) {
393     ime_handler_->CreateImeWindow();
394     ime_handler_->MoveImeWindow();
395   }
396 }
397 
OnIMEStartComposition()398 void OsrWindowWin::OnIMEStartComposition() {
399   if (ime_handler_) {
400     ime_handler_->CreateImeWindow();
401     ime_handler_->MoveImeWindow();
402     ime_handler_->ResetComposition();
403   }
404 }
405 
OnIMEComposition(UINT message,WPARAM wParam,LPARAM lParam)406 void OsrWindowWin::OnIMEComposition(UINT message,
407                                     WPARAM wParam,
408                                     LPARAM lParam) {
409   if (browser_ && ime_handler_) {
410     CefString cTextStr;
411     if (ime_handler_->GetResult(lParam, cTextStr)) {
412       // Send the text to the browser. The |replacement_range| and
413       // |relative_cursor_pos| params are not used on Windows, so provide
414       // default invalid values.
415       browser_->GetHost()->ImeCommitText(cTextStr,
416                                          CefRange(UINT32_MAX, UINT32_MAX), 0);
417       ime_handler_->ResetComposition();
418       // Continue reading the composition string - Japanese IMEs send both
419       // GCS_RESULTSTR and GCS_COMPSTR.
420     }
421 
422     std::vector<CefCompositionUnderline> underlines;
423     int composition_start = 0;
424 
425     if (ime_handler_->GetComposition(lParam, cTextStr, underlines,
426                                      composition_start)) {
427       // Send the composition string to the browser. The |replacement_range|
428       // param is not used on Windows, so provide a default invalid value.
429       browser_->GetHost()->ImeSetComposition(
430           cTextStr, underlines, CefRange(UINT32_MAX, UINT32_MAX),
431           CefRange(composition_start,
432                    static_cast<int>(composition_start + cTextStr.length())));
433 
434       // Update the Candidate Window position. The cursor is at the end so
435       // subtract 1. This is safe because IMM32 does not support non-zero-width
436       // in a composition. Also,  negative values are safely ignored in
437       // MoveImeWindow
438       ime_handler_->UpdateCaretPosition(composition_start - 1);
439     } else {
440       OnIMECancelCompositionEvent();
441     }
442   }
443 }
444 
OnIMECancelCompositionEvent()445 void OsrWindowWin::OnIMECancelCompositionEvent() {
446   if (browser_ && ime_handler_) {
447     browser_->GetHost()->ImeCancelComposition();
448     ime_handler_->ResetComposition();
449     ime_handler_->DestroyImeWindow();
450   }
451 }
452 
453 // static
OsrWndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)454 LRESULT CALLBACK OsrWindowWin::OsrWndProc(HWND hWnd,
455                                           UINT message,
456                                           WPARAM wParam,
457                                           LPARAM lParam) {
458   CEF_REQUIRE_UI_THREAD();
459 
460   OsrWindowWin* self = GetUserDataPtr<OsrWindowWin*>(hWnd);
461   if (!self)
462     return DefWindowProc(hWnd, message, wParam, lParam);
463 
464   // We want to handle IME events before the OS does any default handling.
465   switch (message) {
466     case WM_IME_SETCONTEXT:
467       self->OnIMESetContext(message, wParam, lParam);
468       return 0;
469     case WM_IME_STARTCOMPOSITION:
470       self->OnIMEStartComposition();
471       return 0;
472     case WM_IME_COMPOSITION:
473       self->OnIMEComposition(message, wParam, lParam);
474       return 0;
475     case WM_IME_ENDCOMPOSITION:
476       self->OnIMECancelCompositionEvent();
477       // Let WTL call::DefWindowProc() and release its resources.
478       break;
479 #if defined(CEF_USE_ATL)
480     case WM_GETOBJECT: {
481       // Only the lower 32 bits of lParam are valid when checking the object id
482       // because it sometimes gets sign-extended incorrectly (but not always).
483       DWORD obj_id = static_cast<DWORD>(static_cast<DWORD_PTR>(lParam));
484 
485       // Accessibility readers will send an OBJID_CLIENT message.
486       if (static_cast<DWORD>(OBJID_CLIENT) == obj_id) {
487         if (self->accessibility_root_) {
488           return LresultFromObject(
489               IID_IAccessible, wParam,
490               static_cast<IAccessible*>(self->accessibility_root_));
491         } else {
492           // Notify the renderer to enable accessibility.
493           if (self->browser_ && self->browser_->GetHost())
494             self->browser_->GetHost()->SetAccessibilityState(STATE_ENABLED);
495         }
496       }
497     } break;
498 #endif
499     case WM_LBUTTONDOWN:
500     case WM_RBUTTONDOWN:
501     case WM_MBUTTONDOWN:
502     case WM_LBUTTONUP:
503     case WM_RBUTTONUP:
504     case WM_MBUTTONUP:
505     case WM_MOUSEMOVE:
506     case WM_MOUSELEAVE:
507     case WM_MOUSEWHEEL:
508       self->OnMouseEvent(message, wParam, lParam);
509       break;
510 
511     case WM_SIZE:
512       self->OnSize();
513       break;
514 
515     case WM_SETFOCUS:
516     case WM_KILLFOCUS:
517       self->OnFocus(message == WM_SETFOCUS);
518       break;
519 
520     case WM_CAPTURECHANGED:
521     case WM_CANCELMODE:
522       self->OnCaptureLost();
523       break;
524 
525     case WM_SYSCHAR:
526     case WM_SYSKEYDOWN:
527     case WM_SYSKEYUP:
528     case WM_KEYDOWN:
529     case WM_KEYUP:
530     case WM_CHAR:
531       self->OnKeyEvent(message, wParam, lParam);
532       break;
533 
534     case WM_PAINT:
535       self->OnPaint();
536       return 0;
537 
538     case WM_ERASEBKGND:
539       if (self->OnEraseBkgnd())
540         break;
541       // Don't erase the background.
542       return 0;
543 
544     // If your application does not require Win7 support, please do consider
545     // using WM_POINTER* messages instead of WM_TOUCH. WM_POINTER are more
546     // intutive, complete and simpler to code.
547     // https://msdn.microsoft.com/en-us/library/hh454903(v=vs.85).aspx
548     case WM_TOUCH:
549       if (self->OnTouchEvent(message, wParam, lParam))
550         return 0;
551       break;
552 
553     case WM_NCDESTROY:
554       // Clear the reference to |self|.
555       SetUserDataPtr(hWnd, NULL);
556       self->hwnd_ = NULL;
557       break;
558   }
559 
560   return DefWindowProc(hWnd, message, wParam, lParam);
561 }
562 
OnMouseEvent(UINT message,WPARAM wParam,LPARAM lParam)563 void OsrWindowWin::OnMouseEvent(UINT message, WPARAM wParam, LPARAM lParam) {
564   if (IsMouseEventFromTouch(message))
565     return;
566 
567   CefRefPtr<CefBrowserHost> browser_host;
568   if (browser_)
569     browser_host = browser_->GetHost();
570 
571   LONG currentTime = 0;
572   bool cancelPreviousClick = false;
573 
574   if (message == WM_LBUTTONDOWN || message == WM_RBUTTONDOWN ||
575       message == WM_MBUTTONDOWN || message == WM_MOUSEMOVE ||
576       message == WM_MOUSELEAVE) {
577     currentTime = GetMessageTime();
578     int x = GET_X_LPARAM(lParam);
579     int y = GET_Y_LPARAM(lParam);
580     cancelPreviousClick =
581         (abs(last_click_x_ - x) > (GetSystemMetrics(SM_CXDOUBLECLK) / 2)) ||
582         (abs(last_click_y_ - y) > (GetSystemMetrics(SM_CYDOUBLECLK) / 2)) ||
583         ((currentTime - last_click_time_) > GetDoubleClickTime());
584     if (cancelPreviousClick &&
585         (message == WM_MOUSEMOVE || message == WM_MOUSELEAVE)) {
586       last_click_count_ = 1;
587       last_click_x_ = 0;
588       last_click_y_ = 0;
589       last_click_time_ = 0;
590     }
591   }
592 
593   switch (message) {
594     case WM_LBUTTONDOWN:
595     case WM_RBUTTONDOWN:
596     case WM_MBUTTONDOWN: {
597       ::SetCapture(hwnd_);
598       ::SetFocus(hwnd_);
599       int x = GET_X_LPARAM(lParam);
600       int y = GET_Y_LPARAM(lParam);
601       if (wParam & MK_SHIFT) {
602         // Start rotation effect.
603         last_mouse_pos_.x = current_mouse_pos_.x = x;
604         last_mouse_pos_.y = current_mouse_pos_.y = y;
605         mouse_rotation_ = true;
606       } else {
607         CefBrowserHost::MouseButtonType btnType =
608             (message == WM_LBUTTONDOWN
609                  ? MBT_LEFT
610                  : (message == WM_RBUTTONDOWN ? MBT_RIGHT : MBT_MIDDLE));
611         if (!cancelPreviousClick && (btnType == last_click_button_)) {
612           ++last_click_count_;
613         } else {
614           last_click_count_ = 1;
615           last_click_x_ = x;
616           last_click_y_ = y;
617         }
618         last_click_time_ = currentTime;
619         last_click_button_ = btnType;
620 
621         if (browser_host) {
622           CefMouseEvent mouse_event;
623           mouse_event.x = x;
624           mouse_event.y = y;
625           last_mouse_down_on_view_ = !IsOverPopupWidget(x, y);
626           ApplyPopupOffset(mouse_event.x, mouse_event.y);
627           DeviceToLogical(mouse_event, device_scale_factor_);
628           mouse_event.modifiers = GetCefMouseModifiers(wParam);
629           browser_host->SendMouseClickEvent(mouse_event, btnType, false,
630                                             last_click_count_);
631         }
632       }
633     } break;
634 
635     case WM_LBUTTONUP:
636     case WM_RBUTTONUP:
637     case WM_MBUTTONUP:
638       if (GetCapture() == hwnd_)
639         ReleaseCapture();
640       if (mouse_rotation_) {
641         // End rotation effect.
642         mouse_rotation_ = false;
643         render_handler_->SetSpin(0, 0);
644       } else {
645         int x = GET_X_LPARAM(lParam);
646         int y = GET_Y_LPARAM(lParam);
647         CefBrowserHost::MouseButtonType btnType =
648             (message == WM_LBUTTONUP
649                  ? MBT_LEFT
650                  : (message == WM_RBUTTONUP ? MBT_RIGHT : MBT_MIDDLE));
651         if (browser_host) {
652           CefMouseEvent mouse_event;
653           mouse_event.x = x;
654           mouse_event.y = y;
655           if (last_mouse_down_on_view_ && IsOverPopupWidget(x, y) &&
656               (GetPopupXOffset() || GetPopupYOffset())) {
657             break;
658           }
659           ApplyPopupOffset(mouse_event.x, mouse_event.y);
660           DeviceToLogical(mouse_event, device_scale_factor_);
661           mouse_event.modifiers = GetCefMouseModifiers(wParam);
662           browser_host->SendMouseClickEvent(mouse_event, btnType, true,
663                                             last_click_count_);
664         }
665       }
666       break;
667 
668     case WM_MOUSEMOVE: {
669       int x = GET_X_LPARAM(lParam);
670       int y = GET_Y_LPARAM(lParam);
671       if (mouse_rotation_) {
672         // Apply rotation effect.
673         current_mouse_pos_.x = x;
674         current_mouse_pos_.y = y;
675         render_handler_->IncrementSpin(
676             current_mouse_pos_.x - last_mouse_pos_.x,
677             current_mouse_pos_.y - last_mouse_pos_.y);
678         last_mouse_pos_.x = current_mouse_pos_.x;
679         last_mouse_pos_.y = current_mouse_pos_.y;
680       } else {
681         if (!mouse_tracking_) {
682           // Start tracking mouse leave. Required for the WM_MOUSELEAVE event to
683           // be generated.
684           TRACKMOUSEEVENT tme;
685           tme.cbSize = sizeof(TRACKMOUSEEVENT);
686           tme.dwFlags = TME_LEAVE;
687           tme.hwndTrack = hwnd_;
688           TrackMouseEvent(&tme);
689           mouse_tracking_ = true;
690         }
691 
692         if (browser_host) {
693           CefMouseEvent mouse_event;
694           mouse_event.x = x;
695           mouse_event.y = y;
696           ApplyPopupOffset(mouse_event.x, mouse_event.y);
697           DeviceToLogical(mouse_event, device_scale_factor_);
698           mouse_event.modifiers = GetCefMouseModifiers(wParam);
699           browser_host->SendMouseMoveEvent(mouse_event, false);
700         }
701       }
702       break;
703     }
704 
705     case WM_MOUSELEAVE: {
706       if (mouse_tracking_) {
707         // Stop tracking mouse leave.
708         TRACKMOUSEEVENT tme;
709         tme.cbSize = sizeof(TRACKMOUSEEVENT);
710         tme.dwFlags = TME_LEAVE & TME_CANCEL;
711         tme.hwndTrack = hwnd_;
712         TrackMouseEvent(&tme);
713         mouse_tracking_ = false;
714       }
715 
716       if (browser_host) {
717         // Determine the cursor position in screen coordinates.
718         POINT p;
719         ::GetCursorPos(&p);
720         ::ScreenToClient(hwnd_, &p);
721 
722         CefMouseEvent mouse_event;
723         mouse_event.x = p.x;
724         mouse_event.y = p.y;
725         DeviceToLogical(mouse_event, device_scale_factor_);
726         mouse_event.modifiers = GetCefMouseModifiers(wParam);
727         browser_host->SendMouseMoveEvent(mouse_event, true);
728       }
729     } break;
730 
731     case WM_MOUSEWHEEL:
732       if (browser_host) {
733         POINT screen_point = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
734         HWND scrolled_wnd = ::WindowFromPoint(screen_point);
735         if (scrolled_wnd != hwnd_)
736           break;
737 
738         ScreenToClient(hwnd_, &screen_point);
739         int delta = GET_WHEEL_DELTA_WPARAM(wParam);
740 
741         CefMouseEvent mouse_event;
742         mouse_event.x = screen_point.x;
743         mouse_event.y = screen_point.y;
744         ApplyPopupOffset(mouse_event.x, mouse_event.y);
745         DeviceToLogical(mouse_event, device_scale_factor_);
746         mouse_event.modifiers = GetCefMouseModifiers(wParam);
747         browser_host->SendMouseWheelEvent(mouse_event,
748                                           IsKeyDown(VK_SHIFT) ? delta : 0,
749                                           !IsKeyDown(VK_SHIFT) ? delta : 0);
750       }
751       break;
752   }
753 }
754 
OnSize()755 void OsrWindowWin::OnSize() {
756   // Keep |client_rect_| up to date.
757   ::GetClientRect(hwnd_, &client_rect_);
758 
759   if (browser_)
760     browser_->GetHost()->WasResized();
761 }
762 
OnFocus(bool setFocus)763 void OsrWindowWin::OnFocus(bool setFocus) {
764   if (browser_)
765     browser_->GetHost()->SendFocusEvent(setFocus);
766 }
767 
OnCaptureLost()768 void OsrWindowWin::OnCaptureLost() {
769   if (mouse_rotation_)
770     return;
771 
772   if (browser_)
773     browser_->GetHost()->SendCaptureLostEvent();
774 }
775 
OnKeyEvent(UINT message,WPARAM wParam,LPARAM lParam)776 void OsrWindowWin::OnKeyEvent(UINT message, WPARAM wParam, LPARAM lParam) {
777   if (!browser_)
778     return;
779 
780   CefKeyEvent event;
781   event.windows_key_code = wParam;
782   event.native_key_code = lParam;
783   event.is_system_key = message == WM_SYSCHAR || message == WM_SYSKEYDOWN ||
784                         message == WM_SYSKEYUP;
785 
786   if (message == WM_KEYDOWN || message == WM_SYSKEYDOWN)
787     event.type = KEYEVENT_RAWKEYDOWN;
788   else if (message == WM_KEYUP || message == WM_SYSKEYUP)
789     event.type = KEYEVENT_KEYUP;
790   else
791     event.type = KEYEVENT_CHAR;
792   event.modifiers = GetCefKeyboardModifiers(wParam, lParam);
793 
794   // mimic alt-gr check behaviour from
795   // src/ui/events/win/events_win_utils.cc: GetModifiersFromKeyState
796   if ((event.type == KEYEVENT_CHAR) && IsKeyDown(VK_RMENU)) {
797     // reverse AltGr detection taken from PlatformKeyMap::UsesAltGraph
798     // instead of checking all combination for ctrl-alt, just check current char
799     HKL current_layout = ::GetKeyboardLayout(0);
800 
801     // https://docs.microsoft.com/en-gb/windows/win32/api/winuser/nf-winuser-vkkeyscanexw
802     // ... high-order byte contains the shift state,
803     // which can be a combination of the following flag bits.
804     // 2 Either CTRL key is pressed.
805     // 4 Either ALT key is pressed.
806     SHORT scan_res = ::VkKeyScanExW(wParam, current_layout);
807     if (((scan_res >> 8) & 0xFF) == (2 | 4)) {  // ctrl-alt pressed
808       event.modifiers &= ~(EVENTFLAG_CONTROL_DOWN | EVENTFLAG_ALT_DOWN);
809       event.modifiers |= EVENTFLAG_ALTGR_DOWN;
810     }
811   }
812 
813   browser_->GetHost()->SendKeyEvent(event);
814 }
815 
OnPaint()816 void OsrWindowWin::OnPaint() {
817   // Paint nothing here. Invalidate will cause OnPaint to be called for the
818   // render handler.
819   PAINTSTRUCT ps;
820   BeginPaint(hwnd_, &ps);
821   EndPaint(hwnd_, &ps);
822 
823   if (browser_)
824     browser_->GetHost()->Invalidate(PET_VIEW);
825 }
826 
OnEraseBkgnd()827 bool OsrWindowWin::OnEraseBkgnd() {
828   // Erase the background when the browser does not exist.
829   return (browser_ == nullptr);
830 }
831 
OnTouchEvent(UINT message,WPARAM wParam,LPARAM lParam)832 bool OsrWindowWin::OnTouchEvent(UINT message, WPARAM wParam, LPARAM lParam) {
833   // Handle touch events on Windows.
834   int num_points = LOWORD(wParam);
835   // Chromium only supports upto 16 touch points.
836   if (num_points < 0 || num_points > 16)
837     return false;
838   std::unique_ptr<TOUCHINPUT[]> input(new TOUCHINPUT[num_points]);
839   if (GetTouchInputInfo(reinterpret_cast<HTOUCHINPUT>(lParam), num_points,
840                         input.get(), sizeof(TOUCHINPUT))) {
841     CefTouchEvent touch_event;
842     for (int i = 0; i < num_points; ++i) {
843       POINT point;
844       point.x = TOUCH_COORD_TO_PIXEL(input[i].x);
845       point.y = TOUCH_COORD_TO_PIXEL(input[i].y);
846 
847       if (!IsWindows_8_Or_Newer()) {
848         // Windows 7 sends touch events for touches in the non-client area,
849         // whereas Windows 8 does not. In order to unify the behaviour, always
850         // ignore touch events in the non-client area.
851         LPARAM l_param_ht = MAKELPARAM(point.x, point.y);
852         LRESULT hittest = SendMessage(hwnd_, WM_NCHITTEST, 0, l_param_ht);
853         if (hittest != HTCLIENT)
854           return false;
855       }
856 
857       ScreenToClient(hwnd_, &point);
858       touch_event.x = DeviceToLogical(point.x, device_scale_factor_);
859       touch_event.y = DeviceToLogical(point.y, device_scale_factor_);
860 
861       // Touch point identifier stays consistent in a touch contact sequence
862       touch_event.id = input[i].dwID;
863 
864       if (input[i].dwFlags & TOUCHEVENTF_DOWN) {
865         touch_event.type = CEF_TET_PRESSED;
866       } else if (input[i].dwFlags & TOUCHEVENTF_MOVE) {
867         touch_event.type = CEF_TET_MOVED;
868       } else if (input[i].dwFlags & TOUCHEVENTF_UP) {
869         touch_event.type = CEF_TET_RELEASED;
870       }
871 
872       touch_event.radius_x = 0;
873       touch_event.radius_y = 0;
874       touch_event.rotation_angle = 0;
875       touch_event.pressure = 0;
876       touch_event.modifiers = 0;
877 
878       // Notify the browser of touch event
879       if (browser_)
880         browser_->GetHost()->SendTouchEvent(touch_event);
881     }
882     CloseTouchInputHandle(reinterpret_cast<HTOUCHINPUT>(lParam));
883     return true;
884   }
885 
886   return false;
887 }
888 
IsOverPopupWidget(int x,int y) const889 bool OsrWindowWin::IsOverPopupWidget(int x, int y) const {
890   if (!render_handler_)
891     return false;
892   return render_handler_->IsOverPopupWidget(x, y);
893 }
894 
GetPopupXOffset() const895 int OsrWindowWin::GetPopupXOffset() const {
896   return render_handler_->GetPopupXOffset();
897 }
898 
GetPopupYOffset() const899 int OsrWindowWin::GetPopupYOffset() const {
900   return render_handler_->GetPopupYOffset();
901 }
902 
ApplyPopupOffset(int & x,int & y) const903 void OsrWindowWin::ApplyPopupOffset(int& x, int& y) const {
904   if (IsOverPopupWidget(x, y)) {
905     x += GetPopupXOffset();
906     y += GetPopupYOffset();
907   }
908 }
909 
OnAfterCreated(CefRefPtr<CefBrowser> browser)910 void OsrWindowWin::OnAfterCreated(CefRefPtr<CefBrowser> browser) {
911   CEF_REQUIRE_UI_THREAD();
912   DCHECK(!browser_);
913   browser_ = browser;
914 
915   if (hwnd_) {
916     // The native window will already exist for non-popup browsers.
917     EnsureRenderHandler();
918     render_handler_->SetBrowser(browser);
919   }
920 
921   if (hwnd_) {
922     // Show the browser window. Called asynchronously so that the browser has
923     // time to create associated internal objects.
924     CefPostTask(TID_UI, base::Bind(&OsrWindowWin::Show, this));
925   }
926 }
927 
OnBeforeClose(CefRefPtr<CefBrowser> browser)928 void OsrWindowWin::OnBeforeClose(CefRefPtr<CefBrowser> browser) {
929   CEF_REQUIRE_UI_THREAD();
930   // Detach |this| from the ClientHandlerOsr.
931   static_cast<ClientHandlerOsr*>(browser_->GetHost()->GetClient().get())
932       ->DetachOsrDelegate();
933   browser_ = nullptr;
934   render_handler_->SetBrowser(nullptr);
935   Destroy();
936 }
937 
GetRootScreenRect(CefRefPtr<CefBrowser> browser,CefRect & rect)938 bool OsrWindowWin::GetRootScreenRect(CefRefPtr<CefBrowser> browser,
939                                      CefRect& rect) {
940   CEF_REQUIRE_UI_THREAD();
941   return false;
942 }
943 
GetViewRect(CefRefPtr<CefBrowser> browser,CefRect & rect)944 void OsrWindowWin::GetViewRect(CefRefPtr<CefBrowser> browser, CefRect& rect) {
945   CEF_REQUIRE_UI_THREAD();
946   DCHECK_GT(device_scale_factor_, 0);
947 
948   rect.x = rect.y = 0;
949   rect.width = DeviceToLogical(client_rect_.right - client_rect_.left,
950                                device_scale_factor_);
951   if (rect.width == 0)
952     rect.width = 1;
953   rect.height = DeviceToLogical(client_rect_.bottom - client_rect_.top,
954                                 device_scale_factor_);
955   if (rect.height == 0)
956     rect.height = 1;
957 }
958 
GetScreenPoint(CefRefPtr<CefBrowser> browser,int viewX,int viewY,int & screenX,int & screenY)959 bool OsrWindowWin::GetScreenPoint(CefRefPtr<CefBrowser> browser,
960                                   int viewX,
961                                   int viewY,
962                                   int& screenX,
963                                   int& screenY) {
964   CEF_REQUIRE_UI_THREAD();
965   DCHECK_GT(device_scale_factor_, 0);
966 
967   if (!::IsWindow(hwnd_))
968     return false;
969 
970   // Convert the point from view coordinates to actual screen coordinates.
971   POINT screen_pt = {LogicalToDevice(viewX, device_scale_factor_),
972                      LogicalToDevice(viewY, device_scale_factor_)};
973   ClientToScreen(hwnd_, &screen_pt);
974   screenX = screen_pt.x;
975   screenY = screen_pt.y;
976   return true;
977 }
978 
GetScreenInfo(CefRefPtr<CefBrowser> browser,CefScreenInfo & screen_info)979 bool OsrWindowWin::GetScreenInfo(CefRefPtr<CefBrowser> browser,
980                                  CefScreenInfo& screen_info) {
981   CEF_REQUIRE_UI_THREAD();
982   DCHECK_GT(device_scale_factor_, 0);
983 
984   if (!::IsWindow(hwnd_))
985     return false;
986 
987   CefRect view_rect;
988   GetViewRect(browser, view_rect);
989 
990   screen_info.device_scale_factor = device_scale_factor_;
991 
992   // The screen info rectangles are used by the renderer to create and position
993   // popups. Keep popups inside the view rectangle.
994   screen_info.rect = view_rect;
995   screen_info.available_rect = view_rect;
996   return true;
997 }
998 
OnPopupShow(CefRefPtr<CefBrowser> browser,bool show)999 void OsrWindowWin::OnPopupShow(CefRefPtr<CefBrowser> browser, bool show) {
1000   render_handler_->OnPopupShow(browser, show);
1001 }
1002 
OnPopupSize(CefRefPtr<CefBrowser> browser,const CefRect & rect)1003 void OsrWindowWin::OnPopupSize(CefRefPtr<CefBrowser> browser,
1004                                const CefRect& rect) {
1005   render_handler_->OnPopupSize(browser,
1006                                LogicalToDevice(rect, device_scale_factor_));
1007 }
1008 
OnPaint(CefRefPtr<CefBrowser> browser,CefRenderHandler::PaintElementType type,const CefRenderHandler::RectList & dirtyRects,const void * buffer,int width,int height)1009 void OsrWindowWin::OnPaint(CefRefPtr<CefBrowser> browser,
1010                            CefRenderHandler::PaintElementType type,
1011                            const CefRenderHandler::RectList& dirtyRects,
1012                            const void* buffer,
1013                            int width,
1014                            int height) {
1015   EnsureRenderHandler();
1016   render_handler_->OnPaint(browser, type, dirtyRects, buffer, width, height);
1017 }
1018 
OnAcceleratedPaint(CefRefPtr<CefBrowser> browser,CefRenderHandler::PaintElementType type,const CefRenderHandler::RectList & dirtyRects,void * share_handle)1019 void OsrWindowWin::OnAcceleratedPaint(
1020     CefRefPtr<CefBrowser> browser,
1021     CefRenderHandler::PaintElementType type,
1022     const CefRenderHandler::RectList& dirtyRects,
1023     void* share_handle) {
1024   EnsureRenderHandler();
1025   render_handler_->OnAcceleratedPaint(browser, type, dirtyRects, share_handle);
1026 }
1027 
OnCursorChange(CefRefPtr<CefBrowser> browser,CefCursorHandle cursor,cef_cursor_type_t type,const CefCursorInfo & custom_cursor_info)1028 void OsrWindowWin::OnCursorChange(CefRefPtr<CefBrowser> browser,
1029                                   CefCursorHandle cursor,
1030                                   cef_cursor_type_t type,
1031                                   const CefCursorInfo& custom_cursor_info) {
1032   CEF_REQUIRE_UI_THREAD();
1033 
1034   if (!::IsWindow(hwnd_))
1035     return;
1036 
1037   // Change the plugin window's cursor.
1038   SetClassLongPtr(hwnd_, GCLP_HCURSOR,
1039                   static_cast<LONG>(reinterpret_cast<LONG_PTR>(cursor)));
1040   SetCursor(cursor);
1041 }
1042 
StartDragging(CefRefPtr<CefBrowser> browser,CefRefPtr<CefDragData> drag_data,CefRenderHandler::DragOperationsMask allowed_ops,int x,int y)1043 bool OsrWindowWin::StartDragging(
1044     CefRefPtr<CefBrowser> browser,
1045     CefRefPtr<CefDragData> drag_data,
1046     CefRenderHandler::DragOperationsMask allowed_ops,
1047     int x,
1048     int y) {
1049   CEF_REQUIRE_UI_THREAD();
1050 
1051 #if defined(CEF_USE_ATL)
1052   if (!drop_target_)
1053     return false;
1054 
1055   current_drag_op_ = DRAG_OPERATION_NONE;
1056   CefBrowserHost::DragOperationsMask result =
1057       drop_target_->StartDragging(browser, drag_data, allowed_ops, x, y);
1058   current_drag_op_ = DRAG_OPERATION_NONE;
1059   POINT pt = {};
1060   GetCursorPos(&pt);
1061   ScreenToClient(hwnd_, &pt);
1062 
1063   browser->GetHost()->DragSourceEndedAt(
1064       DeviceToLogical(pt.x, device_scale_factor_),
1065       DeviceToLogical(pt.y, device_scale_factor_), result);
1066   browser->GetHost()->DragSourceSystemDragEnded();
1067   return true;
1068 #else
1069   // Cancel the drag. The dragging implementation requires ATL support.
1070   return false;
1071 #endif
1072 }
1073 
UpdateDragCursor(CefRefPtr<CefBrowser> browser,CefRenderHandler::DragOperation operation)1074 void OsrWindowWin::UpdateDragCursor(CefRefPtr<CefBrowser> browser,
1075                                     CefRenderHandler::DragOperation operation) {
1076   CEF_REQUIRE_UI_THREAD();
1077 
1078 #if defined(CEF_USE_ATL)
1079   current_drag_op_ = operation;
1080 #endif
1081 }
1082 
OnImeCompositionRangeChanged(CefRefPtr<CefBrowser> browser,const CefRange & selection_range,const CefRenderHandler::RectList & character_bounds)1083 void OsrWindowWin::OnImeCompositionRangeChanged(
1084     CefRefPtr<CefBrowser> browser,
1085     const CefRange& selection_range,
1086     const CefRenderHandler::RectList& character_bounds) {
1087   CEF_REQUIRE_UI_THREAD();
1088 
1089   if (ime_handler_) {
1090     // Convert from view coordinates to device coordinates.
1091     CefRenderHandler::RectList device_bounds;
1092     CefRenderHandler::RectList::const_iterator it = character_bounds.begin();
1093     for (; it != character_bounds.end(); ++it) {
1094       device_bounds.push_back(LogicalToDevice(*it, device_scale_factor_));
1095     }
1096 
1097     ime_handler_->ChangeCompositionRange(selection_range, device_bounds);
1098   }
1099 }
1100 
UpdateAccessibilityTree(CefRefPtr<CefValue> value)1101 void OsrWindowWin::UpdateAccessibilityTree(CefRefPtr<CefValue> value) {
1102   CEF_REQUIRE_UI_THREAD();
1103 
1104 #if defined(CEF_USE_ATL)
1105   if (!accessibility_handler_) {
1106     accessibility_handler_.reset(new OsrAccessibilityHelper(value, browser_));
1107   } else {
1108     accessibility_handler_->UpdateAccessibilityTree(value);
1109   }
1110 
1111   // Update |accessibility_root_| because UpdateAccessibilityTree may have
1112   // cleared it.
1113   OsrAXNode* root = accessibility_handler_->GetRootNode();
1114   accessibility_root_ =
1115       root ? root->GetNativeAccessibleObject(nullptr) : nullptr;
1116 #endif  // defined(CEF_USE_ATL)
1117 }
1118 
UpdateAccessibilityLocation(CefRefPtr<CefValue> value)1119 void OsrWindowWin::UpdateAccessibilityLocation(CefRefPtr<CefValue> value) {
1120   CEF_REQUIRE_UI_THREAD();
1121 
1122 #if defined(CEF_USE_ATL)
1123   if (accessibility_handler_) {
1124     accessibility_handler_->UpdateAccessibilityLocation(value);
1125   }
1126 #endif  // defined(CEF_USE_ATL)
1127 }
1128 
1129 #if defined(CEF_USE_ATL)
1130 
OnDragEnter(CefRefPtr<CefDragData> drag_data,CefMouseEvent ev,CefBrowserHost::DragOperationsMask effect)1131 CefBrowserHost::DragOperationsMask OsrWindowWin::OnDragEnter(
1132     CefRefPtr<CefDragData> drag_data,
1133     CefMouseEvent ev,
1134     CefBrowserHost::DragOperationsMask effect) {
1135   if (browser_) {
1136     DeviceToLogical(ev, device_scale_factor_);
1137     browser_->GetHost()->DragTargetDragEnter(drag_data, ev, effect);
1138     browser_->GetHost()->DragTargetDragOver(ev, effect);
1139   }
1140   return current_drag_op_;
1141 }
1142 
OnDragOver(CefMouseEvent ev,CefBrowserHost::DragOperationsMask effect)1143 CefBrowserHost::DragOperationsMask OsrWindowWin::OnDragOver(
1144     CefMouseEvent ev,
1145     CefBrowserHost::DragOperationsMask effect) {
1146   if (browser_) {
1147     DeviceToLogical(ev, device_scale_factor_);
1148     browser_->GetHost()->DragTargetDragOver(ev, effect);
1149   }
1150   return current_drag_op_;
1151 }
1152 
OnDragLeave()1153 void OsrWindowWin::OnDragLeave() {
1154   if (browser_)
1155     browser_->GetHost()->DragTargetDragLeave();
1156 }
1157 
OnDrop(CefMouseEvent ev,CefBrowserHost::DragOperationsMask effect)1158 CefBrowserHost::DragOperationsMask OsrWindowWin::OnDrop(
1159     CefMouseEvent ev,
1160     CefBrowserHost::DragOperationsMask effect) {
1161   if (browser_) {
1162     DeviceToLogical(ev, device_scale_factor_);
1163     browser_->GetHost()->DragTargetDragOver(ev, effect);
1164     browser_->GetHost()->DragTargetDrop(ev);
1165   }
1166   return current_drag_op_;
1167 }
1168 
1169 #endif  // defined(CEF_USE_ATL)
1170 
EnsureRenderHandler()1171 void OsrWindowWin::EnsureRenderHandler() {
1172   CEF_REQUIRE_UI_THREAD();
1173   if (!render_handler_) {
1174     if (settings_.shared_texture_enabled) {
1175       // Try to initialize D3D11 rendering.
1176       auto render_handler = new OsrRenderHandlerWinD3D11(settings_, hwnd_);
1177       if (render_handler->Initialize(browser_,
1178                                      client_rect_.right - client_rect_.left,
1179                                      client_rect_.bottom - client_rect_.top)) {
1180         render_handler_.reset(render_handler);
1181       } else {
1182         LOG(ERROR) << "Failed to initialize D3D11 rendering.";
1183         delete render_handler;
1184       }
1185     }
1186 
1187     // Fall back to GL rendering.
1188     if (!render_handler_) {
1189       auto render_handler = new OsrRenderHandlerWinGL(settings_, hwnd_);
1190       render_handler->Initialize(browser_);
1191       render_handler_.reset(render_handler);
1192     }
1193   }
1194 }
1195 
1196 }  // namespace client
1197