2 * taglist.c - tag list widget
4 * Copyright © 2008 Julien Danjou <julien@danjou.info>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 #include "common/tokenize.h"
28 extern awesome_t globalconf
;
30 /** Data type used to store where we draw the taglist for a particular object.
31 * This is filled in the draw function, and use later when we get a click.
33 typedef struct taglist_drawn_area_t taglist_drawn_area_t
;
34 struct taglist_drawn_area_t
38 taglist_drawn_area_t
*next
, *prev
;
41 /** Delete a taglist_drawn_area_t object.
42 * \param a The drawn area to delete.
45 taglist_drawn_area_delete(taglist_drawn_area_t
**a
)
47 area_array_wipe(&(*a
)->areas
);
51 DO_SLIST(taglist_drawn_area_t
, taglist_drawn_area
, taglist_drawn_area_delete
);
53 /** Taglist widget private data */
56 taglist_drawn_area_t
*drawn_area
;
60 static taglist_drawn_area_t
*
61 taglist_drawn_area_getbyobj(taglist_drawn_area_t
*list
, void *p
)
63 taglist_drawn_area_t
*t
;
65 for(t
= list
; t
; t
= t
->next
)
73 * \param ctx The draw context.
74 * \param screen The screen we're drawing for.
75 * \param w The widget node we're drawing for.
76 * \param offset Offset to draw at.
77 * \param used Space already used.
78 * \param object The object pointer we're drawing onto.
79 * \param type The object type.
80 * \return The width used.
83 taglist_draw(draw_context_t
*ctx
, int screen
, widget_node_t
*w
,
85 int used
__attribute__ ((unused
)),
89 taglist_data_t
*data
= w
->widget
->data
;
91 taglist_drawn_area_t
*tda
;
94 tag_array_t
*tags
= &globalconf
.screens
[screen
].tags
;
95 const char **text
= p_alloca(const char *, tags
->len
);
96 size_t *len
= p_alloca(size_t, tags
->len
);
97 draw_parser_data_t
*pdata
= p_alloca(draw_parser_data_t
, tags
->len
);
99 w
->area
.width
= w
->area
.y
= 0;
101 /* Lookup for our taglist_drawn_area.
102 * This will be used to store area where we draw tag list for each object. */
103 if(!(tda
= taglist_drawn_area_getbyobj(data
->drawn_area
, object
)))
105 /* Oh, we did not find a drawn area for our object. First time? */
106 tda
= p_new(taglist_drawn_area_t
, 1);
107 tda
->object
= object
;
108 taglist_drawn_area_list_push(&data
->drawn_area
, tda
);
113 /* First compute text and widget width */
114 for(int i
= 0; i
< tags
->len
; i
++)
116 tag_t
*tag
= tags
->tab
[i
];
119 luaA_tag_userdata_new(globalconf
.L
, tag
);
120 if(luaA_dofunction(globalconf
.L
, data
->label
, 1, 1))
122 if(lua_isstring(globalconf
.L
, -1))
123 text
[i
] = lua_tolstring(globalconf
.L
, -1, &len
[i
]);
125 lua_pop(globalconf
.L
, 1);
127 draw_parser_data_init(&pdata
[i
]);
128 area
= draw_text_extents(ctx
->connection
, ctx
->phys_screen
,
129 globalconf
.font
, text
[i
], len
[i
], &pdata
[i
]);
131 if(pdata
[i
].bg_image
)
132 area
.width
= MAX(area
.width
,
133 pdata
[i
].bg_resize
? ((double) pdata
[i
].bg_image
->width
/ (double) pdata
[i
].bg_image
->height
) * w
->area
.height
: pdata
[i
].bg_image
->width
);
135 w
->area
.width
+= area
.width
;
137 area_array_append(&tda
->areas
, area
);
140 /* Now that we have widget width we can compute widget x coordinate */
141 w
->area
.x
= widget_calculate_offset(ctx
->width
, w
->area
.width
,
142 offset
, w
->widget
->align
);
144 for(int i
= 0; i
< tags
->len
; i
++)
146 area_t
*r
= &tda
->areas
.tab
[i
];
148 r
->x
= w
->area
.x
+ prev_width
;
149 prev_width
+= r
->width
;
150 draw_text(ctx
, globalconf
.font
, *r
, text
[i
], len
[i
], &pdata
[i
]);
151 draw_parser_data_wipe(&pdata
[i
]);
154 w
->area
.height
= ctx
->height
;
155 return w
->area
.width
;
158 /** Handle button click on tasklist.
159 * \param w The widget node.
160 * \param ev The button press event.
161 * \param screen The screen where the click was.
162 * \param object The object we're onto.
163 * \param type The type object.
166 taglist_button_press(widget_node_t
*w
,
167 xcb_button_press_event_t
*ev
,
172 tag_array_t
*tags
= &globalconf
.screens
[screen
].tags
;
174 taglist_data_t
*data
= w
->widget
->data
;
175 taglist_drawn_area_t
*tda
;
177 /* Find the good drawn area list */
178 if((tda
= taglist_drawn_area_getbyobj(data
->drawn_area
, object
)))
179 for(b
= w
->widget
->buttons
; b
; b
= b
->next
)
180 if(ev
->detail
== b
->button
&& XUTIL_MASK_CLEAN(ev
->state
) == b
->mod
&& b
->fct
)
181 for(int i
= 0; i
< MIN(tags
->len
, tda
->areas
.len
); i
++)
183 tag_t
*tag
= tags
->tab
[i
];
184 area_t
*area
= &tda
->areas
.tab
[i
];
185 if(ev
->event_x
>= AREA_LEFT(*area
)
186 && ev
->event_x
< AREA_RIGHT(*area
))
188 luaA_pushpointer(globalconf
.L
, object
, type
);
189 luaA_tag_userdata_new(globalconf
.L
, tag
);
190 luaA_dofunction(globalconf
.L
, b
->fct
, 2, 0);
197 * \param L The Lua VM state.
198 * \param token The key token.
199 * \return The number of elements pushed on stack.
201 * \lfield label Function used to get the string to display as the tag title.
202 * It gets the tag as argument, and must return a string.
205 luaA_taglist_index(lua_State
*L
, awesome_token_t token
)
207 widget_t
**widget
= luaA_checkudata(L
, 1, "widget");
208 taglist_data_t
*d
= (*widget
)->data
;
213 lua_rawgeti(L
, LUA_REGISTRYINDEX
, d
->label
);
220 /** Newindex function for taglist.
221 * \param L The Lua VM state.
222 * \param token The key token.
223 * \return The number of elements pushed on stack.
226 luaA_taglist_newindex(lua_State
*L
, awesome_token_t token
)
228 widget_t
**widget
= luaA_checkudata(L
, 1, "widget");
229 taglist_data_t
*d
= (*widget
)->data
;
234 luaA_registerfct(L
, &d
->label
);
240 widget_invalidate_bywidget(*widget
);
245 /** Taglist destructor.
246 * \param widget The widget to destroy.
249 taglist_destructor(widget_t
*widget
)
251 taglist_data_t
*d
= widget
->data
;
253 taglist_drawn_area_list_wipe(&d
->drawn_area
);
257 /** Taglist detach function.
258 * \param widget The widget which is detaching.
259 * \param object The object we are leaving.
262 taglist_detach(widget_t
*widget
, void *object
)
264 taglist_data_t
*d
= widget
->data
;
265 taglist_drawn_area_t
*tda
;
267 if((tda
= taglist_drawn_area_getbyobj(d
->drawn_area
, object
)))
269 taglist_drawn_area_list_detach(&d
->drawn_area
, tda
);
270 taglist_drawn_area_delete(&tda
);
274 /** Create a brand new taglist widget.
275 * \param align Widget alignment.
276 * \return A taglist widget.
279 taglist_new(alignment_t align
)
284 w
= p_new(widget_t
, 1);
285 widget_common_new(w
);
286 w
->index
= luaA_taglist_index
;
287 w
->newindex
= luaA_taglist_newindex
;
289 w
->draw
= taglist_draw
;
290 w
->button_press
= taglist_button_press
;
291 w
->destructor
= taglist_destructor
;
292 w
->detach
= taglist_detach
;
294 w
->data
= d
= p_new(taglist_data_t
, 1);
295 d
->label
= LUA_REFNIL
;
297 /* Set cache property */
298 w
->cache_flags
= WIDGET_CACHE_TAGS
| WIDGET_CACHE_CLIENTS
;
303 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80