Changeset 60478 in webkit
- Timestamp:
- Jun 1, 2010 7:58:06 AM (14 years ago)
- Location:
- trunk/WebKitTools
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/WebKitTools/ChangeLog
r60471 r60478 1 2010-06-01 Martin Robinson <mrobinson@igalia.com> 2 3 Reviewed by Xan Lopez. 4 5 [GTK] Double clicks cause three button press events 6 https://bugs.webkit.org/show_bug.cgi?id=38853 7 8 Add rudimentary leapForward support to the GTK+ DRT. leapForward allows a test 9 to pause for a specified amount of time. It is used in the processing of drag- 10 -and-drop data as well as to separate distinct mouse double-clicks in some tests. 11 This patch enables tests that rely on the latter behavior to pass. 12 13 * DumpRenderTree/gtk/DumpRenderTree.cpp: 14 (webViewWindowObjectCleared): Only initialize the EventSender when loading the top frame. 15 * DumpRenderTree/gtk/EventSender.cpp: 16 (leapForwardCallback): Add support for adjusting the time offset on leapForward(). 17 (contextClickCallback): Use sendOrQueueEvent. 18 (updateClickCount): Take the time offset into account when counting clicks. 19 (mouseDownCallback): Use sendOrQueueEvent. 20 (getStateFlags): Change down/currentEventButton into buttonCurrentlyDown/lastClickButton. 21 (mouseUpCallback): Use sendOrQueueEvent. 22 (mouseMoveToCallback): Ditto. 23 (mouseWheelToCallback): Ditto. 24 (sendOrQueueEvent): Added. 25 (dispatchEvent): Added. 26 (replaySavedEvents): Pause when an event has a delay and defer to dispatchEvent. 27 (makeEventSender): Only initialize the EventSender when loading the top frame. 28 * DumpRenderTree/gtk/EventSender.h: Ditto. 29 1 30 2010-06-01 Martin Robinson <mrobinson@igalia.com> 2 31 -
trunk/WebKitTools/DumpRenderTree/gtk/DumpRenderTree.cpp
r60471 r60478 674 674 675 675 JSStringRef eventSenderStr = JSStringCreateWithUTF8CString("eventSender"); 676 JSValueRef eventSender = makeEventSender(context );676 JSValueRef eventSender = makeEventSender(context, !webkit_web_frame_get_parent(frame)); 677 677 JSObjectSetProperty(context, windowObject, eventSenderStr, eventSender, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, 0); 678 678 JSStringRelease(eventSenderStr); -
trunk/WebKitTools/DumpRenderTree/gtk/EventSender.cpp
r56316 r60478 46 46 #include <string.h> 47 47 48 // TODO: Currently drag and drop related code is left out and 49 // should be merged once we have drag and drop support in WebCore. 48 // FIXME: Implement support for synthesizing drop events. 50 49 51 50 extern "C" { … … 53 52 } 54 53 55 static bool down = false; 56 static bool currentEventButton = 1; 57 static bool dragMode = true; 58 static bool replayingSavedEvents = false; 54 static bool dragMode; 55 static int timeOffset = 0; 56 59 57 static int lastMousePositionX; 60 58 static int lastMousePositionY; 61 62 59 static int lastClickPositionX; 63 60 static int lastClickPositionY; 64 static int clickCount = 0; 61 static int lastClickTimeOffset; 62 static int lastClickButton; 63 static int buttonCurrentlyDown; 64 static int clickCount; 65 65 66 66 struct DelayedMessage { 67 67 GdkEvent event; 68 68 gulong delay; 69 gboolean isDragEvent;70 69 }; 71 70 … … 85 84 }; 86 85 86 static void sendOrQueueEvent(GdkEvent event); 87 static void dispatchEvent(GdkEvent event); 88 static guint getStateFlags(); 89 87 90 static JSValueRef getDragModeCallback(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception) 88 91 { … … 98 101 static JSValueRef leapForwardCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) 99 102 { 100 // FIXME: Add proper support for forward leaps 103 if (argumentCount > 0) { 104 msgQueue[endOfQueue].delay = JSValueToNumber(context, arguments[0], exception); 105 timeOffset += msgQueue[endOfQueue].delay; 106 ASSERT(!exception || !*exception); 107 } 108 101 109 return JSValueMakeUndefined(context); 102 110 } … … 104 112 static JSValueRef contextClickCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) 105 113 { 106 webkit_web_frame_layout(mainFrame);107 108 114 WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame); 109 115 if (!view) … … 117 123 event.button.window = GTK_WIDGET(view)->window; 118 124 119 gboolean return_val;120 down = true;121 125 event.type = GDK_BUTTON_PRESS; 122 g_signal_emit_by_name(view, "button_press_event", &event, &return_val); 123 124 down = false; 126 sendOrQueueEvent(event); 125 127 event.type = GDK_BUTTON_RELEASE; 126 g_signal_emit_by_name(view, "button_release_event", &event, &return_val);128 sendOrQueueEvent(event); 127 129 128 130 return JSValueMakeUndefined(context); … … 131 133 static void updateClickCount(int button) 132 134 { 133 // FIXME: take the last clicked button number and the time of last click into account. 134 if (lastClickPositionX != lastMousePositionX || lastClickPositionY != lastMousePositionY || currentEventButton != button) 135 if (lastClickPositionX != lastMousePositionX 136 || lastClickPositionY != lastMousePositionY 137 || lastClickButton != button 138 || timeOffset - lastClickTimeOffset >= 1) 135 139 clickCount = 1; 136 140 else … … 159 163 return JSValueMakeUndefined(context); 160 164 161 down = true;162 163 165 GdkEvent event; 164 166 memset(&event, 0, sizeof(event)); 165 event.type = GDK_BUTTON_PRESS;166 167 event.button.button = 1; 167 168 168 169 if (argumentCount == 1) { 169 event.button.button = (int) JSValueToNumber(context, arguments[0], exception) + 1;170 event.button.button = (int)(JSValueToNumber(context, arguments[0], exception)) + 1; 170 171 g_return_val_if_fail((!exception || !*exception), JSValueMakeUndefined(context)); 171 172 } 172 173 currentEventButton = event.button.button;174 173 175 174 event.button.x = lastMousePositionX; 176 175 event.button.y = lastMousePositionY; 177 176 event.button.window = GTK_WIDGET(view)->window; 178 event.button.time = GDK_CURRENT_TIME; 177 178 // Mouse up & down events dispatched via g_signal_emit_by_name must offset 179 // their time value, so that WebKit can detect where sequences of mouse 180 // clicks begin and end. This should not interfere with GDK or GTK+ event 181 // processing, because the event is only seen by the widget. 182 event.motion.time = GDK_CURRENT_TIME + timeOffset; 179 183 event.button.device = gdk_device_get_core_pointer(); 180 184 … … 185 189 getRootCoords(GTK_WIDGET(view), &x_root, &y_root); 186 190 #endif 187 188 191 event.button.x_root = x_root; 189 192 event.button.y_root = y_root; 190 193 194 event.type = GDK_BUTTON_PRESS; 195 sendOrQueueEvent(event); 196 191 197 updateClickCount(event.button.button); 192 193 if (!msgQueue[endOfQueue].delay) { 194 webkit_web_frame_layout(mainFrame); 195 196 gboolean return_val; 197 g_signal_emit_by_name(view, "button_press_event", &event, &return_val); 198 if (clickCount == 2) { 199 event.type = GDK_2BUTTON_PRESS; 200 g_signal_emit_by_name(view, "button_press_event", &event, &return_val); 201 } 202 } else { 203 // replaySavedEvents should have the required logic to make leapForward delays work 204 msgQueue[endOfQueue++].event = event; 205 replaySavedEvents(); 206 } 207 198 if (clickCount == 2) { 199 event.type = GDK_2BUTTON_PRESS; 200 sendOrQueueEvent(event); 201 } 202 203 buttonCurrentlyDown = event.button.button; 208 204 return JSValueMakeUndefined(context); 209 205 } … … 211 207 static guint getStateFlags() 212 208 { 213 guint state = 0; 214 215 if (down) { 216 if (currentEventButton == 1) 217 state = GDK_BUTTON1_MASK; 218 else if (currentEventButton == 2) 219 state = GDK_BUTTON2_MASK; 220 else if (currentEventButton == 3) 221 state = GDK_BUTTON3_MASK; 222 } else 223 state = 0; 224 225 return state; 209 if (buttonCurrentlyDown == 1) 210 return GDK_BUTTON1_MASK; 211 if (buttonCurrentlyDown == 2) 212 return GDK_BUTTON2_MASK; 213 if (buttonCurrentlyDown == 3) 214 return GDK_BUTTON3_MASK; 215 return 0; 226 216 } 227 217 … … 235 225 GdkEvent event; 236 226 memset(&event, 0, sizeof(event)); 237 event.type = GDK_BUTTON_RELEASE;238 227 event.button.button = 1; 239 228 … … 243 232 } 244 233 245 currentEventButton = event.button.button;246 247 234 event.button.x = lastMousePositionX; 248 235 event.button.y = lastMousePositionY; 249 236 event.button.window = GTK_WIDGET(view)->window; 250 event.button.time = GDK_CURRENT_TIME; 237 238 // Mouse up & down events dispatched via g_signal_emit_by_name must offset 239 // their time value, so that WebKit can detect where sequences of mouse 240 // clicks begin and end. This should not interfere with GDK or GTK+ event 241 // processing, because the event is only seen by the widget. 242 event.button.time = GDK_CURRENT_TIME + timeOffset; 251 243 event.button.device = gdk_device_get_core_pointer(); 252 244 event.button.state = getStateFlags(); 253 254 down = false;255 245 256 246 int x_root, y_root; … … 264 254 event.button.y_root = y_root; 265 255 266 if ((dragMode && !replayingSavedEvents) || msgQueue[endOfQueue].delay) {267 msgQueue[endOfQueue].event = event;268 msgQueue[endOfQueue++].isDragEvent = true;269 replaySavedEvents();270 } else {271 webkit_web_frame_layout(mainFrame);272 273 gboolean return_val;274 g_signal_emit_by_name(view, "button_release_event", &event, &return_val);275 }276 277 256 lastClickPositionX = lastMousePositionX; 278 257 lastClickPositionY = lastMousePositionY; 279 258 lastClickButton = buttonCurrentlyDown; 259 lastClickTimeOffset = timeOffset; 260 buttonCurrentlyDown = 0; 261 262 event.type = GDK_BUTTON_RELEASE; 263 sendOrQueueEvent(event); 280 264 return JSValueMakeUndefined(context); 281 265 } … … 300 284 event.motion.x = lastMousePositionX; 301 285 event.motion.y = lastMousePositionY; 286 302 287 event.motion.time = GDK_CURRENT_TIME; 303 288 event.motion.window = GTK_WIDGET(view)->window; … … 310 295 getRootCoords(GTK_WIDGET(view), &x_root, &y_root); 311 296 #endif 312 313 297 event.motion.x_root = x_root; 314 298 event.motion.y_root = y_root; 315 299 316 300 event.motion.state = getStateFlags(); 317 301 318 if (dragMode && down && !replayingSavedEvents) { 319 msgQueue[endOfQueue].event = event; 320 msgQueue[endOfQueue++].isDragEvent = true; 321 } else { 322 webkit_web_frame_layout(mainFrame); 323 324 gboolean return_val; 325 g_signal_emit_by_name(view, "motion_notify_event", &event, &return_val); 326 } 327 302 sendOrQueueEvent(event); 328 303 return JSValueMakeUndefined(context); 329 304 } … … 364 339 g_assert_not_reached(); 365 340 366 if (dragMode && down && !replayingSavedEvents) { 367 msgQueue[endOfQueue].event = event; 368 msgQueue[endOfQueue++].isDragEvent = true; 369 } else { 370 webkit_web_frame_layout(mainFrame); 341 sendOrQueueEvent(event); 342 return JSValueMakeUndefined(context); 343 } 344 345 static JSValueRef beginDragWithFilesCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) 346 { 347 if (argumentCount < 1) 348 return JSValueMakeUndefined(context); 349 350 // FIXME: Implement this completely once WebCore has complete drag and drop support 351 return JSValueMakeUndefined(context); 352 } 353 354 static void sendOrQueueEvent(GdkEvent event) 355 { 356 // Mouse move events are queued if the previous event was queued or if a 357 // delay was set up by leapForward(). 358 if (endOfQueue != startOfQueue || msgQueue[endOfQueue].delay) { 359 msgQueue[endOfQueue++].event = event; 360 replaySavedEvents(); 361 return; 362 } 363 364 dispatchEvent(event); 365 } 366 367 static void dispatchEvent(GdkEvent event) 368 { 369 webkit_web_frame_layout(mainFrame); 370 WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame); 371 if (!view) 372 return; 373 374 gboolean returnValue; 375 if (event.type == GDK_BUTTON_PRESS || event.type == GDK_2BUTTON_PRESS) 376 g_signal_emit_by_name(view, "button_press_event", &event, &returnValue); 377 else if (event.type == GDK_BUTTON_RELEASE) 378 g_signal_emit_by_name(view, "button_release_event", &event, &returnValue); 379 else if (event.type == GDK_MOTION_NOTIFY) 380 g_signal_emit_by_name(view, "motion_notify_event", &event, &returnValue); 381 else if (event.type == GDK_SCROLL) 371 382 gtk_main_do_event(&event); 372 }373 374 return JSValueMakeUndefined(context);375 }376 377 static JSValueRef beginDragWithFilesCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)378 {379 if (argumentCount < 1)380 return JSValueMakeUndefined(context);381 382 // FIXME: Implement this completely once WebCore has complete drag and drop support383 return JSValueMakeUndefined(context);384 383 } 385 384 386 385 void replaySavedEvents() 387 386 { 388 // FIXME: This doesn't deal with forward leaps, but it should. 389 390 WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame); 391 if (!view) 392 return; 393 394 replayingSavedEvents = true; 395 396 for (unsigned queuePos = 0; queuePos < endOfQueue; queuePos++) { 397 GdkEvent event = msgQueue[queuePos].event; 398 gboolean return_val; 399 400 switch (event.type) { 401 case GDK_BUTTON_RELEASE: 402 g_signal_emit_by_name(view, "button_release_event", &event, &return_val); 403 break; 404 case GDK_BUTTON_PRESS: 405 g_signal_emit_by_name(view, "button_press_event", &event, &return_val); 406 break; 407 case GDK_MOTION_NOTIFY: 408 g_signal_emit_by_name(view, "motion_notify_event", &event, &return_val); 409 break; 410 default: 411 continue; 387 // FIXME: Eventually we may need to have more sophisticated logic to 388 // track drag-and-drop operations. 389 390 // First send all the events that are ready to be sent 391 while (startOfQueue < endOfQueue) { 392 if (msgQueue[startOfQueue].delay) { 393 g_usleep(msgQueue[startOfQueue].delay * 1000); 394 msgQueue[startOfQueue].delay = 0; 412 395 } 413 396 414 startOfQueue++; 415 } 416 417 int numQueuedMessages = endOfQueue - startOfQueue; 418 if (!numQueuedMessages) { 419 startOfQueue = 0; 420 endOfQueue = 0; 421 replayingSavedEvents = false; 422 return; 397 dispatchEvent(msgQueue[startOfQueue++].event); 423 398 } 424 399 425 400 startOfQueue = 0; 426 401 endOfQueue = 0; 427 428 replayingSavedEvents = false;429 402 } 430 403 … … 662 635 } 663 636 664 JSObjectRef makeEventSender(JSContextRef context) 665 { 666 down = false; 667 dragMode = true; 668 lastMousePositionX = lastMousePositionY = 0; 669 lastClickPositionX = lastClickPositionY = 0; 670 671 if (!replayingSavedEvents) { 672 // This function can be called in the middle of a test, even 673 // while replaying saved events. Resetting these while doing that 674 // can break things. 637 JSObjectRef makeEventSender(JSContextRef context, bool isTopFrame) 638 { 639 if (isTopFrame) { 640 dragMode = true; 641 642 // Fly forward in time one second when the main frame loads. This will 643 // ensure that when a test begins clicking in the same location as 644 // a previous test, those clicks won't be interpreted as continuations 645 // of the previous test's click sequences. 646 timeOffset += 1000; 647 648 lastMousePositionX = lastMousePositionY = 0; 649 lastClickPositionX = lastClickPositionY = 0; 650 lastClickTimeOffset = 0; 651 lastClickButton = 0; 652 buttonCurrentlyDown = 0; 653 clickCount = 0; 654 675 655 endOfQueue = 0; 676 656 startOfQueue = 0; -
trunk/WebKitTools/DumpRenderTree/gtk/EventSender.h
r48228 r60478 34 34 typedef struct OpaqueJSValue* JSObjectRef; 35 35 36 JSObjectRef makeEventSender(JSContextRef context );36 JSObjectRef makeEventSender(JSContextRef context, bool isTopFrame); 37 37 void replaySavedEvents(); 38 38
Note: See TracChangeset
for help on using the changeset viewer.