atexit: fix shadow declaration
[awesome.git] / wibox.c
blob3f77ca4e210061787b49e98caed6937478e4d9f7
1 /*
2 * wibox.c - wibox functions
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.
22 #include "screen.h"
23 #include "wibox.h"
24 #include "titlebar.h"
25 #include "client.h"
26 #include "ewmh.h"
27 #include "screen.h"
28 #include "common/xcursor.h"
29 #include "window.h"
31 extern awesome_t globalconf;
33 DO_LUA_NEW(extern, wibox_t, wibox, "wibox", wibox_ref)
34 DO_LUA_GC(wibox_t, wibox, "wibox", wibox_unref)
35 DO_LUA_EQ(wibox_t, wibox, "wibox")
37 static void
38 wibox_move(wibox_t *wibox, int16_t x, int16_t y)
40 if(wibox->sw.window)
42 simplewindow_move(&wibox->sw, x, y);
43 wibox->screen = screen_getbycoord(wibox->screen, x, y);
45 else
47 wibox->sw.geometry.x = x;
48 wibox->sw.geometry.y = y;
52 static void
53 wibox_resize(wibox_t *wibox, uint16_t width, uint16_t height)
55 if(wibox->sw.window)
56 simplewindow_resize(&wibox->sw, width, height);
57 else
59 wibox->sw.geometry.width = width;
60 wibox->sw.geometry.height = height;
62 wibox->need_update = true;
63 wibox->mouse_over = NULL;
66 static void
67 wibox_setposition(wibox_t *wibox, position_t p)
69 if(p != wibox->position)
71 switch((wibox->position = p))
73 case Bottom:
74 case Top:
75 case Floating:
76 simplewindow_orientation_set(&wibox->sw, East);
77 break;
78 case Left:
79 simplewindow_orientation_set(&wibox->sw, North);
80 break;
81 case Right:
82 simplewindow_orientation_set(&wibox->sw, South);
83 break;
85 /* reset width/height to 0 */
86 if(wibox->position != Floating)
87 wibox->sw.geometry.width = wibox->sw.geometry.height = 0;
89 /* recompute position */
90 wibox_position_update(wibox);
92 /* reset all wibox position */
93 wibox_array_t *w = &globalconf.screens[wibox->screen].wiboxes;
94 for(int i = 0; i < w->len; i++)
95 wibox_position_update(w->tab[i]);
97 ewmh_update_workarea(screen_virttophys(wibox->screen));
99 wibox->need_update = true;
100 wibox->mouse_over = NULL;
104 /** Kick out systray windows.
105 * \param phys_screen Physical screen number.
107 static void
108 wibox_systray_kickout(int phys_screen)
110 xcb_screen_t *s = xutil_screen_get(globalconf.connection, phys_screen);
112 /* Who! Check that we're not deleting a wibox with a systray, because it
113 * may be its parent. If so, we reparent to root before, otherwise it will
114 * hurt very much. */
115 xcb_reparent_window(globalconf.connection,
116 globalconf.screens[phys_screen].systray.window,
117 s->root, -512, -512);
119 globalconf.screens[phys_screen].systray.parent = s->root;
122 static void
123 wibox_systray_refresh(wibox_t *wibox)
125 if(wibox->screen == SCREEN_UNDEF)
126 return;
128 for(int i = 0; i < wibox->widgets.len; i++)
130 widget_node_t *systray = &wibox->widgets.tab[i];
131 if(systray->widget->type == widget_systray)
133 uint32_t config_back[] = { wibox->sw.ctx.bg.pixel };
134 uint32_t config_win_vals[4];
135 uint32_t config_win_vals_off[2] = { -512, -512 };
136 xembed_window_t *em;
137 position_t pos;
138 int phys_screen = wibox->sw.ctx.phys_screen;
140 if(wibox->isvisible
141 && systray->widget->isvisible
142 && systray->geometry.width)
144 pos = wibox->position;
146 /* Set background of the systray window. */
147 xcb_change_window_attributes(globalconf.connection,
148 globalconf.screens[phys_screen].systray.window,
149 XCB_CW_BACK_PIXEL, config_back);
150 /* Map it. */
151 xcb_map_window(globalconf.connection, globalconf.screens[phys_screen].systray.window);
152 /* Move it. */
153 switch(wibox->position)
155 case Left:
156 config_win_vals[0] = systray->geometry.y;
157 config_win_vals[1] = wibox->sw.geometry.height - systray->geometry.x - systray->geometry.width;
158 config_win_vals[2] = systray->geometry.height;
159 config_win_vals[3] = systray->geometry.width;
160 break;
161 case Right:
162 config_win_vals[0] = systray->geometry.y;
163 config_win_vals[1] = systray->geometry.x;
164 config_win_vals[2] = systray->geometry.height;
165 config_win_vals[3] = systray->geometry.width;
166 break;
167 default:
168 config_win_vals[0] = systray->geometry.x;
169 config_win_vals[1] = systray->geometry.y;
170 config_win_vals[2] = systray->geometry.width;
171 config_win_vals[3] = systray->geometry.height;
172 break;
174 /* reparent */
175 if(globalconf.screens[phys_screen].systray.parent != wibox->sw.window)
177 xcb_reparent_window(globalconf.connection,
178 globalconf.screens[phys_screen].systray.window,
179 wibox->sw.window,
180 config_win_vals[0], config_win_vals[1]);
181 globalconf.screens[phys_screen].systray.parent = wibox->sw.window;
183 xcb_configure_window(globalconf.connection,
184 globalconf.screens[phys_screen].systray.window,
185 XCB_CONFIG_WINDOW_X
186 | XCB_CONFIG_WINDOW_Y
187 | XCB_CONFIG_WINDOW_WIDTH
188 | XCB_CONFIG_WINDOW_HEIGHT,
189 config_win_vals);
190 /* width = height = systray height */
191 config_win_vals[2] = config_win_vals[3] = systray->geometry.height;
192 config_win_vals[0] = 0;
194 else
195 return wibox_systray_kickout(phys_screen);
197 switch(pos)
199 case Left:
200 config_win_vals[1] = systray->geometry.width - config_win_vals[3];
201 for(int j = 0; j < globalconf.embedded.len; j++)
203 em = &globalconf.embedded.tab[j];
204 if(em->phys_screen == phys_screen)
206 if(config_win_vals[1] - config_win_vals[2] >= (uint32_t) wibox->sw.geometry.y)
208 xcb_map_window(globalconf.connection, em->win);
209 xcb_configure_window(globalconf.connection, em->win,
210 XCB_CONFIG_WINDOW_X
211 | XCB_CONFIG_WINDOW_Y
212 | XCB_CONFIG_WINDOW_WIDTH
213 | XCB_CONFIG_WINDOW_HEIGHT,
214 config_win_vals);
215 config_win_vals[1] -= config_win_vals[3];
217 else
218 xcb_configure_window(globalconf.connection, em->win,
219 XCB_CONFIG_WINDOW_X
220 | XCB_CONFIG_WINDOW_Y,
221 config_win_vals_off);
224 break;
225 case Right:
226 config_win_vals[1] = 0;
227 for(int j = 0; j < globalconf.embedded.len; j++)
229 em = &globalconf.embedded.tab[j];
230 if(em->phys_screen == phys_screen)
232 if(config_win_vals[1] + config_win_vals[3] <= (uint32_t) wibox->sw.geometry.y + wibox->sw.geometry.width)
234 xcb_map_window(globalconf.connection, em->win);
235 xcb_configure_window(globalconf.connection, em->win,
236 XCB_CONFIG_WINDOW_X
237 | XCB_CONFIG_WINDOW_Y
238 | XCB_CONFIG_WINDOW_WIDTH
239 | XCB_CONFIG_WINDOW_HEIGHT,
240 config_win_vals);
241 config_win_vals[1] += config_win_vals[3];
243 else
244 xcb_configure_window(globalconf.connection, em->win,
245 XCB_CONFIG_WINDOW_X
246 | XCB_CONFIG_WINDOW_Y,
247 config_win_vals_off);
250 break;
251 case Floating:
252 case Top:
253 case Bottom:
254 config_win_vals[1] = 0;
255 for(int j = 0; j < globalconf.embedded.len; j++)
257 em = &globalconf.embedded.tab[j];
258 if(em->phys_screen == phys_screen)
260 /* if(x + width < systray.x + systray.width) */
261 if(config_win_vals[0] + config_win_vals[2] <= (uint32_t) AREA_RIGHT(systray->geometry) + wibox->sw.geometry.x)
263 xcb_map_window(globalconf.connection, em->win);
264 xcb_configure_window(globalconf.connection, em->win,
265 XCB_CONFIG_WINDOW_X
266 | XCB_CONFIG_WINDOW_Y
267 | XCB_CONFIG_WINDOW_WIDTH
268 | XCB_CONFIG_WINDOW_HEIGHT,
269 config_win_vals);
270 config_win_vals[0] += config_win_vals[2];
272 else
273 xcb_configure_window(globalconf.connection, em->win,
274 XCB_CONFIG_WINDOW_X
275 | XCB_CONFIG_WINDOW_Y,
276 config_win_vals_off);
279 break;
281 break;
286 /** Update the wibox position. It deletes every wibox resources and
287 * create them back.
288 * \param wibox The wibox.
290 void
291 wibox_position_update(wibox_t *wibox)
293 area_t area, wingeom = wibox->sw.geometry;
294 bool ignore = false;
296 globalconf.screens[wibox->screen].need_arrange = true;
298 area = screen_area_get(wibox->screen, NULL,
299 &globalconf.screens[wibox->screen].padding, true);
301 /* Top and Bottom wibox_t have prio */
302 if(wibox->position != Floating)
303 for(int i = 0; i < globalconf.screens[wibox->screen].wiboxes.len; i++)
305 wibox_t *w = globalconf.screens[wibox->screen].wiboxes.tab[i];
306 /* Ignore every wibox after me that is in the same position */
307 if(wibox == w)
309 ignore = true;
310 continue;
312 else if((ignore && wibox->position == w->position) || !w->isvisible)
313 continue;
314 switch(w->position)
316 case Floating:
317 break;
318 case Left:
319 switch(wibox->position)
321 case Left:
322 area.x += wibox->sw.geometry.height;
323 break;
324 default:
325 break;
327 break;
328 case Right:
329 switch(wibox->position)
331 case Right:
332 area.x -= wibox->sw.geometry.height;
333 break;
334 default:
335 break;
337 break;
338 case Top:
339 switch(wibox->position)
341 case Top:
342 area.y += w->sw.geometry.height;
343 break;
344 case Left:
345 case Right:
346 area.height -= w->sw.geometry.height;
347 area.y += w->sw.geometry.height;
348 break;
349 default:
350 break;
352 break;
353 case Bottom:
354 switch(wibox->position)
356 case Bottom:
357 area.y -= w->sw.geometry.height;
358 break;
359 case Left:
360 case Right:
361 area.height -= w->sw.geometry.height;
362 break;
363 default:
364 break;
366 break;
370 /* The "length" of a wibox is always chosen to be the optimal size (non-floating).
371 * The "width" of a wibox is kept if it exists.
373 switch(wibox->position)
375 case Right:
376 wingeom.height = area.height;
377 wingeom.width = wibox->sw.geometry.width > 0 ? wibox->sw.geometry.width : 1.5 * globalconf.font->height;
378 wingeom.x = area.x + area.width - wingeom.width;
379 switch(wibox->align)
381 default:
382 wingeom.y = area.y;
383 break;
384 case AlignRight:
385 wingeom.y = area.y + area.height - wingeom.height;
386 break;
387 case AlignCenter:
388 wingeom.y = (area.y + area.height - wingeom.height) / 2;
389 break;
391 break;
392 case Left:
393 wingeom.height = area.height;
394 wingeom.width = wibox->sw.geometry.width > 0 ? wibox->sw.geometry.width : 1.5 * globalconf.font->height;
395 wingeom.x = area.x;
396 switch(wibox->align)
398 default:
399 wingeom.y = (area.y + area.height) - wingeom.height;
400 break;
401 case AlignRight:
402 wingeom.y = area.y;
403 break;
404 case AlignCenter:
405 wingeom.y = (area.y + area.height - wingeom.height) / 2;
407 break;
408 case Bottom:
409 wingeom.height = wibox->sw.geometry.height > 0 ? wibox->sw.geometry.height : 1.5 * globalconf.font->height;
410 wingeom.width = area.width;
411 wingeom.y = (area.y + area.height) - wingeom.height;
412 wingeom.x = area.x;
413 switch(wibox->align)
415 default:
416 break;
417 case AlignRight:
418 wingeom.x += area.width - wingeom.width;
419 break;
420 case AlignCenter:
421 wingeom.x += (area.width - wingeom.width) / 2;
422 break;
424 break;
425 case Top:
426 wingeom.height = wibox->sw.geometry.height > 0 ? wibox->sw.geometry.height : 1.5 * globalconf.font->height;
427 wingeom.width = area.width;
428 wingeom.x = area.x;
429 wingeom.y = area.y;
430 switch(wibox->align)
432 default:
433 break;
434 case AlignRight:
435 wingeom.x += area.width - wingeom.width;
436 break;
437 case AlignCenter:
438 wingeom.x += (area.width - wingeom.width) / 2;
439 break;
441 break;
442 case Floating:
443 wingeom.width = MAX(1, wibox->sw.geometry.width);
444 wingeom.height = MAX(1, wibox->sw.geometry.height);
445 break;
448 /* same window size and position ? */
449 if(wingeom.width != wibox->sw.geometry.width
450 || wingeom.height != wibox->sw.geometry.height)
451 wibox_resize(wibox, wingeom.width, wingeom.height);
453 if(wingeom.x != wibox->sw.geometry.x
454 || wingeom.y != wibox->sw.geometry.y)
455 wibox_move(wibox, wingeom.x, wingeom.y);
458 /** Delete a wibox.
459 * \param wibox wibox to delete.
461 void
462 wibox_delete(wibox_t **wibox)
464 simplewindow_wipe(&(*wibox)->sw);
465 button_array_wipe(&(*wibox)->buttons);
466 luaL_unref(globalconf.L, LUA_REGISTRYINDEX, (*wibox)->widgets_table);
467 widget_node_array_wipe(&(*wibox)->widgets);
468 p_delete(wibox);
471 /** Get a wibox by its window.
472 * \param w The window id.
473 * \return A wibox if found, NULL otherwise.
475 wibox_t *
476 wibox_getbywin(xcb_window_t w)
478 for(int screen = 0; screen < globalconf.nscreen; screen++)
479 for(int i = 0; i < globalconf.screens[screen].wiboxes.len; i++)
481 wibox_t *s = globalconf.screens[screen].wiboxes.tab[i];
482 if(s->sw.window == w)
483 return s;
486 for(client_t *c = globalconf.clients; c; c = c->next)
487 if(c->titlebar && c->titlebar->sw.window == w)
488 return c->titlebar;
490 return NULL;
493 /** Draw a wibox.
494 * \param wibox The wibox to draw.
496 static void
497 wibox_draw(wibox_t *wibox)
499 if(wibox->isvisible)
501 widget_render(wibox);
502 simplewindow_refresh_pixmap(&wibox->sw);
504 wibox->need_update = false;
507 wibox_systray_refresh(wibox);
510 /** Refresh all wiboxes.
512 void
513 wibox_refresh(void)
515 for(int screen = 0; screen < globalconf.nscreen; screen++)
516 for(int i = 0; i < globalconf.screens[screen].wiboxes.len; i++)
518 wibox_t *s = globalconf.screens[screen].wiboxes.tab[i];
519 if(s->need_update)
520 wibox_draw(s);
523 for(client_t *c = globalconf.clients; c; c = c->next)
524 if(c->titlebar && c->titlebar->need_update)
525 wibox_draw(c->titlebar);
528 /** Reposition all wiboxes.
530 void
531 wibox_update_positions(void)
533 for(int screen = 0; screen < globalconf.nscreen; screen++)
534 for(int i = 0; i < globalconf.screens[screen].wiboxes.len; i++)
536 wibox_t *s = globalconf.screens[screen].wiboxes.tab[i];
537 wibox_position_update(s);
541 /** Set a wibox visible or not.
542 * \param wibox The wibox.
543 * \param v The visible value.
545 static void
546 wibox_setvisible(wibox_t *wibox, bool v)
548 if(v != wibox->isvisible)
550 wibox->isvisible = v;
551 wibox->mouse_over = NULL;
553 if(wibox->screen != SCREEN_UNDEF)
555 if(wibox->isvisible)
557 xcb_map_window(globalconf.connection, wibox->sw.window);
558 simplewindow_refresh_pixmap(&wibox->sw);
559 /* stack correctly the wibox */
560 client_stack();
562 else
563 xcb_unmap_window(globalconf.connection, wibox->sw.window);
565 /* kick out systray if needed */
566 wibox_systray_refresh(wibox);
568 /* All the other wibox and ourselves need to be repositioned */
569 wibox_array_t *w = &globalconf.screens[wibox->screen].wiboxes;
570 for(int i = 0; i < w->len; i++)
571 wibox_position_update(w->tab[i]);
576 /** Remove a wibox from a screen.
577 * \param wibox Wibox to detach from screen.
579 void
580 wibox_detach(wibox_t *wibox)
582 if(wibox->screen != SCREEN_UNDEF)
584 bool v;
586 /* save visible state */
587 v = wibox->isvisible;
588 wibox->isvisible = false;
589 wibox_systray_refresh(wibox);
590 wibox_position_update(wibox);
591 /* restore position */
592 wibox->isvisible = v;
594 wibox->mouse_over = NULL;
596 simplewindow_wipe(&wibox->sw);
598 for(int i = 0; i < globalconf.screens[wibox->screen].wiboxes.len; i++)
599 if(globalconf.screens[wibox->screen].wiboxes.tab[i] == wibox)
601 wibox_array_take(&globalconf.screens[wibox->screen].wiboxes, i);
602 break;
604 globalconf.screens[wibox->screen].need_arrange = true;
605 wibox->screen = SCREEN_UNDEF;
606 wibox_unref(&wibox);
610 /** Attach a wibox.
611 * \param wibox The wibox to attach.
612 * \param s The screen to attach the wibox to.
614 void
615 wibox_attach(wibox_t *wibox, screen_t *s)
617 int phys_screen = screen_virttophys(s->index);
619 wibox_detach(wibox);
621 /* Set the wibox screen */
622 wibox->screen = s->index;
624 /* Check that the wibox coordinates matches the screen. */
625 int cscreen = screen_getbycoord(wibox->screen, wibox->sw.geometry.x, wibox->sw.geometry.y);
627 /* If it does not match, move it to the screen coordinates */
628 if(cscreen != wibox->screen)
629 wibox_move(wibox, s->geometry.x, s->geometry.y);
631 wibox_array_append(&s->wiboxes, wibox_ref(&wibox));
633 /* compute x/y/width/height if not set */
634 wibox_position_update(wibox);
636 simplewindow_init(&wibox->sw, phys_screen,
637 wibox->sw.geometry,
638 wibox->sw.border.width,
639 wibox->sw.orientation,
640 &wibox->sw.ctx.fg, &wibox->sw.ctx.bg);
642 simplewindow_border_color_set(&wibox->sw, &wibox->sw.border.color);
644 simplewindow_cursor_set(&wibox->sw,
645 xcursor_new(globalconf.connection, xcursor_font_fromstr(wibox->cursor)));
647 /* All the other wibox and ourselves need to be repositioned */
648 for(int i = 0; i < s->wiboxes.len; i++)
649 wibox_position_update(s->wiboxes.tab[i]);
651 ewmh_update_workarea(screen_virttophys(s->index));
653 if(wibox->isvisible)
655 /* draw it right now once to avoid garbage shown */
656 wibox_draw(wibox);
657 xcb_map_window(globalconf.connection, wibox->sw.window);
658 simplewindow_refresh_pixmap(&wibox->sw);
659 /* stack correctly the wibox */
660 client_stack();
662 else
663 wibox->need_update = true;
666 /** Create a new wibox.
667 * \param L The Lua VM state.
669 * \luastack
670 * \lparam A table with optionaly defined values:
671 * position, align, fg, bg, border_width, border_color, ontop, width and height.
672 * \lreturn A brand new wibox.
675 luaA_wibox_new(lua_State *L)
677 wibox_t *w;
678 const char *buf;
679 size_t len;
680 xcolor_init_request_t reqs[3];
681 int i, reqs_nbr = -1;
683 luaA_checktable(L, 2);
685 w = p_new(wibox_t, 1);
686 w->widgets_table = LUA_REFNIL;
688 w->sw.ctx.fg = globalconf.colors.fg;
689 if((buf = luaA_getopt_lstring(L, 2, "fg", NULL, &len)))
690 reqs[++reqs_nbr] = xcolor_init_unchecked(&w->sw.ctx.fg, buf, len);
692 w->sw.ctx.bg = globalconf.colors.bg;
693 if((buf = luaA_getopt_lstring(L, 2, "bg", NULL, &len)))
694 reqs[++reqs_nbr] = xcolor_init_unchecked(&w->sw.ctx.bg, buf, len);
696 w->sw.border.color = globalconf.colors.bg;
697 if((buf = luaA_getopt_lstring(L, 2, "border_color", NULL, &len)))
698 reqs[++reqs_nbr] = xcolor_init_unchecked(&w->sw.border.color, buf, len);
700 w->ontop = luaA_getopt_boolean(L, 2, "ontop", false);
702 buf = luaA_getopt_lstring(L, 2, "align", "left", &len);
703 w->align = draw_align_fromstr(buf, len);
705 w->sw.border.width = luaA_getopt_number(L, 2, "border_width", 0);
707 buf = luaA_getopt_lstring(L, 2, "position", "top", &len);
709 switch((w->position = position_fromstr(buf, len)))
711 case Bottom:
712 case Top:
713 case Floating:
714 simplewindow_orientation_set(&w->sw, East);
715 break;
716 case Left:
717 simplewindow_orientation_set(&w->sw, North);
718 break;
719 case Right:
720 simplewindow_orientation_set(&w->sw, South);
721 break;
724 /* recompute position */
725 wibox_position_update(w);
727 w->sw.geometry.x = luaA_getopt_number(L, 2, "x", 0);
728 w->sw.geometry.y = luaA_getopt_number(L, 2, "y", 0);
729 w->sw.geometry.width = luaA_getopt_number(L, 2, "width", 0);
730 w->sw.geometry.height = luaA_getopt_number(L, 2, "height", 0);
732 w->screen = SCREEN_UNDEF;
733 w->isvisible = true;
734 w->cursor = a_strdup("left_ptr");
736 for(i = 0; i <= reqs_nbr; i++)
737 xcolor_init_reply(reqs[i]);
739 return luaA_wibox_userdata_new(L, w);
742 /** Rebuild wibox widgets list.
743 * \param L The Lua VM state.
744 * \param wibox The wibox.
746 static void
747 wibox_widgets_table_build(lua_State *L, wibox_t *wibox)
749 widget_node_array_wipe(&wibox->widgets);
750 widget_node_array_init(&wibox->widgets);
751 luaA_table2widgets(L, &wibox->widgets);
752 wibox->mouse_over = NULL;
753 wibox->need_update = true;
756 /** Check if a wibox widget table has an item.
757 * \param L The Lua VM state.
758 * \param wibox The wibox.
759 * \param item The item to look for.
761 static bool
762 luaA_wibox_hasitem(lua_State *L, wibox_t *wibox, const void *item)
764 if(wibox->widgets_table != LUA_REFNIL)
766 lua_rawgeti(globalconf.L, LUA_REGISTRYINDEX, wibox->widgets_table);
767 if(lua_topointer(L, -1) == item || luaA_hasitem(L, item))
768 return true;
770 return false;
773 /** Invalidate a wibox by a Lua object (table, etc).
774 * \param L The Lua VM state.
775 * \param item The object identifier.
777 void
778 luaA_wibox_invalidate_byitem(lua_State *L, const void *item)
780 for(int screen = 0; screen < globalconf.nscreen; screen++)
781 for(int i = 0; i < globalconf.screens[screen].wiboxes.len; i++)
783 wibox_t *wibox = globalconf.screens[screen].wiboxes.tab[i];
784 if(luaA_wibox_hasitem(L, wibox, item))
786 /* recompute widget node list */
787 wibox_widgets_table_build(L, wibox);
788 lua_pop(L, 1); /* remove widgets table */
793 for(client_t *c = globalconf.clients; c; c = c->next)
794 if(c->titlebar && luaA_wibox_hasitem(L, c->titlebar, item))
796 /* recompute widget node list */
797 wibox_widgets_table_build(L, c->titlebar);
798 lua_pop(L, 1); /* remove widgets table */
802 /** Wibox object.
803 * \param L The Lua VM state.
804 * \return The number of elements pushed on stack.
805 * \luastack
806 * \lfield screen Screen number.
807 * \lfield client The client attached to this titlebar.
808 * \lfield border_width Border width.
809 * \lfield border_color Border color.
810 * \lfield align The alignment.
811 * \lfield fg Foreground color.
812 * \lfield bg Background color.
813 * \lfield position The position.
814 * \lfield ontop On top of other windows.
815 * \lfield cursor The mouse cursor.
817 static int
818 luaA_wibox_index(lua_State *L)
820 size_t len;
821 wibox_t **wibox = luaA_checkudata(L, 1, "wibox");
822 const char *attr = luaL_checklstring(L, 2, &len);
824 if(luaA_usemetatable(L, 1, 2))
825 return 1;
827 switch(a_tokenize(attr, len))
829 client_t *c;
831 case A_TK_VISIBLE:
832 lua_pushboolean(L, (*wibox)->isvisible);
833 break;
834 case A_TK_CLIENT:
835 if((c = client_getbytitlebar(*wibox)))
836 return luaA_client_userdata_new(L, c);
837 else
838 return 0;
839 case A_TK_SCREEN:
840 if((*wibox)->screen == SCREEN_UNDEF)
841 return 0;
842 lua_pushnumber(L, (*wibox)->screen + 1);
843 break;
844 case A_TK_BORDER_WIDTH:
845 lua_pushnumber(L, (*wibox)->sw.border.width);
846 break;
847 case A_TK_BORDER_COLOR:
848 luaA_pushcolor(L, &(*wibox)->sw.border.color);
849 break;
850 case A_TK_ALIGN:
851 lua_pushstring(L, draw_align_tostr((*wibox)->align));
852 break;
853 case A_TK_FG:
854 luaA_pushcolor(L, &(*wibox)->sw.ctx.fg);
855 break;
856 case A_TK_BG:
857 luaA_pushcolor(L, &(*wibox)->sw.ctx.bg);
858 break;
859 case A_TK_POSITION:
860 lua_pushstring(L, position_tostr((*wibox)->position));
861 break;
862 case A_TK_ONTOP:
863 lua_pushboolean(L, (*wibox)->ontop);
864 break;
865 case A_TK_ORIENTATION:
866 lua_pushstring(L, orientation_tostr((*wibox)->sw.orientation));
867 break;
868 case A_TK_WIDGETS:
869 if((*wibox)->widgets_table != LUA_REFNIL)
870 lua_rawgeti(L, LUA_REGISTRYINDEX, (*wibox)->widgets_table);
871 else
872 lua_pushnil(L);
873 break;
874 case A_TK_CURSOR:
875 lua_pushstring(L, (*wibox)->cursor);
876 break;
877 case A_TK_OPACITY:
879 double d;
880 if ((d = window_opacity_get((*wibox)->sw.window)) >= 0)
881 lua_pushnumber(L, d);
882 else
883 return 0;
885 break;
886 default:
887 return 0;
890 return 1;
893 /* Set or get the wibox geometry.
894 * \param L The Lua VM state.
895 * \return The number of elements pushed on stack.
896 * \luastack
897 * \lparam An optional table with wibox geometry.
898 * \lreturn The wibox geometry.
900 static int
901 luaA_wibox_geometry(lua_State *L)
903 wibox_t **wibox = luaA_checkudata(L, 1, "wibox");
905 if(lua_gettop(L) == 2)
907 area_t wingeom;
909 luaA_checktable(L, 2);
910 wingeom.x = luaA_getopt_number(L, 2, "x", (*wibox)->sw.geometry.x);
911 wingeom.y = luaA_getopt_number(L, 2, "y", (*wibox)->sw.geometry.y);
912 wingeom.width = luaA_getopt_number(L, 2, "width", (*wibox)->sw.geometry.width);
913 wingeom.height = luaA_getopt_number(L, 2, "height", (*wibox)->sw.geometry.height);
915 switch((*wibox)->type)
917 case WIBOX_TYPE_TITLEBAR:
918 wibox_resize(*wibox, wingeom.width, wingeom.height);
919 break;
920 case WIBOX_TYPE_NORMAL:
921 if((*wibox)->position == Floating)
922 wibox_moveresize(*wibox, wingeom);
923 else if(wingeom.width != (*wibox)->sw.geometry.width
924 || wingeom.height != (*wibox)->sw.geometry.height)
926 wibox_resize(*wibox, wingeom.width, wingeom.height);
927 globalconf.screens[(*wibox)->screen].need_arrange = true;
929 break;
933 return luaA_pusharea(L, (*wibox)->sw.geometry);
936 /** Wibox newindex.
937 * \param L The Lua VM state.
938 * \return The number of elements pushed on stack.
940 static int
941 luaA_wibox_newindex(lua_State *L)
943 size_t len;
944 wibox_t **wibox = luaA_checkudata(L, 1, "wibox");
945 const char *buf, *attr = luaL_checklstring(L, 2, &len);
946 awesome_token_t tok;
948 switch((tok = a_tokenize(attr, len)))
950 bool b;
952 case A_TK_FG:
953 if((buf = luaL_checklstring(L, 3, &len)))
954 if(xcolor_init_reply(xcolor_init_unchecked(&(*wibox)->sw.ctx.fg, buf, len)))
955 (*wibox)->need_update = true;
956 break;
957 case A_TK_BG:
958 if((buf = luaL_checklstring(L, 3, &len)))
959 if(xcolor_init_reply(xcolor_init_unchecked(&(*wibox)->sw.ctx.bg, buf, len)))
960 (*wibox)->need_update = true;
961 break;
962 case A_TK_ALIGN:
963 buf = luaL_checklstring(L, 3, &len);
964 (*wibox)->align = draw_align_fromstr(buf, len);
965 switch((*wibox)->type)
967 case WIBOX_TYPE_NORMAL:
968 wibox_position_update(*wibox);
969 break;
970 case WIBOX_TYPE_TITLEBAR:
971 titlebar_update_geometry(client_getbytitlebar(*wibox));
972 break;
974 break;
975 case A_TK_POSITION:
976 switch((*wibox)->type)
978 case WIBOX_TYPE_TITLEBAR:
979 return luaA_titlebar_newindex(L, *wibox, tok);
980 case WIBOX_TYPE_NORMAL:
981 if((buf = luaL_checklstring(L, 3, &len)))
982 wibox_setposition(*wibox, position_fromstr(buf, len));
983 break;
985 break;
986 case A_TK_CLIENT:
987 /* first detach */
988 if(lua_isnil(L, 3))
989 titlebar_client_detach(client_getbytitlebar(*wibox));
990 else
992 client_t **c = luaA_checkudata(L, 3, "client");
993 titlebar_client_attach(*c, *wibox);
995 break;
996 case A_TK_CURSOR:
997 if((buf = luaL_checkstring(L, 3)))
999 uint16_t cursor_font = xcursor_font_fromstr(buf);
1000 if(cursor_font)
1002 xcb_cursor_t cursor = xcursor_new(globalconf.connection, cursor_font);
1003 p_delete(&(*wibox)->cursor);
1004 (*wibox)->cursor = a_strdup(buf);
1005 simplewindow_cursor_set(&(*wibox)->sw, cursor);
1008 break;
1009 case A_TK_SCREEN:
1010 if(lua_isnil(L, 3))
1012 wibox_detach(*wibox);
1013 titlebar_client_detach(client_getbytitlebar(*wibox));
1015 else
1017 int screen = luaL_checknumber(L, 3) - 1;
1018 luaA_checkscreen(screen);
1019 if(screen != (*wibox)->screen)
1021 titlebar_client_detach(client_getbytitlebar(*wibox));
1022 wibox_attach(*wibox, &globalconf.screens[screen]);
1025 break;
1026 case A_TK_ONTOP:
1027 b = luaA_checkboolean(L, 3);
1028 if(b != (*wibox)->ontop)
1030 (*wibox)->ontop = b;
1031 client_stack();
1033 break;
1034 case A_TK_ORIENTATION:
1035 if((buf = luaL_checklstring(L, 3, &len)))
1037 simplewindow_orientation_set(&(*wibox)->sw, orientation_fromstr(buf, len));
1038 (*wibox)->need_update = true;
1039 (*wibox)->mouse_over = NULL;
1041 break;
1042 case A_TK_BORDER_COLOR:
1043 if((buf = luaL_checklstring(L, 3, &len)))
1044 if(xcolor_init_reply(xcolor_init_unchecked(&(*wibox)->sw.border.color, buf, len)))
1045 if((*wibox)->sw.window)
1046 simplewindow_border_color_set(&(*wibox)->sw, &(*wibox)->sw.border.color);
1047 break;
1048 case A_TK_VISIBLE:
1049 b = luaA_checkboolean(L, 3);
1050 if(b != (*wibox)->isvisible)
1051 switch((*wibox)->type)
1053 case WIBOX_TYPE_NORMAL:
1054 wibox_setvisible(*wibox, b);
1055 break;
1056 case WIBOX_TYPE_TITLEBAR:
1057 titlebar_set_visible(*wibox, b);
1058 break;
1060 break;
1061 case A_TK_WIDGETS:
1062 if(luaA_isloop(L, 3))
1064 luaA_warn(L, "table is looping, cannot use this as widget table");
1065 return 0;
1067 luaA_register(L, 3, &(*wibox)->widgets_table);
1068 /* recompute widget node list */
1069 wibox_widgets_table_build(L, *wibox);
1070 luaA_table2wtable(L);
1071 break;
1072 case A_TK_OPACITY:
1073 if(lua_isnil(L, 3))
1074 window_opacity_set((*wibox)->sw.window, -1);
1075 else
1077 double d = luaL_checknumber(L, 3);
1078 if(d >= 0 && d <= 1)
1079 window_opacity_set((*wibox)->sw.window, d);
1081 break;
1082 default:
1083 switch((*wibox)->type)
1085 case WIBOX_TYPE_TITLEBAR:
1086 return luaA_titlebar_newindex(L, *wibox, tok);
1087 case WIBOX_TYPE_NORMAL:
1088 break;
1092 return 0;
1095 /** Get or set mouse buttons bindings to a wibox.
1096 * \param L The Lua VM state.
1097 * \luastack
1098 * \lvalue A wibox.
1099 * \lparam An array of mouse button bindings objects, or nothing.
1100 * \return The array of mouse button bindings objects of this wibox.
1102 static int
1103 luaA_wibox_buttons(lua_State *L)
1105 wibox_t **wibox = luaA_checkudata(L, 1, "wibox");
1106 button_array_t *buttons = &(*wibox)->buttons;
1108 if(lua_gettop(L) == 2)
1110 luaA_button_array_set(L, 2, buttons);
1111 return 1;
1114 return luaA_button_array_get(L, buttons);
1117 const struct luaL_reg awesome_wibox_methods[] =
1119 { "__call", luaA_wibox_new },
1120 { NULL, NULL }
1122 const struct luaL_reg awesome_wibox_meta[] =
1124 { "buttons", luaA_wibox_buttons },
1125 { "geometry", luaA_wibox_geometry },
1126 { "__index", luaA_wibox_index },
1127 { "__newindex", luaA_wibox_newindex },
1128 { "__gc", luaA_wibox_gc },
1129 { "__eq", luaA_wibox_eq },
1130 { "__tostring", luaA_wibox_tostring },
1131 { NULL, NULL },
1134 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80