Last active
October 17, 2024 08:42
-
-
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
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
#! /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