Move window between monitors in visible parts of max res (xdotool or wmctrl)

About writing shell scripts and making the most of your shell
Forum rules
Topics in this forum are automatically closed 6 months after creation.
Post Reply
User avatar
Koentje
Level 7
Level 7
Posts: 1913
Joined: Tue Jan 04, 2022 6:23 pm
Location: Netherlands

Move window between monitors in visible parts of max res (xdotool or wmctrl)

Post by Koentje »

I have been on this for hours and it drives me mad! Maybe my math skills sukk, but i can't seem to find an answer!

What i want is a small window that moves around on my screen. With a single monitor that's not a problem, had this scripted. With multiple monitors there it becomes a problem! Sometimes the window disappears into the dark parts of resolutions! And i can't seem to make a calculation on how to avoid these parts.

This is my setup
resolution.png
resolution.png (6.81 KiB) Viewed 153 times
The black parts are the parts i don't want the window to move to!

With only one monitor i get the resolution with xrandr, create the space were the window can move in.. width of screen minus width of window and height of screen minus height of window and then calculate random values.

But with multiple monitors it becomes a little different! Now, with xrandr i get a max resolution of 4031x2520 with invisible spots.
xrandr | grep "Screen 0: " | sed "s/.*current \([0-9]*\) x \([0-9]*\).*/\1x\2/"

When i run xrandr --listmonitors i get this:

Code: Select all

 0: +*DisplayPort-1 3440/797x1440/334+0+1080  DisplayPort-1
 1: +HDMI-1-1 1920/477x1080/268+2111+0  HDMI-1-1
This is abracadabra to me! :shock:

Since xdotool and wmctrl don't have an option to say that the window must move in a specific monitors resolution, i have to figure it out myself i gues..

I need a script that determines how many monitors there are, and then calculates the visible spaces in the max resolution of all the monitors were i can move that window to.

Somebody?
Image
1000
Level 6
Level 6
Posts: 1051
Joined: Wed Jul 29, 2020 2:14 am

Re: Move window between monitors in visible parts of max res (xdotool or wmctrl)

Post by 1000 »

I don't have 2 monitors to check

https://superuser.com/questions/485120/ ... ith-xrandr

So in your case
... +0+1080 DisplayPort-1 ( have 3440 x 1440 )
= 0 from the left and 1080 from the top
in xev command, width is first , second height
So working area = from 0 to 3440 [width] and from 1080 to $((1080+1440 )) [height]

... +2111+0 HDMI-1-1 ( have 1920 x 1080 )
= 2111 from the left and 0 from the top
So working area = from 2111 to $((2111+1920)) [width] and from 0 to 1080 [height]

Looking at the picture above, it looks like everything is correct
If I'm wrong, please correct me.
User avatar
Koentje
Level 7
Level 7
Posts: 1913
Joined: Tue Jan 04, 2022 6:23 pm
Location: Netherlands

Re: Move window between monitors in visible parts of max res (xdotool or wmctrl)

Post by Koentje »

Well... i'm trying my effin best, but i can't get any solution scripted! This drives me nuts..
Is there an easy way to only move the window around the primary? Skip other monitors, just the primary.

Can someone script an example of that?
Image
1000
Level 6
Level 6
Posts: 1051
Joined: Wed Jul 29, 2020 2:14 am

Re: Move window between monitors in visible parts of max res (xdotool or wmctrl)

Post by 1000 »

Example script to open mate-calc app and move with wmctrl

Code: Select all

#!/bin/bash

# Will show settings all open windows
One=$(wmctrl -l -G)

# Will open mate-calc and move
mate-calc &
mate-calc &

# Needed to work below: wmctrl -l -G
sleep 1

Two=$(wmctrl -l -G)

Two_windows=$(diff -n <(echo "$One" ) <(echo "$Two") | sed '1d')

echo "$Two_windows"

echo " -- 1" ; sleep 1

# Move second window to left and above
while read -r Column_1 Column_2 ; do
    wmctrl -i -c "$Column_1" -e 0,100,200,-1,-1
    echo "$Column_1"
done <<< $(sed '1d'<<< "$Two_windows")

echo " -- 2" ; sleep 1

# Move second window to right
while read -r Column_1 Column_2 ; do
    wmctrl -i -c "$Column_1" -e 0,900,200,-1,-1
    echo "$Column_1"
done <<< $(sed '1d'<<< "$Two_windows")

echo " -- 3" ; sleep 1

# Move second window to below
while read -r Column_1 Column_2 ; do
    wmctrl -i -c "$Column_1" -e 0,900,500,-1,-1
    echo "$Column_1"
done <<< $(sed '1d'<<< "$Two_windows")

echo " -- 4" ; sleep 1

# Move second window to left
while read -r Column_1 Column_2 ; do
    wmctrl -i -c "$Column_1" -e 0,100,500,-1,-1
    echo "$Column_1"
done <<< $(sed '1d'<<< "$Two_windows")

echo " -- 5" ; sleep 1

# Close all windows
while read -r Column_1 Column_2 ; do
    echo "$Column_1"
    wmctrl -i -c "$Column_1"
done <<< "$Two_windows"
User avatar
Koentje
Level 7
Level 7
Posts: 1913
Joined: Tue Jan 04, 2022 6:23 pm
Location: Netherlands

Re: Move window between monitors in visible parts of max res (xdotool or wmctrl)

Post by Koentje »

Yeah.. that doesn't answer my question at all. And what's with the second window? Makes the code only overcomplicated.
I know how to move the window around, no problem there. I know how to get the window id of the window i want to move. But the problem is, when the window on the primary is past the horizontal part were the second screen begins then 0 vertical is not the top of the primary, but the top of the secundary screen. So it moves to the secundary.. If after that the random horizontal value becomes 0 the window moves into the black space and is gone until the next random values.. I want it to stay on the primary or in the visible parts when it randomly moves around.

I need my script to see how many monitors there are, and on what positions they are with what resolutions and then calculate random values to stay out of the black zones! And it has to work on different setups with x monitors.

Or if that's impossible, and this makes it easier, only stay on the primary monitor.

resolution.png
resolution.png (6.81 KiB) Viewed 63 times
Image
1000
Level 6
Level 6
Posts: 1051
Joined: Wed Jul 29, 2020 2:14 am

Re: Move window between monitors in visible parts of max res (xdotool or wmctrl)

Post by 1000 »

Can you paste sample code with detailed comments on what script should do?
User avatar
Koentje
Level 7
Level 7
Posts: 1913
Joined: Tue Jan 04, 2022 6:23 pm
Location: Netherlands

Re: Move window between monitors in visible parts of max res (xdotool or wmctrl)

Post by Koentje »

This is what i have now.

test.sh

Code: Select all

#!/bin/bash

cconf="test.conky"

# Check if conky config exists and get height and width of window
  cconf="./$(basename $cconf)"
  if [ -f "$cconf" ]; then
     # Check if conky is a real conky config
     if [ "$(cat "$cconf" | head -n1)" = "conky.config = {" ]; then
        # Get width of conky window
        cwidth=$(grep 'minimum_width' "$cconf"|xargs|cut -d' ' -f3|sed s/,*$//g)
        if [ "$cwidth" = "" ]; then
          echo -e "\n Error: 'minimum_width' in conky config is empty! Exit script..\n"
          exit 1
        fi
        # Get height of conky window
        cheight=$(grep 'minimum_height' "$cconf"|xargs|cut -d' ' -f3|sed s/,*$//g)
        if [ "$cheight" = "" ]; then
          echo -e "\n Error: 'minimum_width in conky config is empty! Exit script..\n"
          exit 1
        fi
     else
        echo -e "\n Error: $cconf is not recognized as a conky config! Exit script..\n\n"
        exit 1
     fi
  else
    echo -e "\n Error: $cconf not found! Exit script..\n"
    exit 1
  fi


  winid=$(wmctrl -l | grep ' conky-screensaver$' | awk '{print $1}')          # Get Window ID
  reso=$(xrandr --current | grep '*' | uniq | head -n1 | awk '{print $1}')    # Get resolution of primary screen
  resx=$(echo "$reso" | awk -F'x' '{print $1}')                               # pixels width
  resy=$(echo "$reso" | awk -F'x' '{print $2}')                               # pixels height
  echo "resx = $resx"
  echo "resy = $resy"
  echo "winid = $winid"


move-conky () {
  while :
  do
       gapx=$(shuf -i 100-$((resx-cwidth)) -n1)   # random horizontal nr starting at 100 pix to last pix minus width of conky window
       gapy=$(shuf -i 100-$((resy-cheight)) -n1)  # random vetical nr starting at 100 pix to last pix minus height of conky window.
       echo "gapx = $gapx"
       echo "gapy = $gapy"
       wmctrl -i -r $winid -e 0,$gapx,$gapy,-1,-1 # Move window
       sleep 3
  done
}
move-conky


test.conky[/c]

Code: Select all

conky.config = {
-- **********************************************************************
-- "test"
-- **********************************************************************

	background = false,

	alignment = 'top_right',
	gap_x = 30,
	gap_y = 30,
	minimum_width = 306,
	minimum_height = 100,

	draw_borders = true,
	border_width = 1,
	stippled_borders = 0,
	default_color = 'white',
	default_outline_color = 'black',
	default_shade_color = '#BBBBBB',
	draw_graph_borders = false,
	draw_outline = false,
	draw_shades = false,
	show_graph_scale = false,
	show_graph_range = false,
	double_buffer = true,
	no_buffers = true,
	out_to_console = false,
	out_to_stderr = false,
	extra_newline = false,
	uppercase = false,
	use_spacer = 'none',

	own_window = true,
	own_window_class = 'conky-screensaver',
	own_window_title = 'conky-screensaver',
	own_window_type = 'normal',
	own_window_transparent = false,
	own_window_colour = '100000',
	own_window_argb_visual = false,
	own_window_argb_value = 255,
	own_window_hints = 'undecorated,above,sticky,skip_taskbar,skip_pager',

	use_xft = true,
	xftalpha = 1,
	font = 'Ubuntu Mono:bold:size=11',

	color0 = 'white',
	color1 = 'yellow',
	color2 = '#FFA300',
	color3 = '#777777',
	color5 = '#FDB555',
	color6 = '#FE8525',
	color7 = '#666600',
	color8 = '#E0CC00',

	imlib_cache_flush_interval = 1,
	imlib_cache_size = 512,

	update_interval = 1,

};

conky.text = [[
${voffset -5}${alignc}${color8}${font GE Inspira:bold:pixelsize=110:bold}${time %H:%M}${font}
]];
Run the conky window: conky -c ./test.conky
Then run test.sh

I hope you have multiple screens or this is pointless i guess?
Let me know if you need anything else..
Image
Post Reply

Return to “Scripts & Bash”