mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
b=750061 Put the hidden drag widget in the window group of the source node so that the gtk_grab_add during gtk_drag_begin is effective r=roc
--HG-- extra : rebase_source : 8ce17ca75be2b681f08489446bb8fdb2d651fe46
This commit is contained in:
parent
a6b5afba17
commit
cedf9acac4
@ -1,5 +1,5 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* vim:expandtab:shiftwidth=4:tabstop=4:
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:expandtab:shiftwidth=2:tabstop=2:
|
||||
*/
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
@ -103,6 +103,12 @@ gtk_widget_has_focus(GtkWidget *widget)
|
||||
return GTK_WIDGET_HAS_FOCUS(widget);
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
gtk_widget_has_grab(GtkWidget *widget)
|
||||
{
|
||||
return GTK_WIDGET_HAS_GRAB(widget);
|
||||
}
|
||||
|
||||
static inline void
|
||||
gtk_widget_get_allocation(GtkWidget *widget, GtkAllocation *allocation)
|
||||
{
|
||||
@ -181,6 +187,15 @@ gdk_drag_context_get_actions(GdkDragContext *context)
|
||||
{
|
||||
return context->actions;
|
||||
}
|
||||
|
||||
static inline GtkWidget *
|
||||
gtk_window_group_get_current_grab(GtkWindowGroup *window_group)
|
||||
{
|
||||
if (!window_group->grabs)
|
||||
return NULL;
|
||||
|
||||
return GTK_WIDGET(window_group->grabs->data);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !GTK_CHECK_VERSION(2, 24, 0)
|
||||
|
@ -73,6 +73,7 @@
|
||||
#include "nsPresContext.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsISelection.h"
|
||||
#include "nsIViewManager.h"
|
||||
#include "nsIFrame.h"
|
||||
|
||||
// This sets how opaque the drag image is
|
||||
@ -140,7 +141,7 @@ nsDragService::nsDragService()
|
||||
obsServ->AddObserver(this, "quit-application", false);
|
||||
|
||||
// our hidden source widget
|
||||
mHiddenWidget = gtk_invisible_new();
|
||||
mHiddenWidget = gtk_window_new(GTK_WINDOW_POPUP);
|
||||
// make sure that the widget is realized so that
|
||||
// we can use it as a drag source.
|
||||
gtk_widget_realize(mHiddenWidget);
|
||||
@ -264,7 +265,7 @@ DispatchMotionEventCopy(gpointer aData)
|
||||
|
||||
// If there is no longer a grab on the widget, then the drag is over and
|
||||
// there is no need to continue drag motion.
|
||||
if (gtk_grab_get_current() == data->mWidget) {
|
||||
if (gtk_widget_has_grab(data->mWidget)) {
|
||||
gtk_propagate_event(data->mWidget, data->mEvent);
|
||||
}
|
||||
|
||||
@ -286,7 +287,7 @@ OnSourceGrabEventAfter(GtkWidget *widget, GdkEvent *event, gpointer user_data)
|
||||
|
||||
// If there is no longer a grab on the widget, then the drag motion is
|
||||
// over (though the data may not be fetched yet).
|
||||
if (gtk_grab_get_current() != widget)
|
||||
if (!gtk_widget_has_grab(widget))
|
||||
return;
|
||||
|
||||
// Update the cursor position. The last of these recorded gets used for
|
||||
@ -308,6 +309,39 @@ OnSourceGrabEventAfter(GtkWidget *widget, GdkEvent *event, gpointer user_data)
|
||||
DispatchMotionEventCopy, data, DestroyMotionEventData);
|
||||
}
|
||||
|
||||
static GtkWindow*
|
||||
GetGtkWindow(nsIDOMDocument *aDocument)
|
||||
{
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryInterface(aDocument);
|
||||
if (!doc)
|
||||
return NULL;
|
||||
|
||||
nsCOMPtr<nsIPresShell> presShell = doc->GetShell();
|
||||
if (!presShell)
|
||||
return NULL;
|
||||
|
||||
nsCOMPtr<nsIViewManager> vm = presShell->GetViewManager();
|
||||
if (!vm)
|
||||
return NULL;
|
||||
|
||||
nsCOMPtr<nsIWidget> widget;
|
||||
vm->GetRootWidget(getter_AddRefs(widget));
|
||||
if (!widget)
|
||||
return NULL;
|
||||
|
||||
GtkWidget *gtkWidget =
|
||||
static_cast<nsWindow*>(widget.get())->GetMozContainerWidget();
|
||||
if (!gtkWidget)
|
||||
return NULL;
|
||||
|
||||
GtkWidget *toplevel = NULL;
|
||||
toplevel = gtk_widget_get_toplevel(gtkWidget);
|
||||
if (!GTK_IS_WINDOW(toplevel))
|
||||
return NULL;
|
||||
|
||||
return GTK_WINDOW(toplevel);
|
||||
}
|
||||
|
||||
// nsIDragService
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -366,6 +400,14 @@ nsDragService::InvokeDragSession(nsIDOMNode *aDOMNode,
|
||||
event.button.window = mHiddenWidget->window;
|
||||
event.button.time = nsWindow::GetLastUserInputTime();
|
||||
|
||||
// Put the drag widget in the window group of the source node so that the
|
||||
// gtk_grab_add during gtk_drag_begin is effective.
|
||||
// gtk_window_get_group(NULL) returns the default window group.
|
||||
GtkWindowGroup *window_group =
|
||||
gtk_window_get_group(GetGtkWindow(mSourceDocument));
|
||||
gtk_window_group_add_window(window_group,
|
||||
GTK_WINDOW(mHiddenWidget));
|
||||
|
||||
// start our drag.
|
||||
GdkDragContext *context = gtk_drag_begin(mHiddenWidget,
|
||||
sourceList,
|
||||
@ -379,7 +421,7 @@ nsDragService::InvokeDragSession(nsIDOMNode *aDOMNode,
|
||||
StartDragSession();
|
||||
|
||||
// GTK uses another hidden window for receiving mouse events.
|
||||
mGrabWidget = gtk_grab_get_current();
|
||||
mGrabWidget = gtk_window_group_get_current_grab(window_group);
|
||||
if (mGrabWidget) {
|
||||
g_object_ref(mGrabWidget);
|
||||
// Only motion events are required but connect to
|
||||
|
@ -271,9 +271,6 @@ static void drag_data_received_event_cb(GtkWidget *aWidget,
|
||||
/* initialization static functions */
|
||||
static nsresult initialize_prefs (void);
|
||||
|
||||
// Time of the last button release event. We use it to detect when the
|
||||
// drag ended before we could properly setup drag and drop.
|
||||
static guint32 sLastButtonReleaseTime = 0;
|
||||
static guint32 sLastUserInputTime = GDK_CURRENT_TIME;
|
||||
static guint32 sRetryGrabTime;
|
||||
|
||||
@ -2630,8 +2627,6 @@ nsWindow::DispatchMissedButtonReleases(GdkEventCrossing *aGdkEvent)
|
||||
synthEvent.button = buttonType;
|
||||
nsEventStatus status;
|
||||
DispatchEvent(&synthEvent, status);
|
||||
|
||||
sLastButtonReleaseTime = aGdkEvent->time;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2712,9 +2707,6 @@ nsWindow::OnButtonPressEvent(GtkWidget *aWidget, GdkEventButton *aEvent)
|
||||
return;
|
||||
}
|
||||
|
||||
// We haven't received the corresponding release event yet.
|
||||
sLastButtonReleaseTime = 0;
|
||||
|
||||
nsWindow *containerWindow = GetContainerWindow();
|
||||
if (!gFocusWindow && containerWindow) {
|
||||
containerWindow->DispatchActivateEvent();
|
||||
@ -2798,8 +2790,6 @@ nsWindow::OnButtonReleaseEvent(GtkWidget *aWidget, GdkEventButton *aEvent)
|
||||
LOG(("Button %u release on %p\n", aEvent->button, (void *)this));
|
||||
|
||||
PRUint16 domButton;
|
||||
sLastButtonReleaseTime = aEvent->time;
|
||||
|
||||
switch (aEvent->button) {
|
||||
case 1:
|
||||
domButton = nsMouseEvent::eLeftButton;
|
||||
@ -5656,24 +5646,6 @@ drag_motion_event_cb(GtkWidget *aWidget,
|
||||
if (!window)
|
||||
return FALSE;
|
||||
|
||||
if (sLastButtonReleaseTime) {
|
||||
// The drag ended before it was even setup to handle the end of the drag
|
||||
// So, we fake the button getting released again to release the drag
|
||||
GtkWidget *widget = gtk_grab_get_current();
|
||||
GdkEvent event;
|
||||
gboolean retval;
|
||||
memset(&event, 0, sizeof(event));
|
||||
event.type = GDK_BUTTON_RELEASE;
|
||||
event.button.time = sLastButtonReleaseTime;
|
||||
event.button.button = 1;
|
||||
sLastButtonReleaseTime = 0;
|
||||
if (widget) {
|
||||
g_signal_emit_by_name(widget, "button_release_event", &event, &retval);
|
||||
// FALSE means we won't reply with a status message.
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// figure out which internal widget this drag motion actually happened on
|
||||
nscoord retx = 0;
|
||||
nscoord rety = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user