Consecutive identical wmctrl command resizes xfce4-terminal

501 Views Asked by At

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.

0

There are 0 best solutions below