Why doesn't keyDown get called if I don't use XCode and IB?

275 Views Asked by At

When I subclass a widget and define a keyDown method, and then in InterfaceBuilder assign the class of a widget to be the class I defined with the keyDown method, it seems to work fine.

However, if I do it complete programmatically as illustrated in the simple script below, the keyDown method never gets called. Why is this?

Is there something being set up by XCode that is causing the app to listen for events that gets done behind the scenes? What is it, and how do I do it here? Please point me in the right direction.

I'm gonna go read through the apple docs again and try to figure out if there is an event handler registration going on that XCode is setting for me. However, if you know what it is, please let me know.

Thanks!

framework 'Cocoa'

class MyView < NSView
  def acceptsFirstResponder
    true
  end

  def keyDown(event)
    puts "key down MyView"
  end
end

class MyWindow < NSWindow
  def acceptsFirstResponder
    true
  end

  def keyDown(event)
    puts "key down in MyWin"
  end
end

class MyApp < NSApplication
  def acceptsFirstResponder
    true
  end

  def keyDown(event)
    puts "key down in MyApp"
  end
end

application = MyApp.sharedApplication

# create the window
frame  = [0.0, 0.0, 300, 200]
mask = NSTitledWindowMask | NSClosableWindowMask
window = MyWindow.alloc.initWithContentRect(frame,
          styleMask:mask,
          backing:NSBackingStoreBuffered,
          defer:false)

# assign a content view instance
content_view = MyView.alloc.initWithFrame(frame)
window.contentView = content_view

window.makeFirstResponder(window)

# show the window
window.display
window.makeKeyAndOrderFront(nil)

application.run
3

There are 3 best solutions below

0
On BEST ANSWER

You can do it without an application bundle and plist, but you need to start the app like so:

app = MyApp.sharedApplication
app.activationPolicy = NSApplicationActivationPolicyRegular
app.activateIgnoringOtherApps(true)
app.run
3
On

Your script needs to be bundled as an application, with an Info.plist configuration.

Otherwise, your window will be visible but its containing "application" will never be activated and therefore will never receive keyboard events. You should notice that when you try to activate your window the previous application remains active.

Use the MacRuby template in XCode to create a MacRuby application bundle. XCode 4 requires some additional configuration: Follow these instructions.

Once that's done, you can delete the MainMenu.xib and AppDelegate.rb files, paste your code into rb_main.rb, and it will work as expected.

0
On

An application that is not launched from a bundle (so there is no plist) can set itself to accept key events using

[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
[NSApp activateIgnoringOtherApps:YES];
[NSApp run];