Bug 1604048 - Make Wayland DnD behaviour closer match X11's - part 1, r=stransky

- Properly initialize `mSelectedDragAction` of data_offers so `GetSelectedDragAction()`
   does not return random values.
 - Emit a motion event on `data_offer_action`, just like GTK does, to chain up to
   `nsDragService::UpdateDragAction()`
 - Only advertise possible actions if we actually accept them.
 - Rename some things to make them easier to understand

Differential Revision: https://phabricator.services.mozilla.com/D60853

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Robert Mader 2020-01-31 11:37:34 +00:00
Родитель 002bd9b703
Коммит 995e9b73cc
3 изменённых файлов: 52 добавлений и 22 удалений

Просмотреть файл

@ -44,7 +44,7 @@ static inline GdkDragAction wl_to_gdk_actions(uint32_t dnd_actions) {
}
static inline uint32_t gdk_to_wl_actions(GdkDragAction action) {
uint32_t dnd_actions = 0;
uint32_t dnd_actions = WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
if (action & (GDK_ACTION_COPY | GDK_ACTION_LINK | GDK_ACTION_PRIVATE))
dnd_actions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
@ -184,18 +184,20 @@ void WaylandDataOffer::DragOfferAccept(const char* aMimeType, uint32_t aTime) {
/* We follow logic of gdk_wayland_drag_context_commit_status()/gdkdnd-wayland.c
* here.
*/
void WaylandDataOffer::SetDragStatus(GdkDragAction aAction, uint32_t aTime) {
uint32_t dnd_actions = gdk_to_wl_actions(aAction);
uint32_t all_actions = WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY |
WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE;
void WaylandDataOffer::SetDragStatus(GdkDragAction aPreferredAction,
uint32_t aTime) {
uint32_t preferredAction = gdk_to_wl_actions(aPreferredAction);
uint32_t allActions = WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
/* Default to move D&D action (Bug 1576268).
/* We only don't choose a preferred action if we don't accept any.
* If we do accept any, it is currently alway copy and move
*/
if (dnd_actions == 0) {
all_actions = WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE;
if (preferredAction != WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE) {
allActions = WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY |
WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE;
}
wl_data_offer_set_actions(mWaylandDataOffer, all_actions, dnd_actions);
wl_data_offer_set_actions(mWaylandDataOffer, allActions, preferredAction);
/* Workaround Wayland D&D architecture here. To get the data_device_drop()
signal (which routes to nsDragService::GetData() call) we need to
@ -219,11 +221,20 @@ GdkDragAction WaylandDataOffer::GetSelectedDragAction() {
}
void WaylandDataOffer::SetAvailableDragActions(uint32_t aWaylandActions) {
mAvailableDragAction = aWaylandActions;
mAvailableDragActions = aWaylandActions;
}
GdkDragAction WaylandDataOffer::GetAvailableDragActions() {
return wl_to_gdk_actions(mAvailableDragAction);
return wl_to_gdk_actions(mAvailableDragActions);
}
void WaylandDataOffer::SetWaylandDragContext(
nsWaylandDragContext* aDragContext) {
mDragContext = aDragContext;
}
nsWaylandDragContext* WaylandDataOffer::GetWaylandDragContext() {
return mDragContext;
}
static void data_offer_offer(void* data, struct wl_data_offer* wl_data_offer,
@ -250,6 +261,17 @@ static void data_offer_action(void* data, struct wl_data_offer* wl_data_offer,
uint32_t dnd_action) {
auto* offer = static_cast<WaylandDataOffer*>(data);
offer->SetSelectedDragAction(dnd_action);
/* Mimic GTK which triggers the motion event callback */
nsWaylandDragContext* dropContext = offer->GetWaylandDragContext();
if (dropContext) {
uint32_t time;
nscoord x, y;
dropContext->GetLastDropInfo(&time, &x, &y);
WindowDragMotionHandler(dropContext->GetWidget(), nullptr, dropContext, x,
y, time);
}
}
/* wl_data_offer callback description:
@ -265,7 +287,10 @@ static const moz_wl_data_offer_listener data_offer_listener = {
data_offer_offer, data_offer_source_actions, data_offer_action};
WaylandDataOffer::WaylandDataOffer(wl_data_offer* aWaylandDataOffer)
: mWaylandDataOffer(aWaylandDataOffer) {
: mWaylandDataOffer(aWaylandDataOffer),
mDragContext(nullptr),
mSelectedDragAction(0),
mAvailableDragActions(0) {
wl_data_offer_add_listener(
mWaylandDataOffer, (struct wl_data_offer_listener*)&data_offer_listener,
this);
@ -322,7 +347,9 @@ nsWaylandDragContext::nsWaylandDragContext(WaylandDataOffer* aDataOffer,
mTime(0),
mGtkWidget(nullptr),
mX(0),
mY(0) {}
mY(0) {
aDataOffer->SetWaylandDragContext(this);
}
void nsWaylandDragContext::DropDataEnter(GtkWidget* aGtkWidget, uint32_t aTime,
nscoord aX, nscoord aY) {
@ -345,11 +372,11 @@ void nsWaylandDragContext::GetLastDropInfo(uint32_t* aTime, nscoord* aX,
*aY = mY;
}
void nsWaylandDragContext::SetDragStatus(GdkDragAction aAction) {
mDataOffer->SetDragStatus(aAction, mTime);
void nsWaylandDragContext::SetDragStatus(GdkDragAction aPreferredAction) {
mDataOffer->SetDragStatus(aPreferredAction, mTime);
}
GdkDragAction nsWaylandDragContext::GetSelectedDragAction() {
GdkDragAction nsWaylandDragContext::GetAvailableDragActions() {
GdkDragAction gdkAction = mDataOffer->GetSelectedDragAction();
// We emulate gdk_drag_context_get_actions() here.

Просмотреть файл

@ -43,7 +43,7 @@ class WaylandDataOffer : public DataOffer {
explicit WaylandDataOffer(wl_data_offer* aWaylandDataOffer);
void DragOfferAccept(const char* aMimeType, uint32_t aTime);
void SetDragStatus(GdkDragAction aAction, uint32_t aTime);
void SetDragStatus(GdkDragAction aPreferredAction, uint32_t aTime);
GdkDragAction GetSelectedDragAction();
void SetSelectedDragAction(uint32_t aWaylandAction);
@ -51,14 +51,18 @@ class WaylandDataOffer : public DataOffer {
void SetAvailableDragActions(uint32_t aWaylandActions);
GdkDragAction GetAvailableDragActions();
void SetWaylandDragContext(nsWaylandDragContext* aDragContext);
nsWaylandDragContext* GetWaylandDragContext();
virtual ~WaylandDataOffer();
private:
bool RequestDataTransfer(const char* aMimeType, int fd) override;
wl_data_offer* mWaylandDataOffer;
RefPtr<nsWaylandDragContext> mDragContext;
uint32_t mSelectedDragAction;
uint32_t mAvailableDragAction;
uint32_t mAvailableDragActions;
};
class PrimaryDataOffer : public DataOffer {
@ -86,8 +90,8 @@ class nsWaylandDragContext : public nsISupports {
void DropMotion(uint32_t aTime, nscoord aX, nscoord aY);
void GetLastDropInfo(uint32_t* aTime, nscoord* aX, nscoord* aY);
void SetDragStatus(GdkDragAction action);
GdkDragAction GetSelectedDragAction();
void SetDragStatus(GdkDragAction aPreferredAction);
GdkDragAction GetAvailableDragActions();
GtkWidget* GetWidget() { return mGtkWidget; }
GList* GetTargets();

Просмотреть файл

@ -1976,8 +1976,7 @@ void nsDragService::UpdateDragAction() {
}
#ifdef MOZ_WAYLAND
else if (mTargetWaylandDragContext) {
// We got the selected D&D action from compositor on Wayland.
gdkAction = mTargetWaylandDragContext->GetSelectedDragAction();
gdkAction = mTargetWaylandDragContext->GetAvailableDragActions();
}
#endif