udev-discover icon indicating copy to clipboard operation
udev-discover copied to clipboard

Multiseat configuration support

Open shatsky opened this issue 10 years ago • 4 comments

This pull request is not meant for merge yet This is my first attempt to write code using gtk/glade/dbus; it should be first reviewed by somebody with a proper knowledge of these fields. There are likely some things that should be rewritten. One question is about the .ui file: I have edited it using Glade 3.18, which changed the order of definitions, causing a big obscure diff. What is the right way to work with it?

This commit enables systemd/logind multiseat configuration (which is based on assigning seat udev tags to devices which are tagged as seat-attachable; see http://www.freedesktop.org/wiki/Software/systemd/multiseat/). You need to have logind (available in any systemd-enabled distro or latest Ubuntu) to see how it works. Practical usage requirements:

  • multiseat-capable PC: two sets of peripheral devices; monitors should be attached to 2 different video cards, at least one of them should be working under an open-source driver (maybe, a single card with multiple connectors can be sufficient with the latest kernel>3.15 which has a modeset-nodes feature, but I'm not sure)
  • multiseat-capable display manager: GDM3 will do

How to use:

  • "Options"->"Multiseat mode" toggle enables multiseat tree; if it's enabled, there will be a "Seats" top-level tree element which will contain seat elements with all seat-attached devices
  • "Device"->"Attach to seat" submenu will be available for devices which are tagged as seat-attachable (e. g. videocard framebuffers, input devices, usb hubs)
  • initially you will only have seat0; all seat-attachable devices are considered to be attached to it
  • you can attach selected seat-attachable device to any of existing seats or a new one ("Device"->"Attach to seat"->"New seat...")
  • you should attach at least one "master-of-seat" device (these are video card framebuffer devices) to a seat to make it visible on logind interface; after that, GDM should automatically start Xorg with a greeter on a display connected to that video card

shatsky avatar Aug 17 '14 10:08 shatsky

This is how it should look like: screenshot-udev-discover-3

shatsky avatar Sep 06 '14 13:09 shatsky

This is an amazing contribution @shatsky Be sure i'll be doing a peer review on the code and the ui changes.

Give me a week.

fontanon avatar Sep 07 '14 22:09 fontanon

@fontanon I hope this will simplify the work.

Overview of changes:

  1. The code is split into sections: generic treeview stuff, seats, devices, other menu actions (still a bit messed).
  2. The first part of multiseat support is about displaying seats in the tree. It is toggled with the multiseat_tree option.
  3. It complicates the logic of choosing a parent tree element for a device. There is also a need to check for the parent on a device change event, because in multiseat mode a device-to-seat attachment change means it has to be moved to another parent in the tree. Therefore, I've decided to move the parent choosing logic into a separate get_device_parent_treeiter() function.
  4. In addition to multiseat tree handling, there is one more change in the device parent choosing logic. I've decided that for devices which have no parent devices but are not top-level nodes in the sysfs device tree (e. g. /virtual/input/mice) there should be pseudo-parents in the tree (e. g. /virtual/input).
  5. As I said above, there is a case when a device tree element with its subtree has to be moved to another parent. It seems there is no such feature in Gtk, so I've implemented it in a treestore_move() function, which is called from the changed_device() if the get_device_parent_treeiter() gives a new parent which is different from the current one.
  6. A seat tree element becomes obsolete if its seat has no devices attached, and should be removed from the tree. So I've added a remove_if_obsolete() wrapper which is used in removed_device() and changed_device().
  7. I've decided it would be nice to have a tree cursor restored on the chosen device when the tree is rebuilt or changed in another selection-dropping way, e. g. we can switch off the multiseat mode with some seat-attached keyboard selected and see immediately which ps/2 or usb controller it is on. So I've added a preserve_cursor() wrapper which wraps the tree-modifying code here and there.
  8. The second part of multiseat support is about changing the seat attachment of the selected device. This is implemented in the Device->Seat submenu.
  9. Logind D-Bus API is used to attach the device to one of existing seats or to a new one. It is also used to add/remove seat menu items as they appear/disappear.
  10. There is a small complication: I don't want a seat RadioMenuItem to be marked active immediately on activation, because the attachment call in the choose_seat() event handler can fail; besides, when I select a new device in the tree, I want to have the active seat item updated without triggering the handler. Gtk isn't designed this way, so I've written an update_chosen_seat() workaround which calls activate() with temporary-blocked handler; it is called from the handler itself to reset the previously-chosen seat item active prior to an attachment attempt; it is also called from the devices_tv_cursor_changed_cb() to set the initial active seat item for the current device.
  11. Device->Properties and ->Summary menu items/actions are there just for niceness :)

Current problems:

  1. I get multiseat_tree_toggleaction in sync with multiseat_tree option with set_active() call, but this causes an extra tree reload
  2. 'New seat' dialog isn't good enough.
  3. Logind AttachDevice() is called synchronously.
  4. Seat <seat_name> appears in the tree if there is any seat-attachable device attached to <seat_name>. However, this doesn't mean that logind considers it existing (it only lists seats which have master-of-seat device, like a graphics fb). We should draw a warning sign on such 'non-functioning' seats (I still haven't figured out how to draw an icon over another icon).
  5. Seat menu contains seats which are listed by logind. If a device is attached to a non-listed seat, update_chosen_seat() adds it to menu. I haven't decided yet whether we should display menu items for all seats obtained by tree population code (this would mean either disabling seat menu if multiseat_tree is off or making device add/change/remove code even more complicated) or display only logind-listed ones and show none of them active if device is attached no a non-logind-listed one.

shatsky avatar Sep 09 '14 11:09 shatsky

Such an exhaustive changelog, thanks! I'll be putting some effort next week testing udev-discover with those changes, towards the merging!

fontanon avatar Oct 08 '14 08:10 fontanon