awful.layout.suit.magnifier: fix typo
[awesome.git] / wibox.c
blob7c01d7d7abbfa11f601a16a0127b674cabbc43d6
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;
62 wibox->mouse_over = NULL;
65 static void
66 wibox_setposition(wibox_t *wibox, position_t p)
68 if(p != wibox->position)
70 switch((wibox->position = p))
72 case Bottom:
73 case Top:
74 case Floating:
75 simplewindow_orientation_set(&wibox->sw, East);
76 break;
77 case Left:
78 simplewindow_orientation_set(&wibox->sw, North);
79 break;
80 case Right:
81 simplewindow_orientation_set(&wibox->sw, South);
82 break;
84 /* reset width/height to 0 */
85 if(wibox->position != Floating)
86 wibox->sw.geometry.width = wibox->sw.geometry.height = 0;
88 /* recompute position */
89 wibox_position_update(wibox);
91 /* reset all wibox position */
92 wibox_array_t *w = &globalconf.screens[wibox->screen].wiboxes;
93 for(int i = 0; i < w->len; i++)
94 wibox_position_update(w->tab[i]);
96 ewmh_update_workarea(screen_virttophys(wibox->screen));
98 wibox->need_update = true;
99 wibox->mouse_over = NULL;
103 /** Kick out systray windows.
104 * \param phys_screen Physical screen number.
106 static void
107 wibox_systray_kickout(int phys_screen)
109 xcb_screen_t *s = xutil_screen_get(globalconf.connection, phys_screen);
111 /* Who! Check that we're not deleting a wibox with a systray, because it
112 * may be its parent. If so, we reparent to root before, otherwise it will
113 * hurt very much. */
114 xcb_reparent_window(globalconf.connection,
115 globalconf.screens[phys_screen].systray.window,
116 s->root, -512, -512);
118 globalconf.screens[phys_screen].systray.parent = s->root;
121 static void
122 wibox_systray_refresh(wibox_t *wibox)
124 if(wibox->screen == SCREEN_UNDEF)
125 return;
127 for(int i = 0; i < wibox->widgets.len; i++)
129 widget_node_t *systray = &wibox->widgets.tab[i];
130 if(systray->widget->type == widget_systray)
132 uint32_t config_back[] = { wibox->sw.ctx.bg.pixel };
133 uint32_t config_win_vals[4];
134 uint32_t config_win_vals_off[2] = { -512, -512 };
135 xembed_window_t *em;
136 position_t pos;
137 int phys_screen = wibox->sw.ctx.phys_screen;
139 if(wibox->isvisible
140 && systray->widget->isvisible
141 && systray->geometry.width)
143 pos = wibox->position;
145 /* Set background of the systray window. */
146 xcb_change_window_attributes(globalconf.connection,
147 globalconf.screens[phys_screen].systray.window,
148 XCB_CW_BACK_PIXEL, config_back);
149 /* Map it. */
150 xcb_map_window(globalconf.connection, globalconf.screens[phys_screen].systray.window);
151 /* Move it. */
152 switch(wibox->position)
154 case Left:
155 config_win_vals[0] = systray->geometry.y;
156 config_win_vals[1] = wibox->sw.geometry.height - systray->geometry.x - systray->geometry.width;
157 config_win_vals[2] = systray->geometry.height;
158 config_win_vals[3] = systray->geometry.width;
159 break;
160 case Right:
161 config_win_vals[0] = systray->geometry.y;
162 config_win_vals[1] = systray->geometry.x;
163 config_win_vals[2] = systray->geometry.height;
164 config_win_vals[3] = systray->geometry.width;
165 break;
166 default:
167 config_win_vals[0] = systray->geometry.x;
168 config_win_vals[1] = systray->geometry.y;
169 config_win_vals[2] = systray->geometry.width;
170 config_win_vals[3] = systray->geometry.height;
171 break;
173 /* reparent */
174 if(globalconf.screens[phys_screen].systray.parent != wibox->sw.window)
176 xcb_reparent_window(globalconf.connection,
177 globalconf.screens[phys_screen].systray.window,
178 wibox->sw.window,
179 config_win_vals[0], config_win_vals[1]);
180 globalconf.screens[phys_screen].systray.parent = wibox->sw.window;
182 xcb_configure_window(globalconf.connection,
183 globalconf.screens[phys_screen].systray.window,
184 XCB_CONFIG_WINDOW_X
185 | XCB_CONFIG_WINDOW_Y
186 | XCB_CONFIG_WINDOW_WIDTH
187 | XCB_CONFIG_WINDOW_HEIGHT,
188 config_win_vals);
189 /* width = height = systray height */
190 config_win_vals[2] = config_win_vals[3] = systray->geometry.height;
191 config_win_vals[0] = 0;
193 else
194 return wibox_systray_kickout(phys_screen);
196 switch(pos)
198 case Left:
199 config_win_vals[1] = systray->geometry.width - config_win_vals[3];
200 for(int j = 0; j < globalconf.embedded.len; j++)
202 em = &globalconf.embedded.tab[j];
203 if(em->phys_screen == phys_screen)
205 if(config_win_vals[1] - config_win_vals[2] >= (uint32_t) wibox->sw.geometry.y)
207 xcb_map_window(globalconf.connection, em->win);
208 xcb_configure_window(globalconf.connection, em->win,
209 XCB_CONFIG_WINDOW_X
210 | XCB_CONFIG_WINDOW_Y
211 | XCB_CONFIG_WINDOW_WIDTH
212 | XCB_CONFIG_WINDOW_HEIGHT,
213 config_win_vals);
214 config_win_vals[1] -= config_win_vals[3];
216 else
217 xcb_configure_window(globalconf.connection, em->win,
218 XCB_CONFIG_WINDOW_X
219 | XCB_CONFIG_WINDOW_Y,
220 config_win_vals_off);
223 break;
224 case Right:
225 config_win_vals[1] = 0;
226 for(int j = 0; j < globalconf.embedded.len; j++)
228 em = &globalconf.embedded.tab[j];
229 if(em->phys_screen == phys_screen)
231 if(config_win_vals[1] + config_win_vals[3] <= (uint32_t) wibox->sw.geometry.y + wibox->sw.geometry.width)
233 xcb_map_window(globalconf.connection, em->win);
234 xcb_configure_window(globalconf.connection, em->win,
235 XCB_CONFIG_WINDOW_X
236 | XCB_CONFIG_WINDOW_Y
237 | XCB_CONFIG_WINDOW_WIDTH
238 | XCB_CONFIG_WINDOW_HEIGHT,
239 config_win_vals);
240 config_win_vals[1] += config_win_vals[3];
242 else
243 xcb_configure_window(globalconf.connection, em->win,
244 XCB_CONFIG_WINDOW_X
245 | XCB_CONFIG_WINDOW_Y,
246 config_win_vals_off);
249 break;
250 case Floating:
251 case Top:
252 case Bottom:
253 config_win_vals[1] = 0;
254 for(int j = 0; j < globalconf.embedded.len; j++)
256 em = &globalconf.embedded.tab[j];
257 if(em->phys_screen == phys_screen)
259 /* if(x + width < systray.x + systray.width) */
260 if(config_win_vals[0] + config_win_vals[2] <= (uint32_t) AREA_RIGHT(systray->geometry) + wibox->sw.geometry.x)
262 xcb_map_window(globalconf.connection, em->win);
263 xcb_configure_window(globalconf.connection, em->win,
264 XCB_CONFIG_WINDOW_X
265 | XCB_CONFIG_WINDOW_Y
266 | XCB_CONFIG_WINDOW_WIDTH
267 | XCB_CONFIG_WINDOW_HEIGHT,
268 config_win_vals);
269 config_win_vals[0] += config_win_vals[2];
271 else
272 xcb_configure_window(globalconf.connection, em->win,
273 XCB_CONFIG_WINDOW_X
274 | XCB_CONFIG_WINDOW_Y,
275 config_win_vals_off);
278 break;
280 break;
285 /** Update the wibox position. It deletes every wibox resources and
286 * create them back.
287 * \param wibox The wibox.
289 void
290 wibox_position_update(wibox_t *wibox)
292 area_t area, wingeom = wibox->sw.geometry;
293 bool ignore = false;
295 globalconf.screens[wibox->screen].need_arrange = true;
297 area = screen_area_get(wibox->screen, NULL,
298 &globalconf.screens[wibox->screen].padding, true);
300 /* Top and Bottom wibox_t have prio */
301 if(wibox->position != Floating)
302 for(int i = 0; i < globalconf.screens[wibox->screen].wiboxes.len; i++)
304 wibox_t *w = globalconf.screens[wibox->screen].wiboxes.tab[i];
305 /* Ignore every wibox after me that is in the same position */
306 if(wibox == w)
308 ignore = true;
309 continue;
311 else if((ignore && wibox->position == w->position) || !w->isvisible)
312 continue;
313 switch(w->position)
315 case Floating:
316 break;
317 case Left:
318 switch(wibox->position)
320 case Left:
321 area.x += wibox->sw.geometry.height;
322 break;
323 default:
324 break;
326 break;
327 case Right:
328 switch(wibox->position)
330 case Right:
331 area.x -= wibox->sw.geometry.height;
332 break;
333 default:
334 break;
336 break;
337 case Top:
338 switch(wibox->position)
340 case Top:
341 area.y += w->sw.geometry.height;
342 break;
343 case Left:
344 case Right:
345 area.height -= w->sw.geometry.height;
346 area.y += w->sw.geometry.height;
347 break;
348 default:
349 break;
351 break;
352 case Bottom:
353 switch(wibox->position)
355 case Bottom:
356 area.y -= w->sw.geometry.height;
357 break;
358 case Left:
359 case Right:
360 area.height -= w->sw.geometry.height;
361 break;
362 default:
363 break;
365 break;
369 /* The "length" of a wibox is always chosen to be the optimal size (non-floating).
370 * The "width" of a wibox is kept if it exists.
372 switch(wibox->position)
374 case Right:
375 wingeom.height = area.height;
376 wingeom.width = wibox->sw.geometry.width > 0 ? wibox->sw.geometry.width : 1.5 * globalconf.font->height;
377 wingeom.x = area.x + area.width - wingeom.width;
378 switch(wibox->align)
380 default:
381 wingeom.y = area.y;
382 break;
383 case AlignRight:
384 wingeom.y = area.y + area.height - wingeom.height;
385 break;
386 case AlignCenter:
387 wingeom.y = (area.y + area.height - wingeom.height) / 2;
388 break;
390 break;
391 case Left:
392 wingeom.height = area.height;
393 wingeom.width = wibox->sw.geometry.width > 0 ? wibox->sw.geometry.width : 1.5 * globalconf.font->height;
394 wingeom.x = area.x;
395 switch(wibox->align)
397 default:
398 wingeom.y = (area.y + area.height) - wingeom.height;
399 break;
400 case AlignRight:
401 wingeom.y = area.y;
402 break;
403 case AlignCenter:
404 wingeom.y = (area.y + area.height - wingeom.height) / 2;
406 break;
407 case Bottom:
408 wingeom.height = wibox->sw.geometry.height > 0 ? wibox->sw.geometry.height : 1.5 * globalconf.font->height;
409 wingeom.width = area.width;
410 wingeom.y = (area.y + area.height) - wingeom.height;
411 wingeom.x = area.x;
412 switch(wibox->align)
414 default:
415 break;
416 case AlignRight:
417 wingeom.x += area.width - wingeom.width;
418 break;
419 case AlignCenter:
420 wingeom.x += (area.width - wingeom.width) / 2;
421 break;
423 break;
424 case Top:
425 wingeom.height = wibox->sw.geometry.height > 0 ? wibox->sw.geometry.height : 1.5 * globalconf.font->height;
426 wingeom.width = area.width;
427 wingeom.x = area.x;
428 wingeom.y = area.y;
429 switch(wibox->align)
431 default:
432 break;
433 case AlignRight:
434 wingeom.x += area.width - wingeom.width;
435 break;
436 case AlignCenter:
437 wingeom.x += (area.width - wingeom.width) / 2;
438 break;
440 break;
441 case Floating:
442 wingeom.width = MAX(1, wibox->sw.geometry.width);
443 wingeom.height = MAX(1, wibox->sw.geometry.height);
444 break;
447 /* same window size and position ? */
448 if(wingeom.width != wibox->sw.geometry.width
449 || wingeom.height != wibox->sw.geometry.height)
450 wibox_resize(wibox, wingeom.width, wingeom.height);
452 if(wingeom.x != wibox->sw.geometry.x
453 || wingeom.y != wibox->sw.geometry.y)
454 wibox_move(wibox, wingeom.x, wingeom.y);
457 /** Delete a wibox.
458 * \param wibox wibox to delete.
460 void
461 wibox_delete(wibox_t **wibox)
463 simplewindow_wipe(&(*wibox)->sw);
464 button_array_wipe(&(*wibox)->buttons);
465 luaL_unref(globalconf.L, LUA_REGISTRYINDEX, (*wibox)->widgets_table);
466 widget_node_array_wipe(&(*wibox)->widgets);
467 p_delete(wibox);
470 /** Get a wibox by its window.
471 * \param w The window id.
472 * \return A wibox if found, NULL otherwise.
474 wibox_t *
475 wibox_getbywin(xcb_window_t w)
477 for(int screen = 0; screen < globalconf.nscreen; screen++)
478 for(int i = 0; i < globalconf.screens[screen].wiboxes.len; i++)
480 wibox_t *s = globalconf.screens[screen].wiboxes.tab[i];
481 if(s->sw.window == w)
482 return s;
485 for(client_t *c = globalconf.clients; c; c = c->next)
486 if(c->titlebar && c->titlebar->sw.window == w)
487 return c->titlebar;
489 return NULL;
492 /** Draw a wibox.
493 * \param wibox The wibox to draw.
495 static void
496 wibox_draw(wibox_t *wibox)
498 if(wibox->isvisible)
500 widget_render(wibox);
501 simplewindow_refresh_pixmap(&wibox->sw);
503 wibox->need_update = false;
506 wibox_systray_refresh(wibox);
509 /** Refresh all wiboxes.
511 void
512 wibox_refresh(void)
514 for(int screen = 0; screen < globalconf.nscreen; screen++)
515 for(int i = 0; i < globalconf.screens[screen].wiboxes.len; i++)
517 wibox_t *s = globalconf.screens[screen].wiboxes.tab[i];
518 if(s->need_update)
519 wibox_draw(s);
522 for(client_t *c = globalconf.clients; c; c = c->next)
523 if(c->titlebar && c->titlebar->need_update)
524 wibox_draw(c->titlebar);
527 /** Reposition all wiboxes.
529 void
530 wibox_update_positions(void)
532 for(int screen = 0; screen < globalconf.nscreen; screen++)
533 for(int i = 0; i < globalconf.screens[screen].wiboxes.len; i++)
535 wibox_t *s = globalconf.screens[screen].wiboxes.tab[i];
536 wibox_position_update(s);
540 /** Set a wibox visible or not.
541 * \param wibox The wibox.
542 * \param v The visible value.
544 static void
545 wibox_setvisible(wibox_t *wibox, bool v)
547 if(v != wibox->isvisible)
549 wibox->isvisible = v;
550 wibox->mouse_over = NULL;
552 if(wibox->screen != SCREEN_UNDEF)
554 if(wibox->isvisible)
556 xcb_map_window(globalconf.connection, wibox->sw.window);
557 simplewindow_refresh_pixmap(&wibox->sw);
558 /* stack correctly the wibox */
559 client_stack();
561 else
562 xcb_unmap_window(globalconf.connection, wibox->sw.window);
564 /* kick out systray if needed */
565 wibox_systray_refresh(wibox);
567 /* All the other wibox and ourselves need to be repositioned */
568 wibox_array_t *w = &globalconf.screens[wibox->screen].wiboxes;
569 for(int i = 0; i < w->len; i++)
570 wibox_position_update(w->tab[i]);
575 /** Remove a wibox from a screen.
576 * \param wibox Wibox to detach from screen.
578 void
579 wibox_detach(wibox_t *wibox)
581 if(wibox->screen != SCREEN_UNDEF)
583 bool v;
585 /* save visible state */
586 v = wibox->isvisible;
587 wibox->isvisible = false;
588 wibox_systray_refresh(wibox);
589 wibox_position_update(wibox);
590 /* restore position */
591 wibox->isvisible = v;
593 wibox->mouse_over = NULL;
595 simplewindow_wipe(&wibox->sw);
597 for(int i = 0; i < globalconf.screens[wibox->screen].wiboxes.len; i++)
598 if(globalconf.screens[wibox->screen].wiboxes.tab[i] == wibox)
600 wibox_array_take(&globalconf.screens[wibox->screen].wiboxes, i);
601 break;
603 globalconf.screens[wibox->screen].need_arrange = true;
604 wibox->screen = SCREEN_UNDEF;
605 wibox_unref(&wibox);
609 /** Attach a wibox.
610 * \param wibox The wibox to attach.
611 * \param s The screen to attach the wibox to.
613 void
614 wibox_attach(wibox_t *wibox, screen_t *s)
616 int phys_screen = screen_virttophys(s->index);
618 wibox_detach(wibox);
620 /* Set the wibox screen */
621 wibox->screen = s->index;
623 /* Check that the wibox coordinates matches the screen. */
624 int cscreen = screen_getbycoord(wibox->screen, wibox->sw.geometry.x, wibox->sw.geometry.y);
626 /* If it does not match, move it to the screen coordinates */
627 if(cscreen != wibox->screen)
628 wibox_move(wibox, s->geometry.x, s->geometry.y);
630 wibox_array_append(&s->wiboxes, wibox_ref(&wibox));
632 /* compute x/y/width/height if not set */
633 wibox_position_update(wibox);
635 simplewindow_init(&wibox->sw, phys_screen,
636 wibox->sw.geometry,
637 wibox->sw.border.width,
638 wibox->sw.orientation,
639 &wibox->sw.ctx.fg, &wibox->sw.ctx.bg);
641 simplewindow_border_color_set(&wibox->sw, &wibox->sw.border.color);
643 simplewindow_cursor_set(&wibox->sw,
644 xcursor_new(globalconf.connection, xcursor_font_fromstr(wibox->cursor)));
646 /* All the other wibox and ourselves need to be repositioned */
647 for(int i = 0; i < s->wiboxes.len; i++)
648 wibox_position_update(s->wiboxes.tab[i]);
650 ewmh_update_workarea(screen_virttophys(s->index));
652 if(wibox->isvisible)
654 /* draw it right now once to avoid garbage shown */
655 wibox_draw(wibox);
656 xcb_map_window(globalconf.connection, wibox->sw.window);
657 simplewindow_refresh_pixmap(&wibox->sw);
658 /* stack correctly the wibox */
659 client_stack();
661 else
662 wibox->need_update = true;
665 /** Create a new wibox.
666 * \param L The Lua VM state.
668 * \luastack
669 * \lparam A table with optionaly defined values:
670 * position, align, fg, bg, border_width, border_color, ontop, width and height.
671 * \lreturn A brand new wibox.
674 luaA_wibox_new(lua_State *L)
676 wibox_t *w;
677 const char *buf;
678 size_t len;
679 xcolor_init_request_t reqs[3];
680 int i, reqs_nbr = -1;
682 luaA_checktable(L, 2);
684 w = p_new(wibox_t, 1);
685 w->widgets_table = LUA_REFNIL;
687 w->sw.ctx.fg = globalconf.colors.fg;
688 if((buf = luaA_getopt_lstring(L, 2, "fg", NULL, &len)))
689 reqs[++reqs_nbr] = xcolor_init_unchecked(&w->sw.ctx.fg, buf, len);
691 w->sw.ctx.bg = globalconf.colors.bg;
692 if((buf = luaA_getopt_lstring(L, 2, "bg", NULL, &len)))
693 reqs[++reqs_nbr] = xcolor_init_unchecked(&w->sw.ctx.bg, buf, len);
695 w->sw.border.color = globalconf.colors.bg;
696 if((buf = luaA_getopt_lstring(L, 2, "border_color", NULL, &len)))
697 reqs[++reqs_nbr] = xcolor_init_unchecked(&w->sw.border.color, buf, len);
699 w->ontop = luaA_getopt_boolean(L, 2, "ontop", false);
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;
1029 (*wibox)->mouse_over = NULL;
1031 break;
1032 case A_TK_BORDER_COLOR:
1033 if((buf = luaL_checklstring(L, 3, &len)))
1034 if(xcolor_init_reply(xcolor_init_unchecked(&(*wibox)->sw.border.color, buf, len)))
1035 if((*wibox)->sw.window)
1036 simplewindow_border_color_set(&(*wibox)->sw, &(*wibox)->sw.border.color);
1037 break;
1038 case A_TK_VISIBLE:
1039 b = luaA_checkboolean(L, 3);
1040 if(b != (*wibox)->isvisible)
1041 switch((*wibox)->type)
1043 case WIBOX_TYPE_NORMAL:
1044 wibox_setvisible(*wibox, b);
1045 break;
1046 case WIBOX_TYPE_TITLEBAR:
1047 titlebar_set_visible(*wibox, b);
1048 break;
1050 break;
1051 case A_TK_WIDGETS:
1052 if(luaA_isloop(L, 3))
1054 luaA_warn(L, "table is looping, cannot use this as widget table");
1055 return 0;
1057 luaA_register(L, 3, &(*wibox)->widgets_table);
1058 /* recompute widget node list */
1059 wibox_widgets_table_build(L, *wibox);
1060 luaA_table2wtable(L);
1061 break;
1062 default:
1063 switch((*wibox)->type)
1065 case WIBOX_TYPE_TITLEBAR:
1066 return luaA_titlebar_newindex(L, *wibox, tok);
1067 case WIBOX_TYPE_NORMAL:
1068 break;
1072 return 0;
1075 /** Get or set mouse buttons bindings to a wibox.
1076 * \param L The Lua VM state.
1077 * \luastack
1078 * \lvalue A wibox.
1079 * \lparam An array of mouse button bindings objects, or nothing.
1080 * \return The array of mouse button bindings objects of this wibox.
1082 static int
1083 luaA_wibox_buttons(lua_State *L)
1085 wibox_t **wibox = luaA_checkudata(L, 1, "wibox");
1086 button_array_t *buttons = &(*wibox)->buttons;
1088 if(lua_gettop(L) == 2)
1090 luaA_button_array_set(L, 2, buttons);
1091 return 1;
1094 return luaA_button_array_get(L, buttons);
1097 const struct luaL_reg awesome_wibox_methods[] =
1099 { "__call", luaA_wibox_new },
1100 { NULL, NULL }
1102 const struct luaL_reg awesome_wibox_meta[] =
1104 { "buttons", luaA_wibox_buttons },
1105 { "geometry", luaA_wibox_geometry },
1106 { "__index", luaA_wibox_index },
1107 { "__newindex", luaA_wibox_newindex },
1108 { "__gc", luaA_wibox_gc },
1109 { "__eq", luaA_wibox_eq },
1110 { "__tostring", luaA_wibox_tostring },
1111 { NULL, NULL },
1114 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80