diskimage: Compiler delint
[AROS.git] / rom / intuition / inputhandler.c
blob31c52cbde4258670aa059160f0868b4f20b37a2f
1 /*
2 Copyright © 1995-2012, 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"
42 #include "monitorclass_private.h"
44 #ifdef SKINS
45 # include "smallmenu.h"
46 # include "intuition_customizesupport.h"
47 #endif
49 #undef DEBUG
50 #define DEBUG 0
51 #include <aros/debug.h>
53 #define DEBUG_HANDLER(x) ;
54 #define DEBUG_KEY(x) ;
55 #define DEBUG_SCREENKEY(x) ;
56 #define DEBUG_AUTOSCROLL(x)
57 #define DEBUG_CLICK(x)
58 #define DEBUG_DRAG(x)
59 #define DEBUG_GADGET(x)
60 #define DEBUG_MONITOR(x)
61 #define DEBUG_MOUSE(x)
62 #define DEBUG_WINDOW(x)
64 /****************************************************************************************/
66 struct Interrupt *InitIIH(struct IntuitionBase *IntuitionBase)
68 struct Interrupt *iihandler;
70 D(bug("InitIIH(IntuitionBase=%p)\n", IntuitionBase));
72 iihandler = AllocMem(sizeof (struct Interrupt), MEMF_PUBLIC | MEMF_CLEAR);
73 if (iihandler)
75 struct IIHData *iihdata;
77 iihdata = AllocMem(sizeof (struct IIHData), MEMF_PUBLIC | MEMF_CLEAR);
78 if (iihdata)
80 struct MsgPort *port;
82 port = AllocMem(sizeof (struct MsgPort), MEMF_PUBLIC | MEMF_CLEAR);
83 if (port)
85 if ((iihdata->InputEventMemPool = CreatePool(MEMF_PUBLIC | MEMF_CLEAR,
86 sizeof(struct GeneratedInputEvent) * 10,
87 sizeof(struct GeneratedInputEvent) * 10)) &&
88 (iihdata->ActionsMemPool = CreatePool(MEMF_SEM_PROTECTED,
89 2000, 2000)))
91 const struct TagItem dragtags[] =
93 {GA_SysGadget , TRUE },
94 {GA_SysGType , GTYP_WDRAGGING},
95 {TAG_DONE }
98 const struct TagItem sizetags[] =
100 {GA_SysGadget , TRUE },
101 {GA_SysGType , GTYP_SIZING },
102 {TAG_DONE }
105 iihdata->MasterDragGadget = (struct Gadget *)NewObjectA(GetPrivIBase(IntuitionBase)->dragbarclass,
106 NULL,
107 (struct TagItem *)dragtags);
109 iihdata->MasterSizeGadget = (struct Gadget *)NewObjectA(GetPrivIBase(IntuitionBase)->sizebuttonclass,
110 NULL,
111 (struct TagItem *)sizetags);
113 if (iihdata->MasterDragGadget && iihdata->MasterSizeGadget)
115 ULONG lock;
117 /* We do not want to be woken up by message replies.
118 We are anyway woken up about 10 times a second by
119 timer events
121 port->mp_Flags = PA_IGNORE;
123 NEWLIST( &(port->mp_MsgList) );
124 iihdata->IntuiReplyPort = port;
126 NEWLIST((struct List*) &iihdata->IntuiActionQueue);
127 NEWLIST((struct List*)&iihdata->NewAllocatedInputEventList);
128 NEWLIST((struct List*)&iihdata->AllocatedInputEventList);
129 iihdata->EndInputEventChain = &iihdata->ReturnInputEvent;
130 iihdata->FreeInputEvents = NULL;
132 iihdata->ActQualifier = IEQUALIFIER_RELATIVEMOUSE;
134 /* Note: there are several routines like CloseWindow, which
135 expect is_Data to point to the IIHData structure, so don't
136 change this! */
138 iihandler->is_Code = (VOID_FUNC)AROS_ASMSYMNAME(IntuiInputHandler);
139 iihandler->is_Data = iihdata;
140 iihandler->is_Node.ln_Pri = 50;
141 iihandler->is_Node.ln_Name = "Intuition InputHandler";
143 lock = LockIBase(0UL);
145 iihdata->IntuitionBase = IntuitionBase;
147 UnlockIBase(lock);
149 GetPrivIBase(IntuitionBase)->IntuiReplyPort = iihdata->IntuiReplyPort;
150 GetPrivIBase(IntuitionBase)->IntuiActionQueue = &iihdata->IntuiActionQueue;
152 ReturnPtr ("InitIIH", struct Interrupt *, iihandler);
153 } /* f (iihdata->MasterDragGadget && iihdata->MasterSizeGadget) */
155 DisposeObject((Object *)iihdata->MasterDragGadget);
156 DisposeObject((Object *)iihdata->MasterSizeGadget);
158 DeletePool(iihdata->ActionsMemPool);
159 DeletePool(iihdata->InputEventMemPool);
161 } /* if (iihdata->InputEventMemPool = ... */
162 FreeMem(port, sizeof(struct MsgPort));
164 } /* if (port) */
165 FreeMem(iihdata, sizeof (struct IIHData));
166 iihdata->MouseBoundsActiveFlag = FALSE;
168 } /* if (iihdata) */
169 FreeMem(iihandler, sizeof (struct Interrupt));
171 } /* if (iihandler) */
173 ReturnPtr ("InitIIH", struct Interrupt *, NULL);
176 /****************************************************************************************/
178 VOID CleanupIIH(struct Interrupt *iihandler, struct IntuitionBase *IntuitionBase)
180 struct IIHData *iihdata = (struct IIHData *)iihandler->is_Data;
182 DisposeObject((Object *)iihdata->MasterDragGadget);
183 DisposeObject((Object *)iihdata->MasterSizeGadget);
185 FreeGeneratedInputEvents(iihdata);
186 DeletePool(iihdata->InputEventMemPool);
187 DeletePool(iihdata->ActionsMemPool);
189 /* One might think that this port is still in use by the inputhandler.
190 ** However, if intuition is closed for the last time, there should be no
191 ** windows that IntuiMessage can be sent to.
193 FreeMem(iihdata->IntuiReplyPort, sizeof (struct MsgPort));
195 FreeMem(iihdata, sizeof (struct IIHData));
196 FreeMem(iihandler, sizeof (struct Interrupt));
198 return;
201 /****************************************************************************************/
203 static void HandleIntuiReplyPort(struct IIHData *iihdata, struct IntuitionBase *IntuitionBase)
205 struct Library *TimerBase = GetPrivIBase(IntuitionBase)->TimerBase;
206 struct IntuiMessage *im;
208 while ((im = (struct IntuiMessage *)GetMsg(iihdata->IntuiReplyPort)))
210 if (im->IDCMPWindow && ResourceExisting(im->IDCMPWindow, RESOURCE_WINDOW, IntuitionBase))
212 struct IntWindow *win = (struct IntWindow *)im->IDCMPWindow;
214 Forbid();
215 GetSysTime(&win->lastmsgreplied);
216 Permit();
218 switch(im->Class)
220 case IDCMP_MOUSEMOVE:
221 IW(im->IDCMPWindow)->num_mouseevents--;
222 break;
224 case IDCMP_INTUITICKS:
225 AROS_ATOMIC_AND(im->IDCMPWindow->Flags, ~WFLG_WINDOWTICKED);
226 break;
228 #if USE_IDCMPUPDATE_MESSAGECACHE
229 case IDCMP_IDCMPUPDATE:
230 IW(im->IDCMPWindow)->num_idcmpupdate--;
232 if (!(IW(im->IDCMPWindow)->num_idcmpupdate) && IW(im->IDCMPWindow)->messagecache)
234 SendIntuiMessage(im->IDCMPWindow,IW(im->IDCMPWindow)->messagecache);
235 IW(im->IDCMPWindow)->messagecache = 0;
237 break;
238 #endif
240 case IDCMP_MENUVERIFY:
242 struct Window *w = im->IDCMPWindow;
243 struct IntScreen *scr = 0;
245 scr = GetPrivScreen(w->WScreen);
247 if (scr != GetPrivIBase(IntuitionBase)->MenuVerifyScreen ||
248 scr->MenuVerifySeconds > im->Seconds ||
249 (scr->MenuVerifySeconds == im->Seconds &&
250 scr->MenuVerifyMicros > im->Micros))
252 /* The timeout has expired, just ignore. */
254 else
256 --scr->MenuVerifyMsgCount;
257 if (w == scr->MenuVerifyActiveWindow &&
258 im->Code == MENUCANCEL)
260 ULONG lock = LockIBase(0);
261 struct Window *w1;
263 for (w1 = scr->Screen.FirstWindow; w1; w1 = w1->NextWindow)
265 if (w1->IDCMPFlags & IDCMP_MENUVERIFY && w1 != scr->MenuVerifyActiveWindow)
267 ih_fire_intuimessage(w1,
268 IDCMP_MOUSEBUTTONS,
269 MENUUP,
271 IntuitionBase);
275 UnlockIBase(lock);
277 scr->MenuVerifyActiveWindow = NULL;
278 scr->MenuVerifyTimeOut = 0;
279 scr->MenuVerifyMsgCount = 0;
280 scr->MenuVerifySeconds = 0;
281 scr->MenuVerifyMicros = 0;
282 GetPrivIBase(IntuitionBase)->MenuVerifyScreen = NULL;
284 else if (scr->MenuVerifyMsgCount == 0)
286 struct InputEvent ie;
288 /* currently we ONLY need the menu open time ! */
289 ie.ie_TimeStamp.tv_secs = im->Seconds;
290 ie.ie_TimeStamp.tv_micro = im->Micros;
292 if (FireMenuMessage(MMCODE_START, scr->MenuVerifyActiveWindow, &ie, IntuitionBase))
294 /* This lock will be released only when the user is
295 done with menus = when IECLASS_MENU + IESUBCLASS_MENUSTOP
296 event arrives (generated by MenuHandler task) */
298 ObtainSemaphore(&GetPrivIBase(IntuitionBase)->MenuLock);
299 iihdata->MenuWindow = scr->MenuVerifyActiveWindow;
300 MENUS_ACTIVE = TRUE;
303 scr->MenuVerifyActiveWindow = NULL;
304 scr->MenuVerifyTimeOut = 0;
305 scr->MenuVerifyMsgCount = 0;
306 scr->MenuVerifySeconds = 0;
307 scr->MenuVerifyMicros = 0;
308 GetPrivIBase(IntuitionBase)->MenuVerifyScreen = NULL;
311 break;
314 case IDCMP_SIZEVERIFY:
316 struct GadgetInfo *gi = &iihdata->GadgetInfo;
317 struct Window *w = im->IDCMPWindow;
318 struct Gadget *gadget = im->IAddress;
319 struct InputEvent ie;
320 BOOL reuse_event;
322 PrepareGadgetInfo(gi, IntuitionBase->ActiveScreen, w, NULL);
323 SetGadgetInfoGadget(gi, gadget, IntuitionBase);
325 if (IS_BOOPSI_GADGET(gadget))
327 ie.ie_NextEvent = NULL;
328 ie.ie_Class = IECLASS_RAWMOUSE;
329 ie.ie_SubClass = 0;
330 ie.ie_Code = IECODE_LBUTTON;
331 ie.ie_Qualifier = im->Qualifier;
332 ie.ie_X = im->MouseX;
333 ie.ie_Y = im->MouseY;
334 ie.ie_TimeStamp.tv_secs = IntuitionBase->Seconds;
335 ie.ie_TimeStamp.tv_micro = IntuitionBase->Micros;
337 DoGPInput(gi,
338 gadget,
339 &ie,
340 GM_GOACTIVE,
341 &reuse_event,
342 IntuitionBase);
344 /* For compatibility, send a GM_HANDLEINPUT too */
345 ie.ie_Class = IECLASS_RAWMOUSE;
346 ie.ie_Code = IECODE_NOBUTTON;
347 ie.ie_X = 0;
348 ie.ie_Y = 0;
350 gadget = DoGPInput(gi,
351 gadget,
352 &ie,
353 GM_HANDLEINPUT,
354 &reuse_event,
355 IntuitionBase);
358 /* From now on the master drag/size gadget takes over */
360 iihdata->ActiveSysGadget = gadget;
361 gadget = iihdata->MasterSizeGadget;
362 iihdata->ActiveGadget = gadget;
364 ie.ie_Class = IECLASS_RAWMOUSE;
365 ie.ie_Code = IECODE_LBUTTON;
366 ie.ie_X = im->MouseX;
367 ie.ie_Y = im->MouseY;
369 DoGPInput(gi,
370 gadget,
371 &ie,
372 GM_GOACTIVE,
373 &reuse_event,
374 IntuitionBase);
375 break;
378 case IDCMP_REQVERIFY:
380 struct Window *w = im->IDCMPWindow;
382 EndRequest(w->DMRequest, w);
384 ih_fire_intuimessage(w,
385 IDCMP_REQSET,
388 IntuitionBase);
390 break;
392 case IDCMP_WBENCHMESSAGE:
393 DEBUG_WORKBENCH(dprintf("HandleIntuiReplyPort: code 0x%lx\n",
394 im->Code));
395 break;
397 } /* switch(im->Class) */
399 if (im->Qualifier & IEQUALIFIER_REPEAT)
401 /* IDCMP_IDCMPUPDATE messages can also be sent from app task, therefore
402 it would be better if there was an ATOMIC_DEC macro or something */
404 if (IW(im->IDCMPWindow)->num_repeatevents)
406 IW(im->IDCMPWindow)->num_repeatevents--;
410 FreeIntuiMessage(im);
412 } /* while ((im = (struct IntuiMessage *)GetMsg(iihdata->IntuiReplyPort))) */
414 /****************************************************************************************/
416 struct Window *GetToolBoxWindow(struct InputEvent *ie, struct Screen *scr, struct IntuitionBase *IntuitionBase)
418 /* The caller has checked that the input event is a IECLASS_RAWMOUSE, SELECTDOWN event */
419 /* NOTE: may be called with NULL ie ptr! */
420 struct LayersBase *LayersBase = GetPrivIBase(IntuitionBase)->LayersBase;
421 struct Layer *l;
422 struct Window *new_w = NULL;
424 if (scr)
426 D(bug("GetToolBoxWindow: Click at (%d,%d)\n",scr->MouseX,scr->MouseY));
428 /* What layer ? */
429 LockLayerInfo(&scr->LayerInfo);
431 l = WhichLayer(&scr->LayerInfo, scr->MouseX, scr->MouseY);
433 UnlockLayerInfo(&scr->LayerInfo);
435 if (NULL == l)
437 new_w = NULL;
438 D(bug("GetToolBoxWindow: Click not inside layer\n"));
440 else if (l == scr->BarLayer)
443 else
445 new_w = (struct Window *)l->Window;
446 if (new_w)
448 if ((new_w->Flags & WFLG_TOOLBOX) == 0) new_w = NULL;
450 if (!new_w)
452 D(bug("GetToolBoxWindow: Selected layer is not a ToolBox window\n"));
454 else
456 D(bug("GetToolBoxWindow: Found layer %p\n", l));
461 D(bug("GetToolBoxWindow: New window %p\n", new_w));
462 return new_w;
465 /****************************************************************************************/
467 #define KEY_QUALIFIERS (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT | \
468 IEQUALIFIER_CAPSLOCK | IEQUALIFIER_CONTROL | \
469 IEQUALIFIER_LALT | IEQUALIFIER_RALT | \
470 IEQUALIFIER_LCOMMAND | IEQUALIFIER_RCOMMAND | \
471 IEQUALIFIER_NUMERICPAD)
473 #define BUTTON_QUALIFIERS (IEQUALIFIER_MIDBUTTON | IEQUALIFIER_RBUTTON | IEQUALIFIER_LEFTBUTTON)
475 static struct Gadget *Process_RawMouse(struct InputEvent *ie, struct IIHData *iihdata, struct Screen *screen,
476 struct Window *w, struct Gadget *gadget, struct GadgetInfo *gi,
477 ULONG stitlebarhit, BOOL new_active_window, BOOL IsToolbox,
478 struct InputEvent *orig_ie, BOOL *keep_event, BOOL *reuse_event,
479 #if SINGLE_SETPOINTERPOS_PER_EVENTLOOP
480 BOOL *call_setpointerpos,
481 #endif
482 struct IntuitionBase *IntuitionBase)
484 struct Library *InputBase = GetPrivIBase(IntuitionBase)->InputBase;
485 struct Requester *req = w ? w->FirstRequest : NULL;
487 switch (ie->ie_Code) {
488 case SELECTDOWN:
490 BOOL new_gadget = FALSE;
491 BOOL sizeverify = FALSE;
492 UWORD MetaDrag = GetPrivIBase(IntuitionBase)->IControlPrefs.ic_MetaDrag;
494 DEBUG_CLICK(bug("[Inputhandler] Screen 0x%p, Window 0x%p, Gadget 0x%p, screen titlebar %d, new active window %d\n", screen, w, gadget, stitlebarhit, new_active_window));
495 DEBUG_CLICK(if (screen) bug("[Inputhandler] Coordinates: (%d, %d)\n", screen->MouseX, screen->MouseY));
497 iihdata->ActQualifier |= IEQUALIFIER_LEFTBUTTON;
499 /* Enter screen dragging mode if LButton + MetaDrag are pressed. */
500 if (MetaDrag && ((iihdata->ActQualifier & KEY_QUALIFIERS) == MetaDrag)) {
501 iihdata->ScreenDrag = screen;
502 iihdata->ScreenDragPointX = screen->MouseX;
503 iihdata->ScreenDragPointY = screen->MouseY;
504 *keep_event = FALSE;
505 break;
508 #ifdef SKINS
509 iihdata->TitlebarAppearTime = 0;
510 #endif
511 if (MENUS_ACTIVE)
513 FireMenuMessage(MMCODE_EVENT, 0, ie, IntuitionBase);
514 *keep_event = FALSE;
515 break;
518 #ifdef SKINS
519 if (!gadget && w)
521 struct Gadget * draggadget = 0;
523 if ((!(w->FirstRequest)) && (w->Flags & WFLG_DRAGBAR) && MatchHotkey(ie,IA_ACTIVEWINDOWMOVE,IntuitionBase))
525 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)
527 for (draggadget = w->FirstGadget; draggadget; draggadget = draggadget->NextGadget)
529 if ((draggadget->GadgetType & GTYP_SYSTYPEMASK) == GTYP_WDRAGGING)
531 gadget = draggadget;
532 new_gadget = TRUE;
533 break;
539 if ((!(w->FirstRequest)) && (w->Flags & WFLG_SIZEGADGET) && MatchHotkey(ie,IA_ACTIVEWINDOWSIZE,IntuitionBase))
541 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)
543 for (draggadget = w->FirstGadget; draggadget; draggadget = draggadget->NextGadget)
545 if ((draggadget->GadgetType & GTYP_SYSTYPEMASK) == GTYP_SIZING)
547 gadget = draggadget;
548 new_gadget = TRUE;
549 break;
555 #endif
557 if (!gadget)
559 /* use the *current* screen rather than active one when searching
560 for sdepth gadget! */
561 if (screen)
562 gadget = FindGadget (screen, stitlebarhit ? NULL : w, stitlebarhit ? NULL : req,
563 screen->MouseX, screen->MouseY, gi, FALSE, IntuitionBase);
564 DEBUG_CLICK(bug("Click on gadget %p\n", gadget));
565 new_gadget = TRUE;
567 } /* if (!gadget) */
569 /* If we clicked screen titlebar outside of any gadget, enter drag mode */
570 if ((!gadget) && stitlebarhit) {
571 DEBUG_CLICK(bug("[Inputhandler] Entering drag state for screen 0x%p\n", screen));
572 iihdata->ScreenDrag = screen;
573 iihdata->ScreenDragPointX = screen->MouseX;
574 iihdata->ScreenDragPointY = screen->MouseY;
575 *keep_event = FALSE;
576 break;
579 if (!IsToolbox) {
580 if (!gadget && stitlebarhit)
582 struct Window *ww = 0;
584 ww = FindDesktopWindow(screen, IntuitionBase);
585 DEBUG_CLICK(bug("[Inputhandler] Clicked on backdrop window 0x%p\n", ww));
586 if (ww) {
587 ActivateWindow(ww);
588 w = ww;
592 if (!stitlebarhit && !new_active_window && DoubleClick(GetPrivIBase(IntuitionBase)->LastClickSecs,GetPrivIBase(IntuitionBase)->LastClickMicro,
593 ie->ie_TimeStamp.tv_secs,ie->ie_TimeStamp.tv_micro))
595 if (GetPrivIBase(IntuitionBase)->DoubleClickButton != SELECTDOWN)
597 GetPrivIBase(IntuitionBase)->DoubleClickCounter = 0;
598 GetPrivIBase(IntuitionBase)->DoubleClickButton = SELECTDOWN;
600 else
602 GetPrivIBase(IntuitionBase)->DoubleClickCounter ++;
605 else
607 DEBUG_CLICK(bug("[Inputhandler] Resetting doubleclick counter\n"));
608 GetPrivIBase(IntuitionBase)->DoubleClickButton = SELECTDOWN;
609 GetPrivIBase(IntuitionBase)->DoubleClickCounter = 0;
612 /* update last click time for doubleclicktofront */
613 GetPrivIBase(IntuitionBase)->LastClickSecs = ie->ie_TimeStamp.tv_secs;
614 GetPrivIBase(IntuitionBase)->LastClickMicro = ie->ie_TimeStamp.tv_micro;
616 #ifdef SKINS
617 if (!stitlebarhit)
619 ULONG result;
621 if (!(gadget && ((gadget->GadgetType & GTYP_SYSTYPEMASK) == GTYP_WDEPTH)))
622 if ((result = RunHotkeys(ie,IntuitionBase)))
624 //gadget = NULL;
625 if (result == RUNHOTREUSE)
627 *reuse_event = TRUE;
629 else
631 *keep_event = FALSE;
635 #endif
637 if (gadget && new_gadget)
639 DEBUG_GADGET(bug("[Inputhandler] Activate gadget: 0x%p\n", gadget));
640 if (w && (w->IDCMPFlags & IDCMP_SIZEVERIFY) &&
641 (gadget->GadgetType & GTYP_SYSTYPEMASK) == GTYP_SIZING /*||
642 (gadget->GadgetType & GTYP_SYSTYPEMASK) == GTYP_WZOOM*/)
644 ih_fire_intuimessage(w,
645 IDCMP_SIZEVERIFY,
647 gadget,
648 IntuitionBase);
649 gadget = NULL;
650 sizeverify = TRUE;
652 else
654 BOOL is_draggad, is_sizegad;
655 UWORD gsystype;
657 /* Whenever the active gadget changes the gi must be updated
658 because it is cached in iidata->GadgetInfo!!!! Don't
659 forget to do this if somewhere else the active
660 gadget is changed, for example in ActivateGadget!!! */
662 PrepareGadgetInfo(gi, screen, w, req);
663 SetGadgetInfoGadget(gi, gadget, IntuitionBase);
665 gsystype = gadget->GadgetType & GTYP_SYSTYPEMASK;
666 is_draggad = ((gsystype == GTYP_WDRAGGING)
667 #ifdef __MORPHOS__
668 || (gsystype == GTYP_WDRAGGING2)
669 #endif
671 is_sizegad = (gsystype == GTYP_SIZING);
673 /* jDc: intui68k sends IDCMPs for GACT_IMMEDIATE drag&sizegads! */
674 if (gadget->Activation & GACT_IMMEDIATE)
676 ih_fire_intuimessage(w,
677 IDCMP_GADGETDOWN,
679 gadget,
680 IntuitionBase);
683 if (is_draggad || is_sizegad)
685 if (IS_BOOPSI_GADGET(gadget))
687 DoGPInput(gi,
688 gadget,
690 GM_GOACTIVE,
691 reuse_event,
692 IntuitionBase);
694 /* Ignoring retval of dispatcher above is what
695 AmigaOS does too for boopsi drag/resize
696 gadgets */
700 /* From now on the master drag/size gadget takes over */
701 if ((w->MoreFlags & WMFLG_IAMMUI) && (w->Flags & WFLG_BORDERLESS))
702 iihdata->ActiveSysGadget = is_draggad ? gadget : 0;
703 else
704 iihdata->ActiveSysGadget = gadget;
705 gadget = is_draggad ? iihdata->MasterDragGadget : iihdata->MasterSizeGadget;
710 if (gadget)
713 switch (gadget->GadgetType & GTYP_GTYPEMASK)
715 case GTYP_BOOLGADGET:
716 /* Only set the GFLG_SELECTED flag for RELVERIFY and
717 * TOGGLESELECT gadget. It's for the user to do it if
718 * he wants for other GADGIMMEDIATE ones.
719 * Only RELVERIFY gadgets stay active.
722 if (gadget->Activation & (GACT_TOGGLESELECT | GACT_RELVERIFY))
724 gadget->Flags ^= GFLG_SELECTED;
725 RefreshBoolGadgetState(gadget, w, req, IntuitionBase);
728 if (gadget->Activation & GACT_RELVERIFY)
730 gadget->Activation |= GACT_ACTIVEGADGET;
731 iihdata->MouseWasInsideBoolGadget = TRUE;
733 else
735 gadget = NULL;
737 break;
739 case GTYP_PROPGADGET:
740 HandlePropSelectDown(gadget,
742 req,
743 w->MouseX - gi->gi_Domain.Left - GetGadgetLeft(gadget, gi->gi_Screen, gi->gi_Window, NULL),
744 w->MouseY - gi->gi_Domain.Top - GetGadgetTop(gadget, gi->gi_Screen, gi->gi_Window, NULL),
745 IntuitionBase);
748 break;
750 case GTYP_STRGADGET:
751 /* If the click was inside the active strgad,
752 ** then let it update cursor pos,
753 ** else deactivate stringadget and reuse event.
756 if (InsideGadget(gi->gi_Screen, gi->gi_Window,
757 gi->gi_Requester, gadget,
758 gi->gi_Screen->MouseX, gi->gi_Screen->MouseY))
760 UWORD imsgcode;
762 HandleStrInput(gadget, gi, ie, &imsgcode,
763 IntuitionBase);
765 else
767 gadget->Flags &= ~GFLG_SELECTED;
769 RefreshStrGadget(gadget, w, req, IntuitionBase);
770 /* Gadget not active anymore */
771 gadget = NULL;
772 *reuse_event = TRUE;
774 break;
776 case GTYP_CUSTOMGADGET:
777 gadget = DoGPInput(gi,
778 gadget,
780 (new_gadget ? GM_GOACTIVE : GM_HANDLEINPUT),
781 reuse_event,
782 IntuitionBase);
783 D(bug("new_gadget %d, goactive %p\n", new_gadget, gadget));
785 if (gadget && new_gadget && (!(gadget->GadgetType & GTYP_SIZING)))
787 /* For compatibility, send a GM_HANDLEINPUT too */
788 struct InputEvent newie;
789 BOOL reuse_event;
791 newie.ie_NextEvent = NULL;
792 newie.ie_Class = IECLASS_RAWMOUSE;
793 newie.ie_SubClass = 0;
794 newie.ie_Code = IECODE_NOBUTTON;
795 newie.ie_Qualifier = ie->ie_Qualifier;
796 newie.ie_X = 0;
797 newie.ie_Y = 0;
798 newie.ie_TimeStamp.tv_secs = IntuitionBase->Seconds;
799 newie.ie_TimeStamp.tv_micro = IntuitionBase->Micros;
801 gadget = DoGPInput(gi,
802 gadget,
803 &newie,
804 GM_HANDLEINPUT,
805 &reuse_event,
806 IntuitionBase);
807 D(bug("handleinput %p\n", gadget));
809 break;
811 case 0: //orig gadtools / some 1.3 gadgets
812 if (IS_SYS_GADGET(gadget))
814 HandleSysGadgetVerify(gi, gadget, IntuitionBase);
816 else
818 if (gadget->Activation & GACT_RELVERIFY)
820 gadget->Activation |= GACT_ACTIVEGADGET;
821 iihdata->MouseWasInsideBoolGadget = TRUE;
822 if (gadget->Flags & GFLG_GADGHIMAGE)
824 gadget->Flags ^= GFLG_SELECTED;
825 RefreshBoolGadgetState(gadget, w, req, IntuitionBase);
828 else
830 /* jDc: this is what original intuition does, before crashing after a while ;)*/
831 DEBUG_CLICK(bug("[Inputhandler] Sending SELECTDOWN (old gadget), window 0x%p\n", w));
832 ih_fire_intuimessage(w,
833 IDCMP_MOUSEBUTTONS,
834 SELECTDOWN,
836 IntuitionBase);
839 break;
840 } /* switch (GadgetType) */
842 } /* if (a gadget is active) */
843 else if (w && (!req || req->Flags & NOISYREQ) && !sizeverify && !stitlebarhit)
845 DEBUG_CLICK(bug("[Inputhandler] Sending SELECTDOWN, window 0x%p\n", w));
846 ih_fire_intuimessage(w,
847 IDCMP_MOUSEBUTTONS,
848 SELECTDOWN,
850 IntuitionBase);
853 } /* case SELECTDOWN */
854 break;
856 case SELECTUP:
857 iihdata->ActQualifier &= ~IEQUALIFIER_LEFTBUTTON;
859 /* Ignore this event if screen drag qualifier is pressed */
860 if (iihdata->ScreenDrag) {
861 iihdata->ScreenDrag = NULL;
862 *keep_event = FALSE;
863 break;
866 #ifdef SKINS
867 iihdata->TitlebarAppearTime = 0;
868 #endif
869 if (MENUS_ACTIVE)
871 FireMenuMessage(MMCODE_EVENT, 0, ie, IntuitionBase);
872 *keep_event = FALSE;
873 break;
876 if (gadget)
878 BOOL inside = InsideGadget(gi->gi_Screen, gi->gi_Window,
879 gi->gi_Requester, gadget,
880 gi->gi_Screen->MouseX, gi->gi_Screen->MouseY);
882 /*int selected = (gadget->Flags & GFLG_SELECTED) != 0;*/
884 switch (gadget->GadgetType & GTYP_GTYPEMASK)
886 case GTYP_BOOLGADGET:
887 /* Must be a RELVERIFY gadget */
889 if (!(gadget->Activation & GACT_TOGGLESELECT) && inside)
891 gadget->Flags ^= GFLG_SELECTED;
892 RefreshBoolGadgetState(gadget, w, req, IntuitionBase);
895 if (inside)
897 if (IS_SYS_GADGET(gadget))
899 HandleSysGadgetVerify(gi, gadget, IntuitionBase);
901 else
903 if (req && gadget->Activation & GACT_ENDGADGET)
905 EndRequest(req, w);
907 req = w->FirstRequest;
910 ih_fire_intuimessage(w,
911 IDCMP_GADGETUP,
913 gadget,
914 IntuitionBase);
917 else
919 /* RKRM say so */
920 ih_fire_intuimessage(w,
921 IDCMP_MOUSEBUTTONS,
922 SELECTUP,
924 IntuitionBase);
927 gadget->Activation &= ~GACT_ACTIVEGADGET;
928 gadget = NULL;
929 break;
931 case GTYP_PROPGADGET:
932 HandlePropSelectUp(gadget, w, req, IntuitionBase);
933 if (gadget->Activation & GACT_RELVERIFY)
935 ih_fire_intuimessage(w,
936 IDCMP_GADGETUP,
938 gadget,
939 IntuitionBase);
942 gadget = NULL;
943 break;
945 /* Intuition string gadgets don't care about SELECTUP */
947 case GTYP_CUSTOMGADGET:
948 gadget = DoGPInput(gi, gadget, ie, GM_HANDLEINPUT, reuse_event, IntuitionBase);
949 break;
951 case 0: //orig gadtools / some 1.3 gadgets
952 /* jDc: adding a gadget with gtyp field set to NULL crashes intui68k
953 ** seems we don't need compatibility on this field ;) anyway we should
954 ** handle the case of GTYP_CLOSE, etc, set by some "cod3r"
956 gadget->Activation &= ~GACT_ACTIVEGADGET;
957 if (gadget->Activation & GACT_RELVERIFY)
959 if (gadget->Flags & GFLG_GADGHIMAGE)
961 if (inside)
963 gadget->Flags ^= GFLG_SELECTED;
964 RefreshBoolGadgetState(gadget, w, req, IntuitionBase);
968 if (inside)
970 ih_fire_intuimessage(w,
971 IDCMP_GADGETUP,
973 gadget,
974 IntuitionBase);
976 } else {
977 ih_fire_intuimessage(w,
978 IDCMP_MOUSEBUTTONS,
979 SELECTUP,
981 IntuitionBase);
983 gadget = NULL;
984 break;
986 } /* switch GadgetType */
988 } /* if (a gadget is currently active) */
989 else if (w && (!req || req->Flags & NOISYREQ))
991 ih_fire_intuimessage(w,
992 IDCMP_MOUSEBUTTONS,
993 SELECTUP,
995 IntuitionBase);
998 break; /* case SELECTUP */
1000 case MENUDOWN:
1001 iihdata->ActQualifier |= IEQUALIFIER_RBUTTON;
1003 #ifdef SKINS
1004 iihdata->TitlebarAppearTime = 0;
1005 #endif
1006 if (MENUS_ACTIVE)
1008 FireMenuMessage(MMCODE_EVENT, 0, ie, IntuitionBase);
1009 *keep_event = FALSE;
1010 break;
1013 if (DoubleClick(GetPrivIBase(IntuitionBase)->LastClickSecs,GetPrivIBase(IntuitionBase)->LastClickMicro,
1014 ie->ie_TimeStamp.tv_secs,ie->ie_TimeStamp.tv_micro))
1016 if (GetPrivIBase(IntuitionBase)->DoubleClickButton != MENUDOWN)
1018 GetPrivIBase(IntuitionBase)->DoubleClickCounter = 0;
1019 GetPrivIBase(IntuitionBase)->DoubleClickButton = MENUDOWN;
1021 else
1023 GetPrivIBase(IntuitionBase)->DoubleClickCounter ++;
1026 else
1028 GetPrivIBase(IntuitionBase)->DoubleClickButton = MENUDOWN;
1029 GetPrivIBase(IntuitionBase)->DoubleClickCounter = 0;
1032 /* update last click time for doubleclicktofront */
1033 GetPrivIBase(IntuitionBase)->LastClickSecs = ie->ie_TimeStamp.tv_secs;
1034 GetPrivIBase(IntuitionBase)->LastClickMicro = ie->ie_TimeStamp.tv_micro;
1036 #ifdef SKINS
1038 ULONG result;
1040 if ((result = RunHotkeys(ie,IntuitionBase)))
1042 if (result == RUNHOTREUSE)
1044 *reuse_event = TRUE;
1046 else
1048 *keep_event = FALSE;
1050 break;
1052 w = IntuitionBase->ActiveWindow;
1054 #endif
1056 #ifdef SKINS
1057 if ((!MENUS_ACTIVE) && (!gadget) && (!(iihdata->ActQualifier & (IEQUALIFIER_LEFTBUTTON|IEQUALIFIER_MIDBUTTON))))
1059 struct Gadget *gad;
1060 struct GadgetInfo ginf;
1061 ULONG hit;
1062 struct Window *wind = FindActiveWindow(0, screen, &hit,IntuitionBase);
1064 if (wind)
1066 gad = FindGadget (screen,
1067 hit ? 0 : wind,0,
1068 IntuitionBase->ActiveScreen->MouseX,
1069 IntuitionBase->ActiveScreen->MouseY,
1070 &ginf, TRUE, IntuitionBase);
1072 if (gad && ((gad->GadgetType & GTYP_SYSTYPEMASK) == GTYP_WDEPTH))
1074 CreateSmallMenuTask(wind,SMALLMENU_TYPE_WINDOWDEPTH,IntuitionBase);
1075 *keep_event = FALSE;
1076 break;
1079 if (gad && ((gad->GadgetType & GTYP_SYSTYPEMASK) == GTYP_SDEPTH))
1081 CreateSmallMenuTask(0,SMALLMENU_TYPE_SCREENDEPTH,IntuitionBase);
1082 *keep_event = FALSE;
1083 break;
1087 #endif
1089 if (w && !req && w->DMRequest && !(w->Flags & WFLG_RMBTRAP))
1091 if (!MENUS_ACTIVE &&
1092 DoubleClick(GetPrivIBase(IntuitionBase)->DMStartSecs,
1093 GetPrivIBase(IntuitionBase)->DMStartMicro,
1094 ie->ie_TimeStamp.tv_secs,
1095 ie->ie_TimeStamp.tv_micro))
1097 if (w->IDCMPFlags & IDCMP_REQVERIFY)
1099 ih_fire_intuimessage(w,
1100 IDCMP_REQVERIFY,
1101 MENUHOT,
1102 NULL,
1103 IntuitionBase);
1105 else if (Request(w->DMRequest, w))
1107 req = w->DMRequest;
1109 ih_fire_intuimessage(w,
1110 IDCMP_REQSET,
1113 IntuitionBase);
1115 *keep_event = FALSE;
1116 break;
1119 GetPrivIBase(IntuitionBase)->DMStartSecs = ie->ie_TimeStamp.tv_secs;
1120 GetPrivIBase(IntuitionBase)->DMStartMicro = ie->ie_TimeStamp.tv_micro;
1123 if (w && !gadget)
1125 if (!(w->Flags & WFLG_RMBTRAP) && !req)
1127 struct IntScreen *scr = GetPrivScreen(w->WScreen);
1128 struct Window *w1;
1129 ULONG lock;
1130 BOOL mouseon = TRUE;
1132 scr->MenuVerifyMsgCount = 0;
1134 if (w->MouseX < 0 || w->MouseY < 0) mouseon = FALSE;
1135 if (w->MouseX > w->Width || w->MouseY > w->Height) mouseon = FALSE;
1137 if (w->IDCMPFlags & IDCMP_MENUVERIFY && (!(IW(w)->specialflags & SPFLAG_IAMDEAD)))
1139 ih_fire_intuimessage(w,
1140 IDCMP_MENUVERIFY,
1141 mouseon ? MENUHOT : MENUWAITING,
1143 IntuitionBase);
1144 scr->MenuVerifyMsgCount++;
1147 lock = LockIBase(0);
1149 for (w1 = scr->Screen.FirstWindow; w1; w1 = w1->NextWindow)
1151 if ((w1->IDCMPFlags & IDCMP_MENUVERIFY) && (w1 != w) && (!(IW(w)->specialflags & SPFLAG_IAMDEAD)))
1153 ih_fire_intuimessage(w1,
1154 IDCMP_MENUVERIFY,
1155 MENUWAITING,
1157 IntuitionBase);
1158 ++scr->MenuVerifyMsgCount;
1162 UnlockIBase(lock);
1164 /* FIXME: when a window is opened with IDCMP_MENUVERIFY
1165 * (or this event is requested via ModifyIDCMP), and a
1166 * verify operation is pending, the window should get
1167 * a verify message too. Oh well.
1170 if (scr->MenuVerifyMsgCount)
1172 GetPrivIBase(IntuitionBase)->MenuVerifyScreen = scr;
1173 scr->MenuVerifyActiveWindow = w;
1174 scr->MenuVerifyTimeOut = 2;
1175 scr->MenuVerifySeconds = IntuitionBase->Seconds;
1176 scr->MenuVerifyMicros = IntuitionBase->Micros;
1178 else if (FireMenuMessage(MMCODE_START, w, NULL/*ie*/, IntuitionBase))
1180 /* This lock will be released only when the user is
1181 done with menus = when IECLASS_MENU + IESUBCLASS_MENUSTOP
1182 event arrives (generated by MenuHandler task) */
1184 ObtainSemaphore(&GetPrivIBase(IntuitionBase)->MenuLock);
1185 iihdata->MenuWindow = w;
1186 MENUS_ACTIVE = TRUE;
1190 /* fall through */
1192 case MENUUP:
1193 case MIDDLEDOWN:
1194 case MIDDLEUP:
1196 switch(ie->ie_Code) {
1197 case MENUUP:
1198 iihdata->ActQualifier &= ~IEQUALIFIER_RBUTTON;
1199 if (GetPrivIBase(IntuitionBase)->MenuVerifyScreen)
1201 struct Window *w1;
1202 struct IntScreen *scr = GetPrivIBase(IntuitionBase)->MenuVerifyScreen;
1203 ULONG lock = LockIBase(0);
1205 for (w1 = scr->Screen.FirstWindow; w1; w1 = w1->NextWindow)
1207 if (w1->IDCMPFlags & IDCMP_MENUVERIFY && w1->IDCMPFlags & IDCMP_MOUSEBUTTONS)
1209 ih_fire_intuimessage(w1,
1210 IDCMP_MOUSEBUTTONS,
1211 MENUUP,
1213 IntuitionBase);
1217 UnlockIBase(lock);
1219 /* FIXME: when the active window replies the verifymessage,
1220 * it should get a IDCMP_MENUPICK/MENUNULL message.
1222 GetPrivIBase(IntuitionBase)->MenuVerifyScreen = NULL;
1223 scr->MenuVerifyActiveWindow = NULL;
1224 scr->MenuVerifyMsgCount = 0;
1225 scr->MenuVerifyTimeOut = 0;
1226 scr->MenuVerifySeconds = 0;
1227 scr->MenuVerifyMicros = 0;
1229 break;
1231 case MIDDLEDOWN:
1232 iihdata->ActQualifier |= IEQUALIFIER_MIDBUTTON;
1233 if (DoubleClick(GetPrivIBase(IntuitionBase)->LastClickSecs,GetPrivIBase(IntuitionBase)->LastClickMicro,
1234 ie->ie_TimeStamp.tv_secs,ie->ie_TimeStamp.tv_micro))
1236 if (GetPrivIBase(IntuitionBase)->DoubleClickButton != MIDDLEDOWN)
1238 GetPrivIBase(IntuitionBase)->DoubleClickCounter = 0;
1239 GetPrivIBase(IntuitionBase)->DoubleClickButton = MIDDLEDOWN;
1240 } else
1241 GetPrivIBase(IntuitionBase)->DoubleClickCounter ++;
1242 } else {
1243 GetPrivIBase(IntuitionBase)->DoubleClickButton = MIDDLEDOWN;
1244 GetPrivIBase(IntuitionBase)->DoubleClickCounter = 0;
1246 /* update last click time for doubleclicktofront */
1247 GetPrivIBase(IntuitionBase)->LastClickSecs = ie->ie_TimeStamp.tv_secs;
1248 GetPrivIBase(IntuitionBase)->LastClickMicro = ie->ie_TimeStamp.tv_micro;
1249 break;
1251 case MIDDLEUP:
1252 iihdata->ActQualifier &= ~IEQUALIFIER_MIDBUTTON;
1253 break;
1256 #ifdef SKINS
1257 iihdata->TitlebarAppearTime = 0;
1258 #endif
1259 if (MENUS_ACTIVE)
1261 FireMenuMessage(MMCODE_EVENT, 0, ie, IntuitionBase);
1262 *keep_event = FALSE;
1263 break;
1266 #ifdef SKINS
1267 if (ie->ie_Code == MIDDLEDOWN)
1269 ULONG result;
1271 if ((result = RunHotkeys(ie,IntuitionBase)))
1273 if (result == RUNHOTREUSE)
1275 *reuse_event = TRUE;
1277 else
1279 *keep_event = FALSE;
1281 break;
1283 w = IntuitionBase->ActiveWindow;
1285 #endif
1286 if (gadget)
1288 if (IS_BOOPSI_GADGET(gadget))
1290 gadget = DoGPInput(gi, gadget, ie, GM_HANDLEINPUT, reuse_event, IntuitionBase);
1293 } /* if (there is an active gadget) */
1294 else if (w && (!req || req->Flags & NOISYREQ) && w != GetPrivScreen(w->WScreen)->MenuVerifyActiveWindow)
1296 ih_fire_intuimessage(w,
1297 IDCMP_MOUSEBUTTONS,
1298 ie->ie_Code,
1300 IntuitionBase);
1303 break; /* case MENUDOWN */
1305 case IECODE_NOBUTTON: /* MOUSEMOVE */
1307 struct Screen *scr;
1308 UWORD DWidth, DHeight;
1310 if (ie->ie_Qualifier & IEQUALIFIER_RELATIVEMOUSE) {
1311 //ULONG Thresh;
1313 /* Add delta information lost in previous mousemove event. See below. */
1314 iihdata->DeltaMouseX = ie->ie_X + iihdata->DeltaMouseX_Correction;
1315 iihdata->DeltaMouseY = ie->ie_Y + iihdata->DeltaMouseY_Correction;
1317 #define ACCELERATOR_THRESH 2
1318 #define ACCELERATOR_MULTI 2
1320 if (GetPrivIBase(IntuitionBase)->ActivePreferences->EnableCLI & MOUSE_ACCEL) {
1321 /* Acceleration */
1322 if (ABS(iihdata->DeltaMouseX) > ACCELERATOR_THRESH)
1323 iihdata->DeltaMouseX *= ACCELERATOR_MULTI;
1324 if (ABS(iihdata->DeltaMouseY) > ACCELERATOR_THRESH)
1325 iihdata->DeltaMouseY *= ACCELERATOR_MULTI;
1328 switch(GetPrivIBase(IntuitionBase)->ActivePreferences->PointerTicks) {
1329 case 0:
1330 iihdata->DeltaMouseX_Correction = 0;
1331 iihdata->DeltaMouseX_Correction = 0;
1332 break;
1334 default:
1335 /* Remember the delta information which gets lost because of division by PointerTicks.
1336 Will be added to prescaled deltas of next mousemove event. If this is not done, moving
1337 the mouse very slowly would cause it to not move at all */
1339 iihdata->DeltaMouseX_Correction = iihdata->DeltaMouseX % GetPrivIBase(IntuitionBase)->ActivePreferences->PointerTicks;
1340 iihdata->DeltaMouseY_Correction = iihdata->DeltaMouseY % GetPrivIBase(IntuitionBase)->ActivePreferences->PointerTicks;
1342 iihdata->DeltaMouseX /= GetPrivIBase(IntuitionBase)->ActivePreferences->PointerTicks;
1343 iihdata->DeltaMouseY /= GetPrivIBase(IntuitionBase)->ActivePreferences->PointerTicks;
1344 break;
1348 ie->ie_X = iihdata->DeltaMouseX + IntuitionBase->MouseX;
1349 ie->ie_Y = iihdata->DeltaMouseY + IntuitionBase->MouseY;
1350 } else {
1351 DEBUG_MOUSE(bug("[Inputhandler] Last mouse position: (%d, %d), new mouse position: (%d, %d)\n",
1352 IntuitionBase->MouseX, IntuitionBase->MouseY, ie->ie_X, ie->ie_Y));
1353 iihdata->DeltaMouseX = ie->ie_X - IntuitionBase->MouseX;
1354 iihdata->DeltaMouseY = ie->ie_Y - IntuitionBase->MouseY;
1355 DEBUG_MOUSE(bug("[InputHandler] Delta is (%d, %d)\n", iihdata->DeltaMouseX, iihdata->DeltaMouseY));
1358 /* Calculate current display size.
1359 It's determined by the first screen on this monitor.
1360 TODO: perhaps we should just ask display driver about its current display mode? */
1361 scr = FindFirstScreen(GetPrivIBase(IntuitionBase)->ActiveMonitor, IntuitionBase);
1362 if (scr)
1364 DWidth = scr->ViewPort.ColorMap->cm_vpe->DisplayClip.MaxX - scr->ViewPort.ColorMap->cm_vpe->DisplayClip.MinX + 1;
1365 DHeight = scr->ViewPort.ColorMap->cm_vpe->DisplayClip.MaxY - scr->ViewPort.ColorMap->cm_vpe->DisplayClip.MinY + 1;
1367 else
1369 /* If there's no active screen, we take 160x160 as a limit */
1370 DWidth = 160;
1371 DHeight = 160;
1374 scr = iihdata->ScreenDrag;
1375 if (scr) {
1376 WORD dx = iihdata->DeltaMouseX;
1377 WORD dy = iihdata->DeltaMouseY;
1378 WORD min, max, val;
1379 UWORD spFlags = GetPrivScreen(scr)->SpecialFlags;
1380 UWORD DragMode = GetPrivIBase(IntuitionBase)->IControlPrefs.ic_VDragModes[0];
1382 DEBUG_DRAG(bug("[InputHandler] Screen drag, delta is (%d, %d)\n", dx, dy));
1384 /* Restrict dragging to a physical display area if the driver does not allow composition or if the user wants it*/
1385 if (((spFlags & SF_HorCompose) != SF_HorCompose) || (DragMode & ICVDM_HBOUND)) {
1386 /* Calculate limits */
1387 if (scr->Width > DWidth) {
1388 min = DWidth - scr->Width;
1389 max = 0;
1390 } else {
1391 min = 0;
1392 max = DWidth - scr->Width;
1394 /* The purpose of the following complex check is to prevent jumping if the
1395 screen was positioned out of user drag limits by the program itself using
1396 ScreenPosition() or OpenScreen(). We apply restrictions in parts depending
1397 on the dragging direction.
1398 Maybe the user should also be able to drag the screen back off-display in such
1399 a case?
1400 Calculate the position we would go to */
1401 val = scr->LeftEdge + dx;
1402 /* Determine the direction */
1403 if ((dx < 0) && ((!(spFlags & SF_ComposeRight)) || (DragMode & ICVDM_LBOUND))) {
1404 /* Can we move at all in this direction ? */
1405 if (scr->LeftEdge > min) {
1406 /* If too far, restrict it */
1407 if (val < min)
1408 dx = min - scr->LeftEdge;
1409 } else
1410 /* Just don't move if we can't */
1411 dx = 0;
1412 } else if ((!(spFlags & SF_ComposeLeft)) || (DragMode & ICVDM_RBOUND)) {
1413 if (scr->LeftEdge < max) {
1414 if (val > max)
1415 dx = max - scr->LeftEdge;
1416 } else
1417 dx = 0;
1420 if (((spFlags & SF_VertCompose) != SF_VertCompose) || (DragMode & ICVDM_VBOUND)) {
1421 DEBUG_DRAG(bug("[Inputhandler] Restricting vertical drag\n"));
1422 DEBUG_DRAG(bug("[Inputhandler] Screen size: %d, display size: %d\n", scr->Height, DHeight));
1423 if (scr->Height > DHeight) {
1424 min = DHeight - scr->Height;
1425 max = 0;
1426 } else {
1427 min = 0;
1428 max = DHeight - scr->Height;
1430 DEBUG_DRAG(bug("[Inputhandler] Limits: min %d max %d\n", min, max));
1431 val = scr->TopEdge + dy;
1432 DEBUG_DRAG(bug("[Inputhandler] New position would be %d\n", val));
1433 if ((dy < 0) && ((!(spFlags & SF_ComposeBelow)) || (DragMode & ICVDM_TBOUND))) {
1434 if (scr->TopEdge > min) {
1435 if (val < min)
1436 dy = min - scr->TopEdge;
1437 } else
1438 dy = 0;
1439 } else if ((!(spFlags & SF_ComposeAbove)) || (DragMode & ICVDM_BBOUND)) {
1440 if (scr->TopEdge < max) {
1441 if (val > max)
1442 dy = max - scr->TopEdge;
1443 } else
1444 dy = 0;
1446 DEBUG_DRAG(bug("[Inputhandler] Restricted delta will be %d\n", dy));
1448 ScreenPosition(scr, SPOS_RELATIVE, dx, dy, 0, 0);
1451 /* Autoscroll the active screen */
1452 scr = IntuitionBase->ActiveScreen;
1453 if (scr && (scr->Flags & AUTOSCROLL) &&
1454 (GetPrivScreen(scr)->MonitorObject == GetPrivIBase(IntuitionBase)->ActiveMonitor))
1456 WORD xval = scr->LeftEdge;
1457 WORD yval = scr->TopEdge;
1458 WORD min;
1460 DEBUG_AUTOSCROLL(bug("[Inputhandler] Autoscroll screen 0x%p, event at (%d, %d)\n",
1461 scr, ie->ie_X, ie->ie_Y));
1463 if ((ie->ie_X < 0) || (ie->ie_X >= DWidth)) {
1464 DEBUG_AUTOSCROLL(bug("[InputHandler] X delta: %d pixels\n", iihdata->DeltaMouseX));
1465 xval -= iihdata->DeltaMouseX;
1467 if (ie->ie_X < 0) {
1468 if (xval > 0)
1469 xval = 0;
1470 } else if (ie->ie_X >= DWidth) {
1471 min = DWidth - scr->Width;
1472 if (xval < min)
1473 xval = min;
1477 if ((ie->ie_Y < 0) || (ie->ie_Y >= DHeight)) {
1478 yval -= iihdata->DeltaMouseY;
1480 if (ie->ie_Y < 0) {
1481 /* If screen is dragged down and user touched upper screen
1482 boundary, do nothing */
1483 if (scr->TopEdge >= 0)
1484 yval = scr->TopEdge;
1485 else
1486 /* If scrolled down screen is being scrolled up, make sure it
1487 does not go over 0 */
1488 if (yval > 0)
1489 yval = 0;
1490 } else if (ie->ie_Y >= DHeight) {
1491 min = DHeight - scr->Height;
1492 if (yval < min)
1493 yval = min;
1497 if ((xval != scr->LeftEdge) || (yval != scr->TopEdge))
1498 ScreenPosition(scr, SPOS_ABSOLUTE, xval, yval, 0, 0);
1501 /* Restrict mouse coordinates to the physical display area */
1502 if (ie->ie_X >= DWidth) ie->ie_X = DWidth - 1;
1503 if (ie->ie_Y >= DHeight) ie->ie_Y = DHeight - 1;
1504 if (ie->ie_X < 0) ie->ie_X = 0;
1505 if (ie->ie_Y < 0) ie->ie_Y = 0;
1507 #ifdef SKINS
1508 if (gadget == iihdata->MasterDragGadget) {
1509 struct gpInput gpi;
1510 ULONG retval;
1512 gpi.MethodID = GM_MOVETEST;
1513 gpi.gpi_GInfo = gi;
1514 gpi.gpi_Mouse.X = ie->ie_X - gi->gi_Window->WScreen->LeftEdge;
1515 gpi.gpi_Mouse.Y = ie->ie_Y - gi->gi_Window->WScreen->TopEdge;
1516 gpi.gpi_IEvent = ie;
1518 retval = Locked_DoMethodA(gi->gi_Window, gadget, (Msg)&gpi, IntuitionBase);
1519 if (retval == MOVETEST_ADJUSTPOS)
1521 ie->ie_X = gpi.gpi_Mouse.X + gi->gi_Window->WScreen->LeftEdge;
1522 ie->ie_Y = gpi.gpi_Mouse.Y + gi->gi_Window->WScreen->TopEdge;
1526 #endif
1527 /* Do Mouse Bounding - mouse will be most restrictive of screen size or mouse bounds */
1528 if (iihdata->MouseBoundsActiveFlag) {
1529 if (ie->ie_X < iihdata->MouseBoundsLeft)
1530 ie->ie_X = iihdata->MouseBoundsLeft;
1531 else if (ie->ie_X > iihdata->MouseBoundsRight)
1532 ie->ie_X = iihdata->MouseBoundsRight;
1534 if (ie->ie_Y < iihdata->MouseBoundsTop)
1535 ie->ie_Y = iihdata->MouseBoundsTop;
1536 else if (ie->ie_Y > iihdata->MouseBoundsBottom)
1537 ie->ie_Y = iihdata->MouseBoundsBottom;
1540 /* Prevent mouse going above all screens */
1541 scr = FindHighestScreen(IntuitionBase);
1542 if (scr) {
1543 if (ie->ie_Y < scr->TopEdge)
1544 ie->ie_Y = scr->TopEdge;
1547 /* Store new mouse coords. If a screen is being dragged, lock drag point */
1548 scr = iihdata->ScreenDrag;
1549 if (scr) {
1550 IntuitionBase->MouseX = scr->LeftEdge + iihdata->ScreenDragPointX;
1551 IntuitionBase->MouseY = scr->TopEdge + iihdata->ScreenDragPointY;
1552 } else {
1553 IntuitionBase->MouseX = ie->ie_X;
1554 IntuitionBase->MouseY = ie->ie_Y;
1556 notify_mousemove_screensandwindows(IntuitionBase);
1557 #if !SINGLE_SETPOINTERPOS_PER_EVENTLOOP
1558 MySetPointerPos(IntuitionBase);
1559 #else
1560 *call_setpointerpos = TRUE;
1561 #endif
1563 screen = FindActiveScreen(IntuitionBase); /* The mouse was moved, so current screen may have changed */
1565 #ifdef SKINS
1566 if (!gadget) {
1567 if (iihdata->TitlebarOnTop)
1569 if (screen->MouseY > screen->BarHeight && GetPrivScreen(screen)->SpecialFlags & SF_AppearingBar)
1571 iihdata->TitlebarOnTop = FALSE;
1572 iihdata->TitlebarAppearTime = 0;
1574 LOCK_REFRESH(screen);
1576 MoveLayer(0, screen->BarLayer, 0, -(screen->BarHeight + 1));
1577 CheckLayers(screen, IntuitionBase);
1579 UNLOCK_REFRESH(screen);
1582 else
1584 if (screen->MouseY == 0 && GetPrivScreen(screen)->SpecialFlags & SF_AppearingBar && !MENUS_ACTIVE && !(PeekQualifier() & (IEQUALIFIER_LEFTBUTTON|IEQUALIFIER_RBUTTON|IEQUALIFIER_MIDBUTTON)))
1586 if (!(iihdata->TitlebarAppearTime))
1588 iihdata->TitlebarAppearTime = ((UQUAD)ie->ie_TimeStamp.tv_secs) * 50;
1589 iihdata->TitlebarAppearTime += ie->ie_TimeStamp.tv_micro / 20000;
1592 else
1594 iihdata->TitlebarAppearTime = 0;
1598 #endif
1599 if (MENUS_ACTIVE) {
1600 FireMenuMessage(MMCODE_EVENT, 0, ie, IntuitionBase);
1601 *keep_event = FALSE;
1602 break;
1605 if (gadget) {
1606 *keep_event = FALSE;
1608 switch (gadget->GadgetType & GTYP_GTYPEMASK)
1610 case GTYP_BOOLGADGET:
1611 case 0: //fallback for sucky gadgets
1612 /* Must be a RELVERIFY gadget */
1614 BOOL inside;
1616 inside = InsideGadget(gi->gi_Screen,
1617 gi->gi_Window,
1618 gi->gi_Requester,
1619 gadget,
1620 gi->gi_Screen->MouseX,
1621 gi->gi_Screen->MouseY);
1623 if (inside != iihdata->MouseWasInsideBoolGadget) {
1624 iihdata->MouseWasInsideBoolGadget = inside;
1626 gadget->Flags ^= GFLG_SELECTED;
1627 RefreshBoolGadgetState(gadget, w, req, IntuitionBase);
1630 break;
1632 case GTYP_PROPGADGET:
1633 HandlePropMouseMove(gadget,
1635 req,
1636 w->MouseX - gi->gi_Domain.Left - GetGadgetLeft(gadget, gi->gi_Screen, gi->gi_Window, NULL),
1637 w->MouseY - gi->gi_Domain.Top - GetGadgetTop(gadget, gi->gi_Screen, gi->gi_Window, NULL),
1638 IntuitionBase);
1640 break;
1642 case GTYP_CUSTOMGADGET:
1643 gadget = DoGPInput(gi, gadget, ie, GM_HANDLEINPUT, reuse_event, IntuitionBase);
1644 break;
1646 } /* switch GadgetType */
1648 } /* if (a gadget is currently active) */
1650 *keep_event = FALSE;
1652 if (!w)
1653 break;
1655 if (IW(w)->helpflags & HELPF_GADGETHELP && (!(PeekQualifier() & (IEQUALIFIER_LEFTBUTTON|IEQUALIFIER_RBUTTON|IEQUALIFIER_MIDBUTTON)))) {
1656 struct Window *hw;
1657 struct Gadget *g;
1659 hw = FindActiveWindow(ie, screen, 0, IntuitionBase);
1661 if (hw != w &&
1662 (!hw || !(IW(w)->helpflags & HELPF_ISHELPGROUP) ||
1663 !(IW(hw)->helpflags & HELPF_ISHELPGROUP) ||
1664 IW(w)->helpgroup != IW(hw)->helpgroup))
1667 if (iihdata->LastHelpWindow)
1669 fire_intuimessage(w,
1670 IDCMP_GADGETHELP,
1672 NULL,
1673 IntuitionBase);
1675 iihdata->LastHelpGadget = NULL;
1676 iihdata->LastHelpWindow = NULL;
1677 iihdata->HelpGadgetFindTime = 0;
1680 else
1682 g = FindHelpGadget (hw,
1683 IntuitionBase->ActiveScreen->MouseX,
1684 IntuitionBase->ActiveScreen->MouseY,
1685 IntuitionBase);
1686 if (g && g != iihdata->LastHelpGadget)
1688 if (!iihdata->LastHelpGadget)
1690 iihdata->HelpGadgetFindTime = ((UQUAD)ie->ie_TimeStamp.tv_secs) * 50;
1691 iihdata->HelpGadgetFindTime += ie->ie_TimeStamp.tv_micro / 20000;
1692 } else {
1693 if (hw == iihdata->LastHelpWindow)
1695 iihdata->HelpGadgetFindTime = ((UQUAD)ie->ie_TimeStamp.tv_secs) * 50;
1696 iihdata->HelpGadgetFindTime += ie->ie_TimeStamp.tv_micro / 20000;
1697 iihdata->HelpGadgetFindTime += 25;//smaller delay
1701 else if (g != iihdata->LastHelpGadget ||
1702 hw != iihdata->LastHelpWindow)
1704 fire_intuimessage(hw,
1705 IDCMP_GADGETHELP,
1706 0, /* Don't know what it should be */
1708 IntuitionBase);
1711 iihdata->LastHelpGadget = g;
1712 iihdata->LastHelpWindow = hw;
1714 } else {
1715 iihdata->LastHelpGadget = NULL;
1716 iihdata->LastHelpWindow = NULL;
1717 iihdata->HelpGadgetFindTime = 0;
1720 if (!(w->IDCMPFlags & IDCMP_MOUSEMOVE))
1721 break;
1723 /* Send IDCMP_MOUSEMOVE if WFLG_REPORTMOUSE is set
1724 and/or active gadget has GACT_FOLLOWMOUSE set */
1726 /* jDc: do NOT send when sizegad is pressed */
1727 if (!(w->Flags & WFLG_REPORTMOUSE)) {
1728 if (!gadget)
1729 break;
1730 if (!(gadget->Activation & GACT_FOLLOWMOUSE))
1731 break;
1732 } else {
1733 if (gadget && (gadget->GadgetType & (GTYP_SIZING|GTYP_WDRAGGING)))
1734 break;
1737 orig_ie->ie_Class = IECLASS_RAWMOUSE;
1739 /* Limit the number of IDCMP_MOUSEMOVE messages sent to intuition.
1740 note that this comes after handling gadgets, because gadgets should get all events.
1743 if (IW(w)->num_mouseevents >= IW(w)->mousequeue) {
1744 BOOL old_msg_found = FALSE;
1746 /* Mouse Queue is full, so try looking for a not
1747 yet GetMsg()ed IntuiMessage in w->UserPort
1748 trying to modify that. */
1750 Forbid();
1751 if (w->UserPort)
1753 struct IntuiMessage *im;
1755 for (im = (struct IntuiMessage *)w->UserPort->mp_MsgList.lh_TailPred;
1756 im->ExecMessage.mn_Node.ln_Pred;
1757 im = (struct IntuiMessage *)im->ExecMessage.mn_Node.ln_Pred)
1759 if ((im->Class == IDCMP_MOUSEMOVE) &&
1760 (im->IDCMPWindow == w))
1762 im->Qualifier = iihdata->ActQualifier;
1764 if (w->IDCMPFlags & IDCMP_DELTAMOVE)
1766 im->MouseX = iihdata->DeltaMouseX;
1767 im->MouseY = iihdata->DeltaMouseY;
1769 else
1771 im->MouseX = w->MouseX;
1772 im->MouseY = w->MouseY;
1774 CurrentTime(&im->Seconds, &im->Micros);
1776 old_msg_found = TRUE;
1777 break;
1780 } /* if (w->UserPort) */
1781 Permit();
1783 /* no need to send a new message if we modified
1784 an existing one ... */
1786 if (old_msg_found) break;
1788 /* ... otherwise we are in a strange situation. The mouse
1789 queue is full, but we did not find an existing MOUSEMOVE
1790 imsg in w->UserPort. So the app probably has removed
1791 an imsg from the UserPort with GetMsg but we did not get
1792 the ReplyMsg, yet. In this case we do send a new message */
1794 HandleIntuiReplyPort(iihdata, IntuitionBase);
1798 /* MouseQueue is not full, so we can send a message. We increase
1799 IntWindow->num_mouseevents which will later be decreased after
1800 the Intuition InputHandler gets the ReplyMessage from the app
1801 and handles it in HandleIntuiReplyPort() */
1803 if (ih_fire_intuimessage(w, IDCMP_MOUSEMOVE, IECODE_NOBUTTON, w, IntuitionBase))
1804 IW(w)->num_mouseevents++;
1806 break;
1808 } /* case IECODE_NOBUTTON */
1809 } /* switch (ie->ie_Code) (what button was pressed ?) */
1811 return gadget;
1814 /****************************************************************************************/
1816 AROS_UFH2(struct InputEvent *, IntuiInputHandler,
1817 AROS_UFHA(struct InputEvent *, oldchain, A0),
1818 AROS_UFHA(struct IIHData *, iihdata, A1)
1821 AROS_USERFUNC_INIT
1823 struct InputEvent *ie, *orig_ie, *next_ie, stackie;
1824 struct Gadget *gadget = NULL;
1825 struct IntuitionBase *IntuitionBase = iihdata->IntuitionBase;
1826 struct Library *KeymapBase = GetPrivIBase(IntuitionBase)->KeymapBase;
1827 struct Screen *screen;
1828 //ULONG lock;
1829 struct GadgetInfo *gi = &iihdata->GadgetInfo;
1830 BOOL reuse_event, ie_used;
1831 struct Window *w;
1832 struct Requester *req;
1833 ULONG stitlebarhit = 0;
1834 #if 0 /* Toolbox is broken-as-designed */
1835 struct Window *toolbox;
1836 struct GadgetInfo *boxgi = &iihdata->BoxGadgetInfo;
1837 struct Gadget *boxgadget = NULL;
1838 #endif
1839 #if SINGLE_SETPOINTERPOS_PER_EVENTLOOP
1840 BOOL call_setpointerpos = FALSE;
1841 #endif
1843 D(bug("Inside intuition inputhandler, active window=%p\n", IntuitionBase->ActiveWindow));
1844 ObtainSemaphore(&GetPrivIBase(IntuitionBase)->InputHandlerLock);
1846 if (!iihdata->InputDeviceTask) iihdata->InputDeviceTask = FindTask(NULL);
1848 /* Then free generated InputEvents done in the previous round */
1850 FreeGeneratedInputEvents(iihdata);
1852 /* First handle IntuiMessages which were replied back to the IntuiReplyPort
1853 by the apps */
1855 HandleIntuiReplyPort(iihdata, IntuitionBase);
1857 /* Handle action messages */
1859 HandleIntuiActions(iihdata, IntuitionBase);
1861 /* Now handle the input events */
1863 ie = &stackie;
1864 reuse_event = FALSE;
1865 next_ie = oldchain;
1867 /* shut up the compiler */
1868 orig_ie = next_ie;
1869 ie_used = FALSE;
1871 gadget = iihdata->ActiveGadget;
1873 while (reuse_event || next_ie)
1875 struct Window *old_w;
1876 BOOL keep_event = TRUE;
1877 BOOL new_active_window = FALSE;
1878 Object *newmonitor = GetPrivIBase(IntuitionBase)->NewMonitor;
1880 /* Process hosted display activation event (if any).
1881 This is experimental. If this works badly, we'll possibly have to put it into
1882 input events queue */
1883 if (newmonitor) {
1884 DEBUG_MONITOR(bug("[Inputhandler] Activating monitor 0x%p\n", newmonitor));
1885 GetPrivIBase(IntuitionBase)->NewMonitor = NULL;
1886 ActivateMonitor(newmonitor, -1, -1, IntuitionBase);
1887 iihdata->SwitchedMonitor = TRUE;
1890 if (!reuse_event)
1892 *ie = *next_ie;
1893 orig_ie = next_ie;
1894 next_ie = ie->ie_NextEvent;
1895 ie_used = FALSE;
1898 D(bug("iih: Handling event of class %d, code %d\n", ie->ie_Class, ie->ie_Code));
1899 reuse_event = FALSE;
1901 /* If the monitor has been changed, this possibly happened because of mouse click in
1902 its display window. In such a case we have to update current mouse coordinates
1903 from the first absolute mouse event. Otherwise input will misbehave. */
1904 if (iihdata->SwitchedMonitor && (ie->ie_Class == IECLASS_RAWMOUSE)) {
1905 iihdata->SwitchedMonitor = FALSE;
1906 if (!(ie->ie_Qualifier & IEQUALIFIER_RELATIVEMOUSE)) {
1907 DEBUG_MONITOR(bug("[Inputhandler] Adjusting coordinates to (%d, %d)\n", ie->ie_X, ie->ie_Y));
1908 IntuitionBase->MouseX = ie->ie_X;
1909 IntuitionBase->MouseY = ie->ie_Y;
1910 notify_mousemove_screensandwindows(IntuitionBase);
1914 /* new event, we need to reset this */
1915 screen = FindActiveScreen(IntuitionBase);
1916 iihdata->ActEventTablet = 0;
1918 /* Set the timestamp in IntuitionBase */
1920 IntuitionBase->Seconds = ie->ie_TimeStamp.tv_secs;
1921 IntuitionBase->Micros = ie->ie_TimeStamp.tv_micro;
1923 #if 0 /* toolbox stuff disabled. broken. calling LockLayerinfo() for every event is broken. deadlocks */
1924 /* Use event to find the active window */
1926 toolbox = GetToolBoxWindow(ie, screen, IntuitionBase);
1928 if (toolbox)
1930 /* Do ToolBox Window Actions */
1931 /* ToolBox Windows supports only a subset of IECLASS Actions */
1932 switch (ie->ie_Class) {
1934 case IECLASS_RAWMOUSE:
1935 boxgadget = Process_RawMouse(ie, iihdata, screen, toolbox, boxgadget, boxgi, 0, FALSE, TRUE,
1936 orig_ie, &keep_event, &reuse_event,
1937 #if SINGLE_SETPOINTERPOS_PER_EVENTLOOP
1938 &call_setpointerpos,
1939 #endif
1940 IntuitionBase);
1941 break;
1943 } /* switch (ie->ie_Class) */
1944 } /* if (toolbox) */
1945 #endif
1947 w = IntuitionBase->ActiveWindow;
1949 if (!MENUS_ACTIVE && !SYSGADGET_ACTIVE)
1951 /* lock = LockIBase(0UL); */
1953 old_w = w;
1954 if (ie->ie_Class == IECLASS_RAWMOUSE && ie->ie_Code == SELECTDOWN)
1956 w = FindActiveWindow(ie, screen, &stitlebarhit, IntuitionBase);
1957 DEBUG_CLICK(bug("iih:New active window: %p\n", w));
1961 if ( w != old_w )
1963 if (w)
1965 DEBUG_WINDOW(bug("Activating new window (title %s)\n", w->Title ? w->Title : "<noname>"));
1967 DEBUG_WINDOW(bug("Window activated\n"));
1969 else
1971 DEBUG_WINDOW(bug("Making active window inactive. Now there's no active window\n"));
1973 new_active_window = TRUE;
1974 iihdata->NewActWindow = w;
1977 /* UnlockIBase(lock); */
1979 if (new_active_window)
1981 if (gadget && w &&
1982 (!(GetPrivScreen(w->WScreen)->MenuVerifyMsgCount)) &&
1983 (!(MENUS_ACTIVE)) && (!(SYSGADGET_ACTIVE)))
1985 switch (gadget->GadgetType & GTYP_GTYPEMASK)
1988 case GTYP_CUSTOMGADGET:
1990 struct gpGoInactive gpgi;
1992 gpgi.MethodID = GM_GOINACTIVE;
1993 gpgi.gpgi_GInfo = gi;
1994 gpgi.gpgi_Abort = 1;
1996 Locked_DoMethodA(gi->gi_Window, gadget, (Msg)&gpgi, IntuitionBase);
1997 break;
2000 case GTYP_STRGADGET:
2001 gadget->Flags &= ~GFLG_SELECTED;
2002 RefreshStrGadget(gadget, gi->gi_Window, gi->gi_Requester, IntuitionBase);
2003 break;
2005 case GTYP_BOOLGADGET:
2006 /* That a bool gadget is active here can only happen
2007 if user used LMB to activate gadget and LAMIGA + LALT
2008 to activate other window, or viceversa */
2009 /* The gadget must be a RELVERIFY one */
2010 if (!(gadget->Activation & GACT_TOGGLESELECT))
2012 BOOL inside;
2014 inside = InsideGadget(gi->gi_Screen, gi->gi_Window,
2015 gi->gi_Requester, gadget,
2016 gi->gi_Screen->MouseX, gi->gi_Screen->MouseY);
2018 if (inside)
2020 gadget->Flags &= ~GFLG_SELECTED;
2021 RefreshBoolGadgetState(gadget, gi->gi_Window,
2022 gi->gi_Requester, IntuitionBase);
2025 break;
2027 case GTYP_PROPGADGET:
2028 /* That a prop gadget is active here can only happen
2029 if user used LMB to activate gadget and LAMIGA + LALT
2030 to activate other window, or viceversa */
2032 HandlePropSelectUp(gadget, gi->gi_Window, NULL, IntuitionBase);
2033 if (gadget->Activation & GACT_RELVERIFY)
2035 ih_fire_intuimessage(gi->gi_Window,
2036 IDCMP_GADGETUP,
2038 gadget,
2039 IntuitionBase);
2041 break;
2043 } /* switch (gadget->GadgetType & GTYP_GTYPEMASK) */
2045 gadget->Activation &= ~GACT_ACTIVEGADGET;
2046 iihdata->ActiveGadget = NULL;
2047 gadget = NULL;
2050 /* ActivateWindow works if w = NULL */
2051 /* jacaDcaps: some gui toolkits (die reaction, die!) close the window opened by a boopsi gadget when
2052 it gets hit with lmb, so we need to check if the new active window does not go away by
2053 performing GM_GOINACTIVE on the gadget. NOTE: CloseWindow's part performed on input.device context
2054 clears the iihdata->NewActWindow if it's the actually closed one. */
2055 if (w == iihdata->NewActWindow)
2057 ActivateWindow(w);
2059 else
2061 w = IntuitionBase->ActiveWindow;
2062 new_active_window = FALSE;
2063 ie->ie_Class = IECLASS_NULL; //lose the event, otherwise the gadget will get activated again ;)
2066 iihdata->NewActWindow = 0;
2068 } /* if (new_active_window) */
2070 } /* if (!MENUS_ACTIVE) */
2072 req = NULL;
2073 if (w)
2075 req = w->FirstRequest;
2078 D(bug("[Inputhandler] Screen 0x%p Window 0x%p Requester 0x%p gadget 0x%p\n", screen, w, req, gadget));
2080 switch (ie->ie_Class) {
2081 case IECLASS_POINTERPOS:
2082 ie->ie_SubClass = IESUBCLASS_COMPATIBLE;
2083 /* fall through */
2085 case IECLASS_NEWPOINTERPOS:
2086 switch (ie->ie_SubClass)
2088 case IESUBCLASS_COMPATIBLE:
2089 ie->ie_Code = IECODE_NOBUTTON;
2090 break;
2092 case IESUBCLASS_PIXEL:
2094 struct IEPointerPixel *pp = ie->ie_EventAddress;
2096 ie->ie_X = pp->iepp_Position.X + pp->iepp_Screen->LeftEdge;
2097 ie->ie_Y = pp->iepp_Position.Y + pp->iepp_Screen->TopEdge;
2099 ActivateMonitor(GetPrivScreen(pp->iepp_Screen)->MonitorObject, ie->ie_X, ie->ie_Y, IntuitionBase);
2101 ie->ie_Class = IECLASS_RAWMOUSE; /* otherwise a lot of code would ignore this message */
2102 ie->ie_Code = IECODE_NOBUTTON;
2103 break;
2105 case IESUBCLASS_TABLET:
2107 //unsupported - does anything use it anyway? ;)
2109 ie->ie_Code = 0;
2110 break;
2112 case IESUBCLASS_NEWTABLET:
2114 struct IENewTablet *nt = (struct IENewTablet *)ie->ie_EventAddress;
2116 if (nt)
2118 iihdata->ActEventTablet = nt; //cache this
2119 ie->ie_X = (screen->Width * nt->ient_TabletX) / nt->ient_RangeX;
2120 ie->ie_Y = (screen->Height * nt->ient_TabletY) / nt->ient_RangeY;
2122 ie->ie_Class = IECLASS_RAWMOUSE;
2124 break;
2126 default:
2127 ie->ie_Code = 0;
2128 break;
2130 /* fall through */
2132 case IECLASS_RAWMOUSE:
2133 gadget = Process_RawMouse(ie, iihdata, screen, w, gadget, gi, stitlebarhit, new_active_window, FALSE,
2134 orig_ie, &keep_event, &reuse_event,
2135 #if SINGLE_SETPOINTERPOS_PER_EVENTLOOP
2136 &call_setpointerpos,
2137 #endif
2138 IntuitionBase);
2139 keep_event = TRUE;
2140 break;
2142 case IECLASS_RAWKEY:
2143 /* release events go only to gadgets and windows who
2144 have not set IDCMP_VANILLAKEY */
2146 DEBUG_HANDLER(dprintf("Handler: IECLASS_RAWKEY\n"));
2147 DEBUG_KEY(dprintf("Handler: Qual 0x%lx\n",iihdata->ActQualifier));
2149 iihdata->ActQualifier &= ~(KEY_QUALIFIERS | IEQUALIFIER_REPEAT);
2150 iihdata->ActQualifier |= (ie->ie_Qualifier & (KEY_QUALIFIERS | IEQUALIFIER_REPEAT));
2152 DEBUG_KEY(dprintf("Handler: real Qual 0x%lx\n",iihdata->ActQualifier));
2154 /* Keyboard mouse emulation and screen switching */
2157 UWORD code = ie->ie_Code & ~IECODE_UP_PREFIX;
2158 DEBUG_KEY(dprintf("Handler: code 0x%lx\n",code));
2160 /* Left Amiga + N/M screen switching shortcut */
2161 if ((ie->ie_Qualifier & IEQUALIFIER_LCOMMAND) && (code == RAWKEY_N || code == RAWKEY_M)) {
2162 if (!(ie->ie_Qualifier & IEQUALIFIER_REPEAT) && !(ie->ie_Code & IECODE_UP_PREFIX)) {
2163 if (code == RAWKEY_N)
2164 WBenchToFront();
2165 else if (code == RAWKEY_M)
2166 ScreenToBack(IntuitionBase->FirstScreen);
2168 keep_event = FALSE;
2169 break;
2172 /* Mouse button emulation: LALT + LAMIGA = LBUTTON, RALT + RAMIGA = RBUTTON */
2173 if ((code == RAWKEY_LAMIGA) ||
2174 (code == RAWKEY_LALT) ||
2175 (code == RAWKEY_RAMIGA) ||
2176 (code == RAWKEY_RALT))
2178 DEBUG_KEY(dprintf("Handler: KeyMouseEmul\n"));
2179 iihdata->PrevKeyMouseState = iihdata->ActKeyMouseState;
2180 iihdata->ActKeyMouseState = 0;
2181 if ((ie->ie_Qualifier & (IEQUALIFIER_LCOMMAND | IEQUALIFIER_LALT)) == (IEQUALIFIER_LCOMMAND | IEQUALIFIER_LALT))
2183 iihdata->ActKeyMouseState |= IEQUALIFIER_LEFTBUTTON;
2185 if ((ie->ie_Qualifier & (IEQUALIFIER_RCOMMAND | IEQUALIFIER_RALT)) == (IEQUALIFIER_RCOMMAND | IEQUALIFIER_RALT))
2187 iihdata->ActKeyMouseState |= IEQUALIFIER_RBUTTON;
2190 if ((iihdata->ActKeyMouseState & IEQUALIFIER_LEFTBUTTON) != (iihdata->PrevKeyMouseState & IEQUALIFIER_LEFTBUTTON))
2192 orig_ie->ie_Class = IECLASS_RAWMOUSE;
2193 orig_ie->ie_SubClass = 0;
2194 orig_ie->ie_Code = (iihdata->ActKeyMouseState & IEQUALIFIER_LEFTBUTTON) ? IECODE_LBUTTON : IECODE_LBUTTON | IECODE_UP_PREFIX;
2195 orig_ie->ie_X = 0;
2196 orig_ie->ie_Y = 0;
2197 *ie = *orig_ie;
2199 reuse_event = TRUE;
2200 break;
2203 if ((iihdata->ActKeyMouseState & IEQUALIFIER_RBUTTON) != (iihdata->PrevKeyMouseState & IEQUALIFIER_RBUTTON))
2205 orig_ie->ie_Class = IECLASS_RAWMOUSE;
2206 orig_ie->ie_SubClass = 0;
2207 orig_ie->ie_Code = (iihdata->ActKeyMouseState & IEQUALIFIER_RBUTTON) ? IECODE_RBUTTON : IECODE_RBUTTON | IECODE_UP_PREFIX;
2208 orig_ie->ie_X = 0;
2209 orig_ie->ie_Y = 0;
2210 *ie = *orig_ie;
2212 reuse_event = TRUE;
2213 break;
2216 } /* if key is one of LAMIGA/LALT/RAMIGA/RALT */
2218 if ((iihdata->ActQualifier & (IEQUALIFIER_LCOMMAND | IEQUALIFIER_RCOMMAND)) &&
2219 ((ie->ie_Code == RAWKEY_UP) ||
2220 (ie->ie_Code == RAWKEY_DOWN) ||
2221 (ie->ie_Code == RAWKEY_LEFT) ||
2222 (ie->ie_Code == RAWKEY_RIGHT)))
2224 static BYTE const xmap[] = { 0, 0, 1, -1};
2225 static BYTE const ymap[] = {-1, 1, 0, 0};
2226 WORD shift;
2228 shift = (iihdata->ActQualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) ? 40 : 1;
2230 /* Mouse Move Emulation */
2232 orig_ie->ie_Class = IECLASS_RAWMOUSE;
2233 orig_ie->ie_SubClass = 0;
2234 orig_ie->ie_Code = IECODE_NOBUTTON;
2235 orig_ie->ie_Qualifier = IEQUALIFIER_RELATIVEMOUSE;
2236 orig_ie->ie_X = xmap[code - RAWKEY_UP] * shift;
2237 orig_ie->ie_Y = ymap[code - RAWKEY_UP] * shift;
2239 *ie = *orig_ie;
2240 reuse_event = TRUE;
2241 break;
2244 } /**/
2246 /* End Keyboard mouse emulation */
2248 if (MENUS_ACTIVE)
2250 DEBUG_KEY(dprintf("Handler: FireMenuMessage\n"));
2251 FireMenuMessage(MMCODE_EVENT, 0, ie, IntuitionBase);
2252 keep_event = FALSE;
2253 break;
2256 /* Hotkeys processing */
2257 #ifdef SKINS
2259 ULONG result;
2261 if (!(ie->ie_Code & IECODE_UP_PREFIX))
2262 if ((result = RunHotkeys(ie,IntuitionBase)))
2264 if (result == RUNHOTREUSE)
2266 reuse_event = TRUE;
2268 else
2270 keep_event = FALSE;
2272 break;
2274 w = IntuitionBase->ActiveWindow;
2276 #endif
2278 if ( keep_event &&
2279 ((!(ie->ie_Code & IECODE_UP_PREFIX)) ||
2280 gadget ||
2281 (w && ((w->IDCMPFlags & IDCMP_VANILLAKEY) == 0)) ))
2283 if (gadget)
2285 keep_event = FALSE;
2287 DEBUG_KEY(dprintf("Handler: Gadget 0x%lx active\n",gadget));
2288 DEBUG_KEY(dprintf("Handler: GadgetID 0x%lx UserData 0x%lx\n",
2289 gadget->GadgetID,
2290 gadget->UserData));
2291 DEBUG_KEY(dprintf("Handler: GadgetType 0x%lx Flags 0x%lx Activation 0x%lx\n",
2292 gadget->GadgetType,
2293 gadget->Flags,
2294 gadget->Activation));
2295 DEBUG_KEY(dprintf("Handler: MoreFlags 0x%lx\n",
2296 ((struct ExtGadget*)gadget)->MoreFlags));
2298 switch (gadget->GadgetType & GTYP_GTYPEMASK)
2300 case GTYP_STRGADGET:
2302 UWORD imsgcode;
2303 ULONG ret = HandleStrInput(gadget, gi, ie, &imsgcode,
2304 IntuitionBase);
2306 DEBUG_KEY(dprintf("Handler: Key GTYP_STRGADGET ret 0x%lx\n",ret));
2307 if (ret & (SGA_END | SGA_NEXTACTIVE | SGA_PREVACTIVE))
2309 if (gadget->Activation & GACT_RELVERIFY)
2311 DEBUG_KEY(dprintf("Handler: GACT_RELVERIFY\n"));
2312 ih_fire_intuimessage(w,
2313 IDCMP_GADGETUP,
2314 imsgcode,
2315 gadget,
2316 IntuitionBase);
2318 if (req && gadget->Activation & GACT_ENDGADGET)
2320 DEBUG_KEY(dprintf("Handler: GACT_ENDGADGET\n"));
2321 EndRequest(req, w);
2323 req = w->FirstRequest;
2324 ret = 0;
2328 if ((gadget->Flags & GFLG_TABCYCLE) && (ret & SGA_NEXTACTIVE))
2330 gadget = FindCycleGadget(w, req, gadget, GMR_NEXTACTIVE);
2331 DEBUG_KEY(dprintf("Handler: TabCycle next gadget 0x%lx\n",gadget));
2333 else if ((gadget->Flags & GFLG_TABCYCLE) && (ret & SGA_PREVACTIVE))
2335 gadget = FindCycleGadget(w, req, gadget, GMR_PREVACTIVE);
2336 DEBUG_KEY(dprintf("Handler: TabCycle prev gadget 0x%lx\n",gadget));
2338 else
2340 gadget = NULL;
2343 if (gadget)
2345 gadget = DoActivateGadget(w, req, gadget, IntuitionBase);
2348 } /* if (ret & (SGA_END | SGA_NEXTACTIVE | SGA_PREVACTIVE)) */
2350 break;
2353 case GTYP_CUSTOMGADGET:
2354 DEBUG_KEY(dprintf("Handler: GTYP_CUSTOMGADGET\n"));
2355 DEBUG_KEY(dprintf("Handler: send GM_HANDLEINPUT\n"));
2356 gadget = DoGPInput(gi,
2357 gadget,
2359 GM_HANDLEINPUT,
2360 &reuse_event,
2361 IntuitionBase);
2362 DEBUG_KEY(dprintf("Handler: reuse %ld\n",reuse_event));
2363 break;
2365 } /* switch (gadget type) */
2367 } /* if (a gadget is currently active) */
2368 else if (w && (!req || req->Flags & NOISYREQ))
2370 BOOL menushortcut = FALSE;
2372 DEBUG_KEY(dprintf("Handler: No Gadget active\n"));
2373 DEBUG_KEY(dprintf("Handler: Qualifier 0x%lx WinFlags 0x%lx IDCMP 0x%lx\n",ie->ie_Qualifier,w->Flags,w->IDCMPFlags));
2375 if ((ie->ie_Qualifier & IEQUALIFIER_RCOMMAND) &&
2376 (!(w->Flags & WFLG_RMBTRAP)) &&
2377 (w->IDCMPFlags & IDCMP_MENUPICK))
2379 struct Menu *strip = 0;
2381 DEBUG_KEY(dprintf("Handler: MenuKey\n"));
2382 ObtainSemaphore(&GetPrivIBase(IntuitionBase)->MenuLock);
2384 strip = w->MenuStrip;
2386 if (((struct IntWindow *)w)->menulendwindow)
2388 strip = ((struct IntWindow *)w)->menulendwindow->MenuStrip;
2391 DEBUG_KEY(dprintf("Handler: MenuStrip 0x%lx\n",strip));
2392 if (strip)
2394 UBYTE key;
2396 if (MapRawKey(ie, &key, 1, NULL) == 1)
2398 UWORD menucode;
2400 menucode = FindMenuShortCut(strip, key, TRUE, IntuitionBase);
2402 DEBUG_KEY(dprintf("Handler: menucode 0x%lx\n",menucode));
2404 if (menucode != MENUNULL)
2406 DEBUG_KEY(dprintf("Handler: build menuevent\n"));
2407 ie->ie_Class = IECLASS_MENU;
2408 ie->ie_SubClass = IESUBCLASS_MENUSTOP;
2409 ie->ie_EventAddress = w;
2410 ie->ie_Code = menucode;
2412 reuse_event = TRUE;
2413 menushortcut = TRUE;
2415 MENUS_ACTIVE = TRUE;
2416 iihdata->MenuWindow = w;
2419 else
2421 DEBUG_KEY(dprintf("Handler: MapRawKey failed\n"));
2424 if (!menushortcut) /* !! */
2425 ReleaseSemaphore(&GetPrivIBase(IntuitionBase)->MenuLock);
2427 } /* if could be a menu short cut */
2428 else
2429 if ((ie->ie_Qualifier & IEQUALIFIER_RCOMMAND) &&
2430 (!(w->IDCMPFlags & IDCMP_MENUPICK)))
2432 struct Menu *strip = 0;
2433 struct Window *window = w;
2435 /* not sure here about RMBTRAP */
2436 DEBUG_KEY(dprintf("Handler: no idcmp, create a MENULIST idcmp\n"));
2438 ObtainSemaphore(&GetPrivIBase(IntuitionBase)->MenuLock);
2440 strip = w->MenuStrip;
2442 if (((struct IntWindow *)w)->menulendwindow)
2444 strip = ((struct IntWindow *)w)->menulendwindow->MenuStrip;
2445 window = ((struct IntWindow *)w)->menulendwindow;
2448 DEBUG_KEY(dprintf("Handler: MenuStrip 0x%lx\n",strip));
2449 if (strip)
2451 UBYTE key;
2453 if (MapRawKey(ie, &key, 1, NULL) == 1)
2455 UWORD menucode;
2457 menucode = FindMenuShortCut(strip, key, TRUE, IntuitionBase);
2459 DEBUG_KEY(dprintf("Handler: menucode 0x%lx\n",menucode));
2461 if (menucode != MENUNULL)
2463 DEBUG_KEY(dprintf("Handler: build menuevent\n"));
2464 ih_fire_intuimessage(window,
2465 IDCMP_MENUPICK,
2466 menucode,
2467 ie->ie_position.ie_addr, /* ie_dead.ie_prev[1|2]Down[Code|Qual]. 64 bit machines!? */
2468 IntuitionBase);
2469 keep_event = FALSE;
2470 menushortcut = TRUE;
2473 else
2475 DEBUG_KEY(dprintf("Handler: MapRawKey failed\n"));
2478 ReleaseSemaphore(&GetPrivIBase(IntuitionBase)->MenuLock);
2479 } /* if could be a menu short but current window has no idcmp cut */
2481 if (menushortcut)
2483 DEBUG_KEY(dprintf("Handler: menu shortcut..break\n"));
2484 break;
2487 /* This is a regular RAWKEY event (no gadget taking care
2488 of it...). */
2490 if (iihdata->ActQualifier & IEQUALIFIER_REPEAT)
2492 /* don't send repeat key events if repeatqueue is full */
2493 if (IW(w)->num_repeatevents >= IW(w)->repeatqueue)
2495 DEBUG_KEY(dprintf("Handler: RepeatEvents full..don't send more\n"));
2496 break;
2500 if (w->IDCMPFlags & IDCMP_VANILLAKEY)
2502 UBYTE keyBuffer;
2504 DEBUG_KEY(dprintf("Handler: VANILLAKEY\n"));
2505 // DEBUG_KEY(dprintf("Handler: MapRawKey ie 0x%lx KeyMapBase 0x%lx IntutionBase 0x%lx\n",ie,KeymapBase,IntuitionBase));
2507 if (MapRawKey(ie, &keyBuffer, 1, NULL) == 1)
2509 DEBUG_KEY(dprintf("Handler: send VANILLAKEY msg\n"));
2510 ih_fire_intuimessage(w,
2511 IDCMP_VANILLAKEY,
2512 keyBuffer,
2513 ie->ie_position.ie_addr, /* ie_dead.ie_prev[1|2]Down[Code|Qual]. 64 bit machines!? */
2514 IntuitionBase);
2515 DEBUG_KEY(dprintf("Handler: done\n"));
2516 break;
2519 /* If the event mapped to more than one byte, it is not
2520 a legal VANILLAKEY, so we send it as the original
2521 RAWKEY event. */
2525 if (w->IDCMPFlags & IDCMP_RAWKEY)
2527 DEBUG_KEY(dprintf("Handler: send IDCMP_RAWKEY Qual 0x%lx Code 0x%lx addr 0x%lx Event\n",
2528 ie->ie_Qualifier,ie->ie_Code,ie->ie_position.ie_addr));
2529 ih_fire_intuimessage(w,
2530 IDCMP_RAWKEY,
2531 ie->ie_Code,
2532 ie->ie_position.ie_addr, /* ie_dead.ie_prev[1|2]Down[Code|Qual]. 64 bit machine!? */
2533 IntuitionBase);
2534 keep_event = FALSE;
2537 DEBUG_KEY(dprintf("Handler: done\n"));
2538 } /* regular RAWKEY */
2541 break; /* case IECLASS_RAWKEY */
2543 case IECLASS_TIMER:
2544 if (iihdata->MouseBoundsKillTimer)
2546 iihdata->MouseBoundsKillTimer--;
2547 if (iihdata->MouseBoundsKillTimer == 0)
2549 iihdata->MouseBoundsActiveFlag = FALSE;
2553 if (GetPrivIBase(IntuitionBase)->PointerDelay)
2555 ULONG lock = LockIBase(0);
2557 if (--GetPrivIBase(IntuitionBase)->PointerDelay == 0)
2559 struct SharedPointer *shared_pointer;
2560 struct Window *window = IntuitionBase->ActiveWindow;
2561 struct IntScreen *scr;
2562 Object *pointer = ((struct IntWindow *)window)->pointer;
2564 DEBUG_POINTER(dprintf("InputHandler: PointerDelay\n"));
2565 DEBUG_POINTER(dprintf("InputHandler: Pointer 0x%lx\n",
2566 pointer));
2568 if (window)
2570 DEBUG_POINTER(dprintf("InputHandler: Window 0x%lx\n",
2571 window));
2572 scr = GetPrivScreen(window->WScreen);
2573 if (scr)
2575 DEBUG_POINTER(dprintf("InputHandler: Screen 0x%lx\n",
2576 scr));
2577 if (pointer == NULL)
2579 pointer = GetPrivIBase(IntuitionBase)->DefaultPointer;
2582 if (((struct IntWindow *)window)->busy)
2584 pointer = GetPrivIBase(IntuitionBase)->BusyPointer;
2587 GetAttr(POINTERA_SharedPointer, pointer, (IPTR *) &shared_pointer);
2589 DEBUG_POINTER(dprintf("InputHandler: scr 0x%lx pointer 0x%lx shared_pointer 0x%lx\n",
2590 scr, pointer, shared_pointer));
2591 DEBUG_POINTER(dprintf("InputHandler: sprite 0x%lx\n",
2592 shared_pointer->sprite));
2594 if (DoMethod(scr->MonitorObject, MM_SetPointerShape, shared_pointer))
2596 ObtainSharedPointer(shared_pointer, IntuitionBase);
2597 ReleaseSharedPointer(scr->Pointer, IntuitionBase);
2598 scr->Pointer = shared_pointer;
2599 if (window)
2601 window->XOffset = shared_pointer->xoffset;
2602 window->YOffset = shared_pointer->yoffset;
2605 else
2607 DEBUG_POINTER(dprintf("InputHandler: can't set pointer.\n"));
2610 else
2612 DEBUG_POINTER(dprintf("InputHandler: no screen.\n"));
2615 else
2617 DEBUG_POINTER(dprintf("InputHandler: no window.\n"));
2621 UnlockIBase(lock);
2624 if (GetPrivIBase(IntuitionBase)->MenuVerifyScreen)
2626 struct IntScreen *scr = GetPrivIBase(IntuitionBase)->MenuVerifyScreen;
2628 if ((--scr->MenuVerifyTimeOut) <= 0)
2630 struct InputEvent ie;
2632 /* currently we ONLY need the menu open time ! */
2633 ie.ie_TimeStamp.tv_secs = IntuitionBase->Seconds;
2634 ie.ie_TimeStamp.tv_micro = IntuitionBase->Micros;
2636 if (FireMenuMessage(MMCODE_START, scr->MenuVerifyActiveWindow, &ie, IntuitionBase))
2638 /* This lock will be released only when the user is
2639 done with menus = when IECLASS_MENU + IESUBCLASS_MENUSTOP
2640 event arrives (generated by MenuHandler task) */
2642 ObtainSemaphore(&GetPrivIBase(IntuitionBase)->MenuLock);
2643 iihdata->MenuWindow = scr->MenuVerifyActiveWindow;
2644 MENUS_ACTIVE = TRUE;
2647 scr->MenuVerifyActiveWindow = NULL;
2648 scr->MenuVerifyTimeOut = 0;
2649 scr->MenuVerifyMsgCount = 0;
2650 scr->MenuVerifySeconds = 0;
2651 scr->MenuVerifyMicros = 0;
2652 GetPrivIBase(IntuitionBase)->MenuVerifyScreen = NULL;
2655 else if (MENUS_ACTIVE)
2657 FireMenuMessage(MMCODE_EVENT, 0, ie, IntuitionBase);
2658 keep_event = FALSE;
2659 break;
2662 #ifdef SKINS
2663 if (screen->MouseY <= screen->BarHeight && GetPrivScreen(screen)->SpecialFlags & SF_AppearingBar && !iihdata->TitlebarOnTop && iihdata->TitlebarAppearTime)
2665 UQUAD currenttime = (((UQUAD)ie->ie_TimeStamp.tv_secs) * 50) + (UQUAD)(ie->ie_TimeStamp.tv_micro / 20000);
2666 if (currenttime >= iihdata->TitlebarAppearTime + 10)
2668 iihdata->TitlebarOnTop = TRUE;
2669 iihdata->TitlebarAppearTime = 0;
2671 LOCK_REFRESH(screen);
2673 MoveLayer(0, screen->BarLayer, 0, screen->BarHeight + 1);
2674 UpfrontLayer(0, screen->BarLayer);
2675 CheckLayers(screen, IntuitionBase);
2677 UNLOCK_REFRESH(screen);
2680 #endif
2683 UQUAD currenttime = (((UQUAD)ie->ie_TimeStamp.tv_secs) * 50) + (UQUAD)(ie->ie_TimeStamp.tv_micro / 20000);
2684 #define SECONDS(x) (x*50)
2685 if (iihdata->HelpGadgetFindTime && (currenttime >= iihdata->HelpGadgetFindTime + SECONDS(1)))
2687 struct Gadget *lhg = iihdata->LastHelpGadget;
2688 fire_intuimessage(iihdata->LastHelpWindow,
2689 IDCMP_GADGETHELP,
2690 lhg ? lhg->GadgetID : 0, /* Don't know what it should be */
2691 lhg,
2692 IntuitionBase);
2693 iihdata->HelpGadgetFindTime = 0;
2697 if (gadget)
2699 if (IS_BOOPSI_GADGET(gadget))
2701 gadget = DoGPInput(gi, gadget, ie, GM_HANDLEINPUT, &reuse_event, IntuitionBase);
2704 } /* if (gadget) */
2706 #if USE_NEWDISPLAYBEEP
2708 if (GetPrivIBase(IntuitionBase)->BeepingScreens)
2710 ULONG lock;
2711 struct Screen *scr;
2713 lock = LockIBase(0);
2715 for (scr = IntuitionBase->FirstScreen;
2716 scr && GetPrivIBase(IntuitionBase)->BeepingScreens;
2717 scr = scr->NextScreen)
2719 if ((scr->Flags & BEEPING) &&
2720 !GetPrivScreen(scr)->BeepingCounter--)
2722 GetPrivIBase(IntuitionBase)->BeepingScreens--;
2723 scr->Flags &= (UWORD) ~BEEPING;
2725 /* if (GetBitMapAttr(scr->RastPort.BitMap, BMA_DEPTH) <= 8)
2726 // visual beep on CLUT-screen
2728 // SetRGB4 (&screen->ViewPort, 0, scr->SaveColor0 & 0x000F, (scr->SaveColor0 & 0x00F0) >> 4, (scr->SaveColor0 & 0x0F00) >> 8);
2729 SetRGB32 (&scr->ViewPort, 0,
2730 GetPrivScreen(scr)->DisplayBeepColor0[0],
2731 GetPrivScreen(scr)->DisplayBeepColor0[1],
2732 GetPrivScreen(scr)->DisplayBeepColor0[2]
2735 else
2736 // visual beep on hi- and truecolor screens
2738 RenderScreenBar(scr, FALSE, IntuitionBase);
2741 RenderScreenBar(scr, FALSE, IntuitionBase);
2745 UnlockIBase(lock);
2747 #endif /* USE_NEWDISPLAYBEEP */
2749 if (!w) break;
2751 /* Send INTUITICK msg only if app already replied the last INTUITICK msg */
2752 if (w->Flags & WFLG_WINDOWTICKED) break;
2754 if (w->IDCMPFlags & IDCMP_INTUITICKS)
2756 /* Set the WINDOWTICKED flag, it will be cleared again when the app
2757 replies back the msg and the InputHandler handles the replymsg
2758 in HandleIntuiReplyPort() */
2760 ih_fire_intuimessage(w,
2761 IDCMP_INTUITICKS,
2764 IntuitionBase);
2766 break; /* case IECLASS_TIMER */
2768 case IECLASS_MENU:
2769 if (MENUS_ACTIVE && (ie->ie_SubClass == IESUBCLASS_MENUSTOP))
2771 struct Window *eventwin = (struct Window *)ie->ie_EventAddress;
2773 iihdata->MenuWindow = NULL;
2774 MENUS_ACTIVE = FALSE;
2776 /* semaphore was locked when menu action started, see
2777 above where MMCODE_START MenuMessage is sent.
2779 It could have also have been locked if the user
2780 activated one of the menu key shortcuts, see
2781 "case IECLASS_RAWKEY" */
2783 ReleaseSemaphore(&GetPrivIBase(IntuitionBase)->MenuLock);
2785 keep_event = FALSE;
2787 if (((struct IntWindow *)eventwin)->menulendwindow)
2789 eventwin = ((struct IntWindow *)eventwin)->menulendwindow;
2792 ih_fire_intuimessage((struct Window *)eventwin,
2793 IDCMP_MENUPICK,
2794 ie->ie_Code,
2795 (struct Window *)ie->ie_EventAddress,
2796 IntuitionBase);
2799 break;
2801 case IECLASS_DISKINSERTED:
2802 case IECLASS_DISKREMOVED:
2803 case IECLASS_NEWPREFS:
2805 struct Screen *scr;
2806 ULONG idcmp;
2807 LONG lock;
2809 switch (ie->ie_Class)
2811 case IECLASS_DISKINSERTED:
2812 idcmp = IDCMP_DISKINSERTED;
2813 break;
2815 case IECLASS_DISKREMOVED:
2816 idcmp = IDCMP_DISKREMOVED;
2817 break;
2819 default:
2820 idcmp = IDCMP_NEWPREFS;
2822 * Here we need to update the mouse prefs and
2823 * maybe other stuff which comes from the global prefs file.
2825 break;
2828 lock = LockIBase(0);
2830 for (scr = IntuitionBase->FirstScreen; scr; scr = scr->NextScreen)
2832 struct Window *win;
2834 for (win = scr->FirstWindow; win; win = win->NextWindow)
2836 /* stegerg:
2837 CHECKME, really use fire_intuimessage() here,
2838 instead of ih_fireintuimessage? Same for
2839 IDCMP_GADGETHELP above, BTW. */
2841 fire_intuimessage(win,
2842 idcmp,
2844 NULL,
2845 IntuitionBase);
2849 UnlockIBase(lock);
2851 break;
2853 case IECLASS_NEWMOUSE:
2854 #ifdef __MORPHOS__
2856 * The following is only needed on hardware not running
2857 * the NewMouse driver.
2859 if (w->IDCMPFlags & IDCMP_RAWKEY && (!SysBase->MaxLocMem))
2861 ih_fire_intuimessage(w,
2862 IDCMP_RAWKEY,
2863 ie->ie_Code,
2864 ie->ie_position.ie_addr, /* ie_dead.ie_prev[1|2]Down[Code|Qual]. 64 bit machine!? */
2865 IntuitionBase);
2866 keep_event = FALSE;
2868 break;
2869 #endif
2870 case IECLASS_NULL:
2871 break;
2873 #ifdef __MORPHOS__
2874 case IECLASS_NEWTIMER:
2875 if (MENUS_ACTIVE)
2877 FireMenuMessage(MMCODE_EVENT, 0, ie, IntuitionBase);
2878 keep_event = FALSE;
2879 break;
2882 if (gadget)
2884 if (gadget == iihdata->MasterSizeGadget)
2886 gadget = DoGPInput(gi, gadget, ie, GM_HANDLEINPUT, &reuse_event, IntuitionBase);
2889 } /* if (gadget) */
2890 break;
2891 #endif /* __MORPHOS__ */
2893 default:
2894 if (MENUS_ACTIVE)
2896 FireMenuMessage(MMCODE_EVENT, 0, ie, IntuitionBase);
2897 keep_event = FALSE;
2898 break;
2903 "[Intui] InputHandler: Unknown IEClass: addr = %x class = %d (origclass = %d)\n",
2904 orig_ie, ie->ie_Class,orig_ie->ie_Class
2907 break;
2908 } /* switch (ie->ie_Class) */
2910 if (reuse_event)
2913 else if (keep_event && !ie_used)
2915 *iihdata->EndInputEventChain = orig_ie;
2916 iihdata->EndInputEventChain = &orig_ie->ie_NextEvent;
2917 ie_used = TRUE;
2919 else if (!ie_used)
2921 orig_ie->ie_NextEvent = iihdata->FreeInputEvents;
2922 iihdata->FreeInputEvents = orig_ie;
2925 } /* for (each event in the chain) */
2927 iihdata->ActiveGadget = gadget;
2929 D(bug("Outside pollingloop\n"));
2931 #if SINGLE_SETPOINTERPOS_PER_EVENTLOOP
2932 if (call_setpointerpos)
2933 MySetPointerPos(IntuitionBase);
2934 #endif
2936 /* Terminate the event chain. */
2937 *iihdata->EndInputEventChain = NULL;
2939 /* Transfer the list of allocated events in the list of events that should
2940 * be freed the next time the handler is entered.
2942 iihdata->AllocatedInputEventList = iihdata->NewAllocatedInputEventList;
2943 NEWLIST((struct List*)&iihdata->NewAllocatedInputEventList);
2945 /* Reset the event chain here, not at the beginning of the handler, for
2946 * events that might be allocated in other handers.
2948 iihdata->EndInputEventChain = &iihdata->ReturnInputEvent;
2949 iihdata->FreeInputEvents = NULL;
2951 ReleaseSemaphore(&GetPrivIBase(IntuitionBase)->InputHandlerLock);
2953 // DEBUG_HANDLER(dprintf("Handler: ->IBase 0x%lx KeyMapBase 0x%lx\n",IntuitionBase,KeymapBase));
2955 return iihdata->ReturnInputEvent;
2957 AROS_USERFUNC_EXIT
2960 /****************************************************************************************/