<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Sat, Sep 20, 2014 at 1:29 AM, Pekka Paalanen <span dir="ltr"><<a href="mailto:ppaalanen@gmail.com" target="_blank">ppaalanen@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">On Fri, 19 Sep 2014 20:20:53 +0200<br>
<span class="">Jonas Ådahl <<a href="mailto:jadahl@gmail.com">jadahl@gmail.com</a>> wrote:<br>
<br>
> On Fri, Sep 19, 2014 at 11:00:21AM -0600, Jasper St. Pierre wrote:<br>
> > On Fri, Sep 19, 2014 at 2:54 AM, Pekka Paalanen <<a href="mailto:ppaalanen@gmail.com">ppaalanen@gmail.com</a>> wrote:<br>
> ><br>
> > > On Fri, 19 Sep 2014 08:33:13 +0200<br>
> > > Jonas Ådahl <<a href="mailto:jadahl@gmail.com">jadahl@gmail.com</a>> wrote:<br>
> > ><br>
> > > > On Thu, Sep 18, 2014 at 10:43:47AM -0700, Jason Ekstrand wrote:<br>
> > > > > On Thu, Sep 18, 2014 at 2:26 AM, Pekka Paalanen <<a href="mailto:ppaalanen@gmail.com">ppaalanen@gmail.com</a>><br>
> > > wrote:<br>
> > > > ><br>
> > > > > > On Wed, 17 Sep 2014 22:35:40 +0200<br>
> > > > > > Jonas Ådahl <<a href="mailto:jadahl@gmail.com">jadahl@gmail.com</a>> wrote:<br>
> > > > > ><br>
<br>
</span><span class="">> > > You could create a wl_pointer, if you do it from interface whose<br>
> > > ancestor is wl_seat, or directly a request in wl_seat. But it does have<br>
> > > downsides like not being able to let the extension mature in Weston<br>
> > > before moving it to Wayland core.<br>
><br>
> I think its a good practice to have a isolateable kind of way of<br>
> extending protocols (ala wl_relative_pointer, wl_scaler, etc) so that<br>
> core protocol objects don't grow too large with non-removable request<br>
> and events.<br>
<br>
</span>Indeed.<br>
<span class=""><br>
> Maybe we need to define "modes of operation" that would be similar to<br>
> "roles" (e.g. xdg_surface), so that wl_relative_pointer changes the<br>
> "mode" of wl_pointer to wl_relative_pointer. This would allow us to add<br>
> a wl_pointer_lock.confine_pointer that doesn't make sense to enable at<br>
> the same time as the pointer is in relative motion mode.<br>
<br>
</span>Roles are not really modes. Some roles do affect the wl_surface<br>
state somewhat, but they do not seriously alter the behaviour of<br>
wl_surface requests or events.<br>
<br>
Having relative vs. absolute modes on a wl_pointer would, though.<br>
<br>
I'd rather avoid modes where we can, especially on protocol<br>
objects. The underlying thing may have modes where it chooses which<br>
protocol object it targets, which is a bit less confusing than<br>
switching what a protocol object does.<br></blockquote><div><br></div><div>Agreed.  Every time one object modifies another it's a lot of documentation chasing every time you want to understand it, and it's really easy to get completely wrong.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<span class=""><br>
> > > > non-sensible requests (set_cursor) on the additional wl_pointer, and<br>
> > > > potentially more as wl_pointer is extended. The alternatives that has<br>
> > > > come up in IRC discussions and backlog reading are:<br>
> > > ><br>
> > > >  1) Create a wl_relative_pointer that would replace wl_pointer, i.e.<br>
> > > >     have its own button, axis, etc events. This would solve all problems<br>
> > > >     related to versioning and wl_pointer being extended, but brings a<br>
> > > >     bunch of other problems for example we'd have to extend<br>
> > > >     wl_relative_pointer each time wl_pointer is extended to keep up, as<br>
> > > >     well as the issue where a wl_pointer is used in a interface or<br>
> > > >     request.<br>
> > ><br>
> > > Either you use wl_pointer and get extensions automatically even if you<br>
> > > don't want to, or you use a new interface that you have to extend<br>
> > > explicitly if you want the same as in wl_pointer. Two sides of a coin.<br>
> > ><br>
> > > As concluded in IRC, wl_pointer is not used as argument in any messages.<br>
><br>
> But it is by wl_pointer_lock.lock_pointer, and who says it'll be the only<br>
> place its used as an argument?<br>
<br>
</span>I think wl_seat might be a better argument. After all, all<br>
wl_pointer objects created from the same wl_seat in the same way<br>
will be identical. I think we should keep it that way, too.<br></blockquote><div><br></div><div>That's a decent idea.  We could simply have wl_pointer_lock.get_relative_pointer(seat) which creates a relative pointer.  At that point, all the absolute pointers get a leave.  The client, if it wants, can create multiple relative pointers.  Once all of them are destroyed, the absolute pointers get an enter again, and off we go.<br><br></div><div>One note though:  I don't think we want to try too hard to make multiple pointers per seat seamless.  That's going to be an awkward case no matter what we do.  We do need to make it well-defined.  I think that having all the absolute pointers get a leave is a reasonable way to do that.  If the compositor has to break the lock, all the relative pointers should get a leave and absolute motion resumes.  (It probably won't get an absolute enter right away.  The use probably went to an expose or alt-tab view so it probably would have gotten an absolute leave anyway.)<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<span class=""><br>
> > > >  3) Extend wl_pointer similar to how wl_viewport extends wl_surface with<br>
> > > >     a wl_relative_pointer (different from in (1)). Such a<br>
> > > >     wl_relative_pointer would, to begin with, only have one request<br>
> > > >     (release) and one event (motion). It wouldn't change anything to the<br>
> > > >     wl_pointer object, it'd still receive button, axis etc events, but<br>
> > > >     motion events are turned into relative motion events via<br>
> > > >     wl_relative_pointer, not affecting the position of the cursor, i.e.<br>
> > > >     not resulting in wl_pointer.motion events.<br>
> > ><br>
> > > This is an interesting idea. I wonder how it works if the client has<br>
> > > two parts (say, libraries or toolkits with their own input processing),<br>
> > > therefore has multiple wl_pointer objects for the same thing, and only<br>
> > > few of them have the pointer_lock interface associated.<br>
><br>
> Hmm. Maybe we need to lock pointer given a seat instead. It'd change the<br>
> "mode" of the underlying pointer to be locked in its position, i.e. not<br>
> send any wl_pointer.motion events. Locking could then be ref counted, so<br>
> that as long as more than one wl_relative_pointer is alive, it's in<br>
> relative mode. Maybe thats unnecessarily complex though.<br>
<br>
</span>We are distinguishing "wl_relative_pointer exists" from<br>
"pointer-lock is active", right?<br>
<br>
A question is: how does the client know when pointer-lock is<br>
active? I think we'd need something like<br>
wl_relative_pointer.enter/leave.<br></blockquote><div><br></div><div>I'm still a fan of destroying relative pointers when not in use.  It's a bit more protocol churn, but it makes it clear when they are/are not active.  Maybe enter/leave will work, but I'm not convinced it's the right way forward.  I'll have to give that a bit more thought before I could give a real solid argument though.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<span class=""><br>
> > > Or what if an app manually starts pointer-lock because the toolkit does<br>
> > > not support it? This is not a use case to design for at all, but if it<br>
> > > happens to work, it might be a nice bonus.<br>
><br>
> If we make it so that locking simply locks the cursor at its position,<br>
> it'd will just work, as the pointer cursor wouldn't move. No unexpected<br>
> wierd wl_pointer.motion events.<br>
<br>
</span>You also need to account for button, axis etc. events, even if the<br>
pointer appears to stay put.<br></blockquote><div><br></div><div>That's a fair point.  That's why I agree that the absolute pointers need to leave when we're getting relative motion.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<span class=""><br>
> What would a set_cursor_position argument do? It sounds like that could<br>
> be more or less used to implement actual warping by just locking, set<br>
> position then unlocking. It'd probably be more useful to have a<br>
> set_cursor_position request in wl_relative_pointer that can be used when<br>
> implementing pointer warping in Xwayland and then possibly even SDL and<br>
> GLFW. Hmm.<br>
<br>
</span>Like I commented in IRC, doing this for warping may not work. We<br>
haven't figured out the usual conditions where the pointer-lock<br>
would actually activate. We probably even leave that up to<br>
compositors, which means a client cannot reliably "just lock" but<br>
may need some further user action.<br>
<br>
If a compositor uses focus-follow-mouse, it would be very annoying<br>
just moving accross a window with existing wl_pointer_lock to<br>
activate the lock, so such a compositor would likely require a<br>
click or raise on the window.<br>
<span class=""><br>
> > > Though, I don't see anything wrong with requiring the client to<br>
> > > explicitly unset the cursor when pointer-lock activates. Or are there<br>
> > > any room for races where the cursor might flicker?<br>
><br>
> Well, except for the buffer queue extension, is there any way for two<br>
> surfaces to synchronize their rendering (assuming they are not not in a<br>
> subsurface tree)?<br>
<br>
</span>No.<br>
<br>
But that is not what I meant. I meant a case where some state on<br>
the cursor surface or wl_pointer causes it to become visible with<br>
one image and some location, and only afterwards the client has the<br>
opportunity to fix the image (and location) to match reality. That<br>
kind of flicker.<br>
<br>
Note, that if we use the standard wl_pointer semantics of enter<br>
event, there cannot be flicker, because the client needs to repond<br>
by setting the cursor image. That's another argument for causing<br>
the normal wl_pointer to emit leave when pointer-lock activates.<br>
<span class=""><br>
> > > There are at least to different basic use cases:<br>
> > > - Quake, i.e. FPS-games with mouse-look<br>
> > > - a strategy game, which still uses a cursor, but implements special<br>
> > >   behaviour when running against window edges like scrolling the view,<br>
> > >   likely with the pointer confined to the window<br>
</span>...<br>
<span class="">> > > A good question is, do we want to support the latter with<br>
> > > pointer-lock, or should it be another extension?<br>
><br>
> I imagine we could have a wl_pointer_lock.confine_pointer, if we want to<br>
> support such a use case directly in Wayland.<br>
<br>
</span>That is not a reason here. If a client runs on relative events, it<br>
can trivially implement confining in any way it wants, without<br>
compositor's help. E.g. when trying to move over the window edge,<br>
do not move the cursor but move the window content instead (like RTS<br>
map).<br>
<br>
The big question here is the acceleration or not.<br>
<span class=""><br>
> > Also, the latter probably wants the same motion acceleration algorithm<br>
> > > as the desktop has, but the former probably not.<br>
> > ><br>
><br>
> I can imagine that the second use case may very well be implemented both<br>
> with confinement and relative pointer events and as such relative<br>
> pointer events would need support both non-accelerated and accelerated<br>
> modes.<br>
<br>
</span>IMHO that raises the question: should be have separate interfaces,<br>
or at least separate requests for asking raw relative motion vs.<br>
desktop-like relative (i.e. accelerated) motion?<br>
<br>
Or should wl_relative_pointer maybe deliver both at the same time?<br>
<br>
Maybe have separate requests for creating the wl_relative_pointer...<br></blockquote><div><br></div><div>Both of those seem reasonable to me. <br></div></div></div></div>