-
-
Notifications
You must be signed in to change notification settings - Fork 5.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Contextmenu is not triggered on iOS13 #6817
Comments
double-tap to fire doubleClickZoom won't work either in iOS 13. A fix for contextmenu is much more important to solve. |
I do confirm the same issue. After initial examination is seems that iOS 13 Safari does not fire touch events properly. Long tap in iOS Safari does not send any event to Leaflet library and is handled by iOS itself. Double click emits following events: mouseover, mousemove, mousedown, mouseup, click, which results in leaflet's event click. It seems to me like serious issue in mobile Safari iOS 13 and I guess it has something to do to make mobile Safari very similar to desktop Safari. Unless touch events are sent properly to Leaflet I am afraid there is not much to be fixed. Is here anyone that will report this to Apple? |
Last week I send a report to Apple support. There is still no answer. |
I have a little bit more information. If add click handler on map div and zoom control is enabled, then the long-press started work as copy/paste context menu.
also doesn't help, only disable copy/paste menu Maybe it'd be useful for someone. |
As a temporary solution for long-press: than add listener for long-press event. And here in event handler convert coordinates to leaflet coordinates. |
Does the library works? So far I have checked source code and the library listens to touch events that are not sent down to Safari anyway. Just curious. |
Yes, it works. For long-press at least. |
great tip thx |
This is final solution as we use it. It detects long tap and emulate 'contextmenu' MenuEvent. Just place it in your JS codes and you should be good. Note: It is good idea to limit execution just for iOS 13 users, not to have too much listeners // Copied and modified from https://github.com/john-doherty/long-press-event/
import rs from 'rootScope'
import $ from '$'
if( rs.platform === 'ios' && / OS 13_/.test( navigator.userAgent ) ) {
// This is our main map el
const mapEl = $('#map-container')
// This class adds -webkit-user-select: none; -webkit-touch-callout: none;
// to the BODY el
document.body.classList.add('ios13')
let timer = null;
const fireLongPressEvent = originalEvent => {
clearLongPressTimer();
const el = originalEvent.target
, x = originalEvent.touches[0].clientX
, y = originalEvent.touches[0].clientY
// This will emulate contextmenu mouse event
const event = new MouseEvent('contextmenu', {
bubbles: true,
cancelable: true,
clientX: x,
clientY: y
})
// fire the long-press event
const suppressClickEvent = el.dispatchEvent.call(el,event);
if (suppressClickEvent) {
// temporarily intercept and clear the next click
mapEl.addEventListener('touchend', function clearMouseUp(e) {
mapEl.removeEventListener('touchend', clearMouseUp, true);
cancelEvent(e);
}, true);
}
}
const startLongPressTimer = e => {
clearLongPressTimer(e);
timer = setTimeout( fireLongPressEvent.bind(null,e), 1000 );
}
const clearLongPressTimer = () => {
if(timer) {
clearTimeout(timer);
timer = null;
}
}
const cancelEvent = e => {
e.stopImmediatePropagation();
e.preventDefault();
e.stopPropagation();
}
// hook events that clear a pending long press event
mapEl.addEventListener('touchcancel', clearLongPressTimer, true);
mapEl.addEventListener('touchend', clearLongPressTimer, true);
mapEl.addEventListener('touchmove', clearLongPressTimer, true);
// hook events that can trigger a long press event
mapEl.addEventListener('touchstart', startLongPressTimer, true); // <- start
} |
came across this thread while looking into a similar issue. I found that calling I believe this comes down to the fact that mobile Safari changed the way it is simulating hover events (to make websites work that solely rely on hover events to open menus and such) |
So far works opposite for me, just suppress all the clicks except for long tap. Can you share piece of code that works for you? |
sorry I was assuming you were using raw touch events to detect double taps. If you are relying on click/mouse events then Either way, it appears to have been a bug in iOS which was fixed in 13.1. |
@felixhageloh I just tested on iOS 13.1 running this demo: But it doesn't seem like the issue has been fixed! Is there something I'm missing out? |
This is issue is referenced from WebKit bug #202143. The WebKit team (in this case, me) is investigating. |
We are very happy you are diving into this issue. As a web developers we would be happy the Safari on iOS 13.x would behave the same way as on iOS 12.x or Chrome on Android in case of touch events. Happy you are here. |
@majid701 sorry if I caused some confusion. The issue I was seeing in 13.0 was: Since 13.1 I am correctly receiving two touchstart and touchend events again. The app I am maintaining uses raw touch events to detect double taps, so this fixed double tap zoom for us. I was incorrectly assuming this would be the case for you as well. |
Note @ilblog that this isn't going to work on iPadOS where the user-agent string is the same as Safari on desktop and won't advertise iOS. |
(reposting from the WebKit bug so people Cc'd to this bug alone can see this.) The So the lack of a Leaflet |
Actually, this code isn't even run with Pointer Events because of this code: if (Browser.touch && !Browser.pointer) {
Map.addInitHook('addHandler', 'tap', Tap);
} On iOS 13 both |
@ginger-777 Do you have a bug number / feedback ID? Generally though the best way to get the attention of WebKit developers is to file a bug directly at bugs.webkit.org. |
@graouts Yes i noticed that as well after reading your last comment. But I tested out disabling Pointer Events from But it doesn't work inside my app. I am loading leaflet inside a Webview. |
As for double-tap-to-zoom, that is also an issue with Leaflet. Consider this code in function onTouchStart(e) {
var count;
if (Browser.pointer) {
if ((!Browser.edge) || e.pointerType === 'mouse') { return; }
count = _pointersCount;
} else {
count = e.touches.length;
}
if (count > 1) { return; }
var now = Date.now(),
delta = now - (last || now);
touch = e.touches ? e.touches[0] : e;
doubleTap = (delta > 0 && delta <= delay);
last = now;
} If a browser supports Pointer Events and it is not Edge then the function exits early. This is the case of Safari or any WebKit-based browser on iOS 13. As far as I can tell, both issues reported here are Leaflet simply not being ready for a browser that supports both Touch Events and Pointer Events (long press and the I closed the WebKit bug as there is nothing for us to fix at this stage. |
Yes @majid701, I think this setting only applies to Safari, not |
I think the solution will be to fix Leaflet library which detects iOS 13 Safari as "pinterType" browser and thus does not handle Touch events not correctly. Thanks a lot @graouts for your effort and a lot of help in this matter. |
There is PR just in motion #6815 concerning double tap on mobile devices, patching same lines of code, so I have asked them to cover this issue also. |
Well this is is interesting, since it can trigger another series of issues, when developers are unable to distinguish macOS vs iPad. This is not related of this Leaflet bug but I think it should be addressed also by Apple. |
SOLVED Thanks to valuable input from Apple I have managed to fix iOS 13 issue at least on iPhone. Since iPad on iOS13 has the same user agent string as macOS, I was unable to fix the issue on iPad. Just modify // 'false' for all iOS devices, that (as of version iOS13 support both, touch and pointer events)
// Unfortunately as of iOS13 it is not possible to distinguish iPad from OS X by user agent string
export var pointer = !!(window.PointerEvent || msPointer) && !userAgentContains('iphone'); |
Fixes Leaflet#6817 at least on iPhone.
Ah! We used the official release. We didn't realise that PR#6855 wasn't included. Our fault. We downloaded the dev branch and we'll try that, Thanks Rob |
We downloaded 1.6-dev and it works fine. Both the double tap and the context-menu on ios 13.2. Thanks for the help, appreciate it. Rob |
Released in 1.6.0 |
iOS 13 added Pointer Events to Safari, which triggers all sorts of unexpected code paths, as Leaflet only expected Pointer Events on older IE for mobile devices. @mourner suggested a simple patch to have webkit not report having pointer events, which works and avoids an iOS 13.1 bug on the iPad, where pointer events might not be generated. Fixes Leaflet#6817.
@mourner |
* Revert "Fix pointer event hendling on iOS13 (#6855)" This reverts commit 747b1f7. Close #6977 * Fix iOS contextmenu issue in more proper way Ref: #6817 * Fix iOS dblclick issue in more proper way * dblclick emulation: simplify code paths a bit * Make use of PointerEvent.isPrimary https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/isPrimary https://caniuse.com/#search=isPrimary IE 10 or later, but it is safe to use here, as for IE we anyway need return from function.
After iOS was updated to 13 version long press doesn't work and contextmenu event is not triggered.
The text was updated successfully, but these errors were encountered: