[← Home](../README.md) · [Libraries](README.md) # workbench.library — Workbench Integration ## Overview `workbench.library` provides APIs for interacting with the Workbench desktop environment: receiving startup arguments, registering **AppWindows** (drag-and-drop targets), **AppIcons** (desktop icons), and **AppMenuItems** (Workbench Tools menu entries). ```mermaid flowchart TD subgraph "Workbench" WB["Workbench Desktop"] WB --> AW["AppWindow
(file drop target)"] WB --> AI["AppIcon
(custom desktop icon)"] WB --> AM["AppMenuItem
(Tools menu entry)"] end subgraph "Application" PORT["MsgPort"] --> LOOP["Event Loop"] LOOP --> HANDLE["Handle AppMessage"] end AW -->|"User drops file"| PORT AI -->|"User clicks icon"| PORT AM -->|"User selects menu"| PORT style AW fill:#c8e6c9,stroke:#2e7d32,color:#333 style AI fill:#fff9c4,stroke:#f9a825,color:#333 style AM fill:#e8f4fd,stroke:#2196f3,color:#333 ``` --- ## WBStartup Message When launched from Workbench (double-click an icon), the program receives a `WBStartup` message instead of CLI arguments: ```c struct WBStartup { struct Message sm_Message; struct MsgPort *sm_Process; /* process that sent us */ BPTR sm_Segment; /* our loaded segment list */ LONG sm_NumArgs; /* number of arguments (1 = just the tool) */ char *sm_ToolWindow; /* tool window spec (CON: string) */ struct WBArg *sm_ArgList; /* array of arguments */ }; struct WBArg { BPTR wa_Lock; /* directory lock (BPTR) */ BYTE *wa_Name; /* filename (relative to wa_Lock) */ }; ``` ### Handling WBStartup ```c /* In main(): */ struct WBStartup *wbmsg = NULL; if (argc == 0) { /* Launched from Workbench — get the startup message: */ struct Process *me = (struct Process *)FindTask(NULL); WaitPort(&me->pr_MsgPort); wbmsg = (struct WBStartup *)GetMsg(&me->pr_MsgPort); /* ArgList[0] = the tool itself (our icon) */ /* ArgList[1..n] = files the user shift-clicked or dropped on us */ /* CD to the tool's directory for file access: */ BPTR oldDir = CurrentDir(wbmsg->sm_ArgList[0].wa_Lock); /* Process dropped files: */ for (int i = 1; i < wbmsg->sm_NumArgs; i++) { BPTR dir = wbmsg->sm_ArgList[i].wa_Lock; char *name = wbmsg->sm_ArgList[i].wa_Name; BPTR old = CurrentDir(dir); /* ... open and process file 'name' ... */ CurrentDir(old); } /* Read our ToolTypes: */ struct DiskObject *dobj = GetDiskObject(wbmsg->sm_ArgList[0].wa_Name); if (dobj) { char *pubscreen = FindToolType(dobj->do_ToolTypes, "PUBSCREEN"); FreeDiskObject(dobj); } CurrentDir(oldDir); } /* ... main program logic ... */ /* MUST reply before exiting: */ if (wbmsg) { Forbid(); ReplyMsg((struct Message *)wbmsg); } ``` > [!CAUTION] > You **must** reply the WBStartup message before exiting, and you **must** call `Forbid()` before `ReplyMsg()`. If you reply without Forbid, Workbench may unload your code segment before your process finishes exiting → crash. --- ## AppWindow — File Drop Target Register a window to receive files when the user drags icons to it: ```c struct MsgPort *appPort = CreateMsgPort(); /* Register the window: */ struct AppWindow *appWin = AddAppWindow( 1, /* ID (your choice — returned in AppMessage) */ 0, /* user data */ window, /* the Intuition Window */ appPort, /* port for AppMessages */ NULL); /* tags (NULL = defaults) */ /* In event loop: */ struct AppMessage *amsg; while ((amsg = (struct AppMessage *)GetMsg(appPort))) { for (int i = 0; i < amsg->am_NumArgs; i++) { BPTR old = CurrentDir(amsg->am_ArgList[i].wa_Lock); Printf("Dropped: %s\n", amsg->am_ArgList[i].wa_Name); /* ... open and process file ... */ CurrentDir(old); } ReplyMsg((struct Message *)amsg); } /* Cleanup: */ RemoveAppWindow(appWin); DeleteMsgPort(appPort); ``` --- ## AppIcon — Desktop Icon Place a custom icon on the Workbench desktop: ```c struct DiskObject *icon = GetDiskObject("PROGDIR:myapp"); struct AppIcon *appIcon = AddAppIcon( 1, /* ID */ 0, /* user data */ "My App", /* label under the icon */ appPort, /* port for messages */ NULL, /* lock (NULL = Workbench root) */ icon, /* the icon imagery */ NULL); /* tags */ /* When user double-clicks or drops files on the AppIcon: */ /* → AppMessage received on appPort (same as AppWindow) */ RemoveAppIcon(appIcon); FreeDiskObject(icon); ``` --- ## AppMenuItem — Tools Menu Entry Add an entry to the Workbench "Tools" menu: ```c struct AppMenuItem *appMenu = AddAppMenuItem( 1, /* ID */ 0, /* user data */ "My Tool", /* menu text */ appPort, /* port for messages */ NULL); /* tags */ /* When user selects the menu item: */ /* → AppMessage received, am_NumArgs=0 (no file args) */ RemoveAppMenuItem(appMenu); ``` --- ## References - NDK39: `workbench/workbench.h`, `workbench/startup.h` - ADCD 2.1: workbench.library autodocs - See also: [icon.md](icon.md) — icon.library for reading .info files and ToolTypes