I'm writing a tiling script that uses wmctrl to move windows. When using it on an xfce4-terminal instance, the second consecutive identical run resizes the window. Here is the important code:
#!/usr/bin/python3
import subprocess
import os
import sys
class Screen(object):
def __init__(self, rows, cols):
self.rows = rows
self.cols = cols
# All workspaces and their data
desk_output = subprocess.getoutput("wmctrl -d").split("\n")
# All workspace numbers
desk_list = [line.split()[0] for line in desk_output]
# Data about current desktop. Not sure how it works with multiple.
current = [line for line in desk_output if line.split()[1] == "*"][0].split()
self.desktop = current[0]
self.width, self.height = map(int, current[8].split('x'))
self.orig_x, self.orig_y = current[7].split(',')
row_division = self.height // self.rows
col_division = self.width // self.cols
self.grid = []
for rownum in range(rows):
row = []
for colnum in range(cols):
col = []
col.append((col_division*colnum, col_division*(colnum+1)))
col.append((row_division*rownum, row_division*(rownum+1)))
row.append(col)
self.grid.append(row)
# Grid format is something like this:
# [[(0, 640), (0, 522)], [(640, 1280), (0, 522)], [(1280, 1920), (0, 522)]],
# [[(0, 640), (522, 1044)], [(640, 1280), (522, 1044)], [(1280, 1920), (522, 1044)]]
# Debug purposes
for i in self.grid:
print(i)
def get_coords(self, cols, rows):
"""Precondition: two two-tuples of (start,end) for rows and columns.
postcondition: desired x, y, width, height of window in pixels.
"""
row_start, row_end = rows
col_start, col_end = cols
x_start_coord = self.grid[0][col_start-1][0][0]
x_end_coord = self.grid[0][col_end - 1][0][1]
x_coords = (x_start_coord, x_end_coord)
y_start_coord = self.grid[row_start-1][0][1][0]
y_end_coord = self.grid[row_end - 1][0][1][1]
y_coords = (y_start_coord, y_end_coord)
x = x_coords[0]
y = y_coords[0]
w = y_coords[1] - y_coords[0]
h = x_coords[1] - x_coords[0]
return (x, y, h, w)
def move_active(self,x,y,w,h):
command = ','.join(map(str, [" wmctrl -r :ACTIVE: -e 0", x, y, w, h]))
# Print command for debugging
print(command)
os.system(command)
if __name__ == "__main__":
screen_rows = int(sys.argv[1])
screen_cols = int(sys.argv[2])
first_row = int(sys.argv[3])
last_row = int(sys.argv[4])
first_col = int(sys.argv[5])
last_col = int(sys.argv[6])
cols_filled = (first_col, last_col)
rows_filled = (first_row, last_row)
s = Screen(screen_rows, screen_cols)
c = s.get_coords(cols_filled, rows_filled)
# Print the coords we are about to move to
print(c)
s.move_active(*c)
If I call this script twice in a row, using the same coordinates:
python3 screen.py 2 2 1 2 1 1
(this means grid size: 2x2, rows 1-2, columns 1-1 (aka right half of the screen (the command it will run is printed to the terminal))
the window is resized again the second time, ignoring borders and expanding past the xfce panel. Below are images of after the first and second script run. See the bottom of the window for the discrepancy. Notice the wmctrl command run is the same both times.
first run where terminal emulator is moved from the center to the right
second run where terminal emulator expands down several pixels into the panel
This behavior happens when running wmctrl directly from the command line, too, so the problem is not in the python. (for my screen size, wmctrl -r :ACTIVE: -e 0,0,0,960,1024
. I included the python script because it allows you to get that information/command specifically for your screen, if you wish to test the behavior.)
This suggests the problem is that "wmctrl is returning the geometry of the window inside the decorations". I cannot get the parent window, however, and it does not appear to exist, so the solution seems like it might be specific to unity/gedit. It also does not explain why a consecutive duplicate move command changes the geometry of the window, when the first command puts it in the right place.
I tested a few terminal emulators to see if the emulator might be the source of the problem.
This problem does not occur when running the command or program from xterm, terminator (though there is strange behavior), qterminal, eterm, rxvt, stterm, and kterm. It does occur in xfce4-terminal and lilyterm. There is similar, but not identical strange behavior in gnome-terminal and roxterm. This leads me to believe it is a terminal emulator specific bug/quirk. The problem might be related to the first, not second resize, as xterm and the other emulators expand fully on the first run.
I am running xfce 4.12 on a Ubuntu 16.04 (xenial) derivative (kernel: x86_64 Linux 4.8.17-galliumos). My wmctrl version is 1.07. My xfwm4 version is 4.12.3(revision 7fdcb53). My screen resolution is 1920x1080. The window I am resizing is xfce4-terminal 0.6.3.
I would like to know if there is something I can do to prevent this. I have been resizing the window to 0,0,0,0 and then to the desired dimensions, but this requires another command and an ugly flash.
Tldr: running the SAME wmctrl command twice (wmctrl -r :ACTIVE: -e 0,960,0,960,1024
) from an xfce4-terminal instance moves the window the second time, expanding it down. I want to know why this happens and how to stop it from happening.