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;
24 //! Hilighted window (owner of the currently focused window)
25 tWindow *gpWM_HilightedWindow;
28 void WM_Initialise(void)
30 WM_CreateWindow(NULL, NULL, 0, 0x0088FF, "Background");
31 gpWM_RootWindow->W = giScreenWidth;
32 gpWM_RootWindow->H = giScreenHeight;
33 gpWM_RootWindow->Flags = WINFLAG_SHOW|WINFLAG_NODECORATE;
36 void WM_RegisterRenderer(tWMRenderer *Renderer)
38 // TODO: Catch out duplicates
39 Renderer->Next = gpWM_Renderers;
40 gpWM_Renderers = Renderer;
44 tWindow *WM_CreateWindow(tWindow *Parent, tIPC_Client *Client, uint32_t ID, int RendererArg, const char *RendererName)
46 tWMRenderer *renderer;
50 for( renderer = gpWM_Renderers; renderer; renderer = renderer->Next )
52 if(strcmp(RendererName, renderer->Name) == 0)
58 // - Call create window function
59 ret = renderer->CreateWindow(RendererArg);
64 ret->Parent = gpWM_RootWindow;
66 ret->Renderer = renderer;
67 ret->Flags |= WINFLAG_CLEAN; // Needed to stop invaildate early exiting
72 if(ret->Parent->LastChild)
73 ret->Parent->LastChild->NextSibling = ret;
75 ret->Parent->FirstChild = ret;
76 ret->PrevSibling = ret->Parent->LastChild;
77 ret->Parent->LastChild = ret;
78 ret->NextSibling = NULL;
82 gpWM_RootWindow = ret;
85 // Don't decorate child windows by default
88 ret->Flags |= WINFLAG_NODECORATE;
95 tWindow *WM_CreateWindowStruct(size_t ExtraSize)
99 ret = calloc( sizeof(tWindow) + ExtraSize, 1 );
100 ret->RendererInfo = ret + 1; // Get end of tWindow
105 void WM_SetWindowTitle(tWindow *Window, const char *Title)
109 Window->Title = strdup(Title);
110 _SysDebug("Window %p title set to '%s'", Window, Title);
113 void WM_RaiseWindow(tWindow *Window)
115 tWindow *parent = Window->Parent;
116 if(!Window->Parent) return ;
119 if(Window->PrevSibling)
120 Window->PrevSibling->NextSibling = Window->NextSibling;
121 if(Window->NextSibling)
122 Window->NextSibling->PrevSibling = Window->PrevSibling;
123 if(parent->FirstChild == Window)
124 parent->FirstChild = Window->NextSibling;
125 if(parent->LastChild == Window)
126 parent->LastChild = Window->PrevSibling;
129 if(parent->LastChild)
130 parent->LastChild->NextSibling = Window;
132 parent->FirstChild = Window;
133 Window->PrevSibling = parent->LastChild;
134 Window->NextSibling = NULL;
135 parent->LastChild = Window;
138 void WM_FocusWindow(tWindow *Destination)
140 struct sWndMsg_Bool _msg;
142 if( gpWM_FocusedWindow == Destination )
144 if( Destination && !(Destination->Flags & WINFLAG_SHOW) )
148 WM_SendMessage(NULL, gpWM_FocusedWindow, WNDMSG_FOCUS, sizeof(_msg), &_msg);
150 WM_SendMessage(NULL, Destination, WNDMSG_FOCUS, sizeof(_msg), &_msg);
152 WM_Invalidate(gpWM_FocusedWindow);
153 WM_Invalidate(Destination);
154 gpWM_FocusedWindow = Destination;
157 // Get the owner of the focused window
158 // while(Destination && Destination->Owner) Destination = Destination->Owner;
159 // gpWM_HilightedWindow = Destination;
163 void WM_ShowWindow(tWindow *Window, int bShow)
165 struct sWndMsg_Bool _msg;
167 if( !!(Window->Flags & WINFLAG_SHOW) == bShow )
172 WM_SendMessage(NULL, Window, WNDMSG_SHOW, sizeof(_msg), &_msg);
176 Window->Flags |= WINFLAG_SHOW;
179 Window->Flags &= ~WINFLAG_SHOW;
181 if( Window == gpWM_FocusedWindow )
182 WM_FocusWindow(Window->Parent);
184 // Just a little memory saving for large hidden windows
185 if(Window->RenderBuffer) {
186 free(Window->RenderBuffer);
187 Window->RenderBuffer = NULL;
191 WM_Invalidate(Window);
194 void WM_DecorateWindow(tWindow *Window, int bDecorate)
196 if( !(Window->Flags & WINFLAG_NODECORATE) == !!bDecorate )
200 Window->Flags &= ~WINFLAG_NODECORATE;
202 Window->Flags |= WINFLAG_NODECORATE;
204 // Needed because the window size changes
205 if(Window->RenderBuffer) {
206 free(Window->RenderBuffer);
207 Window->RenderBuffer = NULL;
210 WM_Invalidate(Window);
213 int WM_MoveWindow(tWindow *Window, int X, int Y)
216 if(X + Window->W < 0) X = -Window->W + 1;
217 if(Y + Window->H < 0) Y = -Window->H + 1;
218 if(X >= giScreenWidth) X = giScreenWidth - 1;
219 if(Y >= giScreenHeight) Y = giScreenHeight - 1;
221 Window->X = X; Window->Y = Y;
223 WM_Invalidate(Window);
228 int WM_ResizeWindow(tWindow *Window, int W, int H)
230 if(W <= 0 || H <= 0 ) return 1;
231 if(Window->X + W < 0) Window->X = -W + 1;
232 if(Window->Y + H < 0) Window->Y = -H + 1;
234 Window->W = W; Window->H = H;
236 if(Window->RenderBuffer) {
237 free(Window->RenderBuffer);
238 Window->RenderBuffer = NULL;
240 WM_Invalidate(Window);
243 struct sWndMsg_Resize msg;
246 WM_SendMessage(NULL, Window, WNDMSG_RESIZE, sizeof(msg), &msg);
252 int WM_SendMessage(tWindow *Source, tWindow *Dest, int Message, int Length, const void *Data)
254 if(Dest == NULL) return -2;
255 if(Length > 0 && Data == NULL) return -1;
257 if( Decorator_HandleMessage(Dest, Message, Length, Data) != 1 )
259 // TODO: Catch errors from ->HandleMessage
263 // ->HandleMessage returns 1 when the message was not handled
264 if( Dest->Renderer->HandleMessage(Dest, Message, Length, Data) != 1 )
266 // TODO: Catch errors from ->HandleMessage
270 // TODO: Implement message masking
277 else if(Source->Client != Dest->Client) {
278 // TODO: Support different client source windows
279 _SysDebug("WM_SendMessage: TODO - Support inter-client messages");
286 IPC_SendWMMessage(Dest->Client, src_id, Dest->ID, Message, Length, Data);
292 void WM_Invalidate(tWindow *Window)
295 _SysDebug("Invalidating %p", Window);
296 // Don't invalidate twice (speedup)
297 // if( !(Window->Flags & WINFLAG_CLEAN) ) return;
299 // Mark for re-render
300 Window->Flags &= ~WINFLAG_CLEAN;
302 // Mark up the tree that a child window has changed
303 while( (Window = Window->Parent) )
304 Window->Flags &= ~WINFLAG_CHILDCLEAN;
307 // --- Rendering / Update
308 void WM_int_UpdateWindow(tWindow *Window)
310 int bDecoratorRedraw = 0;
312 // Ignore hidden windows
313 if( !(Window->Flags & WINFLAG_SHOW) )
317 if( !(Window->Flags & WINFLAG_CLEAN) )
319 // Calculate RealW/RealH
320 if( !(Window->Flags & WINFLAG_NODECORATE) )
322 _SysDebug("Applying decorations to %p", Window);
323 Decorator_UpdateBorderSize(Window);
324 Window->RealW = Window->BorderL + Window->W + Window->BorderR;
325 Window->RealH = Window->BorderT + Window->H + Window->BorderB;
326 bDecoratorRedraw = 1;
334 Window->RealW = Window->W;
335 Window->RealH = Window->H;
338 Window->Renderer->Redraw(Window);
339 Window->Flags |= WINFLAG_CLEAN;
343 if( !(Window->Flags & WINFLAG_CHILDCLEAN) )
346 for( child = Window->FirstChild; child; child = child->NextSibling )
348 WM_int_UpdateWindow(child);
350 Window->Flags |= WINFLAG_CHILDCLEAN;
353 if( bDecoratorRedraw )
354 Decorator_Redraw(Window);
357 void WM_int_BlitWindow(tWindow *Window)
361 // Ignore hidden windows
362 if( !(Window->Flags & WINFLAG_SHOW) )
365 // _SysDebug("Blit %p to (%i,%i) %ix%i", Window, Window->X, Window->Y, Window->RealW, Window->RealH);
366 Video_Blit(Window->RenderBuffer, Window->X, Window->Y, Window->RealW, Window->RealH);
368 if( Window == gpWM_FocusedWindow && Window->CursorW )
371 Window->X + Window->BorderL + Window->CursorX,
372 Window->Y + Window->BorderT + Window->CursorY,
373 Window->CursorW, Window->CursorH,
379 for( child = Window->FirstChild; child; child = child->NextSibling )
381 WM_int_BlitWindow(child);
387 // Don't redraw if nothing has changed
388 if( (gpWM_RootWindow->Flags & WINFLAG_CHILDCLEAN) )
391 // - Iterate through visible windows, updating them as needed
392 WM_int_UpdateWindow(gpWM_RootWindow);
394 // - Draw windows from back to front to the render buffer
395 WM_int_BlitWindow(gpWM_RootWindow);