AppleScript how to get current display resolution? - applescript

I'm trying to get the current display resolution of both of my displays depending on where the mouse cursor is.
i.e. when the mouse cursor is on the first display I want to get the resolution of this display.
With a shell script I can get both resolutions:
set screenWidth to (do shell script "system_profiler SPDisplaysDataType | grep Resolution | awk '{print $2}'")
But I don't get which display is currently "active".
Any ideas?

This does the trick:
tell application "Finder"
set screen_resolution to bounds of window of desktop
end tell

Applescript does not have any access to cursor location, even via System Events. Sorry.
[There are a couple commercial solutions, but I'm guessing they're not worth the trouble in this case? I suppose I could also whip up a quick command-line tool that just returns the current cursor location... worth the trouble?]
p.s. awk is great at finding matching lines:
set screenWidth to (do shell script "system_profiler SPDisplaysDataType | awk '/Resolution/{print $2}'")

For the sake of even more completeness, here is the code to get the width, height, and Retina scale of a specific display (main or built-in).
This is the code to get the resolution and Retina scale of the built-in display:
set {width, height, scale} to words of (do shell script "system_profiler SPDisplaysDataType | awk '/Built-In: Yes/{found=1} /Resolution/{width=$2; height=$4} /Retina/{scale=($2 == \"Yes\" ? 2 : 1)} /^ {8}[^ ]+/{if(found) {exit}; scale=1} END{printf \"%d %d %d\\n\", width, height, scale}'")
And this is the code to get the resolution and Retina scale of the main display:
set {width, height, scale} to words of (do shell script "system_profiler SPDisplaysDataType | awk '/Main Display: Yes/{found=1} /Resolution/{width=$2; height=$4} /Retina/{scale=($2 == \"Yes\" ? 2 : 1)} /^ {8}[^ ]+/{if(found) {exit}; scale=1} END{printf \"%d %d %d\\n\", width, height, scale}'")
The code is based on this post by Jessi Baughman and the other answers given here.

The following does not solve the OP's problem, but may be helpful to those wanting to determine the resolution of ALL attached displays in AppleScript (thanks to #JoelReid and #iloveitaly for the building blocks):
set resolutions to {}
repeat with p in paragraphs of ¬
(do shell script "system_profiler SPDisplaysDataType | awk '/Resolution:/{ printf \"%s %s\\n\", $2, $4 }'")
set resolutions to resolutions & {{word 1 of p as number, word 2 of p as number}}
end repeat
# `resolutions` now contains a list of size lists;
# e.g., with 2 displays, something like {{2560, 1440}, {1920, 1200}}

For the sake of completeness, here is the code to grab the screen height:
do shell script "system_profiler SPDisplaysDataType | awk '/Resolution/{print $4}'"}

Multi-Monitor and Retina detection
To get the width, height and scaling (retina = 2, else = 1) for all monitors:
set resolutions to {}
repeat with p in paragraphs of ¬
(do shell script "system_profiler SPDisplaysDataType | awk '/Resolution:/{ printf \"%s %s %s\\n\", $2, $4, ($5 == \"Retina\" ? 2 : 1) }'")
set resolutions to resolutions & {{word 1 of p as number, word 2 of p as number, word 3 of p as number}}
end repeat
get resolutions
Based on answers above.
Results in something like this:
{{2304, 1440, 2}, {1920, 1080, 1}}

On my machine system_profiler takes nearly a second to return a reply. For my purposes, that way too long.
Pre-10.12, I used ASObjC Runner but apparently that no longer works.
This is much faster for me:
tell application "Finder" to get bounds of window of desktop
(Taken from https://superuser.com/a/735330/64606)

I have a shell script that makes use of cliclick and displayplacer, both available in Homebrew: https://github.com/huyz/trustytools/blob/master/mac/get-bounds-of-mouse-display.sh
To use from within AppleScript:
set displayBounds to do shell script "PATH=/opt/homebrew/bin:$PATH /Users/huyz/bin/get-bounds-of-mouse-display | xargs -n 1 echo"
set displayBounds to the paragraphs of displayBounds

Related

How to trim a string in shell script with a specific pattern?

How's everyone doing?
So, if I run xdotool getactivewindow getwindowname, it gives the full title of the current window, for example:
fish home/kibe/Documents — Konsole
Blablablabla - Stack Overflow - Google Chrome
The thing is, I only want the application name (Konsole and Google Chrome).
I can easily do it in Python, as such:
def getAppTitle (fullStr):
lastDashIndex = None
for i in range(len(fullStr)):
if fullStr[i] == '-' or fullStr[i] == '—':
lastDashIndex = i
return fullStr[lastDashIndex+2:] if lastDashIndex else fullStr
print(getAppTitle('blablabla - blablabla - ApplicationName'))
# returns ApplicationName
I have been trying to do the same in shell script but I can't do it for the life of me. Also, for some reasons, some applications use "-" (normal dash) and others "—" (em dash).
How can I do that in shell?
You have to use this 'em dash' or dash as the field separator and print the last field:
xdotool getactivewindow getwindowname | awk -F"—|-" '{print $NF}'
I am not sure where this 'em dash' comes from, I had to copy paste it for the above command.
Maybe better, use two characters as the FS, any dash and a space, to get the same as your script, with the space trimmed.
xdotool getactivewindow getwindowname | awk -F"— |- " '{print $NF}'

How to find all available fonts on OSX using the default shell

I'm trying to write a script for Adobe After Effects using extendscript (a proprietary ECMAScript dialect, but mostly ≈ javascript). I can use an inbuilt command system.callSystem() to execute a command using the default(?) shell, but I can't find a bash one liner, or an AppleScript command I can use to list the available fonts.
Is there a way of getting all the fonts on the command line in OSX?
From AppleScript, you can use this ASOC code to get the names of all of the fonts or font families available to the system:
use framework "AppKit"
set fontFamilyNames to (current application's NSFontManager's sharedFontManager's availableFontFamilies) as list
set fontNames to (current application's NSFontManager's sharedFontManager's availableFonts) as list
I'm not sure which of those you want, so I included code for both. If you want to access this script from bash, use the osascript command:
fontFamilyNames=$(osascript << SCPT
use framework "AppKit"
set fontFamilyNames to (current application's NSFontManager's sharedFontManager's availableFontFamilies) as list
return fontFamilyNames
SCPT)
Solution 1: AppleScript
tell application "Font Book" to set activeFontsList to name of every font family --- whose enabled is true
Note that the whose enabled is true filter is commented out because it slows down the query considerably.
Solution 2: AppleScript & Bash
You can execute the AppleScript above from Bash like that:
#!/usr/bin/env bash
# Query the list of fonts with AppleScript.
font_list=$(osascript << SCPT
tell application "Font Book" to set activeFontsList to name of every font family --- whose enabled is true
SCPT)
# Convert the list to column and sort it.
font_list=$(echo $font_list | awk -e 'gsub(", ", "\n")' | sort -f)
# Display the list.
echo -e "$font_list"
# Display the list size.
echo -e "$font_list" | wc -l | xargs printf "\nFont count: %d\n"
Same script but one-liner:
font_list=$(osascript -e 'tell application "Font Book" to set activeFontsList to name of every font family --- whose enabled is true') && font_list=$(echo $font_list | awk -e 'gsub(", ", "\n")' | sort -f) && echo -e "$font_list"
Solution 3: fc-list
fc-list : family | sort -f
fc-list : family | wc -l | xargs printf "\nFont count: %d\n"
You will find some examples here: https://www.geeksforgeeks.org/fc-list-command-in-linux-with-examples/.

A bash/gnuplot script to produce movie-like effects

I would like to plot a sequence of images one after the other on the same window using gnuplot. Images are all the same exact size and I have many of them sequentially called test_0X.gnu and are in gnuplot format.
I wrote this in bash
#! /bin/bash
for i in $(seq -f "%06g" 0 1000)
do
echo "set term pdf enhance color" > script.plg
echo "set output 'demo.pdf'" >> script.plg
echo "plot 'test_$i.gnu' with lines" >> script.plg
echo "set output"
gnuplot < script.plg
evince demo.pdf &
sleep 0.3
done;
The seq -f ensures the correct number of padded zeros is present before the number.
This works but once the script starts I am unable to stop it, as ctrl+c or ctrl+z doesn't work and I cannot access other terminal due to constant coming up of a pdf windows.
How do I stop this?
How do I make the sequence skip (e.g. by 10) and show me only test_000010.gnu, test_000020.gnu, .. etc.
Bonus: Any other, more sensible way to do this is welcome.
Just write a short gnuplot script
set terminal wxt
files = system('ls test_*.gnu')
do for [file in files] {
plot file with lines
pause 0.5
}
and run this
gnuplots "gif" terminal can produce a readymade animation.
skip=5 # change as needed
set term gif animate 10 # 10/100 s delay between frames
set out "test.gif"
# assuming your data files are named "test_0001.dat" etc.
do for [i=1:100:skip] {plot sprintf("test_%04.f.dat",i)}
set out

How can my shell script control the placement of a zenity window?

I'm using zenity to post a simple notification when my spam-filter daemon filters a group of messages. Currently this message is posted to the middle of the screen, which is obtrusive. I want to post it to the upper left corner. However, zenity does not honor the -geometry option which is supposed to be standard for all X applications, and its documentation gives options for controlling window height and width, but not placement.
Is there a way to control the (x,y) coordinate at which a zenity window is posted?
If not, is there a way to solve this problem by tinkering with X resources or the window manager (I'm using the fvwm)?
EDIT: The following do not work in ~/.fvwm2rc (fvwm version 2.5.26):
Style "Information" PositionPlacement -0 -0
Style "Zenity" PositionPlacement -0 -0
They also don't work with the -0 -0 dropped, as suggested in the man page.
(The window title for zenity --info is "Information".)
Interestingly, zenity was ignoring my earlier window-manager directive that windows should be placed manually by default.
EDIT:
Among many other fascinating pieces of information, xprop(1) reports this about the zenity window:
_NET_WM_WINDOW_TYPE(ATOM) = _NET_WM_WINDOW_TYPE_DIALOG
WM_NORMAL_HINTS(WM_SIZE_HINTS):
program specified location: 0, 0
program specified minimum size: 307 by 128
program specified maximum size: 307 by 128
window gravity: NorthWest
WM_CLASS(STRING) = "zenity", "Zenity"
WM_ICON_NAME(STRING) = "Information"
WM_NAME(STRING) = "Information"
Despite this apparently encouraging report, the window is not in fact posted at the location 0,0 :-(
I know the Style command is taking effect because I added the !Borders option, and sure enough the zenity window posts without borders... but still in the center of the damn screen!
I do it by using wmctrl in a subshell. Example:
((sleep .4;wmctrl -r TeaTimer -R TeaTimer -e 0,50,20,-1,-1)
for ((a=$LIMIT; a > 0; a--)); do
# for loop generates text, not shown
done
wmctrl -R TeaTimer
) | zenity --progress --title="TeaTimer" --percentage=0
First wmctrl moves zenity to upper left, second moves it to
current workspace. See a full example.
You could try using the "old" way of doing this, using FvwmEvent.
AddToFunc StartFunction I Module FvwmEvent FvwmEvent-MoveWindow
DestroyModuleConfig FvwmEvent-MoveWindow: *
*FvwmEvent-MoveWindow: Cmd Function
*FvwmEvent-MoveWindow: add_window MoveZenity
DestroyFunc MoveZenity
AddToFunc MoveZenity
+ I ThisWindow ("zenity") Move -0 -0
If this still doesn't work (or you are determined to get it working using PositionPlacement) you could try
BugOpts ExplainWindowPlacement
Fvwm will then write debugging output to it's logfile (or to the console, depending on your setup) explaining how it is placing windows (and why it is doing so).
Also just fyi, if you want to get information about a window you can use the FvwmIdent module to get this information (instead of xprop, though both work fine).
Yes, it is definitely possible with the proper help from window manager. For example, with xmonad it would be one line of code...
My fvwm is little rusty, but it seems like something along the lines of:
Style "zenity" PositionPlacement -0 -0
in your fvwm2rc should do the trick.
EDIT: Notice the lowercase "zenity" since, according to the docs, it should match not only window title, but window class as well (which you can find out using "xprop" utility: launch it and point to window in question).
According to xprop, zenity window has two interesting properties:
It has _NET_WM_WINDOW_TYPE(ATOM) = _NET_WM_WINDOW_TYPE_DIALOG, indicating that it is a dialog window
It has WM_TRANSIENT_FOR(WINDOW): window id # <some window id here>, indicating the main window for which it is a dialog (in my case - xterm window)
So, if my suggestion does not work, then it is almost certainly because fvwm handles dialogs in a special way - either due to configuration or due to hardcoded behavoir.
You can try adding "EWMHIgnoreWindowType" to the style of zenity windows, which should hopefuly made fvwm ignore those hints
Try devilspie: http://burtonini.com/blog/computers/devilspie/
You can use wmctrl to get the windowid, then xdotool to place it wherever you want. Simple and adaptable to many types of environments.
## Arg 1 - Pid of window to move.
## Arg 2 - X-Coord.
## Arg 3 - Y-Coord.
function move_win() {
xdotool windowmove $(wmctrl -lp | grep ${1} | cut -d' ' -f1) ${2} ${3}
}
E.g. $> move_win $(pidof zenity) 0 0

Is there a way to query the current brightness level of a the MacBook LCD?

The idea being that, once the brightness passes a certain level, one could switch to a different visual scheme to give greater visibility. Also, if it could be some sort of listener type thing, that would be even better, but I'll take what I can get.
I believe one could look it up with IOKit. Running the ioreg command in the terminal as below gives two lines where a brightness value is visible.
% ioreg -c AppleGraphicsControlBacklight | grep brightness
| | | "IODisplayParameters" = {"brightness"={"min"=0,"value"=408,"max"=1024},"commit"={"reg"=0}}
| | | "IODisplayParameters" = {"brightness"={"min"=0,"value"=408,"max"=1024},"commit"={"reg"=0}}
Maybe someone with enough IOKit knowledge could put together a sample...
epatel was pretty close, I just had to change the AppleGraphicsControlBacklight keyword to something else to get it to work on my macbook, so I'd guess that this is something that might change between OSX versions and/or macbook versions.
I threw together a short ruby script to print out a little visual indicator on the command line.
# grab the string containing the values
brite_string = `ioreg -c AppleBacklightDisplay | grep brightness`
# build a regex to match those vals
brite_regex = /"brightness"=\{"min"=([0-9]{1,3}),"value"=([0-9]{1,3}),"max"=([0-9]{1,3})/
# match them
match_data = brite_regex.match(brite_string)
# extract the values from the match
min = match_data[1].to_i
val = match_data[2].to_i
max = match_data[3].to_i
# print them out nice
puts "Current Brightness"
print "["
max.times do |i|
print i > val ? " " : "*"
end
puts "]"
I am not a mac guy, but does /proc exist in the filesystem? You might want to look in that virtual file directory if it exists.

Resources