10

There are techniques for Linux and Windows, but is there a way to count mouse and keyboard events in Mac OS X? I'm interested in doing statistical analysis of my daily activity.

5 Answers 5

15

Based on the inspiration provided by MrDaniel, I decided to program a simple little counter.

Screenshot of the main window

The source code for this, minus the UI defined as xib; uses Foundation and AppKit frameworks (full sources and Xcode project on GitHub):

DBAppDelegate.h

//
//  DBAppDelegate.h
//  CocoaActivityCounter
//
//  Created by Daniel Beck on 29.07.2012.
//  Copyright (c) 2012 Daniel Beck. All rights reserved.
//

#import <Cocoa/Cocoa.h>

static id monitorLeftMouseDown;
static id monitorRightMouseDown;
static id monitorKeyDown;

@interface DBAppDelegate : NSObject <NSApplicationDelegate>

@property (assign) IBOutlet NSWindow *window;
@property (strong) IBOutlet NSTextView *logView;

@property (weak) IBOutlet NSToolbarItem *toolbarStartButton;
@property (weak) IBOutlet NSToolbarItem *toolbarStopButton;
@property (weak) IBOutlet NSToolbarItem *toolbarClearButton;

@property (weak) IBOutlet NSTextField *keyPressCounterLabel;
@property (weak) IBOutlet NSTextField *leftMouseCounterLabel;
@property (weak) IBOutlet NSTextField *rightMouseCounterLabel;

@property (readwrite) NSDateFormatter *logDateFormatter;

@property (readwrite) NSNumber *keyPressCounter;
@property (readwrite) NSNumber *leftMouseCounter;
@property (readwrite) NSNumber *rightMouseCounter;

@property (readwrite) BOOL loggingEnabled;

- (IBAction)stopButtonPressed:(id)sender;
- (IBAction)startButtonPressed:(id)sender;
- (IBAction)clearButtonPressed:(id)sender;

- (void)logMessageToLogView:(NSString*)message;

- (BOOL)validateToolbarItem:(NSToolbarItem *)theItem;

@end

DBAppDelegate.m

//
//  DBAppDelegate.m
//  CocoaActivityCounter
//
//  Created by Daniel Beck on 29.07.2012.
//  Copyright (c) 2012 Daniel Beck. All rights reserved.
//

#import "DBAppDelegate.h"
#import <AppKit/NSEvent.h>

@implementation DBAppDelegate
@synthesize logView;
@synthesize toolbarStartButton;
@synthesize toolbarStopButton;
@synthesize keyPressCounterLabel;
@synthesize leftMouseCounterLabel;
@synthesize rightMouseCounterLabel;
@synthesize toolbarClearButton;
@synthesize loggingEnabled;

@synthesize keyPressCounter;
@synthesize leftMouseCounter;
@synthesize rightMouseCounter;


- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    self.loggingEnabled = NO;
    self.logDateFormatter = [[NSDateFormatter alloc] init];
    [self.logDateFormatter setTimeStyle:NSDateFormatterMediumStyle];
    self.keyPressCounter = [NSNumber numberWithInt:0];
    self.leftMouseCounter = [NSNumber numberWithInt:0];
    self.rightMouseCounter = [NSNumber numberWithInt:0];
}

- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication {
    return YES;
}

-(void)logMessageToLogView:(NSString*)message {
    [logView setString: [[logView string] stringByAppendingFormat:@"%@: %@\n", [self.logDateFormatter stringFromDate:[NSDate date]],  message]];
}

- (IBAction)stopButtonPressed:(id)sender {
    if (!self.loggingEnabled) {
        return;
    }
    self.loggingEnabled = false;
    [NSEvent removeMonitor:monitorLeftMouseDown];
    [NSEvent removeMonitor:monitorRightMouseDown];
    [NSEvent removeMonitor:monitorKeyDown];
}

- (IBAction)startButtonPressed:(id)sender {

    if (self.loggingEnabled) {
        return;
    }
    self.loggingEnabled = true;
    monitorLeftMouseDown = [NSEvent addGlobalMonitorForEventsMatchingMask:NSLeftMouseDownMask handler:^(NSEvent *evt) {
        [self logMessageToLogView:[NSString stringWithFormat:@"Left mouse down!"]];
        self.leftMouseCounter = [NSNumber numberWithInt:(1 + [self.leftMouseCounter intValue])];
    }];
    monitorRightMouseDown = [NSEvent addGlobalMonitorForEventsMatchingMask:NSRightMouseDownMask handler:^(NSEvent *evt) {
        [self logMessageToLogView:@"Right mouse down!"];
        self.rightMouseCounter = [NSNumber numberWithInt:(1 + [self.rightMouseCounter intValue])];
    }];
    monitorKeyDown = [NSEvent addGlobalMonitorForEventsMatchingMask:NSKeyDownMask handler:^(NSEvent *evt) {
        [self logMessageToLogView:[NSString stringWithFormat:@"Key down: %@ (key code %d)", [evt characters], [evt keyCode]]];
        self.keyPressCounter = [NSNumber numberWithInt:(1 + [self.keyPressCounter intValue])];
    }];
}

- (IBAction)clearButtonPressed:(id)sender {
    self.keyPressCounter = [NSNumber numberWithInt:0];
    self.leftMouseCounter = [NSNumber numberWithInt:0];
    self.rightMouseCounter = [NSNumber numberWithInt:0];
    [self.logView setString:@""];
}

- (BOOL)validateToolbarItem:(NSToolbarItem *)theItem {
    if ([theItem isEqualTo:toolbarStartButton]) {
        return !self.loggingEnabled;
    }
    if ([theItem isEqualTo:toolbarStopButton]) {
        return self.loggingEnabled;
    }
    if ([theItem isEqualTo:toolbarClearButton]) {
        return !self.loggingEnabled;
    }
    return YES;
}

@end

Icons used in the toolbar are from Tango Desktop Project.

6
  • 1
    how to open it in mac osx ?
    – john Smith
    Commented Sep 10, 2014 at 11:31
  • 1
    Works nice for mouse but doesn't capture key presses in 10.10 :(
    – Mecki
    Commented Apr 15, 2015 at 9:38
  • @Mecki I added that to the repo description a while back when I noticed. Unfortunately I have no idea why, possibly related to per-app access restrictions to universal access API, and the binary being unsigned. Or they even killed this off entirely.
    – Daniel Beck
    Commented Apr 15, 2015 at 13:38
  • On Mac OS X 10.9.5, it works well for mouse but doesn't capture key presses too. Have you figured out the reason, Mecki? Thanks.
    – Jiakuan W
    Commented Jul 8, 2015 at 3:00
  • @JiakuanW I got a PR a while back in the GitHub repository that claims to resolve this problem (untested).
    – Daniel Beck
    Commented Jul 8, 2015 at 11:11
5

WhatPulse runs on Windows, OS X, and Linux.

Thanks to Vsauce for pointing this one out.

2

Typingstats displays a total number of keystrokes and various other metrics. It doesn't count pointing device clicks though.

2
  • Have you tried it yourself? Does it change the keyboard layout based upon what you really have or is it always US?
    – Daniel Beck
    Commented Jul 29, 2012 at 20:42
  • App Store app, not available in Canada and possibly elsewhere.
    – Justin
    Commented Apr 13, 2017 at 14:44
1

A click and button press counter program is possible via writing a Cocoa Objective-C program that can receive and count mouse and keyboard click events.

The class to take a look at is NSEvent specifically the addGlobalMonitorForEventsMatchingMask:handler: class method should prove to be very helpful. Since it offers to monitor events such as:

NSLeftMouseUp

NSRightMouseUp

NSOtherMouseUp

NSLeftMouseDown

NSRightMouseDown

NSOtherMouseDown

NSKeyDown

2
  • 3
    Please try to answer in a way that actually brings the user closer to his goal. Just telling him to learn programming doesn't. You could, for example, provide relevant code snippets or function calls, the gist of an actual solution. While still not useful to everyone, it could be used as foundation by others to provide a working solution.
    – Daniel Beck
    Commented Jul 27, 2012 at 18:09
  • Good call Daniel Beck looks like I was taking the wrong approach when suggesting using the "Accessibility Programming Guidelines for Cocoa", after further reading I was pointed to NSEvent class, which seems like it will do the job...
    – MrDaniel
    Commented Jul 27, 2012 at 20:17
0

There is also open source OctoMouse utility, it can be installed on macos with Homebrew brew install octomouse.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .