static int property_handle_net_wm_opacity(uint8_t state, xcb_window_t window) { drawin_t *drawin = drawin_getbywin(window); if(drawin) { luaA_object_push(globalconf.L, drawin); window_set_opacity(globalconf.L, -1, xwindow_get_opacity(drawin->window)); lua_pop(globalconf.L, -1); } else { client_t *c = client_getbywin(window); if(c) { luaA_object_push(globalconf.L, c); window_set_opacity(globalconf.L, -1, xwindow_get_opacity(c->window)); lua_pop(globalconf.L, 1); } } return 0; }
/** The expose event handler. * \param ev The event. */ static void event_handle_expose(xcb_expose_event_t *ev) { drawin_t *drawin; client_t *client; if((drawin = drawin_getbywin(ev->window))) drawin_refresh_pixmap_partial(drawin, ev->x, ev->y, ev->width, ev->height); if ((client = client_getbyframewin(ev->window))) client_refresh_partial(client, ev->x, ev->y, ev->width, ev->height); }
/** 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; } }
/** 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); } }
/** Get the client which is under the pointer. * \param L The Lua VM state. * \return The number of elements pushed on stack. * \luastack * \lreturn A client or nil. */ static int luaA_mouse_object_under_pointer(lua_State *L) { int16_t mouse_x, mouse_y; xcb_window_t child; if(!mouse_query_pointer_root(&mouse_x, &mouse_y, &child, NULL)) return 0; drawin_t *drawin; client_t *client; if((drawin = drawin_getbywin(child))) return luaA_object_push(L, drawin); if((client = client_getbyframewin(child))) return luaA_object_push(globalconf.L, client); return 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); }
/** The button press event handler. * \param ev The event. */ static void event_handle_button(xcb_button_press_event_t *ev) { lua_State *L = globalconf_get_lua_State(); client_t *c; drawin_t *drawin; globalconf.timestamp = ev->time; { /* ev->state contains the state before the event. Compute the state * after the event for the mousegrabber. */ uint16_t state = ev->state, change = 1 << (ev->detail - 1 + 8); if (XCB_EVENT_RESPONSE_TYPE(ev) == XCB_BUTTON_PRESS) state |= change; else state &= ~change; if(event_handle_mousegrabber(ev->root_x, ev->root_y, state)) return; } /* ev->state is * button status (8 bits) + modifiers status (8 bits) * we don't care for button status that we get, especially on release, so * drop them */ ev->state &= 0x00ff; if((drawin = drawin_getbywin(ev->event)) || (drawin = drawin_getbywin(ev->child))) { /* If the drawin is child, then x,y are * relative to root window */ if(drawin->window == ev->child) { ev->event_x -= drawin->geometry.x + drawin->border_width; ev->event_y -= drawin->geometry.y + drawin->border_width; } /* Push the drawable */ luaA_object_push(L, drawin); luaA_object_push_item(L, -1, drawin->drawable); /* and handle the button raw button event */ event_emit_button(L, ev); lua_pop(L, 1); /* check if any button object matches */ event_button_callback(ev, &drawin->buttons, L, -1, 1, NULL); /* Either we are receiving this due to ButtonPress/Release on the root * window or because we grabbed the button on the window. In the later * case we have to call AllowEvents. * Use AsyncPointer instead of ReplayPointer so that the event is * "eaten" instead of being handled again on the root window. */ if(ev->child == XCB_NONE) xcb_allow_events(globalconf.connection, XCB_ALLOW_ASYNC_POINTER, ev->time); } else if((c = client_getbyframewin(ev->event)) || (c = client_getbywin(ev->event))) { /* For clicks inside of c->window, we get two events. Once because of a * passive grab on c->window and then again for c->frame_window. * Ignore the second event (identifiable by ev->child != XCB_NONE). */ if (ev->event != c->frame_window || ev->child == XCB_NONE) { luaA_object_push(L, c); if (c->window == ev->event) { /* Button event into the client itself (not titlebar), translate * into the frame window. */ ev->event_x += c->titlebar[CLIENT_TITLEBAR_LEFT].size; ev->event_y += c->titlebar[CLIENT_TITLEBAR_TOP].size; } /* And handle the button raw button event */ event_emit_button(L, ev); /* then check if a titlebar was "hit" */ if (c->frame_window == ev->event) { int x = ev->event_x, y = ev->event_y; drawable_t *d = client_get_drawable_offset(c, &x, &y); if (d) { /* Copy the event so that we can fake x/y */ xcb_button_press_event_t event = *ev; event.event_x = x; event.event_y = y; luaA_object_push_item(L, -1, d); event_emit_button(L, &event); lua_pop(L, 1); } } /* then check if any button objects match */ event_button_callback(ev, &c->buttons, L, -1, 1, NULL); } xcb_allow_events(globalconf.connection, XCB_ALLOW_REPLAY_POINTER, ev->time); } else if(ev->child == XCB_NONE) if(globalconf.screen->root == ev->event) { event_button_callback(ev, &globalconf.buttons, L, 0, 0, NULL); return; } }