TODO
[tpg/acess2.git] / Usermode / Applications / axwin3_src / libaxwin3.so_src / wm.c
1 /*
2  * AxWin3 Interface Library
3  * - By John Hodge (thePowersGang)
4  *
5  * wm.c
6  * - Core window management functions
7  */
8 #include <axwin3/axwin.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include "include/internal.h"
12 #include "include/ipc.h"
13
14 #define WINDOWS_PER_ALLOC       (63)
15
16 typedef struct sWindowBlock     tWindowBlock;
17
18 typedef struct sAxWin3_Window   tWindow;
19
20 // === STRUCTURES ===
21 struct sWindowBlock
22 {
23         tWindowBlock    *Next;
24         tWindow *Windows[WINDOWS_PER_ALLOC];
25 };
26
27 // === GLOBALS ===
28  int    giAxWin3_LowestFreeWinID;
29  int    giAxWin3_HighestUsedWinID;
30 tWindowBlock    gAxWin3_WindowList;
31
32 // === CODE ===
33 tWindow *AxWin3_int_CreateWindowStruct(uint32_t ServerID, int ExtraBytes)
34 {
35         tWindow *ret;
36         
37         ret = calloc(sizeof(tWindow) + ExtraBytes, 1);
38         ret->ServerID = ServerID;
39
40         return ret;
41 }
42
43 tWindow *AxWin3_int_GetWindowFromID(uint32_t ServerID)
44 {
45         tWindowBlock    *block = &gAxWin3_WindowList;
46         while(block && ServerID > WINDOWS_PER_ALLOC) {
47                 block = block->Next;
48                 ServerID -= WINDOWS_PER_ALLOC;
49         }
50         if(!block)      return NULL;
51         return block->Windows[ServerID];
52 }
53
54 tWindow *AxWin3_int_AllocateWindowInfo(int DataBytes, int *WinID)
55 {
56          int    idx, newWinID;
57         tWindowBlock *block, *prev = NULL;
58         tWindow *ret;   
59
60         block = &gAxWin3_WindowList;
61         newWinID = giAxWin3_LowestFreeWinID;
62         for( idx = 0; block; newWinID ++ )
63         {
64                 if( block->Windows[idx] == NULL )
65                         break;
66                 idx ++;
67                 if(idx == WINDOWS_PER_ALLOC) {
68                         prev = block;
69                         block = block->Next;
70                         idx = 0;
71                 }
72         }
73         
74         if( !block )
75         {
76                 block = calloc(sizeof(tWindowBlock), 1);
77                 prev->Next = block;
78                 idx = 0;
79         }
80         
81         ret = block->Windows[idx] = AxWin3_int_CreateWindowStruct(newWinID, DataBytes);
82         if(newWinID > giAxWin3_HighestUsedWinID)
83                 giAxWin3_HighestUsedWinID = newWinID;
84         if(newWinID == giAxWin3_LowestFreeWinID)
85                 giAxWin3_HighestUsedWinID ++;
86
87         if(WinID)       *WinID = newWinID;
88
89         return ret;
90 }
91
92 int AxWin3_GetDisplayCount(void)
93 {
94         tAxWin_IPCMessage       *msg;
95         tIPCMsg_ReturnInt       *ret;
96          int    rv;
97         
98         msg = AxWin3_int_AllocateIPCMessage(NULL, IPCMSG_GETDISPLAYCOUNT, IPCMSG_FLAG_RETURN, 0);
99         AxWin3_int_SendIPCMessage(msg);
100         free(msg);      
101
102         msg = AxWin3_int_WaitIPCMessage(IPCMSG_GETDISPLAYCOUNT);
103         if(msg->Size < sizeof(*ret))    return -1;
104         ret = (void*)msg->Data;
105         rv = ret->Value;
106         free(msg);
107         return rv;
108 }
109
110 int AxWin3_GetDisplayDims(int Display, int *X, int *Y, int *Width, int *Height)
111 {
112         tAxWin_IPCMessage       *msg;
113         tIPCMsg_GetDisplayDims  *req;
114         tIPCMsg_RetDisplayDims  *ret;
115         
116         msg = AxWin3_int_AllocateIPCMessage(NULL, IPCMSG_GETDISPLAYDIMS, IPCMSG_FLAG_RETURN, sizeof(*req));
117         req = (void*)msg->Data;
118         req->DisplayID = Display;
119         AxWin3_int_SendIPCMessage(msg);
120         free(msg);
121
122         msg = AxWin3_int_WaitIPCMessage(IPCMSG_GETDISPLAYDIMS);
123         if(msg->Size < sizeof(*ret))    return -1;
124         ret = (void*)msg->Data;
125         
126         if(X)   *X = ret->X;
127         if(X)   *X = ret->Y;
128         if(Width)       *Width = ret->W;
129         if(Height)      *Height = ret->H;
130         
131         return 0;
132 }
133
134 tHWND AxWin3_CreateWindow(
135         tHWND Parent, const char *Renderer, int RendererArg,
136         int DataBytes, tAxWin3_WindowMessageHandler MessageHandler
137         )
138 {
139         tWindow *ret;
140          int    newWinID;
141          int    dataSize = sizeof(tIPCMsg_CreateWin) + strlen(Renderer) + 1;
142         tAxWin_IPCMessage       *msg;
143         tIPCMsg_CreateWin       *create_win;
144
145         // Allocate a window ID
146         ret = AxWin3_int_AllocateWindowInfo(DataBytes, &newWinID);
147         if(!ret)        return NULL;
148         ret->Handler = MessageHandler;
149
150         // Create message
151         msg = AxWin3_int_AllocateIPCMessage(Parent, IPCMSG_CREATEWIN, 0, dataSize);
152         create_win = (void*)msg->Data;  
153         create_win->NewWinID = newWinID;
154         create_win->RendererArg = RendererArg;
155         strcpy(create_win->Renderer, Renderer);
156
157         // Send and clean up
158         AxWin3_int_SendIPCMessage(msg);
159         free(msg);
160
161         // TODO: Detect and handle possible errors
162
163         // Return success
164         return ret;
165 }
166
167 void AxWin3_DestroyWindow(tHWND Window)
168 {
169         tAxWin_IPCMessage       *msg;
170         
171         msg = AxWin3_int_AllocateIPCMessage(Window, IPCMSG_DESTROYWIN, 0, 0);
172         AxWin3_int_SendIPCMessage(msg);
173         free(msg);
174 }
175
176 void *AxWin3_int_GetDataPtr(tHWND Window)
177 {
178         return Window->Data;
179 }
180
181 void AxWin3_int_HandleMessage(tAxWin_IPCMessage *Msg)
182 {
183         tWindow *dest;
184
185         dest = AxWin3_int_GetWindowFromID(Msg->Window);
186
187         switch(Msg->ID)
188         {
189         case IPCMSG_SENDMSG: {
190                 tIPCMsg_SendMsg *info = (void*)Msg->Data;
191                 if(Msg->Size < sizeof(*info) || Msg->Size < sizeof(*info) + info->Length) {
192                         _SysDebug("Message is undersized (%i < %i + %i)",
193                                 Msg->Size < sizeof(*info), info->Length);
194                         return ;
195                 }
196                 if(!dest || !dest->Handler) {
197                         _SysDebug("No handler for destination %p", dest);
198                         return ;
199                 }
200                 _SysDebug("IPC Message 0x%x - %i bytes", info->ID, info->Length);
201                 dest->Handler(dest, info->ID, info->Length, info->Data);
202                 break; }
203         default:
204                 _SysDebug("Unknow message ID %i", Msg->ID);
205                 break;
206         }
207 }
208
209 void AxWin3_SetWindowTitle(tHWND Window, const char *Title)
210 {
211         tAxWin_IPCMessage       *msg;
212          int    len = strlen(Title);
213         
214         msg = AxWin3_int_AllocateIPCMessage(Window, IPCMSG_SETWINTITLE, 0, len+1);
215         strcpy(msg->Data, Title);
216         
217         AxWin3_int_SendIPCMessage(msg);
218         
219         free(msg);
220 }
221
222 void AxWin3_SendMessage(tHWND Window, tHWND Destination, int Message, int Length, void *Data)
223 {
224         tAxWin_IPCMessage       *msg;
225         tIPCMsg_SendMsg *info;
226         
227         msg = AxWin3_int_AllocateIPCMessage(Window, IPCMSG_SENDMSG, 0, sizeof(*info)+Length);
228         info = (void*)msg->Data;
229         info->Remote = AxWin3_int_GetWindowID(Destination);
230         info->ID = Message;
231         info->Length = Length;
232         memcpy(info->Data, Data, Length);
233         
234         AxWin3_int_SendIPCMessage(msg);
235         free(msg);
236 }
237
238 void AxWin3_FocusWindow(tHWND Window)
239 {
240         tAxWin_IPCMessage       *msg;
241         
242         msg = AxWin3_int_AllocateIPCMessage(Window, IPCMSG_FOCUSWINDOW, 0, 0);
243         
244         AxWin3_int_SendIPCMessage(msg);
245         free(msg);
246 }
247
248 void AxWin3_ShowWindow(tHWND Window, int bShow)
249 {
250         tAxWin_IPCMessage       *msg;
251         tIPCMsg_Boolean *info;
252
253         msg = AxWin3_int_AllocateIPCMessage(Window, IPCMSG_SHOWWINDOW, 0, sizeof(*info));
254         info = (void*)msg->Data;
255         info->Value = !!bShow;
256         
257         AxWin3_int_SendIPCMessage(msg);
258         
259         free(msg);
260 }
261
262 void AxWin3_DecorateWindow(tHWND Window, int bDecorate)
263 {
264         tAxWin_IPCMessage       *msg;
265         tIPCMsg_Boolean *info;
266
267         msg = AxWin3_int_AllocateIPCMessage(Window, IPCMSG_DECORATEWINDOW, 0, sizeof(*info));
268         info = (void*)msg->Data;
269         info->Value = !!bDecorate;
270         
271         AxWin3_int_SendIPCMessage(msg);
272         
273         free(msg);
274 }
275
276 void AxWin3_SetWindowPos(tHWND Window, short X, short Y, short W, short H)
277 {
278         tAxWin_IPCMessage       *msg;
279         tIPCMsg_SetWindowPos    *info;
280         
281         msg = AxWin3_int_AllocateIPCMessage(Window, IPCMSG_SETWINPOS, 0, sizeof(*info));
282         info = (void*)msg->Data;
283
284         info->bSetPos = 1;
285         info->bSetDims = 1;
286         info->X = X;    info->Y = Y;
287         info->W = W;    info->H = H;
288
289         AxWin3_int_SendIPCMessage(msg); 
290         free(msg);
291 }
292
293 void AxWin3_MoveWindow(tHWND Window, short X, short Y)
294 {
295         tAxWin_IPCMessage       *msg;
296         tIPCMsg_SetWindowPos    *info;
297         
298         msg = AxWin3_int_AllocateIPCMessage(Window, IPCMSG_SETWINPOS, 0, sizeof(*info));
299         info = (void*)msg->Data;
300
301         info->bSetPos = 1;
302         info->bSetDims = 0;
303         info->X = X;
304         info->Y = Y;
305         
306         AxWin3_int_SendIPCMessage(msg);
307         
308         free(msg);
309 }
310
311 void AxWin3_ResizeWindow(tHWND Window, short W, short H)
312 {
313         tAxWin_IPCMessage       *msg;
314         tIPCMsg_SetWindowPos    *info;
315         
316         msg = AxWin3_int_AllocateIPCMessage(Window, IPCMSG_SETWINPOS, 0, sizeof(*info));
317         info = (void*)msg->Data;
318
319         info->bSetPos = 0;
320         info->bSetDims = 1;
321         info->W = W;
322         info->H = H;
323         
324         AxWin3_int_SendIPCMessage(msg);
325         
326         free(msg);
327 }
328

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