static void event_unmapnotify(XEvent *e) { XUnmapEvent *ev = &e->xunmap; struct client *c; struct _systray *s; if((c = client_gb_win(ev->window)) && ev->send_event && ev->event == W->root) { int d; unsigned char *ret = NULL; if(XGetWindowProperty(EVDPY(e), c->win, W->net_atom[wm_state], 0, 2, False, W->net_atom[wm_state], (Atom*)&d, &d, (long unsigned int*)&d, (long unsigned int*)&d, &ret) == Success) if(*ret == NormalState) client_remove(c); } else if((s = systray_find(ev->window))) { systray_del(s); systray_update(); } }
/** Update the systray * \param L The Lua VM state. * \return The number of elements pushed on stack. * \luastack * \lparam The drawin to display the systray in. * \lparam x X position for the systray. * \lparam y Y position for the systray. * \lparam base_size The size (width and height) each systray item gets. * \lparam horiz If true, the systray is horizontal, else vertical. * \lparam bg Color of the systray background. * \lparam revers If true, the systray icon order will be reversed, else default. * \lparam spacing The size of the spacing between icons. */ int luaA_systray(lua_State *L) { systray_register(); if(lua_gettop(L) != 0) { size_t bg_len; drawin_t *w = luaA_checkudata(L, 1, &drawin_class); int x = luaL_checkinteger(L, 2); int y = luaL_checkinteger(L, 3); int base_size = luaL_checkinteger(L, 4); bool horiz = lua_toboolean(L, 5); const char *bg = luaL_checklstring(L, 6, &bg_len); bool revers = lua_toboolean(L, 7); int spacing = luaL_checkinteger(L, 8); color_t bg_color; if(color_init_reply(color_init_unchecked(&bg_color, bg, bg_len))) { uint32_t config_back[] = { bg_color.pixel }; xcb_change_window_attributes(globalconf.connection, globalconf.systray.window, XCB_CW_BACK_PIXEL, config_back); } if(globalconf.systray.parent != w) xcb_reparent_window(globalconf.connection, globalconf.systray.window, w->window, x, y); else { uint32_t config_vals[2] = { x, y }; xcb_configure_window(globalconf.connection, globalconf.systray.window, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, config_vals); } globalconf.systray.parent = w; if(globalconf.embedded.len != 0) { systray_update(base_size, horiz, revers, spacing); xcb_map_window(globalconf.connection, globalconf.systray.window); } else xcb_unmap_window(globalconf.connection, globalconf.systray.window); } lua_pushinteger(L, globalconf.embedded.len); luaA_object_push(L, globalconf.systray.parent); return 2; }
static void event_selectionclearevent(XEvent *ev) { /* Getting selection if lost it */ if(ev->xselectionclear.window == W->systray.win) systray_acquire(); systray_update(); }
/** SelectionClearEvent handle event * \param ev XSelectionClearEvent pointer */ static void selectionclearevent(XSelectionClearEvent *ev) { /* Getting selection if lost it */ if(ev->window == traywin) systray_acquire(); systray_update(); return; }
/** PropertyNotify handle event * \param ev XPropertyEvent pointer */ static void propertynotify(XPropertyEvent *ev) { Client *c; Systray *s; Window trans; XWMHints *h; if(ev->state == PropertyDelete) return; if((s = systray_find(ev->window))) { systray_state(s); systray_update(); } if((c = client_gb_win(ev->window))) { switch(ev->atom) { case XA_WM_TRANSIENT_FOR: XGetTransientForHint(dpy, c->win, &trans); if((c->flags & TileFlag || c->flags & MaxFlag)) if(((c->flags & HintFlag && (client_gb_win(trans) != NULL))) || (!(c->flags & HintFlag && (client_gb_win(trans) != NULL)))) arrange(c->screen, True); break; case XA_WM_NORMAL_HINTS: client_size_hints(c); break; case XA_WM_HINTS: if((h = XGetWMHints(dpy, c->win)) && (h->flags & XUrgencyHint) && c != sel) { client_urgent(c, True); XFree(h); } break; case XA_WM_NAME: client_get_name(c); break; default: if(ev->atom == net_atom[net_wm_name]) client_get_name(c); break; } } return; }
static void event_destroynotify(XEvent *e) { XDestroyWindowEvent *ev = &e->xdestroywindow; struct client *c; struct _systray *s; if((c = client_gb_win(ev->window))) client_remove(c); else if((s = systray_find(ev->window))) { ewmh_set_wm_state(s->win, WithdrawnState); systray_del(s); systray_update(); } }
static void event_propertynotify(XEvent *e) { XPropertyEvent *ev = &e->xproperty; XWMHints *h; struct client *c; struct _systray *s; if(ev->state == PropertyDelete) return; if((c = client_gb_win(ev->window))) { switch(ev->atom) { case XA_WM_TRANSIENT_FOR: break; case XA_WM_NORMAL_HINTS: client_get_sizeh(c); break; case XA_WM_HINTS: if((h = XGetWMHints(EVDPY(e), c->win)) && (h->flags & XUrgencyHint) && c->tag != W->screen->seltag) { c->tag->flags |= TAG_URGENT; infobar_elem_screen_update(c->screen, ElemTag); XFree(h); } break; default: if(ev->atom == XA_WM_NAME || ev->atom == W->net_atom[net_wm_name]) client_get_name(c); break; } } else if((s = systray_find(ev->window))) { systray_state(s); systray_update(); } }
/** MapRequest handle event * \param ev XMapRequestEvent pointer */ static void maprequest(XMapRequestEvent *ev) { XWindowAttributes at; Systray *s; CHECK(XGetWindowAttributes(dpy, ev->window, &at)); CHECK(!at.override_redirect); if((s = systray_find(ev->window))) { ewmh_send_message(s->win, s->win, "_XEMBED", CurrentTime, XEMBED_WINDOW_ACTIVATE, 0, 0, 0); systray_update(); } else if(!client_gb_win(ev->window)) client_manage(ev->window, &at, True); return; }
/** DestroyNotify handle event * \param ev XDestroyWindowEvent pointer */ static void destroynotify(XDestroyWindowEvent *ev) { Client *c; Systray *s; if((c = client_gb_win(ev->window))) { client_unmanage(c); XSetErrorHandler(errorhandler); } else if((s = systray_find(ev->window))) { setwinstate(s->win, WithdrawnState); systray_del(s); systray_update(); } return; }
static void event_maprequest(XEvent *e) { XMapRequestEvent *ev = &e->xmaprequest; XWindowAttributes at; struct _systray *s; /* Which windows to manage */ if(!XGetWindowAttributes(EVDPY(e), ev->window, &at) || at.override_redirect) return; if(!client_gb_win(ev->window)) client_new(ev->window, &at, false); else if((s = systray_find(ev->window))) { ewmh_send_message(s->win, s->win, "_XEMBED", CurrentTime, XEMBED_WINDOW_ACTIVATE, 0, 0, 0); systray_update(); } }
/** UnmapNotify handle event * \param ev XUnmapEvent pointer */ static void unmapnotify(XUnmapEvent *ev) { Client *c; Systray *s; if((c = client_gb_win(ev->window)) && ev->send_event && !(c->flags & HideFlag)) { client_unmanage(c); XSetErrorHandler(errorhandler); } if((s = systray_find(ev->window))) { systray_del(s); systray_update(); } return; }
static void event_clientmessageevent(XEvent *e) { XClientMessageEvent *ev = &e->xclient; struct client *c; struct _systray *sy; int type = 0; while(type < net_last && W->net_atom[type] != ev->message_type) ++type; /* * Systray message * _NET_WM_SYSTRAY_TRAY_OPCODE */ if(ev->window == W->systray.win && type == net_system_tray_opcode) { if(ev->data.l[1] == XEMBED_EMBEDDED_NOTIFY) { systray_add(ev->data.l[2]); systray_update(); } else if(ev->data.l[1] == XEMBED_REQUEST_FOCUS) { if((sy = systray_find(ev->data.l[2]))) ewmh_send_message(sy->win, sy->win, "_XEMBED", XEMBED_FOCUS_IN, XEMBED_FOCUS_CURRENT, 0, 0, 0); } } else if(ev->window == W->root) { /* WMFS message */ if(ev->data.l[4]) { /* Manage _WMFS_FUNCTION && _WMFS_CMD */ if(type == wmfs_function || type == wmfs_cmd) { int d; long unsigned int len; unsigned char *ret = NULL, *ret_cmd = NULL; void (*func)(Uicb); if(XGetWindowProperty(EVDPY(e), W->root, W->net_atom[wmfs_function], 0, 65536, False, W->net_atom[utf8_string], (Atom*)&d, &d, (long unsigned int*)&d, (long unsigned int*)&d, &ret) == Success && ret && ((func = uicb_name_func((char*)ret)))) { if(XGetWindowProperty(EVDPY(e), W->root, W->net_atom[wmfs_cmd], 0, 65536, False, W->net_atom[utf8_string], (Atom*)&d, &d, &len, (long unsigned int*)&d, &ret_cmd) == Success && len && ret_cmd) { func((Uicb)ret_cmd); XFree(ret_cmd); } else func(NULL); XFree(ret); } } } if(type == net_active_window) if((sy = systray_find(ev->data.l[0]))) XSetInputFocus(W->dpy, sy->win, RevertToNone, CurrentTime); } switch(type) { /* _NET_WM_STATE */ case net_wm_state: if((c = client_gb_win(ev->window))) ewmh_manage_state(ev->data.l, c); break; /* _NET_CLOSE_WINDOW */ case net_close_window: if((c = client_gb_win(ev->window))) client_close(c); break; /* _NET_WM_DESKTOP */ case net_wm_desktop: break; } }
/* ClientMessage handle event *\param ev XClientMessageEvent pointer */ static void clientmessageevent(XClientMessageEvent *ev) { Client *c; Systray *sy; int s, i, mess_t = 0; Atom rt; int rf; ulong ir, il; uchar *ret = NULL; uchar *ret_cmd = NULL; void (*func)(uicb_t); if(ev->format != 32) return; s = screen_count(); for(i = 0; i < net_last + s; ++i) if(net_atom[i] == ev->message_type) mess_t = i; if(ev->window == ROOT) { /* Manage _NET_CURRENT_DESKTOP */ if(mess_t == net_current_desktop && ev->data.l[0] >= 0 && ev->data.l[0] < conf.ntag[selscreen]) tag_set((int)(ev->data.l[0] + 1)); /* Manage _WMFS_SET_SCREEN */ if(mess_t == wmfs_set_screen && ev->data.l[0] >= 0 && ev->data.l[0] <= s) screen_set_sel((int)(ev->data.l[0])); /* Manage _NET_ACTIVE_WINDOW */ else if(mess_t == net_active_window) { if((c = client_gb_win(ev->window))) client_focus(c); else if((sy = systray_find(ev->data.l[0]))) XSetInputFocus(dpy, sy->win, RevertToNone, CurrentTime); } } else if(ev->window == traywin) { /* Manage _NET_WM_SYSTEM_TRAY_OPCODE */ if(mess_t == net_wm_system_tray_opcode) { if(ev->data.l[1] == XEMBED_EMBEDDED_NOTIFY) { systray_add(ev->data.l[2]); systray_update(); } else if(ev->data.l[1] == XEMBED_REQUEST_FOCUS) if((sy = systray_find(ev->data.l[2]))) ewmh_send_message(sy->win, sy->win, "_XEMBED", XEMBED_FOCUS_IN, XEMBED_FOCUS_CURRENT, 0, 0, 0); } } /* Manage _NET_WM_STATE */ if(mess_t == net_wm_state) if((c = client_gb_win(ev->window))) ewmh_manage_net_wm_state(ev->data.l, c); /* Manage _NET_CLOSE_WINDOW */ if(mess_t == net_close_window) if((c = client_gb_win(ev->window))) client_kill(c); /* Manage _NET_WM_DESKTOP */ if(mess_t == net_wm_desktop) if((c = client_gb_win(ev->window)) && ev->data.l[0] != (long)0xFFFFFFFF) tag_transfert(c, ev->data.l[0]); /* Manage _WMFS_STATUSTEXT_x */ if(mess_t >= wmfs_statustext && ev->data.l[4] == True) { if(XGetWindowProperty(dpy, ROOT, net_atom[mess_t], 0, 4096, False, net_atom[utf8_string], &rt, &rf, &ir, &il, &ret) == Success) { statustext_handle(mess_t - wmfs_statustext, (char*)ret); XFree(ret); } } /* Manage _WMFS_FUNCTION && _WMFS_CMD */ if((mess_t == wmfs_function && ev->data.l[4] == True) || (mess_t == wmfs_cmd && ev->data.l[4] == True)) { XGetWindowProperty(dpy, ROOT, net_atom[wmfs_function], 0, 4096, False, net_atom[utf8_string], &rt, &rf, &ir, &il, &ret); XGetWindowProperty(dpy, ROOT, net_atom[wmfs_cmd], 0, 4096, False, net_atom[utf8_string], &rt, &rf, &ir, &il, &ret_cmd); if((func = name_to_func((char*)ret, func_list))) func((uicb_t)ret_cmd); XFree(ret_cmd); XFree(ret); } /* Manage _WMFS_UPDATE_HINTS */ if(mess_t == wmfs_update_hints) { ewmh_get_number_of_desktop(); ewmh_update_current_tag_prop(); ewmh_get_client_list(); ewmh_get_desktop_names(); ewmh_set_desktop_geometry(); screen_count(); screen_get_sel(); } if(mess_t == wmfs_update_status && estatus) spawn(conf.status_path); return; }