Search code examples
pythononclickpyobjc

Listen onclick event in PyObjC


I try to display the current windows for each click on the system.

I do this code :

from AppKit import NSWorkspace

def getwindows():
    activeAppName = NSWorkspace.sharedWorkspace().activeApplication()['NSApplicationName']
    print activeAppName
    return

def main():
    getwindows()

main()

But only the current windows when i setup the script is displayed.

How can i bind this script in a loop with a click event ?

I already try to use Turtle but some errors appended.


Solution

  • Note that the activeApplication method of NSWorkSpace is deprecated. The following can be used to actively probe the running applications for their active status:

    import AppKit
    import time
    rl = AppKit.NSRunLoop.currentRunLoop()
    ws = AppKit.NSWorkspace.sharedWorkspace()
    for i in xrange(10):
      for app in ws.runningApplications():
        if app.isActive():
          print "active app:", app.localizedName()
      date = AppKit.NSDate.date()
      time.sleep(1)
      rl.acceptInputForMode_beforeDate_( AppKit.NSDefaultRunLoopMode, date )
    

    Active means it is the receiving keyboard input. Clicking on an application will cause it to become active. Note that the acceptInputForMode method must be called so that property changes are reflected in the current app. Run this program then click on various other applications -- you should see the active app change.

    A kind of binding can be done through observers:

    import AppKit
    
    ws = AppKit.NSWorkspace.sharedWorkspace()
    appL = ws.runningApplications()
    
    class MyClass( AppKit.NSObject ):
      def observeValueForKeyPath_ofObject_change_context_(self,
              kpath, objid, change, context ):
        print "path change", kpath, change['new'], appL[context].localizedName()
    
    obj = MyClass.new()
    for i in xrange(len(appL)):
      appL[i].addObserver_forKeyPath_options_context_( obj,
                "isActive", AppKit.NSKeyValueObservingOptionNew, i )
    
    date = AppKit.NSDate.date().dateByAddingTimeInterval_( 10 )
    rl = AppKit.NSRunLoop.currentRunLoop()
    rl.acceptInputForMode_beforeDate_( AppKit.NSDefaultRunLoopMode, date )
    
    for app in appL:
      app.removeObserver_forKeyPath_( obj, "isActive" )
    

    Run this program same as the last.

    There are a few other properties of NSRunningApplication that you could probe/observe (such as hidden) but the list is quite short.