2 * Acess2 Window Manager v3
3 * - By John Hodge (thePowersGang)
6 * - Window manager core
9 #include <wm_renderer.h>
13 #include <wm_messages.h>
14 #include <decorator.h>
17 extern void IPC_SendWMMessage(tIPC_Client *Client, uint32_t Src, uint32_t Dst, int Msg, int Len, const void *Data);
20 tWMRenderer *gpWM_Renderers;
21 tWindow *gpWM_RootWindow;
22 //! Window which will recieve the next keyboard event
23 tWindow *gpWM_FocusedWindow;
26 void WM_Initialise(void)
28 WM_CreateWindow(NULL, NULL, 0, 0x0088FF, "Background");
29 gpWM_RootWindow->W = giScreenWidth;
30 gpWM_RootWindow->H = giScreenHeight;
31 gpWM_RootWindow->Flags = WINFLAG_SHOW|WINFLAG_NODECORATE;
34 void WM_RegisterRenderer(tWMRenderer *Renderer)
36 // TODO: Catch out duplicates
37 Renderer->Next = gpWM_Renderers;
38 gpWM_Renderers = Renderer;
42 tWindow *WM_CreateWindow(tWindow *Parent, tIPC_Client *Client, uint32_t ID, int RendererArg, const char *RendererName)
44 tWMRenderer *renderer;
48 for( renderer = gpWM_Renderers; renderer; renderer = renderer->Next )
50 if(strcmp(RendererName, renderer->Name) == 0)
57 Parent = gpWM_RootWindow;
59 // - Call create window function
60 ret = renderer->CreateWindow(RendererArg);
64 ret->Renderer = renderer;
65 ret->Flags |= WINFLAG_CLEAN; // Needed to stop invaildate early exiting
71 Parent->LastChild->NextSibling = ret;
73 Parent->FirstChild = ret;
74 ret->PrevSibling = Parent->LastChild;
75 Parent->LastChild = ret;
76 ret->NextSibling = NULL;
80 gpWM_RootWindow = ret;
83 // Don't decorate child windows by default
84 if(Parent != gpWM_RootWindow)
86 ret->Flags |= WINFLAG_NODECORATE;
93 tWindow *WM_CreateWindowStruct(size_t ExtraSize)
97 ret = calloc( sizeof(tWindow) + ExtraSize, 1 );
98 ret->RendererInfo = ret + 1; // Get end of tWindow
103 void WM_SetWindowTitle(tWindow *Window, const char *Title)
107 Window->Title = strdup(Title);
108 _SysDebug("Window %p title set to '%s'", Window, Title);
111 void WM_RaiseWindow(tWindow *Window)
113 tWindow *parent = Window->Parent;
114 if(!Window->Parent) return ;
117 if(Window->PrevSibling)
118 Window->PrevSibling->NextSibling = Window->NextSibling;
119 if(Window->NextSibling)
120 Window->NextSibling->PrevSibling = Window->PrevSibling;
121 if(parent->FirstChild == Window)
122 parent->FirstChild = Window->NextSibling;
123 if(parent->LastChild == Window)
124 parent->LastChild = Window->PrevSibling;
127 if(parent->LastChild)
128 parent->LastChild->NextSibling = Window;
130 parent->FirstChild = Window;
131 Window->PrevSibling = parent->LastChild;
132 Window->NextSibling = NULL;
133 parent->LastChild = Window;
136 void WM_FocusWindow(tWindow *Destination)
138 struct sWndMsg_Bool _msg;
140 if( gpWM_FocusedWindow == Destination )
142 if( Destination && !(Destination->Flags & WINFLAG_SHOW) )
146 WM_SendMessage(NULL, gpWM_FocusedWindow, WNDMSG_FOCUS, sizeof(_msg), &_msg);
148 WM_SendMessage(NULL, Destination, WNDMSG_FOCUS, sizeof(_msg), &_msg);
150 gpWM_FocusedWindow = Destination;
154 void WM_ShowWindow(tWindow *Window, int bShow)
157 struct sWndMsg_Bool _msg;
159 if( !!(Window->Flags & WINFLAG_SHOW) == bShow )
163 WM_SendMessage(NULL, Window, WNDMSG_SHOW, sizeof(_msg), &_msg);
166 Window->Flags |= WINFLAG_SHOW;
168 Window->Flags &= ~WINFLAG_SHOW;
169 if( Window == gpWM_FocusedWindow )
170 WM_FocusWindow(Window->Parent);
172 // Just a little memory saving for large hidden windows
173 if(Window->RenderBuffer)
174 free(Window->RenderBuffer);
176 WM_Invalidate(Window);
179 void WM_DecorateWindow(tWindow *Window, int bDecorate)
181 if( !(Window->Flags & WINFLAG_NODECORATE) == !!bDecorate )
185 Window->Flags &= ~WINFLAG_NODECORATE;
187 Window->Flags |= WINFLAG_NODECORATE;
189 // Needed because the window size changes
190 if(Window->RenderBuffer)
191 free(Window->RenderBuffer);
193 WM_Invalidate(Window);
196 int WM_MoveWindow(tWindow *Window, int X, int Y)
199 if(X + Window->W < 0) X = -Window->W + 1;
200 if(Y + Window->H < 0) Y = -Window->H + 1;
201 if(X >= giScreenWidth) X = giScreenWidth - 1;
202 if(Y >= giScreenHeight) Y = giScreenHeight - 1;
204 Window->X = X; Window->Y = Y;
206 WM_Invalidate(Window);
211 int WM_ResizeWindow(tWindow *Window, int W, int H)
213 if(W <= 0 || H <= 0 ) return 1;
214 if(Window->X + W < 0) Window->X = -W + 1;
215 if(Window->Y + H < 0) Window->Y = -H + 1;
217 Window->W = W; Window->H = H;
219 if(Window->RenderBuffer)
220 free(Window->RenderBuffer);
221 WM_Invalidate(Window);
224 struct sWndMsg_Resize msg;
227 WM_SendMessage(NULL, Window, WNDMSG_RESIZE, sizeof(msg), &msg);
233 int WM_SendMessage(tWindow *Source, tWindow *Dest, int Message, int Length, const void *Data)
235 if(Dest == NULL) return -2;
236 if(Length > 0 && Data == NULL) return -1;
238 if( Decorator_HandleMessage(Dest, Message, Length, Data) != 1 )
240 // TODO: Catch errors from ->HandleMessage
244 // ->HandleMessage returns 1 when the message was not handled
245 if( Dest->Renderer->HandleMessage(Dest, Message, Length, Data) != 1 )
247 // TODO: Catch errors from ->HandleMessage
251 // TODO: Implement message masking
258 else if(Source->Client != Dest->Client) {
259 // TODO: Support different client source windows
260 _SysDebug("WM_SendMessage: TODO - Support inter-client messages");
267 IPC_SendWMMessage(Dest->Client, src_id, Dest->ID, Message, Length, Data);
273 void WM_Invalidate(tWindow *Window)
275 _SysDebug("Invalidating %p", Window);
276 // Don't invalidate twice (speedup)
277 // if( !(Window->Flags & WINFLAG_CLEAN) ) return;
279 // Mark for re-render
280 Window->Flags &= ~WINFLAG_CLEAN;
282 // Mark up the tree that a child window has changed
283 while( (Window = Window->Parent) )
284 Window->Flags &= ~WINFLAG_CHILDCLEAN;
287 // --- Rendering / Update
288 void WM_int_UpdateWindow(tWindow *Window)
292 // Ignore hidden windows
293 if( !(Window->Flags & WINFLAG_SHOW) )
297 if( !(Window->Flags & WINFLAG_CLEAN) )
299 // Calculate RealW/RealH
300 if( !(Window->Flags & WINFLAG_NODECORATE) )
302 _SysDebug("Applying decorations to %p", Window);
303 Decorator_UpdateBorderSize(Window);
304 Window->RealW = Window->BorderL + Window->W + Window->BorderR;
305 Window->RealH = Window->BorderT + Window->H + Window->BorderB;
306 Decorator_Redraw(Window);
314 Window->RealW = Window->W;
315 Window->RealH = Window->H;
318 Window->Renderer->Redraw(Window);
319 Window->Flags |= WINFLAG_CLEAN;
323 if( !(Window->Flags & WINFLAG_CHILDCLEAN) )
325 for( child = Window->FirstChild; child; child = child->NextSibling )
327 WM_int_UpdateWindow(child);
329 Window->Flags |= WINFLAG_CHILDCLEAN;
334 void WM_int_BlitWindow(tWindow *Window)
338 // Ignore hidden windows
339 if( !(Window->Flags & WINFLAG_SHOW) )
342 _SysDebug("Blit %p to (%i,%i) %ix%i", Window, Window->X, Window->Y, Window->RealW, Window->RealH);
343 Video_Blit(Window->RenderBuffer, Window->X, Window->Y, Window->RealW, Window->RealH);
345 for( child = Window->FirstChild; child; child = child->NextSibling )
347 WM_int_BlitWindow(child);
353 // Don't redraw if nothing has changed
354 if( (gpWM_RootWindow->Flags & WINFLAG_CHILDCLEAN) )
357 // - Iterate through visible windows, updating them as needed
358 WM_int_UpdateWindow(gpWM_RootWindow);
360 // - Draw windows from back to front to the render buffer
361 WM_int_BlitWindow(gpWM_RootWindow);