Skip to content

Instantly share code, notes, and snippets.

@dariusf
Created August 2, 2023 08:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dariusf/21c8952258ce8edb26963610c3b64dda to your computer and use it in GitHub Desktop.
Save dariusf/21c8952258ce8edb26963610c3b64dda to your computer and use it in GitHub Desktop.
Zoom chat notification hacks (macOS)

Updated Dec 2021.

Zoom doesn't have chat notifications. This is a problem when invigilating online exams.

If you're using macOS, notifications can be hacked on by using a bunch of scripts to tell when something on the screen changes.

Rectangles

The first piece is how to capture a small region of the screen. Interestingly, this is built into the screencapture command, which takes the coordinates and dimensions of a rectangular area to capture.

We could fudge around until we get the right coordinates, but there's a better way in AppKit. This tiny Objective-C program (from here) prints the current coordinates of the mouse (with the origin at the top-left).

#import <AppKit/AppKit.h>

int main (int argc, const char * argv[]) {
   NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

   NSRect e = [[NSScreen mainScreen] frame];
   int H = e.size.height;

   NSPoint mouseLoc = [NSEvent mouseLocation];
   // origin is now at the top left
   NSString* locString = [NSString stringWithFormat:@"%d\n%d", (int) mouseLoc.x, H - (int) mouseLoc.y];
   printf("%s\n", [locString UTF8String]);

   [pool drain];
   return 0;
}
gcc -o MouseLocation MouseLocation.m -framework AppKit

Notifications

We also need a way to show a notification. A simple way is to use iTerm-specific escape codes; we simply surround the text we want to show with them.

notify() {
  echo $'\e]9;'$1$'\007'
}

We could also use AppleScript, which allows us to provide a title.

notify() {
  osascript -e "display notification \"$2\" with title \"$1\""
}

Glue

Everything is glued together with this terrible script:

#!/usr/bin/env bash

tlx=$1
tly=$2
brx=$3
bry=$4

capture() {
  screencapture -x -R $tlx,$tly,$(($brx-$tlx)),$(($bry-$tly)) /tmp/screen.png
}

set -x

capture
res="$(md5 /tmp/screen.png)"
prev="$res"

while true; do
  sleep 5
  capture
  res="$(md5 /tmp/screen.png)"
  if [ "$res" != "$prev" ]; then
    notify "Something changed!"
    exit 0
  fi
  prev="$res"
done

The arguments are the coordinates we get from running ./MouseLocation twice, with the mouse cursor at the top-left and bottom-right of the rectangle we want to watch.

One thing that appears silly to do (and is very much in the spirit of this post) is the use of MD5 for comparing images. We want to be notified if anything changes, and for this use case a more sophisticated image diff like ImageMagick's compare wouldn't add much. screencapture is thankfully deterministic as well, so this all works. For something more resilient to small variations, you might want to use one of the metrics offered by ImageMagick.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment