CASA/c_gui/TrayLib.cs
2005-10-12 15:27:21 +00:00

243 lines
7.1 KiB
C#

using System;
using System.Runtime.InteropServices;
using Gtk;
using Gdk;
namespace Egg
{
public class TrayIcon : Plug
{
int stamp;
Orientation orientation;
int selection_atom;
int manager_atom;
int system_tray_opcode_atom;
int orientation_atom;
IntPtr manager_window;
FilterFunc filter;
public TrayIcon (string name)
{
Title = name;
stamp = 1;
orientation = Orientation.Horizontal;
AddEvents ((int)EventMask.PropertyChangeMask);
filter = new FilterFunc (ManagerFilter);
}
protected override void OnRealized ()
{
base.OnRealized ();
Display display = Screen.Display;
IntPtr xdisplay = gdk_x11_display_get_xdisplay (display.Handle);
selection_atom = XInternAtom (xdisplay, "_NET_SYSTEM_TRAY_S" + Screen.Number.ToString (), false);
manager_atom = XInternAtom (xdisplay, "MANAGER", false);
system_tray_opcode_atom = XInternAtom (xdisplay, "_NET_SYSTEM_TRAY_OPCODE", false);
orientation_atom = XInternAtom (xdisplay, "_NET_SYSTEM_TRAY_ORIENTATION", false);
UpdateManagerWindow ();
//Screen.RootWindow.AddFilter (filter);
}
protected override void OnUnrealized ()
{
if (manager_window != IntPtr.Zero)
{
Gdk.Window gdkwin = Gdk.Window.LookupForDisplay (Display, (uint)manager_window);
//gdkwin.RemoveFilter (filter);
}
//Screen.RootWindow.RemoveFilter (filter);
base.OnUnrealized ();
}
private void UpdateManagerWindow ()
{
IntPtr xdisplay = gdk_x11_display_get_xdisplay (Display.Handle);
if (manager_window != IntPtr.Zero)
{
Gdk.Window gdkwin = Gdk.Window.LookupForDisplay (Display, (uint)manager_window);
//gdkwin.RemoveFilter (filter);
}
XGrabServer (xdisplay);
manager_window = XGetSelectionOwner (xdisplay, selection_atom);
if (manager_window != IntPtr.Zero)
XSelectInput (xdisplay, manager_window, EventMask.StructureNotifyMask | EventMask.PropertyChangeMask);
XUngrabServer (xdisplay);
XFlush (xdisplay);
if (manager_window != IntPtr.Zero)
{
Gdk.Window gdkwin = Gdk.Window.LookupForDisplay (Display, (uint)manager_window);
//gdkwin.AddFilter (filter);
SendDockRequest ();
GetOrientationProperty ();
}
}
private void SendDockRequest ()
{
SendManagerMessage (SystemTrayMessage.RequestDock, manager_window, Id, 0, 0);
}
private void SendManagerMessage (SystemTrayMessage message, IntPtr window, uint data1, uint data2, uint data3)
{
XClientMessageEvent ev = new XClientMessageEvent ();
IntPtr display;
ev.type = XEventName.ClientMessage;
ev.window = window;
ev.message_type = (IntPtr)system_tray_opcode_atom;
ev.format = 32;
ev.ptr1 = gdk_x11_get_server_time (GdkWindow.Handle);
ev.ptr2 = (IntPtr)message;
ev.ptr3 = (IntPtr)data1;
ev.ptr4 = (IntPtr)data2;
ev.ptr5 = (IntPtr)data3;
display = gdk_x11_display_get_xdisplay (Display.Handle);
gdk_error_trap_push ();
XSendEvent (display, manager_window, false, EventMask.NoEventMask, ref ev);
gdk_error_trap_pop ();
}
private FilterReturn ManagerFilter (IntPtr xevent, Event evnt)
{
//TODO: Implement;
return FilterReturn.Continue;
}
private void GetOrientationProperty ()
{
//TODO: Implement;
}
[DllImport ("gdk-x11-2.0")]
static extern IntPtr gdk_x11_display_get_xdisplay (IntPtr display);
[DllImport ("gdk-x11-2.0")]
static extern IntPtr gdk_x11_get_server_time (IntPtr window);
[DllImport ("gdk-x11-2.0")]
static extern void gdk_error_trap_push ();
[DllImport ("gdk-x11-2.0")]
static extern void gdk_error_trap_pop ();
[DllImport ("libX11", EntryPoint="XInternAtom")]
extern static int XInternAtom(IntPtr display, string atom_name, bool only_if_exists);
[DllImport ("libX11")]
extern static void XGrabServer (IntPtr display);
[DllImport ("libX11")]
extern static void XUngrabServer (IntPtr display);
[DllImport ("libX11")]
extern static int XFlush (IntPtr display);
[DllImport ("libX11")]
extern static IntPtr XGetSelectionOwner (IntPtr display, int atom);
[DllImport ("libX11")]
extern static IntPtr XSelectInput (IntPtr window, IntPtr display, EventMask mask);
[DllImport ("libX11", EntryPoint="XSendEvent")]
extern static int XSendEvent(IntPtr display, IntPtr window, bool propagate, EventMask event_mask, ref XClientMessageEvent send_event);
}
[Flags]
internal enum EventMask
{
NoEventMask = 0,
KeyPressMask = 1<<0,
KeyReleaseMask = 1<<1,
ButtonPressMask = 1<<2,
ButtonReleaseMask = 1<<3,
EnterWindowMask = 1<<4,
LeaveWindowMask = 1<<5,
PointerMotionMask = 1<<6,
PointerMotionHintMask = 1<<7,
Button1MotionMask = 1<<8,
Button2MotionMask = 1<<9,
Button3MotionMask = 1<<10,
Button4MotionMask = 1<<11,
Button5MotionMask = 1<<12,
ButtonMotionMask = 1<<13,
KeymapStateMask = 1<<14,
ExposureMask = 1<<15,
VisibilityChangeMask = 1<<16,
StructureNotifyMask = 1<<17,
ResizeRedirectMask = 1<<18,
SubstructureNotifyMask = 1<<19,
SubstructureRedirectMask= 1<<20,
FocusChangeMask = 1<<21,
PropertyChangeMask = 1<<22,
ColormapChangeMask = 1<<23,
OwnerGrabButtonMask = 1<<24
}
internal enum SystemTrayMessage
{
RequestDock,
BeginMessage,
CancelMessage
}
internal enum SystemTrayOrientation
{
Horz,
Vert
}
[StructLayout(LayoutKind.Sequential)]
internal struct XClientMessageEvent
{
internal XEventName type;
internal IntPtr serial;
internal bool send_event;
internal IntPtr display;
internal IntPtr window;
internal IntPtr message_type;
internal int format;
internal IntPtr ptr1;
internal IntPtr ptr2;
internal IntPtr ptr3;
internal IntPtr ptr4;
internal IntPtr ptr5;
}
internal enum XEventName
{
KeyPress = 2,
KeyRelease = 3,
ButtonPress = 4,
ButtonRelease = 5,
MotionNotify = 6,
EnterNotify = 7,
LeaveNotify = 8,
FocusIn = 9,
FocusOut = 10,
KeymapNotify = 11,
Expose = 12,
GraphicsExpose = 13,
NoExpose = 14,
VisibilityNotify = 15,
CreateNotify = 16,
DestroyNotify = 17,
UnmapNotify = 18,
MapNotify = 19,
MapRequest = 20,
ReparentNotify = 21,
ConfigureNotify = 22,
ConfigureRequest = 23,
GravityNotify = 24,
ResizeRequest = 25,
CirculateNotify = 26,
CirculateRequest = 27,
PropertyNotify = 28,
SelectionClear = 29,
SelectionRequest = 30,
SelectionNotify = 31,
ColormapNotify = 32,
ClientMessage = 33,
MappingNotify = 34,
TimerNotify = 100,
LASTEvent
}
}