How to track the pressing of a key on OSX

Hi. I wanted to make a button with two actions: when it was pressed with the “SHIFT” pressed, and without it.
Here is the code that works on Windows. Please help with the OSX code.

require 'fiddle/import'

module User32
	extend Fiddle::Importer
	dlload 'user32'
	extern 'int GetAsyncKeyState(int)'
end

toolbar = UI::Toolbar.new 'Test'

cmd = UI::Command.new('Shift_test') {
	if (User32::GetAsyncKeyState VK_SHIFT)>0
		puts 'SHIFT pressed'
	else
		puts 'SHIFT Not pressed'
	end
	}

toolbar = toolbar.add_item cmd
toolbar.show

The general approach to detect key presses (or mouse events for that matter) requires creating a Sketchup::Tool instance (irrespective of the operating system you are on).

You will need to define a class that implements the methods onKeyUp and/or onKeyDown of the Sketchup::Tool interface. (The documentation is here: https://ruby.sketchup.com/Sketchup/Tool.html.)

class MyCustomTool
  def initialize
    # Custom initialization (if needed).
  end
  
  def activate
    puts "MyCustomTool is now active!"
  end
  
  def onKeyDown(key, repeat, flags, view)
    puts "Pressed SHIFT" if key == VK_SHIFT
  end
  
  def onKeyUp(key, repeat, flags, view)
    puts "Released SHIFT" if key == VK_SHIFT
  end
  
  def deactivate(view)
    view.invalidate
  end
end

Then you need to create an instance of this class and add it to the Sketchup::Tools stack like so:

custom_tool = MyCustomTool.new
Sketchup.active_model.tools.push_tool(custom_tool)

Finally, just add these two lines inside your UI::Command block (while removing your current logic) and test the code by invoking your tool from the menu bar. The two messages should show up in the Ruby Console.

True, but this will not work for this special case. The reason is that the instancing and activation of the tool will begin intercepting key presses after the user has clicked on the toolbar button.

It also has the disadvantage that what the user has activated for a tool will be changed. Yes, the new tool can be popped off the toolstack, but it is likely the previous tool would be reset.


The answer is not that simple with regard to the Mac edition of SketchUp. There are various explanations on StackOverflow with regard to reading the keyboard modifiers without implementing an asynchronous responder (event handler). But this would require knowing what frameworks that SketchUp’s Mac edition uses. Carbon? Cocoa Quartz? AppKit? Foundation?, etc.

Oh, right. Now I understand the question… It feels very strange that one would want such behavior. Why not create two separate toolbar buttons then? This reminds me of how one can trigger different actions in macOS when pressing Alt (also called Option key) and then clicking on a button, which is incredibly unintuitive. I don’t even use such “features” as a result.

I wanted to create an additional function, not overload the user interface. For example, rotating a component by 90 degrees or 270. It seems Mac is losing out to Microsoft in this feature. I will be forced to define the platform and assign different functions.

Well, this is not the first time a coder has wanted more than one action per button. For example, in the past, it was desired to have a settings dialog popup when a tool’s toolbar button was double clicked. I think it was even formally requested.

But I think the main argument against was as you say … intuition, discoverability.

I do know (because I participated in the discussion) that a double-click option is easily doable by using a state variable to check if the button has been clicked twice. The trick is to delay action for a fraction of a second, giving enough time for a second click and so a second firing of the command’s proc.
Jim Foltz’ old Ruby toolbar plugin did this to allow setting the path to a ruby file I think, if memory serves. (He has long since left the SketchUp realm, so I don’t know if the plugin is available anymore. Likely not.)

I would rather we get a context click (right click) proc option for buttons.
But this also likely violates the K.I.S.S. principle (or the Principal of Least Surprise.)

Yeah, so it has always been, 1 button, 1 proc.

2 Likes

I still use Jim’s Ruby Toolbar. :slight_smile:

So do I, with tweaks by me and @driven (who has seemingly also left the forum). I never noticed the double-click though. I’ll have to try it once I am again able to work at the computer.

Oh, I would like to know about those tweaks.
when better

I agree not overloading the UI is nice.
I am thinking about a command to move windows around taking care of the openings. So I was hoping I could use the arrow keys to indicate one of the 4 directions. I would not like to add 4 other buttons to my toolbar.
Of course there would be instructions in the status bar.
Some native commands do that when usibg keys; ctrl, opt, cmd …
but… maybe those cmds are not pure ruby coded.