Neither one nor Many

 
May 30 2018

I'm a heavy user of scratch pads with i3, I often don't like the dimensions of a window after you make them floating. As do other people, see here and here2.

I've used a customized version of the solution proposed in one of the comments by the creator of i3-gaps (Airblader) here3. This has served me well, but one thing bugged me when using multiple monitors it wouldn't center the window correctly, so I made a Python script that first uses Qt to get all screen dimensions and determine the correct offset based on the Mouse position. It's a bit overkill probably, but it works, so I'm happy with it.

Step 1: download, make, and make install wmutils.

Note that if you update your system in the meantime, it may have to be recompiled at some point, I've experienced this with the lsw command which is using some X calls that changed after I updated from Ubuntu 17.04 -> 17.10.

Step 2: put this python script somewhere

#!/usr/bin/env python3
import os
import os.path
import psutil
import subprocess
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from pymouse import PyMouse
from sys import platform


def clamp(n, smallest, largest):
    return max(smallest, min(n, largest))


def current_screen_size(mouse_position):
    for screen in app.screens():
        (x, y) = mouse_position
        screen_geom = screen.availableGeometry();
        if (x >= screen_geom.left() and y >= screen_geom.top() and
            x <= screen_geom.left() + screen_geom.width() and
            y <= screen_geom.top() + screen_geom.height()):
            return screen_geom
    return app.desktop().availableGeometry(-1)


# read ratio from config file
ratio_file = "/tmp/resize_ratio.txt"
ratio = 70

if os.path.isfile(ratio_file):
    file = open(ratio_file, "r") 
    ratio = int(file.read())
    file.close()

if len(sys.argv) > 1:
    if sys.argv[1] == 'inc':
        ratio += 10
    elif sys.argv[1] == 'dec':
        ratio -= 10

ratio = clamp(ratio, 10, 100)

# get mouse and screen specs
app = QApplication(sys.argv)
mouse = PyMouse()
screen = current_screen_size(mouse.position())

# call wmutils::core utilities
currentWindow = subprocess.check_output(["pfw"])

# resize the window
new_width = (screen.width() / 100) * ratio
new_height = (screen.height() / 100) * ratio
# subprocess.call([
#     "wrs",
#     "-a",
#     str(new_width),
#     str(new_height),
#     currentWindow
# ])

# position the window centered (+ resize)
new_x = screen.left() + ((screen.width() - new_width) / 2)
new_y = screen.top() + ((screen.height() - new_height) / 2)
subprocess.call([
    "wtp",
    str(new_x),
    str(new_y),
    str(new_width),
    str(new_height),
    currentWindow
])

# persist current ratio
file = open("/tmp/resize_ratio.txt", "w") 
file.write(str(ratio)) 
file.close() 

Don't forget chmod +x /path/to/resize.py

You may need to install some python3 -m pip install ... when you try to run it you'll probably discover what exactly, I forgot to keep a requirements.txt. From what I remember you need at least: python -m pip install pyuserinput pyqt5 python-xlib

Step 3: modify resize mode in i3

Probably you already have a "resize" mode, just add something like SHIFT+J and SHIFT+K to that mode to call the python script:

mode "resize" {
    bindsym Shift+k exec $HOME/.bin/resize.py inc
    bindsym Shift+j exec $HOME/.bin/resize.py dec
    ...
}
bindsym $mod+r mode "resize"
Linux/Unix Comments (2)

jon

2019-09-21 16:37:40

# on arch at least
pyenv shell system
pip install pyuserinput pyqt5 python-xlib pymouse PyQt5 --user

ray

2020-04-16 20:33:19

Tnx for your comment. I still use this simple extension every day


Leave a Reply

Comment may not be visible immediately, because I process everything manually.**

**) I plan to automate this.., but it's on my ToDo since for ever..


Author:
Ray Burgemeestre
february 23th, 1984

Topics:
C++, Linux, Webdev

Other interests:
Music, Art, Zen