~ubuntu-branches/ubuntu/jaunty/beagle/jaunty-security

« back to all changes in this revision

Viewing changes to search/Beagle.Search.Tray/NotificationArea.cs

  • Committer: Bazaar Package Importer
  • Author(s): Stefan Ebner
  • Date: 2008-05-04 00:31:32 UTC
  • mfrom: (1.1.21 upstream)
  • Revision ID: james.westby@ubuntu.com-20080504003132-2tkm5o8moo5952ri
Tags: 0.3.7-2ubuntu1
 * Merge from Debian unstable. (LP: #225746) Remaining Ubuntu changes:
  - debian/control:
    + Rename ice{weasel,dove}-beagle to {mozilla,thunderbird}-beagle and
      and update the dependencies accordingly.
    + Change Maintainer to Ubuntu Mono Team.
  - debian/rules:
    + Install the mozilla-beagle and thunderbird-beagle extensions.
  - ice{dove,weasel}.dirs:
    + Renamed to {mozilla,thunderbird}-beagle.dirs.
    + Fixed paths to point to usr/lib/{firefox,thunderbird}

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//
 
2
//  NotificationAreaIcon.cs
 
3
// 
 
4
//  Copyright (C) 2005 Todd Berman <tberman@off.net>
 
5
//  Copyright (C) 2005 Ed Catmur <ed@catmur.co.uk>
 
6
//  Copyright (C) 2005 Novell, Inc. (Miguel de Icaza, Aaron Bockover)
 
7
//
 
8
 
 
9
//  NOTE: throughout IntPtr is used for the Xlib long type, as this tends to 
 
10
//  have the correct width and does not require any configure checks.
 
11
 
 
12
using System;
 
13
using System.Runtime.InteropServices;
 
14
 
 
15
using Gtk;
 
16
using Gdk;
 
17
 
 
18
namespace Beagle.Search.Tray {
 
19
 
 
20
        public class NotificationArea : Plug
 
21
        {
 
22
                private uint stamp;
 
23
                private Orientation orientation;
 
24
                
 
25
                private IntPtr selection_atom;
 
26
                private IntPtr manager_atom;
 
27
                private IntPtr system_tray_opcode_atom;
 
28
                private IntPtr orientation_atom;
 
29
                private IntPtr message_data_atom;
 
30
                private IntPtr manager_window;
 
31
                private FilterFunc filter;
 
32
                
 
33
                public NotificationArea (string name)
 
34
                {
 
35
                        Title = name;
 
36
                        Init ();
 
37
                }
 
38
        
 
39
                public NotificationArea (string name, Gdk.Screen screen)
 
40
                {
 
41
                        Title = name;
 
42
                        Screen = screen;
 
43
                        Init ();
 
44
                }
 
45
                
 
46
                [DllImport ("libc.so.6")]
 
47
                private static extern IntPtr memcpy (ref XClientMessageEvent.DataUnion dest, IntPtr src, IntPtr len);
 
48
 
 
49
                public uint SendMessage (uint timeout, string message)
 
50
                {
 
51
                        if (manager_window == IntPtr.Zero) {
 
52
                                return 0;
 
53
                        }
 
54
                        
 
55
                        byte[] arr = System.Text.Encoding.UTF8.GetBytes (message);
 
56
                        IntPtr unmanaged_arr = Marshal.AllocHGlobal (arr.Length);
 
57
                        Marshal.Copy (arr, 0, unmanaged_arr, arr.Length);
 
58
 
 
59
                        SendManagerMessage (SystemTrayMessage.BeginMessage, (IntPtr) Id, timeout, (uint) arr.Length, ++stamp);
 
60
 
 
61
                        gdk_error_trap_push ();
 
62
                
 
63
                        for (int index = 0; index < message.Length; index += 20) {
 
64
                                XClientMessageEvent ev = new XClientMessageEvent ();
 
65
                        
 
66
                                IntPtr display = gdk_x11_display_get_xdisplay (Display.Handle);
 
67
                        
 
68
                                ev.type = XEventName.ClientMessage;
 
69
                                ev.window = (IntPtr) Id;
 
70
                                ev.format = 8;
 
71
                                ev.message_type = message_data_atom;
 
72
            
 
73
                                int len = Math.Min (arr.Length - index, 20);
 
74
                                memcpy (ref ev.data, (IntPtr)((int)unmanaged_arr + index), (IntPtr)len);
 
75
                        
 
76
                                XSendEvent (display, manager_window, false, (IntPtr) EventMask.StructureNotifyMask, ref ev);
 
77
                                XSync (display, false);
 
78
                        }
 
79
                
 
80
                        gdk_error_trap_pop ();
 
81
                
 
82
                        return stamp;
 
83
                }
 
84
        
 
85
                public void CancelMessage (uint id)
 
86
                {
 
87
                        if (id == 0) {
 
88
                                return;
 
89
                        }
 
90
                
 
91
                        SendManagerMessage (SystemTrayMessage.CancelMessage, (IntPtr) Id, id, 0, 0);
 
92
                }
 
93
        
 
94
                private void Init ()
 
95
                {
 
96
                        stamp = 1;
 
97
                        orientation = Orientation.Horizontal;
 
98
                        AddEvents ((int)EventMask.PropertyChangeMask);
 
99
                        filter = new FilterFunc (ManagerFilter);
 
100
                }
 
101
 
 
102
                [GLib.ConnectBefore]
 
103
                private void TransparentExposeEvent (object obj, Gtk.ExposeEventArgs args)
 
104
                {
 
105
                        Gtk.Widget widget = (Gtk.Widget)obj;
 
106
                        Gdk.Rectangle area = args.Event.Area;
 
107
 
 
108
                        widget.GdkWindow.ClearArea (area.X, area.Y, area.Width, area.Height);
 
109
                }
 
110
 
 
111
                private void MakeTransparentAgain (object obj, Gtk.StyleSetArgs args)
 
112
                {
 
113
                        Gtk.Widget widget = (Gtk.Widget)obj;
 
114
 
 
115
                        widget.GdkWindow.SetBackPixmap (null, true);
 
116
                }
 
117
        
 
118
                private void MakeTransparent (object obj, EventArgs args)
 
119
                {
 
120
                        Gtk.Widget widget = (Gtk.Widget)obj;
 
121
                        if (widget.IsNoWindow || widget.IsAppPaintable)
 
122
                                return;
 
123
 
 
124
                        widget.AppPaintable = true;
 
125
                        widget.DoubleBuffered = false;
 
126
                        widget.GdkWindow.SetBackPixmap (null, true);
 
127
                        widget.ExposeEvent += TransparentExposeEvent;
 
128
                        widget.StyleSet += MakeTransparentAgain;
 
129
                }
 
130
 
 
131
                protected override void OnRealized ()
 
132
                {
 
133
                        base.OnRealized ();
 
134
                        MakeTransparent (this, EventArgs.Empty);
 
135
                        Display display = Screen.Display;
 
136
                        IntPtr xdisplay = gdk_x11_display_get_xdisplay (display.Handle);
 
137
                        selection_atom = XInternAtom (xdisplay, "_NET_SYSTEM_TRAY_S" + Screen.Number.ToString (), false);
 
138
                        manager_atom = XInternAtom (xdisplay, "MANAGER", false);
 
139
                        system_tray_opcode_atom = XInternAtom (xdisplay, "_NET_SYSTEM_TRAY_OPCODE", false);
 
140
                        orientation_atom = XInternAtom (xdisplay, "_NET_SYSTEM_TRAY_ORIENTATION", false);
 
141
                        message_data_atom = XInternAtom (xdisplay, "_NET_SYSTEM_TRAY_MESSAGE_DATA", false);
 
142
                        UpdateManagerWindow (false);
 
143
                        SendDockRequest ();
 
144
                        Screen.RootWindow.AddFilter (filter);
 
145
                }
 
146
 
 
147
                protected override void OnAdded (Gtk.Widget child)
 
148
                {
 
149
                        child.Realized += MakeTransparent;
 
150
                        base.OnAdded (child);
 
151
                }
 
152
        
 
153
                protected override void OnUnrealized ()
 
154
                {
 
155
                        if (manager_window != IntPtr.Zero) {
 
156
                                Gdk.Window gdkwin = Gdk.Window.ForeignNewForDisplay (Display, (uint)manager_window);
 
157
                                if (gdkwin != null) {
 
158
                                        gdkwin.RemoveFilter (filter);
 
159
                                }
 
160
                        }
 
161
                
 
162
                        Screen.RootWindow.RemoveFilter (filter);
 
163
                        base.OnUnrealized ();
 
164
                }
 
165
        
 
166
                private void UpdateManagerWindow (bool dock_if_realized)
 
167
                {
 
168
                        IntPtr xdisplay = gdk_x11_display_get_xdisplay (Display.Handle);
 
169
                
 
170
                        if (manager_window != IntPtr.Zero) {
 
171
                                return;
 
172
                        }
 
173
                
 
174
                        XGrabServer (xdisplay);
 
175
                
 
176
                        manager_window = XGetSelectionOwner (xdisplay, selection_atom);
 
177
                        if (manager_window != IntPtr.Zero) {
 
178
                                XSelectInput (xdisplay, manager_window, (IntPtr) (EventMask.StructureNotifyMask | EventMask.PropertyChangeMask));
 
179
                        }
 
180
                
 
181
                        XUngrabServer (xdisplay);
 
182
                        XFlush (xdisplay);
 
183
 
 
184
                        if (manager_window != IntPtr.Zero) {
 
185
                                Gdk.Window gdkwin = Gdk.Window.ForeignNewForDisplay (Display, (uint)manager_window);
 
186
                                if (gdkwin != null) {
 
187
                                        gdkwin.AddFilter (filter);
 
188
                                }
 
189
                        
 
190
                                if (dock_if_realized && IsRealized) {
 
191
                                        SendDockRequest ();
 
192
                                }
 
193
                        
 
194
                                GetOrientationProperty ();
 
195
                        }
 
196
                }
 
197
        
 
198
                private void SendDockRequest ()
 
199
                {
 
200
                        SendManagerMessage (SystemTrayMessage.RequestDock, manager_window, Id, 0, 0);
 
201
                }
 
202
        
 
203
                private void SendManagerMessage (SystemTrayMessage message, IntPtr window, uint data1, uint data2, uint data3)
 
204
                {
 
205
                        XClientMessageEvent ev = new XClientMessageEvent ();
 
206
                        IntPtr display;
 
207
                
 
208
                        ev.type = XEventName.ClientMessage;
 
209
                        ev.window = window;
 
210
                        ev.message_type = system_tray_opcode_atom;
 
211
                        ev.format = 32;
 
212
                        ev.data.ptr1 = (IntPtr)gdk_x11_get_server_time (GdkWindow.Handle);
 
213
                        ev.data.ptr2 = (IntPtr)message;
 
214
                        ev.data.ptr3 = (IntPtr)data1;
 
215
                        ev.data.ptr4 = (IntPtr)data2;
 
216
                        ev.data.ptr5 = (IntPtr)data3;
 
217
 
 
218
                        display = gdk_x11_display_get_xdisplay (Display.Handle);
 
219
                        gdk_error_trap_push ();
 
220
                        XSendEvent (display, manager_window, false, (IntPtr) EventMask.NoEventMask, ref ev);
 
221
                        XSync (display, false);
 
222
                        gdk_error_trap_pop ();
 
223
                }
 
224
 
 
225
                private FilterReturn ManagerFilter (IntPtr xevent, Event evnt)
 
226
                {
 
227
                        XAnyEvent xev = (XAnyEvent) Marshal.PtrToStructure (xevent, typeof(XAnyEvent));
 
228
        
 
229
                        if (xev.type == XEventName.ClientMessage){
 
230
                                XClientMessageEvent xclient = (XClientMessageEvent) Marshal.PtrToStructure (xevent, typeof(XClientMessageEvent));
 
231
 
 
232
                                if (xclient.message_type == manager_atom && xclient.data.ptr2 == selection_atom) {
 
233
                                        UpdateManagerWindow (true);
 
234
                                        return FilterReturn.Continue;
 
235
                                }
 
236
                        }
 
237
 
 
238
                        if (xev.window == manager_window) {
 
239
                                if (xev.type == XEventName.PropertyNotify){
 
240
                                        XPropertyEvent xproperty = (XPropertyEvent) Marshal.PtrToStructure (xevent, typeof(XPropertyEvent));
 
241
                                        if (xproperty.atom == orientation_atom) {
 
242
                                                GetOrientationProperty();
 
243
                                                return FilterReturn.Continue;
 
244
                                        }
 
245
                                }
 
246
 
 
247
                                if (xev.type == XEventName.DestroyNotify) {
 
248
                                        ManagerWindowDestroyed();
 
249
                                }
 
250
                        }
 
251
        
 
252
                        return FilterReturn.Continue;
 
253
                }
 
254
 
 
255
                private void ManagerWindowDestroyed ()
 
256
                {
 
257
                        if (manager_window != IntPtr.Zero) {
 
258
                                Gdk.Window gdkwin = Gdk.Window.ForeignNewForDisplay (Display, (uint) manager_window);
 
259
            
 
260
                                if (gdkwin != null) {
 
261
                                        gdkwin.RemoveFilter (filter);
 
262
                                }
 
263
            
 
264
                                manager_window = IntPtr.Zero;
 
265
                                UpdateManagerWindow (true);
 
266
                        }
 
267
                }
 
268
 
 
269
                private void GetOrientationProperty ()
 
270
                {
 
271
                        IntPtr display;
 
272
                        IntPtr type;
 
273
                        int format;
 
274
                        IntPtr prop_return;
 
275
                        IntPtr nitems, bytes_after;
 
276
                        int error, result;
 
277
 
 
278
                        if (manager_window == IntPtr.Zero) {
 
279
                                return;
 
280
                        }
 
281
 
 
282
                        display = gdk_x11_display_get_xdisplay (Display.Handle);
 
283
        
 
284
                        gdk_error_trap_push ();
 
285
                        type = IntPtr.Zero;
 
286
        
 
287
                        result = XGetWindowProperty (display, manager_window, orientation_atom, (IntPtr) 0, 
 
288
                                                     (IntPtr) System.Int32.MaxValue, false, (IntPtr) XAtom.Cardinal, out type, out format, 
 
289
                                                     out nitems, out bytes_after, out prop_return);
 
290
        
 
291
                        error = gdk_error_trap_pop ();
 
292
 
 
293
                        if (error != 0 || result != 0) {
 
294
                                return;
 
295
                        }
 
296
 
 
297
                        if (type == (IntPtr) XAtom.Cardinal) {
 
298
                                orientation = ((SystemTrayOrientation) Marshal.ReadInt32 (prop_return) == SystemTrayOrientation.Horz) 
 
299
                                        ? Orientation.Horizontal 
 
300
                                        : Orientation.Vertical;
 
301
                                if (OrientationChanged != null)
 
302
                                        OrientationChanged (this, orientation);
 
303
                        }
 
304
 
 
305
                        if (prop_return != IntPtr.Zero) {
 
306
                                XFree (prop_return);
 
307
                        }
 
308
                }
 
309
 
 
310
                public Orientation Orientation {
 
311
                        get {
 
312
                                return orientation;
 
313
                        }
 
314
                }
 
315
 
 
316
                public delegate void OrientationChangedHandler (NotificationArea area, Orientation orientation);
 
317
                public event OrientationChangedHandler OrientationChanged;
 
318
 
 
319
                [DllImport ("libgdk-x11-2.0.so.0")]
 
320
                private static extern IntPtr gdk_x11_display_get_xdisplay (IntPtr display);
 
321
    
 
322
                [DllImport ("libgdk-x11-2.0.so.0")]
 
323
                private static extern int gdk_x11_get_server_time (IntPtr window);
 
324
    
 
325
                [DllImport ("libgdk-x11-2.0.so.0")]
 
326
                private static extern void gdk_error_trap_push ();
 
327
    
 
328
                [DllImport ("libgdk-x11-2.0.so.0")]
 
329
                private static extern int gdk_error_trap_pop ();
 
330
    
 
331
                [DllImport ("libX11.so.6")]
 
332
                private extern static IntPtr XInternAtom(IntPtr display, string atom_name, bool only_if_exists);
 
333
    
 
334
                [DllImport ("libX11.so.6")]
 
335
                private extern static void XGrabServer (IntPtr display);
 
336
    
 
337
                [DllImport ("libX11.so.6")]
 
338
                private extern static void XUngrabServer (IntPtr display);
 
339
    
 
340
                [DllImport ("libX11.so.6")]
 
341
                private extern static int XFlush (IntPtr display);
 
342
   
 
343
                [DllImport ("libX11.so.6")]
 
344
                private extern static int XSync (IntPtr display, bool discard);
 
345
    
 
346
                [DllImport ("libX11.so.6")]
 
347
                private extern static int XFree (IntPtr display);
 
348
    
 
349
                [DllImport ("libX11.so.6")]
 
350
                private extern static IntPtr XGetSelectionOwner (IntPtr display, IntPtr atom);
 
351
   
 
352
                [DllImport ("libX11.so.6")]
 
353
                private extern static IntPtr XSelectInput (IntPtr display, IntPtr window, IntPtr mask);
 
354
    
 
355
                [DllImport ("libX11.so.6")]
 
356
                private extern static int XSendEvent(IntPtr display, IntPtr window, bool propagate, IntPtr event_mask, 
 
357
                                                     ref XClientMessageEvent send_event);
 
358
 
 
359
                [DllImport("libX11.so.6")]
 
360
                private extern static int XGetWindowProperty(IntPtr display, IntPtr w, IntPtr property, IntPtr long_offset, 
 
361
                                                             IntPtr long_length, bool deleteProp, IntPtr req_type,
 
362
                                                             out IntPtr actual_type_return, out int actual_format_return, 
 
363
                                                             out IntPtr nitems_return, out IntPtr bytes_after_return, 
 
364
                                                             out IntPtr prop_return);
 
365
 
 
366
                [Flags]
 
367
                private enum EventMask {
 
368
                        NoEventMask              = 0,
 
369
                        KeyPressMask             = 1 << 0,
 
370
                        KeyReleaseMask           = 1 << 1,
 
371
                        ButtonPressMask          = 1 << 2,
 
372
                        ButtonReleaseMask        = 1 << 3,
 
373
                        EnterWindowMask          = 1 << 4,
 
374
                        LeaveWindowMask          = 1 << 5,
 
375
                        PointerMotionMask        = 1 << 6,
 
376
                        PointerMotionHintMask    = 1 << 7,
 
377
                        Button1MotionMask        = 1 << 8,
 
378
                        Button2MotionMask        = 1 << 9,
 
379
                        Button3MotionMask        = 1 << 10,
 
380
                        Button4MotionMask        = 1 << 11,
 
381
                        Button5MotionMask        = 1 << 12,
 
382
                        ButtonMotionMask         = 1 << 13,
 
383
                        KeymapStateMask          = 1 << 14,
 
384
                        ExposureMask             = 1 << 15,
 
385
                        VisibilityChangeMask     = 1 << 16,
 
386
                        StructureNotifyMask      = 1 << 17,
 
387
                        ResizeRedirectMask       = 1 << 18,
 
388
                        SubstructureNotifyMask   = 1 << 19,
 
389
                        SubstructureRedirectMask = 1 << 20,
 
390
                        FocusChangeMask          = 1 << 21,
 
391
                        PropertyChangeMask       = 1 << 22,
 
392
                        ColormapChangeMask       = 1 << 23,
 
393
                        OwnerGrabButtonMask      = 1 << 24
 
394
                }
 
395
 
 
396
                private enum SystemTrayMessage {
 
397
                        RequestDock = 0,
 
398
                        BeginMessage = 1,
 
399
                        CancelMessage = 2
 
400
                }
 
401
 
 
402
                private enum SystemTrayOrientation {
 
403
                        Horz = 0,
 
404
                        Vert = 1
 
405
                }
 
406
 
 
407
                private enum XEventName {
 
408
                        KeyPress                = 2,
 
409
                        KeyRelease              = 3,
 
410
                        ButtonPress             = 4,
 
411
                        ButtonRelease           = 5,
 
412
                        MotionNotify            = 6,
 
413
                        EnterNotify             = 7,
 
414
                        LeaveNotify             = 8,
 
415
                        FocusIn                 = 9,
 
416
                        FocusOut                = 10,
 
417
                        KeymapNotify            = 11,
 
418
                        Expose                  = 12,
 
419
                        GraphicsExpose          = 13,
 
420
                        NoExpose                = 14,
 
421
                        VisibilityNotify        = 15,
 
422
                        CreateNotify            = 16,
 
423
                        DestroyNotify           = 17,
 
424
                        UnmapNotify             = 18,
 
425
                        MapNotify               = 19,
 
426
                        MapRequest              = 20,
 
427
                        ReparentNotify          = 21,
 
428
                        ConfigureNotify         = 22,
 
429
                        ConfigureRequest        = 23,
 
430
                        GravityNotify           = 24,
 
431
                        ResizeRequest           = 25,
 
432
                        CirculateNotify         = 26,
 
433
                        CirculateRequest        = 27,
 
434
                        PropertyNotify          = 28,
 
435
                        SelectionClear          = 29,
 
436
                        SelectionRequest        = 30,
 
437
                        SelectionNotify         = 31,
 
438
                        ColormapNotify          = 32,
 
439
                        ClientMessage           = 33,
 
440
                        MappingNotify           = 34,
 
441
                        TimerNotify             = 100,
 
442
                        LASTEvent
 
443
                }
 
444
 
 
445
                private enum XAtom {
 
446
                        Cardinal                = 6,
 
447
                        LASTAtom
 
448
                }
 
449
        
 
450
                [StructLayout(LayoutKind.Sequential)]
 
451
                private struct XAnyEvent 
 
452
                {
 
453
                        internal XEventName    type;
 
454
                        internal IntPtr        serial;
 
455
                        internal bool          send_event;
 
456
                        internal IntPtr        display;
 
457
                        internal IntPtr        window;
 
458
                }
 
459
 
 
460
                [StructLayout(LayoutKind.Sequential)]
 
461
                private struct XPropertyEvent 
 
462
                {
 
463
                        internal XEventName    type;
 
464
                        internal IntPtr        serial;
 
465
                        internal bool          send_event;
 
466
                        internal IntPtr        display;
 
467
                        internal IntPtr        window;
 
468
                        internal IntPtr        atom;
 
469
                        internal IntPtr        time;
 
470
                        internal int           state;
 
471
                }
 
472
 
 
473
                [StructLayout(LayoutKind.Sequential)]
 
474
                private struct XClientMessageEvent 
 
475
                {
 
476
                        internal XEventName     type;
 
477
                        internal IntPtr         serial;
 
478
                        internal bool           send_event;
 
479
                        internal IntPtr         display;
 
480
                        internal IntPtr         window;
 
481
                        internal IntPtr         message_type;
 
482
                        internal int            format;
 
483
            
 
484
                        [StructLayout(LayoutKind.Sequential)]
 
485
                        internal struct DataUnion 
 
486
                        {
 
487
                                internal IntPtr ptr1;
 
488
                                internal IntPtr ptr2;
 
489
                                internal IntPtr ptr3;
 
490
                                internal IntPtr ptr4;
 
491
                                internal IntPtr ptr5;
 
492
                        }
 
493
            
 
494
                        internal DataUnion      data;
 
495
                }
 
496
        }
 
497
}
 
498
 
 
499