1 #include "net.h"
2 #include "docker.h"
3 #include "icons.h"
4 #include <assert.h>
5 
6 Atom net_opcode_atom;
7 Window net_sel_win;
8 
9 static Atom net_sel_atom;
10 static Atom net_manager_atom;
11 static Atom net_message_data_atom;
12 
13 /* defined in the systray spec */
14 #define SYSTEM_TRAY_REQUEST_DOCK    0
15 #define SYSTEM_TRAY_BEGIN_MESSAGE   1
16 #define SYSTEM_TRAY_CANCEL_MESSAGE  2
17 
net_create_selection_window()18 static void net_create_selection_window()
19 {
20   net_sel_win = XCreateSimpleWindow(display, root, -1, -1, 1, 1, 0, 0, 0);
21   assert(net_sel_win);
22 }
23 
24 
net_destroy_selection_window()25 static void net_destroy_selection_window()
26 {
27   XDestroyWindow(display, net_sel_win);
28   net_sel_win = None;
29 }
30 
31 
net_init()32 void net_init()
33 {
34   char *name;
35   XEvent m;
36 
37   name = g_strdup_printf("_NET_SYSTEM_TRAY_S%d", DefaultScreen(display));
38   net_sel_atom = XInternAtom(display, name, False);
39   assert(net_sel_atom);
40   net_opcode_atom = XInternAtom(display, "_NET_SYSTEM_TRAY_OPCODE", False);
41   assert(net_opcode_atom);
42   net_manager_atom = XInternAtom(display, "MANAGER", False);
43   assert(net_manager_atom);
44   net_message_data_atom = XInternAtom(display, "_NET_SYSTEM_TRAY_MESSAGE_DATA",
45                                       False);
46    assert(net_message_data_atom);
47 
48   net_create_selection_window();
49 
50   XSetSelectionOwner(display, net_sel_atom, net_sel_win, CurrentTime);
51   if (XGetSelectionOwner(display, net_sel_atom) != net_sel_win)
52     return; /* we don't get the selection */
53 
54   m.type = ClientMessage;
55   m.xclient.message_type = net_manager_atom;
56   m.xclient.format = 32;
57   m.xclient.data.l[0] = CurrentTime;
58   m.xclient.data.l[1] = net_sel_atom;
59   m.xclient.data.l[2] = net_sel_win;
60   m.xclient.data.l[3] = 0;
61   m.xclient.data.l[4] = 0;
62   XSendEvent(display, root, False, StructureNotifyMask, &m);
63 }
64 
65 
net_destroy()66 void net_destroy()
67 {
68   net_destroy_selection_window();
69 }
70 
71 
net_message(XClientMessageEvent * e)72 void net_message(XClientMessageEvent *e)
73 {
74   unsigned long opcode;
75   Window id;
76 
77   assert(e);
78 
79   opcode = e->data.l[1];
80 
81   switch (opcode)
82   {
83   case SYSTEM_TRAY_REQUEST_DOCK: /* dock a new icon */
84     id = e->data.l[2];
85     if (id && icon_add(id, NET))
86       XSelectInput(display, id, StructureNotifyMask);
87     break;
88 
89   case SYSTEM_TRAY_BEGIN_MESSAGE:
90     g_printerr("Message From Dockapp\n");
91     id = e->window;
92     break;
93 
94   case SYSTEM_TRAY_CANCEL_MESSAGE:
95     g_printerr("Message Cancelled\n");
96     id = e->window;
97     break;
98 
99   default:
100     if (opcode == net_message_data_atom) {
101       g_printerr("Text For Message From Dockapp:\n%s\n", e->data.b);
102       id = e->window;
103       break;
104     }
105 
106     /* unknown message type. not in the spec. */
107     g_printerr("Warning: Received unknown client message to System Tray "
108                "selection window.\n");
109     break;
110   }
111 }
112 
113 
net_icon_remove(TrayWindow * traywin)114 void net_icon_remove(TrayWindow *traywin)
115 {
116   assert(traywin);
117 
118   XSelectInput(display, traywin->id, NoEventMask);
119 }
120