udev-discover
udev-discover copied to clipboard
Multiseat configuration support
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
This is how it should look like:
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 I hope this will simplify the work.
Overview of changes:
- The code is split into sections: generic treeview stuff, seats, devices, other menu actions (still a bit messed).
- The first part of multiseat support is about displaying seats in the tree. It is toggled with the multiseat_tree option.
- 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. - 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).
- 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 thechanged_device()
if theget_device_parent_treeiter()
gives a new parent which is different from the current one. - 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 inremoved_device()
andchanged_device()
. - 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. - The second part of multiseat support is about changing the seat attachment of the selected device. This is implemented in the Device->Seat submenu.
- 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.
- 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 anupdate_chosen_seat()
workaround which callsactivate()
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 thedevices_tv_cursor_changed_cb()
to set the initial active seat item for the current device. - Device->Properties and ->Summary menu items/actions are there just for niceness :)
Current problems:
- I get
multiseat_tree_toggleaction
in sync withmultiseat_tree
option withset_active()
call, but this causes an extra tree reload - 'New seat' dialog isn't good enough.
- Logind AttachDevice() is called synchronously.
- 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).
- 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.
Such an exhaustive changelog, thanks! I'll be putting some effort next week testing udev-discover with those changes, towards the merging!