rename the directory
[AROS.git] / workbench / tools / commodities / AutoPoint.c
blob77f75cea2cc5a22869e15da7c763e9001dd9b4a3
1 /*
2 Copyright © 1995-2003, The AROS Development Team. All rights reserved.
3 $Id$
5 AutoPoint commodity -- activates the window under the mouse pointer.
6 */
8 /******************************************************************************
10 NAME
12 AutoPoint
14 SYNOPSIS
16 CX_PRIORITY/N/K, LAG/S
18 LOCATION
20 SYS:Tools/Commodities
22 FUNCTION
24 Automatically activates the window under the mouse pointer.
26 INPUTS
28 CX_PRIORITY -- The priority of the commodity
30 LAG -- Wait for the next timer event to activate the window
32 MIDMOUSEPREVENTSACTIVATION -- Don't activate the window under the
33 mouse if middle mouse button is pressed
35 RESULT
37 NOTES
39 EXAMPLE
41 BUGS
43 SEE ALSO
45 INTERNALS
47 HISTORY
49 05.03.2000 SDuvan implemented
51 ******************************************************************************/
53 #include <aros/symbolsets.h>
54 #include <intuition/intuition.h>
55 #include <intuition/intuitionbase.h>
56 #include <libraries/commodities.h>
57 #include <libraries/locale.h>
58 #include <proto/exec.h>
59 #include <proto/dos.h>
60 #include <proto/intuition.h>
61 #include <proto/layers.h>
62 #include <proto/commodities.h>
63 #include <proto/locale.h>
64 #include <proto/alib.h>
66 #include <stdio.h>
67 #include <string.h>
69 #define DEBUG 0
70 #include <aros/debug.h>
72 #define CATCOMP_ARRAY
73 #include "strings.h"
75 #define CATALOG_NAME "System/Tools/Commodities.catalog"
76 #define CATALOG_VERSION 3
79 /***************************************************************************/
81 UBYTE version[] = "\0$VER: AutoPoint 0.4 (17.10.2012)";
83 #define ARG_TEMPLATE "CX_PRIORITY=PRI/N/K,LAG/S,MIDMOUSEPREVENTSACTIVATION=MMPA/S"
85 #define ARG_PRI 0
86 #define ARG_LAG 1
87 #define ARG_MMPA 2
88 #define NUM_ARGS 3
91 static struct NewBroker nb =
93 NB_VERSION,
94 NULL,
95 NULL,
96 NULL,
97 NBU_NOTIFY | NBU_UNIQUE,
100 NULL,
105 typedef struct _APState
107 CxObj *as_broker;
108 struct MsgPort *as_msgPort;
109 } APState;
112 typedef struct AP
114 struct Window *ai_thisWindow;
115 struct Window *ai_lastActivatedWindow;
116 BOOL ai_mouseHasMoved;
117 BOOL ai_leftButtonDown;
118 BOOL ai_rightButtonDown;
119 BOOL ai_middleButtonDown;
120 BOOL ai_midMousePreventsActivation;
121 } AP;
123 static AP apInfo =
125 NULL,
126 NULL,
127 FALSE,
128 FALSE,
129 FALSE,
130 FALSE,
131 FALSE
135 static struct Catalog *catalog;
137 /************************************************************************************/
139 static void freeResources(APState *as);
140 static BOOL initiate(int argc, char **argv, APState *as);
141 static void autoActivateLag(CxMsg *msg, CxObj *co);
142 static void autoActivate(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_AUTOPOINT_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, APState *as)
214 CxObj *customObj;
215 void (*activateFunc)(CxMsg *msg, CxObj *co);
217 memset(as, 0, sizeof(APState));
219 activateFunc = autoActivate;
221 if (Cli() != NULL)
223 struct RDArgs *rda;
224 IPTR *args[] = { NULL, (IPTR)FALSE, (IPTR)FALSE };
226 rda = ReadArgs(ARG_TEMPLATE, (IPTR *)args, NULL);
228 if (rda != NULL)
230 if (args[ARG_PRI] != NULL)
232 nb.nb_Pri = *args[ARG_PRI];
234 if (args[ARG_LAG])
236 activateFunc = autoActivateLag;
238 if (args[ARG_MMPA])
240 apInfo.ai_midMousePreventsActivation = TRUE;
243 FreeArgs(rda);
245 else
247 UBYTE **array = ArgArrayInit(argc, (UBYTE **)argv);
249 nb.nb_Pri = ArgInt(array, "CX_PRIORITY", 0);
251 if (ArgString(array, "LAG", 0))
253 activateFunc = autoActivateLag;
255 if (ArgString(array, "MIDMOUSEPREVENTSACTIVATION", 0))
257 apInfo.ai_midMousePreventsActivation = TRUE;
260 ArgArrayDone();
263 nb.nb_Name = _(MSG_AUTOPOINT_CXNAME);
264 nb.nb_Title = _(MSG_AUTOPOINT_CXTITLE);
265 nb.nb_Descr = _(MSG_AUTOPOINT_CXDESCR);
267 as->as_msgPort = CreateMsgPort();
269 if (as->as_msgPort == NULL)
271 showSimpleMessage(_(MSG_CANT_CREATE_MSGPORT));
273 return FALSE;
276 nb.nb_Port = as->as_msgPort;
278 as->as_broker = CxBroker(&nb, 0);
280 if (as->as_broker == NULL)
282 return FALSE;
285 customObj = CxCustom(activateFunc, 0);
287 if (customObj == NULL)
289 showSimpleMessage(_(MSG_CANT_CREATE_CUSTOM));
291 return FALSE;
294 AttachCxObj(as->as_broker, customObj);
295 ActivateCxObj(as->as_broker, TRUE);
297 apInfo.ai_thisWindow = IntuitionBase->ActiveWindow;
299 return TRUE;
302 /************************************************************************************/
304 static void freeResources(APState *as)
306 struct Message *cxm;
308 if (CxBase != NULL)
310 if (as->as_broker != NULL)
312 DeleteCxObjAll(as->as_broker);
316 if (as->as_msgPort != NULL)
318 while ((cxm = GetMsg(as->as_msgPort)))
320 ReplyMsg(cxm);
323 DeleteMsgPort(as->as_msgPort);
327 /************************************************************************************/
329 /* Our CxCustom() function that is invoked everytime an imputevent is
330 routed to our broker */
331 static void autoActivateLag(CxMsg *msg, CxObj *co)
333 struct InputEvent *ie = (struct InputEvent *)CxMsgData(msg);
335 if (ie->ie_Class == IECLASS_TIMER)
337 struct Screen *screen;
338 struct Layer *layer;
340 if (apInfo.ai_leftButtonDown ||
341 apInfo.ai_rightButtonDown ||
342 apInfo.ai_middleButtonDown )
343 return;
345 if (IntuitionBase->ActiveWindow != NULL)
347 screen = IntuitionBase->ActiveWindow->WScreen;
349 else
351 screen = IntuitionBase->ActiveScreen;
354 if (!screen)
355 layer = NULL;
356 else
358 LockLayerInfo(&screen->LayerInfo);
359 layer = WhichLayer(&screen->LayerInfo, screen->MouseX, screen->MouseY);
360 UnlockLayerInfo(&screen->LayerInfo);
363 apInfo.ai_thisWindow = (layer != NULL) ?
364 (struct Window *)layer->Window : NULL;
366 if (apInfo.ai_mouseHasMoved ||
367 (IntuitionBase->ActiveWindow == apInfo.ai_thisWindow) ||
368 (apInfo.ai_lastActivatedWindow == apInfo.ai_thisWindow))
370 apInfo.ai_mouseHasMoved = FALSE;
371 return;
374 /* Two timer events and mouse hasn't moved in between. */
376 apInfo.ai_mouseHasMoved = FALSE;
378 /* Should be possible to use ActivateWindow(NULL)? Else, we must
379 hack... */
380 if (apInfo.ai_thisWindow != NULL)
382 apInfo.ai_lastActivatedWindow = apInfo.ai_thisWindow;
383 ActivateWindow(apInfo.ai_thisWindow);
386 if (apInfo.ai_thisWindow != NULL)
388 D(bug("Activated window %s\n", apInfo.ai_thisWindow->Title));
390 else
392 D(bug("No window active. %s\n",
393 IntuitionBase->ActiveWindow->Title));
396 return;
399 if (ie->ie_Class == IECLASS_RAWMOUSE)
401 apInfo.ai_mouseHasMoved = FALSE;
402 switch (ie->ie_Code)
404 case IECODE_NOBUTTON:
405 apInfo.ai_mouseHasMoved = TRUE;
406 break;
407 case MIDDLEDOWN:
408 if (apInfo.ai_midMousePreventsActivation)
409 apInfo.ai_middleButtonDown = TRUE;
410 break;
411 case SELECTDOWN:
412 apInfo.ai_leftButtonDown = TRUE;
413 break;
414 case MENUDOWN:
415 apInfo.ai_rightButtonDown = TRUE;
416 break;
417 case MIDDLEUP:
418 apInfo.ai_middleButtonDown = FALSE;
419 break;
420 case SELECTUP:
421 apInfo.ai_leftButtonDown = FALSE;
422 break;
423 case MENUUP:
424 apInfo.ai_rightButtonDown = FALSE;
425 break;
430 /************************************************************************************/
432 static void autoActivate(CxMsg *msg, CxObj *co)
434 struct InputEvent *ie = (struct InputEvent *)CxMsgData(msg);
436 if (ie->ie_Class == IECLASS_RAWMOUSE)
438 struct Screen *screen;
439 struct Layer *layer;
441 if (ie->ie_Code != IECODE_NOBUTTON)
443 switch (ie->ie_Code)
445 case MIDDLEDOWN:
446 if (apInfo.ai_midMousePreventsActivation)
447 apInfo.ai_middleButtonDown = TRUE;
448 break;
449 case SELECTDOWN:
450 apInfo.ai_leftButtonDown = TRUE;
451 break;
452 case MENUDOWN:
453 apInfo.ai_rightButtonDown = TRUE;
454 break;
455 case MIDDLEUP:
456 apInfo.ai_middleButtonDown = FALSE;
457 break;
458 case SELECTUP:
459 apInfo.ai_leftButtonDown = FALSE;
460 break;
461 case MENUUP:
462 apInfo.ai_rightButtonDown = FALSE;
463 break;
465 return;
468 if (apInfo.ai_leftButtonDown ||
469 apInfo.ai_rightButtonDown ||
470 apInfo.ai_middleButtonDown )
471 return;
473 if (IntuitionBase->ActiveWindow != NULL)
475 screen = IntuitionBase->ActiveWindow->WScreen;
477 else
479 screen = IntuitionBase->ActiveScreen;
482 if (!screen)
483 layer = NULL;
484 else
486 LockLayerInfo(&screen->LayerInfo);
487 layer = WhichLayer(&screen->LayerInfo, screen->MouseX, screen->MouseY);
488 UnlockLayerInfo(&screen->LayerInfo);
491 apInfo.ai_thisWindow = (layer != NULL) ?
492 (struct Window *)layer->Window : NULL;
494 if (apInfo.ai_thisWindow != NULL &&
495 apInfo.ai_thisWindow != IntuitionBase->ActiveWindow)
497 ActivateWindow(apInfo.ai_thisWindow);
498 D(bug("Activated window %s\n", apInfo.ai_thisWindow->Title));
501 return;
505 /************************************************************************************/
507 /* React on command messages sent by commodities.library */
508 static void handleCx(APState *as)
510 CxMsg *msg;
511 BOOL quit = FALSE;
512 LONG signals;
514 while (!quit)
516 signals = Wait((1 << nb.nb_Port->mp_SigBit) | SIGBREAKF_CTRL_C);
518 if (signals & (1 << nb.nb_Port->mp_SigBit))
520 while ((msg = (CxMsg *)GetMsg(as->as_msgPort)))
522 switch (CxMsgType(msg))
524 case CXM_COMMAND:
525 switch (CxMsgID(msg))
527 case CXCMD_DISABLE:
528 ActivateCxObj(as->as_broker, FALSE);
529 break;
531 case CXCMD_ENABLE:
532 ActivateCxObj(as->as_broker, TRUE);
533 break;
535 case CXCMD_UNIQUE:
536 /* Running the program twice <=> quit */
537 /* Fall through */
539 case CXCMD_KILL:
540 quit = TRUE;
541 break;
543 } /* switch(CxMsgID(msg)) */
545 break;
546 } /* switch (CxMsgType(msg))*/
548 ReplyMsg((struct Message *)msg);
550 } /* while((msg = (CxMsg *)GetMsg(cs->cs_msgPort))) */
553 if (signals & SIGBREAKF_CTRL_C)
555 quit = TRUE;
558 } /* while (!quit) */
561 /************************************************************************************/
563 int main(int argc, char **argv)
565 APState aState;
566 int error = RETURN_OK;
568 if (initiate(argc, argv, &aState))
570 handleCx(&aState);
572 else
574 error = RETURN_FAIL;
577 freeResources(&aState);
579 return error;
582 /************************************************************************************/
584 ADD2INIT(Locale_Initialize, 90);
585 ADD2EXIT(Locale_Deinitialize, 90);