Last active
April 30, 2025 19:50
-
-
Save predragnikolic/71248630920d7be330d83b60cbbf6388 to your computer and use it in GitHub Desktop.
Resize Openbox
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
OFFSET_RE="\+([-0-9]+)\+([-0-9]+)" | |
# Get the window position | |
pos=($(xwininfo -id $(xdotool getactivewindow) | | |
sed -nr "s/^.*geometry .*$OFFSET_RE.*$/\1 \2/p")) | |
# Loop through each screen and compare the offset with the window | |
# coordinates. | |
while read name width height xoff yoff | |
do | |
if [ "${pos[0]}" -ge "$xoff" \ | |
-a "${pos[1]}" -ge "$yoff" \ | |
-a "${pos[0]}" -lt "$(($xoff+$width))" \ | |
-a "${pos[1]}" -lt "$(($yoff+$height))" ] | |
then | |
monitor=$name | |
fi | |
done < <(xrandr | grep -w connected | | |
sed -r "s/^([^ ]*).*\b([-0-9]+)x([-0-9]+)$OFFSET_RE.*$/\1 \2 \3 \4 \5/" | | |
sort -nk4,5) | |
# If we found a monitor, echo it out, otherwise print an error. | |
if [ ! -z "$monitor" ] | |
then | |
echo $monitor | |
exit 0 | |
else | |
echo "Couldn't find any monitor for the current window." >&2 | |
exit 1 | |
fi |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
import sys | |
import subprocess | |
import re | |
GAP_SIZE = 20 # Define the gap size | |
def get_active_window_id(): | |
"""Gets the ID of the currently active window using xprop.""" | |
try: | |
result = subprocess.run(['xprop', '-root', '_NET_ACTIVE_WINDOW'], capture_output=True, text=True, check=True) | |
match = re.search(r'window id # (0x[0-9a-f]+)', result.stdout) | |
if match: | |
return match.group(1) | |
else: | |
return None | |
except subprocess.CalledProcessError: | |
return None | |
def get_window_geometry(win_id): | |
"""Gets the geometry (x, y, width, height) of a window using xwininfo.""" | |
if not win_id: | |
return None | |
try: | |
result = subprocess.run(['xwininfo', '-id', win_id], capture_output=True, text=True, check=True) | |
print(f"xwininfo output for ID {win_id}:\n{result.stdout}") | |
x_match = re.search(r'Absolute upper-left X:\s+(\d+)', result.stdout) | |
y_match = re.search(r'Absolute upper-left Y:\s+(\d+)', result.stdout) | |
width_match = re.search(r'Width:\s+(\d+)', result.stdout) | |
height_match = re.search(r'Height:\s+(\d+)', result.stdout) | |
if x_match and y_match and width_match and height_match: | |
return int(x_match.group(1)), int(y_match.group(1)), int(width_match.group(1)), int(height_match.group(1)) | |
else: | |
print(f"get_window_geometry: Could not parse geometry for window ID: {win_id}") | |
return None | |
except subprocess.CalledProcessError as e: | |
print(f"get_window_geometry: Error getting window geometry for ID {win_id}: {e}") | |
print(f"Stderr: {e.stderr}") | |
return None | |
def get_screen_geometry(): | |
# Get the active screen name using the provided shell script | |
screen_name_process = subprocess.run(['./get_screen_name.sh'], capture_output=True, text=True, check=True) | |
screen_name = screen_name_process.stdout.strip() | |
print(f"Active screen name: {screen_name}") | |
# Get the output of xrandr | |
xrandr_process = subprocess.run(['xrandr'], capture_output=True, text=True, check=True) | |
xrandr_output = xrandr_process.stdout | |
# Parse the xrandr output to find the resolution of the active screen | |
for line in xrandr_output.splitlines(): | |
if screen_name in line and "connected" in line: | |
# Extract width and height using regex | |
match = re.search(r'(\d+)x(\d+)', line) | |
if match: | |
width = int(match.group(1)) | |
height = int(match.group(2)) | |
print(f"Screen Width: {width}, Height: {height}") | |
return width, height | |
else: | |
print(f"Could not find resolution in xrandr output for screen: {screen_name}") | |
return None | |
print(f"Screen name '{screen_name}' not found in xrandr output.") | |
return None | |
def move_window(win_id, x, y): | |
"""Moves a window using xdotool.""" | |
subprocess.run(['xdotool', 'windowmove', win_id, str(int(x)), str(int(y))]) | |
def resize_window(win_id, width, height): | |
"""Resizes a window using xdotool.""" | |
subprocess.run(['xdotool', 'windowsize', '--sync', win_id, str(int(width)), str(int(height))]) | |
def handle_arrow_resize_move(direction): | |
active_win_id = get_active_window_id() | |
screen_width, screen_height = get_screen_geometry() or (0, 0) | |
print(f'screen_width: {screen_width}, screen_height: {screen_height}') | |
if active_win_id and screen_width > 0 and screen_height > 0: | |
win_x, win_y, win_width, win_height = get_window_geometry(active_win_id) or (0, 0, 0, 0) | |
print(f'Initial win_x: {win_x}, win_y: {win_y}, win_width: {win_width}, win_height: {win_height}') | |
width_small_screen = screen_width / 3 - GAP_SIZE - 10 | |
width_half_screen = screen_width / 2 - GAP_SIZE | |
width_big_screen = screen_width / 1.5- GAP_SIZE - 10 | |
print('win_width', win_width) | |
print('width_small_screen', width_small_screen) | |
height_small_screen = screen_height * 0.4 - GAP_SIZE | |
height_half_screen = screen_height * 0.5 - GAP_SIZE | |
height_big_screen = screen_height * 0.6 - GAP_SIZE | |
if direction == "left": | |
if win_x == screen_width - win_width - GAP_SIZE and win_width == width_small_screen: | |
move_window(active_win_id, GAP_SIZE + width_small_screen + GAP_SIZE, win_y) | |
return | |
if win_x == GAP_SIZE + width_small_screen + GAP_SIZE and win_width == width_small_screen: | |
move_window(active_win_id, GAP_SIZE, win_y) | |
return | |
if width_half_screen - 100 <= win_width <= width_half_screen + 100: | |
resize_window(active_win_id, width_small_screen, win_height) | |
elif win_width < width_half_screen - 100: | |
resize_window(active_win_id, width_big_screen, win_height) | |
else: | |
resize_window(active_win_id, width_half_screen, win_height) | |
move_window(active_win_id, GAP_SIZE, win_y) | |
elif direction == "right": | |
if win_x == GAP_SIZE and win_width == width_small_screen: | |
move_window(active_win_id, GAP_SIZE + width_small_screen + GAP_SIZE, win_y) | |
return | |
if win_x == GAP_SIZE + win_width + GAP_SIZE and win_width == width_small_screen: | |
move_window(active_win_id, screen_width - win_width - GAP_SIZE, win_y) | |
return | |
if width_half_screen - 100 <= win_width <= width_half_screen + 100: | |
resize_window(active_win_id, width_small_screen, win_height) | |
elif win_width < width_half_screen - 100: | |
resize_window(active_win_id, width_big_screen, win_height) | |
else: | |
resize_window(active_win_id, width_half_screen, win_height) | |
_, _, win_width, _ = get_window_geometry(active_win_id) or (0, 0, 0, 0) | |
x = screen_width - win_width - GAP_SIZE | |
move_window(active_win_id, x, win_y) | |
elif direction == "up": | |
if height_half_screen - 100 <= win_height <= height_half_screen + 100: | |
resize_window(active_win_id, win_width, height_small_screen - 20) | |
elif win_height < height_half_screen - 100: | |
resize_window(active_win_id, win_width, height_big_screen - 20) | |
else: | |
resize_window(active_win_id, win_width, height_half_screen - 20) | |
move_window(active_win_id, win_x, GAP_SIZE) | |
elif direction == "down": | |
if height_half_screen - 100 <= win_height <= height_half_screen + 100: | |
resize_window(active_win_id, win_width, height_small_screen) | |
elif win_height < height_half_screen - 100: | |
resize_window(active_win_id, win_width, height_big_screen) | |
else: | |
resize_window(active_win_id, win_width, height_half_screen) | |
_, _, _, win_height = get_window_geometry(active_win_id) or (0, 0, 0, 0) | |
y = screen_height - win_height - GAP_SIZE | |
move_window(active_win_id, win_x, y) | |
def main(): | |
global GAP_SIZE | |
GAP_SIZE = 20 | |
if len(sys.argv) == 2 and sys.argv[1] in ["left", "right", "up", "down"]: | |
handle_arrow_resize_move(sys.argv[1]) | |
else: | |
print(f"This script is intended to be executed by Openbox keybindings with a gap of {GAP_SIZE}px.") | |
print("Configure keybindings for Super + Arrows to run:") | |
print("`python3 /path/to/your/script.py left`") | |
print("`python3 /path/to/your/script.py right`") | |
print("`python3 /path/to/your/script.py up`") | |
print("`python3 /path/to/your/script.py down`") | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.