Browse Source

Prepare code for Systray

Martin Duquesnoy 12 years ago
parent
commit
e0aa3ed034
6 changed files with 169 additions and 4 deletions
  1. 82 3
      src/event.c
  2. 25 1
      src/ewmh.c
  3. 43 0
      src/ewmh.h
  4. 0 0
      src/systray.c
  5. 0 0
      src/systray.h
  6. 19 0
      src/wmfs.h

+ 82 - 3
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;
 }
 

+ 25 - 1
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);

+ 43 - 0
src/ewmh.h

@@ -11,6 +11,29 @@
 #include <X11/Xutil.h>
 
 #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);

+ 0 - 0
src/systray.c


+ 0 - 0
src/systray.h


+ 19 - 0
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
       */