265 lines
8.1 KiB
C#
265 lines
8.1 KiB
C#
/***********************************************************************
|
|
*
|
|
* Copyright (C) 2005-2006 Novell, Inc. Inc. All Rights Reserved.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; version 2.1
|
|
* of the License.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, Novell, Inc.
|
|
*
|
|
* To contact Novell about this file by physical or electronic mail,
|
|
* you may find current contact information at www.novell.com.
|
|
*
|
|
***********************************************************************/
|
|
|
|
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
|
|
}
|
|
} |