wibox: check coordinates and screen attributes match
[awesome.git] / wibox.c
blob79c32c8e2b8b63cebe562cf326607ee79d7e6f19
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, 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 buf = luaA_getopt_lstring(L, 2, "align", "left", &len);
702 w->align = draw_align_fromstr(buf, len);
704 w->sw.border.width = luaA_getopt_number(L, 2, "border_width", 0);
706 buf = luaA_getopt_lstring(L, 2, "position", "top", &len);
708 switch((w->position = position_fromstr(buf, len)))
710 case Bottom:
711 case Top:
712 case Floating:
713 simplewindow_orientation_set(&w->sw, East);
714 break;
715 case Left:
716 simplewindow_orientation_set(&w->sw, North);
717 break;
718 case Right:
719 simplewindow_orientation_set(&w->sw, South);
720 break;
723 /* recompute position */
724 wibox_position_update(w);
726 w->sw.geometry.x = luaA_getopt_number(L, 2, "x", 0);
727 w->sw.geometry.y = luaA_getopt_number(L, 2, "y", 0);
728 w->sw.geometry.width = luaA_getopt_number(L, 2, "width", 0);
729 w->sw.geometry.height = luaA_getopt_number(L, 2, "height", 0);
731 w->screen = SCREEN_UNDEF;
732 w->isvisible = true;
733 w->cursor = a_strdup("left_ptr");
735 for(i = 0; i <= reqs_nbr; i++)
736 xcolor_init_reply(reqs[i]);
738 return luaA_wibox_userdata_new(L, w);
741 /** Rebuild wibox widgets list.
742 * \param L The Lua VM state.
743 * \param wibox The wibox.
745 static void
746 wibox_widgets_table_build(lua_State *L, wibox_t *wibox)
748 widget_node_array_wipe(&wibox->widgets);
749 widget_node_array_init(&wibox->widgets);
750 luaA_table2widgets(L, &wibox->widgets);
751 wibox->mouse_over = NULL;
752 wibox->need_update = true;
755 /** Check if a wibox widget table has an item.
756 * \param L The Lua VM state.
757 * \param wibox The wibox.
758 * \param item The item to look for.
760 static bool
761 luaA_wibox_hasitem(lua_State *L, wibox_t *wibox, const void *item)
763 if(wibox->widgets_table != LUA_REFNIL)
765 lua_rawgeti(globalconf.L, LUA_REGISTRYINDEX, wibox->widgets_table);
766 if(lua_topointer(L, -1) == item || luaA_hasitem(L, item))
767 return true;
769 return false;
772 /** Invalidate a wibox by a Lua object (table, etc).
773 * \param L The Lua VM state.
774 * \param item The object identifier.
776 void
777 luaA_wibox_invalidate_byitem(lua_State *L, const void *item)
779 for(int screen = 0; screen < globalconf.nscreen; screen++)
780 for(int i = 0; i < globalconf.screens[screen].wiboxes.len; i++)
782 wibox_t *wibox = globalconf.screens[screen].wiboxes.tab[i];
783 if(luaA_wibox_hasitem(L, wibox, item))
785 /* recompute widget node list */
786 wibox_widgets_table_build(L, wibox);
787 lua_pop(L, 1); /* remove widgets table */
792 for(client_t *c = globalconf.clients; c; c = c->next)
793 if(c->titlebar && luaA_wibox_hasitem(L, c->titlebar, item))
795 /* recompute widget node list */
796 wibox_widgets_table_build(L, c->titlebar);
797 lua_pop(L, 1); /* remove widgets table */
801 /** Wibox object.
802 * \param L The Lua VM state.
803 * \return The number of elements pushed on stack.
804 * \luastack
805 * \lfield screen Screen number.
806 * \lfield client The client attached to this titlebar.
807 * \lfield border_width Border width.
808 * \lfield border_color Border color.
809 * \lfield align The alignment.
810 * \lfield fg Foreground color.
811 * \lfield bg Background color.
812 * \lfield position The position.
813 * \lfield ontop On top of other windows.
814 * \lfield cursor The mouse cursor.
816 static int
817 luaA_wibox_index(lua_State *L)
819 size_t len;
820 wibox_t **wibox = luaA_checkudata(L, 1, "wibox");
821 const char *attr = luaL_checklstring(L, 2, &len);
823 if(luaA_usemetatable(L, 1, 2))
824 return 1;
826 switch(a_tokenize(attr, len))
828 client_t *c;
830 case A_TK_VISIBLE:
831 lua_pushboolean(L, (*wibox)->isvisible);
832 break;
833 case A_TK_CLIENT:
834 if((c = client_getbytitlebar(*wibox)))
835 return luaA_client_userdata_new(L, c);
836 else
837 return 0;
838 case A_TK_SCREEN:
839 if((*wibox)->screen == SCREEN_UNDEF)
840 return 0;
841 lua_pushnumber(L, (*wibox)->screen + 1);
842 break;
843 case A_TK_BORDER_WIDTH:
844 lua_pushnumber(L, (*wibox)->sw.border.width);
845 break;
846 case A_TK_BORDER_COLOR:
847 luaA_pushcolor(L, &(*wibox)->sw.border.color);
848 break;
849 case A_TK_ALIGN:
850 lua_pushstring(L, draw_align_tostr((*wibox)->align));
851 break;
852 case A_TK_FG:
853 luaA_pushcolor(L, &(*wibox)->sw.ctx.fg);
854 break;
855 case A_TK_BG:
856 luaA_pushcolor(L, &(*wibox)->sw.ctx.bg);
857 break;
858 case A_TK_POSITION:
859 lua_pushstring(L, position_tostr((*wibox)->position));
860 break;
861 case A_TK_ONTOP:
862 lua_pushboolean(L, (*wibox)->ontop);
863 break;
864 case A_TK_ORIENTATION:
865 lua_pushstring(L, orientation_tostr((*wibox)->sw.orientation));
866 break;
867 case A_TK_WIDGETS:
868 if((*wibox)->widgets_table != LUA_REFNIL)
869 lua_rawgeti(L, LUA_REGISTRYINDEX, (*wibox)->widgets_table);
870 else
871 lua_pushnil(L);
872 break;
873 case A_TK_CURSOR:
874 lua_pushstring(L, (*wibox)->cursor);
875 break;
876 default:
877 return 0;
880 return 1;
883 /* Set or get the wibox geometry.
884 * \param L The Lua VM state.
885 * \return The number of elements pushed on stack.
886 * \luastack
887 * \lparam An optional table with wibox geometry.
888 * \lreturn The wibox geometry.
890 static int
891 luaA_wibox_geometry(lua_State *L)
893 wibox_t **wibox = luaA_checkudata(L, 1, "wibox");
895 if(lua_gettop(L) == 2)
897 area_t wingeom;
899 luaA_checktable(L, 2);
900 wingeom.x = luaA_getopt_number(L, 2, "x", (*wibox)->sw.geometry.x);
901 wingeom.y = luaA_getopt_number(L, 2, "y", (*wibox)->sw.geometry.y);
902 wingeom.width = luaA_getopt_number(L, 2, "width", (*wibox)->sw.geometry.width);
903 wingeom.height = luaA_getopt_number(L, 2, "height", (*wibox)->sw.geometry.height);
905 switch((*wibox)->type)
907 case WIBOX_TYPE_TITLEBAR:
908 wibox_resize(*wibox, wingeom.width, wingeom.height);
909 break;
910 case WIBOX_TYPE_NORMAL:
911 if((*wibox)->position == Floating)
912 wibox_moveresize(*wibox, wingeom);
913 else if(wingeom.width != (*wibox)->sw.geometry.width
914 || wingeom.height != (*wibox)->sw.geometry.height)
916 wibox_resize(*wibox, wingeom.width, wingeom.height);
917 globalconf.screens[(*wibox)->screen].need_arrange = true;
919 break;
923 return luaA_pusharea(L, (*wibox)->sw.geometry);
926 /** Wibox newindex.
927 * \param L The Lua VM state.
928 * \return The number of elements pushed on stack.
930 static int
931 luaA_wibox_newindex(lua_State *L)
933 size_t len;
934 wibox_t **wibox = luaA_checkudata(L, 1, "wibox");
935 const char *buf, *attr = luaL_checklstring(L, 2, &len);
936 awesome_token_t tok;
938 switch((tok = a_tokenize(attr, len)))
940 bool b;
942 case A_TK_FG:
943 if((buf = luaL_checklstring(L, 3, &len)))
944 if(xcolor_init_reply(xcolor_init_unchecked(&(*wibox)->sw.ctx.fg, buf, len)))
945 (*wibox)->need_update = true;
946 break;
947 case A_TK_BG:
948 if((buf = luaL_checklstring(L, 3, &len)))
949 if(xcolor_init_reply(xcolor_init_unchecked(&(*wibox)->sw.ctx.bg, buf, len)))
950 (*wibox)->need_update = true;
951 break;
952 case A_TK_ALIGN:
953 buf = luaL_checklstring(L, 3, &len);
954 (*wibox)->align = draw_align_fromstr(buf, len);
955 switch((*wibox)->type)
957 case WIBOX_TYPE_NORMAL:
958 wibox_position_update(*wibox);
959 break;
960 case WIBOX_TYPE_TITLEBAR:
961 titlebar_update_geometry(client_getbytitlebar(*wibox));
962 break;
964 break;
965 case A_TK_POSITION:
966 switch((*wibox)->type)
968 case WIBOX_TYPE_TITLEBAR:
969 return luaA_titlebar_newindex(L, *wibox, tok);
970 case WIBOX_TYPE_NORMAL:
971 if((buf = luaL_checklstring(L, 3, &len)))
972 wibox_setposition(*wibox, position_fromstr(buf, len));
973 break;
975 break;
976 case A_TK_CLIENT:
977 /* first detach */
978 if(lua_isnil(L, 3))
979 titlebar_client_detach(client_getbytitlebar(*wibox));
980 else
982 client_t **c = luaA_checkudata(L, 3, "client");
983 titlebar_client_attach(*c, *wibox);
985 break;
986 case A_TK_CURSOR:
987 if((buf = luaL_checkstring(L, 3)))
989 uint16_t cursor_font = xcursor_font_fromstr(buf);
990 if(cursor_font)
992 xcb_cursor_t cursor = xcursor_new(globalconf.connection, cursor_font);
993 p_delete(&(*wibox)->cursor);
994 (*wibox)->cursor = a_strdup(buf);
995 simplewindow_cursor_set(&(*wibox)->sw, cursor);
998 break;
999 case A_TK_SCREEN:
1000 if(lua_isnil(L, 3))
1002 wibox_detach(*wibox);
1003 titlebar_client_detach(client_getbytitlebar(*wibox));
1005 else
1007 int screen = luaL_checknumber(L, 3) - 1;
1008 luaA_checkscreen(screen);
1009 if(screen != (*wibox)->screen)
1011 titlebar_client_detach(client_getbytitlebar(*wibox));
1012 wibox_attach(*wibox, &globalconf.screens[screen]);
1015 break;
1016 case A_TK_ONTOP:
1017 b = luaA_checkboolean(L, 3);
1018 if(b != (*wibox)->ontop)
1020 (*wibox)->ontop = b;
1021 client_stack();
1023 break;
1024 case A_TK_ORIENTATION:
1025 if((buf = luaL_checklstring(L, 3, &len)))
1027 simplewindow_orientation_set(&(*wibox)->sw, orientation_fromstr(buf, len));
1028 (*wibox)->need_update = true;
1030 break;
1031 case A_TK_BORDER_COLOR:
1032 if((buf = luaL_checklstring(L, 3, &len)))
1033 if(xcolor_init_reply(xcolor_init_unchecked(&(*wibox)->sw.border.color, buf, len)))
1034 if((*wibox)->sw.window)
1035 simplewindow_border_color_set(&(*wibox)->sw, &(*wibox)->sw.border.color);
1036 break;
1037 case A_TK_VISIBLE:
1038 b = luaA_checkboolean(L, 3);
1039 if(b != (*wibox)->isvisible)
1040 switch((*wibox)->type)
1042 case WIBOX_TYPE_NORMAL:
1043 wibox_setvisible(*wibox, b);
1044 break;
1045 case WIBOX_TYPE_TITLEBAR:
1046 titlebar_set_visible(*wibox, b);
1047 break;
1049 break;
1050 case A_TK_WIDGETS:
1051 if(luaA_isloop(L, 3))
1053 luaA_warn(L, "table is looping, cannot use this as widget table");
1054 return 0;
1056 luaA_register(L, 3, &(*wibox)->widgets_table);
1057 /* recompute widget node list */
1058 wibox_widgets_table_build(L, *wibox);
1059 luaA_table2wtable(L);
1060 break;
1061 default:
1062 switch((*wibox)->type)
1064 case WIBOX_TYPE_TITLEBAR:
1065 return luaA_titlebar_newindex(L, *wibox, tok);
1066 case WIBOX_TYPE_NORMAL:
1067 break;
1071 return 0;
1074 /** Get or set mouse buttons bindings to a wibox.
1075 * \param L The Lua VM state.
1076 * \luastack
1077 * \lvalue A wibox.
1078 * \lparam An array of mouse button bindings objects, or nothing.
1079 * \return The array of mouse button bindings objects of this wibox.
1081 static int
1082 luaA_wibox_buttons(lua_State *L)
1084 wibox_t **wibox = luaA_checkudata(L, 1, "wibox");
1085 button_array_t *buttons = &(*wibox)->buttons;
1087 if(lua_gettop(L) == 2)
1089 luaA_button_array_set(L, 2, buttons);
1090 return 1;
1093 return luaA_button_array_get(L, buttons);
1096 const struct luaL_reg awesome_wibox_methods[] =
1098 { "__call", luaA_wibox_new },
1099 { NULL, NULL }
1101 const struct luaL_reg awesome_wibox_meta[] =
1103 { "buttons", luaA_wibox_buttons },
1104 { "geometry", luaA_wibox_geometry },
1105 { "__index", luaA_wibox_index },
1106 { "__newindex", luaA_wibox_newindex },
1107 { "__gc", luaA_wibox_gc },
1108 { "__eq", luaA_wibox_eq },
1109 { "__tostring", luaA_wibox_tostring },
1110 { NULL, NULL },
1113 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80