2 Copyright © 1995-2006, The AROS Development Team. All rights reserved.
5 The Workbench Handler process and associated functions.
9 #include <aros/debug.h>
11 #include <exec/ports.h>
12 #include <utility/hooks.h>
13 #include <dos/dosextens.h>
15 #include <proto/alib.h>
16 #include <proto/intuition.h>
17 #include <proto/workbench.h>
18 #include <proto/utility.h>
19 #include <proto/exec.h>
20 #include <proto/dos.h>
22 #include <workbench/workbench.h>
23 #include <workbench/startup.h>
25 #include "workbench_intern.h"
27 #include "support_messages.h"
29 #include "handler_support.h"
33 /* Ports and signals ---------------------------------------------------*/
34 struct MsgPort
*hc_CommandPort
; /* Command messages from the library */
35 ULONG hc_CommandSignal
; /* Signal bit field for the above */
36 struct MsgPort
*hc_StartupReplyPort
; /* Replies to startup messages */
37 ULONG hc_StartupReplySignal
; /* Signal bit field for the above */
38 struct MsgPort
*hc_RelayReplyPort
; /* Replies to messages sent to the workbench application */
39 ULONG hc_RelayReplySignal
; /* Signal bit field for the above */
40 struct MsgPort
*hc_IntuitionPort
; /* Messages from Intuition */
41 ULONG hc_IntuitionSignal
; /* Signal bit field for the above */
43 ULONG hc_Signals
; /* Mask from all signals above */
47 /*** Prototypes *************************************************************/
48 static BOOL
__Initialize_WB(struct HandlerContext
*hc
, struct WorkbenchBase
*WorkbenchBase
);
49 static VOID
__Deinitialize_WB(struct HandlerContext
*hc
, struct WorkbenchBase
*WorkbenchBase
);
51 static VOID
__HandleLaunch_WB(struct WBCommandMessage
*message
, struct HandlerContext
*hc
, struct WorkbenchBase
*WorkbenchBase
);
52 static VOID
__HandleRelay_WB(struct WBCommandMessage
*message
, struct HandlerContext
*hc
, struct WorkbenchBase
*WorkbenchBase
);
53 static VOID
__HandleIntuition_WB(struct IntuiMessage
*message
, struct HandlerContext
*hc
, struct WorkbenchBase
*WorkbenchBase
);
55 /*** Macros *****************************************************************/
56 #define Initialize() (__Initialize_WB(hc, WorkbenchBase))
57 #define Deinitialize() (__Deinitialize_WB(hc, WorkbenchBase))
59 #define HandleLaunch(message) (__HandleLaunch_WB((message), hc, WorkbenchBase))
60 #define HandleRelay(message) (__HandleRelay_WB((message), hc, WorkbenchBase))
61 #define HandleIntuition(message) (__HandleIntuition_WB((message), hc, WorkbenchBase))
63 /*** Entry point ************************************************************/
66 LONG
, WorkbenchHandler
,
67 AROS_UFHA(STRPTR
, args
, A0
),
68 AROS_UFHA(ULONG
, argsLength
, D0
),
69 AROS_UFHA(struct ExecBase
*, SysBase
, A6
)
74 struct WorkbenchBase
*WorkbenchBase
= FindTask(NULL
)->tc_UserData
;
75 struct HandlerContext context
= { 0 };
76 struct HandlerContext
*hc
= &context
;
79 /*-- Initialization ----------------------------------------------------*/
80 if (!Initialize()) return 20; // FIXME: report error to user somehow. displaybeep? alert?
82 /*-- Event loop --------------------------------------------------------*/
83 D(bug("[WBLIB] WorkbenchHandler: entering event loop\n"));
87 ULONG signals
= Wait(hc
->hc_Signals
);
89 D(bug("[WBLIB] WorkbenchHandler: Got message(s)...\n"));
91 /*== Messages from the library =====================================*/
92 if (signals
& hc
->hc_CommandSignal
)
94 struct WBCommandMessage
*message
;
96 D(bug("[WBLIB] WorkbenchHandler: Got message(s) at command port\n"));
98 while ((message
= WBCM(GetMsg(hc
->hc_CommandPort
))) != NULL
)
100 /* Handle the message */
101 switch (message
->wbcm_Type
)
103 case WBCM_TYPE_LAUNCH
:
104 D(bug("[WBLIB] WorkbenchHandler: Got WBCM_Launch message\n"));
105 HandleLaunch(message
);
108 case WBCM_TYPE_RELAY
:
109 D(bug("[WBLIB] WorkbenchHandler: Got WBCM_Relay message\n"));
110 HandleRelay(message
);
114 /* Deallocate the message */
115 DestroyWBCM(message
);
119 /*== Message replies from started WB programs ======================*/
120 if (signals
& hc
->hc_StartupReplySignal
)
122 struct WBStartup
*message
;
124 D(bug("[WBLIB] WorkbenchHandler: Got message(s) at startup reply port\n"));
126 while ((message
= WBS(GetMsg(hc
->hc_StartupReplyPort
))) != NULL
)
128 if (message
->sm_Message
.mn_Node
.ln_Type
== NT_REPLYMSG
)
130 D(bug("[WBLIB] WorkbenchHandler: Deallocating WBStartup message and arguments\n"));
136 Eh, we should only get replies here. Just reply the
137 message and hope the sender will fail gracefully.
139 ReplyMsg((struct Message
*) message
);
144 /*== Message replies from the workbench application ================*/
145 if (signals
& hc
->hc_RelayReplySignal
)
147 struct WBHandlerMessage
*message
;
149 D(bug("[WBLIB] WorkbenchHandler: Got message(s) at relay reply port\n"));
151 while ((message
= WBHM(GetMsg(hc
->hc_RelayReplyPort
))) != NULL
)
153 if (message
->wbhm_Message
.mn_Node
.ln_Type
== NT_REPLYMSG
)
155 D(bug("[WBLIB] WorkbenchHandler: Deallocating WBHandlerMessage\n"));
156 if (message
->wbhm_Type
== WBHM_TYPE_HIDE
)
158 struct IntWBHandlerMessage
*iwbhm
= (struct IntWBHandlerMessage
*)message
;
160 D(bug("[WBLIB] WorkbenchHandler: Replying IntuiMessage because Type = "
161 "WBHM_TYPE_HIDE\n"));
162 ReplyMsg((struct Message
*)iwbhm
->iwbhm_Data
.Hide
.imsg
);
164 DestroyWBHM(message
);
168 /* FIXME: comment ;-) */
169 ReplyMsg((struct Message
*) message
);
175 /*== Messages from Intuition =======================================*/
176 if (signals
& hc
->hc_IntuitionSignal
)
178 struct IntuiMessage
*message
;
180 D(bug("[WBLIB] WorkbenchHandler: Got message(s) at intuition port\n"));
182 while ((message
= (struct IntuiMessage
*) GetMsg(hc
->hc_IntuitionPort
)))
184 HandleIntuition(message
); /* takes care of replying */
189 //FIXME: shutdown not properly implemented
199 static BOOL __Initialize_WB
201 struct HandlerContext
*hc
, struct WorkbenchBase
*WorkbenchBase
204 /* Create message ports ------------------------------------------------*/
207 (hc
->hc_StartupReplyPort
= CreateMsgPort()) != NULL
208 && (hc
->hc_RelayReplyPort
= CreateMsgPort()) != NULL
209 && (hc
->hc_IntuitionPort
= CreateMsgPort()) != NULL
212 /* Store command port ----------------------------------------------*/
213 hc
->hc_CommandPort
= &(WorkbenchBase
->wb_HandlerPort
);
215 /* Calculate and store signal flags --------------------------------*/
216 hc
->hc_CommandSignal
= 1UL << hc
->hc_CommandPort
->mp_SigBit
;
217 hc
->hc_StartupReplySignal
= 1UL << hc
->hc_StartupReplyPort
->mp_SigBit
;
218 hc
->hc_RelayReplySignal
= 1UL << hc
->hc_RelayReplyPort
->mp_SigBit
;
219 hc
->hc_IntuitionSignal
= 1UL << hc
->hc_IntuitionPort
->mp_SigBit
;
221 hc
->hc_Signals
= hc
->hc_CommandSignal
222 | hc
->hc_StartupReplySignal
223 | hc
->hc_RelayReplySignal
224 | hc
->hc_IntuitionSignal
;
226 /* We're now ready to accept messages ------------------------------*/
227 WorkbenchBase
->wb_HandlerPort
.mp_SigTask
= FindTask(NULL
);
228 WorkbenchBase
->wb_HandlerPort
.mp_Flags
= PA_SIGNAL
;
230 /* Make sure to process messages that arrived before we were ready -*/
231 Signal(FindTask(NULL
), SIGBREAKF_CTRL_F
);
233 /* Register ourselves with Intuition -------------------------------*/
234 AlohaWorkbench(hc
->hc_IntuitionPort
);
246 static VOID __Deinitialize_WB
248 struct HandlerContext
*hc
, struct WorkbenchBase
*WorkbenchBase
251 /* Unregister ourselves with Intuition ---------------------------------*/
252 AlohaWorkbench(NULL
);
254 /* We no longer accept messages ----------------------------------------*/
255 WorkbenchBase
->wb_HandlerPort
.mp_Flags
= PA_IGNORE
;
256 WorkbenchBase
->wb_HandlerPort
.mp_SigTask
= NULL
;
258 /* Deallocate message ports --------------------------------------------*/
259 // FIXME: should we get & deallocate all queued messages?
260 if (hc
->hc_IntuitionPort
!= NULL
) DeleteMsgPort(hc
->hc_IntuitionPort
);
261 if (hc
->hc_RelayReplyPort
!= NULL
) DeleteMsgPort(hc
->hc_RelayReplyPort
);
262 if (hc
->hc_StartupReplyPort
!= NULL
) DeleteMsgPort(hc
->hc_StartupReplyPort
);
265 static VOID __HandleLaunch_WB
267 struct WBCommandMessage
*message
,
268 struct HandlerContext
*hc
, struct WorkbenchBase
*WorkbenchBase
271 struct WBStartup
*startup
= message
->wbcm_Data
.Launch
.Startup
;
272 struct TagItem
*msgTags
= (struct TagItem
*)message
->wbcm_Tags
;
273 struct TagItem
*foundTag
= NULL
;
275 STRPTR name
= startup
->sm_ArgList
[0].wa_Name
;
276 BPTR lock
= startup
->sm_ArgList
[0].wa_Lock
;
279 IPTR stacksize
= WorkbenchBase
->wb_DefaultStackSize
;
280 struct Process
*process
;
282 D(bug("[WBLIB] __HandleLaunch_WB('%s')\n", name
));
286 if ((foundTag
= FindTagItem(NP_StackSize
, msgTags
)) != NULL
)
287 stacksize
= foundTag
->ti_Data
;
288 FreeTagItems(msgTags
);
291 /* Change directory to where the program resides */
292 cd
= CurrentDir(startup
->sm_ArgList
[0].wa_Lock
);
294 /* Load the program from disk */
295 startup
->sm_Segment
= LoadSeg(name
);
296 if (startup
->sm_Segment
== NULL
) goto error
;
298 /* Duplicate lock for NP_HomeDir */
299 home
= DupLock(lock
);
300 if (home
== NULL
) goto error
;
302 const struct TagItem tags
[]=
304 {NP_Seglist
, (IPTR
)startup
->sm_Segment
},
305 {NP_Name
, (IPTR
)name
},
306 {NP_HomeDir
, (IPTR
)home
},
307 {NP_StackSize
, stacksize
},
311 D(bug("[WBLIB] __HandleLaunch_WB: Starting '%s' with %d stack\n", tags
[1].ti_Data
, tags
[3].ti_Data
));
313 /* Launch the program */
314 process
= CreateNewProc(tags
);
318 D(bug("[WBLIB] __HandleLaunch_WB: Process created successfully @ %p\n", process
));
320 /* Setup startup message */
321 startup
->sm_Process
= &process
->pr_MsgPort
;
322 startup
->sm_Message
.mn_ReplyPort
= hc
->hc_StartupReplyPort
;
324 /* Send startup message to program */
325 PutMsg(startup
->sm_Process
, (struct Message
*) startup
);
331 //FIXME: report error somehow?
332 D(bug("[WBLIB] __HandleLaunch_WB: Failed to launch program. Deallocating resources.\n"));
333 if (startup
->sm_Segment
!= NULL
) UnLoadSeg(startup
->sm_Segment
);
337 /* Restore current directory */
341 static VOID __HandleRelay_WB
343 struct WBCommandMessage
*message
,
344 struct HandlerContext
*hc
, struct WorkbenchBase
*WorkbenchBase
347 struct WBHandlerMessage
*relaymsg
= message
->wbcm_Data
.Relay
.Message
;
349 D(bug("[WBLIB] __HandleRelay_WB: Relaying message to workbench application\n"));
350 D(bug("[WBLIB] __HandleRelay_WB: destination port %p\n", WorkbenchBase
->wb_WorkbenchPort
));
351 relaymsg
->wbhm_Message
.mn_ReplyPort
= hc
->hc_RelayReplyPort
;
352 PutMsg(WorkbenchBase
->wb_WorkbenchPort
, (struct Message
*) relaymsg
);
355 static void __HandleIntuition_WB
357 struct IntuiMessage
*message
,
358 struct HandlerContext
*hc
, struct WorkbenchBase
*WorkbenchBase
361 struct IntWBHandlerMessage
*iwbhm
;
363 if (message
->Class
== IDCMP_WBENCHMESSAGE
)
365 switch (message
->Code
)
368 D(bug("[WBLIB] __HandleIntuition_WB: WBENCHOPEN\n"));
369 iwbhm
= CreateIWBHM(WBHM_TYPE_SHOW
, hc
->hc_RelayReplyPort
);
372 D(bug("[WBLIB] __HandleIntuition_WB: WBENCHCLOSE\n"));
373 iwbhm
= CreateIWBHM(WBHM_TYPE_HIDE
, hc
->hc_RelayReplyPort
);
374 iwbhm
->iwbhm_Data
.Hide
.imsg
= message
;
381 if ((iwbhm
!= NULL
) && (WorkbenchBase
->wb_WorkbenchPort
!= NULL
))
383 D(bug("[WBLIB] __HandleIntuition_WB: Forwarding message to Workbench port @ %p\n", WorkbenchBase
->wb_WorkbenchPort
));
384 PutMsg(WorkbenchBase
->wb_WorkbenchPort
, (struct Message
*)iwbhm
);
386 /* Don't reply immediately if we're asked to close the WB,
387 we'll do it when handling replied message, so that the WB
388 will have a chance to close its windows. */
389 if (message
->Code
== WBENCHCLOSE
)
394 ReplyMsg((struct Message
*) message
);