Get the Current Position of a Keyboard Maestro Palette

Probably won’t have time to do it myself in the next week or two,
but do feel free to adjust it and amend the attribution …

Will do. Thanks.

Can’t remember whether the internals are in AS or something like this:

(function () {
    'use strict';

    var se = Application('com.apple.systemevents'),
        procs = se.applicationProcesses.whose({
            name: 'Keyboard Maestro Engine'
        }),
        procKME = procs.length ? procs[0] : undefined,
        ws = procKME ? procKME.windows() : [];

    return ws.map(function (w) {
        return {
            title: w.title(),
            position: w.position(),
            size: w.size()
        }
    });

})();

Yeah, they’re in JXA, and it’s taxing my brain to figure it out. I can do it, but it’ll take time. There’s so many syntactical elements I’m unfamiliar with (they’re not incomprehensible, I just have to think a little…). I’ve seen them all before, but it’s not a native language for me, so…

Couldn’t you just do it in C#? Then I’d understand it in no time!! :stuck_out_tongue:

I’ve got an AS version working, so I may just go with that. We’ll see.

1 Like

( Don’t hesitate to message me for clarification of opacities)

Thanks.

This works for me for now:

tell application "System Events"
	set _kme to first application process where name = "Keyboard Maestro Engine"
	set _palette to first window of _kme where name = "_Sandbox"
	set _size to the size of _palette
	return item 1 of _size
end tell

F’ing AS. Took me forever to find the correct syntax for each property. Yeah, just “tell” me these things - only I have to guess the exact wording because God forbid you understand things like Window.Title, Window.Position and Window.Size. And code completion? Naw, that’s too 1990’s.

And I refuse to think about error checking. Honestly, with no defined mechanism for returning exit statuses to KM, it doesn’t really matter. If it doesn’t work, display the results in a window, and Bob’s your uncle.

Not exactly rock solid, but if I wanted that, I should have stayed with Windows (HA!).

OK, let’s start at the top and work our way down, little by little, a few questions at a time.

Please remember - nothing I say is intended as criticism - this is just how I learn.

  1. I notice that you start the function with some statements, then you have some embedded functions, then some more statements following them. Am I reading that correctly - that JS lets you stick embedded functions anywhere? And assuming I’m correct, why did you structure it that way?

Thanks.

The whole thing is wrapped as an anonymous function (you could also call it function run() { …}) because that avoids pollution of the (overpopulated) global namespace, and, above all, means that your own local variables appear grouped in a separate panel of the the Safari JavaScript debugger.

(Wrapping in an anonymous function to get a local namespace sometimes gets called ‘the module pattern’ in discussions of Javascript)

The name rebindings at the start are a fairly traditional way of ensuring default fall-back values for the arguments of the main function. Have to say that I’m moving away from that now – prefer to avoid mutation and use fresh names, lower down, that take values from the arguments if they are provided.

JavaScript functions are nestable objects like any other object (you can convert them to strings, use them as values in records, etc etc). Given the ‘module pattern’ of an outermost anonymous function, you will tend to see some function definitions at the top of the module. (The compiler lifts them there anyway if you place them further down).

One use of the module pattern in OS X scripting is that the arguments to the outer (anonymous) function can be an interface to some broader context. If you are running the JavaScript in a shell script, they might be bash variables bound to KM variable values.

1 Like

Wanting to play with AppleScript myself I tried to use your code. I get an error when I try...

activate "Mail"
tell application "System Events"
	set _kme to first application process where name = "Keyboard Maestro Engine"
	set _palette to first window of _kme where name = "Email Palette"
	set _size to the size of _palette
	return item 1 of _size
end tell

Error:
System Events got an error: Can’t get window 1 of application process "Keyboard Maestro Engine" whose name = "Email Palette". Invalid index.

I took it that your _Sandbox what the name of your palette, is that correct?

Yes it is.

My guess is your palette hasn't been displayed yet, after activating Mail. Try putting a delay in, although I'm not sure how to do that in AppleScript. You could activate it in KM and use a KM pause, then run your AppleScript, and see if that's what's wrong.

Ultimately you can trigger your macro when Mail becomes active - the palette will have been displayed by then (I think).

Also, have you seen:

If you download the action (you don't need to install it unless you want to), unzip it and look in the script file, it has all sorts of AppleScript window position stuff in it.

Hey Guys,

Here’s how I do diagnostics on those sorts of things.

This script is in document 1 of the Script Editor.app (or Script Debugger).

tell application "System Events"
  tell application process "Keyboard Maestro Engine"
    return properties of windows
  end tell
end tell

Then I switch to the app where the palette appears and run this from a Keyboard Maestro macro:

tell application "Script Editor"
  tell document 1 to execute
  delay 0.25
  activate
end tell

That way I get a properly formatted AppleScript record in an AppleScript editor.

I can write any arbitrary code in my AppleScript editor and execute it remotely, and that comes in handy when I need another application to be frontmost for context.

-Chris

2 Likes

How do I use this? I find installation instructions but no how to use instructions. The Wiki article on Plug In Actions https://wiki.keyboardmaestro.com/manual/Plug_In_Actions doesn't help either. Any other resources to check?

Thanks in advance for any assistance. :smiley:

Hello!

Does anyone already have a KM macro that "memorizes" the position of a given application's KM palettes and can restore them to their memorized position (in case the user has inadvertently moved them)?

In other words, a KM macro that is something like [Desktop Icon Manager] for KM palettes.

Many thanks in advance!

Hey there, recording and then setting palettes positions is very doable with AppleScript. I’m not at my computer right now but when I am I’ll share something with you to get you started.

HI Chris,

Many thanks for your posting.

Finder is one of the apps for which I want to do this, and I think that AppleScript recording is not supported in Finder (could be mistaken!).

Hi Barry, unless I misunderstood you post, this shouldn’t be an issue. Finder does have AppleScript support, but in this case it's irrelevant since what I understand you want to record is a palette's size/position which is part of the Keyboard Maestro Engine app, not Finder.

EDIT: Hey @BF-H, here is a simple macro that uses AppleScript to record the front palette's position, and then compiles the XML to insert a new AppleScript that will position that palette to wherever it was when the macro was triggered. If you're like me, once you have your palettes positioned where you like them, it's unlikely you'll need to change that from time to time. So I have a variety of macros that position my open apps and palettes for me, and this macro can be used to build another macro designed to position your palettes. It is not designed to record a palette's position, and then restore that later on. It's designed to store the position insert that into the macro that is currently being edited.

06)Record Front Palette's Position and Insert Into Macro as Applescript to Restore It (for BF-H).kmmacros (14 KB)

Macro screenshot (click to expand/collapse)

Hi Chris,

Got it, thanks for clarifying!

1 Like

I've been using this for years. I even forgot it was a plugin:

Hi cdthomer,
Many thanks for your helpful posting and regrets for the lengthy delay in replying.

I will check out your macro!

Barry

1 Like

Hi Dan,

Many thanks for your helpful posting and regrets for the lengthy delay in responding.

I will check it out!

Barry

1 Like