void drawable_set_geometry(lua_State *L, int didx, area_t geom) { drawable_t *d = luaA_checkudata(L, didx, &drawable_class); area_t old = d->geometry; d->geometry = geom; bool size_changed = (old.width != geom.width) || (old.height != geom.height); if (size_changed) drawable_unset_surface(d); if (size_changed && geom.width > 0 && geom.height > 0) { d->pixmap = xcb_generate_id(globalconf.connection); xcb_create_pixmap(globalconf.connection, globalconf.default_depth, d->pixmap, globalconf.screen->root, geom.width, geom.height); d->surface = cairo_xcb_surface_create(globalconf.connection, d->pixmap, globalconf.visual, geom.width, geom.height); luaA_object_emit_signal(L, didx, "property::surface", 0); } if (old.x != geom.x) luaA_object_emit_signal(L, didx, "property::x", 0); if (old.y != geom.y) luaA_object_emit_signal(L, didx, "property::y", 0); if (old.width != geom.width) luaA_object_emit_signal(L, didx, "property::width", 0); if (old.height != geom.height) luaA_object_emit_signal(L, didx, "property::height", 0); }
/** Record that the given drawable contains the pointer. */ void event_drawable_under_mouse(lua_State *L, int ud) { void *d; lua_pushvalue(L, ud); d = luaA_object_ref(L, -1); if (d == globalconf.drawable_under_mouse) { /* Nothing to do */ luaA_object_unref(L, d); return; } if (globalconf.drawable_under_mouse != NULL) { /* Emit leave on previous drawable */ luaA_object_push(L, globalconf.drawable_under_mouse); luaA_object_emit_signal(L, -1, "mouse::leave", 0); lua_pop(L, 1); /* Unref the previous drawable */ luaA_object_unref(L, globalconf.drawable_under_mouse); globalconf.drawable_under_mouse = NULL; } if (d != NULL) { /* Reference the drawable for leave event later */ globalconf.drawable_under_mouse = d; /* Emit enter */ luaA_object_emit_signal(L, ud, "mouse::enter", 0); } }
/** Move and/or resize a drawin * \param L The Lua VM state. * \param udx The index of the drawin. * \param geometry The new geometry. */ static void drawin_moveresize(lua_State *L, int udx, area_t geometry) { drawin_t *w = luaA_checkudata(L, udx, &drawin_class); int number_of_vals = 0; uint32_t moveresize_win_vals[4], mask_vals = 0; if(w->geometry.x != geometry.x) { w->geometry.x = moveresize_win_vals[number_of_vals++] = geometry.x; mask_vals |= XCB_CONFIG_WINDOW_X; } if(w->geometry.y != geometry.y) { w->geometry.y = moveresize_win_vals[number_of_vals++] = geometry.y; mask_vals |= XCB_CONFIG_WINDOW_Y; } if(geometry.width > 0 && w->geometry.width != geometry.width) { w->geometry.width = moveresize_win_vals[number_of_vals++] = geometry.width; mask_vals |= XCB_CONFIG_WINDOW_WIDTH; } if(geometry.height > 0 && w->geometry.height != geometry.height) { w->geometry.height = moveresize_win_vals[number_of_vals++] = geometry.height; mask_vals |= XCB_CONFIG_WINDOW_HEIGHT; } if(mask_vals & (XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT)) drawin_update_drawing(w, udx); else { /* We still have to set x/y */ luaA_object_push_item(L, udx, w->drawable); drawable_set_geometry(w->drawable, -1, w->geometry); lua_pop(L, 1); } /* Activate BMA */ client_ignore_enterleave_events(); if(mask_vals) xcb_configure_window(globalconf.connection, w->window, mask_vals, moveresize_win_vals); /* Deactivate BMA */ client_restore_enterleave_events(); if(mask_vals & XCB_CONFIG_WINDOW_X) luaA_object_emit_signal(L, udx, "property::x", 0); if(mask_vals & XCB_CONFIG_WINDOW_Y) luaA_object_emit_signal(L, udx, "property::y", 0); if(mask_vals & XCB_CONFIG_WINDOW_WIDTH) luaA_object_emit_signal(L, udx, "property::width", 0); if(mask_vals & XCB_CONFIG_WINDOW_HEIGHT) luaA_object_emit_signal(L, udx, "property::height", 0); }
/** The shape notify event handler. * \param ev The event. */ static void event_handle_shape_notify(xcb_shape_notify_event_t *ev) { client_t *c = client_getbywin(ev->affected_window); if (c) { lua_State *L = globalconf_get_lua_State(); luaA_object_push(L, c); if (ev->shape_kind == XCB_SHAPE_SK_BOUNDING) luaA_object_emit_signal(L, -1, "property::shape_client_bounding", 0); if (ev->shape_kind == XCB_SHAPE_SK_CLIP) luaA_object_emit_signal(L, -1, "property::shape_client_clip", 0); lua_pop(L, 1); } }
static void tag_client_emit_signal(lua_State *L, tag_t *t, client_t *c, const char *signame) { luaA_object_push(L, c); luaA_object_push(L, t); /* emit signal on client, with new tag as argument */ luaA_object_emit_signal(L, -2, signame, 1); /* re push tag */ luaA_object_push(L, t); /* move tag before client */ lua_insert(L, -2); luaA_object_emit_signal(L, -2, signame, 1); /* Remove tag */ lua_pop(L, 1); }
static int luaA_button_set_modifiers(lua_State *L, button_t *b) { b->modifiers = luaA_tomodifiers(L, -1); luaA_object_emit_signal(L, -3, "property::modifiers", 0); return 0; }
static int luaA_button_set_button(lua_State *L, button_t *b) { b->button = luaL_checknumber(L, -1); luaA_object_emit_signal(L, -3, "property::button", 0); return 0; }
/** The leave notify event handler. * \param ev The event. */ static void event_handle_leavenotify(xcb_leave_notify_event_t *ev) { lua_State *L = globalconf_get_lua_State(); client_t *c; globalconf.timestamp = ev->time; if(ev->mode != XCB_NOTIFY_MODE_NORMAL) return; /* Ignore leave with detail inferior (we were left for a window contained in * our window, so technically the pointer is still inside of this window). */ if(ev->detail != XCB_NOTIFY_DETAIL_INFERIOR && (c = client_getbyframewin(ev->event))) { luaA_object_push(L, c); luaA_object_emit_signal(L, -1, "mouse::leave", 0); lua_pop(L, 1); } lua_pushnil(L); event_drawable_under_mouse(L, -1); lua_pop(L, 1); }
/** View or unview a tag. * \param L The Lua VM state. * \param udx The index of the tag on the stack. * \param view Set visible or not. */ static void tag_view(lua_State *L, int udx, bool view) { tag_t *tag = luaA_checkudata(L, udx, &tag_class); if(tag->selected != view) { tag->selected = view; if(tag->screen) { int screen_index = screen_array_indexof(&globalconf.screens, tag->screen); banning_need_update(tag->screen); ewmh_update_net_current_desktop(screen_virttophys(screen_index)); if(globalconf.hooks.tags != LUA_REFNIL) { lua_pushnumber(globalconf.L, screen_index + 1); luaA_object_push(globalconf.L, tag); if(view) lua_pushliteral(globalconf.L, "select"); else lua_pushliteral(globalconf.L, "unselect"); luaA_dofunction_from_registry(globalconf.L, globalconf.hooks.tags, 3, 0); } } luaA_object_emit_signal(L, udx, "property::selected", 0); } }
static int luaA_key_set_modifiers(lua_State *L, keyb_t *k) { k->modifiers = luaA_tomodifiers(L, -1); luaA_object_emit_signal(L, -3, "property::modifiers", 0); return 0; }
static void luaA_keystore(lua_State *L, int ud, const char *str, ssize_t len) { keyb_t *key = luaA_checkudata(L, ud, &key_class); if(len) { if(*str != '#') { key->keysym = XStringToKeysym(str); if(!key->keysym) { if(len == 1) key->keysym = *str; else warn("there's no keysym named \"%s\"", str); } key->keycode = 0; } else { key->keycode = atoi(str + 1); key->keysym = 0; } luaA_object_emit_signal(L, ud, "property::key", 0); } }
static int luaA_timer_set_timeout(lua_State *L, atimer_t *timer) { double timeout = luaL_checknumber(L, -1); timer->timeout = timeout; luaA_object_emit_signal(L, -3, "property::timeout", 0); return 0; }
static gboolean timer_emit_signal(gpointer data) { luaA_object_push(globalconf.L, data); luaA_object_emit_signal(globalconf.L, -1, "timeout", 0); lua_pop(globalconf.L, 1); return TRUE; }
/** The motion notify event handler. * \param ev The event. */ static void event_handle_motionnotify(xcb_motion_notify_event_t *ev) { lua_State *L = globalconf_get_lua_State(); drawin_t *w; client_t *c; globalconf.timestamp = ev->time; if(event_handle_mousegrabber(ev->root_x, ev->root_y, ev->state)) return; if((c = client_getbyframewin(ev->event))) { luaA_object_push(L, c); lua_pushinteger(L, ev->event_x); lua_pushinteger(L, ev->event_y); luaA_object_emit_signal(L, -3, "mouse::move", 2); /* now check if a titlebar was "hit" */ int x = ev->event_x, y = ev->event_y; drawable_t *d = client_get_drawable_offset(c, &x, &y); if (d) { luaA_object_push_item(L, -1, d); event_drawable_under_mouse(L, -1); lua_pushinteger(L, x); lua_pushinteger(L, y); luaA_object_emit_signal(L, -3, "mouse::move", 2); lua_pop(L, 1); } lua_pop(L, 1); } if((w = drawin_getbywin(ev->event))) { luaA_object_push(L, w); luaA_object_push_item(L, -1, w->drawable); event_drawable_under_mouse(L, -1); lua_pushinteger(L, ev->event_x); lua_pushinteger(L, ev->event_y); luaA_object_emit_signal(L, -3, "mouse::move", 2); lua_pop(L, 2); } }
/** Set a window opacity. * \param L The Lua VM state. * \param idx The index of the window on the stack. * \param opacity The opacity value. */ void window_set_opacity(lua_State *L, int idx, double opacity) { window_t *window = luaA_checkudata(L, idx, &window_class); if(window->opacity != opacity) { window->opacity = opacity; xwindow_set_opacity(window_get(window), opacity); luaA_object_emit_signal(L, idx, "property::opacity", 0); } }
/** View or unview a tag. * \param L The Lua VM state. * \param udx The index of the tag on the stack. * \param view Set selected or not. */ static void tag_view(lua_State *L, int udx, bool view) { tag_t *tag = luaA_checkudata(L, udx, &tag_class); if(tag->selected != view) { tag->selected = view; banning_need_update(); ewmh_update_net_current_desktop(); luaA_object_emit_signal(L, udx, "property::selected", 0); } }
/** Get or set mouse buttons bindings on a window. * \param L The Lua VM state. * \return The number of elements pushed on the stack. */ static int luaA_window_buttons(lua_State *L) { window_t *window = luaA_checkudata(L, 1, &window_class); if(lua_gettop(L) == 2) { luaA_button_array_set(L, 1, 2, &window->buttons); luaA_object_emit_signal(L, 1, "property::buttons", 0); xwindow_buttons_grab(window_get(window), &window->buttons); } return luaA_button_array_get(L, 1, &window->buttons); }
/** Set the window type. * \param L The Lua VM state. * \param window The window object. * \return The number of elements pushed on stack. */ int luaA_window_set_type(lua_State *L, window_t *w) { window_type_t type; const char *buf = luaL_checkstring(L, -1); if (A_STREQ(buf, "desktop")) type = WINDOW_TYPE_DESKTOP; else if(A_STREQ(buf, "dock")) type = WINDOW_TYPE_DOCK; else if(A_STREQ(buf, "splash")) type = WINDOW_TYPE_SPLASH; else if(A_STREQ(buf, "dialog")) type = WINDOW_TYPE_DIALOG; else if(A_STREQ(buf, "menu")) type = WINDOW_TYPE_MENU; else if(A_STREQ(buf, "toolbar")) type = WINDOW_TYPE_TOOLBAR; else if(A_STREQ(buf, "utility")) type = WINDOW_TYPE_UTILITY; else if(A_STREQ(buf, "dropdown_menu")) type = WINDOW_TYPE_DROPDOWN_MENU; else if(A_STREQ(buf, "popup_menu")) type = WINDOW_TYPE_POPUP_MENU; else if(A_STREQ(buf, "tooltip")) type = WINDOW_TYPE_TOOLTIP; else if(A_STREQ(buf, "notification")) type = WINDOW_TYPE_NOTIFICATION; else if(A_STREQ(buf, "combo")) type = WINDOW_TYPE_COMBO; else if(A_STREQ(buf, "dnd")) type = WINDOW_TYPE_DND; else if(A_STREQ(buf, "normal")) type = WINDOW_TYPE_NORMAL; else { warn("Unknown window type '%s'", buf); return 0; } if(w->type != type) { w->type = type; if(w->window != XCB_WINDOW_NONE) ewmh_update_window_type(w->window, window_translate_type(w->type)); luaA_object_emit_signal(globalconf.L, -3, "property::type", 0); } return 0; }
/** Set the window border color. * \param L The Lua VM state. * \param window The window object. * \return The number of elements pushed on stack. */ static int luaA_window_set_border_color(lua_State *L, window_t *window) { size_t len; const char *color_name = luaL_checklstring(L, -1, &len); if(color_name && color_init_reply(color_init_unchecked(&window->border_color, color_name, len))) { xwindow_set_border_color(window_get(window), &window->border_color); luaA_object_emit_signal(L, -3, "property::border_color", 0); } return 0; }
/** Return window struts (reserved space at the edge of the screen). * \param L The Lua VM state. * \return The number of elements pushed on stack. */ static int luaA_window_struts(lua_State *L) { window_t *window = luaA_checkudata(L, 1, &window_class); if(lua_gettop(L) == 2) { luaA_tostrut(L, 2, &window->strut); ewmh_update_strut(window->window, &window->strut); luaA_object_emit_signal(L, 1, "property::struts", 0); /* We don't know the correct screen, update them all */ foreach(s, globalconf.screens) screen_update_workarea(*s); } return luaA_pushstrut(L, window->strut); }
/** Set a window border width. * \param L The Lua VM state. * \param idx The window index. * \param width The border width. */ void window_set_border_width(lua_State *L, int idx, int width) { window_t *window = luaA_checkudata(L, idx, &window_class); if(width == window->border_width || width < 0) return; if(window->window) xcb_configure_window(globalconf.connection, window_get(window), XCB_CONFIG_WINDOW_BORDER_WIDTH, (uint32_t[]) { width }); window->border_width = width; luaA_object_emit_signal(L, idx, "property::border_width", 0); }
/** Set a window border width. * \param L The Lua VM state. * \param idx The window index. * \param width The border width. */ void window_set_border_width(lua_State *L, int idx, int width) { window_t *window = luaA_checkudata(L, idx, &window_class); uint16_t old_width = window->border_width; if(width == window->border_width || width < 0) return; window->border_need_update = true; window->border_width = width; if(window->border_width_callback) (*window->border_width_callback)(window, old_width, width); luaA_object_emit_signal(L, idx, "property::border_width", 0); }
/** The enter notify event handler. * \param ev The event. */ static void event_handle_enternotify(xcb_enter_notify_event_t *ev) { lua_State *L = globalconf_get_lua_State(); client_t *c; drawin_t *drawin; globalconf.timestamp = ev->time; if(ev->mode != XCB_NOTIFY_MODE_NORMAL) return; if((drawin = drawin_getbywin(ev->event))) { luaA_object_push(L, drawin); luaA_object_push_item(L, -1, drawin->drawable); event_drawable_under_mouse(L, -1); lua_pop(L, 2); } if((c = client_getbyframewin(ev->event))) { luaA_object_push(L, c); /* Ignore enter with detail inferior: The pointer was previously inside * of a child window, so technically this isn't a 'real' enter. */ if (ev->detail != XCB_NOTIFY_DETAIL_INFERIOR) luaA_object_emit_signal(L, -1, "mouse::enter", 0); drawable_t *d = client_get_drawable(c, ev->event_x, ev->event_y); if (d) { luaA_object_push_item(L, -1, d); event_drawable_under_mouse(L, -1); lua_pop(L, 1); } lua_pop(L, 1); } else if (ev->event == globalconf.screen->root) { /* When there are multiple X screens with awesome running separate * instances, reset focus. */ globalconf.focus.need_update = true; } }
/** Return window struts (reserved space at the edge of the screen). * \param L The Lua VM state. * \return The number of elements pushed on stack. */ static int luaA_window_struts(lua_State *L) { window_t *window = luaA_checkudata(L, 1, &window_class); if(lua_gettop(L) == 2) { luaA_tostrut(L, 2, &window->strut); ewmh_update_strut(window->window, &window->strut); luaA_object_emit_signal(L, 1, "property::struts", 0); /* FIXME: Only emit if the workarea actually changed * (= window is visible, only on the right screen)? */ foreach(s, globalconf.screens) screen_emit_signal(L, s, "property::workarea", 0); } return luaA_pushstrut(L, window->strut); }
/** Remove a tag from screen. Tag must be on a screen and have no clients. * \param tag The tag to remove. */ void tag_remove_from_screen(tag_t *tag) { if(!tag->screen) return; int screen_index = screen_array_indexof(&globalconf.screens, tag->screen); int phys_screen = screen_virttophys(screen_index); tag_array_t *tags = &tag->screen->tags; for(int i = 0; i < tags->len; i++) if(tags->tab[i] == tag) { tag_array_take(tags, i); break; } /* tag was selected? If so, reban */ if(tag->selected) banning_need_update(tag->screen); ewmh_update_net_numbers_of_desktop(phys_screen); ewmh_update_net_desktop_names(phys_screen); /* call hook */ if(globalconf.hooks.tags != LUA_REFNIL) { lua_pushnumber(globalconf.L, screen_index + 1); luaA_object_push(globalconf.L, tag); lua_pushliteral(globalconf.L, "remove"); luaA_dofunction_from_registry(globalconf.L, globalconf.hooks.tags, 3, 0); } screen_t *s = tag->screen; tag->screen = NULL; luaA_object_push(globalconf.L, tag); luaA_object_emit_signal(globalconf.L, -1, "property::screen", 0); screen_emit_signal(globalconf.L, s, "tag::detach", 1); luaA_object_unref(globalconf.L, tag); }
/** Append a tag to a screen. * \param L The Lua VM state. * \param udx The tag index on the stack. * \param s The screen. */ void tag_append_to_screen(lua_State *L, int udx, screen_t *s) { tag_t *tag = luaA_checkudata(globalconf.L, udx, &tag_class); /* can't attach a tag twice */ if(tag->screen) { lua_remove(L, udx); return; } int screen_index = screen_array_indexof(&globalconf.screens, s); int phys_screen = screen_virttophys(screen_index); tag->screen = s; tag_array_append(&s->tags, luaA_object_ref_class(globalconf.L, udx, &tag_class)); ewmh_update_net_numbers_of_desktop(phys_screen); ewmh_update_net_desktop_names(phys_screen); luaA_object_push(globalconf.L, tag); luaA_object_emit_signal(L, -1, "property::screen", 0); lua_pop(L, 1); /* call hook */ if(globalconf.hooks.tags != LUA_REFNIL) { lua_pushnumber(globalconf.L, screen_index + 1); luaA_object_push(globalconf.L, tag); lua_pushliteral(globalconf.L, "add"); luaA_dofunction_from_registry(globalconf.L, globalconf.hooks.tags, 3, 0); } luaA_object_push(globalconf.L, tag); screen_emit_signal(globalconf.L, s, "tag::attach", 1); }
/** Emit a button signal. * The top of the lua stack has to be the object on which to emit the event. * \param L The Lua VM state. * \param ev The event to handle. */ static void event_emit_button(lua_State *L, xcb_button_press_event_t *ev) { const char *name; switch(XCB_EVENT_RESPONSE_TYPE(ev)) { case XCB_BUTTON_PRESS: name = "button::press"; break; case XCB_BUTTON_RELEASE: name = "button::release"; break; default: fatal("Invalid event type"); } /* Push the event's info */ lua_pushinteger(L, ev->event_x); lua_pushinteger(L, ev->event_y); lua_pushinteger(L, ev->detail); luaA_pushmodifiers(L, ev->state); /* And emit the signal */ luaA_object_emit_signal(L, -5, name, 4); }
int luaA_object_emit_signal_simple(lua_State *L) { luaA_object_emit_signal(L, 1, luaL_checkstring(L, 2), lua_gettop(L) - 2); return 0; }
/** The configure event handler. * \param ev The event. */ static void event_handle_configurerequest(xcb_configure_request_event_t *ev) { client_t *c; if((c = client_getbywin(ev->window))) { area_t geometry = c->geometry; uint16_t bw = c->border_width; uint16_t tb_left = c->titlebar[CLIENT_TITLEBAR_LEFT].size; uint16_t tb_right = c->titlebar[CLIENT_TITLEBAR_RIGHT].size; uint16_t tb_top = c->titlebar[CLIENT_TITLEBAR_TOP].size; uint16_t tb_bottom = c->titlebar[CLIENT_TITLEBAR_BOTTOM].size; uint16_t deco_left = bw + tb_left; uint16_t deco_right = bw + tb_right; uint16_t deco_top = bw + tb_top; uint16_t deco_bottom = bw + tb_bottom; int16_t diff_w = 0, diff_h = 0, diff_border = 0; lua_State *L = globalconf_get_lua_State(); if(ev->value_mask & XCB_CONFIG_WINDOW_X) { int16_t diff = 0; geometry.x = ev->x; xwindow_translate_for_gravity(c->size_hints.win_gravity, deco_left, 0, deco_right, 0, &diff, NULL); geometry.x += diff; } if(ev->value_mask & XCB_CONFIG_WINDOW_Y) { int16_t diff = 0; geometry.y = ev->y; xwindow_translate_for_gravity(c->size_hints.win_gravity, 0, deco_top, 0, deco_bottom, NULL, &diff); geometry.y += diff; } if(ev->value_mask & XCB_CONFIG_WINDOW_WIDTH) { uint16_t old_w = geometry.width; geometry.width = ev->width; /* The ConfigureRequest specifies the size of the client window, we want the frame */ geometry.width += tb_left + tb_right; diff_w = geometry.width - old_w; } if(ev->value_mask & XCB_CONFIG_WINDOW_HEIGHT) { uint16_t old_h = geometry.height; geometry.height = ev->height; /* The ConfigureRequest specifies the size of the client window, we want the frame */ geometry.height += tb_top + tb_bottom; diff_h = geometry.height - old_h; } if(ev->value_mask & XCB_CONFIG_WINDOW_BORDER_WIDTH) { diff_border = ev->border_width - bw; diff_h += diff_border; diff_w += diff_border; luaA_object_push(L, c); window_set_border_width(L, -1, ev->border_width); lua_pop(L, 1); } /* If the client resizes without moving itself, apply window gravity */ if(c->size_hints.flags & XCB_ICCCM_SIZE_HINT_P_WIN_GRAVITY) { int16_t diff_x = 0, diff_y = 0; xwindow_translate_for_gravity(c->size_hints.win_gravity, diff_border, diff_border, diff_w, diff_h, &diff_x, &diff_y); if(!(ev->value_mask & XCB_CONFIG_WINDOW_X)) geometry.x += diff_x; if(!(ev->value_mask & XCB_CONFIG_WINDOW_Y)) geometry.y += diff_y; } c->got_configure_request = true; /* Request the changes to be applied */ luaA_object_push(L, c); lua_pushstring(L, "ewmh"); /* context */ lua_newtable(L); /* props */ /* area, it needs to be directly in the `hints` table to comply with the "protocol" */ lua_pushstring(L, "x"); lua_pushinteger(L, geometry.x); lua_rawset(L, -3); lua_pushstring(L, "y"); lua_pushinteger(L, geometry.y); lua_rawset(L, -3); lua_pushstring(L, "width"); lua_pushinteger(L, geometry.width); lua_rawset(L, -3); lua_pushstring(L, "height"); lua_pushinteger(L, geometry.height); lua_rawset(L, -3); luaA_object_emit_signal(L, -3, "request::geometry", 2); lua_pop(L, 1); } else if (xembed_getbywin(&globalconf.embedded, ev->window)) { /* Ignore this so that systray icons cannot resize themselves. * We decide their size! * However, Xembed says that we act like a WM to the embedded window and * thus we have to send a synthetic configure notify informing the * window that its configure request was denied. */ xcb_get_geometry_cookie_t geom_cookie = xcb_get_geometry_unchecked(globalconf.connection, ev->window); xcb_translate_coordinates_cookie_t coords_cookie = xcb_translate_coordinates_unchecked(globalconf.connection, ev->window, globalconf.screen->root, 0, 0); xcb_get_geometry_reply_t *geom = xcb_get_geometry_reply(globalconf.connection, geom_cookie, NULL); xcb_translate_coordinates_reply_t *coords = xcb_translate_coordinates_reply(globalconf.connection, coords_cookie, NULL); if (geom && coords) { xwindow_configure(ev->window, (area_t) { .x = coords->dst_x, .y = coords->dst_y, .width = geom->width, .height = geom->height }, 0);
/** The property notify event handler handling xproperties. * \param ev The event. */ static void property_handle_propertynotify_xproperty(xcb_property_notify_event_t *ev) { xproperty_t *prop; xproperty_t lookup = { .atom = ev->atom }; buffer_t buf; void *obj; prop = xproperty_array_lookup(&globalconf.xproperties, &lookup); if(!prop) /* Property is not registered */ return; if (ev->window != globalconf.screen->root) { obj = client_getbywin(ev->window); if(!obj) obj = drawin_getbywin(ev->window); if(!obj) return; } else obj = NULL; /* Get us the name of the property */ buffer_inita(&buf, a_strlen(prop->name) + a_strlen("xproperty::") + 1); buffer_addf(&buf, "xproperty::%s", prop->name); /* And emit the right signal */ if (obj) { luaA_object_push(globalconf.L, obj); luaA_object_emit_signal(globalconf.L, -1, buf.s, 0); lua_pop(globalconf.L, 1); } else signal_object_emit(globalconf.L, &global_signals, buf.s, 0); buffer_wipe(&buf); } /** The property notify event handler. * \param ev The event. */ void property_handle_propertynotify(xcb_property_notify_event_t *ev) { int (*handler)(uint8_t state, xcb_window_t window) = NULL; globalconf.timestamp = ev->time; property_handle_propertynotify_xproperty(ev); /* Find the correct event handler */ #define HANDLE(atom_, cb) \ if (ev->atom == atom_) \ { \ handler = cb; \ } else #define END return /* Xembed stuff */ HANDLE(_XEMBED_INFO, property_handle_xembed_info) /* ICCCM stuff */ HANDLE(XCB_ATOM_WM_TRANSIENT_FOR, property_handle_wm_transient_for) HANDLE(WM_CLIENT_LEADER, property_handle_wm_client_leader) HANDLE(XCB_ATOM_WM_NORMAL_HINTS, property_handle_wm_normal_hints) HANDLE(XCB_ATOM_WM_HINTS, property_handle_wm_hints) HANDLE(XCB_ATOM_WM_NAME, property_handle_wm_name) HANDLE(XCB_ATOM_WM_ICON_NAME, property_handle_wm_icon_name) HANDLE(XCB_ATOM_WM_CLASS, property_handle_wm_class) HANDLE(WM_PROTOCOLS, property_handle_wm_protocols) HANDLE(XCB_ATOM_WM_CLIENT_MACHINE, property_handle_wm_client_machine) HANDLE(WM_WINDOW_ROLE, property_handle_wm_window_role) /* EWMH stuff */ HANDLE(_NET_WM_NAME, property_handle_net_wm_name) HANDLE(_NET_WM_ICON_NAME, property_handle_net_wm_icon_name) HANDLE(_NET_WM_STRUT_PARTIAL, property_handle_net_wm_strut_partial) HANDLE(_NET_WM_ICON, property_handle_net_wm_icon) HANDLE(_NET_WM_PID, property_handle_net_wm_pid) HANDLE(_NET_WM_WINDOW_OPACITY, property_handle_net_wm_opacity) /* background change */ HANDLE(_XROOTPMAP_ID, property_handle_xrootpmap_id) /* If nothing was found, return */ END; #undef HANDLE #undef END (*handler)(ev->state, ev->window); }