Linux: Add drag&drop support (issue #1258).

- Requires proper handling of the "XdndProxy" property on the top-level window. This currently works in cefsimple but not cefclient (perhaps due to https://bugzilla.gnome.org/show_bug.cgi?id=653264).

git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@1759 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
Marshall Greenblatt 2014-07-08 22:37:06 +00:00
parent 81f8883b4a
commit 824f8f4009
5 changed files with 154 additions and 37 deletions

View File

@ -417,8 +417,10 @@ void CefBrowserHostImpl::PlatformTranslateMouseEvent(
GetBrowser(),
result.x, result.y,
result.globalX, result.globalY);
} else {
// TODO(linux): Convert global{X,Y} to screen coordinates.
} else if (window_x11_) {
const gfx::Point& origin = window_x11_->bounds().origin();
result.globalX += origin.x();
result.globalY += origin.y();
}
// modifiers

View File

@ -12,14 +12,23 @@
#include "ui/base/x/x11_util.h"
#include "ui/events/platform/x11/x11_event_source.h"
#include "ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h"
#include "ui/views/widget/desktop_aura/x11_topmost_window_finder.h"
namespace {
const char kWMDeleteWindow[] = "WM_DELETE_WINDOW";
const char kWMProtocols[] = "WM_PROTOCOLS";
const char kNetWMPing[] = "_NET_WM_PING";
const char kNetWMPid[] = "_NET_WM_PID";
const char kXdndProxy[] = "XdndProxy";
const char* kAtomsToCache[] = {
"WM_DELETE_WINDOW",
"WM_PROTOCOLS",
"_NET_WM_PING",
"_NET_WM_PID",
kWMDeleteWindow,
kWMProtocols,
kNetWMPing,
kNetWMPid,
kXdndProxy,
NULL
};
@ -90,8 +99,8 @@ CefWindowX11::CefWindowX11(CefRefPtr<CefBrowserHostImpl> browser,
// should listen for activation events and anything else that GTK+ listens
// for, and do something useful.
::Atom protocols[2];
protocols[0] = atom_cache_.GetAtom("WM_DELETE_WINDOW");
protocols[1] = atom_cache_.GetAtom("_NET_WM_PING");
protocols[0] = atom_cache_.GetAtom(kWMDeleteWindow);
protocols[1] = atom_cache_.GetAtom(kNetWMPing);
XSetWMProtocols(xdisplay_, xwindow_, protocols, 2);
// We need a WM_CLIENT_MACHINE and WM_LOCALE_NAME value so we integrate with
@ -105,7 +114,7 @@ CefWindowX11::CefWindowX11(CefRefPtr<CefBrowserHostImpl> browser,
long pid = getpid();
XChangeProperty(xdisplay_,
xwindow_,
atom_cache_.GetAtom("_NET_WM_PID"),
atom_cache_.GetAtom(kNetWMPid),
XA_CARDINAL,
32,
PropModeReplace,
@ -125,9 +134,9 @@ void CefWindowX11::Close() {
XEvent ev = {0};
ev.xclient.type = ClientMessage;
ev.xclient.window = xwindow_;
ev.xclient.message_type = atom_cache_.GetAtom("WM_PROTOCOLS");
ev.xclient.message_type = atom_cache_.GetAtom(kWMProtocols);
ev.xclient.format = 32;
ev.xclient.data.l[0] = atom_cache_.GetAtom("WM_DELETE_WINDOW");
ev.xclient.data.l[0] = atom_cache_.GetAtom(kWMDeleteWindow);
ev.xclient.data.l[1] = CurrentTime;
XSendEvent(xdisplay_, xwindow_, False, NoEventMask, &ev);
}
@ -245,13 +254,52 @@ uint32_t CefWindowX11::DispatchEvent(const ui::PlatformEvent& event) {
changes.width = bounds.width();
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(bounds);
// Find the top-most window containing the browser window.
views::X11TopmostWindowFinder finder;
::Window topmost_window = finder.FindWindowAt(bounds.origin());
DCHECK(topmost_window);
// Configure the drag&drop proxy property for the top-most window so
// that all drag&drop-related messages will be sent to the child
// DesktopWindowTreeHostX11. The proxy property is referenced by
// DesktopDragDropClientAuraX11::FindWindowFor.
::Window proxy_target = gfx::kNullAcceleratedWidget;
ui::GetXIDProperty(topmost_window, kXdndProxy, &proxy_target);
if (proxy_target != child) {
// Set the proxy target for the top-most window.
XChangeProperty(xdisplay_,
topmost_window,
atom_cache_.GetAtom(kXdndProxy),
XA_WINDOW,
32,
PropModeReplace,
reinterpret_cast<unsigned char*>(&child), 1);
// Do the same for the proxy target per the spec.
XChangeProperty(xdisplay_,
child,
atom_cache_.GetAtom(kXdndProxy),
XA_WINDOW,
32,
PropModeReplace,
reinterpret_cast<unsigned char*>(&child), 1);
}
}
}
break;
}
case ClientMessage: {
Atom message_type = static_cast<Atom>(xev->xclient.data.l[0]);
if (message_type == atom_cache_.GetAtom("WM_DELETE_WINDOW")) {
Atom message_type = xev->xclient.message_type;
if (message_type == atom_cache_.GetAtom(kWMProtocols)) {
Atom protocol = static_cast<Atom>(xev->xclient.data.l[0]);
if (protocol == atom_cache_.GetAtom(kWMDeleteWindow)) {
// We have received a close message from the window manager.
if (browser_ && browser_->destruction_state() <=
CefBrowserHostImpl::DESTRUCTION_STATE_PENDING) {
@ -266,7 +314,7 @@ uint32_t CefWindowX11::DispatchEvent(const ui::PlatformEvent& event) {
// Allow the close.
XDestroyWindow(xdisplay_, xwindow_);
}
} else if (message_type == atom_cache_.GetAtom("_NET_WM_PING")) {
} else if (protocol == atom_cache_.GetAtom(kNetWMPing)) {
XEvent reply_event = *xev;
reply_event.xclient.window = parent_xwindow_;
@ -277,6 +325,7 @@ uint32_t CefWindowX11::DispatchEvent(const ui::PlatformEvent& event) {
&reply_event);
XFlush(xdisplay_);
}
}
break;
}
case DestroyNotify:

View File

@ -112,6 +112,12 @@ patches = [
'name': 'webkit_platform_mac_328814',
'path': '../third_party/WebKit/Source/platform/mac/',
},
{
# Fix drag&drop of combined text and URL data on Linux/Aura.
# https://codereview.chromium.org/208313009
'name': 'ui_dragdrop_355390',
'path': '../ui/base/dragdrop/',
},
{
# Disable scollbar bounce and overlay on OS X.
# http://code.google.com/p/chromiumembedded/issues/detail?id=364

View File

@ -0,0 +1,14 @@
Index: os_exchange_data_provider_aurax11.cc
===================================================================
--- os_exchange_data_provider_aurax11.cc (revision 280796)
+++ os_exchange_data_provider_aurax11.cc (working copy)
@@ -155,7 +155,8 @@
format_map_.Insert(atom_cache_.GetAtom(kMimeTypeMozillaURL), mem);
// Set a string fallback as well.
- SetString(spec);
+ if (!HasString())
+ SetString(spec);
// Return early if this drag already contains file contents (this implies
// that file contents must be populated before URLs). Nautilus (and possibly

View File

@ -80,7 +80,34 @@ Index: desktop_aura/desktop_window_tree_host_x11.cc
xwindow_ = None;
desktop_native_widget_aura_->OnHostClosed();
@@ -1042,9 +1044,13 @@
@@ -443,6 +445,8 @@
}
gfx::Rect DesktopWindowTreeHostX11::GetWindowBoundsInScreen() const {
+ if (!screen_bounds_.IsEmpty())
+ return screen_bounds_;
return bounds_;
}
@@ -455,6 +459,8 @@
// Attempts to calculate the rect by asking the NonClientFrameView what it
// thought its GetBoundsForClientView() were broke combobox drop down
// placement.
+ if (!screen_bounds_.IsEmpty())
+ return screen_bounds_;
return bounds_;
}
@@ -899,6 +905,8 @@
}
gfx::Point DesktopWindowTreeHostX11::GetLocationOnNativeScreen() const {
+ if (!screen_bounds_.IsEmpty())
+ return screen_bounds_.origin();
return bounds_.origin();
}
@@ -1042,9 +1050,13 @@
}
}
@ -95,7 +122,7 @@ Index: desktop_aura/desktop_window_tree_host_x11.cc
bounds_.x(), bounds_.y(),
bounds_.width(), bounds_.height(),
0, // border width
@@ -1600,6 +1606,10 @@
@@ -1600,6 +1612,10 @@
}
break;
}
@ -110,7 +137,26 @@ Index: desktop_aura/desktop_window_tree_host_x11.h
===================================================================
--- desktop_aura/desktop_window_tree_host_x11.h (revision 280796)
+++ desktop_aura/desktop_window_tree_host_x11.h (working copy)
@@ -331,6 +331,9 @@
@@ -84,6 +84,8 @@
// Deallocates the internal list of open windows.
static void CleanUpWindowList();
+ void set_screen_bounds(const gfx::Rect& bounds) { screen_bounds_ = bounds; }
+
protected:
// Overridden from DesktopWindowTreeHost:
virtual void Init(aura::Window* content_window,
@@ -250,6 +252,9 @@
// The bounds of |xwindow_|.
gfx::Rect bounds_;
+ // Override the screen bounds when the host is a child window.
+ gfx::Rect screen_bounds_;
+
// Whenever the bounds are set, we keep the previous set of bounds around so
// we can have a better chance of getting the real |restored_bounds_|. Window
// managers tend to send a Configure message with the maximized bounds, and
@@ -331,6 +336,9 @@
// the frame when |xwindow_| gains focus or handles a mouse button event.
bool urgency_hint_set_;