VMware fusion and applescript with global hotkeys - macos

I need a terminal to a Linux vm inside my osx installation. Its a dropdown terminal and in the vm I can use F12 as a global hotkey to toggle show/hide.
The name of the dropdown terminal is yakuake, I know there is a dropdown terminal that works with osx to, but for various reasons, I need both a Linux terminal and easy access to it.
There is several things that makes this difficult.
VMware fusion doesnt have any good applescript support
I need to be able to run several vm's on the same time.
Speed
Hiding the application.
I am using iKey to get a global hotkey on my mac binded to a little oneliner:
/Library/Application\ Support/VMware\ Fusion/vmrun -T fusion -gu username -gp password runScriptInGuest "/Users/username/Documents/Virtual Machines.localized/Ubuntu.vmwarevm/Ubuntu.vmx" -interactive "/bin/bash" "/home/username/bin/toggle_yakuake"
The /home/username/bin/toggle_yakuake script is just a:
/usr/bin/xdotool key Control+Shift+Y # Which is what I bound to yakuake
This works, except its taking around 1-2 seconds, and yakuake will show up below every other windows.
Therefor I will use logic to just do this if yakuake isnt running, and then I can just hide/show it in osx to toggle it instantly.
However, I am able to show yakuake using a simple "tell application "Yakuake - Ubuntu" to activate. I am not able to hide it without hiding every other application belonging to the same vm.
It seems that every application spawned by vmware is tied together a little to tight.
Even if I find the pid of yakuake on my osx installastion, and uses it like:
tell application "System Events"
set yakuakeproc to every process whose unix id is 58518
repeat with proc in yakuakeproc
set the frontmost of proc to true
end repeat
end tell
It will hide every application belonging to that vm.
I have tried to figure out a solution for this for days now. Is there anyone that have any tips or anything? How can I get applescript to hide one specific application which is inside my vm?

The way you're starting yakukake is unnecessarily complex. You should be able to simply run the VMware proxy application, rather than using a shell script; i.e. your tell application "Yakukake - Ubuntu" to activate.
Then your only real problem is how to show and hide an application from a script. I think it is possible to do this with System Events, but it's easier to do it with my tool appswitch:
I don't have GUI Linux installed in VMware Fusion but here's an example with Windows.
To view information about a process:
% appswitch -La Notepad
PSN PID TYPE CREA NAME PATH (bundle identifier)
15994688.0 24758 APPL ???? Notepad /Users/nicholas/Library/Application Support/VMware Fusion/Virtual Machines/Boot Camp/Boot Camp.vmwarevm/Applications/Notepad — Windows 7.app (com.vmware.proxyApp.564dbc100b31a4b5-4f8d8088bf0c3705.2009924420)
To hide it:
% appswitch -ha Notepad
To show it:
% appswitch -a Notepad
That's it.

Related

Run a Applescript on a locked Mac by keypress or alternative options

I have an Applescript written for a specific purpose that launches an application and performs a couple of tasks. I would like to be able to run this script by pressing a key on my keyboard, however, while the Mac is locked. (Note: Mac is only locked, not "asleep")
I'm open to alternative options, if such (or more efficient) options exist.
The above scenario is my "ideal" configuration, the only thing I don't have flexibility on, is that the mac must stay locked for this process.
I have full administrative access to the Mac.
I would suggest you use ssh to "get into" your Mac while the screen is locked and then run your script from the shell. You would probably use osascript for that if it is Applescript, by the way.
In order to do this, you will need to ensure the sshd is running on your Mac by going to the Apple Menu, then System Preferences then Sharing and check the box beside Remote Login.
In order to ssh into your Mac, you could use another Mac, or a PC or the free iPhone/iPad app called Terminus which is brilliant for remotely controlling machines via ssh.
Rather than have to run a command when you log in, a technique which I often use is to have a user who can only execute a specific function and the very act of logging in does that function and then logs the user out again. So, for example, if I wanted a login that can reboot a machine, I would create a new user called reboot and instead of that user having bash in /etc/passwd as his shell, he would have /sbin/reboot as his shell. Just a thought - YMMV.
I've tried this same thing and when the Mac becomes locked, normal processing will not occur but slow to a crawl, so I had to turn my screens off instead of locking my Mac. There is no way around it.

Mac OS X: interacting with an application programmatically

I am working on a project where I need to call methods on an existing application (my own) and use some of its functionality. For e.g. my application ThunderBolt runs on Mac OS X 10.10. It also provides a dictionary of events that can be called externally through Apple Script or some other way that I don't know yet.
My question is what are the different (and better) ways of interacting with an application programmatically on Mac OSX? If I use something like the following code in Apple Script Editor:
tell application "ThunderBolt"
set open_file to (choose file with prompt "Choose the file you wish to parse")
set theContents to read open_file as data
set retPict to (image convert theContents)
end tell
then it is going to launch ThunderBolt with a splash screen and then call "image convert". This can be done via NSAppleScript but still it would launch the application and call methods/events on it.
Is it possible to somehow create an instance of (or get a pointer to) one of the class inside the application and use that? Something similar to COM or automation on a Windows system?
If you're working on OS X 10.10, you might consider taking a look at JavaScript for Automation (JXA).
With it you can apparently build methods into your app that can be invoked from client scripts written in JS (although I'm not yet familiar with the particulars of how to handle implementation of such a thing on the app side). But many of the apps that ship as part of OS X Yosemite have such APIs built in (e.g. iTunes and Finder).
Here's a great tutorial on JXA written by Alex Guyot: http://www.macstories.net/tutorials/getting-started-with-javascript-for-automation-on-yosemite/
The JXA-Cookbook repo also appears to be a nice resource: https://github.com/dtinth/JXA-Cookbook/wiki
Here's a brief example - this script makes iTunes go back one track. Try it while iTunes is playing (by putting the text into Script Editor, with the language option set to JavaScript, and hitting the Run button):
iTunes = Application('iTunes')
state = iTunes.playerState()
// Console msgs show up in the Messages tab of the bottom view:
console.log("playerState: " + state)
iTunes.backTrack()
Alternatively, you can place the code into a .js file and run it on the command line:
$ osascript itunes-backTrack.js
playerState: playing
The way you specify the 'tell application' is the best way, in my opinion.
What do you do with your app that needs to be called? Maybe some of the functionalities can be done with Applescript? It would simplify things a lot.

Is it possible to create a Mac OS X gui app which is not a bundle?

I want to make an executable file (not the Mac .app bundle) which when run with a specific option (e.g. -gui) will pop up the gui.
For example, say I'm writing wget. I could do: wget www.google.com and that would print the result to the console, but if I instead do: wget -gui www.google.com that would pop up a gui window with the render of the html.
Is this possible in OS X (it is in windows)?
Note: I mean that the gui code is contained in the executable, calling open on another app is not acceptable.
Simple: Yes
Your second question will be how I guess.
Sometimes people ask me for applications that when launched by the Finder they should behave normal but when started by another process or terminal it should behave different. So, just like firefox, you can start the application the normal way or you can start it with special option.
Another way is creating agents. They are applications but don't appear in the dock and are designed to show interface elements when needed.
If you don't want to use a bundle per se you can just create a (cocoa) command line utility that loads an NSApplication when needed (depending on the command line options).

Is there a way to capture console controls (keyboard/mouse/remote) in OSX so they can be replicated on another machine?

I need to mirror GUI console activity happening on one Macbook so that it is duplicated on a second identical Macbook.
The idea is to control an application that will run on two Macbooks simultaneously. The application is sort of a presentation with two variations in content, but identical controls. Think of it as two versions of PowerPoint presentation with some slides that are different.
I'm thinking that it may be possible to capture the keypresses and mouse events on one Mac, then use RFB protocol to send these across the network to the other Mac. I'm looking at rfbproxy and rfbplaymacro, but these are somewhat inelegant hacks, and any solution built on these will also be a bit of a hack. And of course, I'd prefer to avoid a solution that requires me to compile and perhaps debug software that hasn't been touched in half a decade. :-)
I could conceivably use Cliclick or xdotool (from MacPorts) to initiate console events on the "slave" Mac. But then I don't know what I'd use to capture the events on the "master". Or would an xdotool-based solution require that both Macs be slaves, and then use some other device as a master?
Input devices could be a presentation mouse, an Apple remote, or in a pinch, the keyboard of on of the Macbooks or even a third device.
Can you suggest tools? Or is there another strategy I haven't thought of?
If the computers are in the same room, a single Apple Remote can control both Macs as long as the remote is not paired to either one. I'm assuming you need a solution that will work over any arbitrary distance, though.
Have you considered AppleScript? It's pretty good at sending keystrokes to ssh-accessible Macs. The receiving application doesn't even need to be aware of AppleScript (i.e. scriptable). You'll just have to be sure GUI scripting is enabled on the targets by checking the Enable access for assistive devices option in the Universal Access system prefs panel.
Here's an example of a shell command that will send a keystroke to the frontmost app via applescript:
osascript -e "tell application \"System Events\" to keystroke \"a\""
If you set up key-based ssh auth between the master and slaves you can simply tack ssh onto the front of this command:
ssh slave osascript -e "tell application \"System Events\" to keystroke \"a\""
For elegance, you could wrap any number of desired keystrokes into a menu-based bash script and run it from a third computer.
I have tried to synchronise systems like this that are NOT Macs a few years ago using rfbproxy and rfbplaymacro which you already know about. The systems were both X terminals running at the same resolution. We still had problems because of different font size settings putting application controls in different places, but the basic VNCiness of the solution seemed to work just fine.
That said, if you want to write a stand-alone application to send stuff using osascript or cliclick or xdotool, and you have a wii, you might get some joy from DarwiinRemote.
Kindof convoluted, but you could use clusterSSH for OSX to start shell sessions from a third machines master window, and then send commands to the two slaves. This could be paired with a screen control utility similar to the ones you list above, another of which is pymaCursor.
If everything could instead be recorded in advance, you could try good ol' applescript/automator recording, or a newer project like sikuli - http://sikuli.org/

Better terminal in Mac OS X -- reversing the control and command key-mappings

I'm trying to have the same KDE Konsole experience within Mac OS X.
Here's my (overly complicated?) setup:
I have Control and Command swapped at the System Preferences level. (Can't live without this)
Parallels lets you, at the Parallels application level, also reverse Control and Command. So I can undo the System Preferences setting (and get the setup I want within virtual Linux)
I want this same per-application-opt-out for the Mac OS X Terminal app. Is it possible?
The solution you're looking for is KeyRemap4MacBook. There is a Tiger, Leopard, Snow Leopard, and Lion version.
Once installed, goto System Preferences -> KeyRemap4MacBook
Then select the following options:
Change Command_L Key (Left Command)
---> Command_L to Control_L (except Terminal, Virtual Machine, RDC)
Change Control_L Key (Left Control)
---> Control_L to Command_L (except Terminal, Virtual Machine, RDC)
You can repeat this for Command_R (Right Command) and Control_R (Right Control) also if you desire. Tested and working on my Macbook.
You can simply ssh into the Linux/Unix system and run X11 programs direct to your Mac screen: ssh -X user#host_or_ipaddress, login, and just run the X11 programs you want (e.g. emacs&) and the X11 apps will appear on the Mac display.
Pros:
X11 windows work just like any other window, including Exposé goodness, etc...
No need to work only inside the Parallels console window
Same solution works with any Linux/Unix system, remote or virtual
ssh connection is secure even over the internet
Tech info:
"ssh -X" turns on X11 forwarding for the ssh connection, i.e. the X11 display connection is tunneled through ssh securely
"ssh -X" also handles X11 authentication tunneling
X11.app is automagically started on OSX by launchd when needed
X11 can connect to displays over the network, which is one of the few cool things about it ;-)
There is very good and key-mapping flexible terminal: iTerm2
My favorite set: iTerm + zsh + oh-my-zsh
The 2016 solution is to use Karabiner open-source program which allows you to remap modifier and other keys with very fine granularity, for example
Remap only the left ⌘ Cmd or Option key.
Remap a key only for specific applications, e.g. only inside Terminal, Emacs, or virtual machine.
For example, here's how to remap left ⌘ Cmd key to act as Ctrl only inside Terminal (and leave the right one unaffected so that you could still use e.g. ⌘ Cmd + Tab to switch between apps):
You can customize the command keys used for an individual application in System Preferences > Keyboard & Mouse > Keyboard Shortcuts. I think (if I understand correctly what you're trying to do) that this might allow you to accomplish your goal. You could remap all of Terminal's command keys to use control instead of command, to get them out of your way... but then you might need to do a lot of customization on the machines you ssh into, so that they use Command instead of control
It seems that you're going to have to do an ENORMOUS amount of work just to allow you to use your pinky instead of your thumb for the modifier key.
Another possibility: user preferences can be manipulated by the "defaults" command. I haven't been able to find a way to use this to control they modifier key mappings, but it should logically be possible (if you're willing to do a lot of digging). If so, then you could write short scripts to switch back and forth between Mac default and your swapped mode. Trigger the scripts with Quicksilver, and whenever you use Terminal you can call one script, and whenever you leave it you can call another. Again, a big pain to achieve what you want, but it might be possible.
I don't think there's a clean and simple solution.
I've seen third-party programs that give more control over manipulating modifier keys, if you're willing to install them (probably kernel extensions). They might be able to do what you want, but I don't recall the names. If you google for programs to fix emacs and vi keys you might find them.
Good luck.
I had exactly the same problem as you. I've remapped Command to CAPS Lock, and Control to Command, but as a frequent Linux user I want both setups to be as similar as possible. This is how I solved it:
Install Keyboard Maestro (not free, but totally worth it), and set it up to run at login.
Inside KM, define macros to send CMD+{key} to CTRL+{key} inside Terminal.
If you want to remap a lot of keys this is a lot of work. But I've already done it myself, you can just download this file kmmacros. Double-clicking is enough to install it. A couple of caveats:
You need to set Terminal to use option as a meta key (Terminal > Preferences > Keyboard).
The bindings are only for emacs-mode. This cheat sheet should be helpful.
Most default shortcuts don't work anymore (CMD-N, CMD-C, ...), and the menu in Terminal does not reflect this. For some conflicts (New Window, Close Window), I've taken the ones from Gnome.

Resources