Clocky - a Tiny Title Bar Clock in Linux
I am a compulsive screen maximizer. Start menu bars are set to auto-vanish on my screen, and the app rules the day. If you think I ever see my desktop, I have to disappoint you. Plasma widgets are useless on my computer, and frankly I don’t understand how anyone ends up having enough screen real estate to see the background picture they chose, unless there is a sudden crash of an application.
That leaves no room for a clock to be visible on my screen. A clock is one of those things you really need, once in a while, but unless it’s “once in a while,” it’s perfectly pointless.
Like the title bar on windows. You got the app icon, the title, and the close/maximize area, but otherwise it’s a waste of space.
Back in the old days, I had a Windows 3.1 utility that would make a little clock appear in the title bar. That was nifty and useful. It would follow the active window, so that you’d always look up from where you were working and get the time at a glance.
I wanted one for my desktop, too. I looked on the Intertubes and on the repositories, but there was nothing like the simple thing I wanted. There was something called, “tiny dockable clock,” or tdc, but it seemed not to move or dock to anything.
So I decided to give it a try. I wanted something basic, but easily extended, and quick. So I used Tcl/Tk. You can re-implement it in any language if you feel like it, but Tcl/Tk is widely available on Linux and is a fairly small install (2MB, apparently). The script itself runs 22 lines of code, a majestic 58 with comments and additional configuration and utility. You’ll understand that, given the circumstances, the script is entirely inlined to this article.
The main problem I had to face was that Tk has no idea about other windows. It is perfectly happy and competent to manage its own windows, but it ignores the rest of the screen. So, to get to the id of the window with current focus, I needed something else. Fortunately, X11 is a mature and robust environment with tons of utilities and tools. The package x11-utils (on Ubuntu) had what I wanted: xwininfo and xprop.
So, the Ubuntu dependencies for the program are tcl, wish, and x11-utils. Install them using sudo apt-get install tcl wish x11-utils. Hint: if you are asked to provide a specific version, just choose the latest one.
The script itself is at the end of this post. Just copy and paste to a file of your choosing, then run (for now) from the command line. I called it clocky.tcl, so I run wish clocky.tcl. A little window will pop up and move a fraction of a second later to the top of your title bar, smack in the middle. You can terminate it by double-clicking. Also, when you enter it, the clock background changes from whatever color it was to white.
This is all very no-frills and ready for augmentation. How about popping up a menu on double-click? How about popping up a calendar on right mouse click? It’s all incredibly easy to do, so fire your ideas my way.
If you want to install clicky in a more permanent way, you can put it into a more permanent place – say, /usr/local/bin by typing mv clicky.tcl /usr/local/bin/clocky. You give it execute permissions with chmod agu+x /usr/local/bin/clocky. After that, you can just start clicky from anywhere.
Not bad for 22 lines of functional code, huh?
#!/usr/bin/wish array set o { -format %H:%M:%S -geometry above -update 200 -minuteflash red } wm overrideredirect . 1 proc curtime {} { return [clock format [clock seconds] -format $::o(-format)] } proc xplacewin {} { # find current window id catch {exec xprop -root} out if {![regexp {_NET_ACTIVE_WINDOW\(WINDOW\).*?(0x.*)\n} $out dummy id] || $id == 0 || $id == "0x0"} { return "" } # find the props of the current window id catch {exec xwininfo -id $id} out regexp {Absolute upper-left X: ([0-9]+)} $out dummy x regexp {Absolute upper-left Y: ([0-9]+)} $out dummy y regexp {Width: ([0-9]+)} $out dummy w regexp {Height: ([0-9]+)} $out dummy h # now determine where the clock should be placed if {[info exists x] || [info exists y] || [info exists w] || [info exists h]} { set xpos [expr $x + ($w - [winfo width .]) / 2] if {$::o(-geometry) == "above"} { set ypos [expr $y - [winfo height .]] } else { set ypos $y } wm geometry . +$xpos+$ypos } } proc recur {} { set time [curtime] .b configure -text "$time" switch [string range $time 6 7] { 00 { .b configure -fg $::o(-minuteflash) } 01 { .b configure -fg $::o(-fg) } } xplacewin after $::o(-update) recur } pack [label .b] set o(-bg) [.b cget -bg] set o(-fg) [.b cget -fg] bind .b exit bind .b <enter> {.b configure -bg white} bind .b <leave> {.b configure -bg $::o(-bg)} recur </leave></enter>