2 Copyright © 1995-2006, The AROS Development Team. All rights reserved.
5 The Workbench Handler process and associated functions.
8 #include <aros/debug.h>
10 #include <exec/ports.h>
11 #include <utility/hooks.h>
12 #include <dos/dosextens.h>
14 #include <proto/alib.h>
15 #include <proto/intuition.h>
16 #include <proto/workbench.h>
17 #include <proto/utility.h>
18 #include <proto/exec.h>
19 #include <proto/dos.h>
21 #include <workbench/workbench.h>
22 #include <workbench/startup.h>
24 #include "workbench_intern.h"
26 #include "support_messages.h"
28 #include "handler_support.h"
32 /* Ports and signals ---------------------------------------------------*/
33 struct MsgPort
*hc_CommandPort
; /* Command messages from the library */
34 ULONG hc_CommandSignal
; /* Signal bit field for the above */
35 struct MsgPort
*hc_StartupReplyPort
; /* Replies to startup messages */
36 ULONG hc_StartupReplySignal
; /* Signal bit field for the above */
37 struct MsgPort
*hc_RelayReplyPort
; /* Replies to messages sent to the workbench application */
38 ULONG hc_RelayReplySignal
; /* Signal bit field for the above */
39 struct MsgPort
*hc_IntuitionPort
; /* Messages from Intuition */
40 ULONG hc_IntuitionSignal
; /* Signal bit field for the above */
42 ULONG hc_Signals
; /* Mask from all signals above */
46 /*** Prototypes *************************************************************/
47 static BOOL
__Initialize_WB(struct HandlerContext
*hc
, struct WorkbenchBase
*WorkbenchBase
);
48 static VOID
__Deinitialize_WB(struct HandlerContext
*hc
, struct WorkbenchBase
*WorkbenchBase
);
50 static VOID
__HandleLaunch_WB(struct WBCommandMessage
*message
, struct HandlerContext
*hc
, struct WorkbenchBase
*WorkbenchBase
);
51 static VOID
__HandleRelay_WB(struct WBCommandMessage
*message
, struct HandlerContext
*hc
, struct WorkbenchBase
*WorkbenchBase
);
52 static VOID
__HandleIntuition_WB(struct IntuiMessage
*message
, struct HandlerContext
*hc
, struct WorkbenchBase
*WorkbenchBase
);
54 /*** Macros *****************************************************************/
55 #define Initialize() (__Initialize_WB(hc, WorkbenchBase))
56 #define Deinitialize() (__Deinitialize_WB(hc, WorkbenchBase))
58 #define HandleLaunch(message) (__HandleLaunch_WB((message), hc, WorkbenchBase))
59 #define HandleRelay(message) (__HandleRelay_WB((message), hc, WorkbenchBase))
60 #define HandleIntuition(message) (__HandleIntuition_WB((message), hc, WorkbenchBase))
62 /*** Entry point ************************************************************/
65 LONG
, WorkbenchHandler
,
66 AROS_UFHA(STRPTR
, args
, A0
),
67 AROS_UFHA(ULONG
, argsLength
, D0
),
68 AROS_UFHA(struct ExecBase
*, SysBase
, A6
)
73 struct WorkbenchBase
*WorkbenchBase
= FindTask(NULL
)->tc_UserData
;
74 struct HandlerContext context
= { 0 };
75 struct HandlerContext
*hc
= &context
;
78 /*-- Initialization ----------------------------------------------------*/
79 if (!Initialize()) return 20; // FIXME: report error to user somehow. displaybeep? alert?
81 /*-- Event loop --------------------------------------------------------*/
82 D(bug("Workbench Handler: entering event loop\n"));
86 ULONG signals
= Wait(hc
->hc_Signals
);
88 D(bug("Workbench Handler: Got message(s)...\n"));
90 /*== Messages from the library =====================================*/
91 if (signals
& hc
->hc_CommandSignal
)
93 struct WBCommandMessage
*message
;
95 D(bug("Workbench Handler: Got message(s) at command port\n"));
97 while ((message
= WBCM(GetMsg(hc
->hc_CommandPort
))) != NULL
)
99 /* Handle the message */
100 switch (message
->wbcm_Type
)
102 case WBCM_TYPE_LAUNCH
:
103 D(bug("Workbench Handler: Got WBCM_Launch message\n"));
104 HandleLaunch(message
);
107 case WBCM_TYPE_RELAY
:
108 D(bug("Workbench Handler: Got WBCM_Relay message\n"));
109 HandleRelay(message
);
113 /* Deallocate the message */
114 DestroyWBCM(message
);
118 /*== Message replies from started WB programs ======================*/
119 if (signals
& hc
->hc_StartupReplySignal
)
121 struct WBStartup
*message
;
123 D(bug("Workbench Handler: Got message(s) at startup reply port\n"));
125 while ((message
= WBS(GetMsg(hc
->hc_StartupReplyPort
))) != NULL
)
127 if (message
->sm_Message
.mn_Node
.ln_Type
== NT_REPLYMSG
)
129 D(bug("Workbench Handler: Deallocating WBStartup message and arguments\n"));
135 Eh, we should only get replies here. Just reply the
136 message and hope the sender will fail gracefully.
138 ReplyMsg((struct Message
*) message
);
143 /*== Message replies from the workbench application ================*/
144 if (signals
& hc
->hc_RelayReplySignal
)
146 struct WBHandlerMessage
*message
;
148 D(bug("Workbench Handler: Got message(s) at relay reply port\n"));
150 while ((message
= WBHM(GetMsg(hc
->hc_RelayReplyPort
))) != NULL
)
152 if (message
->wbhm_Message
.mn_Node
.ln_Type
== NT_REPLYMSG
)
154 D(bug("Workbench Handler: Deallocating WBHandlerMessage\n"));
155 if (message
->wbhm_Type
== WBHM_TYPE_HIDE
)
157 struct IntWBHandlerMessage
*iwbhm
= (struct IntWBHandlerMessage
*)message
;
159 D(bug("Workbench Handler: Replying IntuiMessage because Type = "
161 ReplyMsg((struct Message
*)iwbhm
->iwbhm_Data
.Hide
.imsg
);
163 DestroyWBHM(message
);
167 /* FIXME: comment ;-) */
168 ReplyMsg((struct Message
*) message
);
174 /*== Messages from Intuition =======================================*/
175 if (signals
& hc
->hc_IntuitionSignal
)
177 struct IntuiMessage
*message
;
179 D(bug("Workbench Handler: Got message(s) at intuition port\n"));
181 while ((message
= (struct IntuiMessage
*) GetMsg(hc
->hc_IntuitionPort
)))
183 HandleIntuition(message
); /* takes care of replying */
188 //FIXME: shutdown not properly implemented
198 static BOOL __Initialize_WB
200 struct HandlerContext
*hc
, struct WorkbenchBase
*WorkbenchBase
203 /* Create message ports ------------------------------------------------*/
206 (hc
->hc_StartupReplyPort
= CreateMsgPort()) != NULL
207 && (hc
->hc_RelayReplyPort
= CreateMsgPort()) != NULL
208 && (hc
->hc_IntuitionPort
= CreateMsgPort()) != NULL
211 /* Store command port ----------------------------------------------*/
212 hc
->hc_CommandPort
= &(WorkbenchBase
->wb_HandlerPort
);
214 /* Calculate and store signal flags --------------------------------*/
215 hc
->hc_CommandSignal
= 1UL << hc
->hc_CommandPort
->mp_SigBit
;
216 hc
->hc_StartupReplySignal
= 1UL << hc
->hc_StartupReplyPort
->mp_SigBit
;
217 hc
->hc_RelayReplySignal
= 1UL << hc
->hc_RelayReplyPort
->mp_SigBit
;
218 hc
->hc_IntuitionSignal
= 1UL << hc
->hc_IntuitionPort
->mp_SigBit
;
220 hc
->hc_Signals
= hc
->hc_CommandSignal
221 | hc
->hc_StartupReplySignal
222 | hc
->hc_RelayReplySignal
223 | hc
->hc_IntuitionSignal
;
225 /* We're now ready to accept messages ------------------------------*/
226 WorkbenchBase
->wb_HandlerPort
.mp_SigTask
= FindTask(NULL
);
227 WorkbenchBase
->wb_HandlerPort
.mp_Flags
= PA_SIGNAL
;
229 /* Make sure to process messages that arrived before we were ready -*/
230 Signal(FindTask(NULL
), SIGBREAKF_CTRL_F
);
232 /* Register ourselves with Intuition -------------------------------*/
233 AlohaWorkbench(hc
->hc_IntuitionPort
);
245 static VOID __Deinitialize_WB
247 struct HandlerContext
*hc
, struct WorkbenchBase
*WorkbenchBase
250 /* Unregister ourselves with Intuition ---------------------------------*/
251 AlohaWorkbench(NULL
);
253 /* We no longer accept messages ----------------------------------------*/
254 WorkbenchBase
->wb_HandlerPort
.mp_Flags
= PA_IGNORE
;
255 WorkbenchBase
->wb_HandlerPort
.mp_SigTask
= NULL
;
257 /* Deallocate message ports --------------------------------------------*/
258 // FIXME: should we get & deallocate all queued messages?
259 if (hc
->hc_IntuitionPort
!= NULL
) DeleteMsgPort(hc
->hc_IntuitionPort
);
260 if (hc
->hc_RelayReplyPort
!= NULL
) DeleteMsgPort(hc
->hc_RelayReplyPort
);
261 if (hc
->hc_StartupReplyPort
!= NULL
) DeleteMsgPort(hc
->hc_StartupReplyPort
);
264 static VOID __HandleLaunch_WB
266 struct WBCommandMessage
*message
,
267 struct HandlerContext
*hc
, struct WorkbenchBase
*WorkbenchBase
270 struct WBStartup
*startup
= message
->wbcm_Data
.Launch
.Startup
;
271 STRPTR name
= startup
->sm_ArgList
[0].wa_Name
;
272 BPTR lock
= startup
->sm_ArgList
[0].wa_Lock
;
275 struct Process
*process
;
277 D(bug("Workbench Handler: HandleLaunch: name = %s\n", name
));
279 /* Change directory to where the program resides */
280 cd
= CurrentDir(startup
->sm_ArgList
[0].wa_Lock
);
282 /* Load the program from disk */
283 startup
->sm_Segment
= LoadSeg(name
);
284 if (startup
->sm_Segment
== NULL
) goto error
;
286 /* Duplicate lock for NP_HomeDir */
287 home
= DupLock(lock
);
288 if (home
== NULL
) goto error
;
290 /* Launch the program */
291 process
= CreateNewProcTags
293 NP_Seglist
, (IPTR
) startup
->sm_Segment
,
294 NP_Name
, (IPTR
) name
,
295 NP_HomeDir
, (IPTR
) home
,
296 NP_StackSize
, WorkbenchBase
->wb_DefaultStackSize
, /* FIXME: should be read from icon */
302 D(bug("Workbench Handler: HandleLaunch: Process created successfully\n"));
304 /* Setup startup message */
305 startup
->sm_Process
= &process
->pr_MsgPort
;
306 startup
->sm_Message
.mn_ReplyPort
= hc
->hc_StartupReplyPort
;
308 /* Send startup message to program */
309 PutMsg(startup
->sm_Process
, (struct Message
*) startup
);
315 //FIXME: report error somehow?
316 D(bug("Workbench Handler: HandleLaunch: Failed to launch program. Deallocating resources.\n"));
317 if (startup
->sm_Segment
!= NULL
) UnLoadSeg(startup
->sm_Segment
);
321 /* Restore current directory */
325 static VOID __HandleRelay_WB
327 struct WBCommandMessage
*message
,
328 struct HandlerContext
*hc
, struct WorkbenchBase
*WorkbenchBase
331 struct WBHandlerMessage
*relaymsg
= message
->wbcm_Data
.Relay
.Message
;
333 D(bug("Workbench Handler: HandleRelay: Relaying message to workbench application\n"));
334 D(bug("Workbench Handler: HandleRelay: destination port %p\n", WorkbenchBase
->wb_WorkbenchPort
));
335 relaymsg
->wbhm_Message
.mn_ReplyPort
= hc
->hc_RelayReplyPort
;
336 PutMsg(WorkbenchBase
->wb_WorkbenchPort
, (struct Message
*) relaymsg
);
339 static void __HandleIntuition_WB
341 struct IntuiMessage
*message
,
342 struct HandlerContext
*hc
, struct WorkbenchBase
*WorkbenchBase
345 struct IntWBHandlerMessage
*iwbhm
;
347 if (message
->Class
== IDCMP_WBENCHMESSAGE
)
349 switch (message
->Code
)
352 iwbhm
= CreateIWBHM(WBHM_TYPE_SHOW
, hc
->hc_RelayReplyPort
);
355 iwbhm
= CreateIWBHM(WBHM_TYPE_HIDE
, hc
->hc_RelayReplyPort
);
356 iwbhm
->iwbhm_Data
.Hide
.imsg
= message
;
363 if ((iwbhm
!= NULL
) && (WorkbenchBase
->wb_WorkbenchPort
!= NULL
))
365 PutMsg(WorkbenchBase
->wb_WorkbenchPort
, (struct Message
*)iwbhm
);
367 /* Don't reply immediately if we're asked to close the WB,
368 we'll do it when handling replied message, so that the WB
369 will have a chance to close its windows. */
370 if (message
->Code
== WBENCHCLOSE
)
375 ReplyMsg((struct Message
*) message
);