Moved the dereferencing of a window pointer to after the check for its
[AROS.git] / rom / intuition / inputhandler.c
blobb6f5bfe161c66229a60a0b0b0d46797d5bdba7ea
1 /*
2 Copyright © 1995-2014, 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)
1322 /* Acceleration */
1323 if (ABS(iihdata->DeltaMouseX) > ACCELERATOR_THRESH)
1324 iihdata->DeltaMouseX *= ACCELERATOR_MULTI;
1325 if (ABS(iihdata->DeltaMouseY) > ACCELERATOR_THRESH)
1326 iihdata->DeltaMouseY *= ACCELERATOR_MULTI;
1329 switch (GetPrivIBase(IntuitionBase)->ActivePreferences.PointerTicks)
1331 case 0:
1332 iihdata->DeltaMouseX_Correction = 0;
1333 iihdata->DeltaMouseX_Correction = 0;
1334 break;
1336 default:
1337 /* Remember the delta information which gets lost because of division by PointerTicks.
1338 Will be added to prescaled deltas of next mousemove event. If this is not done, moving
1339 the mouse very slowly would cause it to not move at all */
1341 iihdata->DeltaMouseX_Correction = iihdata->DeltaMouseX % GetPrivIBase(IntuitionBase)->ActivePreferences.PointerTicks;
1342 iihdata->DeltaMouseY_Correction = iihdata->DeltaMouseY % GetPrivIBase(IntuitionBase)->ActivePreferences.PointerTicks;
1344 iihdata->DeltaMouseX /= GetPrivIBase(IntuitionBase)->ActivePreferences.PointerTicks;
1345 iihdata->DeltaMouseY /= GetPrivIBase(IntuitionBase)->ActivePreferences.PointerTicks;
1346 break;
1350 ie->ie_X = iihdata->DeltaMouseX + IntuitionBase->MouseX;
1351 ie->ie_Y = iihdata->DeltaMouseY + IntuitionBase->MouseY;
1352 } else {
1353 DEBUG_MOUSE(bug("[Inputhandler] Last mouse position: (%d, %d), new mouse position: (%d, %d)\n",
1354 IntuitionBase->MouseX, IntuitionBase->MouseY, ie->ie_X, ie->ie_Y));
1355 iihdata->DeltaMouseX = ie->ie_X - IntuitionBase->MouseX;
1356 iihdata->DeltaMouseY = ie->ie_Y - IntuitionBase->MouseY;
1357 DEBUG_MOUSE(bug("[InputHandler] Delta is (%d, %d)\n", iihdata->DeltaMouseX, iihdata->DeltaMouseY));
1360 /* Calculate current display size.
1361 It's determined by the first screen on this monitor.
1362 TODO: perhaps we should just ask display driver about its current display mode? */
1363 scr = FindFirstScreen(GetPrivIBase(IntuitionBase)->ActiveMonitor, IntuitionBase);
1364 if (scr)
1366 DWidth = scr->ViewPort.ColorMap->cm_vpe->DisplayClip.MaxX - scr->ViewPort.ColorMap->cm_vpe->DisplayClip.MinX + 1;
1367 DHeight = scr->ViewPort.ColorMap->cm_vpe->DisplayClip.MaxY - scr->ViewPort.ColorMap->cm_vpe->DisplayClip.MinY + 1;
1369 else
1371 /* If there's no active screen, we take 160x160 as a limit */
1372 DWidth = 160;
1373 DHeight = 160;
1376 scr = iihdata->ScreenDrag;
1377 if (scr) {
1378 WORD dx = iihdata->DeltaMouseX;
1379 WORD dy = iihdata->DeltaMouseY;
1380 WORD min, max, val;
1381 UWORD spFlags = GetPrivScreen(scr)->SpecialFlags;
1382 UWORD DragMode = GetPrivIBase(IntuitionBase)->IControlPrefs.ic_VDragModes[0];
1384 DEBUG_DRAG(bug("[InputHandler] Screen drag, delta is (%d, %d)\n", dx, dy));
1386 /* Restrict dragging to a physical display area if the driver does not allow composition or if the user wants it*/
1387 if (((spFlags & SF_HorCompose) != SF_HorCompose) || (DragMode & ICVDM_HBOUND)) {
1388 /* Calculate limits */
1389 if (scr->Width > DWidth) {
1390 min = DWidth - scr->Width;
1391 max = 0;
1392 } else {
1393 min = 0;
1394 max = DWidth - scr->Width;
1396 /* The purpose of the following complex check is to prevent jumping if the
1397 screen was positioned out of user drag limits by the program itself using
1398 ScreenPosition() or OpenScreen(). We apply restrictions in parts depending
1399 on the dragging direction.
1400 Maybe the user should also be able to drag the screen back off-display in such
1401 a case?
1402 Calculate the position we would go to */
1403 val = scr->LeftEdge + dx;
1404 /* Determine the direction */
1405 if ((dx < 0) && ((!(spFlags & SF_ComposeRight)) || (DragMode & ICVDM_LBOUND))) {
1406 /* Can we move at all in this direction ? */
1407 if (scr->LeftEdge > min) {
1408 /* If too far, restrict it */
1409 if (val < min)
1410 dx = min - scr->LeftEdge;
1411 } else
1412 /* Just don't move if we can't */
1413 dx = 0;
1414 } else if ((!(spFlags & SF_ComposeLeft)) || (DragMode & ICVDM_RBOUND)) {
1415 if (scr->LeftEdge < max) {
1416 if (val > max)
1417 dx = max - scr->LeftEdge;
1418 } else
1419 dx = 0;
1422 if (((spFlags & SF_VertCompose) != SF_VertCompose) || (DragMode & ICVDM_VBOUND)) {
1423 DEBUG_DRAG(bug("[Inputhandler] Restricting vertical drag\n"));
1424 DEBUG_DRAG(bug("[Inputhandler] Screen size: %d, display size: %d\n", scr->Height, DHeight));
1425 if (scr->Height > DHeight) {
1426 min = DHeight - scr->Height;
1427 max = 0;
1428 } else {
1429 min = 0;
1430 max = DHeight - scr->Height;
1432 DEBUG_DRAG(bug("[Inputhandler] Limits: min %d max %d\n", min, max));
1433 val = scr->TopEdge + dy;
1434 DEBUG_DRAG(bug("[Inputhandler] New position would be %d\n", val));
1435 if ((dy < 0) && ((!(spFlags & SF_ComposeBelow)) || (DragMode & ICVDM_TBOUND))) {
1436 if (scr->TopEdge > min) {
1437 if (val < min)
1438 dy = min - scr->TopEdge;
1439 } else
1440 dy = 0;
1441 } else if ((!(spFlags & SF_ComposeAbove)) || (DragMode & ICVDM_BBOUND)) {
1442 if (scr->TopEdge < max) {
1443 if (val > max)
1444 dy = max - scr->TopEdge;
1445 } else
1446 dy = 0;
1448 DEBUG_DRAG(bug("[Inputhandler] Restricted delta will be %d\n", dy));
1450 ScreenPosition(scr, SPOS_RELATIVE, dx, dy, 0, 0);
1453 /* Autoscroll the active screen */
1454 scr = IntuitionBase->ActiveScreen;
1455 if (scr && (scr->Flags & AUTOSCROLL) &&
1456 (GetPrivScreen(scr)->IMonitorNode == GetPrivIBase(IntuitionBase)->ActiveMonitor))
1458 WORD xval = scr->LeftEdge;
1459 WORD yval = scr->TopEdge;
1460 WORD min;
1462 DEBUG_AUTOSCROLL(bug("[Inputhandler] Autoscroll screen 0x%p, event at (%d, %d)\n",
1463 scr, ie->ie_X, ie->ie_Y));
1465 if ((ie->ie_X < 0) || (ie->ie_X >= DWidth)) {
1466 DEBUG_AUTOSCROLL(bug("[InputHandler] X delta: %d pixels\n", iihdata->DeltaMouseX));
1467 xval -= iihdata->DeltaMouseX;
1469 if (ie->ie_X < 0) {
1470 if (xval > 0)
1471 xval = 0;
1472 } else if (ie->ie_X >= DWidth) {
1473 min = DWidth - scr->Width;
1474 if (xval < min)
1475 xval = min;
1479 if ((ie->ie_Y < 0) || (ie->ie_Y >= DHeight)) {
1480 yval -= iihdata->DeltaMouseY;
1482 if (ie->ie_Y < 0) {
1483 /* If screen is dragged down and user touched upper screen
1484 boundary, do nothing */
1485 if (scr->TopEdge >= 0)
1486 yval = scr->TopEdge;
1487 else
1488 /* If scrolled down screen is being scrolled up, make sure it
1489 does not go over 0 */
1490 if (yval > 0)
1491 yval = 0;
1492 } else if (ie->ie_Y >= DHeight) {
1493 min = DHeight - scr->Height;
1494 if (yval < min)
1495 yval = min;
1499 if ((xval != scr->LeftEdge) || (yval != scr->TopEdge))
1500 ScreenPosition(scr, SPOS_ABSOLUTE, xval, yval, 0, 0);
1503 /* Restrict mouse coordinates to the physical display area */
1504 if (ie->ie_X >= DWidth) ie->ie_X = DWidth - 1;
1505 if (ie->ie_Y >= DHeight) ie->ie_Y = DHeight - 1;
1506 if (ie->ie_X < 0) ie->ie_X = 0;
1507 if (ie->ie_Y < 0) ie->ie_Y = 0;
1509 #ifdef SKINS
1510 if (gadget == iihdata->MasterDragGadget) {
1511 struct gpInput gpi;
1512 ULONG retval;
1514 gpi.MethodID = GM_MOVETEST;
1515 gpi.gpi_GInfo = gi;
1516 gpi.gpi_Mouse.X = ie->ie_X - gi->gi_Window->WScreen->LeftEdge;
1517 gpi.gpi_Mouse.Y = ie->ie_Y - gi->gi_Window->WScreen->TopEdge;
1518 gpi.gpi_IEvent = ie;
1520 retval = Locked_DoMethodA(gi->gi_Window, gadget, (Msg)&gpi, IntuitionBase);
1521 if (retval == MOVETEST_ADJUSTPOS)
1523 ie->ie_X = gpi.gpi_Mouse.X + gi->gi_Window->WScreen->LeftEdge;
1524 ie->ie_Y = gpi.gpi_Mouse.Y + gi->gi_Window->WScreen->TopEdge;
1528 #endif
1529 /* Do Mouse Bounding - mouse will be most restrictive of screen size or mouse bounds */
1530 if (iihdata->MouseBoundsActiveFlag) {
1531 if (ie->ie_X < iihdata->MouseBoundsLeft)
1532 ie->ie_X = iihdata->MouseBoundsLeft;
1533 else if (ie->ie_X > iihdata->MouseBoundsRight)
1534 ie->ie_X = iihdata->MouseBoundsRight;
1536 if (ie->ie_Y < iihdata->MouseBoundsTop)
1537 ie->ie_Y = iihdata->MouseBoundsTop;
1538 else if (ie->ie_Y > iihdata->MouseBoundsBottom)
1539 ie->ie_Y = iihdata->MouseBoundsBottom;
1542 /* Prevent mouse going above all screens */
1543 scr = FindHighestScreen(IntuitionBase);
1544 if (scr) {
1545 if (ie->ie_Y < scr->TopEdge)
1546 ie->ie_Y = scr->TopEdge;
1549 /* Store new mouse coords. If a screen is being dragged, lock drag point */
1550 scr = iihdata->ScreenDrag;
1551 if (scr) {
1552 IntuitionBase->MouseX = scr->LeftEdge + iihdata->ScreenDragPointX;
1553 IntuitionBase->MouseY = scr->TopEdge + iihdata->ScreenDragPointY;
1554 } else {
1555 IntuitionBase->MouseX = ie->ie_X;
1556 IntuitionBase->MouseY = ie->ie_Y;
1558 notify_mousemove_screensandwindows(IntuitionBase);
1559 #if !SINGLE_SETPOINTERPOS_PER_EVENTLOOP
1560 MySetPointerPos(IntuitionBase);
1561 #else
1562 *call_setpointerpos = TRUE;
1563 #endif
1565 screen = FindActiveScreen(IntuitionBase); /* The mouse was moved, so current screen may have changed */
1567 #ifdef SKINS
1568 if (!gadget) {
1569 if (iihdata->TitlebarOnTop)
1571 if (screen->MouseY > screen->BarHeight && GetPrivScreen(screen)->SpecialFlags & SF_AppearingBar)
1573 iihdata->TitlebarOnTop = FALSE;
1574 iihdata->TitlebarAppearTime = 0;
1576 LOCK_REFRESH(screen);
1578 MoveLayer(0, screen->BarLayer, 0, -(screen->BarHeight + 1));
1579 CheckLayers(screen, IntuitionBase);
1581 UNLOCK_REFRESH(screen);
1584 else
1586 if (screen->MouseY == 0 && GetPrivScreen(screen)->SpecialFlags & SF_AppearingBar && !MENUS_ACTIVE && !(PeekQualifier() & (IEQUALIFIER_LEFTBUTTON|IEQUALIFIER_RBUTTON|IEQUALIFIER_MIDBUTTON)))
1588 if (!(iihdata->TitlebarAppearTime))
1590 iihdata->TitlebarAppearTime = ((UQUAD)ie->ie_TimeStamp.tv_secs) * 50;
1591 iihdata->TitlebarAppearTime += ie->ie_TimeStamp.tv_micro / 20000;
1594 else
1596 iihdata->TitlebarAppearTime = 0;
1600 #endif
1601 if (MENUS_ACTIVE) {
1602 FireMenuMessage(MMCODE_EVENT, 0, ie, IntuitionBase);
1603 *keep_event = FALSE;
1604 break;
1607 if (gadget) {
1608 *keep_event = FALSE;
1610 switch (gadget->GadgetType & GTYP_GTYPEMASK)
1612 case GTYP_BOOLGADGET:
1613 case 0: //fallback for sucky gadgets
1614 /* Must be a RELVERIFY gadget */
1616 BOOL inside;
1618 inside = InsideGadget(gi->gi_Screen,
1619 gi->gi_Window,
1620 gi->gi_Requester,
1621 gadget,
1622 gi->gi_Screen->MouseX,
1623 gi->gi_Screen->MouseY);
1625 if (inside != iihdata->MouseWasInsideBoolGadget) {
1626 iihdata->MouseWasInsideBoolGadget = inside;
1628 gadget->Flags ^= GFLG_SELECTED;
1629 RefreshBoolGadgetState(gadget, w, req, IntuitionBase);
1632 break;
1634 case GTYP_PROPGADGET:
1635 HandlePropMouseMove(gadget,
1637 req,
1638 w->MouseX - gi->gi_Domain.Left - GetGadgetLeft(gadget, gi->gi_Screen, gi->gi_Window, NULL),
1639 w->MouseY - gi->gi_Domain.Top - GetGadgetTop(gadget, gi->gi_Screen, gi->gi_Window, NULL),
1640 IntuitionBase);
1642 break;
1644 case GTYP_CUSTOMGADGET:
1645 gadget = DoGPInput(gi, gadget, ie, GM_HANDLEINPUT, reuse_event, IntuitionBase);
1646 break;
1648 } /* switch GadgetType */
1650 } /* if (a gadget is currently active) */
1652 *keep_event = FALSE;
1654 if (!w)
1655 break;
1657 if (IW(w)->helpflags & HELPF_GADGETHELP && (!(PeekQualifier() & (IEQUALIFIER_LEFTBUTTON|IEQUALIFIER_RBUTTON|IEQUALIFIER_MIDBUTTON)))) {
1658 struct Window *hw;
1659 struct Gadget *g;
1661 hw = FindActiveWindow(ie, screen, 0, IntuitionBase);
1663 if (hw != w &&
1664 (!hw || !(IW(w)->helpflags & HELPF_ISHELPGROUP) ||
1665 !(IW(hw)->helpflags & HELPF_ISHELPGROUP) ||
1666 IW(w)->helpgroup != IW(hw)->helpgroup))
1669 if (iihdata->LastHelpWindow)
1671 fire_intuimessage(w,
1672 IDCMP_GADGETHELP,
1674 NULL,
1675 IntuitionBase);
1677 iihdata->LastHelpGadget = NULL;
1678 iihdata->LastHelpWindow = NULL;
1679 iihdata->HelpGadgetFindTime = 0;
1682 else
1684 g = FindHelpGadget (hw,
1685 IntuitionBase->ActiveScreen->MouseX,
1686 IntuitionBase->ActiveScreen->MouseY,
1687 IntuitionBase);
1688 if (g && g != iihdata->LastHelpGadget)
1690 if (!iihdata->LastHelpGadget)
1692 iihdata->HelpGadgetFindTime = ((UQUAD)ie->ie_TimeStamp.tv_secs) * 50;
1693 iihdata->HelpGadgetFindTime += ie->ie_TimeStamp.tv_micro / 20000;
1694 } else {
1695 if (hw == iihdata->LastHelpWindow)
1697 iihdata->HelpGadgetFindTime = ((UQUAD)ie->ie_TimeStamp.tv_secs) * 50;
1698 iihdata->HelpGadgetFindTime += ie->ie_TimeStamp.tv_micro / 20000;
1699 iihdata->HelpGadgetFindTime += 25;//smaller delay
1703 else if (g != iihdata->LastHelpGadget ||
1704 hw != iihdata->LastHelpWindow)
1706 fire_intuimessage(hw,
1707 IDCMP_GADGETHELP,
1708 0, /* Don't know what it should be */
1710 IntuitionBase);
1713 iihdata->LastHelpGadget = g;
1714 iihdata->LastHelpWindow = hw;
1716 } else {
1717 iihdata->LastHelpGadget = NULL;
1718 iihdata->LastHelpWindow = NULL;
1719 iihdata->HelpGadgetFindTime = 0;
1722 if (!(w->IDCMPFlags & IDCMP_MOUSEMOVE))
1723 break;
1725 /* Send IDCMP_MOUSEMOVE if WFLG_REPORTMOUSE is set
1726 and/or active gadget has GACT_FOLLOWMOUSE set */
1728 /* jDc: do NOT send when sizegad is pressed */
1729 if (!(w->Flags & WFLG_REPORTMOUSE)) {
1730 if (!gadget)
1731 break;
1732 if (!(gadget->Activation & GACT_FOLLOWMOUSE))
1733 break;
1734 } else {
1735 if (gadget && (gadget->GadgetType & (GTYP_SIZING|GTYP_WDRAGGING)))
1736 break;
1739 orig_ie->ie_Class = IECLASS_RAWMOUSE;
1741 /* Limit the number of IDCMP_MOUSEMOVE messages sent to intuition.
1742 note that this comes after handling gadgets, because gadgets should get all events.
1745 if (IW(w)->num_mouseevents >= IW(w)->mousequeue) {
1746 BOOL old_msg_found = FALSE;
1748 /* Mouse Queue is full, so try looking for a not
1749 yet GetMsg()ed IntuiMessage in w->UserPort
1750 trying to modify that. */
1752 Forbid();
1753 if (w->UserPort)
1755 struct IntuiMessage *im;
1757 for (im = (struct IntuiMessage *)w->UserPort->mp_MsgList.lh_TailPred;
1758 im->ExecMessage.mn_Node.ln_Pred;
1759 im = (struct IntuiMessage *)im->ExecMessage.mn_Node.ln_Pred)
1761 if ((im->Class == IDCMP_MOUSEMOVE) &&
1762 (im->IDCMPWindow == w))
1764 im->Qualifier = iihdata->ActQualifier;
1766 if (w->IDCMPFlags & IDCMP_DELTAMOVE)
1768 im->MouseX = iihdata->DeltaMouseX;
1769 im->MouseY = iihdata->DeltaMouseY;
1771 else
1773 im->MouseX = w->MouseX;
1774 im->MouseY = w->MouseY;
1776 CurrentTime(&im->Seconds, &im->Micros);
1778 old_msg_found = TRUE;
1779 break;
1782 } /* if (w->UserPort) */
1783 Permit();
1785 /* no need to send a new message if we modified
1786 an existing one ... */
1788 if (old_msg_found) break;
1790 /* ... otherwise we are in a strange situation. The mouse
1791 queue is full, but we did not find an existing MOUSEMOVE
1792 imsg in w->UserPort. So the app probably has removed
1793 an imsg from the UserPort with GetMsg but we did not get
1794 the ReplyMsg, yet. In this case we do send a new message */
1796 HandleIntuiReplyPort(iihdata, IntuitionBase);
1800 /* MouseQueue is not full, so we can send a message. We increase
1801 IntWindow->num_mouseevents which will later be decreased after
1802 the Intuition InputHandler gets the ReplyMessage from the app
1803 and handles it in HandleIntuiReplyPort() */
1805 if (ih_fire_intuimessage(w, IDCMP_MOUSEMOVE, IECODE_NOBUTTON, w, IntuitionBase))
1806 IW(w)->num_mouseevents++;
1808 break;
1810 } /* case IECODE_NOBUTTON */
1811 } /* switch (ie->ie_Code) (what button was pressed ?) */
1813 return gadget;
1816 /****************************************************************************************/
1818 AROS_UFH2(struct InputEvent *, IntuiInputHandler,
1819 AROS_UFHA(struct InputEvent *, oldchain, A0),
1820 AROS_UFHA(struct IIHData *, iihdata, A1)
1823 AROS_USERFUNC_INIT
1825 struct InputEvent *ie, *orig_ie, *next_ie, stackie;
1826 struct Gadget *gadget = NULL;
1827 struct IntuitionBase *IntuitionBase = iihdata->IntuitionBase;
1828 struct Library *KeymapBase = GetPrivIBase(IntuitionBase)->KeymapBase;
1829 struct Screen *screen;
1830 //ULONG lock;
1831 struct GadgetInfo *gi = &iihdata->GadgetInfo;
1832 BOOL reuse_event, ie_used;
1833 struct Window *w;
1834 struct Requester *req;
1835 ULONG stitlebarhit = 0;
1836 #if 0 /* Toolbox is broken-as-designed */
1837 struct Window *toolbox;
1838 struct GadgetInfo *boxgi = &iihdata->BoxGadgetInfo;
1839 struct Gadget *boxgadget = NULL;
1840 #endif
1841 #if SINGLE_SETPOINTERPOS_PER_EVENTLOOP
1842 BOOL call_setpointerpos = FALSE;
1843 #endif
1845 D(bug("Inside intuition inputhandler, active window=%p\n", IntuitionBase->ActiveWindow));
1846 ObtainSemaphore(&GetPrivIBase(IntuitionBase)->InputHandlerLock);
1848 if (!iihdata->InputDeviceTask) iihdata->InputDeviceTask = FindTask(NULL);
1850 /* Then free generated InputEvents done in the previous round */
1852 FreeGeneratedInputEvents(iihdata);
1854 /* First handle IntuiMessages which were replied back to the IntuiReplyPort
1855 by the apps */
1857 HandleIntuiReplyPort(iihdata, IntuitionBase);
1859 /* Handle action messages */
1861 HandleIntuiActions(iihdata, IntuitionBase);
1863 /* Now handle the input events */
1865 ie = &stackie;
1866 reuse_event = FALSE;
1867 next_ie = oldchain;
1869 /* shut up the compiler */
1870 orig_ie = next_ie;
1871 ie_used = FALSE;
1873 gadget = iihdata->ActiveGadget;
1875 while (reuse_event || next_ie)
1877 struct Window *old_w;
1878 BOOL keep_event = TRUE;
1879 BOOL new_active_window = FALSE;
1880 Object *newmonitor = GetPrivIBase(IntuitionBase)->NewMonitor;
1882 /* Process hosted display activation event (if any).
1883 This is experimental. If this works badly, we'll possibly have to put it into
1884 input events queue */
1885 if (newmonitor) {
1886 DEBUG_MONITOR(bug("[Inputhandler] Activating monitor 0x%p\n", newmonitor));
1887 GetPrivIBase(IntuitionBase)->NewMonitor = NULL;
1888 ActivateMonitor(newmonitor, -1, -1, IntuitionBase);
1889 iihdata->SwitchedMonitor = TRUE;
1892 if (!reuse_event)
1894 *ie = *next_ie;
1895 orig_ie = next_ie;
1896 next_ie = ie->ie_NextEvent;
1897 ie_used = FALSE;
1900 D(bug("iih: Handling event of class %d, code %d\n", ie->ie_Class, ie->ie_Code));
1901 reuse_event = FALSE;
1903 /* If the monitor has been changed, this possibly happened because of mouse click in
1904 its display window. In such a case we have to update current mouse coordinates
1905 from the first absolute mouse event. Otherwise input will misbehave. */
1906 if (iihdata->SwitchedMonitor && (ie->ie_Class == IECLASS_RAWMOUSE)) {
1907 iihdata->SwitchedMonitor = FALSE;
1908 if (!(ie->ie_Qualifier & IEQUALIFIER_RELATIVEMOUSE)) {
1909 DEBUG_MONITOR(bug("[Inputhandler] Adjusting coordinates to (%d, %d)\n", ie->ie_X, ie->ie_Y));
1910 IntuitionBase->MouseX = ie->ie_X;
1911 IntuitionBase->MouseY = ie->ie_Y;
1912 notify_mousemove_screensandwindows(IntuitionBase);
1916 /* new event, we need to reset this */
1917 screen = FindActiveScreen(IntuitionBase);
1918 iihdata->ActEventTablet = 0;
1920 /* Set the timestamp in IntuitionBase */
1922 IntuitionBase->Seconds = ie->ie_TimeStamp.tv_secs;
1923 IntuitionBase->Micros = ie->ie_TimeStamp.tv_micro;
1925 #if 0 /* toolbox stuff disabled. broken. calling LockLayerinfo() for every event is broken. deadlocks */
1926 /* Use event to find the active window */
1928 toolbox = GetToolBoxWindow(ie, screen, IntuitionBase);
1930 if (toolbox)
1932 /* Do ToolBox Window Actions */
1933 /* ToolBox Windows supports only a subset of IECLASS Actions */
1934 switch (ie->ie_Class) {
1936 case IECLASS_RAWMOUSE:
1937 boxgadget = Process_RawMouse(ie, iihdata, screen, toolbox, boxgadget, boxgi, 0, FALSE, TRUE,
1938 orig_ie, &keep_event, &reuse_event,
1939 #if SINGLE_SETPOINTERPOS_PER_EVENTLOOP
1940 &call_setpointerpos,
1941 #endif
1942 IntuitionBase);
1943 break;
1945 } /* switch (ie->ie_Class) */
1946 } /* if (toolbox) */
1947 #endif
1949 w = IntuitionBase->ActiveWindow;
1951 if (!MENUS_ACTIVE && !SYSGADGET_ACTIVE)
1953 /* lock = LockIBase(0UL); */
1955 old_w = w;
1956 if (ie->ie_Class == IECLASS_RAWMOUSE && ie->ie_Code == SELECTDOWN)
1958 w = FindActiveWindow(ie, screen, &stitlebarhit, IntuitionBase);
1959 DEBUG_CLICK(bug("iih:New active window: %p\n", w));
1963 if ( w != old_w )
1965 if (w)
1967 DEBUG_WINDOW(bug("Activating new window (title %s)\n", w->Title ? w->Title : "<noname>"));
1969 DEBUG_WINDOW(bug("Window activated\n"));
1971 else
1973 DEBUG_WINDOW(bug("Making active window inactive. Now there's no active window\n"));
1975 new_active_window = TRUE;
1976 iihdata->NewActWindow = w;
1979 /* UnlockIBase(lock); */
1981 if (new_active_window)
1983 if (gadget && w &&
1984 (!(GetPrivScreen(w->WScreen)->MenuVerifyMsgCount)) &&
1985 (!(MENUS_ACTIVE)) && (!(SYSGADGET_ACTIVE)))
1987 switch (gadget->GadgetType & GTYP_GTYPEMASK)
1990 case GTYP_CUSTOMGADGET:
1992 struct gpGoInactive gpgi;
1994 gpgi.MethodID = GM_GOINACTIVE;
1995 gpgi.gpgi_GInfo = gi;
1996 gpgi.gpgi_Abort = 1;
1998 Locked_DoMethodA(gi->gi_Window, gadget, (Msg)&gpgi, IntuitionBase);
1999 break;
2002 case GTYP_STRGADGET:
2003 gadget->Flags &= ~GFLG_SELECTED;
2004 RefreshStrGadget(gadget, gi->gi_Window, gi->gi_Requester, IntuitionBase);
2005 break;
2007 case GTYP_BOOLGADGET:
2008 /* That a bool gadget is active here can only happen
2009 if user used LMB to activate gadget and LAMIGA + LALT
2010 to activate other window, or viceversa */
2011 /* The gadget must be a RELVERIFY one */
2012 if (!(gadget->Activation & GACT_TOGGLESELECT))
2014 BOOL inside;
2016 inside = InsideGadget(gi->gi_Screen, gi->gi_Window,
2017 gi->gi_Requester, gadget,
2018 gi->gi_Screen->MouseX, gi->gi_Screen->MouseY);
2020 if (inside)
2022 gadget->Flags &= ~GFLG_SELECTED;
2023 RefreshBoolGadgetState(gadget, gi->gi_Window,
2024 gi->gi_Requester, IntuitionBase);
2027 break;
2029 case GTYP_PROPGADGET:
2030 /* That a prop gadget is active here can only happen
2031 if user used LMB to activate gadget and LAMIGA + LALT
2032 to activate other window, or viceversa */
2034 HandlePropSelectUp(gadget, gi->gi_Window, NULL, IntuitionBase);
2035 if (gadget->Activation & GACT_RELVERIFY)
2037 ih_fire_intuimessage(gi->gi_Window,
2038 IDCMP_GADGETUP,
2040 gadget,
2041 IntuitionBase);
2043 break;
2045 } /* switch (gadget->GadgetType & GTYP_GTYPEMASK) */
2047 gadget->Activation &= ~GACT_ACTIVEGADGET;
2048 iihdata->ActiveGadget = NULL;
2049 gadget = NULL;
2052 /* ActivateWindow works if w = NULL */
2053 /* jacaDcaps: some gui toolkits (die reaction, die!) close the window opened by a boopsi gadget when
2054 it gets hit with lmb, so we need to check if the new active window does not go away by
2055 performing GM_GOINACTIVE on the gadget. NOTE: CloseWindow's part performed on input.device context
2056 clears the iihdata->NewActWindow if it's the actually closed one. */
2057 if (w == iihdata->NewActWindow)
2059 ActivateWindow(w);
2061 else
2063 w = IntuitionBase->ActiveWindow;
2064 new_active_window = FALSE;
2065 ie->ie_Class = IECLASS_NULL; //lose the event, otherwise the gadget will get activated again ;)
2068 iihdata->NewActWindow = 0;
2070 } /* if (new_active_window) */
2072 } /* if (!MENUS_ACTIVE) */
2074 req = NULL;
2075 if (w)
2077 req = w->FirstRequest;
2080 D(bug("[Inputhandler] Screen 0x%p Window 0x%p Requester 0x%p gadget 0x%p\n", screen, w, req, gadget));
2082 switch (ie->ie_Class) {
2083 case IECLASS_POINTERPOS:
2084 ie->ie_SubClass = IESUBCLASS_COMPATIBLE;
2085 /* fall through */
2087 case IECLASS_NEWPOINTERPOS:
2088 switch (ie->ie_SubClass)
2090 case IESUBCLASS_COMPATIBLE:
2091 ie->ie_Code = IECODE_NOBUTTON;
2092 break;
2094 case IESUBCLASS_PIXEL:
2096 struct IEPointerPixel *pp = ie->ie_EventAddress;
2098 ie->ie_X = pp->iepp_Position.X + pp->iepp_Screen->LeftEdge;
2099 ie->ie_Y = pp->iepp_Position.Y + pp->iepp_Screen->TopEdge;
2101 ActivateMonitor(GetPrivScreen(pp->iepp_Screen)->IMonitorNode, ie->ie_X, ie->ie_Y, IntuitionBase);
2103 ie->ie_Class = IECLASS_RAWMOUSE; /* otherwise a lot of code would ignore this message */
2104 ie->ie_Code = IECODE_NOBUTTON;
2105 break;
2107 case IESUBCLASS_TABLET:
2109 //unsupported - does anything use it anyway? ;)
2111 ie->ie_Code = 0;
2112 break;
2114 case IESUBCLASS_NEWTABLET:
2116 struct IENewTablet *nt = (struct IENewTablet *)ie->ie_EventAddress;
2118 if (nt)
2120 iihdata->ActEventTablet = nt; //cache this
2121 ie->ie_X = (screen->Width * nt->ient_TabletX) / nt->ient_RangeX;
2122 ie->ie_Y = (screen->Height * nt->ient_TabletY) / nt->ient_RangeY;
2124 ie->ie_Class = IECLASS_RAWMOUSE;
2126 break;
2128 default:
2129 ie->ie_Code = 0;
2130 break;
2132 /* fall through */
2134 case IECLASS_RAWMOUSE:
2135 gadget = Process_RawMouse(ie, iihdata, screen, w, gadget, gi, stitlebarhit, new_active_window, FALSE,
2136 orig_ie, &keep_event, &reuse_event,
2137 #if SINGLE_SETPOINTERPOS_PER_EVENTLOOP
2138 &call_setpointerpos,
2139 #endif
2140 IntuitionBase);
2141 keep_event = TRUE;
2142 break;
2144 case IECLASS_RAWKEY:
2145 /* release events go only to gadgets and windows who
2146 have not set IDCMP_VANILLAKEY */
2148 DEBUG_HANDLER(dprintf("Handler: IECLASS_RAWKEY\n"));
2149 DEBUG_KEY(dprintf("Handler: Qual 0x%lx\n",iihdata->ActQualifier));
2151 iihdata->ActQualifier &= ~(KEY_QUALIFIERS | IEQUALIFIER_REPEAT);
2152 iihdata->ActQualifier |= (ie->ie_Qualifier & (KEY_QUALIFIERS | IEQUALIFIER_REPEAT));
2154 DEBUG_KEY(dprintf("Handler: real Qual 0x%lx\n",iihdata->ActQualifier));
2156 /* Keyboard mouse emulation and screen switching */
2159 UWORD code = ie->ie_Code & ~IECODE_UP_PREFIX;
2160 DEBUG_KEY(dprintf("Handler: code 0x%lx\n",code));
2162 /* Left Amiga + N/M screen switching shortcut */
2163 if ((ie->ie_Qualifier & IEQUALIFIER_LCOMMAND) && (code == RAWKEY_N || code == RAWKEY_M)) {
2164 if (!(ie->ie_Qualifier & IEQUALIFIER_REPEAT) && !(ie->ie_Code & IECODE_UP_PREFIX)) {
2165 if (code == RAWKEY_N)
2166 WBenchToFront();
2167 else if (code == RAWKEY_M)
2168 ScreenToBack(IntuitionBase->FirstScreen);
2170 keep_event = FALSE;
2171 break;
2174 /* Mouse button emulation: LALT + LAMIGA = LBUTTON, RALT + RAMIGA = RBUTTON */
2175 if ((code == RAWKEY_LAMIGA) ||
2176 (code == RAWKEY_LALT) ||
2177 (code == RAWKEY_RAMIGA) ||
2178 (code == RAWKEY_RALT))
2180 DEBUG_KEY(dprintf("Handler: KeyMouseEmul\n"));
2181 iihdata->PrevKeyMouseState = iihdata->ActKeyMouseState;
2182 iihdata->ActKeyMouseState = 0;
2183 if ((ie->ie_Qualifier & (IEQUALIFIER_LCOMMAND | IEQUALIFIER_LALT)) == (IEQUALIFIER_LCOMMAND | IEQUALIFIER_LALT))
2185 iihdata->ActKeyMouseState |= IEQUALIFIER_LEFTBUTTON;
2187 if ((ie->ie_Qualifier & (IEQUALIFIER_RCOMMAND | IEQUALIFIER_RALT)) == (IEQUALIFIER_RCOMMAND | IEQUALIFIER_RALT))
2189 iihdata->ActKeyMouseState |= IEQUALIFIER_RBUTTON;
2192 if ((iihdata->ActKeyMouseState & IEQUALIFIER_LEFTBUTTON) != (iihdata->PrevKeyMouseState & IEQUALIFIER_LEFTBUTTON))
2194 orig_ie->ie_Class = IECLASS_RAWMOUSE;
2195 orig_ie->ie_SubClass = 0;
2196 orig_ie->ie_Code = (iihdata->ActKeyMouseState & IEQUALIFIER_LEFTBUTTON) ? IECODE_LBUTTON : IECODE_LBUTTON | IECODE_UP_PREFIX;
2197 orig_ie->ie_X = 0;
2198 orig_ie->ie_Y = 0;
2199 *ie = *orig_ie;
2201 reuse_event = TRUE;
2202 break;
2205 if ((iihdata->ActKeyMouseState & IEQUALIFIER_RBUTTON) != (iihdata->PrevKeyMouseState & IEQUALIFIER_RBUTTON))
2207 orig_ie->ie_Class = IECLASS_RAWMOUSE;
2208 orig_ie->ie_SubClass = 0;
2209 orig_ie->ie_Code = (iihdata->ActKeyMouseState & IEQUALIFIER_RBUTTON) ? IECODE_RBUTTON : IECODE_RBUTTON | IECODE_UP_PREFIX;
2210 orig_ie->ie_X = 0;
2211 orig_ie->ie_Y = 0;
2212 *ie = *orig_ie;
2214 reuse_event = TRUE;
2215 break;
2218 } /* if key is one of LAMIGA/LALT/RAMIGA/RALT */
2220 if ((iihdata->ActQualifier & (IEQUALIFIER_LCOMMAND | IEQUALIFIER_RCOMMAND)) &&
2221 ((ie->ie_Code == RAWKEY_UP) ||
2222 (ie->ie_Code == RAWKEY_DOWN) ||
2223 (ie->ie_Code == RAWKEY_LEFT) ||
2224 (ie->ie_Code == RAWKEY_RIGHT)))
2226 static BYTE const xmap[] = { 0, 0, 1, -1};
2227 static BYTE const ymap[] = {-1, 1, 0, 0};
2228 WORD shift;
2230 shift = (iihdata->ActQualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) ? 40 : 1;
2232 /* Mouse Move Emulation */
2234 orig_ie->ie_Class = IECLASS_RAWMOUSE;
2235 orig_ie->ie_SubClass = 0;
2236 orig_ie->ie_Code = IECODE_NOBUTTON;
2237 orig_ie->ie_Qualifier = IEQUALIFIER_RELATIVEMOUSE;
2238 orig_ie->ie_X = xmap[code - RAWKEY_UP] * shift;
2239 orig_ie->ie_Y = ymap[code - RAWKEY_UP] * shift;
2241 *ie = *orig_ie;
2242 reuse_event = TRUE;
2243 break;
2246 } /**/
2248 /* End Keyboard mouse emulation */
2250 if (MENUS_ACTIVE)
2252 DEBUG_KEY(dprintf("Handler: FireMenuMessage\n"));
2253 FireMenuMessage(MMCODE_EVENT, 0, ie, IntuitionBase);
2254 keep_event = FALSE;
2255 break;
2258 /* Hotkeys processing */
2259 #ifdef SKINS
2261 ULONG result;
2263 if (!(ie->ie_Code & IECODE_UP_PREFIX))
2264 if ((result = RunHotkeys(ie,IntuitionBase)))
2266 if (result == RUNHOTREUSE)
2268 reuse_event = TRUE;
2270 else
2272 keep_event = FALSE;
2274 break;
2276 w = IntuitionBase->ActiveWindow;
2278 #endif
2280 if ( keep_event &&
2281 ((!(ie->ie_Code & IECODE_UP_PREFIX)) ||
2282 gadget ||
2283 (w && ((w->IDCMPFlags & IDCMP_VANILLAKEY) == 0)) ))
2285 if (gadget)
2287 keep_event = FALSE;
2289 DEBUG_KEY(dprintf("Handler: Gadget 0x%lx active\n",gadget));
2290 DEBUG_KEY(dprintf("Handler: GadgetID 0x%lx UserData 0x%lx\n",
2291 gadget->GadgetID,
2292 gadget->UserData));
2293 DEBUG_KEY(dprintf("Handler: GadgetType 0x%lx Flags 0x%lx Activation 0x%lx\n",
2294 gadget->GadgetType,
2295 gadget->Flags,
2296 gadget->Activation));
2297 DEBUG_KEY(dprintf("Handler: MoreFlags 0x%lx\n",
2298 ((struct ExtGadget*)gadget)->MoreFlags));
2300 switch (gadget->GadgetType & GTYP_GTYPEMASK)
2302 case GTYP_STRGADGET:
2304 UWORD imsgcode;
2305 ULONG ret = HandleStrInput(gadget, gi, ie, &imsgcode,
2306 IntuitionBase);
2308 DEBUG_KEY(dprintf("Handler: Key GTYP_STRGADGET ret 0x%lx\n",ret));
2309 if (ret & (SGA_END | SGA_NEXTACTIVE | SGA_PREVACTIVE))
2311 if (gadget->Activation & GACT_RELVERIFY)
2313 DEBUG_KEY(dprintf("Handler: GACT_RELVERIFY\n"));
2314 ih_fire_intuimessage(w,
2315 IDCMP_GADGETUP,
2316 imsgcode,
2317 gadget,
2318 IntuitionBase);
2320 if (req && gadget->Activation & GACT_ENDGADGET)
2322 DEBUG_KEY(dprintf("Handler: GACT_ENDGADGET\n"));
2323 EndRequest(req, w);
2325 req = w->FirstRequest;
2326 ret = 0;
2330 if ((gadget->Flags & GFLG_TABCYCLE) && (ret & SGA_NEXTACTIVE))
2332 gadget = FindCycleGadget(w, req, gadget, GMR_NEXTACTIVE);
2333 DEBUG_KEY(dprintf("Handler: TabCycle next gadget 0x%lx\n",gadget));
2335 else if ((gadget->Flags & GFLG_TABCYCLE) && (ret & SGA_PREVACTIVE))
2337 gadget = FindCycleGadget(w, req, gadget, GMR_PREVACTIVE);
2338 DEBUG_KEY(dprintf("Handler: TabCycle prev gadget 0x%lx\n",gadget));
2340 else
2342 gadget = NULL;
2345 if (gadget)
2347 gadget = DoActivateGadget(w, req, gadget, IntuitionBase);
2350 } /* if (ret & (SGA_END | SGA_NEXTACTIVE | SGA_PREVACTIVE)) */
2352 break;
2355 case GTYP_CUSTOMGADGET:
2356 DEBUG_KEY(dprintf("Handler: GTYP_CUSTOMGADGET\n"));
2357 DEBUG_KEY(dprintf("Handler: send GM_HANDLEINPUT\n"));
2358 gadget = DoGPInput(gi,
2359 gadget,
2361 GM_HANDLEINPUT,
2362 &reuse_event,
2363 IntuitionBase);
2364 DEBUG_KEY(dprintf("Handler: reuse %ld\n",reuse_event));
2365 break;
2367 } /* switch (gadget type) */
2369 } /* if (a gadget is currently active) */
2370 else if (w && (!req || req->Flags & NOISYREQ))
2372 BOOL menushortcut = FALSE;
2374 DEBUG_KEY(dprintf("Handler: No Gadget active\n"));
2375 DEBUG_KEY(dprintf("Handler: Qualifier 0x%lx WinFlags 0x%lx IDCMP 0x%lx\n",ie->ie_Qualifier,w->Flags,w->IDCMPFlags));
2377 if ((ie->ie_Qualifier & IEQUALIFIER_RCOMMAND) &&
2378 (!(w->Flags & WFLG_RMBTRAP)) &&
2379 (w->IDCMPFlags & IDCMP_MENUPICK))
2381 struct Menu *strip = 0;
2383 DEBUG_KEY(dprintf("Handler: MenuKey\n"));
2384 ObtainSemaphore(&GetPrivIBase(IntuitionBase)->MenuLock);
2386 strip = w->MenuStrip;
2388 if (((struct IntWindow *)w)->menulendwindow)
2390 strip = ((struct IntWindow *)w)->menulendwindow->MenuStrip;
2393 DEBUG_KEY(dprintf("Handler: MenuStrip 0x%lx\n",strip));
2394 if (strip)
2396 UBYTE key;
2398 if (MapRawKey(ie, &key, 1, NULL) == 1)
2400 UWORD menucode;
2402 menucode = FindMenuShortCut(strip, key, TRUE, IntuitionBase);
2404 DEBUG_KEY(dprintf("Handler: menucode 0x%lx\n",menucode));
2406 if (menucode != MENUNULL)
2408 DEBUG_KEY(dprintf("Handler: build menuevent\n"));
2409 ie->ie_Class = IECLASS_MENU;
2410 ie->ie_SubClass = IESUBCLASS_MENUSTOP;
2411 ie->ie_EventAddress = w;
2412 ie->ie_Code = menucode;
2414 reuse_event = TRUE;
2415 menushortcut = TRUE;
2417 MENUS_ACTIVE = TRUE;
2418 iihdata->MenuWindow = w;
2421 else
2423 DEBUG_KEY(dprintf("Handler: MapRawKey failed\n"));
2426 if (!menushortcut) /* !! */
2427 ReleaseSemaphore(&GetPrivIBase(IntuitionBase)->MenuLock);
2429 } /* if could be a menu short cut */
2430 else
2431 if ((ie->ie_Qualifier & IEQUALIFIER_RCOMMAND) &&
2432 (!(w->IDCMPFlags & IDCMP_MENUPICK)))
2434 struct Menu *strip = 0;
2435 struct Window *window = w;
2437 /* not sure here about RMBTRAP */
2438 DEBUG_KEY(dprintf("Handler: no idcmp, create a MENULIST idcmp\n"));
2440 ObtainSemaphore(&GetPrivIBase(IntuitionBase)->MenuLock);
2442 strip = w->MenuStrip;
2444 if (((struct IntWindow *)w)->menulendwindow)
2446 strip = ((struct IntWindow *)w)->menulendwindow->MenuStrip;
2447 window = ((struct IntWindow *)w)->menulendwindow;
2450 DEBUG_KEY(dprintf("Handler: MenuStrip 0x%lx\n",strip));
2451 if (strip)
2453 UBYTE key;
2455 if (MapRawKey(ie, &key, 1, NULL) == 1)
2457 UWORD menucode;
2459 menucode = FindMenuShortCut(strip, key, TRUE, IntuitionBase);
2461 DEBUG_KEY(dprintf("Handler: menucode 0x%lx\n",menucode));
2463 if (menucode != MENUNULL)
2465 DEBUG_KEY(dprintf("Handler: build menuevent\n"));
2466 ih_fire_intuimessage(window,
2467 IDCMP_MENUPICK,
2468 menucode,
2469 ie->ie_position.ie_addr, /* ie_dead.ie_prev[1|2]Down[Code|Qual]. 64 bit machines!? */
2470 IntuitionBase);
2471 keep_event = FALSE;
2472 menushortcut = TRUE;
2475 else
2477 DEBUG_KEY(dprintf("Handler: MapRawKey failed\n"));
2480 ReleaseSemaphore(&GetPrivIBase(IntuitionBase)->MenuLock);
2481 } /* if could be a menu short but current window has no idcmp cut */
2483 if (menushortcut)
2485 DEBUG_KEY(dprintf("Handler: menu shortcut..break\n"));
2486 break;
2489 /* This is a regular RAWKEY event (no gadget taking care
2490 of it...). */
2492 if (iihdata->ActQualifier & IEQUALIFIER_REPEAT)
2494 /* don't send repeat key events if repeatqueue is full */
2495 if (IW(w)->num_repeatevents >= IW(w)->repeatqueue)
2497 DEBUG_KEY(dprintf("Handler: RepeatEvents full..don't send more\n"));
2498 break;
2502 if (w->IDCMPFlags & IDCMP_VANILLAKEY)
2504 UBYTE keyBuffer;
2506 DEBUG_KEY(dprintf("Handler: VANILLAKEY\n"));
2507 // DEBUG_KEY(dprintf("Handler: MapRawKey ie 0x%lx KeyMapBase 0x%lx IntutionBase 0x%lx\n",ie,KeymapBase,IntuitionBase));
2509 if (MapRawKey(ie, &keyBuffer, 1, NULL) == 1)
2511 DEBUG_KEY(dprintf("Handler: send VANILLAKEY msg\n"));
2512 ih_fire_intuimessage(w,
2513 IDCMP_VANILLAKEY,
2514 keyBuffer,
2515 ie->ie_position.ie_addr, /* ie_dead.ie_prev[1|2]Down[Code|Qual]. 64 bit machines!? */
2516 IntuitionBase);
2517 DEBUG_KEY(dprintf("Handler: done\n"));
2518 break;
2521 /* If the event mapped to more than one byte, it is not
2522 a legal VANILLAKEY, so we send it as the original
2523 RAWKEY event. */
2527 if (w->IDCMPFlags & IDCMP_RAWKEY)
2529 DEBUG_KEY(dprintf("Handler: send IDCMP_RAWKEY Qual 0x%lx Code 0x%lx addr 0x%lx Event\n",
2530 ie->ie_Qualifier,ie->ie_Code,ie->ie_position.ie_addr));
2531 ih_fire_intuimessage(w,
2532 IDCMP_RAWKEY,
2533 ie->ie_Code,
2534 ie->ie_position.ie_addr, /* ie_dead.ie_prev[1|2]Down[Code|Qual]. 64 bit machine!? */
2535 IntuitionBase);
2536 keep_event = FALSE;
2539 DEBUG_KEY(dprintf("Handler: done\n"));
2540 } /* regular RAWKEY */
2543 break; /* case IECLASS_RAWKEY */
2545 case IECLASS_TIMER:
2546 if (iihdata->MouseBoundsKillTimer)
2548 iihdata->MouseBoundsKillTimer--;
2549 if (iihdata->MouseBoundsKillTimer == 0)
2551 iihdata->MouseBoundsActiveFlag = FALSE;
2555 if (GetPrivIBase(IntuitionBase)->PointerDelay)
2557 ULONG lock = LockIBase(0);
2559 if (--GetPrivIBase(IntuitionBase)->PointerDelay == 0)
2561 struct SharedPointer *shared_pointer;
2562 struct Window *window = IntuitionBase->ActiveWindow;
2563 struct IntScreen *scr;
2565 DEBUG_POINTER(dprintf("InputHandler: PointerDelay\n"));
2566 DEBUG_POINTER(dprintf("InputHandler: Window 0x%lx\n",
2567 window));
2569 if (window)
2571 Object *pointer = ((struct IntWindow *)window)->pointer;
2573 DEBUG_POINTER(dprintf("InputHandler: Pointer 0x%lx\n",
2574 pointer));
2575 scr = GetPrivScreen(window->WScreen);
2576 if (scr)
2578 DEBUG_POINTER(dprintf("InputHandler: Screen 0x%lx\n",
2579 scr));
2580 if (pointer == NULL)
2582 pointer = GetPrivIBase(IntuitionBase)->DefaultPointer;
2585 if (((struct IntWindow *)window)->busy)
2587 pointer = GetPrivIBase(IntuitionBase)->BusyPointer;
2590 GetAttr(POINTERA_SharedPointer, pointer, (IPTR *) &shared_pointer);
2592 DEBUG_POINTER(dprintf("InputHandler: scr 0x%lx pointer 0x%lx shared_pointer 0x%lx\n",
2593 scr, pointer, shared_pointer));
2594 DEBUG_POINTER(dprintf("InputHandler: sprite 0x%lx\n",
2595 shared_pointer->sprite));
2597 if (DoMethod(scr->IMonitorNode, MM_SetPointerShape, shared_pointer))
2599 ObtainSharedPointer(shared_pointer, IntuitionBase);
2600 ReleaseSharedPointer(scr->Pointer, IntuitionBase);
2601 scr->Pointer = shared_pointer;
2602 if (window)
2604 window->XOffset = shared_pointer->xoffset;
2605 window->YOffset = shared_pointer->yoffset;
2608 else
2610 DEBUG_POINTER(dprintf("InputHandler: can't set pointer.\n"));
2613 else
2615 DEBUG_POINTER(dprintf("InputHandler: no screen.\n"));
2618 else
2620 DEBUG_POINTER(dprintf("InputHandler: no window.\n"));
2624 UnlockIBase(lock);
2627 if (GetPrivIBase(IntuitionBase)->MenuVerifyScreen)
2629 struct IntScreen *scr = GetPrivIBase(IntuitionBase)->MenuVerifyScreen;
2631 if ((--scr->MenuVerifyTimeOut) <= 0)
2633 struct InputEvent ie;
2635 /* currently we ONLY need the menu open time ! */
2636 ie.ie_TimeStamp.tv_secs = IntuitionBase->Seconds;
2637 ie.ie_TimeStamp.tv_micro = IntuitionBase->Micros;
2639 if (FireMenuMessage(MMCODE_START, scr->MenuVerifyActiveWindow, &ie, IntuitionBase))
2641 /* This lock will be released only when the user is
2642 done with menus = when IECLASS_MENU + IESUBCLASS_MENUSTOP
2643 event arrives (generated by MenuHandler task) */
2645 ObtainSemaphore(&GetPrivIBase(IntuitionBase)->MenuLock);
2646 iihdata->MenuWindow = scr->MenuVerifyActiveWindow;
2647 MENUS_ACTIVE = TRUE;
2650 scr->MenuVerifyActiveWindow = NULL;
2651 scr->MenuVerifyTimeOut = 0;
2652 scr->MenuVerifyMsgCount = 0;
2653 scr->MenuVerifySeconds = 0;
2654 scr->MenuVerifyMicros = 0;
2655 GetPrivIBase(IntuitionBase)->MenuVerifyScreen = NULL;
2658 else if (MENUS_ACTIVE)
2660 FireMenuMessage(MMCODE_EVENT, 0, ie, IntuitionBase);
2661 keep_event = FALSE;
2662 break;
2665 #ifdef SKINS
2666 if (screen->MouseY <= screen->BarHeight && GetPrivScreen(screen)->SpecialFlags & SF_AppearingBar && !iihdata->TitlebarOnTop && iihdata->TitlebarAppearTime)
2668 UQUAD currenttime = (((UQUAD)ie->ie_TimeStamp.tv_secs) * 50) + (UQUAD)(ie->ie_TimeStamp.tv_micro / 20000);
2669 if (currenttime >= iihdata->TitlebarAppearTime + 10)
2671 iihdata->TitlebarOnTop = TRUE;
2672 iihdata->TitlebarAppearTime = 0;
2674 LOCK_REFRESH(screen);
2676 MoveLayer(0, screen->BarLayer, 0, screen->BarHeight + 1);
2677 UpfrontLayer(0, screen->BarLayer);
2678 CheckLayers(screen, IntuitionBase);
2680 UNLOCK_REFRESH(screen);
2683 #endif
2686 UQUAD currenttime = (((UQUAD)ie->ie_TimeStamp.tv_secs) * 50) + (UQUAD)(ie->ie_TimeStamp.tv_micro / 20000);
2687 #define SECONDS(x) (x*50)
2688 if (iihdata->HelpGadgetFindTime && (currenttime >= iihdata->HelpGadgetFindTime + SECONDS(1)))
2690 struct Gadget *lhg = iihdata->LastHelpGadget;
2691 fire_intuimessage(iihdata->LastHelpWindow,
2692 IDCMP_GADGETHELP,
2693 lhg ? lhg->GadgetID : 0, /* Don't know what it should be */
2694 lhg,
2695 IntuitionBase);
2696 iihdata->HelpGadgetFindTime = 0;
2700 if (gadget)
2702 if (IS_BOOPSI_GADGET(gadget))
2704 gadget = DoGPInput(gi, gadget, ie, GM_HANDLEINPUT, &reuse_event, IntuitionBase);
2707 } /* if (gadget) */
2709 #if USE_NEWDISPLAYBEEP
2711 if (GetPrivIBase(IntuitionBase)->BeepingScreens)
2713 ULONG lock;
2714 struct Screen *scr;
2716 lock = LockIBase(0);
2718 for (scr = IntuitionBase->FirstScreen;
2719 scr && GetPrivIBase(IntuitionBase)->BeepingScreens;
2720 scr = scr->NextScreen)
2722 if ((scr->Flags & BEEPING) &&
2723 !GetPrivScreen(scr)->BeepingCounter--)
2725 GetPrivIBase(IntuitionBase)->BeepingScreens--;
2726 scr->Flags &= (UWORD) ~BEEPING;
2728 /* if (GetBitMapAttr(scr->RastPort.BitMap, BMA_DEPTH) <= 8)
2729 // visual beep on CLUT-screen
2731 // SetRGB4 (&screen->ViewPort, 0, scr->SaveColor0 & 0x000F, (scr->SaveColor0 & 0x00F0) >> 4, (scr->SaveColor0 & 0x0F00) >> 8);
2732 SetRGB32 (&scr->ViewPort, 0,
2733 GetPrivScreen(scr)->DisplayBeepColor0[0],
2734 GetPrivScreen(scr)->DisplayBeepColor0[1],
2735 GetPrivScreen(scr)->DisplayBeepColor0[2]
2738 else
2739 // visual beep on hi- and truecolor screens
2741 RenderScreenBar(scr, FALSE, IntuitionBase);
2744 RenderScreenBar(scr, FALSE, IntuitionBase);
2748 UnlockIBase(lock);
2750 #endif /* USE_NEWDISPLAYBEEP */
2752 if (!w) break;
2754 /* Send INTUITICK msg only if app already replied the last INTUITICK msg */
2755 if (w->Flags & WFLG_WINDOWTICKED) break;
2757 if (w->IDCMPFlags & IDCMP_INTUITICKS)
2759 /* Set the WINDOWTICKED flag, it will be cleared again when the app
2760 replies back the msg and the InputHandler handles the replymsg
2761 in HandleIntuiReplyPort() */
2763 ih_fire_intuimessage(w,
2764 IDCMP_INTUITICKS,
2767 IntuitionBase);
2769 break; /* case IECLASS_TIMER */
2771 case IECLASS_MENU:
2772 if (MENUS_ACTIVE && (ie->ie_SubClass == IESUBCLASS_MENUSTOP))
2774 struct Window *eventwin = (struct Window *)ie->ie_EventAddress;
2776 iihdata->MenuWindow = NULL;
2777 MENUS_ACTIVE = FALSE;
2779 /* semaphore was locked when menu action started, see
2780 above where MMCODE_START MenuMessage is sent.
2782 It could have also have been locked if the user
2783 activated one of the menu key shortcuts, see
2784 "case IECLASS_RAWKEY" */
2786 ReleaseSemaphore(&GetPrivIBase(IntuitionBase)->MenuLock);
2788 keep_event = FALSE;
2790 if (((struct IntWindow *)eventwin)->menulendwindow)
2792 eventwin = ((struct IntWindow *)eventwin)->menulendwindow;
2795 ih_fire_intuimessage((struct Window *)eventwin,
2796 IDCMP_MENUPICK,
2797 ie->ie_Code,
2798 (struct Window *)ie->ie_EventAddress,
2799 IntuitionBase);
2802 break;
2804 case IECLASS_DISKINSERTED:
2805 case IECLASS_DISKREMOVED:
2806 case IECLASS_NEWPREFS:
2808 struct Screen *scr;
2809 ULONG idcmp;
2810 LONG lock;
2812 switch (ie->ie_Class)
2814 case IECLASS_DISKINSERTED:
2815 idcmp = IDCMP_DISKINSERTED;
2816 break;
2818 case IECLASS_DISKREMOVED:
2819 idcmp = IDCMP_DISKREMOVED;
2820 break;
2822 default:
2823 idcmp = IDCMP_NEWPREFS;
2825 * Here we need to update the mouse prefs and
2826 * maybe other stuff which comes from the global prefs file.
2828 break;
2831 lock = LockIBase(0);
2833 for (scr = IntuitionBase->FirstScreen; scr; scr = scr->NextScreen)
2835 struct Window *win;
2837 for (win = scr->FirstWindow; win; win = win->NextWindow)
2839 /* stegerg:
2840 CHECKME, really use fire_intuimessage() here,
2841 instead of ih_fireintuimessage? Same for
2842 IDCMP_GADGETHELP above, BTW. */
2844 fire_intuimessage(win,
2845 idcmp,
2847 NULL,
2848 IntuitionBase);
2852 UnlockIBase(lock);
2854 break;
2856 case IECLASS_NEWMOUSE:
2857 #ifdef __MORPHOS__
2859 * The following is only needed on hardware not running
2860 * the NewMouse driver.
2862 if (w->IDCMPFlags & IDCMP_RAWKEY && (!SysBase->MaxLocMem))
2864 ih_fire_intuimessage(w,
2865 IDCMP_RAWKEY,
2866 ie->ie_Code,
2867 ie->ie_position.ie_addr, /* ie_dead.ie_prev[1|2]Down[Code|Qual]. 64 bit machine!? */
2868 IntuitionBase);
2869 keep_event = FALSE;
2871 break;
2872 #endif
2873 case IECLASS_NULL:
2874 break;
2876 #ifdef __MORPHOS__
2877 case IECLASS_NEWTIMER:
2878 if (MENUS_ACTIVE)
2880 FireMenuMessage(MMCODE_EVENT, 0, ie, IntuitionBase);
2881 keep_event = FALSE;
2882 break;
2885 if (gadget)
2887 if (gadget == iihdata->MasterSizeGadget)
2889 gadget = DoGPInput(gi, gadget, ie, GM_HANDLEINPUT, &reuse_event, IntuitionBase);
2892 } /* if (gadget) */
2893 break;
2894 #endif /* __MORPHOS__ */
2896 default:
2897 if (MENUS_ACTIVE)
2899 FireMenuMessage(MMCODE_EVENT, 0, ie, IntuitionBase);
2900 keep_event = FALSE;
2901 break;
2906 "[Intui] InputHandler: Unknown IEClass: addr = %x class = %d (origclass = %d)\n",
2907 orig_ie, ie->ie_Class,orig_ie->ie_Class
2910 break;
2911 } /* switch (ie->ie_Class) */
2913 if (reuse_event)
2916 else if (keep_event && !ie_used)
2918 *iihdata->EndInputEventChain = orig_ie;
2919 iihdata->EndInputEventChain = &orig_ie->ie_NextEvent;
2920 ie_used = TRUE;
2922 else if (!ie_used)
2924 orig_ie->ie_NextEvent = iihdata->FreeInputEvents;
2925 iihdata->FreeInputEvents = orig_ie;
2928 } /* for (each event in the chain) */
2930 iihdata->ActiveGadget = gadget;
2932 D(bug("Outside pollingloop\n"));
2934 #if SINGLE_SETPOINTERPOS_PER_EVENTLOOP
2935 if (call_setpointerpos)
2936 MySetPointerPos(IntuitionBase);
2937 #endif
2939 /* Terminate the event chain. */
2940 *iihdata->EndInputEventChain = NULL;
2942 /* Transfer the list of allocated events in the list of events that should
2943 * be freed the next time the handler is entered.
2945 iihdata->AllocatedInputEventList = iihdata->NewAllocatedInputEventList;
2946 NEWLIST((struct List*)&iihdata->NewAllocatedInputEventList);
2948 /* Reset the event chain here, not at the beginning of the handler, for
2949 * events that might be allocated in other handers.
2951 iihdata->EndInputEventChain = &iihdata->ReturnInputEvent;
2952 iihdata->FreeInputEvents = NULL;
2954 ReleaseSemaphore(&GetPrivIBase(IntuitionBase)->InputHandlerLock);
2956 // DEBUG_HANDLER(dprintf("Handler: ->IBase 0x%lx KeyMapBase 0x%lx\n",IntuitionBase,KeymapBase));
2958 return iihdata->ReturnInputEvent;
2960 AROS_USERFUNC_EXIT
2963 /****************************************************************************************/