7

I use Ubuntu 14.04 on my laptop at my desk with a second monitor. When I disconnect from the second monitor---without fail---my window for Emacs moves off screen.

I can Alt-TAB to make Emacs the active window, and, working blindly, stop Emacs so I can restart it, which causes it to reappear on the screen. But, it seems to me there should be a way in Ubuntu to get an off-screen window back onto the screen. Is there?

Of course, a better solution would be to prevent the windows from going off screen in response to monitor disconnection, and I would accept a solution to that problem.

UPDATE:

The output of xrandr while connected to a second monitor:

Screen 0: minimum 320 x 200, current 3200 x 1080, maximum 32767 x 32767
eDP1 connected primary 1920x1080+1280+0 (normal left inverted right x axis y axis) 382mm x 215mm
   1920x1080      60.0*+   59.9  
   1680x1050      60.0     59.9  
   1600x1024      60.2  
   1400x1050      60.0  
   1280x1024      60.0  
   1440x900       59.9  
   1280x960       60.0  
   1360x768       59.8     60.0  
   1152x864       60.0  
   1024x768       60.0  
   800x600        60.3     56.2  
   640x480        59.9  
VGA1 connected 1280x1024+0+0 (normal left inverted right x axis y axis) 376mm x 301mm
   1280x1024      60.0*+   75.0  
   1280x960       60.0  
   1152x864       75.0  
   1024x768       75.1     70.1     60.0  
   832x624        74.6  
   800x600        72.2     75.0     60.3     56.2  
   640x480        75.0     72.8     66.7     60.0  
   720x400        70.1  
HDMI1 disconnected (normal left inverted right x axis y axis)
VIRTUAL1 disconnected (normal left inverted right x axis y axis)

The output of xrandr after disconnecting from the second monitor:

Screen 0: minimum 320 x 200, current 1920 x 1080, maximum 32767 x 32767
eDP1 connected primary 1920x1080+0+0 (normal left inverted right x axis y axis) 382mm x 215mm
   1920x1080      60.0*+   59.9  
   1680x1050      60.0     59.9  
   1600x1024      60.2  
   1400x1050      60.0  
   1280x1024      60.0  
   1440x900       59.9  
   1280x960       60.0  
   1360x768       59.8     60.0  
   1152x864       60.0  
   1024x768       60.0  
   800x600        60.3     56.2  
   640x480        59.9  
VGA1 disconnected (normal left inverted right x axis y axis)
HDMI1 disconnected (normal left inverted right x axis y axis)
VIRTUAL1 disconnected (normal left inverted right x axis y axis)

Also, I tried swapping the left-right positions of my Terminal window and my Emacs window and then disconnecting. This allows the Emacs window to remain on-screen after disconnecting from the second monitor. And the Terminal window survives in the position that eliminated Emacs. So, it seems as if the application has something to do with this.

  • The thing is, it should move automatically, and it does on my system. What is your Ubunto version? does it happen with all applications or just some? what is the output of xrandr after disconnecting the second monitor? – Jacob Vlijm Aug 25 '15 at 16:58
  • Added the information you requested. Ubuntu version of 14.04. – davidrmcharles Aug 25 '15 at 18:14
  • Thanks for the info. Not sure what it is caused by, but as a workaround, would a script (shortcut) to move all windows to the visual area be an acceptable solution for now? – Jacob Vlijm Aug 25 '15 at 19:57
  • That is certainly better than nothing, and I very curious as to how one would do that! – davidrmcharles Aug 25 '15 at 20:01
  • I'll post one tomorrow :) – Jacob Vlijm Aug 25 '15 at 20:16
6

Move all windows into the visible area

As proposed/requested in a comment, the script below will move all "normal" windows to the visible area on the current workspace.

The solution is a workaround; the screen info is updated correctly, given the difference in the output of xrandr, before and and after disconnecting. The reason why the windows do not move by themselves is (currently) unknown, unless another answer solves the issue.

The script

#!/usr/bin/env python3
import subprocess

# get the resolution of the screen (+0+0)
res = [
    int(n) for n in [
        s.split("+")[0].split("x")\
        for s in subprocess.check_output(["xrandr"]).decode("utf-8").split()\
        if "+0+0" in s][0]
    ]
# create list of windows
w_list = [w.split() for w in subprocess.check_output(["wmctrl", "-lG"]).decode("utf-8").splitlines()]
# filter only "normal" ones
valid = [
    w for w in w_list if "_NET_WM_WINDOW_TYPE_NORMAL" in\
    subprocess.check_output(["xprop", "-id", w[0]]).decode("utf-8")
    ]
# get the number of valid windows and calculate a targeted position
# the targeted position is a hunch, it will be exact if the window fits completely inside the resolution
# it will work anyway
parts = len(valid)+2
positions = [(int(n*res[0]/parts), int(n*res[1]/parts)) for n in list(range(parts))[1:-1]]
# unmaximaize, move the windows to the visible area (current workspace)
for i, w in enumerate(valid):
    subprocess.Popen(["wmctrl", "-ir", w[0], "-b", "remove,maximized_vert,remove,maximized_horz"])
    # weird, but sometimes wmctrl refuses to move a window if it is not resized first (?)
    subprocess.Popen(["wmctrl", "-ir", w[0], "-e", "0,200,200,200,200"])      
    subprocess.Popen(["wmctrl", "-ir", w[0], "-e", (",").join(["0", str(positions[i][0]), str(positions[i][1]),w[4],w[5]])])

How to use

  1. The script needs wmctrl:

    sudo apt-get install wmctrl
    
  2. Copy the script into an empty file, safe it as move_windows.py

  3. Test- run it: open a number of windows, place them on different workspaces etc., or try disconnecting the second monitor. Then run the command:

    python3 /path/to/move_windows.py
    

    All "normal" windows should move to the visible area of the current workspace.

  4. If all works fine, add it to a shortcut key: choose: System Settings > "Keyboard" > "Shortcuts" > "Custom Shortcuts". Click the "+" and add the command:

    python3 /path/to/move_windows.py
    

Now you should be able to move all windows into the visible area on the current workspace, with your shortcut key.

  • Great script, but it won't move the windows back to the right place on my dual-screen setup. I found out that the misplaced windows all get moved by x + 2*screenwith - in other words to a virtual (and non-existing in my case) workspace to the right. So, something like this would move them back to the correct place: while xpos > 3840*2: xpos -= 3840 subprocess.Popen(["wmctrl", "-ir", w[0], "-e", ",".join([w[1], str(xpos), w[3], w[4], w[5]])]) (of course should be modified to account for the corr. screen width) – Bachi Jan 11 '16 at 16:27
  • @Bachi although the script is from august last year, it feels like a long time ago :). A quick look shows that the "lost" windows are moved to 200/200, which was the goal, not so much restore original position (if you can speak of that in a dual monitor setup). If that does not happen in your case, and windows are moved to a non existant workspace, you might have another exceptional error than OP, at least that's the impression on a quick look. – Jacob Vlijm Jan 11 '16 at 16:45
  • yeah, pity that after a year this bug still exists. My case might be a bit different than the OP's: After resuming from suspend, but without disconnecting the second display, some windows are moved (but always in the same fashion), and what I'd naturally want is having the windows not go offscreen but stay where they were last. Maybe this helps others with this issue. Thanks for your script! – Bachi Jan 12 '16 at 8:50
  • 1
    This script is giving me an error on line 9 on Ubuntu 17.04 - the if "+0+0" in s][0] line – RoundSparrow hilltx Jun 30 '17 at 2:29
  • @RoundSparrowhilltx possibly your screen setup does not originate at 0, 0. Could you post the output of xrandr on pastebin.com, and what is exactly the error message? – Jacob Vlijm Jun 30 '17 at 4:33
0

A simple solution that worked for me in recovering windows left on "screens" of disconnected monitors (not quite the same problem as the OP, but related) is using the keyboard shortcut to maximise the window: Ctrl + Super + ↑.

[N.B. Super is the key with the "Windows" symbol on it, usually between Fn and Alt. On a Mac it corresponds to Command = ⌘. On older versions of Ubuntu than mine (16.04) you might not need to include Ctrl.]

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.