Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Implementation of popups in CefSharp.Wpf/WebView.cpp

  • Loading branch information...
commit e7510ff61ed3ac7aff1534f95fbe0110df169906 1 parent cedab75
@dvarchev dvarchev authored
View
1  .gitignore
@@ -13,6 +13,7 @@ _ReSharper*
obj/
bin/
+Debug/
CefSharp/app.aps
TestResult.xml
debug.log
View
199 CefSharp.Wpf/WebView.cpp
@@ -23,8 +23,9 @@ namespace Wpf
gcnew PropertyChangedEventHandler(this, &WebView::BrowserCore_PropertyChanged);
_scriptCore = new ScriptCore();
-
_paintDelegate = gcnew ActionHandler(this, &WebView::SetBitmap);
+ _paintPopupDelegate = gcnew ActionHandler(this, &WebView::SetPopupBitmap);
+ _resizePopupDelegate = gcnew ActionHandler(this, &WebView::SetPopupSizeAndPositionImpl);
ToolTip = _toolTip =
gcnew System::Windows::Controls::ToolTip();
@@ -152,6 +153,24 @@ namespace Wpf
bitmap->Invalidate();
}
+ void WebView::SetPopupBitmap()
+ {
+ InteropBitmap^ bitmap = _popupIbitmap;
+
+ if(bitmap == nullptr)
+ {
+ _popupImage->Source = nullptr;
+ GC::Collect(1);
+
+ int stride = _popupWidth * PixelFormats::Bgr32.BitsPerPixel / 8;
+ bitmap = (InteropBitmap^)Interop::Imaging::CreateBitmapSourceFromMemorySection(
+ (IntPtr)_popupFileMappingHandle, _popupWidth, _popupHeight, PixelFormats::Bgr32, stride, 0);
+ _popupImage->Source = bitmap;
+ _popupIbitmap = bitmap;
+ }
+
+ bitmap->Invalidate();
+ }
void WebView::OnPreviewKey(KeyEventArgs^ e)
{
CefRefPtr<CefBrowser> browser;
@@ -202,6 +221,7 @@ namespace Wpf
{
Point point = _matrix->Transform(Point(size.Width, size.Height));
browser->SetSize(PET_VIEW, (int)point.X, (int)point.Y);
+ HidePopup();
}
else
{
@@ -230,6 +250,8 @@ namespace Wpf
{
browser->SendFocusEvent(false);
}
+
+ HidePopup();
ContentControl::OnLostFocus(e);
}
@@ -274,7 +296,7 @@ namespace Wpf
void WebView::OnMouseUp(MouseButtonEventArgs^ e)
{
OnMouseButton(e);
- Mouse::Capture(nullptr);
+ Mouse::Capture(nullptr);
}
void WebView::OnMouseLeave(MouseEventArgs^ e)
@@ -303,6 +325,7 @@ namespace Wpf
{
browser->GetMainFrame()->LoadURL(toNative(url));
}
+
}
void WebView::LoadHtml(String^ html)
@@ -584,10 +607,33 @@ namespace Wpf
source->AddHook(gcnew Interop::HwndSourceHook(this, &WebView::SourceHook));
Content = _image = gcnew Image();
+
+ _popup = gcnew Popup();
+
+ _popup->Child = _popupImage = gcnew Image();
+
+ _popup->MouseDown += gcnew MouseButtonEventHandler(this, &WebView::OnPopupMouseDown);
+ _popup->MouseUp += gcnew MouseButtonEventHandler(this, &WebView::OnPopupMouseUp);
+ _popup->MouseMove += gcnew MouseEventHandler(this, &WebView::OnPopupMouseMove);
+ _popup->MouseLeave += gcnew MouseEventHandler(this, &WebView::OnPopupMouseLeave);
+ _popup->MouseWheel += gcnew MouseWheelEventHandler(this, &WebView::OnPopupMouseWheel);
+
+ _popup->PlacementTarget = this;
+ _popup->Placement = PlacementMode::Relative;
+
+ Window^ currentWindow = Window::GetWindow(this);
+ currentWindow->LocationChanged += gcnew EventHandler(this, &WebView::OnWindowLocationChanged);
+ currentWindow->Deactivated += gcnew EventHandler(this, &WebView::OnWindowLocationChanged);
+
+
_image->Stretch = Stretch::None;
_image->HorizontalAlignment = ::HorizontalAlignment::Left;
_image->VerticalAlignment = ::VerticalAlignment::Top;
+ _popupImage->Stretch = Stretch::None;
+ _popupImage->HorizontalAlignment = ::HorizontalAlignment::Left;
+ _popupImage->VerticalAlignment = ::VerticalAlignment::Top;
+
_matrix = source->CompositionTarget->TransformToDevice;
}
@@ -615,46 +661,163 @@ namespace Wpf
void WebView::SetBuffer(int width, int height, const void* buffer)
{
- if (!_backBufferHandle || _width != width || _height != height)
+ int currentWidth = _width, currentHeight = _height;
+ HANDLE fileMappingHandle = _fileMappingHandle, backBufferHandle = _backBufferHandle;
+ InteropBitmap^ ibitmap = _ibitmap;
+
+ SetBuffer( currentWidth, currentHeight, width, height, fileMappingHandle, backBufferHandle, ibitmap, _paintDelegate, buffer);
+
+ _ibitmap = ibitmap;
+ _fileMappingHandle = fileMappingHandle;
+ _backBufferHandle = backBufferHandle;
+
+ _width = currentWidth;
+ _height = currentHeight;
+ }
+
+ void WebView::SetPopupBuffer(int width, int height, const void* buffer)
+ {
+ int currentWidth = _popupWidth, currentHeight = _popupHeight;
+ HANDLE fileMappingHandle = _popupFileMappingHandle, backBufferHandle = _popupBackBufferHandle;
+ InteropBitmap^ ibitmap = _popupIbitmap;
+
+ SetBuffer( currentWidth, currentHeight, width, height, fileMappingHandle, backBufferHandle, ibitmap, _paintPopupDelegate, buffer);
+
+ _popupIbitmap = ibitmap;
+ _popupFileMappingHandle = fileMappingHandle;
+ _popupBackBufferHandle = backBufferHandle;
+
+ _popupWidth = currentWidth;
+ _popupHeight = currentHeight;
+ }
+
+
+ void WebView::SetBuffer(int &currentWidth, int& currentHeight,
+ int width, int height,
+ HANDLE& fileMappingHandle,
+ HANDLE& backBufferHandle,
+ InteropBitmap^& ibitmap,
+ ActionHandler^ paintDelegate,
+ const void* buffer)
+ {
+ if (!backBufferHandle || currentWidth != width || currentHeight != height)
{
- _ibitmap = nullptr;
+ ibitmap = nullptr;
- if (_backBufferHandle)
+ if (backBufferHandle)
{
- UnmapViewOfFile(_backBufferHandle);
- _backBufferHandle = NULL;
+ UnmapViewOfFile(backBufferHandle);
+ backBufferHandle = NULL;
}
- if (_fileMappingHandle)
+ if (fileMappingHandle)
{
- CloseHandle(_fileMappingHandle);
- _fileMappingHandle = NULL;
+ CloseHandle(fileMappingHandle);
+ fileMappingHandle = NULL;
}
int pixels = width * height;
int bytes = pixels * PixelFormats::Bgr32.BitsPerPixel / 8;
- _fileMappingHandle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, bytes, NULL);
- if(!_fileMappingHandle)
+ fileMappingHandle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, bytes, NULL);
+ if(!fileMappingHandle)
{
return;
}
- _backBufferHandle = MapViewOfFile(_fileMappingHandle, FILE_MAP_ALL_ACCESS, 0, 0, bytes);
- if(!_backBufferHandle)
+ backBufferHandle = MapViewOfFile(fileMappingHandle, FILE_MAP_ALL_ACCESS, 0, 0, bytes);
+ if(!backBufferHandle)
{
return;
}
- _width = width;
- _height = height;
+ currentWidth = width;
+ currentHeight = height;
}
int stride = width * PixelFormats::Bgr32.BitsPerPixel / 8;
- CopyMemory(_backBufferHandle, (void*) buffer, height * stride);
+ CopyMemory(backBufferHandle, (void*) buffer, height * stride);
if(!Dispatcher->HasShutdownStarted) {
- Dispatcher->BeginInvoke(DispatcherPriority::Render, _paintDelegate);
+ Dispatcher->BeginInvoke(DispatcherPriority::Render, paintDelegate);
}
}
+
+ void WebView::SetPopupSizeAndPosition(const CefRect& rect)
+ {
+ _popupX = rect.x;
+ _popupY = rect.y;
+ _popupWidth = rect.width;
+ _popupHeight = rect.height;
+
+ if(!Dispatcher->HasShutdownStarted) {
+ Dispatcher->BeginInvoke(DispatcherPriority::Render, _resizePopupDelegate);
+ }
+ }
+
+ void WebView::SetPopupIsOpen(bool isOpen){
+ if(!Dispatcher->HasShutdownStarted) {
+ Dispatcher->BeginInvoke(gcnew Action<bool>(this, &WebView::ShowHidePopup), DispatcherPriority::Render, isOpen);
+ }
+ }
+
+ void WebView::SetPopupSizeAndPositionImpl()
+ {
+ _popup->Width = _popupWidth;
+ _popup->Height = _popupHeight;
+
+ _popup->HorizontalOffset = _popupX;
+ _popup->VerticalOffset = _popupY;
+
+ }
+ void WebView::ShowHidePopup(bool isOpened)
+ {
+ _popup->IsOpen = isOpened;
+ }
+
+
+ void WebView::OnPopupMouseMove(Object^ sender, MouseEventArgs^ e)
+ {
+ OnMouseMove(e);
+ }
+
+ void WebView::OnPopupMouseWheel(Object^ sender, MouseWheelEventArgs^ e)
+ {
+ OnMouseWheel(e);
+ }
+
+ void WebView::OnPopupMouseDown(Object^ sender,MouseButtonEventArgs^ e)
+ {
+ OnMouseDown(e);
+ }
+
+ void WebView::OnPopupMouseUp(Object^ sender,MouseButtonEventArgs^ e)
+ {
+ OnMouseUp(e);
+ }
+
+ void WebView::OnPopupMouseLeave(Object^ sender,MouseEventArgs^ e)
+ {
+ OnMouseLeave(e);
+ }
+
+ void WebView::OnWindowLocationChanged(Object^ sender, EventArgs^ e)
+ {
+ HidePopup();
+ }
+
+ void WebView::HidePopup()
+ {
+ CefRefPtr<CefBrowser> browser;
+ if (TryGetCefBrowser(browser))
+ {
+ if(_popup != nullptr && _popup->IsOpen)
+ {
+ // This is the only decent way I found to hide popup properly so that clicking again on the a drop down (<select>)
+ // opens it.
+ browser->SendMouseClickEvent(-1,-1, CefBrowser::MouseButtonType::MBT_LEFT, false, 1 );
+ }
+ }
+ }
+
}}
View
38 CefSharp.Wpf/WebView.h
@@ -33,16 +33,23 @@ namespace Wpf
MCefRefPtr<RenderClientAdapter> _clientAdapter;
BrowserCore^ _browserCore;
MCefRefPtr<ScriptCore> _scriptCore;
-
+
+ Popup^ _popup;
+
+ Image^ _popupImage;
Image^ _image;
Matrix^ _matrix;
::ToolTip^ _toolTip;
DispatcherTimer^ _timer;
- int _width, _height;
+ int _width, _height, _popupWidth, _popupHeight, _popupX, _popupY;
InteropBitmap^ _ibitmap;
+ InteropBitmap^ _popupIbitmap;
HANDLE _fileMappingHandle, _backBufferHandle;
+ HANDLE _popupFileMappingHandle, _popupBackBufferHandle;
+ ActionHandler^ _resizePopupDelegate;
ActionHandler^ _paintDelegate;
+ ActionHandler^ _paintPopupDelegate;
void Initialize(String^ address, BrowserSettings^ settings);
bool TryGetCefBrowser(CefRefPtr<CefBrowser>& browser);
@@ -53,15 +60,37 @@ namespace Wpf
void SetTooltipText(String^ text);
IntPtr SourceHook(IntPtr hWnd, int message, IntPtr wParam, IntPtr lParam, bool% handled);
void SetBitmap();
+
+ void SetBuffer(int& currentWidth, int& currentHeight,
+ int width, int height,
+ HANDLE& fileMappingHandle,
+ HANDLE& backBufferHandle,
+ InteropBitmap^& ibitmap,
+ ActionHandler^ paintDelegate,
+ const void* buffer);
+
+ void SetPopupBitmap();
void OnPreviewKey(KeyEventArgs^ e);
void OnMouseButton(MouseButtonEventArgs^ e);
+ void ShowHidePopup(bool isOpened);
+ void SetPopupSizeAndPositionImpl();
+
+ void OnPopupMouseMove(Object^ sender, MouseEventArgs^ e);
+ void OnPopupMouseWheel(Object^ sender,MouseWheelEventArgs^ e) ;
+ void OnPopupMouseDown(Object^ sender,MouseButtonEventArgs^ e) ;
+ void OnPopupMouseUp(Object^ sender, MouseButtonEventArgs^ e) ;
+ void OnPopupMouseLeave(Object^ sender, MouseEventArgs^ e) ;
+ void OnWindowLocationChanged(Object^ sender, EventArgs^ e) ;
+ void HidePopup();
+
protected:
virtual Size ArrangeOverride(Size size) override;
virtual void OnGotFocus(RoutedEventArgs^ e) override;
virtual void OnLostFocus(RoutedEventArgs^ e) override;
virtual void OnPreviewKeyDown(KeyEventArgs^ e) override;
virtual void OnPreviewKeyUp(KeyEventArgs^ e) override;
+
virtual void OnMouseMove(MouseEventArgs^ e) override;
virtual void OnMouseWheel(MouseWheelEventArgs^ e) override;
virtual void OnMouseDown(MouseButtonEventArgs^ e) override;
@@ -228,5 +257,10 @@ namespace Wpf
virtual void OnApplyTemplate() override;
virtual void SetCursor(CefCursorHandle cursor);
virtual void SetBuffer(int width, int height, const void* buffer);
+ virtual void SetPopupBuffer(int width, int height, const void* buffer);
+
+ virtual void SetPopupIsOpen(bool isOpen);
+ virtual void SetPopupSizeAndPosition(const CefRect& rect);
+
};
}}
View
6 CefSharp/IRenderWebBrowser.h
@@ -3,6 +3,7 @@
#include "IWebBrowser.h"
+
namespace CefSharp
{
public interface class IRenderWebBrowser : IWebBrowser
@@ -10,5 +11,10 @@ namespace CefSharp
public:
void SetCursor(CefCursorHandle cursor);
void SetBuffer(int width, int height, const void* buffer);
+
+ void SetPopupBuffer(int width, int height, const void* buffer);
+ void SetPopupIsOpen(bool isOpen);
+
+ void SetPopupSizeAndPosition(const CefRect& rect);
};
}
View
9 CefSharp/RenderClientAdapter.cpp
@@ -7,12 +7,12 @@ namespace CefSharp
{
void RenderClientAdapter::OnPopupShow(CefRefPtr<CefBrowser> browser, bool show)
{
-
+ _renderBrowserControl->SetPopupIsOpen(show);
}
void RenderClientAdapter::OnPopupSize(CefRefPtr<CefBrowser> browser, const CefRect& rect)
{
-
+ _renderBrowserControl->SetPopupSizeAndPosition(rect);
}
void RenderClientAdapter::OnPaint(CefRefPtr<CefBrowser> browser, PaintElementType type, const RectList& dirtyRects, const void* buffer)
@@ -26,7 +26,10 @@ namespace CefSharp
}
else if (type == PET_POPUP)
{
- // XXX
+ int width, height;
+ browser->GetSize(type, width, height);
+
+ _renderBrowserControl->SetPopupBuffer(width, height, buffer);
}
}
Please sign in to comment.
Something went wrong with that request. Please try again.