Skip to content

Instantly share code, notes, and snippets.

@zumikkebe
Last active October 17, 2024 08:42
Show Gist options
  • Save zumikkebe/1aea6d017eb78ba672a751cf78ef9810 to your computer and use it in GitHub Desktop.
Save zumikkebe/1aea6d017eb78ba672a751cf78ef9810 to your computer and use it in GitHub Desktop.
winpwnr.sh is a one-liner Haikus' hey front-end with the intent to domate windows
#! /bin/bash
# The MIT License (MIT)
# Copyright © 2024 Michele Frau aka zuMi
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
fHelpUsage() # help usage function, receives input
{
local help_usage
help_usage="usage: $(basename ${0}) [-h] [-D] [-a argument] [-l] [-i argument] [-dfI] [-twLFGpPMAmHnr argument]
Options:
-D automatically detects the current active window, obtaining the name of the application and the ID number
-a select the application by name
-l list windows of the selected application
-i select application window via ID number or title
-I get info about the selected window
-d avoid DeskBar
-f force fullscreen for the selected window
-t change the title of the selected window
-w show the selected window on {x} workspace(s),
· set multiple values separated by any character, like \"1,2,4,5\" or \"5.6.1\"
· use \"a|all\" to show the selected window in every workspace
· use l|left, r|right, u|up and d|down to move the selected window in the adjacent workspace by the given direction
-L change the LOOK of the selected window:
· b OR B_BORDERED_WINDOW_LOOK
· n OR B_NO_BORDER_WINDOW_LOOK
· t OR B_TITLED_WINDOW_LOOK
· d OR B_DOCUMENT_WINDOW_LOOK
· m OR B_MODAL_WINDOW_LOOK
· f OR B_FLOATING_WINDOW_LOOK
-F change the FEEL of the selected window:
· n OR B_NORMAL_WINDOW_FEEL
· ms OR B_MODAL_SUBSET_WINDOW_FEEL
· mp OR B_MODAL_APP_WINDOW_FEEL
· ml OR B_MODAL_ALL_WINDOW_FEEL
· fs OR B_FLOATING_SUBSET_WINDOW_FEEL
· fp OR B_FLOATING_APP_WINDOW_FEEL
· fl OR B_FLOATING_ALL_WINDOW_FEEL
-G change the FLAGS of the selected window, multiple values are accepted separated by commas
· nm OR B_NOT_MOVABLE
· nc OR B_NOT_CLOSABLE
· nz OR B_NOT_ZOOMABLE
· nb OR B_NOT_MINIMIZABLE
· nr OR B_NOT_RESIZABLE
· nh OR B_NOT_H_RESIZABLE
· nv OR B_NOT_V_RESIZABLE
· af OR B_AVOID_FRONT
· as OR B_AVOID_FOCUS
· fc OR B_WILL_ACCEPT_FIRST_CLICK
· or OR B_OUTLINE_RESIZE
· nw OR B_NO_WORKSPACE_ACTIVATION
· na OR B_NOT_ANCHORED_ON_ACTIVATE
· ac OR B_ASYNCHRONOUS_CONTROLS
· qc OR B_QUIT_ON_WINDOW_CLOSE
· sp OR B_SAME_POSITION_IN_ALL_WORKSPACES
· au OR B_AUTO_UPDATE_SIZE_LIMITS
· ce OR B_CLOSE_ON_ESCAPE
· ns OR B_NO_SERVER_SIDE_WINDOW_MODIFIERS
· l OR lock (shortcut for nm,nc,nr,nz,nr)
-p move the selected window to [x,y] (absolute) position
-P move the selected window by [x,y] pixels (relative)
-r resize the frame of the selected window to [width, height], centering it with the original one and avoiding to exit the edges of the screen
omit a value to preserve the current one (i.e. -r ,300; -r 300, ), use any letter to enlarge to max size (i.e. -r f,200; -r 200,f )
-R as above, but [width, height] are relative values
-M minimize the selected window [1|t|true|on|y|yes,0|f|false|off|n|no,toggle]
-A active the selected window [1|t|true|on|y|yes,0|f|false|off|n|no,toggle]
-m move the selected window against the edges and corners of the screen:
7 8 9 ul u ur up-left up up-right
4 5 6 OR l c r OR left center right
1 2 3 dl d dr down-left down down-right
combine the option center + selected edge to move the selected window centered against the edge to a centered position (i.e. use -m 45, 54, cl, lc, center-left or left-center)
ce or closest-edge moves the window against the closest edge
cc or closest-corner moves the window against the closest corner
-H as the -m option but the selected window will be moved against the edges, resized to halves of the screen size, resized to quarters of the screen size to the corners
-n as the -m option but the selected window will be moved against the edges, resized to ninths of the screen size
with this option it is possible to assign a group of adjacent ninths to the selected window using the digits (numpad)
Examples:
-n 12 ░ ░ ░
░ ░ ░
█ █ ░
-n 59 ░ █ █
░ █ █
░ ░ ░
-n 28 ░ █ ░
░ █ ░
░ █ ░
Insert the digits that match the screen portions you want to take care of the window, the script is not restrictive about the order of the digits, it reorders and discards what is not necessary, so it is possible to enter 12 or 21, 28,82,258,285,582,etc. or 59,95,9586,etc., just make sure only to select the ends of the desired area
-z zoom in/out the selected window
-q quit the selected window
-h print this help"
if [ ${1} ] ; then # if input is true
echo "${help_usage}" >&2 # print to stderr
exit 1 # and exit with error
else # print to stdin and exit with no erro
echo "${help_usage}"
exit
fi
}
fAutoDiscoveryActiveWindow() # Auto-discovery of the active window, not the most efficient approach but it works in Bash
{
local i
# Loop through each application name retrieved from 'roster', excluding servers
# 'roster' lists running apps, awk extracts app names, and sort removes duplicates
while read app_name ; do
# Loop through each window ID for the current app
while read i; do
for ((win_ID=0; win_ID<i; win_ID++)) ; do
# For each window, check if it is active by using 'hey'
# 'timeout 0.1' limits the wait time to 0.1 seconds to avoid long delays
# If the 'Active' status of the window is true, the function returns (successful)
[[ "$(timeout 0.1 hey -o "${app_name}" get Active of Window ${win_ID})" == "true" ]] && return
done
done <<< $(hey -o ${app_name} count of Window) # Get the number of windows for the current app
done <<< $(roster | grep -v 'server' | awk '/\(/{print $2}' FS='[()]' | sort -u) # Get list of running apps
echo "No active window found!" >&2 # shüt happens, no active window has been found
exit 1
}
fSetWindowWorkspace() # set the window's workspace
{
local work_space
case ${1} in
a|all)
# If "a" or "all" is passed, set the window to be in all workspaces (-1)
work_space=-1
;;
# If the option is a direction (left, right, up, down), move window to adjacent workspace
l|left|r|right|u|up|d|down)
local rows columns curr_row curr_column
# Get the number of rows and columns for the workspace grid from the system settings
IFS=',' read -r columns rows <<< "$(message ${XDG_CONFIG_HOME}/system/app_server/workspaces | awk '/columns/,/rows/ {printf "%d,",$(NF-1)}' FS='[^0-9]')"
# Get the current workspace of the app's window and compute its index
work_space=$(hey -o "${app_name}" get Workspaces of Window "${win_ID}" | awk '{if($0>0) print 1+log($0)/log(2)}')
# If work_space is null or is a float, return (the window is displayed on multiple workspaces)
( [[ -z "${work_space}" ]] || [[ "${work_space}" =~ [.] ]] ) && return
# Calculate the current column and row based on the workspace index
curr_column=$(( ( work_space - 1 ) % columns + 1 ))
curr_row=$(( ( ( work_space - curr_column ) / rows ) + 1 ))
# Handle movement based on the given direction (left, right, up, down)
case ${1:0:1} in
l) # Move left
if (( curr_column > 1 )) ; then
work_space=$(( work_space - 1 )) # Move to the previous column
else
work_space=$(( columns * curr_row )) # Move to the last column of the current row
fi
;;
r) # Move right
if (( curr_column < columns )) ; then
work_space=$(( work_space + 1 )) # Move to the next column
else
work_space=$(( 1 + columns * ( curr_row - 1 ))) # Wrap around to the first column of the next row
fi
;;
u) # Move up
if (( curr_row > 1 )) ; then
work_space=$(( work_space - columns )) # Move to the previous row
else
work_space=$(( curr_column + ( ( rows - curr_row ) * columns ) )) # Wrap around to the last row
fi
;;
d) # Move down
if (( curr_row < rows )) ; then
work_space=$(( work_space + columns )) # Move to the next row
else
work_space=${curr_column} # Wrap around to the first row
fi
;;
esac
# Convert the calculated workspace index back to a power of 2 (to set the correct workspace bitmask)
work_space=$(( 2 ** ( work_space - 1 ) ))
;;
# If a numeric value is passed, set the window to that specific workspace(s)
*)
local rows columns max_workspaces
# Get the number of rows and columns from the system settings
IFS=',' read -r columns rows <<< "$(message ${XDG_CONFIG_HOME}/system/app_server/workspaces | awk '/columns/,/rows/ {printf "%s,",$(NF-1)}' FS='[^0-9]')"
# Calculate the maximum number of workspaces available
max_workspaces=$(( columns * rows ))
# Parse the input (numeric values) and convert it to a workspace bitmask
work_space=$(echo -n ${1} | awk -v max=${max_workspaces} '{for(i=1;i<=NF;i++){if($i<=max)print ($i-1)}}' FS="[^0-9]" | sort -nu | awk '{work_space+=2^($0)} END {print work_space}')
;;
esac
# Set the window's workspace to the calculated bitmask
hey -o "${app_name}" set Workspaces of Window "${win_ID}" to ${work_space}
# Check if the job is done
fJobDone
}
fListApplicationWindows() # List all windows of the specified application
{
# Get the total number of windows for the specified application
local windows_count=$(hey "${app_name}" count Window | awk '/result/{print $4}')
# Loop through each window by index (from 0 to windows_count - 1)
for ((i=0;i<windows_count;i++)); do
# Print the window index (i)
printf "%s) " ${i}
# Retrieve and print the title of each window
hey "${app_name}" get Title of Window "${i}" | awk '/result/{print $4}' FS="\""
done
# Mark the job as done
fJobDone
}
fSetWindowTitle() # Set the title of a specified window
{
hey -o "${app_name}" set Title of Window "${win_ID}" To "${1}"
# Check if the job is done
fJobDone
}
fSetAbsoluteWindowSize() # Set the window size to an absolute value, adjusting its position and dimensions if necessary
{
# Declare local variables
local b_rect
local work_frame_x work_frame_y work_frame_w work_frame_h
local win_frame_x win_frame_y win_frame_w win_frame_h
local new_frame_x new_frame_y new_frame_w new_frame_h
local delta_w delta_h max_w max_h
# If the workspace frame is not yet calculated, retrieve it using fGetWorkspaceFrame
[[ -z "${work_frame}" ]] && fGetWorkspaceFrame
# Extract workspace frame dimensions from work_frame (X, Y, width, height)
IFS=',' read -r work_frame_x work_frame_y work_frame_w work_frame_h <<< "${work_frame}"
# Extract current window frame dimensions (X, Y, width, height) for the specific window
IFS=',' read -r win_frame_x win_frame_y win_frame_w win_frame_h <<< "$(fGetFrame "${app_name}" Frame "${win_ID}")"
# Extract new frame dimensions (width and height) from the function input
IFS=',' read -r new_frame_w new_frame_h <<< "${1}"
# Adjust the workspace frame boundaries to account for window borders and tab heights
let work_frame_x+=border_size
let work_frame_y+=tab_height
let work_frame_w-=border_size
let work_frame_h-=border_size
# Calculate the maximum allowed width and height for the new window size within the workspace
max_w=$(( work_frame_w - work_frame_x ))
max_h=$(( work_frame_h - work_frame_y ))
# Ensure the new window width does not exceed the workspace width
(( new_frame_w > max_w )) && new_frame_w=${max_w}
# Ensure the new window height does not exceed the workspace height
(( new_frame_h > max_h )) && new_frame_h=${max_h}
# If the new width is not a number or not specified, set it to the current window width
if (( ! new_frame_w )) ; then
if [[ -z "${new_frame_w}" ]] ; then
new_frame_w=$(( win_frame_w - win_frame_x ))
else
[[ ! "${new_frame_w}" =~ ^[0-9]+$ ]] && new_frame_w=${max_w} # If the is specified a character (i.e. f), set it to the current workspace width
fi
fi
# If the new width is not a number or not specified, set it to the current window height
if (( ! new_frame_h )) ; then
if [[ -z "${new_frame_h}" ]] ; then
new_frame_h=$(( win_frame_h - win_frame_y ))
else
[[ ! "${new_frame_h}" =~ ^[0-9]+$ ]] && new_frame_h=${max_h} # If the is specified a character (i.e. f), set it to the current workspace height
fi
fi
# Calculate the difference (delta) between the current and new window dimensions
delta_w=$(( new_frame_w - ( win_frame_w - win_frame_x ) ))
delta_h=$(( new_frame_h - ( win_frame_h - win_frame_y ) ))
# If no changes in dimensions (both deltas are zero), return without further action
(( ! delta_w && ! delta_h )) && return
# Calculate the new position for the window, centering it based on the new dimensions
new_frame_x=$(( win_frame_x - delta_w / 2 ))
new_frame_y=$(( win_frame_y - delta_h / 2 ))
# Calculate the new frame dimensions by adding the width and height to the new position
new_frame_w=$(( new_frame_x + new_frame_w ))
new_frame_h=$(( new_frame_y + new_frame_h ))
# Adjust the window frame if it goes beyond the workspace boundaries (left/top/right/bottom)
(( new_frame_x < work_frame_x )) && { let new_frame_w+=$(( work_frame_x - new_frame_x )); new_frame_x=${work_frame_x}; }
(( new_frame_y < work_frame_y )) && { let new_frame_h+=$(( work_frame_y - new_frame_y )); new_frame_y=${work_frame_y}; }
(( new_frame_w > work_frame_w )) && { let new_frame_x-=$(( new_frame_w - work_frame_w )); new_frame_w=${work_frame_w}; }
(( new_frame_h > work_frame_h )) && { let new_frame_y-=$(( new_frame_h - work_frame_h )); new_frame_h=${work_frame_h}; }
# Combine the new frame dimensions into a single string (rectangular coordinates)
b_rect="${new_frame_x},${new_frame_y},${new_frame_w},${new_frame_h}"
# Set the window frame to the new dimensions
fSetWindowFrame "${b_rect}"
}
fSetRelativeSize() # Adjust the window size relatively, keeping the window centered and respecting workspace boundaries
{
# Declare local variables
local b_rect # Stores the coordinates of the window's new frame
local work_frame_x work_frame_y work_frame_w work_frame_h # Variables to store workspace dimensions
local win_frame_x win_frame_y win_frame_w win_frame_h # Variables to store windows dimensions
local new_frame_x new_frame_y new_frame_w new_frame_h # Variables to calculate new windows dimensions
local lock_x lock_y lock_w lock_h # Flags to lock dimension adjustments
local delta_w delta_h # Variables to calculate new windows variations
# If the workspace frame is not yet calculated, retrieve it using fGetWorkspaceFrame
[[ -z "${work_frame}" ]] && fGetWorkspaceFrame
# Extract workspace frame dimensions from work_frame (X, Y, width, height)
IFS=',' read -r work_frame_x work_frame_y work_frame_w work_frame_h <<< "${work_frame}"
# Extract current window frame dimensions (X, Y, width, height) for the specific window
IFS=',' read -r win_frame_x win_frame_y win_frame_w win_frame_h <<< "$(fGetFrame "${app_name}" Frame "${win_ID}")"
# Determine the delta values (changes in width and height) based on the input argument
if [[ "${1}" =~ [,] ]] ; then # if is comma separated
IFS=',' read -r delta_w delta_h <<< "${1}" # get values from input
else
delta_w=${1}
delta_h=${delta_w} # only one value has been given, use the same for both width and height
fi
# Adjust workspace frame boundaries to account for window borders and tab heights
let work_frame_x+=border_size
let work_frame_y+=tab_height
let work_frame_w-=border_size
let work_frame_h-=border_size
# Calculate the new frame's position and size based on the deltas
new_frame_x=$(( win_frame_x - delta_w / 2 )) # Center the window horizontally by adjusting X position
new_frame_y=$(( win_frame_y - delta_h / 2 )) # Center the window vertically by adjusting Y position
new_frame_w=$(( win_frame_w + delta_w )) # Increase/decrease the width by delta_w
new_frame_h=$(( win_frame_h + delta_h )) # Increase/decrease the height by delta_h
# Ensure the new frame doesn't exceed workspace boundaries and adjust if necessary
# Check if the new X position is outside the left boundary
if (( new_frame_x < work_frame_x )); then
if (( ! lock_w )) ; then
new_frame_w=$(( new_frame_w + ( work_frame_x - new_frame_x ) )) # Expand the width to compensate
fi
new_frame_x=${work_frame_x} # Lock the X position to the workspace boundary
lock_x=1 # Mark that X is locked
fi
# Check if the new width exceeds the right boundary of the workspace
if (( new_frame_w > work_frame_w )); then
if (( ! lock_x )) ; then
new_frame_x=$(( new_frame_x - ( new_frame_w - work_frame_w ) )) # Move window left to fit in workspace
fi
new_frame_w=${work_frame_w} # Limit the width to the workspace width
lock_w=1 # Mark that the width is locked
fi
# Check if the new Y position is outside the top boundary
if (( new_frame_y < work_frame_y )); then
if (( ! lock_h )) ; then
new_frame_h=$(( new_frame_h + ( work_frame_y - new_frame_y ) )) # Expand the height to compensate
fi
new_frame_y=${work_frame_y} # Lock the Y position to the workspace boundary
lock_y=1 # Mark that Y is locked
fi
# Check if the new height exceeds the bottom boundary of the workspace
if (( new_frame_h > work_frame_h )); then
if (( ! lock_y )) ; then
new_frame_y=$(( new_frame_y - ( new_frame_h - work_frame_h ) )) # Move window up to fit in workspace
fi
new_frame_h=${work_frame_h} # Limit the height to the workspace height
lock_h=1 # Mark that the height is locked
fi
# Combine the new frame dimensions into a single string (rectangular coordinates)
b_rect="${new_frame_x},${new_frame_y},${new_frame_w},${new_frame_h}"
# Set the window frame to the new dimensions
fSetWindowFrame "${b_rect}"
}
fResizeWindowAndMove4() # Resize and move the window to specific quadrants or halves of the screen
{
# Declare local variables
local b_rect # Stores the coordinates of the window's new frame
local work_frame_x work_frame_y work_frame_w work_frame_h # Variables to store workspace dimensions
# If the workspace frame is not set, retrieve it using fGetWorkspaceFrame
[[ -z "${work_frame}" ]] && fGetWorkspaceFrame
# Extract workspace frame dimensions (X, Y, width, height)
IFS=',' read -r work_frame_x work_frame_y work_frame_w work_frame_h <<< "${work_frame}"
# Calculate available width and height inside the workspace
local delta_w=$(( work_frame_w - work_frame_x )) # Width of the usable workspace
local delta_h=$(( work_frame_h - work_frame_y )) # Height of the usable workspace
# Determine window placement based on the input argument
case ${1} in
7|ul|up-left) # Upper-left corner, occupying half the screen size
b_rect="$(( work_frame_x + border_size )),$(( work_frame_y + tab_height )),$(( work_frame_x + delta_w / 2 - border_size )),$(( work_frame_y + delta_h / 2 - border_size ))"
;;
8|u|up) # Top half of the screen
b_rect="$(( work_frame_x + border_size )),$(( work_frame_y + tab_height )),$(( work_frame_w - border_size )),$(( work_frame_y + delta_h / 2 - border_size ))"
;;
9|ur|up-right) # Upper-right corner, occupying half the screen size
b_rect="$(( work_frame_x + delta_w / 2 + border_size )),$(( work_frame_y + tab_height )),$(( work_frame_w - border_size )),$(( work_frame_y + delta_h / 2 - border_size ))"
;;
4|l|left) # Left half of the screen
b_rect="$(( work_frame_x + border_size )),$(( work_frame_y + tab_height )),$(( work_frame_x + delta_w / 2 - border_size )),$(( work_frame_h - border_size ))"
;;
5|c|center) # Center of the screen, occupying half the screen size
b_rect="$(( work_frame_x + delta_w / 4 + border_size )),$(( work_frame_y + delta_h / 4 + tab_height )),$(( work_frame_x + delta_w * 3 / 4 - border_size )),$(( work_frame_y + delta_h * 3 / 4 - border_size ))"
;;
6|r|right) # Right half of the screen
b_rect="$(( work_frame_x + delta_w / 2 + border_size )),$(( work_frame_y + tab_height )),$(( work_frame_w - border_size )),$(( work_frame_h - border_size ))"
;;
1|dl|down-left) # Lower-left corner, occupying half the screen size
b_rect="$(( work_frame_x + border_size )),$(( work_frame_y + delta_h / 2 + tab_height )),$(( work_frame_x + delta_w / 2 - border_size )),$(( work_frame_h - border_size ))"
;;
2|d|down) # Bottom half of the screen
b_rect="$(( work_frame_x + border_size )),$(( work_frame_y + delta_h / 2 + tab_height )),$(( work_frame_w - border_size )),$(( work_frame_h - border_size ))"
;;
3|dr|down-right) # Lower-right corner, occupying half the screen size
b_rect="$(( work_frame_x + delta_w / 2 + border_size )),$(( work_frame_y + delta_h / 2 + tab_height )),$(( work_frame_w - border_size )),$(( work_frame_h - border_size ))"
;;
*)
# If the input is not valid, display help usage message
fHelpUsage 1
;;
esac
# Set the window frame to the new dimensions and position
fSetWindowFrame "${b_rect}"
}
fResizeWindowAndMoveToNinths() # Resize and move the window to specific ninths of the screen
{
# Declare local variables
local b_rect
local min=9
local max=0
local temp
local i
local work_frame_x work_frame_y work_frame_w work_frame_h
# If the workspace frame is not set, retrieve it using fGetWorkspaceFrame
[[ -z "${work_frame}" ]] && fGetWorkspaceFrame
IFS=',' read -r work_frame_x work_frame_y work_frame_w work_frame_h <<< "${work_frame}"
# Check if input contains only numbers and is valid (more than one digit)
if ( [[ "${1}" =~ ^[0-9]+$ ]] && [ ${#1} -gt 1 ] ) ; then
for ((i=0;i<${#1};i++)) ; do # Sort digits in input
temp=${1:i:1}
(( temp < min )) && min=${temp} # Update min
(( temp > max )) && max=${temp} # Update max
done
case ${min}${max} in
12) # Bottom left corner, 2/3 screen width
b_rect="$(( work_frame_x + border_size )),$(( work_frame_h * 2 / 3 + tab_height )),$(( work_frame_w * 2 / 3 - border_size )),$(( work_frame_h - border_size ))"
;;
13) # Bottom row, 1/3 screen height
b_rect="$(( work_frame_x + border_size )),$(( work_frame_h * 2 / 3 + tab_height )),$(( work_frame_w - border_size )),$(( work_frame_h - border_size ))"
;;
14) # Bottom left corner, 2/3 screen height
b_rect="$(( work_frame_x + border_size )),$(( work_frame_h / 3 + tab_height )),$(( work_frame_w / 3 - border_size)),$(( work_frame_h - border_size ))"
;;
15|24) # Bottom left corner, 2/3 screen height, 2/3 screen width
b_rect="$(( work_frame_x + border_size )),$(( work_frame_h / 3 + tab_height )),$(( work_frame_w * 2 / 3 - border_size )),$(( work_frame_h - border_size ))"
;;
16|34) # Bottom row, 2/3 screen height
b_rect="$(( work_frame_x + border_size )),$(( work_frame_h / 3 + tab_height )),$(( work_frame_w - border_size )),$(( work_frame_h - border_size ))"
;;
17) # Left column, 1/3 screen width
b_rect="$(( work_frame_x + border_size )),$(( work_frame_y + tab_height )),$(( work_frame_w / 3 - border_size )),$(( work_frame_h - border_size ))"
;;
18|27) # Left column, 2/3 screen width
b_rect="$(( work_frame_x + border_size )),$(( work_frame_y + tab_height )),$(( work_frame_w * 2 / 3 - border_size )),$(( work_frame_h - border_size ))"
;;
19|37) # Fullscreen
b_rect="$(( work_frame_x + border_size )),$(( work_frame_y + tab_height )),$(( work_frame_w - border_size )),$(( work_frame_h - border_size ))"
;;
23) # Bottom right corner, 2/3 screen width
b_rect="$(( work_frame_w / 3 + border_size )),$(( work_frame_h * 2 / 3 + tab_height )),$(( work_frame_w - border_size )),$(( work_frame_h - border_size ))"
;;
25) # Bottom middle, 2/3 screen height
b_rect="$(( work_frame_w / 3 + border_size )),$(( work_frame_h / 3 + tab_height )),$(( work_frame_w * 2 / 3 - border_size )),$(( work_frame_h - border_size ))"
;;
26|35) # Bottom right corner, 2/3 screen height, 2/3 screen width
b_rect="$(( work_frame_w / 3 + border_size )),$(( work_frame_h / 3 + tab_height )),$(( work_frame_w - border_size )),$(( work_frame_h - border_size ))"
;;
28) # Middle column, 1/3 screen width
b_rect="$(( work_frame_w / 3 + border_size )),$(( work_frame_y + tab_height )),$(( work_frame_w * 2 / 3 - border_size )),$(( work_frame_h - border_size ))"
;;
29|38) # Right column, 2/3 screen width
b_rect="$(( work_frame_w / 3 + border_size )),$(( work_frame_y + tab_height )),$(( work_frame_w - border_size )),$(( work_frame_h - border_size ))"
;;
36) # Bottom right corner, 2/3 screen height, 1/3 screen width
b_rect="$(( work_frame_w * 2 / 3 + border_size )),$(( work_frame_h / 3 + tab_height )),$(( work_frame_w - border_size )),$(( work_frame_h - border_size ))"
;;
39) # Right column, 1/3 screen width
b_rect="$(( work_frame_w * 2 / 3 + border_size )),$(( work_frame_y + tab_height )),$(( work_frame_w - border_size )),$(( work_frame_h - border_size ))"
;;
45) # Middle left, 2/3 screen width, 1/3 screen height
b_rect="$(( work_frame_x + border_size )),$(( work_frame_h / 3 + tab_height )),$(( work_frame_w * 2 / 3 - border_size )),$(( work_frame_h * 2 / 3 - border_size ))"
;;
46) # Middle row, 1/3 screen height
b_rect="$(( work_frame_x + border_size )),$(( work_frame_h / 3 + tab_height )),$(( work_frame_w - border_size )),$(( work_frame_h * 2 / 3 - border_size ))"
;;
47) # Upper left corner, 1/3 screen width, 2/3 screen height
b_rect="$(( work_frame_x + border_size )),$(( work_frame_y + tab_height )),$(( work_frame_w / 3 - border_size )),$(( work_frame_h * 2 / 3 - border_size ))"
;;
48|57) # Upper left corner, 2/3 screen height, 2/3 screen width
b_rect="$(( work_frame_x + border_size )),$(( work_frame_y + tab_height )),$(( work_frame_w * 2 / 3 - border_size )),$(( work_frame_h * 2 / 3 - border_size ))"
;;
49|67) # Upper row, 2/3 screen height
b_rect="$(( work_frame_x + border_size )),$(( work_frame_y + tab_height )),$(( work_frame_w - border_size )),$(( work_frame_h * 2 / 3 - border_size ))"
;;
56) # Middle right, 2/3 screen width, 1/3 screen height
b_rect="$(( work_frame_w / 3 + border_size )),$(( work_frame_h / 3 + tab_height )),$(( work_frame_w - border_size )),$(( work_frame_h * 2 / 3 - border_size ))"
;;
58) # Upper middle, 1/3 screen width, 2/3 screen height
b_rect="$(( work_frame_w / 3 + border_size )),$(( work_frame_y + tab_height )),$(( work_frame_w * 2 / 3 - border_size )),$(( work_frame_h * 2 / 3 - border_size ))"
;;
59|68) # Upper right corner, 2/3 screen width, 2/3 screen height
b_rect="$(( work_frame_w / 3 + border_size )),$(( work_frame_y + tab_height )),$(( work_frame_w - border_size )),$(( work_frame_h * 2 / 3 - border_size ))"
;;
69) # Upper right corner, 1/3 screen width, 2/3 screen height
b_rect="$(( work_frame_w * 2 / 3 + border_size )),$(( work_frame_y + tab_height )),$(( work_frame_w - border_size )),$(( work_frame_h * 2 / 3 - border_size ))"
;;
78) # Upper left corner, 2/3 screen width, 1/3 screen height
b_rect="$(( work_frame_x + border_size )),$(( work_frame_y + tab_height )),$(( work_frame_w * 2 / 3 - border_size )),$(( work_frame_h / 3 - border_size ))"
;;
79) # Upper row, 1/3 screen height
b_rect="$(( work_frame_x + border_size )),$(( work_frame_y + tab_height )),$(( work_frame_w - border_size )),$(( work_frame_h / 3 - border_size ))"
;;
89) # Upper right corner, 2/3 screen width, 1/3 screen height
b_rect="$(( work_frame_w / 3 + border_size )),$(( work_frame_y + tab_height )),$(( work_frame_w - border_size )),$(( work_frame_h / 3 - border_size ))"
;;
esac
else
# Handle single digit or string input
case ${1} in
7|ul|up-left) # Upper left corner, a third screen size
b_rect="$(( work_frame_x + border_size )),$(( work_frame_y + tab_height )),$(( work_frame_w / 3 - border_size )),$(( work_frame_h / 3 - border_size ))"
;;
8|u|up) # Upper half screen height
b_rect="$(( work_frame_w / 3 + border_size )),$(( work_frame_y + tab_height )),$(( work_frame_w * 2 / 3 - border_size )),$(( work_frame_h / 3 - border_size ))"
;;
9|ur|up-right) # Upper right corner, a third screen size
b_rect="$(( work_frame_w * 2 / 3 + border_size )),$(( work_frame_y + tab_height )),$(( work_frame_w - border_size )),$(( work_frame_h / 3 - border_size ))"
;;
4|l|left) # Left half screen width
b_rect="$(( work_frame_x + border_size )),$(( work_frame_h / 3 + tab_height )),$(( work_frame_w / 3 - border_size )),$(( work_frame_h * 2 / 3 - border_size ))"
;;
5|c|center) # Middle screen, a third screen size
b_rect="$(( work_frame_w / 3 + border_size )),$(( work_frame_h / 3 + tab_height )),$(( work_frame_w * 2 / 3 - border_size )),$(( work_frame_h * 2 / 3 - border_size ))"
;;
6|r|right) # Right half screen width
b_rect="$(( work_frame_w * 2/ 3 + border_size )),$(( work_frame_h / 3 + tab_height )),$(( work_frame_w - border_size )),$(( work_frame_h * 2 / 3 - border_size ))"
;;
1|dl|down-left) # Lower left corner, a third screen size
b_rect="$(( work_frame_x + border_size )),$(( work_frame_h * 2 / 3 + tab_height )),$(( work_frame_w / 3 - border_size )),$(( work_frame_h - border_size ))"
;;
2|d|down) # Lower half screen height
b_rect="$(( work_frame_w / 3 + border_size )),$(( work_frame_h * 2 / 3 + tab_height )),$(( work_frame_w * 2 / 3 - border_size )),$(( work_frame_h - border_size ))"
;;
3|dr|down-right) # Lower right corner, a third screen size
b_rect="$(( work_frame_w * 2 / 3 + border_size )),$(( work_frame_h * 2 / 3 + tab_height )),$(( work_frame_w - border_size )),$(( work_frame_h - border_size ))"
;;
*)
fHelpUsage 1 # Display help if input doesn't match
;;
esac
fi
# Set the window frame to the new dimensions and position
fSetWindowFrame "${b_rect}"
}
fSetWindowFrame() # Set the window frame to the new dimensions and position
{
hey -o "${app_name}" set Frame of Window "${win_ID}" to BRect["${1}"]
# Check if the job is done
fJobDone
}
fSetWindowFullScreen() # Set the window frame to the fullscreen
{
# Redirect to another function that handles the resizing and moving of the window fo full screen
fResizeWindowAndMoveToNinths 19
}
fSetWindowLook() # Set windows look (style)
{
local look # Variable to hold the look value corresponding to the window style
# Determine the appropriate look value based on the input argument
case ${1} in
b|B_BORDERED_WINDOW_LOOK) # Bordered window look
look=20
;;
n|B_NO_BORDER_WINDOW_LOOK) # No border window look
look=19
;;
t|B_TITLED_WINDOW_LOOK) # Titled window look
look=1
;;
d|B_DOCUMENT_WINDOW_LOOK) # Document window look
look=11
;;
m|B_MODAL_WINDOW_LOOK) # Modal window look
look=3
;;
f|B_FLOATING_WINDOW_LOOK) # Floating window look
look=7
;;
*) # If an unrecognized option is provided
fHelpUsage 1
;;
esac
# Set the look of the specified window using the determined value
hey -o "${app_name}" set Look of Window "${win_ID}" to ${look}
# Check if the job is done
fJobDone
}
fSetWindowFeel() # Set windows feel (behaviour)
{
local feel # Variable to hold the feel value corresponding to the window behavior
# Determine the appropriate feel value based on the input argument
case ${1} in
n|B_NORMAL_WINDOW_FEEL) # Normal window feel
feel=0
;;
ms|B_MODAL_SUBSET_WINDOW_FEEL) # Modal subset window feel
feel=2
;;
mp|B_MODAL_APP_WINDOW_FEEL) # Modal application window feel
feel=1
;;
ml|B_MODAL_ALL_WINDOW_FEEL) # Modal for all windows feel
feel=3
;;
fs|B_FLOATING_SUBSET_WINDOW_FEEL) # Floating subset window feel
feel=5
;;
fp|B_FLOATING_APP_WINDOW_FEEL) # Floating application window feel
feel=4
;;
fl|B_FLOATING_ALL_WINDOW_FEEL) # Floating for all windows feel
feel=6
;;
*) # If an unrecognized option is provided
fHelpUsage 1
;;
esac
# Set the feel of the specified window using the determined value
hey -o "${app_name}" set Feel of Window "${win_ID}" to ${feel}
# Check if the job is done
fJobDone
}
fGetFlagBitValue() # Returns the significant bit value corresponding to the flag in input
{
local bit_exponent # Variable to store the bit exponent corresponding to the flag
# Match the input flag (either short or full name) to the corresponding bit exponent value
case ${1} in
nm|B_NOT_MOVABLE) # Not movable flag
bit_exponent=0
;;
nr|B_NOT_RESIZABLE) # Not resizable flag
bit_exponent=1
;;
nh|B_NOT_H_RESIZABLE) # Not horizontally resizable flag
bit_exponent=2
;;
nv|B_NOT_V_RESIZABLE) # Not vertically resizable flag
bit_exponent=3
;;
fc|B_WILL_ACCEPT_FIRST_CLICK) # Accepts first click flag
bit_exponent=4
;;
nc|B_NOT_CLOSABLE) # Not closable flag
bit_exponent=5
;;
nz|B_NOT_ZOOMABLE) # Not zoomable flag
bit_exponent=6
;;
af|B_AVOID_FRONT) # Avoid front flag
bit_exponent=7
;;
nw|B_NO_WORKSPACE_ACTIVATION) # No workspace activation flag
bit_exponent=8
;;
ns|B_NO_SERVER_SIDE_WINDOW_MODIFIERS) # No server-side window modifiers flag
bit_exponent=9
;;
or|B_OUTLINE_RESIZE) # Outline resize flag
bit_exponent=12
;;
as|B_AVOID_FOCUS) # Avoid focus flag
bit_exponent=13
;;
nb|B_NOT_MINIMIZABLE) # Not minimizable flag
bit_exponent=14
;;
na|B_NOT_ANCHORED_ON_ACTIVATE) # Not anchored on activate flag
bit_exponent=17
;;
ac|B_ASYNCHRONOUS_CONTROLS) # Asynchronous controls flag
bit_exponent=19
;;
qc|B_QUIT_ON_WINDOW_CLOSE) # Quit on window close flag
bit_exponent=20
;;
sp|B_SAME_POSITION_IN_ALL_WORKSPACES) # Same position in all workspaces flag
bit_exponent=21
;;
au|B_AUTO_UPDATE_SIZE_LIMITS) # Auto-update size limits flag
bit_exponent=22
;;
ce|B_CLOSE_ON_ESCAPE) # Close on escape flag
bit_exponent=23
;;
*) # If the flag is unrecognized, call the help/usage function
fHelpUsage 1
;;
esac
# Return the bit exponent value (bash style)
echo $bit_exponent
}
fSetWindowFlags() # Set window flags
{
local IFS=',' # Internal Field Separator for processing flags list
local flag bit_value # Variables to hold each flag and its bit value
# If the flags variable is not set, retrieve the current window flags
(( ! flags )) && local flags=$(hey "${app_name}" get Flags of Window "${win_ID}" | awk '/result/ {print $4}')
# Loop through each flag provided as an argument
for flag in ${1}; do
# If the flag starts with 'l', set common flags for locked window (not movable, resizable, closable, zoomable, minimizable)
if [[ "${flag,0,1}" == "l" ]] ; then
fSetWindowFlags "nm,nr,nc,nz,nb"
return
else
# Get the bit value for the flag
bit_value=$((1 << $(fGetFlagBitValue ${flag})))
# If the flag is not already set (bitwise check), add it
if ((( flags & bit_value ) == 0 )); then
flags=$(( flags | bit_value ))
else
# If the flag is set, remove it
flags=$(( flags & ~bit_value ))
fi
fi
done
# Update the window flags
hey -o "${app_name}" set Flags of Window "${win_ID}" to ${flags}
# Check if the job is done
fJobDone
}
fSetWindowToggle() # Toggle or set window properties
{
local value # Variable to store the value (true/false)
# Determine the state based on the input argument
case ${1} in
1|t|true|on|y|yes) # If the input is any variation of "true" or "on"
value=true
;;
0|f|false|off|n|no) # If the input is any variation of "false" or "off"
value=false
;;
toggle) # If the argument is "toggle", invert the current property state
# Use 'hey' get the current value of the property for the window
# If the current value is "true", set it to false; otherwise, set it to true
[[ "$(hey -o "${app_name}" get ${2} of Window "${win_ID}")" == "true" ]] && fSetWindowToggle 0 ${2} || fSetWindowToggle 1 ${2} # ${2} << ${1}
return
;;
*) # If the argument is unrecognized, show the help/usage function
fHelpUsage 1
;;
esac
# set the property of the window to the specified toggle value (true/false)
hey -o "${app_name}" set ${2} of Window "${win_ID}" to ${value}
# Check if the job is done
fJobDone
}
fSetWindowActive() # Set the window active state (visible and focused)
{
fSetWindowToggle ${1} Active # set the "Active" state based on input ${1}
}
fSetWindowMinimize() # Minimize or restore the window
{
fSetWindowToggle ${1} Minimize # set the "Minimize" state based on input ${1}
}
fSetWindowHidden() # Show or hide the window
{
fSetWindowToggle ${1} Hidden # set the "Hidden" state based on input ${1}
}
fMoveWindowToEdges()
{
local b_point # Variable to hold the bottom point (target position) for moving the window
local work_frame_x work_frame_y work_frame_w work_frame_h # Workspace frame dimensions
local win_frame_x win_frame_y win_frame_w win_frame_h # Window frame dimensions
local win_width win_height # Variables to hold window dimensions
# If workspace frame is not set, retrieve it
[[ -z "${work_frame}" ]] && fGetWorkspaceFrame
# Read workspace frame dimensions into local variables
IFS=',' read -r work_frame_x work_frame_y work_frame_w work_frame_h <<< "${work_frame}"
# Read window frame dimensions into local variables
IFS=',' read -r win_frame_x win_frame_y win_frame_w win_frame_h <<< "$(fGetFrame "${app_name}" Frame "${win_ID}")"
# Calculate the width and height of the window
win_width=$(( win_frame_w - win_frame_x ))
win_height=$(( win_frame_h - win_frame_y ))
# Determine the target position based on the provided argument
case ${1} in
7|ul|lu|left-up|up-left) # Move to upper left corner
b_point="$(( work_frame_x + border_size )),$(( work_frame_y + tab_height ))"
;;
1|dl|ld|left-down|down-left) # Move to lower left corner
b_point="$(( work_frame_x + border_size )),$(( work_frame_h - win_height - border_size))"
;;
3|dr|rd|right-down|down-right) # Move to lower right corner
b_point="$(( work_frame_w - win_width - border_size )),$(( work_frame_h - win_height - border_size ))"
;;
9|ur|ru|right-up|up-right) # Move to upper right corner
b_point="$(( work_frame_w - win_width - border_size )),$(( work_frame_y + tab_height ))"
;;
5|c|center) # Move to center of the workspace
b_point="$(( ( work_frame_w - win_width ) / 2 )),$(( ( work_frame_h - win_height ) / 2 ))"
;;
4|l|left) # Move to left edge
b_point="$(( work_frame_x + border_size )),${win_frame_y}"
;;
6|r|right) # Move to right edge
b_point="$(( work_frame_w - win_width - border_size )),${win_frame_y}"
;;
2|d|down) # Move to bottom edge
b_point="${win_frame_x},$(( work_frame_h - win_height - border_size ))"
;;
8|u|up) # Move to top edge
b_point="${win_frame_x},$(( work_frame_y + tab_height ))"
;;
58|85|uc|cu|center-up|up-center) # Move to center of the top edge
b_point="$(( ( work_frame_w - win_width ) / 2 )),$(( work_frame_y + tab_height ))"
;;
45|54|lc|cl|left-center|center-left) # Move to center of the left edge
b_point="$(( work_frame_x + border_size )),$(( ( work_frame_h - win_height ) / 2 ))"
;;
65|56|rc|cr|right-center|center-right) # Move to center of the right edge
b_point="$(( work_frame_w - win_width )),$(( ( work_frame_h - win_height ) / 2 ))"
;;
25|52|dc|cd|down-center|center-down) # Move to center of the bottom edge
b_point="$(( ( work_frame_w - win_width ) / 2 )),$(( work_frame_h - win_height - border_size ))"
;;
ce|closest-edge) # Move to the closest edge of the workspace
local left_dist=$(( win_frame_x - work_frame_x )) # Calculate distance to the left edge
local closest="l" # Initialize closest edge as left
local min_dist=${left_dist} # Initialize minimum distance
local right_dist=$(( work_frame_w - win_frame_w )) # Calculate distance to the right edge
local up_dist=$(( win_frame_y - work_frame_y )) # Calculate distance to the top edge
local down_dist=$(( work_frame_h - win_frame_h )) # Calculate distance to the bottom edge
# Determine the closest edge
if (( right_dist < min_dist )) ; then
closest="r"; min_dist=${right_dist}
fi
if (( up_dist < min_dist )) ; then
closest="u"; min_dist=${up_dist}
fi
if (( down_dist < min_dist )) ; then
closest="d"
fi
# Recursively call the function to move to the closest edge
fMoveWindowToEdges ${closest}
return
;;
cc|closest-corner) # Move to the closest corner of the workspace
local left_dist=$(( win_frame_x - work_frame_x )) # Calculate distance to the left edge
local closest="l" # Initialize closest corner as left
local right_dist=$(( work_frame_w - win_frame_w )) # Calculate distance to the right edge
local up_dist=$(( win_frame_y - win_frame_y )) # Calculate distance to the top edge
local down_dist=$(( work_frame_h - win_frame_h )) # Calculate distance to the bottom edge
# Determine the closest corner
if (( right_dist < left_dist )) ; then
closest="r"
fi
if (( up_dist < down_dist )) ; then
closest="u${closest}"
else
closest="d${closest}"
fi
# Recursively call the function to move to the closest corner
fMoveWindowToEdges ${closest}
return
;;
*)
# If an unrecognized option is provided, display help usage
fHelpUsage 1
;;
esac
# Set the absolute position of the window to the calculated bottom point
fSetAbsolutePosition "${b_point}"
}
fSetAbsolutePosition()
{
hey -o "${app_name}" let Window "${win_ID}" do MoveTo BPoint[${1}]
# Check if the job is done
fJobDone
}
fSetRelativePosition()
{
hey -o "${app_name}" let Window "${win_ID}" do MoveBy BPoint[${1}]
# Check if the job is done
fJobDone
}
fGetTabHeight() # Get the height of the title tab and the window's border size
{
local tab_frame_x tab_frame_y tab_frame_w tab_frame_h # Variables to hold the dimensions of the tab frame
local win_frame_x win_frame_y win_frame_w win_frame_h # Variables to hold the dimensions of the window frame
border_size=0 # Initialize the border size to zero (for bordered or non-bordered windows)
tab_height=0 # Initialize the tab height to zero
# Retrieve the frame dimensions of the tab and window using fGetFrame function
IFS=',' read -r tab_frame_x tab_frame_y tab_frame_w tab_frame_h <<< "$(fGetFrame "${app_name}" TabFrame "${win_ID}")"
IFS=',' read -r win_frame_x win_frame_y win_frame_w win_frame_h <<< "$(fGetFrame "${app_name}" Frame "${win_ID}")"
# Check if tab_frame_x is set, indicating the window is not modal and has a defined border
if [[ -n "${tab_frame_x}" ]] ; then
# Calculate the border size as the difference between the window frame and tab frame x-coordinates
border_size=$(( win_frame_x - tab_frame_x ))
# Calculate the tab height as the difference between the window frame and tab frame y-coordinates
tab_height=$(( win_frame_y - tab_frame_y ))
fi
}
fGetWorkspaceFrame() # Get workspace available room, avoiding the Deskbar if specified
{
# If the workspace frame is not yet defined, calculate it
if [[ -z "${work_frame}" ]] ; then
# Declare variables to store the workspace and desktop dimensions
local work_frame_x work_frame_y work_frame_w work_frame_h
# Get the height of title tab (if relevant) by calling fGetTabHeight
fGetTabHeight
# Get the dimensions of the desktop (full screen) by calling fGetFrame for the "Tracker" window
# fGetFrame returns the desktop (x, y, width, height)
IFS=',' read -r work_frame_x work_frame_y work_frame_w work_frame_h <<< "$(fGetFrame Tracker Frame 0)"
# If deskbar should be considered
if (( avoid_deskbar )) ; then
# Declare variables to store the deskbar's frame
local deskbar_x deskbar_y deskbar_w deskbar_h
# Get the deskbar frame using fGetFrame
IFS=',' read -r deskbar_x deskbar_y deskbar_w deskbar_h <<< "$(fGetFrame Deskbar Frame 0)"
# Adjust workspace frame based on the deskbar position and size
if (( ! deskbar_x && deskbar_w == work_frame_w )); then
# Deskbar spans the full width of the desktop
if (( deskbar_y )); then
# Deskbar is at the bottom, workspace ends where Deskbar starts
work_frame_h=${deskbar_y}
else
# Deskbar is at the top, workspace starts where Deskbar ends
work_frame_y=${deskbar_h}
fi
else
# Deskbar is in a corner
local deskbar_shelf_y=$(hey Deskbar get Frame of View 1 of View 0 of Window 0 | awk '/result/ {printf "%d", $7}' FS='[(), ]+')
# determines if deskbar occupies more than 1 row
if (( deskbar_h == work_frame_h )); then
# Deskbar is at the bottom
if (( deskbar_shelf_y )); then
# Deskbar occupies > 1 rows
if (( deskbar_x )); then
# Deskbar on the right, workspace width ends where Deskbar starts
work_frame_w=${deskbar_x}
else
# Deskbar on the left, workspace width starts where Deskbar ends
work_frame_x=${deskbar_w}
fi
else
# Deskbar occupies one row, workspace height ends where Deskbar starts
work_frame_h=${deskbar_y}
fi
else
# Deskbar is at the top
if (( deskbar_shelf_y )); then
# Deskbar occupies two rows
if (( deskbar_x )); then
# Deskbar on the right, workspace width ends where Deskbar starts
work_frame_w=${deskbar_x}
else
# Deskbar on the left, workspace width starts where Deskbar ends
work_frame_x=${deskbar_w}
fi
else
# Deskbar occupies one row, if it's on the left, workspace height starts where Deskbar ends
(( ! deskbar_x )) && work_frame_y=${deskbar_h}
fi
fi
fi
fi
# Save the calculated workspace frame as a string in the format: x,y,width,height
work_frame="${work_frame_x},${work_frame_y},${work_frame_w},${work_frame_h}"
fi
}
fGetFrame() # Retrieve the frame (coordinates and size) of the specified window using 'hey'
{
# $1: Application name
# $2: Frame type (e.g., "Frame" or any other frame property)
# $3: Window ID
# Print the windows frame (x, y, width, height) as a comma-separated string
hey "${1}" get ${2} of Window "${3}" | awk '/result/ {
printf "%d,%d,%d,%d\n", $6, $7, $8, $9
}' FS='[(), ]+'
}
fGetWindowInfo() # print informations about the current selected window
{
declare flag # Declare a variable for storing window flags
declare look # Declare a variable for storing window look
declare feel # Declare a variable for storing window feel
# Check if the apps window supports the getsuites command
# If so, proceed to gather and display the windows information
if [[ ! $(hey -o "${app_name}" getsuites of Window "${win_ID}") ]] ; then
# Print the application name and window ID
echo "app: ${app_name};"
echo "window: ${win_ID};"
# Get the window title and print it if different from the window ID
hey "${app_name}" get Title of Window "${win_ID}" | awk -v title="${win_ID}" '/result/ {if(title!=$(NF-1))printf "title:\t\t%s;\n",$(NF-1)}' FS="\""
# Get the window frame (coordinates and size) and format it for display
hey "${app_name}" get Frame of Window "${win_ID}" | awk '/result/{sub(/^.*\(/,"");sub(/\)/,"");gsub(" ","");printf "%s,",$0}' | awk '{printf "x:\t\t%s;\ny:\t\t%s;\nw:\t\t%s;\nh:\t\t%s;\n",int($1),int($2),$3-$1,$4-$2}' FS=","
# Get the window flags and decode them to human-readable form using a lookup table
hey "${app_name}" get Flags of Window "${win_ID}" | awk 'BEGIN{\
flag[0]="B_NOT_MOVABLE";\
flag[5]="B_NOT_CLOSABLE";\
flag[6]="B_NOT_ZOOMABLE";\
flag[14]="B_NOT_MINIMIZABLE";\
flag[1]="B_NOT_RESIZABLE";\
flag[2]="B_NOT_H_RESIZABLE";\
flag[3]="B_NOT_V_RESIZABLE";\
flag[7]="B_AVOID_FRONT";\
flag[13]="B_AVOID_FOCUS";\
flag[4]="B_WILL_ACCEPT_FIRST_CLICK";\
flag[12]="B_OUTLINE_RESIZE";\
flag[8]="B_NO_WORKSPACE_ACTIVATION";\
flag[17]="B_NOT_ANCHORED_ON_ACTIVATE";\
flag[19]="B_ASYNCHRONOUS_CONTROLS";\
flag[20]="B_QUIT_ON_WINDOW_CLOSE";\
flag[21]="B_SAME_POSITION_IN_ALL_WORKSPACES";\
flag[22]="B_AUTO_UPDATE_SIZE_LIMITS";\
flag[23]="B_CLOSE_ON_ESCAPE";\
flag[9]="B_NO_SERVER_SIDE_WINDOW_MODIFIERS";\
} /result/ {curr_flag=$4;for(i=23;i>=0;i--){if(flag[i]&&curr_flag>=2^i){printf "\t\t%s;\n",flag[i];curr_flag-=2^i}};printf "flag:\t\t%s;\n",$4}' | tac
# Get the window look (style) and print its name using a lookup table
hey "${app_name}" get Look of Window "${win_ID}" | awk 'BEGIN{\
look[20]="B_BORDERED_WINDOW_LOOK";\
look[19]="B_NO_BORDER_WINDOW_LOOK";\
look[1]="B_TITLED_WINDOW_LOOK";\
look[11]="B_DOCUMENT_WINDOW_LOOK";\
look[3]="B_MODAL_WINDOW_LOOK";\
look[7]="B_FLOATING_WINDOW_LOOK";\
} /result/ {printf "look:\t\t%s;\n\t\t%s;\n",$4,look[$4]}'
# Get the window feel (behavior) and print its name using a lookup table
hey "${app_name}" get Feel of Window "${win_ID}" | awk 'BEGIN{\
feel[0]="B_NORMAL_WINDOW_FEEL";\
feel[1]="B_MODAL_APP_WINDOW_FEEL";\
feel[2]="B_MODAL_SUBSET_WINDOW_FEEL";\
feel[3]="B_MODAL_ALL_WINDOW_FEEL";\
feel[4]="B_FLOATING_APP_WINDOW_FEEL";\
feel[5]="B_FLOATING_SUBSET_WINDOW_FEEL";\
feel[6]="B_FLOATING_ALL_WINDOW_FEEL";\
} /result/ {printf "feel:\t\t%s;\n\t\t%s;\n",$4,feel[$4]}'
# Get the workspaces where the window is present and list them
hey "${app_name}" get Workspaces of Window "${win_ID}" | awk '/result/ {curr_ws=$4;printf "workspaces:\t%s;\n",curr_ws;for(i=0;curr_ws>0;i++){if(and(curr_ws,1)){printf "\t\t%s;\n",i+1};curr_ws=rshift(curr_ws,1)}}'
# Get the active, hidden, and minimized states of the window
hey "${app_name}" get Active of Window "${win_ID}" | awk '/result/ {printf "active:\t\t%s;\n",$4}'
hey "${app_name}" get Hidden of Window "${win_ID}" | awk '/result/ {printf "hidden:\t\t%s;\n",$4}'
hey "${app_name}" get Minimize of Window "${win_ID}" | awk '/result/ {printf "minimized:\t%s;\n",$4}'
else
exit 1 # If the window does not respond to messages, exit with an error
fi
# Check if the job is done
fJobDone
}
fJobDone() # Check if the job is done
{
# If the previous command was successful (exit status is not 1), increment the 'job_done' counter
[ $? -ne 1 ] && let job_done+=1
}
fCheckOptions()
{
# If 'show_help' is set, display usage information and exit
(( show_help )) && fHelpUsage
# If an 'error' flag is set, display usage information with an error message and exit
(( error )) && fHelpUsage 1
# If 'app_name' is not set
if [[ -z "${app_name}" ]] ; then
# If 'auto_discovery' is enabled, try to auto-discover the active window
if (( auto_discovery )) ; then
fAutoDiscoveryActiveWindow # Call the function to discover active window
auto_discovery=0 # Disable auto_discovery after its done
fCheckOptions # Re-run the option checks after discovery
fi
else
# If 'app_name' is set but 'win_ID' is not provided
if [[ -z "${win_ID}" ]] ; then
# If 'list_windows' flag is set, list all windows of the application
(( list_windows )) && fListApplicationWindows
else
# If 'win_ID' is set, handle various window-related operations
# Get window information if the 'get_info' flag is set
(( get_info )) && fGetWindowInfo
# Set window to full screen if 'full_screen' flag is set
(( full_screen )) && fSetWindowFullScreen
# If the 'do_quit' flag is set, close the window and mark the job as done
if (( do_quit )) ; then
hey -o "${app_name}" quit Window "${win_ID}"
# Check if the job is done
fJobDone
fi
# If the 'do_zoom' flag is set, zoom the window and mark the job as done
if (( do_zoom )) ; then
hey -o "${app_name}" let Window "${win_ID}" do '_WZM'
# Check if the job is done
fJobDone
fi
# Handle other window operations based on user inputs
# Set a new window title if 'set_title' is provided
[[ -n "${set_title}" ]] && fSetWindowTitle "${set_title}"
# Move the window to the specified edges if 'move_edges' is provided
[[ -n "${move_edges}" ]] && fMoveWindowToEdges ${move_edges}
# Set absolute window position if 'abs_pos' is provided
[[ -n "${abs_pos}" ]] && fSetAbsolutePosition ${abs_pos}
# Set relative window position if 'rel_pos' is provided
[[ -n "${rel_pos}" ]] && fSetRelativePosition ${rel_pos}
# Set absolute window size if 'abs_size' is provided
[[ -n "${abs_size}" ]] && fSetAbsoluteWindowSize ${abs_size}
# Set relative window size if 'rel_size' is provided
[[ -n "${rel_size}" ]] && fSetRelativeSize ${rel_size}
# Move and resize the window using a 4-point system if 'move_resize_quarters_halves' is provided
[[ -n "${move_resize_quarters_halves}" ]] && fResizeWindowAndMove4 ${move_resize_quarters_halves}
# Move and resize the window using a 9-point system if 'move_resize_ninths' is provided
[[ -n "${move_resize_ninths}" ]] && fResizeWindowAndMoveToNinths ${move_resize_ninths}
# Set the window "look" attribute if 'set_look' is provided
[[ -n "${set_look}" ]] && fSetWindowLook ${set_look}
# Set the window "feel" attribute if 'set_feel' is provided
[[ -n "${set_feel}" ]] && fSetWindowFeel ${set_feel}
# Set window flags if 'set_flags' is provided
[[ -n "${set_flags}" ]] && fSetWindowFlags ${set_flags}
# Assign the window to a specific workspace if 'set_workspace' is provided
[[ -n "${set_workspace}" ]] && fSetWindowWorkspace ${set_workspace}
# Set the window as active if 'set_active' is provided
[[ -n "${set_active}" ]] && fSetWindowActive ${set_active}
# Minimize the window if 'set_minimize' is provided
[[ -n "${set_minimize}" ]] && fSetWindowMinimize ${set_minimize}
# Hide the window if 'set_hidden' is provided
[[ -n "${set_hidden}" ]] && fSetWindowHidden ${set_hidden}
fi
fi
# If no job was completed, show usage information and exit with an error
(( job_done )) || fHelpUsage 1
}
while getopts "hDdlIfqza:i:t:m:p:P:r:R:H:n:A:M:N:L:F:G:w:" opt ; do
case ${opt} in
h)
show_help=1
;;
D)
auto_discovery=1
;;
d)
avoid_deskbar=1
;;
l)
list_windows=1
;;
I)
get_info=1
;;
f)
full_screen=1
;;
q)
do_quit=1
;;
z)
do_zoom=1
;;
a)
app_name="$OPTARG"
;;
i)
win_ID="$OPTARG"
;;
t)
set_title="$OPTARG"
;;
m)
move_edges="$OPTARG"
;;
p)
abs_pos="$OPTARG"
;;
P)
rel_pos="$OPTARG"
;;
r)
abs_size="$OPTARG"
;;
R)
rel_size="$OPTARG"
;;
H)
move_resize_quarters_halves="$OPTARG"
;;
n)
move_resize_ninths="$OPTARG"
;;
A)
set_active="$OPTARG"
;;
M)
set_minimize="$OPTARG"
;;
N)
set_hidden="$OPTARG"
;;
L)
set_look="$OPTARG"
;;
F)
set_feel="$OPTARG"
;;
G)
set_flags="$OPTARG"
;;
w)
set_workspace="$OPTARG"
;;
*|\?)
error=1
;;
esac
done
fCheckOptions
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment