Showing posts with label Xephyr. Show all posts
Showing posts with label Xephyr. Show all posts

Monday, March 24, 2008

Multiseat in Ubuntu 8.04 (III)

<< step (II) <<

After the previous modifications, our system is almost ready to use. Unfortunately there are still some pending details to be resolved.

The first problem is to achieve having every Xephyr screen properly placed (one display for every Xephyr). The current Xephyr version does not support the geometry parameter that most X applications include, so it is not possible to place the Xephyr window in the desired place (i.e. one Xephyr on every display).

To workaround this problem we can use some command line tools in order to place every Xephyr window just in the place where we want to have it. We will need the following packages: xwininfo, wmctrl. Install them with your favorite tool (synaptic, apt-get).

The next step is to modify the gdm.conf file in order to invoke a wrapping script when calling the gdm greeter.

In our example, we have the following script wrapper placed in /usr/sbin just as we did with the Xephyr wrapper (be sure to give the script execution permissions):


#!/bin/bash
# /usr/sbin/Xephyr-login.sh

XAUTHORITY=/var/lib/gdm/:0.Xauth
XEP=$(xwininfo -root -children -display :0 | grep "Xephyr on :1" --max-count=1)
echo XEP ${XEP} >> /tmp/logXephyr
set -- ${XEP}
XAUTHORITY=/var/lib/gdm/:0.Xauth
DISPLAY=:0 wmctrl -i -r $1 -e 0,1280,0,-1,-1
/usr/lib/gdm/gdmlogin
# /usr/lib/gdm/gdmgreeter


In our particular case, we have tho displays at 1280x1024. Having the display resolutions hardcoded in such a script is very awful, so consider it just as a dirty and quick workaround to have things working. Experienced bash script coders with nicer solutions are welcome :-)

As we said before, you have to modify the /etc/gdm/gdm.conf file (the gdm greeter call) in order to call this script. The script will move one of the Xephyr sessions to the right display while maintaining the other on the left display.


# The greeter for attached (non-xdmcp) logins. Change gdmlogin to gdmgreeter
# to get the new graphical greeter.
# Greeter=/usr/lib/gdm/gdmgreeter
Greeter=/usr/sbin/Xephyr-login.sh


As you can see, when the greeter is expected to be invoked, the wrapper script (including greeter invocation) is executed instead.

The last comment is about the greeter. There is something wrong about screen size detection with the default gdm greeter (gdmgreeter). It always try to start at a resolution of 1600x1200, so we had to change to the old greeter (gdmlogin) which detects properly the screen resolutions of the Xephyr sessions.

Thursday, February 21, 2008

Multiseat in Ubuntu 8.04 (II)

<< step (I) <<

Once we have modified the xorg.conf file and we have a big desktop in the two monitors, the next thing is to configure gdm to launch the two Xephyr sessions.

Previously, you will need to obtain the information related to the input events on your system. The way of referencing the events has been recently modified. Now, the operating system allows you to access the events via their paths, and on some systems, via their names. The script wrapper to launch Xephyr it is now simpler compared to the previous version. It is not necessary any more to match the events with the physical locations (as we did through /proc/bus/input/devices)

You must obtain the path-based symbolic links to the events corresponding to your keyboards and mouses. In our particular case, whe have two USB keyboards, one USB mouse and one PS/2 mouse.


# ls -la /dev/input/by-path/ | grep event | grep kbd
lrwxrwxrwx 1 root root 9 2008-02-20 09:49 pci-0000:00:1d.2-usb-0:1:1.0-event-kbd -> ../event5
lrwxrwxrwx 1 root root 9 2008-02-20 09:49 pci-0000:00:1d.2-usb-0:2:1.0-event-kbd -> ../event6

# ls -la /dev/input/by-path/ | grep event | grep mouse
lrwxrwxrwx 1 root root 9 2008-02-20 09:49 pci-0000:00:1d.3-usb-0:1:1.0-event-mouse -> ../event8
lrwxrwxrwx 1 root root 9 2008-02-20 09:49 platform-i8042-serio-1-event-mouse -> ../event2


The invocation of the Xephyr wrapper in the (/etc/gdm/gdm.conf) file will be something like this (remember to do a backup of your files before doing any modification!):


# ****************************************************************************

# Modificaciones multiseat (20080109)

0=Xephyr0
1=Xephyr1
2=Xephyr2

[server-Xephyr0]
name=Xephyr0
command=/usr/bin/X -br -dpms -s 0
handled=false
flexible=false

[server-Xephyr1]
name=Xephyr1
command=/usr/sbin/Xephyr-path.sh -display :0 -br -xauthority /var/lib/gdm/:0.Xauth -screen 1280x1024 -kbdpath pci-0000:00:1d.2-usb-0:2:1.0-event-kbd -mousepath platform-i8042-serio-1-event-mouse
handled=true
flexible=false

[server-Xephyr2]
name=Xephyr2
command=/usr/sbin/Xephyr-path.sh -display :0 -br -xauthority /var/lib/gdm/:0.Xauth -screen 1280x1024+1280+0 -kbdpath pci-0000:00:1d.2-usb-0:1:1.0-event-kbd -mousepath pci-0000:00:1d.3-usb-0:1:1.0-event-mouse
handled=true
flexible=false

# ****************************************************************************


Notice that the Xepyr wrapper is called Xephyr-path.sh (just to remark the modification). If you prefer to reference the devices by its name instead of the path, obtain the names in a similar way (have a look at /dev/input/by-name/) and do the necessary modifications on the wrapper.

Since the previous version, xserver-xephyr has been modified so the script is slightly different from the old one. Place the script somewhere in your computer (and remember to give it execution permissions) so it can be invoked when gdm starts. In our prototype, the wrapper is placed at /usr/sbin/Xephyr-path.sh


#!/bin/bash

# 20080109..20080221 - josean
# http://netpatia.blogspot.com/

trap "" usr1

XEPHYR=/usr/bin/Xephyr

args=()

while [ ! -z "$1" ]; do
if [[ "$1" == "-xauthority" ]]; then
shift
if [ ! -z "$1" ]; then
export XAUTHORITY="$1"
fi
elif [[ "$1" == "-display" ]]; then
shift
if [ ! -z "$1" ]; then
export DISPLAY="$1"
fi
elif [[ "$1" == "-kbdpath" ]]; then
shift
if [ ! -z "$1" ]; then
args=("${args[@]}" "-keybd")
args=("${args[@]}" "evdev,,device=/dev/input/by-path/$1,xkbrules=xorg,xkbmodel=evdev,xkblayout=es")
fi
elif [[ "$1" == "-mousepath" ]]; then
shift
if [ ! -z "$1" ]; then
args=("${args[@]}" "-mouse")
args=("${args[@]}" "evdev,,device=/dev/input/by-path/$1,WHEELRelativeAxisButtons 6 7")
fi
else
args=("${args[@]}" "$1")
echo "+++ args $1 +++" >> /tmp/logXephyr
fi
shift
done

echo $XEPHYR -ac "${args[@]}" >> /tmp/logXephyr
exec $XEPHYR -ac "${args[@]}"


Notice the changes, mainly in the options passed to the evdev driver for mouse and keyboard.

Another significant change on the wrapper script is the removal of the line...

elif ! expr match $1 'vt[0-9][0-9]*' >/dev/null; then

...from the 6.06 version. Now, the parameters related to virtual terminals are not filtered, so they are passed in the final invocation. In our prototype, the two seats share the same vt (vt9) and this seems to be no problem at all. If you have more seats or you experience some problem, maybe you will need to filter the vt parameters in the final Xephyr call.

Currently, the mouse wheel (vertical scroll) is not working. The option WHEELRelativeAxisButtons is just to try to get it working, but without success at the moment. Unfortunately there is not much documentation about evdev and its options. If somebody achieves to manage the mouse wheel, feedback is welcome.

The good news is that the keyboard mapping seems to work properly. After dozens of trials with parameters (keyboard layouts, mapping, geometry), an updated package of xserver-xephyr was published some days ago. The new package corrected a bug in the path locations where evdev was looking for keyboard definition files. Now everything works perfect, you just have to choose the language layout for your keyboard (Spanish in our example).

If you test the system at this stage, you will probably see just only one login window. There is still a couple of things to do before your system is ready to use.

>> step (III) >>

Friday, September 08, 2006

Multiseat (IV): evdev and Xephyr

(...comes from step III)




What is evdev?


evdev is the generic input event device driver. It passes the events generated in the kernel (since version 2.6.8) straight to the program, with timestamps.

The evdev driver is able to separate and distinguish events coming from different keyboards and mouses plugged into the computer. The xorg supports evdev input driver module since version 6.9/7.0 . This way, it can get separated input events coming from every seat (keyboard and mouse pair) on the system.


This is a great step compared to previous multiseat solutions, since it makes possible to have multiterminal systems without having to patch neither the kernel nor the X server.

What is Xephyr?

Xephyr is a kdrive based X Server which targets a window on a host X Server as its framebuffer. In other words, it is a piece of software which creates a X server on top of another X server. That will allow us to run as many Xephyr instances as seats we have in our system. Every Xephyr instance will cover the area shown in a given display, and finally, evdev will allow us to separate the different input devices.

The good news

Xephyr is included in the universe repository from Ubuntu.

The bad news

The Xephyr version included in the Ubuntu repository, does not support evdev. I hope in a near future Xephyr comes with evdev upport.

Right now, you will have either to patch the Xephyr sources and compile it, or download an already patched solution. Download links for both solutions are available here.

# wget http://www.c3sl.ufpr.br/multiterminal/howtos/xephyr-precompiled.tar.bz2
# tar -xjf xephyr-precompiled.tar.bz2 --directory /usr/local/

Now it is time to plug your second set of keyboard and mouse. The evdev driver will access the input coming from every device by means of a given event in the form of /dev/input/eventNN. You must obtain the event id associated to every input device.

A new problem arises, since the event number assigned can change (in fact, it changes) between different boots. To solve this problem we well use a wrapper script. The script is the same as proposed here, but modified in order to obtain the event number given the physical connection of the device. We are assuming that the devices will be always plugged in the same position (you can label the back connectors to remember the correct position). Since the physical device addresses do not change between boots, the script can obtain the corresponding event id and match it properly with one physical keyboard or mouse.

Input devices and events, once plugged the second keyboard and mouse:

# cat /proc/bus/input/devices
I: Bus=0011 Vendor=0001 Product=0001 Version=ab41
N: Name="AT Translated Set 2 keyboard"
P: Phys=isa0060/serio0/input0
S: Sysfs=/class/input/input0
H: Handlers=kbd event0
B: EV=120013
B: KEY=4 2000000 3802078 f840d001 f2ffffdf ffefffff ffffffff fffffffe
B: MSC=10
B: LED=7

I: Bus=0011 Vendor=0002 Product=0005 Version=0000
N: Name="ImPS/2 Generic Wheel Mouse"
P: Phys=isa0060/serio1/input0
S: Sysfs=/class/input/input1
H: Handlers=mouse0 event1 ts0
B: EV=7
B: KEY=70000 0 0 0 0 0 0 0 0
B: REL=103

I: Bus=0010 Vendor=001f Product=0001 Version=0100
N: Name="PC Speaker"
P: Phys=isa0061/input0
S: Sysfs=/class/input/input2
H: Handlers=kbd event2
B: EV=40001
B: SND=6

I: Bus=0003 Vendor=0d62 Product=001c Version=0202
N: Name="Darfon USB Combo Keyboard"
P: Phys=usb-0000:00:1d.1-1/input0
S: Sysfs=/class/input/input5
H: Handlers=kbd event4
B: EV=120003
B: KEY=10000 7 ff87207a c14057ff febeffdf ffefffff ffffffff fffffffe
B: LED=7

I: Bus=0003 Vendor=0d62 Product=001c Version=0202
N: Name="Darfon USB Combo Keyboard"
P: Phys=usb-0000:00:1d.1-1/input1
S: Sysfs=/class/input/input6
H: Handlers=kbd event5
B: EV=3
B: KEY=3078 d801d101 1e0000 0 0 0

I: Bus=0003 Vendor=046d Product=c03f Version=2000
N: Name="Logitech USB-PS/2 Optical Mouse"
P: Phys=usb-0000:00:1d.1-2/input0
S: Sysfs=/class/input/input8
H: Handlers=mouse1 event3 ts1
B: EV=7
B: KEY=f0000 0 0 0 0 0 0 0 0
B: REL=103


The Name section will help us to identify the device. The Phys section is the parameter that we will send to the wrapper script in order to start every Xephyr instance.

The Xephyr wrapper

Now, it is time to create the wrapper script. The original one is modified to obtain the event numbers from the physical addresses

# vi /usr/sbin/Xephyr.sh


This is the final wrapper script:

#!/bin/bash

# 20060905 - josean - added get_event() function to obtain eventNN from a physical address
# Original version:
# http://en.wikibooks.org/wiki/Multiterminal_with_Xephyr
# http://www.c3sl.ufpr.br/multiterminal/howtos/Xephyr.sh

trap "" usr1

XEPHYR=/usr/local/bin/Xephyr

get_event()
{
evento=`grep -A2 $1 /proc/bus/input/devices | grep 'H: Handlers=' | grep --only-matching -e 'event[0-9]*'`
}

args=()

while [ ! -z "$1" ]; do
if [[ "$1" == "-xauthority" ]]; then
shift
if [ ! -z "$1" ]; then
export XAUTHORITY="$1"
fi
elif [[ "$1" == "-display" ]]; then
shift
if [ ! -z "$1" ]; then
export DISPLAY="$1"
fi
elif [[ "$1" == "-kbdphys" ]]; then
shift
if [ ! -z "$1" ]; then
get_event $1
args=("${args[@]}" "-keyboard")
args=("${args[@]}" "/dev/input/$evento")
fi
elif [[ "$1" == "-mousephys" ]]; then
shift
if [ ! -z "$1" ]; then
get_event $1
args=("${args[@]}" "-mouse")
args=("${args[@]}" "/dev/input/$evento,5")
fi
else
if ! expr match $1 'vt[0-9][0-9]*' >/dev/null; then
args=("${args[@]}" "$1")
fi
fi

shift
done

# echo $XEPHYR "${args[@]}" >> /tmp/logXephyr

exec $XEPHYR "${args[@]}"


Finally, be sure to allow the script to be executed.

# chmod +x /usr/sbin/Xephyr.sh


(continues on step V...)