wayfire icon indicating copy to clipboard operation
wayfire copied to clipboard

Consider a simple IPC socket

Open ammen99 opened this issue 5 years ago • 24 comments

This would allow users to create simple scripts in the language they prefer. Of course, if #48 is solved, we can just provide bindings to common languages.

ammen99 avatar Aug 09 '18 15:08 ammen99

Please don't implement it with DBus. IPC socket is enough. DBus is also implemented on top of sockets, but it brings more complication.

notramo avatar Aug 29 '18 11:08 notramo

@notramo I also prefer IPC, although I still haven't decided the format

UPD: accidentally clicked close button

ammen99 avatar Aug 29 '18 12:08 ammen99

@ammen99 what's the status for it? It'll be a really useful addon to later add wayfire-supported waybar modules, like "sway/workspaces".

shivanshs9 avatar Jun 28 '20 16:06 shivanshs9

@ammen99 what's the status for it? It'll be a really useful addon to later add wayfire-supported waybar modules, like "sway/workspaces".

For that very specific use-case, we should eventually get a workspace protocol which would then work on any compositor supporting it (but I always postpone this task, so I can't say when it'll be implemented).

Anyway, for the IPC idea status - I have no idea what would be useful. The following questions are open:

  1. What information do we want to export via the IPC? (needs a semi-exhaustive list)
  2. What commands do we want to support? (needs a semi-exhaustive list)
  3. How would plugins and IPC interact with each other?

A necessary first step would be answering these questions, but as I said, I currently have no need of the IPC so I do not know what people would find useful - especially considering there are already plugins which will always be more powerful than any IPC we can come up with.

ammen99 avatar Jun 28 '20 20:06 ammen99

While I agree plugins would always be more powerful than IPC, it's not possible to extend a third-party application to support wayfire, for example, Waybar. Maybe instead of integrating into the wayfire core code, each IPC socket could be integrated into the plugin code, on a per-need basis.

Right now, I can think of adding IPC socket for the workspaces:

  • Information
    • List all workspaces
    • Get current workspace
  • Command
    • Switch to the workspace with a given index

shivanshs9 avatar Jul 02 '20 18:07 shivanshs9

The way I see it, if someone wants to implement IPC for wayfire, they should create an ipc plugin. Aside from coming up with a solid API, there's not much more to it than writing an implementation including some sort of client.

  1. How would plugins and IPC interact with each other?

The ipc plugin would interact with other plugins the same way that plugins currently interact. Perhaps it is the case that I don't fully understand the implications of this question but it seems like everything could be handled in the ipc plugin.

  1. How powerful do we make this IPC in comparison with a plugin? (although you could say this overlaps with 1./2.)

Since ipc would be a plugin, they would have the same 'power'. Again, perhaps I don't fully know what you mean by this.

Also, there is a dbus plugin thanks to @damianatorrpm, that will likely be released eventually, which contains a fair set of capabilities.

soreau avatar Jul 02 '20 20:07 soreau

The ipc plugin would interact with other plugins the same way that plugins currently interact. Perhaps it is the case that I don't fully understand the implications of this question but it seems like everything could be handled in the ipc plugin.

Yes, but then we need to define APIs. Like, plugins can register commands, emit events to the IPC, etc.

Since ipc would be a plugin, they would have the same 'power'. Again, perhaps I don't fully know what you mean by this.

The more I think of it, the more this question fully overlaps with the 1. and 2, so it doesn't make sense. I'll remove it from my list.

ammen99 avatar Jul 02 '20 20:07 ammen99

@shivanshs9 I have created a dbus plugin, which can do the actions described at the end. It is proprietary at this point (with the exception of two people to whom it is licensed under MIT and they could fork it if they wanted to) and can be used on one distribution (theoretically can be used on all distros, but it is designed to add vaue to that distro which is not released just yet) only.

As I can see from your profile you are a skilled developer yourself, so I could add you to those people, granted that you do some work on wayfire. Acceptable to me would be the following (all of them would need to be done):

  1. Chrome tabs can not be dragged straight from the tabbar to another output
  2. Take over https://github.com/swaywm/wlroots/pull/2264 and get it merged
  3. Add the same workaround gnome uses for steam regarding maximize icon https://github.com/ValveSoftware/steam-for-linux/issues/3792
  4. add a signal to wayfire when screen edge is approached (like gnome top-left corner)
  1. and 3. are very small tasks 2. the code already exists it just needs communication skills with wlroots developers and maybe small changes. The other option would be to wait until the distro is released and use wayfire in conjuction with the plugin under a proprietary license or to write your own IPC plugin.

Below you can see what the dbus plugins is capable of:

const gchar introspection_xml[] =
    "<node>"
    "  <interface name='org.wayland.compositor'>"
    /************************* Methods ************************/

    /************************* Output Methods ************************/
    "    <method name='query_output_ids'>"
    "      <arg direction='out' type='au' />"
    "    </method>"
    "    <method name='query_output_name'>"
    "      <arg type='u' name='output_id' direction='in'/>"
    "      <arg type='s' name='name' direction='out'/>"
    "    </method>"
    "    <method name='query_output_manufacturer'>"
    "      <arg type='u' name='output_id' direction='in'/>"
    "      <arg type='s' name='name' direction='out'/>"
    "    </method>"
    "    <method name='query_output_model'>"
    "      <arg type='u' name='output_id' direction='in'/>"
    "      <arg type='s' name='name' direction='out'/>"
    "    </method>"
    "    <method name='query_output_serial'>"
    "      <arg type='u' name='output_id' direction='in'/>"
    "      <arg type='s' name='name' direction='out'/>"
    "    </method>"
    "    <method name='query_output_workspace'>"
    "      <arg type='u' name='output_id' direction='in'/>"
    "      <arg type='u' name='xHorizontal' direction='out'/>"
    "      <arg type='u' name='yVertical' direction='out'/>"
    "    </method>"
    "    <method name='query_xwayland_display'>"
    "      <arg type='s' name='xdisplay' direction='out'/>"
    "    </method>"
    /************************* View Methods ************************/
    "    <method name='query_view_vector_ids'>"
    "      <arg direction='out' type='au' />"
    "    </method>"
    "    <method name='query_view_vector_taskman_ids'>"
    "      <arg direction='out' type='au' />"
    "    </method>"
    "    <method name='query_view_app_id'>"
    "      <arg type='u' name='view_id' direction='in'/>"
    "      <arg type='s' name='app_id' direction='out'/>"
    "    </method>"
    "    <method name='query_view_app_id_gtk_shell'>"
    "      <arg type='u' name='view_id' direction='in'/>"
    "      <arg type='s' name='app_id' direction='out'/>"
    "    </method>"
    "    <method name='query_view_app_id_xwayland_net_wm_name'>"
    "      <arg type='u' name='view_id' direction='in'/>"
    "      <arg type='s' name='app_id' direction='out'/>"
    "    </method>"
    "    <method name='query_view_title'>"
    "      <arg type='u' name='view_id' direction='in'/>"
    "      <arg type='s' name='title' direction='out'/>"
    "    </method>"
    "    <method name='query_view_credentials'>"
    "      <arg type='u' name='view_id' direction='in'/>"
    "      <arg type='i' name='pid' direction='out'/>"
    "      <arg type='u' name='uid' direction='out'/>"
    "      <arg type='u' name='gid' direction='out'/>"
    "    </method>"
    "    <method name='query_view_active'>"
    "      <arg type='u' name='view_id' direction='in'/>"
    "      <arg type='b' name='view_state' direction='out'/>"
    "    </method>"
    "    <method name='query_view_minimized'>"
    "      <arg type='u' name='view_id' direction='in'/>"
    "      <arg type='b' name='view_state' direction='out'/>"
    "    </method>"
    "    <method name='query_view_maximized'>"
    "      <arg type='u' name='view_id' direction='in'/>"
    "      <arg type='b' name='view_state' direction='out'/>"
    "    </method>"
    "    <method name='query_view_fullscreen'>"
    "      <arg type='u' name='view_id' direction='in'/>"
    "      <arg type='b' name='view_state' direction='out'/>"
    "    </method>"
    "    <method name='query_view_output'>"
    "      <arg type='u' name='view_id' direction='in'/>"
    "      <arg type='u' name='output' direction='out'/>"
    "    </method>"
    "    <method name='query_view_layer'>"
    "      <arg type='u' name='view_id' direction='in'/>"
    "      <arg type='u' name='layer' direction='out'/>"
    "    </method>"
    "    <method name='query_view_workspaces'>"
    "      <arg type='u' name='view_id' direction='in'/>"
    "      <arg type='a(ii)' name='workspaces' direction='out'/>"
    "    </method>"
    "    <method name='query_view_group_leader'>"
    "      <arg type='u' name='view_id' direction='in'/>"
    "      <arg type='u' name='view_group_leader_view_id' direction='out'/>"
    "    </method>"
    "    <method name='query_view_role'>"
    "      <arg type='u' name='view_id' direction='in'/>"
    "      <arg type='u' name='view_state' direction='out'/>"
    "    </method>"
    "    <method name='query_workspace_grid_size'>"
    "      <arg type='i' name='rows' direction='out'/>"
    "      <arg type='i' name='columns' direction='out'/>"
    "    </method>"
    "    <method name='query_view_attention'>"
    "      <arg type='u' name='view_id' direction='in'/>"
    "      <arg type='b' name='attention' direction='out'/>"
    "    </method>"
    "    <method name='query_view_xwayland_wid'>"
    "      <arg type='u' name='view_id' direction='in'/>"
    "      <arg type='u' name='xwayland_wid' direction='out'/>"
    "    </method>"
    "    <method name='query_view_xwayland_atom_cardinal'>"
    "      <arg type='u' name='view_id' direction='in'/>"
    "      <arg type='s' name='atom' direction='in'/>"
    "      <arg type='u' name='atom_value' direction='out'/>"
    "    </method>"
    "    <method name='query_view_xwayland_atom_string'>"
    "      <arg type='u' name='view_id' direction='in'/>"
    "      <arg type='s' name='atom' direction='in'/>"
    "      <arg type='s' name='atom_value' direction='out'/>"
    "    </method>"
    "    <method name='query_view_test_data'>"
    "      <arg type='u' name='view_id' direction='in'/>"
    "      <arg type='u' name='value' direction='out'/>"
    "      <arg type='u' name='value2' direction='out'/>"
    "    </method>"
    "    <method name='minimize_view'>"
    "      <arg type='u' name='view_id' direction='in'/>"
    "      <arg type='u' name='action' direction='in'/>"
    "    </method>"
    "    <method name='maximize_view'>"
    "      <arg type='u' name='view_id' direction='in'/>"
    "      <arg type='u' name='action' direction='in'/>"
    "    </method>"
    "    <method name='focus_view'>"
    "      <arg type='u' name='view_id' direction='in'/>"
    "      <arg type='u' name='action' direction='in'/>"
    "    </method>"
    "    <method name='fullscreen_view'>"
    "      <arg type='u' name='view_id' direction='in'/>"
    "      <arg type='u' name='action' direction='in'/>"
    "    </method>"
    "    <method name='close_view'>"
    "      <arg type='u' name='view_id' direction='in'/>"
    "    </method>"
    "    <method name='change_view_minimize_hint'>"
    "      <arg type='u' name='view_id' direction='in'/>"
    "      <arg type='u' name='a' direction='in'/>"
    "      <arg type='u' name='b' direction='in'/>"
    "      <arg type='u' name='c' direction='in'/>"
    "      <arg type='u' name='d' direction='in'/>"
    "    </method>"
    "    <method name='change_output_view'>"
    "      <arg type='u' name='view_id' direction='in'/>"
    "      <arg type='u' name='output' direction='in'/>"
    "    </method>"
    "    <method name='change_workspace_view'>"
    "      <arg type='u' name='view_id' direction='in'/>"
    "      <arg type='u' name='workspace_horizontal' direction='in'/>"
    "      <arg type='u' name='workspace_vertical' direction='in'/>"
    "    </method>"
    "    <method name='change_workspace_output'>"
    "      <arg type='u' name='output' direction='in'/>"
    "      <arg type='u' name='workspace_horizontal' direction='in'/>"
    "      <arg type='u' name='workspace_vertical' direction='in'/>"
    "    </method>"
    "    <method name='change_workspace_all_outputs'>"
    "      <arg type='u' name='workspace_horizontal' direction='in'/>"
    "      <arg type='u' name='workspace_vertical' direction='in'/>"
    "    </method>"
    "    <method name='request_view_sticky'>"
    "      <arg type='u' name='view_id' direction='in'/>"
    "      <arg type='b' name='sticky' direction='in'/>"
    "    </method>"
    /************************* Signals ************************/
    "    <signal name='view_added'>"
    "      <arg type='u' name='view_id'/>"
    "    </signal>"
    "    <signal name='view_closed'>"
    "      <arg type='u' name='view_id'/>"
    "    </signal>"
    "    <signal name='view_app_id_changed'>"
    "      <arg type='u' name='view_id'/>"
    "      <arg type='s' name='new_app_id'/>"
    "    </signal>"
    "    <signal name='view_title_changed'>"
    "      <arg type='u' name='view_id'/>"
    "      <arg type='s' name='new_title'/>"
    "    </signal>"
    "    <signal name='view_state_changed'>"
    "      <arg type='u' name='view_id'/>"
    "      <arg type='i' name='new_state'/>"
    "    </signal>"
    "    <signal name='view_output_move_requested'>"
    "      <arg type='u' name='view_id'/>"
    "      <arg type='u' name='old_output'/>"
    "      <arg type='u' name='new_output'/>"
    "    </signal>"
    "    <signal name='view_output_moved'>"
    "      <arg type='u' name='view_id'/>"
    "      <arg type='u' name='old_output'/>"
    "      <arg type='u' name='new_output'/>"
    "    </signal>"
    "    <signal name='view_workspaces_changed'>"
    "      <arg type='u' name='view_id'/>"
    "    </signal>"
    "    <signal name='view_attention_changed'>"
    "      <arg type='u' name='view_id'/>"
    "      <arg type='b' name='attention'/>"
    "    </signal>"
    "    <signal name='view_group_leader_changed'>"
    "      <arg type='u' name='view_id'/>"
    "      <arg type='u' name='view_group_leader_view_id'/>"
    "    </signal>"
    "    <signal name='view_tiling_changed'>"
    "      <arg type='s' name='test'/>"
    "    </signal>"
    "    <signal name='view_geometry_changed'>"
    "      <arg type='s' name='test'/>"
    "    </signal>"
    "    <signal name='view_moving_changed'>"
    "      <arg type='s' name='test'/>"
    "    </signal>"
    "    <signal name='view_resizing_changed'>"
    "      <arg type='s' name='test'/>"
    "    </signal>"
    "    <signal name='output_view_resizing'>"
    "      <arg type='s' name='test'/>"
    "    </signal>"
    "    <signal name='view_role_changed'>"
    "      <arg type='u' name='view_id'/>"
    "      <arg type='u' name='view_role'/>"
    "    </signal>"

    /****
    * Core Input Events
    ****/
    "    <signal name='pointer_clicked'/>"
    "    <signal name='tablet_touched'/>"
    "    <signal name='view_maximized_changed'>"
    "      <arg type='u' name='view_id'/>"
    "      <arg type='b' name='maximized'/>"
    "    </signal>"
    "    <signal name='view_minimized_changed'>"
    "      <arg type='u' name='view_id'/>"
    "      <arg type='b' name='minimized'/>"
    "    </signal>"
    "    <signal name='view_fullscreen_changed'>"
    "      <arg type='u' name='view_id'/>"
    "      <arg type='b' name='fullscreened'/>"
    "    </signal>"
    "    <signal name='view_focus_changed'>"
    "      <arg type='u' name='view_id'/>"
    "    </signal>"
    "    <signal name='view_focus_changed'>"
    "      <arg type='u' name='view_id'/>"
    "    </signal>"
    "    <signal name='view_layer_changed'>"
    "      <arg type='u' name='view_id'/>"
    "      <arg type='u' name='layer'/>"
    "    </signal>"
    "    <signal name='output_workspace_changed'>"
    "      <arg type='u' name='output_id'/>"
    "      <arg type='i' name='workspace_horizontal'/>"
    "      <arg type='i' name='workspace_vertical'/>"
    "    </signal>"

    "  </interface>"
    "</node>";

damianatorrpm avatar Jul 03 '20 10:07 damianatorrpm

  • Chrome tabs can not be dragged straight from the tabbar to another output

FWIW, the best approach for this is to support Xwayland DnD in wlroots, which is hard (wayland DnD icons are already multi-output in wayfire).

ammen99 avatar Jul 03 '20 10:07 ammen99

The other option would be to wait until the distro is released and use wayfire in conjuction with the plugin under a proprietary license

@damianatorrpm I can't understand why that plugin needs to be released under a proprietary license anyways, especially compared to other big projects (like wayfire). While I gotta agree that your DBus plugin seems to have the capabilities I was looking for, and a lot more, I believe it makes sense to have it as an extension to wlroots, if it can indeed be used for any Wayland compositor. Although, I do understand if you don't want to reveal the plugin now since it would then be a feature for the distro you mentioned.

Anyways, I would prefer to discuss with @ammen99 @soreau, define APIs and implement an IPC plugin for Wayfire, even if it has only workspace-related capabilities.

shivanshs9 avatar Jul 03 '20 16:07 shivanshs9

Sway-ipc and altdesktop/i3ipc-python provide examples of real usage. And https://github.com/Alexays/Waybar/wiki/Module:-Sway is simple query from serialized data is it not.

If Wayfire model shell aims to add traditional desktop paradigm functionalities it could be used to test IPC powers and completeness. Waybar has Taskbar but is very limited. Not possible to mimic Windows' function of having pinned program launcher that once open transforms in active program windows control. I understand Wayland and XWayland have StartupWMClass and app-id confusion, and parent children spawn. If you could implement this functionality for Waybar with IPC and Wayfire shell from calling IPC plugin you have a strong benchmark of your architecture.

ghost avatar Jul 03 '20 19:07 ghost

Sway-ipc and altdesktop/i3ipc-python provide examples of real usage. And https://github.com/Alexays/Waybar/wiki/Module:-Sway is simple query from serialized data is it not.

If Wayfire model shell aims to add traditional desktop paradigm functionalities it could be used to test IPC powers and completeness. Waybar has Taskbar but is very limited. Not possible to mimic Windows' function of having pinned program launcher that once open transforms in active program windows control. I understand Wayland and XWayland have StartupWMClass and app-id confusion, and parent children spawn. If you could implement this functionality for Waybar with IPC and Wayfire shell from calling IPC plugin you have a strong benchmark of your architecture.

This is already possible and it is supported via the foreign-toplevel protocol, see for example the window-list widget in wf-panel and wf-dock. The pinning feature is not there, true, however it is perfectly possible to implement. The way it works is that apps report their app-ids, then Wayfire uses the aforementioned protocol to communicate this to clients. They can then match the app-id of the specific window to a .desktop file to get the icon, or match it against a pinned entry.

ammen99 avatar Jul 03 '20 19:07 ammen99

It appears that the parties interested in an IPC implementation are ignoring the request for an API. Pointing to sway and other projects' documentation is simply not an answer. Until an API is proposed, there's not really much to discuss.

soreau avatar Jul 03 '20 20:07 soreau

Anyways, I would prefer to discuss with @ammen99 @soreau, define APIs and implement an IPC plugin for Wayfire, even if it has only workspace-related capabilities.

Forgot to answer to this, if @shivanshs9 is willing to develop a plugin, I can provide some assistance in the technical parts (like integrating with core & plugins).

ammen99 avatar Jul 03 '20 20:07 ammen99

It was reply for https://github.com/WayfireWM/wayfire/issues/49#issuecomment-653163371 with a more complex example but I forgot to quote in this terrible git UI. I don't need the feature and I don't need pull requests welcome. I will abstain, good luck.

ghost avatar Jul 03 '20 20:07 ghost

Sway-ipc and altdesktop/i3ipc-python provide examples of real usage. And Alexays/Waybar/wiki/Module:-Sway is simple query from serialized data is it not.

Indeed, I've already gone through their implementation. Once a basic plugin is ready, it won't be hard to use it in Waybar.

It appears that the parties interested in an IPC implementation are ignoring the request for an API. Pointing to sway and other projects' documentation is simply not an answer. Until an API is proposed, there's not really much to discuss.

Why don't we focus on the minimal IPC capabilities we have thought of for now and start with their API?

Yes, but then we need to define APIs. Like, plugins can register commands, emit events to the IPC, etc.

@ammen99 Signal API can be reused for plugins to emit events to IPC, right? As for command registration, I'm not sure how one plugin triggers another one right now. Have been looking for a good example. Maybe we can chat in IRC to discuss more about it?

Forgot to answer to this, if @shivanshs9 is willing to develop a plugin, I can provide some assistance in the technical parts (like integrating with core & plugins).

That would actually be great, thanks! :smile:

shivanshs9 avatar Jul 04 '20 08:07 shivanshs9

Why don't we focus on the minimal IPC capabilities we have thought of for now and start with their API?

I am not sure exactly the capabilities to which you refer. Do you mean your suggestions here?

Maybe we can chat in IRC to discuss more about it?

Yes, it would probably be easier to hash out details on IRC.

Please don't implement it with DBus. IPC socket is enough. DBus is also implemented on top of sockets, but it brings more complication.

If this does become a thing, it would be nice to have an in-house solution that doesn't rely on dbus but it looks like we might get both.

soreau avatar Jul 04 '20 08:07 soreau

Maybe we can chat in IRC to discuss more about it?

Yeah, please come over to IRC, it is better suited for longer conversations and asking questions.

ammen99 avatar Jul 04 '20 09:07 ammen99

Instantly turning off the screen with DPMS can't be done before this IPC can it? (like swaymsg "output * dpms off")

Arnaudv6 avatar Feb 03 '21 21:02 Arnaudv6

Instantly turning off the screen with DPMS can't be done before this IPC can it? (like swaymsg "output * dpms off")

It can be done, see https://github.com/WayfireWM/wayfire/issues/455#issuecomment-630125354

ammen99 avatar Feb 05 '21 06:02 ammen99

Thanks! and sorry for the noise... I searched "DPMS" in the repository, and it is not written in #455. I edited the wiki. Thanks

Arnaudv6 avatar Feb 05 '21 09:02 Arnaudv6

https://github.com/swaywm/wlroots/tree/master/examples

Arnaudv6 avatar Mar 16 '21 18:03 Arnaudv6

...granted, IMHO, this belongs somewhere more in view, given we must be a lot to use it in this form.

Arnaudv6 avatar Mar 16 '21 18:03 Arnaudv6

I've been working on some convenience Bash functions wrapping @damianatorrpm's D-Bus plugin: https://github.com/tombh/wf-msg

More discussion here: https://github.com/WayfireWM/wayfire/discussions/1477

tombh avatar May 11 '22 02:05 tombh

Wayfire now has a very basic ipc plugin providing the infrastructure for IPC commands, as well as a few very basic commands (the ipc-rules plugin). The plan for the future is to extend this and also other plugins when the need arises.

ammen99 avatar Aug 22 '23 10:08 ammen99