Skip to content

Commit

Permalink
Pass the modifier key state to javascript drag&drop events on Desktop…
Browse files Browse the repository at this point in the history
… Linux

BUG=413839
TEST=DesktopDragDropClientAuraX11ChromeSourceTargetTest.*

Review URL: https://codereview.chromium.org/755873002

Cr-Commit-Position: refs/heads/master@{#306093}
  • Loading branch information
pkotwicz authored and Commit bot committed Nov 28, 2014
1 parent 7b3fe5e commit 02429d1
Show file tree
Hide file tree
Showing 8 changed files with 398 additions and 112 deletions.
85 changes: 67 additions & 18 deletions ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "ui/base/x/x11_foreign_window_manager.h"
#include "ui/base/x/x11_util.h"
#include "ui/events/event.h"
#include "ui/events/event_utils.h"
#include "ui/events/platform/platform_event_source.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/screen.h"
Expand Down Expand Up @@ -75,6 +76,33 @@ const char* kAtomsToCache[] = {
NULL
};

int XGetModifiers() {
XDisplay* display = gfx::GetXDisplay();

XID root, child;
int root_x, root_y, win_x, win_y;
unsigned int mask;
XQueryPointer(display,
DefaultRootWindow(display),
&root,
&child,
&root_x,
&root_y,
&win_x,
&win_y,
&mask);
int modifiers = ui::EF_NONE;
if (mask & ShiftMask)
modifiers |= ui::EF_SHIFT_DOWN;
if (mask & ControlMask)
modifiers |= ui::EF_CONTROL_DOWN;
if (mask & Mod1Mask)
modifiers |= ui::EF_ALT_DOWN;
if (mask & Mod4Mask)
modifiers |= ui::EF_COMMAND_DOWN;
return modifiers;
}

// The time to wait for the target to respond after the user has released the
// mouse button before ending the move loop.
const int kEndMoveLoopTimeoutMs = 1000;
Expand Down Expand Up @@ -138,6 +166,8 @@ class DesktopDragDropClientAuraX11::X11DragContext
// action list.
int GetDragOperation() const;

DesktopDragDropClientAuraX11* source_client() { return source_client_; }

private:
// Masks the X11 atom |xdnd_operation|'s views representation onto
// |drag_operation|.
Expand Down Expand Up @@ -204,24 +234,24 @@ DesktopDragDropClientAuraX11::X11DragContext::X11DragContext(
drag_drop_client_(NULL),
waiting_to_handle_position_(false),
suggested_action_(None) {
bool get_types = ((event.data.l[1] & 1) != 0);
if (!source_client_) {
bool get_types = ((event.data.l[1] & 1) != 0);

if (get_types) {
if (!ui::GetAtomArrayProperty(source_window_,
"XdndTypeList",
&unfetched_targets_)) {
return;
}
} else {
// data.l[2,3,4] contain the first three types. Unused slots can be None.
for (int i = 0; i < 3; ++i) {
if (event.data.l[2+i] != None) {
unfetched_targets_.push_back(event.data.l[2+i]);
if (get_types) {
if (!ui::GetAtomArrayProperty(source_window_,
"XdndTypeList",
&unfetched_targets_)) {
return;
}
} else {
// data.l[2,3,4] contain the first three types. Unused slots can be None.
for (int i = 0; i < 3; ++i) {
if (event.data.l[2+i] != None) {
unfetched_targets_.push_back(event.data.l[2+i]);
}
}
}
}

if (!source_client_) {
// The window doesn't have a DesktopDragDropClientAuraX11, that means it's
// created by some other process. Listen for messages on it.
ui::PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this);
Expand All @@ -237,7 +267,6 @@ DesktopDragDropClientAuraX11::X11DragContext::X11DragContext(
// that we can shortcut the X11 server and ask the owning SelectionOwner
// for the data it's offering.
fetched_targets_ = source_client_->GetFormatMap();
unfetched_targets_.clear();
}

ReadActions();
Expand Down Expand Up @@ -379,6 +408,7 @@ DesktopDragDropClientAuraX11::DesktopDragDropClientAuraX11(
xdisplay_(xdisplay),
xwindow_(xwindow),
atom_cache_(xdisplay_, kAtomsToCache),
current_modifier_state_(ui::EF_NONE),
target_window_(NULL),
waiting_on_status_(false),
status_received_since_enter_(false),
Expand Down Expand Up @@ -572,6 +602,13 @@ void DesktopDragDropClientAuraX11::OnXdndDrop(
target_window_location_,
target_window_root_location_,
target_current_context_->GetDragOperation());
if (target_current_context_->source_client()) {
event.set_flags(target_current_context_->source_client()
->current_modifier_state());
} else {
event.set_flags(XGetModifiers());
}

drag_operation = delegate->OnPerformDrop(event);
}

Expand Down Expand Up @@ -695,17 +732,23 @@ void DesktopDragDropClientAuraX11::OnWindowDestroyed(aura::Window* window) {
target_window_ = NULL;
}

void DesktopDragDropClientAuraX11::OnMouseMovement(XMotionEvent* event) {
gfx::Point screen_point(event->x_root, event->y_root);
void DesktopDragDropClientAuraX11::OnMouseMovement(
const gfx::Point& screen_point,
int flags,
base::TimeDelta event_time) {
if (drag_widget_.get()) {
drag_widget_->SetBounds(
gfx::Rect(screen_point - drag_widget_offset_,
drag_widget_->GetWindowBoundsInScreen().size()));
drag_widget_->StackAtTop();
}

const int kModifiers = ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN |
ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN;
current_modifier_state_ = flags & kModifiers;

repeat_mouse_move_timer_.Stop();
ProcessMouseMove(screen_point, event->time);
ProcessMouseMove(screen_point, event_time.InMilliseconds());
}

void DesktopDragDropClientAuraX11::OnMouseReleased() {
Expand Down Expand Up @@ -925,6 +968,12 @@ void DesktopDragDropClientAuraX11::DragTranslate(
location,
root_location,
drag_op));
if (target_current_context_->source_client()) {
(*event)->set_flags(
target_current_context_->source_client()->current_modifier_state());
} else {
(*event)->set_flags(XGetModifiers());
}
if (target_window_changed)
(*delegate)->OnDragEntered(*event->get());
}
Expand Down
13 changes: 12 additions & 1 deletion ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,9 @@ class VIEWS_EXPORT DesktopDragDropClientAuraX11
void OnWindowDestroyed(aura::Window* window) override;

// Overridden from X11WholeScreenMoveLoopDelegate:
void OnMouseMovement(XMotionEvent* event) override;
void OnMouseMovement(const gfx::Point& screen_point,
int flags,
base::TimeDelta event_time) override;
void OnMouseReleased() override;
void OnMoveLoopEnded() override;

Expand Down Expand Up @@ -170,6 +172,12 @@ class VIEWS_EXPORT DesktopDragDropClientAuraX11
// server.
ui::SelectionFormatMap GetFormatMap() const;

// Returns the modifier state for the most recent mouse move. This is done to
// bypass an asynchronous roundtrip with the X11 server.
int current_modifier_state() const {
return current_modifier_state_;
}

// Handling XdndPosition can be paused while waiting for more data; this is
// called either synchronously from OnXdndPosition, or asynchronously after
// we've received data requested from the other window.
Expand Down Expand Up @@ -205,6 +213,9 @@ class VIEWS_EXPORT DesktopDragDropClientAuraX11
class X11DragContext;
scoped_ptr<X11DragContext> target_current_context_;

// The modifier state for the most recent mouse move.
int current_modifier_state_;

// The Aura window that is currently under the cursor. We need to manually
// keep track of this because Windows will only call our drag enter method
// once when the user enters the associated X Window. But inside that X
Expand Down
Loading

0 comments on commit 02429d1

Please sign in to comment.