зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
002bd9b703
Коммит
995e9b73cc
|
@ -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
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче