Probably the best new feature of Conky 1.7.2 is that it has built-in Cairo bindings for Lua, which, translated for people who speak English, means you can draw nifty stuff directly to the Conky window.

Here’s my first outing with the new feature…It was my goal to recreate the “Air” clock from KDE 4.3, but from within Conky. Now that I’m running Crunchbang with Openbox, I’m sadly lacking in eye-candy and needed to get a little back.

So…what do you think?

Air Clock Screenshot

And a closeup:

Air Clock Closeup
The Lua script to draw this clock (clock.lua.tar.gz):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
--[[
Air Clock by londonali1010 (2009)
 
This clock is designed to look like KDE 4.3's "Air" clock, but from inside Conky.
 
You can adjust the clock's radius and placement, as well as the size and offset of the drop shadow. You can also choose whether to display the seconds hand. This clock updates every time Conky does, so if you want to show seconds, it is recommended that you set update_interval to no more than 0.5s. If you turn off seconds, you can set the update_interval to as long as 30s.  The settings are in the "Settings" section, starting at Line 21.
 
Call this script in Conky using the following before TEXT (assuming you save this script to ~/scripts/clock.lua):
lua_load ~/scripts/clock.lua
lua_draw_hook_pre draw_clock
]]
 
require 'cairo'
function conky_draw_clock()
if conky_window==nil then return end
local w=conky_window.width
local h=conky_window.height
local cs=cairo_xlib_surface_create(conky_window.display, conky_window.drawable, conky_window.visual, w, h)
cr=cairo_create(cs)
 
-- Settings
 
-- What radius should the clock face (not including border) be, in pixels?
 
local clock_r=60
 
-- x and y coordinates, relative to the top left corner of Conky, in pixels
 
local xc=w/2
local yc=h/2
 
-- Extent of the shadow, in pixels
 
shadow_width=5
 
-- x and y offsets of the drop shadow, relative to the centre of the clock face, in pixels. Can be positive (downward) or negative (upward)
 
shadow_xoffset=0
shadow_yoffset=2
 
-- Do you want to show the second hand? Use this if you use a Conky update_interval > 1s. Can be true or false.
 
show_seconds=true
 
-- Grab time
 
local hours=os.date("%I")
local mins=os.date("%M")
local secs=os.date("%S")
 
secs_arc=(2*math.pi/60)*secs
mins_arc=(2*math.pi/60)*mins
hours_arc=(2*math.pi/12)*hours+mins_arc/12
 
-- Drop shadow
 
local ds_pat=cairo_pattern_create_radial(xc+shadow_xoffset,yc+shadow_yoffset,clock_r*1.25,xc+shadow_xoffset,yc+shadow_yoffset,clock_r*1.25+shadow_width)
cairo_pattern_add_color_stop_rgba(ds_pat,0,0,0,0,0.2)
cairo_pattern_add_color_stop_rgba(ds_pat,1,0,0,0,0)
 
cairo_move_to(cr,0,0)
cairo_line_to(cr,w,0)
cairo_line_to(cr,w,h)
cairo_line_to(cr,0,h)
cairo_new_sub_path(cr)
cairo_arc(cr,xc,yc,clock_r*1.25,0,2*math.pi)
cairo_set_source(cr,ds_pat)
cairo_set_fill_rule(cr,CAIRO_FILL_RULE_EVEN_ODD)
cairo_fill(cr)
 
-- Glassy border
 
cairo_arc(cr,xc,yc,clock_r*1.25,0,2*math.pi)
cairo_set_source_rgba(cr,0.5,0.5,0.5,0.2)
cairo_set_line_width(cr,1)
cairo_stroke(cr)
 
local border_pat=cairo_pattern_create_linear(xc,yc-clock_r*1.25,xc,yc+clock_r*1.25)
 
cairo_pattern_add_color_stop_rgba(border_pat,0,1,1,1,0.7)
cairo_pattern_add_color_stop_rgba(border_pat,0.3,1,1,1,0)
cairo_pattern_add_color_stop_rgba(border_pat,0.5,1,1,1,0)
cairo_pattern_add_color_stop_rgba(border_pat,0.7,1,1,1,0)
cairo_pattern_add_color_stop_rgba(border_pat,1,1,1,1,0.7)
cairo_set_source(cr,border_pat)
cairo_arc(cr,xc,yc,clock_r*1.125,0,2*math.pi)
cairo_close_path(cr)
cairo_set_line_width(cr,clock_r*0.25)
cairo_stroke(cr)
 
-- Set clock face
 
cairo_arc(cr,xc,yc,clock_r,0,2*math.pi)
cairo_close_path(cr)
 
local face_pat=cairo_pattern_create_radial(xc,yc-clock_r*0.75,0,xc,yc,clock_r)
 
cairo_pattern_add_color_stop_rgba(face_pat,0,1,1,1,0.9)
cairo_pattern_add_color_stop_rgba(face_pat,0.5,1,1,1,0.9)
cairo_pattern_add_color_stop_rgba(face_pat,1,0.9,0.9,0.9,0.9)
cairo_set_source(cr,face_pat)
cairo_fill_preserve(cr)
cairo_set_source_rgba(cr,0.5,0.5,0.5,0.2)
cairo_set_line_width(cr, 1)
cairo_stroke (cr)
 
-- Draw hour hand
 
xh=xc+0.7*clock_r*math.sin(hours_arc)
yh=yc-0.7*clock_r*math.cos(hours_arc)
cairo_move_to(cr,xc,yc)
cairo_line_to(cr,xh,yh)
 
cairo_set_line_cap(cr,CAIRO_LINE_CAP_ROUND)
cairo_set_line_width(cr,5)
cairo_set_source_rgba(cr,0,0,0,0.5)
cairo_stroke(cr)
 
-- Draw minute hand
 
xm=xc+0.9*clock_r*math.sin(mins_arc)
ym=yc-0.9*clock_r*math.cos(mins_arc)
cairo_move_to(cr,xc,yc)
cairo_line_to(cr,xm,ym)
 
cairo_set_line_width(cr,3)
cairo_stroke(cr)
 
-- Draw seconds hand
 
if show_seconds then
xs=xc+0.9*clock_r*math.sin(secs_arc)
ys=yc-0.9*clock_r*math.cos(secs_arc)
cairo_move_to(cr,xc,yc)
cairo_line_to(cr,xs,ys)
 
cairo_set_line_width(cr,1)
cairo_stroke(cr)
end
end

And the .conkyrc to call the script:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# -- Conky settings -- #
background no
update_interval 0.5
 
cpu_avg_samples 2
net_avg_samples 2
 
override_utf8_locale yes
 
double_buffer yes
no_buffers yes
 
text_buffer_size 2048
imlib_cache_size 0
 
# -- Window specifications -- #
 
own_window yes
own_window_type desktop
own_window_transparent yes
own_window_hints undecorate,sticky,skip_taskbar,skip_pager,below
 
border_inner_margin 0
border_outer_margin 0
 
minimum_size 200 200
maximum_width 1024
 
alignment tr
gap_x 10
gap_y 10
 
# -- Graphics settings -- #
draw_shades no
draw_outline no
draw_borders no
draw_graph_borders no
 
# -- Text settings -- #
use_xft yes
xftfont Santana:size=12
xftalpha 0.8
 
uppercase no
 
default_color FFFFFF
 
# -- Lua load -- #
lua_load ~/scripts/clock.lua
lua_draw_hook_pre draw_clock
 
TEXT

Note the ” ” after TEXT; it is needed for Conky to draw the window if you’re not putting any other text in it. You can control the size of the window by using the minimum_size config variable.

Using this script:

  1. You can customise the clock radius and placement, the size and offsets of the drop shadow, and whether you show the seconds hand. If you decide to show the seconds hand, make sure your .conkyrc update_interval is no more than 0.5s. If you decide not to show the seconds hand, you can use an update_interval as long as 30s.

Special thanks to NaBHaN for his gorgeous “Gold” wallpaper, available from DeviantArt.

UPDATE: This script is now available as a widget code block, for use with my Conky Widgets script:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
--[[ AIR CLOCK WIDGET ]]
--[[ Options (xc, yc, size):
	"xc" and "yc" are the x and y coordinates of the centre of the clock, in pixels, relative to the top left of the Conky window
	"size" is the total size of the widget, in pixels ]]
 
function air_clock(cr, xc, yc, size)
	local offset = 0
 
	shadow_width = size * 0.03
	shadow_xoffset = 0
	shadow_yoffset = size * 0.01
 
	if shadow_xoffset >= shadow_yoffset then
		offset = shadow_xoffset
	else offset = shadow_yoffset
	end
 
	local clock_r = (size - 2 * offset) / (2 * 1.25)
 
	show_seconds=true
 
	-- Grab time
 
	local hours=os.date("%I")
	local mins=os.date("%M")
	local secs=os.date("%S")
 
	secs_arc=(2*math.pi/60)*secs
	mins_arc=(2*math.pi/60)*mins
	hours_arc=(2*math.pi/12)*hours+mins_arc/12
 
	-- Drop shadow
 
	local ds_pat=cairo_pattern_create_radial(xc+shadow_xoffset,yc+shadow_yoffset,clock_r*1.25,xc+shadow_xoffset,yc+shadow_yoffset,clock_r*1.25+shadow_width)
	cairo_pattern_add_color_stop_rgba(ds_pat,0,0,0,0,0.2)
	cairo_pattern_add_color_stop_rgba(ds_pat,1,0,0,0,0)
 
	cairo_move_to(cr,0,0)
	cairo_line_to(cr,conky_window.width,0)
	cairo_line_to(cr,conky_window.width, conky_window.height)
	cairo_line_to(cr,0,conky_window.height)
	cairo_close_path(cr)
	cairo_new_sub_path(cr)
	cairo_arc(cr,xc,yc,clock_r*1.25,0,2*math.pi)
	cairo_set_source(cr,ds_pat)
	cairo_set_fill_rule(cr,CAIRO_FILL_RULE_EVEN_ODD)
	cairo_fill(cr)
 
	-- Glassy border
 
	cairo_arc(cr,xc,yc,clock_r*1.25,0,2*math.pi)
	cairo_set_source_rgba(cr,0.5,0.5,0.5,0.2)
	cairo_set_line_width(cr,1)
	cairo_stroke(cr)
 
	local border_pat=cairo_pattern_create_linear(xc,yc-clock_r*1.25,xc,yc+clock_r*1.25)
 
	cairo_pattern_add_color_stop_rgba(border_pat,0,1,1,1,0.7)
	cairo_pattern_add_color_stop_rgba(border_pat,0.3,1,1,1,0)
	cairo_pattern_add_color_stop_rgba(border_pat,0.5,1,1,1,0)
	cairo_pattern_add_color_stop_rgba(border_pat,0.7,1,1,1,0)
	cairo_pattern_add_color_stop_rgba(border_pat,1,1,1,1,0.7)
	cairo_set_source(cr,border_pat)
	cairo_arc(cr,xc,yc,clock_r*1.125,0,2*math.pi)
	cairo_close_path(cr)
	cairo_set_line_width(cr,clock_r*0.25)
	cairo_stroke(cr)
 
	-- Set clock face
 
	cairo_arc(cr,xc,yc,clock_r,0,2*math.pi)
	cairo_close_path(cr)
 
	local face_pat=cairo_pattern_create_radial(xc,yc-clock_r*0.75,0,xc,yc,clock_r)
 
	cairo_pattern_add_color_stop_rgba(face_pat,0,1,1,1,0.9)
	cairo_pattern_add_color_stop_rgba(face_pat,0.5,1,1,1,0.9)
	cairo_pattern_add_color_stop_rgba(face_pat,1,0.9,0.9,0.9,0.9)
	cairo_set_source(cr,face_pat)
	cairo_fill_preserve(cr)
	cairo_set_source_rgba(cr,0.5,0.5,0.5,0.2)
	cairo_set_line_width(cr, 1)
	cairo_stroke (cr)
 
	-- Draw hour hand
 
	xh=xc+0.7*clock_r*math.sin(hours_arc)
	yh=yc-0.7*clock_r*math.cos(hours_arc)
	cairo_move_to(cr,xc,yc)
	cairo_line_to(cr,xh,yh)
 
	cairo_set_line_cap(cr,CAIRO_LINE_CAP_ROUND)
	cairo_set_line_width(cr,5)
	cairo_set_source_rgba(cr,0,0,0,0.5)
	cairo_stroke(cr)
 
	-- Draw minute hand
 
	xm=xc+0.9*clock_r*math.sin(mins_arc)
	ym=yc-0.9*clock_r*math.cos(mins_arc)
	cairo_move_to(cr,xc,yc)
	cairo_line_to(cr,xm,ym)
 
	cairo_set_line_width(cr,3)
	cairo_stroke(cr)
 
	-- Draw seconds hand
 
	if show_seconds then
		xs=xc+0.9*clock_r*math.sin(secs_arc)
		ys=yc-0.9*clock_r*math.cos(secs_arc)
		cairo_move_to(cr,xc,yc)
		cairo_line_to(cr,xs,ys)
 
		cairo_set_line_width(cr,1)
		cairo_stroke(cr)
	end
end
 
--[[ END AIR CLOCK WIDGET ]]

Happy Conkying!

Author: londonali1010

Distro: Crunchbang 9.04, Openbox

Conky Version: 1.7.2