add casts to zune macros to silence some warnings
[tangerine.git] / workbench / tools / commodities / ClickToFront.c
blob389729897020d46a321cb018ebec92532ff957ab
1 /*
2 Copyright © 1995-2006, The AROS Development Team. All rights reserved.
3 $Id$
5 ClickToFront commodity -- puts windows to front when clicked in.
6 */
8 /******************************************************************************
10 NAME
12 ClickToFront
14 SYNOPSIS
16 CX_PRIORITY/N/K, QUALIFIER/K, DOUBLE/S
18 LOCATION
20 Workbench:Tools/Commodities
22 FUNCTION
24 Automatically raises and activates a window when clicking in it.
26 INPUTS
28 CX_PRIORITY -- The priority of the commodity
30 QUALIFIER -- Qualifier to match the double click (LEFT_ALT,
31 RIGHT_ALT, CTRL or NONE).
33 DOUBLE -- If specified, clicking means double-clicking.
35 RESULT
37 NOTES
39 EXAMPLE
41 BUGS
43 SEE ALSO
45 INTERNALS
47 ******************************************************************************/
49 #include <aros/symbolsets.h>
50 #include <intuition/intuition.h>
51 #include <intuition/intuitionbase.h>
52 #include <libraries/commodities.h>
53 #include <libraries/locale.h>
54 #include <proto/exec.h>
55 #include <proto/dos.h>
56 #include <proto/intuition.h>
57 #include <proto/layers.h>
58 #include <proto/commodities.h>
59 #include <proto/input.h>
60 #include <proto/alib.h>
61 #include <proto/locale.h>
63 #include <stdio.h>
64 #include <string.h>
66 #define DEBUG 0
67 #include <aros/debug.h>
69 #define CATCOMP_ARRAY
70 #include "strings.h"
72 #define CATALOG_NAME "System/Tools/Commodities.catalog"
73 #define CATALOG_VERSION 2
76 /***************************************************************************/
78 UBYTE version[] = "$VER: ClickToFront 0.3 (15.04.2006)";
80 #define ARG_TEMPLATE "CX_PRIORITY=PRI/N/K,QUALIFIER/K,DOUBLE/S"
82 #define ARG_PRI 0
83 #define ARG_QUALIFIER 1
84 #define ARG_DOUBLE 2
85 #define NUM_ARGS 3
87 struct Device *InputBase = NULL;
88 struct Catalog *catalog;
89 struct IOStdReq *inputIO;
92 /* The ClickToFront broker */
93 static struct NewBroker nb =
95 NB_VERSION,
96 NULL,
97 NULL,
98 NULL,
99 NBU_NOTIFY | NBU_UNIQUE,
102 NULL,
107 typedef struct _CFState
109 CxObj *cs_broker;
110 struct MsgPort *cs_msgPort;
111 } CFState;
114 typedef struct CF
116 struct Window *ci_thisWindow;
117 struct Window *ci_lastWindow;
118 UWORD ci_qualifiers; /* Qualifiers that must match */
119 BOOL ci_mouseHasMoved;
120 BOOL ci_doubleClick;
121 ULONG ci_lcSeconds; /* Time stamp for the last click */
122 ULONG ci_lcMicros;
123 } CF;
126 static CF cfInfo =
128 NULL,
129 NULL,
131 FALSE,
132 FALSE,
137 /************************************************************************************/
139 static void freeResources(CFState *cs);
140 static BOOL initiate(int argc, char **argv, CFState *cs);
141 static void getQualifier(STRPTR qualString);
142 static void clicktoFront(CxMsg *msg, CxObj *co);
143 static CONST_STRPTR _(ULONG id);
144 static BOOL Locale_Initialize(VOID);
145 static VOID Locale_Deinitialize(VOID);
146 static void showSimpleMessage(CONST_STRPTR msgString);
148 /************************************************************************************/
150 static CONST_STRPTR _(ULONG id)
152 if (LocaleBase != NULL && catalog != NULL)
154 return GetCatalogStr(catalog, id, CatCompArray[id].cca_Str);
156 else
158 return CatCompArray[id].cca_Str;
162 /************************************************************************************/
164 static BOOL Locale_Initialize(VOID)
166 if (LocaleBase != NULL)
168 catalog = OpenCatalog
170 NULL, CATALOG_NAME, OC_Version, CATALOG_VERSION, TAG_DONE
173 else
175 catalog = NULL;
178 return TRUE;
181 /************************************************************************************/
183 static VOID Locale_Deinitialize(VOID)
185 if(LocaleBase != NULL && catalog != NULL) CloseCatalog(catalog);
188 /************************************************************************************/
190 static void showSimpleMessage(CONST_STRPTR msgString)
192 struct EasyStruct easyStruct;
194 easyStruct.es_StructSize = sizeof(easyStruct);
195 easyStruct.es_Flags = 0;
196 easyStruct.es_Title = _(MSG_CLICK2FNT_CXNAME);
197 easyStruct.es_TextFormat = msgString;
198 easyStruct.es_GadgetFormat = _(MSG_OK);
200 if (IntuitionBase != NULL && !Cli() )
202 EasyRequestArgs(NULL, &easyStruct, NULL, NULL);
204 else
206 PutStr(msgString);
210 /************************************************************************************/
212 static BOOL initiate(int argc, char **argv, CFState *cs)
214 CxObj *customObj;
216 memset(cs, 0, sizeof(CFState));
218 if (Cli() != NULL)
220 struct RDArgs *rda;
221 IPTR args[] = { (IPTR) NULL, (IPTR) NULL, FALSE };
223 rda = ReadArgs(ARG_TEMPLATE, args, NULL);
225 if (rda != NULL)
227 if (args[ARG_PRI] != (IPTR) NULL)
229 nb.nb_Pri = *(LONG *)args[ARG_PRI];
232 getQualifier((STRPTR)args[ARG_QUALIFIER]);
234 cfInfo.ci_doubleClick = args[ARG_DOUBLE];
236 if (cfInfo.ci_doubleClick)
238 D(bug("Using the double clicking method.\n"));
242 FreeArgs(rda);
244 else
246 UBYTE **array = ArgArrayInit(argc, (UBYTE **)argv);
248 nb.nb_Pri = ArgInt(array, "CX_PRIORITY", 0);
249 cfInfo.ci_doubleClick = ArgString(array, "DOUBLE", NULL) != NULL;
251 getQualifier(ArgString(array, "QUALIFIER", NULL));
253 ArgArrayDone();
256 nb.nb_Name = _(MSG_CLICK2FNT_CXNAME);
257 nb.nb_Title = _(MSG_CLICK2FNT_CXTITLE);
258 nb.nb_Descr = _(MSG_CLICK2FNT_CXDESCR);
260 cs->cs_msgPort = CreateMsgPort();
262 if (cs->cs_msgPort == NULL)
264 showSimpleMessage(_(MSG_CANT_CREATE_MSGPORT));
266 return FALSE;
269 nb.nb_Port = cs->cs_msgPort;
271 cs->cs_broker = CxBroker(&nb, 0);
273 if (cs->cs_broker == NULL)
275 return FALSE;
278 customObj = CxCustom(clicktoFront, 0);
280 if (customObj == NULL)
282 showSimpleMessage(_(MSG_CANT_CREATE_MSGPORT));
284 return FALSE;
287 AttachCxObj(cs->cs_broker, customObj);
288 ActivateCxObj(cs->cs_broker, TRUE);
290 cfInfo.ci_thisWindow = IntuitionBase->ActiveWindow;
292 inputIO = (struct IOStdReq *)CreateIORequest(cs->cs_msgPort,
293 sizeof(struct IOStdReq));
295 if (inputIO == NULL)
297 showSimpleMessage(_(MSG_CANT_ALLOCATE_MEM));
299 return FALSE;
302 if ((OpenDevice("input.device", 0, (struct IORequest *)inputIO, 0)) != 0)
304 showSimpleMessage(_(MSG_CANT_OPEN_INPUTDEVICE));
306 return FALSE;
309 InputBase = (struct Device *)inputIO->io_Device;
311 return TRUE;
314 /************************************************************************************/
316 static void getQualifier(STRPTR qualString)
318 if (qualString == NULL)
320 return;
323 if (strcmp("CTRL", qualString) == 0)
325 cfInfo.ci_qualifiers = IEQUALIFIER_CONTROL;
328 if (strcmp("LEFT_ALT", qualString) == 0)
330 cfInfo.ci_qualifiers = IEQUALIFIER_LALT;
333 if (strcmp("RIGHT_ALT", qualString) == 0)
335 cfInfo.ci_qualifiers = IEQUALIFIER_RALT;
338 /* Default is NONE */
341 /************************************************************************************/
343 static void freeResources(CFState *cs)
345 struct Message *cxm;
347 if (cs->cs_broker != NULL)
349 DeleteCxObjAll(cs->cs_broker);
352 if (cs->cs_msgPort != NULL)
354 while ((cxm = GetMsg(cs->cs_msgPort)))
356 ReplyMsg(cxm);
359 DeleteMsgPort(cs->cs_msgPort);
362 if (inputIO != NULL)
364 CloseDevice((struct IORequest *)inputIO);
365 DeleteIORequest((struct IORequest *)inputIO);
369 /************************************************************************************/
371 /* Currently we use single click, not double click... */
372 static void clicktoFront(CxMsg *cxm, CxObj *co)
374 /* NOTE! Should use arbitration for IntuitionBase... */
376 struct InputEvent *ie = (struct InputEvent *)CxMsgData(cxm);
378 if (ie->ie_Class == IECLASS_RAWMOUSE)
380 if (ie->ie_Code == SELECTDOWN)
382 struct Screen *screen;
383 struct Layer *layer;
385 /* Mask relvant qualifiers (key qualifiers) */
386 if ((PeekQualifier() & 0xff) != cfInfo.ci_qualifiers)
388 D(bug("Qualifiers: %i, Wanted qualifiers: %i\n",
389 (int)PeekQualifier(),
390 (int)cfInfo.ci_qualifiers | IEQUALIFIER_LEFTBUTTON));
392 return;
395 cfInfo.ci_lastWindow = cfInfo.ci_thisWindow;
397 if (IntuitionBase->ActiveWindow != NULL)
399 screen = IntuitionBase->ActiveWindow->WScreen;
401 else
403 screen = IntuitionBase->ActiveScreen;
406 layer = WhichLayer(&screen->LayerInfo,
407 screen->MouseX, screen->MouseY);
409 if (layer == NULL)
411 return;
414 cfInfo.ci_thisWindow = (layer != NULL) ?
415 (struct Window *)layer->Window : NULL;
417 /* Error: IB->ActiveWindow is non-NULL even if there is no
418 active window! */
419 if (layer->front != NULL)
421 if (cfInfo.ci_doubleClick)
423 if (!DoubleClick(cfInfo.ci_lcSeconds, cfInfo.ci_lcMicros,
424 ie->ie_TimeStamp.tv_secs,
425 ie->ie_TimeStamp.tv_micro))
427 cfInfo.ci_lcSeconds = ie->ie_TimeStamp.tv_secs;
428 cfInfo.ci_lcMicros = ie->ie_TimeStamp.tv_micro;
430 return;
433 D(bug("Time %i %i, last time %i %i\n",
434 ie->ie_TimeStamp.tv_secs,
435 ie->ie_TimeStamp.tv_micro,
436 cfInfo.ci_lcSeconds,
437 cfInfo.ci_lcMicros));
439 cfInfo.ci_lcSeconds = ie->ie_TimeStamp.tv_secs;
440 cfInfo.ci_lcMicros = ie->ie_TimeStamp.tv_micro;
442 /* Both clicks better have been in the same window */
443 if (cfInfo.ci_lastWindow != cfInfo.ci_thisWindow)
445 return;
449 WindowToFront(cfInfo.ci_thisWindow);
451 if (cfInfo.ci_thisWindow != IntuitionBase->ActiveWindow)
453 ActivateWindow(cfInfo.ci_thisWindow);
456 //DisposeCxMsg(cxm);
458 D(bug("Put window %s to front.\n",
459 cfInfo.ci_thisWindow->Title));
461 else
463 D(bug("New: %p Old: %p\n", cfInfo.ci_thisWindow,
464 IntuitionBase->ActiveWindow));
470 /************************************************************************************/
472 static void handleCx(CFState *cs)
474 CxMsg *msg;
475 BOOL quit = FALSE;
476 LONG signals;
478 while (!quit)
480 signals = Wait((1 << nb.nb_Port->mp_SigBit) | SIGBREAKF_CTRL_C);
482 if (signals & (1 << nb.nb_Port->mp_SigBit))
484 while ((msg = (CxMsg *)GetMsg(cs->cs_msgPort)))
486 switch (CxMsgType(msg))
488 case CXM_COMMAND:
489 switch (CxMsgID(msg))
491 case CXCMD_DISABLE:
492 ActivateCxObj(cs->cs_broker, FALSE);
493 break;
495 case CXCMD_ENABLE:
496 ActivateCxObj(cs->cs_broker, TRUE);
497 break;
499 case CXCMD_UNIQUE:
500 /* Running the program twice is the same as shutting
501 down the existing program... */
502 /* Fall through */
504 case CXCMD_KILL:
505 quit = TRUE;
506 break;
508 } /* switch (CxMsgID(msg)) */
509 break;
510 } /* switch (CxMsgType(msg))*/
512 ReplyMsg((struct Message *)msg);
514 } /* while ((msg = (CxMsg *)GetMsg(cs->cs_msgPort))) */
517 if (signals & SIGBREAKF_CTRL_C)
519 quit = TRUE;
522 } /* while(!quit) */
525 /************************************************************************************/
527 int main(int argc, char **argv)
529 CFState cState;
530 int error = RETURN_OK;
532 if (initiate(argc, argv, &cState))
534 handleCx(&cState);
536 else
538 error = RETURN_FAIL;
541 freeResources(&cState);
543 return error;
546 /************************************************************************************/
548 ADD2INIT(Locale_Initialize, 90);
549 ADD2EXIT(Locale_Deinitialize, 90);