Merge branch 'master' of git://localhost/acess2
[tpg/acess2.git] / Usermode / Applications / axwin3_src / WM / ipc.c
1 /*
2  * Acess2 GUI (AxWin) Version 3
3  * - By John Hodge (thePowersGang)
4  * 
5  * ipc.c
6  * - Interprocess communication
7  */
8 #include <common.h>
9 #include <acess/sys.h>
10 #include <net.h>
11 #include <string.h>
12 #include <ipcmessages.h>
13 #include <stdio.h>
14 #include <wm.h>
15 #include <wm_internals.h>
16 #include <wm_hotkeys.h> // Hotkey registration
17 #include <wm_renderer.h>        // Renderer IPC messages
18
19 #define AXWIN_PORT      4101
20
21 #define STATICBUF_SIZE  64
22 #define MAX_WINDOWS_PER_APP     128
23
24 // === TYPES ===
25 typedef struct sIPC_Type        tIPC_Type;
26
27 struct sIPC_Type
28 {
29          int    (*GetIdentSize)(const void *Ident);
30          int    (*CompareIdent)(const void *Ident1, const void *Ident2);
31         void    (*SendMessage)(const void *Ident, size_t Length, const void *Data);
32 };
33
34 struct sIPC_Client
35 {
36         const tIPC_Type *IPCType;
37         const void      *Ident; // Stored after structure
38
39          int    nWindows;
40         tWindow **Windows;
41 };
42
43 // === IMPORTS ===
44 extern tWindow  *gpWM_FocusedWindow;    // Needed for _FocusWindow
45
46 // === PROTOTYPES ===
47 void    IPC_Init(void);
48 void    IPC_FillSelect(int *nfds, fd_set *set);
49 void    IPC_HandleSelect(fd_set *set);
50  int    IPC_Type_Datagram_GetSize(const void *Ident);
51  int    IPC_Type_Datagram_Compare(const void *Ident1, const void *Ident2);
52 void    IPC_Type_Datagram_Send(const void *Ident, size_t Length, const void *Data);
53  int    IPC_Type_Sys_GetSize(const void *Ident);
54  int    IPC_Type_Sys_Compare(const void *Ident1, const void *Ident2);
55 void    IPC_Type_Sys_Send(const void *Ident, size_t Length, const void *Data);
56  int    IPC_Type_IPCPipe_GetSize(const void *Ident);
57  int    IPC_Type_IPCPipe_Compare(const void *Ident1, const void *Ident2);
58 void    IPC_Type_IPCPipe_Send(const void *Ident, size_t Length, const void *Data);
59 tIPC_Client     *IPC_int_GetClient(const tIPC_Type *IPCType, const void *Ident);
60 void    IPC_int_DropClient(tIPC_Client *Client);
61 void    IPC_Handle(tIPC_Client *Client, size_t MsgLen, tAxWin_IPCMessage *Msg);
62
63 // === GLOBALS ===
64 const tIPC_Type gIPC_Type_Datagram = {
65         IPC_Type_Datagram_GetSize,
66         IPC_Type_Datagram_Compare, 
67         IPC_Type_Datagram_Send
68 };
69 const tIPC_Type gIPC_Type_SysMessage = {
70         IPC_Type_Sys_GetSize,
71         IPC_Type_Sys_Compare,
72         IPC_Type_Sys_Send
73 };
74 const tIPC_Type gIPC_Type_IPCPipe = {
75         IPC_Type_IPCPipe_GetSize,
76         IPC_Type_IPCPipe_Compare,
77         IPC_Type_IPCPipe_Send
78 };
79  int    giNetworkFileHandle = -1;
80  int    giIPCPipeHandle = -1;
81  int    giIPC_ClientCount;
82 tIPC_Client     **gIPC_Clients;
83
84 // === CODE ===
85 void IPC_Init(void)
86 {
87          int    tmp;
88         // TODO: Check this
89         giNetworkFileHandle = _SysOpen("/Devices/ip/loop/udp", OPENFLAG_READ);
90         if( giNetworkFileHandle != -1 )
91         {
92                 tmp = AXWIN_PORT;
93                 _SysIOCtl(giNetworkFileHandle, 4, &tmp);        // TODO: Don't hard-code IOCtl number
94         }
95         
96         giIPCPipeHandle = _SysOpen("/Devices/ipcpipe/axwin"/*-$USER*/, OPENFLAG_CREATE);
97         _SysDebug("giIPCPipeHandle = %i", giIPCPipeHandle);
98         if( giIPCPipeHandle == -1 )
99                 _SysDebug("ERROR: Can't create IPCPipe handle");
100 }
101
102 void _setfd(int fd, int *nfds, fd_set *set)
103 {
104         if( fd >= 0 )
105         {
106                 if( fd >= *nfds )       *nfds = fd+1;
107                 FD_SET(fd, set);
108         }
109 }
110
111 void IPC_FillSelect(int *nfds, fd_set *set)
112 {
113         _setfd(giNetworkFileHandle, nfds, set);
114         _setfd(giIPCPipeHandle, nfds, set);
115         for( int i = 0; i < giIPC_ClientCount; i ++ )
116         {
117                 if( gIPC_Clients[i] && gIPC_Clients[i]->IPCType == &gIPC_Type_IPCPipe )
118                         _setfd( *(int*)(gIPC_Clients[i]->Ident), nfds, set );
119         }
120 }
121
122 void IPC_HandleSelect(fd_set *set)
123 {
124         if( giNetworkFileHandle != -1 && FD_ISSET(giNetworkFileHandle, set) )
125         {
126                 char    staticBuf[STATICBUF_SIZE];
127                  int    readlen, identlen;
128                 char    *msg;
129
130                 readlen = _SysRead(giNetworkFileHandle, staticBuf, sizeof(staticBuf));
131                 
132                 identlen = 4 + Net_GetAddressSize( ((uint16_t*)staticBuf)[1] );
133                 msg = staticBuf + identlen;
134
135                 IPC_Handle( IPC_int_GetClient(&gIPC_Type_Datagram, staticBuf), readlen - identlen, (void*)msg);
136                 //_SysDebug("IPC_HandleSelect: UDP handled");
137         }
138         
139         if( giIPCPipeHandle != -1 && FD_ISSET(giIPCPipeHandle, set) )
140         {
141                 int newfd = _SysOpenChild(giIPCPipeHandle, "newclient", OPENFLAG_READ|OPENFLAG_WRITE);
142                 _SysDebug("newfd = %i", newfd);
143                 IPC_int_GetClient(&gIPC_Type_IPCPipe, &newfd);
144         }
145         
146         for( int i = 0; i < giIPC_ClientCount; i ++ )
147         {
148                 if( gIPC_Clients[i] && gIPC_Clients[i]->IPCType == &gIPC_Type_IPCPipe )
149                 {
150                          int fd = *(const int*)gIPC_Clients[i]->Ident;
151                         if( FD_ISSET(fd, set) )
152                         {
153                                 char    staticBuf[STATICBUF_SIZE];
154                                 size_t  len;
155                                 len = _SysRead(fd, staticBuf, sizeof(staticBuf));
156                                 if( len == (size_t)-1 ) {
157                                         // TODO: Check errno for EINTR
158                                         IPC_int_DropClient(gIPC_Clients[i]);
159                                         break;
160                                 }
161                                 IPC_Handle( gIPC_Clients[i], len, (void*)staticBuf );
162                         }
163                 }
164         }
165
166         size_t  len;
167         int     tid;
168         while( (len = _SysGetMessage(&tid, 0, NULL)) )
169         {
170                 char    data[len];
171                 _SysGetMessage(NULL, len, data);
172
173                 IPC_Handle( IPC_int_GetClient(&gIPC_Type_SysMessage, &tid), len, (void*)data );
174 //              _SysDebug("IPC_HandleSelect: Message handled");
175         }
176 }
177
178 int IPC_Type_Datagram_GetSize(const void *Ident)
179 {
180         return 4 + Net_GetAddressSize( ((const uint16_t*)Ident)[1] );
181 }
182
183 int IPC_Type_Datagram_Compare(const void *Ident1, const void *Ident2)
184 {
185         // Pass the buck :)
186         // - No need to worry about mis-matching sizes, as the size is computed
187         //   from the 3rd/4th bytes, hence it will differ before the size is hit.
188         return memcmp(Ident1, Ident2, IPC_Type_Datagram_GetSize(Ident1));
189 }
190
191 void IPC_Type_Datagram_Send(const void *Ident, size_t Length, const void *Data)
192 {
193          int    identlen = IPC_Type_Datagram_GetSize(Ident);
194         char    tmpbuf[ identlen + Length ];
195         memcpy(tmpbuf, Ident, identlen);        // Header
196         memcpy(tmpbuf + identlen, Data, Length);        // Data
197         // TODO: Handle fragmented packets
198         _SysWrite(giNetworkFileHandle, tmpbuf, sizeof(tmpbuf));
199 }
200
201 int IPC_Type_Sys_GetSize(const void *Ident)
202 {
203         return sizeof(pid_t);
204 }
205
206 int IPC_Type_Sys_Compare(const void *Ident1, const void *Ident2)
207 {
208         return *(const tid_t*)Ident1 - *(const tid_t*)Ident2;
209 }
210
211 void IPC_Type_Sys_Send(const void *Ident, size_t Length, const void *Data)
212 {
213         _SysSendMessage( *(const tid_t*)Ident, Length, Data );
214 }
215
216 int IPC_Type_IPCPipe_GetSize(const void *Ident)
217 {
218         return sizeof(int);
219 }
220 int IPC_Type_IPCPipe_Compare(const void *Ident1, const void *Ident2)
221 {
222         return *(const int*)Ident1 - *(const int*)Ident2;
223 }
224 void IPC_Type_IPCPipe_Send(const void *Ident, size_t Length, const void *Data)
225 {
226         size_t rv = _SysWrite( *(const int*)Ident, Data, Length );
227         if(rv != Length) {
228                 _SysDebug("Sent message oversize %x", Length);
229         }
230 }
231
232 // --- Client -> Window Mappings
233 int _CompareClientPtrs(const void *_a, const void *_b)
234 {
235         tIPC_Client     *a = *(tIPC_Client**)_a;
236         tIPC_Client     *b = *(tIPC_Client**)_b;
237
238         ASSERT(a);
239         ASSERT(b);
240
241         if(a->IPCType < b->IPCType)     return -1;
242         if(a->IPCType > b->IPCType)     return 1;
243         
244         return a->IPCType->CompareIdent(a->Ident, b->Ident);
245 }
246
247 int IPC_int_BSearchClients(const tIPC_Client *TargetClient, int *Pos)
248 {
249          int    div;
250          int    cmp = -1;
251          int    pos = 0;
252
253         div = giIPC_ClientCount;
254         pos = div/2;
255         while(div > 0)
256         {
257                 div /= 2;
258                 cmp = _CompareClientPtrs(&TargetClient, &gIPC_Clients[pos]);
259 //              _SysDebug("Checking against %i gives %i", pos, cmp);
260                 if(cmp == 0)    break;
261                 if(cmp < 0)
262                         pos -= div;
263                 else
264                         pos += div;
265         }
266         
267         // - Return if found    
268         if(cmp == 0) {
269                 *Pos = pos;
270                 return 1;
271         }
272
273         // Adjust pos to be the index where the new client will be placed
274         if(cmp > 0)     pos ++;
275         *Pos = pos;
276         return 0;
277 }
278
279 tIPC_Client *IPC_int_GetClient(const tIPC_Type *IPCType, const void *Ident)
280 {
281          int    pos = 0;        // Position where the new client will be inserted
282          int    ident_size;
283         tIPC_Client     *ret;
284
285         // - Search list of registered clients
286         if(giIPC_ClientCount > 0)
287         {
288                 tIPC_Client     target;
289                 target.IPCType = IPCType;
290                 target.Ident = Ident;
291                 if( IPC_int_BSearchClients(&target, &pos) )
292                         return gIPC_Clients[pos];
293         }
294
295
296         // - Create a new client entry
297         ident_size = IPCType->GetIdentSize(Ident);
298 //      _SysDebug("ident_size = %i", ident_size);
299         ret = malloc( sizeof(tIPC_Client) + ident_size );
300         if(!ret)        return NULL;
301         ret->IPCType = IPCType;
302         ret->Ident = ret + 1;   // Get the end of the structure
303         memcpy( (void*)ret->Ident, Ident, ident_size );
304         ret->nWindows = 0;
305         ret->Windows = NULL;
306         
307         // TODO: Register some way of detecting the client disconnecting
308         //       > Wait on the thread / register with kernel somehow
309         //       > Sockets are easier, but UDP is harder. Might get rid of it
310
311         // - Insert
312         giIPC_ClientCount ++;
313         gIPC_Clients = realloc(gIPC_Clients, giIPC_ClientCount*sizeof(tIPC_Client*));
314         memmove(&gIPC_Clients[pos+1], &gIPC_Clients[pos], (giIPC_ClientCount-pos-1) * sizeof(tIPC_Client*));
315         gIPC_Clients[pos] = ret;
316
317         return ret;
318 }
319
320 void IPC_int_DropClient(tIPC_Client *Client)
321 {
322         // Remove from client list
323          int    pos;
324         if( !IPC_int_BSearchClients(Client, &pos) ) {
325                 _SysDebug("IPC_int_DropClient: Can't find client %p", Client);
326                 return ;
327         }
328
329         giIPC_ClientCount --;
330         memmove(&gIPC_Clients[pos], &gIPC_Clients[pos+1], (giIPC_ClientCount-pos)*sizeof(tIPC_Client*));
331
332         // Terminate client's windows
333         // - If there were active windows, show an error?
334          int    nWindowsDestroyed = 0;
335         for(int i = 0; i < Client->nWindows; i ++)
336         {
337                 if( Client->Windows[i] )
338                 {
339                         _SysDebug("Window %p:%i %p still exists", Client, i, Client->Windows[i]);
340                         WM_DestroyWindow(Client->Windows[i]);
341                         nWindowsDestroyed ++;
342                 }
343         }
344         if( nWindowsDestroyed )
345         {
346                 _SysDebug("TODO: Show notice that application exited without destroying windows");
347         }
348         
349         // Free client structure
350         free(Client);
351         _SysDebug("Dropped client %p", Client);
352 }
353
354 tWindow *IPC_int_GetWindow(tIPC_Client *Client, uint32_t WindowID)
355 {
356         if( WindowID == -1 )
357                 return NULL;
358
359         if( WindowID >= Client->nWindows ) {
360                 return NULL;
361         }
362
363         return Client->Windows[WindowID];
364 }
365
366 void IPC_int_SetWindow(tIPC_Client *Client, uint32_t WindowID, tWindow *WindowPtr)
367 {
368         if( WindowID >= MAX_WINDOWS_PER_APP )
369                 return ;
370
371         if( WindowID >= Client->nWindows )
372         {
373                  int    oldCount = Client->nWindows;
374                 Client->nWindows = WindowID + 1;
375                 Client->Windows = realloc(Client->Windows, Client->nWindows*sizeof(tWindow*));
376                 memset( &Client->Windows[oldCount],  0, (Client->nWindows-oldCount)*sizeof(tWindow*) );
377                 _SysDebug("Expanded %p's window list from %i to %i", Client, oldCount, Client->nWindows);
378         }
379
380         _SysDebug("Assigned %p to window %i for %p", WindowPtr, WindowID, Client);      
381         Client->Windows[WindowID] = WindowPtr;
382 }
383
384 // --- IPC Message Handlers ---
385 int IPC_Msg_Ping(tIPC_Client *Client, tAxWin_IPCMessage *Msg)
386 {
387         ASSERT(Msg->ID == IPCMSG_PING);
388         
389         if( !(Msg->Flags & IPCMSG_FLAG_RETURN) )        return 0;
390         
391         if( Msg->Size < 4 )     return -1;
392         
393         tIPCMsg_ReturnInt       *ret = (void*)Msg->Data;
394         Msg->ID = IPCMSG_PING;
395         Msg->Size = sizeof(*ret);
396         ret->Value = AXWIN_VERSION;
397         Client->IPCType->SendMessage(Client->Ident, sizeof(*Msg)+sizeof(*ret), Msg);
398         return 0;
399 }
400
401 int IPC_Msg_GetDisplayCount(tIPC_Client *Client, tAxWin_IPCMessage *Msg)
402 {
403         tAxWin_IPCMessage       *ret_hdr;
404         tIPCMsg_ReturnInt       *ret;
405         char    buf[sizeof(*ret_hdr)+sizeof(*ret)];
406         
407         ASSERT(Msg->ID == IPCMSG_GETDISPLAYCOUNT);
408
409         if( !(Msg->Flags & IPCMSG_FLAG_RETURN) )        return 0;
410         
411         ret_hdr = (void*)buf;
412         ret_hdr->ID = IPCMSG_GETDISPLAYCOUNT;
413         ret_hdr->Flags = 0;
414         ret_hdr->Window = -1;
415         ret_hdr->Size = sizeof(*ret);
416         ret = (void*)ret_hdr->Data;
417         ret->Value = 1; // HARD CODE - Current version only supports one display
418         
419         Client->IPCType->SendMessage(Client->Ident, sizeof(buf), buf);
420         return 0;
421 }
422
423 int IPC_Msg_GetDisplayDims(tIPC_Client *Client, tAxWin_IPCMessage *Msg)
424 {
425         tIPCMsg_GetDisplayDims  *info;
426         tAxWin_IPCMessage       *ret_hdr;
427         tIPCMsg_RetDisplayDims  *ret;
428         char    buf[sizeof(*ret_hdr)+sizeof(*ret)];
429         
430         ASSERT(Msg->ID == IPCMSG_GETDISPLAYDIMS);
431
432         if( !(Msg->Flags & IPCMSG_FLAG_RETURN) )        return 0;
433
434         info = (void*)Msg->Data;        
435
436         ret_hdr = (void*)buf;
437         ret_hdr->ID = IPCMSG_GETDISPLAYDIMS;
438         ret_hdr->Flags = 0;
439         ret_hdr->Window = -1;
440         ret_hdr->Size = sizeof(*ret);
441         ret = (void*)ret_hdr->Data;
442         
443         // HARD CODE! Only one display supported
444         if( info->DisplayID == 0 )
445         {
446                 ret->X = 0;
447                 ret->Y = 0;
448                 ret->W = giScreenWidth;
449                 ret->H = giScreenHeight;
450         }
451         else
452         {
453                 ret->X = 0;     ret->Y = 0;
454                 ret->W = 0;     ret->H = 0;
455         }
456         
457         Client->IPCType->SendMessage(Client->Ident, sizeof(buf), buf);
458         return 0;
459 }
460
461 int IPC_Msg_SendMsg(tIPC_Client *Client, tAxWin_IPCMessage *Msg)
462 {
463         tIPCMsg_SendMsg *info = (void*)Msg->Data;
464         tWindow *src, *dest;
465
466         ASSERT(Msg->ID == IPCMSG_SENDMSG);
467         
468         // - Sanity checks
469         if( Msg->Size < sizeof(tIPCMsg_SendMsg) )
470                 return -1;
471         if( Msg->Size < sizeof(tIPCMsg_SendMsg) + info->Length )
472                 return -1;
473         
474         src = IPC_int_GetWindow(Client, Msg->Window);
475         if(!src)        return 1;
476         dest = IPC_int_GetWindow(Client, info->Remote);
477         if(!dest)       return 1;
478
479         WM_SendMessage(src, dest, info->ID, info->Length, info->Data);  
480
481         return 0;
482 }
483
484 int IPC_Msg_CreateWin(tIPC_Client *Client, tAxWin_IPCMessage *Msg)
485 {
486         tIPCMsg_CreateWin       *info = (void*)Msg->Data;
487         tWindow *newwin, *parent;
488
489         ASSERT(Msg->ID == IPCMSG_CREATEWIN);
490
491         // - Sanity checks
492         //  > +1 is for NULL byte on string
493         if( Msg->Size < sizeof(*info) + 1 ) {
494                 _SysDebug("IPC_Msg_CreateWin: Size check 1 failed");
495                 return -1;
496         }
497         if( info->Renderer[Msg->Size - sizeof(*info) - 1] != '\0' ) {
498                 _SysDebug("IPC_Msg_CreateWin: Size check 2 failed");
499                 _SysDebug("info = {");
500                 _SysDebug("  .NewWinID = %i", info->NewWinID);
501                 _SysDebug("  .RendererArg = %i", info->RendererArg);
502                 _SysDebug("  .Renderer = '%.*s'", Msg->Size - sizeof(*info), info->Renderer);
503                 _SysDebug("}");
504                 return -1;
505         }
506         
507         // - Get the parent window ID
508         parent = IPC_int_GetWindow(Client, Msg->Window);
509
510         // Catch creating a window with an existing ID
511         if( IPC_int_GetWindow(Client, info->NewWinID) )
512                 return 1;
513
514         // - Create the new window, and save its pointer
515         newwin = WM_CreateWindow(parent, Client, info->NewWinID, info->RendererArg, info->Renderer);
516         IPC_int_SetWindow(Client, info->NewWinID, newwin);
517
518         return 0;
519 }
520
521 int IPC_Msg_DestroyWin(tIPC_Client *Client, tAxWin_IPCMessage *Msg)
522 {
523         tWindow *win;
524         
525         ASSERT(Msg->ID == IPCMSG_DESTROYWIN);
526
527         win = IPC_int_GetWindow(Client, Msg->Window);
528         if( !win )
529                 return 0;
530         
531         WM_DestroyWindow(win);
532         IPC_int_SetWindow(Client, Msg->Window, NULL);
533         return 0;
534 }
535
536 int IPC_Msg_SetWindowTitle(tIPC_Client *Client, tAxWin_IPCMessage *Msg)
537 {
538         tWindow *win;
539
540         ASSERT(Msg->ID == IPCMSG_SETWINTITLE);
541         
542         if( Msg->Size < 1 )     return -1;
543         if( Msg->Data[ Msg->Size-1 ] != '\0' )  return -1;      
544
545         win = IPC_int_GetWindow(Client, Msg->Window);
546         if(!win)        return 1;
547
548         WM_SetWindowTitle(win, Msg->Data);
549
550         return 0;
551 }
552
553 int IPC_Msg_ShowWindow(tIPC_Client *Client, tAxWin_IPCMessage *Msg)
554 {
555         tIPCMsg_Boolean *info = (void*)Msg->Data;
556         tWindow *win;
557         
558         ASSERT(Msg->ID == IPCMSG_SHOWWINDOW);
559         
560         if( Msg->Size < sizeof(*info) ) return -1;
561         
562         win = IPC_int_GetWindow(Client, Msg->Window);
563         if(!win)        return 1;
564
565         WM_ShowWindow(win, !!info->Value);
566         
567         return 0;
568 }
569
570 int IPC_Msg_DecorateWindow(tIPC_Client *Client, tAxWin_IPCMessage *Msg)
571 {
572         tIPCMsg_Boolean *info = (void*)Msg->Data;
573         tWindow *win;
574         
575         if( Msg->Size < sizeof(*info) ) return -1;
576         
577         win = IPC_int_GetWindow(Client, Msg->Window);
578         if(!win)        return 1;
579         
580         WM_DecorateWindow(win, !!info->Value);
581         return 0;
582 }
583
584 int IPC_Msg_FocusWindow(tIPC_Client *Client, tAxWin_IPCMessage *Msg)
585 {
586         tWindow *win;
587
588         ASSERT(Msg->ID == IPCMSG_FOCUSWINDOW);
589         
590         // Don't allow the focus to be changed unless the client has the focus
591 //      if(!gpWM_FocusedWindow) return 1;
592 //      if(gpWM_FocusedWindow->Client != Client)        return 1;
593
594         win = IPC_int_GetWindow(Client, Msg->Window);
595         if(!win)        return 1;
596
597         WM_FocusWindow(win);
598
599         return 0;
600 }
601
602 int IPC_Msg_SetWinPos(tIPC_Client *Client, tAxWin_IPCMessage *Msg)
603 {
604         tIPCMsg_SetWindowPos    *info = (void*)Msg->Data;
605         tWindow *win;
606         
607         ASSERT(Msg->ID == IPCMSG_SETWINPOS);
608         
609         if(Msg->Size < sizeof(*info))   return -1;
610         
611         win = IPC_int_GetWindow(Client, Msg->Window);
612         if(!win)        return 1;
613         
614         _SysDebug("info = {..., bSetPos=%i,bSetDims=%i}", info->bSetPos, info->bSetDims);
615         
616         if(info->bSetPos)
617                 WM_MoveWindow(win, info->X, info->Y);
618         if(info->bSetDims)
619                 WM_ResizeWindow(win, info->W, info->H);
620         
621         return 0;
622 }
623
624 int IPC_Msg_RegisterAction(tIPC_Client *Client, tAxWin_IPCMessage *Msg)
625 {
626         tIPCMsg_RegAction       *info = (void*)Msg->Data;
627         tWindow *win;
628         
629         ASSERT(Msg->ID == IPCMSG_REGACTION);
630
631         if( Msg->Size < sizeof(*info) + 1 )
632                 return -1;
633         
634         win = IPC_int_GetWindow(Client, Msg->Window);
635         if(!win)        return 1;
636
637         if( strnlen(info->Action, Msg->Size - sizeof(*info)) == Msg->Size - sizeof(*info) )
638                 return 1;
639
640         _SysDebug("RegisterAction %p:%i [%i]\"%s\"",
641                 Client, Msg->Window, info->Index, info->Action
642                 );
643
644         WM_Hotkey_RegisterAction(info->Action, win, info->Index);
645
646         return 0;
647 }
648
649 int (*gIPC_MessageHandlers[])(tIPC_Client *Client, tAxWin_IPCMessage *Msg) = {
650         IPC_Msg_Ping,
651         IPC_Msg_GetDisplayCount,
652         IPC_Msg_GetDisplayDims,
653         IPC_Msg_SendMsg,
654         IPC_Msg_CreateWin,
655         IPC_Msg_DestroyWin,     // Destroy window
656         IPC_Msg_SetWindowTitle,
657         IPC_Msg_ShowWindow,
658         IPC_Msg_DecorateWindow,
659         IPC_Msg_FocusWindow,
660         IPC_Msg_SetWinPos,
661         IPC_Msg_RegisterAction
662 };
663 const int giIPC_NumMessageHandlers = sizeof(gIPC_MessageHandlers)/sizeof(gIPC_MessageHandlers[0]);
664
665 void IPC_Handle(tIPC_Client *Client, size_t MsgLen, tAxWin_IPCMessage *Msg)
666 {
667          int    rv = 0;
668         
669 //      _SysDebug("IPC_Handle: (IPCType=%p, Ident=%p, MsgLen=%i, Msg=%p)",
670 //              IPCType, Ident, MsgLen, Msg);
671         
672         if( MsgLen < sizeof(tAxWin_IPCMessage) )
673                 return ;
674         if( MsgLen < sizeof(tAxWin_IPCMessage) + Msg->Size )
675                 return ;
676         
677         if( Msg->Flags & IPCMSG_FLAG_RENDERER )
678         {
679                 tWindow *win = IPC_int_GetWindow(Client, Msg->Window);
680                 if( !win ) {
681                         _SysDebug("WARNING: NULL window in message %i (%x)", Msg->ID, Msg->Window);
682                         return ;
683                 }
684                 tWMRenderer     *renderer = win->Renderer;
685                 if( Msg->ID >= renderer->nIPCHandlers ) {
686                         _SysDebug("WARNING: Message %i out of range in %s", Msg->ID, renderer->Name);
687                         return ;
688                 }
689                 if( !renderer->IPCHandlers[Msg->ID] ) {
690                         _SysDebug("WARNING: Message %i has no handler in %s", Msg->ID, renderer->Name);
691                         return ;
692                 }
693                 _SysDebug("IPC_Handle: Call %s-%i", renderer->Name, Msg->ID);
694                 rv = renderer->IPCHandlers[Msg->ID](win, Msg->Size, Msg->Data);
695                 if( rv )
696                         _SysDebug("IPC_Handle: rv != 0 (%i)", rv);
697         }
698         else
699         {
700                 if( Msg->ID >= giIPC_NumMessageHandlers ) {
701                         fprintf(stderr, "WARNING: Unknown message %i (%p)\n", Msg->ID, Client);
702                         _SysDebug("WARNING: Unknown message %i (%p)", Msg->ID, Client);
703                         return ;
704                 }
705                 
706                 if( !gIPC_MessageHandlers[ Msg->ID ] ) {
707                         fprintf(stderr, "WARNING: Message %i does not have a handler\n", Msg->ID);
708                         _SysDebug("WARNING: Message %i does not have a handler", Msg->ID);
709                         return ;
710                 }
711         
712                 _SysDebug("IPC_Handle: Call WM-%i", Msg->ID);
713                 rv = gIPC_MessageHandlers[Msg->ID](Client, Msg);
714                 if( rv )
715                         _SysDebug("IPC_Handle: rv != 0 (%i)", rv);
716         }
717 }
718
719 // Dispatch a message to the client
720 void IPC_SendWMMessage(tIPC_Client *Client, uint32_t Src, uint32_t Dst, int MsgID, int Len, void *Data)
721 {
722         tAxWin_IPCMessage       *hdr;
723         tIPCMsg_SendMsg         *msg;
724         char    buf[sizeof(*hdr)+sizeof(*msg)+Len];
725         
726         hdr = (void*)buf;
727         msg = (void*)hdr->Data;
728         
729         hdr->ID = IPCMSG_SENDMSG;
730         hdr->Flags = 0;
731         hdr->Size = sizeof(*msg) + Len;
732         hdr->Window = Dst;
733         
734         msg->Remote = Src;
735         msg->ID = MsgID;
736         msg->Length = Len;
737         memcpy(msg->Data, Data, Len);
738         
739         Client->IPCType->SendMessage(Client->Ident, sizeof(buf), buf);
740 }
741
742 // --- Server->Client replies
743 void IPC_SendReply(tIPC_Client *Client, uint32_t WinID, int MsgID, size_t Len, const void *Data)
744 {
745         tAxWin_IPCMessage       *hdr;
746         char    buf[sizeof(*hdr)+Len];
747         
748         hdr = (void*)buf;
749         
750         hdr->ID = MsgID;
751         hdr->Flags = IPCMSG_FLAG_RENDERER;
752         hdr->Size = Len;
753         hdr->Window = WinID;
754         
755         memcpy(hdr->Data, Data, Len);
756         Client->IPCType->SendMessage(Client->Ident, sizeof(buf), buf);
757 }
758

UCC git Repository :: git.ucc.asn.au