luaa: do not replace string.len(), export wlen()
[awesome.git] / wibox.c
blob9c0f8b5720a51baf18a62c19e4edbcb497b44860
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 "common/xcursor.h"
29 extern awesome_t globalconf;
31 DO_LUA_NEW(extern, wibox_t, wibox, "wibox", wibox_ref)
32 DO_LUA_GC(wibox_t, wibox, "wibox", wibox_unref)
33 DO_LUA_EQ(wibox_t, wibox, "wibox")
35 static void
36 wibox_move(wibox_t *wibox, int16_t x, int16_t y)
38 if(wibox->sw.window)
39 simplewindow_move(&wibox->sw, x, y);
40 else
42 wibox->sw.geometry.x = x;
43 wibox->sw.geometry.y = y;
47 static void
48 wibox_resize(wibox_t *wibox, uint16_t width, uint16_t height)
50 if(wibox->sw.window)
51 simplewindow_resize(&wibox->sw, width, height);
52 else
54 wibox->sw.geometry.width = width;
55 wibox->sw.geometry.height = height;
57 wibox->need_update = true;
60 static void
61 wibox_setposition(wibox_t *wibox, position_t p)
63 if(p != wibox->position)
65 switch((wibox->position = p))
67 case Bottom:
68 case Top:
69 case Floating:
70 simplewindow_orientation_set(&wibox->sw, East);
71 break;
72 case Left:
73 simplewindow_orientation_set(&wibox->sw, North);
74 break;
75 case Right:
76 simplewindow_orientation_set(&wibox->sw, South);
77 break;
79 /* reset width/height to 0 */
80 if(wibox->position != Floating)
81 wibox->sw.geometry.width = wibox->sw.geometry.height = 0;
83 /* recompute position */
84 wibox_position_update(wibox);
86 /* reset all wibox position */
87 wibox_array_t *w = &globalconf.screens[wibox->screen].wiboxes;
88 for(int i = 0; i < w->len; i++)
89 wibox_position_update(w->tab[i]);
91 ewmh_update_workarea(screen_virttophys(wibox->screen));
93 wibox->need_update = true;
97 /** Kick out systray windows.
98 * \param phys_screen Physical screen number.
100 static void
101 wibox_systray_kickout(int phys_screen)
103 xcb_screen_t *s = xutil_screen_get(globalconf.connection, phys_screen);
105 /* Who! Check that we're not deleting a wibox with a systray, because it
106 * may be its parent. If so, we reparent to root before, otherwise it will
107 * hurt very much. */
108 xcb_reparent_window(globalconf.connection,
109 globalconf.screens[phys_screen].systray.window,
110 s->root, -512, -512);
112 globalconf.screens[phys_screen].systray.parent = s->root;
115 static void
116 wibox_systray_refresh(wibox_t *wibox)
118 if(wibox->screen == SCREEN_UNDEF)
119 return;
121 for(int i = 0; i < wibox->widgets.len; i++)
123 widget_node_t *systray = &wibox->widgets.tab[i];
124 if(systray->widget->type == widget_systray)
126 uint32_t config_back[] = { wibox->sw.ctx.bg.pixel };
127 uint32_t config_win_vals[4];
128 uint32_t config_win_vals_off[2] = { -512, -512 };
129 xembed_window_t *em;
130 position_t pos;
131 int phys_screen = wibox->sw.ctx.phys_screen;
133 if(wibox->isvisible
134 && systray->widget->isvisible
135 && systray->geometry.width)
137 pos = wibox->position;
139 /* Set background of the systray window. */
140 xcb_change_window_attributes(globalconf.connection,
141 globalconf.screens[phys_screen].systray.window,
142 XCB_CW_BACK_PIXEL, config_back);
143 /* Map it. */
144 xcb_map_window(globalconf.connection, globalconf.screens[phys_screen].systray.window);
145 /* Move it. */
146 switch(wibox->position)
148 case Left:
149 config_win_vals[0] = systray->geometry.y;
150 config_win_vals[1] = wibox->sw.geometry.height - systray->geometry.x - systray->geometry.width;
151 config_win_vals[2] = systray->geometry.height;
152 config_win_vals[3] = systray->geometry.width;
153 break;
154 case Right:
155 config_win_vals[0] = systray->geometry.y;
156 config_win_vals[1] = systray->geometry.x;
157 config_win_vals[2] = systray->geometry.height;
158 config_win_vals[3] = systray->geometry.width;
159 break;
160 default:
161 config_win_vals[0] = systray->geometry.x;
162 config_win_vals[1] = systray->geometry.y;
163 config_win_vals[2] = systray->geometry.width;
164 config_win_vals[3] = systray->geometry.height;
165 break;
167 /* reparent */
168 if(globalconf.screens[phys_screen].systray.parent != wibox->sw.window)
170 xcb_reparent_window(globalconf.connection,
171 globalconf.screens[phys_screen].systray.window,
172 wibox->sw.window,
173 config_win_vals[0], config_win_vals[1]);
174 globalconf.screens[phys_screen].systray.parent = wibox->sw.window;
176 xcb_configure_window(globalconf.connection,
177 globalconf.screens[phys_screen].systray.window,
178 XCB_CONFIG_WINDOW_X
179 | XCB_CONFIG_WINDOW_Y
180 | XCB_CONFIG_WINDOW_WIDTH
181 | XCB_CONFIG_WINDOW_HEIGHT,
182 config_win_vals);
183 /* width = height = systray height */
184 config_win_vals[2] = config_win_vals[3] = systray->geometry.height;
185 config_win_vals[0] = 0;
187 else
188 return wibox_systray_kickout(phys_screen);
190 switch(pos)
192 case Left:
193 config_win_vals[1] = systray->geometry.width - config_win_vals[3];
194 for(int j = 0; j < globalconf.embedded.len; j++)
196 em = &globalconf.embedded.tab[j];
197 if(em->phys_screen == phys_screen)
199 if(config_win_vals[1] - config_win_vals[2] >= (uint32_t) wibox->sw.geometry.y)
201 xcb_map_window(globalconf.connection, em->win);
202 xcb_configure_window(globalconf.connection, em->win,
203 XCB_CONFIG_WINDOW_X
204 | XCB_CONFIG_WINDOW_Y
205 | XCB_CONFIG_WINDOW_WIDTH
206 | XCB_CONFIG_WINDOW_HEIGHT,
207 config_win_vals);
208 config_win_vals[1] -= config_win_vals[3];
210 else
211 xcb_configure_window(globalconf.connection, em->win,
212 XCB_CONFIG_WINDOW_X
213 | XCB_CONFIG_WINDOW_Y,
214 config_win_vals_off);
217 break;
218 case Right:
219 config_win_vals[1] = 0;
220 for(int j = 0; j < globalconf.embedded.len; j++)
222 em = &globalconf.embedded.tab[j];
223 if(em->phys_screen == phys_screen)
225 if(config_win_vals[1] + config_win_vals[3] <= (uint32_t) wibox->sw.geometry.y + wibox->sw.geometry.width)
227 xcb_map_window(globalconf.connection, em->win);
228 xcb_configure_window(globalconf.connection, em->win,
229 XCB_CONFIG_WINDOW_X
230 | XCB_CONFIG_WINDOW_Y
231 | XCB_CONFIG_WINDOW_WIDTH
232 | XCB_CONFIG_WINDOW_HEIGHT,
233 config_win_vals);
234 config_win_vals[1] += config_win_vals[3];
236 else
237 xcb_configure_window(globalconf.connection, em->win,
238 XCB_CONFIG_WINDOW_X
239 | XCB_CONFIG_WINDOW_Y,
240 config_win_vals_off);
243 break;
244 case Floating:
245 case Top:
246 case Bottom:
247 config_win_vals[1] = 0;
248 for(int j = 0; j < globalconf.embedded.len; j++)
250 em = &globalconf.embedded.tab[j];
251 if(em->phys_screen == phys_screen)
253 /* if(x + width < systray.x + systray.width) */
254 if(config_win_vals[0] + config_win_vals[2] <= (uint32_t) AREA_RIGHT(systray->geometry) + wibox->sw.geometry.x)
256 xcb_map_window(globalconf.connection, em->win);
257 xcb_configure_window(globalconf.connection, em->win,
258 XCB_CONFIG_WINDOW_X
259 | XCB_CONFIG_WINDOW_Y
260 | XCB_CONFIG_WINDOW_WIDTH
261 | XCB_CONFIG_WINDOW_HEIGHT,
262 config_win_vals);
263 config_win_vals[0] += config_win_vals[2];
265 else
266 xcb_configure_window(globalconf.connection, em->win,
267 XCB_CONFIG_WINDOW_X
268 | XCB_CONFIG_WINDOW_Y,
269 config_win_vals_off);
272 break;
274 break;
279 /** Update the wibox position. It deletes every wibox resources and
280 * create them back.
281 * \param wibox The wibox.
283 void
284 wibox_position_update(wibox_t *wibox)
286 area_t area, wingeom = wibox->sw.geometry;
287 bool ignore = false;
289 globalconf.screens[wibox->screen].need_arrange = true;
291 area = screen_area_get(wibox->screen, NULL,
292 &globalconf.screens[wibox->screen].padding, true);
294 /* Top and Bottom wibox_t have prio */
295 if(wibox->position != Floating)
296 for(int i = 0; i < globalconf.screens[wibox->screen].wiboxes.len; i++)
298 wibox_t *w = globalconf.screens[wibox->screen].wiboxes.tab[i];
299 /* Ignore every wibox after me that is in the same position */
300 if(wibox == w)
302 ignore = true;
303 continue;
305 else if((ignore && wibox->position == w->position) || !w->isvisible)
306 continue;
307 switch(w->position)
309 case Floating:
310 break;
311 case Left:
312 switch(wibox->position)
314 case Left:
315 area.x += wibox->sw.geometry.height;
316 break;
317 default:
318 break;
320 break;
321 case Right:
322 switch(wibox->position)
324 case Right:
325 area.x -= wibox->sw.geometry.height;
326 break;
327 default:
328 break;
330 break;
331 case Top:
332 switch(wibox->position)
334 case Top:
335 area.y += w->sw.geometry.height;
336 break;
337 case Left:
338 case Right:
339 area.height -= w->sw.geometry.height;
340 area.y += w->sw.geometry.height;
341 break;
342 default:
343 break;
345 break;
346 case Bottom:
347 switch(wibox->position)
349 case Bottom:
350 area.y -= w->sw.geometry.height;
351 break;
352 case Left:
353 case Right:
354 area.height -= w->sw.geometry.height;
355 break;
356 default:
357 break;
359 break;
363 /* The "length" of a wibox is always chosen to be the optimal size (non-floating).
364 * The "width" of a wibox is kept if it exists.
366 switch(wibox->position)
368 case Right:
369 wingeom.height = area.height;
370 wingeom.width = wibox->sw.geometry.width > 0 ? wibox->sw.geometry.width : 1.5 * globalconf.font->height;
371 wingeom.x = area.x + area.width - wingeom.width;
372 switch(wibox->align)
374 default:
375 wingeom.y = area.y;
376 break;
377 case AlignRight:
378 wingeom.y = area.y + area.height - wingeom.height;
379 break;
380 case AlignCenter:
381 wingeom.y = (area.y + area.height - wingeom.height) / 2;
382 break;
384 break;
385 case Left:
386 wingeom.height = area.height;
387 wingeom.width = wibox->sw.geometry.width > 0 ? wibox->sw.geometry.width : 1.5 * globalconf.font->height;
388 wingeom.x = area.x;
389 switch(wibox->align)
391 default:
392 wingeom.y = (area.y + area.height) - wingeom.height;
393 break;
394 case AlignRight:
395 wingeom.y = area.y;
396 break;
397 case AlignCenter:
398 wingeom.y = (area.y + area.height - wingeom.height) / 2;
400 break;
401 case Bottom:
402 wingeom.height = wibox->sw.geometry.height > 0 ? wibox->sw.geometry.height : 1.5 * globalconf.font->height;
403 wingeom.width = area.width;
404 wingeom.y = (area.y + area.height) - wingeom.height;
405 wingeom.x = area.x;
406 switch(wibox->align)
408 default:
409 break;
410 case AlignRight:
411 wingeom.x += area.width - wingeom.width;
412 break;
413 case AlignCenter:
414 wingeom.x += (area.width - wingeom.width) / 2;
415 break;
417 break;
418 case Top:
419 wingeom.height = wibox->sw.geometry.height > 0 ? wibox->sw.geometry.height : 1.5 * globalconf.font->height;
420 wingeom.width = area.width;
421 wingeom.x = area.x;
422 wingeom.y = area.y;
423 switch(wibox->align)
425 default:
426 break;
427 case AlignRight:
428 wingeom.x += area.width - wingeom.width;
429 break;
430 case AlignCenter:
431 wingeom.x += (area.width - wingeom.width) / 2;
432 break;
434 break;
435 case Floating:
436 wingeom.width = MAX(1, wibox->sw.geometry.width);
437 wingeom.height = MAX(1, wibox->sw.geometry.height);
438 break;
441 /* same window size and position ? */
442 if(wingeom.width != wibox->sw.geometry.width
443 || wingeom.height != wibox->sw.geometry.height)
444 wibox_resize(wibox, wingeom.width, wingeom.height);
446 if(wingeom.x != wibox->sw.geometry.x
447 || wingeom.y != wibox->sw.geometry.y)
448 wibox_move(wibox, wingeom.x, wingeom.y);
451 /** Delete a wibox.
452 * \param wibox wibox to delete.
454 void
455 wibox_delete(wibox_t **wibox)
457 simplewindow_wipe(&(*wibox)->sw);
458 button_array_wipe(&(*wibox)->buttons);
459 luaL_unref(globalconf.L, LUA_REGISTRYINDEX, (*wibox)->widgets_table);
460 widget_node_array_wipe(&(*wibox)->widgets);
461 p_delete(wibox);
464 /** Get a wibox by its window.
465 * \param w The window id.
466 * \return A wibox if found, NULL otherwise.
468 wibox_t *
469 wibox_getbywin(xcb_window_t w)
471 for(int screen = 0; screen < globalconf.nscreen; screen++)
472 for(int i = 0; i < globalconf.screens[screen].wiboxes.len; i++)
474 wibox_t *s = globalconf.screens[screen].wiboxes.tab[i];
475 if(s->sw.window == w)
476 return s;
479 for(client_t *c = globalconf.clients; c; c = c->next)
480 if(c->titlebar && c->titlebar->sw.window == w)
481 return c->titlebar;
483 return NULL;
486 /** Draw a wibox.
487 * \param wibox The wibox to draw.
489 static void
490 wibox_draw(wibox_t *wibox)
492 if(wibox->isvisible)
494 widget_render(&wibox->widgets, &wibox->sw.ctx, wibox->sw.gc,
495 wibox->sw.pixmap,
496 wibox->screen, wibox->sw.orientation,
497 wibox->sw.geometry.x, wibox->sw.geometry.y,
498 wibox);
499 simplewindow_refresh_pixmap(&wibox->sw);
501 wibox->need_update = false;
504 wibox_systray_refresh(wibox);
507 /** Refresh all wiboxes.
509 void
510 wibox_refresh(void)
512 for(int screen = 0; screen < globalconf.nscreen; screen++)
513 for(int i = 0; i < globalconf.screens[screen].wiboxes.len; i++)
515 wibox_t *s = globalconf.screens[screen].wiboxes.tab[i];
516 if(s->need_update)
517 wibox_draw(s);
520 for(client_t *c = globalconf.clients; c; c = c->next)
521 if(c->titlebar && c->titlebar->need_update)
522 wibox_draw(c->titlebar);
525 /** Reposition all wiboxes.
527 void
528 wibox_update_positions(void)
530 for(int screen = 0; screen < globalconf.nscreen; screen++)
531 for(int i = 0; i < globalconf.screens[screen].wiboxes.len; i++)
533 wibox_t *s = globalconf.screens[screen].wiboxes.tab[i];
534 wibox_position_update(s);
538 /** Set a wibox visible or not.
539 * \param wibox The wibox.
540 * \param v The visible value.
542 static void
543 wibox_setvisible(wibox_t *wibox, bool v)
545 if(v != wibox->isvisible)
547 wibox->isvisible = v;
549 if(wibox->screen != SCREEN_UNDEF)
551 if(wibox->isvisible)
553 xcb_map_window(globalconf.connection, wibox->sw.window);
554 simplewindow_refresh_pixmap(&wibox->sw);
555 /* stack correctly the wibox */
556 client_stack();
558 else
559 xcb_unmap_window(globalconf.connection, wibox->sw.window);
561 /* kick out systray if needed */
562 wibox_systray_refresh(wibox);
564 /* All the other wibox and ourselves need to be repositioned */
565 wibox_array_t *w = &globalconf.screens[wibox->screen].wiboxes;
566 for(int i = 0; i < w->len; i++)
567 wibox_position_update(w->tab[i]);
572 /** Remove a wibox from a screen.
573 * \param wibox Wibox to detach from screen.
575 void
576 wibox_detach(wibox_t *wibox)
578 if(wibox->screen != SCREEN_UNDEF)
580 bool v;
582 /* save visible state */
583 v = wibox->isvisible;
584 wibox->isvisible = false;
585 wibox_systray_refresh(wibox);
586 wibox_position_update(wibox);
587 /* restore position */
588 wibox->isvisible = v;
590 simplewindow_wipe(&wibox->sw);
592 for(int i = 0; i < globalconf.screens[wibox->screen].wiboxes.len; i++)
593 if(globalconf.screens[wibox->screen].wiboxes.tab[i] == wibox)
595 wibox_array_take(&globalconf.screens[wibox->screen].wiboxes, i);
596 break;
598 globalconf.screens[wibox->screen].need_arrange = true;
599 wibox->screen = SCREEN_UNDEF;
600 wibox_unref(&wibox);
604 /** Attach a wibox.
605 * \param wibox The wibox to attach.
606 * \param s The screen to attach the wibox to.
608 void
609 wibox_attach(wibox_t *wibox, screen_t *s)
611 int phys_screen = screen_virttophys(s->index);
613 wibox_detach(wibox);
615 wibox->screen = s->index;
617 wibox_array_append(&s->wiboxes, wibox_ref(&wibox));
619 /* compute x/y/width/height if not set */
620 wibox_position_update(wibox);
622 simplewindow_init(&wibox->sw, phys_screen,
623 wibox->sw.geometry,
624 wibox->sw.border.width,
625 wibox->sw.orientation,
626 &wibox->sw.ctx.fg, &wibox->sw.ctx.bg);
628 simplewindow_border_color_set(&wibox->sw, &wibox->sw.border.color);
630 simplewindow_cursor_set(&wibox->sw,
631 xcursor_new(globalconf.connection, xcursor_font_fromstr(wibox->cursor)));
633 /* All the other wibox and ourselves need to be repositioned */
634 for(int i = 0; i < s->wiboxes.len; i++)
635 wibox_position_update(s->wiboxes.tab[i]);
637 ewmh_update_workarea(screen_virttophys(s->index));
639 if(wibox->isvisible)
641 /* draw it right now once to avoid garbage shown */
642 wibox_draw(wibox);
643 xcb_map_window(globalconf.connection, wibox->sw.window);
644 simplewindow_refresh_pixmap(&wibox->sw);
645 /* stack correctly the wibox */
646 client_stack();
648 else
649 wibox->need_update = true;
652 /** Create a new wibox.
653 * \param L The Lua VM state.
655 * \luastack
656 * \lparam A table with optionaly defined values:
657 * position, align, fg, bg, border_width, border_color, width and height.
658 * \lreturn A brand new wibox.
661 luaA_wibox_new(lua_State *L)
663 wibox_t *w;
664 const char *buf;
665 size_t len;
666 xcolor_init_request_t reqs[3];
667 int8_t i, reqs_nbr = -1;
669 luaA_checktable(L, 2);
671 w = p_new(wibox_t, 1);
672 w->widgets_table = LUA_REFNIL;
674 w->sw.ctx.fg = globalconf.colors.fg;
675 if((buf = luaA_getopt_lstring(L, 2, "fg", NULL, &len)))
676 reqs[++reqs_nbr] = xcolor_init_unchecked(&w->sw.ctx.fg, buf, len);
678 w->sw.ctx.bg = globalconf.colors.bg;
679 if((buf = luaA_getopt_lstring(L, 2, "bg", NULL, &len)))
680 reqs[++reqs_nbr] = xcolor_init_unchecked(&w->sw.ctx.bg, buf, len);
682 w->sw.border.color = globalconf.colors.bg;
683 if((buf = luaA_getopt_lstring(L, 2, "border_color", NULL, &len)))
684 reqs[++reqs_nbr] = xcolor_init_unchecked(&w->sw.border.color, buf, len);
686 buf = luaA_getopt_lstring(L, 2, "align", "left", &len);
687 w->align = draw_align_fromstr(buf, len);
689 w->sw.border.width = luaA_getopt_number(L, 2, "border_width", 0);
691 buf = luaA_getopt_lstring(L, 2, "position", "top", &len);
693 switch((w->position = position_fromstr(buf, len)))
695 case Bottom:
696 case Top:
697 case Floating:
698 simplewindow_orientation_set(&w->sw, East);
699 break;
700 case Left:
701 simplewindow_orientation_set(&w->sw, North);
702 break;
703 case Right:
704 simplewindow_orientation_set(&w->sw, South);
705 break;
708 /* recompute position */
709 wibox_position_update(w);
711 w->sw.geometry.width = luaA_getopt_number(L, 2, "width", 0);
712 w->sw.geometry.height = luaA_getopt_number(L, 2, "height", 0);
714 w->screen = SCREEN_UNDEF;
715 w->isvisible = true;
716 w->cursor = a_strdup("left_ptr");
718 for(i = 0; i <= reqs_nbr; i++)
719 xcolor_init_reply(reqs[i]);
721 return luaA_wibox_userdata_new(L, w);
724 /** Rebuild wibox widgets list.
725 * \param L The Lua VM state.
726 * \param wibox The wibox.
728 static void
729 wibox_widgets_table_build(lua_State *L, wibox_t *wibox)
731 widget_node_array_wipe(&wibox->widgets);
732 widget_node_array_init(&wibox->widgets);
733 luaA_table2widgets(L, &wibox->widgets);
734 wibox->mouse_over = NULL;
735 wibox->need_update = true;
738 /** Check if a wibox widget table has an item.
739 * \param L The Lua VM state.
740 * \param wibox The wibox.
741 * \param item The item to look for.
743 static bool
744 luaA_wibox_hasitem(lua_State *L, wibox_t *wibox, const void *item)
746 if(wibox->widgets_table != LUA_REFNIL)
748 lua_rawgeti(globalconf.L, LUA_REGISTRYINDEX, wibox->widgets_table);
749 if(lua_topointer(L, -1) == item || luaA_hasitem(L, item))
750 return true;
752 return false;
755 /** Invalidate a wibox by a Lua object (table, etc).
756 * \param L The Lua VM state.
757 * \param item The object identifier.
759 void
760 luaA_wibox_invalidate_byitem(lua_State *L, const void *item)
762 for(int screen = 0; screen < globalconf.nscreen; screen++)
763 for(int i = 0; i < globalconf.screens[screen].wiboxes.len; i++)
765 wibox_t *wibox = globalconf.screens[screen].wiboxes.tab[i];
766 if(luaA_wibox_hasitem(L, wibox, item))
768 /* recompute widget node list */
769 wibox_widgets_table_build(L, wibox);
770 lua_pop(L, 1); /* remove widgets table */
775 for(client_t *c = globalconf.clients; c; c = c->next)
776 if(c->titlebar && luaA_wibox_hasitem(L, c->titlebar, item))
778 /* recompute widget node list */
779 wibox_widgets_table_build(L, c->titlebar);
780 lua_pop(L, 1); /* remove widgets table */
784 /** Wibox object.
785 * \param L The Lua VM state.
786 * \return The number of elements pushed on stack.
787 * \luastack
788 * \lfield screen Screen number.
789 * \lfield client The client attached to this titlebar.
790 * \lfield border_width Border width.
791 * \lfield border_color Border color.
792 * \lfield align The alignment.
793 * \lfield fg Foreground color.
794 * \lfield bg Background color.
795 * \lfield position The position.
796 * \lfield ontop On top of other windows.
797 * \lfield cursor The mouse cursor.
799 static int
800 luaA_wibox_index(lua_State *L)
802 size_t len;
803 wibox_t **wibox = luaA_checkudata(L, 1, "wibox");
804 const char *attr = luaL_checklstring(L, 2, &len);
806 if(luaA_usemetatable(L, 1, 2))
807 return 1;
809 switch(a_tokenize(attr, len))
811 client_t *c;
813 case A_TK_VISIBLE:
814 lua_pushboolean(L, (*wibox)->isvisible);
815 break;
816 case A_TK_CLIENT:
817 if((c = client_getbytitlebar(*wibox)))
818 return luaA_client_userdata_new(L, c);
819 else
820 return 0;
821 case A_TK_SCREEN:
822 if((*wibox)->screen == SCREEN_UNDEF)
823 return 0;
824 lua_pushnumber(L, (*wibox)->screen + 1);
825 break;
826 case A_TK_BORDER_WIDTH:
827 lua_pushnumber(L, (*wibox)->sw.border.width);
828 break;
829 case A_TK_BORDER_COLOR:
830 luaA_pushcolor(L, &(*wibox)->sw.border.color);
831 break;
832 case A_TK_ALIGN:
833 lua_pushstring(L, draw_align_tostr((*wibox)->align));
834 break;
835 case A_TK_FG:
836 luaA_pushcolor(L, &(*wibox)->sw.ctx.fg);
837 break;
838 case A_TK_BG:
839 luaA_pushcolor(L, &(*wibox)->sw.ctx.bg);
840 break;
841 case A_TK_POSITION:
842 lua_pushstring(L, position_tostr((*wibox)->position));
843 break;
844 case A_TK_ONTOP:
845 lua_pushboolean(L, (*wibox)->ontop);
846 break;
847 case A_TK_ORIENTATION:
848 lua_pushstring(L, orientation_tostr((*wibox)->sw.orientation));
849 break;
850 case A_TK_WIDGETS:
851 if((*wibox)->widgets_table != LUA_REFNIL)
852 lua_rawgeti(L, LUA_REGISTRYINDEX, (*wibox)->widgets_table);
853 else
854 lua_pushnil(L);
855 break;
856 case A_TK_CURSOR:
857 lua_pushstring(L, (*wibox)->cursor);
858 break;
859 default:
860 return 0;
863 return 1;
866 /* Set or get the wibox geometry.
867 * \param L The Lua VM state.
868 * \return The number of elements pushed on stack.
869 * \luastack
870 * \lparam An optional table with wibox geometry.
871 * \lreturn The wibox geometry.
873 static int
874 luaA_wibox_geometry(lua_State *L)
876 wibox_t **wibox = luaA_checkudata(L, 1, "wibox");
878 if(lua_gettop(L) == 2)
880 area_t wingeom;
882 luaA_checktable(L, 2);
883 wingeom.x = luaA_getopt_number(L, 2, "x", (*wibox)->sw.geometry.x);
884 wingeom.y = luaA_getopt_number(L, 2, "y", (*wibox)->sw.geometry.y);
885 wingeom.width = luaA_getopt_number(L, 2, "width", (*wibox)->sw.geometry.width);
886 wingeom.height = luaA_getopt_number(L, 2, "height", (*wibox)->sw.geometry.height);
888 switch((*wibox)->type)
890 case WIBOX_TYPE_TITLEBAR:
891 wibox_resize(*wibox, wingeom.width, wingeom.height);
892 break;
893 case WIBOX_TYPE_NORMAL:
894 if((*wibox)->position == Floating)
895 wibox_moveresize(*wibox, wingeom);
896 else if(wingeom.width != (*wibox)->sw.geometry.width
897 || wingeom.height != (*wibox)->sw.geometry.height)
899 wibox_resize(*wibox, wingeom.width, wingeom.height);
900 globalconf.screens[(*wibox)->screen].need_arrange = true;
902 break;
906 return luaA_pusharea(L, (*wibox)->sw.geometry);
909 /** Wibox newindex.
910 * \param L The Lua VM state.
911 * \return The number of elements pushed on stack.
913 static int
914 luaA_wibox_newindex(lua_State *L)
916 size_t len;
917 wibox_t **wibox = luaA_checkudata(L, 1, "wibox");
918 const char *buf, *attr = luaL_checklstring(L, 2, &len);
919 awesome_token_t tok;
921 switch((tok = a_tokenize(attr, len)))
923 bool b;
925 case A_TK_FG:
926 if((buf = luaL_checklstring(L, 3, &len)))
927 if(xcolor_init_reply(xcolor_init_unchecked(&(*wibox)->sw.ctx.fg, buf, len)))
928 (*wibox)->need_update = true;
929 break;
930 case A_TK_BG:
931 if((buf = luaL_checklstring(L, 3, &len)))
932 if(xcolor_init_reply(xcolor_init_unchecked(&(*wibox)->sw.ctx.bg, buf, len)))
933 (*wibox)->need_update = true;
934 break;
935 case A_TK_ALIGN:
936 buf = luaL_checklstring(L, 3, &len);
937 (*wibox)->align = draw_align_fromstr(buf, len);
938 switch((*wibox)->type)
940 case WIBOX_TYPE_NORMAL:
941 wibox_position_update(*wibox);
942 break;
943 case WIBOX_TYPE_TITLEBAR:
944 titlebar_update_geometry(client_getbytitlebar(*wibox));
945 break;
947 break;
948 case A_TK_POSITION:
949 switch((*wibox)->type)
951 case WIBOX_TYPE_TITLEBAR:
952 return luaA_titlebar_newindex(L, *wibox, tok);
953 case WIBOX_TYPE_NORMAL:
954 if((buf = luaL_checklstring(L, 3, &len)))
955 wibox_setposition(*wibox, position_fromstr(buf, len));
956 break;
958 break;
959 case A_TK_CLIENT:
960 /* first detach */
961 if(lua_isnil(L, 3))
962 titlebar_client_detach(client_getbytitlebar(*wibox));
963 else
965 client_t **c = luaA_checkudata(L, 3, "client");
966 titlebar_client_attach(*c, *wibox);
968 break;
969 case A_TK_CURSOR:
970 if((buf = luaL_checkstring(L, 3)))
972 uint16_t cursor_font = xcursor_font_fromstr(buf);
973 if(cursor_font)
975 xcb_cursor_t cursor = xcursor_new(globalconf.connection, cursor_font);
976 p_delete(&(*wibox)->cursor);
977 (*wibox)->cursor = a_strdup(buf);
978 simplewindow_cursor_set(&(*wibox)->sw, cursor);
981 break;
982 case A_TK_SCREEN:
983 if(lua_isnil(L, 3))
985 wibox_detach(*wibox);
986 titlebar_client_detach(client_getbytitlebar(*wibox));
988 else
990 int screen = luaL_checknumber(L, 3) - 1;
991 luaA_checkscreen(screen);
992 if(screen != (*wibox)->screen)
994 titlebar_client_detach(client_getbytitlebar(*wibox));
995 wibox_attach(*wibox, &globalconf.screens[screen]);
998 break;
999 case A_TK_ONTOP:
1000 b = luaA_checkboolean(L, 3);
1001 if(b != (*wibox)->ontop)
1003 (*wibox)->ontop = b;
1004 client_stack();
1006 break;
1007 case A_TK_ORIENTATION:
1008 if((buf = luaL_checklstring(L, 3, &len)))
1010 simplewindow_orientation_set(&(*wibox)->sw, orientation_fromstr(buf, len));
1011 (*wibox)->need_update = true;
1013 break;
1014 case A_TK_BORDER_COLOR:
1015 if((buf = luaL_checklstring(L, 3, &len)))
1016 if(xcolor_init_reply(xcolor_init_unchecked(&(*wibox)->sw.border.color, buf, len)))
1017 if((*wibox)->sw.window)
1018 simplewindow_border_color_set(&(*wibox)->sw, &(*wibox)->sw.border.color);
1019 break;
1020 case A_TK_VISIBLE:
1021 b = luaA_checkboolean(L, 3);
1022 if(b != (*wibox)->isvisible)
1023 switch((*wibox)->type)
1025 case WIBOX_TYPE_NORMAL:
1026 wibox_setvisible(*wibox, b);
1027 break;
1028 case WIBOX_TYPE_TITLEBAR:
1029 titlebar_set_visible(*wibox, b);
1030 break;
1032 break;
1033 case A_TK_WIDGETS:
1034 if(luaA_isloop(L, 3))
1036 luaA_warn(L, "table is looping, cannot use this as widget table");
1037 return 0;
1039 luaA_register(L, 3, &(*wibox)->widgets_table);
1040 /* recompute widget node list */
1041 wibox_widgets_table_build(L, *wibox);
1042 luaA_table2wtable(L);
1043 break;
1044 default:
1045 switch((*wibox)->type)
1047 case WIBOX_TYPE_TITLEBAR:
1048 return luaA_titlebar_newindex(L, *wibox, tok);
1049 case WIBOX_TYPE_NORMAL:
1050 break;
1054 return 0;
1057 /** Get or set mouse buttons bindings to a wibox.
1058 * \param L The Lua VM state.
1059 * \luastack
1060 * \lvalue A wibox.
1061 * \lparam An array of mouse button bindings objects, or nothing.
1062 * \return The array of mouse button bindings objects of this wibox.
1064 static int
1065 luaA_wibox_buttons(lua_State *L)
1067 wibox_t **wibox = luaA_checkudata(L, 1, "wibox");
1068 button_array_t *buttons = &(*wibox)->buttons;
1070 if(lua_gettop(L) == 2)
1072 luaA_button_array_set(L, 2, buttons);
1073 return 1;
1076 return luaA_button_array_get(L, buttons);
1079 const struct luaL_reg awesome_wibox_methods[] =
1081 { "__call", luaA_wibox_new },
1082 { NULL, NULL }
1084 const struct luaL_reg awesome_wibox_meta[] =
1086 { "buttons", luaA_wibox_buttons },
1087 { "geometry", luaA_wibox_geometry },
1088 { "__index", luaA_wibox_index },
1089 { "__newindex", luaA_wibox_newindex },
1090 { "__gc", luaA_wibox_gc },
1091 { "__eq", luaA_wibox_eq },
1092 { "__tostring", luaA_wibox_tostring },
1093 { NULL, NULL },
1096 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80