2 Copyright © 1995-2010, 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
;
80 /*-- Initialization ----------------------------------------------------*/
81 if (!Initialize()) return 20; // FIXME: report error to user somehow. displaybeep? alert?
83 /*-- Event loop --------------------------------------------------------*/
84 D(bug("[WBLIB] WorkbenchHandler: entering event loop\n"));
88 ULONG signals
= Wait(hc
->hc_Signals
);
90 D(bug("[WBLIB] WorkbenchHandler: Got message(s)...\n"));
92 /*== Messages from the library =====================================*/
93 if (signals
& hc
->hc_CommandSignal
)
95 struct WBCommandMessage
*message
;
97 D(bug("[WBLIB] WorkbenchHandler: Got message(s) at command port\n"));
99 while ((message
= WBCM(GetMsg(hc
->hc_CommandPort
))) != NULL
)
101 /* Handle the message */
102 switch (message
->wbcm_Type
)
104 case WBCM_TYPE_LAUNCH
:
105 D(bug("[WBLIB] WorkbenchHandler: Got WBCM_Launch message\n"));
106 HandleLaunch(message
);
109 case WBCM_TYPE_RELAY
:
110 D(bug("[WBLIB] WorkbenchHandler: Got WBCM_Relay message\n"));
111 HandleRelay(message
);
115 /* Deallocate the message */
116 DestroyWBCM(message
);
120 /*== Message replies from started WB programs ======================*/
121 if (signals
& hc
->hc_StartupReplySignal
)
123 struct WBStartup
*message
;
125 D(bug("[WBLIB] WorkbenchHandler: Got message(s) at startup reply port\n"));
127 while ((message
= WBS(GetMsg(hc
->hc_StartupReplyPort
))) != NULL
)
129 if (message
->sm_Message
.mn_Node
.ln_Type
== NT_REPLYMSG
)
131 D(bug("[WBLIB] WorkbenchHandler: Deallocating WBStartup message and arguments\n"));
137 Eh, we should only get replies here. Just reply the
138 message and hope the sender will fail gracefully.
140 ReplyMsg((struct Message
*) message
);
145 /*== Message replies from the workbench application ================*/
146 if (signals
& hc
->hc_RelayReplySignal
)
148 struct WBHandlerMessage
*message
;
150 D(bug("[WBLIB] WorkbenchHandler: Got message(s) at relay reply port\n"));
152 while ((message
= WBHM(GetMsg(hc
->hc_RelayReplyPort
))) != NULL
)
154 if (message
->wbhm_Message
.mn_Node
.ln_Type
== NT_REPLYMSG
)
156 D(bug("[WBLIB] WorkbenchHandler: Deallocating WBHandlerMessage\n"));
157 if (message
->wbhm_Type
== WBHM_TYPE_HIDE
)
159 struct IntWBHandlerMessage
*iwbhm
= (struct IntWBHandlerMessage
*)message
;
161 D(bug("[WBLIB] WorkbenchHandler: Replying IntuiMessage because Type = "
162 "WBHM_TYPE_HIDE\n"));
163 ReplyMsg((struct Message
*)iwbhm
->iwbhm_Data
.Hide
.imsg
);
165 DestroyWBHM(message
);
169 /* FIXME: comment ;-) */
170 ReplyMsg((struct Message
*) message
);
176 /*== Messages from Intuition =======================================*/
177 if (signals
& hc
->hc_IntuitionSignal
)
179 struct IntuiMessage
*message
;
181 D(bug("[WBLIB] WorkbenchHandler: Got message(s) at intuition port\n"));
183 while ((message
= (struct IntuiMessage
*) GetMsg(hc
->hc_IntuitionPort
)))
185 HandleIntuition(message
); /* takes care of replying */
190 //FIXME: shutdown not properly implemented
200 static BOOL __Initialize_WB
202 struct HandlerContext
*hc
, struct WorkbenchBase
*WorkbenchBase
205 /* Create message ports ------------------------------------------------*/
208 (hc
->hc_StartupReplyPort
= CreateMsgPort()) != NULL
209 && (hc
->hc_RelayReplyPort
= CreateMsgPort()) != NULL
210 && (hc
->hc_IntuitionPort
= CreateMsgPort()) != NULL
213 /* Store command port ----------------------------------------------*/
214 hc
->hc_CommandPort
= &(WorkbenchBase
->wb_HandlerPort
);
216 /* Calculate and store signal flags --------------------------------*/
217 hc
->hc_CommandSignal
= 1UL << hc
->hc_CommandPort
->mp_SigBit
;
218 hc
->hc_StartupReplySignal
= 1UL << hc
->hc_StartupReplyPort
->mp_SigBit
;
219 hc
->hc_RelayReplySignal
= 1UL << hc
->hc_RelayReplyPort
->mp_SigBit
;
220 hc
->hc_IntuitionSignal
= 1UL << hc
->hc_IntuitionPort
->mp_SigBit
;
222 hc
->hc_Signals
= hc
->hc_CommandSignal
223 | hc
->hc_StartupReplySignal
224 | hc
->hc_RelayReplySignal
225 | hc
->hc_IntuitionSignal
;
227 /* We're now ready to accept messages ------------------------------*/
228 WorkbenchBase
->wb_HandlerPort
.mp_SigTask
= FindTask(NULL
);
229 WorkbenchBase
->wb_HandlerPort
.mp_Flags
= PA_SIGNAL
;
231 /* Make sure to process messages that arrived before we were ready -*/
232 Signal(FindTask(NULL
), SIGBREAKF_CTRL_F
);
234 /* Register ourselves with Intuition -------------------------------*/
235 AlohaWorkbench(hc
->hc_IntuitionPort
);
247 static VOID __Deinitialize_WB
249 struct HandlerContext
*hc
, struct WorkbenchBase
*WorkbenchBase
252 /* Unregister ourselves with Intuition ---------------------------------*/
253 AlohaWorkbench(NULL
);
255 /* We no longer accept messages ----------------------------------------*/
256 WorkbenchBase
->wb_HandlerPort
.mp_Flags
= PA_IGNORE
;
257 WorkbenchBase
->wb_HandlerPort
.mp_SigTask
= NULL
;
259 /* Deallocate message ports --------------------------------------------*/
260 // FIXME: should we get & deallocate all queued messages?
261 if (hc
->hc_IntuitionPort
!= NULL
) DeleteMsgPort(hc
->hc_IntuitionPort
);
262 if (hc
->hc_RelayReplyPort
!= NULL
) DeleteMsgPort(hc
->hc_RelayReplyPort
);
263 if (hc
->hc_StartupReplyPort
!= NULL
) DeleteMsgPort(hc
->hc_StartupReplyPort
);
266 static VOID __HandleLaunch_WB
268 struct WBCommandMessage
*message
,
269 struct HandlerContext
*hc
, struct WorkbenchBase
*WorkbenchBase
272 struct WBStartup
*startup
= message
->wbcm_Data
.Launch
.Startup
;
273 struct TagItem
*msgTags
= (struct TagItem
*)message
->wbcm_Tags
;
274 struct TagItem
*foundTag
= NULL
;
276 STRPTR name
= startup
->sm_ArgList
[0].wa_Name
;
277 BPTR lock
= startup
->sm_ArgList
[0].wa_Lock
;
280 IPTR stacksize
= WorkbenchBase
->wb_DefaultStackSize
;
282 struct Process
*process
;
284 D(bug("[WBLIB] __HandleLaunch_WB('%s')\n", name
));
288 foundTag
= FindTagItem(NP_StackSize
, msgTags
);
289 if (foundTag
!= NULL
)
291 stacksize
= foundTag
->ti_Data
;
294 foundTag
= FindTagItem(NP_Priority
, msgTags
);
295 if (foundTag
!= NULL
)
297 priority
= foundTag
->ti_Data
;
300 FreeTagItems(msgTags
);
303 /* Change directory to where the program resides */
304 cd
= CurrentDir(startup
->sm_ArgList
[0].wa_Lock
);
306 /* Load the program from disk */
307 if (startup
->sm_Segment
== BNULL
)
308 startup
->sm_Segment
= LoadSeg(name
);
309 if (startup
->sm_Segment
== BNULL
) goto error
;
311 /* Duplicate lock for NP_HomeDir */
312 home
= DupLock(lock
);
313 if (home
== BNULL
) goto error
;
315 const struct TagItem tags
[]=
317 {NP_Seglist
, (IPTR
)startup
->sm_Segment
},
318 {NP_Name
, (IPTR
)name
},
319 {NP_HomeDir
, (IPTR
)home
},
320 {NP_StackSize
, stacksize
},
321 {NP_Priority
, priority
},
322 {NP_Input
, (IPTR
)BNULL
},
323 {NP_Output
, (IPTR
)BNULL
},
324 {NP_CurrentDir
, (IPTR
)BNULL
},
328 D(bug("[WBLIB] __HandleLaunch_WB: Starting '%s' with %d stack\n", tags
[1].ti_Data
, tags
[3].ti_Data
));
330 /* Launch the program */
331 process
= CreateNewProc(tags
);
335 D(bug("[WBLIB] __HandleLaunch_WB: Process created successfully @ %p\n", process
));
337 /* Setup startup message */
338 startup
->sm_Process
= &process
->pr_MsgPort
;
339 startup
->sm_Message
.mn_ReplyPort
= hc
->hc_StartupReplyPort
;
341 /* Send startup message to program */
342 PutMsg(startup
->sm_Process
, (struct Message
*) startup
);
348 //FIXME: report error somehow?
349 D(bug("[WBLIB] __HandleLaunch_WB: Failed to launch program. Deallocating resources.\n"));
350 if (startup
->sm_Segment
!= BNULL
) UnLoadSeg(startup
->sm_Segment
);
354 /* Restore current directory */
358 static VOID __HandleRelay_WB
360 struct WBCommandMessage
*message
,
361 struct HandlerContext
*hc
, struct WorkbenchBase
*WorkbenchBase
364 struct WBHandlerMessage
*relaymsg
= message
->wbcm_Data
.Relay
.Message
;
366 D(bug("[WBLIB] __HandleRelay_WB: Relaying message to workbench application\n"));
367 D(bug("[WBLIB] __HandleRelay_WB: destination port %p\n", WorkbenchBase
->wb_WorkbenchPort
));
368 relaymsg
->wbhm_Message
.mn_ReplyPort
= hc
->hc_RelayReplyPort
;
369 PutMsg(WorkbenchBase
->wb_WorkbenchPort
, (struct Message
*) relaymsg
);
372 static void __HandleIntuition_WB
374 struct IntuiMessage
*message
,
375 struct HandlerContext
*hc
, struct WorkbenchBase
*WorkbenchBase
378 struct IntWBHandlerMessage
*iwbhm
;
380 if (message
->Class
== IDCMP_WBENCHMESSAGE
)
382 switch (message
->Code
)
385 D(bug("[WBLIB] __HandleIntuition_WB: WBENCHOPEN\n"));
386 iwbhm
= CreateIWBHM(WBHM_TYPE_SHOW
, hc
->hc_RelayReplyPort
);
389 D(bug("[WBLIB] __HandleIntuition_WB: WBENCHCLOSE\n"));
390 iwbhm
= CreateIWBHM(WBHM_TYPE_HIDE
, hc
->hc_RelayReplyPort
);
391 iwbhm
->iwbhm_Data
.Hide
.imsg
= message
;
398 if ((iwbhm
!= NULL
) && (WorkbenchBase
->wb_WorkbenchPort
!= NULL
))
400 D(bug("[WBLIB] __HandleIntuition_WB: Forwarding message to Workbench port @ %p\n", WorkbenchBase
->wb_WorkbenchPort
));
401 PutMsg(WorkbenchBase
->wb_WorkbenchPort
, (struct Message
*)iwbhm
);
403 /* Don't reply immediately if we're asked to close the WB,
404 we'll do it when handling replied message, so that the WB
405 will have a chance to close its windows. */
406 if (message
->Code
== WBENCHCLOSE
)
411 ReplyMsg((struct Message
*) message
);