b=500081 use a timestamp when grabbing the pointer and generate timestamps for drags in the same way r=roc

--HG--
extra : transplant_source : %CF%87%19S%2C%8C2%BD%C9%0C%2B%C6%BA%22%EE%CB%06%BC%D2%00
This commit is contained in:
Karl Tomlinson 2012-02-02 15:12:26 +13:00
Родитель 049ad9d694
Коммит f3074628f1
3 изменённых файлов: 46 добавлений и 18 удалений

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

@ -323,17 +323,15 @@ nsDragService::InvokeDragSession(nsIDOMNode *aDOMNode,
if (aActionType & DRAGDROP_ACTION_LINK)
action = (GdkDragAction)(action | GDK_ACTION_LINK);
// Create a fake event for the drag so we can pass the time
// (so to speak.) If we don't do this the drag can end as a
// result of a button release that is actually _earlier_ than
// CurrentTime. So we use the time on the last button press
// event, as that will always be older than the button release
// that ends any drag.
// Create a fake event for the drag so we can pass the time (so to speak).
// If we don't do this, then, when the timestamp for the pending button
// release event is used for the ungrab, the ungrab can fail due to the
// timestamp being _earlier_ than CurrentTime.
GdkEvent event;
memset(&event, 0, sizeof(GdkEvent));
event.type = GDK_BUTTON_PRESS;
event.button.window = mHiddenWidget->window;
event.button.time = nsWindow::sLastButtonPressTime;
event.button.time = nsWindow::GetCurrentEventTime();
// start our drag.
GdkDragContext *context = gtk_drag_begin(mHiddenWidget,

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

@ -295,12 +295,10 @@ UpdateLastInputEventTime()
nsWindow *nsWindow::sLastDragMotionWindow = NULL;
bool nsWindow::sIsDraggingOutOf = false;
// This is the time of the last button press event. The drag service
// uses it as the time to start drags.
guint32 nsWindow::sLastButtonPressTime = 0;
// Time of the last button release event. We use it to detect when the
// drag ended before we could properly setup drag and drop.
guint32 nsWindow::sLastButtonReleaseTime = 0;
static guint32 sRetryGrabTime;
static NS_DEFINE_IID(kCDragServiceCID, NS_DRAGSERVICE_CID);
@ -1428,6 +1426,31 @@ SetUserTimeAndStartupIDForActivatedWindow(GtkWidget* aWindow)
GTKToolkit->SetDesktopStartupID(EmptyCString());
}
/* static */ guint32
nsWindow::GetCurrentEventTime()
{
static guint32 sLastCurrentEventTime = GDK_CURRENT_TIME;
guint32 timestamp = gtk_get_current_event_time();
if (timestamp == GDK_CURRENT_TIME) {
timestamp = gdk_x11_display_get_user_time(gdk_display_get_default());
// The user_time is not updated on all user events, so check that we
// haven't returned a more recent timestamp. If so, use the more
// recent timestamp to ensure that subsequent requests will override
// previous requests. Timestamps are just the least significant bits
// of a monotonically increasing function, and so the use of unsigned
// overflow arithmetic.
if (sLastCurrentEventTime != GDK_CURRENT_TIME &&
sLastCurrentEventTime - timestamp <= G_MAXUINT32/2)
return sLastCurrentEventTime;
}
sLastCurrentEventTime = timestamp;
return timestamp;
}
NS_IMETHODIMP
nsWindow::SetFocus(bool aRaise)
{
@ -1881,7 +1904,7 @@ nsWindow::CaptureMouse(bool aCapture)
if (aCapture) {
gtk_grab_add(widget);
GrabPointer();
GrabPointer(GetCurrentEventTime());
}
else {
ReleaseGrabs();
@ -1913,7 +1936,7 @@ nsWindow::CaptureRollupEvents(nsIRollupListener *aListener,
// real grab is only done when there is no dragging
if (!nsWindow::DragInProgress()) {
gtk_grab_add(widget);
GrabPointer();
GrabPointer(GetCurrentEventTime());
}
}
else {
@ -2739,8 +2762,7 @@ nsWindow::OnButtonPressEvent(GtkWidget *aWidget, GdkEventButton *aEvent)
return;
}
// Always save the time of this event
sLastButtonPressTime = aEvent->time;
// We haven't received the corresponding release event yet.
sLastButtonReleaseTime = 0;
nsWindow *containerWindow = GetContainerWindow();
@ -4494,7 +4516,7 @@ void
nsWindow::EnsureGrabs(void)
{
if (mRetryPointerGrab)
GrabPointer();
GrabPointer(sRetryGrabTime);
}
void
@ -4883,7 +4905,7 @@ nsWindow::UpdateTranslucentWindowAlphaInternal(const nsIntRect& aRect,
}
void
nsWindow::GrabPointer(void)
nsWindow::GrabPointer(guint32 aTime)
{
LOG(("GrabPointer %d\n", mRetryPointerGrab));
@ -4911,11 +4933,12 @@ nsWindow::GrabPointer(void)
GDK_POINTER_MOTION_HINT_MASK |
#endif
GDK_POINTER_MOTION_MASK),
(GdkWindow *)NULL, NULL, GDK_CURRENT_TIME);
(GdkWindow *)NULL, NULL, aTime);
if (retval == GDK_GRAB_NOT_VIEWABLE) {
LOG(("GrabPointer: window not viewable; will retry\n"));
mRetryPointerGrab = true;
sRetryGrabTime = aTime;
} else if (retval != GDK_GRAB_SUCCESS) {
LOG(("GrabPointer: pointer grab failed: %i\n", retval));
// A failed grab indicates that another app has grabbed the pointer.

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

@ -191,6 +191,13 @@ public:
NS_IMETHOD MakeFullScreen(bool aFullScreen);
NS_IMETHOD HideWindowChrome(bool aShouldHide);
/**
* GetCurrentEventTime guesses a timestamp for the most recent user input
* event (when the event is not available). This is intended for pointer
* grab or focus requests, for example.
*/
static guint32 GetCurrentEventTime();
// utility method, -1 if no change should be made, otherwise returns a
// value that can be passed to gdk_window_set_decorations
gint ConvertBorderStyles(nsBorderStyle aStyle);
@ -275,7 +282,7 @@ private:
nsIntSize GetSafeWindowSize(nsIntSize aSize);
void EnsureGrabs (void);
void GrabPointer (void);
void GrabPointer (guint32 aTime);
void ReleaseGrabs (void);
public: