Reposition a Keyboard Maestro Palette

Move a Keyboard Maestro palette.zip (6.6 KB)

Custom Keyboard Maestro Plug-in

NAME

  • Move a named Keyboard Maestro palette

VERSION

  • 0.2
    • Updated to bring the moved palette to the front, so that it acts as the anchor if the move is followed by its companion plugin Tile all open KM palettes

SYNOPSIS

  • Changes the X and or Y position of the named palette
  • (X, Y) values are (across, down) in pixels

REQUIREMENTS

  • Yosemite
    • The core script movePalette.sh is mainly written in Javascript for Applications

OPTIONS

  • Name of palette
    • The global palette can be referred to as Global or Keyboard Maestro
    • Group and other palettes should be specifed exactly as spelled (case-sensitive) in their title bars
  • New X position:
    • Integer: pixels across (left edge of palette)
    • (or left blank to change only vertical position)
  • New Y position
    • Integer: pixels down (top edge of palette)
    • (or left blank to change only horizontal position)

INSTALLATION

  • Drag the .zip file onto the Keyboard Maestro icon in the OS X toolbar.
  • (if updating a previous version of the action, first manually remove the previous copy from the custom actions folder)
    • ~/Library/Application Support/Keyboard Maestro/Keyboard Maestro Actions

CONTACT


osascript -l JavaScript <<JXA_END 2>/dev/null
(function (strPaletteName, X, Y) {
	var dctReturn = {};
	if (!strPaletteName) {
		dctReturn.message = "Palette name not specified";
	} else {
		if (strPaletteName.toLowerCase() === 'global') strPaletteName =
			'Keyboard Maestro';
		var appSE = Application('System Events'),
			lstProc = appSE.applicationProcesses.where({
				name: 'Keyboard Maestro Engine'
			}),
			procKMEngine = lstProc.length ? lstProc[0] : null,
			oWin = procKMEngine.windows.byName(strPaletteName),
			lstXY, lstDXY;

		try {
			lstXY = oWin.position();
			oWin.position = [X || lstXY[0], Y || lstXY[1]];
			appSE.perform(oWin.actions['AXRaise']);
			
			lstDXY = oWin.position();
			dctReturn.message = (strPaletteName === 'Keyboard Maestro' ?
					'Global' : strPaletteName) +
				' palette moved to ' + lstDXY;
			dctReturn.x = lstDXY[0];
			dctReturn.y = lstDXY[1];
		} catch (e) {
			dctReturn.message = 'Palette not open, or not found as spelled: ' +
				strPaletteName;
		}
	}
	return JSON.stringify(dctReturn, null, 2);
})(
	"$KMPARAM_Palette_name",
	"$KMPARAM_New_X_position",
	"$KMPARAM_New_Y_position"
)
JXA_END
6 Likes

Awesome, thanks. Can’t wait to try it out. Mind if I share it on my http://macautomationtips.com blogsite?

Of course – feel free

UPDATE

See also:

I’ve just updated this action (in the first post of this thread) See the installation notes for the details of how to install a new version.

( Essentially, it now brings the moved window to the foreground, which enables it to act as the anchor palette for a related tiling action )

@ComplexPoint, any chance you could update this plugin again to make it work with KM8.2.4 and Mojave? I drag the .zip file onto the KM menu icon and nothing happens. Thanks

It seems to be working here – I attach a fresh zip:

Move a Keyboard Maestro palette.zip (6.6 KB)

At what point does it seem to be failing ?

Once you have installed it by dropping it on the KM icon, it should show up in the 3rd party plugins folder of the action-adding dialog:

33

and become available for inclusion in your macros.

Thanks. I see it now. I didn’t know where it was suppose to go, and I couldn’t tell if it was installed. All is good now. It looks like it is exactly what I need. I will give it a test run. Thanks for creating it.

1 Like

Got it working. Thank you, thank you, thank you. It does exactly what I need.

1 Like

Is there any way to move a palette to a second screen? I use a secondary screen to the right of my main screen and would ideally like to have a Tools palette at the left edge of that second screen. Thanx!

@ComplexPoint how would I determine palette name? I've tried putting in whatever appears in the top bar (in my case, it's "Macros", as it was created via Show Palette of Macros), unfortunately that doesn't work.

Try running this AppleScript:

tell application "System Events"
	tell application process "Keyboard Maestro Engine"
		tell (first window whose subrole is "AXSystemDialog")
			set palName to its name
		end tell
	end tell
end tell

palName

It works on regular palettes, I just haven't tried it with conflict palettes.

1 Like

Thanks. This outputs "Macros", in line with what appears in the Title palette field. Unfortunately, the plugin won't reposition the palette using that name as the handle.

That's because the Show Palette of Macros action doesn’t produce a specific name like most palettes do.

I'm not familiar with the plugin from this post, because I usually use regular AppleScript to do any palette positioning I need.

For example: these two macros in conjunction will identify the conflict-style palette and position it to 20, 20 (you can change those coordinates, they're just there for an example). You simply place the subroutine macro before the Show Palette of Macros action in your calling macro, and have it run asynchronously. (The calling macro below is just my way of testing, you don't need it, I just included it in case you wanted to test it before trying it in your personal macros)

If none of that makes sense just let me know and I can explain further. And if it does work and you need help customizing it just let me know and I can help with that too. Sorry I don't know about the original plugin btw. :grin:

-Chris

show palette of macros (calling macro).kmmacros (2.0 KB)

show palette of macros (calling macro) screenshot (click to expand/collapse)

show palette of macros (retrieve name and position subroutine).kmmacros (3.2 KB)

show palette of macros (retrieve name and position subroutine) screenshot (click to expand/collapse)

2 Likes

Thanks a lot, Chris!
Gave it a spin and it works indeed, though there's a noticeable lag. I've tried changing the delay value, but it didn't help.
On the bright side, it would only be visible the first time after each display change, so basically whenever I'm going from internal to external display and vice versa. Other than that it would just stay in place.

I think I could also get it set up during each Display Changed (or whatever it was) event.

EDIT: By the way, do you have any manual at hand where I would work out how to set the AppleScript to center the window regardless of the display resolution and/or palette's dimensions?

Always glad to help! :grin:

Not sure why there would be a delay... on my end it worked almost instantly.

That's really complicated with just regular AppleScript (at least really complicated to me haha), but there is a way to do it via a combination of KM actions and AppleScript.

I'm working right now and don't have a lot of time to work anything up.....but I will share a macro and script I use to center a Typinator window in the front screen. You might be able to figure it out by looking at the macro/AppleScript.

Take a look at the variables set in the first group of actions, (the local_xRes and local_yRes variables), and then look at the AppleScript to see how those variables interact with the AppleScript variables for the Typinator window.

If it's confusing, just let me know and when I get some free time I'll try and work up a template for you.

03)Typinator- Create autocorrection expansion (English) [for sharing].kmmacros (31 KB)

Macro screenshot (click to expand/collapse)

1 Like

Thanks again :slight_smile: I appreciated you went as far as annotating the macro :slight_smile:

What I meant by the delay is an approximately 100-300 ms delay, which is noticeable to me. Though like I said it's a one-time event assuming the window stays put in the center after the initial repositioning.

Ha I just didn't want to confuse you (or even worse have you execute a macro that wasn’t designed for your computer :laughing:)

Anyway I ended up finishing work early and tinkered around a bit...

Try this subroutine macro... it basically uses Keyboard Maestro to get the front screen info, and passes that to variables that AppleScript uses to run calculations and position the palette front and center.

04)show palette of macros (retrieve name and position subroutine).kmmacros (6.0 KB)

Macro screenshot (click to expand/collapse)

1 Like

OK, I won't pretend to understand the code involved, but it works great, even if the palette is not triggered (the initial repositioning is visible for a split second, then it renders as usual). I will be able to use that with each display change, awesome! Thanks a lot, Chris :slight_smile:

EDIT: Just played with it for a bit and it seems the macro gets in a loop until the palette is triggered (shown), so it works a bit differently than I initially thought. With the current setup if I use it as a subroutine (I mean via "Execute Macro" in a larger setting) it makes the encompassing macro freeze. Do you know how to mitigate that? I've tried looking for async run options, but it's not there for this type of action/macro.

To get a better idea of what each section of code does check out the notes in the AppleScript below.

AppleScript (click to expand/collapse)
set kmInst to system attribute "KMINSTANCE"
tell application "Keyboard Maestro Engine"
	set xRes to getvariable "local_xRes" instance kmInst --retrieves the local_xRes variable from KM
	set yRes to getvariable "local_yRes" instance kmInst --retrieves the local_yRes variable from KM
end tell


tell application "System Events" to tell application process "Keyboard Maestro Engine"
	
	--repeatedly delays 1/10 of a second until the conflict palette appears
	--the subrole is the kind of "window" that the palette is
	repeat until (first window whose subrole is "AXSystemDialog") exists
		delay 0.1
	end repeat
	
	--sets the name of the palette of the AppleScript variable "palName"
	tell (first window whose subrole is "AXSystemDialog")
		set palName to its name
	end tell
	
	--controls the palette
	tell window palName
		
		--sets two variables to the palettes size
		--palXsize is it's width
		--palYsize is it's height
		set {palXsize, palYsize} to its size
		
		--does some math to position the palette in the center of the front screen
		--xRes - palXsize takes the screens width, subtracts the palette's width, and then divides that by 2
		--yRes - palYsize takes the screen's height, subtracts the palette's height, and then divides that by 2
		--that basically gives it the coordinates to position the palette so it is centered according to it's size and the screen resolution
		set its position to {(xRes - palXsize) / 2, (yRes - palYsize) / 2}

	end tell	
end tell

I don't quite follow what the issue is you’re referring to... but I haven't had my afternoon coffee yet :sweat_smile:
Could you elaborate please?

1 Like

Thanks for the annotations. I'll need to abandon tweaking it for now due to a massive backlog of unfinished tasks, but thanks anyway for everything so far!
Hopefully I can sit down to it again once the time allows (or my AppleScript/Keyboard Maestro skills improve :)))

1 Like