client: geometry() honors size hints hint
[awesome.git] / wibox.c
blob50e8ed7d7c7f484793f69a141c2069c5679977fc
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"
28 extern awesome_t globalconf;
30 DO_LUA_NEW(extern, wibox_t, wibox, "wibox", wibox_ref)
31 DO_LUA_GC(wibox_t, wibox, "wibox", wibox_unref)
32 DO_LUA_EQ(wibox_t, wibox, "wibox")
34 static void
35 wibox_move(wibox_t *wibox, int16_t x, int16_t y)
37 if(wibox->sw.window)
38 simplewindow_move(&wibox->sw, x, y);
39 else
41 wibox->sw.geometry.x = x;
42 wibox->sw.geometry.y = y;
46 static void
47 wibox_resize(wibox_t *wibox, uint16_t width, uint16_t height)
49 if(wibox->sw.window)
50 simplewindow_resize(&wibox->sw, width, height);
51 else
53 wibox->sw.geometry.width = width;
54 wibox->sw.geometry.height = height;
56 wibox->need_update = true;
59 static void
60 wibox_setposition(wibox_t *wibox, position_t p)
62 if(p != wibox->position)
64 switch((wibox->position = p))
66 case Bottom:
67 case Top:
68 case Floating:
69 simplewindow_orientation_set(&wibox->sw, East);
70 break;
71 case Left:
72 simplewindow_orientation_set(&wibox->sw, North);
73 break;
74 case Right:
75 simplewindow_orientation_set(&wibox->sw, South);
76 break;
78 /* reset width/height to 0 */
79 if(wibox->position != Floating)
80 wibox->sw.geometry.width = wibox->sw.geometry.height = 0;
82 /* recompute position */
83 wibox_position_update(wibox);
85 /* reset all wibox position */
86 wibox_array_t *w = &globalconf.screens[wibox->screen].wiboxes;
87 for(int i = 0; i < w->len; i++)
88 wibox_position_update(w->tab[i]);
90 ewmh_update_workarea(screen_virttophys(wibox->screen));
92 wibox->need_update = true;
96 /** Kick out systray windows.
97 * \param phys_screen Physical screen number.
99 static void
100 wibox_systray_kickout(int phys_screen)
102 xcb_screen_t *s = xutil_screen_get(globalconf.connection, phys_screen);
104 /* Who! Check that we're not deleting a wibox with a systray, because it
105 * may be its parent. If so, we reparent to root before, otherwise it will
106 * hurt very much. */
107 xcb_reparent_window(globalconf.connection,
108 globalconf.screens[phys_screen].systray.window,
109 s->root, -512, -512);
111 globalconf.screens[phys_screen].systray.parent = s->root;
114 static void
115 wibox_systray_refresh(wibox_t *wibox)
117 if(wibox->screen == SCREEN_UNDEF)
118 return;
120 for(int i = 0; i < wibox->widgets.len; i++)
122 widget_node_t *systray = &wibox->widgets.tab[i];
123 if(systray->widget->type == systray_new)
125 uint32_t config_back[] = { wibox->sw.ctx.bg.pixel };
126 uint32_t config_win_vals[4];
127 uint32_t config_win_vals_off[2] = { -512, -512 };
128 xembed_window_t *em;
129 position_t pos;
130 int phys_screen = wibox->sw.ctx.phys_screen;
132 if(wibox->isvisible
133 && systray->widget->isvisible
134 && systray->geometry.width)
136 pos = wibox->position;
138 /* Set background of the systray window. */
139 xcb_change_window_attributes(globalconf.connection,
140 globalconf.screens[phys_screen].systray.window,
141 XCB_CW_BACK_PIXEL, config_back);
142 /* Map it. */
143 xcb_map_window(globalconf.connection, globalconf.screens[phys_screen].systray.window);
144 /* Move it. */
145 switch(wibox->position)
147 case Left:
148 config_win_vals[0] = systray->geometry.y;
149 config_win_vals[1] = wibox->sw.geometry.height - systray->geometry.x - systray->geometry.width;
150 config_win_vals[2] = systray->geometry.height;
151 config_win_vals[3] = systray->geometry.width;
152 break;
153 case Right:
154 config_win_vals[0] = systray->geometry.y;
155 config_win_vals[1] = systray->geometry.x;
156 config_win_vals[2] = systray->geometry.height;
157 config_win_vals[3] = systray->geometry.width;
158 break;
159 default:
160 config_win_vals[0] = systray->geometry.x;
161 config_win_vals[1] = systray->geometry.y;
162 config_win_vals[2] = systray->geometry.width;
163 config_win_vals[3] = systray->geometry.height;
164 break;
166 /* reparent */
167 if(globalconf.screens[phys_screen].systray.parent != wibox->sw.window)
169 xcb_reparent_window(globalconf.connection,
170 globalconf.screens[phys_screen].systray.window,
171 wibox->sw.window,
172 config_win_vals[0], config_win_vals[1]);
173 globalconf.screens[phys_screen].systray.parent = wibox->sw.window;
175 xcb_configure_window(globalconf.connection,
176 globalconf.screens[phys_screen].systray.window,
177 XCB_CONFIG_WINDOW_X
178 | XCB_CONFIG_WINDOW_Y
179 | XCB_CONFIG_WINDOW_WIDTH
180 | XCB_CONFIG_WINDOW_HEIGHT,
181 config_win_vals);
182 /* width = height = systray height */
183 config_win_vals[2] = config_win_vals[3] = systray->geometry.height;
184 config_win_vals[0] = 0;
186 else
187 return wibox_systray_kickout(phys_screen);
189 switch(pos)
191 case Left:
192 config_win_vals[1] = systray->geometry.width - config_win_vals[3];
193 for(em = globalconf.embedded; em; em = em->next)
194 if(em->phys_screen == phys_screen)
196 if(config_win_vals[1] - config_win_vals[2] >= (uint32_t) wibox->sw.geometry.y)
198 xcb_map_window(globalconf.connection, em->win);
199 xcb_configure_window(globalconf.connection, em->win,
200 XCB_CONFIG_WINDOW_X
201 | XCB_CONFIG_WINDOW_Y
202 | XCB_CONFIG_WINDOW_WIDTH
203 | XCB_CONFIG_WINDOW_HEIGHT,
204 config_win_vals);
205 config_win_vals[1] -= config_win_vals[3];
207 else
208 xcb_configure_window(globalconf.connection, em->win,
209 XCB_CONFIG_WINDOW_X
210 | XCB_CONFIG_WINDOW_Y,
211 config_win_vals_off);
213 break;
214 case Right:
215 config_win_vals[1] = 0;
216 for(em = globalconf.embedded; em; em = em->next)
217 if(em->phys_screen == phys_screen)
219 if(config_win_vals[1] + config_win_vals[3] <= (uint32_t) wibox->sw.geometry.y + wibox->sw.geometry.width)
221 xcb_map_window(globalconf.connection, em->win);
222 xcb_configure_window(globalconf.connection, em->win,
223 XCB_CONFIG_WINDOW_X
224 | XCB_CONFIG_WINDOW_Y
225 | XCB_CONFIG_WINDOW_WIDTH
226 | XCB_CONFIG_WINDOW_HEIGHT,
227 config_win_vals);
228 config_win_vals[1] += config_win_vals[3];
230 else
231 xcb_configure_window(globalconf.connection, em->win,
232 XCB_CONFIG_WINDOW_X
233 | XCB_CONFIG_WINDOW_Y,
234 config_win_vals_off);
236 break;
237 case Floating:
238 case Top:
239 case Bottom:
240 config_win_vals[1] = 0;
241 for(em = globalconf.embedded; em; em = em->next)
242 if(em->phys_screen == phys_screen)
244 /* if(x + width < systray.x + systray.width) */
245 if(config_win_vals[0] + config_win_vals[2] <= (uint32_t) AREA_RIGHT(systray->geometry) + wibox->sw.geometry.x)
247 xcb_map_window(globalconf.connection, em->win);
248 xcb_configure_window(globalconf.connection, em->win,
249 XCB_CONFIG_WINDOW_X
250 | XCB_CONFIG_WINDOW_Y
251 | XCB_CONFIG_WINDOW_WIDTH
252 | XCB_CONFIG_WINDOW_HEIGHT,
253 config_win_vals);
254 config_win_vals[0] += config_win_vals[2];
256 else
257 xcb_configure_window(globalconf.connection, em->win,
258 XCB_CONFIG_WINDOW_X
259 | XCB_CONFIG_WINDOW_Y,
260 config_win_vals_off);
262 break;
264 break;
269 /** Update the wibox position. It deletes every wibox resources and
270 * create them back.
271 * \param wibox The wibox.
273 void
274 wibox_position_update(wibox_t *wibox)
276 area_t area, wingeom = wibox->sw.geometry;
277 bool ignore = false;
279 globalconf.screens[wibox->screen].need_arrange = true;
281 area = screen_area_get(wibox->screen, NULL,
282 &globalconf.screens[wibox->screen].padding, true);
284 /* Top and Bottom wibox_t have prio */
285 if(wibox->position != Floating)
286 for(int i = 0; i < globalconf.screens[wibox->screen].wiboxes.len; i++)
288 wibox_t *w = globalconf.screens[wibox->screen].wiboxes.tab[i];
289 /* Ignore every wibox after me that is in the same position */
290 if(wibox == w)
292 ignore = true;
293 continue;
295 else if((ignore && wibox->position == w->position) || !w->isvisible)
296 continue;
297 switch(w->position)
299 case Floating:
300 break;
301 case Left:
302 switch(wibox->position)
304 case Left:
305 area.x += wibox->sw.geometry.height;
306 break;
307 default:
308 break;
310 break;
311 case Right:
312 switch(wibox->position)
314 case Right:
315 area.x -= wibox->sw.geometry.height;
316 break;
317 default:
318 break;
320 break;
321 case Top:
322 switch(wibox->position)
324 case Top:
325 area.y += w->sw.geometry.height;
326 break;
327 case Left:
328 case Right:
329 area.height -= w->sw.geometry.height;
330 area.y += w->sw.geometry.height;
331 break;
332 default:
333 break;
335 break;
336 case Bottom:
337 switch(wibox->position)
339 case Bottom:
340 area.y -= w->sw.geometry.height;
341 break;
342 case Left:
343 case Right:
344 area.height -= w->sw.geometry.height;
345 break;
346 default:
347 break;
349 break;
353 switch(wibox->position)
355 case Right:
356 wingeom.height = wibox->sw.geometry.height > 0 ?
357 wibox->sw.geometry.height : area.height - 2 * wibox->sw.border.width;
358 wingeom.width = wibox->sw.geometry.width > 0 ? wibox->sw.geometry.width : 1.5 * globalconf.font->height;
359 wingeom.x = area.x + area.width - wingeom.width - 2 * wibox->sw.border.width;
360 switch(wibox->align)
362 default:
363 wingeom.y = area.y;
364 break;
365 case AlignRight:
366 wingeom.y = area.y + area.height - wingeom.height;
367 break;
368 case AlignCenter:
369 wingeom.y = (area.y + area.height - wingeom.height) / 2;
370 break;
372 break;
373 case Left:
374 wingeom.height = wibox->sw.geometry.height > 0 ?
375 wibox->sw.geometry.height : area.height - 2 * wibox->sw.border.width;
376 wingeom.width = wibox->sw.geometry.width > 0 ? wibox->sw.geometry.width : 1.5 * globalconf.font->height;
377 wingeom.x = area.x;
378 switch(wibox->align)
380 default:
381 wingeom.y = (area.y + area.height) - wingeom.height - 2 * wibox->sw.border.width;
382 break;
383 case AlignRight:
384 wingeom.y = area.y;
385 break;
386 case AlignCenter:
387 wingeom.y = (area.y + area.height - wingeom.height) / 2;
389 break;
390 case Bottom:
391 wingeom.height = wibox->sw.geometry.height > 0 ? wibox->sw.geometry.height : 1.5 * globalconf.font->height;
392 wingeom.width = wibox->sw.geometry.width > 0 ?
393 wibox->sw.geometry.width : area.width - 2 * wibox->sw.border.width;
394 wingeom.y = (area.y + area.height) - wingeom.height - 2 * wibox->sw.border.width;
395 wingeom.x = area.x;
396 switch(wibox->align)
398 default:
399 break;
400 case AlignRight:
401 wingeom.x += area.width - wingeom.width;
402 break;
403 case AlignCenter:
404 wingeom.x += (area.width - wingeom.width) / 2;
405 break;
407 break;
408 case Top:
409 wingeom.height = wibox->sw.geometry.height > 0 ? wibox->sw.geometry.height : 1.5 * globalconf.font->height;
410 wingeom.width = wibox->sw.geometry.width > 0 ?
411 wibox->sw.geometry.width : area.width - 2 * wibox->sw.border.width;
412 wingeom.x = area.x;
413 wingeom.y = area.y;
414 switch(wibox->align)
416 default:
417 break;
418 case AlignRight:
419 wingeom.x += area.width - wingeom.width;
420 break;
421 case AlignCenter:
422 wingeom.x += (area.width - wingeom.width) / 2;
423 break;
425 break;
426 case Floating:
427 wingeom.width = MAX(1, wibox->sw.geometry.width);
428 wingeom.height = MAX(1, wibox->sw.geometry.height);
429 break;
432 /* same window size and position ? */
433 if(wingeom.width != wibox->sw.geometry.width
434 || wingeom.height != wibox->sw.geometry.height)
435 wibox_resize(wibox, wingeom.width, wingeom.height);
437 if(wingeom.x != wibox->sw.geometry.x
438 || wingeom.y != wibox->sw.geometry.y)
439 wibox_move(wibox, wingeom.x, wingeom.y);
442 /** Delete a wibox.
443 * \param wibox wibox to delete.
445 void
446 wibox_delete(wibox_t **wibox)
448 simplewindow_wipe(&(*wibox)->sw);
449 luaL_unref(globalconf.L, LUA_REGISTRYINDEX, (*wibox)->widgets_table);
450 widget_node_array_wipe(&(*wibox)->widgets);
451 p_delete(wibox);
454 /** Get a wibox by its window.
455 * \param w The window id.
456 * \return A wibox if found, NULL otherwise.
458 wibox_t *
459 wibox_getbywin(xcb_window_t w)
461 for(int screen = 0; screen < globalconf.nscreen; screen++)
462 for(int i = 0; i < globalconf.screens[screen].wiboxes.len; i++)
464 wibox_t *s = globalconf.screens[screen].wiboxes.tab[i];
465 if(s->sw.window == w)
466 return s;
469 for(client_t *c = globalconf.clients; c; c = c->next)
470 if(c->titlebar && c->titlebar->sw.window == w)
471 return c->titlebar;
473 return NULL;
476 /** Draw a wibox.
477 * \param wibox The wibox to draw.
479 static void
480 wibox_draw(wibox_t *wibox)
482 if(wibox->isvisible)
484 widget_render(&wibox->widgets, &wibox->sw.ctx, wibox->sw.gc,
485 wibox->sw.pixmap,
486 wibox->screen, wibox->sw.orientation,
487 wibox->sw.geometry.x, wibox->sw.geometry.y,
488 wibox);
489 simplewindow_refresh_pixmap(&wibox->sw);
491 wibox->need_update = false;
494 wibox_systray_refresh(wibox);
497 /** Refresh all wiboxes.
499 void
500 wibox_refresh(void)
502 for(int screen = 0; screen < globalconf.nscreen; screen++)
503 for(int i = 0; i < globalconf.screens[screen].wiboxes.len; i++)
505 wibox_t *s = globalconf.screens[screen].wiboxes.tab[i];
506 if(s->need_update)
507 wibox_draw(s);
510 for(client_t *c = globalconf.clients; c; c = c->next)
511 if(c->titlebar && c->titlebar->need_update)
512 wibox_draw(c->titlebar);
515 /** Set a wibox visible or not.
516 * \param wibox The wibox.
517 * \param v The visible value.
519 static void
520 wibox_setvisible(wibox_t *wibox, bool v)
522 if(v != wibox->isvisible)
524 if((wibox->isvisible = v))
526 xcb_map_window(globalconf.connection, wibox->sw.window);
527 simplewindow_refresh_pixmap(&wibox->sw);
528 /* stack correctly the wibox */
529 client_stack();
531 else
532 xcb_unmap_window(globalconf.connection, wibox->sw.window);
534 /* kick out systray if needed */
535 wibox_systray_refresh(wibox);
537 /* All the other wibox and ourselves need to be repositioned */
538 wibox_array_t *w = &globalconf.screens[wibox->screen].wiboxes;
539 for(int i = 0; i < w->len; i++)
540 wibox_position_update(w->tab[i]);
544 /** Remove a wibox from a screen.
545 * \param wibox Wibox to detach from screen.
547 void
548 wibox_detach(wibox_t *wibox)
550 if(wibox->screen != SCREEN_UNDEF)
552 bool v;
554 /* save visible state */
555 v = wibox->isvisible;
556 wibox->isvisible = false;
557 wibox_systray_refresh(wibox);
558 wibox_position_update(wibox);
559 /* restore position */
560 wibox->isvisible = v;
562 simplewindow_wipe(&wibox->sw);
564 for(int i = 0; i < globalconf.screens[wibox->screen].wiboxes.len; i++)
565 if(globalconf.screens[wibox->screen].wiboxes.tab[i] == wibox)
567 wibox_array_take(&globalconf.screens[wibox->screen].wiboxes, i);
568 break;
570 globalconf.screens[wibox->screen].need_arrange = true;
571 wibox->screen = SCREEN_UNDEF;
572 wibox_unref(&wibox);
576 /** Attach a wibox.
577 * \param wibox The wibox to attach.
578 * \param s The screen to attach the wibox to.
580 void
581 wibox_attach(wibox_t *wibox, screen_t *s)
583 int phys_screen = screen_virttophys(s->index);
585 wibox_detach(wibox);
587 wibox->screen = s->index;
589 wibox_array_append(&s->wiboxes, wibox_ref(&wibox));
591 /* compute x/y/width/height if not set */
592 wibox_position_update(wibox);
594 simplewindow_init(&wibox->sw, phys_screen,
595 wibox->sw.geometry,
596 wibox->sw.border.width,
597 wibox->sw.orientation,
598 &wibox->sw.ctx.fg, &wibox->sw.ctx.bg);
600 simplewindow_border_color_set(&wibox->sw, &wibox->sw.border.color);
602 /* All the other wibox and ourselves need to be repositioned */
603 for(int i = 0; i < s->wiboxes.len; i++)
604 wibox_position_update(s->wiboxes.tab[i]);
606 ewmh_update_workarea(screen_virttophys(s->index));
608 if(wibox->isvisible)
610 /* draw it right now once to avoid garbage shown */
611 wibox_draw(wibox);
612 xcb_map_window(globalconf.connection, wibox->sw.window);
613 simplewindow_refresh_pixmap(&wibox->sw);
614 /* stack correctly the wibox */
615 client_stack();
617 else
618 wibox->need_update = true;
621 /** Create a new wibox.
622 * \param L The Lua VM state.
624 * \luastack
625 * \lparam A table with optionaly defined values:
626 * position, align, fg, bg, border_width, border_color, width and height.
627 * \lreturn A brand new wibox.
630 luaA_wibox_new(lua_State *L)
632 wibox_t *w;
633 const char *buf;
634 size_t len;
635 xcolor_init_request_t reqs[3];
636 int8_t i, reqs_nbr = -1;
638 luaA_checktable(L, 2);
640 w = p_new(wibox_t, 1);
641 w->widgets_table = LUA_REFNIL;
643 w->sw.ctx.fg = globalconf.colors.fg;
644 if((buf = luaA_getopt_lstring(L, 2, "fg", NULL, &len)))
645 reqs[++reqs_nbr] = xcolor_init_unchecked(&w->sw.ctx.fg, buf, len);
647 w->sw.ctx.bg = globalconf.colors.bg;
648 if((buf = luaA_getopt_lstring(L, 2, "bg", NULL, &len)))
649 reqs[++reqs_nbr] = xcolor_init_unchecked(&w->sw.ctx.bg, buf, len);
651 w->sw.border.color = globalconf.colors.bg;
652 if((buf = luaA_getopt_lstring(L, 2, "border_color", NULL, &len)))
653 reqs[++reqs_nbr] = xcolor_init_unchecked(&w->sw.border.color, buf, len);
655 buf = luaA_getopt_lstring(L, 2, "align", "left", &len);
656 w->align = draw_align_fromstr(buf, len);
658 w->sw.border.width = luaA_getopt_number(L, 2, "border_width", 0);
660 buf = luaA_getopt_lstring(L, 2, "position", "top", &len);
662 switch((w->position = position_fromstr(buf, len)))
664 case Bottom:
665 case Top:
666 case Floating:
667 simplewindow_orientation_set(&w->sw, East);
668 break;
669 case Left:
670 simplewindow_orientation_set(&w->sw, North);
671 break;
672 case Right:
673 simplewindow_orientation_set(&w->sw, South);
674 break;
677 /* recompute position */
678 wibox_position_update(w);
680 w->sw.geometry.width = luaA_getopt_number(L, 2, "width", 0);
681 w->sw.geometry.height = luaA_getopt_number(L, 2, "height", 0);
683 w->screen = SCREEN_UNDEF;
684 w->isvisible = true;
686 for(i = 0; i <= reqs_nbr; i++)
687 xcolor_init_reply(reqs[i]);
689 return luaA_wibox_userdata_new(L, w);
692 /** Rebuild wibox widgets list.
693 * \param L The Lua VM state.
694 * \param wibox The wibox.
696 static void
697 wibox_widgets_table_build(lua_State *L, wibox_t *wibox)
699 widget_node_array_wipe(&wibox->widgets);
700 widget_node_array_init(&wibox->widgets);
701 luaA_table2widgets(L, &wibox->widgets);
702 wibox->mouse_over = NULL;
703 wibox->need_update = true;
706 /** Check if a wibox widget table has an item.
707 * \param L The Lua VM state.
708 * \param wibox The wibox.
709 * \param item The item to look for.
711 static bool
712 luaA_wibox_hasitem(lua_State *L, wibox_t *wibox, const void *item)
714 bool ret = false;
715 if(wibox->widgets_table != LUA_REFNIL)
717 lua_rawgeti(globalconf.L, LUA_REGISTRYINDEX, wibox->widgets_table);
718 if(lua_topointer(L, -1) == item || luaA_hasitem(L, item))
719 ret = true;
721 return ret;
724 /** Invalidate a wibox by a Lua object (table, etc).
725 * \param L The Lua VM state.
726 * \param item The object identifier.
728 void
729 luaA_wibox_invalidate_byitem(lua_State *L, const void *item)
731 for(int screen = 0; screen < globalconf.nscreen; screen++)
732 for(int i = 0; i < globalconf.screens[screen].wiboxes.len; i++)
734 wibox_t *wibox = globalconf.screens[screen].wiboxes.tab[i];
735 if(luaA_wibox_hasitem(L, wibox, item))
737 /* recompute widget node list */
738 wibox_widgets_table_build(L, wibox);
739 lua_pop(L, 1); /* remove widgets table */
744 for(client_t *c = globalconf.clients; c; c = c->next)
745 if(c->titlebar && luaA_wibox_hasitem(L, c->titlebar, item))
747 /* recompute widget node list */
748 wibox_widgets_table_build(L, c->titlebar);
749 lua_pop(L, 1); /* remove widgets table */
754 /** Wibox object.
755 * \param L The Lua VM state.
756 * \return The number of elements pushed on stack.
757 * \luastack
758 * \lfield screen Screen number.
759 * \lfield client The client attached to this titlebar.
760 * \lfield border_width Border width.
761 * \lfield border_color Border color.
762 * \lfield align The alignment.
763 * \lfield fg Foreground color.
764 * \lfield bg Background color.
765 * \lfield position The position.
766 * \lfield ontop On top of other windows.
768 static int
769 luaA_wibox_index(lua_State *L)
771 size_t len;
772 wibox_t **wibox = luaA_checkudata(L, 1, "wibox");
773 const char *attr = luaL_checklstring(L, 2, &len);
775 if(luaA_usemetatable(L, 1, 2))
776 return 1;
778 switch(a_tokenize(attr, len))
780 client_t *c;
782 case A_TK_VISIBLE:
783 lua_pushboolean(L, (*wibox)->isvisible);
784 break;
785 case A_TK_CLIENT:
786 if((c = client_getbytitlebar(*wibox)))
787 return luaA_client_userdata_new(L, c);
788 else
789 return 0;
790 case A_TK_SCREEN:
791 if((*wibox)->screen == SCREEN_UNDEF)
792 return 0;
793 lua_pushnumber(L, (*wibox)->screen + 1);
794 break;
795 case A_TK_BORDER_WIDTH:
796 lua_pushnumber(L, (*wibox)->sw.border.width);
797 break;
798 case A_TK_BORDER_COLOR:
799 luaA_pushcolor(L, &(*wibox)->sw.border.color);
800 break;
801 case A_TK_ALIGN:
802 lua_pushstring(L, draw_align_tostr((*wibox)->align));
803 break;
804 case A_TK_FG:
805 luaA_pushcolor(L, &(*wibox)->sw.ctx.fg);
806 break;
807 case A_TK_BG:
808 luaA_pushcolor(L, &(*wibox)->sw.ctx.bg);
809 break;
810 case A_TK_POSITION:
811 lua_pushstring(L, position_tostr((*wibox)->position));
812 break;
813 case A_TK_ONTOP:
814 lua_pushboolean(L, (*wibox)->ontop);
815 break;
816 case A_TK_ORIENTATION:
817 lua_pushstring(L, orientation_tostr((*wibox)->sw.orientation));
818 break;
819 case A_TK_WIDGETS:
820 if((*wibox)->widgets_table != LUA_REFNIL)
821 lua_rawgeti(L, LUA_REGISTRYINDEX, (*wibox)->widgets_table);
822 else
823 lua_pushnil(L);
824 break;
825 default:
826 return 0;
829 return 1;
832 /* Set or get the wibox geometry.
833 * \param L The Lua VM state.
834 * \return The number of elements pushed on stack.
835 * \luastack
836 * \lparam An optional table with wibox geometry.
837 * \lreturn The wibox geometry.
839 static int
840 luaA_wibox_geometry(lua_State *L)
842 wibox_t **wibox = luaA_checkudata(L, 1, "wibox");
844 if(lua_gettop(L) == 2)
846 area_t wingeom;
848 luaA_checktable(L, 2);
849 wingeom.x = luaA_getopt_number(L, 2, "x", (*wibox)->sw.geometry.x);
850 wingeom.y = luaA_getopt_number(L, 2, "y", (*wibox)->sw.geometry.y);
851 wingeom.width = luaA_getopt_number(L, 2, "width", (*wibox)->sw.geometry.width);
852 wingeom.height = luaA_getopt_number(L, 2, "height", (*wibox)->sw.geometry.height);
854 switch((*wibox)->type)
856 case WIBOX_TYPE_TITLEBAR:
857 wibox_resize(*wibox, wingeom.width, wingeom.height);
858 break;
859 case WIBOX_TYPE_NORMAL:
860 if((*wibox)->position == Floating)
861 wibox_moveresize(*wibox, wingeom);
862 else if(wingeom.width != (*wibox)->sw.geometry.width
863 || wingeom.height != (*wibox)->sw.geometry.height)
865 wibox_resize(*wibox, wingeom.width, wingeom.height);
866 globalconf.screens[(*wibox)->screen].need_arrange = true;
868 break;
872 return luaA_pusharea(L, (*wibox)->sw.geometry);
875 /** Wibox newindex.
876 * \param L The Lua VM state.
877 * \return The number of elements pushed on stack.
879 static int
880 luaA_wibox_newindex(lua_State *L)
882 size_t len;
883 wibox_t **wibox = luaA_checkudata(L, 1, "wibox");
884 const char *buf, *attr = luaL_checklstring(L, 2, &len);
885 awesome_token_t tok;
887 switch((tok = a_tokenize(attr, len)))
889 bool b;
891 case A_TK_FG:
892 if((buf = luaL_checklstring(L, 3, &len)))
893 if(xcolor_init_reply(xcolor_init_unchecked(&(*wibox)->sw.ctx.fg, buf, len)))
894 (*wibox)->need_update = true;
895 break;
896 case A_TK_BG:
897 if((buf = luaL_checklstring(L, 3, &len)))
898 if(xcolor_init_reply(xcolor_init_unchecked(&(*wibox)->sw.ctx.bg, buf, len)))
899 (*wibox)->need_update = true;
900 break;
901 case A_TK_ALIGN:
902 buf = luaL_checklstring(L, 3, &len);
903 (*wibox)->align = draw_align_fromstr(buf, len);
904 switch((*wibox)->type)
906 case WIBOX_TYPE_NORMAL:
907 wibox_position_update(*wibox);
908 break;
909 case WIBOX_TYPE_TITLEBAR:
910 titlebar_update_geometry_floating(client_getbytitlebar(*wibox));
911 break;
913 break;
914 case A_TK_POSITION:
915 switch((*wibox)->type)
917 case WIBOX_TYPE_TITLEBAR:
918 return luaA_titlebar_newindex(L, *wibox, tok);
919 case WIBOX_TYPE_NORMAL:
920 if((buf = luaL_checklstring(L, 3, &len)))
921 wibox_setposition(*wibox, position_fromstr(buf, len));
922 break;
924 break;
925 case A_TK_CLIENT:
926 /* first detach */
927 if(lua_isnil(L, 3))
928 titlebar_client_detach(client_getbytitlebar(*wibox));
929 else
931 client_t **c = luaA_checkudata(L, 3, "client");
932 titlebar_client_attach(*c, *wibox);
934 break;
935 case A_TK_SCREEN:
936 if(lua_isnil(L, 3))
938 wibox_detach(*wibox);
939 titlebar_client_detach(client_getbytitlebar(*wibox));
941 else
943 int screen = luaL_checknumber(L, 3) - 1;
944 luaA_checkscreen(screen);
945 if(screen != (*wibox)->screen)
947 titlebar_client_detach(client_getbytitlebar(*wibox));
948 wibox_attach(*wibox, &globalconf.screens[screen]);
951 break;
952 case A_TK_ONTOP:
953 b = luaA_checkboolean(L, 3);
954 if(b != (*wibox)->ontop)
956 (*wibox)->ontop = b;
957 client_stack();
959 break;
960 case A_TK_ORIENTATION:
961 if((buf = luaL_checklstring(L, 3, &len)))
963 simplewindow_orientation_set(&(*wibox)->sw, orientation_fromstr(buf, len));
964 (*wibox)->need_update = true;
966 break;
967 case A_TK_BORDER_COLOR:
968 if((buf = luaL_checklstring(L, 3, &len)))
969 if(xcolor_init_reply(xcolor_init_unchecked(&(*wibox)->sw.border.color, buf, len)))
970 if((*wibox)->sw.window)
971 simplewindow_border_color_set(&(*wibox)->sw, &(*wibox)->sw.border.color);
972 break;
973 case A_TK_VISIBLE:
974 b = luaA_checkboolean(L, 3);
975 if(b != (*wibox)->isvisible)
976 switch((*wibox)->type)
978 case WIBOX_TYPE_NORMAL:
979 wibox_setvisible(*wibox, b);
980 break;
981 case WIBOX_TYPE_TITLEBAR:
982 (*wibox)->isvisible = b;
983 globalconf.screens[(*wibox)->screen].need_arrange = true;
984 break;
986 break;
987 case A_TK_WIDGETS:
988 if(luaA_isloop(L, 3))
990 luaA_warn(L, "table is looping, cannot use this as widget table");
991 return 0;
993 luaA_register(L, 3, &(*wibox)->widgets_table);
994 /* recompute widget node list */
995 wibox_widgets_table_build(L, *wibox);
996 luaA_table2wtable(L);
997 break;
998 default:
999 switch((*wibox)->type)
1001 case WIBOX_TYPE_TITLEBAR:
1002 return luaA_titlebar_newindex(L, *wibox, tok);
1003 case WIBOX_TYPE_NORMAL:
1004 break;
1008 return 0;
1011 const struct luaL_reg awesome_wibox_methods[] =
1013 { "__call", luaA_wibox_new },
1014 { NULL, NULL }
1016 const struct luaL_reg awesome_wibox_meta[] =
1018 { "geometry", luaA_wibox_geometry },
1019 { "__index", luaA_wibox_index },
1020 { "__newindex", luaA_wibox_newindex },
1021 { "__gc", luaA_wibox_gc },
1022 { "__eq", luaA_wibox_eq },
1023 { "__tostring", luaA_wibox_tostring },
1024 { NULL, NULL },
1027 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80