2 * Acess2 Window Manager v3
3 * - By John Hodge (thePowersGang)
6 * - Window manager core
9 #include <wm_renderer.h>
13 #include <wm_messages.h>
16 extern void IPC_SendWMMessage(tIPC_Client *Client, uint32_t Src, uint32_t Dst, int Msg, int Len, void *Data);
19 tWMRenderer *gpWM_Renderers;
20 tWindow *gpWM_RootWindow;
21 //! Window which will recieve the next keyboard event
22 tWindow *gpWM_FocusedWindow;
25 void WM_Initialise(void)
27 WM_CreateWindow(NULL, NULL, 0, 0x0088FF, "Background");
28 gpWM_RootWindow->W = giScreenWidth;
29 gpWM_RootWindow->H = giScreenHeight;
30 gpWM_RootWindow->Flags = WINFLAG_SHOW;
33 void WM_RegisterRenderer(tWMRenderer *Renderer)
35 // TODO: Catch out duplicates
36 Renderer->Next = gpWM_Renderers;
37 gpWM_Renderers = Renderer;
41 tWindow *WM_CreateWindow(tWindow *Parent, tIPC_Client *Client, uint32_t ID, int RendererArg, const char *RendererName)
43 tWMRenderer *renderer;
47 for( renderer = gpWM_Renderers; renderer; renderer = renderer->Next )
49 if(strcmp(RendererName, renderer->Name) == 0)
56 Parent = gpWM_RootWindow;
58 // - Call create window function
59 ret = renderer->CreateWindow(RendererArg);
63 ret->Renderer = renderer;
64 ret->Flags = WINFLAG_CLEAN; // Needed to stop invaildate early exiting
70 Parent->LastChild->NextSibling = ret;
72 Parent->FirstChild = ret;
73 ret->PrevSibling = Parent->LastChild;
74 Parent->LastChild = ret;
75 ret->NextSibling = NULL;
79 gpWM_RootWindow = ret;
86 tWindow *WM_CreateWindowStruct(size_t ExtraSize)
90 ret = calloc( sizeof(tWindow) + ExtraSize, 1 );
91 ret->RendererInfo = ret + 1; // Get end of tWindow
96 void WM_RaiseWindow(tWindow *Window)
98 tWindow *parent = Window->Parent;
99 if(!Window->Parent) return ;
102 if(Window->PrevSibling)
103 Window->PrevSibling->NextSibling = Window->NextSibling;
104 if(Window->NextSibling)
105 Window->NextSibling->PrevSibling = Window->PrevSibling;
106 if(parent->FirstChild == Window)
107 parent->FirstChild = Window->NextSibling;
108 if(parent->LastChild == Window)
109 parent->LastChild = Window->PrevSibling;
112 if(parent->LastChild)
113 parent->LastChild->NextSibling = Window;
115 parent->FirstChild = Window;
116 Window->PrevSibling = parent->LastChild;
117 Window->NextSibling = NULL;
118 parent->LastChild = Window;
121 void WM_FocusWindow(tWindow *Destination)
123 struct sWndMsg_Bool _msg;
125 if( gpWM_FocusedWindow == Destination )
127 if( Destination && !(Destination->Flags & WINFLAG_SHOW) )
131 WM_SendMessage(NULL, gpWM_FocusedWindow, WNDMSG_FOCUS, sizeof(_msg), &_msg);
133 WM_SendMessage(NULL, Destination, WNDMSG_FOCUS, sizeof(_msg), &_msg);
135 gpWM_FocusedWindow = Destination;
139 void WM_ShowWindow(tWindow *Window, int bShow)
142 struct sWndMsg_Bool _msg;
144 if( !!(Window->Flags & WINFLAG_SHOW) == bShow )
148 WM_SendMessage(NULL, Window, WNDMSG_SHOW, sizeof(_msg), &_msg);
151 Window->Flags |= WINFLAG_SHOW;
153 Window->Flags &= ~WINFLAG_SHOW;
154 if( Window == gpWM_FocusedWindow )
155 WM_FocusWindow(Window->Parent);
157 WM_Invalidate(Window);
160 int WM_MoveWindow(tWindow *Window, int X, int Y)
163 if(X + Window->W < 0) X = -Window->W + 1;
164 if(Y + Window->H < 0) Y = -Window->H + 1;
165 if(X >= giScreenWidth) X = giScreenWidth - 1;
166 if(Y >= giScreenHeight) Y = giScreenHeight - 1;
168 Window->X = X; Window->Y = Y;
170 WM_Invalidate(Window);
175 int WM_ResizeWindow(tWindow *Window, int W, int H)
177 if(W <= 0 || H <= 0 ) return 1;
178 if(Window->X + W < 0) Window->X = -W + 1;
179 if(Window->Y + H < 0) Window->Y = -H + 1;
181 Window->W = W; Window->H = H;
183 WM_Invalidate(Window);
186 struct sWndMsg_Resize msg;
189 WM_SendMessage(NULL, Window, WNDMSG_RESIZE, sizeof(msg), &msg);
195 int WM_SendMessage(tWindow *Source, tWindow *Dest, int Message, int Length, void *Data)
197 if(Dest == NULL) return -2;
198 if(Length > 0 && Data == NULL) return -1;
200 // ->HandleMessage returns 1 when the message was not handled
201 if( Dest->Renderer->HandleMessage(Dest, Message, Length, Data) != 1 )
203 // TODO: Catch errors from ->HandleMessage
207 // TODO: Implement message masking
214 else if(Source->Client != Dest->Client) {
215 // TODO: Support different client source windows
216 _SysDebug("WM_SendMessage: TODO - Support inter-client messages");
223 IPC_SendWMMessage(Dest->Client, src_id, Dest->ID, Message, Length, Data);
229 void WM_Invalidate(tWindow *Window)
231 _SysDebug("Invalidating %p", Window);
232 // Don't invalidate twice (speedup)
233 // if( !(Window->Flags & WINFLAG_CLEAN) ) return;
235 // Mark for re-render
236 Window->Flags &= ~WINFLAG_CLEAN;
238 // Mark up the tree that a child window has changed
239 while( (Window = Window->Parent) )
240 Window->Flags &= ~WINFLAG_CHILDCLEAN;
243 // --- Rendering / Update
244 void WM_int_UpdateWindow(tWindow *Window)
248 // Ignore hidden windows
249 if( !(Window->Flags & WINFLAG_SHOW) )
253 if( !(Window->Flags & WINFLAG_CLEAN) )
255 Window->Renderer->Redraw(Window);
256 Window->Flags |= WINFLAG_CLEAN;
260 if( !(Window->Flags & WINFLAG_CHILDCLEAN) )
262 for( child = Window->FirstChild; child; child = child->NextSibling )
264 WM_int_UpdateWindow(child);
266 Window->Flags |= WINFLAG_CHILDCLEAN;
271 void WM_int_BlitWindow(tWindow *Window)
275 // Ignore hidden windows
276 if( !(Window->Flags & WINFLAG_SHOW) )
279 _SysDebug("Blit %p to (%i,%i) %ix%i", Window, Window->X, Window->Y, Window->W, Window->H);
280 Video_Blit(Window->RenderBuffer, Window->X, Window->Y, Window->W, Window->H);
282 for( child = Window->FirstChild; child; child = child->NextSibling )
284 WM_int_BlitWindow(child);
290 // Don't redraw if nothing has changed
291 if( (gpWM_RootWindow->Flags & WINFLAG_CHILDCLEAN) )
294 // - Iterate through visible windows, updating them as needed
295 WM_int_UpdateWindow(gpWM_RootWindow);
297 // - Draw windows from back to front to the render buffer
298 WM_int_BlitWindow(gpWM_RootWindow);