forked from mirrors/gecko-dev
		
	 87ca855ece
			
		
	
	
		87ca855ece
		
	
	
	
	
		
			
			`synthesizePlainDragAndDrop()` synthesizes drag events with `DataTransfer` object which is set to `DragEvent.dataTransfer` of `dragstart` after starting drag session explicitly. However, this causes `EventStateManager::DoDefaltDragStart()` does not initialize `nsIDragService` instance. Therefore, synthesized drag events cannot work with editor because `DragEvent::GetMozSourceNode()` returns `nullptr` due to `nsIDragSession::GetSourceNode()` returning `nullptr`. On the other hand, synthesized drag events cannot use `nsIDragService::InvodeDragSession()` normally because of hitting an assertion. https://searchfox.org/mozilla-central/rev/690e903ef689a4eca335b96bd903580394864a1c/widget/nsBaseDragService.cpp#230-233 This patch does: - mark drag events caused by synthesized mouse events as "synthesized for tests" - make `synthesizePlainDragAndDrop()` stop using `nsIDragService.startDragSession()` - make `nsBaseDragService` initialize and start session even for synthesized `dragstart` event - make `synthesizePlainDragAndDrop()` stop synthesizing drag events with `DataTransfer` object since it's normal behavior and it'll be initialized with `nsIDragService::GetDataTransfer()` - make `nsBaseDragService` store `effectAllowed` for the session only when it's synthesized session because it's required at initializing synthesized default `dropEffect` value of `dragenter`, `dragover`, `dragexit` and `drop` events' `dataTransfer` - make all tests which use `nsIDragService.startDragSession()` use new API, `nsIDragService.startDragSessionForTests()` to initialize session's `effectAllowed` value - make `EventStateManager::PostHandleEvent()` set drag end point of the test session to `eDrop` event's screen point - make `synthesizePlainDragAndDrop()` set drag end point of the session if it does not synthesize `drop` event because following `endDragSession()` use it at dispatching `dragend` event on the source element Additionally, this adds `dumpFunc` new param to `synthesizePlainDragAndDrop()` because it's really useful to investigate the reason why requesting DnD isn't performed as expected. Differential Revision: https://phabricator.services.mozilla.com/D57425 --HG-- extra : moz-landing-system : lando
		
			
				
	
	
		
			158 lines
		
	
	
	
		
			3.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			158 lines
		
	
	
	
		
			3.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| add_task(async function() {
 | |
|   const url =
 | |
|     "data:text/html,<html><head></head><body>" +
 | |
|     '<a id="target" href="about:blank" title="This is tooltip text" ' +
 | |
|     'style="display:block;height:20px;margin:10px;" ' +
 | |
|     'onclick="return false;">here is an anchor element</a></body></html>';
 | |
| 
 | |
|   let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
 | |
|   let browser = gBrowser.selectedBrowser;
 | |
| 
 | |
|   await new Promise(resolve => {
 | |
|     SpecialPowers.pushPrefEnv({ set: [["ui.tooltipDelay", 0]] }, resolve);
 | |
|   });
 | |
| 
 | |
|   // Send a mousemove at a known position to start the test.
 | |
|   await BrowserTestUtils.synthesizeMouse(
 | |
|     "#target",
 | |
|     -5,
 | |
|     -5,
 | |
|     { type: "mousemove" },
 | |
|     browser
 | |
|   );
 | |
| 
 | |
|   // show tooltip by mousemove into target.
 | |
|   let popupShownPromise = BrowserTestUtils.waitForEvent(document, "popupshown");
 | |
|   await BrowserTestUtils.synthesizeMouse(
 | |
|     "#target",
 | |
|     5,
 | |
|     15,
 | |
|     { type: "mousemove" },
 | |
|     browser
 | |
|   );
 | |
|   await popupShownPromise;
 | |
| 
 | |
|   // hide tooltip by mousemove to outside.
 | |
|   let popupHiddenPromise = BrowserTestUtils.waitForEvent(
 | |
|     document,
 | |
|     "popuphidden"
 | |
|   );
 | |
|   await BrowserTestUtils.synthesizeMouse(
 | |
|     "#target",
 | |
|     -5,
 | |
|     15,
 | |
|     { type: "mousemove" },
 | |
|     browser
 | |
|   );
 | |
|   await popupHiddenPromise;
 | |
| 
 | |
|   // mousemove into the target and start drag by emulation via nsIDragService.
 | |
|   // Note that on some platforms, we cannot actually start the drag by
 | |
|   // synthesized events.  E.g., Windows waits an actual mousemove event after
 | |
|   // dragstart.
 | |
| 
 | |
|   // Emulate a buggy mousemove event.  widget might dispatch mousemove event
 | |
|   // during drag.
 | |
| 
 | |
|   function tooltipNotExpected() {
 | |
|     ok(false, "tooltip is shown during drag");
 | |
|   }
 | |
|   addEventListener("popupshown", tooltipNotExpected, true);
 | |
| 
 | |
|   let dragService = Cc["@mozilla.org/widget/dragservice;1"].getService(
 | |
|     Ci.nsIDragService
 | |
|   );
 | |
|   dragService.startDragSessionForTests(
 | |
|     Ci.nsIDragService.DRAGDROP_ACTION_MOVE |
 | |
|       Ci.nsIDragService.DRAGDROP_ACTION_COPY |
 | |
|       Ci.nsIDragService.DRAGDROP_ACTION_LINK
 | |
|   );
 | |
|   try {
 | |
|     await BrowserTestUtils.synthesizeMouse(
 | |
|       "#target",
 | |
|       5,
 | |
|       15,
 | |
|       { type: "mousemove" },
 | |
|       browser
 | |
|     );
 | |
| 
 | |
|     // eslint-disable-next-line mozilla/no-arbitrary-setTimeout
 | |
|     await new Promise(resolve => setTimeout(resolve, 100));
 | |
|   } finally {
 | |
|     removeEventListener("popupshown", tooltipNotExpected, true);
 | |
|     dragService.endDragSession(true);
 | |
|   }
 | |
| 
 | |
|   await BrowserTestUtils.synthesizeMouse(
 | |
|     "#target",
 | |
|     -5,
 | |
|     -5,
 | |
|     { type: "mousemove" },
 | |
|     browser
 | |
|   );
 | |
| 
 | |
|   // If tooltip listener used a flag for managing D&D state, we would need
 | |
|   // to test if the tooltip is shown after drag.
 | |
| 
 | |
|   // show tooltip by mousemove into target.
 | |
|   popupShownPromise = BrowserTestUtils.waitForEvent(document, "popupshown");
 | |
|   await BrowserTestUtils.synthesizeMouse(
 | |
|     "#target",
 | |
|     5,
 | |
|     15,
 | |
|     { type: "mousemove" },
 | |
|     browser
 | |
|   );
 | |
|   await popupShownPromise;
 | |
| 
 | |
|   // hide tooltip by mousemove to outside.
 | |
|   popupHiddenPromise = BrowserTestUtils.waitForEvent(document, "popuphidden");
 | |
|   await BrowserTestUtils.synthesizeMouse(
 | |
|     "#target",
 | |
|     -5,
 | |
|     15,
 | |
|     { type: "mousemove" },
 | |
|     browser
 | |
|   );
 | |
|   await popupHiddenPromise;
 | |
| 
 | |
|   // Show tooltip after mousedown
 | |
|   popupShownPromise = BrowserTestUtils.waitForEvent(document, "popupshown");
 | |
|   await BrowserTestUtils.synthesizeMouse(
 | |
|     "#target",
 | |
|     5,
 | |
|     15,
 | |
|     { type: "mousemove" },
 | |
|     browser
 | |
|   );
 | |
|   await popupShownPromise;
 | |
| 
 | |
|   popupHiddenPromise = BrowserTestUtils.waitForEvent(document, "popuphidden");
 | |
|   await BrowserTestUtils.synthesizeMouse(
 | |
|     "#target",
 | |
|     5,
 | |
|     15,
 | |
|     { type: "mousedown" },
 | |
|     browser
 | |
|   );
 | |
|   await popupHiddenPromise;
 | |
| 
 | |
|   await BrowserTestUtils.synthesizeMouse(
 | |
|     "#target",
 | |
|     5,
 | |
|     15,
 | |
|     { type: "mouseup" },
 | |
|     browser
 | |
|   );
 | |
|   await BrowserTestUtils.synthesizeMouse(
 | |
|     "#target",
 | |
|     -5,
 | |
|     15,
 | |
|     { type: "mousemove" },
 | |
|     browser
 | |
|   );
 | |
| 
 | |
|   ok(true, "tooltips appear properly");
 | |
| 
 | |
|   gBrowser.removeCurrentTab();
 | |
| });
 |