21

I've setup a VM that works great except for the auto resize functionality which seems to be inconsistent. I've got it randomly working a few times but it also randomly stops working. It's currently not working and I'm not sure what I need to do to get it to work reliably (like VirtualBox autoresizing). Please see below for my configuration.

setup

Host: Ubuntu 16.10
Guest: Ubuntu 16.04.2, et. al (I've tried with other Linux distros with similar results)
Guest: created using virt-manager
Guest: installed spice-vdagent
Guest: virt-manager > View > Scale Display > Auto resize VM with window (checked)

spice

user@ubuntu:~$ ps aux | grep spice
root       805  0.0  0.0  30568   260 ?        Ss   08:59   0:00 /usr/sbin/spice-vdagentd
user      1365  0.0  0.0  35124  2360 ?        Ss   08:59   0:00 /usr/bin/spice-vdagent
user      1933  0.0  0.0  21292  1020 pts/17   S+   09:00   0:00 grep --color=auto spice

qxl

user@ubuntu:~$ sudo lshw -c Video
  *-display               
       description: VGA compatible controller
       product: QXL paravirtual graphic card
       vendor: Red Hat, Inc.
       physical id: 2
       bus info: pci@0000:00:02.0
       version: 04
       width: 32 bits
       clock: 33MHz
       capabilities: vga_controller rom
       configuration: driver=qxl latency=0
       resources: irq:10 memory:f4000000-f7ffffff memory:f8000000-fbffffff memory:fc058000-fc059fff ioport:c040(size=32) memory:c0000-dffff

What am I missing to correctly enable auto resize with qemu/kvm?

1
  • 1
    This bug is still active in 2019, KDE resize,Gnome resize, Windows resize..but not xfce4
    – elbarna
    Commented Jul 8, 2019 at 3:23

6 Answers 6

20

The gnome desktop, mutter, has some hotplug code that deals with the resize.

If you have any other desktop like xfce4 or KDE or a bare .xinitrc file running compiz like I do, you are pretty stuck, but I think I finally found an elegant and easy solution.

xrandr --output Virtual-0 --auto will pick up the size and apply it from vdagent. All that's need is a trigger.

Here is the trigger and how to handle it.

udev exposes the resize event as a drm device change that looks like this:
UDEV [10758.537471] change /devices/pci0000:00/0000:00:02.0 `drm/card0 (drm)

To have your desktop react to it create a udev rule and refer to a script to resize:
Rule in /etc/udev/rules.d/50-x-resize.rules:

ACTION=="change",KERNEL=="card0", SUBSYSTEM=="drm", RUN+="/usr/local/bin/x-resize" 

Script in /usr/local/bin/x-resize:

#! /bin/sh
PATH=/usr/bin
export DISPLAY=:0.0
xrandr --output "$(xrandr | awk '/ connected/{print $1; exit; }')" --auto

You may need to customize that shell script for your situation.

I found that on debian 10 and Ubuntu 20.04 I didn't even have to restart anything; it picked it up immediately.

Update: 2021-03-17

I recently found that I had to get permissions to allow that script to work. I changed it to this:

#! /bin/sh 
PATH=/usr/bin
desktopuser=$(/bin/ps -ef  | /bin/grep -oP '^\w+ (?=.*vdagent( |$))') || exit 0
export DISPLAY=:0
export XAUTHORITY=$(eval echo "~$desktopuser")/.Xauthority
xrandr --output $(xrandr | awk '/ connected/{print $1; exit; }') --auto
5
  • 1
    It's a known bug for some DEs. Commented May 1, 2020 at 13:51
  • This is great, but be carfeul, it made my XFCE VM fail to boot with a blinking cursor. The answer by Joe H. below works without such problems
    – keen
    Commented Mar 16, 2021 at 19:43
  • The udev trigger works, but xrandr --output Virtual-1 --auto doesn't work in my case (the output name is Virtual-1, not Virtual-0 in my GNOME Boxes). Only xrandr -s 0 works for me. Also see: gitlab.freedesktop.org/xorg/app/xrandr/-/issues/71
    – user30747
    Commented Dec 17, 2023 at 23:05
  • @user30747 That would make me wonder if you are actually using the QXL video driver. unix.stackexchange.com/questions/614027/… . Check the output of sudo lshw -c Video
    – gsker
    Commented Dec 19, 2023 at 16:08
  • lshw -c Video in GNOME Boxes with the vm-image.template Guix System says: configuration: driver=qxl latency=0, so yes, it is.
    – user30747
    Commented Dec 31, 2023 at 3:37
9

I'm using Debian 10 and icewm as guest VM. When spice-vdagent is running I can manually adjust the screen size with xrandr --output Virtual-1 --auto

A change in the display size can also be observed with xev:

joe@l1:~$ xev -root -event randr 

RRScreenChangeNotify event, serial 18, synthetic NO, window 0x3af,
    root 0x3af, timestamp 39153, config_timestamp 82137
    size_index 65535, subpixel_order SubPixelUnknown
    rotation RR_Rotate_0
    width 1320, height 949, mwidth 348, mheight 250

RRNotify event, serial 18, synthetic NO, window 0x3af,
    subtype XRROutputChangeNotifyEvent
    output Virtual-1, crtc 63, mode 1320x949 (1320x949)
    rotation RR_Rotate_0
    connection RR_Connected, subpixel_order SubPixelUnknown

Using that as a trigger seems less intrusive than working with udev, in particular when using different desktop environments or window managers in the same VM.

joe@l1:~$ cat /home/joe/.xsession
#!/bin/sh

if [ -x /usr/bin/spice-vdagent ] ; then
    /usr/bin/spice-vdagent
    /home/joe/.icewm/xrandr-loop &
fi
exec /usr/bin/icewm-session

joe@l1:~$ cat /home/joe/.icewm/xrandr-loop
#!/bin/sh

sleep 2

xrandr --output "$(xrandr | awk '/ connected/{print $1; exit; }')" --auto

xev -root -event randr | \
grep --line-buffered 'subtype XRROutputChangeNotifyEvent' | \
while read foo ; do \
    xrandr --output "$(xrandr | awk '/ connected/{print $1; exit; }')" --auto
done

joe@l1:~$ 
0
1

I had a really hard time getting my guest VMs to support two monitors with a resolution greater than 1080p. As it turns out, this was because the default QXL memory buffer of 16 mib isn't big enough. You probably won't run into this issue if both your monitors are only 1080p. But if they are, then need to set heads=2 AND increase the memory buffer via the vgamem attribute (32 mib worked in my case).

On my systems, I had to to edit the libvirt XML configuration by hand to make this change. To do this, look for the vgamem attribute. It will probably have a default value of 16384 (aka 16 mib). To increase it, to say, 32 mib, change the attribute value to 32768. On my system, this modified XML fragment when from:

<video>
  <model type="qxl" ram="65536" vram="65536" vgamem="16384" heads="1" primary="yes"/>
  <address type="pci" domain="0x0000" bus="0x00" slot="0x01" function="0x0"/>
</video>

To:

<video>
  <model type="qxl" ram="65536" vram="65536" vgamem="32768" heads="2" primary="yes"/>
  <address type="pci" domain="0x0000" bus="0x00" slot="0x01" function="0x0"/>
</video>

If your not sure what values are actually being used, you can find out by looking at the qemu command line parameters. On a Unix/Linux system, start the guest, and then run ps -ef | grep qemu ... and look for the QXL device. It will probably look something like -device qxl-vga,id=video0,ram_size=67108864,vram_size=67108864,vram64_size_mb=0,vgamem_mb=32,max_outputs=2,bus=pcie.0,addr=0x1. The vgamem_mb value of 32 is what's important.

Once you have the QXL driver setup properly, changing the guest resolution should be easy. You can use the graphical display configurator, or you can use xrandr via the command line. In my case I chose to automate the process with the following script:

#!/bin/bash
if [ `xrandr | grep --extended-regexp --count "Virtual-0 connected|Virtual-1 connected"` == 2 ]; then
xrandr --newmode "1920x1200_60.00"  193.25  1920 2056 2256 2592  1200 1203 1209 1245 -hsync +vsync
xrandr --addmode Virtual-0 "1920x1200_60.00"
xrandr --addmode Virtual-1 "1920x1200_60.00"
xrandr --output Virtual-0 --mode "1920x1200_60.00" --panning 1920x1200+0+0 --output Virtual-1 --mode "1920x1200_60.00" --panning 1920x1200+1920+0
elif [ `xrandr | grep --extended-regexp --count "qxl-0 connected|qxl-1 connected"` == 2 ]; then
xrandr --newmode "1920x1200_60.00"  193.25  1920 2056 2256 2592  1200 1203 1209 1245 -hsync +vsync
xrandr --addmode qxl-0 "1920x1200_60.00"
xrandr --addmode qxl-1 "1920x1200_60.00"
xrandr --output qxl-0 --mode "1920x1200_60.00" --panning 1920x1200+0+0 --output qxl-1 --mode "1920x1200_60.00" --panning 1920x1200+1920+0
elif [ `xrandr | grep --extended-regexp --count "Virtual-0 connected"` == 1 ]; then
xrandr --newmode "1920x1200_60.00"  193.25  1920 2056 2256 2592  1200 1203 1209 1245 -hsync +vsync
xrandr --addmode Virtual-0 "1920x1200_60.00"
xrandr --output Virtual-0 --mode "1920x1200_60.00" --panning 1920x1200+0+0
else
xrandr --newmode "1920x1200_60.00"  193.25  1920 2056 2256 2592  1200 1203 1209 1245 -hsync +vsync
xrandr --addmode qxl-0 "1920x1200_60.00"
xrandr --output qxl-0 --mode "1920x1200_60.00" --panning 1920x1200+0+0
fi

Note this is for a 1920x1200 setup. It's also worth noting that depending on your display server, kernel version, and driver setup, etc, it's possible the display adapters will show up as either "qxl-#" or "Virtual-#".

To use the above script for a resolution other than 1920x1200, you'll need to use the appropriate modeline. To get the correct modeline, use the cvt command line tool. As an example, if what you wanted was the modeline for a 4k (aka 2160p) monitor, you would run cvt 3840 2160 60 (assuming 60hz is the refresh rate). This would give you the modeline:

# 3840x2160 59.98 Hz (CVT 8.29M9) hsync: 134.18 kHz; pclk: 712.75 MHz
Modeline "3840x2160_60.00"  712.75  3840 4160 4576 5312  2160 2163 2168 2237 -hsync +vsync

Now the take the value which appears after "Modeline":

"3840x2160_60.00"  712.75  3840 4160 4576 5312  2160 2163 2168 2237 -hsync +vsync

And replace the value:

"1920x1200_60.00"  193.25  1920 2056 2256 2592  1200 1203 1209 1245 -hsync +vsync

In the example script above.

A couple of notes. Namely the text inside the quotes is actually the "label" ... so you'll need to replace the references to "1920x1200_60.00" with the label for your new modeline. It's also worth noting that you can omit the refresh rate when calling cvt and it will guess ... but that guess could be wrong if your running it inside the guest system. To avoid this problem, you may want to call cvt on your host. In that case you could omit the refresh rate, and cvt will determine the right value by looking at your hardware.

0

go to the hardware section of your VM

Remove existing channel device if there is one and add the com.redhat.spice.0 spicevmc device

1
  • Already the case when using GNOME Boxes, yet this doesn't help, at least when using Xfce.
    – user30747
    Commented Dec 17, 2023 at 23:00
0

If you use a desktop environment such as Xfce that lacks native support for dynamic screen resizing (https://gitlab.xfce.org/xfce/xfce4-settings/-/issues/142), you can run a script that calls xrandr -s 0 every time udev notifies on drm subsystem changes to achieve something similar.

For a readily usable solution that is easy to package/install, you may be interested in trying this: https://gitlab.com/Apteryks/x-resize/, which installs an autostart script and logs screen changes in ~/.local/state/x-resize.log.1:

2023-12-30 04:31:58 (INFO): x-resize started; logging to /home/guest/.local/state/x-resize.log
2023-12-30 04:33:41 (INFO): screen 0 resized from 1024x768 to 1918x1010
2023-12-30 04:33:48 (INFO): screen 0 resized from 1918x1010 to 958x1010
2023-12-30 04:34:27 (INFO): screen 0 resized from 958x1010 to 958x470

It's available in GNU Guix and can be installed with guix install x-resize.

0

I set up my Kubuntu 22.04 guest using virt-manager and the above scripts/udev-rules, etc. somehow did not work.

Instead this dumber approach worked for me:

Configure virt-manager settings for the VM:

Display Spice:
  Spice Server:
    Type: Spice Server
    Listen Type: Address
    Address: Localhost only
    Port: [X] Auto Port (Port 5900)
Video QXL:
  Video:
    Model: QXL

In virt-manager menu, View -> Scale Display -> check "Auto resize VM with window"

Install guest agents:

sudo apt update

sudo apt install qemu-guest-agent
sudo systemctl enable qemu-guest-agent
sudo systemctl start qemu-guest-agent
sudo systemctl status qemu-guest-agent

sudo apt install spice-vdagent
sudo systemctl enable spice-vdagent
sudo systemctl start spice-vdagent
sudo systemctl status spice-vdagent

If spice-vdagent doesn't start automatically, edit /usr/lib/systemd/user/plasma-core.target and add "spice-vdagent.service" to the end of the Wants= line.

Then run xrandr, which tells me that "Virtual-1" is connected on my setup:

xrandr
Screen 0: minimum 320 x 200, current 2560 x 1298, maximum 8192 x 8192
Virtual-1 connected primary 2560x1298+0+0 0mm x 0mm
   2560x1298     59.98*+
   2560x1600     59.99    59.97  
   1920x1440     60.00  
   1856x1392     60.00  
   1792x1344     60.00  
   2048x1152     60.00  
   1920x1200     59.88    59.95  
   1920x1080     60.00  
   1600x1200     60.00  
   1680x1050     59.95    59.88  
   1400x1050     59.98    59.95  
   1600x900      60.00  
   1280x1024     60.02  
   1440x900      59.89    59.90  
   1280x960      60.00  
   1280x854      59.95  
   1366x768      59.79    60.00  
   1360x768      60.02  
   1280x800      59.81    59.91  
   1280x768      59.87    59.99  
   1280x720      60.00  
   1152x768      59.95  
   1024x768      60.00  
   800x600       60.32    56.25  
   848x480       60.00  
   720x480       59.94  
   640x480       59.94  
Virtual-2 disconnected
Virtual-3 disconnected
Virtual-4 disconnected

Then create a script in my home directory: ~/screen-resize.sh:

#!/bin/bash
xrandr --output Virtual-1 --auto

Make it executable:

chmod a+x ~/screen-resize.sh

And finally add the script as autostart app in KDE Plasma settings:

Settings -> Startup and Shutdown -> Autostart -> Add... -> Add Application... -> choose the ~/screen-resize.sh script and, this is important, under Terminal Options: check "Run in terminal"

After restart and login, the screen now automatically adapts.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .