define __KERNEL_STRICT_NAMES to avoid inclusion of kernel types on systems that carry...
[cake.git] / rom / intuition / inputhandler.c
blob766344f615f7e57af411c070c3348c855de4a966
1 /*
2 Copyright 1995-2003, The AROS Development Team. All rights reserved.
3 Copyright 2001-2003, The MorphOS Development Team. All Rights Reserved.
4 $Id$
5 */
7 /****************************************************************************************/
9 #include <proto/exec.h>
10 #include <proto/intuition.h>
11 #include <proto/alib.h>
12 #include <proto/layers.h>
13 #include <proto/graphics.h>
14 #include <proto/keymap.h>
15 #include <proto/utility.h>
16 #include <proto/input.h>
17 #include <proto/timer.h>
18 #include <exec/memory.h>
19 #include <exec/alerts.h>
20 #include <exec/interrupts.h>
21 #include <exec/ports.h>
22 #include <intuition/intuition.h>
23 #include <intuition/intuitionbase.h>
24 #include <intuition/gadgetclass.h>
25 #include <intuition/pointerclass.h>
26 #include <intuition/cghooks.h>
27 #include <intuition/sghooks.h>
28 #include <devices/inputevent.h>
29 #include <devices/rawkeycodes.h>
30 #include <clib/macros.h>
31 #include "inputhandler.h"
33 #include "boopsigadgets.h"
34 #include "boolgadgets.h"
35 #include "propgadgets.h"
36 #include "strgadgets.h"
37 #include "gadgets.h"
38 #include "intuition_intern.h" /* EWFLG_xxx */
39 #include "inputhandler_support.h"
40 #include "inputhandler_actions.h"
41 #include "menus.h"
43 #ifdef SKINS
44 # include "smallmenu.h"
45 # include "intuition_customizesupport.h"
46 #endif
48 #undef DEBUG
49 #define DEBUG 0
50 #include <aros/debug.h>
52 #define DEBUG_HANDLER(x) ;
53 #define DEBUG_KEY(x) ;
54 #define DEBUG_SCREENKEY(x) ;
56 /****************************************************************************************/
58 struct Interrupt *InitIIH(struct IntuitionBase *IntuitionBase)
60 struct Interrupt *iihandler;
62 D(bug("InitIIH(IntuitionBase=%p)\n", IntuitionBase));
64 iihandler = AllocMem(sizeof (struct Interrupt), MEMF_PUBLIC | MEMF_CLEAR);
65 if (iihandler)
67 struct IIHData *iihdata;
69 iihdata = AllocMem(sizeof (struct IIHData), MEMF_PUBLIC | MEMF_CLEAR);
70 if (iihdata)
72 struct MsgPort *port;
74 port = AllocMem(sizeof (struct MsgPort), MEMF_PUBLIC | MEMF_CLEAR);
75 if (port)
77 if ((iihdata->InputEventMemPool = CreatePool(MEMF_PUBLIC | MEMF_CLEAR,
78 sizeof(struct GeneratedInputEvent) * 10,
79 sizeof(struct GeneratedInputEvent) * 10)) &&
80 (iihdata->ActionsMemPool = CreatePool(MEMF_SEM_PROTECTED,
81 2000, 2000)))
83 const struct TagItem dragtags[] =
85 {GA_SysGadget , TRUE },
86 {GA_SysGType , GTYP_WDRAGGING},
87 {TAG_DONE }
90 const struct TagItem sizetags[] =
92 {GA_SysGadget , TRUE },
93 {GA_SysGType , GTYP_SIZING },
94 {TAG_DONE }
97 iihdata->MasterDragGadget = (struct Gadget *)NewObjectA(GetPrivIBase(IntuitionBase)->dragbarclass,
98 NULL,
99 dragtags);
101 iihdata->MasterSizeGadget = (struct Gadget *)NewObjectA(GetPrivIBase(IntuitionBase)->sizebuttonclass,
102 NULL,
103 sizetags);
105 if (iihdata->MasterDragGadget && iihdata->MasterSizeGadget)
107 ULONG lock;
109 /* We do not want to be woken up by message replies.
110 We are anyway woken up about 10 times a second by
111 timer events
113 port->mp_Flags = PA_IGNORE;
115 NEWLIST( &(port->mp_MsgList) );
116 iihdata->IntuiReplyPort = port;
118 NEWLIST((struct List*) &iihdata->IntuiActionQueue);
119 NEWLIST((struct List*)&iihdata->NewAllocatedInputEventList);
120 NEWLIST((struct List*)&iihdata->AllocatedInputEventList);
121 iihdata->EndInputEventChain = &iihdata->ReturnInputEvent;
122 iihdata->FreeInputEvents = NULL;
124 iihdata->ActQualifier = IEQUALIFIER_RELATIVEMOUSE;
126 /* Note: there are several routines like CloseWindow, which
127 expect is_Data to point to the IIHData structure, so don't
128 change this! */
130 iihandler->is_Code = (APTR)AROS_ASMSYMNAME(IntuiInputHandler);
131 iihandler->is_Data = iihdata;
132 iihandler->is_Node.ln_Pri = 50;
133 iihandler->is_Node.ln_Name = "Intuition InputHandler";
135 lock = LockIBase(0UL);
137 iihdata->IntuitionBase = IntuitionBase;
139 UnlockIBase(lock);
141 GetPrivIBase(IntuitionBase)->IntuiReplyPort = iihdata->IntuiReplyPort;
142 GetPrivIBase(IntuitionBase)->IntuiActionQueue = &iihdata->IntuiActionQueue;
144 ReturnPtr ("InitIIH", struct Interrupt *, iihandler);
145 } /* f (iihdata->MasterDragGadget && iihdata->MasterSizeGadget) */
147 DisposeObject((Object *)iihdata->MasterDragGadget);
148 DisposeObject((Object *)iihdata->MasterSizeGadget);
150 DeletePool(iihdata->ActionsMemPool);
151 DeletePool(iihdata->InputEventMemPool);
153 } /* if (iihdata->InputEventMemPool = ... */
154 FreeMem(port, sizeof(struct MsgPort));
156 } /* if (port) */
157 FreeMem(iihdata, sizeof (struct IIHData));
158 iihdata->MouseBoundsActiveFlag = FALSE;
160 } /* if (iihdata) */
161 FreeMem(iihandler, sizeof (struct Interrupt));
163 } /* if (iihandler) */
165 ReturnPtr ("InitIIH", struct Interrupt *, NULL);
168 /****************************************************************************************/
170 VOID CleanupIIH(struct Interrupt *iihandler, struct IntuitionBase *IntuitionBase)
172 struct IIHData *iihdata = (struct IIHData *)iihandler->is_Data;
174 DisposeObject((Object *)iihdata->MasterDragGadget);
175 DisposeObject((Object *)iihdata->MasterSizeGadget);
177 FreeGeneratedInputEvents(iihdata);
178 DeletePool(iihdata->InputEventMemPool);
179 DeletePool(iihdata->ActionsMemPool);
181 /* One might think that this port is still in use by the inputhandler.
182 ** However, if intuition is closed for the last time, there should be no
183 ** windows that IntuiMessage can be sent to.
185 FreeMem(iihdata->IntuiReplyPort, sizeof (struct MsgPort));
187 FreeMem(iihdata, sizeof (struct IIHData));
188 FreeMem(iihandler, sizeof (struct Interrupt));
190 return;
193 /****************************************************************************************/
195 static void HandleIntuiReplyPort(struct IIHData *iihdata, struct IntuitionBase *IntuitionBase)
197 struct IntuiMessage *im;
199 while ((im = (struct IntuiMessage *)GetMsg(iihdata->IntuiReplyPort)))
201 if (im->IDCMPWindow && ResourceExisting(im->IDCMPWindow, RESOURCE_WINDOW, IntuitionBase))
203 struct IntWindow *win = (struct IntWindow *)im->IDCMPWindow;
205 Forbid();
206 GetSysTime(&win->lastmsgreplied);
207 Permit();
209 switch(im->Class)
211 case IDCMP_MOUSEMOVE:
212 IW(im->IDCMPWindow)->num_mouseevents--;
213 break;
215 case IDCMP_INTUITICKS:
216 AROS_ATOMIC_AND(im->IDCMPWindow->Flags, ~WFLG_WINDOWTICKED);
217 break;
219 #if USE_IDCMPUPDATE_MESSAGECACHE
220 case IDCMP_IDCMPUPDATE:
221 IW(im->IDCMPWindow)->num_idcmpupdate--;
223 if (!(IW(im->IDCMPWindow)->num_idcmpupdate) && IW(im->IDCMPWindow)->messagecache)
225 SendIntuiMessage(im->IDCMPWindow,IW(im->IDCMPWindow)->messagecache);
226 IW(im->IDCMPWindow)->messagecache = 0;
228 break;
229 #endif
231 case IDCMP_MENUVERIFY:
233 struct Window *w = im->IDCMPWindow;
234 struct IntScreen *scr = 0;
236 scr = GetPrivScreen(w->WScreen);
238 if (scr != GetPrivIBase(IntuitionBase)->MenuVerifyScreen ||
239 scr->MenuVerifySeconds > im->Seconds ||
240 (scr->MenuVerifySeconds == im->Seconds &&
241 scr->MenuVerifyMicros > im->Micros))
243 /* The timeout has expired, just ignore. */
245 else
247 --scr->MenuVerifyMsgCount;
248 if (w == scr->MenuVerifyActiveWindow &&
249 im->Code == MENUCANCEL)
251 ULONG lock = LockIBase(0);
252 struct Window *w1;
254 for (w1 = scr->Screen.FirstWindow; w1; w1 = w1->NextWindow)
256 if (w1->IDCMPFlags & IDCMP_MENUVERIFY && w1 != scr->MenuVerifyActiveWindow)
258 ih_fire_intuimessage(w1,
259 IDCMP_MOUSEBUTTONS,
260 MENUUP,
262 IntuitionBase);
266 UnlockIBase(lock);
268 scr->MenuVerifyActiveWindow = NULL;
269 scr->MenuVerifyTimeOut = 0;
270 scr->MenuVerifyMsgCount = 0;
271 scr->MenuVerifySeconds = 0;
272 scr->MenuVerifyMicros = 0;
273 GetPrivIBase(IntuitionBase)->MenuVerifyScreen = NULL;
275 else if (scr->MenuVerifyMsgCount == 0)
277 struct InputEvent ie;
279 /* currently we ONLY need the menu open time ! */
280 ie.ie_TimeStamp.tv_secs = im->Seconds;
281 ie.ie_TimeStamp.tv_micro = im->Micros;
283 if (FireMenuMessage(MMCODE_START, scr->MenuVerifyActiveWindow, &ie, IntuitionBase))
285 /* This lock will be released only when the user is
286 done with menus = when IECLASS_MENU + IESUBCLASS_MENUSTOP
287 event arrives (generated by MenuHandler task) */
289 ObtainSemaphore(&GetPrivIBase(IntuitionBase)->MenuLock);
290 iihdata->MenuWindow = scr->MenuVerifyActiveWindow;
291 MENUS_ACTIVE = TRUE;
294 scr->MenuVerifyActiveWindow = NULL;
295 scr->MenuVerifyTimeOut = 0;
296 scr->MenuVerifyMsgCount = 0;
297 scr->MenuVerifySeconds = 0;
298 scr->MenuVerifyMicros = 0;
299 GetPrivIBase(IntuitionBase)->MenuVerifyScreen = NULL;
302 break;
305 case IDCMP_SIZEVERIFY:
307 struct GadgetInfo *gi = &iihdata->GadgetInfo;
308 struct Window *w = im->IDCMPWindow;
309 struct Gadget *gadget = im->IAddress;
310 struct InputEvent ie;
311 BOOL reuse_event;
313 PrepareGadgetInfo(gi, IntuitionBase->ActiveScreen, w, NULL);
314 SetGadgetInfoGadget(gi, gadget, IntuitionBase);
316 if (IS_BOOPSI_GADGET(gadget))
318 ie.ie_NextEvent = NULL;
319 ie.ie_Class = IECLASS_RAWMOUSE;
320 ie.ie_SubClass = 0;
321 ie.ie_Code = IECODE_LBUTTON;
322 ie.ie_Qualifier = im->Qualifier;
323 ie.ie_X = im->MouseX;
324 ie.ie_Y = im->MouseY;
325 ie.ie_TimeStamp.tv_secs = IntuitionBase->Seconds;
326 ie.ie_TimeStamp.tv_micro = IntuitionBase->Micros;
328 DoGPInput(gi,
329 gadget,
330 &ie,
331 GM_GOACTIVE,
332 &reuse_event,
333 IntuitionBase);
335 /* For compatibility, send a GM_HANDLEINPUT too */
336 ie.ie_Class = IECLASS_RAWMOUSE;
337 ie.ie_Code = IECODE_NOBUTTON;
338 ie.ie_X = 0;
339 ie.ie_Y = 0;
341 gadget = DoGPInput(gi,
342 gadget,
343 &ie,
344 GM_HANDLEINPUT,
345 &reuse_event,
346 IntuitionBase);
349 /* From now on the master drag/size gadget takes over */
351 iihdata->ActiveSysGadget = gadget;
352 gadget = iihdata->MasterSizeGadget;
353 iihdata->ActiveGadget = gadget;
355 ie.ie_Class = IECLASS_RAWMOUSE;
356 ie.ie_Code = IECODE_LBUTTON;
357 ie.ie_X = im->MouseX;
358 ie.ie_Y = im->MouseY;
360 DoGPInput(gi,
361 gadget,
362 &ie,
363 GM_GOACTIVE,
364 &reuse_event,
365 IntuitionBase);
366 break;
369 case IDCMP_REQVERIFY:
371 struct Window *w = im->IDCMPWindow;
373 EndRequest(w->DMRequest, w);
375 ih_fire_intuimessage(w,
376 IDCMP_REQSET,
379 IntuitionBase);
381 break;
383 case IDCMP_WBENCHMESSAGE:
384 DEBUG_WORKBENCH(dprintf("HandleIntuiReplyPort: code 0x%lx\n",
385 im->Code));
386 break;
388 } /* switch(im->Class) */
390 if (im->Qualifier & IEQUALIFIER_REPEAT)
392 /* IDCMP_IDCMPUPDATE messages can also be sent from app task, therefore
393 it would be better if there was an ATOMIC_DEC macro or something */
395 if (IW(im->IDCMPWindow)->num_repeatevents)
397 IW(im->IDCMPWindow)->num_repeatevents--;
401 FreeIntuiMessage(im);
403 } /* while ((im = (struct IntuiMessage *)GetMsg(iihdata->IntuiReplyPort))) */
405 /****************************************************************************************/
407 struct Window *GetToolBoxWindow(struct InputEvent *ie, struct IntuitionBase *IntuitionBase)
409 /* The caller has checked that the input event is a IECLASS_RAWMOUSE, SELECTDOWN event */
410 /* NOTE: may be called with NULL ie ptr! */
411 struct Layer *l;
412 struct Window *new_w = NULL;
413 struct Screen *scr;
414 ULONG lock;
416 lock = LockIBase(0UL);
418 UnlockIBase(lock);
420 scr = IntuitionBase->FirstScreen;
422 if (scr)
424 D(bug("GetToolBoxWindow: Click at (%d,%d)\n",scr->MouseX,scr->MouseY));
426 /* What layer ? */
427 LockLayerInfo(&scr->LayerInfo);
429 l = WhichLayer(&scr->LayerInfo, scr->MouseX, scr->MouseY);
431 UnlockLayerInfo(&scr->LayerInfo);
433 if (NULL == l)
435 new_w = NULL;
436 D(bug("GetToolBoxWindow: Click not inside layer\n"));
438 else if (l == scr->BarLayer)
441 else
443 new_w = (struct Window *)l->Window;
444 if (new_w)
446 if ((new_w->Flags & WFLG_TOOLBOX) == 0) new_w = NULL;
448 if (!new_w)
450 D(bug("GetToolBoxWindow: Selected layer is not a ToolBox window\n"));
452 else
454 D(bug("GetToolBoxWindow: Found layer %p\n", l));
459 D(bug("GetToolBoxWindow: New window %p\n", new_w));
460 return new_w;
463 /****************************************************************************************/
465 AROS_UFH2(struct InputEvent *, IntuiInputHandler,
466 AROS_UFHA(struct InputEvent *, oldchain, A0),
467 AROS_UFHA(struct IIHData *, iihdata, A1)
470 AROS_USERFUNC_INIT
472 struct InputEvent *ie, *orig_ie, *next_ie, stackie;
473 struct Gadget *gadget = NULL, *boxgadget = NULL;
474 struct IntuitionBase *IntuitionBase = iihdata->IntuitionBase;
475 //ULONG lock;
476 struct GadgetInfo *gi = &iihdata->GadgetInfo;
477 struct GadgetInfo *boxgi = &iihdata->BoxGadgetInfo;
478 BOOL reuse_event, ie_used;
479 struct Window *w, *toolbox;
480 struct Requester *req;
481 ULONG stitlebarhit = 0;
482 #if SINGLE_SETPOINTERPOS_PER_EVENTLOOP
483 WORD pointerposx, pointerposy;
484 BOOL call_setpointerpos = FALSE;
485 #endif
487 D(bug("Inside intuition inputhandler, active window=%p\n", IntuitionBase->ActiveWindow));
489 // DEBUG_HANDLER(dprintf("Handler: IBase 0x%lx KeyMapBase 0x%lx\n",IntuitionBase,KeymapBase));
491 ObtainSemaphore(&GetPrivIBase(IntuitionBase)->InputHandlerLock);
493 if (!iihdata->InputDeviceTask) iihdata->InputDeviceTask = FindTask(NULL);
495 /* Then free generated InputEvents done in the previous round */
497 FreeGeneratedInputEvents(iihdata);
499 /* First handle IntuiMessages which were replied back to the IntuiReplyPort
500 by the apps */
502 HandleIntuiReplyPort(iihdata, IntuitionBase);
504 /* Handle action messages */
506 HandleIntuiActions(iihdata, IntuitionBase);
508 /* Now handle the input events */
510 ie = &stackie;
511 reuse_event = FALSE;
512 next_ie = oldchain;
514 /* shut up the compiler */
515 orig_ie = next_ie;
516 ie_used = FALSE;
518 gadget = iihdata->ActiveGadget;
520 while (reuse_event || next_ie)
523 struct Window *old_w;
524 BOOL keep_event = TRUE;
525 BOOL new_active_window = FALSE;
527 /* new event, we need to reset this */
529 iihdata->ActEventTablet = 0;
531 if (!reuse_event)
533 *ie = *next_ie;
534 orig_ie = next_ie;
535 next_ie = ie->ie_NextEvent;
536 ie_used = FALSE;
539 D(bug("iih: Handling event of class %d, code %d\n", ie->ie_Class, ie->ie_Code));
540 reuse_event = FALSE;
542 /* Set the timestamp in IntuitionBase */
544 IntuitionBase->Seconds = ie->ie_TimeStamp.tv_secs;
545 IntuitionBase->Micros = ie->ie_TimeStamp.tv_micro;
547 /* Use event to find the active window */
549 toolbox = GetToolBoxWindow(ie, IntuitionBase);
551 if (toolbox)
554 /* Do ToolBox Window Actions */
555 /* ToolBox Windows supports only a subset of IECLASS Actions */
556 w = toolbox;
557 req = NULL;
558 if (w)
560 req = w->FirstRequest;
562 switch (ie->ie_Class)
593 case IECLASS_RAWMOUSE:
594 switch (ie->ie_Code)
596 case SELECTDOWN:
599 BOOL new_boxgadget = FALSE;
600 BOOL sizeverify = FALSE;
602 iihdata->ActQualifier |= IEQUALIFIER_LEFTBUTTON;
604 if (MENUS_ACTIVE)
606 FireMenuMessage(MMCODE_EVENT, 0, ie, IntuitionBase);
607 keep_event = FALSE;
608 break;
611 if (!boxgadget)
613 /* use the *frontmost* screen rather than active one when searching
614 for sdepth gadget! */
615 boxgadget = FindGadget (IntuitionBase->FirstScreen,
616 stitlebarhit ? 0 : w, stitlebarhit ? 0 : req,
617 IntuitionBase->ActiveScreen ? IntuitionBase->ActiveScreen->MouseX : 0,
618 IntuitionBase->ActiveScreen ? IntuitionBase->ActiveScreen->MouseY : 0,
619 boxgi, FALSE, IntuitionBase);
621 D(bug("Click on gadget %p\n", boxgadget));
622 new_boxgadget = TRUE;
624 } /* if (!boxgadget) */
627 if (boxgadget && new_boxgadget)
629 if (w && (w->IDCMPFlags & IDCMP_SIZEVERIFY) &&
630 ((boxgadget->GadgetType & GTYP_SYSTYPEMASK) == GTYP_SIZING /*||
631 (boxgadget->GadgetType & GTYP_SYSTYPEMASK) == GTYP_WZOOM*/))
633 ih_fire_intuimessage(w,
634 IDCMP_SIZEVERIFY,
636 boxgadget,
637 IntuitionBase);
638 boxgadget = NULL;
639 sizeverify = TRUE;
641 else
643 BOOL is_draggad, is_sizegad;
645 /* Whenever the active gadget changes the gi must be updated
646 because it is cached in iidata->GadgetInfo!!!! Don't
647 forget to do this if somewhere else the active
648 gadget is changed, for example in ActivateGadget!!! */
650 PrepareGadgetInfo(boxgi, IntuitionBase->ActiveScreen, w, req);
651 SetGadgetInfoGadget(boxgi, boxgadget, IntuitionBase);
654 is_draggad = ((boxgadget->GadgetType & GTYP_SYSTYPEMASK) == GTYP_WDRAGGING);
655 is_sizegad = ((boxgadget->GadgetType & GTYP_SYSTYPEMASK) == GTYP_SIZING);
657 /* jDc: intui68k sends IDCMPs for GACT_IMMEDIATE drag&sizegads! */
658 if (boxgadget->Activation & GACT_IMMEDIATE)
660 ih_fire_intuimessage(w,
661 IDCMP_GADGETDOWN,
663 boxgadget,
664 IntuitionBase);
667 if (is_draggad || is_sizegad)
669 if (IS_BOOPSI_GADGET(boxgadget))
671 DoGPInput(boxgi,
672 boxgadget,
674 GM_GOACTIVE,
675 &reuse_event,
676 IntuitionBase);
678 /* Ignoring retval of dispatcher above is what
679 AmigaOS does too for boopsi drag/resize
680 gadgets */
684 /* From now on the master drag/size gadget takes over */
685 if ((w->MoreFlags & WMFLG_IAMMUI) && (w->Flags & WFLG_BORDERLESS))
687 iihdata->ActiveSysGadget = is_draggad ? boxgadget : 0;
689 else
691 iihdata->ActiveSysGadget = boxgadget;
693 boxgadget = is_draggad ? iihdata->MasterDragGadget : iihdata->MasterSizeGadget;
698 if (boxgadget)
702 switch (boxgadget->GadgetType & GTYP_GTYPEMASK)
704 case GTYP_BOOLGADGET:
705 /* Only set the GFLG_SELECTED flag for RELVERIFY and
706 * TOGGLESELECT gadget. It's for the user to do it if
707 * he wants for other GADGIMMEDIATE ones.
708 * Only RELVERIFY gadgets stay active.
711 if (boxgadget->Activation & (GACT_TOGGLESELECT | GACT_RELVERIFY))
713 boxgadget->Flags ^= GFLG_SELECTED;
714 RefreshBoolGadgetState(boxgadget, w, req, IntuitionBase);
717 if (boxgadget->Activation & GACT_RELVERIFY)
719 boxgadget->Activation |= GACT_ACTIVEGADGET;
720 iihdata->MouseWasInsideBoolGadget = TRUE;
722 else
724 boxgadget = NULL;
727 break;
729 case GTYP_PROPGADGET:
730 HandlePropSelectDown(boxgadget,
732 req,
733 w->MouseX - boxgi->gi_Domain.Left - GetGadgetLeft(boxgadget, boxgi->gi_Screen, boxgi->gi_Window, NULL),
734 w->MouseY - boxgi->gi_Domain.Top - GetGadgetTop(boxgadget, boxgi->gi_Screen, boxgi->gi_Window, NULL),
735 IntuitionBase);
738 break;
740 case GTYP_STRGADGET:
743 if (InsideGadget(boxgi->gi_Screen, boxgi->gi_Window,
744 boxgi->gi_Requester, boxgadget,
745 boxgi->gi_Screen->MouseX, boxgi->gi_Screen->MouseY))
747 UWORD imsgcode;
749 HandleStrInput(boxgadget, boxgi, ie, &imsgcode,
750 IntuitionBase);
752 else
754 boxgadget->Flags &= ~GFLG_SELECTED;
756 RefreshStrGadget(boxgadget, w, req, IntuitionBase);
757 boxgadget = NULL;
758 reuse_event = TRUE;
760 break;
762 case GTYP_CUSTOMGADGET:
764 boxgadget = DoGPInput(boxgi,
765 boxgadget,
767 (new_boxgadget ? GM_GOACTIVE : GM_HANDLEINPUT),
768 &reuse_event,
769 IntuitionBase);
770 D(bug("new_boxgadget %d, goactive %p\n", new_boxgadget, boxgadget));
773 if (boxgadget && new_boxgadget && (!(boxgadget->GadgetType & GTYP_SIZING)))
775 /* For compatibility, send a GM_HANDLEINPUT too */
776 struct InputEvent newie;
777 BOOL reuse_event;
779 newie.ie_NextEvent = NULL;
780 newie.ie_Class = IECLASS_RAWMOUSE;
781 newie.ie_SubClass = 0;
782 newie.ie_Code = IECODE_NOBUTTON;
783 newie.ie_Qualifier = ie->ie_Qualifier;
784 newie.ie_X = 0;
785 newie.ie_Y = 0;
786 newie.ie_TimeStamp.tv_secs = IntuitionBase->Seconds;
787 newie.ie_TimeStamp.tv_micro = IntuitionBase->Micros;
789 boxgadget = DoGPInput(boxgi,
790 boxgadget,
791 &newie,
792 GM_HANDLEINPUT,
793 &reuse_event,
794 IntuitionBase);
795 D(bug("handleinput %p\n", boxgadget));
798 break;
800 case 0: //orig gadtools / some 1.3 gadgets
802 if (IS_SYS_GADGET(boxgadget))
804 HandleSysGadgetVerify(boxgi, boxgadget, IntuitionBase);
806 else
808 if (boxgadget->Activation & GACT_RELVERIFY)
810 boxgadget->Activation |= GACT_ACTIVEGADGET;
811 iihdata->MouseWasInsideBoolGadget = TRUE;
812 if (boxgadget->Flags & GFLG_GADGHIMAGE)
814 boxgadget->Flags ^= GFLG_SELECTED;
815 RefreshBoolGadgetState(boxgadget, w, req, IntuitionBase);
818 else
820 /* jDc: this is what original intuition does, before crashing after a while ;)*/
821 ih_fire_intuimessage(w,
822 IDCMP_MOUSEBUTTONS,
823 SELECTDOWN,
825 IntuitionBase);
829 break;
830 } /* switch (GadgetType) */
832 } /* if (a boxgadget is active) */
833 else if (w && (!req || req->Flags & NOISYREQ) && !sizeverify && !stitlebarhit)
836 ih_fire_intuimessage(w,
837 IDCMP_MOUSEBUTTONS,
838 SELECTDOWN,
840 IntuitionBase);
845 } /* case SELECTDOWN */
847 break;
849 case SELECTUP:
850 iihdata->ActQualifier &= ~IEQUALIFIER_LEFTBUTTON;
853 if (MENUS_ACTIVE)
855 FireMenuMessage(MMCODE_EVENT, 0, ie, IntuitionBase);
856 keep_event = FALSE;
857 break;
860 if (boxgadget)
862 BOOL inside = InsideGadget(boxgi->gi_Screen, boxgi->gi_Window,
863 boxgi->gi_Requester, boxgadget,
864 boxgi->gi_Screen->MouseX, boxgi->gi_Screen->MouseY);
866 /*int selected = (boxgadget->Flags & GFLG_SELECTED) != 0;*/
868 switch (boxgadget->GadgetType & GTYP_GTYPEMASK)
870 case GTYP_BOOLGADGET:
871 /* Must be a RELVERIFY boxgadget */
873 if (!(boxgadget->Activation & GACT_TOGGLESELECT) && inside)
875 boxgadget->Flags ^= GFLG_SELECTED;
876 RefreshBoolGadgetState(boxgadget, w, req, IntuitionBase);
879 if (inside)
881 if (IS_SYS_GADGET(boxgadget))
883 HandleSysGadgetVerify(boxgi, boxgadget, IntuitionBase);
885 else
887 if (req && boxgadget->Activation & GACT_ENDGADGET)
889 EndRequest(req, w);
891 req = w->FirstRequest;
894 ih_fire_intuimessage(w,
895 IDCMP_GADGETUP,
897 boxgadget,
898 IntuitionBase);
901 else
903 /* RKRM say so */
904 ih_fire_intuimessage(w,
905 IDCMP_MOUSEBUTTONS,
906 SELECTUP,
908 IntuitionBase);
911 boxgadget->Activation &= ~GACT_ACTIVEGADGET;
912 boxgadget = NULL;
913 break;
915 case GTYP_PROPGADGET:
916 HandlePropSelectUp(boxgadget, w, req, IntuitionBase);
917 if (boxgadget->Activation & GACT_RELVERIFY)
919 ih_fire_intuimessage(w,
920 IDCMP_GADGETUP,
922 boxgadget,
923 IntuitionBase);
926 boxgadget = NULL;
927 break;
929 /* Intuition string gadgets don't care about SELECTUP */
931 case GTYP_CUSTOMGADGET:
932 boxgadget = DoGPInput(boxgi, boxgadget, ie, GM_HANDLEINPUT, &reuse_event, IntuitionBase);
933 break;
935 case 0: //orig gadtools / some 1.3 gadgets
937 boxgadget->Activation &= ~GACT_ACTIVEGADGET;
938 if (boxgadget->Activation & GACT_RELVERIFY)
940 if (boxgadget->Flags & GFLG_GADGHIMAGE)
942 if (inside)
944 boxgadget->Flags ^= GFLG_SELECTED;
945 RefreshBoolGadgetState(boxgadget, w, req, IntuitionBase);
949 if (inside)
951 ih_fire_intuimessage(w,
952 IDCMP_GADGETUP,
954 boxgadget,
955 IntuitionBase);
957 } else {
958 ih_fire_intuimessage(w,
959 IDCMP_MOUSEBUTTONS,
960 SELECTUP,
962 IntuitionBase);
964 boxgadget = NULL;
965 break;
968 } /* switch GadgetType */
970 } /* if (a boxgadget is currently active) */
971 else if (w && (!req || req->Flags & NOISYREQ))
973 ih_fire_intuimessage(w,
974 IDCMP_MOUSEBUTTONS,
975 SELECTUP,
977 IntuitionBase);
980 break; /* case SELECTUP */
982 case MENUDOWN:
983 iihdata->ActQualifier |= IEQUALIFIER_RBUTTON;
986 if (MENUS_ACTIVE)
988 FireMenuMessage(MMCODE_EVENT, 0, ie, IntuitionBase);
989 keep_event = FALSE;
990 break;
994 if (w && !req && w->DMRequest && !(w->Flags & WFLG_RMBTRAP))
996 if (!MENUS_ACTIVE &&
997 DoubleClick(GetPrivIBase(IntuitionBase)->DMStartSecs,
998 GetPrivIBase(IntuitionBase)->DMStartMicro,
999 ie->ie_TimeStamp.tv_secs,
1000 ie->ie_TimeStamp.tv_micro))
1002 if (w->IDCMPFlags & IDCMP_REQVERIFY)
1004 ih_fire_intuimessage(w,
1005 IDCMP_REQVERIFY,
1006 MENUHOT,
1007 NULL,
1008 IntuitionBase);
1010 else if (Request(w->DMRequest, w))
1012 req = w->DMRequest;
1014 ih_fire_intuimessage(w,
1015 IDCMP_REQSET,
1018 IntuitionBase);
1020 keep_event = FALSE;
1021 break;
1026 if (w && !boxgadget)
1028 if (!(w->Flags & WFLG_RMBTRAP) && !req)
1030 struct IntScreen *scr = GetPrivScreen(w->WScreen);
1031 struct Window *w1;
1032 ULONG lock;
1033 BOOL mouseon = TRUE;
1035 scr->MenuVerifyMsgCount = 0;
1037 if (w->MouseX < 0 || w->MouseY < 0) mouseon = FALSE;
1038 if (w->MouseX > w->Width || w->MouseY > w->Height) mouseon = FALSE;
1040 if (w->IDCMPFlags & IDCMP_MENUVERIFY && (!(IW(w)->specialflags & SPFLAG_IAMDEAD)))
1042 ih_fire_intuimessage(w,
1043 IDCMP_MENUVERIFY,
1044 mouseon ? MENUHOT : MENUWAITING,
1046 IntuitionBase);
1047 scr->MenuVerifyMsgCount++;
1050 lock = LockIBase(0);
1052 for (w1 = scr->Screen.FirstWindow; w1; w1 = w1->NextWindow)
1054 if ((w1->IDCMPFlags & IDCMP_MENUVERIFY) && (w1 != w) && (!(IW(w)->specialflags & SPFLAG_IAMDEAD)))
1056 ih_fire_intuimessage(w1,
1057 IDCMP_MENUVERIFY,
1058 MENUWAITING,
1060 IntuitionBase);
1061 ++scr->MenuVerifyMsgCount;
1065 UnlockIBase(lock);
1067 /* FIXME: when a window is opened with IDCMP_MENUVERIFY
1068 * (or this event is requested via ModifyIDCMP), and a
1069 * verify operation is pending, the window should get
1070 * a verify message too. Oh well.
1073 if (scr->MenuVerifyMsgCount)
1075 GetPrivIBase(IntuitionBase)->MenuVerifyScreen = scr;
1076 scr->MenuVerifyActiveWindow = w;
1077 scr->MenuVerifyTimeOut = 2;
1078 scr->MenuVerifySeconds = IntuitionBase->Seconds;
1079 scr->MenuVerifyMicros = IntuitionBase->Micros;
1081 else if (FireMenuMessage(MMCODE_START, w, NULL/*ie*/, IntuitionBase))
1083 /* This lock will be released only when the user is
1084 done with menus = when IECLASS_MENU + IESUBCLASS_MENUSTOP
1085 event arrives (generated by MenuHandler task) */
1087 ObtainSemaphore(&GetPrivIBase(IntuitionBase)->MenuLock);
1088 iihdata->MenuWindow = w;
1089 MENUS_ACTIVE = TRUE;
1093 /* fall through */
1095 case MENUUP:
1096 case MIDDLEDOWN:
1097 case MIDDLEUP:
1099 switch(ie->ie_Code)
1101 case MENUUP:
1102 iihdata->ActQualifier &= ~IEQUALIFIER_RBUTTON;
1103 if (GetPrivIBase(IntuitionBase)->MenuVerifyScreen)
1105 struct Window *w1;
1106 struct IntScreen *scr = GetPrivIBase(IntuitionBase)->MenuVerifyScreen;
1107 ULONG lock = LockIBase(0);
1109 for (w1 = scr->Screen.FirstWindow; w1; w1 = w1->NextWindow)
1111 if (w1->IDCMPFlags & IDCMP_MENUVERIFY && w1->IDCMPFlags & IDCMP_MOUSEBUTTONS)
1113 ih_fire_intuimessage(w1,
1114 IDCMP_MOUSEBUTTONS,
1115 MENUUP,
1117 IntuitionBase);
1121 UnlockIBase(lock);
1123 /* FIXME: when the active window replies the verifymessage,
1124 * it should get a IDCMP_MENUPICK/MENUNULL message.
1126 GetPrivIBase(IntuitionBase)->MenuVerifyScreen = NULL;
1127 scr->MenuVerifyActiveWindow = NULL;
1128 scr->MenuVerifyMsgCount = 0;
1129 scr->MenuVerifyTimeOut = 0;
1130 scr->MenuVerifySeconds = 0;
1131 scr->MenuVerifyMicros = 0;
1133 break;
1135 case MIDDLEDOWN:
1136 iihdata->ActQualifier |= IEQUALIFIER_MIDBUTTON;
1137 if (DoubleClick(GetPrivIBase(IntuitionBase)->LastClickSecs,GetPrivIBase(IntuitionBase)->LastClickMicro,
1138 ie->ie_TimeStamp.tv_secs,ie->ie_TimeStamp.tv_micro))
1140 if (GetPrivIBase(IntuitionBase)->DoubleClickButton != MIDDLEDOWN)
1142 GetPrivIBase(IntuitionBase)->DoubleClickCounter = 0;
1143 GetPrivIBase(IntuitionBase)->DoubleClickButton = MIDDLEDOWN;
1145 else
1147 GetPrivIBase(IntuitionBase)->DoubleClickCounter ++;
1150 else
1152 GetPrivIBase(IntuitionBase)->DoubleClickButton = MIDDLEDOWN;
1153 GetPrivIBase(IntuitionBase)->DoubleClickCounter = 0;
1155 /* update last click time for doubleclicktofront */
1156 GetPrivIBase(IntuitionBase)->LastClickSecs = ie->ie_TimeStamp.tv_secs;
1157 GetPrivIBase(IntuitionBase)->LastClickMicro = ie->ie_TimeStamp.tv_micro;
1158 break;
1160 case MIDDLEUP:
1161 iihdata->ActQualifier &= ~IEQUALIFIER_MIDBUTTON;
1162 break;
1165 if (MENUS_ACTIVE)
1167 FireMenuMessage(MMCODE_EVENT, 0, ie, IntuitionBase);
1168 keep_event = FALSE;
1169 break;
1173 if (boxgadget)
1175 if (IS_BOOPSI_GADGET(boxgadget))
1177 boxgadget = DoGPInput(boxgi, boxgadget, ie, GM_HANDLEINPUT, &reuse_event, IntuitionBase);
1180 } /* if (there is an active boxgadget) */
1181 else if (w && (!req || req->Flags & NOISYREQ) && w != GetPrivScreen(w->WScreen)->MenuVerifyActiveWindow)
1183 ih_fire_intuimessage(w,
1184 IDCMP_MOUSEBUTTONS,
1185 ie->ie_Code,
1187 IntuitionBase);
1190 break; /* case MENUDOWN */
1192 case IECODE_NOBUTTON: /* MOUSEMOVE */
1195 if (ie->ie_Qualifier & IEQUALIFIER_RELATIVEMOUSE)
1197 struct Screen *scr;
1198 //ULONG Thresh;
1200 /* Add delta information lost in previous mousemove event. See below. */
1201 iihdata->DeltaMouseX = ie->ie_X + iihdata->DeltaMouseX_Correction;
1202 iihdata->DeltaMouseY = ie->ie_Y + iihdata->DeltaMouseY_Correction;
1204 #define ACCELERATOR_THRESH 2
1205 #define ACCELERATOR_MULTI 2
1207 if (GetPrivIBase(IntuitionBase)->ActivePreferences->EnableCLI & MOUSE_ACCEL)
1209 /* Acceleration */
1210 if (ABS(iihdata->DeltaMouseX) > ACCELERATOR_THRESH)
1212 iihdata->DeltaMouseX *= ACCELERATOR_MULTI;
1214 if (ABS(iihdata->DeltaMouseY) > ACCELERATOR_THRESH)
1216 iihdata->DeltaMouseY *= ACCELERATOR_MULTI;
1220 switch(GetPrivIBase(IntuitionBase)->ActivePreferences->PointerTicks)
1222 case 0:
1223 iihdata->DeltaMouseX_Correction = 0;
1224 iihdata->DeltaMouseX_Correction = 0;
1225 break;
1227 default:
1228 /* Remember the delta information which gets lost because of division by PointerTicks.
1229 Will be added to prescaled deltas of next mousemove event. If this is not done, moving
1230 the mouse very slowly would cause it to not move at all */
1232 iihdata->DeltaMouseX_Correction = iihdata->DeltaMouseX % GetPrivIBase(IntuitionBase)->ActivePreferences->PointerTicks;
1233 iihdata->DeltaMouseY_Correction = iihdata->DeltaMouseY % GetPrivIBase(IntuitionBase)->ActivePreferences->PointerTicks;
1235 iihdata->DeltaMouseX /= GetPrivIBase(IntuitionBase)->ActivePreferences->PointerTicks;
1236 iihdata->DeltaMouseY /= GetPrivIBase(IntuitionBase)->ActivePreferences->PointerTicks;
1237 break;
1241 ie->ie_X = iihdata->DeltaMouseX + iihdata->LastMouseX;
1242 ie->ie_Y = iihdata->DeltaMouseY + iihdata->LastMouseY;
1244 //jDc: not really necessary to lock this for reading since this ptr is only modified
1245 //by functions synced with inputhandler
1246 //lock = LockIBase(0);
1247 scr = IntuitionBase->FirstScreen;
1249 if (scr)
1251 if (IntuitionBase->FirstScreen->Flags & AUTOSCROLL)
1254 #define VWIDTH IntuitionBase->ViewLord.ViewPort->DWidth
1255 #define VHEIGHT IntuitionBase->ViewLord.ViewPort->DHeight
1256 #define VDX IntuitionBase->ViewLord.ViewPort->DxOffset
1257 #define VDY IntuitionBase->ViewLord.ViewPort->DyOffset
1259 if ((ie->ie_X > VWIDTH - scr->LeftEdge - 1) || (ie->ie_X < - scr->LeftEdge) ||
1260 (ie->ie_Y > VHEIGHT - scr->TopEdge - 1) || (ie->ie_Y < - scr->TopEdge))
1262 if (ie->ie_X > VWIDTH - scr->LeftEdge - 1)
1264 scr->LeftEdge = VWIDTH - ie->ie_X;
1265 if (VWIDTH - scr->LeftEdge > scr->Width) scr->LeftEdge = VWIDTH - scr->Width;
1266 VDX = scr->LeftEdge;
1269 if (ie->ie_X < -scr->LeftEdge)
1271 scr->LeftEdge = -ie->ie_X;
1272 if (scr->LeftEdge < VWIDTH - scr->Width) scr->LeftEdge = VWIDTH - scr->Width;
1273 if(scr->LeftEdge > 0) scr->LeftEdge = 0; // we don't support > 0 LeftEdges
1274 VDX = scr->LeftEdge;
1277 if (ie->ie_Y > VHEIGHT - scr->TopEdge - 1)
1279 scr->TopEdge = VHEIGHT - ie->ie_Y;
1280 if (VHEIGHT - scr->TopEdge > scr->Height) scr->TopEdge = VHEIGHT - scr->Height;
1281 VDY = scr->TopEdge;
1284 if (ie->ie_Y < -scr->TopEdge)
1286 scr->TopEdge = - ie->ie_Y;
1287 if (scr->TopEdge < VHEIGHT - scr->Height) scr->TopEdge = VHEIGHT - scr->Height;
1288 if(scr->TopEdge > 0) scr->TopEdge = 0;
1289 VDY = scr->TopEdge;
1292 ScrollVPort(IntuitionBase->ViewLord.ViewPort);
1296 if (ie->ie_X >= scr->Width + max(scr->LeftEdge,0)) ie->ie_X = scr->Width + max(scr->LeftEdge,0) - 1;
1297 if (ie->ie_Y >= scr->Height + max(scr->TopEdge,0)) ie->ie_Y = scr->Height + max(scr->TopEdge,0) - 1;
1298 if (ie->ie_X < - scr->LeftEdge) ie->ie_X = - scr->LeftEdge;
1299 if (ie->ie_Y < - scr->TopEdge) ie->ie_Y = - scr->TopEdge;
1302 else
1304 if (ie->ie_X >= 320) ie->ie_X = 320 - 1;
1305 if (ie->ie_Y >= 200) ie->ie_Y = 200 - 1;
1306 if (ie->ie_X < 0) ie->ie_X = 0;
1307 if (ie->ie_Y < 0) ie->ie_Y = 0;
1309 //UnlockIBase(lock);
1311 else
1313 iihdata->DeltaMouseX = ie->ie_X - iihdata->LastMouseX;
1314 iihdata->DeltaMouseY = ie->ie_Y - iihdata->LastMouseY;
1318 /* Do Mouse Bounding - mouse will be most restrictive of screen size or mouse bounds */
1319 if (iihdata->MouseBoundsActiveFlag)
1321 if (ie->ie_X < iihdata->MouseBoundsLeft)
1323 ie->ie_X = iihdata->MouseBoundsLeft;
1325 else if (ie->ie_X > iihdata->MouseBoundsRight)
1327 ie->ie_X = iihdata->MouseBoundsRight;
1330 if (ie->ie_Y < iihdata->MouseBoundsTop)
1332 ie->ie_Y = iihdata->MouseBoundsTop;
1334 else if (ie->ie_Y > iihdata->MouseBoundsBottom)
1336 ie->ie_Y = iihdata->MouseBoundsBottom;
1340 #if !SINGLE_SETPOINTERPOS_PER_EVENTLOOP
1341 SetPointerPos(ie->ie_X, ie->ie_Y);
1342 #else
1343 pointerposx = ie->ie_X;
1344 pointerposy = ie->ie_Y;
1345 call_setpointerpos = TRUE;
1346 #endif
1348 iihdata->LastMouseX = ie->ie_X;
1349 iihdata->LastMouseY = ie->ie_Y;
1351 notify_mousemove_screensandwindows(ie->ie_X,
1352 ie->ie_Y,
1353 IntuitionBase);
1356 if (MENUS_ACTIVE)
1358 FireMenuMessage(MMCODE_EVENT, 0, ie, IntuitionBase);
1359 keep_event = FALSE;
1360 break;
1363 if (boxgadget)
1365 keep_event = FALSE;
1367 switch (boxgadget->GadgetType & GTYP_GTYPEMASK)
1369 case GTYP_BOOLGADGET:
1370 case 0: //fallback for sucky gadgets
1371 /* Must be a RELVERIFY boxgadget */
1373 BOOL inside;
1375 inside = InsideGadget(boxgi->gi_Screen,
1376 boxgi->gi_Window,
1377 boxgi->gi_Requester,
1378 boxgadget,
1379 boxgi->gi_Screen->MouseX,
1380 boxgi->gi_Screen->MouseY);
1382 if (inside != iihdata->MouseWasInsideBoolGadget)
1384 iihdata->MouseWasInsideBoolGadget = inside;
1386 boxgadget->Flags ^= GFLG_SELECTED;
1387 RefreshBoolGadgetState(boxgadget, w, req, IntuitionBase);
1390 break;
1392 case GTYP_PROPGADGET:
1393 HandlePropMouseMove(boxgadget,
1395 req,
1396 w->MouseX - boxgi->gi_Domain.Left - GetGadgetLeft(boxgadget, boxgi->gi_Screen, boxgi->gi_Window, NULL),
1397 w->MouseY - boxgi->gi_Domain.Top - GetGadgetTop(boxgadget, boxgi->gi_Screen, boxgi->gi_Window, NULL),
1398 IntuitionBase);
1400 break;
1402 case GTYP_CUSTOMGADGET:
1403 boxgadget = DoGPInput(boxgi, boxgadget, ie, GM_HANDLEINPUT, &reuse_event, IntuitionBase);
1404 break;
1406 } /* switch GadgetType */
1408 } /* if (a boxgadget is currently active) */
1410 keep_event = FALSE;
1412 if (!w) break;
1414 if (IW(w)->helpflags & HELPF_GADGETHELP && (!(PeekQualifier() & (IEQUALIFIER_LEFTBUTTON|IEQUALIFIER_RBUTTON|IEQUALIFIER_MIDBUTTON))))
1416 struct Window *hw;
1417 struct Gadget *g;
1419 hw = FindActiveWindow(ie, 0, IntuitionBase);
1421 if (hw != w &&
1422 (!hw || !(IW(w)->helpflags & HELPF_ISHELPGROUP) ||
1423 !(IW(hw)->helpflags & HELPF_ISHELPGROUP) ||
1424 IW(w)->helpgroup != IW(hw)->helpgroup))
1427 if (iihdata->LastHelpWindow)
1429 fire_intuimessage(w,
1430 IDCMP_GADGETHELP,
1432 NULL,
1433 IntuitionBase);
1435 iihdata->LastHelpGadget = NULL;
1436 iihdata->LastHelpWindow = NULL;
1437 iihdata->HelpGadgetFindTime = 0;
1440 else
1442 g = FindHelpGadget (hw,
1443 IntuitionBase->ActiveScreen->MouseX,
1444 IntuitionBase->ActiveScreen->MouseY,
1445 IntuitionBase);
1446 if (g && g != iihdata->LastHelpGadget)
1448 if (!iihdata->LastHelpGadget)
1450 iihdata->HelpGadgetFindTime = ((UQUAD)ie->ie_TimeStamp.tv_secs) * 50;
1451 iihdata->HelpGadgetFindTime += ie->ie_TimeStamp.tv_micro / 20000;
1453 else
1455 if (hw == iihdata->LastHelpWindow)
1457 iihdata->HelpGadgetFindTime = ((UQUAD)ie->ie_TimeStamp.tv_secs) * 50;
1458 iihdata->HelpGadgetFindTime += ie->ie_TimeStamp.tv_micro / 20000;
1459 iihdata->HelpGadgetFindTime += 25;//smaller delay
1463 else if (g != iihdata->LastHelpGadget ||
1464 hw != iihdata->LastHelpWindow)
1466 fire_intuimessage(hw,
1467 IDCMP_GADGETHELP,
1468 0, /* Don't know what it should be */
1470 IntuitionBase);
1473 iihdata->LastHelpGadget = g;
1474 iihdata->LastHelpWindow = hw;
1477 else
1479 iihdata->LastHelpGadget = NULL;
1480 iihdata->LastHelpWindow = NULL;
1481 iihdata->HelpGadgetFindTime = 0;
1484 if (!(w->IDCMPFlags & IDCMP_MOUSEMOVE)) break;
1486 /* Send IDCMP_MOUSEMOVE if WFLG_REPORTMOUSE is set
1487 and/or active boxgadget has GACT_FOLLOWMOUSE set */
1489 /* jDc: do NOT send when sizegad is pressed */
1491 if (!(w->Flags & WFLG_REPORTMOUSE))
1493 if (!boxgadget) break;
1494 if (!(boxgadget->Activation & GACT_FOLLOWMOUSE)) break;
1496 else
1498 if (boxgadget && (boxgadget->GadgetType & (GTYP_SIZING|GTYP_WDRAGGING))) break;
1501 orig_ie->ie_Class = IECLASS_RAWMOUSE;
1503 /* Limit the number of IDCMP_MOUSEMOVE messages sent to intuition.
1504 note that this comes after handling gadgets, because gadgets should get all events.
1507 if (IW(w)->num_mouseevents >= IW(w)->mousequeue)
1509 BOOL old_msg_found = FALSE;
1511 /* Mouse Queue is full, so try looking for a not
1512 yet GetMsg()ed IntuiMessage in w->UserPort
1513 trying to modify that. */
1515 Forbid();
1516 if (w->UserPort)
1518 struct IntuiMessage *im;
1520 for (im = (struct IntuiMessage *)w->UserPort->mp_MsgList.lh_TailPred;
1521 im->ExecMessage.mn_Node.ln_Pred;
1522 im = (struct IntuiMessage *)im->ExecMessage.mn_Node.ln_Pred)
1524 if ((im->Class == IDCMP_MOUSEMOVE) &&
1525 (im->IDCMPWindow == w))
1527 im->Qualifier = iihdata->ActQualifier;
1529 if (w->IDCMPFlags & IDCMP_DELTAMOVE)
1531 im->MouseX = iihdata->DeltaMouseX;
1532 im->MouseY = iihdata->DeltaMouseY;
1534 else
1536 im->MouseX = w->MouseX;
1537 im->MouseY = w->MouseY;
1539 CurrentTime(&im->Seconds, &im->Micros);
1541 old_msg_found = TRUE;
1542 break;
1545 } /* if (w->UserPort) */
1546 Permit();
1548 /* no need to send a new message if we modified
1549 an existing one ... */
1551 if (old_msg_found) break;
1553 /* ... otherwise we are in a strange situation. The mouse
1554 queue is full, but we did not find an existing MOUSEMOVE
1555 imsg in w->UserPort. So the app probably has removed
1556 an imsg from the UserPort with GetMsg but we did not get
1557 the ReplyMsg, yet. In this case we do send a new message */
1559 HandleIntuiReplyPort(iihdata, IntuitionBase);
1563 /* MouseQueue is not full, so we can send a message. We increase
1564 IntWindow->num_mouseevents which will later be decreased after
1565 the Intuition InputHandler gets the ReplyMessage from the app
1566 and handles it in HandleIntuiReplyPort() */
1568 if (ih_fire_intuimessage(w,
1569 IDCMP_MOUSEMOVE,
1570 IECODE_NOBUTTON,
1572 IntuitionBase))
1574 IW(w)->num_mouseevents++;
1577 break;
1579 } /* case IECODE_NOBUTTON */
1581 } /* switch (ie->ie_Code) (what button was pressed ?) */
1582 break;
1632 w = IntuitionBase->ActiveWindow;
1634 if (!MENUS_ACTIVE && !SYSGADGET_ACTIVE)
1636 /* lock = LockIBase(0UL); */
1638 old_w = w;
1639 if (ie->ie_Class == IECLASS_RAWMOUSE && ie->ie_Code == SELECTDOWN)
1641 w = FindActiveWindow(ie, &stitlebarhit, IntuitionBase);
1642 D(bug("iih:New active window: %p\n", w));
1646 if ( w != old_w )
1648 if (w)
1650 D(bug("Activating new window (title %s)\n", w->Title ? w->Title : "<noname>"));
1652 D(bug("Window activated\n"));
1654 else
1656 D(bug("Making active window inactive. Now there's no active window\n"));
1658 new_active_window = TRUE;
1659 iihdata->NewActWindow = w;
1662 /* UnlockIBase(lock); */
1664 if (new_active_window)
1666 if (gadget && w &&
1667 (!(GetPrivScreen(w->WScreen)->MenuVerifyMsgCount)) &&
1668 (!(MENUS_ACTIVE)) && (!(SYSGADGET_ACTIVE)))
1670 switch (gadget->GadgetType & GTYP_GTYPEMASK)
1673 case GTYP_CUSTOMGADGET:
1675 struct gpGoInactive gpgi;
1677 gpgi.MethodID = GM_GOINACTIVE;
1678 gpgi.gpgi_GInfo = gi;
1679 gpgi.gpgi_Abort = 1;
1681 Locked_DoMethodA(gi->gi_Window, gadget, (Msg)&gpgi, IntuitionBase);
1682 break;
1685 case GTYP_STRGADGET:
1686 gadget->Flags &= ~GFLG_SELECTED;
1687 RefreshStrGadget(gadget, gi->gi_Window, gi->gi_Requester, IntuitionBase);
1688 break;
1690 case GTYP_BOOLGADGET:
1691 /* That a bool gadget is active here can only happen
1692 if user used LMB to activate gadget and LAMIGA + LALT
1693 to activate other window, or viceversa */
1694 /* The gadget must be a RELVERIFY one */
1695 if (!(gadget->Activation & GACT_TOGGLESELECT))
1697 BOOL inside;
1699 inside = InsideGadget(gi->gi_Screen, gi->gi_Window,
1700 gi->gi_Requester, gadget,
1701 gi->gi_Screen->MouseX, gi->gi_Screen->MouseY);
1703 if (inside)
1705 gadget->Flags &= ~GFLG_SELECTED;
1706 RefreshBoolGadgetState(gadget, gi->gi_Window,
1707 gi->gi_Requester, IntuitionBase);
1710 break;
1712 case GTYP_PROPGADGET:
1713 /* That a prop gadget is active here can only happen
1714 if user used LMB to activate gadget and LAMIGA + LALT
1715 to activate other window, or viceversa */
1717 HandlePropSelectUp(gadget, gi->gi_Window, NULL, IntuitionBase);
1718 if (gadget->Activation & GACT_RELVERIFY)
1720 ih_fire_intuimessage(gi->gi_Window,
1721 IDCMP_GADGETUP,
1723 gadget,
1724 IntuitionBase);
1726 break;
1728 } /* switch (gadget->GadgetType & GTYP_GTYPEMASK) */
1730 gadget->Activation &= ~GACT_ACTIVEGADGET;
1731 iihdata->ActiveGadget = NULL;
1732 gadget = NULL;
1735 /* ActivateWindow works if w = NULL */
1736 /* jacaDcaps: some gui toolkits (die reaction, die!) close the window opened by a boopsi gadget when
1737 it gets hit with lmb, so we need to check if the new active window does not go away by
1738 performing GM_GOINACTIVE on the gadget. NOTE: CloseWindow's part performed on input.device context
1739 clears the iihdata->NewActWindow if it's the actually closed one. */
1740 if (w == iihdata->NewActWindow)
1742 ActivateWindow(w);
1744 else
1746 w = IntuitionBase->ActiveWindow;
1747 new_active_window = FALSE;
1748 ie->ie_Class = IECLASS_NULL; //lose the event, otherwise the gadget will get activated again ;)
1751 iihdata->NewActWindow = 0;
1753 } /* if (new_active_window) */
1755 } /* if (!MENUS_ACTIVE) */
1757 req = NULL;
1758 if (w)
1760 req = w->FirstRequest;
1763 D(bug("w %p req %p gadget %p\n", w, req, gadget));
1765 switch (ie->ie_Class)
1767 case IECLASS_POINTERPOS:
1768 ie->ie_SubClass = IESUBCLASS_COMPATIBLE;
1769 /* fall through */
1771 case IECLASS_NEWPOINTERPOS:
1772 switch (ie->ie_SubClass)
1774 case IESUBCLASS_COMPATIBLE:
1775 ie->ie_Code = IECODE_NOBUTTON;
1776 break;
1778 case IESUBCLASS_PIXEL:
1780 struct IEPointerPixel *pp = ie->ie_EventAddress;
1782 ie->ie_X = pp->iepp_Position.X + pp->iepp_Screen->LeftEdge;
1783 ie->ie_Y = pp->iepp_Position.Y + pp->iepp_Screen->TopEdge;
1785 ie->ie_Code = IECODE_NOBUTTON;
1786 break;
1788 case IESUBCLASS_TABLET:
1790 //unsupported - does anything use it anyway? ;)
1792 ie->ie_Code = 0;
1793 break;
1795 case IESUBCLASS_NEWTABLET:
1797 struct IENewTablet *nt = (struct IENewTablet *)ie->ie_EventAddress;
1798 struct Screen *scr = IntuitionBase->FirstScreen;
1800 if (nt)
1802 iihdata->ActEventTablet = nt; //cache this
1803 ie->ie_X = (scr->Width * nt->ient_TabletX) / nt->ient_RangeX;
1804 ie->ie_Y = (scr->Height * nt->ient_TabletY) / nt->ient_RangeY;
1806 ie->ie_Class = IECLASS_RAWMOUSE;
1808 break;
1810 default:
1811 ie->ie_Code = 0;
1812 break;
1814 /* fall through */
1816 case IECLASS_RAWMOUSE:
1817 switch (ie->ie_Code)
1819 case SELECTDOWN:
1821 BOOL new_gadget = FALSE;
1822 BOOL sizeverify = FALSE;
1824 iihdata->ActQualifier |= IEQUALIFIER_LEFTBUTTON;
1826 #ifdef SKINS
1827 iihdata->TitlebarAppearTime = 0;
1828 #endif
1829 if (MENUS_ACTIVE)
1831 FireMenuMessage(MMCODE_EVENT, 0, ie, IntuitionBase);
1832 keep_event = FALSE;
1833 break;
1836 #ifdef SKINS
1837 if (!gadget && w)
1839 struct Gadget * draggadget = 0;
1841 if ((!(w->FirstRequest)) && (w->Flags & WFLG_DRAGBAR) && MatchHotkey(ie,IA_ACTIVEWINDOWMOVE,IntuitionBase))
1843 if (w->MouseX < IW(w)->sizeimage_width || w->MouseX > w->Width - IW(w)->sizeimage_width - 1 || w->MouseY < ((IW(w)->sizeimage_height > w->BorderTop) ? IW(w)->sizeimage_height : w->BorderTop) || w->MouseY > w->Height - IW(w)->sizeimage_height - 1)
1845 for (draggadget = w->FirstGadget; draggadget; draggadget = draggadget->NextGadget)
1847 if ((draggadget->GadgetType & GTYP_SYSTYPEMASK) == GTYP_WDRAGGING)
1849 gadget = draggadget;
1850 new_gadget = TRUE;
1851 break;
1857 if ((!(w->FirstRequest)) && (w->Flags & WFLG_SIZEGADGET) && MatchHotkey(ie,IA_ACTIVEWINDOWSIZE,IntuitionBase))
1859 if (w->MouseX < IW(w)->sizeimage_width || w->MouseX > w->Width - IW(w)->sizeimage_width - 1 || w->MouseY < ((IW(w)->sizeimage_height > w->BorderTop) ? IW(w)->sizeimage_height : w->BorderTop) || w->MouseY > w->Height - IW(w)->sizeimage_height - 1)
1861 for (draggadget = w->FirstGadget; draggadget; draggadget = draggadget->NextGadget)
1863 if ((draggadget->GadgetType & GTYP_SYSTYPEMASK) == GTYP_SIZING)
1865 gadget = draggadget;
1866 new_gadget = TRUE;
1867 break;
1873 #endif
1875 if (!gadget)
1877 /* use the *frontmost* screen rather than active one when searching
1878 for sdepth gadget! */
1879 gadget = FindGadget (IntuitionBase->FirstScreen,
1880 stitlebarhit ? 0 : w, stitlebarhit ? 0 : req,
1881 IntuitionBase->ActiveScreen ? IntuitionBase->ActiveScreen->MouseX : 0,
1882 IntuitionBase->ActiveScreen ? IntuitionBase->ActiveScreen->MouseY : 0,
1883 gi, FALSE, IntuitionBase);
1885 D(bug("Click on gadget %p\n", gadget));
1886 new_gadget = TRUE;
1888 } /* if (!gadget) */
1890 if (!gadget && stitlebarhit)
1892 struct Window *ww = 0;
1894 if ((ww = FindDesktopWindow(IntuitionBase->FirstScreen,IntuitionBase)))
1896 ActivateWindow(ww);
1897 w = ww;
1901 if (!stitlebarhit && !new_active_window && DoubleClick(GetPrivIBase(IntuitionBase)->LastClickSecs,GetPrivIBase(IntuitionBase)->LastClickMicro,
1902 ie->ie_TimeStamp.tv_secs,ie->ie_TimeStamp.tv_micro))
1904 if (GetPrivIBase(IntuitionBase)->DoubleClickButton != SELECTDOWN)
1906 GetPrivIBase(IntuitionBase)->DoubleClickCounter = 0;
1907 GetPrivIBase(IntuitionBase)->DoubleClickButton = SELECTDOWN;
1909 else
1911 GetPrivIBase(IntuitionBase)->DoubleClickCounter ++;
1914 else
1916 GetPrivIBase(IntuitionBase)->DoubleClickButton = SELECTDOWN;
1917 GetPrivIBase(IntuitionBase)->DoubleClickCounter = 0;
1920 /* update last click time for doubleclicktofront */
1921 GetPrivIBase(IntuitionBase)->LastClickSecs = ie->ie_TimeStamp.tv_secs;
1922 GetPrivIBase(IntuitionBase)->LastClickMicro = ie->ie_TimeStamp.tv_micro;
1924 #ifdef SKINS
1925 if (!stitlebarhit)
1927 ULONG result;
1929 if (!(gadget && ((gadget->GadgetType & GTYP_SYSTYPEMASK) == GTYP_WDEPTH)))
1930 if ((result = RunHotkeys(ie,IntuitionBase)))
1932 //gadget = NULL;
1933 if (result == RUNHOTREUSE)
1935 reuse_event = TRUE;
1937 else
1939 keep_event = FALSE;
1943 #endif
1944 if (gadget && new_gadget)
1946 if (w && (w->IDCMPFlags & IDCMP_SIZEVERIFY) &&
1947 ((gadget->GadgetType & GTYP_SYSTYPEMASK) == GTYP_SIZING /*||
1948 (gadget->GadgetType & GTYP_SYSTYPEMASK) == GTYP_WZOOM*/))
1950 ih_fire_intuimessage(w,
1951 IDCMP_SIZEVERIFY,
1953 gadget,
1954 IntuitionBase);
1955 gadget = NULL;
1956 sizeverify = TRUE;
1958 else
1960 BOOL is_draggad, is_sizegad;
1962 /* Whenever the active gadget changes the gi must be updated
1963 because it is cached in iidata->GadgetInfo!!!! Don't
1964 forget to do this if somewhere else the active
1965 gadget is changed, for example in ActivateGadget!!! */
1967 PrepareGadgetInfo(gi, IntuitionBase->ActiveScreen, w, req);
1968 SetGadgetInfoGadget(gi, gadget, IntuitionBase);
1970 #ifdef __MORPHOS__
1971 is_draggad = (((gadget->GadgetType & GTYP_SYSTYPEMASK) == GTYP_WDRAGGING) || ((gadget->GadgetType & GTYP_SYSTYPEMASK) == GTYP_WDRAGGING2));
1972 #else
1973 is_draggad = ((gadget->GadgetType & GTYP_SYSTYPEMASK) == GTYP_WDRAGGING);
1974 #endif
1975 is_sizegad = ((gadget->GadgetType & GTYP_SYSTYPEMASK) == GTYP_SIZING);
1977 #if 1
1978 /* jDc: intui68k sends IDCMPs for GACT_IMMEDIATE drag&sizegads! */
1979 if (gadget->Activation & GACT_IMMEDIATE)
1981 ih_fire_intuimessage(w,
1982 IDCMP_GADGETDOWN,
1984 gadget,
1985 IntuitionBase);
1987 #endif
1989 if (is_draggad || is_sizegad)
1991 if (IS_BOOPSI_GADGET(gadget))
1993 DoGPInput(gi,
1994 gadget,
1996 GM_GOACTIVE,
1997 &reuse_event,
1998 IntuitionBase);
2000 /* Ignoring retval of dispatcher above is what
2001 AmigaOS does too for boopsi drag/resize
2002 gadgets */
2006 /* From now on the master drag/size gadget takes over */
2007 if ((w->MoreFlags & WMFLG_IAMMUI) && (w->Flags & WFLG_BORDERLESS))
2009 iihdata->ActiveSysGadget = is_draggad ? gadget : 0;
2011 else
2013 iihdata->ActiveSysGadget = gadget;
2015 gadget = is_draggad ? iihdata->MasterDragGadget : iihdata->MasterSizeGadget;
2020 if (gadget)
2023 switch (gadget->GadgetType & GTYP_GTYPEMASK)
2025 case GTYP_BOOLGADGET:
2026 /* Only set the GFLG_SELECTED flag for RELVERIFY and
2027 * TOGGLESELECT gadget. It's for the user to do it if
2028 * he wants for other GADGIMMEDIATE ones.
2029 * Only RELVERIFY gadgets stay active.
2032 if (gadget->Activation & (GACT_TOGGLESELECT | GACT_RELVERIFY))
2034 gadget->Flags ^= GFLG_SELECTED;
2035 RefreshBoolGadgetState(gadget, w, req, IntuitionBase);
2038 if (gadget->Activation & GACT_RELVERIFY)
2040 gadget->Activation |= GACT_ACTIVEGADGET;
2041 iihdata->MouseWasInsideBoolGadget = TRUE;
2043 else
2045 gadget = NULL;
2047 break;
2049 case GTYP_PROPGADGET:
2050 HandlePropSelectDown(gadget,
2052 req,
2053 w->MouseX - gi->gi_Domain.Left - GetGadgetLeft(gadget, gi->gi_Screen, gi->gi_Window, NULL),
2054 w->MouseY - gi->gi_Domain.Top - GetGadgetTop(gadget, gi->gi_Screen, gi->gi_Window, NULL),
2055 IntuitionBase);
2058 break;
2060 case GTYP_STRGADGET:
2061 /* If the click was inside the active strgad,
2062 ** then let it update cursor pos,
2063 ** else deactivate stringadget and reuse event.
2066 if (InsideGadget(gi->gi_Screen, gi->gi_Window,
2067 gi->gi_Requester, gadget,
2068 gi->gi_Screen->MouseX, gi->gi_Screen->MouseY))
2070 UWORD imsgcode;
2072 HandleStrInput(gadget, gi, ie, &imsgcode,
2073 IntuitionBase);
2075 else
2077 gadget->Flags &= ~GFLG_SELECTED;
2079 RefreshStrGadget(gadget, w, req, IntuitionBase);
2080 /* Gadget not active anymore */
2081 gadget = NULL;
2082 reuse_event = TRUE;
2084 break;
2086 case GTYP_CUSTOMGADGET:
2087 gadget = DoGPInput(gi,
2088 gadget,
2090 (new_gadget ? GM_GOACTIVE : GM_HANDLEINPUT),
2091 &reuse_event,
2092 IntuitionBase);
2093 D(bug("new_gadget %d, goactive %p\n", new_gadget, gadget));
2095 if (gadget && new_gadget && (!(gadget->GadgetType & GTYP_SIZING)))
2097 /* For compatibility, send a GM_HANDLEINPUT too */
2098 struct InputEvent newie;
2099 BOOL reuse_event;
2101 newie.ie_NextEvent = NULL;
2102 newie.ie_Class = IECLASS_RAWMOUSE;
2103 newie.ie_SubClass = 0;
2104 newie.ie_Code = IECODE_NOBUTTON;
2105 newie.ie_Qualifier = ie->ie_Qualifier;
2106 newie.ie_X = 0;
2107 newie.ie_Y = 0;
2108 newie.ie_TimeStamp.tv_secs = IntuitionBase->Seconds;
2109 newie.ie_TimeStamp.tv_micro = IntuitionBase->Micros;
2111 gadget = DoGPInput(gi,
2112 gadget,
2113 &newie,
2114 GM_HANDLEINPUT,
2115 &reuse_event,
2116 IntuitionBase);
2117 D(bug("handleinput %p\n", gadget));
2119 break;
2121 case 0: //orig gadtools / some 1.3 gadgets
2122 if (IS_SYS_GADGET(gadget))
2124 HandleSysGadgetVerify(gi, gadget, IntuitionBase);
2126 else
2128 if (gadget->Activation & GACT_RELVERIFY)
2130 gadget->Activation |= GACT_ACTIVEGADGET;
2131 iihdata->MouseWasInsideBoolGadget = TRUE;
2132 if (gadget->Flags & GFLG_GADGHIMAGE)
2134 gadget->Flags ^= GFLG_SELECTED;
2135 RefreshBoolGadgetState(gadget, w, req, IntuitionBase);
2138 else
2140 /* jDc: this is what original intuition does, before crashing after a while ;)*/
2141 ih_fire_intuimessage(w,
2142 IDCMP_MOUSEBUTTONS,
2143 SELECTDOWN,
2145 IntuitionBase);
2148 break;
2149 } /* switch (GadgetType) */
2151 } /* if (a gadget is active) */
2152 else if (w && (!req || req->Flags & NOISYREQ) && !sizeverify && !stitlebarhit)
2154 ih_fire_intuimessage(w,
2155 IDCMP_MOUSEBUTTONS,
2156 SELECTDOWN,
2158 IntuitionBase);
2162 } /* case SELECTDOWN */
2163 break;
2165 case SELECTUP:
2166 iihdata->ActQualifier &= ~IEQUALIFIER_LEFTBUTTON;
2168 #ifdef SKINS
2169 iihdata->TitlebarAppearTime = 0;
2170 #endif
2171 if (MENUS_ACTIVE)
2173 FireMenuMessage(MMCODE_EVENT, 0, ie, IntuitionBase);
2174 keep_event = FALSE;
2175 break;
2178 if (gadget)
2180 BOOL inside = InsideGadget(gi->gi_Screen, gi->gi_Window,
2181 gi->gi_Requester, gadget,
2182 gi->gi_Screen->MouseX, gi->gi_Screen->MouseY);
2184 /*int selected = (gadget->Flags & GFLG_SELECTED) != 0;*/
2186 switch (gadget->GadgetType & GTYP_GTYPEMASK)
2188 case GTYP_BOOLGADGET:
2189 /* Must be a RELVERIFY gadget */
2191 if (!(gadget->Activation & GACT_TOGGLESELECT) && inside)
2193 gadget->Flags ^= GFLG_SELECTED;
2194 RefreshBoolGadgetState(gadget, w, req, IntuitionBase);
2197 if (inside)
2199 if (IS_SYS_GADGET(gadget))
2201 HandleSysGadgetVerify(gi, gadget, IntuitionBase);
2203 else
2205 if (req && gadget->Activation & GACT_ENDGADGET)
2207 EndRequest(req, w);
2209 req = w->FirstRequest;
2212 ih_fire_intuimessage(w,
2213 IDCMP_GADGETUP,
2215 gadget,
2216 IntuitionBase);
2219 else
2221 /* RKRM say so */
2222 ih_fire_intuimessage(w,
2223 IDCMP_MOUSEBUTTONS,
2224 SELECTUP,
2226 IntuitionBase);
2229 gadget->Activation &= ~GACT_ACTIVEGADGET;
2230 gadget = NULL;
2231 break;
2233 case GTYP_PROPGADGET:
2234 HandlePropSelectUp(gadget, w, req, IntuitionBase);
2235 if (gadget->Activation & GACT_RELVERIFY)
2237 ih_fire_intuimessage(w,
2238 IDCMP_GADGETUP,
2240 gadget,
2241 IntuitionBase);
2244 gadget = NULL;
2245 break;
2247 /* Intuition string gadgets don't care about SELECTUP */
2249 case GTYP_CUSTOMGADGET:
2250 gadget = DoGPInput(gi, gadget, ie, GM_HANDLEINPUT, &reuse_event, IntuitionBase);
2251 break;
2253 case 0: //orig gadtools / some 1.3 gadgets
2254 /* jDc: adding a gadget with gtyp field set to NULL crashes intui68k
2255 ** seems we don't need compatibility on this field ;) anyway we should
2256 ** handle the case of GTYP_CLOSE, etc, set by some "cod3r"
2258 gadget->Activation &= ~GACT_ACTIVEGADGET;
2259 if (gadget->Activation & GACT_RELVERIFY)
2261 if (gadget->Flags & GFLG_GADGHIMAGE)
2263 if (inside)
2265 gadget->Flags ^= GFLG_SELECTED;
2266 RefreshBoolGadgetState(gadget, w, req, IntuitionBase);
2270 if (inside)
2272 ih_fire_intuimessage(w,
2273 IDCMP_GADGETUP,
2275 gadget,
2276 IntuitionBase);
2278 } else {
2279 ih_fire_intuimessage(w,
2280 IDCMP_MOUSEBUTTONS,
2281 SELECTUP,
2283 IntuitionBase);
2285 gadget = NULL;
2286 break;
2288 } /* switch GadgetType */
2290 } /* if (a gadget is currently active) */
2291 else if (w && (!req || req->Flags & NOISYREQ))
2293 ih_fire_intuimessage(w,
2294 IDCMP_MOUSEBUTTONS,
2295 SELECTUP,
2297 IntuitionBase);
2300 break; /* case SELECTUP */
2302 case MENUDOWN:
2303 iihdata->ActQualifier |= IEQUALIFIER_RBUTTON;
2305 #ifdef SKINS
2306 iihdata->TitlebarAppearTime = 0;
2307 #endif
2308 if (MENUS_ACTIVE)
2310 FireMenuMessage(MMCODE_EVENT, 0, ie, IntuitionBase);
2311 keep_event = FALSE;
2312 break;
2315 if (DoubleClick(GetPrivIBase(IntuitionBase)->LastClickSecs,GetPrivIBase(IntuitionBase)->LastClickMicro,
2316 ie->ie_TimeStamp.tv_secs,ie->ie_TimeStamp.tv_micro))
2318 if (GetPrivIBase(IntuitionBase)->DoubleClickButton != MENUDOWN)
2320 GetPrivIBase(IntuitionBase)->DoubleClickCounter = 0;
2321 GetPrivIBase(IntuitionBase)->DoubleClickButton = MENUDOWN;
2323 else
2325 GetPrivIBase(IntuitionBase)->DoubleClickCounter ++;
2328 else
2330 GetPrivIBase(IntuitionBase)->DoubleClickButton = MENUDOWN;
2331 GetPrivIBase(IntuitionBase)->DoubleClickCounter = 0;
2334 /* update last click time for doubleclicktofront */
2335 GetPrivIBase(IntuitionBase)->LastClickSecs = ie->ie_TimeStamp.tv_secs;
2336 GetPrivIBase(IntuitionBase)->LastClickMicro = ie->ie_TimeStamp.tv_micro;
2338 #ifdef SKINS
2340 ULONG result;
2342 if ((result = RunHotkeys(ie,IntuitionBase)))
2344 if (result == RUNHOTREUSE)
2346 reuse_event = TRUE;
2348 else
2350 keep_event = FALSE;
2352 break;
2354 w = IntuitionBase->ActiveWindow;
2356 #endif
2358 #ifdef SKINS
2359 if ((!MENUS_ACTIVE) && (!gadget) && (!(iihdata->ActQualifier & (IEQUALIFIER_LEFTBUTTON|IEQUALIFIER_MIDBUTTON))))
2361 struct Gadget *gad;
2362 struct GadgetInfo ginf;
2363 ULONG hit;
2364 struct Window *wind = FindActiveWindow(0,&hit,IntuitionBase);
2366 if (wind)
2368 gad = FindGadget (IntuitionBase->FirstScreen,
2369 hit ? 0 : wind,0,
2370 IntuitionBase->ActiveScreen->MouseX,
2371 IntuitionBase->ActiveScreen->MouseY,
2372 &ginf, TRUE, IntuitionBase);
2374 if (gad && ((gad->GadgetType & GTYP_SYSTYPEMASK) == GTYP_WDEPTH))
2376 CreateSmallMenuTask(wind,SMALLMENU_TYPE_WINDOWDEPTH,IntuitionBase);
2377 keep_event = FALSE;
2378 break;
2381 if (gad && ((gad->GadgetType & GTYP_SYSTYPEMASK) == GTYP_SDEPTH))
2383 CreateSmallMenuTask(0,SMALLMENU_TYPE_SCREENDEPTH,IntuitionBase);
2384 keep_event = FALSE;
2385 break;
2389 #endif
2391 if (w && !req && w->DMRequest && !(w->Flags & WFLG_RMBTRAP))
2393 if (!MENUS_ACTIVE &&
2394 DoubleClick(GetPrivIBase(IntuitionBase)->DMStartSecs,
2395 GetPrivIBase(IntuitionBase)->DMStartMicro,
2396 ie->ie_TimeStamp.tv_secs,
2397 ie->ie_TimeStamp.tv_micro))
2399 if (w->IDCMPFlags & IDCMP_REQVERIFY)
2401 ih_fire_intuimessage(w,
2402 IDCMP_REQVERIFY,
2403 MENUHOT,
2404 NULL,
2405 IntuitionBase);
2407 else if (Request(w->DMRequest, w))
2409 req = w->DMRequest;
2411 ih_fire_intuimessage(w,
2412 IDCMP_REQSET,
2415 IntuitionBase);
2417 keep_event = FALSE;
2418 break;
2421 GetPrivIBase(IntuitionBase)->DMStartSecs = ie->ie_TimeStamp.tv_secs;
2422 GetPrivIBase(IntuitionBase)->DMStartMicro = ie->ie_TimeStamp.tv_micro;
2425 if (w && !gadget)
2427 if (!(w->Flags & WFLG_RMBTRAP) && !req)
2429 struct IntScreen *scr = GetPrivScreen(w->WScreen);
2430 struct Window *w1;
2431 ULONG lock;
2432 BOOL mouseon = TRUE;
2434 scr->MenuVerifyMsgCount = 0;
2436 if (w->MouseX < 0 || w->MouseY < 0) mouseon = FALSE;
2437 if (w->MouseX > w->Width || w->MouseY > w->Height) mouseon = FALSE;
2439 if (w->IDCMPFlags & IDCMP_MENUVERIFY && (!(IW(w)->specialflags & SPFLAG_IAMDEAD)))
2441 ih_fire_intuimessage(w,
2442 IDCMP_MENUVERIFY,
2443 mouseon ? MENUHOT : MENUWAITING,
2445 IntuitionBase);
2446 scr->MenuVerifyMsgCount++;
2449 lock = LockIBase(0);
2451 for (w1 = scr->Screen.FirstWindow; w1; w1 = w1->NextWindow)
2453 if ((w1->IDCMPFlags & IDCMP_MENUVERIFY) && (w1 != w) && (!(IW(w)->specialflags & SPFLAG_IAMDEAD)))
2455 ih_fire_intuimessage(w1,
2456 IDCMP_MENUVERIFY,
2457 MENUWAITING,
2459 IntuitionBase);
2460 ++scr->MenuVerifyMsgCount;
2464 UnlockIBase(lock);
2466 /* FIXME: when a window is opened with IDCMP_MENUVERIFY
2467 * (or this event is requested via ModifyIDCMP), and a
2468 * verify operation is pending, the window should get
2469 * a verify message too. Oh well.
2472 if (scr->MenuVerifyMsgCount)
2474 GetPrivIBase(IntuitionBase)->MenuVerifyScreen = scr;
2475 scr->MenuVerifyActiveWindow = w;
2476 scr->MenuVerifyTimeOut = 2;
2477 scr->MenuVerifySeconds = IntuitionBase->Seconds;
2478 scr->MenuVerifyMicros = IntuitionBase->Micros;
2480 else if (FireMenuMessage(MMCODE_START, w, NULL/*ie*/, IntuitionBase))
2482 /* This lock will be released only when the user is
2483 done with menus = when IECLASS_MENU + IESUBCLASS_MENUSTOP
2484 event arrives (generated by MenuHandler task) */
2486 ObtainSemaphore(&GetPrivIBase(IntuitionBase)->MenuLock);
2487 iihdata->MenuWindow = w;
2488 MENUS_ACTIVE = TRUE;
2492 /* fall through */
2494 case MENUUP:
2495 case MIDDLEDOWN:
2496 case MIDDLEUP:
2498 switch(ie->ie_Code)
2500 case MENUUP:
2501 iihdata->ActQualifier &= ~IEQUALIFIER_RBUTTON;
2502 if (GetPrivIBase(IntuitionBase)->MenuVerifyScreen)
2504 struct Window *w1;
2505 struct IntScreen *scr = GetPrivIBase(IntuitionBase)->MenuVerifyScreen;
2506 ULONG lock = LockIBase(0);
2508 for (w1 = scr->Screen.FirstWindow; w1; w1 = w1->NextWindow)
2510 if (w1->IDCMPFlags & IDCMP_MENUVERIFY && w1->IDCMPFlags & IDCMP_MOUSEBUTTONS)
2512 ih_fire_intuimessage(w1,
2513 IDCMP_MOUSEBUTTONS,
2514 MENUUP,
2516 IntuitionBase);
2520 UnlockIBase(lock);
2522 /* FIXME: when the active window replies the verifymessage,
2523 * it should get a IDCMP_MENUPICK/MENUNULL message.
2525 GetPrivIBase(IntuitionBase)->MenuVerifyScreen = NULL;
2526 scr->MenuVerifyActiveWindow = NULL;
2527 scr->MenuVerifyMsgCount = 0;
2528 scr->MenuVerifyTimeOut = 0;
2529 scr->MenuVerifySeconds = 0;
2530 scr->MenuVerifyMicros = 0;
2532 break;
2534 case MIDDLEDOWN:
2535 iihdata->ActQualifier |= IEQUALIFIER_MIDBUTTON;
2536 if (DoubleClick(GetPrivIBase(IntuitionBase)->LastClickSecs,GetPrivIBase(IntuitionBase)->LastClickMicro,
2537 ie->ie_TimeStamp.tv_secs,ie->ie_TimeStamp.tv_micro))
2539 if (GetPrivIBase(IntuitionBase)->DoubleClickButton != MIDDLEDOWN)
2541 GetPrivIBase(IntuitionBase)->DoubleClickCounter = 0;
2542 GetPrivIBase(IntuitionBase)->DoubleClickButton = MIDDLEDOWN;
2544 else
2546 GetPrivIBase(IntuitionBase)->DoubleClickCounter ++;
2549 else
2551 GetPrivIBase(IntuitionBase)->DoubleClickButton = MIDDLEDOWN;
2552 GetPrivIBase(IntuitionBase)->DoubleClickCounter = 0;
2554 /* update last click time for doubleclicktofront */
2555 GetPrivIBase(IntuitionBase)->LastClickSecs = ie->ie_TimeStamp.tv_secs;
2556 GetPrivIBase(IntuitionBase)->LastClickMicro = ie->ie_TimeStamp.tv_micro;
2557 break;
2559 case MIDDLEUP:
2560 iihdata->ActQualifier &= ~IEQUALIFIER_MIDBUTTON;
2561 break;
2564 #ifdef SKINS
2565 iihdata->TitlebarAppearTime = 0;
2566 #endif
2567 if (MENUS_ACTIVE)
2569 FireMenuMessage(MMCODE_EVENT, 0, ie, IntuitionBase);
2570 keep_event = FALSE;
2571 break;
2574 #ifdef SKINS
2575 if (ie->ie_Code == MIDDLEDOWN)
2577 ULONG result;
2579 if ((result = RunHotkeys(ie,IntuitionBase)))
2581 if (result == RUNHOTREUSE)
2583 reuse_event = TRUE;
2585 else
2587 keep_event = FALSE;
2589 break;
2591 w = IntuitionBase->ActiveWindow;
2593 #endif
2594 if (gadget)
2596 if (IS_BOOPSI_GADGET(gadget))
2598 gadget = DoGPInput(gi, gadget, ie, GM_HANDLEINPUT, &reuse_event, IntuitionBase);
2601 } /* if (there is an active gadget) */
2602 else if (w && (!req || req->Flags & NOISYREQ) && w != GetPrivScreen(w->WScreen)->MenuVerifyActiveWindow)
2604 ih_fire_intuimessage(w,
2605 IDCMP_MOUSEBUTTONS,
2606 ie->ie_Code,
2608 IntuitionBase);
2611 break; /* case MENUDOWN */
2613 case IECODE_NOBUTTON: /* MOUSEMOVE */
2616 if (ie->ie_Qualifier & IEQUALIFIER_RELATIVEMOUSE)
2618 struct Screen *scr;
2619 //ULONG Thresh;
2621 /* Add delta information lost in previous mousemove event. See below. */
2622 iihdata->DeltaMouseX = ie->ie_X + iihdata->DeltaMouseX_Correction;
2623 iihdata->DeltaMouseY = ie->ie_Y + iihdata->DeltaMouseY_Correction;
2625 #define ACCELERATOR_THRESH 2
2626 #define ACCELERATOR_MULTI 2
2628 if (GetPrivIBase(IntuitionBase)->ActivePreferences->EnableCLI & MOUSE_ACCEL)
2630 /* Acceleration */
2631 if (ABS(iihdata->DeltaMouseX) > ACCELERATOR_THRESH)
2633 iihdata->DeltaMouseX *= ACCELERATOR_MULTI;
2635 if (ABS(iihdata->DeltaMouseY) > ACCELERATOR_THRESH)
2637 iihdata->DeltaMouseY *= ACCELERATOR_MULTI;
2641 switch(GetPrivIBase(IntuitionBase)->ActivePreferences->PointerTicks)
2643 case 0:
2644 iihdata->DeltaMouseX_Correction = 0;
2645 iihdata->DeltaMouseX_Correction = 0;
2646 break;
2648 default:
2649 /* Remember the delta information which gets lost because of division by PointerTicks.
2650 Will be added to prescaled deltas of next mousemove event. If this is not done, moving
2651 the mouse very slowly would cause it to not move at all */
2653 iihdata->DeltaMouseX_Correction = iihdata->DeltaMouseX % GetPrivIBase(IntuitionBase)->ActivePreferences->PointerTicks;
2654 iihdata->DeltaMouseY_Correction = iihdata->DeltaMouseY % GetPrivIBase(IntuitionBase)->ActivePreferences->PointerTicks;
2656 iihdata->DeltaMouseX /= GetPrivIBase(IntuitionBase)->ActivePreferences->PointerTicks;
2657 iihdata->DeltaMouseY /= GetPrivIBase(IntuitionBase)->ActivePreferences->PointerTicks;
2658 break;
2662 ie->ie_X = iihdata->DeltaMouseX + iihdata->LastMouseX;
2663 ie->ie_Y = iihdata->DeltaMouseY + iihdata->LastMouseY;
2665 //jDc: not really necessary to lock this for reading since this ptr is only modified
2666 //by functions synced with inputhandler
2667 //lock = LockIBase(0);
2668 scr = IntuitionBase->FirstScreen;
2670 if (scr)
2672 if (IntuitionBase->FirstScreen->Flags & AUTOSCROLL)
2675 #define VWIDTH IntuitionBase->ViewLord.ViewPort->DWidth
2676 #define VHEIGHT IntuitionBase->ViewLord.ViewPort->DHeight
2677 #define VDX IntuitionBase->ViewLord.ViewPort->DxOffset
2678 #define VDY IntuitionBase->ViewLord.ViewPort->DyOffset
2680 if ((ie->ie_X > VWIDTH - scr->LeftEdge - 1) || (ie->ie_X < - scr->LeftEdge) ||
2681 (ie->ie_Y > VHEIGHT - scr->TopEdge - 1) || (ie->ie_Y < - scr->TopEdge))
2683 if (ie->ie_X > VWIDTH - scr->LeftEdge - 1)
2685 scr->LeftEdge = VWIDTH - ie->ie_X;
2686 if (VWIDTH - scr->LeftEdge > scr->Width) scr->LeftEdge = VWIDTH - scr->Width;
2687 VDX = scr->LeftEdge;
2690 if (ie->ie_X < -scr->LeftEdge)
2692 scr->LeftEdge = -ie->ie_X;
2693 if (scr->LeftEdge < VWIDTH - scr->Width) scr->LeftEdge = VWIDTH - scr->Width;
2694 if(scr->LeftEdge > 0) scr->LeftEdge = 0; // we don't support > 0 LeftEdges
2695 VDX = scr->LeftEdge;
2698 if (ie->ie_Y > VHEIGHT - scr->TopEdge - 1)
2700 scr->TopEdge = VHEIGHT - ie->ie_Y;
2701 if (VHEIGHT - scr->TopEdge > scr->Height) scr->TopEdge = VHEIGHT - scr->Height;
2702 VDY = scr->TopEdge;
2705 if (ie->ie_Y < -scr->TopEdge)
2707 scr->TopEdge = - ie->ie_Y;
2708 if (scr->TopEdge < VHEIGHT - scr->Height) scr->TopEdge = VHEIGHT - scr->Height;
2709 if(scr->TopEdge > 0) scr->TopEdge = 0;
2710 VDY = scr->TopEdge;
2713 ScrollVPort(IntuitionBase->ViewLord.ViewPort);
2717 if (ie->ie_X >= scr->Width + max(scr->LeftEdge,0)) ie->ie_X = scr->Width + max(scr->LeftEdge,0) - 1;
2718 if (ie->ie_Y >= scr->Height + max(scr->TopEdge,0)) ie->ie_Y = scr->Height + max(scr->TopEdge,0) - 1;
2719 if (ie->ie_X < - scr->LeftEdge) ie->ie_X = - scr->LeftEdge;
2720 if (ie->ie_Y < - scr->TopEdge) ie->ie_Y = - scr->TopEdge;
2723 else
2725 if (ie->ie_X >= 320) ie->ie_X = 320 - 1;
2726 if (ie->ie_Y >= 200) ie->ie_Y = 200 - 1;
2727 if (ie->ie_X < 0) ie->ie_X = 0;
2728 if (ie->ie_Y < 0) ie->ie_Y = 0;
2730 //UnlockIBase(lock);
2732 else
2734 iihdata->DeltaMouseX = ie->ie_X - iihdata->LastMouseX;
2735 iihdata->DeltaMouseY = ie->ie_Y - iihdata->LastMouseY;
2738 #ifdef SKINS
2739 if (gadget == iihdata->MasterDragGadget)
2741 struct gpInput gpi;
2742 ULONG retval;
2744 gpi.MethodID = GM_MOVETEST;
2745 gpi.gpi_GInfo = gi;
2746 gpi.gpi_Mouse.X = ie->ie_X - gi->gi_Window->WScreen->LeftEdge;
2747 gpi.gpi_Mouse.Y = ie->ie_Y - gi->gi_Window->WScreen->TopEdge;
2748 gpi.gpi_IEvent = ie;
2750 retval = Locked_DoMethodA(gi->gi_Window, gadget, (Msg)&gpi, IntuitionBase);
2751 if (retval == MOVETEST_ADJUSTPOS)
2753 ie->ie_X = gpi.gpi_Mouse.X + gi->gi_Window->WScreen->LeftEdge;
2754 ie->ie_Y = gpi.gpi_Mouse.Y + gi->gi_Window->WScreen->TopEdge;
2758 #endif
2759 /* Do Mouse Bounding - mouse will be most restrictive of screen size or mouse bounds */
2760 if (iihdata->MouseBoundsActiveFlag)
2762 if (ie->ie_X < iihdata->MouseBoundsLeft)
2764 ie->ie_X = iihdata->MouseBoundsLeft;
2766 else if (ie->ie_X > iihdata->MouseBoundsRight)
2768 ie->ie_X = iihdata->MouseBoundsRight;
2771 if (ie->ie_Y < iihdata->MouseBoundsTop)
2773 ie->ie_Y = iihdata->MouseBoundsTop;
2775 else if (ie->ie_Y > iihdata->MouseBoundsBottom)
2777 ie->ie_Y = iihdata->MouseBoundsBottom;
2781 #if !SINGLE_SETPOINTERPOS_PER_EVENTLOOP
2782 SetPointerPos(ie->ie_X, ie->ie_Y);
2783 #else
2784 pointerposx = ie->ie_X;
2785 pointerposy = ie->ie_Y;
2786 call_setpointerpos = TRUE;
2787 #endif
2789 iihdata->LastMouseX = ie->ie_X;
2790 iihdata->LastMouseY = ie->ie_Y;
2792 notify_mousemove_screensandwindows(ie->ie_X,
2793 ie->ie_Y,
2794 IntuitionBase);
2796 #ifdef SKINS
2797 if (!gadget)
2799 if (iihdata->TitlebarOnTop)
2801 if (IntuitionBase->FirstScreen->MouseY > IntuitionBase->FirstScreen->BarHeight && GetPrivScreen(IntuitionBase->FirstScreen)->SpecialFlags & SF_AppearingBar)
2803 iihdata->TitlebarOnTop = FALSE;
2804 iihdata->TitlebarAppearTime = 0;
2806 LOCK_REFRESH(IntuitionBase->FirstScreen);
2808 MoveLayer(0,IntuitionBase->FirstScreen->BarLayer,0,-(IntuitionBase->FirstScreen->BarHeight + 1));
2809 CheckLayers(IntuitionBase->FirstScreen, IntuitionBase);
2811 UNLOCK_REFRESH(IntuitionBase->FirstScreen);
2814 else
2816 if (IntuitionBase->FirstScreen->MouseY == 0 && GetPrivScreen(IntuitionBase->FirstScreen)->SpecialFlags & SF_AppearingBar && !MENUS_ACTIVE && !(PeekQualifier() & (IEQUALIFIER_LEFTBUTTON|IEQUALIFIER_RBUTTON|IEQUALIFIER_MIDBUTTON)))
2818 if (!(iihdata->TitlebarAppearTime))
2820 iihdata->TitlebarAppearTime = ((UQUAD)ie->ie_TimeStamp.tv_secs) * 50;
2821 iihdata->TitlebarAppearTime += ie->ie_TimeStamp.tv_micro / 20000;
2824 else
2826 iihdata->TitlebarAppearTime = 0;
2830 #endif
2832 if (MENUS_ACTIVE)
2834 FireMenuMessage(MMCODE_EVENT, 0, ie, IntuitionBase);
2835 keep_event = FALSE;
2836 break;
2839 if (gadget)
2841 keep_event = FALSE;
2843 switch (gadget->GadgetType & GTYP_GTYPEMASK)
2845 case GTYP_BOOLGADGET:
2846 case 0: //fallback for sucky gadgets
2847 /* Must be a RELVERIFY gadget */
2849 BOOL inside;
2851 inside = InsideGadget(gi->gi_Screen,
2852 gi->gi_Window,
2853 gi->gi_Requester,
2854 gadget,
2855 gi->gi_Screen->MouseX,
2856 gi->gi_Screen->MouseY);
2858 if (inside != iihdata->MouseWasInsideBoolGadget)
2860 iihdata->MouseWasInsideBoolGadget = inside;
2862 gadget->Flags ^= GFLG_SELECTED;
2863 RefreshBoolGadgetState(gadget, w, req, IntuitionBase);
2866 break;
2868 case GTYP_PROPGADGET:
2869 HandlePropMouseMove(gadget,
2871 req,
2872 w->MouseX - gi->gi_Domain.Left - GetGadgetLeft(gadget, gi->gi_Screen, gi->gi_Window, NULL),
2873 w->MouseY - gi->gi_Domain.Top - GetGadgetTop(gadget, gi->gi_Screen, gi->gi_Window, NULL),
2874 IntuitionBase);
2876 break;
2878 case GTYP_CUSTOMGADGET:
2879 gadget = DoGPInput(gi, gadget, ie, GM_HANDLEINPUT, &reuse_event, IntuitionBase);
2880 break;
2882 } /* switch GadgetType */
2884 } /* if (a gadget is currently active) */
2886 keep_event = FALSE;
2888 if (!w) break;
2890 if (IW(w)->helpflags & HELPF_GADGETHELP && (!(PeekQualifier() & (IEQUALIFIER_LEFTBUTTON|IEQUALIFIER_RBUTTON|IEQUALIFIER_MIDBUTTON))))
2892 struct Window *hw;
2893 struct Gadget *g;
2895 hw = FindActiveWindow(ie, 0, IntuitionBase);
2897 if (hw != w &&
2898 (!hw || !(IW(w)->helpflags & HELPF_ISHELPGROUP) ||
2899 !(IW(hw)->helpflags & HELPF_ISHELPGROUP) ||
2900 IW(w)->helpgroup != IW(hw)->helpgroup))
2903 if (iihdata->LastHelpWindow)
2905 fire_intuimessage(w,
2906 IDCMP_GADGETHELP,
2908 NULL,
2909 IntuitionBase);
2911 iihdata->LastHelpGadget = NULL;
2912 iihdata->LastHelpWindow = NULL;
2913 iihdata->HelpGadgetFindTime = 0;
2916 else
2918 g = FindHelpGadget (hw,
2919 IntuitionBase->ActiveScreen->MouseX,
2920 IntuitionBase->ActiveScreen->MouseY,
2921 IntuitionBase);
2922 if (g && g != iihdata->LastHelpGadget)
2924 if (!iihdata->LastHelpGadget)
2926 iihdata->HelpGadgetFindTime = ((UQUAD)ie->ie_TimeStamp.tv_secs) * 50;
2927 iihdata->HelpGadgetFindTime += ie->ie_TimeStamp.tv_micro / 20000;
2929 else
2931 if (hw == iihdata->LastHelpWindow)
2933 iihdata->HelpGadgetFindTime = ((UQUAD)ie->ie_TimeStamp.tv_secs) * 50;
2934 iihdata->HelpGadgetFindTime += ie->ie_TimeStamp.tv_micro / 20000;
2935 iihdata->HelpGadgetFindTime += 25;//smaller delay
2939 else if (g != iihdata->LastHelpGadget ||
2940 hw != iihdata->LastHelpWindow)
2942 fire_intuimessage(hw,
2943 IDCMP_GADGETHELP,
2944 0, /* Don't know what it should be */
2946 IntuitionBase);
2949 iihdata->LastHelpGadget = g;
2950 iihdata->LastHelpWindow = hw;
2953 else
2955 iihdata->LastHelpGadget = NULL;
2956 iihdata->LastHelpWindow = NULL;
2957 iihdata->HelpGadgetFindTime = 0;
2960 if (!(w->IDCMPFlags & IDCMP_MOUSEMOVE)) break;
2962 /* Send IDCMP_MOUSEMOVE if WFLG_REPORTMOUSE is set
2963 and/or active gadget has GACT_FOLLOWMOUSE set */
2965 /* jDc: do NOT send when sizegad is pressed */
2967 if (!(w->Flags & WFLG_REPORTMOUSE))
2969 if (!gadget) break;
2970 if (!(gadget->Activation & GACT_FOLLOWMOUSE)) break;
2972 else
2974 if (gadget && (gadget->GadgetType & (GTYP_SIZING|GTYP_WDRAGGING))) break;
2977 orig_ie->ie_Class = IECLASS_RAWMOUSE;
2979 /* Limit the number of IDCMP_MOUSEMOVE messages sent to intuition.
2980 note that this comes after handling gadgets, because gadgets should get all events.
2983 if (IW(w)->num_mouseevents >= IW(w)->mousequeue)
2985 BOOL old_msg_found = FALSE;
2987 /* Mouse Queue is full, so try looking for a not
2988 yet GetMsg()ed IntuiMessage in w->UserPort
2989 trying to modify that. */
2991 Forbid();
2992 if (w->UserPort)
2994 struct IntuiMessage *im;
2996 for (im = (struct IntuiMessage *)w->UserPort->mp_MsgList.lh_TailPred;
2997 im->ExecMessage.mn_Node.ln_Pred;
2998 im = (struct IntuiMessage *)im->ExecMessage.mn_Node.ln_Pred)
3000 if ((im->Class == IDCMP_MOUSEMOVE) &&
3001 (im->IDCMPWindow == w))
3003 im->Qualifier = iihdata->ActQualifier;
3005 if (w->IDCMPFlags & IDCMP_DELTAMOVE)
3007 im->MouseX = iihdata->DeltaMouseX;
3008 im->MouseY = iihdata->DeltaMouseY;
3010 else
3012 im->MouseX = w->MouseX;
3013 im->MouseY = w->MouseY;
3015 CurrentTime(&im->Seconds, &im->Micros);
3017 old_msg_found = TRUE;
3018 break;
3021 } /* if (w->UserPort) */
3022 Permit();
3024 /* no need to send a new message if we modified
3025 an existing one ... */
3027 if (old_msg_found) break;
3029 /* ... otherwise we are in a strange situation. The mouse
3030 queue is full, but we did not find an existing MOUSEMOVE
3031 imsg in w->UserPort. So the app probably has removed
3032 an imsg from the UserPort with GetMsg but we did not get
3033 the ReplyMsg, yet. In this case we do send a new message */
3035 HandleIntuiReplyPort(iihdata, IntuitionBase);
3039 /* MouseQueue is not full, so we can send a message. We increase
3040 IntWindow->num_mouseevents which will later be decreased after
3041 the Intuition InputHandler gets the ReplyMessage from the app
3042 and handles it in HandleIntuiReplyPort() */
3044 if (ih_fire_intuimessage(w,
3045 IDCMP_MOUSEMOVE,
3046 IECODE_NOBUTTON,
3048 IntuitionBase))
3050 IW(w)->num_mouseevents++;
3053 break;
3055 } /* case IECODE_NOBUTTON */
3057 } /* switch (ie->ie_Code) (what button was pressed ?) */
3058 break;
3060 #define KEY_QUALIFIERS (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT | \
3061 IEQUALIFIER_CAPSLOCK | IEQUALIFIER_CONTROL | \
3062 IEQUALIFIER_LALT | IEQUALIFIER_RALT | \
3063 IEQUALIFIER_LCOMMAND | IEQUALIFIER_RCOMMAND | \
3064 IEQUALIFIER_NUMERICPAD | IEQUALIFIER_REPEAT)
3066 case IECLASS_RAWKEY:
3067 /* release events go only to gadgets and windows who
3068 have not set IDCMP_VANILLAKEY */
3070 DEBUG_HANDLER(dprintf("Handler: IECLASS_RAWKEY\n"));
3071 DEBUG_KEY(dprintf("Handler: Qual 0x%lx\n",iihdata->ActQualifier));
3073 iihdata->ActQualifier &= ~KEY_QUALIFIERS;
3074 iihdata->ActQualifier |= (ie->ie_Qualifier & KEY_QUALIFIERS);
3076 DEBUG_KEY(dprintf("Handler: real Qual 0x%lx\n",iihdata->ActQualifier));
3078 /* Keyboard mouse emulation */
3081 UWORD code = ie->ie_Code & ~IECODE_UP_PREFIX;
3083 /* Mouse button emulation: LALT + LAMIGA = LBUTTON, RALT + RAMIGA = RBUTTON */
3085 DEBUG_KEY(dprintf("Handler: code 0x%lx\n",code));
3086 if ((code == RAWKEY_LAMIGA) ||
3087 (code == RAWKEY_LALT) ||
3088 (code == RAWKEY_RAMIGA) ||
3089 (code == RAWKEY_RALT))
3091 DEBUG_KEY(dprintf("Handler: KeyMouseEmul\n"));
3092 iihdata->PrevKeyMouseState = iihdata->ActKeyMouseState;
3093 iihdata->ActKeyMouseState = 0;
3094 if ((ie->ie_Qualifier & (IEQUALIFIER_LCOMMAND | IEQUALIFIER_LALT)) == (IEQUALIFIER_LCOMMAND | IEQUALIFIER_LALT))
3096 iihdata->ActKeyMouseState |= IEQUALIFIER_LEFTBUTTON;
3098 if ((ie->ie_Qualifier & (IEQUALIFIER_RCOMMAND | IEQUALIFIER_RALT)) == (IEQUALIFIER_RCOMMAND | IEQUALIFIER_RALT))
3100 iihdata->ActKeyMouseState |= IEQUALIFIER_RBUTTON;
3103 if ((iihdata->ActKeyMouseState & IEQUALIFIER_LEFTBUTTON) != (iihdata->PrevKeyMouseState & IEQUALIFIER_LEFTBUTTON))
3105 orig_ie->ie_Class = IECLASS_RAWMOUSE;
3106 orig_ie->ie_SubClass = 0;
3107 orig_ie->ie_Code = (iihdata->ActKeyMouseState & IEQUALIFIER_LEFTBUTTON) ? IECODE_LBUTTON : IECODE_LBUTTON | IECODE_UP_PREFIX;
3108 orig_ie->ie_X = 0;
3109 orig_ie->ie_Y = 0;
3110 *ie = *orig_ie;
3112 reuse_event = TRUE;
3113 break;
3116 if ((iihdata->ActKeyMouseState & IEQUALIFIER_RBUTTON) != (iihdata->PrevKeyMouseState & IEQUALIFIER_RBUTTON))
3118 orig_ie->ie_Class = IECLASS_RAWMOUSE;
3119 orig_ie->ie_SubClass = 0;
3120 orig_ie->ie_Code = (iihdata->ActKeyMouseState & IEQUALIFIER_RBUTTON) ? IECODE_RBUTTON : IECODE_RBUTTON | IECODE_UP_PREFIX;
3121 orig_ie->ie_X = 0;
3122 orig_ie->ie_Y = 0;
3123 *ie = *orig_ie;
3125 reuse_event = TRUE;
3126 break;
3129 } /* if key is one of LAMIGA/LALT/RAMIGA/RALT */
3131 if ((iihdata->ActQualifier & (IEQUALIFIER_LCOMMAND | IEQUALIFIER_RCOMMAND)) &&
3132 MouseCoordsRelative() &&
3133 ((ie->ie_Code == RAWKEY_UP) ||
3134 (ie->ie_Code == RAWKEY_DOWN) ||
3135 (ie->ie_Code == RAWKEY_LEFT) ||
3136 (ie->ie_Code == RAWKEY_RIGHT)))
3138 static BYTE xmap[] = { 0, 0, 1, -1};
3139 static BYTE ymap[] = {-1, 1, 0, 0};
3140 WORD shift;
3142 shift = (iihdata->ActQualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) ? 40 : 1;
3144 /* Mouse Move Emulation */
3146 orig_ie->ie_Class = IECLASS_RAWMOUSE;
3147 orig_ie->ie_SubClass = 0;
3148 orig_ie->ie_Code = IECODE_NOBUTTON;
3149 orig_ie->ie_Qualifier = IEQUALIFIER_RELATIVEMOUSE;
3150 orig_ie->ie_X = xmap[code - RAWKEY_UP] * shift;
3151 orig_ie->ie_Y = ymap[code - RAWKEY_UP] * shift;
3153 *ie = *orig_ie;
3154 reuse_event = TRUE;
3155 break;
3158 } /**/
3160 /* End Keyboard mouse emulation */
3162 if (MENUS_ACTIVE)
3164 DEBUG_KEY(dprintf("Handler: FireMenuMessage\n"));
3165 FireMenuMessage(MMCODE_EVENT, 0, ie, IntuitionBase);
3166 keep_event = FALSE;
3167 break;
3170 /* Hotkeys processing */
3171 #ifdef SKINS
3173 ULONG result;
3175 if (!(ie->ie_Code & IECODE_UP_PREFIX))
3176 if ((result = RunHotkeys(ie,IntuitionBase)))
3178 if (result == RUNHOTREUSE)
3180 reuse_event = TRUE;
3182 else
3184 keep_event = FALSE;
3186 break;
3188 w = IntuitionBase->ActiveWindow;
3190 #endif
3192 if ( keep_event &&
3193 ((!(ie->ie_Code & IECODE_UP_PREFIX)) ||
3194 gadget ||
3195 (w && ((w->IDCMPFlags & IDCMP_VANILLAKEY) == 0)) ))
3197 if (gadget)
3199 keep_event = FALSE;
3201 DEBUG_KEY(dprintf("Handler: Gadget 0x%lx active\n",gadget));
3202 DEBUG_KEY(dprintf("Handler: GadgetID 0x%lx UserData 0x%lx\n",
3203 gadget->GadgetID,
3204 gadget->UserData));
3205 DEBUG_KEY(dprintf("Handler: GadgetType 0x%lx Flags 0x%lx Activation 0x%lx\n",
3206 gadget->GadgetType,
3207 gadget->Flags,
3208 gadget->Activation));
3209 DEBUG_KEY(dprintf("Handler: MoreFlags 0x%lx\n",
3210 ((struct ExtGadget*)gadget)->MoreFlags));
3212 switch (gadget->GadgetType & GTYP_GTYPEMASK)
3214 case GTYP_STRGADGET:
3216 UWORD imsgcode;
3217 ULONG ret = HandleStrInput(gadget, gi, ie, &imsgcode,
3218 IntuitionBase);
3220 DEBUG_KEY(dprintf("Handler: Key GTYP_STRGADGET ret 0x%lx\n",ret));
3221 if (ret & (SGA_END | SGA_NEXTACTIVE | SGA_PREVACTIVE))
3223 if (gadget->Activation & GACT_RELVERIFY)
3225 DEBUG_KEY(dprintf("Handler: GACT_RELVERIFY\n"));
3226 ih_fire_intuimessage(w,
3227 IDCMP_GADGETUP,
3228 imsgcode,
3229 gadget,
3230 IntuitionBase);
3232 if (req && gadget->Activation & GACT_ENDGADGET)
3234 DEBUG_KEY(dprintf("Handler: GACT_ENDGADGET\n"));
3235 EndRequest(req, w);
3237 req = w->FirstRequest;
3238 ret = 0;
3242 if ((gadget->Flags & GFLG_TABCYCLE) && (ret & SGA_NEXTACTIVE))
3244 gadget = FindCycleGadget(w, req, gadget, GMR_NEXTACTIVE);
3245 DEBUG_KEY(dprintf("Handler: TabCycle next gadget 0x%lx\n",gadget));
3247 else if ((gadget->Flags & GFLG_TABCYCLE) && (ret & SGA_PREVACTIVE))
3249 gadget = FindCycleGadget(w, req, gadget, GMR_PREVACTIVE);
3250 DEBUG_KEY(dprintf("Handler: TabCycle prev gadget 0x%lx\n",gadget));
3252 else
3254 gadget = NULL;
3257 if (gadget)
3259 gadget = DoActivateGadget(w, req, gadget, IntuitionBase);
3262 } /* if (ret & (SGA_END | SGA_NEXTACTIVE | SGA_PREVACTIVE)) */
3264 break;
3267 case GTYP_CUSTOMGADGET:
3268 DEBUG_KEY(dprintf("Handler: GTYP_CUSTOMGADGET\n"));
3269 DEBUG_KEY(dprintf("Handler: send GM_HANDLEINPUT\n"));
3270 gadget = DoGPInput(gi,
3271 gadget,
3273 GM_HANDLEINPUT,
3274 &reuse_event,
3275 IntuitionBase);
3276 DEBUG_KEY(dprintf("Handler: reuse %ld\n",reuse_event));
3277 break;
3279 } /* switch (gadget type) */
3281 } /* if (a gadget is currently active) */
3282 else if (w && (!req || req->Flags & NOISYREQ))
3284 BOOL menushortcut = FALSE;
3286 DEBUG_KEY(dprintf("Handler: No Gadget active\n"));
3287 DEBUG_KEY(dprintf("Handler: Qualifier 0x%lx WinFlags 0x%lx IDCMP 0x%lx\n",ie->ie_Qualifier,w->Flags,w->IDCMPFlags));
3289 if ((ie->ie_Qualifier & IEQUALIFIER_RCOMMAND) &&
3290 (!(w->Flags & WFLG_RMBTRAP)) &&
3291 (w->IDCMPFlags & IDCMP_MENUPICK))
3293 struct Menu *strip = 0;
3295 DEBUG_KEY(dprintf("Handler: MenuKey\n"));
3296 ObtainSemaphore(&GetPrivIBase(IntuitionBase)->MenuLock);
3298 strip = w->MenuStrip;
3300 if (((struct IntWindow *)w)->menulendwindow)
3302 strip = ((struct IntWindow *)w)->menulendwindow->MenuStrip;
3305 DEBUG_KEY(dprintf("Handler: MenuStrip 0x%lx\n",strip));
3306 if (strip)
3308 UBYTE key;
3310 if (MapRawKey(ie, &key, 1, NULL) == 1)
3312 UWORD menucode;
3314 menucode = FindMenuShortCut(strip, key, TRUE, IntuitionBase);
3316 DEBUG_KEY(dprintf("Handler: menucode 0x%lx\n",menucode));
3318 if (menucode != MENUNULL)
3320 DEBUG_KEY(dprintf("Handler: build menuevent\n"));
3321 ie->ie_Class = IECLASS_MENU;
3322 ie->ie_SubClass = IESUBCLASS_MENUSTOP;
3323 ie->ie_EventAddress = w;
3324 ie->ie_Code = menucode;
3326 reuse_event = TRUE;
3327 menushortcut = TRUE;
3329 MENUS_ACTIVE = TRUE;
3330 iihdata->MenuWindow = w;
3333 else
3335 DEBUG_KEY(dprintf("Handler: MapRawKey failed\n"));
3338 if (!menushortcut) /* !! */
3339 ReleaseSemaphore(&GetPrivIBase(IntuitionBase)->MenuLock);
3341 } /* if could be a menu short cut */
3342 else
3343 if ((ie->ie_Qualifier & IEQUALIFIER_RCOMMAND) &&
3344 (!(w->IDCMPFlags & IDCMP_MENUPICK)))
3346 struct Menu *strip = 0;
3347 struct Window *window = w;
3349 /* not sure here about RMBTRAP */
3350 DEBUG_KEY(dprintf("Handler: no idcmp, create a MENULIST idcmp\n"));
3352 ObtainSemaphore(&GetPrivIBase(IntuitionBase)->MenuLock);
3354 strip = w->MenuStrip;
3356 if (((struct IntWindow *)w)->menulendwindow)
3358 strip = ((struct IntWindow *)w)->menulendwindow->MenuStrip;
3359 window = ((struct IntWindow *)w)->menulendwindow;
3362 DEBUG_KEY(dprintf("Handler: MenuStrip 0x%lx\n",strip));
3363 if (strip)
3365 UBYTE key;
3367 if (MapRawKey(ie, &key, 1, NULL) == 1)
3369 UWORD menucode;
3371 menucode = FindMenuShortCut(strip, key, TRUE, IntuitionBase);
3373 DEBUG_KEY(dprintf("Handler: menucode 0x%lx\n",menucode));
3375 if (menucode != MENUNULL)
3377 DEBUG_KEY(dprintf("Handler: build menuevent\n"));
3378 ih_fire_intuimessage(window,
3379 IDCMP_MENUPICK,
3380 menucode,
3381 ie->ie_position.ie_addr, /* ie_dead.ie_prev[1|2]Down[Code|Qual]. 64 bit machines!? */
3382 IntuitionBase);
3383 keep_event = FALSE;
3384 menushortcut = TRUE;
3387 else
3389 DEBUG_KEY(dprintf("Handler: MapRawKey failed\n"));
3392 ReleaseSemaphore(&GetPrivIBase(IntuitionBase)->MenuLock);
3393 } /* if could be a menu short but current window has no idcmp cut */
3395 if (menushortcut)
3397 DEBUG_KEY(dprintf("Handler: menu shortcut..break\n"));
3398 break;
3401 /* This is a regular RAWKEY event (no gadget taking care
3402 of it...). */
3404 if (iihdata->ActQualifier & IEQUALIFIER_REPEAT)
3406 /* don't send repeat key events if repeatqueue is full */
3407 if (IW(w)->num_repeatevents >= IW(w)->repeatqueue)
3409 DEBUG_KEY(dprintf("Handler: RepeatEvents full..don't send more\n"));
3410 break;
3414 if (w->IDCMPFlags & IDCMP_VANILLAKEY)
3416 UBYTE keyBuffer;
3418 DEBUG_KEY(dprintf("Handler: VANILLAKEY\n"));
3419 // DEBUG_KEY(dprintf("Handler: MapRawKey ie 0x%lx KeyMapBase 0x%lx IntutionBase 0x%lx\n",ie,KeymapBase,IntuitionBase));
3421 if (MapRawKey(ie, &keyBuffer, 1, NULL) == 1)
3423 DEBUG_KEY(dprintf("Handler: send VANILLAKEY msg\n"));
3424 ih_fire_intuimessage(w,
3425 IDCMP_VANILLAKEY,
3426 keyBuffer,
3427 ie->ie_position.ie_addr, /* ie_dead.ie_prev[1|2]Down[Code|Qual]. 64 bit machines!? */
3428 IntuitionBase);
3429 DEBUG_KEY(dprintf("Handler: done\n"));
3430 break;
3433 /* If the event mapped to more than one byte, it is not
3434 a legal VANILLAKEY, so we send it as the original
3435 RAWKEY event. */
3439 if (w->IDCMPFlags & IDCMP_RAWKEY)
3441 DEBUG_KEY(dprintf("Handler: send IDCMP_RAWKEY Qual 0x%lx Code 0x%lx addr 0x%lx Event\n",
3442 ie->ie_Qualifier,ie->ie_Code,ie->ie_position.ie_addr));
3443 ih_fire_intuimessage(w,
3444 IDCMP_RAWKEY,
3445 ie->ie_Code,
3446 ie->ie_position.ie_addr, /* ie_dead.ie_prev[1|2]Down[Code|Qual]. 64 bit machine!? */
3447 IntuitionBase);
3448 keep_event = FALSE;
3451 DEBUG_KEY(dprintf("Handler: done\n"));
3452 } /* regular RAWKEY */
3455 break; /* case IECLASS_RAWKEY */
3457 case IECLASS_TIMER:
3458 if (iihdata->MouseBoundsKillTimer)
3460 iihdata->MouseBoundsKillTimer--;
3461 if (iihdata->MouseBoundsKillTimer == 0)
3463 iihdata->MouseBoundsActiveFlag = FALSE;
3467 if (GetPrivIBase(IntuitionBase)->PointerDelay)
3469 ULONG lock = LockIBase(0);
3471 if (--GetPrivIBase(IntuitionBase)->PointerDelay == 0)
3473 struct SharedPointer *shared_pointer;
3474 struct Window *window = IntuitionBase->ActiveWindow;
3475 struct IntScreen *scr;
3476 Object *pointer = ((struct IntWindow *)window)->pointer;
3478 DEBUG_POINTER(dprintf("InputHandler: PointerDelay\n"));
3479 DEBUG_POINTER(dprintf("InputHandler: Pointer 0x%lx\n",
3480 pointer));
3482 if (window)
3484 DEBUG_POINTER(dprintf("InputHandler: Window 0x%lx\n",
3485 window));
3486 scr = GetPrivScreen(window->WScreen);
3487 if (scr)
3489 DEBUG_POINTER(dprintf("InputHandler: Screen 0x%lx\n",
3490 scr));
3491 if (pointer == NULL)
3493 pointer = GetPrivIBase(IntuitionBase)->DefaultPointer;
3496 if (((struct IntWindow *)window)->busy)
3498 pointer = GetPrivIBase(IntuitionBase)->BusyPointer;
3501 GetAttr(POINTERA_SharedPointer, pointer, (IPTR *) &shared_pointer);
3503 DEBUG_POINTER(dprintf("InputHandler: scr 0x%lx pointer 0x%lx shared_pointer 0x%lx\n",
3504 scr, pointer, shared_pointer));
3505 DEBUG_POINTER(dprintf("InputHandler: sprite 0x%lx\n",
3506 shared_pointer->sprite));
3508 if (ChangeExtSpriteA(&scr->Screen.ViewPort,
3509 scr->Pointer->sprite, shared_pointer->sprite, NULL))
3511 ObtainSharedPointer(shared_pointer, IntuitionBase);
3512 ReleaseSharedPointer(scr->Pointer, IntuitionBase);
3513 scr->Pointer = shared_pointer;
3514 if (window)
3516 window->XOffset = shared_pointer->xoffset;
3517 window->YOffset = shared_pointer->yoffset;
3520 else
3522 DEBUG_POINTER(dprintf("InputHandler: can't set pointer.\n"));
3525 else
3527 DEBUG_POINTER(dprintf("InputHandler: no screen.\n"));
3530 else
3532 DEBUG_POINTER(dprintf("InputHandler: no window.\n"));
3536 UnlockIBase(lock);
3539 if (GetPrivIBase(IntuitionBase)->MenuVerifyScreen)
3541 struct IntScreen *scr = GetPrivIBase(IntuitionBase)->MenuVerifyScreen;
3543 if ((--scr->MenuVerifyTimeOut) <= 0)
3545 struct InputEvent ie;
3547 /* currently we ONLY need the menu open time ! */
3548 ie.ie_TimeStamp.tv_secs = IntuitionBase->Seconds;
3549 ie.ie_TimeStamp.tv_micro = IntuitionBase->Micros;
3551 if (FireMenuMessage(MMCODE_START, scr->MenuVerifyActiveWindow, &ie, IntuitionBase))
3553 /* This lock will be released only when the user is
3554 done with menus = when IECLASS_MENU + IESUBCLASS_MENUSTOP
3555 event arrives (generated by MenuHandler task) */
3557 ObtainSemaphore(&GetPrivIBase(IntuitionBase)->MenuLock);
3558 iihdata->MenuWindow = scr->MenuVerifyActiveWindow;
3559 MENUS_ACTIVE = TRUE;
3562 scr->MenuVerifyActiveWindow = NULL;
3563 scr->MenuVerifyTimeOut = 0;
3564 scr->MenuVerifyMsgCount = 0;
3565 scr->MenuVerifySeconds = 0;
3566 scr->MenuVerifyMicros = 0;
3567 GetPrivIBase(IntuitionBase)->MenuVerifyScreen = NULL;
3570 else if (MENUS_ACTIVE)
3572 FireMenuMessage(MMCODE_EVENT, 0, ie, IntuitionBase);
3573 keep_event = FALSE;
3574 break;
3577 #ifdef SKINS
3578 if (IntuitionBase->FirstScreen->MouseY <= IntuitionBase->FirstScreen->BarHeight && GetPrivScreen(IntuitionBase->FirstScreen)->SpecialFlags & SF_AppearingBar && !iihdata->TitlebarOnTop && iihdata->TitlebarAppearTime)
3580 UQUAD currenttime = (((UQUAD)ie->ie_TimeStamp.tv_secs) * 50) + (UQUAD)(ie->ie_TimeStamp.tv_micro / 20000);
3581 if (currenttime >= iihdata->TitlebarAppearTime + 10)
3583 iihdata->TitlebarOnTop = TRUE;
3584 iihdata->TitlebarAppearTime = 0;
3586 LOCK_REFRESH(IntuitionBase->FirstScreen);
3588 MoveLayer(0,IntuitionBase->FirstScreen->BarLayer,0,IntuitionBase->FirstScreen->BarHeight + 1);
3589 UpfrontLayer(0,IntuitionBase->FirstScreen->BarLayer);
3590 CheckLayers(IntuitionBase->FirstScreen, IntuitionBase);
3592 UNLOCK_REFRESH(IntuitionBase->FirstScreen);
3595 #endif
3598 UQUAD currenttime = (((UQUAD)ie->ie_TimeStamp.tv_secs) * 50) + (UQUAD)(ie->ie_TimeStamp.tv_micro / 20000);
3599 #define SECONDS(x) (x*50)
3600 if (iihdata->HelpGadgetFindTime && (currenttime >= iihdata->HelpGadgetFindTime + SECONDS(1)))
3602 struct Gadget *lhg = iihdata->LastHelpGadget;
3603 fire_intuimessage(iihdata->LastHelpWindow,
3604 IDCMP_GADGETHELP,
3605 lhg ? lhg->GadgetID : 0, /* Don't know what it should be */
3606 lhg,
3607 IntuitionBase);
3608 iihdata->HelpGadgetFindTime = 0;
3612 if (gadget)
3614 if (IS_BOOPSI_GADGET(gadget))
3616 gadget = DoGPInput(gi, gadget, ie, GM_HANDLEINPUT, &reuse_event, IntuitionBase);
3619 } /* if (gadget) */
3621 #if USE_NEWDISPLAYBEEP
3623 if (GetPrivIBase(IntuitionBase)->BeepingScreens)
3625 ULONG lock;
3626 struct Screen *scr;
3628 lock = LockIBase(0);
3630 for (scr = IntuitionBase->FirstScreen;
3631 scr && GetPrivIBase(IntuitionBase)->BeepingScreens;
3632 scr = scr->NextScreen)
3634 if ((scr->Flags & BEEPING) &&
3635 !GetPrivScreen(scr)->BeepingCounter--)
3637 GetPrivIBase(IntuitionBase)->BeepingScreens--;
3638 scr->Flags &= (UWORD) ~BEEPING;
3640 /* if (GetBitMapAttr(scr->RastPort.BitMap, BMA_DEPTH) <= 8)
3641 // visual beep on CLUT-screen
3643 // SetRGB4 (&screen->ViewPort, 0, scr->SaveColor0 & 0x000F, (scr->SaveColor0 & 0x00F0) >> 4, (scr->SaveColor0 & 0x0F00) >> 8);
3644 SetRGB32 (&scr->ViewPort, 0,
3645 GetPrivScreen(scr)->DisplayBeepColor0[0],
3646 GetPrivScreen(scr)->DisplayBeepColor0[1],
3647 GetPrivScreen(scr)->DisplayBeepColor0[2]
3650 else
3651 // visual beep on hi- and truecolor screens
3653 RenderScreenBar(scr, FALSE, IntuitionBase);
3656 RenderScreenBar(scr, FALSE, IntuitionBase);
3660 UnlockIBase(lock);
3662 #endif /* USE_NEWDISPLAYBEEP */
3665 /* stegerg: on the Amiga, Intuition's InputHandler seems to always
3666 swallow IECLASS_TIMER InputEvents. They never reach InputHandlers with
3667 lower priorities. So we mark the event as eaten by Intuition */
3668 keep_event = FALSE;
3670 if (!w) break;
3672 /* Send INTUITICK msg only if app already replied the last INTUITICK msg */
3673 if (w->Flags & WFLG_WINDOWTICKED) break;
3675 if (w->IDCMPFlags & IDCMP_INTUITICKS)
3677 /* Set the WINDOWTICKED flag, it will be cleared again when the app
3678 replies back the msg and the InputHandler handles the replymsg
3679 in HandleIntuiReplyPort() */
3681 ih_fire_intuimessage(w,
3682 IDCMP_INTUITICKS,
3685 IntuitionBase);
3687 break; /* case IECLASS_TIMER */
3689 case IECLASS_MENU:
3690 if (MENUS_ACTIVE && (ie->ie_SubClass == IESUBCLASS_MENUSTOP))
3692 struct Window *eventwin = (struct Window *)ie->ie_EventAddress;
3694 iihdata->MenuWindow = NULL;
3695 MENUS_ACTIVE = FALSE;
3697 /* semaphore was locked when menu action started, see
3698 above where MMCODE_START MenuMessage is sent.
3700 It could have also have been looked if the user
3701 activated one of the menu key shortcuts, see
3702 "case IECLASS_RAWKEY" */
3704 ReleaseSemaphore(&GetPrivIBase(IntuitionBase)->MenuLock);
3706 keep_event = FALSE;
3708 if (((struct IntWindow *)eventwin)->menulendwindow)
3710 eventwin = ((struct IntWindow *)eventwin)->menulendwindow;
3713 ih_fire_intuimessage((struct Window *)eventwin,
3714 IDCMP_MENUPICK,
3715 ie->ie_Code,
3716 (struct Window *)ie->ie_EventAddress,
3717 IntuitionBase);
3720 break;
3722 case IECLASS_DISKINSERTED:
3723 case IECLASS_DISKREMOVED:
3724 case IECLASS_NEWPREFS:
3726 struct Screen *scr;
3727 ULONG idcmp;
3728 LONG lock;
3730 switch (ie->ie_Class)
3732 case IECLASS_DISKINSERTED:
3733 idcmp = IDCMP_DISKINSERTED;
3734 break;
3736 case IECLASS_DISKREMOVED:
3737 idcmp = IDCMP_DISKREMOVED;
3738 break;
3740 default:
3741 idcmp = IDCMP_NEWPREFS;
3743 * Here we need to update the mouse prefs and
3744 * maybe other stuff which comes from the global prefs file.
3746 break;
3749 lock = LockIBase(0);
3751 for (scr = IntuitionBase->FirstScreen; scr; scr = scr->NextScreen)
3753 struct Window *win;
3755 for (win = scr->FirstWindow; win; win = win->NextWindow)
3757 /* stegerg:
3758 CHECKME, really use fire_intuimessage() here,
3759 instead of ih_fireintuimessage? Same for
3760 IDCMP_GADGETHELP above, BTW. */
3762 fire_intuimessage(win,
3763 idcmp,
3765 NULL,
3766 IntuitionBase);
3770 UnlockIBase(lock);
3772 break;
3774 #ifdef __MORPHOS__
3775 #define NEWMOUSEIDCMP !SysBase->MaxLocMem
3776 #else
3777 #define NEWMOUSEIDCMP FALSE
3778 #endif
3779 case IECLASS_NEWMOUSE:
3781 * The following is only needed on hardware not running
3782 * the NewMouse driver.
3784 if (w->IDCMPFlags & IDCMP_RAWKEY && NEWMOUSEIDCMP)
3786 ih_fire_intuimessage(w,
3787 IDCMP_RAWKEY,
3788 ie->ie_Code,
3789 ie->ie_position.ie_addr, /* ie_dead.ie_prev[1|2]Down[Code|Qual]. 64 bit machine!? */
3790 IntuitionBase);
3791 keep_event = FALSE;
3793 break;
3795 case IECLASS_NULL:
3796 break;
3798 #ifdef __MORPHOS__
3799 case IECLASS_NEWTIMER:
3800 if (MENUS_ACTIVE)
3802 FireMenuMessage(MMCODE_EVENT, 0, ie, IntuitionBase);
3803 keep_event = FALSE;
3804 break;
3807 if (gadget)
3809 if (gadget == iihdata->MasterSizeGadget)
3811 gadget = DoGPInput(gi, gadget, ie, GM_HANDLEINPUT, &reuse_event, IntuitionBase);
3814 } /* if (gadget) */
3815 break;
3816 #endif /* __MORPHOS__ */
3818 default:
3819 if (MENUS_ACTIVE)
3821 FireMenuMessage(MMCODE_EVENT, 0, ie, IntuitionBase);
3822 keep_event = FALSE;
3823 break;
3828 "[Intui] InputHandler: Unknown IEClass: addr = %x class = %d (origclass = %d)\n",
3829 orig_ie, ie->ie_Class,orig_ie->ie_Class
3832 break;
3833 } /* switch (ie->ie_Class) */
3835 if (reuse_event)
3838 else if (keep_event && !ie_used)
3840 *iihdata->EndInputEventChain = orig_ie;
3841 iihdata->EndInputEventChain = &orig_ie->ie_NextEvent;
3842 ie_used = TRUE;
3844 else if (!ie_used)
3846 orig_ie->ie_NextEvent = iihdata->FreeInputEvents;
3847 iihdata->FreeInputEvents = orig_ie;
3850 } /* for (each event in the chain) */
3852 iihdata->ActiveGadget = gadget;
3854 D(bug("Outside pollingloop\n"));
3856 #if SINGLE_SETPOINTERPOS_PER_EVENTLOOP
3857 if (call_setpointerpos)
3859 SetPointerPos(pointerposx, pointerposy);
3861 #endif
3863 /* Terminate the event chain. */
3864 *iihdata->EndInputEventChain = NULL;
3866 /* Transfer the list of allocated events in the list of events that should
3867 * be freed the next time the handler is entered.
3869 iihdata->AllocatedInputEventList = iihdata->NewAllocatedInputEventList;
3870 NEWLIST((struct List*)&iihdata->NewAllocatedInputEventList);
3872 /* Reset the event chain here, not at the beginning of the handler, for
3873 * events that might be allocated in other handers.
3875 iihdata->EndInputEventChain = &iihdata->ReturnInputEvent;
3876 iihdata->FreeInputEvents = NULL;
3878 ReleaseSemaphore(&GetPrivIBase(IntuitionBase)->InputHandlerLock);
3880 // DEBUG_HANDLER(dprintf("Handler: ->IBase 0x%lx KeyMapBase 0x%lx\n",IntuitionBase,KeymapBase));
3882 return iihdata->ReturnInputEvent;
3884 AROS_USERFUNC_EXIT
3887 /****************************************************************************************/