1 // 2 // Copyright notice and author unknown. 3 // Source extracted from: http://www.mono-project.com/GtkSharpNotificationIcon 4 // 5 6 using System; 7 using System.Runtime.InteropServices; 8 using Gtk; 9 using Gdk; 10 11 namespace OpenVPN.Admin 12 { 13 public class TrayIcon : Plug 14 { 15 int selection_atom; 16 int system_tray_opcode_atom; 17 IntPtr manager_window; 18 TrayIcon(string name)19 public TrayIcon (string name) 20 { 21 AddEvents ((int)EventMask.PropertyChangeMask); 22 } 23 OnRealized()24 protected override void OnRealized () 25 { 26 base.OnRealized (); 27 Display display = Screen.Display; 28 IntPtr xdisplay = gdk_x11_display_get_xdisplay (display.Handle); 29 selection_atom = XInternAtom (xdisplay, "_NET_SYSTEM_TRAY_S" + Screen.Number.ToString (), false); 30 31 XInternAtom (xdisplay, "MANAGER", false); 32 system_tray_opcode_atom = XInternAtom (xdisplay, "_NET_SYSTEM_TRAY_OPCODE", false); 33 34 XInternAtom (xdisplay, "_NET_SYSTEM_TRAY_ORIENTATION", false); 35 UpdateManagerWindow (); 36 } 37 OnUnrealized()38 protected override void OnUnrealized () 39 { 40 if (manager_window != IntPtr.Zero) 41 Gdk.Window.LookupForDisplay (Display, (uint)manager_window); 42 43 base.OnUnrealized (); 44 } 45 UpdateManagerWindow()46 private void UpdateManagerWindow () 47 { 48 IntPtr xdisplay = gdk_x11_display_get_xdisplay (Display.Handle); 49 if (manager_window != IntPtr.Zero) 50 Gdk.Window.LookupForDisplay (Display, (uint)manager_window); 51 52 XGrabServer (xdisplay); 53 54 manager_window = XGetSelectionOwner (xdisplay, selection_atom); 55 if (manager_window != IntPtr.Zero) 56 XSelectInput (xdisplay, manager_window, EventMask.StructureNotifyMask | EventMask.PropertyChangeMask); 57 XUngrabServer (xdisplay); 58 XFlush (xdisplay); 59 60 if (manager_window != IntPtr.Zero) { 61 Gdk.Window.LookupForDisplay (Display, (uint)manager_window); 62 SendDockRequest (); 63 } 64 } 65 SendDockRequest()66 private void SendDockRequest () 67 { 68 SendManagerMessage (SystemTrayMessage.RequestDock, manager_window, Id, 0, 0); 69 } 70 SendManagerMessage(SystemTrayMessage message, IntPtr window, uint data1, uint data2, uint data3)71 private void SendManagerMessage (SystemTrayMessage message, IntPtr window, uint data1, uint data2, uint data3) 72 { 73 XClientMessageEvent ev = new XClientMessageEvent (); 74 IntPtr display; 75 76 ev.type = XEventName.ClientMessage; 77 ev.window = window; 78 ev.message_type = (IntPtr)system_tray_opcode_atom; 79 ev.format = 32; 80 ev.ptr1 = gdk_x11_get_server_time (GdkWindow.Handle); 81 ev.ptr2 = (IntPtr)message; 82 ev.ptr3 = (IntPtr)data1; 83 ev.ptr4 = (IntPtr)data2; 84 ev.ptr5 = (IntPtr)data3; 85 86 display = gdk_x11_display_get_xdisplay (Display.Handle); 87 gdk_error_trap_push (); 88 XSendEvent (display, manager_window, false, EventMask.NoEventMask, ref ev); 89 gdk_error_trap_pop (); 90 } 91 92 [DllImport ("gdk-x11-2.0.so.0")] gdk_x11_display_get_xdisplay(IntPtr display)93 static extern IntPtr gdk_x11_display_get_xdisplay (IntPtr display); 94 [DllImport ("gdk-x11-2.0.so.0")] gdk_x11_get_server_time(IntPtr window)95 static extern IntPtr gdk_x11_get_server_time (IntPtr window); 96 [DllImport ("gdk-x11-2.0.so.0")] gdk_error_trap_push()97 static extern void gdk_error_trap_push (); 98 [DllImport ("gdk-x11-2.0.so.0")] gdk_error_trap_pop()99 static extern void gdk_error_trap_pop (); 100 101 [DllImport ("libX11", EntryPoint="XInternAtom")] XInternAtom(IntPtr display, string atom_name, bool only_if_exists)102 extern static int XInternAtom(IntPtr display, string atom_name, bool only_if_exists); 103 [DllImport ("libX11")] XGrabServer(IntPtr display)104 extern static void XGrabServer (IntPtr display); 105 [DllImport ("libX11")] XUngrabServer(IntPtr display)106 extern static void XUngrabServer (IntPtr display); 107 [DllImport ("libX11")] XFlush(IntPtr display)108 extern static int XFlush (IntPtr display); 109 [DllImport ("libX11")] XGetSelectionOwner(IntPtr display, int atom)110 extern static IntPtr XGetSelectionOwner (IntPtr display, int atom); 111 [DllImport ("libX11")] XSelectInput(IntPtr window, IntPtr display, EventMask mask)112 extern static IntPtr XSelectInput (IntPtr window, IntPtr display, EventMask mask); 113 [DllImport ("libX11", EntryPoint="XSendEvent")] XSendEvent(IntPtr display, IntPtr window, bool propagate, EventMask event_mask, ref XClientMessageEvent send_event)114 extern static int XSendEvent(IntPtr display, IntPtr window, bool propagate, EventMask event_mask, ref XClientMessageEvent send_event); 115 } 116 117 [Flags] 118 internal enum EventMask 119 { 120 NoEventMask = 0, 121 KeyPressMask = 1<<0, 122 KeyReleaseMask = 1<<1, 123 ButtonPressMask = 1<<2, 124 ButtonReleaseMask = 1<<3, 125 EnterWindowMask = 1<<4, 126 LeaveWindowMask = 1<<5, 127 PointerMotionMask = 1<<6, 128 PointerMotionHintMask = 1<<7, 129 Button1MotionMask = 1<<8, 130 Button2MotionMask = 1<<9, 131 Button3MotionMask = 1<<10, 132 Button4MotionMask = 1<<11, 133 Button5MotionMask = 1<<12, 134 ButtonMotionMask = 1<<13, 135 KeymapStateMask = 1<<14, 136 ExposureMask = 1<<15, 137 VisibilityChangeMask = 1<<16, 138 StructureNotifyMask = 1<<17, 139 ResizeRedirectMask = 1<<18, 140 SubstructureNotifyMask = 1<<19, 141 SubstructureRedirectMask= 1<<20, 142 FocusChangeMask = 1<<21, 143 PropertyChangeMask = 1<<22, 144 ColormapChangeMask = 1<<23, 145 OwnerGrabButtonMask = 1<<24 146 } 147 148 internal enum SystemTrayMessage 149 { 150 RequestDock, 151 BeginMessage, 152 CancelMessage 153 } 154 155 internal enum SystemTrayOrientation 156 { 157 Horz, 158 Vert 159 } 160 161 [StructLayout(LayoutKind.Sequential)] 162 internal struct XClientMessageEvent 163 { 164 internal XEventName type; 165 internal IntPtr serial; 166 internal bool send_event; 167 internal IntPtr display; 168 internal IntPtr window; 169 internal IntPtr message_type; 170 internal int format; 171 internal IntPtr ptr1; 172 internal IntPtr ptr2; 173 internal IntPtr ptr3; 174 internal IntPtr ptr4; 175 internal IntPtr ptr5; 176 } 177 178 internal enum XEventName 179 { 180 KeyPress = 2, 181 KeyRelease = 3, 182 ButtonPress = 4, 183 ButtonRelease = 5, 184 MotionNotify = 6, 185 EnterNotify = 7, 186 LeaveNotify = 8, 187 FocusIn = 9, 188 FocusOut = 10, 189 KeymapNotify = 11, 190 Expose = 12, 191 GraphicsExpose = 13, 192 NoExpose = 14, 193 VisibilityNotify = 15, 194 CreateNotify = 16, 195 DestroyNotify = 17, 196 UnmapNotify = 18, 197 MapNotify = 19, 198 MapRequest = 20, 199 ReparentNotify = 21, 200 ConfigureNotify = 22, 201 ConfigureRequest = 23, 202 GravityNotify = 24, 203 ResizeRequest = 25, 204 CirculateNotify = 26, 205 CirculateRequest = 27, 206 PropertyNotify = 28, 207 SelectionClear = 29, 208 SelectionRequest = 30, 209 SelectionNotify = 31, 210 ColormapNotify = 32, 211 ClientMessage = 33, 212 MappingNotify = 34, 213 TimerNotify = 100, 214 215 LASTEvent 216 } 217 }