awful.client: fix floating detection
[awesome.git] / wibox.c
blob87e243339f08b1eaedfe2183aa4bfcba517b60d2
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;
548 wibox->mouse_over = NULL;
550 if(wibox->screen != SCREEN_UNDEF)
552 if(wibox->isvisible)
554 xcb_map_window(globalconf.connection, wibox->sw.window);
555 simplewindow_refresh_pixmap(&wibox->sw);
556 /* stack correctly the wibox */
557 client_stack();
559 else
560 xcb_unmap_window(globalconf.connection, wibox->sw.window);
562 /* kick out systray if needed */
563 wibox_systray_refresh(wibox);
565 /* All the other wibox and ourselves need to be repositioned */
566 wibox_array_t *w = &globalconf.screens[wibox->screen].wiboxes;
567 for(int i = 0; i < w->len; i++)
568 wibox_position_update(w->tab[i]);
573 /** Remove a wibox from a screen.
574 * \param wibox Wibox to detach from screen.
576 void
577 wibox_detach(wibox_t *wibox)
579 if(wibox->screen != SCREEN_UNDEF)
581 bool v;
583 /* save visible state */
584 v = wibox->isvisible;
585 wibox->isvisible = false;
586 wibox_systray_refresh(wibox);
587 wibox_position_update(wibox);
588 /* restore position */
589 wibox->isvisible = v;
591 wibox->mouse_over = NULL;
593 simplewindow_wipe(&wibox->sw);
595 for(int i = 0; i < globalconf.screens[wibox->screen].wiboxes.len; i++)
596 if(globalconf.screens[wibox->screen].wiboxes.tab[i] == wibox)
598 wibox_array_take(&globalconf.screens[wibox->screen].wiboxes, i);
599 break;
601 globalconf.screens[wibox->screen].need_arrange = true;
602 wibox->screen = SCREEN_UNDEF;
603 wibox_unref(&wibox);
607 /** Attach a wibox.
608 * \param wibox The wibox to attach.
609 * \param s The screen to attach the wibox to.
611 void
612 wibox_attach(wibox_t *wibox, screen_t *s)
614 int phys_screen = screen_virttophys(s->index);
616 wibox_detach(wibox);
618 wibox->screen = s->index;
620 wibox_array_append(&s->wiboxes, wibox_ref(&wibox));
622 /* compute x/y/width/height if not set */
623 wibox_position_update(wibox);
625 simplewindow_init(&wibox->sw, phys_screen,
626 wibox->sw.geometry,
627 wibox->sw.border.width,
628 wibox->sw.orientation,
629 &wibox->sw.ctx.fg, &wibox->sw.ctx.bg);
631 simplewindow_border_color_set(&wibox->sw, &wibox->sw.border.color);
633 simplewindow_cursor_set(&wibox->sw,
634 xcursor_new(globalconf.connection, xcursor_font_fromstr(wibox->cursor)));
636 /* All the other wibox and ourselves need to be repositioned */
637 for(int i = 0; i < s->wiboxes.len; i++)
638 wibox_position_update(s->wiboxes.tab[i]);
640 ewmh_update_workarea(screen_virttophys(s->index));
642 if(wibox->isvisible)
644 /* draw it right now once to avoid garbage shown */
645 wibox_draw(wibox);
646 xcb_map_window(globalconf.connection, wibox->sw.window);
647 simplewindow_refresh_pixmap(&wibox->sw);
648 /* stack correctly the wibox */
649 client_stack();
651 else
652 wibox->need_update = true;
655 /** Create a new wibox.
656 * \param L The Lua VM state.
658 * \luastack
659 * \lparam A table with optionaly defined values:
660 * position, align, fg, bg, border_width, border_color, width and height.
661 * \lreturn A brand new wibox.
664 luaA_wibox_new(lua_State *L)
666 wibox_t *w;
667 const char *buf;
668 size_t len;
669 xcolor_init_request_t reqs[3];
670 int8_t i, reqs_nbr = -1;
672 luaA_checktable(L, 2);
674 w = p_new(wibox_t, 1);
675 w->widgets_table = LUA_REFNIL;
677 w->sw.ctx.fg = globalconf.colors.fg;
678 if((buf = luaA_getopt_lstring(L, 2, "fg", NULL, &len)))
679 reqs[++reqs_nbr] = xcolor_init_unchecked(&w->sw.ctx.fg, buf, len);
681 w->sw.ctx.bg = globalconf.colors.bg;
682 if((buf = luaA_getopt_lstring(L, 2, "bg", NULL, &len)))
683 reqs[++reqs_nbr] = xcolor_init_unchecked(&w->sw.ctx.bg, buf, len);
685 w->sw.border.color = globalconf.colors.bg;
686 if((buf = luaA_getopt_lstring(L, 2, "border_color", NULL, &len)))
687 reqs[++reqs_nbr] = xcolor_init_unchecked(&w->sw.border.color, buf, len);
689 buf = luaA_getopt_lstring(L, 2, "align", "left", &len);
690 w->align = draw_align_fromstr(buf, len);
692 w->sw.border.width = luaA_getopt_number(L, 2, "border_width", 0);
694 buf = luaA_getopt_lstring(L, 2, "position", "top", &len);
696 switch((w->position = position_fromstr(buf, len)))
698 case Bottom:
699 case Top:
700 case Floating:
701 simplewindow_orientation_set(&w->sw, East);
702 break;
703 case Left:
704 simplewindow_orientation_set(&w->sw, North);
705 break;
706 case Right:
707 simplewindow_orientation_set(&w->sw, South);
708 break;
711 /* recompute position */
712 wibox_position_update(w);
714 w->sw.geometry.width = luaA_getopt_number(L, 2, "width", 0);
715 w->sw.geometry.height = luaA_getopt_number(L, 2, "height", 0);
717 w->screen = SCREEN_UNDEF;
718 w->isvisible = true;
719 w->cursor = a_strdup("left_ptr");
721 for(i = 0; i <= reqs_nbr; i++)
722 xcolor_init_reply(reqs[i]);
724 return luaA_wibox_userdata_new(L, w);
727 /** Rebuild wibox widgets list.
728 * \param L The Lua VM state.
729 * \param wibox The wibox.
731 static void
732 wibox_widgets_table_build(lua_State *L, wibox_t *wibox)
734 widget_node_array_wipe(&wibox->widgets);
735 widget_node_array_init(&wibox->widgets);
736 luaA_table2widgets(L, &wibox->widgets);
737 wibox->mouse_over = NULL;
738 wibox->need_update = true;
741 /** Check if a wibox widget table has an item.
742 * \param L The Lua VM state.
743 * \param wibox The wibox.
744 * \param item The item to look for.
746 static bool
747 luaA_wibox_hasitem(lua_State *L, wibox_t *wibox, const void *item)
749 if(wibox->widgets_table != LUA_REFNIL)
751 lua_rawgeti(globalconf.L, LUA_REGISTRYINDEX, wibox->widgets_table);
752 if(lua_topointer(L, -1) == item || luaA_hasitem(L, item))
753 return true;
755 return false;
758 /** Invalidate a wibox by a Lua object (table, etc).
759 * \param L The Lua VM state.
760 * \param item The object identifier.
762 void
763 luaA_wibox_invalidate_byitem(lua_State *L, const void *item)
765 for(int screen = 0; screen < globalconf.nscreen; screen++)
766 for(int i = 0; i < globalconf.screens[screen].wiboxes.len; i++)
768 wibox_t *wibox = globalconf.screens[screen].wiboxes.tab[i];
769 if(luaA_wibox_hasitem(L, wibox, item))
771 /* recompute widget node list */
772 wibox_widgets_table_build(L, wibox);
773 lua_pop(L, 1); /* remove widgets table */
778 for(client_t *c = globalconf.clients; c; c = c->next)
779 if(c->titlebar && luaA_wibox_hasitem(L, c->titlebar, item))
781 /* recompute widget node list */
782 wibox_widgets_table_build(L, c->titlebar);
783 lua_pop(L, 1); /* remove widgets table */
787 /** Wibox object.
788 * \param L The Lua VM state.
789 * \return The number of elements pushed on stack.
790 * \luastack
791 * \lfield screen Screen number.
792 * \lfield client The client attached to this titlebar.
793 * \lfield border_width Border width.
794 * \lfield border_color Border color.
795 * \lfield align The alignment.
796 * \lfield fg Foreground color.
797 * \lfield bg Background color.
798 * \lfield position The position.
799 * \lfield ontop On top of other windows.
800 * \lfield cursor The mouse cursor.
802 static int
803 luaA_wibox_index(lua_State *L)
805 size_t len;
806 wibox_t **wibox = luaA_checkudata(L, 1, "wibox");
807 const char *attr = luaL_checklstring(L, 2, &len);
809 if(luaA_usemetatable(L, 1, 2))
810 return 1;
812 switch(a_tokenize(attr, len))
814 client_t *c;
816 case A_TK_VISIBLE:
817 lua_pushboolean(L, (*wibox)->isvisible);
818 break;
819 case A_TK_CLIENT:
820 if((c = client_getbytitlebar(*wibox)))
821 return luaA_client_userdata_new(L, c);
822 else
823 return 0;
824 case A_TK_SCREEN:
825 if((*wibox)->screen == SCREEN_UNDEF)
826 return 0;
827 lua_pushnumber(L, (*wibox)->screen + 1);
828 break;
829 case A_TK_BORDER_WIDTH:
830 lua_pushnumber(L, (*wibox)->sw.border.width);
831 break;
832 case A_TK_BORDER_COLOR:
833 luaA_pushcolor(L, &(*wibox)->sw.border.color);
834 break;
835 case A_TK_ALIGN:
836 lua_pushstring(L, draw_align_tostr((*wibox)->align));
837 break;
838 case A_TK_FG:
839 luaA_pushcolor(L, &(*wibox)->sw.ctx.fg);
840 break;
841 case A_TK_BG:
842 luaA_pushcolor(L, &(*wibox)->sw.ctx.bg);
843 break;
844 case A_TK_POSITION:
845 lua_pushstring(L, position_tostr((*wibox)->position));
846 break;
847 case A_TK_ONTOP:
848 lua_pushboolean(L, (*wibox)->ontop);
849 break;
850 case A_TK_ORIENTATION:
851 lua_pushstring(L, orientation_tostr((*wibox)->sw.orientation));
852 break;
853 case A_TK_WIDGETS:
854 if((*wibox)->widgets_table != LUA_REFNIL)
855 lua_rawgeti(L, LUA_REGISTRYINDEX, (*wibox)->widgets_table);
856 else
857 lua_pushnil(L);
858 break;
859 case A_TK_CURSOR:
860 lua_pushstring(L, (*wibox)->cursor);
861 break;
862 default:
863 return 0;
866 return 1;
869 /* Set or get the wibox geometry.
870 * \param L The Lua VM state.
871 * \return The number of elements pushed on stack.
872 * \luastack
873 * \lparam An optional table with wibox geometry.
874 * \lreturn The wibox geometry.
876 static int
877 luaA_wibox_geometry(lua_State *L)
879 wibox_t **wibox = luaA_checkudata(L, 1, "wibox");
881 if(lua_gettop(L) == 2)
883 area_t wingeom;
885 luaA_checktable(L, 2);
886 wingeom.x = luaA_getopt_number(L, 2, "x", (*wibox)->sw.geometry.x);
887 wingeom.y = luaA_getopt_number(L, 2, "y", (*wibox)->sw.geometry.y);
888 wingeom.width = luaA_getopt_number(L, 2, "width", (*wibox)->sw.geometry.width);
889 wingeom.height = luaA_getopt_number(L, 2, "height", (*wibox)->sw.geometry.height);
891 switch((*wibox)->type)
893 case WIBOX_TYPE_TITLEBAR:
894 wibox_resize(*wibox, wingeom.width, wingeom.height);
895 break;
896 case WIBOX_TYPE_NORMAL:
897 if((*wibox)->position == Floating)
898 wibox_moveresize(*wibox, wingeom);
899 else if(wingeom.width != (*wibox)->sw.geometry.width
900 || wingeom.height != (*wibox)->sw.geometry.height)
902 wibox_resize(*wibox, wingeom.width, wingeom.height);
903 globalconf.screens[(*wibox)->screen].need_arrange = true;
905 break;
909 return luaA_pusharea(L, (*wibox)->sw.geometry);
912 /** Wibox newindex.
913 * \param L The Lua VM state.
914 * \return The number of elements pushed on stack.
916 static int
917 luaA_wibox_newindex(lua_State *L)
919 size_t len;
920 wibox_t **wibox = luaA_checkudata(L, 1, "wibox");
921 const char *buf, *attr = luaL_checklstring(L, 2, &len);
922 awesome_token_t tok;
924 switch((tok = a_tokenize(attr, len)))
926 bool b;
928 case A_TK_FG:
929 if((buf = luaL_checklstring(L, 3, &len)))
930 if(xcolor_init_reply(xcolor_init_unchecked(&(*wibox)->sw.ctx.fg, buf, len)))
931 (*wibox)->need_update = true;
932 break;
933 case A_TK_BG:
934 if((buf = luaL_checklstring(L, 3, &len)))
935 if(xcolor_init_reply(xcolor_init_unchecked(&(*wibox)->sw.ctx.bg, buf, len)))
936 (*wibox)->need_update = true;
937 break;
938 case A_TK_ALIGN:
939 buf = luaL_checklstring(L, 3, &len);
940 (*wibox)->align = draw_align_fromstr(buf, len);
941 switch((*wibox)->type)
943 case WIBOX_TYPE_NORMAL:
944 wibox_position_update(*wibox);
945 break;
946 case WIBOX_TYPE_TITLEBAR:
947 titlebar_update_geometry(client_getbytitlebar(*wibox));
948 break;
950 break;
951 case A_TK_POSITION:
952 switch((*wibox)->type)
954 case WIBOX_TYPE_TITLEBAR:
955 return luaA_titlebar_newindex(L, *wibox, tok);
956 case WIBOX_TYPE_NORMAL:
957 if((buf = luaL_checklstring(L, 3, &len)))
958 wibox_setposition(*wibox, position_fromstr(buf, len));
959 break;
961 break;
962 case A_TK_CLIENT:
963 /* first detach */
964 if(lua_isnil(L, 3))
965 titlebar_client_detach(client_getbytitlebar(*wibox));
966 else
968 client_t **c = luaA_checkudata(L, 3, "client");
969 titlebar_client_attach(*c, *wibox);
971 break;
972 case A_TK_CURSOR:
973 if((buf = luaL_checkstring(L, 3)))
975 uint16_t cursor_font = xcursor_font_fromstr(buf);
976 if(cursor_font)
978 xcb_cursor_t cursor = xcursor_new(globalconf.connection, cursor_font);
979 p_delete(&(*wibox)->cursor);
980 (*wibox)->cursor = a_strdup(buf);
981 simplewindow_cursor_set(&(*wibox)->sw, cursor);
984 break;
985 case A_TK_SCREEN:
986 if(lua_isnil(L, 3))
988 wibox_detach(*wibox);
989 titlebar_client_detach(client_getbytitlebar(*wibox));
991 else
993 int screen = luaL_checknumber(L, 3) - 1;
994 luaA_checkscreen(screen);
995 if(screen != (*wibox)->screen)
997 titlebar_client_detach(client_getbytitlebar(*wibox));
998 wibox_attach(*wibox, &globalconf.screens[screen]);
1001 break;
1002 case A_TK_ONTOP:
1003 b = luaA_checkboolean(L, 3);
1004 if(b != (*wibox)->ontop)
1006 (*wibox)->ontop = b;
1007 client_stack();
1009 break;
1010 case A_TK_ORIENTATION:
1011 if((buf = luaL_checklstring(L, 3, &len)))
1013 simplewindow_orientation_set(&(*wibox)->sw, orientation_fromstr(buf, len));
1014 (*wibox)->need_update = true;
1016 break;
1017 case A_TK_BORDER_COLOR:
1018 if((buf = luaL_checklstring(L, 3, &len)))
1019 if(xcolor_init_reply(xcolor_init_unchecked(&(*wibox)->sw.border.color, buf, len)))
1020 if((*wibox)->sw.window)
1021 simplewindow_border_color_set(&(*wibox)->sw, &(*wibox)->sw.border.color);
1022 break;
1023 case A_TK_VISIBLE:
1024 b = luaA_checkboolean(L, 3);
1025 if(b != (*wibox)->isvisible)
1026 switch((*wibox)->type)
1028 case WIBOX_TYPE_NORMAL:
1029 wibox_setvisible(*wibox, b);
1030 break;
1031 case WIBOX_TYPE_TITLEBAR:
1032 titlebar_set_visible(*wibox, b);
1033 break;
1035 break;
1036 case A_TK_WIDGETS:
1037 if(luaA_isloop(L, 3))
1039 luaA_warn(L, "table is looping, cannot use this as widget table");
1040 return 0;
1042 luaA_register(L, 3, &(*wibox)->widgets_table);
1043 /* recompute widget node list */
1044 wibox_widgets_table_build(L, *wibox);
1045 luaA_table2wtable(L);
1046 break;
1047 default:
1048 switch((*wibox)->type)
1050 case WIBOX_TYPE_TITLEBAR:
1051 return luaA_titlebar_newindex(L, *wibox, tok);
1052 case WIBOX_TYPE_NORMAL:
1053 break;
1057 return 0;
1060 /** Get or set mouse buttons bindings to a wibox.
1061 * \param L The Lua VM state.
1062 * \luastack
1063 * \lvalue A wibox.
1064 * \lparam An array of mouse button bindings objects, or nothing.
1065 * \return The array of mouse button bindings objects of this wibox.
1067 static int
1068 luaA_wibox_buttons(lua_State *L)
1070 wibox_t **wibox = luaA_checkudata(L, 1, "wibox");
1071 button_array_t *buttons = &(*wibox)->buttons;
1073 if(lua_gettop(L) == 2)
1075 luaA_button_array_set(L, 2, buttons);
1076 return 1;
1079 return luaA_button_array_get(L, buttons);
1082 const struct luaL_reg awesome_wibox_methods[] =
1084 { "__call", luaA_wibox_new },
1085 { NULL, NULL }
1087 const struct luaL_reg awesome_wibox_meta[] =
1089 { "buttons", luaA_wibox_buttons },
1090 { "geometry", luaA_wibox_geometry },
1091 { "__index", luaA_wibox_index },
1092 { "__newindex", luaA_wibox_newindex },
1093 { "__gc", luaA_wibox_gc },
1094 { "__eq", luaA_wibox_eq },
1095 { "__tostring", luaA_wibox_tostring },
1096 { NULL, NULL },
1099 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80