9

Days ago I broke my laptop display by accident, the right side of the screen is damaged but the most part of the left side is usable. I did some research trying to find a way to modify the dimension of the screen to fit into the area with no damage and I found xrandr.

enter image description here

I found the next .sh archive but I can't find a way to put the screen into the left side, neither modifying the --transform parameters or the --fb command.

#!/bin/bash

#change these 4 variables accordingly
ORIG_X=1280
ORIG_Y=800
NEW_X=1160
NEW_Y=800
###

X_DIFF=$(($NEW_X - $ORIG_X))
Y_DIFF=$(($NEW_Y - $ORIG_Y))

ORIG_RES="$ORIG_X"x"$ORIG_Y"
NEW_RES="$NEW_X"x"$NEW_Y"
ACTIVEOUTPUT=$(xrandr | grep -e " connected [^(]" | sed -e "s/\([A-z0-9]\+\) connected.*/\1/")
MODELINE=$(cvt $NEW_X $NEW_Y | grep Modeline | cut -d' ' -f3-)

xrandr --newmode $NEW_RES $MODELINE
xrandr --addmode $ACTIVEOUTPUT $NEW_RES
xrandr --output $ACTIVEOUTPUT --fb $NEW_RES --panning $NEW_RES --mode $NEW_RES
xrandr --fb $NEW_RES --output $ACTIVEOUTPUT --mode $ORIG_RES --transform 1,0,$X_DIFF,0,1,$Y_DIFF,0,0,1

I also tried to do it without the .sh archive running the next line:

xrandr --output LVDS-1 --fb 800x768 --mode 800x768 --transform 1,0,566,0,1,0,0,0,1

The screen took the position I want but after running that command a black border on the left side of the screen appears and I can't remove it.

enter image description here

Any idea of what it's going wrong here?

2 Answers 2

4

Just set the screen size with xrandr --fb (no --mode, --transform, whatever).

$ xrandr --fb 800x768

xrandr will complain about the screen size being too small, but will apply the settings nonetheless.

Example:

$ xrandr --fb 1520x1080
xrandr: specified screen 1520x1080 not large enough for output VGA-0 (1920x1080+0+0)
X Error of failed request:  BadMatch (invalid parameter attributes)
  Major opcode of failed request:  140 (RANDR)
  Minor opcode of failed request:  29 (RRSetPanning)
  Serial number of failed request:  43
  Current serial number in output stream:  43

# from the xtruss output
--- ConfigureNotify(event=w#000004A8, window=w#000004A8, x=0, y=0, width=1520, height=1080, border-width=0, above-sibling=None, override-redirect=False)

$ xwininfo -root | grep geo
  -geometry 1520x1080+0+0

That should probably be a warning rather than an error; there are situations where it makes perfect sense to set the screen size to something smaller than the actual display(s).

Update:

Multi-head enabled window managers get the info about the screen(s) via the Xrandr(3) and Xinerama(3) extensions, and do not clamp their dimensions inside the root window rectangle.

A temporary workaround would be to prevent them from using the Xrandr and Xinerama extensions via a LD_PRELOAD hack. That could be improved by turning the dummy functions into wrappers that trim the returned rectangles.

This worked for me on vanilla debian 9.5 with the mate desktop environment and either the lightdm or gdm3 display manager:

root# apt-get install mate-desktop-environment lightdm
root# apt-get install gcc

root# cat <<'EOT' | cc -fPIC -x c - -shared -o /etc/X11/no_xrr.so
int XineramaIsActive(void *d){ return 0; }
void *XineramaQueryScreens(void *dpy, int *n){ *n = 0; return 0; }
int XineramaQueryExtension(void *d, int *i, int *j){ return 0; }
int XRRQueryExtension(void *d, int *i, int *j){ return 0; }
EOT

root# cat <<'EOT' >/etc/X11/Xsession.d/98-no_xrr
export LD_PRELOAD=/etc/X11/no_xrr.so
case $STARTUP in
/usr/bin/ssh-agent*)
        STARTUP="/usr/bin/ssh-agent env LD_PRELOAD=$LD_PRELOAD ${STARTUP#* }";;
esac
EOT

Then, from the session menu of lightdm choose "MATE", and as the logged-in user:

$ LD_PRELOAD= xrandr --fb 800x768

I wasn't able to get it to work though with either plasma or gnome3/gnome-shell/mutter yet.

12
  • I tried to do that before, the problem is --fb just shrink the usable dimension of the screen to x and y values but it doesn't set the current size of the screen to that values. In another words, the half of the screen get unreachable using that command. imgur.com/a/bOCHrqI there you can see that the half of the screen has been cut using --fb, the rest of the screen is dark.
    – Daniel
    Oct 1, 2018 at 2:21
  • should the broken part of the screen be "reachable"? how? And the command really does set the size of the screen to those values -- look at the xtruss and xwininfo output; and the new size was readily picked by the window manager. What window manager are you using?
    – mosvy
    Oct 1, 2018 at 2:25
  • I'm trying to reduce the dimension of the entire screen to fit into the no damage area, when I use --fb XxY I get something like this imgur.com/a/1uszcyd the idea is reduce the dimension to see the entire window like this imgur.com/a/udSwTTl but smaller (smaller enough to be able to see it into the no damage area of my display). I don't know what is a window manager, any help?
    – Daniel
    Oct 1, 2018 at 2:34
  • What system / distribution is that? As to wm, that's a program like compiz, xfwm. It should handle the change in the root window size automatically. Could you please run the xwininfo -root command in a terminal and post the output?
    – mosvy
    Oct 1, 2018 at 2:41
  • 1
    You should have tried the commands given in the "Update" part on your debian 9.5 -- they're not destructive; if it didn't work, you could've just removed the two files created (rm /etc/X11/Xsession.d/98-no_xrr /etc/X11/no_xrr.so) and uninstall mate (apt-get remove --purge mate-desktop-environment). But I'll try to have the hack work with gnome3/mutter too.
    – mosvy
    Oct 3, 2018 at 17:22
0

Here's my modified version of that script ( with KDE changes found elsewhere )

#!/bin/bash

# (if using as a KDE autostart script)
# sleep 10

# change these 4 variables accordingly
ORIG_X=2880
ORIG_Y=1800
NEW_X=2810
NEW_Y=1800
###
#Modify to multiple of 8. Issues with window sizing etc without these next two lines.
NEW_X=$(($NEW_X/8*8))
NEW_Y=$(($NEW_Y/8*8))
X_DIFF=$(($NEW_X - $ORIG_X))
Y_DIFF=$(($NEW_Y - $ORIG_Y))
# Uncomment the next line to use left portion of screen:
#X_DIFF=0
# Uncomment the next line to use upper portion of screen:
#Y_DIFF=0

ORIG_RES="$ORIG_X"x"$ORIG_Y"
NEW_RES="$NEW_X"x"$NEW_Y"
ACTIVEOUTPUT=$(xrandr | grep -e " connected [^(]" | sed -e "s/\([A-z0-9]\+\) connected.*/\1/")
MODELINE=$(cvt $NEW_X $NEW_Y | grep Modeline | cut -d' ' -f3-)

xrandr --newmode $NEW_RES $MODELINE
xrandr --addmode $ACTIVEOUTPUT $NEW_RES
xrandr --output $ACTIVEOUTPUT --fb $NEW_RES --panning $NEW_RES --mode $NEW_RES
xrandr --fb $NEW_RES --output $ACTIVEOUTPUT --mode $ORIG_RES --transform 1,0,$X_DIFF,0,1,$Y_DIFF,0,0,1

# KDE specific -- restart shell so that icon tray is properly sized
# kquitapp5 plasmashell
# kstart5 plasmashell

SDDM: To have this take effect at the sddm login screen put an echo in front of each xrandr line then copy the resulting xrandr commands into the sddm startup. If you are running KDE you will need to disable KScreen to carry over the settings into KDE Plasma.

With your display connected run...

grep "Manufacturer:" /var/log/Xorg.0.log

... to look up the display in your /var/log/Xorg.0.log and modify the if grep line below accordingly. Don't forget to change the xrandr lines as mentioned above. Add to your /usr/share/sddm/scripts/Xsetup:

if grep -q -wi "Manufacturer: SKY  Model: 1801" /var/log/Xorg.0.log; then
xrandr --newmode 2872x2160 531.25 2872 3104 3416 3960 2160 2163 2173 2237 -hsync +vsync
xrandr --addmode HDMI-A-0 2872x2160
xrandr --output HDMI-A-0 --fb 2872x2160 --panning 2872x2160 --mode 2872x2160
xrandr --fb 2872x2160 --output HDMI-A-0 --mode 3840x2160 --transform 1,0,-968,0,1,0,0,0,1
fi

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.