awful.tag: fix screen in viewonly
[awesome.git] / client.c
blobf726ca5908953edb4da1328783cb43e7e584c12f
1 /*
2 * client.c - client management
4 * Copyright © 2007-2009 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 <xcb/xcb_atom.h>
23 #include <xcb/xcb_image.h>
25 #include "tag.h"
26 #include "ewmh.h"
27 #include "screen.h"
28 #include "titlebar.h"
29 #include "systray.h"
30 #include "property.h"
31 #include "spawn.h"
32 #include "luaa.h"
33 #include "common/atoms.h"
34 #include "common/xutil.h"
36 client_t *
37 luaA_client_checkudata(lua_State *L, int ud)
39 client_t *c = luaA_checkudata(L, ud, &client_class);
40 if(c->invalid)
41 luaL_error(L, "client is invalid\n");
42 return c;
45 /** Collect a client.
46 * \param L The Lua VM state.
47 * \return The number of element pushed on stack.
49 static int
50 luaA_client_gc(lua_State *L)
52 client_t *c = luaA_checkudata(L, 1, &client_class);
53 button_array_wipe(&c->buttons);
54 key_array_wipe(&c->keys);
55 xcb_get_wm_protocols_reply_wipe(&c->protocols);
56 p_delete(&c->machine);
57 p_delete(&c->class);
58 p_delete(&c->instance);
59 p_delete(&c->icon_name);
60 p_delete(&c->alt_icon_name);
61 p_delete(&c->name);
62 p_delete(&c->alt_name);
63 return luaA_object_gc(L);
66 /** Change the client opacity.
67 * \param L The Lua VM state.
68 * \param cidx The client index.
69 * \param opacity The opacity.
71 void
72 client_set_opacity(lua_State *L, int cidx, double opacity)
74 client_t *c = luaA_client_checkudata(L, cidx);
76 if(c->opacity != opacity)
78 c->opacity = opacity;
79 window_opacity_set(c->window, opacity);
80 luaA_object_emit_signal(L, cidx, "property::opacity", 0);
84 /** Change the clients urgency flag.
85 * \param L The Lua VM state.
86 * \param cidx The client index on the stack.
87 * \param urgent The new flag state.
89 void
90 client_set_urgent(lua_State *L, int cidx, bool urgent)
92 client_t *c = luaA_client_checkudata(L, cidx);
94 if(c->urgent != urgent)
96 xcb_get_property_cookie_t hints =
97 xcb_get_wm_hints_unchecked(globalconf.connection, c->window);
99 c->urgent = urgent;
100 ewmh_client_update_hints(c);
102 /* update ICCCM hints */
103 xcb_wm_hints_t wmh;
104 xcb_get_wm_hints_reply(globalconf.connection, hints, &wmh, NULL);
106 if(urgent)
107 wmh.flags |= XCB_WM_HINT_X_URGENCY;
108 else
109 wmh.flags &= ~XCB_WM_HINT_X_URGENCY;
111 xcb_set_wm_hints(globalconf.connection, c->window, &wmh);
113 hook_property(c, "urgent");
114 luaA_object_emit_signal(L, cidx, "property::urgent", 0);
118 void
119 client_set_group_window(lua_State *L, int cidx, xcb_window_t window)
121 client_t *c = luaA_client_checkudata(L, cidx);
123 if(c->group_window != window)
125 c->group_window = window;
126 luaA_object_emit_signal(L, cidx, "property::group_window", 0);
130 void
131 client_set_type(lua_State *L, int cidx, window_type_t type)
133 client_t *c = luaA_client_checkudata(L, cidx);
135 if(c->type != type)
137 c->type = type;
138 luaA_object_emit_signal(L, cidx, "property::type", 0);
142 void
143 client_set_pid(lua_State *L, int cidx, uint32_t pid)
145 client_t *c = luaA_client_checkudata(L, cidx);
147 if(c->pid != pid)
149 c->pid = pid;
150 luaA_object_emit_signal(L, cidx, "property::pid", 0);
154 void
155 client_set_icon_name(lua_State *L, int cidx, char *icon_name)
157 client_t *c = luaA_client_checkudata(L, cidx);
158 p_delete(&c->icon_name);
159 c->icon_name = icon_name;
160 luaA_object_emit_signal(L, cidx, "property::icon_name", 0);
161 hook_property(c, "icon_name");
164 void
165 client_set_alt_icon_name(lua_State *L, int cidx, char *icon_name)
167 client_t *c = luaA_client_checkudata(L, cidx);
168 p_delete(&c->alt_icon_name);
169 c->alt_icon_name = icon_name;
170 luaA_object_emit_signal(L, cidx, "property::icon_name", 0);
171 hook_property(c, "icon_name");
174 void
175 client_set_role(lua_State *L, int cidx, char *role)
177 client_t *c = luaA_client_checkudata(L, cidx);
178 p_delete(&c->role);
179 c->role = role;
180 luaA_object_emit_signal(L, cidx, "property::role", 0);
183 void
184 client_set_machine(lua_State *L, int cidx, char *machine)
186 client_t *c = luaA_client_checkudata(L, cidx);
187 p_delete(&c->machine);
188 c->machine = machine;
189 luaA_object_emit_signal(L, cidx, "property::machine", 0);
192 void
193 client_set_class_instance(lua_State *L, int cidx, const char *class, const char *instance)
195 client_t *c = luaA_client_checkudata(L, cidx);
196 p_delete(&c->class);
197 p_delete(&c->instance);
198 c->class = a_strdup(class);
199 c->instance = a_strdup(instance);
200 luaA_object_emit_signal(L, cidx, "property::class", 0);
201 luaA_object_emit_signal(L, cidx, "property::instance", 0);
204 void
205 client_set_transient_for(lua_State *L, int cidx, client_t *transient_for)
207 client_t *c = luaA_client_checkudata(L, cidx);
209 if(c->transient_for != transient_for)
211 c->transient_for = transient_for;
212 luaA_object_emit_signal(L, cidx, "property::transient_for", 0);
216 void
217 client_set_name(lua_State *L, int cidx, char *name)
219 client_t *c = luaA_client_checkudata(L, cidx);
220 p_delete(&c->name);
221 c->name = name;
222 hook_property(c, "name");
223 luaA_object_emit_signal(L, cidx, "property::name", 0);
226 void
227 client_set_alt_name(lua_State *L, int cidx, char *name)
229 client_t *c = luaA_client_checkudata(L, cidx);
230 p_delete(&c->alt_name);
231 c->alt_name = name;
232 hook_property(c, "name");
233 luaA_object_emit_signal(L, cidx, "property::name", 0);
236 /** Returns true if a client is tagged
237 * with one of the tags of the specified screen.
238 * \param c The client to check.
239 * \param screen Virtual screen.
240 * \return true if the client is visible, false otherwise.
242 bool
243 client_maybevisible(client_t *c, screen_t *screen)
245 if(screen && c->screen == screen)
247 if(c->sticky || c->type == WINDOW_TYPE_DESKTOP)
248 return true;
250 foreach(tag, screen->tags)
251 if(tag_get_selected(*tag) && is_client_tagged(c, *tag))
252 return true;
254 return false;
257 /** Get a client by its window.
258 * \param w The client window to find.
259 * \return A client pointer if found, NULL otherwise.
261 client_t *
262 client_getbywin(xcb_window_t w)
264 foreach(c, globalconf.clients)
265 if((*c)->window == w)
266 return *c;
268 return NULL;
271 /** Record that a client lost focus.
272 * \param c Client being unfocused
274 void
275 client_unfocus_update(client_t *c)
277 globalconf.screens.tab[c->phys_screen].client_focus = NULL;
278 ewmh_update_net_active_window(c->phys_screen);
280 /* Call hook */
281 if(globalconf.hooks.unfocus != LUA_REFNIL)
283 luaA_object_push(globalconf.L, c);
284 luaA_dofunction_from_registry(globalconf.L, globalconf.hooks.unfocus, 1, 0);
287 luaA_object_push(globalconf.L, c);
288 luaA_class_emit_signal(globalconf.L, &client_class, "unfocus", 1);
291 /** Unfocus a client.
292 * \param c The client.
294 void
295 client_unfocus(client_t *c)
298 xcb_window_t root_win = xutil_screen_get(globalconf.connection, c->phys_screen)->root;
299 /* Set focus on root window, so no events leak to the current window.
300 * This kind of inlines client_set_focus(), but a root window will never have
301 * the WM_TAKE_FOCUS protocol.
303 xcb_set_input_focus(globalconf.connection, XCB_INPUT_FOCUS_PARENT,
304 root_win, XCB_CURRENT_TIME);
306 client_unfocus_update(c);
309 /** Check if client supports atom a protocol in WM_PROTOCOL.
310 * \param c The client.
311 * \param atom The protocol atom to check for.
312 * \return True if client has the atom in protocol, false otherwise.
314 bool
315 client_hasproto(client_t *c, xcb_atom_t atom)
317 for(uint32_t i = 0; i < c->protocols.atoms_len; i++)
318 if(c->protocols.atoms[i] == atom)
319 return true;
320 return false;
323 /** Sets focus on window - using xcb_set_input_focus or WM_TAKE_FOCUS
324 * \param c Client that should get focus
325 * \param set_input_focus Should we call xcb_set_input_focus
327 void
328 client_set_focus(client_t *c, bool set_input_focus)
330 bool takefocus = client_hasproto(c, WM_TAKE_FOCUS);
331 if(set_input_focus)
332 xcb_set_input_focus(globalconf.connection, XCB_INPUT_FOCUS_PARENT,
333 c->window, XCB_CURRENT_TIME);
334 if(takefocus)
335 window_takefocus(c->window);
338 /** Ban client and move it out of the viewport.
339 * \param c The client.
341 void
342 client_ban(client_t *c)
344 if(!c->isbanned)
346 xcb_unmap_window(globalconf.connection, c->window);
348 c->isbanned = true;
350 if(globalconf.screens.tab[c->phys_screen].prev_client_focus == c)
351 globalconf.screens.tab[c->phys_screen].prev_client_focus = NULL;
353 /* Wait until the last moment to take away the focus from the window. */
354 if(globalconf.screens.tab[c->phys_screen].client_focus == c)
355 client_unfocus(c);
359 /** This is part of The Bob Marley Algorithm: we ignore enter and leave window
360 * in certain cases, like map/unmap or move, so we don't get spurious events.
362 void
363 client_ignore_enterleave_events(void)
365 foreach(c, globalconf.clients)
366 xcb_change_window_attributes(globalconf.connection,
367 (*c)->window,
368 XCB_CW_EVENT_MASK,
369 (const uint32_t []) { CLIENT_SELECT_INPUT_EVENT_MASK & ~(XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW) });
372 void
373 client_restore_enterleave_events(void)
375 foreach(c, globalconf.clients)
376 xcb_change_window_attributes(globalconf.connection,
377 (*c)->window,
378 XCB_CW_EVENT_MASK,
379 (const uint32_t []) { CLIENT_SELECT_INPUT_EVENT_MASK });
382 /** Record that a client got focus.
383 * \param c The client.
385 void
386 client_focus_update(client_t *c)
388 if(!client_maybevisible(c, c->screen))
390 /* Focus previously focused client */
391 client_focus(globalconf.screen_focus->prev_client_focus);
392 return;
395 if(globalconf.screen_focus
396 && globalconf.screen_focus->client_focus)
398 if (globalconf.screen_focus->client_focus != c)
399 client_unfocus_update(globalconf.screen_focus->client_focus);
400 else
401 /* Already focused */
402 return;
404 luaA_object_push(globalconf.L, c);
405 client_set_minimized(globalconf.L, -1, false);
407 /* unban the client before focusing for consistency */
408 client_unban(c);
410 globalconf.screen_focus = &globalconf.screens.tab[c->phys_screen];
411 globalconf.screen_focus->prev_client_focus = c;
412 globalconf.screen_focus->client_focus = c;
414 /* according to EWMH, we have to remove the urgent state from a client */
415 client_set_urgent(globalconf.L, -1, false);
417 ewmh_update_net_active_window(c->phys_screen);
419 /* execute hook */
420 if(globalconf.hooks.focus != LUA_REFNIL)
422 luaA_object_push(globalconf.L, c);
423 luaA_dofunction_from_registry(globalconf.L, globalconf.hooks.focus, 1, 0);
426 luaA_object_push(globalconf.L, c);
427 luaA_class_emit_signal(globalconf.L, &client_class, "focus", 1);
430 /** Give focus to client, or to first client if client is NULL.
431 * \param c The client.
433 void
434 client_focus(client_t *c)
436 /* We have to set focus on first client */
437 if(!c && globalconf.clients.len && !(c = globalconf.clients.tab[0]))
438 return;
440 if(!client_maybevisible(c, c->screen))
441 return;
443 if (!c->nofocus)
444 client_focus_update(c);
446 client_set_focus(c, !c->nofocus);
449 /** Stack a window below.
450 * \param c The client.
451 * \param previous The previous window on the stack.
452 * \return The next-previous!
454 static xcb_window_t
455 client_stack_above(client_t *c, xcb_window_t previous)
457 uint32_t config_win_vals[2];
459 config_win_vals[0] = previous;
460 config_win_vals[1] = XCB_STACK_MODE_ABOVE;
462 xcb_configure_window(globalconf.connection, c->window,
463 XCB_CONFIG_WINDOW_SIBLING | XCB_CONFIG_WINDOW_STACK_MODE,
464 config_win_vals);
466 config_win_vals[0] = c->window;
468 if(c->titlebar)
470 xcb_configure_window(globalconf.connection,
471 c->titlebar->window,
472 XCB_CONFIG_WINDOW_SIBLING | XCB_CONFIG_WINDOW_STACK_MODE,
473 config_win_vals);
474 previous = c->titlebar->window;
476 else
477 previous = c->window;
479 /* stack transient window on top of their parents */
480 foreach(node, globalconf.stack)
481 if((*node)->transient_for == c)
482 previous = client_stack_above(*node, previous);
484 return previous;
487 /** Stacking layout layers */
488 typedef enum
490 /** This one is a special layer */
491 LAYER_IGNORE,
492 LAYER_DESKTOP,
493 LAYER_BELOW,
494 LAYER_NORMAL,
495 LAYER_ABOVE,
496 LAYER_FULLSCREEN,
497 LAYER_ONTOP,
498 /** This one only used for counting and is not a real layer */
499 LAYER_COUNT
500 } layer_t;
502 /** Get the real layer of a client according to its attribute (fullscreen, …)
503 * \param c The client.
504 * \return The real layer.
506 static layer_t
507 client_layer_translator(client_t *c)
509 /* first deal with user set attributes */
510 if(c->ontop)
511 return LAYER_ONTOP;
512 else if(c->fullscreen)
513 return LAYER_FULLSCREEN;
514 else if(c->above)
515 return LAYER_ABOVE;
516 else if(c->below)
517 return LAYER_BELOW;
519 /* check for transient attr */
520 if(c->transient_for)
521 return LAYER_IGNORE;
523 /* then deal with windows type */
524 switch(c->type)
526 case WINDOW_TYPE_DESKTOP:
527 return LAYER_DESKTOP;
528 default:
529 break;
532 return LAYER_NORMAL;
535 /** Restack clients.
536 * \todo It might be worth stopping to restack everyone and only stack `c'
537 * relatively to the first matching in the list.
539 void
540 client_stack_refresh()
542 uint32_t config_win_vals[2];
543 layer_t layer;
545 if (!globalconf.client_need_stack_refresh)
546 return;
547 globalconf.client_need_stack_refresh = false;
549 config_win_vals[0] = XCB_NONE;
550 config_win_vals[1] = XCB_STACK_MODE_ABOVE;
552 /* stack desktop windows */
553 for(layer = LAYER_DESKTOP; layer < LAYER_BELOW; layer++)
554 foreach(node, globalconf.stack)
555 if(client_layer_translator(*node) == layer)
556 config_win_vals[0] = client_stack_above(*node,
557 config_win_vals[0]);
559 /* first stack not ontop wibox window */
560 foreach(_sb, globalconf.wiboxes)
562 wibox_t *sb = *_sb;
563 if(!sb->ontop)
565 xcb_configure_window(globalconf.connection,
566 sb->window,
567 XCB_CONFIG_WINDOW_SIBLING | XCB_CONFIG_WINDOW_STACK_MODE,
568 config_win_vals);
569 config_win_vals[0] = sb->window;
573 /* then stack clients */
574 for(layer = LAYER_BELOW; layer < LAYER_COUNT; layer++)
575 foreach(node, globalconf.stack)
576 if(client_layer_translator(*node) == layer)
577 config_win_vals[0] = client_stack_above(*node,
578 config_win_vals[0]);
580 /* then stack ontop wibox window */
581 foreach(_sb, globalconf.wiboxes)
583 wibox_t *sb = *_sb;
584 if(sb->ontop)
586 xcb_configure_window(globalconf.connection,
587 sb->window,
588 XCB_CONFIG_WINDOW_SIBLING | XCB_CONFIG_WINDOW_STACK_MODE,
589 config_win_vals);
590 config_win_vals[0] = sb->window;
595 /** Manage a new client.
596 * \param w The window.
597 * \param wgeom Window geometry.
598 * \param phys_screen Physical screen number.
599 * \param startup True if we are managing at startup time.
601 void
602 client_manage(xcb_window_t w, xcb_get_geometry_reply_t *wgeom, int phys_screen, bool startup)
604 const uint32_t select_input_val[] = { CLIENT_SELECT_INPUT_EVENT_MASK };
606 if(systray_iskdedockapp(w))
608 systray_request_handle(w, phys_screen, NULL);
609 return;
612 /* If this is a new client that just has been launched, then request its
613 * startup id. */
614 xcb_get_property_cookie_t startup_id_q = { 0 };
615 if(!startup)
616 startup_id_q = xcb_get_any_property(globalconf.connection,
617 false, w, _NET_STARTUP_ID, UINT_MAX);
619 xcb_change_window_attributes(globalconf.connection, w, XCB_CW_EVENT_MASK, select_input_val);
621 client_t *c = client_new(globalconf.L);
623 /* This cannot change, ever. */
624 c->phys_screen = phys_screen;
625 /* consider the window banned */
626 c->isbanned = true;
627 /* Store window */
628 c->window = w;
629 luaA_object_emit_signal(globalconf.L, -1, "property::window", 0);
631 /* Duplicate client and push it in client list */
632 lua_pushvalue(globalconf.L, -1);
633 client_array_push(&globalconf.clients, luaA_object_ref(globalconf.L, -1));
635 /* Set the right screen */
636 screen_client_moveto(c, screen_getbycoord(&globalconf.screens.tab[phys_screen], wgeom->x, wgeom->y), false);
638 /* Store initial geometry and emits signals so we inform that geometry have
639 * been set. */
640 #define HANDLE_GEOM(attr) \
641 c->geometry.attr = wgeom->attr; \
642 c->geometries.internal.attr = wgeom->attr; \
643 luaA_object_emit_signal(globalconf.L, -1, "property::" #attr, 0);
644 HANDLE_GEOM(x)
645 HANDLE_GEOM(y)
646 HANDLE_GEOM(width)
647 HANDLE_GEOM(height)
648 #undef HANDLE_GEOM
650 luaA_object_emit_signal(globalconf.L, -1, "property::geometry", 0);
652 /* Push client */
653 client_set_border_width(globalconf.L, -1, wgeom->border_width);
655 /* we honor size hints by default */
656 c->size_hints_honor = true;
657 luaA_object_emit_signal(globalconf.L, -1, "property::size_hints_honor", 0);
659 /* update hints */
660 property_update_wm_normal_hints(c, NULL);
661 property_update_wm_hints(c, NULL);
662 property_update_wm_transient_for(c, NULL);
663 property_update_wm_client_leader(c, NULL);
664 property_update_wm_client_machine(c, NULL);
665 property_update_wm_window_role(c, NULL);
666 property_update_net_wm_pid(c, NULL);
667 property_update_net_wm_icon(c, NULL);
669 /* get opacity */
670 client_set_opacity(globalconf.L, -1, window_opacity_get(c->window));
672 /* Then check clients hints */
673 ewmh_client_check_hints(c);
675 /* Push client in stack */
676 client_raise(c);
678 /* update window title */
679 property_update_wm_name(c, NULL);
680 property_update_net_wm_name(c, NULL);
681 property_update_wm_icon_name(c, NULL);
682 property_update_net_wm_icon_name(c, NULL);
683 property_update_wm_class(c, NULL);
684 property_update_wm_protocols(c, NULL);
686 /* update strut */
687 ewmh_process_client_strut(c, NULL);
689 ewmh_update_net_client_list(c->phys_screen);
691 /* Always stay in NORMAL_STATE. Even though iconified seems more
692 * appropriate sometimes. The only possible loss is that clients not using
693 * visibility events may continue to process data (when banned).
694 * Without any exposes or other events the cost should be fairly limited though.
696 * Some clients may expect the window to be unmapped when STATE_ICONIFIED.
697 * Two conflicting parts of the ICCCM v2.0 (section 4.1.4):
699 * "Normal -> Iconic - The client should send a ClientMessage event as described later in this section."
700 * (note no explicit mention of unmapping, while Normal->Widthdrawn does mention that)
702 * "Once a client's window has left the Withdrawn state, the window will be mapped
703 * if it is in the Normal state and the window will be unmapped if it is in the Iconic state."
705 * At this stage it's just safer to keep it in normal state and avoid confusion.
707 window_state_set(c->window, XCB_WM_STATE_NORMAL);
709 if(!startup)
711 /* Request our response */
712 xcb_get_property_reply_t *reply =
713 xcb_get_property_reply(globalconf.connection, startup_id_q, NULL);
714 /* Say spawn that a client has been started, with startup id as argument */
715 char *startup_id = xutil_get_text_property_from_reply(reply);
716 p_delete(&reply);
717 spawn_start_notify(c, startup_id);
718 p_delete(&startup_id);
721 /* Call hook to notify list change */
722 if(globalconf.hooks.clients != LUA_REFNIL)
723 luaA_dofunction_from_registry(globalconf.L, globalconf.hooks.clients, 0, 0);
725 luaA_class_emit_signal(globalconf.L, &client_class, "list", 0);
727 /* call hook */
728 if(globalconf.hooks.manage != LUA_REFNIL)
730 luaA_object_push(globalconf.L, c);
731 lua_pushboolean(globalconf.L, startup);
732 luaA_dofunction_from_registry(globalconf.L, globalconf.hooks.manage, 2, 0);
735 /* client is still on top of the stack; push startup value,
736 * and emit signals with 2 args */
737 lua_pushboolean(globalconf.L, startup);
738 luaA_class_emit_signal(globalconf.L, &client_class, "manage", 2);
741 /** Compute client geometry with respect to its geometry hints.
742 * \param c The client.
743 * \param geometry The geometry that the client might receive.
744 * \return The geometry the client must take respecting its hints.
746 area_t
747 client_geometry_hints(client_t *c, area_t geometry)
749 int32_t basew, baseh, minw, minh;
751 /* base size is substituted with min size if not specified */
752 if(c->size_hints.flags & XCB_SIZE_HINT_P_SIZE)
754 basew = c->size_hints.base_width;
755 baseh = c->size_hints.base_height;
757 else if(c->size_hints.flags & XCB_SIZE_HINT_P_MIN_SIZE)
759 basew = c->size_hints.min_width;
760 baseh = c->size_hints.min_height;
762 else
763 basew = baseh = 0;
765 /* min size is substituted with base size if not specified */
766 if(c->size_hints.flags & XCB_SIZE_HINT_P_MIN_SIZE)
768 minw = c->size_hints.min_width;
769 minh = c->size_hints.min_height;
771 else if(c->size_hints.flags & XCB_SIZE_HINT_P_SIZE)
773 minw = c->size_hints.base_width;
774 minh = c->size_hints.base_height;
776 else
777 minw = minh = 0;
779 if(c->size_hints.flags & XCB_SIZE_HINT_P_ASPECT
780 && c->size_hints.min_aspect_num > 0
781 && c->size_hints.min_aspect_den > 0
782 && geometry.height - baseh > 0
783 && geometry.width - basew > 0)
785 double dx = (double) (geometry.width - basew);
786 double dy = (double) (geometry.height - baseh);
787 double min = (double) c->size_hints.min_aspect_num / (double) c->size_hints.min_aspect_den;
788 double max = (double) c->size_hints.max_aspect_num / (double) c->size_hints.min_aspect_den;
789 double ratio = dx / dy;
790 if(max > 0 && min > 0 && ratio > 0)
792 if(ratio < min)
794 dy = (dx * min + dy) / (min * min + 1);
795 dx = dy * min;
796 geometry.width = (int) dx + basew;
797 geometry.height = (int) dy + baseh;
799 else if(ratio > max)
801 dy = (dx * min + dy) / (max * max + 1);
802 dx = dy * min;
803 geometry.width = (int) dx + basew;
804 geometry.height = (int) dy + baseh;
809 if(minw)
810 geometry.width = MAX(geometry.width, minw);
811 if(minh)
812 geometry.height = MAX(geometry.height, minh);
814 if(c->size_hints.flags & XCB_SIZE_HINT_P_MAX_SIZE)
816 if(c->size_hints.max_width)
817 geometry.width = MIN(geometry.width, c->size_hints.max_width);
818 if(c->size_hints.max_height)
819 geometry.height = MIN(geometry.height, c->size_hints.max_height);
822 if(c->size_hints.flags & (XCB_SIZE_HINT_P_RESIZE_INC | XCB_SIZE_HINT_BASE_SIZE)
823 && c->size_hints.width_inc && c->size_hints.height_inc)
825 uint16_t t1 = geometry.width, t2 = geometry.height;
826 unsigned_subtract(t1, basew);
827 unsigned_subtract(t2, baseh);
828 geometry.width -= t1 % c->size_hints.width_inc;
829 geometry.height -= t2 % c->size_hints.height_inc;
832 return geometry;
835 /** Resize client window.
836 * The sizes given as parameters are with titlebar and borders!
837 * \param c Client to resize.
838 * \param geometry New window geometry.
839 * \param hints Use size hints.
840 * \return true if an actual resize occurred.
842 bool
843 client_resize(client_t *c, area_t geometry, bool hints)
845 area_t geometry_internal;
846 area_t area;
848 /* offscreen appearance fixes */
849 area = display_area_get(c->phys_screen);
851 if(geometry.x > area.width)
852 geometry.x = area.width - geometry.width;
853 if(geometry.y > area.height)
854 geometry.y = area.height - geometry.height;
855 if(geometry.x + geometry.width < 0)
856 geometry.x = 0;
857 if(geometry.y + geometry.height < 0)
858 geometry.y = 0;
860 /* Real client geometry, please keep it contained to C code at the very least. */
861 geometry_internal = titlebar_geometry_remove(c->titlebar, c->border_width, geometry);
863 if(hints)
864 geometry_internal = client_geometry_hints(c, geometry_internal);
866 if(geometry_internal.width == 0 || geometry_internal.height == 0)
867 return false;
869 /* Also let client hints propagate to the "official" geometry. */
870 geometry = titlebar_geometry_add(c->titlebar, c->border_width, geometry_internal);
872 if(c->geometries.internal.x != geometry_internal.x
873 || c->geometries.internal.y != geometry_internal.y
874 || c->geometries.internal.width != geometry_internal.width
875 || c->geometries.internal.height != geometry_internal.height)
877 screen_t *new_screen = screen_getbycoord(c->screen,
878 geometry_internal.x, geometry_internal.y);
880 /* Values to configure a window is an array where values are
881 * stored according to 'value_mask' */
882 uint32_t values[4];
884 c->geometries.internal.x = values[0] = geometry_internal.x;
885 c->geometries.internal.y = values[1] = geometry_internal.y;
886 c->geometries.internal.width = values[2] = geometry_internal.width;
887 c->geometries.internal.height = values[3] = geometry_internal.height;
889 /* Also store geometry including border and titlebar. */
890 c->geometry = geometry;
892 titlebar_update_geometry(c);
894 /* Ignore all spurious enter/leave notify events */
895 client_ignore_enterleave_events();
897 xcb_configure_window(globalconf.connection, c->window,
898 XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y
899 | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT,
900 values);
902 client_restore_enterleave_events();
904 screen_client_moveto(c, new_screen, false);
906 /* execute hook */
907 hook_property(c, "geometry");
909 luaA_object_push(globalconf.L, c);
910 luaA_object_emit_signal(globalconf.L, -1, "property::geometry", 0);
911 /** \todo This need to be VERIFIED before it is emitted! */
912 luaA_object_emit_signal(globalconf.L, -1, "property::x", 0);
913 luaA_object_emit_signal(globalconf.L, -1, "property::y", 0);
914 luaA_object_emit_signal(globalconf.L, -1, "property::width", 0);
915 luaA_object_emit_signal(globalconf.L, -1, "property::height", 0);
916 lua_pop(globalconf.L, 1);
918 return true;
921 return false;
924 /** Set a client minimized, or not.
925 * \param L The Lua VM state.
926 * \param cidx The client index.
927 * \param s Set or not the client minimized.
929 void
930 client_set_minimized(lua_State *L, int cidx, bool s)
932 client_t *c = luaA_client_checkudata(L, cidx);
934 if(c->minimized != s)
936 c->minimized = s;
937 banning_refresh((c)->screen);
938 if(s)
939 window_state_set(c->window, XCB_WM_STATE_ICONIC);
940 else
941 window_state_set(c->window, XCB_WM_STATE_NORMAL);
942 ewmh_client_update_hints(c);
943 if(strut_has_value(&c->strut))
944 screen_emit_signal(globalconf.L, c->screen, "property::workarea", 0);
945 /* execute hook */
946 hook_property(c, "minimized");
947 luaA_object_emit_signal(L, cidx, "property::minimized", 0);
951 /** Set a client sticky, or not.
952 * \param L The Lua VM state.
953 * \param cidx The client index.
954 * \param s Set or not the client sticky.
956 void
957 client_set_sticky(lua_State *L, int cidx, bool s)
959 client_t *c = luaA_client_checkudata(L, cidx);
961 if(c->sticky != s)
963 c->sticky = s;
964 banning_refresh((c)->screen);
965 ewmh_client_update_hints(c);
966 hook_property(c, "sticky");
967 luaA_object_emit_signal(L, cidx, "property::sticky", 0);
971 /** Set a client fullscreen, or not.
972 * \param L The Lua VM state.
973 * \param cidx The client index.
974 * \param s Set or not the client fullscreen.
976 void
977 client_set_fullscreen(lua_State *L, int cidx, bool s)
979 client_t *c = luaA_client_checkudata(L, cidx);
981 if(c->fullscreen != s)
983 area_t geometry;
985 /* become fullscreen! */
986 if(s)
988 /* Make sure the current geometry is stored without titlebar. */
989 titlebar_ban(c->titlebar);
990 /* remove any max state */
991 client_set_maximized_horizontal(L, cidx, false);
992 client_set_maximized_vertical(L, cidx, false);
993 /* You can only be part of one of the special layers. */
994 client_set_below(L, cidx, false);
995 client_set_above(L, cidx, false);
996 client_set_ontop(L, cidx, false);
998 geometry = screen_area_get(c->screen, false);
999 c->geometries.fullscreen = c->geometry;
1000 c->border_width_fs = c->border_width;
1001 client_set_border_width(L, cidx, 0);
1002 c->fullscreen = true;
1004 else
1006 geometry = c->geometries.fullscreen;
1007 c->fullscreen = false;
1008 client_set_border_width(L, cidx, c->border_width_fs);
1010 client_resize(c, geometry, false);
1011 client_stack();
1012 ewmh_client_update_hints(c);
1013 hook_property(c, "fullscreen");
1014 luaA_object_emit_signal(L, cidx, "property::fullscreen", 0);
1018 /** Set a client horizontally maximized.
1019 * \param L The Lua VM state.
1020 * \param cidx The client index.
1021 * \param s The maximized status.
1023 void
1024 client_set_maximized_horizontal(lua_State *L, int cidx, bool s)
1026 client_t *c = luaA_client_checkudata(L, cidx);
1028 if(c->maximized_horizontal != s)
1030 area_t geometry;
1032 if((c->maximized_horizontal = s))
1034 /* remove fullscreen mode */
1035 client_set_fullscreen(L, cidx, false);
1037 geometry = screen_area_get(c->screen, true);
1038 geometry.y = c->geometry.y;
1039 geometry.height = c->geometry.height;
1040 c->geometries.max.x = c->geometry.x;
1041 c->geometries.max.width = c->geometry.width;
1043 else
1045 geometry = c->geometry;
1046 geometry.x = c->geometries.max.x;
1047 geometry.width = c->geometries.max.width;
1050 client_resize(c, geometry, c->size_hints_honor);
1051 client_stack();
1052 ewmh_client_update_hints(c);
1053 hook_property(c, "maximized_horizontal");
1054 luaA_object_emit_signal(L, cidx, "property::maximized_horizontal", 0);
1058 /** Set a client vertically maximized.
1059 * \param L The Lua VM state.
1060 * \param cidx The client index.
1061 * \param s The maximized status.
1063 void
1064 client_set_maximized_vertical(lua_State *L, int cidx, bool s)
1066 client_t *c = luaA_client_checkudata(L, cidx);
1068 if(c->maximized_vertical != s)
1070 area_t geometry;
1072 if((c->maximized_vertical = s))
1074 /* remove fullscreen mode */
1075 client_set_fullscreen(L, cidx, false);
1077 geometry = screen_area_get(c->screen, true);
1078 geometry.x = c->geometry.x;
1079 geometry.width = c->geometry.width;
1080 c->geometries.max.y = c->geometry.y;
1081 c->geometries.max.height = c->geometry.height;
1083 else
1085 geometry = c->geometry;
1086 geometry.y = c->geometries.max.y;
1087 geometry.height = c->geometries.max.height;
1090 client_resize(c, geometry, c->size_hints_honor);
1091 client_stack();
1092 ewmh_client_update_hints(c);
1093 hook_property(c, "maximized_vertical");
1094 luaA_object_emit_signal(L, cidx, "property::maximized_vertical", 0);
1098 /** Set a client above, or not.
1099 * \param L The Lua VM state.
1100 * \param cidx The client index.
1101 * \param s Set or not the client above.
1103 void
1104 client_set_above(lua_State *L, int cidx, bool s)
1106 client_t *c = luaA_client_checkudata(L, cidx);
1108 if(c->above != s)
1110 /* You can only be part of one of the special layers. */
1111 if(s)
1113 client_set_below(L, cidx, false);
1114 client_set_ontop(L, cidx, false);
1115 client_set_fullscreen(L, cidx, false);
1117 c->above = s;
1118 client_stack();
1119 ewmh_client_update_hints(c);
1120 /* execute hook */
1121 hook_property(c, "above");
1122 luaA_object_emit_signal(L, cidx, "property::above", 0);
1126 /** Set a client below, or not.
1127 * \param L The Lua VM state.
1128 * \param cidx The client index.
1129 * \param s Set or not the client below.
1131 void
1132 client_set_below(lua_State *L, int cidx, bool s)
1134 client_t *c = luaA_client_checkudata(L, cidx);
1136 if(c->below != s)
1138 /* You can only be part of one of the special layers. */
1139 if(s)
1141 client_set_above(L, cidx, false);
1142 client_set_ontop(L, cidx, false);
1143 client_set_fullscreen(L, cidx, false);
1145 c->below = s;
1146 client_stack();
1147 ewmh_client_update_hints(c);
1148 /* execute hook */
1149 hook_property(c, "below");
1150 luaA_object_emit_signal(L, cidx, "property::below", 0);
1154 /** Set a client modal, or not.
1155 * \param L The Lua VM state.
1156 * \param cidx The client index.
1157 * \param s Set or not the client modal attribute.
1159 void
1160 client_set_modal(lua_State *L, int cidx, bool s)
1162 client_t *c = luaA_client_checkudata(L, cidx);
1164 if(c->modal != s)
1166 c->modal = s;
1167 client_stack();
1168 ewmh_client_update_hints(c);
1169 /* execute hook */
1170 hook_property(c, "modal");
1171 luaA_object_emit_signal(L, cidx, "property::modal", 0);
1175 /** Set a client ontop, or not.
1176 * \param L The Lua VM state.
1177 * \param cidx The client index.
1178 * \param s Set or not the client ontop attribute.
1180 void
1181 client_set_ontop(lua_State *L, int cidx, bool s)
1183 client_t *c = luaA_client_checkudata(L, cidx);
1185 if(c->ontop != s)
1187 /* You can only be part of one of the special layers. */
1188 if(s)
1190 client_set_above(L, cidx, false);
1191 client_set_below(L, cidx, false);
1192 client_set_fullscreen(L, cidx, false);
1194 c->ontop = s;
1195 client_stack();
1196 /* execute hook */
1197 hook_property(c, "ontop");
1198 luaA_object_emit_signal(L, cidx, "property::ontop", 0);
1202 /** Set a client skip taskbar attribute.
1203 * \param L Tha Lua VM state.
1204 * \param cidx The client index.
1205 * \param s Set or not the client skip taskbar attribute.
1207 void
1208 client_set_skip_taskbar(lua_State *L, int cidx, bool s)
1210 client_t *c = luaA_client_checkudata(L, cidx);
1212 if(c->skip_taskbar != s)
1214 c->skip_taskbar = s;
1215 ewmh_client_update_hints(c);
1216 luaA_object_emit_signal(L, cidx, "property::skip_taskbar", 0);
1220 /** Unban a client and move it back into the viewport.
1221 * \param c The client.
1223 void
1224 client_unban(client_t *c)
1226 if(c->isbanned)
1228 xcb_map_window(globalconf.connection, c->window);
1230 c->isbanned = false;
1234 /** Unmanage a client.
1235 * \param c The client.
1237 void
1238 client_unmanage(client_t *c)
1240 tag_array_t *tags = &c->screen->tags;
1242 /* Reset transient_for attributes of widows that maybe referring to us */
1243 foreach(_tc, globalconf.clients)
1245 client_t *tc = *_tc;
1246 if(tc->transient_for == c)
1247 tc->transient_for = NULL;
1250 if(globalconf.screens.tab[c->phys_screen].prev_client_focus == c)
1251 globalconf.screens.tab[c->phys_screen].prev_client_focus = NULL;
1253 if(globalconf.screens.tab[c->phys_screen].client_focus == c)
1254 client_unfocus(c);
1256 /* remove client from global list and everywhere else */
1257 foreach(elem, globalconf.clients)
1258 if(*elem == c)
1260 client_array_remove(&globalconf.clients, elem);
1261 break;
1263 stack_client_remove(c);
1264 for(int i = 0; i < tags->len; i++)
1265 untag_client(c, tags->tab[i]);
1267 /* call hook */
1268 if(globalconf.hooks.unmanage != LUA_REFNIL)
1270 luaA_object_push(globalconf.L, c);
1271 luaA_dofunction_from_registry(globalconf.L, globalconf.hooks.unmanage, 1, 0);
1274 luaA_object_push(globalconf.L, c);
1275 luaA_class_emit_signal(globalconf.L, &client_class, "unmanage", 1);
1277 /* Call hook to notify list change */
1278 if(globalconf.hooks.clients != LUA_REFNIL)
1279 luaA_dofunction_from_registry(globalconf.L, globalconf.hooks.clients, 0, 0);
1281 luaA_class_emit_signal(globalconf.L, &client_class, "list", 0);
1283 if(strut_has_value(&c->strut))
1284 screen_emit_signal(globalconf.L, c->screen, "property::workarea", 0);
1286 window_state_set(c->window, XCB_WM_STATE_WITHDRAWN);
1288 titlebar_client_detach(c);
1290 ewmh_update_net_client_list(c->phys_screen);
1292 /* set client as invalid */
1293 c->invalid = true;
1295 luaA_object_unref(globalconf.L, c);
1298 /** Kill a client via a WM_DELETE_WINDOW request or KillClient if not
1299 * supported.
1300 * \param c The client to kill.
1302 void
1303 client_kill(client_t *c)
1305 if(client_hasproto(c, WM_DELETE_WINDOW))
1307 xcb_client_message_event_t ev;
1309 /* Initialize all of event's fields first */
1310 p_clear(&ev, 1);
1312 ev.response_type = XCB_CLIENT_MESSAGE;
1313 ev.window = c->window;
1314 ev.format = 32;
1315 ev.data.data32[1] = XCB_CURRENT_TIME;
1316 ev.type = WM_PROTOCOLS;
1317 ev.data.data32[0] = WM_DELETE_WINDOW;
1319 xcb_send_event(globalconf.connection, false, c->window,
1320 XCB_EVENT_MASK_NO_EVENT, (char *) &ev);
1322 else
1323 xcb_kill_client(globalconf.connection, c->window);
1326 /** Get all clients into a table.
1327 * \param L The Lua VM state.
1328 * \return The number of elements pushed on stack.
1329 * \luastack
1330 * \lparam An optional screen number.
1331 * \lreturn A table with all clients.
1333 static int
1334 luaA_client_get(lua_State *L)
1336 int i = 1, screen;
1338 screen = luaL_optnumber(L, 1, 0) - 1;
1340 lua_newtable(L);
1342 if(screen == -1)
1343 foreach(c, globalconf.clients)
1345 luaA_object_push(L, *c);
1346 lua_rawseti(L, -2, i++);
1348 else
1350 luaA_checkscreen(screen);
1351 foreach(c, globalconf.clients)
1352 if((*c)->screen == &globalconf.screens.tab[screen])
1354 luaA_object_push(L, *c);
1355 lua_rawseti(L, -2, i++);
1359 return 1;
1362 /** Check if a client is visible on its screen.
1363 * \param L The Lua VM state.
1364 * \return The number of elements pushed on stack.
1365 * \luastack
1366 * \lvalue A client.
1367 * \lreturn A boolean value, true if the client is visible, false otherwise.
1369 static int
1370 luaA_client_isvisible(lua_State *L)
1372 client_t *c = luaA_client_checkudata(L, 1);
1373 lua_pushboolean(L, client_isvisible(c, c->screen));
1374 return 1;
1377 /** Set client border width.
1378 * \param L The Lua VM state.
1379 * \param cidx The client index.
1380 * \param width The border width.
1382 void
1383 client_set_border_width(lua_State *L, int cidx, int width)
1385 client_t *c = luaA_client_checkudata(L, cidx);
1386 uint32_t w = width;
1388 if(width > 0 && (c->type == WINDOW_TYPE_DOCK
1389 || c->type == WINDOW_TYPE_SPLASH
1390 || c->type == WINDOW_TYPE_DESKTOP
1391 || c->fullscreen))
1392 return;
1394 if(width == c->border_width || width < 0)
1395 return;
1397 /* disallow change of border width if the client is fullscreen */
1398 if(c->fullscreen)
1399 return;
1401 /* Update geometry with the new border. */
1402 c->geometry.width -= 2 * c->border_width;
1403 c->geometry.height -= 2 * c->border_width;
1405 c->border_width = width;
1406 xcb_configure_window(globalconf.connection, c->window,
1407 XCB_CONFIG_WINDOW_BORDER_WIDTH, &w);
1409 c->geometry.width += 2 * c->border_width;
1410 c->geometry.height += 2 * c->border_width;
1412 /* Changing border size also affects the size of the titlebar. */
1413 titlebar_update_geometry(c);
1415 hook_property(c, "border_width");
1416 luaA_object_emit_signal(L, cidx, "property::border_width", 0);
1419 /** Set a client icon.
1420 * \param L The Lua VM state.
1421 * \param cidx The client index on the stack.
1422 * \param iidx The image index on the stack.
1424 void
1425 client_set_icon(lua_State *L, int cidx, int iidx)
1427 client_t *c = luaA_client_checkudata(L, cidx);
1428 /* convert index to absolute */
1429 cidx = luaA_absindex(L, cidx);
1430 iidx = luaA_absindex(L, iidx);
1431 luaA_checkudata(L, iidx, &image_class);
1432 luaA_object_unref_item(L, cidx, c->icon);
1433 c->icon = luaA_object_ref_item(L, cidx, iidx);
1434 luaA_object_emit_signal(L, cidx < iidx ? cidx : cidx - 1, "property::icon", 0);
1435 /* execute hook */
1436 hook_property(c, "icon");
1439 /** Kill a client.
1440 * \param L The Lua VM state.
1442 * \luastack
1443 * \lvalue A client.
1445 static int
1446 luaA_client_kill(lua_State *L)
1448 client_t *c = luaA_client_checkudata(L, 1);
1449 client_kill(c);
1450 return 0;
1453 /** Swap a client with another one.
1454 * \param L The Lua VM state.
1455 * \luastack
1456 * \lvalue A client.
1457 * \lparam A client to swap with.
1459 static int
1460 luaA_client_swap(lua_State *L)
1462 client_t *c = luaA_client_checkudata(L, 1);
1463 client_t *swap = luaA_client_checkudata(L, 2);
1465 if(c != swap)
1467 client_t **ref_c = NULL, **ref_swap = NULL;
1468 foreach(item, globalconf.clients)
1470 if(*item == c)
1471 ref_c = item;
1472 else if(*item == swap)
1473 ref_swap = item;
1474 if(ref_c && ref_swap)
1475 break;
1477 /* swap ! */
1478 *ref_c = swap;
1479 *ref_swap = c;
1481 /* Call hook to notify list change */
1482 if(globalconf.hooks.clients != LUA_REFNIL)
1483 luaA_dofunction_from_registry(L, globalconf.hooks.clients, 0, 0);
1485 luaA_class_emit_signal(globalconf.L, &client_class, "list", 0);
1488 return 0;
1491 /** Access or set the client tags.
1492 * \param L The Lua VM state.
1493 * \return The number of elements pushed on stack.
1494 * \lparam A table with tags to set, or none to get the current tags table.
1495 * \return The clients tag.
1497 static int
1498 luaA_client_tags(lua_State *L)
1500 client_t *c = luaA_client_checkudata(L, 1);
1501 tag_array_t *tags = &c->screen->tags;
1502 int j = 0;
1504 if(lua_gettop(L) == 2)
1506 luaA_checktable(L, 2);
1507 for(int i = 0; i < tags->len; i++)
1508 untag_client(c, tags->tab[i]);
1509 lua_pushnil(L);
1510 while(lua_next(L, 2))
1511 tag_client(c);
1512 lua_pop(L, 1);
1515 lua_newtable(L);
1516 foreach(tag, *tags)
1517 if(is_client_tagged(c, *tag))
1519 luaA_object_push(L, *tag);
1520 lua_rawseti(L, -2, ++j);
1523 return 1;
1526 /** Raise a client on top of others which are on the same layer.
1527 * \param L The Lua VM state.
1528 * \luastack
1529 * \lvalue A client.
1531 static int
1532 luaA_client_raise(lua_State *L)
1534 client_t *c = luaA_client_checkudata(L, 1);
1535 client_raise(c);
1536 return 0;
1539 /** Lower a client on bottom of others which are on the same layer.
1540 * \param L The Lua VM state.
1541 * \luastack
1542 * \lvalue A client.
1544 static int
1545 luaA_client_lower(lua_State *L)
1547 client_t *c = luaA_client_checkudata(L, 1);
1549 stack_client_push(c);
1551 /* Traverse all transient layers. */
1552 for(client_t *tc = c->transient_for; tc; tc = tc->transient_for)
1553 stack_client_push(tc);
1555 client_stack();
1557 return 0;
1560 /** Redraw a client by unmapping and mapping it quickly.
1561 * \param L The Lua VM state.
1563 * \luastack
1564 * \lvalue A client.
1566 static int
1567 luaA_client_redraw(lua_State *L)
1569 client_t *c = luaA_client_checkudata(L, 1);
1571 xcb_unmap_window(globalconf.connection, c->window);
1572 xcb_map_window(globalconf.connection, c->window);
1574 /* Set the focus on the current window if the redraw has been
1575 performed on the window where the pointer is currently on
1576 because after the unmapping/mapping, the focus is lost */
1577 if(globalconf.screen_focus->client_focus == c)
1579 client_unfocus(c);
1580 client_focus(c);
1583 return 0;
1586 /** Stop managing a client.
1587 * \param L The Lua VM state.
1588 * \return The number of elements pushed on stack.
1589 * \luastack
1590 * \lvalue A client.
1592 static int
1593 luaA_client_unmanage(lua_State *L)
1595 client_t *c = luaA_client_checkudata(L, 1);
1596 client_unmanage(c);
1597 return 0;
1600 /** Return client geometry.
1601 * \param L The Lua VM state.
1602 * \return The number of elements pushed on stack.
1603 * \luastack
1604 * \lparam A table with new coordinates, or none.
1605 * \lreturn A table with client coordinates.
1607 static int
1608 luaA_client_geometry(lua_State *L)
1610 client_t *c = luaA_client_checkudata(L, 1);
1612 if(lua_gettop(L) == 2 && !lua_isnil(L, 2))
1614 area_t geometry;
1616 luaA_checktable(L, 2);
1617 geometry.x = luaA_getopt_number(L, 2, "x", c->geometry.x);
1618 geometry.y = luaA_getopt_number(L, 2, "y", c->geometry.y);
1619 if(client_isfixed(c))
1621 geometry.width = c->geometry.width;
1622 geometry.height = c->geometry.height;
1624 else
1626 geometry.width = luaA_getopt_number(L, 2, "width", c->geometry.width);
1627 geometry.height = luaA_getopt_number(L, 2, "height", c->geometry.height);
1630 client_resize(c, geometry, c->size_hints_honor);
1633 return luaA_pusharea(L, c->geometry);
1636 /** Return client struts (reserved space at the edge of the screen).
1637 * \param L The Lua VM state.
1638 * \return The number of elements pushed on stack.
1639 * \luastack
1640 * \lparam A table with new strut values, or none.
1641 * \lreturn A table with strut values.
1643 static int
1644 luaA_client_struts(lua_State *L)
1646 client_t *c = luaA_client_checkudata(L, 1);
1648 if(lua_gettop(L) == 2)
1650 luaA_tostrut(L, 2, &c->strut);
1651 ewmh_update_strut(c->window, &c->strut);
1652 hook_property(c, "struts");
1653 luaA_object_emit_signal(L, 1, "property::struts", 0);
1654 screen_emit_signal(L, c->screen, "property::workarea", 0);
1657 return luaA_pushstrut(L, c->strut);
1660 static int
1661 luaA_client_set_screen(lua_State *L, client_t *c)
1663 if(globalconf.xinerama_is_active)
1665 int screen = luaL_checknumber(L, -1) - 1;
1666 luaA_checkscreen(screen);
1667 screen_client_moveto(c, &globalconf.screens.tab[screen], true);
1669 return 0;
1672 static int
1673 luaA_client_set_hidden(lua_State *L, client_t *c)
1675 bool b = luaA_checkboolean(L, -1);
1676 if(b != c->hidden)
1678 c->hidden = b;
1679 banning_refresh((c)->screen);
1680 hook_property(c, "hidden");
1681 if(strut_has_value(&c->strut))
1682 screen_emit_signal(globalconf.L, c->screen, "property::workarea", 0);
1683 luaA_object_emit_signal(L, -3, "property::hidden", 0);
1685 return 0;
1688 static int
1689 luaA_client_set_minimized(lua_State *L, client_t *c)
1691 client_set_minimized(L, -3, luaA_checkboolean(L, -1));
1692 return 0;
1695 static int
1696 luaA_client_set_fullscreen(lua_State *L, client_t *c)
1698 client_set_fullscreen(L, -3, luaA_checkboolean(L, -1));
1699 return 0;
1702 static int
1703 luaA_client_set_modal(lua_State *L, client_t *c)
1705 client_set_modal(L, -3, luaA_checkboolean(L, -1));
1706 return 0;
1709 static int
1710 luaA_client_set_maximized_horizontal(lua_State *L, client_t *c)
1712 client_set_maximized_horizontal(L, -3, luaA_checkboolean(L, -1));
1713 return 0;
1716 static int
1717 luaA_client_set_maximized_vertical(lua_State *L, client_t *c)
1719 client_set_maximized_vertical(L, -3, luaA_checkboolean(L, -1));
1720 return 0;
1723 static int
1724 luaA_client_set_icon(lua_State *L, client_t *c)
1726 client_set_icon(L, -3, -1);
1727 return 0;
1730 static int
1731 luaA_client_set_opacity(lua_State *L, client_t *c)
1733 if(lua_isnil(L, -1))
1734 client_set_opacity(L, -3, -1);
1735 else
1736 client_set_opacity(L, -3, luaL_checknumber(L, -1));
1737 return 0;
1740 static int
1741 luaA_client_set_sticky(lua_State *L, client_t *c)
1743 client_set_sticky(L, -3, luaA_checkboolean(L, -1));
1744 return 0;
1747 static int
1748 luaA_client_set_size_hints_honor(lua_State *L, client_t *c)
1750 c->size_hints_honor = luaA_checkboolean(L, -1);
1751 hook_property(c, "size_hints_honor");
1752 luaA_object_emit_signal(L, -3, "property::size_hints_honor", 0);
1753 return 0;
1756 static int
1757 luaA_client_set_border_width(lua_State *L, client_t *c)
1759 client_set_border_width(L, -3, luaL_checknumber(L, -1));
1760 return 0;
1763 static int
1764 luaA_client_set_ontop(lua_State *L, client_t *c)
1766 client_set_ontop(L, -3, luaA_checkboolean(L, -1));
1767 return 0;
1770 static int
1771 luaA_client_set_below(lua_State *L, client_t *c)
1773 client_set_below(L, -3, luaA_checkboolean(L, -1));
1774 return 0;
1777 static int
1778 luaA_client_set_above(lua_State *L, client_t *c)
1780 client_set_above(L, -3, luaA_checkboolean(L, -1));
1781 return 0;
1784 static int
1785 luaA_client_set_urgent(lua_State *L, client_t *c)
1787 client_set_urgent(L, -3, luaA_checkboolean(L, -1));
1788 return 0;
1791 static int
1792 luaA_client_set_border_color(lua_State *L, client_t *c)
1794 size_t len;
1795 const char *buf;
1796 if((buf = luaL_checklstring(L, -1, &len))
1797 && xcolor_init_reply(xcolor_init_unchecked(&c->border_color, buf, len)))
1799 xcb_change_window_attributes(globalconf.connection, c->window,
1800 XCB_CW_BORDER_PIXEL, &c->border_color.pixel);
1801 luaA_object_emit_signal(L, -3, "property::border_color", 0);
1803 return 0;
1806 static int
1807 luaA_client_set_titlebar(lua_State *L, client_t *c)
1809 if(lua_isnil(L, -1))
1810 titlebar_client_detach(c);
1811 else
1812 titlebar_client_attach(c);
1813 return 0;
1816 static int
1817 luaA_client_set_skip_taskbar(lua_State *L, client_t *c)
1819 client_set_skip_taskbar(L, -3, luaA_checkboolean(L, -1));
1820 return 0;
1823 static int
1824 luaA_client_get_name(lua_State *L, client_t *c)
1826 lua_pushstring(L, c->name ? c->name : c->alt_name);
1827 return 1;
1830 static int
1831 luaA_client_get_icon_name(lua_State *L, client_t *c)
1833 lua_pushstring(L, c->icon_name ? c->icon_name : c->alt_icon_name);
1834 return 1;
1837 LUA_OBJECT_EXPORT_PROPERTY(client, client_t, class, lua_pushstring)
1838 LUA_OBJECT_EXPORT_PROPERTY(client, client_t, instance, lua_pushstring)
1839 LUA_OBJECT_EXPORT_PROPERTY(client, client_t, machine, lua_pushstring)
1840 LUA_OBJECT_EXPORT_PROPERTY(client, client_t, role, lua_pushstring)
1841 LUA_OBJECT_EXPORT_PROPERTY(client, client_t, transient_for, luaA_object_push)
1842 LUA_OBJECT_EXPORT_PROPERTY(client, client_t, skip_taskbar, lua_pushboolean)
1843 LUA_OBJECT_EXPORT_PROPERTY(client, client_t, window, lua_pushnumber)
1844 LUA_OBJECT_EXPORT_PROPERTY(client, client_t, leader_window, lua_pushnumber)
1845 LUA_OBJECT_EXPORT_PROPERTY(client, client_t, group_window, lua_pushnumber)
1846 LUA_OBJECT_EXPORT_PROPERTY(client, client_t, pid, lua_pushnumber)
1847 LUA_OBJECT_EXPORT_PROPERTY(client, client_t, hidden, lua_pushboolean)
1848 LUA_OBJECT_EXPORT_PROPERTY(client, client_t, minimized, lua_pushboolean)
1849 LUA_OBJECT_EXPORT_PROPERTY(client, client_t, fullscreen, lua_pushboolean)
1850 LUA_OBJECT_EXPORT_PROPERTY(client, client_t, modal, lua_pushboolean)
1851 LUA_OBJECT_EXPORT_PROPERTY(client, client_t, ontop, lua_pushboolean)
1852 LUA_OBJECT_EXPORT_PROPERTY(client, client_t, urgent, lua_pushboolean)
1853 LUA_OBJECT_EXPORT_PROPERTY(client, client_t, above, lua_pushboolean)
1854 LUA_OBJECT_EXPORT_PROPERTY(client, client_t, below, lua_pushboolean)
1855 LUA_OBJECT_EXPORT_PROPERTY(client, client_t, sticky, lua_pushboolean)
1856 LUA_OBJECT_EXPORT_PROPERTY(client, client_t, size_hints_honor, lua_pushboolean)
1857 LUA_OBJECT_EXPORT_PROPERTY(client, client_t, maximized_horizontal, lua_pushboolean)
1858 LUA_OBJECT_EXPORT_PROPERTY(client, client_t, maximized_vertical, lua_pushboolean)
1859 LUA_OBJECT_EXPORT_PROPERTY(client, client_t, opacity, lua_pushnumber)
1860 LUA_OBJECT_EXPORT_PROPERTY(client, client_t, border_width, lua_pushnumber)
1861 LUA_OBJECT_EXPORT_PROPERTY(client, client_t, border_color, luaA_pushxcolor)
1863 static int
1864 luaA_client_get_content(lua_State *L, client_t *c)
1866 xcb_image_t *ximage = xcb_image_get(globalconf.connection,
1867 c->window,
1868 0, 0,
1869 c->geometries.internal.width,
1870 c->geometries.internal.height,
1871 ~0, XCB_IMAGE_FORMAT_Z_PIXMAP);
1872 int retval = 0;
1874 if(ximage)
1876 if(ximage->bpp >= 24)
1878 uint32_t *data = p_alloca(uint32_t, ximage->width * ximage->height);
1880 for(int y = 0; y < ximage->height; y++)
1881 for(int x = 0; x < ximage->width; x++)
1883 data[y * ximage->width + x] = xcb_image_get_pixel(ximage, x, y);
1884 data[y * ximage->width + x] |= 0xff000000; /* set alpha to 0xff */
1887 retval = image_new_from_argb32(ximage->width, ximage->height, data);
1889 xcb_image_destroy(ximage);
1892 return retval;
1895 static int
1896 luaA_client_get_type(lua_State *L, client_t *c)
1898 switch(c->type)
1900 case WINDOW_TYPE_DESKTOP:
1901 lua_pushliteral(L, "desktop");
1902 break;
1903 case WINDOW_TYPE_DOCK:
1904 lua_pushliteral(L, "dock");
1905 break;
1906 case WINDOW_TYPE_SPLASH:
1907 lua_pushliteral(L, "splash");
1908 break;
1909 case WINDOW_TYPE_DIALOG:
1910 lua_pushliteral(L, "dialog");
1911 break;
1912 case WINDOW_TYPE_MENU:
1913 lua_pushliteral(L, "menu");
1914 break;
1915 case WINDOW_TYPE_TOOLBAR:
1916 lua_pushliteral(L, "toolbar");
1917 break;
1918 case WINDOW_TYPE_UTILITY:
1919 lua_pushliteral(L, "utility");
1920 break;
1921 case WINDOW_TYPE_DROPDOWN_MENU:
1922 lua_pushliteral(L, "dropdown_menu");
1923 break;
1924 case WINDOW_TYPE_POPUP_MENU:
1925 lua_pushliteral(L, "popup_menu");
1926 break;
1927 case WINDOW_TYPE_TOOLTIP:
1928 lua_pushliteral(L, "tooltip");
1929 break;
1930 case WINDOW_TYPE_NOTIFICATION:
1931 lua_pushliteral(L, "notification");
1932 break;
1933 case WINDOW_TYPE_COMBO:
1934 lua_pushliteral(L, "combo");
1935 break;
1936 case WINDOW_TYPE_DND:
1937 lua_pushliteral(L, "dnd");
1938 break;
1939 case WINDOW_TYPE_NORMAL:
1940 lua_pushliteral(L, "normal");
1941 break;
1943 return 1;
1946 static int
1947 luaA_client_get_screen(lua_State *L, client_t *c)
1949 if(!c->screen)
1950 return 0;
1951 lua_pushnumber(L, 1 + screen_array_indexof(&globalconf.screens, c->screen));
1952 return 1;
1955 static int
1956 luaA_client_get_icon(lua_State *L, client_t *c)
1958 return luaA_object_push_item(L, -2, c->icon);
1961 static int
1962 luaA_client_get_titlebar(lua_State *L, client_t *c)
1964 return luaA_object_push(L, c->titlebar);
1967 static int
1968 luaA_client_get_size_hints(lua_State *L, client_t *c)
1970 const char *u_or_p = NULL;
1972 lua_createtable(L, 0, 1);
1974 if(c->size_hints.flags & XCB_SIZE_HINT_US_POSITION)
1975 u_or_p = "user_position";
1976 else if(c->size_hints.flags & XCB_SIZE_HINT_P_POSITION)
1977 u_or_p = "program_position";
1979 if(u_or_p)
1981 lua_createtable(L, 0, 2);
1982 lua_pushnumber(L, c->size_hints.x);
1983 lua_setfield(L, -2, "x");
1984 lua_pushnumber(L, c->size_hints.y);
1985 lua_setfield(L, -2, "y");
1986 lua_setfield(L, -2, u_or_p);
1987 u_or_p = NULL;
1990 if(c->size_hints.flags & XCB_SIZE_HINT_US_SIZE)
1991 u_or_p = "user_size";
1992 else if(c->size_hints.flags & XCB_SIZE_HINT_P_SIZE)
1993 u_or_p = "program_size";
1995 if(u_or_p)
1997 lua_createtable(L, 0, 2);
1998 lua_pushnumber(L, c->size_hints.width);
1999 lua_setfield(L, -2, "width");
2000 lua_pushnumber(L, c->size_hints.height);
2001 lua_setfield(L, -2, "height");
2002 lua_setfield(L, -2, u_or_p);
2005 if(c->size_hints.flags & XCB_SIZE_HINT_P_MIN_SIZE)
2007 lua_pushnumber(L, c->size_hints.min_width);
2008 lua_setfield(L, -2, "min_width");
2009 lua_pushnumber(L, c->size_hints.min_height);
2010 lua_setfield(L, -2, "min_height");
2013 if(c->size_hints.flags & XCB_SIZE_HINT_P_MAX_SIZE)
2015 lua_pushnumber(L, c->size_hints.max_width);
2016 lua_setfield(L, -2, "max_width");
2017 lua_pushnumber(L, c->size_hints.max_height);
2018 lua_setfield(L, -2, "max_height");
2021 if(c->size_hints.flags & XCB_SIZE_HINT_P_RESIZE_INC)
2023 lua_pushnumber(L, c->size_hints.width_inc);
2024 lua_setfield(L, -2, "width_inc");
2025 lua_pushnumber(L, c->size_hints.height_inc);
2026 lua_setfield(L, -2, "height_inc");
2029 if(c->size_hints.flags & XCB_SIZE_HINT_P_ASPECT)
2031 lua_pushnumber(L, c->size_hints.min_aspect_num);
2032 lua_setfield(L, -2, "min_aspect_num");
2033 lua_pushnumber(L, c->size_hints.min_aspect_den);
2034 lua_setfield(L, -2, "min_aspect_den");
2035 lua_pushnumber(L, c->size_hints.max_aspect_num);
2036 lua_setfield(L, -2, "max_aspect_num");
2037 lua_pushnumber(L, c->size_hints.max_aspect_den);
2038 lua_setfield(L, -2, "max_aspect_den");
2041 if(c->size_hints.flags & XCB_SIZE_HINT_BASE_SIZE)
2043 lua_pushnumber(L, c->size_hints.base_width);
2044 lua_setfield(L, -2, "base_width");
2045 lua_pushnumber(L, c->size_hints.base_height);
2046 lua_setfield(L, -2, "base_height");
2049 if(c->size_hints.flags & XCB_SIZE_HINT_P_WIN_GRAVITY)
2051 switch(c->size_hints.win_gravity)
2053 default:
2054 lua_pushliteral(L, "north_west");
2055 break;
2056 case XCB_GRAVITY_NORTH:
2057 lua_pushliteral(L, "north");
2058 break;
2059 case XCB_GRAVITY_NORTH_EAST:
2060 lua_pushliteral(L, "north_east");
2061 break;
2062 case XCB_GRAVITY_WEST:
2063 lua_pushliteral(L, "west");
2064 break;
2065 case XCB_GRAVITY_CENTER:
2066 lua_pushliteral(L, "center");
2067 break;
2068 case XCB_GRAVITY_EAST:
2069 lua_pushliteral(L, "east");
2070 break;
2071 case XCB_GRAVITY_SOUTH_WEST:
2072 lua_pushliteral(L, "south_west");
2073 break;
2074 case XCB_GRAVITY_SOUTH:
2075 lua_pushliteral(L, "south");
2076 break;
2077 case XCB_GRAVITY_SOUTH_EAST:
2078 lua_pushliteral(L, "south_east");
2079 break;
2080 case XCB_GRAVITY_STATIC:
2081 lua_pushliteral(L, "static");
2082 break;
2084 lua_setfield(L, -2, "win_gravity");
2087 return 1;
2090 /** Get or set mouse buttons bindings for a client.
2091 * \param L The Lua VM state.
2092 * \return The number of element pushed on stack.
2093 * \luastack
2094 * \lvalue A client.
2095 * \lparam An array of mouse button bindings objects, or nothing.
2096 * \return The array of mouse button bindings objects of this client.
2098 static int
2099 luaA_client_buttons(lua_State *L)
2101 client_t *client = luaA_client_checkudata(L, 1);
2102 button_array_t *buttons = &client->buttons;
2104 if(lua_gettop(L) == 2)
2106 luaA_button_array_set(L, 1, 2, buttons);
2107 luaA_object_emit_signal(L, 1, "property::buttons", 0);
2108 window_buttons_grab(client->window, &client->buttons);
2111 return luaA_button_array_get(L, 1, buttons);
2114 /** Get or set keys bindings for a client.
2115 * \param L The Lua VM state.
2116 * \return The number of element pushed on stack.
2117 * \luastack
2118 * \lvalue A client.
2119 * \lparam An array of key bindings objects, or nothing.
2120 * \return The array of key bindings objects of this client.
2122 static int
2123 luaA_client_keys(lua_State *L)
2125 client_t *c = luaA_client_checkudata(L, 1);
2126 key_array_t *keys = &c->keys;
2128 if(lua_gettop(L) == 2)
2130 luaA_key_array_set(L, 1, 2, keys);
2131 luaA_object_emit_signal(L, 1, "property::keys", 0);
2132 xcb_ungrab_key(globalconf.connection, XCB_GRAB_ANY, c->window, XCB_BUTTON_MASK_ANY);
2133 window_grabkeys(c->window, keys);
2136 return luaA_key_array_get(L, 1, keys);
2139 /* Client module.
2140 * \param L The Lua VM state.
2141 * \return The number of pushed elements.
2143 static int
2144 luaA_client_module_index(lua_State *L)
2146 size_t len;
2147 const char *buf = luaL_checklstring(L, 2, &len);
2149 switch(a_tokenize(buf, len))
2151 case A_TK_FOCUS:
2152 return luaA_object_push(globalconf.L, globalconf.screen_focus->client_focus);
2153 break;
2154 default:
2155 return 0;
2159 /* Client module new index.
2160 * \param L The Lua VM state.
2161 * \return The number of pushed elements.
2163 static int
2164 luaA_client_module_newindex(lua_State *L)
2166 size_t len;
2167 const char *buf = luaL_checklstring(L, 2, &len);
2168 client_t *c;
2170 switch(a_tokenize(buf, len))
2172 case A_TK_FOCUS:
2173 c = luaA_client_checkudata(L, 3);
2174 client_focus(c);
2175 break;
2176 default:
2177 break;
2180 return 0;
2183 void
2184 client_class_setup(lua_State *L)
2186 static const struct luaL_reg client_methods[] =
2188 LUA_CLASS_METHODS(client)
2189 { "get", luaA_client_get },
2190 { "__index", luaA_client_module_index },
2191 { "__newindex", luaA_client_module_newindex },
2192 { NULL, NULL }
2195 static const struct luaL_reg client_meta[] =
2197 LUA_OBJECT_META(client)
2198 LUA_CLASS_META
2199 { "buttons", luaA_client_buttons },
2200 { "keys", luaA_client_keys },
2201 { "isvisible", luaA_client_isvisible },
2202 { "geometry", luaA_client_geometry },
2203 { "struts", luaA_client_struts },
2204 { "tags", luaA_client_tags },
2205 { "kill", luaA_client_kill },
2206 { "swap", luaA_client_swap },
2207 { "raise", luaA_client_raise },
2208 { "lower", luaA_client_lower },
2209 { "redraw", luaA_client_redraw },
2210 { "unmanage", luaA_client_unmanage },
2211 { "__gc", luaA_client_gc },
2212 { NULL, NULL }
2215 luaA_class_setup(L, &client_class, "client", (lua_class_allocator_t) client_new,
2216 luaA_class_index_miss_property, luaA_class_newindex_miss_property,
2217 client_methods, client_meta);
2218 luaA_class_add_property(&client_class, A_TK_NAME,
2219 NULL,
2220 (lua_class_propfunc_t) luaA_client_get_name,
2221 NULL);
2222 luaA_class_add_property(&client_class, A_TK_TRANSIENT_FOR,
2223 NULL,
2224 (lua_class_propfunc_t) luaA_client_get_transient_for,
2225 NULL);
2226 luaA_class_add_property(&client_class, A_TK_SKIP_TASKBAR,
2227 (lua_class_propfunc_t) luaA_client_set_skip_taskbar,
2228 (lua_class_propfunc_t) luaA_client_get_skip_taskbar,
2229 (lua_class_propfunc_t) luaA_client_set_skip_taskbar);
2230 luaA_class_add_property(&client_class, A_TK_CONTENT,
2231 NULL,
2232 (lua_class_propfunc_t) luaA_client_get_content,
2233 NULL);
2234 luaA_class_add_property(&client_class, A_TK_TYPE,
2235 NULL,
2236 (lua_class_propfunc_t) luaA_client_get_type,
2237 NULL);
2238 luaA_class_add_property(&client_class, A_TK_CLASS,
2239 NULL,
2240 (lua_class_propfunc_t) luaA_client_get_class,
2241 NULL);
2242 luaA_class_add_property(&client_class, A_TK_INSTANCE,
2243 NULL,
2244 (lua_class_propfunc_t) luaA_client_get_instance,
2245 NULL);
2246 luaA_class_add_property(&client_class, A_TK_ROLE,
2247 NULL,
2248 (lua_class_propfunc_t) luaA_client_get_role,
2249 NULL);
2250 luaA_class_add_property(&client_class, A_TK_PID,
2251 NULL,
2252 (lua_class_propfunc_t) luaA_client_get_pid,
2253 NULL);
2254 luaA_class_add_property(&client_class, A_TK_WINDOW,
2255 NULL,
2256 (lua_class_propfunc_t) luaA_client_get_window,
2257 NULL);
2258 luaA_class_add_property(&client_class, A_TK_LEADER_WINDOW,
2259 NULL,
2260 (lua_class_propfunc_t) luaA_client_get_leader_window,
2261 NULL);
2262 luaA_class_add_property(&client_class, A_TK_MACHINE,
2263 NULL,
2264 (lua_class_propfunc_t) luaA_client_get_machine,
2265 NULL);
2266 luaA_class_add_property(&client_class, A_TK_ICON_NAME,
2267 NULL,
2268 (lua_class_propfunc_t) luaA_client_get_icon_name,
2269 NULL);
2270 luaA_class_add_property(&client_class, A_TK_SCREEN,
2271 NULL,
2272 (lua_class_propfunc_t) luaA_client_get_screen,
2273 (lua_class_propfunc_t) luaA_client_set_screen);
2274 luaA_class_add_property(&client_class, A_TK_HIDDEN,
2275 (lua_class_propfunc_t) luaA_client_set_hidden,
2276 (lua_class_propfunc_t) luaA_client_get_hidden,
2277 (lua_class_propfunc_t) luaA_client_set_hidden);
2278 luaA_class_add_property(&client_class, A_TK_MINIMIZED,
2279 (lua_class_propfunc_t) luaA_client_set_minimized,
2280 (lua_class_propfunc_t) luaA_client_get_minimized,
2281 (lua_class_propfunc_t) luaA_client_set_minimized);
2282 luaA_class_add_property(&client_class, A_TK_FULLSCREEN,
2283 (lua_class_propfunc_t) luaA_client_set_fullscreen,
2284 (lua_class_propfunc_t) luaA_client_get_fullscreen,
2285 (lua_class_propfunc_t) luaA_client_set_fullscreen);
2286 luaA_class_add_property(&client_class, A_TK_MODAL,
2287 (lua_class_propfunc_t) luaA_client_set_modal,
2288 (lua_class_propfunc_t) luaA_client_get_modal,
2289 (lua_class_propfunc_t) luaA_client_set_modal);
2290 luaA_class_add_property(&client_class, A_TK_GROUP_WINDOW,
2291 NULL,
2292 (lua_class_propfunc_t) luaA_client_get_group_window,
2293 NULL);
2294 luaA_class_add_property(&client_class, A_TK_MAXIMIZED_HORIZONTAL,
2295 (lua_class_propfunc_t) luaA_client_set_maximized_horizontal,
2296 (lua_class_propfunc_t) luaA_client_get_maximized_horizontal,
2297 (lua_class_propfunc_t) luaA_client_set_maximized_horizontal);
2298 luaA_class_add_property(&client_class, A_TK_MAXIMIZED_VERTICAL,
2299 (lua_class_propfunc_t) luaA_client_set_maximized_vertical,
2300 (lua_class_propfunc_t) luaA_client_get_maximized_vertical,
2301 (lua_class_propfunc_t) luaA_client_set_maximized_vertical);
2302 luaA_class_add_property(&client_class, A_TK_ICON,
2303 (lua_class_propfunc_t) luaA_client_set_icon,
2304 (lua_class_propfunc_t) luaA_client_get_icon,
2305 (lua_class_propfunc_t) luaA_client_set_icon);
2306 luaA_class_add_property(&client_class, A_TK_OPACITY,
2307 (lua_class_propfunc_t) luaA_client_set_opacity,
2308 (lua_class_propfunc_t) luaA_client_get_opacity,
2309 (lua_class_propfunc_t) luaA_client_set_opacity);
2310 luaA_class_add_property(&client_class, A_TK_ONTOP,
2311 (lua_class_propfunc_t) luaA_client_set_ontop,
2312 (lua_class_propfunc_t) luaA_client_get_ontop,
2313 (lua_class_propfunc_t) luaA_client_set_ontop);
2314 luaA_class_add_property(&client_class, A_TK_ABOVE,
2315 (lua_class_propfunc_t) luaA_client_set_above,
2316 (lua_class_propfunc_t) luaA_client_get_above,
2317 (lua_class_propfunc_t) luaA_client_set_above);
2318 luaA_class_add_property(&client_class, A_TK_BELOW,
2319 (lua_class_propfunc_t) luaA_client_set_below,
2320 (lua_class_propfunc_t) luaA_client_get_below,
2321 (lua_class_propfunc_t) luaA_client_set_below);
2322 luaA_class_add_property(&client_class, A_TK_STICKY,
2323 (lua_class_propfunc_t) luaA_client_set_sticky,
2324 (lua_class_propfunc_t) luaA_client_get_sticky,
2325 (lua_class_propfunc_t) luaA_client_set_sticky);
2326 luaA_class_add_property(&client_class, A_TK_SIZE_HINTS_HONOR,
2327 (lua_class_propfunc_t) luaA_client_set_size_hints_honor,
2328 (lua_class_propfunc_t) luaA_client_get_size_hints_honor,
2329 (lua_class_propfunc_t) luaA_client_set_size_hints_honor);
2330 luaA_class_add_property(&client_class, A_TK_BORDER_WIDTH,
2331 (lua_class_propfunc_t) luaA_client_set_border_width,
2332 (lua_class_propfunc_t) luaA_client_get_border_width,
2333 (lua_class_propfunc_t) luaA_client_set_border_width);
2334 luaA_class_add_property(&client_class, A_TK_BORDER_COLOR,
2335 (lua_class_propfunc_t) luaA_client_set_border_color,
2336 (lua_class_propfunc_t) luaA_client_get_border_color,
2337 (lua_class_propfunc_t) luaA_client_set_border_color);
2338 luaA_class_add_property(&client_class, A_TK_TITLEBAR,
2339 (lua_class_propfunc_t) luaA_client_set_titlebar,
2340 (lua_class_propfunc_t) luaA_client_get_titlebar,
2341 (lua_class_propfunc_t) luaA_client_set_titlebar);
2342 luaA_class_add_property(&client_class, A_TK_URGENT,
2343 (lua_class_propfunc_t) luaA_client_set_urgent,
2344 (lua_class_propfunc_t) luaA_client_get_urgent,
2345 (lua_class_propfunc_t) luaA_client_set_urgent);
2346 luaA_class_add_property(&client_class, A_TK_SIZE_HINTS,
2347 NULL,
2348 (lua_class_propfunc_t) luaA_client_get_size_hints,
2349 NULL);
2352 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80