Yes as the grabPermissions docs say:
This property specifies the permissions when this handler's logic decides to take over the exclusive grab, or when it is asked to approve grab takeover or cancellation by another handler.
"Exclusive" means it's the conventional kind of grab that only one Item or Handler can hold at any given moment. Whereas passive grabs are made for stealth, to deal with the fact that all gestures are ambiguous at the time when the user presses initially: several handlers can take passive grabs to register interest in that point, to monitor mouse or touchpoint movements independently, and then perhaps one of them can decide later to transition to taking the exclusive grab when some condition is met, such that the handler believes the user is initiating a gesture that is relevant to that handler. At the time of the transition, grabPermissions control the negotiation that will occur: which one gets to take over the exclusive grab.
But TapHandler's default gesturePolicy is DragThreshold, and in that case it can detect a tap using only a passive grab, which makes it work independently of other items or handlers. This is meant to be useful for augmenting behavior of other components without interfering with their built-in behavior; but it's not so useful if you want to ensure that only one thing can detect a tap or click. If you want TapHandler to participate in exclusive-grab negotiations (stealing the grab from other items or handlers, and allowing or disallowing the grab to be stolen by another), then you need to set gesturePolicy first, to make it use an exclusive grab. Then, if the TapHandler takes the exclusive grab on press, and the grab is stolen by something else, it will emit canceled rather than tapped.
Sorry it turned out a bit unintuitive: the intention was that gesturePolicy is a designer-friendly property, you just specify the behavior you want and don't worry about grabs. But in practice, it seems to me that we often end up changing gesturePolicy specifically to make TapHandler take an exclusive grab, to not be so stealthy, to participate in the negotations with other components.
If you need to troubleshoot grab-transition scenarios at runtime (which in practice is the first thing to think about whenever mouse or touch behavior is not what you expected), there are several grabbing-related logging categories: qt.pointer.grab qt.quick.handler.grab and qt.quick.pointer.grab. (There are some logging differences between Qt 5 and 6 though.) What I do on Linux is I have a big ~/.config/QtProject/qtlogging.ini file with all logging categories that I've ever cared about, in alphabetical order, mostly commented out (first line begins with # symbol), but those related to event delivery and grabs are often uncommented, since I spend a lot of time trying to fix Qt bugs related to that.
As for setting accepted to true or false on an individual event: that's an old MouseArea pattern, not carried forward into the way that Pointer Handlers are used. There are several problems with it:
QPointerEvent and QEventPoint are stack-allocated Q_GADGET types, not Q_OBJECT. That means they are passed from C++ to QML by value. So setting the accepted property would have no effect, even if we made it a writeable property: you'd be modifying a copy, and the event delivery logic would not see it. When MouseArea lets you do that, it has to populate a special QMouseEvent (QObject) on the fly so that it can be emitted by pointer, just so that you can set that property, and Qt code can see that you set it. (At least since 5.8 those wrapper objects get reused rather than being allocated on-the-fly.)
QML is supposed to be a declarative language. It's not declarative (and not FP) to require you to write a snippet of JS that imperatively sets a property for the sake of its side effect on delivery logic.
QML is supposed to be a designer-friendly language. Newbies should not need to understand what it means to accept an event. (ok perhaps that's really not achieved... nice goal though?)
Accepting a whole event is sensible for mouse but not for touch: if some fingers touch one item and other fingers touch another, you could execute multiple gestures simultaneously (for example you could drag multiple sliders with multiple fingers, if the slider component uses DragHandlers). If accepting the event implies that one item is grabbing all fingers at the same time, that's incompatible with providing the complete event to each item. Because of this, we have to split up QTouchEvents during delivery to Items, which is complex and bad for efficiency. We'd like to be able to stop doing that some day. For now, only Handlers get to see the complete events (all touchpoints, even those that are outside the Item's bounds). This allows things like the margin property to work.
Accepting an event does two things: you are asking to stop propagation, and you are also implicitly asking for an exclusive grab, of the entire event, as you saw it (after the touch-splitting). Basically you are saying "the buck stops here", which is a bit arrogant. (How can one component know for sure, at the time of press, that it's the sole component in the entire application that could possibly care about that gesture?) This is legacy logic that we have to maintain because of all the legacy Items that do event handling that way (MouseArea, Qt Quick Controls, stuff in other Qt modules, lots of third-party components). In the future it's probably better to separate grabbing from control of propagation. This is part of why passive grabs exist too: handlers must be able to act cooperatively, to deal with ambiguity, so they generally should avoid stopping propagation, to allow other handlers to also see the same events. Only when a handler is sure that a gesture has really started should it attempt to take the exclusive grab.