Windows/Linux: Fix positioning of select popups and dismissal on window move/resize by calling new CefBrowserHost::NotifyMoveOrResizeStarted() method from client applications (issue #1208).
git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@1901 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
parent
0cbadc6e07
commit
470518a52e
|
@ -456,6 +456,13 @@ typedef struct _cef_browser_host_t {
|
|||
void (CEF_CALLBACK *send_capture_lost_event)(
|
||||
struct _cef_browser_host_t* self);
|
||||
|
||||
///
|
||||
// Notify the browser that the window hosting it is about to be moved or
|
||||
// resized. This function is only used on Windows and Linux.
|
||||
///
|
||||
void (CEF_CALLBACK *notify_move_or_resize_started)(
|
||||
struct _cef_browser_host_t* self);
|
||||
|
||||
///
|
||||
// Get the NSTextInputContext implementation for enabling IME on Mac when
|
||||
// window rendering is disabled.
|
||||
|
|
|
@ -507,6 +507,13 @@ class CefBrowserHost : public virtual CefBase {
|
|||
/*--cef()--*/
|
||||
virtual void SendCaptureLostEvent() =0;
|
||||
|
||||
///
|
||||
// Notify the browser that the window hosting it is about to be moved or
|
||||
// resized. This method is only used on Windows and Linux.
|
||||
///
|
||||
/*--cef()--*/
|
||||
virtual void NotifyMoveOrResizeStarted() =0;
|
||||
|
||||
///
|
||||
// Get the NSTextInputContext implementation for enabling IME on Mac when
|
||||
// window rendering is disabled.
|
||||
|
|
|
@ -1164,6 +1164,24 @@ void CefBrowserHostImpl::SendCaptureLostEvent() {
|
|||
widget->LostCapture();
|
||||
}
|
||||
|
||||
void CefBrowserHostImpl::NotifyMoveOrResizeStarted() {
|
||||
if (!CEF_CURRENTLY_ON_UIT()) {
|
||||
CEF_POST_TASK(CEF_UIT,
|
||||
base::Bind(&CefBrowserHostImpl::NotifyMoveOrResizeStarted, this));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!web_contents())
|
||||
return;
|
||||
|
||||
// Dismiss any existing popups.
|
||||
content::RenderViewHost* rvh = web_contents()->GetRenderViewHost();
|
||||
if (rvh)
|
||||
rvh->NotifyMoveOrResizeStarted();
|
||||
|
||||
PlatformNotifyMoveOrResizeStarted();
|
||||
}
|
||||
|
||||
// CefBrowser methods.
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
|
|
|
@ -175,6 +175,7 @@ class CefBrowserHostImpl : public CefBrowserHost,
|
|||
int deltaX, int deltaY) OVERRIDE;
|
||||
virtual void SendFocusEvent(bool setFocus) OVERRIDE;
|
||||
virtual void SendCaptureLostEvent() OVERRIDE;
|
||||
virtual void NotifyMoveOrResizeStarted() OVERRIDE;
|
||||
virtual CefTextInputContext GetNSTextInputContext() OVERRIDE;
|
||||
virtual void HandleKeyEventBeforeTextInputClient(CefEventHandle keyEvent)
|
||||
OVERRIDE;
|
||||
|
@ -540,6 +541,8 @@ class CefBrowserHostImpl : public CefBrowserHost,
|
|||
void PlatformTranslateMouseEvent(blink::WebMouseEvent& web_event,
|
||||
const CefMouseEvent& mouse_event);
|
||||
|
||||
void PlatformNotifyMoveOrResizeStarted();
|
||||
|
||||
int TranslateModifiers(uint32 cefKeyStates);
|
||||
void SendMouseEvent(const blink::WebMouseEvent& web_event);
|
||||
|
||||
|
|
|
@ -5,6 +5,10 @@
|
|||
|
||||
#include "libcef/browser/browser_host_impl.h"
|
||||
|
||||
// Include this first to avoid type conflict errors.
|
||||
#include "base/tracked_objects.h"
|
||||
#undef Status
|
||||
|
||||
#include <sys/sysinfo.h>
|
||||
#include <X11/cursorfont.h>
|
||||
|
||||
|
@ -14,10 +18,13 @@
|
|||
#include "libcef/browser/thread_util.h"
|
||||
|
||||
#include "base/bind.h"
|
||||
#include "content/browser/renderer_host/render_widget_host_impl.h"
|
||||
#include "content/public/browser/native_web_keyboard_event.h"
|
||||
#include "content/public/browser/render_view_host.h"
|
||||
#include "content/public/common/file_chooser_params.h"
|
||||
#include "content/public/common/renderer_preferences.h"
|
||||
#include "third_party/WebKit/public/web/WebInputEvent.h"
|
||||
#include "ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h"
|
||||
#include "ui/views/widget/widget.h"
|
||||
|
||||
namespace {
|
||||
|
@ -429,3 +436,26 @@ void CefBrowserHostImpl::PlatformTranslateMouseEvent(
|
|||
// timestamp
|
||||
result.timeStampSeconds = GetSystemUptime();
|
||||
}
|
||||
|
||||
void CefBrowserHostImpl::PlatformNotifyMoveOrResizeStarted() {
|
||||
if (IsWindowless())
|
||||
return;
|
||||
|
||||
if (!window_x11_)
|
||||
return;
|
||||
|
||||
views::DesktopWindowTreeHostX11* tree_host = window_x11_->GetHost();
|
||||
if (!tree_host)
|
||||
return;
|
||||
|
||||
// Explicitly set the screen bounds so that WindowTreeHost::*Screen()
|
||||
// methods return the correct results.
|
||||
const gfx::Rect& bounds = window_x11_->GetBoundsInScreen();
|
||||
tree_host->set_screen_bounds(bounds);
|
||||
|
||||
// Send updated screen rectangle information to the renderer process so that
|
||||
// popups are displayed in the correct location.
|
||||
content::RenderWidgetHostImpl::From(web_contents()->GetRenderViewHost())->
|
||||
SendScreenRects();
|
||||
}
|
||||
|
||||
|
|
|
@ -717,3 +717,6 @@ void CefBrowserHostImpl::PlatformTranslateMouseEvent(
|
|||
// timestamp - Mac OSX specific
|
||||
result.timeStampSeconds = currentEventTimestamp();
|
||||
}
|
||||
|
||||
void CefBrowserHostImpl::PlatformNotifyMoveOrResizeStarted() {
|
||||
}
|
||||
|
|
|
@ -31,10 +31,13 @@
|
|||
#include "grit/ui_unscaled_resources.h"
|
||||
#include "net/base/mime_util.h"
|
||||
#include "third_party/WebKit/public/web/WebInputEvent.h"
|
||||
#include "ui/aura/window_tree_host.h"
|
||||
#include "ui/base/l10n/l10n_util.h"
|
||||
#include "ui/base/win/shell.h"
|
||||
#include "ui/gfx/win/hwnd_util.h"
|
||||
#include "ui/views/widget/desktop_aura/desktop_window_tree_host_win.h"
|
||||
#include "ui/views/widget/widget.h"
|
||||
#include "ui/views/win/hwnd_message_handler_delegate.h"
|
||||
#include "ui/views/win/hwnd_util.h"
|
||||
|
||||
#pragma comment(lib, "dwmapi.lib")
|
||||
|
@ -601,6 +604,12 @@ LRESULT CALLBACK CefBrowserHostImpl::WndProc(HWND hwnd, UINT message,
|
|||
}
|
||||
return 0;
|
||||
|
||||
case WM_MOVING:
|
||||
case WM_MOVE:
|
||||
if (browser)
|
||||
browser->NotifyMoveOrResizeStarted();
|
||||
return 0;
|
||||
|
||||
case WM_SETFOCUS:
|
||||
if (browser)
|
||||
browser->SetFocus(true);
|
||||
|
@ -942,3 +951,24 @@ void CefBrowserHostImpl::PlatformTranslateMouseEvent(
|
|||
// timestamp
|
||||
result.timeStampSeconds = GetMessageTime() / 1000.0;
|
||||
}
|
||||
|
||||
void CefBrowserHostImpl::PlatformNotifyMoveOrResizeStarted() {
|
||||
if (IsWindowless())
|
||||
return;
|
||||
|
||||
if (!window_widget_)
|
||||
return;
|
||||
|
||||
// Notify DesktopWindowTreeHostWin of move events so that screen rectangle
|
||||
// information is communicated to the renderer process and popups are
|
||||
// displayed in the correct location.
|
||||
views::DesktopWindowTreeHostWin* tree_host =
|
||||
static_cast<views::DesktopWindowTreeHostWin*>(
|
||||
aura::WindowTreeHost::GetForAcceleratedWidget(
|
||||
HWNDForWidget(window_widget_)));
|
||||
DCHECK(tree_host);
|
||||
if (tree_host) {
|
||||
// Cast to HWNDMessageHandlerDelegate so we can access HandleMove().
|
||||
static_cast<views::HWNDMessageHandlerDelegate*>(tree_host)->HandleMove();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -290,6 +290,15 @@ gfx::Rect CefWindowX11::GetBoundsInScreen() {
|
|||
return gfx::Rect();
|
||||
}
|
||||
|
||||
views::DesktopWindowTreeHostX11* CefWindowX11::GetHost() {
|
||||
if (browser_.get()) {
|
||||
::Window child = FindChild(xdisplay_, xwindow_);
|
||||
if (child)
|
||||
return views::DesktopWindowTreeHostX11::GetHostForXID(child);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool CefWindowX11::CanDispatchEvent(const ui::PlatformEvent& event) {
|
||||
::Window target = FindEventTarget(event);
|
||||
return target == xwindow_;
|
||||
|
@ -317,14 +326,7 @@ uint32_t CefWindowX11::DispatchEvent(const ui::PlatformEvent& event) {
|
|||
changes.height = bounds.height();
|
||||
XConfigureWindow(xdisplay_, child, CWHeight | CWWidth, &changes);
|
||||
|
||||
// Explicitly set the screen bounds so that WindowTreeHost::*Screen()
|
||||
// methods return the correct results.
|
||||
views::DesktopWindowTreeHostX11* window_tree_host =
|
||||
views::DesktopWindowTreeHostX11::GetHostForXID(child);
|
||||
if (window_tree_host) {
|
||||
window_tree_host->set_screen_bounds(
|
||||
CefWindowX11::GetBoundsInScreen());
|
||||
}
|
||||
browser_->NotifyMoveOrResizeStarted();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -385,23 +387,6 @@ uint32_t CefWindowX11::DispatchEvent(const ui::PlatformEvent& event) {
|
|||
base::Bind(&CefWindowX11::ContinueFocus,
|
||||
weak_ptr_factory_.GetWeakPtr()),
|
||||
100);
|
||||
|
||||
// Explicitly set the screen bounds so that WindowTreeHost::*Screen()
|
||||
// methods return the correct results. This is done here to update the
|
||||
// bounds for the case of a simple window move which will not result in
|
||||
// a ConfigureEvent in the case that this window is hosted in a parent,
|
||||
// i.e. the CefClient use case.
|
||||
if (browser_.get()) {
|
||||
::Window child = FindChild(xdisplay_, xwindow_);
|
||||
if (child) {
|
||||
views::DesktopWindowTreeHostX11* window_tree_host =
|
||||
views::DesktopWindowTreeHostX11::GetHostForXID(child);
|
||||
if (window_tree_host) {
|
||||
window_tree_host->set_screen_bounds(
|
||||
CefWindowX11::GetBoundsInScreen());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case FocusOut:
|
||||
|
@ -454,3 +439,4 @@ void CefWindowX11::ContinueFocus() {
|
|||
browser_->SetFocus(true);
|
||||
focus_pending_ = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,10 @@
|
|||
#include "ui/gfx/rect.h"
|
||||
#include "ui/gfx/x/x11_atom_cache.h"
|
||||
|
||||
namespace views {
|
||||
class DesktopWindowTreeHostX11;
|
||||
}
|
||||
|
||||
// Object wrapper for an X11 Window.
|
||||
// Based on WindowTreeHostX11 and DesktopWindowTreeHostX11.
|
||||
class CefWindowX11 : public ui::PlatformEventDispatcher {
|
||||
|
@ -36,6 +40,8 @@ class CefWindowX11 : public ui::PlatformEventDispatcher {
|
|||
|
||||
gfx::Rect GetBoundsInScreen();
|
||||
|
||||
views::DesktopWindowTreeHostX11* GetHost();
|
||||
|
||||
// ui::PlatformEventDispatcher methods:
|
||||
virtual bool CanDispatchEvent(const ui::PlatformEvent& event) OVERRIDE;
|
||||
virtual uint32_t DispatchEvent(const ui::PlatformEvent& event) OVERRIDE;
|
||||
|
|
|
@ -637,6 +637,18 @@ void CEF_CALLBACK browser_host_send_capture_lost_event(
|
|||
CefBrowserHostCppToC::Get(self)->SendCaptureLostEvent();
|
||||
}
|
||||
|
||||
void CEF_CALLBACK browser_host_notify_move_or_resize_started(
|
||||
struct _cef_browser_host_t* self) {
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
DCHECK(self);
|
||||
if (!self)
|
||||
return;
|
||||
|
||||
// Execute
|
||||
CefBrowserHostCppToC::Get(self)->NotifyMoveOrResizeStarted();
|
||||
}
|
||||
|
||||
cef_text_input_context_t CEF_CALLBACK browser_host_get_nstext_input_context(
|
||||
struct _cef_browser_host_t* self) {
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
@ -838,6 +850,8 @@ CefBrowserHostCppToC::CefBrowserHostCppToC(CefBrowserHost* cls)
|
|||
struct_.struct_.send_focus_event = browser_host_send_focus_event;
|
||||
struct_.struct_.send_capture_lost_event =
|
||||
browser_host_send_capture_lost_event;
|
||||
struct_.struct_.notify_move_or_resize_started =
|
||||
browser_host_notify_move_or_resize_started;
|
||||
struct_.struct_.get_nstext_input_context =
|
||||
browser_host_get_nstext_input_context;
|
||||
struct_.struct_.handle_key_event_before_text_input_client =
|
||||
|
|
|
@ -495,6 +495,16 @@ void CefBrowserHostCToCpp::SendCaptureLostEvent() {
|
|||
struct_->send_capture_lost_event(struct_);
|
||||
}
|
||||
|
||||
void CefBrowserHostCToCpp::NotifyMoveOrResizeStarted() {
|
||||
if (CEF_MEMBER_MISSING(struct_, notify_move_or_resize_started))
|
||||
return;
|
||||
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
// Execute
|
||||
struct_->notify_move_or_resize_started(struct_);
|
||||
}
|
||||
|
||||
CefTextInputContext CefBrowserHostCToCpp::GetNSTextInputContext() {
|
||||
if (CEF_MEMBER_MISSING(struct_, get_nstext_input_context))
|
||||
return NULL;
|
||||
|
|
|
@ -78,6 +78,7 @@ class CefBrowserHostCToCpp
|
|||
int deltaY) OVERRIDE;
|
||||
virtual void SendFocusEvent(bool setFocus) OVERRIDE;
|
||||
virtual void SendCaptureLostEvent() OVERRIDE;
|
||||
virtual void NotifyMoveOrResizeStarted() OVERRIDE;
|
||||
virtual CefTextInputContext GetNSTextInputContext() OVERRIDE;
|
||||
virtual void HandleKeyEventBeforeTextInputClient(
|
||||
CefEventHandle keyEvent) OVERRIDE;
|
||||
|
|
|
@ -57,7 +57,7 @@ index d184ae4..92ffd42 100644
|
|||
if (input_method)
|
||||
input_method->OnBlur();
|
||||
diff --git desktop_aura/desktop_window_tree_host_x11.cc desktop_aura/desktop_window_tree_host_x11.cc
|
||||
index 9831992..081a56a0 100644
|
||||
index 9831992..23a00a9 100644
|
||||
--- desktop_aura/desktop_window_tree_host_x11.cc
|
||||
+++ desktop_aura/desktop_window_tree_host_x11.cc
|
||||
@@ -147,7 +147,8 @@ DesktopWindowTreeHostX11::DesktopWindowTreeHostX11(
|
||||
|
@ -98,7 +98,16 @@ index 9831992..081a56a0 100644
|
|||
return bounds_;
|
||||
}
|
||||
|
||||
@@ -933,6 +939,8 @@ void DesktopWindowTreeHostX11::SetBounds(const gfx::Rect& requested_bounds) {
|
||||
@@ -879,6 +885,8 @@ void DesktopWindowTreeHostX11::Hide() {
|
||||
}
|
||||
|
||||
gfx::Rect DesktopWindowTreeHostX11::GetBounds() const {
|
||||
+ if (!screen_bounds_.IsEmpty())
|
||||
+ return screen_bounds_;
|
||||
return bounds_;
|
||||
}
|
||||
|
||||
@@ -933,6 +941,8 @@ void DesktopWindowTreeHostX11::SetBounds(const gfx::Rect& requested_bounds) {
|
||||
}
|
||||
|
||||
gfx::Point DesktopWindowTreeHostX11::GetLocationOnNativeScreen() const {
|
||||
|
@ -107,7 +116,7 @@ index 9831992..081a56a0 100644
|
|||
return bounds_.origin();
|
||||
}
|
||||
|
||||
@@ -1085,10 +1093,14 @@ void DesktopWindowTreeHostX11::InitX11Window(
|
||||
@@ -1085,10 +1095,14 @@ void DesktopWindowTreeHostX11::InitX11Window(
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -123,7 +132,7 @@ index 9831992..081a56a0 100644
|
|||
bounds_.x(), bounds_.y(),
|
||||
bounds_.width(), bounds_.height(),
|
||||
0, // border width
|
||||
@@ -1706,6 +1718,10 @@ uint32_t DesktopWindowTreeHostX11::DispatchEvent(
|
||||
@@ -1706,6 +1720,10 @@ uint32_t DesktopWindowTreeHostX11::DispatchEvent(
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -205,6 +205,24 @@ gboolean WindowState(GtkWidget* widget,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean WindowConfigure(GtkWindow* window,
|
||||
GdkEvent* event,
|
||||
gpointer data) {
|
||||
// Called when size, position or stack order changes.
|
||||
if (g_handler) {
|
||||
CefRefPtr<CefBrowser> browser = g_handler->GetBrowser();
|
||||
if (browser) {
|
||||
// Notify the browser of move/resize events so that:
|
||||
// - Popup windows are displayed in the correct location and dismissed
|
||||
// when the window moves.
|
||||
// - Drag&drop areas are updated accordingly.
|
||||
browser->GetHost()->NotifyMoveOrResizeStarted();
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE; // Don't stop this message.
|
||||
}
|
||||
|
||||
// Callback for Tests > Get Source... menu item.
|
||||
gboolean GetSourceActivated(GtkWidget* widget) {
|
||||
if (g_handler.get() && g_handler->GetBrowserId())
|
||||
|
@ -454,6 +472,8 @@ int main(int argc, char* argv[]) {
|
|||
G_CALLBACK(WindowFocusIn), NULL);
|
||||
g_signal_connect(window, "window-state-event",
|
||||
G_CALLBACK(WindowState), NULL);
|
||||
g_signal_connect(G_OBJECT(window), "configure-event",
|
||||
G_CALLBACK(WindowConfigure), NULL);
|
||||
|
||||
GtkWidget* vbox = gtk_vbox_new(FALSE, 0);
|
||||
g_signal_connect(vbox, "size-allocate",
|
||||
|
|
|
@ -645,6 +645,14 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam,
|
|||
}
|
||||
} break;
|
||||
|
||||
case WM_MOVING:
|
||||
case WM_MOVE:
|
||||
// Notify the browser of move events so that popup windows are displayed
|
||||
// in the correct location and dismissed when the window moves.
|
||||
if (g_handler.get() && g_handler->GetBrowser())
|
||||
g_handler->GetBrowser()->GetHost()->NotifyMoveOrResizeStarted();
|
||||
return 0;
|
||||
|
||||
case WM_ERASEBKGND:
|
||||
if (g_handler.get() && g_handler->GetBrowser()) {
|
||||
CefWindowHandle hwnd =
|
||||
|
|
Loading…
Reference in New Issue