Cygwin: Create a Windows notification and focus a program when the notification is clicked

Viewed 126

I want a cygwin shell script to create a Windows notification (one of those events you see in the lower right-hand corner). When you click on the notification, I want it to bring another application into focus.

Here's how I'll use this: from the command line, I run tests. When they finish, I want to be notified with the notification. If I click on that notification, I want cygwin to go back into focus so I can decide what to do next.

1 Answers

Okay this was a huge pain to figure out, and even still, this solution is far from ideal -- but it does work so it's worth writing down.

It's not hard to create a notification. It's not hard to focus an application. But it is hard to create a notification that focuses a window when clicked.

Here is a script:

set -ex

notification_exit_code=0 # default value, exited successfully
# create a notification that says "Build Done". When notifu64 exits, it's exit code tells why it exited (see below)
notifu64.exe /i 'C:\\cygwin64\\Cygwin-Terminal.ico' /t info /p "Build Done" /m "Build Done" || notification_exit_code=$?

# these are some of the ways the notification could have exited
user_clicked_on_notification=3
notification_timeout=4
user_clicked_on_notification_icon=7
if [[ "$notification_exit_code" -eq "$user_clicked_on_notification" ]] || [[ "$notification_exit_code" -eq "$user_clicked_on_notification_icon" ]]
then
  # The order of the steps is very important or else the window will remain in the background. I figured out these steps from here: https://stackoverflow.com/a/59819671/61624
  nircmd win activate process mintty.exe
  # I'm not sure why, but "activate" resizes the window. This puts it back the way it always is on my computer: maximized
  nircmd win max process mintty.exe
  nircmd win settopmost process mintty.exe 1
  nircmd win settopmost process mintty.exe 0
  nircmd win focus process mintty.exe
  # This is 99% of the way there. The problem is the window still doesn't have focus, even though it brings it to the front. It's the ShellExperienceHost.exe that maintains it, and I can't figure out how to stop that from happening. I have to manually click on the window to give it focus
  # And here's the workaround I wish I didn't have to do: Because the window is going to be full-sized, by moving the mouse up, I know with certainty that I won't be clicking on the taskbar (because it's docked on the bottom of my screen).
  nircmd sendmouse move 0 -1000
  # Now I click, to bring the window I've switched to into focus.
  nircmd sendmouse left click
fi
if [[ "$notification_exit_code" -eq "$notification_timeout" ]]
then
  # this makes the taskbar icon highlighted to remind me that the build is done even if I don't want to look at it immediately
  nircmd win flash process mintty.exe
fi

notifu64.exe is a commandline tool that can create windows notifications.

nircmd is a commandline tool that can control various aspects of the Windows operating system. In this script, I use it to control application windows.

Related