Is the any way to get WINDOW(Bottom) for a dialog box?

Wow, that's great, thanks! And I can actually help you out a bit, I think—splitting a returned list of values in AppleScript can be done like this:

set {fromLeft, fromTop, width, height} to uipCoords

That will create the four variables using the four values in uipCoords. So I modified your macro by adding this at the end (and removing the other steps):

set kmInst to system attribute "KMINSTANCE"
tell application "Keyboard Maestro Engine"
  setvariable "instanceDialogFromTop" instance kmInst to fromTop
  setvariable "instanceDialogHeight" instance kmInst to height
end tell

This works great; here's the returned values in a display briefly window:

(Sorry, I haven't installed your AppleScript code post macro yet!)

Those are the only two data points I need, but I can easily modify it to get the others if I want. Now I just need to do a bit of work to get the menu bar height, and I'll be there—thanks!

-rob.

2 Likes

Correction: Height isn't height but window bottom—even better!

thanks again;
-rob.

Outstanding! I rarely work with delimiters so I wasn’t aware of the method you posted. I’ll be making note of it and implementing it now. Thank you!

Glad you got it figured out now!

I was running into a problem with the macro running asynchronously and before I put the dialog onscreen: No matter what I did, my macro wouldn't use the value returned by the AppleScript. Even though I could see it held the right value in the Variables section of preferences, my macro would not use the value at all.

I think the problem was the combination of running asynchronously and having the input dialog onscreen. Luckily, it seems to work fine when I switched the mode to non-asynch, and put it after the code that displays the input dialog (and then removed the delay step, too).

-rob.

I'm concluding that asynch mode, though powerful, can also be very frustrating. First there was the problem with the variable not getting passed. That one was relatively easy to work around by running your macro in normal mode.

However, to even get a text window to appear while there's an input dialog box onscreen, that input box has to be loaded asynchronously—if it's not, the display text bits won't do anything at all. And the AppleScript to get the bottom location won't run either.

But if you load an input box asynchronously, it's no longer a real input box, i.e. you can't take action on user response, so I can't control the macro (it acts like the user already clicked a button, when they haven't done anything).

What I wound up having to do is annoying, but the only fix I could find: I display the window asynchronously, run the AppleScript to get my location, then send an Escape to close the window. I can then put my windows onscreen, and display the input box again, this time synchronously.

It flashes on/off/on, but I don't see any way around this issue. (I tried using an HTML prompt, but it too won't show if the input box is onscreen.)

So, working solution, not ideal, but good enough for a free macro that's a spare time project :).

thanks again;
-rob.

Rethinking your situation makes me realize that my initial approach likely won't work without a lot of extra hassle (though it was a fun script to write and I learned some new things, so not a wasted effort for me).

Let's take a different approach. Please correct me if I'm wrong, but from what I understand you want to accomplish the following:

  1. Position the UIP window to horizontal center, and just above vertical center.
  2. Position another window (not sure what kind of window, but I'll call it "test window" for clarity) just below the UIP.

Obviously the UIP does not allow any subsequent actions to be executed until it itself is acted upon. This means that a potential solution would be to position the "test window" first, horizontally centered, and just below vertical center, and then have the UIP positioned above the "test window" according to it's coordinates.

Is that the gist of what you need to do?

Yea, I guess I'd never thought about it that way—I can take a shot at that, no help needed (yet! :)), but thanks for the "duh, do it the other way around!" idea.

-rob.

Well too bad because I'm off today and don't have anything else to work on :laughing:

Keep me posted and I'll tool around with it over here too.

Alright here's something I came up with. It works well for me, but will no doubt need to be modified to suit your needs. Since I don't know what kind of window you need to place below the UIP window, I just used a Display Text action from KM itself. But the principle is the same.

You still need to run the get uip coordinates macro asynchronously from within the calling macro but it handles all of the positioning from within the same AppleScript so it doesn’t need to wait for the prompt window to be acted on.

Try this out, see if it could be adapted to your needs and let me know what you think!

EDIT: These macros and AppleScripts use global variables, prefixed with debug_ to facilitate troubleshooting while building. The calling macro has a basic AppleScript at the end (currently disabled) to delete all those variables. You could probably convert them to instance variables if you wanted, but I didn't feel like messing with that part haha.

-Chris

place uip above dt.kmmacros (6.7 KB)

Macro screenshot (click to expand/collapse)

AppleScript for place uip above dt macro:

----------------------------------------------------------
# Author:				Chris Thomerson
#
# Current Version:		1.0
# Version History:		1.0 (Initial script)
#
# Created:				Friday, December 24, 2021
# Modified:				Friday, December 24, 2021
# macOS:				12.1 (Monterey)
#
# DISCLAIMER
# Permission to use, copy, modify, and/or distribute this
# software for any purpose with or without fee is hereby granted.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
# WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
# THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
----------------------------------------------------------

tell application "Keyboard Maestro Engine"
	
	--gets DT variables from Keyboard Maestro
	set dtXPos to getvariable "debug_dtXPos"
	set dtYPos to getvariable "debug_dtYPos"
	set dtXSize to getvariable "debug_dtXSize"
	set dtXSize to getvariable "debug_dtYSize"
	
end tell

tell application "System Events"
	tell application process "Keyboard Maestro Engine"
		
		--checks for user prompt existence
		repeat until window "Keyboard Maestro User Input" exists
			delay 0.1
		end repeat
		
		--gets all coordinates for user prompt
		tell window "Keyboard Maestro User Input"
			
			--gets user prompt position and size
			set uipPos to its position
			set uipSize to its size
			
			--separates user prompt individual coordinates
			set {uipXPos, uipYPos} to uipPos
			set {uipXSize, uipYSize} to uipSize
			
			set its position to {dtXPos, dtYPos - uipYSize}
			--set its position to {100, 100}
			
		end tell
		
	end tell
end tell

tell application "Keyboard Maestro Engine"
	
	--sets separated UIP coordinates to Keyboard Maestro variables
	setvariable "debug_uipXPos" to uipXPos
	setvariable "debug_uipYPos" to uipYPos
	setvariable "debug_uipXSize" to uipXSize
	setvariable "debug_uipYSize" to uipYSize
	
end tell

get uip coordinates (subroutine).kmmacros (4.1 KB)

Macro screenshot (click to expand/collapse)

AppleScript for get uip coordinates (subroutine) macro:

----------------------------------------------------------
# Author:				Chris Thomerson
#
# Current Version:		1.0
# Version History:		1.0 (Initial script)
#
# Created:				Friday, December 24, 2021
# Modified:				Friday, December 24, 2021
# macOS:				12.1 (Monterey)
#
# DISCLAIMER
# Permission to use, copy, modify, and/or distribute this
# software for any purpose with or without fee is hereby granted.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
# WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
# THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
----------------------------------------------------------

tell application "System Events"
	tell application process "Keyboard Maestro Engine" to tell window "Keyboard Maestro - Display Text"
		set position to {800, 600}
		set size to {300, 150}
		set dtPos to its position
		set dtSize to its size
		set {dtXPos, dtYPos} to dtPos
		set {dtXSize, dtYSize} to dtSize
	end tell
end tell

tell application "Keyboard Maestro Engine"
	setvariable "debug_dtXPos" to dtXPos
	setvariable "debug_dtYPos" to dtYPos
	setvariable "debug_dtXSize" to dtXSize
	setvariable "debug_dtYSize" to dtYSize
end tell
1 Like

Hooray, and thanks for that—I used bits of your new one, and bits of the original one, and then massaged some more AppleScript and Keyboard Maestro, and I think I got it.

This all came up when I decided to make it simpler for users to keep a customized version of my web search macro—updating prior versions meant a fair bit of copy and paste work to get their customizations back. I've now separated their customizations into a separate area, complete with its own help screens, and I won't overwrite these macros.

But that meant I had to be able to display either one (just the user) or two (built in and user) help windows, and I wanted them attached to the associated dialog box (at least visually attached). I also wanted this to work on any display or resolution, so the boxes are all scaled and placed based on screen size.

Here's the final result with one help window:

And with two help windows:

I've attached a demo version of the help display portion of the macro, so anyone can play around with it if they like. After installing and activating, run the macro named zm-Display Help Pages to see it in action. Change instanceUseMode from BOTH to USER to see two boxes versus one box.

It turned out to be quite complicated, but (as always) I learned a ton about Keyboard Maestro in the process (and some about AppleScript, and a lot about instance variables versus AppleScript versus ansynchronous mode). The final result works as well as I think I can make it work, given the constraints.

Window Grouping Demo Macros.kmmacros (49.3 KB)

Thanks, Chris!
-rob.

2 Likes

Very nice! Glad you got a finished, working product, and glad I was able to help (even though I'm certain you would have figured it out without me :grin:).

Just to circle back on this, as with many things I do…I wound up throwing away 95% of the work I'd done, because I wasn't happy with the way it was working. Instead, I tackled another project I'd been meaning to figure out for a while: How to use the HTML Input Form just for display, not for input.

Net net, I'm still using your AppleScript to position the input window (still can't figure out how to make it active, though, but that's a minor inconvenience), but my help window is now just a single pane of HTML and CSS that I build on the fly.

By doing this, I can also make it much easier to use—it's one window that integrates both help sources, and the scrolling table beats two long text windows any day:

So much better than what I had—none of which was your fault, just me going about things in the wrong way. The key to happiness was learning about this...

document.write(window.KeyboardMaestro.GetVariable('KMvar'));

Which I discovered in this forum thread. Instead of just dumbly showing two text boxes, I build a set of HTML and CSS variables (to keep the editing easier), mash them all together, then display the result:

The "For Each" and "Switch" variables do the work of creating each row in the table, and handling the two help data sources; everything else is just static text.

If anyone else is looking for more control over text in windows, creating a set of HTML+CSS variables and then displaying them via a Custom HTML Prompt provides a lot more control over both the display of the content and the appearance of the window.

-rob.

3 Likes

That looks great!

Are you referring to making the custom HTML prompt active?

I'll be the first to admit that I know next to nothing about HTML and CSS. I would love to learn but for the tie being I'm focusing on AppleScript.

-Chris

No, it's the opposite issue, i.e. the same one I had before: Once I put the Custom HTML prompt onscreen, the input dialog no longer has focus, even though it comes onscreen after the custom prompt—due, again I think, to the async setting required for the Custom HTML prompt to enable the input dialog to appear at all.

-rob.

Try running this AppleScript after your custom HTML action...

tell application "System Events"
	tell application process "Keyboard Maestro Engine" to tell window "Keyboard Maestro User Input"
		perform action "AXRaise"
	end tell
end tell

It will bring the UIP to the front.

2 Likes

Doh! It was even easier than that—I just added the AXRaise action as the final step in your positioning macro; works perfectly!

thanks;
-rob.

3 Likes

Even better! I thought about that but didn't have a chance to look at the original script I wrote, and figured with your experience level you would make it work one way or another :sweat_smile:

I just want to say that although this level of macro/Applescript/CSS work is way beyond my level, just reading through your conversation is a delight -- and has prompted me to download the macro! Rob, I've been a Many Tricks fan for I don't even know how long, the oldest Witch purchase I have a record of is 2008 but I'm sure that wasn't my first, and I used Butler until I, er, replaced it with KM; and Chris, I really appreciate your comments and helpfulness in this forum. Thanks to you both!

2 Likes

Thanks for the kind words, much appreciated! (I still use Butler for a couple tasks that it does really well, but all the automation has moved to KM.)

And yes, Chris' help has been invaluable!

-rob.

Thank you both for your kind words! I don’t have near the experience others do but I’m always glad to help where I can.