wibox: add ontop as possible opt in constructor
[awesome.git] / wibox.c
blob037044051981ec8484f62c6b3e9d572e0a924559
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"
30 extern awesome_t globalconf;
32 DO_LUA_NEW(extern, wibox_t, wibox, "wibox", wibox_ref)
33 DO_LUA_GC(wibox_t, wibox, "wibox", wibox_unref)
34 DO_LUA_EQ(wibox_t, wibox, "wibox")
36 static void
37 wibox_move(wibox_t *wibox, int16_t x, int16_t y)
39 if(wibox->sw.window)
41 simplewindow_move(&wibox->sw, x, y);
42 wibox->screen = screen_getbycoord(wibox->screen, x, y);
44 else
46 wibox->sw.geometry.x = x;
47 wibox->sw.geometry.y = y;
51 static void
52 wibox_resize(wibox_t *wibox, uint16_t width, uint16_t height)
54 if(wibox->sw.window)
55 simplewindow_resize(&wibox->sw, width, height);
56 else
58 wibox->sw.geometry.width = width;
59 wibox->sw.geometry.height = height;
61 wibox->need_update = true;
64 static void
65 wibox_setposition(wibox_t *wibox, position_t p)
67 if(p != wibox->position)
69 switch((wibox->position = p))
71 case Bottom:
72 case Top:
73 case Floating:
74 simplewindow_orientation_set(&wibox->sw, East);
75 break;
76 case Left:
77 simplewindow_orientation_set(&wibox->sw, North);
78 break;
79 case Right:
80 simplewindow_orientation_set(&wibox->sw, South);
81 break;
83 /* reset width/height to 0 */
84 if(wibox->position != Floating)
85 wibox->sw.geometry.width = wibox->sw.geometry.height = 0;
87 /* recompute position */
88 wibox_position_update(wibox);
90 /* reset all wibox position */
91 wibox_array_t *w = &globalconf.screens[wibox->screen].wiboxes;
92 for(int i = 0; i < w->len; i++)
93 wibox_position_update(w->tab[i]);
95 ewmh_update_workarea(screen_virttophys(wibox->screen));
97 wibox->need_update = true;
101 /** Kick out systray windows.
102 * \param phys_screen Physical screen number.
104 static void
105 wibox_systray_kickout(int phys_screen)
107 xcb_screen_t *s = xutil_screen_get(globalconf.connection, phys_screen);
109 /* Who! Check that we're not deleting a wibox with a systray, because it
110 * may be its parent. If so, we reparent to root before, otherwise it will
111 * hurt very much. */
112 xcb_reparent_window(globalconf.connection,
113 globalconf.screens[phys_screen].systray.window,
114 s->root, -512, -512);
116 globalconf.screens[phys_screen].systray.parent = s->root;
119 static void
120 wibox_systray_refresh(wibox_t *wibox)
122 if(wibox->screen == SCREEN_UNDEF)
123 return;
125 for(int i = 0; i < wibox->widgets.len; i++)
127 widget_node_t *systray = &wibox->widgets.tab[i];
128 if(systray->widget->type == widget_systray)
130 uint32_t config_back[] = { wibox->sw.ctx.bg.pixel };
131 uint32_t config_win_vals[4];
132 uint32_t config_win_vals_off[2] = { -512, -512 };
133 xembed_window_t *em;
134 position_t pos;
135 int phys_screen = wibox->sw.ctx.phys_screen;
137 if(wibox->isvisible
138 && systray->widget->isvisible
139 && systray->geometry.width)
141 pos = wibox->position;
143 /* Set background of the systray window. */
144 xcb_change_window_attributes(globalconf.connection,
145 globalconf.screens[phys_screen].systray.window,
146 XCB_CW_BACK_PIXEL, config_back);
147 /* Map it. */
148 xcb_map_window(globalconf.connection, globalconf.screens[phys_screen].systray.window);
149 /* Move it. */
150 switch(wibox->position)
152 case Left:
153 config_win_vals[0] = systray->geometry.y;
154 config_win_vals[1] = wibox->sw.geometry.height - systray->geometry.x - systray->geometry.width;
155 config_win_vals[2] = systray->geometry.height;
156 config_win_vals[3] = systray->geometry.width;
157 break;
158 case Right:
159 config_win_vals[0] = systray->geometry.y;
160 config_win_vals[1] = systray->geometry.x;
161 config_win_vals[2] = systray->geometry.height;
162 config_win_vals[3] = systray->geometry.width;
163 break;
164 default:
165 config_win_vals[0] = systray->geometry.x;
166 config_win_vals[1] = systray->geometry.y;
167 config_win_vals[2] = systray->geometry.width;
168 config_win_vals[3] = systray->geometry.height;
169 break;
171 /* reparent */
172 if(globalconf.screens[phys_screen].systray.parent != wibox->sw.window)
174 xcb_reparent_window(globalconf.connection,
175 globalconf.screens[phys_screen].systray.window,
176 wibox->sw.window,
177 config_win_vals[0], config_win_vals[1]);
178 globalconf.screens[phys_screen].systray.parent = wibox->sw.window;
180 xcb_configure_window(globalconf.connection,
181 globalconf.screens[phys_screen].systray.window,
182 XCB_CONFIG_WINDOW_X
183 | XCB_CONFIG_WINDOW_Y
184 | XCB_CONFIG_WINDOW_WIDTH
185 | XCB_CONFIG_WINDOW_HEIGHT,
186 config_win_vals);
187 /* width = height = systray height */
188 config_win_vals[2] = config_win_vals[3] = systray->geometry.height;
189 config_win_vals[0] = 0;
191 else
192 return wibox_systray_kickout(phys_screen);
194 switch(pos)
196 case Left:
197 config_win_vals[1] = systray->geometry.width - config_win_vals[3];
198 for(int j = 0; j < globalconf.embedded.len; j++)
200 em = &globalconf.embedded.tab[j];
201 if(em->phys_screen == phys_screen)
203 if(config_win_vals[1] - config_win_vals[2] >= (uint32_t) wibox->sw.geometry.y)
205 xcb_map_window(globalconf.connection, em->win);
206 xcb_configure_window(globalconf.connection, em->win,
207 XCB_CONFIG_WINDOW_X
208 | XCB_CONFIG_WINDOW_Y
209 | XCB_CONFIG_WINDOW_WIDTH
210 | XCB_CONFIG_WINDOW_HEIGHT,
211 config_win_vals);
212 config_win_vals[1] -= config_win_vals[3];
214 else
215 xcb_configure_window(globalconf.connection, em->win,
216 XCB_CONFIG_WINDOW_X
217 | XCB_CONFIG_WINDOW_Y,
218 config_win_vals_off);
221 break;
222 case Right:
223 config_win_vals[1] = 0;
224 for(int j = 0; j < globalconf.embedded.len; j++)
226 em = &globalconf.embedded.tab[j];
227 if(em->phys_screen == phys_screen)
229 if(config_win_vals[1] + config_win_vals[3] <= (uint32_t) wibox->sw.geometry.y + wibox->sw.geometry.width)
231 xcb_map_window(globalconf.connection, em->win);
232 xcb_configure_window(globalconf.connection, em->win,
233 XCB_CONFIG_WINDOW_X
234 | XCB_CONFIG_WINDOW_Y
235 | XCB_CONFIG_WINDOW_WIDTH
236 | XCB_CONFIG_WINDOW_HEIGHT,
237 config_win_vals);
238 config_win_vals[1] += config_win_vals[3];
240 else
241 xcb_configure_window(globalconf.connection, em->win,
242 XCB_CONFIG_WINDOW_X
243 | XCB_CONFIG_WINDOW_Y,
244 config_win_vals_off);
247 break;
248 case Floating:
249 case Top:
250 case Bottom:
251 config_win_vals[1] = 0;
252 for(int j = 0; j < globalconf.embedded.len; j++)
254 em = &globalconf.embedded.tab[j];
255 if(em->phys_screen == phys_screen)
257 /* if(x + width < systray.x + systray.width) */
258 if(config_win_vals[0] + config_win_vals[2] <= (uint32_t) AREA_RIGHT(systray->geometry) + wibox->sw.geometry.x)
260 xcb_map_window(globalconf.connection, em->win);
261 xcb_configure_window(globalconf.connection, em->win,
262 XCB_CONFIG_WINDOW_X
263 | XCB_CONFIG_WINDOW_Y
264 | XCB_CONFIG_WINDOW_WIDTH
265 | XCB_CONFIG_WINDOW_HEIGHT,
266 config_win_vals);
267 config_win_vals[0] += config_win_vals[2];
269 else
270 xcb_configure_window(globalconf.connection, em->win,
271 XCB_CONFIG_WINDOW_X
272 | XCB_CONFIG_WINDOW_Y,
273 config_win_vals_off);
276 break;
278 break;
283 /** Update the wibox position. It deletes every wibox resources and
284 * create them back.
285 * \param wibox The wibox.
287 void
288 wibox_position_update(wibox_t *wibox)
290 area_t area, wingeom = wibox->sw.geometry;
291 bool ignore = false;
293 globalconf.screens[wibox->screen].need_arrange = true;
295 area = screen_area_get(wibox->screen, NULL,
296 &globalconf.screens[wibox->screen].padding, true);
298 /* Top and Bottom wibox_t have prio */
299 if(wibox->position != Floating)
300 for(int i = 0; i < globalconf.screens[wibox->screen].wiboxes.len; i++)
302 wibox_t *w = globalconf.screens[wibox->screen].wiboxes.tab[i];
303 /* Ignore every wibox after me that is in the same position */
304 if(wibox == w)
306 ignore = true;
307 continue;
309 else if((ignore && wibox->position == w->position) || !w->isvisible)
310 continue;
311 switch(w->position)
313 case Floating:
314 break;
315 case Left:
316 switch(wibox->position)
318 case Left:
319 area.x += wibox->sw.geometry.height;
320 break;
321 default:
322 break;
324 break;
325 case Right:
326 switch(wibox->position)
328 case Right:
329 area.x -= wibox->sw.geometry.height;
330 break;
331 default:
332 break;
334 break;
335 case Top:
336 switch(wibox->position)
338 case Top:
339 area.y += w->sw.geometry.height;
340 break;
341 case Left:
342 case Right:
343 area.height -= w->sw.geometry.height;
344 area.y += w->sw.geometry.height;
345 break;
346 default:
347 break;
349 break;
350 case Bottom:
351 switch(wibox->position)
353 case Bottom:
354 area.y -= w->sw.geometry.height;
355 break;
356 case Left:
357 case Right:
358 area.height -= w->sw.geometry.height;
359 break;
360 default:
361 break;
363 break;
367 /* The "length" of a wibox is always chosen to be the optimal size (non-floating).
368 * The "width" of a wibox is kept if it exists.
370 switch(wibox->position)
372 case Right:
373 wingeom.height = area.height;
374 wingeom.width = wibox->sw.geometry.width > 0 ? wibox->sw.geometry.width : 1.5 * globalconf.font->height;
375 wingeom.x = area.x + area.width - wingeom.width;
376 switch(wibox->align)
378 default:
379 wingeom.y = area.y;
380 break;
381 case AlignRight:
382 wingeom.y = area.y + area.height - wingeom.height;
383 break;
384 case AlignCenter:
385 wingeom.y = (area.y + area.height - wingeom.height) / 2;
386 break;
388 break;
389 case Left:
390 wingeom.height = area.height;
391 wingeom.width = wibox->sw.geometry.width > 0 ? wibox->sw.geometry.width : 1.5 * globalconf.font->height;
392 wingeom.x = area.x;
393 switch(wibox->align)
395 default:
396 wingeom.y = (area.y + area.height) - wingeom.height;
397 break;
398 case AlignRight:
399 wingeom.y = area.y;
400 break;
401 case AlignCenter:
402 wingeom.y = (area.y + area.height - wingeom.height) / 2;
404 break;
405 case Bottom:
406 wingeom.height = wibox->sw.geometry.height > 0 ? wibox->sw.geometry.height : 1.5 * globalconf.font->height;
407 wingeom.width = area.width;
408 wingeom.y = (area.y + area.height) - wingeom.height;
409 wingeom.x = area.x;
410 switch(wibox->align)
412 default:
413 break;
414 case AlignRight:
415 wingeom.x += area.width - wingeom.width;
416 break;
417 case AlignCenter:
418 wingeom.x += (area.width - wingeom.width) / 2;
419 break;
421 break;
422 case Top:
423 wingeom.height = wibox->sw.geometry.height > 0 ? wibox->sw.geometry.height : 1.5 * globalconf.font->height;
424 wingeom.width = area.width;
425 wingeom.x = area.x;
426 wingeom.y = area.y;
427 switch(wibox->align)
429 default:
430 break;
431 case AlignRight:
432 wingeom.x += area.width - wingeom.width;
433 break;
434 case AlignCenter:
435 wingeom.x += (area.width - wingeom.width) / 2;
436 break;
438 break;
439 case Floating:
440 wingeom.width = MAX(1, wibox->sw.geometry.width);
441 wingeom.height = MAX(1, wibox->sw.geometry.height);
442 break;
445 /* same window size and position ? */
446 if(wingeom.width != wibox->sw.geometry.width
447 || wingeom.height != wibox->sw.geometry.height)
448 wibox_resize(wibox, wingeom.width, wingeom.height);
450 if(wingeom.x != wibox->sw.geometry.x
451 || wingeom.y != wibox->sw.geometry.y)
452 wibox_move(wibox, wingeom.x, wingeom.y);
455 /** Delete a wibox.
456 * \param wibox wibox to delete.
458 void
459 wibox_delete(wibox_t **wibox)
461 simplewindow_wipe(&(*wibox)->sw);
462 button_array_wipe(&(*wibox)->buttons);
463 luaL_unref(globalconf.L, LUA_REGISTRYINDEX, (*wibox)->widgets_table);
464 widget_node_array_wipe(&(*wibox)->widgets);
465 p_delete(wibox);
468 /** Get a wibox by its window.
469 * \param w The window id.
470 * \return A wibox if found, NULL otherwise.
472 wibox_t *
473 wibox_getbywin(xcb_window_t w)
475 for(int screen = 0; screen < globalconf.nscreen; screen++)
476 for(int i = 0; i < globalconf.screens[screen].wiboxes.len; i++)
478 wibox_t *s = globalconf.screens[screen].wiboxes.tab[i];
479 if(s->sw.window == w)
480 return s;
483 for(client_t *c = globalconf.clients; c; c = c->next)
484 if(c->titlebar && c->titlebar->sw.window == w)
485 return c->titlebar;
487 return NULL;
490 /** Draw a wibox.
491 * \param wibox The wibox to draw.
493 static void
494 wibox_draw(wibox_t *wibox)
496 if(wibox->isvisible)
498 widget_render(&wibox->widgets, &wibox->sw.ctx, wibox->sw.gc,
499 wibox->sw.pixmap,
500 wibox->screen, wibox->sw.orientation,
501 wibox->sw.geometry.x, wibox->sw.geometry.y,
502 wibox);
503 simplewindow_refresh_pixmap(&wibox->sw);
505 wibox->need_update = false;
508 wibox_systray_refresh(wibox);
511 /** Refresh all wiboxes.
513 void
514 wibox_refresh(void)
516 for(int screen = 0; screen < globalconf.nscreen; screen++)
517 for(int i = 0; i < globalconf.screens[screen].wiboxes.len; i++)
519 wibox_t *s = globalconf.screens[screen].wiboxes.tab[i];
520 if(s->need_update)
521 wibox_draw(s);
524 for(client_t *c = globalconf.clients; c; c = c->next)
525 if(c->titlebar && c->titlebar->need_update)
526 wibox_draw(c->titlebar);
529 /** Reposition all wiboxes.
531 void
532 wibox_update_positions(void)
534 for(int screen = 0; screen < globalconf.nscreen; screen++)
535 for(int i = 0; i < globalconf.screens[screen].wiboxes.len; i++)
537 wibox_t *s = globalconf.screens[screen].wiboxes.tab[i];
538 wibox_position_update(s);
542 /** Set a wibox visible or not.
543 * \param wibox The wibox.
544 * \param v The visible value.
546 static void
547 wibox_setvisible(wibox_t *wibox, bool v)
549 if(v != wibox->isvisible)
551 wibox->isvisible = v;
552 wibox->mouse_over = NULL;
554 if(wibox->screen != SCREEN_UNDEF)
556 if(wibox->isvisible)
558 xcb_map_window(globalconf.connection, wibox->sw.window);
559 simplewindow_refresh_pixmap(&wibox->sw);
560 /* stack correctly the wibox */
561 client_stack();
563 else
564 xcb_unmap_window(globalconf.connection, wibox->sw.window);
566 /* kick out systray if needed */
567 wibox_systray_refresh(wibox);
569 /* All the other wibox and ourselves need to be repositioned */
570 wibox_array_t *w = &globalconf.screens[wibox->screen].wiboxes;
571 for(int i = 0; i < w->len; i++)
572 wibox_position_update(w->tab[i]);
577 /** Remove a wibox from a screen.
578 * \param wibox Wibox to detach from screen.
580 void
581 wibox_detach(wibox_t *wibox)
583 if(wibox->screen != SCREEN_UNDEF)
585 bool v;
587 /* save visible state */
588 v = wibox->isvisible;
589 wibox->isvisible = false;
590 wibox_systray_refresh(wibox);
591 wibox_position_update(wibox);
592 /* restore position */
593 wibox->isvisible = v;
595 wibox->mouse_over = NULL;
597 simplewindow_wipe(&wibox->sw);
599 for(int i = 0; i < globalconf.screens[wibox->screen].wiboxes.len; i++)
600 if(globalconf.screens[wibox->screen].wiboxes.tab[i] == wibox)
602 wibox_array_take(&globalconf.screens[wibox->screen].wiboxes, i);
603 break;
605 globalconf.screens[wibox->screen].need_arrange = true;
606 wibox->screen = SCREEN_UNDEF;
607 wibox_unref(&wibox);
611 /** Attach a wibox.
612 * \param wibox The wibox to attach.
613 * \param s The screen to attach the wibox to.
615 void
616 wibox_attach(wibox_t *wibox, screen_t *s)
618 int phys_screen = screen_virttophys(s->index);
620 wibox_detach(wibox);
622 /* Set the wibox screen */
623 wibox->screen = s->index;
625 /* Check that the wibox coordinates matches the screen. */
626 int cscreen = screen_getbycoord(wibox->screen, wibox->sw.geometry.x, wibox->sw.geometry.y);
628 /* If it does not match, move it to the screen coordinates */
629 if(cscreen != wibox->screen)
630 wibox_move(wibox, s->geometry.x, s->geometry.y);
632 wibox_array_append(&s->wiboxes, wibox_ref(&wibox));
634 /* compute x/y/width/height if not set */
635 wibox_position_update(wibox);
637 simplewindow_init(&wibox->sw, phys_screen,
638 wibox->sw.geometry,
639 wibox->sw.border.width,
640 wibox->sw.orientation,
641 &wibox->sw.ctx.fg, &wibox->sw.ctx.bg);
643 simplewindow_border_color_set(&wibox->sw, &wibox->sw.border.color);
645 simplewindow_cursor_set(&wibox->sw,
646 xcursor_new(globalconf.connection, xcursor_font_fromstr(wibox->cursor)));
648 /* All the other wibox and ourselves need to be repositioned */
649 for(int i = 0; i < s->wiboxes.len; i++)
650 wibox_position_update(s->wiboxes.tab[i]);
652 ewmh_update_workarea(screen_virttophys(s->index));
654 if(wibox->isvisible)
656 /* draw it right now once to avoid garbage shown */
657 wibox_draw(wibox);
658 xcb_map_window(globalconf.connection, wibox->sw.window);
659 simplewindow_refresh_pixmap(&wibox->sw);
660 /* stack correctly the wibox */
661 client_stack();
663 else
664 wibox->need_update = true;
667 /** Create a new wibox.
668 * \param L The Lua VM state.
670 * \luastack
671 * \lparam A table with optionaly defined values:
672 * position, align, fg, bg, border_width, border_color, ontop, width and height.
673 * \lreturn A brand new wibox.
676 luaA_wibox_new(lua_State *L)
678 wibox_t *w;
679 const char *buf;
680 size_t len;
681 xcolor_init_request_t reqs[3];
682 int8_t i, reqs_nbr = -1;
684 luaA_checktable(L, 2);
686 w = p_new(wibox_t, 1);
687 w->widgets_table = LUA_REFNIL;
689 w->sw.ctx.fg = globalconf.colors.fg;
690 if((buf = luaA_getopt_lstring(L, 2, "fg", NULL, &len)))
691 reqs[++reqs_nbr] = xcolor_init_unchecked(&w->sw.ctx.fg, buf, len);
693 w->sw.ctx.bg = globalconf.colors.bg;
694 if((buf = luaA_getopt_lstring(L, 2, "bg", NULL, &len)))
695 reqs[++reqs_nbr] = xcolor_init_unchecked(&w->sw.ctx.bg, buf, len);
697 w->sw.border.color = globalconf.colors.bg;
698 if((buf = luaA_getopt_lstring(L, 2, "border_color", NULL, &len)))
699 reqs[++reqs_nbr] = xcolor_init_unchecked(&w->sw.border.color, buf, len);
701 w->ontop = luaA_getopt_boolean(L, 2, "ontop", false);
703 buf = luaA_getopt_lstring(L, 2, "align", "left", &len);
704 w->align = draw_align_fromstr(buf, len);
706 w->sw.border.width = luaA_getopt_number(L, 2, "border_width", 0);
708 buf = luaA_getopt_lstring(L, 2, "position", "top", &len);
710 switch((w->position = position_fromstr(buf, len)))
712 case Bottom:
713 case Top:
714 case Floating:
715 simplewindow_orientation_set(&w->sw, East);
716 break;
717 case Left:
718 simplewindow_orientation_set(&w->sw, North);
719 break;
720 case Right:
721 simplewindow_orientation_set(&w->sw, South);
722 break;
725 /* recompute position */
726 wibox_position_update(w);
728 w->sw.geometry.x = luaA_getopt_number(L, 2, "x", 0);
729 w->sw.geometry.y = luaA_getopt_number(L, 2, "y", 0);
730 w->sw.geometry.width = luaA_getopt_number(L, 2, "width", 0);
731 w->sw.geometry.height = luaA_getopt_number(L, 2, "height", 0);
733 w->screen = SCREEN_UNDEF;
734 w->isvisible = true;
735 w->cursor = a_strdup("left_ptr");
737 for(i = 0; i <= reqs_nbr; i++)
738 xcolor_init_reply(reqs[i]);
740 return luaA_wibox_userdata_new(L, w);
743 /** Rebuild wibox widgets list.
744 * \param L The Lua VM state.
745 * \param wibox The wibox.
747 static void
748 wibox_widgets_table_build(lua_State *L, wibox_t *wibox)
750 widget_node_array_wipe(&wibox->widgets);
751 widget_node_array_init(&wibox->widgets);
752 luaA_table2widgets(L, &wibox->widgets);
753 wibox->mouse_over = NULL;
754 wibox->need_update = true;
757 /** Check if a wibox widget table has an item.
758 * \param L The Lua VM state.
759 * \param wibox The wibox.
760 * \param item The item to look for.
762 static bool
763 luaA_wibox_hasitem(lua_State *L, wibox_t *wibox, const void *item)
765 if(wibox->widgets_table != LUA_REFNIL)
767 lua_rawgeti(globalconf.L, LUA_REGISTRYINDEX, wibox->widgets_table);
768 if(lua_topointer(L, -1) == item || luaA_hasitem(L, item))
769 return true;
771 return false;
774 /** Invalidate a wibox by a Lua object (table, etc).
775 * \param L The Lua VM state.
776 * \param item The object identifier.
778 void
779 luaA_wibox_invalidate_byitem(lua_State *L, const void *item)
781 for(int screen = 0; screen < globalconf.nscreen; screen++)
782 for(int i = 0; i < globalconf.screens[screen].wiboxes.len; i++)
784 wibox_t *wibox = globalconf.screens[screen].wiboxes.tab[i];
785 if(luaA_wibox_hasitem(L, wibox, item))
787 /* recompute widget node list */
788 wibox_widgets_table_build(L, wibox);
789 lua_pop(L, 1); /* remove widgets table */
794 for(client_t *c = globalconf.clients; c; c = c->next)
795 if(c->titlebar && luaA_wibox_hasitem(L, c->titlebar, item))
797 /* recompute widget node list */
798 wibox_widgets_table_build(L, c->titlebar);
799 lua_pop(L, 1); /* remove widgets table */
803 /** Wibox object.
804 * \param L The Lua VM state.
805 * \return The number of elements pushed on stack.
806 * \luastack
807 * \lfield screen Screen number.
808 * \lfield client The client attached to this titlebar.
809 * \lfield border_width Border width.
810 * \lfield border_color Border color.
811 * \lfield align The alignment.
812 * \lfield fg Foreground color.
813 * \lfield bg Background color.
814 * \lfield position The position.
815 * \lfield ontop On top of other windows.
816 * \lfield cursor The mouse cursor.
818 static int
819 luaA_wibox_index(lua_State *L)
821 size_t len;
822 wibox_t **wibox = luaA_checkudata(L, 1, "wibox");
823 const char *attr = luaL_checklstring(L, 2, &len);
825 if(luaA_usemetatable(L, 1, 2))
826 return 1;
828 switch(a_tokenize(attr, len))
830 client_t *c;
832 case A_TK_VISIBLE:
833 lua_pushboolean(L, (*wibox)->isvisible);
834 break;
835 case A_TK_CLIENT:
836 if((c = client_getbytitlebar(*wibox)))
837 return luaA_client_userdata_new(L, c);
838 else
839 return 0;
840 case A_TK_SCREEN:
841 if((*wibox)->screen == SCREEN_UNDEF)
842 return 0;
843 lua_pushnumber(L, (*wibox)->screen + 1);
844 break;
845 case A_TK_BORDER_WIDTH:
846 lua_pushnumber(L, (*wibox)->sw.border.width);
847 break;
848 case A_TK_BORDER_COLOR:
849 luaA_pushcolor(L, &(*wibox)->sw.border.color);
850 break;
851 case A_TK_ALIGN:
852 lua_pushstring(L, draw_align_tostr((*wibox)->align));
853 break;
854 case A_TK_FG:
855 luaA_pushcolor(L, &(*wibox)->sw.ctx.fg);
856 break;
857 case A_TK_BG:
858 luaA_pushcolor(L, &(*wibox)->sw.ctx.bg);
859 break;
860 case A_TK_POSITION:
861 lua_pushstring(L, position_tostr((*wibox)->position));
862 break;
863 case A_TK_ONTOP:
864 lua_pushboolean(L, (*wibox)->ontop);
865 break;
866 case A_TK_ORIENTATION:
867 lua_pushstring(L, orientation_tostr((*wibox)->sw.orientation));
868 break;
869 case A_TK_WIDGETS:
870 if((*wibox)->widgets_table != LUA_REFNIL)
871 lua_rawgeti(L, LUA_REGISTRYINDEX, (*wibox)->widgets_table);
872 else
873 lua_pushnil(L);
874 break;
875 case A_TK_CURSOR:
876 lua_pushstring(L, (*wibox)->cursor);
877 break;
878 default:
879 return 0;
882 return 1;
885 /* Set or get the wibox geometry.
886 * \param L The Lua VM state.
887 * \return The number of elements pushed on stack.
888 * \luastack
889 * \lparam An optional table with wibox geometry.
890 * \lreturn The wibox geometry.
892 static int
893 luaA_wibox_geometry(lua_State *L)
895 wibox_t **wibox = luaA_checkudata(L, 1, "wibox");
897 if(lua_gettop(L) == 2)
899 area_t wingeom;
901 luaA_checktable(L, 2);
902 wingeom.x = luaA_getopt_number(L, 2, "x", (*wibox)->sw.geometry.x);
903 wingeom.y = luaA_getopt_number(L, 2, "y", (*wibox)->sw.geometry.y);
904 wingeom.width = luaA_getopt_number(L, 2, "width", (*wibox)->sw.geometry.width);
905 wingeom.height = luaA_getopt_number(L, 2, "height", (*wibox)->sw.geometry.height);
907 switch((*wibox)->type)
909 case WIBOX_TYPE_TITLEBAR:
910 wibox_resize(*wibox, wingeom.width, wingeom.height);
911 break;
912 case WIBOX_TYPE_NORMAL:
913 if((*wibox)->position == Floating)
914 wibox_moveresize(*wibox, wingeom);
915 else if(wingeom.width != (*wibox)->sw.geometry.width
916 || wingeom.height != (*wibox)->sw.geometry.height)
918 wibox_resize(*wibox, wingeom.width, wingeom.height);
919 globalconf.screens[(*wibox)->screen].need_arrange = true;
921 break;
925 return luaA_pusharea(L, (*wibox)->sw.geometry);
928 /** Wibox newindex.
929 * \param L The Lua VM state.
930 * \return The number of elements pushed on stack.
932 static int
933 luaA_wibox_newindex(lua_State *L)
935 size_t len;
936 wibox_t **wibox = luaA_checkudata(L, 1, "wibox");
937 const char *buf, *attr = luaL_checklstring(L, 2, &len);
938 awesome_token_t tok;
940 switch((tok = a_tokenize(attr, len)))
942 bool b;
944 case A_TK_FG:
945 if((buf = luaL_checklstring(L, 3, &len)))
946 if(xcolor_init_reply(xcolor_init_unchecked(&(*wibox)->sw.ctx.fg, buf, len)))
947 (*wibox)->need_update = true;
948 break;
949 case A_TK_BG:
950 if((buf = luaL_checklstring(L, 3, &len)))
951 if(xcolor_init_reply(xcolor_init_unchecked(&(*wibox)->sw.ctx.bg, buf, len)))
952 (*wibox)->need_update = true;
953 break;
954 case A_TK_ALIGN:
955 buf = luaL_checklstring(L, 3, &len);
956 (*wibox)->align = draw_align_fromstr(buf, len);
957 switch((*wibox)->type)
959 case WIBOX_TYPE_NORMAL:
960 wibox_position_update(*wibox);
961 break;
962 case WIBOX_TYPE_TITLEBAR:
963 titlebar_update_geometry(client_getbytitlebar(*wibox));
964 break;
966 break;
967 case A_TK_POSITION:
968 switch((*wibox)->type)
970 case WIBOX_TYPE_TITLEBAR:
971 return luaA_titlebar_newindex(L, *wibox, tok);
972 case WIBOX_TYPE_NORMAL:
973 if((buf = luaL_checklstring(L, 3, &len)))
974 wibox_setposition(*wibox, position_fromstr(buf, len));
975 break;
977 break;
978 case A_TK_CLIENT:
979 /* first detach */
980 if(lua_isnil(L, 3))
981 titlebar_client_detach(client_getbytitlebar(*wibox));
982 else
984 client_t **c = luaA_checkudata(L, 3, "client");
985 titlebar_client_attach(*c, *wibox);
987 break;
988 case A_TK_CURSOR:
989 if((buf = luaL_checkstring(L, 3)))
991 uint16_t cursor_font = xcursor_font_fromstr(buf);
992 if(cursor_font)
994 xcb_cursor_t cursor = xcursor_new(globalconf.connection, cursor_font);
995 p_delete(&(*wibox)->cursor);
996 (*wibox)->cursor = a_strdup(buf);
997 simplewindow_cursor_set(&(*wibox)->sw, cursor);
1000 break;
1001 case A_TK_SCREEN:
1002 if(lua_isnil(L, 3))
1004 wibox_detach(*wibox);
1005 titlebar_client_detach(client_getbytitlebar(*wibox));
1007 else
1009 int screen = luaL_checknumber(L, 3) - 1;
1010 luaA_checkscreen(screen);
1011 if(screen != (*wibox)->screen)
1013 titlebar_client_detach(client_getbytitlebar(*wibox));
1014 wibox_attach(*wibox, &globalconf.screens[screen]);
1017 break;
1018 case A_TK_ONTOP:
1019 b = luaA_checkboolean(L, 3);
1020 if(b != (*wibox)->ontop)
1022 (*wibox)->ontop = b;
1023 client_stack();
1025 break;
1026 case A_TK_ORIENTATION:
1027 if((buf = luaL_checklstring(L, 3, &len)))
1029 simplewindow_orientation_set(&(*wibox)->sw, orientation_fromstr(buf, len));
1030 (*wibox)->need_update = true;
1032 break;
1033 case A_TK_BORDER_COLOR:
1034 if((buf = luaL_checklstring(L, 3, &len)))
1035 if(xcolor_init_reply(xcolor_init_unchecked(&(*wibox)->sw.border.color, buf, len)))
1036 if((*wibox)->sw.window)
1037 simplewindow_border_color_set(&(*wibox)->sw, &(*wibox)->sw.border.color);
1038 break;
1039 case A_TK_VISIBLE:
1040 b = luaA_checkboolean(L, 3);
1041 if(b != (*wibox)->isvisible)
1042 switch((*wibox)->type)
1044 case WIBOX_TYPE_NORMAL:
1045 wibox_setvisible(*wibox, b);
1046 break;
1047 case WIBOX_TYPE_TITLEBAR:
1048 titlebar_set_visible(*wibox, b);
1049 break;
1051 break;
1052 case A_TK_WIDGETS:
1053 if(luaA_isloop(L, 3))
1055 luaA_warn(L, "table is looping, cannot use this as widget table");
1056 return 0;
1058 luaA_register(L, 3, &(*wibox)->widgets_table);
1059 /* recompute widget node list */
1060 wibox_widgets_table_build(L, *wibox);
1061 luaA_table2wtable(L);
1062 break;
1063 default:
1064 switch((*wibox)->type)
1066 case WIBOX_TYPE_TITLEBAR:
1067 return luaA_titlebar_newindex(L, *wibox, tok);
1068 case WIBOX_TYPE_NORMAL:
1069 break;
1073 return 0;
1076 /** Get or set mouse buttons bindings to a wibox.
1077 * \param L The Lua VM state.
1078 * \luastack
1079 * \lvalue A wibox.
1080 * \lparam An array of mouse button bindings objects, or nothing.
1081 * \return The array of mouse button bindings objects of this wibox.
1083 static int
1084 luaA_wibox_buttons(lua_State *L)
1086 wibox_t **wibox = luaA_checkudata(L, 1, "wibox");
1087 button_array_t *buttons = &(*wibox)->buttons;
1089 if(lua_gettop(L) == 2)
1091 luaA_button_array_set(L, 2, buttons);
1092 return 1;
1095 return luaA_button_array_get(L, buttons);
1098 const struct luaL_reg awesome_wibox_methods[] =
1100 { "__call", luaA_wibox_new },
1101 { NULL, NULL }
1103 const struct luaL_reg awesome_wibox_meta[] =
1105 { "buttons", luaA_wibox_buttons },
1106 { "geometry", luaA_wibox_geometry },
1107 { "__index", luaA_wibox_index },
1108 { "__newindex", luaA_wibox_newindex },
1109 { "__gc", luaA_wibox_gc },
1110 { "__eq", luaA_wibox_eq },
1111 { "__tostring", luaA_wibox_tostring },
1112 { NULL, NULL },
1115 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80