Enable VFP unit as early as possible. This has to be so since e.g. gcc9 uses vfp...
[AROS.git] / rom / intuition / inputhandler.c
blob0381000f3e090d94944d2342f27e78d2b693b23f
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 <aros/config.h>
11 #include <proto/exec.h>
12 #include <proto/execlock.h>
13 #include <proto/intuition.h>
14 #include <proto/alib.h>
15 #include <proto/layers.h>
16 #include <proto/graphics.h>
17 #include <proto/keymap.h>
18 #include <proto/utility.h>
19 #include <proto/input.h>
20 #include <proto/timer.h>
21 #include <exec/memory.h>
22 #include <exec/alerts.h>
23 #include <exec/interrupts.h>
24 #include <exec/ports.h>
25 #include <intuition/intuition.h>
26 #include <intuition/intuitionbase.h>
27 #include <intuition/gadgetclass.h>
28 #include <intuition/pointerclass.h>
29 #include <intuition/cghooks.h>
30 #include <intuition/sghooks.h>
31 #include <devices/inputevent.h>
32 #include <devices/rawkeycodes.h>
33 #include <clib/macros.h>
34 #include "inputhandler.h"
36 #include "boopsigadgets.h"
37 #include "boolgadgets.h"
38 #include "propgadgets.h"
39 #include "strgadgets.h"
40 #include "gadgets.h"
41 #include "intuition_intern.h" /* EWFLG_xxx */
42 #include "inputhandler_support.h"
43 #include "inputhandler_actions.h"
44 #include "menus.h"
45 #include "monitorclass_private.h"
47 #ifdef SKINS
48 # include "smallmenu.h"
49 # include "intuition_customizesupport.h"
50 #endif
52 #undef DEBUG
53 #define DEBUG 0
54 #include <aros/debug.h>
56 #define DEBUG_HANDLER(x) ;
57 #define DEBUG_KEY(x) ;
58 #define DEBUG_SCREENKEY(x) ;
59 #define DEBUG_AUTOSCROLL(x)
60 #define DEBUG_CLICK(x)
61 #define DEBUG_DRAG(x)
62 #define DEBUG_GADGET(x)
63 #define DEBUG_MONITOR(x)
64 #define DEBUG_MOUSE(x)
65 #define DEBUG_WINDOW(x)
67 /****************************************************************************************/
69 struct Interrupt *InitIIH(struct IntuitionBase *IntuitionBase)
71 struct Interrupt *iihandler;
73 D(bug("[Intuition] %s(IntuitionBase=%p)\n", __func__, IntuitionBase));
75 iihandler = AllocMem(sizeof (struct Interrupt), MEMF_PUBLIC | MEMF_CLEAR);
76 if (iihandler)
78 struct IIHData *iihdata;
80 iihdata = AllocMem(sizeof (struct IIHData), MEMF_PUBLIC | MEMF_CLEAR);
81 if (iihdata)
83 struct MsgPort *port;
85 port = CreateMsgPort();
86 if (port)
88 if ((iihdata->InputEventMemPool = CreatePool(MEMF_PUBLIC | MEMF_CLEAR,
89 sizeof(struct GeneratedInputEvent) * 10,
90 sizeof(struct GeneratedInputEvent) * 10)) &&
91 (iihdata->ActionsMemPool = CreatePool(MEMF_SEM_PROTECTED,
92 2000, 2000)))
94 const struct TagItem dragtags[] =
96 {GA_SysGadget , TRUE },
97 {GA_SysGType , GTYP_WDRAGGING},
98 {TAG_DONE }
101 const struct TagItem sizetags[] =
103 {GA_SysGadget , TRUE },
104 {GA_SysGType , GTYP_SIZING },
105 {TAG_DONE }
108 iihdata->MasterDragGadget = (struct Gadget *)NewObjectA(GetPrivIBase(IntuitionBase)->dragbarclass,
109 NULL,
110 (struct TagItem *)dragtags);
112 iihdata->MasterSizeGadget = (struct Gadget *)NewObjectA(GetPrivIBase(IntuitionBase)->sizebuttonclass,
113 NULL,
114 (struct TagItem *)sizetags);
116 if (iihdata->MasterDragGadget && iihdata->MasterSizeGadget)
118 ULONG lock;
120 /* We do not want to be woken up by message replies.
121 We are anyway woken up about 10 times a second by
122 timer events
124 FreeSignal(port->mp_SigBit);
125 port->mp_SigBit = -1;
126 port->mp_Flags = PA_IGNORE;
128 iihdata->IntuiReplyPort = port;
130 NEWLIST((struct List*) &iihdata->IntuiActionQueue);
131 NEWLIST((struct List*)&iihdata->NewAllocatedInputEventList);
132 NEWLIST((struct List*)&iihdata->AllocatedInputEventList);
133 iihdata->EndInputEventChain = &iihdata->ReturnInputEvent;
134 iihdata->FreeInputEvents = NULL;
136 iihdata->ActQualifier = IEQUALIFIER_RELATIVEMOUSE;
138 /* Note: there are several routines like CloseWindow, which
139 expect is_Data to point to the IIHData structure, so don't
140 change this! */
142 iihandler->is_Code = (VOID_FUNC)AROS_ASMSYMNAME(IntuiInputHandler);
143 iihandler->is_Data = iihdata;
144 iihandler->is_Node.ln_Pri = 50;
145 iihandler->is_Node.ln_Name = "Intuition InputHandler";
147 lock = LockIBase(0UL);
149 iihdata->IntuitionBase = IntuitionBase;
151 UnlockIBase(lock);
153 GetPrivIBase(IntuitionBase)->IntuiReplyPort = iihdata->IntuiReplyPort;
154 GetPrivIBase(IntuitionBase)->IntuiActionQueue = &iihdata->IntuiActionQueue;
156 ReturnPtr ("InitIIH", struct Interrupt *, iihandler);
157 } /* f (iihdata->MasterDragGadget && iihdata->MasterSizeGadget) */
159 DisposeObject((Object *)iihdata->MasterDragGadget);
160 DisposeObject((Object *)iihdata->MasterSizeGadget);
162 DeletePool(iihdata->ActionsMemPool);
163 DeletePool(iihdata->InputEventMemPool);
165 } /* if (iihdata->InputEventMemPool = ... */
166 DeleteMsgPort(port);
168 } /* if (port) */
169 FreeMem(iihdata, sizeof (struct IIHData));
170 iihdata->MouseBoundsActiveFlag = FALSE;
172 } /* if (iihdata) */
173 FreeMem(iihandler, sizeof (struct Interrupt));
175 } /* if (iihandler) */
177 ReturnPtr ("InitIIH", struct Interrupt *, NULL);
180 /****************************************************************************************/
182 VOID CleanupIIH(struct Interrupt *iihandler, struct IntuitionBase *IntuitionBase)
184 struct IIHData *iihdata = (struct IIHData *)iihandler->is_Data;
186 D(bug("[Intuition] %s()\n", __func__));
188 DisposeObject((Object *)iihdata->MasterDragGadget);
189 DisposeObject((Object *)iihdata->MasterSizeGadget);
191 FreeGeneratedInputEvents(iihdata);
192 DeletePool(iihdata->InputEventMemPool);
193 DeletePool(iihdata->ActionsMemPool);
195 /* One might think that this port is still in use by the inputhandler.
196 ** However, if intuition is closed for the last time, there should be no
197 ** windows that IntuiMessage can be sent to.
199 FreeMem(iihdata->IntuiReplyPort, sizeof (struct MsgPort));
201 FreeMem(iihdata, sizeof (struct IIHData));
202 FreeMem(iihandler, sizeof (struct Interrupt));
204 return;
207 /****************************************************************************************/
209 static void HandleIntuiReplyPort(struct IIHData *iihdata, struct IntuitionBase *IntuitionBase)
211 struct Library *TimerBase = GetPrivIBase(IntuitionBase)->TimerBase;
212 struct IntuiMessage *im;
214 D(bug("[Intuition] %s()\n", __func__));
216 while ((im = (struct IntuiMessage *)GetMsg(iihdata->IntuiReplyPort)))
218 if (im->IDCMPWindow && ResourceExisting(im->IDCMPWindow, RESOURCE_WINDOW, IntuitionBase))
220 struct IntWindow *win = (struct IntWindow *)im->IDCMPWindow;
222 Forbid();
223 GetSysTime(&win->lastmsgreplied);
224 Permit();
226 switch(im->Class)
228 case IDCMP_MOUSEMOVE:
229 IW(im->IDCMPWindow)->num_mouseevents--;
230 break;
232 case IDCMP_INTUITICKS:
233 AROS_ATOMIC_AND(im->IDCMPWindow->Flags, ~WFLG_WINDOWTICKED);
234 break;
236 #if USE_IDCMPUPDATE_MESSAGECACHE
237 case IDCMP_IDCMPUPDATE:
238 IW(im->IDCMPWindow)->num_idcmpupdate--;
240 if (!(IW(im->IDCMPWindow)->num_idcmpupdate) && IW(im->IDCMPWindow)->messagecache)
242 SendIntuiMessage(im->IDCMPWindow,IW(im->IDCMPWindow)->messagecache);
243 IW(im->IDCMPWindow)->messagecache = 0;
245 break;
246 #endif
248 case IDCMP_MENUVERIFY:
250 struct Window *w = im->IDCMPWindow;
251 struct IntScreen *scr = 0;
253 scr = GetPrivScreen(w->WScreen);
255 if (scr != GetPrivIBase(IntuitionBase)->MenuVerifyScreen ||
256 scr->MenuVerifySeconds > im->Seconds ||
257 (scr->MenuVerifySeconds == im->Seconds &&
258 scr->MenuVerifyMicros > im->Micros))
260 /* The timeout has expired, just ignore. */
262 else
264 --scr->MenuVerifyMsgCount;
265 if (w == scr->MenuVerifyActiveWindow &&
266 im->Code == MENUCANCEL)
268 ULONG lock = LockIBase(0);
269 struct Window *w1;
271 for (w1 = scr->Screen.FirstWindow; w1; w1 = w1->NextWindow)
273 if (w1->IDCMPFlags & IDCMP_MENUVERIFY && w1 != scr->MenuVerifyActiveWindow)
275 ih_fire_intuimessage(w1,
276 IDCMP_MOUSEBUTTONS,
277 MENUUP,
279 IntuitionBase);
283 UnlockIBase(lock);
285 scr->MenuVerifyActiveWindow = NULL;
286 scr->MenuVerifyTimeOut = 0;
287 scr->MenuVerifyMsgCount = 0;
288 scr->MenuVerifySeconds = 0;
289 scr->MenuVerifyMicros = 0;
290 GetPrivIBase(IntuitionBase)->MenuVerifyScreen = NULL;
292 else if (scr->MenuVerifyMsgCount == 0)
294 struct InputEvent ie;
296 /* currently we ONLY need the menu open time ! */
297 ie.ie_TimeStamp.tv_secs = im->Seconds;
298 ie.ie_TimeStamp.tv_micro = im->Micros;
300 if (FireMenuMessage(MMCODE_START, scr->MenuVerifyActiveWindow, &ie, IntuitionBase))
302 /* This lock will be released only when the user is
303 done with menus = when IECLASS_MENU + IESUBCLASS_MENUSTOP
304 event arrives (generated by MenuHandler task) */
306 ObtainSemaphore(&GetPrivIBase(IntuitionBase)->MenuLock);
307 iihdata->MenuWindow = scr->MenuVerifyActiveWindow;
308 MENUS_ACTIVE = TRUE;
311 scr->MenuVerifyActiveWindow = NULL;
312 scr->MenuVerifyTimeOut = 0;
313 scr->MenuVerifyMsgCount = 0;
314 scr->MenuVerifySeconds = 0;
315 scr->MenuVerifyMicros = 0;
316 GetPrivIBase(IntuitionBase)->MenuVerifyScreen = NULL;
319 break;
322 case IDCMP_SIZEVERIFY:
324 struct GadgetInfo *gi = &iihdata->GadgetInfo;
325 struct Window *w = im->IDCMPWindow;
326 struct Gadget *gadget = im->IAddress;
327 struct InputEvent ie;
328 BOOL reuse_event;
330 PrepareGadgetInfo(gi, IntuitionBase->ActiveScreen, w, NULL);
331 SetGadgetInfoGadget(gi, gadget, IntuitionBase);
333 if (IS_BOOPSI_GADGET(gadget))
335 ie.ie_NextEvent = NULL;
336 ie.ie_Class = IECLASS_RAWMOUSE;
337 ie.ie_SubClass = 0;
338 ie.ie_Code = IECODE_LBUTTON;
339 ie.ie_Qualifier = im->Qualifier;
340 ie.ie_X = im->MouseX;
341 ie.ie_Y = im->MouseY;
342 ie.ie_TimeStamp.tv_secs = IntuitionBase->Seconds;
343 ie.ie_TimeStamp.tv_micro = IntuitionBase->Micros;
345 DoGPInput(gi,
346 gadget,
347 &ie,
348 GM_GOACTIVE,
349 &reuse_event,
350 IntuitionBase);
352 /* For compatibility, send a GM_HANDLEINPUT too */
353 ie.ie_Class = IECLASS_RAWMOUSE;
354 ie.ie_Code = IECODE_NOBUTTON;
355 ie.ie_X = 0;
356 ie.ie_Y = 0;
358 gadget = DoGPInput(gi,
359 gadget,
360 &ie,
361 GM_HANDLEINPUT,
362 &reuse_event,
363 IntuitionBase);
366 /* From now on the master drag/size gadget takes over */
368 iihdata->ActiveSysGadget = gadget;
369 gadget = iihdata->MasterSizeGadget;
370 iihdata->ActiveGadget = gadget;
372 ie.ie_Class = IECLASS_RAWMOUSE;
373 ie.ie_Code = IECODE_LBUTTON;
374 ie.ie_X = im->MouseX;
375 ie.ie_Y = im->MouseY;
377 DoGPInput(gi,
378 gadget,
379 &ie,
380 GM_GOACTIVE,
381 &reuse_event,
382 IntuitionBase);
383 break;
386 case IDCMP_REQVERIFY:
388 struct Window *w = im->IDCMPWindow;
390 EndRequest(w->DMRequest, w);
392 ih_fire_intuimessage(w,
393 IDCMP_REQSET,
396 IntuitionBase);
398 break;
400 case IDCMP_WBENCHMESSAGE:
401 DEBUG_WORKBENCH(dprintf("HandleIntuiReplyPort: code 0x%lx\n",
402 im->Code));
403 break;
405 } /* switch(im->Class) */
407 if (im->Qualifier & IEQUALIFIER_REPEAT)
409 /* IDCMP_IDCMPUPDATE messages can also be sent from app task, therefore
410 it would be better if there was an ATOMIC_DEC macro or something */
412 if (IW(im->IDCMPWindow)->num_repeatevents)
414 IW(im->IDCMPWindow)->num_repeatevents--;
418 FreeIntuiMessage(im);
420 } /* while ((im = (struct IntuiMessage *)GetMsg(iihdata->IntuiReplyPort))) */
422 /****************************************************************************************/
424 struct Window *GetToolBoxWindow(struct InputEvent *ie, struct Screen *scr, struct IntuitionBase *IntuitionBase)
426 /* The caller has checked that the input event is a IECLASS_RAWMOUSE, SELECTDOWN event */
427 /* NOTE: may be called with NULL ie ptr! */
428 struct LayersBase *LayersBase = GetPrivIBase(IntuitionBase)->LayersBase;
429 struct Layer *l;
430 struct Window *new_w = NULL;
432 D(bug("[Intuition] %s()\n", __func__));
434 if (scr)
436 D(bug("GetToolBoxWindow: Click at (%d,%d)\n",scr->MouseX,scr->MouseY));
438 /* What layer ? */
439 LockLayerInfo(&scr->LayerInfo);
441 l = WhichLayer(&scr->LayerInfo, scr->MouseX, scr->MouseY);
443 UnlockLayerInfo(&scr->LayerInfo);
445 if (NULL == l)
447 new_w = NULL;
448 D(bug("GetToolBoxWindow: Click not inside layer\n"));
450 else if (l == scr->BarLayer)
453 else
455 new_w = (struct Window *)l->Window;
456 if (new_w)
458 if ((new_w->Flags & WFLG_TOOLBOX) == 0) new_w = NULL;
460 if (!new_w)
462 D(bug("GetToolBoxWindow: Selected layer is not a ToolBox window\n"));
464 else
466 D(bug("GetToolBoxWindow: Found layer %p\n", l));
471 D(bug("GetToolBoxWindow: New window %p\n", new_w));
472 return new_w;
475 /****************************************************************************************/
477 #define KEY_QUALIFIERS (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT | \
478 IEQUALIFIER_CAPSLOCK | IEQUALIFIER_CONTROL | \
479 IEQUALIFIER_LALT | IEQUALIFIER_RALT | \
480 IEQUALIFIER_LCOMMAND | IEQUALIFIER_RCOMMAND | \
481 IEQUALIFIER_NUMERICPAD)
483 #define BUTTON_QUALIFIERS (IEQUALIFIER_MIDBUTTON | IEQUALIFIER_RBUTTON | IEQUALIFIER_LEFTBUTTON)
485 static struct Gadget *Process_RawMouse(struct InputEvent *ie, struct IIHData *iihdata, struct Screen *screen,
486 struct Window *w, struct Gadget *gadget, struct GadgetInfo *gi,
487 ULONG stitlebarhit, BOOL new_active_window, BOOL IsToolbox,
488 struct InputEvent *orig_ie, BOOL *keep_event, BOOL *reuse_event,
489 #if SINGLE_SETPOINTERPOS_PER_EVENTLOOP
490 BOOL *call_setpointerpos,
491 #endif
492 struct IntuitionBase *IntuitionBase)
494 struct Library *InputBase = GetPrivIBase(IntuitionBase)->InputBase;
495 struct Requester *req = w ? w->FirstRequest : NULL;
497 D(bug("[Intuition] %s()\n", __func__));
499 switch (ie->ie_Code) {
500 case SELECTDOWN:
502 BOOL new_gadget = FALSE;
503 BOOL sizeverify = FALSE;
504 UWORD MetaDrag = GetPrivIBase(IntuitionBase)->IControlPrefs.ic_MetaDrag;
506 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));
507 DEBUG_CLICK(if (screen) bug("[Inputhandler] Coordinates: (%d, %d)\n", screen->MouseX, screen->MouseY));
509 iihdata->ActQualifier |= IEQUALIFIER_LEFTBUTTON;
511 /* Enter screen dragging mode if LButton + MetaDrag are pressed. */
512 if (MetaDrag && ((iihdata->ActQualifier & KEY_QUALIFIERS) == MetaDrag)) {
513 iihdata->ScreenDrag = screen;
514 iihdata->ScreenDragPointX = screen->MouseX;
515 iihdata->ScreenDragPointY = screen->MouseY;
516 *keep_event = FALSE;
517 break;
520 #ifdef SKINS
521 iihdata->TitlebarAppearTime = 0;
522 #endif
523 if (MENUS_ACTIVE)
525 FireMenuMessage(MMCODE_EVENT, 0, ie, IntuitionBase);
526 *keep_event = FALSE;
527 break;
530 #ifdef SKINS
531 if (!gadget && w)
533 struct Gadget * draggadget = 0;
535 if ((!(w->FirstRequest)) && (w->Flags & WFLG_DRAGBAR) && MatchHotkey(ie,IA_ACTIVEWINDOWMOVE,IntuitionBase))
537 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)
539 for (draggadget = w->FirstGadget; draggadget; draggadget = draggadget->NextGadget)
541 if ((draggadget->GadgetType & GTYP_SYSTYPEMASK) == GTYP_WDRAGGING)
543 gadget = draggadget;
544 new_gadget = TRUE;
545 break;
551 if ((!(w->FirstRequest)) && (w->Flags & WFLG_SIZEGADGET) && MatchHotkey(ie,IA_ACTIVEWINDOWSIZE,IntuitionBase))
553 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)
555 for (draggadget = w->FirstGadget; draggadget; draggadget = draggadget->NextGadget)
557 if ((draggadget->GadgetType & GTYP_SYSTYPEMASK) == GTYP_SIZING)
559 gadget = draggadget;
560 new_gadget = TRUE;
561 break;
567 #endif
569 if (!gadget)
571 /* use the *current* screen rather than active one when searching
572 for sdepth gadget! */
573 if (screen)
574 gadget = FindGadget (screen, stitlebarhit ? NULL : w, stitlebarhit ? NULL : req,
575 screen->MouseX, screen->MouseY, gi, FALSE, IntuitionBase);
576 DEBUG_CLICK(bug("Click on gadget %p\n", gadget));
577 new_gadget = TRUE;
579 } /* if (!gadget) */
581 /* If we clicked screen titlebar outside of any gadget, enter drag mode */
582 if ((!gadget) && stitlebarhit) {
583 DEBUG_CLICK(bug("[Inputhandler] Entering drag state for screen 0x%p\n", screen));
584 iihdata->ScreenDrag = screen;
585 iihdata->ScreenDragPointX = screen->MouseX;
586 iihdata->ScreenDragPointY = screen->MouseY;
587 *keep_event = FALSE;
588 break;
591 if (!IsToolbox) {
592 if (!gadget && stitlebarhit)
594 struct Window *ww = 0;
596 ww = FindDesktopWindow(screen, IntuitionBase);
597 DEBUG_CLICK(bug("[Inputhandler] Clicked on backdrop window 0x%p\n", ww));
598 if (ww) {
599 ActivateWindow(ww);
600 w = ww;
604 if (!stitlebarhit && !new_active_window && DoubleClick(GetPrivIBase(IntuitionBase)->LastClickSecs,GetPrivIBase(IntuitionBase)->LastClickMicro,
605 ie->ie_TimeStamp.tv_secs,ie->ie_TimeStamp.tv_micro))
607 if (GetPrivIBase(IntuitionBase)->DoubleClickButton != SELECTDOWN)
609 GetPrivIBase(IntuitionBase)->DoubleClickCounter = 0;
610 GetPrivIBase(IntuitionBase)->DoubleClickButton = SELECTDOWN;
612 else
614 GetPrivIBase(IntuitionBase)->DoubleClickCounter ++;
617 else
619 DEBUG_CLICK(bug("[Inputhandler] Resetting doubleclick counter\n"));
620 GetPrivIBase(IntuitionBase)->DoubleClickButton = SELECTDOWN;
621 GetPrivIBase(IntuitionBase)->DoubleClickCounter = 0;
624 /* update last click time for doubleclicktofront */
625 GetPrivIBase(IntuitionBase)->LastClickSecs = ie->ie_TimeStamp.tv_secs;
626 GetPrivIBase(IntuitionBase)->LastClickMicro = ie->ie_TimeStamp.tv_micro;
628 #ifdef SKINS
629 if (!stitlebarhit)
631 ULONG result;
633 if (!(gadget && ((gadget->GadgetType & GTYP_SYSTYPEMASK) == GTYP_WDEPTH)))
634 if ((result = RunHotkeys(ie,IntuitionBase)))
636 //gadget = NULL;
637 if (result == RUNHOTREUSE)
639 *reuse_event = TRUE;
641 else
643 *keep_event = FALSE;
647 #endif
649 if (gadget && new_gadget)
651 DEBUG_GADGET(bug("[Inputhandler] Activate gadget: 0x%p\n", gadget));
652 if (w && (w->IDCMPFlags & IDCMP_SIZEVERIFY) &&
653 (gadget->GadgetType & GTYP_SYSTYPEMASK) == GTYP_SIZING /*||
654 (gadget->GadgetType & GTYP_SYSTYPEMASK) == GTYP_WZOOM*/)
656 ih_fire_intuimessage(w,
657 IDCMP_SIZEVERIFY,
659 gadget,
660 IntuitionBase);
661 gadget = NULL;
662 sizeverify = TRUE;
664 else
666 BOOL is_draggad, is_sizegad;
667 UWORD gsystype;
669 /* Whenever the active gadget changes the gi must be updated
670 because it is cached in iidata->GadgetInfo!!!! Don't
671 forget to do this if somewhere else the active
672 gadget is changed, for example in ActivateGadget!!! */
674 PrepareGadgetInfo(gi, screen, w, req);
675 SetGadgetInfoGadget(gi, gadget, IntuitionBase);
677 gsystype = gadget->GadgetType & GTYP_SYSTYPEMASK;
678 is_draggad = ((gsystype == GTYP_WDRAGGING)
679 #ifdef __MORPHOS__
680 || (gsystype == GTYP_WDRAGGING2)
681 #endif
683 is_sizegad = (gsystype == GTYP_SIZING);
685 /* jDc: intui68k sends IDCMPs for GACT_IMMEDIATE drag&sizegads! */
686 if (gadget->Activation & GACT_IMMEDIATE)
688 ih_fire_intuimessage(w,
689 IDCMP_GADGETDOWN,
691 gadget,
692 IntuitionBase);
695 if (is_draggad || is_sizegad)
697 if (IS_BOOPSI_GADGET(gadget))
699 DoGPInput(gi,
700 gadget,
702 GM_GOACTIVE,
703 reuse_event,
704 IntuitionBase);
706 /* Ignoring retval of dispatcher above is what
707 AmigaOS does too for boopsi drag/resize
708 gadgets */
712 /* From now on the master drag/size gadget takes over */
713 if ((w->MoreFlags & WMFLG_IAMMUI) && (w->Flags & WFLG_BORDERLESS))
714 iihdata->ActiveSysGadget = is_draggad ? gadget : 0;
715 else
716 iihdata->ActiveSysGadget = gadget;
717 gadget = is_draggad ? iihdata->MasterDragGadget : iihdata->MasterSizeGadget;
722 if (gadget)
725 switch (gadget->GadgetType & GTYP_GTYPEMASK)
727 case GTYP_BOOLGADGET:
728 /* Only set the GFLG_SELECTED flag for RELVERIFY and
729 * TOGGLESELECT gadget. It's for the user to do it if
730 * he wants for other GADGIMMEDIATE ones.
731 * Only RELVERIFY gadgets stay active.
734 if (gadget->Activation & (GACT_TOGGLESELECT | GACT_RELVERIFY))
736 gadget->Flags ^= GFLG_SELECTED;
737 RefreshBoolGadgetState(gadget, w, req, IntuitionBase);
740 if (gadget->Activation & GACT_RELVERIFY)
742 gadget->Activation |= GACT_ACTIVEGADGET;
743 iihdata->MouseWasInsideBoolGadget = TRUE;
745 else
747 gadget = NULL;
749 break;
751 case GTYP_PROPGADGET:
752 HandlePropSelectDown(gadget,
754 req,
755 w->MouseX - gi->gi_Domain.Left - GetGadgetLeft(gadget, gi->gi_Screen, gi->gi_Window, NULL),
756 w->MouseY - gi->gi_Domain.Top - GetGadgetTop(gadget, gi->gi_Screen, gi->gi_Window, NULL),
757 IntuitionBase);
760 break;
762 case GTYP_STRGADGET:
763 /* If the click was inside the active strgad,
764 ** then let it update cursor pos,
765 ** else deactivate stringadget and reuse event.
768 if (InsideGadget(gi->gi_Screen, gi->gi_Window,
769 gi->gi_Requester, gadget,
770 gi->gi_Screen->MouseX, gi->gi_Screen->MouseY))
772 UWORD imsgcode;
774 HandleStrInput(gadget, gi, ie, &imsgcode,
775 IntuitionBase);
777 else
779 gadget->Flags &= ~GFLG_SELECTED;
781 RefreshStrGadget(gadget, w, req, IntuitionBase);
782 /* Gadget not active anymore */
783 gadget = NULL;
784 *reuse_event = TRUE;
786 break;
788 case GTYP_CUSTOMGADGET:
789 gadget = DoGPInput(gi,
790 gadget,
792 (new_gadget ? GM_GOACTIVE : GM_HANDLEINPUT),
793 reuse_event,
794 IntuitionBase);
795 D(bug("new_gadget %d, goactive %p\n", new_gadget, gadget));
797 if (gadget && new_gadget && (!(gadget->GadgetType & GTYP_SIZING)))
799 /* For compatibility, send a GM_HANDLEINPUT too */
800 struct InputEvent newie;
801 BOOL reuse_event;
803 newie.ie_NextEvent = NULL;
804 newie.ie_Class = IECLASS_RAWMOUSE;
805 newie.ie_SubClass = 0;
806 newie.ie_Code = IECODE_NOBUTTON;
807 newie.ie_Qualifier = ie->ie_Qualifier;
808 newie.ie_X = 0;
809 newie.ie_Y = 0;
810 newie.ie_TimeStamp.tv_secs = IntuitionBase->Seconds;
811 newie.ie_TimeStamp.tv_micro = IntuitionBase->Micros;
813 gadget = DoGPInput(gi,
814 gadget,
815 &newie,
816 GM_HANDLEINPUT,
817 &reuse_event,
818 IntuitionBase);
819 D(bug("handleinput %p\n", gadget));
821 break;
823 case 0: //orig gadtools / some 1.3 gadgets
824 if (IS_SYS_GADGET(gadget))
826 HandleSysGadgetVerify(gi, gadget, IntuitionBase);
828 else
830 if (gadget->Activation & GACT_RELVERIFY)
832 gadget->Activation |= GACT_ACTIVEGADGET;
833 iihdata->MouseWasInsideBoolGadget = TRUE;
834 if (gadget->Flags & GFLG_GADGHIMAGE)
836 gadget->Flags ^= GFLG_SELECTED;
837 RefreshBoolGadgetState(gadget, w, req, IntuitionBase);
840 else
842 /* jDc: this is what original intuition does, before crashing after a while ;)*/
843 DEBUG_CLICK(bug("[Inputhandler] Sending SELECTDOWN (old gadget), window 0x%p\n", w));
844 ih_fire_intuimessage(w,
845 IDCMP_MOUSEBUTTONS,
846 SELECTDOWN,
848 IntuitionBase);
851 break;
852 } /* switch (GadgetType) */
854 } /* if (a gadget is active) */
855 else if (w && (!req || req->Flags & NOISYREQ) && !sizeverify && !stitlebarhit)
857 DEBUG_CLICK(bug("[Inputhandler] Sending SELECTDOWN, window 0x%p\n", w));
858 ih_fire_intuimessage(w,
859 IDCMP_MOUSEBUTTONS,
860 SELECTDOWN,
862 IntuitionBase);
865 } /* case SELECTDOWN */
866 break;
868 case SELECTUP:
869 iihdata->ActQualifier &= ~IEQUALIFIER_LEFTBUTTON;
871 /* Ignore this event if screen drag qualifier is pressed */
872 if (iihdata->ScreenDrag) {
873 iihdata->ScreenDrag = NULL;
874 *keep_event = FALSE;
875 break;
878 #ifdef SKINS
879 iihdata->TitlebarAppearTime = 0;
880 #endif
881 if (MENUS_ACTIVE)
883 FireMenuMessage(MMCODE_EVENT, 0, ie, IntuitionBase);
884 *keep_event = FALSE;
885 break;
888 if (gadget)
890 BOOL inside = InsideGadget(gi->gi_Screen, gi->gi_Window,
891 gi->gi_Requester, gadget,
892 gi->gi_Screen->MouseX, gi->gi_Screen->MouseY);
894 /*int selected = (gadget->Flags & GFLG_SELECTED) != 0;*/
896 switch (gadget->GadgetType & GTYP_GTYPEMASK)
898 case GTYP_BOOLGADGET:
899 /* Must be a RELVERIFY gadget */
901 if (!(gadget->Activation & GACT_TOGGLESELECT) && inside)
903 gadget->Flags ^= GFLG_SELECTED;
904 RefreshBoolGadgetState(gadget, w, req, IntuitionBase);
907 if (inside)
909 if (IS_SYS_GADGET(gadget))
911 HandleSysGadgetVerify(gi, gadget, IntuitionBase);
913 else
915 if (req && gadget->Activation & GACT_ENDGADGET)
917 EndRequest(req, w);
919 req = w->FirstRequest;
922 ih_fire_intuimessage(w,
923 IDCMP_GADGETUP,
925 gadget,
926 IntuitionBase);
929 else
931 /* RKRM say so */
932 ih_fire_intuimessage(w,
933 IDCMP_MOUSEBUTTONS,
934 SELECTUP,
936 IntuitionBase);
939 gadget->Activation &= ~GACT_ACTIVEGADGET;
940 gadget = NULL;
941 break;
943 case GTYP_PROPGADGET:
944 HandlePropSelectUp(gadget, w, req, IntuitionBase);
945 if (gadget->Activation & GACT_RELVERIFY)
947 ih_fire_intuimessage(w,
948 IDCMP_GADGETUP,
950 gadget,
951 IntuitionBase);
954 gadget = NULL;
955 break;
957 /* Intuition string gadgets don't care about SELECTUP */
959 case GTYP_CUSTOMGADGET:
960 gadget = DoGPInput(gi, gadget, ie, GM_HANDLEINPUT, reuse_event, IntuitionBase);
961 break;
963 case 0: //orig gadtools / some 1.3 gadgets
964 /* jDc: adding a gadget with gtyp field set to NULL crashes intui68k
965 ** seems we don't need compatibility on this field ;) anyway we should
966 ** handle the case of GTYP_CLOSE, etc, set by some "cod3r"
968 gadget->Activation &= ~GACT_ACTIVEGADGET;
969 if (gadget->Activation & GACT_RELVERIFY)
971 if (gadget->Flags & GFLG_GADGHIMAGE)
973 if (inside)
975 gadget->Flags ^= GFLG_SELECTED;
976 RefreshBoolGadgetState(gadget, w, req, IntuitionBase);
980 if (inside)
982 ih_fire_intuimessage(w,
983 IDCMP_GADGETUP,
985 gadget,
986 IntuitionBase);
988 } else {
989 ih_fire_intuimessage(w,
990 IDCMP_MOUSEBUTTONS,
991 SELECTUP,
993 IntuitionBase);
995 gadget = NULL;
996 break;
998 } /* switch GadgetType */
1000 } /* if (a gadget is currently active) */
1001 else if (w && (!req || req->Flags & NOISYREQ))
1003 ih_fire_intuimessage(w,
1004 IDCMP_MOUSEBUTTONS,
1005 SELECTUP,
1007 IntuitionBase);
1010 break; /* case SELECTUP */
1012 case MENUDOWN:
1013 iihdata->ActQualifier |= IEQUALIFIER_RBUTTON;
1015 #ifdef SKINS
1016 iihdata->TitlebarAppearTime = 0;
1017 #endif
1018 if (MENUS_ACTIVE)
1020 FireMenuMessage(MMCODE_EVENT, 0, ie, IntuitionBase);
1021 *keep_event = FALSE;
1022 break;
1025 if (DoubleClick(GetPrivIBase(IntuitionBase)->LastClickSecs,GetPrivIBase(IntuitionBase)->LastClickMicro,
1026 ie->ie_TimeStamp.tv_secs,ie->ie_TimeStamp.tv_micro))
1028 if (GetPrivIBase(IntuitionBase)->DoubleClickButton != MENUDOWN)
1030 GetPrivIBase(IntuitionBase)->DoubleClickCounter = 0;
1031 GetPrivIBase(IntuitionBase)->DoubleClickButton = MENUDOWN;
1033 else
1035 GetPrivIBase(IntuitionBase)->DoubleClickCounter ++;
1038 else
1040 GetPrivIBase(IntuitionBase)->DoubleClickButton = MENUDOWN;
1041 GetPrivIBase(IntuitionBase)->DoubleClickCounter = 0;
1044 /* update last click time for doubleclicktofront */
1045 GetPrivIBase(IntuitionBase)->LastClickSecs = ie->ie_TimeStamp.tv_secs;
1046 GetPrivIBase(IntuitionBase)->LastClickMicro = ie->ie_TimeStamp.tv_micro;
1048 #ifdef SKINS
1050 ULONG result;
1052 if ((result = RunHotkeys(ie,IntuitionBase)))
1054 if (result == RUNHOTREUSE)
1056 *reuse_event = TRUE;
1058 else
1060 *keep_event = FALSE;
1062 break;
1064 w = IntuitionBase->ActiveWindow;
1066 #endif
1068 #ifdef SKINS
1069 if ((!MENUS_ACTIVE) && (!gadget) && (!(iihdata->ActQualifier & (IEQUALIFIER_LEFTBUTTON|IEQUALIFIER_MIDBUTTON))))
1071 struct Gadget *gad;
1072 struct GadgetInfo ginf;
1073 ULONG hit;
1074 struct Window *wind = FindActiveWindow(0, screen, &hit,IntuitionBase);
1076 if (wind)
1078 gad = FindGadget (screen,
1079 hit ? 0 : wind,0,
1080 IntuitionBase->ActiveScreen->MouseX,
1081 IntuitionBase->ActiveScreen->MouseY,
1082 &ginf, TRUE, IntuitionBase);
1084 if (gad && ((gad->GadgetType & GTYP_SYSTYPEMASK) == GTYP_WDEPTH))
1086 CreateSmallMenuTask(wind,SMALLMENU_TYPE_WINDOWDEPTH,IntuitionBase);
1087 *keep_event = FALSE;
1088 break;
1091 if (gad && ((gad->GadgetType & GTYP_SYSTYPEMASK) == GTYP_SDEPTH))
1093 CreateSmallMenuTask(0,SMALLMENU_TYPE_SCREENDEPTH,IntuitionBase);
1094 *keep_event = FALSE;
1095 break;
1099 #endif
1101 if (w && !req && w->DMRequest && !(w->Flags & WFLG_RMBTRAP))
1103 if (!MENUS_ACTIVE &&
1104 DoubleClick(GetPrivIBase(IntuitionBase)->DMStartSecs,
1105 GetPrivIBase(IntuitionBase)->DMStartMicro,
1106 ie->ie_TimeStamp.tv_secs,
1107 ie->ie_TimeStamp.tv_micro))
1109 if (w->IDCMPFlags & IDCMP_REQVERIFY)
1111 ih_fire_intuimessage(w,
1112 IDCMP_REQVERIFY,
1113 MENUHOT,
1114 NULL,
1115 IntuitionBase);
1117 else if (Request(w->DMRequest, w))
1119 req = w->DMRequest;
1121 ih_fire_intuimessage(w,
1122 IDCMP_REQSET,
1125 IntuitionBase);
1127 *keep_event = FALSE;
1128 break;
1131 GetPrivIBase(IntuitionBase)->DMStartSecs = ie->ie_TimeStamp.tv_secs;
1132 GetPrivIBase(IntuitionBase)->DMStartMicro = ie->ie_TimeStamp.tv_micro;
1135 if (w && !gadget)
1137 if (!(w->Flags & WFLG_RMBTRAP) && !req)
1139 struct IntScreen *scr = GetPrivScreen(w->WScreen);
1140 struct Window *w1;
1141 ULONG lock;
1142 BOOL mouseon = TRUE;
1144 scr->MenuVerifyMsgCount = 0;
1146 if (w->MouseX < 0 || w->MouseY < 0) mouseon = FALSE;
1147 if (w->MouseX > w->Width || w->MouseY > w->Height) mouseon = FALSE;
1149 if (w->IDCMPFlags & IDCMP_MENUVERIFY && (!(IW(w)->specialflags & SPFLAG_IAMDEAD)))
1151 ih_fire_intuimessage(w,
1152 IDCMP_MENUVERIFY,
1153 mouseon ? MENUHOT : MENUWAITING,
1155 IntuitionBase);
1156 scr->MenuVerifyMsgCount++;
1159 lock = LockIBase(0);
1161 for (w1 = scr->Screen.FirstWindow; w1; w1 = w1->NextWindow)
1163 if ((w1->IDCMPFlags & IDCMP_MENUVERIFY) && (w1 != w) && (!(IW(w)->specialflags & SPFLAG_IAMDEAD)))
1165 ih_fire_intuimessage(w1,
1166 IDCMP_MENUVERIFY,
1167 MENUWAITING,
1169 IntuitionBase);
1170 ++scr->MenuVerifyMsgCount;
1174 UnlockIBase(lock);
1176 /* FIXME: when a window is opened with IDCMP_MENUVERIFY
1177 * (or this event is requested via ModifyIDCMP), and a
1178 * verify operation is pending, the window should get
1179 * a verify message too. Oh well.
1182 if (scr->MenuVerifyMsgCount)
1184 GetPrivIBase(IntuitionBase)->MenuVerifyScreen = scr;
1185 scr->MenuVerifyActiveWindow = w;
1186 scr->MenuVerifyTimeOut = 2;
1187 scr->MenuVerifySeconds = IntuitionBase->Seconds;
1188 scr->MenuVerifyMicros = IntuitionBase->Micros;
1190 else if (FireMenuMessage(MMCODE_START, w, NULL/*ie*/, IntuitionBase))
1192 /* This lock will be released only when the user is
1193 done with menus = when IECLASS_MENU + IESUBCLASS_MENUSTOP
1194 event arrives (generated by MenuHandler task) */
1196 ObtainSemaphore(&GetPrivIBase(IntuitionBase)->MenuLock);
1197 iihdata->MenuWindow = w;
1198 MENUS_ACTIVE = TRUE;
1202 /* fall through */
1204 case MENUUP:
1205 case MIDDLEDOWN:
1206 case MIDDLEUP:
1208 switch(ie->ie_Code) {
1209 case MENUUP:
1210 iihdata->ActQualifier &= ~IEQUALIFIER_RBUTTON;
1211 if (GetPrivIBase(IntuitionBase)->MenuVerifyScreen)
1213 struct Window *w1;
1214 struct IntScreen *scr = GetPrivIBase(IntuitionBase)->MenuVerifyScreen;
1215 ULONG lock = LockIBase(0);
1217 for (w1 = scr->Screen.FirstWindow; w1; w1 = w1->NextWindow)
1219 if (w1->IDCMPFlags & IDCMP_MENUVERIFY && w1->IDCMPFlags & IDCMP_MOUSEBUTTONS)
1221 ih_fire_intuimessage(w1,
1222 IDCMP_MOUSEBUTTONS,
1223 MENUUP,
1225 IntuitionBase);
1229 UnlockIBase(lock);
1231 /* FIXME: when the active window replies the verifymessage,
1232 * it should get a IDCMP_MENUPICK/MENUNULL message.
1234 GetPrivIBase(IntuitionBase)->MenuVerifyScreen = NULL;
1235 scr->MenuVerifyActiveWindow = NULL;
1236 scr->MenuVerifyMsgCount = 0;
1237 scr->MenuVerifyTimeOut = 0;
1238 scr->MenuVerifySeconds = 0;
1239 scr->MenuVerifyMicros = 0;
1241 break;
1243 case MIDDLEDOWN:
1244 iihdata->ActQualifier |= IEQUALIFIER_MIDBUTTON;
1245 if (DoubleClick(GetPrivIBase(IntuitionBase)->LastClickSecs,GetPrivIBase(IntuitionBase)->LastClickMicro,
1246 ie->ie_TimeStamp.tv_secs,ie->ie_TimeStamp.tv_micro))
1248 if (GetPrivIBase(IntuitionBase)->DoubleClickButton != MIDDLEDOWN)
1250 GetPrivIBase(IntuitionBase)->DoubleClickCounter = 0;
1251 GetPrivIBase(IntuitionBase)->DoubleClickButton = MIDDLEDOWN;
1252 } else
1253 GetPrivIBase(IntuitionBase)->DoubleClickCounter ++;
1254 } else {
1255 GetPrivIBase(IntuitionBase)->DoubleClickButton = MIDDLEDOWN;
1256 GetPrivIBase(IntuitionBase)->DoubleClickCounter = 0;
1258 /* update last click time for doubleclicktofront */
1259 GetPrivIBase(IntuitionBase)->LastClickSecs = ie->ie_TimeStamp.tv_secs;
1260 GetPrivIBase(IntuitionBase)->LastClickMicro = ie->ie_TimeStamp.tv_micro;
1261 break;
1263 case MIDDLEUP:
1264 iihdata->ActQualifier &= ~IEQUALIFIER_MIDBUTTON;
1265 break;
1268 #ifdef SKINS
1269 iihdata->TitlebarAppearTime = 0;
1270 #endif
1271 if (MENUS_ACTIVE)
1273 FireMenuMessage(MMCODE_EVENT, 0, ie, IntuitionBase);
1274 *keep_event = FALSE;
1275 break;
1278 #ifdef SKINS
1279 if (ie->ie_Code == MIDDLEDOWN)
1281 ULONG result;
1283 if ((result = RunHotkeys(ie,IntuitionBase)))
1285 if (result == RUNHOTREUSE)
1287 *reuse_event = TRUE;
1289 else
1291 *keep_event = FALSE;
1293 break;
1295 w = IntuitionBase->ActiveWindow;
1297 #endif
1298 if (gadget)
1300 if (IS_BOOPSI_GADGET(gadget))
1302 gadget = DoGPInput(gi, gadget, ie, GM_HANDLEINPUT, reuse_event, IntuitionBase);
1305 } /* if (there is an active gadget) */
1306 else if (w && (!req || req->Flags & NOISYREQ) && w != GetPrivScreen(w->WScreen)->MenuVerifyActiveWindow)
1308 ih_fire_intuimessage(w,
1309 IDCMP_MOUSEBUTTONS,
1310 ie->ie_Code,
1312 IntuitionBase);
1315 break; /* case MENUDOWN */
1317 case IECODE_NOBUTTON: /* MOUSEMOVE */
1319 struct Screen *scr;
1320 UWORD DWidth, DHeight;
1322 if (ie->ie_Qualifier & IEQUALIFIER_RELATIVEMOUSE) {
1323 //ULONG Thresh;
1325 /* Add delta information lost in previous mousemove event. See below. */
1326 iihdata->DeltaMouseX = ie->ie_X + iihdata->DeltaMouseX_Correction;
1327 iihdata->DeltaMouseY = ie->ie_Y + iihdata->DeltaMouseY_Correction;
1329 #define ACCELERATOR_THRESH 2
1330 #define ACCELERATOR_MULTI 2
1332 if (GetPrivIBase(IntuitionBase)->ActivePreferences.EnableCLI & MOUSE_ACCEL)
1334 /* Acceleration */
1335 if (ABS(iihdata->DeltaMouseX) > ACCELERATOR_THRESH)
1336 iihdata->DeltaMouseX *= ACCELERATOR_MULTI;
1337 if (ABS(iihdata->DeltaMouseY) > ACCELERATOR_THRESH)
1338 iihdata->DeltaMouseY *= ACCELERATOR_MULTI;
1341 switch (GetPrivIBase(IntuitionBase)->ActivePreferences.PointerTicks)
1343 case 0:
1344 iihdata->DeltaMouseX_Correction = 0;
1345 iihdata->DeltaMouseX_Correction = 0;
1346 break;
1348 default:
1349 /* Remember the delta information which gets lost because of division by PointerTicks.
1350 Will be added to prescaled deltas of next mousemove event. If this is not done, moving
1351 the mouse very slowly would cause it to not move at all */
1353 iihdata->DeltaMouseX_Correction = iihdata->DeltaMouseX % GetPrivIBase(IntuitionBase)->ActivePreferences.PointerTicks;
1354 iihdata->DeltaMouseY_Correction = iihdata->DeltaMouseY % GetPrivIBase(IntuitionBase)->ActivePreferences.PointerTicks;
1356 iihdata->DeltaMouseX /= GetPrivIBase(IntuitionBase)->ActivePreferences.PointerTicks;
1357 iihdata->DeltaMouseY /= GetPrivIBase(IntuitionBase)->ActivePreferences.PointerTicks;
1358 break;
1362 ie->ie_X = iihdata->DeltaMouseX + IntuitionBase->MouseX;
1363 ie->ie_Y = iihdata->DeltaMouseY + IntuitionBase->MouseY;
1364 } else {
1365 DEBUG_MOUSE(bug("[Inputhandler] Last mouse position: (%d, %d), new mouse position: (%d, %d)\n",
1366 IntuitionBase->MouseX, IntuitionBase->MouseY, ie->ie_X, ie->ie_Y));
1367 iihdata->DeltaMouseX = ie->ie_X - IntuitionBase->MouseX;
1368 iihdata->DeltaMouseY = ie->ie_Y - IntuitionBase->MouseY;
1369 DEBUG_MOUSE(bug("[InputHandler] Delta is (%d, %d)\n", iihdata->DeltaMouseX, iihdata->DeltaMouseY));
1372 /* Calculate current display size.
1373 It's determined by the first screen on this monitor.
1374 TODO: perhaps we should just ask display driver about its current display mode? */
1375 scr = FindFirstScreen(GetPrivIBase(IntuitionBase)->ActiveMonitor, IntuitionBase);
1376 if (scr)
1378 DWidth = scr->ViewPort.ColorMap->cm_vpe->DisplayClip.MaxX - scr->ViewPort.ColorMap->cm_vpe->DisplayClip.MinX + 1;
1379 DHeight = scr->ViewPort.ColorMap->cm_vpe->DisplayClip.MaxY - scr->ViewPort.ColorMap->cm_vpe->DisplayClip.MinY + 1;
1381 else
1383 /* If there's no active screen, we take 160x160 as a limit */
1384 DWidth = 160;
1385 DHeight = 160;
1388 scr = iihdata->ScreenDrag;
1389 if (scr) {
1390 WORD dx = iihdata->DeltaMouseX;
1391 WORD dy = iihdata->DeltaMouseY;
1392 WORD min, max, val;
1393 UWORD spFlags = GetPrivScreen(scr)->SpecialFlags;
1394 UWORD DragMode = GetPrivIBase(IntuitionBase)->IControlPrefs.ic_VDragModes[0];
1396 DEBUG_DRAG(bug("[InputHandler] Screen drag, delta is (%d, %d)\n", dx, dy));
1398 /* Restrict dragging to a physical display area if the driver does not allow composition or if the user wants it*/
1399 if (((spFlags & SF_HorCompose) != SF_HorCompose) || (DragMode & ICVDM_HBOUND)) {
1400 /* Calculate limits */
1401 if (scr->Width > DWidth) {
1402 min = DWidth - scr->Width;
1403 max = 0;
1404 } else {
1405 min = 0;
1406 max = DWidth - scr->Width;
1408 /* The purpose of the following complex check is to prevent jumping if the
1409 screen was positioned out of user drag limits by the program itself using
1410 ScreenPosition() or OpenScreen(). We apply restrictions in parts depending
1411 on the dragging direction.
1412 Maybe the user should also be able to drag the screen back off-display in such
1413 a case?
1414 Calculate the position we would go to */
1415 val = scr->LeftEdge + dx;
1416 /* Determine the direction */
1417 if ((dx < 0) && ((!(spFlags & SF_ComposeRight)) || (DragMode & ICVDM_LBOUND))) {
1418 /* Can we move at all in this direction ? */
1419 if (scr->LeftEdge > min) {
1420 /* If too far, restrict it */
1421 if (val < min)
1422 dx = min - scr->LeftEdge;
1423 } else
1424 /* Just don't move if we can't */
1425 dx = 0;
1426 } else if ((!(spFlags & SF_ComposeLeft)) || (DragMode & ICVDM_RBOUND)) {
1427 if (scr->LeftEdge < max) {
1428 if (val > max)
1429 dx = max - scr->LeftEdge;
1430 } else
1431 dx = 0;
1434 if (((spFlags & SF_VertCompose) != SF_VertCompose) || (DragMode & ICVDM_VBOUND)) {
1435 DEBUG_DRAG(bug("[Inputhandler] Restricting vertical drag\n"));
1436 DEBUG_DRAG(bug("[Inputhandler] Screen size: %d, display size: %d\n", scr->Height, DHeight));
1437 if (scr->Height > DHeight) {
1438 min = DHeight - scr->Height;
1439 max = 0;
1440 } else {
1441 min = 0;
1442 max = DHeight - scr->Height;
1444 DEBUG_DRAG(bug("[Inputhandler] Limits: min %d max %d\n", min, max));
1445 val = scr->TopEdge + dy;
1446 DEBUG_DRAG(bug("[Inputhandler] New position would be %d\n", val));
1447 if ((dy < 0) && ((!(spFlags & SF_ComposeBelow)) || (DragMode & ICVDM_TBOUND))) {
1448 if (scr->TopEdge > min) {
1449 if (val < min)
1450 dy = min - scr->TopEdge;
1451 } else
1452 dy = 0;
1453 } else if ((!(spFlags & SF_ComposeAbove)) || (DragMode & ICVDM_BBOUND)) {
1454 if (scr->TopEdge < max) {
1455 if (val > max)
1456 dy = max - scr->TopEdge;
1457 } else
1458 dy = 0;
1460 DEBUG_DRAG(bug("[Inputhandler] Restricted delta will be %d\n", dy));
1462 ScreenPosition(scr, SPOS_RELATIVE, dx, dy, 0, 0);
1465 /* Autoscroll the active screen */
1466 scr = IntuitionBase->ActiveScreen;
1467 if (scr && (scr->Flags & AUTOSCROLL) &&
1468 (GetPrivScreen(scr)->IMonitorNode == GetPrivIBase(IntuitionBase)->ActiveMonitor))
1470 WORD xval = scr->LeftEdge;
1471 WORD yval = scr->TopEdge;
1472 WORD min;
1474 DEBUG_AUTOSCROLL(bug("[Inputhandler] Autoscroll screen 0x%p, event at (%d, %d)\n",
1475 scr, ie->ie_X, ie->ie_Y));
1477 if ((ie->ie_X < 0) || (ie->ie_X >= DWidth)) {
1478 DEBUG_AUTOSCROLL(bug("[InputHandler] X delta: %d pixels\n", iihdata->DeltaMouseX));
1479 xval -= iihdata->DeltaMouseX;
1481 if (ie->ie_X < 0) {
1482 if (xval > 0)
1483 xval = 0;
1484 } else if (ie->ie_X >= DWidth) {
1485 min = DWidth - scr->Width;
1486 if (xval < min)
1487 xval = min;
1491 if ((ie->ie_Y < 0) || (ie->ie_Y >= DHeight)) {
1492 yval -= iihdata->DeltaMouseY;
1494 if (ie->ie_Y < 0) {
1495 /* If screen is dragged down and user touched upper screen
1496 boundary, do nothing */
1497 if (scr->TopEdge >= 0)
1498 yval = scr->TopEdge;
1499 else
1500 /* If scrolled down screen is being scrolled up, make sure it
1501 does not go over 0 */
1502 if (yval > 0)
1503 yval = 0;
1504 } else if (ie->ie_Y >= DHeight) {
1505 min = DHeight - scr->Height;
1506 if (yval < min)
1507 yval = min;
1511 if ((xval != scr->LeftEdge) || (yval != scr->TopEdge))
1512 ScreenPosition(scr, SPOS_ABSOLUTE, xval, yval, 0, 0);
1515 /* Restrict mouse coordinates to the physical display area */
1516 if (ie->ie_X >= DWidth) ie->ie_X = DWidth - 1;
1517 if (ie->ie_Y >= DHeight) ie->ie_Y = DHeight - 1;
1518 if (ie->ie_X < 0) ie->ie_X = 0;
1519 if (ie->ie_Y < 0) ie->ie_Y = 0;
1521 #ifdef SKINS
1522 if (gadget == iihdata->MasterDragGadget) {
1523 struct gpInput gpi;
1524 ULONG retval;
1526 gpi.MethodID = GM_MOVETEST;
1527 gpi.gpi_GInfo = gi;
1528 gpi.gpi_Mouse.X = ie->ie_X - gi->gi_Window->WScreen->LeftEdge;
1529 gpi.gpi_Mouse.Y = ie->ie_Y - gi->gi_Window->WScreen->TopEdge;
1530 gpi.gpi_IEvent = ie;
1532 retval = Locked_DoMethodA(gi->gi_Window, gadget, (Msg)&gpi, IntuitionBase);
1533 if (retval == MOVETEST_ADJUSTPOS)
1535 ie->ie_X = gpi.gpi_Mouse.X + gi->gi_Window->WScreen->LeftEdge;
1536 ie->ie_Y = gpi.gpi_Mouse.Y + gi->gi_Window->WScreen->TopEdge;
1540 #endif
1541 /* Do Mouse Bounding - mouse will be most restrictive of screen size or mouse bounds */
1542 if (iihdata->MouseBoundsActiveFlag) {
1543 if (ie->ie_X < iihdata->MouseBoundsLeft)
1544 ie->ie_X = iihdata->MouseBoundsLeft;
1545 else if (ie->ie_X > iihdata->MouseBoundsRight)
1546 ie->ie_X = iihdata->MouseBoundsRight;
1548 if (ie->ie_Y < iihdata->MouseBoundsTop)
1549 ie->ie_Y = iihdata->MouseBoundsTop;
1550 else if (ie->ie_Y > iihdata->MouseBoundsBottom)
1551 ie->ie_Y = iihdata->MouseBoundsBottom;
1554 /* Prevent mouse going above all screens */
1555 scr = FindHighestScreen(IntuitionBase);
1556 if (scr) {
1557 if (ie->ie_Y < scr->TopEdge)
1558 ie->ie_Y = scr->TopEdge;
1561 /* Store new mouse coords. If a screen is being dragged, lock drag point */
1562 scr = iihdata->ScreenDrag;
1563 if (scr) {
1564 IntuitionBase->MouseX = scr->LeftEdge + iihdata->ScreenDragPointX;
1565 IntuitionBase->MouseY = scr->TopEdge + iihdata->ScreenDragPointY;
1566 } else {
1567 IntuitionBase->MouseX = ie->ie_X;
1568 IntuitionBase->MouseY = ie->ie_Y;
1570 notify_mousemove_screensandwindows(IntuitionBase);
1571 #if !SINGLE_SETPOINTERPOS_PER_EVENTLOOP
1572 MySetPointerPos(IntuitionBase);
1573 #else
1574 *call_setpointerpos = TRUE;
1575 #endif
1577 screen = FindActiveScreen(IntuitionBase); /* The mouse was moved, so current screen may have changed */
1579 #ifdef SKINS
1580 if (!gadget) {
1581 if (iihdata->TitlebarOnTop)
1583 if (screen->MouseY > screen->BarHeight && GetPrivScreen(screen)->SpecialFlags & SF_AppearingBar)
1585 iihdata->TitlebarOnTop = FALSE;
1586 iihdata->TitlebarAppearTime = 0;
1588 LOCK_REFRESH(screen);
1590 MoveLayer(0, screen->BarLayer, 0, -(screen->BarHeight + 1));
1591 CheckLayers(screen, IntuitionBase);
1593 UNLOCK_REFRESH(screen);
1596 else
1598 if (screen->MouseY == 0 && GetPrivScreen(screen)->SpecialFlags & SF_AppearingBar && !MENUS_ACTIVE && !(PeekQualifier() & (IEQUALIFIER_LEFTBUTTON|IEQUALIFIER_RBUTTON|IEQUALIFIER_MIDBUTTON)))
1600 if (!(iihdata->TitlebarAppearTime))
1602 iihdata->TitlebarAppearTime = ((UQUAD)ie->ie_TimeStamp.tv_secs) * 50;
1603 iihdata->TitlebarAppearTime += ie->ie_TimeStamp.tv_micro / 20000;
1606 else
1608 iihdata->TitlebarAppearTime = 0;
1612 #endif
1613 if (MENUS_ACTIVE) {
1614 FireMenuMessage(MMCODE_EVENT, 0, ie, IntuitionBase);
1615 *keep_event = FALSE;
1616 break;
1619 if (gadget) {
1620 *keep_event = FALSE;
1622 switch (gadget->GadgetType & GTYP_GTYPEMASK)
1624 case GTYP_BOOLGADGET:
1625 case 0: //fallback for sucky gadgets
1626 /* Must be a RELVERIFY gadget */
1628 BOOL inside;
1630 inside = InsideGadget(gi->gi_Screen,
1631 gi->gi_Window,
1632 gi->gi_Requester,
1633 gadget,
1634 gi->gi_Screen->MouseX,
1635 gi->gi_Screen->MouseY);
1637 if (inside != iihdata->MouseWasInsideBoolGadget) {
1638 iihdata->MouseWasInsideBoolGadget = inside;
1640 gadget->Flags ^= GFLG_SELECTED;
1641 RefreshBoolGadgetState(gadget, w, req, IntuitionBase);
1644 break;
1646 case GTYP_PROPGADGET:
1647 HandlePropMouseMove(gadget,
1649 req,
1650 w->MouseX - gi->gi_Domain.Left - GetGadgetLeft(gadget, gi->gi_Screen, gi->gi_Window, NULL),
1651 w->MouseY - gi->gi_Domain.Top - GetGadgetTop(gadget, gi->gi_Screen, gi->gi_Window, NULL),
1652 IntuitionBase);
1654 break;
1656 case GTYP_CUSTOMGADGET:
1657 gadget = DoGPInput(gi, gadget, ie, GM_HANDLEINPUT, reuse_event, IntuitionBase);
1658 break;
1660 } /* switch GadgetType */
1662 } /* if (a gadget is currently active) */
1664 *keep_event = FALSE;
1666 if (!w)
1667 break;
1669 if (IW(w)->helpflags & HELPF_GADGETHELP && (!(PeekQualifier() & (IEQUALIFIER_LEFTBUTTON|IEQUALIFIER_RBUTTON|IEQUALIFIER_MIDBUTTON)))) {
1670 struct Window *hw;
1671 struct Gadget *g;
1673 hw = FindActiveWindow(ie, screen, 0, IntuitionBase);
1675 if (hw != w &&
1676 (!hw || !(IW(w)->helpflags & HELPF_ISHELPGROUP) ||
1677 !(IW(hw)->helpflags & HELPF_ISHELPGROUP) ||
1678 IW(w)->helpgroup != IW(hw)->helpgroup))
1681 if (iihdata->LastHelpWindow)
1683 fire_intuimessage(w,
1684 IDCMP_GADGETHELP,
1686 NULL,
1687 IntuitionBase);
1689 iihdata->LastHelpGadget = NULL;
1690 iihdata->LastHelpWindow = NULL;
1691 iihdata->HelpGadgetFindTime = 0;
1694 else
1696 g = FindHelpGadget (hw,
1697 IntuitionBase->ActiveScreen->MouseX,
1698 IntuitionBase->ActiveScreen->MouseY,
1699 IntuitionBase);
1700 if (g && g != iihdata->LastHelpGadget)
1702 if (!iihdata->LastHelpGadget)
1704 iihdata->HelpGadgetFindTime = ((UQUAD)ie->ie_TimeStamp.tv_secs) * 50;
1705 iihdata->HelpGadgetFindTime += ie->ie_TimeStamp.tv_micro / 20000;
1706 } else {
1707 if (hw == iihdata->LastHelpWindow)
1709 iihdata->HelpGadgetFindTime = ((UQUAD)ie->ie_TimeStamp.tv_secs) * 50;
1710 iihdata->HelpGadgetFindTime += ie->ie_TimeStamp.tv_micro / 20000;
1711 iihdata->HelpGadgetFindTime += 25;//smaller delay
1715 else if (g != iihdata->LastHelpGadget ||
1716 hw != iihdata->LastHelpWindow)
1718 fire_intuimessage(hw,
1719 IDCMP_GADGETHELP,
1720 0, /* Don't know what it should be */
1722 IntuitionBase);
1725 iihdata->LastHelpGadget = g;
1726 iihdata->LastHelpWindow = hw;
1728 } else {
1729 iihdata->LastHelpGadget = NULL;
1730 iihdata->LastHelpWindow = NULL;
1731 iihdata->HelpGadgetFindTime = 0;
1734 if (!(w->IDCMPFlags & IDCMP_MOUSEMOVE))
1735 break;
1737 /* Send IDCMP_MOUSEMOVE if WFLG_REPORTMOUSE is set
1738 and/or active gadget has GACT_FOLLOWMOUSE set */
1740 /* jDc: do NOT send when sizegad is pressed */
1741 if (!(w->Flags & WFLG_REPORTMOUSE)) {
1742 if (!gadget)
1743 break;
1744 if (!(gadget->Activation & GACT_FOLLOWMOUSE))
1745 break;
1746 } else {
1747 if (gadget && (gadget->GadgetType & (GTYP_SIZING|GTYP_WDRAGGING)))
1748 break;
1751 orig_ie->ie_Class = IECLASS_RAWMOUSE;
1753 /* Limit the number of IDCMP_MOUSEMOVE messages sent to intuition.
1754 note that this comes after handling gadgets, because gadgets should get all events.
1757 if (IW(w)->num_mouseevents >= IW(w)->mousequeue) {
1758 BOOL old_msg_found = FALSE;
1760 /* Mouse Queue is full, so try looking for a not
1761 yet GetMsg()ed IntuiMessage in w->UserPort
1762 trying to modify that. */
1764 Forbid();
1765 if (w->UserPort)
1767 struct IntuiMessage *im;
1768 #if defined(__AROSEXEC_SMP__)
1769 struct ExecLockBase *ExecLockBase = GetPrivIBase(IntuitionBase)->ExecLockBase;
1770 if (ExecLockBase) ObtainLock(&w->UserPort->mp_SpinLock, SPINLOCK_MODE_READ, 0);
1771 #endif
1772 for (im = (struct IntuiMessage *)w->UserPort->mp_MsgList.lh_TailPred;
1773 im->ExecMessage.mn_Node.ln_Pred;
1774 im = (struct IntuiMessage *)im->ExecMessage.mn_Node.ln_Pred)
1776 if ((im->Class == IDCMP_MOUSEMOVE) &&
1777 (im->IDCMPWindow == w))
1779 im->Qualifier = iihdata->ActQualifier;
1781 if (w->IDCMPFlags & IDCMP_DELTAMOVE)
1783 im->MouseX = iihdata->DeltaMouseX;
1784 im->MouseY = iihdata->DeltaMouseY;
1786 else
1788 im->MouseX = w->MouseX;
1789 im->MouseY = w->MouseY;
1791 CurrentTime(&im->Seconds, &im->Micros);
1793 old_msg_found = TRUE;
1794 break;
1797 #if defined(__AROSEXEC_SMP__)
1798 if (ExecLockBase) ReleaseLock(&w->UserPort->mp_SpinLock, 0);
1799 #endif
1800 } /* if (w->UserPort) */
1801 Permit();
1803 /* no need to send a new message if we modified
1804 an existing one ... */
1806 if (old_msg_found) break;
1808 /* ... otherwise we are in a strange situation. The mouse
1809 queue is full, but we did not find an existing MOUSEMOVE
1810 imsg in w->UserPort. So the app probably has removed
1811 an imsg from the UserPort with GetMsg but we did not get
1812 the ReplyMsg, yet. In this case we do send a new message */
1814 HandleIntuiReplyPort(iihdata, IntuitionBase);
1818 /* MouseQueue is not full, so we can send a message. We increase
1819 IntWindow->num_mouseevents which will later be decreased after
1820 the Intuition InputHandler gets the ReplyMessage from the app
1821 and handles it in HandleIntuiReplyPort() */
1823 if (ih_fire_intuimessage(w, IDCMP_MOUSEMOVE, IECODE_NOBUTTON, w, IntuitionBase))
1824 IW(w)->num_mouseevents++;
1826 break;
1828 } /* case IECODE_NOBUTTON */
1829 } /* switch (ie->ie_Code) (what button was pressed ?) */
1831 return gadget;
1834 /****************************************************************************************/
1836 AROS_UFH2(struct InputEvent *, IntuiInputHandler,
1837 AROS_UFHA(struct InputEvent *, oldchain, A0),
1838 AROS_UFHA(struct IIHData *, iihdata, A1)
1841 AROS_USERFUNC_INIT
1843 struct InputEvent *ie, *orig_ie, *next_ie, stackie;
1844 struct Gadget *gadget = NULL;
1845 struct IntuitionBase *IntuitionBase = iihdata->IntuitionBase;
1846 struct Library *KeymapBase = GetPrivIBase(IntuitionBase)->KeymapBase;
1847 struct Screen *screen;
1848 //ULONG lock;
1849 struct GadgetInfo *gi = &iihdata->GadgetInfo;
1850 BOOL reuse_event, ie_used;
1851 struct Window *w;
1852 struct Requester *req;
1853 ULONG stitlebarhit = 0;
1854 #if 0 /* Toolbox is broken-as-designed */
1855 struct Window *toolbox;
1856 struct GadgetInfo *boxgi = &iihdata->BoxGadgetInfo;
1857 struct Gadget *boxgadget = NULL;
1858 #endif
1859 #if SINGLE_SETPOINTERPOS_PER_EVENTLOOP
1860 BOOL call_setpointerpos = FALSE;
1861 #endif
1863 D(bug("Inside intuition inputhandler, active window=%p\n", IntuitionBase->ActiveWindow));
1864 ObtainSemaphore(&GetPrivIBase(IntuitionBase)->InputHandlerLock);
1866 if (!iihdata->InputDeviceTask) iihdata->InputDeviceTask = FindTask(NULL);
1868 /* Then free generated InputEvents done in the previous round */
1870 FreeGeneratedInputEvents(iihdata);
1872 /* First handle IntuiMessages which were replied back to the IntuiReplyPort
1873 by the apps */
1875 HandleIntuiReplyPort(iihdata, IntuitionBase);
1877 /* Handle action messages */
1879 HandleIntuiActions(iihdata, IntuitionBase);
1881 /* Now handle the input events */
1883 ie = &stackie;
1884 reuse_event = FALSE;
1885 next_ie = oldchain;
1887 /* shut up the compiler */
1888 orig_ie = next_ie;
1889 ie_used = FALSE;
1891 gadget = iihdata->ActiveGadget;
1893 while (reuse_event || next_ie)
1895 struct Window *old_w;
1896 BOOL keep_event = TRUE;
1897 BOOL new_active_window = FALSE;
1898 Object *newmonitor = GetPrivIBase(IntuitionBase)->NewMonitor;
1900 /* Process hosted display activation event (if any).
1901 This is experimental. If this works badly, we'll possibly have to put it into
1902 input events queue */
1903 if (newmonitor) {
1904 DEBUG_MONITOR(bug("[Inputhandler] Activating monitor 0x%p\n", newmonitor));
1905 GetPrivIBase(IntuitionBase)->NewMonitor = NULL;
1906 ActivateMonitor(newmonitor, -1, -1, IntuitionBase);
1907 iihdata->SwitchedMonitor = TRUE;
1910 if (!reuse_event)
1912 *ie = *next_ie;
1913 orig_ie = next_ie;
1914 next_ie = ie->ie_NextEvent;
1915 ie_used = FALSE;
1918 D(bug("iih: Handling event of class %d, code %d\n", ie->ie_Class, ie->ie_Code));
1919 reuse_event = FALSE;
1921 /* If the monitor has been changed, this possibly happened because of mouse click in
1922 its display window. In such a case we have to update current mouse coordinates
1923 from the first absolute mouse event. Otherwise input will misbehave. */
1924 if (iihdata->SwitchedMonitor && (ie->ie_Class == IECLASS_RAWMOUSE)) {
1925 iihdata->SwitchedMonitor = FALSE;
1926 if (!(ie->ie_Qualifier & IEQUALIFIER_RELATIVEMOUSE)) {
1927 DEBUG_MONITOR(bug("[Inputhandler] Adjusting coordinates to (%d, %d)\n", ie->ie_X, ie->ie_Y));
1928 IntuitionBase->MouseX = ie->ie_X;
1929 IntuitionBase->MouseY = ie->ie_Y;
1930 notify_mousemove_screensandwindows(IntuitionBase);
1934 /* new event, we need to reset this */
1935 screen = FindActiveScreen(IntuitionBase);
1936 iihdata->ActEventTablet = 0;
1938 /* Set the timestamp in IntuitionBase */
1940 IntuitionBase->Seconds = ie->ie_TimeStamp.tv_secs;
1941 IntuitionBase->Micros = ie->ie_TimeStamp.tv_micro;
1943 #if 0 /* toolbox stuff disabled. broken. calling LockLayerinfo() for every event is broken. deadlocks */
1944 /* Use event to find the active window */
1946 toolbox = GetToolBoxWindow(ie, screen, IntuitionBase);
1948 if (toolbox)
1950 /* Do ToolBox Window Actions */
1951 /* ToolBox Windows supports only a subset of IECLASS Actions */
1952 switch (ie->ie_Class) {
1954 case IECLASS_RAWMOUSE:
1955 boxgadget = Process_RawMouse(ie, iihdata, screen, toolbox, boxgadget, boxgi, 0, FALSE, TRUE,
1956 orig_ie, &keep_event, &reuse_event,
1957 #if SINGLE_SETPOINTERPOS_PER_EVENTLOOP
1958 &call_setpointerpos,
1959 #endif
1960 IntuitionBase);
1961 break;
1963 } /* switch (ie->ie_Class) */
1964 } /* if (toolbox) */
1965 #endif
1967 w = IntuitionBase->ActiveWindow;
1969 if (!MENUS_ACTIVE && !SYSGADGET_ACTIVE)
1971 /* lock = LockIBase(0UL); */
1973 old_w = w;
1974 if (ie->ie_Class == IECLASS_RAWMOUSE && ie->ie_Code == SELECTDOWN)
1976 w = FindActiveWindow(ie, screen, &stitlebarhit, IntuitionBase);
1977 DEBUG_CLICK(bug("iih:New active window: %p\n", w));
1981 if ( w != old_w )
1983 if (w)
1985 DEBUG_WINDOW(bug("Activating new window (title %s)\n", w->Title ? w->Title : "<noname>"));
1987 DEBUG_WINDOW(bug("Window activated\n"));
1989 else
1991 DEBUG_WINDOW(bug("Making active window inactive. Now there's no active window\n"));
1993 new_active_window = TRUE;
1994 iihdata->NewActWindow = w;
1997 /* UnlockIBase(lock); */
1999 if (new_active_window)
2001 if (gadget && w &&
2002 (!(GetPrivScreen(w->WScreen)->MenuVerifyMsgCount)) &&
2003 (!(MENUS_ACTIVE)) && (!(SYSGADGET_ACTIVE)))
2005 switch (gadget->GadgetType & GTYP_GTYPEMASK)
2008 case GTYP_CUSTOMGADGET:
2010 struct gpGoInactive gpgi;
2012 gpgi.MethodID = GM_GOINACTIVE;
2013 gpgi.gpgi_GInfo = gi;
2014 gpgi.gpgi_Abort = 1;
2016 Locked_DoMethodA(gi->gi_Window, gadget, (Msg)&gpgi, IntuitionBase);
2017 break;
2020 case GTYP_STRGADGET:
2021 gadget->Flags &= ~GFLG_SELECTED;
2022 RefreshStrGadget(gadget, gi->gi_Window, gi->gi_Requester, IntuitionBase);
2023 break;
2025 case GTYP_BOOLGADGET:
2026 /* That a bool gadget is active here can only happen
2027 if user used LMB to activate gadget and LAMIGA + LALT
2028 to activate other window, or viceversa */
2029 /* The gadget must be a RELVERIFY one */
2030 if (!(gadget->Activation & GACT_TOGGLESELECT))
2032 BOOL inside;
2034 inside = InsideGadget(gi->gi_Screen, gi->gi_Window,
2035 gi->gi_Requester, gadget,
2036 gi->gi_Screen->MouseX, gi->gi_Screen->MouseY);
2038 if (inside)
2040 gadget->Flags &= ~GFLG_SELECTED;
2041 RefreshBoolGadgetState(gadget, gi->gi_Window,
2042 gi->gi_Requester, IntuitionBase);
2045 break;
2047 case GTYP_PROPGADGET:
2048 /* That a prop gadget is active here can only happen
2049 if user used LMB to activate gadget and LAMIGA + LALT
2050 to activate other window, or viceversa */
2052 HandlePropSelectUp(gadget, gi->gi_Window, NULL, IntuitionBase);
2053 if (gadget->Activation & GACT_RELVERIFY)
2055 ih_fire_intuimessage(gi->gi_Window,
2056 IDCMP_GADGETUP,
2058 gadget,
2059 IntuitionBase);
2061 break;
2063 } /* switch (gadget->GadgetType & GTYP_GTYPEMASK) */
2065 gadget->Activation &= ~GACT_ACTIVEGADGET;
2066 iihdata->ActiveGadget = NULL;
2067 gadget = NULL;
2070 /* ActivateWindow works if w = NULL */
2071 /* jacaDcaps: some gui toolkits (die reaction, die!) close the window opened by a boopsi gadget when
2072 it gets hit with lmb, so we need to check if the new active window does not go away by
2073 performing GM_GOINACTIVE on the gadget. NOTE: CloseWindow's part performed on input.device context
2074 clears the iihdata->NewActWindow if it's the actually closed one. */
2075 if (w == iihdata->NewActWindow)
2077 ActivateWindow(w);
2079 else
2081 w = IntuitionBase->ActiveWindow;
2082 new_active_window = FALSE;
2083 ie->ie_Class = IECLASS_NULL; //lose the event, otherwise the gadget will get activated again ;)
2086 iihdata->NewActWindow = 0;
2088 } /* if (new_active_window) */
2090 } /* if (!MENUS_ACTIVE) */
2092 req = NULL;
2093 if (w)
2095 req = w->FirstRequest;
2098 D(bug("[Inputhandler] Screen 0x%p Window 0x%p Requester 0x%p gadget 0x%p\n", screen, w, req, gadget));
2100 switch (ie->ie_Class) {
2101 case IECLASS_POINTERPOS:
2102 ie->ie_SubClass = IESUBCLASS_COMPATIBLE;
2103 /* fall through */
2105 case IECLASS_NEWPOINTERPOS:
2106 switch (ie->ie_SubClass)
2108 case IESUBCLASS_COMPATIBLE:
2109 ie->ie_Code = IECODE_NOBUTTON;
2110 break;
2112 case IESUBCLASS_PIXEL:
2114 struct IEPointerPixel *pp = ie->ie_EventAddress;
2116 ie->ie_X = pp->iepp_Position.X + pp->iepp_Screen->LeftEdge;
2117 ie->ie_Y = pp->iepp_Position.Y + pp->iepp_Screen->TopEdge;
2119 ActivateMonitor(GetPrivScreen(pp->iepp_Screen)->IMonitorNode, ie->ie_X, ie->ie_Y, IntuitionBase);
2121 ie->ie_Class = IECLASS_RAWMOUSE; /* otherwise a lot of code would ignore this message */
2122 ie->ie_Code = IECODE_NOBUTTON;
2123 break;
2125 case IESUBCLASS_TABLET:
2127 //unsupported - does anything use it anyway? ;)
2129 ie->ie_Code = 0;
2130 break;
2132 case IESUBCLASS_NEWTABLET:
2134 struct IENewTablet *nt = (struct IENewTablet *)ie->ie_EventAddress;
2136 if (nt)
2138 iihdata->ActEventTablet = nt; //cache this
2139 ie->ie_X = (screen->Width * nt->ient_TabletX) / nt->ient_RangeX;
2140 ie->ie_Y = (screen->Height * nt->ient_TabletY) / nt->ient_RangeY;
2142 ie->ie_Class = IECLASS_RAWMOUSE;
2144 break;
2146 default:
2147 ie->ie_Code = 0;
2148 break;
2150 /* fall through */
2152 case IECLASS_RAWMOUSE:
2153 gadget = Process_RawMouse(ie, iihdata, screen, w, gadget, gi, stitlebarhit, new_active_window, FALSE,
2154 orig_ie, &keep_event, &reuse_event,
2155 #if SINGLE_SETPOINTERPOS_PER_EVENTLOOP
2156 &call_setpointerpos,
2157 #endif
2158 IntuitionBase);
2159 keep_event = TRUE;
2160 break;
2162 case IECLASS_RAWKEY:
2163 /* release events go only to gadgets and windows who
2164 have not set IDCMP_VANILLAKEY */
2166 DEBUG_HANDLER(dprintf("Handler: IECLASS_RAWKEY\n"));
2167 DEBUG_KEY(dprintf("Handler: Qual 0x%lx\n",iihdata->ActQualifier));
2169 iihdata->ActQualifier &= ~(KEY_QUALIFIERS | IEQUALIFIER_REPEAT);
2170 iihdata->ActQualifier |= (ie->ie_Qualifier & (KEY_QUALIFIERS | IEQUALIFIER_REPEAT));
2172 DEBUG_KEY(dprintf("Handler: real Qual 0x%lx\n",iihdata->ActQualifier));
2174 /* Keyboard mouse emulation and screen switching */
2177 UWORD code = ie->ie_Code & ~IECODE_UP_PREFIX;
2178 DEBUG_KEY(dprintf("Handler: code 0x%lx\n",code));
2180 /* Left Amiga + N/M screen switching shortcut */
2181 if ((ie->ie_Qualifier & IEQUALIFIER_LCOMMAND) && (code == RAWKEY_N || code == RAWKEY_M)) {
2182 if (!(ie->ie_Qualifier & IEQUALIFIER_REPEAT) && !(ie->ie_Code & IECODE_UP_PREFIX)) {
2183 if (code == RAWKEY_N)
2184 WBenchToFront();
2185 else if (code == RAWKEY_M)
2186 ScreenToBack(IntuitionBase->FirstScreen);
2188 keep_event = FALSE;
2189 break;
2192 /* Mouse button emulation: LALT + LAMIGA = LBUTTON, RALT + RAMIGA = RBUTTON */
2193 if ((code == RAWKEY_LAMIGA) ||
2194 (code == RAWKEY_LALT) ||
2195 (code == RAWKEY_RAMIGA) ||
2196 (code == RAWKEY_RALT))
2198 DEBUG_KEY(dprintf("Handler: KeyMouseEmul\n"));
2199 iihdata->PrevKeyMouseState = iihdata->ActKeyMouseState;
2200 iihdata->ActKeyMouseState = 0;
2201 if ((ie->ie_Qualifier & (IEQUALIFIER_LCOMMAND | IEQUALIFIER_LALT)) == (IEQUALIFIER_LCOMMAND | IEQUALIFIER_LALT))
2203 iihdata->ActKeyMouseState |= IEQUALIFIER_LEFTBUTTON;
2205 if ((ie->ie_Qualifier & (IEQUALIFIER_RCOMMAND | IEQUALIFIER_RALT)) == (IEQUALIFIER_RCOMMAND | IEQUALIFIER_RALT))
2207 iihdata->ActKeyMouseState |= IEQUALIFIER_RBUTTON;
2210 if ((iihdata->ActKeyMouseState & IEQUALIFIER_LEFTBUTTON) != (iihdata->PrevKeyMouseState & IEQUALIFIER_LEFTBUTTON))
2212 orig_ie->ie_Class = IECLASS_RAWMOUSE;
2213 orig_ie->ie_SubClass = 0;
2214 orig_ie->ie_Code = (iihdata->ActKeyMouseState & IEQUALIFIER_LEFTBUTTON) ? IECODE_LBUTTON : IECODE_LBUTTON | IECODE_UP_PREFIX;
2215 orig_ie->ie_X = 0;
2216 orig_ie->ie_Y = 0;
2217 *ie = *orig_ie;
2219 reuse_event = TRUE;
2220 break;
2223 if ((iihdata->ActKeyMouseState & IEQUALIFIER_RBUTTON) != (iihdata->PrevKeyMouseState & IEQUALIFIER_RBUTTON))
2225 orig_ie->ie_Class = IECLASS_RAWMOUSE;
2226 orig_ie->ie_SubClass = 0;
2227 orig_ie->ie_Code = (iihdata->ActKeyMouseState & IEQUALIFIER_RBUTTON) ? IECODE_RBUTTON : IECODE_RBUTTON | IECODE_UP_PREFIX;
2228 orig_ie->ie_X = 0;
2229 orig_ie->ie_Y = 0;
2230 *ie = *orig_ie;
2232 reuse_event = TRUE;
2233 break;
2236 } /* if key is one of LAMIGA/LALT/RAMIGA/RALT */
2238 if ((iihdata->ActQualifier & (IEQUALIFIER_LCOMMAND | IEQUALIFIER_RCOMMAND)) &&
2239 ((ie->ie_Code == RAWKEY_UP) ||
2240 (ie->ie_Code == RAWKEY_DOWN) ||
2241 (ie->ie_Code == RAWKEY_LEFT) ||
2242 (ie->ie_Code == RAWKEY_RIGHT)))
2244 static BYTE const xmap[] = { 0, 0, 1, -1};
2245 static BYTE const ymap[] = {-1, 1, 0, 0};
2246 WORD shift;
2248 shift = (iihdata->ActQualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) ? 40 : 1;
2250 /* Mouse Move Emulation */
2252 orig_ie->ie_Class = IECLASS_RAWMOUSE;
2253 orig_ie->ie_SubClass = 0;
2254 orig_ie->ie_Code = IECODE_NOBUTTON;
2255 orig_ie->ie_Qualifier = IEQUALIFIER_RELATIVEMOUSE;
2256 orig_ie->ie_X = xmap[code - RAWKEY_UP] * shift;
2257 orig_ie->ie_Y = ymap[code - RAWKEY_UP] * shift;
2259 *ie = *orig_ie;
2260 reuse_event = TRUE;
2261 break;
2264 } /**/
2266 /* End Keyboard mouse emulation */
2268 if (MENUS_ACTIVE)
2270 DEBUG_KEY(dprintf("Handler: FireMenuMessage\n"));
2271 FireMenuMessage(MMCODE_EVENT, 0, ie, IntuitionBase);
2272 keep_event = FALSE;
2273 break;
2276 /* Hotkeys processing */
2277 #ifdef SKINS
2279 ULONG result;
2281 if (!(ie->ie_Code & IECODE_UP_PREFIX))
2282 if ((result = RunHotkeys(ie,IntuitionBase)))
2284 if (result == RUNHOTREUSE)
2286 reuse_event = TRUE;
2288 else
2290 keep_event = FALSE;
2292 break;
2294 w = IntuitionBase->ActiveWindow;
2296 #endif
2298 if ( keep_event &&
2299 ((!(ie->ie_Code & IECODE_UP_PREFIX)) ||
2300 gadget ||
2301 (w && ((w->IDCMPFlags & IDCMP_VANILLAKEY) == 0)) ))
2303 if (gadget)
2305 keep_event = FALSE;
2307 DEBUG_KEY(dprintf("Handler: Gadget 0x%lx active\n",gadget));
2308 DEBUG_KEY(dprintf("Handler: GadgetID 0x%lx UserData 0x%lx\n",
2309 gadget->GadgetID,
2310 gadget->UserData));
2311 DEBUG_KEY(dprintf("Handler: GadgetType 0x%lx Flags 0x%lx Activation 0x%lx\n",
2312 gadget->GadgetType,
2313 gadget->Flags,
2314 gadget->Activation));
2315 DEBUG_KEY(dprintf("Handler: MoreFlags 0x%lx\n",
2316 ((struct ExtGadget*)gadget)->MoreFlags));
2318 switch (gadget->GadgetType & GTYP_GTYPEMASK)
2320 case GTYP_STRGADGET:
2322 UWORD imsgcode;
2323 ULONG ret = HandleStrInput(gadget, gi, ie, &imsgcode,
2324 IntuitionBase);
2326 DEBUG_KEY(dprintf("Handler: Key GTYP_STRGADGET ret 0x%lx\n",ret));
2327 if (ret & (SGA_END | SGA_NEXTACTIVE | SGA_PREVACTIVE))
2329 if (gadget->Activation & GACT_RELVERIFY)
2331 DEBUG_KEY(dprintf("Handler: GACT_RELVERIFY\n"));
2332 ih_fire_intuimessage(w,
2333 IDCMP_GADGETUP,
2334 imsgcode,
2335 gadget,
2336 IntuitionBase);
2338 if (req && gadget->Activation & GACT_ENDGADGET)
2340 DEBUG_KEY(dprintf("Handler: GACT_ENDGADGET\n"));
2341 EndRequest(req, w);
2343 req = w->FirstRequest;
2344 ret = 0;
2348 if ((gadget->Flags & GFLG_TABCYCLE) && (ret & SGA_NEXTACTIVE))
2350 gadget = FindCycleGadget(w, req, gadget, GMR_NEXTACTIVE);
2351 DEBUG_KEY(dprintf("Handler: TabCycle next gadget 0x%lx\n",gadget));
2353 else if ((gadget->Flags & GFLG_TABCYCLE) && (ret & SGA_PREVACTIVE))
2355 gadget = FindCycleGadget(w, req, gadget, GMR_PREVACTIVE);
2356 DEBUG_KEY(dprintf("Handler: TabCycle prev gadget 0x%lx\n",gadget));
2358 else
2360 gadget = NULL;
2363 if (gadget)
2365 gadget = DoActivateGadget(w, req, gadget, IntuitionBase);
2368 } /* if (ret & (SGA_END | SGA_NEXTACTIVE | SGA_PREVACTIVE)) */
2370 break;
2373 case GTYP_CUSTOMGADGET:
2374 DEBUG_KEY(dprintf("Handler: GTYP_CUSTOMGADGET\n"));
2375 DEBUG_KEY(dprintf("Handler: send GM_HANDLEINPUT\n"));
2376 gadget = DoGPInput(gi,
2377 gadget,
2379 GM_HANDLEINPUT,
2380 &reuse_event,
2381 IntuitionBase);
2382 DEBUG_KEY(dprintf("Handler: reuse %ld\n",reuse_event));
2383 break;
2385 } /* switch (gadget type) */
2387 } /* if (a gadget is currently active) */
2388 else if (w && (!req || req->Flags & NOISYREQ))
2390 BOOL menushortcut = FALSE;
2392 DEBUG_KEY(dprintf("Handler: No Gadget active\n"));
2393 DEBUG_KEY(dprintf("Handler: Qualifier 0x%lx WinFlags 0x%lx IDCMP 0x%lx\n",ie->ie_Qualifier,w->Flags,w->IDCMPFlags));
2395 if ((ie->ie_Qualifier & IEQUALIFIER_RCOMMAND) &&
2396 (!(w->Flags & WFLG_RMBTRAP)) &&
2397 (w->IDCMPFlags & IDCMP_MENUPICK))
2399 struct Menu *strip = 0;
2401 DEBUG_KEY(dprintf("Handler: MenuKey\n"));
2402 ObtainSemaphore(&GetPrivIBase(IntuitionBase)->MenuLock);
2404 strip = w->MenuStrip;
2406 if (((struct IntWindow *)w)->menulendwindow)
2408 strip = ((struct IntWindow *)w)->menulendwindow->MenuStrip;
2411 DEBUG_KEY(dprintf("Handler: MenuStrip 0x%lx\n",strip));
2412 if (strip)
2414 UBYTE key;
2416 if (MapRawKey(ie, &key, 1, NULL) == 1)
2418 UWORD menucode;
2420 menucode = FindMenuShortCut(strip, key, TRUE, IntuitionBase);
2422 DEBUG_KEY(dprintf("Handler: menucode 0x%lx\n",menucode));
2424 if (menucode != MENUNULL)
2426 DEBUG_KEY(dprintf("Handler: build menuevent\n"));
2427 ie->ie_Class = IECLASS_MENU;
2428 ie->ie_SubClass = IESUBCLASS_MENUSTOP;
2429 ie->ie_EventAddress = w;
2430 ie->ie_Code = menucode;
2432 reuse_event = TRUE;
2433 menushortcut = TRUE;
2435 MENUS_ACTIVE = TRUE;
2436 iihdata->MenuWindow = w;
2439 else
2441 DEBUG_KEY(dprintf("Handler: MapRawKey failed\n"));
2444 if (!menushortcut) /* !! */
2445 ReleaseSemaphore(&GetPrivIBase(IntuitionBase)->MenuLock);
2447 } /* if could be a menu short cut */
2448 else
2449 if ((ie->ie_Qualifier & IEQUALIFIER_RCOMMAND) &&
2450 (!(w->IDCMPFlags & IDCMP_MENUPICK)))
2452 struct Menu *strip = 0;
2453 struct Window *window = w;
2455 /* not sure here about RMBTRAP */
2456 DEBUG_KEY(dprintf("Handler: no idcmp, create a MENULIST idcmp\n"));
2458 ObtainSemaphore(&GetPrivIBase(IntuitionBase)->MenuLock);
2460 strip = w->MenuStrip;
2462 if (((struct IntWindow *)w)->menulendwindow)
2464 strip = ((struct IntWindow *)w)->menulendwindow->MenuStrip;
2465 window = ((struct IntWindow *)w)->menulendwindow;
2468 DEBUG_KEY(dprintf("Handler: MenuStrip 0x%lx\n",strip));
2469 if (strip)
2471 UBYTE key;
2473 if (MapRawKey(ie, &key, 1, NULL) == 1)
2475 UWORD menucode;
2477 menucode = FindMenuShortCut(strip, key, TRUE, IntuitionBase);
2479 DEBUG_KEY(dprintf("Handler: menucode 0x%lx\n",menucode));
2481 if (menucode != MENUNULL)
2483 DEBUG_KEY(dprintf("Handler: build menuevent\n"));
2484 ih_fire_intuimessage(window,
2485 IDCMP_MENUPICK,
2486 menucode,
2487 ie->ie_position.ie_addr, /* ie_dead.ie_prev[1|2]Down[Code|Qual]. 64 bit machines!? */
2488 IntuitionBase);
2489 keep_event = FALSE;
2490 menushortcut = TRUE;
2493 else
2495 DEBUG_KEY(dprintf("Handler: MapRawKey failed\n"));
2498 ReleaseSemaphore(&GetPrivIBase(IntuitionBase)->MenuLock);
2499 } /* if could be a menu short but current window has no idcmp cut */
2501 if (menushortcut)
2503 DEBUG_KEY(dprintf("Handler: menu shortcut..break\n"));
2504 break;
2507 /* This is a regular RAWKEY event (no gadget taking care
2508 of it...). */
2510 if (iihdata->ActQualifier & IEQUALIFIER_REPEAT)
2512 /* don't send repeat key events if repeatqueue is full */
2513 if (IW(w)->num_repeatevents >= IW(w)->repeatqueue)
2515 DEBUG_KEY(dprintf("Handler: RepeatEvents full..don't send more\n"));
2516 break;
2520 if (w->IDCMPFlags & IDCMP_VANILLAKEY)
2522 UBYTE keyBuffer;
2524 DEBUG_KEY(dprintf("Handler: VANILLAKEY\n"));
2525 // DEBUG_KEY(dprintf("Handler: MapRawKey ie 0x%lx KeyMapBase 0x%lx IntutionBase 0x%lx\n",ie,KeymapBase,IntuitionBase));
2527 if (MapRawKey(ie, &keyBuffer, 1, NULL) == 1)
2529 DEBUG_KEY(dprintf("Handler: send VANILLAKEY msg\n"));
2530 ih_fire_intuimessage(w,
2531 IDCMP_VANILLAKEY,
2532 keyBuffer,
2533 ie->ie_position.ie_addr, /* ie_dead.ie_prev[1|2]Down[Code|Qual]. 64 bit machines!? */
2534 IntuitionBase);
2535 DEBUG_KEY(dprintf("Handler: done\n"));
2536 break;
2539 /* If the event mapped to more than one byte, it is not
2540 a legal VANILLAKEY, so we send it as the original
2541 RAWKEY event. */
2545 if (w->IDCMPFlags & IDCMP_RAWKEY)
2547 DEBUG_KEY(dprintf("Handler: send IDCMP_RAWKEY Qual 0x%lx Code 0x%lx addr 0x%lx Event\n",
2548 ie->ie_Qualifier,ie->ie_Code,ie->ie_position.ie_addr));
2549 ih_fire_intuimessage(w,
2550 IDCMP_RAWKEY,
2551 ie->ie_Code,
2552 ie->ie_position.ie_addr, /* ie_dead.ie_prev[1|2]Down[Code|Qual]. 64 bit machine!? */
2553 IntuitionBase);
2554 keep_event = FALSE;
2557 DEBUG_KEY(dprintf("Handler: done\n"));
2558 } /* regular RAWKEY */
2561 break; /* case IECLASS_RAWKEY */
2563 case IECLASS_TIMER:
2564 if (iihdata->MouseBoundsKillTimer)
2566 iihdata->MouseBoundsKillTimer--;
2567 if (iihdata->MouseBoundsKillTimer == 0)
2569 iihdata->MouseBoundsActiveFlag = FALSE;
2573 if (GetPrivIBase(IntuitionBase)->PointerDelay)
2575 ULONG lock = LockIBase(0);
2577 if (--GetPrivIBase(IntuitionBase)->PointerDelay == 0)
2579 struct SharedPointer *shared_pointer;
2580 struct Window *window = IntuitionBase->ActiveWindow;
2581 struct IntScreen *scr;
2583 DEBUG_POINTER(dprintf("InputHandler: PointerDelay\n"));
2584 DEBUG_POINTER(dprintf("InputHandler: Window 0x%lx\n",
2585 window));
2587 if (window)
2589 Object *pointer = ((struct IntWindow *)window)->pointer;
2591 DEBUG_POINTER(dprintf("InputHandler: Pointer 0x%lx\n",
2592 pointer));
2593 scr = GetPrivScreen(window->WScreen);
2594 if (scr)
2596 DEBUG_POINTER(dprintf("InputHandler: Screen 0x%lx\n",
2597 scr));
2598 if (pointer == NULL)
2600 pointer = GetPrivIBase(IntuitionBase)->DefaultPointer;
2603 if (((struct IntWindow *)window)->busy)
2605 pointer = GetPrivIBase(IntuitionBase)->BusyPointer;
2608 GetAttr(POINTERA_SharedPointer, pointer, (IPTR *) &shared_pointer);
2610 DEBUG_POINTER(dprintf("InputHandler: scr 0x%lx pointer 0x%lx shared_pointer 0x%lx\n",
2611 scr, pointer, shared_pointer));
2612 DEBUG_POINTER(dprintf("InputHandler: sprite 0x%lx\n",
2613 shared_pointer->sprite));
2615 if (DoMethod(scr->IMonitorNode, MM_SetPointerShape, shared_pointer))
2617 ObtainSharedPointer(shared_pointer, IntuitionBase);
2618 ReleaseSharedPointer(scr->Pointer, IntuitionBase);
2619 scr->Pointer = shared_pointer;
2620 if (window)
2622 window->XOffset = shared_pointer->xoffset;
2623 window->YOffset = shared_pointer->yoffset;
2626 else
2628 DEBUG_POINTER(dprintf("InputHandler: can't set pointer.\n"));
2631 else
2633 DEBUG_POINTER(dprintf("InputHandler: no screen.\n"));
2636 else
2638 DEBUG_POINTER(dprintf("InputHandler: no window.\n"));
2642 UnlockIBase(lock);
2645 if (GetPrivIBase(IntuitionBase)->MenuVerifyScreen)
2647 struct IntScreen *scr = GetPrivIBase(IntuitionBase)->MenuVerifyScreen;
2649 if ((--scr->MenuVerifyTimeOut) <= 0)
2651 struct InputEvent ie;
2653 /* currently we ONLY need the menu open time ! */
2654 ie.ie_TimeStamp.tv_secs = IntuitionBase->Seconds;
2655 ie.ie_TimeStamp.tv_micro = IntuitionBase->Micros;
2657 if (FireMenuMessage(MMCODE_START, scr->MenuVerifyActiveWindow, &ie, IntuitionBase))
2659 /* This lock will be released only when the user is
2660 done with menus = when IECLASS_MENU + IESUBCLASS_MENUSTOP
2661 event arrives (generated by MenuHandler task) */
2663 ObtainSemaphore(&GetPrivIBase(IntuitionBase)->MenuLock);
2664 iihdata->MenuWindow = scr->MenuVerifyActiveWindow;
2665 MENUS_ACTIVE = TRUE;
2668 scr->MenuVerifyActiveWindow = NULL;
2669 scr->MenuVerifyTimeOut = 0;
2670 scr->MenuVerifyMsgCount = 0;
2671 scr->MenuVerifySeconds = 0;
2672 scr->MenuVerifyMicros = 0;
2673 GetPrivIBase(IntuitionBase)->MenuVerifyScreen = NULL;
2676 else if (MENUS_ACTIVE)
2678 FireMenuMessage(MMCODE_EVENT, 0, ie, IntuitionBase);
2679 keep_event = FALSE;
2680 break;
2683 #ifdef SKINS
2684 if (screen->MouseY <= screen->BarHeight && GetPrivScreen(screen)->SpecialFlags & SF_AppearingBar && !iihdata->TitlebarOnTop && iihdata->TitlebarAppearTime)
2686 UQUAD currenttime = (((UQUAD)ie->ie_TimeStamp.tv_secs) * 50) + (UQUAD)(ie->ie_TimeStamp.tv_micro / 20000);
2687 if (currenttime >= iihdata->TitlebarAppearTime + 10)
2689 iihdata->TitlebarOnTop = TRUE;
2690 iihdata->TitlebarAppearTime = 0;
2692 LOCK_REFRESH(screen);
2694 MoveLayer(0, screen->BarLayer, 0, screen->BarHeight + 1);
2695 UpfrontLayer(0, screen->BarLayer);
2696 CheckLayers(screen, IntuitionBase);
2698 UNLOCK_REFRESH(screen);
2701 #endif
2704 UQUAD currenttime = (((UQUAD)ie->ie_TimeStamp.tv_secs) * 50) + (UQUAD)(ie->ie_TimeStamp.tv_micro / 20000);
2705 #define SECONDS(x) (x*50)
2706 if (iihdata->HelpGadgetFindTime && (currenttime >= iihdata->HelpGadgetFindTime + SECONDS(1)))
2708 struct Gadget *lhg = iihdata->LastHelpGadget;
2709 fire_intuimessage(iihdata->LastHelpWindow,
2710 IDCMP_GADGETHELP,
2711 lhg ? lhg->GadgetID : 0, /* Don't know what it should be */
2712 lhg,
2713 IntuitionBase);
2714 iihdata->HelpGadgetFindTime = 0;
2718 if (gadget)
2720 if (IS_BOOPSI_GADGET(gadget))
2722 gadget = DoGPInput(gi, gadget, ie, GM_HANDLEINPUT, &reuse_event, IntuitionBase);
2725 } /* if (gadget) */
2727 #if USE_NEWDISPLAYBEEP
2729 if (GetPrivIBase(IntuitionBase)->BeepingScreens)
2731 ULONG lock;
2732 struct Screen *scr;
2734 lock = LockIBase(0);
2736 for (scr = IntuitionBase->FirstScreen;
2737 scr && GetPrivIBase(IntuitionBase)->BeepingScreens;
2738 scr = scr->NextScreen)
2740 if ((scr->Flags & BEEPING) &&
2741 !GetPrivScreen(scr)->BeepingCounter--)
2743 GetPrivIBase(IntuitionBase)->BeepingScreens--;
2744 scr->Flags &= (UWORD) ~BEEPING;
2746 /* if (GetBitMapAttr(scr->RastPort.BitMap, BMA_DEPTH) <= 8)
2747 // visual beep on CLUT-screen
2749 // SetRGB4 (&screen->ViewPort, 0, scr->SaveColor0 & 0x000F, (scr->SaveColor0 & 0x00F0) >> 4, (scr->SaveColor0 & 0x0F00) >> 8);
2750 SetRGB32 (&scr->ViewPort, 0,
2751 GetPrivScreen(scr)->DisplayBeepColor0[0],
2752 GetPrivScreen(scr)->DisplayBeepColor0[1],
2753 GetPrivScreen(scr)->DisplayBeepColor0[2]
2756 else
2757 // visual beep on hi- and truecolor screens
2759 RenderScreenBar(scr, FALSE, IntuitionBase);
2762 RenderScreenBar(scr, FALSE, IntuitionBase);
2766 UnlockIBase(lock);
2768 #endif /* USE_NEWDISPLAYBEEP */
2770 if (!w) break;
2772 /* Send INTUITICK msg only if app already replied the last INTUITICK msg */
2773 if (w->Flags & WFLG_WINDOWTICKED) break;
2775 if (w->IDCMPFlags & IDCMP_INTUITICKS)
2777 /* Set the WINDOWTICKED flag, it will be cleared again when the app
2778 replies back the msg and the InputHandler handles the replymsg
2779 in HandleIntuiReplyPort() */
2781 ih_fire_intuimessage(w,
2782 IDCMP_INTUITICKS,
2785 IntuitionBase);
2787 break; /* case IECLASS_TIMER */
2789 case IECLASS_MENU:
2790 if (MENUS_ACTIVE && (ie->ie_SubClass == IESUBCLASS_MENUSTOP))
2792 struct Window *eventwin = (struct Window *)ie->ie_EventAddress;
2794 iihdata->MenuWindow = NULL;
2795 MENUS_ACTIVE = FALSE;
2797 /* semaphore was locked when menu action started, see
2798 above where MMCODE_START MenuMessage is sent.
2800 It could have also have been locked if the user
2801 activated one of the menu key shortcuts, see
2802 "case IECLASS_RAWKEY" */
2804 ReleaseSemaphore(&GetPrivIBase(IntuitionBase)->MenuLock);
2806 keep_event = FALSE;
2808 if (((struct IntWindow *)eventwin)->menulendwindow)
2810 eventwin = ((struct IntWindow *)eventwin)->menulendwindow;
2813 ih_fire_intuimessage((struct Window *)eventwin,
2814 IDCMP_MENUPICK,
2815 ie->ie_Code,
2816 (struct Window *)ie->ie_EventAddress,
2817 IntuitionBase);
2820 break;
2822 case IECLASS_DISKINSERTED:
2823 case IECLASS_DISKREMOVED:
2824 case IECLASS_NEWPREFS:
2826 struct Screen *scr;
2827 ULONG idcmp;
2828 LONG lock;
2830 switch (ie->ie_Class)
2832 case IECLASS_DISKINSERTED:
2833 idcmp = IDCMP_DISKINSERTED;
2834 break;
2836 case IECLASS_DISKREMOVED:
2837 idcmp = IDCMP_DISKREMOVED;
2838 break;
2840 default:
2841 idcmp = IDCMP_NEWPREFS;
2843 * Here we need to update the mouse prefs and
2844 * maybe other stuff which comes from the global prefs file.
2846 break;
2849 lock = LockIBase(0);
2851 for (scr = IntuitionBase->FirstScreen; scr; scr = scr->NextScreen)
2853 struct Window *win;
2855 for (win = scr->FirstWindow; win; win = win->NextWindow)
2857 /* stegerg:
2858 CHECKME, really use fire_intuimessage() here,
2859 instead of ih_fireintuimessage? Same for
2860 IDCMP_GADGETHELP above, BTW. */
2862 fire_intuimessage(win,
2863 idcmp,
2865 NULL,
2866 IntuitionBase);
2870 UnlockIBase(lock);
2872 break;
2874 case IECLASS_NEWMOUSE:
2875 #ifdef __MORPHOS__
2877 * The following is only needed on hardware not running
2878 * the NewMouse driver.
2880 if (w->IDCMPFlags & IDCMP_RAWKEY && (!SysBase->MaxLocMem))
2882 ih_fire_intuimessage(w,
2883 IDCMP_RAWKEY,
2884 ie->ie_Code,
2885 ie->ie_position.ie_addr, /* ie_dead.ie_prev[1|2]Down[Code|Qual]. 64 bit machine!? */
2886 IntuitionBase);
2887 keep_event = FALSE;
2889 break;
2890 #endif
2891 case IECLASS_NULL:
2892 break;
2894 #ifdef __MORPHOS__
2895 case IECLASS_NEWTIMER:
2896 if (MENUS_ACTIVE)
2898 FireMenuMessage(MMCODE_EVENT, 0, ie, IntuitionBase);
2899 keep_event = FALSE;
2900 break;
2903 if (gadget)
2905 if (gadget == iihdata->MasterSizeGadget)
2907 gadget = DoGPInput(gi, gadget, ie, GM_HANDLEINPUT, &reuse_event, IntuitionBase);
2910 } /* if (gadget) */
2911 break;
2912 #endif /* __MORPHOS__ */
2914 default:
2915 if (MENUS_ACTIVE)
2917 FireMenuMessage(MMCODE_EVENT, 0, ie, IntuitionBase);
2918 keep_event = FALSE;
2919 break;
2924 "[Intui] InputHandler: Unknown IEClass: addr = %x class = %d (origclass = %d)\n",
2925 orig_ie, ie->ie_Class,orig_ie->ie_Class
2928 break;
2929 } /* switch (ie->ie_Class) */
2931 if (reuse_event)
2934 else if (keep_event && !ie_used)
2936 *iihdata->EndInputEventChain = orig_ie;
2937 iihdata->EndInputEventChain = &orig_ie->ie_NextEvent;
2938 ie_used = TRUE;
2940 else if (!ie_used)
2942 orig_ie->ie_NextEvent = iihdata->FreeInputEvents;
2943 iihdata->FreeInputEvents = orig_ie;
2946 } /* for (each event in the chain) */
2948 iihdata->ActiveGadget = gadget;
2950 D(bug("Outside pollingloop\n"));
2952 #if SINGLE_SETPOINTERPOS_PER_EVENTLOOP
2953 if (call_setpointerpos)
2954 MySetPointerPos(IntuitionBase);
2955 #endif
2957 /* Terminate the event chain. */
2958 *iihdata->EndInputEventChain = NULL;
2960 /* Transfer the list of allocated events in the list of events that should
2961 * be freed the next time the handler is entered.
2963 iihdata->AllocatedInputEventList = iihdata->NewAllocatedInputEventList;
2964 NEWLIST((struct List*)&iihdata->NewAllocatedInputEventList);
2966 /* Reset the event chain here, not at the beginning of the handler, for
2967 * events that might be allocated in other handers.
2969 iihdata->EndInputEventChain = &iihdata->ReturnInputEvent;
2970 iihdata->FreeInputEvents = NULL;
2972 ReleaseSemaphore(&GetPrivIBase(IntuitionBase)->InputHandlerLock);
2974 // DEBUG_HANDLER(dprintf("Handler: ->IBase 0x%lx KeyMapBase 0x%lx\n",IntuitionBase,KeymapBase));
2976 return iihdata->ReturnInputEvent;
2978 AROS_USERFUNC_EXIT
2981 /****************************************************************************************/