Skip to content
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

It isn't clear why separate Pen Events are needed #324

Closed
smaug---- opened this issue May 25, 2020 · 12 comments
Closed

It isn't clear why separate Pen Events are needed #324

smaug---- opened this issue May 25, 2020 · 12 comments
Assignees

Comments

@smaug----
Copy link

https://discourse.wicg.io/t/penevents-to-enable-rich-pen-scenarios-on-the-web/3747/3

@gked
Copy link
Contributor

gked commented May 28, 2020

Thank you for the feedback, @smaug---- .

We initially thought of Pen button events as natural extensions of pointer events. We did receive some feedback in this thread suggesting that Pointer Events may not be an appropriate venue for this. Key difference is pen events are ambient events. They do not require the stylus touching the surface of a screen.

If you are referring to the specificity of the API being pen-related, we couldn't think of another device that delivered similar experience. We are opened to suggestions though on making it to be a more generic API.

CC: @luisjuansp

@BoCupp-Microsoft
Copy link
Contributor

Note the explainer has been updated to address this question. You can find the relevant bits in System Interactions and Alternatives Considered / Dispatching Additional PointerEvents.

Quoting them here for convenience:

System Interactions

Note on some operating systems, adding or removing the event listener may cause side-effects. For example, on Windows, the shell provides configurable behavior for launching frequently used inking applications when pen button interactions are detected. Applications may register with the system to provide alternative behaviors and suppress the default behavior from the OS. For web applications, it is expected that only active documents that have a registered event listener can override the system behavior.

These side effects are one reason why new events are proposed instead of reusing existing events like pointerdown, pointerup and click. Sites which listen to these existing events don't intend to override system behavior. In contrast, listening to a penbuttonclick is well aligned with the event that generates the specialized behavior for pens on Windows and serves as a clear signal that the web app intends to provide its own behavior to replace the default system action.

Alternative: Dispatch Additional PointerEvents

Currently PointerEvents are named as such because the common trait of all devices that generate PointerEvents is that they point at some location on the screen. Specifically for pens, a PointerEvent represents a "button" of the pen coming into contact with the digitizer (or being moved near the digitizer) at a specific location.

Because the actions represented by the proposed events don't relate to a particular location, generating a PointerEvent seems semantically wrong. As a result, this option is not being pursued.

@othermaciej
Copy link

Copying an old comment of mine from discourse since I was directed here:

These events seem awfully hardware specific. For the button events my first thought would be, why special events just for pens and not an extension to pointer events? If the button press happens while the stylus is down then it should clearly be a pointer event, so I guess the problem case is when the stylus is not touching the screen, but couldn’t there be some extension to pointer events to handle a location free case? This would help for future pointing devices that might at times not have a screen location.

At the very least, the Explainer should address “why not pointer events” and it doesn’t.

For the dock change event, does it affect anything other than specifically the Microsoft Surface with dockable stylus? I’m not aware of other similar hardware having behaviors like this. I think it might be too hardware-specific to be a web standard.

I still think these events are too narrowly hardware-specific. They seem the exact opposite of the inspiration Microsoft showed in unifying mouse events and touch events as pointer events.

Some aspects are also too platform-specific. It seems like a bad idea to send events to webpages when an Apple Pencil is docked or undocked, and I really doubt we would do that. Likewise, the notion that registering for specific event listeners would affect system behavior seems wrong. Even calling it a "pen" instead of something more generic like a "stylus" is a bit of a Windows-ism. The term "pen" seems to only be used with Microsoft products and platforms. Regrettably it also made it into Pointer Events, perhaps because of Apple's in retrospect regrettable decision not to engage. The iPad's term for an accessory of this type is "pencil" but that's obviously also platform-specific.

@BoCupp-Microsoft
Copy link
Contributor

They seem the exact opposite of the inspiration Microsoft showed in unifying mouse events and touch events as pointer events.

When we unified touch/pen and mouse events into pointer events, it was because there was a large amount of existing software written to work with the mouse, and we wanted to define a model where a pen or a finger could also make that software work, i.e. we wanted touch and pen to be able to produce mouse events that would run the same click, contextmenu, etc event handlers that web pages already had defined.

In the case of bluetooth button presses on the pen, we obviously don't want to trigger any existing mouse event handlers on the web page - we want a separate unique signal to enable new unique behaviors, e.g. switching from drawing to erasing mode when clicking the eraser button. This is why we aren't pursuing any unification.

If the goal is simply to minimize the number of types, we can make a button and even a dock/undock event fit into an existing PointerEvent, but at a minimum we need to define new event names or a new event target so that existing handlers won't be run in response to these new signals from the pen.

It seems like a bad idea to send events to webpages when an Apple Pencil is docked or undocked, and I really doubt we would do that.

Can you elaborate on your specific concern, i.e. why is it a bad idea to send pen dock events to web pages? Maybe we can address it. If it helps, our canonical scenario is that when the user takes the pen out of the dock, an author can open a drawing menu.

Likewise, the notion that registering for specific event listeners would affect system behavior seems wrong.

This seems like the most ergonomic approach to me. If an author wants to offer specialized behavior for a pen event then just handling the event will make all the right behavior happen. I didn't see any value in building some alternative interface to EventTarget. If you have another idea you'd like me to explore let me know.

Even calling it a "pen" instead of something more generic like a "stylus" is a bit of a Windows-ism.

I think there is value it keeping the name of the event aligned with the corresponding pointerType value. If you can convince the editors of the pointer events spec to introduce stylus I'm happy to make these events use the more generic name.

@domenic
Copy link

domenic commented Aug 7, 2020

Likewise, the notion that registering for specific event listeners would affect system behavior seems wrong.

I want to second this concern. Registering for event listeners should not have side effects. Events should not have side effects. See the related https://dom.spec.whatwg.org/#action-versus-occurance.

@BoCupp-Microsoft
Copy link
Contributor

BoCupp-Microsoft commented Aug 9, 2020

To address concerns with addEventListener creating side effects, we could instead create a PenObserver. The observe method would trigger any registration that may be necessary to start receiving the events. Here's some code for how it might work.

Your thoughts are appreciated.

// Construct a PenEventListener to register for a set of events.
let po = new PenObserver([
    { 
        type: "click",
        // Because a future pen may have multiple buttons with independent system-wide actions 
        // that can be independently overridden, list buttons the author intends to handle explicitly.
        buttons: [5]
    },
    { 
        type: "dblclick",
        buttons: [5]
    },
    { 
        type: "pressandhold",
        buttons: [5]
    },
    { 
        type: "dockchange"
    }
])

// Observe the events whenever this window is focused
po.observe(window)

// Event handlers
po.addEventListener("click", (e) => {
    if (e.button == 5) {
        // handle pen click for button 5
    }
})

po.addEventListener("dblclick", (e) => {
    if (e.button == 5) {
        // handle pen dblclick for button 5
    }
})

po.addEventListener("pressandhold", (e) => {
    if (e.button == 5) {
        // handle pen pressandhold for button 5
    }
})

po.addEventListener("dockchange", (e) => {
    if (!e.docked) {
        // handle the pen being undocked
    } else {
        // handle the pen being docked
    }
})

// If you're done listening for events call disconnect
po.disconnect()

@domenic
Copy link

domenic commented Aug 9, 2020

I think observing, no matter the API, should be a separate API from the side effect trigger API.

@BoCupp-Microsoft
Copy link
Contributor

To clarify, is it just a naming issue? If I had called the interface PenRegistrar with methods register and unregister and then dispatched any events that you've registered for at an instance of PenRegistrar would that address your issue?

@domenic
Copy link

domenic commented Aug 10, 2020

I'm sorry; I didn't read the above proposal carefully enough. I assumed that it would be an Observer in the style of IntersectionObserver/etc. The above proposal seems great, actually, in terms of making the side effects explicit.

(Nit: taking the window argument is probably not necessary; you should use the PenObserver's relevant global object, instead of allowing PenObservers created from new window1.PenObserver() to .observe(window2).)

But yes, a different name would probably help distinguish it from those other Observer pattern instances. (To be clear, I like the API you've proposed better than using the Observer pattern; see https://w3ctag.github.io/design-principles/#events-vs-observers for more.) Registrar seems reasonable, or maybe handler, or something like that.

@BoCupp-Microsoft
Copy link
Contributor

The above proposal seems great, actually, in terms of making the side effects explicit.

OK. Thank you.

(Nit: taking the window argument is probably not necessary; you should use the PenObserver's relevant global object, instead of allowing PenObservers created from new window1.PenObserver() to .observe(window2).)

OK will do.

But yes, a different name would probably help distinguish it from those other Observer pattern instances.

New candidate names: construct a PenEventTarget which you can connect to have it start dispatching events and disconnect to have it stop.

@BoCupp-Microsoft
Copy link
Contributor

I've updated the explainer with the changes we've discussed in this issue so far. I think I've addressed @domenic's suggestions and one of @othermaciej's concerns about side-effects from event listeners.

I don't see anything else currently actionable in this issue so I'll wait for a few days and then considered it closed if I don't see any new comments.

Thanks for the feedback!
Bo

@BoCupp-Microsoft
Copy link
Contributor

Closing this issue per my last comment above. Please do comment and reopen if there are any additional aspects you'd like me to address.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants