wibox: reparent systray only if needed (FS#436)
[awesome.git] / wibox.c
blob26ee2828e389b7682a9cd75c1ad286f9e35c3ab5
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 if(globalconf.screens[phys_screen].systray.parent != s->root)
106 /* Who! Check that we're not deleting a wibox with a systray, because it
107 * may be its parent. If so, we reparent to root before, otherwise it will
108 * hurt very much. */
109 xcb_reparent_window(globalconf.connection,
110 globalconf.screens[phys_screen].systray.window,
111 s->root, -512, -512);
113 globalconf.screens[phys_screen].systray.parent = s->root;
117 static void
118 wibox_systray_refresh(wibox_t *wibox)
120 if(wibox->screen == SCREEN_UNDEF)
121 return;
123 for(int i = 0; i < wibox->widgets.len; i++)
125 widget_node_t *systray = &wibox->widgets.tab[i];
126 if(systray->widget->type == systray_new)
128 uint32_t config_back[] = { wibox->sw.ctx.bg.pixel };
129 uint32_t config_win_vals[4];
130 uint32_t config_win_vals_off[2] = { -512, -512 };
131 xembed_window_t *em;
132 position_t pos;
133 int phys_screen = wibox->sw.ctx.phys_screen;
135 if(wibox->isvisible
136 && systray->widget->isvisible
137 && systray->geometry.width)
139 pos = wibox->position;
141 /* Set background of the systray window. */
142 xcb_change_window_attributes(globalconf.connection,
143 globalconf.screens[phys_screen].systray.window,
144 XCB_CW_BACK_PIXEL, config_back);
145 /* Map it. */
146 xcb_map_window(globalconf.connection, globalconf.screens[phys_screen].systray.window);
147 /* Move it. */
148 switch(wibox->position)
150 case Left:
151 config_win_vals[0] = systray->geometry.y;
152 config_win_vals[1] = wibox->sw.geometry.height - systray->geometry.x - systray->geometry.width;
153 config_win_vals[2] = systray->geometry.height;
154 config_win_vals[3] = systray->geometry.width;
155 break;
156 case Right:
157 config_win_vals[0] = systray->geometry.y;
158 config_win_vals[1] = systray->geometry.x;
159 config_win_vals[2] = systray->geometry.height;
160 config_win_vals[3] = systray->geometry.width;
161 break;
162 default:
163 config_win_vals[0] = systray->geometry.x;
164 config_win_vals[1] = systray->geometry.y;
165 config_win_vals[2] = systray->geometry.width;
166 config_win_vals[3] = systray->geometry.height;
167 break;
169 /* reparent */
170 if(globalconf.screens[phys_screen].systray.parent != wibox->sw.window)
172 xcb_reparent_window(globalconf.connection,
173 globalconf.screens[phys_screen].systray.window,
174 wibox->sw.window,
175 config_win_vals[0], config_win_vals[1]);
176 globalconf.screens[phys_screen].systray.parent = wibox->sw.window;
178 xcb_configure_window(globalconf.connection,
179 globalconf.screens[phys_screen].systray.window,
180 XCB_CONFIG_WINDOW_X
181 | XCB_CONFIG_WINDOW_Y
182 | XCB_CONFIG_WINDOW_WIDTH
183 | XCB_CONFIG_WINDOW_HEIGHT,
184 config_win_vals);
185 /* width = height = systray height */
186 config_win_vals[2] = config_win_vals[3] = systray->geometry.height;
187 config_win_vals[0] = 0;
189 else
190 return wibox_systray_kickout(phys_screen);
192 switch(pos)
194 case Left:
195 config_win_vals[1] = systray->geometry.width - config_win_vals[3];
196 for(em = globalconf.embedded; em; em = em->next)
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);
216 break;
217 case Right:
218 config_win_vals[1] = 0;
219 for(em = globalconf.embedded; em; em = em->next)
220 if(em->phys_screen == phys_screen)
222 if(config_win_vals[1] + config_win_vals[3] <= (uint32_t) wibox->sw.geometry.y + wibox->sw.geometry.width)
224 xcb_map_window(globalconf.connection, em->win);
225 xcb_configure_window(globalconf.connection, em->win,
226 XCB_CONFIG_WINDOW_X
227 | XCB_CONFIG_WINDOW_Y
228 | XCB_CONFIG_WINDOW_WIDTH
229 | XCB_CONFIG_WINDOW_HEIGHT,
230 config_win_vals);
231 config_win_vals[1] += config_win_vals[3];
233 else
234 xcb_configure_window(globalconf.connection, em->win,
235 XCB_CONFIG_WINDOW_X
236 | XCB_CONFIG_WINDOW_Y,
237 config_win_vals_off);
239 break;
240 case Floating:
241 case Top:
242 case Bottom:
243 config_win_vals[1] = 0;
244 for(em = globalconf.embedded; em; em = em->next)
245 if(em->phys_screen == phys_screen)
247 /* if(x + width < systray.x + systray.width) */
248 if(config_win_vals[0] + config_win_vals[2] <= (uint32_t) AREA_RIGHT(systray->geometry) + wibox->sw.geometry.x)
250 xcb_map_window(globalconf.connection, em->win);
251 xcb_configure_window(globalconf.connection, em->win,
252 XCB_CONFIG_WINDOW_X
253 | XCB_CONFIG_WINDOW_Y
254 | XCB_CONFIG_WINDOW_WIDTH
255 | XCB_CONFIG_WINDOW_HEIGHT,
256 config_win_vals);
257 config_win_vals[0] += config_win_vals[2];
259 else
260 xcb_configure_window(globalconf.connection, em->win,
261 XCB_CONFIG_WINDOW_X
262 | XCB_CONFIG_WINDOW_Y,
263 config_win_vals_off);
265 break;
267 break;
272 /** Update the wibox position. It deletes every wibox resources and
273 * create them back.
274 * \param wibox The wibox.
276 void
277 wibox_position_update(wibox_t *wibox)
279 area_t area, wingeom = wibox->sw.geometry;
280 bool ignore = false;
282 globalconf.screens[wibox->screen].need_arrange = true;
284 area = screen_area_get(wibox->screen, NULL,
285 &globalconf.screens[wibox->screen].padding, true);
287 /* Top and Bottom wibox_t have prio */
288 if(wibox->position != Floating)
289 for(int i = 0; i < globalconf.screens[wibox->screen].wiboxes.len; i++)
291 wibox_t *w = globalconf.screens[wibox->screen].wiboxes.tab[i];
292 /* Ignore every wibox after me that is in the same position */
293 if(wibox == w)
295 ignore = true;
296 continue;
298 else if((ignore && wibox->position == w->position) || !w->isvisible)
299 continue;
300 switch(w->position)
302 case Floating:
303 break;
304 case Left:
305 switch(wibox->position)
307 case Left:
308 area.x += wibox->sw.geometry.height;
309 break;
310 default:
311 break;
313 break;
314 case Right:
315 switch(wibox->position)
317 case Right:
318 area.x -= wibox->sw.geometry.height;
319 break;
320 default:
321 break;
323 break;
324 case Top:
325 switch(wibox->position)
327 case Top:
328 area.y += w->sw.geometry.height;
329 break;
330 case Left:
331 case Right:
332 area.height -= w->sw.geometry.height;
333 area.y += w->sw.geometry.height;
334 break;
335 default:
336 break;
338 break;
339 case Bottom:
340 switch(wibox->position)
342 case Bottom:
343 area.y -= w->sw.geometry.height;
344 break;
345 case Left:
346 case Right:
347 area.height -= w->sw.geometry.height;
348 break;
349 default:
350 break;
352 break;
356 switch(wibox->position)
358 case Right:
359 wingeom.height = wibox->sw.geometry.height > 0 ?
360 wibox->sw.geometry.height : area.height - 2 * wibox->sw.border.width;
361 wingeom.width = wibox->sw.geometry.width > 0 ? wibox->sw.geometry.width : 1.5 * globalconf.font->height;
362 wingeom.x = area.x + area.width - wingeom.width - 2 * wibox->sw.border.width;
363 switch(wibox->align)
365 default:
366 wingeom.y = area.y;
367 break;
368 case AlignRight:
369 wingeom.y = area.y + area.height - wingeom.height;
370 break;
371 case AlignCenter:
372 wingeom.y = (area.y + area.height - wingeom.height) / 2;
373 break;
375 break;
376 case Left:
377 wingeom.height = wibox->sw.geometry.height > 0 ?
378 wibox->sw.geometry.height : area.height - 2 * wibox->sw.border.width;
379 wingeom.width = wibox->sw.geometry.width > 0 ? wibox->sw.geometry.width : 1.5 * globalconf.font->height;
380 wingeom.x = area.x;
381 switch(wibox->align)
383 default:
384 wingeom.y = (area.y + area.height) - wingeom.height - 2 * wibox->sw.border.width;
385 break;
386 case AlignRight:
387 wingeom.y = area.y;
388 break;
389 case AlignCenter:
390 wingeom.y = (area.y + area.height - wingeom.height) / 2;
392 break;
393 case Bottom:
394 wingeom.height = wibox->sw.geometry.height > 0 ? wibox->sw.geometry.height : 1.5 * globalconf.font->height;
395 wingeom.width = wibox->sw.geometry.width > 0 ?
396 wibox->sw.geometry.width : area.width - 2 * wibox->sw.border.width;
397 wingeom.y = (area.y + area.height) - wingeom.height - 2 * wibox->sw.border.width;
398 wingeom.x = area.x;
399 switch(wibox->align)
401 default:
402 break;
403 case AlignRight:
404 wingeom.x += area.width - wingeom.width;
405 break;
406 case AlignCenter:
407 wingeom.x += (area.width - wingeom.width) / 2;
408 break;
410 break;
411 case Top:
412 wingeom.height = wibox->sw.geometry.height > 0 ? wibox->sw.geometry.height : 1.5 * globalconf.font->height;
413 wingeom.width = wibox->sw.geometry.width > 0 ?
414 wibox->sw.geometry.width : area.width - 2 * wibox->sw.border.width;
415 wingeom.x = area.x;
416 wingeom.y = area.y;
417 switch(wibox->align)
419 default:
420 break;
421 case AlignRight:
422 wingeom.x += area.width - wingeom.width;
423 break;
424 case AlignCenter:
425 wingeom.x += (area.width - wingeom.width) / 2;
426 break;
428 break;
429 case Floating:
430 wingeom.width = MAX(1, wibox->sw.geometry.width);
431 wingeom.height = MAX(1, wibox->sw.geometry.height);
432 break;
435 /* same window size and position ? */
436 if(wingeom.width != wibox->sw.geometry.width
437 || wingeom.height != wibox->sw.geometry.height)
438 wibox_resize(wibox, wingeom.width, wingeom.height);
440 if(wingeom.x != wibox->sw.geometry.x
441 || wingeom.y != wibox->sw.geometry.y)
442 wibox_move(wibox, wingeom.x, wingeom.y);
445 /** Delete a wibox.
446 * \param wibox wibox to delete.
448 void
449 wibox_delete(wibox_t **wibox)
451 simplewindow_wipe(&(*wibox)->sw);
452 luaL_unref(globalconf.L, LUA_REGISTRYINDEX, (*wibox)->widgets_table);
453 widget_node_array_wipe(&(*wibox)->widgets);
454 p_delete(wibox);
457 /** Get a wibox by its window.
458 * \param w The window id.
459 * \return A wibox if found, NULL otherwise.
461 wibox_t *
462 wibox_getbywin(xcb_window_t w)
464 for(int screen = 0; screen < globalconf.nscreen; screen++)
465 for(int i = 0; i < globalconf.screens[screen].wiboxes.len; i++)
467 wibox_t *s = globalconf.screens[screen].wiboxes.tab[i];
468 if(s->sw.window == w)
469 return s;
472 for(client_t *c = globalconf.clients; c; c = c->next)
473 if(c->titlebar && c->titlebar->sw.window == w)
474 return c->titlebar;
476 return NULL;
479 /** Draw a wibox.
480 * \param wibox The wibox to draw.
482 static void
483 wibox_draw(wibox_t *wibox)
485 if(wibox->isvisible)
487 widget_render(&wibox->widgets, &wibox->sw.ctx, wibox->sw.gc,
488 wibox->sw.pixmap,
489 wibox->screen, wibox->sw.orientation,
490 wibox->sw.geometry.x, wibox->sw.geometry.y,
491 wibox);
492 simplewindow_refresh_pixmap(&wibox->sw);
494 wibox->need_update = false;
497 wibox_systray_refresh(wibox);
500 /** Refresh all wiboxes.
502 void
503 wibox_refresh(void)
505 for(int screen = 0; screen < globalconf.nscreen; screen++)
506 for(int i = 0; i < globalconf.screens[screen].wiboxes.len; i++)
508 wibox_t *s = globalconf.screens[screen].wiboxes.tab[i];
509 if(s->need_update)
510 wibox_draw(s);
513 for(client_t *c = globalconf.clients; c; c = c->next)
514 if(c->titlebar && c->titlebar->need_update)
515 wibox_draw(c->titlebar);
518 /** Set a wibox visible or not.
519 * \param wibox The wibox.
520 * \param v The visible value.
522 static void
523 wibox_setvisible(wibox_t *wibox, bool v)
525 if(v != wibox->isvisible)
527 wibox->isvisible = v;
528 wibox->mouse_over = NULL;
530 if(wibox->screen != SCREEN_UNDEF)
532 if(wibox->isvisible)
534 xcb_map_window(globalconf.connection, wibox->sw.window);
535 simplewindow_refresh_pixmap(&wibox->sw);
536 /* stack correctly the wibox */
537 client_stack();
539 else
540 xcb_unmap_window(globalconf.connection, wibox->sw.window);
542 /* kick out systray if needed */
543 wibox_systray_refresh(wibox);
545 /* All the other wibox and ourselves need to be repositioned */
546 wibox_array_t *w = &globalconf.screens[wibox->screen].wiboxes;
547 for(int i = 0; i < w->len; i++)
548 wibox_position_update(w->tab[i]);
553 /** Remove a wibox from a screen.
554 * \param wibox Wibox to detach from screen.
556 void
557 wibox_detach(wibox_t *wibox)
559 if(wibox->screen != SCREEN_UNDEF)
561 bool v;
563 /* save visible state */
564 v = wibox->isvisible;
565 wibox->isvisible = false;
566 wibox_systray_refresh(wibox);
567 wibox_position_update(wibox);
568 /* restore position */
569 wibox->isvisible = v;
571 wibox->mouse_over = NULL;
573 simplewindow_wipe(&wibox->sw);
575 for(int i = 0; i < globalconf.screens[wibox->screen].wiboxes.len; i++)
576 if(globalconf.screens[wibox->screen].wiboxes.tab[i] == wibox)
578 wibox_array_take(&globalconf.screens[wibox->screen].wiboxes, i);
579 break;
581 globalconf.screens[wibox->screen].need_arrange = true;
582 wibox->screen = SCREEN_UNDEF;
583 wibox_unref(&wibox);
587 /** Attach a wibox.
588 * \param wibox The wibox to attach.
589 * \param s The screen to attach the wibox to.
591 void
592 wibox_attach(wibox_t *wibox, screen_t *s)
594 int phys_screen = screen_virttophys(s->index);
596 wibox_detach(wibox);
598 wibox->screen = s->index;
600 wibox_array_append(&s->wiboxes, wibox_ref(&wibox));
602 /* compute x/y/width/height if not set */
603 wibox_position_update(wibox);
605 simplewindow_init(&wibox->sw, phys_screen,
606 wibox->sw.geometry,
607 wibox->sw.border.width,
608 wibox->sw.orientation,
609 &wibox->sw.ctx.fg, &wibox->sw.ctx.bg);
611 simplewindow_border_color_set(&wibox->sw, &wibox->sw.border.color);
613 /* All the other wibox and ourselves need to be repositioned */
614 for(int i = 0; i < s->wiboxes.len; i++)
615 wibox_position_update(s->wiboxes.tab[i]);
617 ewmh_update_workarea(screen_virttophys(s->index));
619 if(wibox->isvisible)
621 /* draw it right now once to avoid garbage shown */
622 wibox_draw(wibox);
623 xcb_map_window(globalconf.connection, wibox->sw.window);
624 simplewindow_refresh_pixmap(&wibox->sw);
625 /* stack correctly the wibox */
626 client_stack();
628 else
629 wibox->need_update = true;
632 /** Create a new wibox.
633 * \param L The Lua VM state.
635 * \luastack
636 * \lparam A table with optionaly defined values:
637 * position, align, fg, bg, border_width, border_color, width and height.
638 * \lreturn A brand new wibox.
641 luaA_wibox_new(lua_State *L)
643 wibox_t *w;
644 const char *buf;
645 size_t len;
646 xcolor_init_request_t reqs[3];
647 int8_t i, reqs_nbr = -1;
649 luaA_checktable(L, 2);
651 w = p_new(wibox_t, 1);
652 w->widgets_table = LUA_REFNIL;
654 w->sw.ctx.fg = globalconf.colors.fg;
655 if((buf = luaA_getopt_lstring(L, 2, "fg", NULL, &len)))
656 reqs[++reqs_nbr] = xcolor_init_unchecked(&w->sw.ctx.fg, buf, len);
658 w->sw.ctx.bg = globalconf.colors.bg;
659 if((buf = luaA_getopt_lstring(L, 2, "bg", NULL, &len)))
660 reqs[++reqs_nbr] = xcolor_init_unchecked(&w->sw.ctx.bg, buf, len);
662 w->sw.border.color = globalconf.colors.bg;
663 if((buf = luaA_getopt_lstring(L, 2, "border_color", NULL, &len)))
664 reqs[++reqs_nbr] = xcolor_init_unchecked(&w->sw.border.color, buf, len);
666 buf = luaA_getopt_lstring(L, 2, "align", "left", &len);
667 w->align = draw_align_fromstr(buf, len);
669 w->sw.border.width = luaA_getopt_number(L, 2, "border_width", 0);
671 buf = luaA_getopt_lstring(L, 2, "position", "top", &len);
673 switch((w->position = position_fromstr(buf, len)))
675 case Bottom:
676 case Top:
677 case Floating:
678 simplewindow_orientation_set(&w->sw, East);
679 break;
680 case Left:
681 simplewindow_orientation_set(&w->sw, North);
682 break;
683 case Right:
684 simplewindow_orientation_set(&w->sw, South);
685 break;
688 /* recompute position */
689 wibox_position_update(w);
691 w->sw.geometry.width = luaA_getopt_number(L, 2, "width", 0);
692 w->sw.geometry.height = luaA_getopt_number(L, 2, "height", 0);
694 w->screen = SCREEN_UNDEF;
695 w->isvisible = true;
697 for(i = 0; i <= reqs_nbr; i++)
698 xcolor_init_reply(reqs[i]);
700 return luaA_wibox_userdata_new(L, w);
703 /** Rebuild wibox widgets list.
704 * \param L The Lua VM state.
705 * \param wibox The wibox.
707 static void
708 wibox_widgets_table_build(lua_State *L, wibox_t *wibox)
710 widget_node_array_wipe(&wibox->widgets);
711 widget_node_array_init(&wibox->widgets);
712 luaA_table2widgets(L, &wibox->widgets);
713 wibox->mouse_over = NULL;
714 wibox->need_update = true;
717 /** Check if a wibox widget table has an item.
718 * \param L The Lua VM state.
719 * \param wibox The wibox.
720 * \param item The item to look for.
722 static bool
723 luaA_wibox_hasitem(lua_State *L, wibox_t *wibox, const void *item)
725 if(wibox->widgets_table != LUA_REFNIL)
727 lua_rawgeti(globalconf.L, LUA_REGISTRYINDEX, wibox->widgets_table);
728 if(lua_topointer(L, -1) == item || luaA_hasitem(L, item))
729 return true;
731 return false;
734 /** Invalidate a wibox by a Lua object (table, etc).
735 * \param L The Lua VM state.
736 * \param item The object identifier.
738 void
739 luaA_wibox_invalidate_byitem(lua_State *L, const void *item)
741 for(int screen = 0; screen < globalconf.nscreen; screen++)
742 for(int i = 0; i < globalconf.screens[screen].wiboxes.len; i++)
744 wibox_t *wibox = globalconf.screens[screen].wiboxes.tab[i];
745 if(luaA_wibox_hasitem(L, wibox, item))
747 /* recompute widget node list */
748 wibox_widgets_table_build(L, wibox);
749 lua_pop(L, 1); /* remove widgets table */
754 for(client_t *c = globalconf.clients; c; c = c->next)
755 if(c->titlebar && luaA_wibox_hasitem(L, c->titlebar, item))
757 /* recompute widget node list */
758 wibox_widgets_table_build(L, c->titlebar);
759 lua_pop(L, 1); /* remove widgets table */
763 /** Wibox object.
764 * \param L The Lua VM state.
765 * \return The number of elements pushed on stack.
766 * \luastack
767 * \lfield screen Screen number.
768 * \lfield client The client attached to this titlebar.
769 * \lfield border_width Border width.
770 * \lfield border_color Border color.
771 * \lfield align The alignment.
772 * \lfield fg Foreground color.
773 * \lfield bg Background color.
774 * \lfield position The position.
775 * \lfield ontop On top of other windows.
777 static int
778 luaA_wibox_index(lua_State *L)
780 size_t len;
781 wibox_t **wibox = luaA_checkudata(L, 1, "wibox");
782 const char *attr = luaL_checklstring(L, 2, &len);
784 if(luaA_usemetatable(L, 1, 2))
785 return 1;
787 switch(a_tokenize(attr, len))
789 client_t *c;
791 case A_TK_VISIBLE:
792 lua_pushboolean(L, (*wibox)->isvisible);
793 break;
794 case A_TK_CLIENT:
795 if((c = client_getbytitlebar(*wibox)))
796 return luaA_client_userdata_new(L, c);
797 else
798 return 0;
799 case A_TK_SCREEN:
800 if((*wibox)->screen == SCREEN_UNDEF)
801 return 0;
802 lua_pushnumber(L, (*wibox)->screen + 1);
803 break;
804 case A_TK_BORDER_WIDTH:
805 lua_pushnumber(L, (*wibox)->sw.border.width);
806 break;
807 case A_TK_BORDER_COLOR:
808 luaA_pushcolor(L, &(*wibox)->sw.border.color);
809 break;
810 case A_TK_ALIGN:
811 lua_pushstring(L, draw_align_tostr((*wibox)->align));
812 break;
813 case A_TK_FG:
814 luaA_pushcolor(L, &(*wibox)->sw.ctx.fg);
815 break;
816 case A_TK_BG:
817 luaA_pushcolor(L, &(*wibox)->sw.ctx.bg);
818 break;
819 case A_TK_POSITION:
820 lua_pushstring(L, position_tostr((*wibox)->position));
821 break;
822 case A_TK_ONTOP:
823 lua_pushboolean(L, (*wibox)->ontop);
824 break;
825 case A_TK_ORIENTATION:
826 lua_pushstring(L, orientation_tostr((*wibox)->sw.orientation));
827 break;
828 case A_TK_WIDGETS:
829 if((*wibox)->widgets_table != LUA_REFNIL)
830 lua_rawgeti(L, LUA_REGISTRYINDEX, (*wibox)->widgets_table);
831 else
832 lua_pushnil(L);
833 break;
834 default:
835 return 0;
838 return 1;
841 /* Set or get the wibox geometry.
842 * \param L The Lua VM state.
843 * \return The number of elements pushed on stack.
844 * \luastack
845 * \lparam An optional table with wibox geometry.
846 * \lreturn The wibox geometry.
848 static int
849 luaA_wibox_geometry(lua_State *L)
851 wibox_t **wibox = luaA_checkudata(L, 1, "wibox");
853 if(lua_gettop(L) == 2)
855 area_t wingeom;
857 luaA_checktable(L, 2);
858 wingeom.x = luaA_getopt_number(L, 2, "x", (*wibox)->sw.geometry.x);
859 wingeom.y = luaA_getopt_number(L, 2, "y", (*wibox)->sw.geometry.y);
860 wingeom.width = luaA_getopt_number(L, 2, "width", (*wibox)->sw.geometry.width);
861 wingeom.height = luaA_getopt_number(L, 2, "height", (*wibox)->sw.geometry.height);
863 switch((*wibox)->type)
865 case WIBOX_TYPE_TITLEBAR:
866 wibox_resize(*wibox, wingeom.width, wingeom.height);
867 break;
868 case WIBOX_TYPE_NORMAL:
869 if((*wibox)->position == Floating)
870 wibox_moveresize(*wibox, wingeom);
871 else if(wingeom.width != (*wibox)->sw.geometry.width
872 || wingeom.height != (*wibox)->sw.geometry.height)
874 wibox_resize(*wibox, wingeom.width, wingeom.height);
875 globalconf.screens[(*wibox)->screen].need_arrange = true;
877 break;
881 return luaA_pusharea(L, (*wibox)->sw.geometry);
884 /** Wibox newindex.
885 * \param L The Lua VM state.
886 * \return The number of elements pushed on stack.
888 static int
889 luaA_wibox_newindex(lua_State *L)
891 size_t len;
892 wibox_t **wibox = luaA_checkudata(L, 1, "wibox");
893 const char *buf, *attr = luaL_checklstring(L, 2, &len);
894 awesome_token_t tok;
896 switch((tok = a_tokenize(attr, len)))
898 bool b;
900 case A_TK_FG:
901 if((buf = luaL_checklstring(L, 3, &len)))
902 if(xcolor_init_reply(xcolor_init_unchecked(&(*wibox)->sw.ctx.fg, buf, len)))
903 (*wibox)->need_update = true;
904 break;
905 case A_TK_BG:
906 if((buf = luaL_checklstring(L, 3, &len)))
907 if(xcolor_init_reply(xcolor_init_unchecked(&(*wibox)->sw.ctx.bg, buf, len)))
908 (*wibox)->need_update = true;
909 break;
910 case A_TK_ALIGN:
911 buf = luaL_checklstring(L, 3, &len);
912 (*wibox)->align = draw_align_fromstr(buf, len);
913 switch((*wibox)->type)
915 case WIBOX_TYPE_NORMAL:
916 wibox_position_update(*wibox);
917 break;
918 case WIBOX_TYPE_TITLEBAR:
919 titlebar_update_geometry_floating(client_getbytitlebar(*wibox));
920 break;
922 break;
923 case A_TK_POSITION:
924 switch((*wibox)->type)
926 case WIBOX_TYPE_TITLEBAR:
927 return luaA_titlebar_newindex(L, *wibox, tok);
928 case WIBOX_TYPE_NORMAL:
929 if((buf = luaL_checklstring(L, 3, &len)))
930 wibox_setposition(*wibox, position_fromstr(buf, len));
931 break;
933 break;
934 case A_TK_CLIENT:
935 /* first detach */
936 if(lua_isnil(L, 3))
937 titlebar_client_detach(client_getbytitlebar(*wibox));
938 else
940 client_t **c = luaA_checkudata(L, 3, "client");
941 titlebar_client_attach(*c, *wibox);
943 break;
944 case A_TK_SCREEN:
945 if(lua_isnil(L, 3))
947 wibox_detach(*wibox);
948 titlebar_client_detach(client_getbytitlebar(*wibox));
950 else
952 int screen = luaL_checknumber(L, 3) - 1;
953 luaA_checkscreen(screen);
954 if(screen != (*wibox)->screen)
956 titlebar_client_detach(client_getbytitlebar(*wibox));
957 wibox_attach(*wibox, &globalconf.screens[screen]);
960 break;
961 case A_TK_ONTOP:
962 b = luaA_checkboolean(L, 3);
963 if(b != (*wibox)->ontop)
965 (*wibox)->ontop = b;
966 client_stack();
968 break;
969 case A_TK_ORIENTATION:
970 if((buf = luaL_checklstring(L, 3, &len)))
972 simplewindow_orientation_set(&(*wibox)->sw, orientation_fromstr(buf, len));
973 (*wibox)->need_update = true;
975 break;
976 case A_TK_BORDER_COLOR:
977 if((buf = luaL_checklstring(L, 3, &len)))
978 if(xcolor_init_reply(xcolor_init_unchecked(&(*wibox)->sw.border.color, buf, len)))
979 if((*wibox)->sw.window)
980 simplewindow_border_color_set(&(*wibox)->sw, &(*wibox)->sw.border.color);
981 break;
982 case A_TK_VISIBLE:
983 b = luaA_checkboolean(L, 3);
984 if(b != (*wibox)->isvisible)
985 switch((*wibox)->type)
987 case WIBOX_TYPE_NORMAL:
988 wibox_setvisible(*wibox, b);
989 break;
990 case WIBOX_TYPE_TITLEBAR:
991 (*wibox)->isvisible = b;
992 globalconf.screens[(*wibox)->screen].need_arrange = true;
993 break;
995 break;
996 case A_TK_WIDGETS:
997 if(luaA_isloop(L, 3))
999 luaA_warn(L, "table is looping, cannot use this as widget table");
1000 return 0;
1002 luaA_register(L, 3, &(*wibox)->widgets_table);
1003 /* recompute widget node list */
1004 wibox_widgets_table_build(L, *wibox);
1005 luaA_table2wtable(L);
1006 break;
1007 default:
1008 switch((*wibox)->type)
1010 case WIBOX_TYPE_TITLEBAR:
1011 return luaA_titlebar_newindex(L, *wibox, tok);
1012 case WIBOX_TYPE_NORMAL:
1013 break;
1017 return 0;
1020 const struct luaL_reg awesome_wibox_methods[] =
1022 { "__call", luaA_wibox_new },
1023 { NULL, NULL }
1025 const struct luaL_reg awesome_wibox_meta[] =
1027 { "geometry", luaA_wibox_geometry },
1028 { "__index", luaA_wibox_index },
1029 { "__newindex", luaA_wibox_newindex },
1030 { "__gc", luaA_wibox_gc },
1031 { "__eq", luaA_wibox_eq },
1032 { "__tostring", luaA_wibox_tostring },
1033 { NULL, NULL },
1036 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80