Mouse button and keypress counter for Mac OS X

12,967

Solution 1

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.

Solution 2

WhatPulse runs on Windows, OS X, and Linux.

Thanks to Vsauce for pointing this one out.

Solution 3

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

Solution 4

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

Share:
12,967

Related videos on Youtube

Admin
Author by

Admin

Updated on September 18, 2022

Comments

  • Admin
    Admin over 1 year

    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.

  • HikeMike
    HikeMike almost 12 years
    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.
  • MrDaniel
    MrDaniel almost 12 years
    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...
  • HikeMike
    HikeMike almost 12 years
    Have you tried it yourself? Does it change the keyboard layout based upon what you really have or is it always US?
  • john Smith
    john Smith over 9 years
    how to open it in mac osx ?
  • Francesco De Rosa
    Francesco De Rosa about 9 years
    Works nice for mouse but doesn't capture key presses in 10.10 :(
  • HikeMike
    HikeMike about 9 years
    @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.
  • Jiakuan W
    Jiakuan W almost 9 years
    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.
  • HikeMike
    HikeMike almost 9 years
    @JiakuanW I got a PR a while back in the GitHub repository that claims to resolve this problem (untested).
  • Jiakuan W
    Jiakuan W almost 9 years
    Thanks for your reply. Yes, I checked that code, checkAccessibility() is especially useful. Now my app can capture keyboard events too.
  • Justin
    Justin about 7 years
    App Store app, not available in Canada and possibly elsewhere.