<div id="geary-body" dir="auto"><div><br></div></div><div id="geary-quote" dir="auto"><br>On Fri, Jul 6, 2018 at 1:26 AM, David Edmundson <david@davidedmundson.co.uk> wrote:<br><blockquote type="cite"><div dir="ltr"><div>This protocol is to address the following use case.</div><div><br></div><div>A user clicks on a URL link in an IRC chat and a web browser opens. We want an existing browser window to raise or if it's a newly spawned application to claim focus on startup.<br></div><div><br></div><div>Naturally we also don't want any arbitrary client to be able to raise themselves arbitrarily. <br></div><div></div><div><br></div><div>The protocol is a combination of xdg-foreign and some very simplified aspects of X's startup-notification. <br></div><div><br></div><div>In the example above, the chat client gets a token from the compositor and passes it to the browser using:<br></div><div>  - an environment variable for newly spawned apps</div><div></div><div>  - platofrm-hints in the org.freedesktop.Application interface <br></div><div>  - some hint in the relevant xdg-portal interface <br></div><div>  -  any custom mechanism</div><div><br></div><div> The browser then requests a raise of a top-level using this token.<br></div><div><br></div><div>(Exact common mechanisms should probably be defined, but maybe not in this document)<br></div><div><br></div><div>The exporter is virtually identical to xdg-foreign's exporter, but we can't re-use directly it as it's important that clients know what the exported handle could be used for. <br></div><div><br></div><div>Extending xdg-foreign would be a viable solution, but the lifespan of handles needs to be different..</div><div><br></div><div>Honouring the activation request is entirely up to the compositor which can have whatever advanced focus rules it wants.<br></div><div><br></div></div></blockquote><div><br></div>This is a topic close to my heart - I've been wanting to make GNOME Shell's naive “new surfaces always get focus” behaviour annoy me less!<div><br></div><div>How this works in Mir is that each input event that might signify user intent - button press/release, key press/release, touch down/up - includes a handle derived from the input timestamp. A couple of APIs - including the “raise window” API - then require the presentation of a handle. Just like your handle here, the Mir handle is a blob of bytes that can be shared via whatever out-of-band signalling mechanism is available.</div><div><br></div><div>I think I could pretty easily implement this proposal in a way that provides the same behaviour as Mir's API (and could easily be implemented on top of it), so there's evidence that this is implementable and usable ☺. Hm. If you wanted to, you could make this explicit by requiring an event serial in the export_surface request rather than the wl_surface.</div><div><br></div><div>I wonder if this shouldn't end up as a part of a new xdg_shell revision? It's already tied to xdg_shell in the activate_toplevel request, and I believe that this sort of focus information is a core part of desktop shell behaviour.</div><div><br><blockquote type="cite"><div dir="ltr"><div>Draft proposal below:<br></div><div><br></div><div>-----------<br></div><div><br></div><div><?xml version="1.0" encoding="UTF-8"?><br><protocol name="xdg_foreign_activator"><br><br>  <copyright></div><div>      <br></div><div>  </copyright><br><br>  <description summary="Protocol for sharing focus between cross-process xdg surfaces"><br>      This protocol allows a top level to give up focus and pass it to a specific other client.<br><br>      An example use case would be a chat client opening a link in a browser, that should raise an existing window<br>      or start the newly opened window with focus.<br><br>      The application releasing focus (focus_exported) fetches a handle from the compositor and then passes it to another client using a third party mechanism. <br><br>      The receiving application can use this handle to request focus from the compositor. <br>  </description><br><br>  <interface name="zxdg_focus_exporter_v1" version="1"><br>    <description summary="interface for exporting surfaces"><br>      A global interface used for exporting surfaces that can later be imported<br>      using xdg_importer.<br>    </description><br><br>    <request name="destroy" type="destructor"><br>      <description summary="destroy the xdg_focus_exporter object"><br>        Notify the compositor that the xdg_exporter object will no longer be<br>        used.<br>      </description><br>    </request><br><br>    <request name="export_surface"><br>      <description summary="export a toplevel surface"><br>          It is an error to export a focus that is not mapped.<br>      </description><br>      <arg name="id" type="new_id" interface="zxdg_focus_<wbr>exported_v1"<br>           summary="the new xdg_exported object"/><br>      <arg name="surface" type="object" interface="wl_surface"<br>           summary="the surface to export"/><br>    </request><br>  </interface><br><br>  <interface name="zxdg_focus_exported_v1" version="1"><br>    <description summary="an exported activation handle"><br>    </description></div></div></blockquote><div><br></div><div>Does this interface need to exist? Its purpose appears to be the return-value of export_surface, but that could just as easily be done as an event on zxdg_focus_exporter_v1?</div><div><br></div><div>As far as I can tell there's no resource management enabled by having this client-side object - the handle's lifetime is independent of the lifetime of this object, and there's no other resource tied to this object's lifetime. </div><br><blockquote type="cite"><div dir="ltr"><div><br>    <request name="destroy" type="destructor"><br>      <description summary="unexport the exported surface"><br>          Inform the compositor that this focus_exported object is no longer used.<br>          The handle remains valid and can still be used by the compositor. This is to allow windows to close themselves<br>          after activating another application.<br>      </description><br>    </request><br><br>    <event name="handle"><br>      <description summary="the exported activation handle"><br>        The handle event contains the unique handle of this exported surface<br>        reference. It may be shared with any client, which then can use it to<br>        import the surface by calling zxdg_activator_v1.activate_<wbr>toplevel. A handle<br>        may be used only once.<br>      </description><br>      <arg name="handle" type="string" summary="the exported activation handle"/><br>    </event><br>  </interface><br><br>  <interface name="zxdg_focus_activator_v1" version="1"><br>    <description summary="interface for importing surfaces"></div></div></blockquote><blockquote type="cite"><div dir="ltr"><div>      A global interface used for importing surfaces exported by xdg_focus_exporter.<br>      With this interface, a client can create a reference to a surface of<br>      another client.<br>    </description></div></div></blockquote><div><br></div><div>Your copy/paste is a little bit too zealous :).</div><br><blockquote type="cite"><div dir="ltr"><div><br>    <request name="destroy" type="destructor"><br>      <description summary="destroy the xdg_activator object"><br>        Notify the compositor that the xdg_activator object will no longer be<br>        used.<br>      </description><br>    </request><br><br>    <request name="activate_toplevel"><br>      <description summary="activate a toplevel surface"><br>          Request to the compositor that this surface should claim focus from the exported handle.<br><br>          This request can be sent at any time to raise an alread mapped window or before the window is<br>          mapped to request focus when the window is first configured.<br><br>          At this point the handle is invalidated and cannot be used again.<br><br>          The compositor is free to ignore this request.<br>      </description><br>      <arg name="toplevel" type="xdg_toplevel"><br>      <arg name="handle" type="string"<br>           summary="the exported activation handle"/><br>    </request><br>  </interface><br><br></protocol><br><br></div></div>
</blockquote></div></div>