synch mmakefile behaviour
[AROS.git] / rom / intuition / inputhandler.c
blob9af2d043828c63aa47d33b02373d504c13c32035
1 /*
2 Copyright � 1995-2017, 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 = CreateMsgPort();
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 FreeSignal(port->mp_SigBit);
122 port->mp_SigBit = -1;
123 port->mp_Flags = PA_IGNORE;
125 iihdata->IntuiReplyPort = port;
127 NEWLIST((struct List*) &iihdata->IntuiActionQueue);
128 NEWLIST((struct List*)&iihdata->NewAllocatedInputEventList);
129 NEWLIST((struct List*)&iihdata->AllocatedInputEventList);
130 iihdata->EndInputEventChain = &iihdata->ReturnInputEvent;
131 iihdata->FreeInputEvents = NULL;
133 iihdata->ActQualifier = IEQUALIFIER_RELATIVEMOUSE;
135 /* Note: there are several routines like CloseWindow, which
136 expect is_Data to point to the IIHData structure, so don't
137 change this! */
139 iihandler->is_Code = (VOID_FUNC)AROS_ASMSYMNAME(IntuiInputHandler);
140 iihandler->is_Data = iihdata;
141 iihandler->is_Node.ln_Pri = 50;
142 iihandler->is_Node.ln_Name = "Intuition InputHandler";
144 lock = LockIBase(0UL);
146 iihdata->IntuitionBase = IntuitionBase;
148 UnlockIBase(lock);
150 GetPrivIBase(IntuitionBase)->IntuiReplyPort = iihdata->IntuiReplyPort;
151 GetPrivIBase(IntuitionBase)->IntuiActionQueue = &iihdata->IntuiActionQueue;
153 ReturnPtr ("InitIIH", struct Interrupt *, iihandler);
154 } /* f (iihdata->MasterDragGadget && iihdata->MasterSizeGadget) */
156 DisposeObject((Object *)iihdata->MasterDragGadget);
157 DisposeObject((Object *)iihdata->MasterSizeGadget);
159 DeletePool(iihdata->ActionsMemPool);
160 DeletePool(iihdata->InputEventMemPool);
162 } /* if (iihdata->InputEventMemPool = ... */
163 DeleteMsgPort(port);
165 } /* if (port) */
166 FreeMem(iihdata, sizeof (struct IIHData));
167 iihdata->MouseBoundsActiveFlag = FALSE;
169 } /* if (iihdata) */
170 FreeMem(iihandler, sizeof (struct Interrupt));
172 } /* if (iihandler) */
174 ReturnPtr ("InitIIH", struct Interrupt *, NULL);
177 /****************************************************************************************/
179 VOID CleanupIIH(struct Interrupt *iihandler, struct IntuitionBase *IntuitionBase)
181 struct IIHData *iihdata = (struct IIHData *)iihandler->is_Data;
183 DisposeObject((Object *)iihdata->MasterDragGadget);
184 DisposeObject((Object *)iihdata->MasterSizeGadget);
186 FreeGeneratedInputEvents(iihdata);
187 DeletePool(iihdata->InputEventMemPool);
188 DeletePool(iihdata->ActionsMemPool);
190 /* One might think that this port is still in use by the inputhandler.
191 ** However, if intuition is closed for the last time, there should be no
192 ** windows that IntuiMessage can be sent to.
194 FreeMem(iihdata->IntuiReplyPort, sizeof (struct MsgPort));
196 FreeMem(iihdata, sizeof (struct IIHData));
197 FreeMem(iihandler, sizeof (struct Interrupt));
199 return;
202 /****************************************************************************************/
204 static void HandleIntuiReplyPort(struct IIHData *iihdata, struct IntuitionBase *IntuitionBase)
206 struct Library *TimerBase = GetPrivIBase(IntuitionBase)->TimerBase;
207 struct IntuiMessage *im;
209 while ((im = (struct IntuiMessage *)GetMsg(iihdata->IntuiReplyPort)))
211 if (im->IDCMPWindow && ResourceExisting(im->IDCMPWindow, RESOURCE_WINDOW, IntuitionBase))
213 struct IntWindow *win = (struct IntWindow *)im->IDCMPWindow;
215 Forbid();
216 GetSysTime(&win->lastmsgreplied);
217 Permit();
219 switch(im->Class)
221 case IDCMP_MOUSEMOVE:
222 IW(im->IDCMPWindow)->num_mouseevents--;
223 break;
225 case IDCMP_INTUITICKS:
226 AROS_ATOMIC_AND(im->IDCMPWindow->Flags, ~WFLG_WINDOWTICKED);
227 break;
229 #if USE_IDCMPUPDATE_MESSAGECACHE
230 case IDCMP_IDCMPUPDATE:
231 IW(im->IDCMPWindow)->num_idcmpupdate--;
233 if (!(IW(im->IDCMPWindow)->num_idcmpupdate) && IW(im->IDCMPWindow)->messagecache)
235 SendIntuiMessage(im->IDCMPWindow,IW(im->IDCMPWindow)->messagecache);
236 IW(im->IDCMPWindow)->messagecache = 0;
238 break;
239 #endif
241 case IDCMP_MENUVERIFY:
243 struct Window *w = im->IDCMPWindow;
244 struct IntScreen *scr = 0;
246 scr = GetPrivScreen(w->WScreen);
248 if (scr != GetPrivIBase(IntuitionBase)->MenuVerifyScreen ||
249 scr->MenuVerifySeconds > im->Seconds ||
250 (scr->MenuVerifySeconds == im->Seconds &&
251 scr->MenuVerifyMicros > im->Micros))
253 /* The timeout has expired, just ignore. */
255 else
257 --scr->MenuVerifyMsgCount;
258 if (w == scr->MenuVerifyActiveWindow &&
259 im->Code == MENUCANCEL)
261 ULONG lock = LockIBase(0);
262 struct Window *w1;
264 for (w1 = scr->Screen.FirstWindow; w1; w1 = w1->NextWindow)
266 if (w1->IDCMPFlags & IDCMP_MENUVERIFY && w1 != scr->MenuVerifyActiveWindow)
268 ih_fire_intuimessage(w1,
269 IDCMP_MOUSEBUTTONS,
270 MENUUP,
272 IntuitionBase);
276 UnlockIBase(lock);
278 scr->MenuVerifyActiveWindow = NULL;
279 scr->MenuVerifyTimeOut = 0;
280 scr->MenuVerifyMsgCount = 0;
281 scr->MenuVerifySeconds = 0;
282 scr->MenuVerifyMicros = 0;
283 GetPrivIBase(IntuitionBase)->MenuVerifyScreen = NULL;
285 else if (scr->MenuVerifyMsgCount == 0)
287 struct InputEvent ie;
289 /* currently we ONLY need the menu open time ! */
290 ie.ie_TimeStamp.tv_secs = im->Seconds;
291 ie.ie_TimeStamp.tv_micro = im->Micros;
293 if (FireMenuMessage(MMCODE_START, scr->MenuVerifyActiveWindow, &ie, IntuitionBase))
295 /* This lock will be released only when the user is
296 done with menus = when IECLASS_MENU + IESUBCLASS_MENUSTOP
297 event arrives (generated by MenuHandler task) */
299 ObtainSemaphore(&GetPrivIBase(IntuitionBase)->MenuLock);
300 iihdata->MenuWindow = scr->MenuVerifyActiveWindow;
301 MENUS_ACTIVE = TRUE;
304 scr->MenuVerifyActiveWindow = NULL;
305 scr->MenuVerifyTimeOut = 0;
306 scr->MenuVerifyMsgCount = 0;
307 scr->MenuVerifySeconds = 0;
308 scr->MenuVerifyMicros = 0;
309 GetPrivIBase(IntuitionBase)->MenuVerifyScreen = NULL;
312 break;
315 case IDCMP_SIZEVERIFY:
317 struct GadgetInfo *gi = &iihdata->GadgetInfo;
318 struct Window *w = im->IDCMPWindow;
319 struct Gadget *gadget = im->IAddress;
320 struct InputEvent ie;
321 BOOL reuse_event;
323 PrepareGadgetInfo(gi, IntuitionBase->ActiveScreen, w, NULL);
324 SetGadgetInfoGadget(gi, gadget, IntuitionBase);
326 if (IS_BOOPSI_GADGET(gadget))
328 ie.ie_NextEvent = NULL;
329 ie.ie_Class = IECLASS_RAWMOUSE;
330 ie.ie_SubClass = 0;
331 ie.ie_Code = IECODE_LBUTTON;
332 ie.ie_Qualifier = im->Qualifier;
333 ie.ie_X = im->MouseX;
334 ie.ie_Y = im->MouseY;
335 ie.ie_TimeStamp.tv_secs = IntuitionBase->Seconds;
336 ie.ie_TimeStamp.tv_micro = IntuitionBase->Micros;
338 DoGPInput(gi,
339 gadget,
340 &ie,
341 GM_GOACTIVE,
342 &reuse_event,
343 IntuitionBase);
345 /* For compatibility, send a GM_HANDLEINPUT too */
346 ie.ie_Class = IECLASS_RAWMOUSE;
347 ie.ie_Code = IECODE_NOBUTTON;
348 ie.ie_X = 0;
349 ie.ie_Y = 0;
351 gadget = DoGPInput(gi,
352 gadget,
353 &ie,
354 GM_HANDLEINPUT,
355 &reuse_event,
356 IntuitionBase);
359 /* From now on the master drag/size gadget takes over */
361 iihdata->ActiveSysGadget = gadget;
362 gadget = iihdata->MasterSizeGadget;
363 iihdata->ActiveGadget = gadget;
365 ie.ie_Class = IECLASS_RAWMOUSE;
366 ie.ie_Code = IECODE_LBUTTON;
367 ie.ie_X = im->MouseX;
368 ie.ie_Y = im->MouseY;
370 DoGPInput(gi,
371 gadget,
372 &ie,
373 GM_GOACTIVE,
374 &reuse_event,
375 IntuitionBase);
376 break;
379 case IDCMP_REQVERIFY:
381 struct Window *w = im->IDCMPWindow;
383 EndRequest(w->DMRequest, w);
385 ih_fire_intuimessage(w,
386 IDCMP_REQSET,
389 IntuitionBase);
391 break;
393 case IDCMP_WBENCHMESSAGE:
394 DEBUG_WORKBENCH(dprintf("HandleIntuiReplyPort: code 0x%lx\n",
395 im->Code));
396 break;
398 } /* switch(im->Class) */
400 if (im->Qualifier & IEQUALIFIER_REPEAT)
402 /* IDCMP_IDCMPUPDATE messages can also be sent from app task, therefore
403 it would be better if there was an ATOMIC_DEC macro or something */
405 if (IW(im->IDCMPWindow)->num_repeatevents)
407 IW(im->IDCMPWindow)->num_repeatevents--;
411 FreeIntuiMessage(im);
413 } /* while ((im = (struct IntuiMessage *)GetMsg(iihdata->IntuiReplyPort))) */
415 /****************************************************************************************/
417 struct Window *GetToolBoxWindow(struct InputEvent *ie, struct Screen *scr, struct IntuitionBase *IntuitionBase)
419 /* The caller has checked that the input event is a IECLASS_RAWMOUSE, SELECTDOWN event */
420 /* NOTE: may be called with NULL ie ptr! */
421 struct LayersBase *LayersBase = GetPrivIBase(IntuitionBase)->LayersBase;
422 struct Layer *l;
423 struct Window *new_w = NULL;
425 if (scr)
427 D(bug("GetToolBoxWindow: Click at (%d,%d)\n",scr->MouseX,scr->MouseY));
429 /* What layer ? */
430 LockLayerInfo(&scr->LayerInfo);
432 l = WhichLayer(&scr->LayerInfo, scr->MouseX, scr->MouseY);
434 UnlockLayerInfo(&scr->LayerInfo);
436 if (NULL == l)
438 new_w = NULL;
439 D(bug("GetToolBoxWindow: Click not inside layer\n"));
441 else if (l == scr->BarLayer)
444 else
446 new_w = (struct Window *)l->Window;
447 if (new_w)
449 if ((new_w->Flags & WFLG_TOOLBOX) == 0) new_w = NULL;
451 if (!new_w)
453 D(bug("GetToolBoxWindow: Selected layer is not a ToolBox window\n"));
455 else
457 D(bug("GetToolBoxWindow: Found layer %p\n", l));
462 D(bug("GetToolBoxWindow: New window %p\n", new_w));
463 return new_w;
466 /****************************************************************************************/
468 #define KEY_QUALIFIERS (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT | \
469 IEQUALIFIER_CAPSLOCK | IEQUALIFIER_CONTROL | \
470 IEQUALIFIER_LALT | IEQUALIFIER_RALT | \
471 IEQUALIFIER_LCOMMAND | IEQUALIFIER_RCOMMAND | \
472 IEQUALIFIER_NUMERICPAD)
474 #define BUTTON_QUALIFIERS (IEQUALIFIER_MIDBUTTON | IEQUALIFIER_RBUTTON | IEQUALIFIER_LEFTBUTTON)
476 static struct Gadget *Process_RawMouse(struct InputEvent *ie, struct IIHData *iihdata, struct Screen *screen,
477 struct Window *w, struct Gadget *gadget, struct GadgetInfo *gi,
478 ULONG stitlebarhit, BOOL new_active_window, BOOL IsToolbox,
479 struct InputEvent *orig_ie, BOOL *keep_event, BOOL *reuse_event,
480 #if SINGLE_SETPOINTERPOS_PER_EVENTLOOP
481 BOOL *call_setpointerpos,
482 #endif
483 struct IntuitionBase *IntuitionBase)
485 struct Library *InputBase = GetPrivIBase(IntuitionBase)->InputBase;
486 struct Requester *req = w ? w->FirstRequest : NULL;
488 switch (ie->ie_Code) {
489 case SELECTDOWN:
491 BOOL new_gadget = FALSE;
492 BOOL sizeverify = FALSE;
493 UWORD MetaDrag = GetPrivIBase(IntuitionBase)->IControlPrefs.ic_MetaDrag;
495 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));
496 DEBUG_CLICK(if (screen) bug("[Inputhandler] Coordinates: (%d, %d)\n", screen->MouseX, screen->MouseY));
498 iihdata->ActQualifier |= IEQUALIFIER_LEFTBUTTON;
500 /* Enter screen dragging mode if LButton + MetaDrag are pressed. */
501 if (MetaDrag && ((iihdata->ActQualifier & KEY_QUALIFIERS) == MetaDrag)) {
502 iihdata->ScreenDrag = screen;
503 iihdata->ScreenDragPointX = screen->MouseX;
504 iihdata->ScreenDragPointY = screen->MouseY;
505 *keep_event = FALSE;
506 break;
509 #ifdef SKINS
510 iihdata->TitlebarAppearTime = 0;
511 #endif
512 if (MENUS_ACTIVE)
514 FireMenuMessage(MMCODE_EVENT, 0, ie, IntuitionBase);
515 *keep_event = FALSE;
516 break;
519 #ifdef SKINS
520 if (!gadget && w)
522 struct Gadget * draggadget = 0;
524 if ((!(w->FirstRequest)) && (w->Flags & WFLG_DRAGBAR) && MatchHotkey(ie,IA_ACTIVEWINDOWMOVE,IntuitionBase))
526 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)
528 for (draggadget = w->FirstGadget; draggadget; draggadget = draggadget->NextGadget)
530 if ((draggadget->GadgetType & GTYP_SYSTYPEMASK) == GTYP_WDRAGGING)
532 gadget = draggadget;
533 new_gadget = TRUE;
534 break;
540 if ((!(w->FirstRequest)) && (w->Flags & WFLG_SIZEGADGET) && MatchHotkey(ie,IA_ACTIVEWINDOWSIZE,IntuitionBase))
542 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)
544 for (draggadget = w->FirstGadget; draggadget; draggadget = draggadget->NextGadget)
546 if ((draggadget->GadgetType & GTYP_SYSTYPEMASK) == GTYP_SIZING)
548 gadget = draggadget;
549 new_gadget = TRUE;
550 break;
556 #endif
558 if (!gadget)
560 /* use the *current* screen rather than active one when searching
561 for sdepth gadget! */
562 if (screen)
563 gadget = FindGadget (screen, stitlebarhit ? NULL : w, stitlebarhit ? NULL : req,
564 screen->MouseX, screen->MouseY, gi, FALSE, IntuitionBase);
565 DEBUG_CLICK(bug("Click on gadget %p\n", gadget));
566 new_gadget = TRUE;
568 } /* if (!gadget) */
570 /* If we clicked screen titlebar outside of any gadget, enter drag mode */
571 if ((!gadget) && stitlebarhit) {
572 DEBUG_CLICK(bug("[Inputhandler] Entering drag state for screen 0x%p\n", screen));
573 iihdata->ScreenDrag = screen;
574 iihdata->ScreenDragPointX = screen->MouseX;
575 iihdata->ScreenDragPointY = screen->MouseY;
576 *keep_event = FALSE;
577 break;
580 if (!IsToolbox) {
581 if (!gadget && stitlebarhit)
583 struct Window *ww = 0;
585 ww = FindDesktopWindow(screen, IntuitionBase);
586 DEBUG_CLICK(bug("[Inputhandler] Clicked on backdrop window 0x%p\n", ww));
587 if (ww) {
588 ActivateWindow(ww);
589 w = ww;
593 if (!stitlebarhit && !new_active_window && DoubleClick(GetPrivIBase(IntuitionBase)->LastClickSecs,GetPrivIBase(IntuitionBase)->LastClickMicro,
594 ie->ie_TimeStamp.tv_secs,ie->ie_TimeStamp.tv_micro))
596 if (GetPrivIBase(IntuitionBase)->DoubleClickButton != SELECTDOWN)
598 GetPrivIBase(IntuitionBase)->DoubleClickCounter = 0;
599 GetPrivIBase(IntuitionBase)->DoubleClickButton = SELECTDOWN;
601 else
603 GetPrivIBase(IntuitionBase)->DoubleClickCounter ++;
606 else
608 DEBUG_CLICK(bug("[Inputhandler] Resetting doubleclick counter\n"));
609 GetPrivIBase(IntuitionBase)->DoubleClickButton = SELECTDOWN;
610 GetPrivIBase(IntuitionBase)->DoubleClickCounter = 0;
613 /* update last click time for doubleclicktofront */
614 GetPrivIBase(IntuitionBase)->LastClickSecs = ie->ie_TimeStamp.tv_secs;
615 GetPrivIBase(IntuitionBase)->LastClickMicro = ie->ie_TimeStamp.tv_micro;
617 #ifdef SKINS
618 if (!stitlebarhit)
620 ULONG result;
622 if (!(gadget && ((gadget->GadgetType & GTYP_SYSTYPEMASK) == GTYP_WDEPTH)))
623 if ((result = RunHotkeys(ie,IntuitionBase)))
625 //gadget = NULL;
626 if (result == RUNHOTREUSE)
628 *reuse_event = TRUE;
630 else
632 *keep_event = FALSE;
636 #endif
638 if (gadget && new_gadget)
640 DEBUG_GADGET(bug("[Inputhandler] Activate gadget: 0x%p\n", gadget));
641 if (w && (w->IDCMPFlags & IDCMP_SIZEVERIFY) &&
642 (gadget->GadgetType & GTYP_SYSTYPEMASK) == GTYP_SIZING /*||
643 (gadget->GadgetType & GTYP_SYSTYPEMASK) == GTYP_WZOOM*/)
645 ih_fire_intuimessage(w,
646 IDCMP_SIZEVERIFY,
648 gadget,
649 IntuitionBase);
650 gadget = NULL;
651 sizeverify = TRUE;
653 else
655 BOOL is_draggad, is_sizegad;
656 UWORD gsystype;
658 /* Whenever the active gadget changes the gi must be updated
659 because it is cached in iidata->GadgetInfo!!!! Don't
660 forget to do this if somewhere else the active
661 gadget is changed, for example in ActivateGadget!!! */
663 PrepareGadgetInfo(gi, screen, w, req);
664 SetGadgetInfoGadget(gi, gadget, IntuitionBase);
666 gsystype = gadget->GadgetType & GTYP_SYSTYPEMASK;
667 is_draggad = ((gsystype == GTYP_WDRAGGING)
668 #ifdef __MORPHOS__
669 || (gsystype == GTYP_WDRAGGING2)
670 #endif
672 is_sizegad = (gsystype == GTYP_SIZING);
674 /* jDc: intui68k sends IDCMPs for GACT_IMMEDIATE drag&sizegads! */
675 if (gadget->Activation & GACT_IMMEDIATE)
677 ih_fire_intuimessage(w,
678 IDCMP_GADGETDOWN,
680 gadget,
681 IntuitionBase);
684 if (is_draggad || is_sizegad)
686 if (IS_BOOPSI_GADGET(gadget))
688 DoGPInput(gi,
689 gadget,
691 GM_GOACTIVE,
692 reuse_event,
693 IntuitionBase);
695 /* Ignoring retval of dispatcher above is what
696 AmigaOS does too for boopsi drag/resize
697 gadgets */
701 /* From now on the master drag/size gadget takes over */
702 if ((w->MoreFlags & WMFLG_IAMMUI) && (w->Flags & WFLG_BORDERLESS))
703 iihdata->ActiveSysGadget = is_draggad ? gadget : 0;
704 else
705 iihdata->ActiveSysGadget = gadget;
706 gadget = is_draggad ? iihdata->MasterDragGadget : iihdata->MasterSizeGadget;
711 if (gadget)
714 switch (gadget->GadgetType & GTYP_GTYPEMASK)
716 case GTYP_BOOLGADGET:
717 /* Only set the GFLG_SELECTED flag for RELVERIFY and
718 * TOGGLESELECT gadget. It's for the user to do it if
719 * he wants for other GADGIMMEDIATE ones.
720 * Only RELVERIFY gadgets stay active.
723 if (gadget->Activation & (GACT_TOGGLESELECT | GACT_RELVERIFY))
725 gadget->Flags ^= GFLG_SELECTED;
726 RefreshBoolGadgetState(gadget, w, req, IntuitionBase);
729 if (gadget->Activation & GACT_RELVERIFY)
731 gadget->Activation |= GACT_ACTIVEGADGET;
732 iihdata->MouseWasInsideBoolGadget = TRUE;
734 else
736 gadget = NULL;
738 break;
740 case GTYP_PROPGADGET:
741 HandlePropSelectDown(gadget,
743 req,
744 w->MouseX - gi->gi_Domain.Left - GetGadgetLeft(gadget, gi->gi_Screen, gi->gi_Window, NULL),
745 w->MouseY - gi->gi_Domain.Top - GetGadgetTop(gadget, gi->gi_Screen, gi->gi_Window, NULL),
746 IntuitionBase);
749 break;
751 case GTYP_STRGADGET:
752 /* If the click was inside the active strgad,
753 ** then let it update cursor pos,
754 ** else deactivate stringadget and reuse event.
757 if (InsideGadget(gi->gi_Screen, gi->gi_Window,
758 gi->gi_Requester, gadget,
759 gi->gi_Screen->MouseX, gi->gi_Screen->MouseY))
761 UWORD imsgcode;
763 HandleStrInput(gadget, gi, ie, &imsgcode,
764 IntuitionBase);
766 else
768 gadget->Flags &= ~GFLG_SELECTED;
770 RefreshStrGadget(gadget, w, req, IntuitionBase);
771 /* Gadget not active anymore */
772 gadget = NULL;
773 *reuse_event = TRUE;
775 break;
777 case GTYP_CUSTOMGADGET:
778 gadget = DoGPInput(gi,
779 gadget,
781 (new_gadget ? GM_GOACTIVE : GM_HANDLEINPUT),
782 reuse_event,
783 IntuitionBase);
784 D(bug("new_gadget %d, goactive %p\n", new_gadget, gadget));
786 if (gadget && new_gadget && (!(gadget->GadgetType & GTYP_SIZING)))
788 /* For compatibility, send a GM_HANDLEINPUT too */
789 struct InputEvent newie;
790 BOOL reuse_event;
792 newie.ie_NextEvent = NULL;
793 newie.ie_Class = IECLASS_RAWMOUSE;
794 newie.ie_SubClass = 0;
795 newie.ie_Code = IECODE_NOBUTTON;
796 newie.ie_Qualifier = ie->ie_Qualifier;
797 newie.ie_X = 0;
798 newie.ie_Y = 0;
799 newie.ie_TimeStamp.tv_secs = IntuitionBase->Seconds;
800 newie.ie_TimeStamp.tv_micro = IntuitionBase->Micros;
802 gadget = DoGPInput(gi,
803 gadget,
804 &newie,
805 GM_HANDLEINPUT,
806 &reuse_event,
807 IntuitionBase);
808 D(bug("handleinput %p\n", gadget));
810 break;
812 case 0: //orig gadtools / some 1.3 gadgets
813 if (IS_SYS_GADGET(gadget))
815 HandleSysGadgetVerify(gi, gadget, IntuitionBase);
817 else
819 if (gadget->Activation & GACT_RELVERIFY)
821 gadget->Activation |= GACT_ACTIVEGADGET;
822 iihdata->MouseWasInsideBoolGadget = TRUE;
823 if (gadget->Flags & GFLG_GADGHIMAGE)
825 gadget->Flags ^= GFLG_SELECTED;
826 RefreshBoolGadgetState(gadget, w, req, IntuitionBase);
829 else
831 /* jDc: this is what original intuition does, before crashing after a while ;)*/
832 DEBUG_CLICK(bug("[Inputhandler] Sending SELECTDOWN (old gadget), window 0x%p\n", w));
833 ih_fire_intuimessage(w,
834 IDCMP_MOUSEBUTTONS,
835 SELECTDOWN,
837 IntuitionBase);
840 break;
841 } /* switch (GadgetType) */
843 } /* if (a gadget is active) */
844 else if (w && (!req || req->Flags & NOISYREQ) && !sizeverify && !stitlebarhit)
846 DEBUG_CLICK(bug("[Inputhandler] Sending SELECTDOWN, window 0x%p\n", w));
847 ih_fire_intuimessage(w,
848 IDCMP_MOUSEBUTTONS,
849 SELECTDOWN,
851 IntuitionBase);
854 } /* case SELECTDOWN */
855 break;
857 case SELECTUP:
858 iihdata->ActQualifier &= ~IEQUALIFIER_LEFTBUTTON;
860 /* Ignore this event if screen drag qualifier is pressed */
861 if (iihdata->ScreenDrag) {
862 iihdata->ScreenDrag = NULL;
863 *keep_event = FALSE;
864 break;
867 #ifdef SKINS
868 iihdata->TitlebarAppearTime = 0;
869 #endif
870 if (MENUS_ACTIVE)
872 FireMenuMessage(MMCODE_EVENT, 0, ie, IntuitionBase);
873 *keep_event = FALSE;
874 break;
877 if (gadget)
879 BOOL inside = InsideGadget(gi->gi_Screen, gi->gi_Window,
880 gi->gi_Requester, gadget,
881 gi->gi_Screen->MouseX, gi->gi_Screen->MouseY);
883 /*int selected = (gadget->Flags & GFLG_SELECTED) != 0;*/
885 switch (gadget->GadgetType & GTYP_GTYPEMASK)
887 case GTYP_BOOLGADGET:
888 /* Must be a RELVERIFY gadget */
890 if (!(gadget->Activation & GACT_TOGGLESELECT) && inside)
892 gadget->Flags ^= GFLG_SELECTED;
893 RefreshBoolGadgetState(gadget, w, req, IntuitionBase);
896 if (inside)
898 if (IS_SYS_GADGET(gadget))
900 HandleSysGadgetVerify(gi, gadget, IntuitionBase);
902 else
904 if (req && gadget->Activation & GACT_ENDGADGET)
906 EndRequest(req, w);
908 req = w->FirstRequest;
911 ih_fire_intuimessage(w,
912 IDCMP_GADGETUP,
914 gadget,
915 IntuitionBase);
918 else
920 /* RKRM say so */
921 ih_fire_intuimessage(w,
922 IDCMP_MOUSEBUTTONS,
923 SELECTUP,
925 IntuitionBase);
928 gadget->Activation &= ~GACT_ACTIVEGADGET;
929 gadget = NULL;
930 break;
932 case GTYP_PROPGADGET:
933 HandlePropSelectUp(gadget, w, req, IntuitionBase);
934 if (gadget->Activation & GACT_RELVERIFY)
936 ih_fire_intuimessage(w,
937 IDCMP_GADGETUP,
939 gadget,
940 IntuitionBase);
943 gadget = NULL;
944 break;
946 /* Intuition string gadgets don't care about SELECTUP */
948 case GTYP_CUSTOMGADGET:
949 gadget = DoGPInput(gi, gadget, ie, GM_HANDLEINPUT, reuse_event, IntuitionBase);
950 break;
952 case 0: //orig gadtools / some 1.3 gadgets
953 /* jDc: adding a gadget with gtyp field set to NULL crashes intui68k
954 ** seems we don't need compatibility on this field ;) anyway we should
955 ** handle the case of GTYP_CLOSE, etc, set by some "cod3r"
957 gadget->Activation &= ~GACT_ACTIVEGADGET;
958 if (gadget->Activation & GACT_RELVERIFY)
960 if (gadget->Flags & GFLG_GADGHIMAGE)
962 if (inside)
964 gadget->Flags ^= GFLG_SELECTED;
965 RefreshBoolGadgetState(gadget, w, req, IntuitionBase);
969 if (inside)
971 ih_fire_intuimessage(w,
972 IDCMP_GADGETUP,
974 gadget,
975 IntuitionBase);
977 } else {
978 ih_fire_intuimessage(w,
979 IDCMP_MOUSEBUTTONS,
980 SELECTUP,
982 IntuitionBase);
984 gadget = NULL;
985 break;
987 } /* switch GadgetType */
989 } /* if (a gadget is currently active) */
990 else if (w && (!req || req->Flags & NOISYREQ))
992 ih_fire_intuimessage(w,
993 IDCMP_MOUSEBUTTONS,
994 SELECTUP,
996 IntuitionBase);
999 break; /* case SELECTUP */
1001 case MENUDOWN:
1002 iihdata->ActQualifier |= IEQUALIFIER_RBUTTON;
1004 #ifdef SKINS
1005 iihdata->TitlebarAppearTime = 0;
1006 #endif
1007 if (MENUS_ACTIVE)
1009 FireMenuMessage(MMCODE_EVENT, 0, ie, IntuitionBase);
1010 *keep_event = FALSE;
1011 break;
1014 if (DoubleClick(GetPrivIBase(IntuitionBase)->LastClickSecs,GetPrivIBase(IntuitionBase)->LastClickMicro,
1015 ie->ie_TimeStamp.tv_secs,ie->ie_TimeStamp.tv_micro))
1017 if (GetPrivIBase(IntuitionBase)->DoubleClickButton != MENUDOWN)
1019 GetPrivIBase(IntuitionBase)->DoubleClickCounter = 0;
1020 GetPrivIBase(IntuitionBase)->DoubleClickButton = MENUDOWN;
1022 else
1024 GetPrivIBase(IntuitionBase)->DoubleClickCounter ++;
1027 else
1029 GetPrivIBase(IntuitionBase)->DoubleClickButton = MENUDOWN;
1030 GetPrivIBase(IntuitionBase)->DoubleClickCounter = 0;
1033 /* update last click time for doubleclicktofront */
1034 GetPrivIBase(IntuitionBase)->LastClickSecs = ie->ie_TimeStamp.tv_secs;
1035 GetPrivIBase(IntuitionBase)->LastClickMicro = ie->ie_TimeStamp.tv_micro;
1037 #ifdef SKINS
1039 ULONG result;
1041 if ((result = RunHotkeys(ie,IntuitionBase)))
1043 if (result == RUNHOTREUSE)
1045 *reuse_event = TRUE;
1047 else
1049 *keep_event = FALSE;
1051 break;
1053 w = IntuitionBase->ActiveWindow;
1055 #endif
1057 #ifdef SKINS
1058 if ((!MENUS_ACTIVE) && (!gadget) && (!(iihdata->ActQualifier & (IEQUALIFIER_LEFTBUTTON|IEQUALIFIER_MIDBUTTON))))
1060 struct Gadget *gad;
1061 struct GadgetInfo ginf;
1062 ULONG hit;
1063 struct Window *wind = FindActiveWindow(0, screen, &hit,IntuitionBase);
1065 if (wind)
1067 gad = FindGadget (screen,
1068 hit ? 0 : wind,0,
1069 IntuitionBase->ActiveScreen->MouseX,
1070 IntuitionBase->ActiveScreen->MouseY,
1071 &ginf, TRUE, IntuitionBase);
1073 if (gad && ((gad->GadgetType & GTYP_SYSTYPEMASK) == GTYP_WDEPTH))
1075 CreateSmallMenuTask(wind,SMALLMENU_TYPE_WINDOWDEPTH,IntuitionBase);
1076 *keep_event = FALSE;
1077 break;
1080 if (gad && ((gad->GadgetType & GTYP_SYSTYPEMASK) == GTYP_SDEPTH))
1082 CreateSmallMenuTask(0,SMALLMENU_TYPE_SCREENDEPTH,IntuitionBase);
1083 *keep_event = FALSE;
1084 break;
1088 #endif
1090 if (w && !req && w->DMRequest && !(w->Flags & WFLG_RMBTRAP))
1092 if (!MENUS_ACTIVE &&
1093 DoubleClick(GetPrivIBase(IntuitionBase)->DMStartSecs,
1094 GetPrivIBase(IntuitionBase)->DMStartMicro,
1095 ie->ie_TimeStamp.tv_secs,
1096 ie->ie_TimeStamp.tv_micro))
1098 if (w->IDCMPFlags & IDCMP_REQVERIFY)
1100 ih_fire_intuimessage(w,
1101 IDCMP_REQVERIFY,
1102 MENUHOT,
1103 NULL,
1104 IntuitionBase);
1106 else if (Request(w->DMRequest, w))
1108 req = w->DMRequest;
1110 ih_fire_intuimessage(w,
1111 IDCMP_REQSET,
1114 IntuitionBase);
1116 *keep_event = FALSE;
1117 break;
1120 GetPrivIBase(IntuitionBase)->DMStartSecs = ie->ie_TimeStamp.tv_secs;
1121 GetPrivIBase(IntuitionBase)->DMStartMicro = ie->ie_TimeStamp.tv_micro;
1124 if (w && !gadget)
1126 if (!(w->Flags & WFLG_RMBTRAP) && !req)
1128 struct IntScreen *scr = GetPrivScreen(w->WScreen);
1129 struct Window *w1;
1130 ULONG lock;
1131 BOOL mouseon = TRUE;
1133 scr->MenuVerifyMsgCount = 0;
1135 if (w->MouseX < 0 || w->MouseY < 0) mouseon = FALSE;
1136 if (w->MouseX > w->Width || w->MouseY > w->Height) mouseon = FALSE;
1138 if (w->IDCMPFlags & IDCMP_MENUVERIFY && (!(IW(w)->specialflags & SPFLAG_IAMDEAD)))
1140 ih_fire_intuimessage(w,
1141 IDCMP_MENUVERIFY,
1142 mouseon ? MENUHOT : MENUWAITING,
1144 IntuitionBase);
1145 scr->MenuVerifyMsgCount++;
1148 lock = LockIBase(0);
1150 for (w1 = scr->Screen.FirstWindow; w1; w1 = w1->NextWindow)
1152 if ((w1->IDCMPFlags & IDCMP_MENUVERIFY) && (w1 != w) && (!(IW(w)->specialflags & SPFLAG_IAMDEAD)))
1154 ih_fire_intuimessage(w1,
1155 IDCMP_MENUVERIFY,
1156 MENUWAITING,
1158 IntuitionBase);
1159 ++scr->MenuVerifyMsgCount;
1163 UnlockIBase(lock);
1165 /* FIXME: when a window is opened with IDCMP_MENUVERIFY
1166 * (or this event is requested via ModifyIDCMP), and a
1167 * verify operation is pending, the window should get
1168 * a verify message too. Oh well.
1171 if (scr->MenuVerifyMsgCount)
1173 GetPrivIBase(IntuitionBase)->MenuVerifyScreen = scr;
1174 scr->MenuVerifyActiveWindow = w;
1175 scr->MenuVerifyTimeOut = 2;
1176 scr->MenuVerifySeconds = IntuitionBase->Seconds;
1177 scr->MenuVerifyMicros = IntuitionBase->Micros;
1179 else if (FireMenuMessage(MMCODE_START, w, NULL/*ie*/, IntuitionBase))
1181 /* This lock will be released only when the user is
1182 done with menus = when IECLASS_MENU + IESUBCLASS_MENUSTOP
1183 event arrives (generated by MenuHandler task) */
1185 ObtainSemaphore(&GetPrivIBase(IntuitionBase)->MenuLock);
1186 iihdata->MenuWindow = w;
1187 MENUS_ACTIVE = TRUE;
1191 /* fall through */
1193 case MENUUP:
1194 case MIDDLEDOWN:
1195 case MIDDLEUP:
1197 switch(ie->ie_Code) {
1198 case MENUUP:
1199 iihdata->ActQualifier &= ~IEQUALIFIER_RBUTTON;
1200 if (GetPrivIBase(IntuitionBase)->MenuVerifyScreen)
1202 struct Window *w1;
1203 struct IntScreen *scr = GetPrivIBase(IntuitionBase)->MenuVerifyScreen;
1204 ULONG lock = LockIBase(0);
1206 for (w1 = scr->Screen.FirstWindow; w1; w1 = w1->NextWindow)
1208 if (w1->IDCMPFlags & IDCMP_MENUVERIFY && w1->IDCMPFlags & IDCMP_MOUSEBUTTONS)
1210 ih_fire_intuimessage(w1,
1211 IDCMP_MOUSEBUTTONS,
1212 MENUUP,
1214 IntuitionBase);
1218 UnlockIBase(lock);
1220 /* FIXME: when the active window replies the verifymessage,
1221 * it should get a IDCMP_MENUPICK/MENUNULL message.
1223 GetPrivIBase(IntuitionBase)->MenuVerifyScreen = NULL;
1224 scr->MenuVerifyActiveWindow = NULL;
1225 scr->MenuVerifyMsgCount = 0;
1226 scr->MenuVerifyTimeOut = 0;
1227 scr->MenuVerifySeconds = 0;
1228 scr->MenuVerifyMicros = 0;
1230 break;
1232 case MIDDLEDOWN:
1233 iihdata->ActQualifier |= IEQUALIFIER_MIDBUTTON;
1234 if (DoubleClick(GetPrivIBase(IntuitionBase)->LastClickSecs,GetPrivIBase(IntuitionBase)->LastClickMicro,
1235 ie->ie_TimeStamp.tv_secs,ie->ie_TimeStamp.tv_micro))
1237 if (GetPrivIBase(IntuitionBase)->DoubleClickButton != MIDDLEDOWN)
1239 GetPrivIBase(IntuitionBase)->DoubleClickCounter = 0;
1240 GetPrivIBase(IntuitionBase)->DoubleClickButton = MIDDLEDOWN;
1241 } else
1242 GetPrivIBase(IntuitionBase)->DoubleClickCounter ++;
1243 } else {
1244 GetPrivIBase(IntuitionBase)->DoubleClickButton = MIDDLEDOWN;
1245 GetPrivIBase(IntuitionBase)->DoubleClickCounter = 0;
1247 /* update last click time for doubleclicktofront */
1248 GetPrivIBase(IntuitionBase)->LastClickSecs = ie->ie_TimeStamp.tv_secs;
1249 GetPrivIBase(IntuitionBase)->LastClickMicro = ie->ie_TimeStamp.tv_micro;
1250 break;
1252 case MIDDLEUP:
1253 iihdata->ActQualifier &= ~IEQUALIFIER_MIDBUTTON;
1254 break;
1257 #ifdef SKINS
1258 iihdata->TitlebarAppearTime = 0;
1259 #endif
1260 if (MENUS_ACTIVE)
1262 FireMenuMessage(MMCODE_EVENT, 0, ie, IntuitionBase);
1263 *keep_event = FALSE;
1264 break;
1267 #ifdef SKINS
1268 if (ie->ie_Code == MIDDLEDOWN)
1270 ULONG result;
1272 if ((result = RunHotkeys(ie,IntuitionBase)))
1274 if (result == RUNHOTREUSE)
1276 *reuse_event = TRUE;
1278 else
1280 *keep_event = FALSE;
1282 break;
1284 w = IntuitionBase->ActiveWindow;
1286 #endif
1287 if (gadget)
1289 if (IS_BOOPSI_GADGET(gadget))
1291 gadget = DoGPInput(gi, gadget, ie, GM_HANDLEINPUT, reuse_event, IntuitionBase);
1294 } /* if (there is an active gadget) */
1295 else if (w && (!req || req->Flags & NOISYREQ) && w != GetPrivScreen(w->WScreen)->MenuVerifyActiveWindow)
1297 ih_fire_intuimessage(w,
1298 IDCMP_MOUSEBUTTONS,
1299 ie->ie_Code,
1301 IntuitionBase);
1304 break; /* case MENUDOWN */
1306 case IECODE_NOBUTTON: /* MOUSEMOVE */
1308 struct Screen *scr;
1309 UWORD DWidth, DHeight;
1311 if (ie->ie_Qualifier & IEQUALIFIER_RELATIVEMOUSE) {
1312 //ULONG Thresh;
1314 /* Add delta information lost in previous mousemove event. See below. */
1315 iihdata->DeltaMouseX = ie->ie_X + iihdata->DeltaMouseX_Correction;
1316 iihdata->DeltaMouseY = ie->ie_Y + iihdata->DeltaMouseY_Correction;
1318 #define ACCELERATOR_THRESH 2
1319 #define ACCELERATOR_MULTI 2
1321 if (GetPrivIBase(IntuitionBase)->ActivePreferences.EnableCLI & MOUSE_ACCEL)
1323 /* Acceleration */
1324 if (ABS(iihdata->DeltaMouseX) > ACCELERATOR_THRESH)
1325 iihdata->DeltaMouseX *= ACCELERATOR_MULTI;
1326 if (ABS(iihdata->DeltaMouseY) > ACCELERATOR_THRESH)
1327 iihdata->DeltaMouseY *= ACCELERATOR_MULTI;
1330 switch (GetPrivIBase(IntuitionBase)->ActivePreferences.PointerTicks)
1332 case 0:
1333 iihdata->DeltaMouseX_Correction = 0;
1334 iihdata->DeltaMouseX_Correction = 0;
1335 break;
1337 default:
1338 /* Remember the delta information which gets lost because of division by PointerTicks.
1339 Will be added to prescaled deltas of next mousemove event. If this is not done, moving
1340 the mouse very slowly would cause it to not move at all */
1342 iihdata->DeltaMouseX_Correction = iihdata->DeltaMouseX % GetPrivIBase(IntuitionBase)->ActivePreferences.PointerTicks;
1343 iihdata->DeltaMouseY_Correction = iihdata->DeltaMouseY % GetPrivIBase(IntuitionBase)->ActivePreferences.PointerTicks;
1345 iihdata->DeltaMouseX /= GetPrivIBase(IntuitionBase)->ActivePreferences.PointerTicks;
1346 iihdata->DeltaMouseY /= GetPrivIBase(IntuitionBase)->ActivePreferences.PointerTicks;
1347 break;
1351 ie->ie_X = iihdata->DeltaMouseX + IntuitionBase->MouseX;
1352 ie->ie_Y = iihdata->DeltaMouseY + IntuitionBase->MouseY;
1353 } else {
1354 DEBUG_MOUSE(bug("[Inputhandler] Last mouse position: (%d, %d), new mouse position: (%d, %d)\n",
1355 IntuitionBase->MouseX, IntuitionBase->MouseY, ie->ie_X, ie->ie_Y));
1356 iihdata->DeltaMouseX = ie->ie_X - IntuitionBase->MouseX;
1357 iihdata->DeltaMouseY = ie->ie_Y - IntuitionBase->MouseY;
1358 DEBUG_MOUSE(bug("[InputHandler] Delta is (%d, %d)\n", iihdata->DeltaMouseX, iihdata->DeltaMouseY));
1361 /* Calculate current display size.
1362 It's determined by the first screen on this monitor.
1363 TODO: perhaps we should just ask display driver about its current display mode? */
1364 scr = FindFirstScreen(GetPrivIBase(IntuitionBase)->ActiveMonitor, IntuitionBase);
1365 if (scr)
1367 DWidth = scr->ViewPort.ColorMap->cm_vpe->DisplayClip.MaxX - scr->ViewPort.ColorMap->cm_vpe->DisplayClip.MinX + 1;
1368 DHeight = scr->ViewPort.ColorMap->cm_vpe->DisplayClip.MaxY - scr->ViewPort.ColorMap->cm_vpe->DisplayClip.MinY + 1;
1370 else
1372 /* If there's no active screen, we take 160x160 as a limit */
1373 DWidth = 160;
1374 DHeight = 160;
1377 scr = iihdata->ScreenDrag;
1378 if (scr) {
1379 WORD dx = iihdata->DeltaMouseX;
1380 WORD dy = iihdata->DeltaMouseY;
1381 WORD min, max, val;
1382 UWORD spFlags = GetPrivScreen(scr)->SpecialFlags;
1383 UWORD DragMode = GetPrivIBase(IntuitionBase)->IControlPrefs.ic_VDragModes[0];
1385 DEBUG_DRAG(bug("[InputHandler] Screen drag, delta is (%d, %d)\n", dx, dy));
1387 /* Restrict dragging to a physical display area if the driver does not allow composition or if the user wants it*/
1388 if (((spFlags & SF_HorCompose) != SF_HorCompose) || (DragMode & ICVDM_HBOUND)) {
1389 /* Calculate limits */
1390 if (scr->Width > DWidth) {
1391 min = DWidth - scr->Width;
1392 max = 0;
1393 } else {
1394 min = 0;
1395 max = DWidth - scr->Width;
1397 /* The purpose of the following complex check is to prevent jumping if the
1398 screen was positioned out of user drag limits by the program itself using
1399 ScreenPosition() or OpenScreen(). We apply restrictions in parts depending
1400 on the dragging direction.
1401 Maybe the user should also be able to drag the screen back off-display in such
1402 a case?
1403 Calculate the position we would go to */
1404 val = scr->LeftEdge + dx;
1405 /* Determine the direction */
1406 if ((dx < 0) && ((!(spFlags & SF_ComposeRight)) || (DragMode & ICVDM_LBOUND))) {
1407 /* Can we move at all in this direction ? */
1408 if (scr->LeftEdge > min) {
1409 /* If too far, restrict it */
1410 if (val < min)
1411 dx = min - scr->LeftEdge;
1412 } else
1413 /* Just don't move if we can't */
1414 dx = 0;
1415 } else if ((!(spFlags & SF_ComposeLeft)) || (DragMode & ICVDM_RBOUND)) {
1416 if (scr->LeftEdge < max) {
1417 if (val > max)
1418 dx = max - scr->LeftEdge;
1419 } else
1420 dx = 0;
1423 if (((spFlags & SF_VertCompose) != SF_VertCompose) || (DragMode & ICVDM_VBOUND)) {
1424 DEBUG_DRAG(bug("[Inputhandler] Restricting vertical drag\n"));
1425 DEBUG_DRAG(bug("[Inputhandler] Screen size: %d, display size: %d\n", scr->Height, DHeight));
1426 if (scr->Height > DHeight) {
1427 min = DHeight - scr->Height;
1428 max = 0;
1429 } else {
1430 min = 0;
1431 max = DHeight - scr->Height;
1433 DEBUG_DRAG(bug("[Inputhandler] Limits: min %d max %d\n", min, max));
1434 val = scr->TopEdge + dy;
1435 DEBUG_DRAG(bug("[Inputhandler] New position would be %d\n", val));
1436 if ((dy < 0) && ((!(spFlags & SF_ComposeBelow)) || (DragMode & ICVDM_TBOUND))) {
1437 if (scr->TopEdge > min) {
1438 if (val < min)
1439 dy = min - scr->TopEdge;
1440 } else
1441 dy = 0;
1442 } else if ((!(spFlags & SF_ComposeAbove)) || (DragMode & ICVDM_BBOUND)) {
1443 if (scr->TopEdge < max) {
1444 if (val > max)
1445 dy = max - scr->TopEdge;
1446 } else
1447 dy = 0;
1449 DEBUG_DRAG(bug("[Inputhandler] Restricted delta will be %d\n", dy));
1451 ScreenPosition(scr, SPOS_RELATIVE, dx, dy, 0, 0);
1454 /* Autoscroll the active screen */
1455 scr = IntuitionBase->ActiveScreen;
1456 if (scr && (scr->Flags & AUTOSCROLL) &&
1457 (GetPrivScreen(scr)->IMonitorNode == GetPrivIBase(IntuitionBase)->ActiveMonitor))
1459 WORD xval = scr->LeftEdge;
1460 WORD yval = scr->TopEdge;
1461 WORD min;
1463 DEBUG_AUTOSCROLL(bug("[Inputhandler] Autoscroll screen 0x%p, event at (%d, %d)\n",
1464 scr, ie->ie_X, ie->ie_Y));
1466 if ((ie->ie_X < 0) || (ie->ie_X >= DWidth)) {
1467 DEBUG_AUTOSCROLL(bug("[InputHandler] X delta: %d pixels\n", iihdata->DeltaMouseX));
1468 xval -= iihdata->DeltaMouseX;
1470 if (ie->ie_X < 0) {
1471 if (xval > 0)
1472 xval = 0;
1473 } else if (ie->ie_X >= DWidth) {
1474 min = DWidth - scr->Width;
1475 if (xval < min)
1476 xval = min;
1480 if ((ie->ie_Y < 0) || (ie->ie_Y >= DHeight)) {
1481 yval -= iihdata->DeltaMouseY;
1483 if (ie->ie_Y < 0) {
1484 /* If screen is dragged down and user touched upper screen
1485 boundary, do nothing */
1486 if (scr->TopEdge >= 0)
1487 yval = scr->TopEdge;
1488 else
1489 /* If scrolled down screen is being scrolled up, make sure it
1490 does not go over 0 */
1491 if (yval > 0)
1492 yval = 0;
1493 } else if (ie->ie_Y >= DHeight) {
1494 min = DHeight - scr->Height;
1495 if (yval < min)
1496 yval = min;
1500 if ((xval != scr->LeftEdge) || (yval != scr->TopEdge))
1501 ScreenPosition(scr, SPOS_ABSOLUTE, xval, yval, 0, 0);
1504 /* Restrict mouse coordinates to the physical display area */
1505 if (ie->ie_X >= DWidth) ie->ie_X = DWidth - 1;
1506 if (ie->ie_Y >= DHeight) ie->ie_Y = DHeight - 1;
1507 if (ie->ie_X < 0) ie->ie_X = 0;
1508 if (ie->ie_Y < 0) ie->ie_Y = 0;
1510 #ifdef SKINS
1511 if (gadget == iihdata->MasterDragGadget) {
1512 struct gpInput gpi;
1513 ULONG retval;
1515 gpi.MethodID = GM_MOVETEST;
1516 gpi.gpi_GInfo = gi;
1517 gpi.gpi_Mouse.X = ie->ie_X - gi->gi_Window->WScreen->LeftEdge;
1518 gpi.gpi_Mouse.Y = ie->ie_Y - gi->gi_Window->WScreen->TopEdge;
1519 gpi.gpi_IEvent = ie;
1521 retval = Locked_DoMethodA(gi->gi_Window, gadget, (Msg)&gpi, IntuitionBase);
1522 if (retval == MOVETEST_ADJUSTPOS)
1524 ie->ie_X = gpi.gpi_Mouse.X + gi->gi_Window->WScreen->LeftEdge;
1525 ie->ie_Y = gpi.gpi_Mouse.Y + gi->gi_Window->WScreen->TopEdge;
1529 #endif
1530 /* Do Mouse Bounding - mouse will be most restrictive of screen size or mouse bounds */
1531 if (iihdata->MouseBoundsActiveFlag) {
1532 if (ie->ie_X < iihdata->MouseBoundsLeft)
1533 ie->ie_X = iihdata->MouseBoundsLeft;
1534 else if (ie->ie_X > iihdata->MouseBoundsRight)
1535 ie->ie_X = iihdata->MouseBoundsRight;
1537 if (ie->ie_Y < iihdata->MouseBoundsTop)
1538 ie->ie_Y = iihdata->MouseBoundsTop;
1539 else if (ie->ie_Y > iihdata->MouseBoundsBottom)
1540 ie->ie_Y = iihdata->MouseBoundsBottom;
1543 /* Prevent mouse going above all screens */
1544 scr = FindHighestScreen(IntuitionBase);
1545 if (scr) {
1546 if (ie->ie_Y < scr->TopEdge)
1547 ie->ie_Y = scr->TopEdge;
1550 /* Store new mouse coords. If a screen is being dragged, lock drag point */
1551 scr = iihdata->ScreenDrag;
1552 if (scr) {
1553 IntuitionBase->MouseX = scr->LeftEdge + iihdata->ScreenDragPointX;
1554 IntuitionBase->MouseY = scr->TopEdge + iihdata->ScreenDragPointY;
1555 } else {
1556 IntuitionBase->MouseX = ie->ie_X;
1557 IntuitionBase->MouseY = ie->ie_Y;
1559 notify_mousemove_screensandwindows(IntuitionBase);
1560 #if !SINGLE_SETPOINTERPOS_PER_EVENTLOOP
1561 MySetPointerPos(IntuitionBase);
1562 #else
1563 *call_setpointerpos = TRUE;
1564 #endif
1566 screen = FindActiveScreen(IntuitionBase); /* The mouse was moved, so current screen may have changed */
1568 #ifdef SKINS
1569 if (!gadget) {
1570 if (iihdata->TitlebarOnTop)
1572 if (screen->MouseY > screen->BarHeight && GetPrivScreen(screen)->SpecialFlags & SF_AppearingBar)
1574 iihdata->TitlebarOnTop = FALSE;
1575 iihdata->TitlebarAppearTime = 0;
1577 LOCK_REFRESH(screen);
1579 MoveLayer(0, screen->BarLayer, 0, -(screen->BarHeight + 1));
1580 CheckLayers(screen, IntuitionBase);
1582 UNLOCK_REFRESH(screen);
1585 else
1587 if (screen->MouseY == 0 && GetPrivScreen(screen)->SpecialFlags & SF_AppearingBar && !MENUS_ACTIVE && !(PeekQualifier() & (IEQUALIFIER_LEFTBUTTON|IEQUALIFIER_RBUTTON|IEQUALIFIER_MIDBUTTON)))
1589 if (!(iihdata->TitlebarAppearTime))
1591 iihdata->TitlebarAppearTime = ((UQUAD)ie->ie_TimeStamp.tv_secs) * 50;
1592 iihdata->TitlebarAppearTime += ie->ie_TimeStamp.tv_micro / 20000;
1595 else
1597 iihdata->TitlebarAppearTime = 0;
1601 #endif
1602 if (MENUS_ACTIVE) {
1603 FireMenuMessage(MMCODE_EVENT, 0, ie, IntuitionBase);
1604 *keep_event = FALSE;
1605 break;
1608 if (gadget) {
1609 *keep_event = FALSE;
1611 switch (gadget->GadgetType & GTYP_GTYPEMASK)
1613 case GTYP_BOOLGADGET:
1614 case 0: //fallback for sucky gadgets
1615 /* Must be a RELVERIFY gadget */
1617 BOOL inside;
1619 inside = InsideGadget(gi->gi_Screen,
1620 gi->gi_Window,
1621 gi->gi_Requester,
1622 gadget,
1623 gi->gi_Screen->MouseX,
1624 gi->gi_Screen->MouseY);
1626 if (inside != iihdata->MouseWasInsideBoolGadget) {
1627 iihdata->MouseWasInsideBoolGadget = inside;
1629 gadget->Flags ^= GFLG_SELECTED;
1630 RefreshBoolGadgetState(gadget, w, req, IntuitionBase);
1633 break;
1635 case GTYP_PROPGADGET:
1636 HandlePropMouseMove(gadget,
1638 req,
1639 w->MouseX - gi->gi_Domain.Left - GetGadgetLeft(gadget, gi->gi_Screen, gi->gi_Window, NULL),
1640 w->MouseY - gi->gi_Domain.Top - GetGadgetTop(gadget, gi->gi_Screen, gi->gi_Window, NULL),
1641 IntuitionBase);
1643 break;
1645 case GTYP_CUSTOMGADGET:
1646 gadget = DoGPInput(gi, gadget, ie, GM_HANDLEINPUT, reuse_event, IntuitionBase);
1647 break;
1649 } /* switch GadgetType */
1651 } /* if (a gadget is currently active) */
1653 *keep_event = FALSE;
1655 if (!w)
1656 break;
1658 if (IW(w)->helpflags & HELPF_GADGETHELP && (!(PeekQualifier() & (IEQUALIFIER_LEFTBUTTON|IEQUALIFIER_RBUTTON|IEQUALIFIER_MIDBUTTON)))) {
1659 struct Window *hw;
1660 struct Gadget *g;
1662 hw = FindActiveWindow(ie, screen, 0, IntuitionBase);
1664 if (hw != w &&
1665 (!hw || !(IW(w)->helpflags & HELPF_ISHELPGROUP) ||
1666 !(IW(hw)->helpflags & HELPF_ISHELPGROUP) ||
1667 IW(w)->helpgroup != IW(hw)->helpgroup))
1670 if (iihdata->LastHelpWindow)
1672 fire_intuimessage(w,
1673 IDCMP_GADGETHELP,
1675 NULL,
1676 IntuitionBase);
1678 iihdata->LastHelpGadget = NULL;
1679 iihdata->LastHelpWindow = NULL;
1680 iihdata->HelpGadgetFindTime = 0;
1683 else
1685 g = FindHelpGadget (hw,
1686 IntuitionBase->ActiveScreen->MouseX,
1687 IntuitionBase->ActiveScreen->MouseY,
1688 IntuitionBase);
1689 if (g && g != iihdata->LastHelpGadget)
1691 if (!iihdata->LastHelpGadget)
1693 iihdata->HelpGadgetFindTime = ((UQUAD)ie->ie_TimeStamp.tv_secs) * 50;
1694 iihdata->HelpGadgetFindTime += ie->ie_TimeStamp.tv_micro / 20000;
1695 } else {
1696 if (hw == iihdata->LastHelpWindow)
1698 iihdata->HelpGadgetFindTime = ((UQUAD)ie->ie_TimeStamp.tv_secs) * 50;
1699 iihdata->HelpGadgetFindTime += ie->ie_TimeStamp.tv_micro / 20000;
1700 iihdata->HelpGadgetFindTime += 25;//smaller delay
1704 else if (g != iihdata->LastHelpGadget ||
1705 hw != iihdata->LastHelpWindow)
1707 fire_intuimessage(hw,
1708 IDCMP_GADGETHELP,
1709 0, /* Don't know what it should be */
1711 IntuitionBase);
1714 iihdata->LastHelpGadget = g;
1715 iihdata->LastHelpWindow = hw;
1717 } else {
1718 iihdata->LastHelpGadget = NULL;
1719 iihdata->LastHelpWindow = NULL;
1720 iihdata->HelpGadgetFindTime = 0;
1723 if (!(w->IDCMPFlags & IDCMP_MOUSEMOVE))
1724 break;
1726 /* Send IDCMP_MOUSEMOVE if WFLG_REPORTMOUSE is set
1727 and/or active gadget has GACT_FOLLOWMOUSE set */
1729 /* jDc: do NOT send when sizegad is pressed */
1730 if (!(w->Flags & WFLG_REPORTMOUSE)) {
1731 if (!gadget)
1732 break;
1733 if (!(gadget->Activation & GACT_FOLLOWMOUSE))
1734 break;
1735 } else {
1736 if (gadget && (gadget->GadgetType & (GTYP_SIZING|GTYP_WDRAGGING)))
1737 break;
1740 orig_ie->ie_Class = IECLASS_RAWMOUSE;
1742 /* Limit the number of IDCMP_MOUSEMOVE messages sent to intuition.
1743 note that this comes after handling gadgets, because gadgets should get all events.
1746 if (IW(w)->num_mouseevents >= IW(w)->mousequeue) {
1747 BOOL old_msg_found = FALSE;
1749 /* Mouse Queue is full, so try looking for a not
1750 yet GetMsg()ed IntuiMessage in w->UserPort
1751 trying to modify that. */
1753 Forbid();
1754 if (w->UserPort)
1756 struct IntuiMessage *im;
1758 //TODO: __AROSEXEC_SMP_ should spinlock protect access...
1759 for (im = (struct IntuiMessage *)w->UserPort->mp_MsgList.lh_TailPred;
1760 im->ExecMessage.mn_Node.ln_Pred;
1761 im = (struct IntuiMessage *)im->ExecMessage.mn_Node.ln_Pred)
1763 if ((im->Class == IDCMP_MOUSEMOVE) &&
1764 (im->IDCMPWindow == w))
1766 im->Qualifier = iihdata->ActQualifier;
1768 if (w->IDCMPFlags & IDCMP_DELTAMOVE)
1770 im->MouseX = iihdata->DeltaMouseX;
1771 im->MouseY = iihdata->DeltaMouseY;
1773 else
1775 im->MouseX = w->MouseX;
1776 im->MouseY = w->MouseY;
1778 CurrentTime(&im->Seconds, &im->Micros);
1780 old_msg_found = TRUE;
1781 break;
1784 } /* if (w->UserPort) */
1785 Permit();
1787 /* no need to send a new message if we modified
1788 an existing one ... */
1790 if (old_msg_found) break;
1792 /* ... otherwise we are in a strange situation. The mouse
1793 queue is full, but we did not find an existing MOUSEMOVE
1794 imsg in w->UserPort. So the app probably has removed
1795 an imsg from the UserPort with GetMsg but we did not get
1796 the ReplyMsg, yet. In this case we do send a new message */
1798 HandleIntuiReplyPort(iihdata, IntuitionBase);
1802 /* MouseQueue is not full, so we can send a message. We increase
1803 IntWindow->num_mouseevents which will later be decreased after
1804 the Intuition InputHandler gets the ReplyMessage from the app
1805 and handles it in HandleIntuiReplyPort() */
1807 if (ih_fire_intuimessage(w, IDCMP_MOUSEMOVE, IECODE_NOBUTTON, w, IntuitionBase))
1808 IW(w)->num_mouseevents++;
1810 break;
1812 } /* case IECODE_NOBUTTON */
1813 } /* switch (ie->ie_Code) (what button was pressed ?) */
1815 return gadget;
1818 /****************************************************************************************/
1820 AROS_UFH2(struct InputEvent *, IntuiInputHandler,
1821 AROS_UFHA(struct InputEvent *, oldchain, A0),
1822 AROS_UFHA(struct IIHData *, iihdata, A1)
1825 AROS_USERFUNC_INIT
1827 struct InputEvent *ie, *orig_ie, *next_ie, stackie;
1828 struct Gadget *gadget = NULL;
1829 struct IntuitionBase *IntuitionBase = iihdata->IntuitionBase;
1830 struct Library *KeymapBase = GetPrivIBase(IntuitionBase)->KeymapBase;
1831 struct Screen *screen;
1832 //ULONG lock;
1833 struct GadgetInfo *gi = &iihdata->GadgetInfo;
1834 BOOL reuse_event, ie_used;
1835 struct Window *w;
1836 struct Requester *req;
1837 ULONG stitlebarhit = 0;
1838 #if 0 /* Toolbox is broken-as-designed */
1839 struct Window *toolbox;
1840 struct GadgetInfo *boxgi = &iihdata->BoxGadgetInfo;
1841 struct Gadget *boxgadget = NULL;
1842 #endif
1843 #if SINGLE_SETPOINTERPOS_PER_EVENTLOOP
1844 BOOL call_setpointerpos = FALSE;
1845 #endif
1847 D(bug("Inside intuition inputhandler, active window=%p\n", IntuitionBase->ActiveWindow));
1848 ObtainSemaphore(&GetPrivIBase(IntuitionBase)->InputHandlerLock);
1850 if (!iihdata->InputDeviceTask) iihdata->InputDeviceTask = FindTask(NULL);
1852 /* Then free generated InputEvents done in the previous round */
1854 FreeGeneratedInputEvents(iihdata);
1856 /* First handle IntuiMessages which were replied back to the IntuiReplyPort
1857 by the apps */
1859 HandleIntuiReplyPort(iihdata, IntuitionBase);
1861 /* Handle action messages */
1863 HandleIntuiActions(iihdata, IntuitionBase);
1865 /* Now handle the input events */
1867 ie = &stackie;
1868 reuse_event = FALSE;
1869 next_ie = oldchain;
1871 /* shut up the compiler */
1872 orig_ie = next_ie;
1873 ie_used = FALSE;
1875 gadget = iihdata->ActiveGadget;
1877 while (reuse_event || next_ie)
1879 struct Window *old_w;
1880 BOOL keep_event = TRUE;
1881 BOOL new_active_window = FALSE;
1882 Object *newmonitor = GetPrivIBase(IntuitionBase)->NewMonitor;
1884 /* Process hosted display activation event (if any).
1885 This is experimental. If this works badly, we'll possibly have to put it into
1886 input events queue */
1887 if (newmonitor) {
1888 DEBUG_MONITOR(bug("[Inputhandler] Activating monitor 0x%p\n", newmonitor));
1889 GetPrivIBase(IntuitionBase)->NewMonitor = NULL;
1890 ActivateMonitor(newmonitor, -1, -1, IntuitionBase);
1891 iihdata->SwitchedMonitor = TRUE;
1894 if (!reuse_event)
1896 *ie = *next_ie;
1897 orig_ie = next_ie;
1898 next_ie = ie->ie_NextEvent;
1899 ie_used = FALSE;
1902 D(bug("iih: Handling event of class %d, code %d\n", ie->ie_Class, ie->ie_Code));
1903 reuse_event = FALSE;
1905 /* If the monitor has been changed, this possibly happened because of mouse click in
1906 its display window. In such a case we have to update current mouse coordinates
1907 from the first absolute mouse event. Otherwise input will misbehave. */
1908 if (iihdata->SwitchedMonitor && (ie->ie_Class == IECLASS_RAWMOUSE)) {
1909 iihdata->SwitchedMonitor = FALSE;
1910 if (!(ie->ie_Qualifier & IEQUALIFIER_RELATIVEMOUSE)) {
1911 DEBUG_MONITOR(bug("[Inputhandler] Adjusting coordinates to (%d, %d)\n", ie->ie_X, ie->ie_Y));
1912 IntuitionBase->MouseX = ie->ie_X;
1913 IntuitionBase->MouseY = ie->ie_Y;
1914 notify_mousemove_screensandwindows(IntuitionBase);
1918 /* new event, we need to reset this */
1919 screen = FindActiveScreen(IntuitionBase);
1920 iihdata->ActEventTablet = 0;
1922 /* Set the timestamp in IntuitionBase */
1924 IntuitionBase->Seconds = ie->ie_TimeStamp.tv_secs;
1925 IntuitionBase->Micros = ie->ie_TimeStamp.tv_micro;
1927 #if 0 /* toolbox stuff disabled. broken. calling LockLayerinfo() for every event is broken. deadlocks */
1928 /* Use event to find the active window */
1930 toolbox = GetToolBoxWindow(ie, screen, IntuitionBase);
1932 if (toolbox)
1934 /* Do ToolBox Window Actions */
1935 /* ToolBox Windows supports only a subset of IECLASS Actions */
1936 switch (ie->ie_Class) {
1938 case IECLASS_RAWMOUSE:
1939 boxgadget = Process_RawMouse(ie, iihdata, screen, toolbox, boxgadget, boxgi, 0, FALSE, TRUE,
1940 orig_ie, &keep_event, &reuse_event,
1941 #if SINGLE_SETPOINTERPOS_PER_EVENTLOOP
1942 &call_setpointerpos,
1943 #endif
1944 IntuitionBase);
1945 break;
1947 } /* switch (ie->ie_Class) */
1948 } /* if (toolbox) */
1949 #endif
1951 w = IntuitionBase->ActiveWindow;
1953 if (!MENUS_ACTIVE && !SYSGADGET_ACTIVE)
1955 /* lock = LockIBase(0UL); */
1957 old_w = w;
1958 if (ie->ie_Class == IECLASS_RAWMOUSE && ie->ie_Code == SELECTDOWN)
1960 w = FindActiveWindow(ie, screen, &stitlebarhit, IntuitionBase);
1961 DEBUG_CLICK(bug("iih:New active window: %p\n", w));
1965 if ( w != old_w )
1967 if (w)
1969 DEBUG_WINDOW(bug("Activating new window (title %s)\n", w->Title ? w->Title : "<noname>"));
1971 DEBUG_WINDOW(bug("Window activated\n"));
1973 else
1975 DEBUG_WINDOW(bug("Making active window inactive. Now there's no active window\n"));
1977 new_active_window = TRUE;
1978 iihdata->NewActWindow = w;
1981 /* UnlockIBase(lock); */
1983 if (new_active_window)
1985 if (gadget && w &&
1986 (!(GetPrivScreen(w->WScreen)->MenuVerifyMsgCount)) &&
1987 (!(MENUS_ACTIVE)) && (!(SYSGADGET_ACTIVE)))
1989 switch (gadget->GadgetType & GTYP_GTYPEMASK)
1992 case GTYP_CUSTOMGADGET:
1994 struct gpGoInactive gpgi;
1996 gpgi.MethodID = GM_GOINACTIVE;
1997 gpgi.gpgi_GInfo = gi;
1998 gpgi.gpgi_Abort = 1;
2000 Locked_DoMethodA(gi->gi_Window, gadget, (Msg)&gpgi, IntuitionBase);
2001 break;
2004 case GTYP_STRGADGET:
2005 gadget->Flags &= ~GFLG_SELECTED;
2006 RefreshStrGadget(gadget, gi->gi_Window, gi->gi_Requester, IntuitionBase);
2007 break;
2009 case GTYP_BOOLGADGET:
2010 /* That a bool gadget is active here can only happen
2011 if user used LMB to activate gadget and LAMIGA + LALT
2012 to activate other window, or viceversa */
2013 /* The gadget must be a RELVERIFY one */
2014 if (!(gadget->Activation & GACT_TOGGLESELECT))
2016 BOOL inside;
2018 inside = InsideGadget(gi->gi_Screen, gi->gi_Window,
2019 gi->gi_Requester, gadget,
2020 gi->gi_Screen->MouseX, gi->gi_Screen->MouseY);
2022 if (inside)
2024 gadget->Flags &= ~GFLG_SELECTED;
2025 RefreshBoolGadgetState(gadget, gi->gi_Window,
2026 gi->gi_Requester, IntuitionBase);
2029 break;
2031 case GTYP_PROPGADGET:
2032 /* That a prop gadget is active here can only happen
2033 if user used LMB to activate gadget and LAMIGA + LALT
2034 to activate other window, or viceversa */
2036 HandlePropSelectUp(gadget, gi->gi_Window, NULL, IntuitionBase);
2037 if (gadget->Activation & GACT_RELVERIFY)
2039 ih_fire_intuimessage(gi->gi_Window,
2040 IDCMP_GADGETUP,
2042 gadget,
2043 IntuitionBase);
2045 break;
2047 } /* switch (gadget->GadgetType & GTYP_GTYPEMASK) */
2049 gadget->Activation &= ~GACT_ACTIVEGADGET;
2050 iihdata->ActiveGadget = NULL;
2051 gadget = NULL;
2054 /* ActivateWindow works if w = NULL */
2055 /* jacaDcaps: some gui toolkits (die reaction, die!) close the window opened by a boopsi gadget when
2056 it gets hit with lmb, so we need to check if the new active window does not go away by
2057 performing GM_GOINACTIVE on the gadget. NOTE: CloseWindow's part performed on input.device context
2058 clears the iihdata->NewActWindow if it's the actually closed one. */
2059 if (w == iihdata->NewActWindow)
2061 ActivateWindow(w);
2063 else
2065 w = IntuitionBase->ActiveWindow;
2066 new_active_window = FALSE;
2067 ie->ie_Class = IECLASS_NULL; //lose the event, otherwise the gadget will get activated again ;)
2070 iihdata->NewActWindow = 0;
2072 } /* if (new_active_window) */
2074 } /* if (!MENUS_ACTIVE) */
2076 req = NULL;
2077 if (w)
2079 req = w->FirstRequest;
2082 D(bug("[Inputhandler] Screen 0x%p Window 0x%p Requester 0x%p gadget 0x%p\n", screen, w, req, gadget));
2084 switch (ie->ie_Class) {
2085 case IECLASS_POINTERPOS:
2086 ie->ie_SubClass = IESUBCLASS_COMPATIBLE;
2087 /* fall through */
2089 case IECLASS_NEWPOINTERPOS:
2090 switch (ie->ie_SubClass)
2092 case IESUBCLASS_COMPATIBLE:
2093 ie->ie_Code = IECODE_NOBUTTON;
2094 break;
2096 case IESUBCLASS_PIXEL:
2098 struct IEPointerPixel *pp = ie->ie_EventAddress;
2100 ie->ie_X = pp->iepp_Position.X + pp->iepp_Screen->LeftEdge;
2101 ie->ie_Y = pp->iepp_Position.Y + pp->iepp_Screen->TopEdge;
2103 ActivateMonitor(GetPrivScreen(pp->iepp_Screen)->IMonitorNode, ie->ie_X, ie->ie_Y, IntuitionBase);
2105 ie->ie_Class = IECLASS_RAWMOUSE; /* otherwise a lot of code would ignore this message */
2106 ie->ie_Code = IECODE_NOBUTTON;
2107 break;
2109 case IESUBCLASS_TABLET:
2111 //unsupported - does anything use it anyway? ;)
2113 ie->ie_Code = 0;
2114 break;
2116 case IESUBCLASS_NEWTABLET:
2118 struct IENewTablet *nt = (struct IENewTablet *)ie->ie_EventAddress;
2120 if (nt)
2122 iihdata->ActEventTablet = nt; //cache this
2123 ie->ie_X = (screen->Width * nt->ient_TabletX) / nt->ient_RangeX;
2124 ie->ie_Y = (screen->Height * nt->ient_TabletY) / nt->ient_RangeY;
2126 ie->ie_Class = IECLASS_RAWMOUSE;
2128 break;
2130 default:
2131 ie->ie_Code = 0;
2132 break;
2134 /* fall through */
2136 case IECLASS_RAWMOUSE:
2137 gadget = Process_RawMouse(ie, iihdata, screen, w, gadget, gi, stitlebarhit, new_active_window, FALSE,
2138 orig_ie, &keep_event, &reuse_event,
2139 #if SINGLE_SETPOINTERPOS_PER_EVENTLOOP
2140 &call_setpointerpos,
2141 #endif
2142 IntuitionBase);
2143 keep_event = TRUE;
2144 break;
2146 case IECLASS_RAWKEY:
2147 /* release events go only to gadgets and windows who
2148 have not set IDCMP_VANILLAKEY */
2150 DEBUG_HANDLER(dprintf("Handler: IECLASS_RAWKEY\n"));
2151 DEBUG_KEY(dprintf("Handler: Qual 0x%lx\n",iihdata->ActQualifier));
2153 iihdata->ActQualifier &= ~(KEY_QUALIFIERS | IEQUALIFIER_REPEAT);
2154 iihdata->ActQualifier |= (ie->ie_Qualifier & (KEY_QUALIFIERS | IEQUALIFIER_REPEAT));
2156 DEBUG_KEY(dprintf("Handler: real Qual 0x%lx\n",iihdata->ActQualifier));
2158 /* Keyboard mouse emulation and screen switching */
2161 UWORD code = ie->ie_Code & ~IECODE_UP_PREFIX;
2162 DEBUG_KEY(dprintf("Handler: code 0x%lx\n",code));
2164 /* Left Amiga + N/M screen switching shortcut */
2165 if ((ie->ie_Qualifier & IEQUALIFIER_LCOMMAND) && (code == RAWKEY_N || code == RAWKEY_M)) {
2166 if (!(ie->ie_Qualifier & IEQUALIFIER_REPEAT) && !(ie->ie_Code & IECODE_UP_PREFIX)) {
2167 if (code == RAWKEY_N)
2168 WBenchToFront();
2169 else if (code == RAWKEY_M)
2170 ScreenToBack(IntuitionBase->FirstScreen);
2172 keep_event = FALSE;
2173 break;
2176 /* Mouse button emulation: LALT + LAMIGA = LBUTTON, RALT + RAMIGA = RBUTTON */
2177 if ((code == RAWKEY_LAMIGA) ||
2178 (code == RAWKEY_LALT) ||
2179 (code == RAWKEY_RAMIGA) ||
2180 (code == RAWKEY_RALT))
2182 DEBUG_KEY(dprintf("Handler: KeyMouseEmul\n"));
2183 iihdata->PrevKeyMouseState = iihdata->ActKeyMouseState;
2184 iihdata->ActKeyMouseState = 0;
2185 if ((ie->ie_Qualifier & (IEQUALIFIER_LCOMMAND | IEQUALIFIER_LALT)) == (IEQUALIFIER_LCOMMAND | IEQUALIFIER_LALT))
2187 iihdata->ActKeyMouseState |= IEQUALIFIER_LEFTBUTTON;
2189 if ((ie->ie_Qualifier & (IEQUALIFIER_RCOMMAND | IEQUALIFIER_RALT)) == (IEQUALIFIER_RCOMMAND | IEQUALIFIER_RALT))
2191 iihdata->ActKeyMouseState |= IEQUALIFIER_RBUTTON;
2194 if ((iihdata->ActKeyMouseState & IEQUALIFIER_LEFTBUTTON) != (iihdata->PrevKeyMouseState & IEQUALIFIER_LEFTBUTTON))
2196 orig_ie->ie_Class = IECLASS_RAWMOUSE;
2197 orig_ie->ie_SubClass = 0;
2198 orig_ie->ie_Code = (iihdata->ActKeyMouseState & IEQUALIFIER_LEFTBUTTON) ? IECODE_LBUTTON : IECODE_LBUTTON | IECODE_UP_PREFIX;
2199 orig_ie->ie_X = 0;
2200 orig_ie->ie_Y = 0;
2201 *ie = *orig_ie;
2203 reuse_event = TRUE;
2204 break;
2207 if ((iihdata->ActKeyMouseState & IEQUALIFIER_RBUTTON) != (iihdata->PrevKeyMouseState & IEQUALIFIER_RBUTTON))
2209 orig_ie->ie_Class = IECLASS_RAWMOUSE;
2210 orig_ie->ie_SubClass = 0;
2211 orig_ie->ie_Code = (iihdata->ActKeyMouseState & IEQUALIFIER_RBUTTON) ? IECODE_RBUTTON : IECODE_RBUTTON | IECODE_UP_PREFIX;
2212 orig_ie->ie_X = 0;
2213 orig_ie->ie_Y = 0;
2214 *ie = *orig_ie;
2216 reuse_event = TRUE;
2217 break;
2220 } /* if key is one of LAMIGA/LALT/RAMIGA/RALT */
2222 if ((iihdata->ActQualifier & (IEQUALIFIER_LCOMMAND | IEQUALIFIER_RCOMMAND)) &&
2223 ((ie->ie_Code == RAWKEY_UP) ||
2224 (ie->ie_Code == RAWKEY_DOWN) ||
2225 (ie->ie_Code == RAWKEY_LEFT) ||
2226 (ie->ie_Code == RAWKEY_RIGHT)))
2228 static BYTE const xmap[] = { 0, 0, 1, -1};
2229 static BYTE const ymap[] = {-1, 1, 0, 0};
2230 WORD shift;
2232 shift = (iihdata->ActQualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) ? 40 : 1;
2234 /* Mouse Move Emulation */
2236 orig_ie->ie_Class = IECLASS_RAWMOUSE;
2237 orig_ie->ie_SubClass = 0;
2238 orig_ie->ie_Code = IECODE_NOBUTTON;
2239 orig_ie->ie_Qualifier = IEQUALIFIER_RELATIVEMOUSE;
2240 orig_ie->ie_X = xmap[code - RAWKEY_UP] * shift;
2241 orig_ie->ie_Y = ymap[code - RAWKEY_UP] * shift;
2243 *ie = *orig_ie;
2244 reuse_event = TRUE;
2245 break;
2248 } /**/
2250 /* End Keyboard mouse emulation */
2252 if (MENUS_ACTIVE)
2254 DEBUG_KEY(dprintf("Handler: FireMenuMessage\n"));
2255 FireMenuMessage(MMCODE_EVENT, 0, ie, IntuitionBase);
2256 keep_event = FALSE;
2257 break;
2260 /* Hotkeys processing */
2261 #ifdef SKINS
2263 ULONG result;
2265 if (!(ie->ie_Code & IECODE_UP_PREFIX))
2266 if ((result = RunHotkeys(ie,IntuitionBase)))
2268 if (result == RUNHOTREUSE)
2270 reuse_event = TRUE;
2272 else
2274 keep_event = FALSE;
2276 break;
2278 w = IntuitionBase->ActiveWindow;
2280 #endif
2282 if ( keep_event &&
2283 ((!(ie->ie_Code & IECODE_UP_PREFIX)) ||
2284 gadget ||
2285 (w && ((w->IDCMPFlags & IDCMP_VANILLAKEY) == 0)) ))
2287 if (gadget)
2289 keep_event = FALSE;
2291 DEBUG_KEY(dprintf("Handler: Gadget 0x%lx active\n",gadget));
2292 DEBUG_KEY(dprintf("Handler: GadgetID 0x%lx UserData 0x%lx\n",
2293 gadget->GadgetID,
2294 gadget->UserData));
2295 DEBUG_KEY(dprintf("Handler: GadgetType 0x%lx Flags 0x%lx Activation 0x%lx\n",
2296 gadget->GadgetType,
2297 gadget->Flags,
2298 gadget->Activation));
2299 DEBUG_KEY(dprintf("Handler: MoreFlags 0x%lx\n",
2300 ((struct ExtGadget*)gadget)->MoreFlags));
2302 switch (gadget->GadgetType & GTYP_GTYPEMASK)
2304 case GTYP_STRGADGET:
2306 UWORD imsgcode;
2307 ULONG ret = HandleStrInput(gadget, gi, ie, &imsgcode,
2308 IntuitionBase);
2310 DEBUG_KEY(dprintf("Handler: Key GTYP_STRGADGET ret 0x%lx\n",ret));
2311 if (ret & (SGA_END | SGA_NEXTACTIVE | SGA_PREVACTIVE))
2313 if (gadget->Activation & GACT_RELVERIFY)
2315 DEBUG_KEY(dprintf("Handler: GACT_RELVERIFY\n"));
2316 ih_fire_intuimessage(w,
2317 IDCMP_GADGETUP,
2318 imsgcode,
2319 gadget,
2320 IntuitionBase);
2322 if (req && gadget->Activation & GACT_ENDGADGET)
2324 DEBUG_KEY(dprintf("Handler: GACT_ENDGADGET\n"));
2325 EndRequest(req, w);
2327 req = w->FirstRequest;
2328 ret = 0;
2332 if ((gadget->Flags & GFLG_TABCYCLE) && (ret & SGA_NEXTACTIVE))
2334 gadget = FindCycleGadget(w, req, gadget, GMR_NEXTACTIVE);
2335 DEBUG_KEY(dprintf("Handler: TabCycle next gadget 0x%lx\n",gadget));
2337 else if ((gadget->Flags & GFLG_TABCYCLE) && (ret & SGA_PREVACTIVE))
2339 gadget = FindCycleGadget(w, req, gadget, GMR_PREVACTIVE);
2340 DEBUG_KEY(dprintf("Handler: TabCycle prev gadget 0x%lx\n",gadget));
2342 else
2344 gadget = NULL;
2347 if (gadget)
2349 gadget = DoActivateGadget(w, req, gadget, IntuitionBase);
2352 } /* if (ret & (SGA_END | SGA_NEXTACTIVE | SGA_PREVACTIVE)) */
2354 break;
2357 case GTYP_CUSTOMGADGET:
2358 DEBUG_KEY(dprintf("Handler: GTYP_CUSTOMGADGET\n"));
2359 DEBUG_KEY(dprintf("Handler: send GM_HANDLEINPUT\n"));
2360 gadget = DoGPInput(gi,
2361 gadget,
2363 GM_HANDLEINPUT,
2364 &reuse_event,
2365 IntuitionBase);
2366 DEBUG_KEY(dprintf("Handler: reuse %ld\n",reuse_event));
2367 break;
2369 } /* switch (gadget type) */
2371 } /* if (a gadget is currently active) */
2372 else if (w && (!req || req->Flags & NOISYREQ))
2374 BOOL menushortcut = FALSE;
2376 DEBUG_KEY(dprintf("Handler: No Gadget active\n"));
2377 DEBUG_KEY(dprintf("Handler: Qualifier 0x%lx WinFlags 0x%lx IDCMP 0x%lx\n",ie->ie_Qualifier,w->Flags,w->IDCMPFlags));
2379 if ((ie->ie_Qualifier & IEQUALIFIER_RCOMMAND) &&
2380 (!(w->Flags & WFLG_RMBTRAP)) &&
2381 (w->IDCMPFlags & IDCMP_MENUPICK))
2383 struct Menu *strip = 0;
2385 DEBUG_KEY(dprintf("Handler: MenuKey\n"));
2386 ObtainSemaphore(&GetPrivIBase(IntuitionBase)->MenuLock);
2388 strip = w->MenuStrip;
2390 if (((struct IntWindow *)w)->menulendwindow)
2392 strip = ((struct IntWindow *)w)->menulendwindow->MenuStrip;
2395 DEBUG_KEY(dprintf("Handler: MenuStrip 0x%lx\n",strip));
2396 if (strip)
2398 UBYTE key;
2400 if (MapRawKey(ie, &key, 1, NULL) == 1)
2402 UWORD menucode;
2404 menucode = FindMenuShortCut(strip, key, TRUE, IntuitionBase);
2406 DEBUG_KEY(dprintf("Handler: menucode 0x%lx\n",menucode));
2408 if (menucode != MENUNULL)
2410 DEBUG_KEY(dprintf("Handler: build menuevent\n"));
2411 ie->ie_Class = IECLASS_MENU;
2412 ie->ie_SubClass = IESUBCLASS_MENUSTOP;
2413 ie->ie_EventAddress = w;
2414 ie->ie_Code = menucode;
2416 reuse_event = TRUE;
2417 menushortcut = TRUE;
2419 MENUS_ACTIVE = TRUE;
2420 iihdata->MenuWindow = w;
2423 else
2425 DEBUG_KEY(dprintf("Handler: MapRawKey failed\n"));
2428 if (!menushortcut) /* !! */
2429 ReleaseSemaphore(&GetPrivIBase(IntuitionBase)->MenuLock);
2431 } /* if could be a menu short cut */
2432 else
2433 if ((ie->ie_Qualifier & IEQUALIFIER_RCOMMAND) &&
2434 (!(w->IDCMPFlags & IDCMP_MENUPICK)))
2436 struct Menu *strip = 0;
2437 struct Window *window = w;
2439 /* not sure here about RMBTRAP */
2440 DEBUG_KEY(dprintf("Handler: no idcmp, create a MENULIST idcmp\n"));
2442 ObtainSemaphore(&GetPrivIBase(IntuitionBase)->MenuLock);
2444 strip = w->MenuStrip;
2446 if (((struct IntWindow *)w)->menulendwindow)
2448 strip = ((struct IntWindow *)w)->menulendwindow->MenuStrip;
2449 window = ((struct IntWindow *)w)->menulendwindow;
2452 DEBUG_KEY(dprintf("Handler: MenuStrip 0x%lx\n",strip));
2453 if (strip)
2455 UBYTE key;
2457 if (MapRawKey(ie, &key, 1, NULL) == 1)
2459 UWORD menucode;
2461 menucode = FindMenuShortCut(strip, key, TRUE, IntuitionBase);
2463 DEBUG_KEY(dprintf("Handler: menucode 0x%lx\n",menucode));
2465 if (menucode != MENUNULL)
2467 DEBUG_KEY(dprintf("Handler: build menuevent\n"));
2468 ih_fire_intuimessage(window,
2469 IDCMP_MENUPICK,
2470 menucode,
2471 ie->ie_position.ie_addr, /* ie_dead.ie_prev[1|2]Down[Code|Qual]. 64 bit machines!? */
2472 IntuitionBase);
2473 keep_event = FALSE;
2474 menushortcut = TRUE;
2477 else
2479 DEBUG_KEY(dprintf("Handler: MapRawKey failed\n"));
2482 ReleaseSemaphore(&GetPrivIBase(IntuitionBase)->MenuLock);
2483 } /* if could be a menu short but current window has no idcmp cut */
2485 if (menushortcut)
2487 DEBUG_KEY(dprintf("Handler: menu shortcut..break\n"));
2488 break;
2491 /* This is a regular RAWKEY event (no gadget taking care
2492 of it...). */
2494 if (iihdata->ActQualifier & IEQUALIFIER_REPEAT)
2496 /* don't send repeat key events if repeatqueue is full */
2497 if (IW(w)->num_repeatevents >= IW(w)->repeatqueue)
2499 DEBUG_KEY(dprintf("Handler: RepeatEvents full..don't send more\n"));
2500 break;
2504 if (w->IDCMPFlags & IDCMP_VANILLAKEY)
2506 UBYTE keyBuffer;
2508 DEBUG_KEY(dprintf("Handler: VANILLAKEY\n"));
2509 // DEBUG_KEY(dprintf("Handler: MapRawKey ie 0x%lx KeyMapBase 0x%lx IntutionBase 0x%lx\n",ie,KeymapBase,IntuitionBase));
2511 if (MapRawKey(ie, &keyBuffer, 1, NULL) == 1)
2513 DEBUG_KEY(dprintf("Handler: send VANILLAKEY msg\n"));
2514 ih_fire_intuimessage(w,
2515 IDCMP_VANILLAKEY,
2516 keyBuffer,
2517 ie->ie_position.ie_addr, /* ie_dead.ie_prev[1|2]Down[Code|Qual]. 64 bit machines!? */
2518 IntuitionBase);
2519 DEBUG_KEY(dprintf("Handler: done\n"));
2520 break;
2523 /* If the event mapped to more than one byte, it is not
2524 a legal VANILLAKEY, so we send it as the original
2525 RAWKEY event. */
2529 if (w->IDCMPFlags & IDCMP_RAWKEY)
2531 DEBUG_KEY(dprintf("Handler: send IDCMP_RAWKEY Qual 0x%lx Code 0x%lx addr 0x%lx Event\n",
2532 ie->ie_Qualifier,ie->ie_Code,ie->ie_position.ie_addr));
2533 ih_fire_intuimessage(w,
2534 IDCMP_RAWKEY,
2535 ie->ie_Code,
2536 ie->ie_position.ie_addr, /* ie_dead.ie_prev[1|2]Down[Code|Qual]. 64 bit machine!? */
2537 IntuitionBase);
2538 keep_event = FALSE;
2541 DEBUG_KEY(dprintf("Handler: done\n"));
2542 } /* regular RAWKEY */
2545 break; /* case IECLASS_RAWKEY */
2547 case IECLASS_TIMER:
2548 if (iihdata->MouseBoundsKillTimer)
2550 iihdata->MouseBoundsKillTimer--;
2551 if (iihdata->MouseBoundsKillTimer == 0)
2553 iihdata->MouseBoundsActiveFlag = FALSE;
2557 if (GetPrivIBase(IntuitionBase)->PointerDelay)
2559 ULONG lock = LockIBase(0);
2561 if (--GetPrivIBase(IntuitionBase)->PointerDelay == 0)
2563 struct SharedPointer *shared_pointer;
2564 struct Window *window = IntuitionBase->ActiveWindow;
2565 struct IntScreen *scr;
2567 DEBUG_POINTER(dprintf("InputHandler: PointerDelay\n"));
2568 DEBUG_POINTER(dprintf("InputHandler: Window 0x%lx\n",
2569 window));
2571 if (window)
2573 Object *pointer = ((struct IntWindow *)window)->pointer;
2575 DEBUG_POINTER(dprintf("InputHandler: Pointer 0x%lx\n",
2576 pointer));
2577 scr = GetPrivScreen(window->WScreen);
2578 if (scr)
2580 DEBUG_POINTER(dprintf("InputHandler: Screen 0x%lx\n",
2581 scr));
2582 if (pointer == NULL)
2584 pointer = GetPrivIBase(IntuitionBase)->DefaultPointer;
2587 if (((struct IntWindow *)window)->busy)
2589 pointer = GetPrivIBase(IntuitionBase)->BusyPointer;
2592 GetAttr(POINTERA_SharedPointer, pointer, (IPTR *) &shared_pointer);
2594 DEBUG_POINTER(dprintf("InputHandler: scr 0x%lx pointer 0x%lx shared_pointer 0x%lx\n",
2595 scr, pointer, shared_pointer));
2596 DEBUG_POINTER(dprintf("InputHandler: sprite 0x%lx\n",
2597 shared_pointer->sprite));
2599 if (DoMethod(scr->IMonitorNode, MM_SetPointerShape, shared_pointer))
2601 ObtainSharedPointer(shared_pointer, IntuitionBase);
2602 ReleaseSharedPointer(scr->Pointer, IntuitionBase);
2603 scr->Pointer = shared_pointer;
2604 if (window)
2606 window->XOffset = shared_pointer->xoffset;
2607 window->YOffset = shared_pointer->yoffset;
2610 else
2612 DEBUG_POINTER(dprintf("InputHandler: can't set pointer.\n"));
2615 else
2617 DEBUG_POINTER(dprintf("InputHandler: no screen.\n"));
2620 else
2622 DEBUG_POINTER(dprintf("InputHandler: no window.\n"));
2626 UnlockIBase(lock);
2629 if (GetPrivIBase(IntuitionBase)->MenuVerifyScreen)
2631 struct IntScreen *scr = GetPrivIBase(IntuitionBase)->MenuVerifyScreen;
2633 if ((--scr->MenuVerifyTimeOut) <= 0)
2635 struct InputEvent ie;
2637 /* currently we ONLY need the menu open time ! */
2638 ie.ie_TimeStamp.tv_secs = IntuitionBase->Seconds;
2639 ie.ie_TimeStamp.tv_micro = IntuitionBase->Micros;
2641 if (FireMenuMessage(MMCODE_START, scr->MenuVerifyActiveWindow, &ie, IntuitionBase))
2643 /* This lock will be released only when the user is
2644 done with menus = when IECLASS_MENU + IESUBCLASS_MENUSTOP
2645 event arrives (generated by MenuHandler task) */
2647 ObtainSemaphore(&GetPrivIBase(IntuitionBase)->MenuLock);
2648 iihdata->MenuWindow = scr->MenuVerifyActiveWindow;
2649 MENUS_ACTIVE = TRUE;
2652 scr->MenuVerifyActiveWindow = NULL;
2653 scr->MenuVerifyTimeOut = 0;
2654 scr->MenuVerifyMsgCount = 0;
2655 scr->MenuVerifySeconds = 0;
2656 scr->MenuVerifyMicros = 0;
2657 GetPrivIBase(IntuitionBase)->MenuVerifyScreen = NULL;
2660 else if (MENUS_ACTIVE)
2662 FireMenuMessage(MMCODE_EVENT, 0, ie, IntuitionBase);
2663 keep_event = FALSE;
2664 break;
2667 #ifdef SKINS
2668 if (screen->MouseY <= screen->BarHeight && GetPrivScreen(screen)->SpecialFlags & SF_AppearingBar && !iihdata->TitlebarOnTop && iihdata->TitlebarAppearTime)
2670 UQUAD currenttime = (((UQUAD)ie->ie_TimeStamp.tv_secs) * 50) + (UQUAD)(ie->ie_TimeStamp.tv_micro / 20000);
2671 if (currenttime >= iihdata->TitlebarAppearTime + 10)
2673 iihdata->TitlebarOnTop = TRUE;
2674 iihdata->TitlebarAppearTime = 0;
2676 LOCK_REFRESH(screen);
2678 MoveLayer(0, screen->BarLayer, 0, screen->BarHeight + 1);
2679 UpfrontLayer(0, screen->BarLayer);
2680 CheckLayers(screen, IntuitionBase);
2682 UNLOCK_REFRESH(screen);
2685 #endif
2688 UQUAD currenttime = (((UQUAD)ie->ie_TimeStamp.tv_secs) * 50) + (UQUAD)(ie->ie_TimeStamp.tv_micro / 20000);
2689 #define SECONDS(x) (x*50)
2690 if (iihdata->HelpGadgetFindTime && (currenttime >= iihdata->HelpGadgetFindTime + SECONDS(1)))
2692 struct Gadget *lhg = iihdata->LastHelpGadget;
2693 fire_intuimessage(iihdata->LastHelpWindow,
2694 IDCMP_GADGETHELP,
2695 lhg ? lhg->GadgetID : 0, /* Don't know what it should be */
2696 lhg,
2697 IntuitionBase);
2698 iihdata->HelpGadgetFindTime = 0;
2702 if (gadget)
2704 if (IS_BOOPSI_GADGET(gadget))
2706 gadget = DoGPInput(gi, gadget, ie, GM_HANDLEINPUT, &reuse_event, IntuitionBase);
2709 } /* if (gadget) */
2711 #if USE_NEWDISPLAYBEEP
2713 if (GetPrivIBase(IntuitionBase)->BeepingScreens)
2715 ULONG lock;
2716 struct Screen *scr;
2718 lock = LockIBase(0);
2720 for (scr = IntuitionBase->FirstScreen;
2721 scr && GetPrivIBase(IntuitionBase)->BeepingScreens;
2722 scr = scr->NextScreen)
2724 if ((scr->Flags & BEEPING) &&
2725 !GetPrivScreen(scr)->BeepingCounter--)
2727 GetPrivIBase(IntuitionBase)->BeepingScreens--;
2728 scr->Flags &= (UWORD) ~BEEPING;
2730 /* if (GetBitMapAttr(scr->RastPort.BitMap, BMA_DEPTH) <= 8)
2731 // visual beep on CLUT-screen
2733 // SetRGB4 (&screen->ViewPort, 0, scr->SaveColor0 & 0x000F, (scr->SaveColor0 & 0x00F0) >> 4, (scr->SaveColor0 & 0x0F00) >> 8);
2734 SetRGB32 (&scr->ViewPort, 0,
2735 GetPrivScreen(scr)->DisplayBeepColor0[0],
2736 GetPrivScreen(scr)->DisplayBeepColor0[1],
2737 GetPrivScreen(scr)->DisplayBeepColor0[2]
2740 else
2741 // visual beep on hi- and truecolor screens
2743 RenderScreenBar(scr, FALSE, IntuitionBase);
2746 RenderScreenBar(scr, FALSE, IntuitionBase);
2750 UnlockIBase(lock);
2752 #endif /* USE_NEWDISPLAYBEEP */
2754 if (!w) break;
2756 /* Send INTUITICK msg only if app already replied the last INTUITICK msg */
2757 if (w->Flags & WFLG_WINDOWTICKED) break;
2759 if (w->IDCMPFlags & IDCMP_INTUITICKS)
2761 /* Set the WINDOWTICKED flag, it will be cleared again when the app
2762 replies back the msg and the InputHandler handles the replymsg
2763 in HandleIntuiReplyPort() */
2765 ih_fire_intuimessage(w,
2766 IDCMP_INTUITICKS,
2769 IntuitionBase);
2771 break; /* case IECLASS_TIMER */
2773 case IECLASS_MENU:
2774 if (MENUS_ACTIVE && (ie->ie_SubClass == IESUBCLASS_MENUSTOP))
2776 struct Window *eventwin = (struct Window *)ie->ie_EventAddress;
2778 iihdata->MenuWindow = NULL;
2779 MENUS_ACTIVE = FALSE;
2781 /* semaphore was locked when menu action started, see
2782 above where MMCODE_START MenuMessage is sent.
2784 It could have also have been locked if the user
2785 activated one of the menu key shortcuts, see
2786 "case IECLASS_RAWKEY" */
2788 ReleaseSemaphore(&GetPrivIBase(IntuitionBase)->MenuLock);
2790 keep_event = FALSE;
2792 if (((struct IntWindow *)eventwin)->menulendwindow)
2794 eventwin = ((struct IntWindow *)eventwin)->menulendwindow;
2797 ih_fire_intuimessage((struct Window *)eventwin,
2798 IDCMP_MENUPICK,
2799 ie->ie_Code,
2800 (struct Window *)ie->ie_EventAddress,
2801 IntuitionBase);
2804 break;
2806 case IECLASS_DISKINSERTED:
2807 case IECLASS_DISKREMOVED:
2808 case IECLASS_NEWPREFS:
2810 struct Screen *scr;
2811 ULONG idcmp;
2812 LONG lock;
2814 switch (ie->ie_Class)
2816 case IECLASS_DISKINSERTED:
2817 idcmp = IDCMP_DISKINSERTED;
2818 break;
2820 case IECLASS_DISKREMOVED:
2821 idcmp = IDCMP_DISKREMOVED;
2822 break;
2824 default:
2825 idcmp = IDCMP_NEWPREFS;
2827 * Here we need to update the mouse prefs and
2828 * maybe other stuff which comes from the global prefs file.
2830 break;
2833 lock = LockIBase(0);
2835 for (scr = IntuitionBase->FirstScreen; scr; scr = scr->NextScreen)
2837 struct Window *win;
2839 for (win = scr->FirstWindow; win; win = win->NextWindow)
2841 /* stegerg:
2842 CHECKME, really use fire_intuimessage() here,
2843 instead of ih_fireintuimessage? Same for
2844 IDCMP_GADGETHELP above, BTW. */
2846 fire_intuimessage(win,
2847 idcmp,
2849 NULL,
2850 IntuitionBase);
2854 UnlockIBase(lock);
2856 break;
2858 case IECLASS_NEWMOUSE:
2859 #ifdef __MORPHOS__
2861 * The following is only needed on hardware not running
2862 * the NewMouse driver.
2864 if (w->IDCMPFlags & IDCMP_RAWKEY && (!SysBase->MaxLocMem))
2866 ih_fire_intuimessage(w,
2867 IDCMP_RAWKEY,
2868 ie->ie_Code,
2869 ie->ie_position.ie_addr, /* ie_dead.ie_prev[1|2]Down[Code|Qual]. 64 bit machine!? */
2870 IntuitionBase);
2871 keep_event = FALSE;
2873 break;
2874 #endif
2875 case IECLASS_NULL:
2876 break;
2878 #ifdef __MORPHOS__
2879 case IECLASS_NEWTIMER:
2880 if (MENUS_ACTIVE)
2882 FireMenuMessage(MMCODE_EVENT, 0, ie, IntuitionBase);
2883 keep_event = FALSE;
2884 break;
2887 if (gadget)
2889 if (gadget == iihdata->MasterSizeGadget)
2891 gadget = DoGPInput(gi, gadget, ie, GM_HANDLEINPUT, &reuse_event, IntuitionBase);
2894 } /* if (gadget) */
2895 break;
2896 #endif /* __MORPHOS__ */
2898 default:
2899 if (MENUS_ACTIVE)
2901 FireMenuMessage(MMCODE_EVENT, 0, ie, IntuitionBase);
2902 keep_event = FALSE;
2903 break;
2908 "[Intui] InputHandler: Unknown IEClass: addr = %x class = %d (origclass = %d)\n",
2909 orig_ie, ie->ie_Class,orig_ie->ie_Class
2912 break;
2913 } /* switch (ie->ie_Class) */
2915 if (reuse_event)
2918 else if (keep_event && !ie_used)
2920 *iihdata->EndInputEventChain = orig_ie;
2921 iihdata->EndInputEventChain = &orig_ie->ie_NextEvent;
2922 ie_used = TRUE;
2924 else if (!ie_used)
2926 orig_ie->ie_NextEvent = iihdata->FreeInputEvents;
2927 iihdata->FreeInputEvents = orig_ie;
2930 } /* for (each event in the chain) */
2932 iihdata->ActiveGadget = gadget;
2934 D(bug("Outside pollingloop\n"));
2936 #if SINGLE_SETPOINTERPOS_PER_EVENTLOOP
2937 if (call_setpointerpos)
2938 MySetPointerPos(IntuitionBase);
2939 #endif
2941 /* Terminate the event chain. */
2942 *iihdata->EndInputEventChain = NULL;
2944 /* Transfer the list of allocated events in the list of events that should
2945 * be freed the next time the handler is entered.
2947 iihdata->AllocatedInputEventList = iihdata->NewAllocatedInputEventList;
2948 NEWLIST((struct List*)&iihdata->NewAllocatedInputEventList);
2950 /* Reset the event chain here, not at the beginning of the handler, for
2951 * events that might be allocated in other handers.
2953 iihdata->EndInputEventChain = &iihdata->ReturnInputEvent;
2954 iihdata->FreeInputEvents = NULL;
2956 ReleaseSemaphore(&GetPrivIBase(IntuitionBase)->InputHandlerLock);
2958 // DEBUG_HANDLER(dprintf("Handler: ->IBase 0x%lx KeyMapBase 0x%lx\n",IntuitionBase,KeymapBase));
2960 return iihdata->ReturnInputEvent;
2962 AROS_USERFUNC_EXIT
2965 /****************************************************************************************/