1/* -------------------------------------------------------------------------
2 * Project: Mac Notifier Support
3 * Name:    macnotfy.c
4 * Author:  Stefan CSomor
5 * Purpose: Mac Notifier main file
6 * CVSID:   $Id: macnotfy.cpp 26277 2004-03-20 07:43:01Z SC $
7 * -------------------------------------------------------------------------
8 */
9
10#include "wx/wx.h"
11
12#include "wx/mac/private.h"
13
14#include "wx/mac/macnotfy.h"
15
16const short kMaxEvents = 1000 ;
17
18struct wxMacNotificationEvents
19{
20    short top ;
21    short bottom ;
22
23    wxMacNotificationProcPtr proc[kMaxEvents] ;
24    unsigned long events[kMaxEvents] ;
25    void* data[kMaxEvents] ;
26} ;
27
28typedef struct wxMacNotificationEvents wxMacNotificationEvents ;
29static wxMacNotificationEvents gMacNotificationEvents ;
30
31static ProcessSerialNumber gAppProcess ;
32
33void wxMacWakeUp()
34{
35    ProcessSerialNumber psn ;
36    Boolean isSame ;
37    psn.highLongOfPSN = 0 ;
38    psn.lowLongOfPSN = kCurrentProcess ;
39    SameProcess( &gAppProcess , &psn , &isSame ) ;
40    if ( isSame )
41    {
42#if TARGET_CARBON
43        EventRef dummyEvent ;
44        OSStatus err = MacCreateEvent(nil, 'WXMC', 'WXMC', GetCurrentEventTime(),
45                        kEventAttributeNone, &dummyEvent);
46        if (err == noErr)
47        {
48            err = PostEventToQueue(GetMainEventQueue(), dummyEvent,
49                                  kEventPriorityHigh);
50        }
51#else
52        PostEvent( nullEvent , 0 ) ;
53#endif
54    }
55    else
56    {
57        WakeUpProcess( &gAppProcess ) ;
58    }
59}
60
61void wxMacCreateNotifierTable()
62{
63      GetCurrentProcess(&gAppProcess);
64    gMacNotificationEvents.top = 0 ;
65    gMacNotificationEvents.bottom = 0 ;
66    for ( int i = 0 ; i < kMaxEvents ; ++i )
67    {
68        gMacNotificationEvents.proc[i] = NULL ;
69        gMacNotificationEvents.events[i] = NULL ;
70        gMacNotificationEvents.data[i] = NULL ;
71    }
72}
73
74void wxMacDestroyNotifierTable()
75{
76}
77
78wxMacNotifierTableRef wxMacGetNotifierTable()
79{
80    return (wxMacNotifierTableRef) &gMacNotificationEvents ;
81}
82
83void wxMacAddEvent(
84    wxMacNotifierTableRef table ,
85    wxMacNotificationProcPtr handler ,
86    unsigned long event ,
87    void* data ,
88    short wakeUp )
89{
90    wxMacNotificationEvents *e = (wxMacNotificationEvents *) table ;
91    wxASSERT_MSG( handler != NULL , wxT("illegal notification proc ptr") ) ;
92    /* this should be protected eventually */
93    short index = e->top++ ;
94
95    if ( e->top == kMaxEvents )
96        e->top = 0 ;
97
98    e->proc[index] = handler ;
99    e->events[index] = event ;
100    e->data[index] = data ;
101    if ( wakeUp )
102        wxMacWakeUp() ;
103}
104
105bool gInProcessing = false ;
106
107void wxMacRemoveAllNotifiersForData( wxMacNotifierTableRef table , void* data )
108{
109    wxMacNotificationEvents *e = (wxMacNotificationEvents *) table ;
110    /* this should be protected eventually */
111    short index = e->bottom ;
112
113    while ( e->top != index )
114    {
115        if ( e->data[index] == data )
116            e->data[index] = NULL ;
117        index++ ;
118        if ( index == kMaxEvents )
119            index = 0 ;
120    }
121}
122
123void wxMacProcessNotifierEvents()
124{
125    //  if ( gInProcessing )
126    //      return ;
127
128    gInProcessing = true ;
129    if ( gMacNotificationEvents.top != gMacNotificationEvents.bottom )
130    {
131        // we only should process the notifiers that were here when we entered it
132        // otherwise we might never get out...
133        short count = gMacNotificationEvents.top - gMacNotificationEvents.bottom ;
134        if ( count < 0 )
135            count += kMaxEvents ;
136
137        while ( count-- )
138        {
139            // consume event at bottom
140            short index = gMacNotificationEvents.bottom++ ;
141            if ( gMacNotificationEvents.bottom == kMaxEvents )
142                gMacNotificationEvents.bottom = 0 ;
143            void* data = gMacNotificationEvents.data[index] ;
144            unsigned long event = gMacNotificationEvents.events[index] ;
145            wxMacNotificationProcPtr handler =  gMacNotificationEvents.proc[index] ;
146
147            gMacNotificationEvents.data[index] = NULL ;
148            gMacNotificationEvents.events[index] = NULL ;
149            gMacNotificationEvents.proc[index]  = NULL ;
150
151            if ( handler )
152                handler( event , data  ) ;
153        }
154    }
155    gInProcessing = false ;
156}
157
158void wxMacProcessNotifierAndPendingEvents()
159{
160    wxMacProcessNotifierEvents() ;
161    wxTheApp->ProcessPendingEvents() ;
162}
163