From e0aa3ed0349d5070e3ae710d43d077fcfc077728 Mon Sep 17 00:00:00 2001 From: Martin Duquesnoy Date: Mon, 23 Jan 2012 11:28:13 +0100 Subject: [PATCH] Prepare code for Systray --- src/event.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++++-- src/ewmh.c | 26 +++++++++++++++- src/ewmh.h | 43 ++++++++++++++++++++++++++ src/systray.c | 0 src/systray.h | 0 src/wmfs.h | 19 ++++++++++++ 6 files changed, 169 insertions(+), 4 deletions(-) create mode 100644 src/systray.c create mode 100644 src/systray.h diff --git a/src/event.c b/src/event.c index e20cd85..3a2fcfb 100644 --- a/src/event.c +++ b/src/event.c @@ -10,6 +10,7 @@ #include "client.h" #include "barwin.h" #include "screen.h" +#include "systray.h" #define EVDPY(e) (e)->xany.display @@ -53,6 +54,9 @@ event_enternotify(XEvent *e) && ev->window != W->root) return; + if(ev->window == W->systray.win /* || systray_find(ev->window) */) + return; + if((c = client_gb_win(ev->window)) || (c = client_gb_frame(ev->window))) { @@ -68,11 +72,32 @@ 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_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);*/ + + } + } + switch(type) { /* _NET_WM_STATE */ @@ -126,9 +151,16 @@ 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 @@ -145,14 +177,20 @@ 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) + || 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(); + }*/ } static void @@ -170,6 +208,7 @@ event_propertynotify(XEvent *e) { XPropertyEvent *ev = &e->xproperty; struct client *c; + struct _systray *s; if(ev->state == PropertyDelete) return; @@ -200,6 +239,11 @@ event_propertynotify(XEvent *e) break; } } + /*else if((s = systray_find(ev->window))) + { + systray_state(s); + systray_update(); + }*/ } static void @@ -207,9 +251,15 @@ event_unmapnotify(XEvent *e) { XUnmapEvent *ev = &e->xunmap; struct client *c; + struct systray *s; if((c = client_gb_win(ev->window)) && ev->send_event) client_remove(c); + /*else if((s = systray_find(ev->window))) + { + systray_del(s); + systray_update(s); + }*/ } static void @@ -241,6 +291,35 @@ event_expose(XEvent *e) } } +static void +event_mapnotify(XEvent *e) +{ + XMapEvent *ev = &e->xmap; + struct client *c; + struct _systray *s; + + if(ev->window != ev->event && !ev->send_event) + return; + + if((c = client_gb_win(ev->window))) + ewmh_set_wm_state(c->win, NormalState); + /*else if((s = systray_find(ev->window))) + { + ewmh_set_wm_state(s->win, NormalState); + ewmh_send_message(s->win, s->win, "_XEMBED", CurrentTime, XEMBED_WINDOW_ACTIVATE, 0, 0, 0); + }*/ +} + +static void +event_selectionclearevent(XEvent *ev) +{ + /* Getting selection if lost it */ +/* if(ev->xselectionclear.window == W->systray.win) + systray_acquire(); + + systray_update();*/ +} + static void event_dummy(XEvent *e) { @@ -264,12 +343,12 @@ event_init(void) event_handle[Expose] = event_expose; event_handle[FocusIn] = event_focusin; event_handle[KeyPress] = event_keypress; - /*event_handle[MapNotify] = event_mapnotify;*/ + event_handle[MapNotify] = event_mapnotify; event_handle[MapRequest] = event_maprequest; event_handle[MappingNotify] = event_mappingnotify; event_handle[PropertyNotify] = event_propertynotify; /*event_handle[ReparentNotify] = event_reparentnotify;*/ - /*event_handle[SelectionClear] = event_selectionclearevent;*/ + event_handle[SelectionClear] = event_selectionclearevent; event_handle[UnmapNotify] = event_unmapnotify; } diff --git a/src/ewmh.c b/src/ewmh.c index f2fd9f8..d4dfaa3 100644 --- a/src/ewmh.c +++ b/src/ewmh.c @@ -106,6 +106,31 @@ ewmh_set_wm_state(Window w, int state) W->net_atom[wm_state], 32, PropModeReplace, d, 2); } +/* + * Get xembed state + */ +long +ewmh_get_xembed_state(Window win) +{ + Atom rf; + int f; + long ret = 0; + unsigned long n, il; + unsigned char *data = NULL; + + if(XGetWindowProperty(W->dpy, win, W->net_atom[xembedinfo], 0L, 2, False, + W->net_atom[xembedinfo], &rf, &f, &n, &il, &data) != Success) + return 0; + + if(rf == W->net_atom[xembedinfo] && n == 2) + ret = (long)data[1]; + + if(n && data) + XFree(data); + + return ret; +} + void ewmh_update_wmfs_props(void) { @@ -118,7 +143,6 @@ ewmh_update_wmfs_props(void) cts = xcalloc(ns, sizeof(long)); - for(i = 0; i < ns; ++i) { s = screen_gb_id(i); diff --git a/src/ewmh.h b/src/ewmh.h index 61337ac..cb4dd80 100644 --- a/src/ewmh.h +++ b/src/ewmh.h @@ -11,6 +11,29 @@ #include #include "wmfs.h" +#include "util.h" + +/* EWMH/Xembed const from freedesktop */ +#define XEMBED_MAPPED (1 << 0) +#define XEMBED_EMBEDDED_NOTIFY 0 +#define XEMBED_WINDOW_ACTIVATE 1 +#define XEMBED_WINDOW_DEACTIVATE 2 +#define XEMBED_REQUEST_FOCUS 3 +#define XEMBED_FOCUS_IN 4 +#define XEMBED_FOCUS_OUT 5 +#define XEMBED_FOCUS_NEXT 6 +#define XEMBED_FOCUS_PREV 7 +/* 8-9 were used for XEMBED_GRAB_KEY/XEMBED_UNGRAB_KEY */ +#define XEMBED_MODALITY_ON 10 +#define XEMBED_MODALITY_OFF 11 +#define XEMBED_REGISTER_ACCELERATOR 12 +#define XEMBED_UNREGISTER_ACCELERATOR 13 +#define XEMBED_ACTIVATE_ACCELERATOR 14 + +/* Details for XEMBED_FOCUS_IN: */ +#define XEMBED_FOCUS_CURRENT0 +#define XEMBED_FOCUS_FIRST 1 +#define XEMBED_FOCUS_LAST2 /* Ewmh hints list */ enum @@ -72,8 +95,28 @@ enum net_last }; +static inline void +ewmh_send_message(Window d, Window w, char *atom, long d0, long d1, long d2, long d3, long d4) +{ + XClientMessageEvent e; + + e.type = ClientMessage; + e.message_type = ATOM(atom); + e.window = w; + e.format = 32; + e.data.l[0] = d0; + e.data.l[1] = d1; + e.data.l[2] = d2; + e.data.l[3] = d3; + e.data.l[4] = d4; + + XSendEvent(W->dpy, d, false, StructureNotifyMask, (XEvent*)&e); + XSync(W->dpy, False); +} + void ewmh_init(void); void ewmh_set_wm_state(Window w, int state); +long ewmh_get_xembed_state(Window win); void ewmh_update_wmfs_props(void); void ewmh_manage_state(long data[], struct client *c); void ewmh_manage_window_type(struct client *c); diff --git a/src/systray.c b/src/systray.c new file mode 100644 index 0000000..e69de29 diff --git a/src/systray.h b/src/systray.h new file mode 100644 index 0000000..e69de29 diff --git a/src/wmfs.h b/src/wmfs.h index 086e293..bab8373 100644 --- a/src/wmfs.h +++ b/src/wmfs.h @@ -275,6 +275,13 @@ struct rule SLIST_ENTRY(rule) next; }; +struct _systray +{ + struct geo geo; + Window win; + SLIST_ENTRY(_systray) next; +}; + #define MAX_PATH_LEN 8192 struct wmfs @@ -289,6 +296,8 @@ struct wmfs #define WMFS_SCAN 0x01 #define WMFS_RUNNING 0x02 #define WMFS_RELOAD 0x04 +#define WMFS_SYSTRAY 0x08 +#define WMFS_LOG 0x10 Flags flags; GC gc, rgc; Atom *net_atom; @@ -330,6 +339,16 @@ struct wmfs struct mbhead root; } tmp_head; + /* + * Because there is only one systray per display, + * set struct there + */ + struct + { + Window win; + SLIST_HEAD(, _systray) head; + } systray; + /* * Selected screen, client */