use the cached method id's to improve performance.
[AROS.git] / rom / intuition / inputhandler_support.c
bloba82630fdc9844922b6f61384d7ce68a83ae8d4df
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$
6 Support functions for InputHandler.
7 */
9 /****************************************************************************************/
11 #include <proto/exec.h>
12 #include <proto/intuition.h>
13 #include <proto/alib.h>
14 #include <proto/layers.h>
15 #include <proto/graphics.h>
16 #include <proto/utility.h>
17 #include <proto/keymap.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/cghooks.h>
26 #include <intuition/sghooks.h>
27 #include <devices/inputevent.h>
28 #include <hidd/gfx.h>
29 #include <string.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_actions.h"
40 #include "inputhandler_support.h"
41 #include "menus.h"
43 #ifdef SKINS
44 # include "mosmisc.h"
45 #endif
47 #undef DEBUG
48 #define DEBUG 0
49 #include <aros/debug.h>
51 #define DEBUG_WINDOWNEEDSREFRESH(x) ;
52 #define DEBUG_DOGPINPUT(x) ;
53 #define DEBUG_HANDLECUSTOMRETVAL(x) ;
54 #define DEBUG_ACTIVATEGADGET(x) ;
55 #define DEBUG_FIREINTUIMSG(x) ;
56 #define DEBUG_CLICK(x)
58 #include <stddef.h>
60 /****************************************************************************************/
63 All screens and windows on active monitor will be updated with the current position of
64 the mouse pointer. Windows will receive relative mouse coordinates.
67 /****************************************************************************************/
69 void notify_mousemove_screensandwindows(struct IntuitionBase * IntuitionBase)
71 LONG lock = LockIBase(0);
72 struct Screen *scr;
74 for (scr = IntuitionBase->FirstScreen; scr; scr = scr->NextScreen)
76 struct Window *win;
78 /* Ignore screens which are not on our current monitor */
79 if (GetPrivScreen(scr)->IMonitorNode != GetPrivIBase(IntuitionBase)->ActiveMonitor)
80 continue;
82 scr->MouseX = IntuitionBase->MouseX - scr->LeftEdge;
83 scr->MouseY = IntuitionBase->MouseY - scr->TopEdge;
85 /* update windows belonging to this screen */
86 for (win = scr->FirstWindow; win; win = win->NextWindow)
88 UpdateMouseCoords(win);
92 UnlockIBase(lock);
95 /****************************************************************************************/
97 void send_intuimessage(struct IntuiMessage *imsg, struct Window *w,
98 struct IntuitionBase *IntuitionBase)
100 SendIntuiMessage(w, imsg);
103 /****************************************************************************************/
105 void free_intuimessage(struct IntuiMessage *imsg,
106 struct IntuitionBase *IntuitionBase)
108 FreeIntuiMessage(imsg);
111 /****************************************************************************************/
113 struct IntuiMessage *alloc_intuimessage(struct Window *w,
114 struct IntuitionBase *IntuitionBase)
116 struct IntuiMessage *imsg;
118 imsg = AllocIntuiMessage(w);
119 if (imsg)
121 if (w)
123 if (w->IDCMPFlags & IDCMP_DELTAMOVE)
125 struct IIHData *iihd = (struct IIHData *)GetPrivIBase(IntuitionBase)->InputHandler->is_Data;
127 imsg->MouseX = iihd->DeltaMouseX;
128 imsg->MouseY = iihd->DeltaMouseY;
130 else
132 imsg->MouseX = w->MouseX;
133 imsg->MouseY = w->MouseY;
136 CurrentTime(&imsg->Seconds, &imsg->Micros);
139 return imsg;
142 /****************************************************************************************/
144 BOOL fire_intuimessage(struct Window *w,
145 ULONG Class,
146 UWORD Code,
147 APTR IAddress,
148 struct IntuitionBase *IntuitionBase)
150 struct IntuiMessage *imsg;
151 BOOL result = FALSE;
153 if ((w->IDCMPFlags & Class) && (w->UserPort))
155 if ((imsg = alloc_intuimessage(w, IntuitionBase)))
157 struct IIHData *iihd = (struct IIHData *)GetPrivIBase(IntuitionBase)->InputHandler->is_Data;
159 imsg->Class = Class;
160 imsg->Code = Code;
161 imsg->Qualifier = iihd->ActQualifier;
162 if (Class == IDCMP_RAWKEY)
164 INT_INTUIMESSAGE(imsg)->prevCodeQuals = IAddress;
165 imsg->IAddress = &INT_INTUIMESSAGE(imsg)->prevCodeQuals;
167 else
169 imsg->IAddress = IAddress;
172 send_intuimessage(imsg, w, IntuitionBase);
174 result = TRUE;
176 else
178 DEBUG_FIREINTUIMSG(dprintf("fire_intuimessage: can't alloc imsg\n"));
181 else
183 DEBUG_FIREINTUIMSG(dprintf("fire_intuimessage: no Userport or masked out idcmpflags\n"));
186 return result;
189 BOOL fire_message(struct Window *w,ULONG Class, UWORD Code, APTR IAddress, struct IntuitionBase *IntuitionBase)
191 struct Library *UtilityBase = GetPrivIBase(IntuitionBase)->UtilityBase;
192 struct ExtIntuiMessage *imsg;
193 BOOL result = FALSE;
195 if ((w->IDCMPFlags & Class) && (w->UserPort))
197 if ((imsg = (struct ExtIntuiMessage *)alloc_intuimessage(w, IntuitionBase)))
199 struct IIHData *iihdata = (struct IIHData *)GetPrivIBase(IntuitionBase)->InputHandler->is_Data;
201 imsg->eim_IntuiMessage.Class = Class;
202 imsg->eim_IntuiMessage.Code = Code;
203 imsg->eim_IntuiMessage.Qualifier = iihdata->ActQualifier;
204 if (Class == IDCMP_RAWKEY)
206 INT_INTUIMESSAGE(imsg)->prevCodeQuals = IAddress;
207 imsg->eim_IntuiMessage.IAddress = &INT_INTUIMESSAGE(imsg)->prevCodeQuals;
209 else
211 imsg->eim_IntuiMessage.IAddress = IAddress;
214 if (iihdata->ActEventTablet && (w->MoreFlags & WMFLG_TABLETMESSAGES))
216 if ((imsg->eim_TabletData = AllocPooled(GetPrivIBase(IntuitionBase)->IDCMPPool,sizeof (struct TabletData))))
218 memclr(imsg->eim_TabletData,sizeof (struct TabletData));
219 imsg->eim_TabletData->td_XFraction = iihdata->ActEventTablet->ient_ScaledXFraction;
220 imsg->eim_TabletData->td_YFraction = iihdata->ActEventTablet->ient_ScaledYFraction;
221 imsg->eim_TabletData->td_TabletX = iihdata->ActEventTablet->ient_TabletX;
222 imsg->eim_TabletData->td_TabletY = iihdata->ActEventTablet->ient_TabletY;
223 imsg->eim_TabletData->td_RangeX = iihdata->ActEventTablet->ient_RangeX;
224 imsg->eim_TabletData->td_RangeY = iihdata->ActEventTablet->ient_RangeY;
225 imsg->eim_TabletData->td_TagList = CloneTagItems(iihdata->ActEventTablet->ient_TagList);
229 send_intuimessage((struct IntuiMessage *)imsg, w, IntuitionBase);
231 result = TRUE;
233 else
235 DEBUG_FIREINTUIMSG(dprintf("fire_intuimessage: can't alloc imsg\n"));
238 else
240 DEBUG_FIREINTUIMSG(dprintf("fire_intuimessage: no Userport or masked out idcmpflags\n"));
243 return result;
246 /****************************************************************************************/
249 use ih_fire_intuimessage if A) the inputevent because of which
250 you call this function might have to be eaten or modified
251 by Intuition or B) an inputevent might have to be created
252 by Intuition because of a deferred action.
254 In any case this function may be called only from inside Intuition's
255 InputHandler!!!!!!
258 /****************************************************************************************/
260 BOOL ih_fire_intuimessage(struct Window * w,
261 ULONG Class,
262 UWORD Code,
263 APTR IAddress,
264 struct IntuitionBase *IntuitionBase)
266 struct IIHData *iihd = (struct IIHData *)GetPrivIBase(IntuitionBase)->InputHandler->is_Data;
267 struct InputEvent *ie/* = iihd->ActInputEvent*/;
269 BOOL result;
271 DEBUG_FIREINTUIMSG(dprintf("ih_fire_intuimessage: win 0x%lx class 0x%lx code 0x%lx IAddress 0x%lx\n",
273 Class,
274 Code,
275 IAddress));
277 result = fire_message(w, Class, Code, IAddress, IntuitionBase);
279 DEBUG_FIREINTUIMSG(dprintf("ih_fire_intuimessage: fire_intuimessage result 0x%lx\n",
280 result));
282 if (result /*&& ie*/)
284 /* was sent as IDCMP to window so eat inputevent */
286 //ie->ie_Class = IECLASS_NULL;
290 #if 0
291 else if (ie/* && (ie->ie_Class != IECLASS_NULL) && !iihd->ActInputEventUsed*/)
294 /* ih_fire_intuimessage was called from inside Intuition's event handling loop */
296 //iihd->ActInputEventUsed = TRUE;
298 ie->ie_SubClass = 0;
299 ie->ie_Code = Code;
300 //ie->ie_Qualifier = iihd->ActQualifier;
301 ie->ie_EventAddress = IAddress;
303 switch(Class)
305 case IDCMP_GADGETUP:
306 /* Note: on the Amiga if a boopsi Gadget which is GA_Immediate
307 and GA_RelVerify immediately in GM_GOACTIVE returns GMR_VERIFY,
308 then this sends IDCMP_GADGETDOWN + IDCMP_GADGETUP. AROS does
309 the same. But for changed inputevents (if window does not have this
310 IDCMP Flags set) there will be only one IECLASS_GADGETDOWN
313 ie->ie_Class = IECLASS_GADGETUP;
314 break;
316 case IDCMP_GADGETDOWN:
317 ie->ie_Class = IECLASS_GADGETDOWN;
318 break;
320 case IDCMP_ACTIVEWINDOW:
321 ie->ie_Class = IECLASS_ACTIVEWINDOW;
322 break;
324 case IDCMP_INACTIVEWINDOW:
325 ie->ie_Class = IECLASS_INACTIVEWINDOW;
326 break;
328 case IDCMP_CLOSEWINDOW:
329 ie->ie_Class = IECLASS_CLOSEWINDOW;
330 break;
332 case IDCMP_MENUHELP:
333 ie->ie_Class = IECLASS_MENUHELP;
334 break;
336 case IDCMP_MENUPICK:
337 ie->ie_Class = IECLASS_MENULIST;
338 break;
340 case IDCMP_MOUSEBUTTONS:
341 case IDCMP_MOUSEMOVE:
342 case IDCMP_RAWKEY:
343 case IDCMP_VANILLAKEY:
344 break;
346 default:
347 D(bug("ih_fireintuimessage: unexpected IDCMP (%x) for an inputevent-handling-fireintuimessage!\n", Class));
348 break;
352 #endif
353 else //if (!ie)
355 /* ih_fire_intuimessage was called from inside Intuition's defered action handling routines */
357 if ((ie = AllocInputEvent(iihd)))
359 switch(Class)
361 case IDCMP_NEWSIZE:
362 ie->ie_Class = IECLASS_SIZEWINDOW;
363 break;
365 case IDCMP_CHANGEWINDOW:
366 ie->ie_Class = IECLASS_CHANGEWINDOW;
367 break;
369 case IDCMP_ACTIVEWINDOW:
370 ie->ie_Class = IECLASS_ACTIVEWINDOW;
371 break;
373 case IDCMP_INACTIVEWINDOW:
374 ie->ie_Class = IECLASS_INACTIVEWINDOW;
375 break;
377 case IDCMP_CLOSEWINDOW:
378 ie->ie_Class = IECLASS_CLOSEWINDOW;
379 break;
381 case IDCMP_GADGETUP:
382 ie->ie_Class = IECLASS_GADGETUP;
383 break;
385 case IDCMP_GADGETDOWN:
386 ie->ie_Class = IECLASS_GADGETDOWN;
387 break;
389 case IDCMP_REFRESHWINDOW:
390 ie->ie_Class = IECLASS_REFRESHWINDOW;
391 break;
393 case IDCMP_MENUHELP:
394 ie->ie_Class = IECLASS_MENUHELP;
395 break;
397 case IDCMP_MENUPICK:
398 ie->ie_Class = IECLASS_MENULIST;
399 break;
401 default:
402 D(bug("ih_fireintuimessage: unexpected IDCMP (0x%X) for a deferred-action-fireintuimessage!\n", Class));
403 break;
405 } /* switch(Class) */
407 ie->ie_Code = Code;
408 ie->ie_Qualifier = iihd->ActQualifier;
409 ie->ie_EventAddress = IAddress;
410 CurrentTime(&ie->ie_TimeStamp.tv_secs, &ie->ie_TimeStamp.tv_micro);
412 D(bug("ih_fireintuimessage: generated InputEvent. Class = 0x%X Code = %d EventAddress = 0x%X\n",
413 ie->ie_Class,
414 ie->ie_Code,
415 ie->ie_EventAddress));
417 } /* if ((ie = AllocInputEvent(iihd))) */
420 DEBUG_FIREINTUIMSG(dprintf("ih_fire_intuimessage: result 0x%lx\n",
421 result));
423 return result;
426 /*********************************************************************/
428 /* This function must never be called with the layer/layerinfo locked,
429 * otherwise a deadlock with ObtainGIRPort can happen.
431 IPTR Locked_DoMethodA (struct Window *w, struct Gadget *g, Msg message, struct IntuitionBase *IntuitionBase)
433 struct LayersBase *LayersBase = GetPrivIBase(IntuitionBase)->LayersBase;
434 IPTR rc;
435 BOOL lock = w && (g->GadgetType & GTYP_SYSGADGET &&
436 ((g->GadgetType & GTYP_SYSTYPEMASK) == GTYP_WDRAGGING ||
437 (g->GadgetType & GTYP_SYSTYPEMASK) == GTYP_SIZING));
439 if (lock)
441 LOCK_REFRESH(w->WScreen);
444 LOCKGADGET(IntuitionBase)
445 rc = Custom_DoMethodA(IntuitionBase, g, message);
446 UNLOCKGADGET(IntuitionBase)
448 if (lock)
450 UNLOCK_REFRESH(w->WScreen);
453 return rc;
456 /*********************************************************************/
458 IPTR Custom_DoMethodA (struct IntuitionBase *IntuitionBase, struct Gadget *g, Msg message)
460 if (g->MutualExclude)
462 return AROS_UFC4(IPTR, ((struct Hook *)g->MutualExclude)->h_Entry,
463 AROS_UFCA(struct Hook *, (struct Hook *)g->MutualExclude, A0),
464 AROS_UFCA(struct Gadget *, g, A2),
465 AROS_UFCA(APTR, message, A1),
466 AROS_UFCA(struct IntuitionBase *, IntuitionBase, A6));
468 else /* Not needed since gadgetclass sets MutualExclude, but doesn't hurt. */
469 return DoMethodA((Object *)g, message);
472 /****************************************************************************************/
474 void NotifyDepthArrangement(struct Window *w, struct IntuitionBase *IntuitionBase)
476 if(w->MoreFlags & WMFLG_NOTIFYDEPTH)
478 ih_fire_intuimessage(w,
479 IDCMP_CHANGEWINDOW,
480 CWCODE_DEPTH,
482 IntuitionBase);
487 /****************************************************************************************/
489 void PrepareGadgetInfo(struct GadgetInfo *gi, struct Screen *scr, struct Window *win,
490 struct Requester *req)
492 gi->gi_Screen = scr;
493 gi->gi_Window = win;
494 gi->gi_Requester = req;
495 gi->gi_RastPort = 0;
496 gi->gi_Pens.DetailPen = scr->DetailPen;
497 gi->gi_Pens.BlockPen = scr->BlockPen;
498 gi->gi_DrInfo = (APTR)&(((struct IntScreen *)gi->gi_Screen)->DInfo);
501 /****************************************************************************************/
503 void SetGadgetInfoGadget(struct GadgetInfo *gi, struct Gadget *gad,
504 struct IntuitionBase *IntuitionBase)
506 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
507 struct IIHData *iihd = (struct IIHData *)GetPrivIBase(IntuitionBase)->InputHandler->is_Data;
509 SET_GI_RPORT(gi, gi->gi_Window, gi->gi_Requester, gad);
510 InitRastPort(&iihd->GadgetInfoRastPort);
512 iihd->GadgetInfoRastPort.Layer = gi->gi_RastPort->Layer;
513 iihd->GadgetInfoRastPort.BitMap = gi->gi_RastPort->BitMap;
515 SetFont(&iihd->GadgetInfoRastPort, gi->gi_DrInfo->dri_Font);
517 gi->gi_Layer = gi->gi_RastPort->Layer;
518 gi->gi_RastPort = &iihd->GadgetInfoRastPort;
520 GetGadgetDomain(gad, gi->gi_Screen, gi->gi_Window, gi->gi_Requester, &gi->gi_Domain);
523 /****************************************************************************************/
525 void SetGPIMouseCoords(struct gpInput *gpi, struct Gadget *gad)
527 struct GadgetInfo *gi = gpi->gpi_GInfo;
529 WORD mousex, mousey;
531 if (IS_SCREEN_GADGET(gad) || !gi->gi_Window)
533 mousex = gi->gi_Screen->MouseX;
534 mousey = gi->gi_Screen->MouseY;
536 else
539 mousex = gi->gi_Window->MouseX;
540 mousey = gi->gi_Window->MouseY;
543 gpi->gpi_Mouse.X = mousex - gi->gi_Domain.Left - GetGadgetLeft(gad, gi->gi_Screen, gi->gi_Window, gi->gi_Requester);
544 gpi->gpi_Mouse.Y = mousey - gi->gi_Domain.Top - GetGadgetTop(gad, gi->gi_Screen, gi->gi_Window, gi->gi_Requester);
548 /****************************************************************************************/
550 void HandleSysGadgetVerify(struct GadgetInfo *gi, struct Gadget *gadget,
551 struct IntuitionBase *IntuitionBase)
553 struct LayersBase *LayersBase = GetPrivIBase(IntuitionBase)->LayersBase;
554 struct Screen *scr;
555 struct IIHData *iihd = (struct IIHData *)GetPrivIBase(IntuitionBase)->InputHandler->is_Data;
557 switch(gadget->GadgetType & GTYP_SYSTYPEMASK)
559 case GTYP_CLOSE:
560 #ifdef __MORPHOS__
561 if (((struct IntWindow *)(gi->gi_Window))->specialflags & SPFLAG_IAMDEAD)
563 CrashedDispose(gi->gi_Window,IntuitionBase);
565 else
567 #endif
568 ih_fire_intuimessage(gi->gi_Window,
569 IDCMP_CLOSEWINDOW,
571 gi->gi_Window,
572 IntuitionBase);
573 #ifdef __MORPHOS__
575 #endif
576 break;
578 case GTYP_WDEPTH:
579 if (!IsLayerHiddenBySibling(WLAYER(gi->gi_Window), FALSE)
580 || (iihd->ActQualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) != 0)
582 /* Send window to back */
583 WindowToBack(gi->gi_Window);
585 else
587 /* Send window to front */
588 WindowToFront(gi->gi_Window);
590 break;
592 case GTYP_WZOOM:
593 ZipWindow(gi->gi_Window);
594 break;
596 case GTYP_SDEPTH:
597 scr = FindFirstScreen(GetPrivIBase(IntuitionBase)->ActiveMonitor, IntuitionBase);
598 if (gi->gi_Screen == scr
599 || (iihd->ActQualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) != 0)
601 ScreenToBack(gi->gi_Screen);
603 else
605 ScreenToFront(gi->gi_Screen);
607 break;
609 } /* switch(gad->GadgetType & GTYP_SYSTYPEMASK) */
612 /****************************************************************************************/
614 struct Gadget *HandleCustomGadgetRetVal(IPTR retval, struct GadgetInfo *gi, struct Gadget *gadget,
615 ULONG termination, BOOL *reuse_event,
616 struct IntuitionBase *IntuitionBase)
618 struct IIHData *iihdata = (struct IIHData *)GetPrivIBase(IntuitionBase)->InputHandler->is_Data;
620 DEBUG_HANDLECUSTOMRETVAL(dprintf("HandleCustomGadgetRetVal: retval %ld gi 0x%lx gadget 0x%lx termination %ld reuse %ld\n",
621 retval,
623 gadget,
624 termination,
625 *reuse_event));
627 if (retval != GMR_MEACTIVE)
629 struct gpGoInactive gpgi;
631 DEBUG_HANDLECUSTOMRETVAL(dprintf("HandleCustomGadgetRetVal: !GMR_MEACTIVE\n"));
633 if (retval & GMR_REUSE)
635 DEBUG_HANDLECUSTOMRETVAL(dprintf("HandleCustomGadgetRetVal: GMR_REUSE\n"));
636 *reuse_event = TRUE;
639 if (retval & GMR_VERIFY)
641 DEBUG_HANDLECUSTOMRETVAL(dprintf("HandleCustomGadgetRetVal: GMR_VERIFY\n"));
642 if (IS_SYS_GADGET(gadget))
644 DEBUG_HANDLECUSTOMRETVAL(dprintf("HandleCustomGadgetRetVal: SysGad\n"));
645 HandleSysGadgetVerify(gi, gadget, IntuitionBase);
647 else
649 /* Not a system gadget. Send IDCMP_GADGETUP, but not
650 if it is a screen gadget where gi->gi_Window would
651 be NULL */
653 DEBUG_HANDLECUSTOMRETVAL(dprintf("HandleCustomGadgetRetVal: no sysgad\n"));
654 if ((gadget->Activation & GACT_RELVERIFY) &&
655 (gi->gi_Window))
657 DEBUG_HANDLECUSTOMRETVAL(dprintf("HandleCustomGadgetRetVal: Send IDCMP_GADGETUP\n"));
658 ih_fire_intuimessage(gi->gi_Window,
659 IDCMP_GADGETUP,
660 termination & 0x0000FFFF,
661 gadget,
662 IntuitionBase);
665 } /* switch(gad->GadgetType & GTYP_SYSTYPEMASK) */
667 } /* if (retval & GMR_VERIFY) */
669 DEBUG_HANDLECUSTOMRETVAL(dprintf("HandleCustomGadgetRetVal: Send GM_GOINACTIVE\n"));
671 gpgi.MethodID = GM_GOINACTIVE;
672 gpgi.gpgi_GInfo = gi;
673 gpgi.gpgi_Abort = 0;
675 Locked_DoMethodA(gi->gi_Window, gadget, (Msg)&gpgi, IntuitionBase);
677 if (SYSGADGET_ACTIVE)
679 /* Switch back from Master Drag or Size Gadget to
680 real/original/app Size or Drag Gadget */
682 DEBUG_HANDLECUSTOMRETVAL(dprintf("HandleCustomGadgetRetVal: SYSGADGET_ACTIVE\n"));
683 gadget = iihdata->ActiveSysGadget;
684 iihdata->ActiveSysGadget = NULL;
686 if (IS_BOOPSI_GADGET(gadget))
688 Locked_DoMethodA(gi->gi_Window, gadget, (Msg)&gpgi, IntuitionBase);
691 #ifdef __MORPHOS__
692 if ((gadget->GadgetType & GTYP_SYSTYPEMASK) == GTYP_WDRAGGING2)
694 ih_fire_intuimessage(gi->gi_Window,
695 IDCMP_GADGETUP,
697 gadget,
698 IntuitionBase);
700 #endif
702 retval = 0;
705 if (retval & GMR_VERIFY && gi->gi_Requester && gadget->Activation & GACT_ENDGADGET)
707 DEBUG_HANDLECUSTOMRETVAL(dprintf("HandleCustomGadgetRetVal: EndRequest\n"));
708 EndRequest(gi->gi_Requester, gi->gi_Window);
709 retval = 0;
712 gadget->Activation &= ~GACT_ACTIVEGADGET;
714 DEBUG_HANDLECUSTOMRETVAL(dprintf("HandleCustomGadgetRetVal: TabCycle 0x%lx retval 0x%lx\n",
715 (gadget->Flags & GFLG_TABCYCLE),
716 retval));
718 if ((gadget->Flags & GFLG_TABCYCLE) && (retval & GMR_NEXTACTIVE))
720 DEBUG_HANDLECUSTOMRETVAL(dprintf("HandleCustomGadgetRetVal: TabCycle+GMR_NEXTACTIVE\n"));
721 gadget = FindCycleGadget(gi->gi_Window, gi->gi_Requester, gadget, GMR_NEXTACTIVE);
723 else if ((gadget->Flags & GFLG_TABCYCLE) && (retval & GMR_PREVACTIVE))
725 DEBUG_HANDLECUSTOMRETVAL(dprintf("HandleCustomGadgetRetVal: TabCycle+GMR_PREVACTIVE\n"));
726 gadget = FindCycleGadget(gi->gi_Window, gi->gi_Requester, gadget, GMR_PREVACTIVE);
728 else
730 gadget = NULL;
731 DEBUG_HANDLECUSTOMRETVAL(dprintf("HandleCustomGadgetRetVal: No gadget\n"));
734 if (gadget)
736 DEBUG_HANDLECUSTOMRETVAL(dprintf("HandleCustomGadgetRetVal: activate gadget 0x%lx\n",gadget));
737 gadget = DoActivateGadget(gi->gi_Window, gi->gi_Requester, gadget, IntuitionBase);
740 } /* if (retval != GMR_MEACTIVE) */
741 else
743 DEBUG_HANDLECUSTOMRETVAL(dprintf("HandleCustomGadgetRetVal: set GACT_ACTIVEGADGET\n"));
744 gadget->Activation |= GACT_ACTIVEGADGET;
747 DEBUG_HANDLECUSTOMRETVAL(dprintf("HandleCustomGadgetRetVal: return 0x%x\n", gadget));
748 return gadget;
751 /****************************************************************************************/
753 /* This function must never be called with the layer/layerinfo locked,
754 * otherwise a deadlock with ObtainGIRPort can happen.
756 struct Gadget *DoGPInput(struct GadgetInfo *gi, struct Gadget *gadget,
757 struct InputEvent *ie, STACKULONG methodid,
758 BOOL *reuse_event, struct IntuitionBase *IntuitionBase)
760 struct IIHData *iihdata = (struct IIHData *)GetPrivIBase(IntuitionBase)->InputHandler->is_Data;
761 struct gpInput gpi;
762 IPTR retval;
763 ULONG termination;
764 ie->ie_Qualifier = iihdata->ActQualifier;
766 gpi.MethodID = methodid;
767 gpi.gpi_GInfo = gi;
768 gpi.gpi_IEvent = ie;
769 gpi.gpi_Termination = &termination;
770 gpi.gpi_TabletData = NULL;
772 SetGPIMouseCoords(&gpi, gadget);
774 retval = Locked_DoMethodA (gi->gi_Window, gadget, (Msg)&gpi, IntuitionBase);
776 DEBUG_DOGPINPUT(dprintf("DoGPInput: Locked_DoMethod gadget %p method 0x%lx retval %ld termination 0x%lx\n",
777 gadget, methodid, retval, termination));
779 return HandleCustomGadgetRetVal(retval, gi, gadget, termination,
780 reuse_event, IntuitionBase);
784 /****************************************************************************************/
786 struct Gadget * FindGadget (struct Screen *scr, struct Window * window,
787 struct Requester * req, int x, int y,
788 struct GadgetInfo * gi,BOOL sysonly,
789 struct IntuitionBase *IntuitionBase)
791 struct Gadget *gadget, *firstgadget, *draggadget = 0;
792 struct gpHitTest gpht;
793 struct IBox ibox;
794 WORD xrel, yrel;
795 BOOL sys_only = sysonly;
797 DEBUG_CLICK(bug("[Inputhandler] FindGadget(0x%p, 0x%p, 0x%p, %d, %d, %d)\n", scr, window, req, x, y, sysonly));
798 gpht.MethodID = GM_HITTEST;
799 gpht.gpht_GInfo = gi;
801 while (req || window || scr)
803 if (req)
805 firstgadget = req->ReqGadget;
807 else if (window)
809 firstgadget = window->FirstGadget;
811 else
813 if (draggadget) return draggadget;
814 firstgadget = scr->FirstGadget;
817 for (gadget = firstgadget; gadget; gadget = gadget->NextGadget)
819 if (!(gadget->Flags & GFLG_DISABLED) &&
820 (!sys_only ||
821 (gadget->GadgetType & GTYP_SYSGADGET &&
822 ((gadget->GadgetType & GTYP_SYSTYPEMASK) == GTYP_SIZING ||
823 (gadget->GadgetType & GTYP_SYSTYPEMASK) == GTYP_WDRAGGING ||
824 (gadget->GadgetType & GTYP_SYSTYPEMASK) == GTYP_WDEPTH ||
825 (gadget->GadgetType & GTYP_SYSTYPEMASK) == GTYP_SDEPTH ||
826 (gadget->GadgetType & GTYP_SYSTYPEMASK) == GTYP_WZOOM ||
827 (gadget->GadgetType & GTYP_SYSTYPEMASK) == GTYP_CLOSE))))
829 /* stegerg: domain depends on gadgettype and windowflags! */
830 GetGadgetDomain(gadget, scr, window, req, &gi->gi_Domain);
832 /* Get coords relative to window */
834 GetGadgetIBox(gadget, gi, &ibox);
836 xrel = x - gi->gi_Domain.Left;
837 yrel = y - gi->gi_Domain.Top;
839 /*if (req)
841 xrel -= req->LeftEdge + window->BorderLeft;
842 yrel -= req->TopEdge + window->BorderTop;
845 if (window)
847 xrel -= window->LeftEdge;
848 yrel -= window->TopEdge;
851 if ((xrel >= ibox.Left) &&
852 (yrel >= ibox.Top) &&
853 (xrel < ibox.Left + ibox.Width) &&
854 (yrel < ibox.Top + ibox.Height))
856 if ((gadget->GadgetType & GTYP_SYSTYPEMASK) == GTYP_WDRAGGING)
858 if (!draggadget) draggadget = gadget;
860 else
863 if ((gadget->GadgetType & GTYP_GTYPEMASK) == GTYP_CUSTOMGADGET)
866 gpht.gpht_Mouse.X = xrel - ibox.Left;
867 gpht.gpht_Mouse.Y = yrel - ibox.Top;
869 /* jDc: don't check for == GMR_GADGETHIT since some reaction classes*/
870 /* (BURN IN HELL!) return TRUE here (related to imageclass HITEST?)*/
871 if (Locked_DoMethodA (window, gadget, (Msg)&gpht, IntuitionBase))
872 return (gadget);
874 else
876 return (gadget);
881 } /* if (!(gadget->Flags & GFLG_DISABLED)) */
883 } /* for (gadget = window->FirstGadget; gadget; gadget = gadget->NextGadget) */
885 sys_only = sysonly;
887 if (req)
889 req = NULL;
890 sys_only = TRUE;
892 else if (window)
894 #ifdef SKINS
895 draggadget = findbordergadget(window,draggadget,IntuitionBase);
896 #endif
897 window = NULL;
899 else
900 scr = NULL;
903 return (draggadget);
905 } /* FindGadget */
908 /****************************************************************************************/
910 struct Gadget * FindHelpGadget (struct Window * window,
911 int x, int y, struct IntuitionBase *IntuitionBase)
913 struct Gadget *gadget, *firstgadget;
914 struct Requester *req = window->FirstRequest;
916 while (req || window)
918 if (req)
920 firstgadget = req->ReqGadget;
922 else
924 firstgadget = window->FirstGadget;
927 for (gadget = firstgadget; gadget; gadget = gadget->NextGadget)
929 if ((gadget->Flags & GFLG_EXTENDED) &&
930 (((struct ExtGadget *)gadget)->MoreFlags & GMORE_GADGETHELP))
932 if (InsideGadget(window->WScreen, window, req, gadget, x, y))
934 return (gadget);
940 if (req)
941 req = req->OlderRequest;
942 else
943 window = NULL;
946 return (NULL);
948 } /* FindHelpGadget */
951 /****************************************************************************************/
953 BOOL InsideGadget(struct Screen *scr, struct Window *win, struct Requester *req,
954 struct Gadget *gad, WORD x, WORD y)
956 struct IBox box;
957 BOOL rc = FALSE;
959 GetScrGadgetIBox(gad, scr, win, req, &box);
961 if ((x >= box.Left) &&
962 (y >= box.Top) &&
963 (x < box.Left + box.Width) &&
964 (y < box.Top + box.Height))
966 rc = TRUE;
969 return rc;
972 /****************************************************************************************/
974 struct Gadget *DoActivateGadget(struct Window *win, struct Requester *req, struct Gadget *gad,
975 struct IntuitionBase *IntuitionBase)
977 struct IIHData *iihd = (struct IIHData *)GetPrivIBase(IntuitionBase)->InputHandler->is_Data;
978 struct GadgetInfo *gi = &iihd->GadgetInfo;
979 struct Gadget *result = NULL;
981 DEBUG_ACTIVATEGADGET(dprintf("DoActivateGadget: Window 0x%lx Req 0x%lx Gadget 0x%lx\n",
982 win,
983 req,
984 gad));
986 DEBUG_ACTIVATEGADGET(dprintf("DoActivateGadget: Activation 0x%lx\n",
987 gad->Activation));
989 if (gad->Activation & GACT_IMMEDIATE)
991 DEBUG_ACTIVATEGADGET(dprintf("DoActivateGadget: Send GADGETDOWN msg\n"));
992 ih_fire_intuimessage(win,
993 IDCMP_GADGETDOWN,
995 gad,
996 IntuitionBase);
999 PrepareGadgetInfo(gi, win->WScreen, win, req);
1000 SetGadgetInfoGadget(gi, gad, IntuitionBase);
1002 DEBUG_ACTIVATEGADGET(dprintf("DoActivateGadget: Type 0x%lx\n",
1003 gad->GadgetType & GTYP_GTYPEMASK));
1005 switch(gad->GadgetType & GTYP_GTYPEMASK)
1007 case GTYP_STRGADGET:
1009 struct StringInfo *si = (struct StringInfo *)gad->SpecialInfo;
1011 DEBUG_ACTIVATEGADGET(dprintf("DoActivateGadget: GTYP_STRGADGET\n"));
1013 gad->Flags |= GFLG_SELECTED;
1014 if (si && si->UndoBuffer)
1016 strcpy(si->UndoBuffer, si->Buffer);
1019 gad->Activation |= GACT_ACTIVEGADGET;
1020 UpdateStrGadget(gad, win, req, IntuitionBase);
1021 result = gad;
1022 break;
1025 case GTYP_CUSTOMGADGET:
1027 struct gpInput gpi;
1028 ULONG termination;
1029 IPTR retval;
1030 BOOL reuse_event;
1032 DEBUG_ACTIVATEGADGET(dprintf("DoActivateGadget: GTYP_CUSTOMGADGET\n"));
1034 gpi.MethodID = GM_GOACTIVE;
1035 gpi.gpi_GInfo = gi;
1036 gpi.gpi_IEvent = NULL;
1037 gpi.gpi_Termination = &termination;
1038 gpi.gpi_Mouse.X = win->MouseX - gi->gi_Domain.Left - GetGadgetLeft(gad, gi->gi_Screen, gi->gi_Window, NULL);
1039 gpi.gpi_Mouse.Y = win->MouseY - gi->gi_Domain.Top - GetGadgetTop(gad, gi->gi_Screen, gi->gi_Window, NULL);
1040 gpi.gpi_TabletData = NULL;
1042 retval = Locked_DoMethodA (win, gad, (Msg)&gpi, IntuitionBase);
1044 gad = HandleCustomGadgetRetVal(retval, gi, gad,termination,
1045 &reuse_event, IntuitionBase);
1047 if (gad)
1049 gad->Activation |= GACT_ACTIVEGADGET;
1050 result = gad;
1052 break;
1055 } /* switch(gad->GadgetType & GTYP_GTYPEMASK) */
1057 DEBUG_ACTIVATEGADGET(dprintf("DoActivateGadget: result 0x%lx\n",
1058 result));
1060 if (result) iihd->ActiveGadget = result;
1062 return result;
1066 /****************************************************************************************/
1068 struct Gadget *FindCycleGadget(struct Window *win, struct Requester *req,
1069 struct Gadget *gad, WORD direction)
1071 struct Gadget *g = NULL, *gg, *prev, *first;
1073 D(bug("FindCycleGadget: win = %p req %p gad = %p direction = %d\n", win, req, gad, direction));
1075 if (req)
1076 first = req->ReqGadget;
1077 else
1078 first = win->FirstGadget;
1080 switch(direction)
1082 case GMR_NEXTACTIVE:
1083 g = gad->NextGadget;
1084 if (!g) g = first;
1086 while(g)
1088 if (g == gad)
1090 if (!(gad->Flags & GFLG_TABCYCLE) || (gad->Flags & GFLG_DISABLED))
1092 /* should never happen */
1093 g = NULL;
1095 break;
1097 if (!(g->Flags & GFLG_DISABLED) && (g->Flags & GFLG_TABCYCLE)) break;
1099 g = g->NextGadget;
1100 if (!g) g = first;
1102 break;
1104 case GMR_PREVACTIVE:
1105 prev = 0;
1106 g = 0;
1107 gg = first;
1109 /* find a TABCYCLE gadget which is before gad in window's gadgetlist */
1110 while (gg)
1112 if (gg == gad)
1114 if (prev) g = prev;
1115 break;
1117 if (!(gg->Flags & GFLG_DISABLED) && (gg->Flags & GFLG_TABCYCLE)) prev = gg;
1118 gg = gg->NextGadget;
1121 if (gg && !g)
1123 /* There was no TABCYCLE gadget before gad in window's gadgetlist */
1125 gg = gg->NextGadget;
1126 if (!gg)
1128 if (!(gad->Flags & GFLG_DISABLED) && (gad->Flags & GFLG_TABCYCLE)) g = gad;
1129 break;
1131 prev = 0;
1133 while(gg)
1135 if (!(gg->Flags & GFLG_DISABLED) && (gg->Flags & GFLG_TABCYCLE)) prev = gg;
1136 gg = gg->NextGadget;
1139 if (prev)
1141 g = prev;
1143 else
1145 if (!(gad->Flags & GFLG_DISABLED) && (gad->Flags & GFLG_TABCYCLE)) g = gad;
1150 break;
1152 default: /* Unused, but well... */
1153 g = first;
1154 break;
1156 } /* switch(direction) */
1158 return g;
1161 /****************************************************************************************/
1163 void FixWindowCoords(struct Window *win, LONG *left, LONG *top, LONG *width, LONG *height,struct IntuitionBase *IntuitionBase)
1165 struct Screen *scr = win->WScreen;
1167 if (*width < 1) *width = 1;
1168 if (*height < 1) *height = 1;
1170 if (*width > scr->Width) *width = scr->Width;
1171 if (*height > scr->Height) *height = scr->Height;
1173 if ((GetPrivIBase(IntuitionBase)->IControlPrefs.ic_Flags & ICF_OFFSCREENLAYERS) && (win->WScreen->LayerInfo.Flags & LIFLG_SUPPORTS_OFFSCREEN_LAYERS))
1175 if (*left > scr->Width - 1) *left = scr->Width - 1;
1176 if (*top > scr->Height - 1) *top = scr->Height -1;
1178 else
1181 if ((*left + *width) > scr->Width)
1183 *left = scr->Width - *width;
1185 else if (*left < 0)
1187 *left = 0;
1190 if ((*top + *height) > scr->Height)
1192 *top = scr->Height - *height;
1194 else if (*top < 0)
1196 *top = 0;
1201 /****************************************************************************************/
1203 void WindowNeedsRefresh(struct Window * w,
1204 struct IntuitionBase * IntuitionBase )
1206 /* Supposed to send a message to this window, saying that it needs a
1207 refresh. I will check whether there is no such a message queued in
1208 its messageport, though. It only needs one such message!
1211 /* Refresh the window's gadgetry ...
1212 ... stegerg: and in the actual implementation
1213 call RefreshWindowFrame first, as the border gadgets don't
1214 cover the whole border area.*/
1217 jDc: in actual implementation sizeevent means that we need to send
1218 idcmp, etc and do not clear the flag for smart_refresh window that
1219 has no idcmp_refreshwindow, otherwise we clear the flag!
1222 DEBUG_WINDOWNEEDSREFRESH(dprintf("WindowNeedsRefresh: window 0x%lx gzz %d nocarerefresh %d\n",
1223 w, IS_GZZWINDOW(w), IS_NOCAREREFRESH(w)));
1225 //trashregion means that we use delayed refreshing!
1227 if (
1228 #ifdef DAMAGECACHE
1229 (!IW(w)->trashregion) ||
1230 #else
1231 (!(w->Flags & WFLG_SIMPLE_REFRESH)) ||
1232 #endif
1233 IS_NOCAREREFRESH(w))
1236 Gad_BeginUpdate(WLAYER(w), IntuitionBase);
1238 if (IS_NOCAREREFRESH(w) || (!((!(w->Flags & WFLG_SIMPLE_REFRESH)) && (!(IW(w)->specialflags & SPFLAG_LAYERRESIZED)))))
1240 if (!IS_GZZWINDOW(w))
1242 if (w->Flags & WFLG_BORDERLESS)
1244 int_refreshglist(w->FirstGadget, w, NULL, -1, 0, 0, IntuitionBase);
1246 else
1248 int_refreshwindowframe(w,0,0,IntuitionBase);
1251 else
1253 /* refresh all gadgets except border gadgets */
1254 int_refreshglist(w->FirstGadget, w, NULL, -1, 0, REFRESHGAD_BORDER, IntuitionBase);
1256 IW(w)->specialflags &= ~SPFLAG_LAYERRESIZED;
1259 if (IS_NOCAREREFRESH(w)) WLAYER(w)->Flags &= ~LAYERREFRESH;
1261 Gad_EndUpdate(WLAYER(w), IS_NOCAREREFRESH(w) ? TRUE : FALSE, IntuitionBase);
1263 } else {
1264 #ifdef DAMAGECACHE
1265 struct Rectangle rect;
1266 BOOL doclear = (w->Flags & WFLG_BORDERLESS) ? FALSE : TRUE;
1268 rect.MinX = w->BorderLeft;
1269 rect.MinY = w->BorderTop;
1270 rect.MaxX = w->Width - w->BorderRight - 1;
1271 rect.MaxY = w->Height - w->BorderBottom - 1;
1272 #endif
1274 #ifndef BEGINUPDATEGADGETREFRESH
1275 Gad_BeginUpdate(WLAYER(w), IntuitionBase);
1276 #else
1277 #ifdef DAMAGECACHE
1278 LockLayer(0,WLAYER(w));
1279 #endif
1280 #endif
1282 #ifndef BEGINUPDATEGADGETREFRESH
1283 if (!IS_GZZWINDOW(w))
1285 if (w->Flags & WFLG_BORDERLESS)
1287 int_refreshglist(w->FirstGadget, w, NULL, -1, 0, 0, IntuitionBase);
1289 else
1291 int_refreshwindowframe(w,0,0,IntuitionBase);
1294 else
1296 /* refresh all gadgets except border and gadtools gadgets */
1297 int_refreshglist(w->FirstGadget, w, NULL, -1, 0, REFRESHGAD_BORDER , IntuitionBase);
1299 #endif
1301 #ifdef DAMAGECACHE
1302 //add rects to trashregion here
1303 OrRegionRegion(WLAYER(w)->DamageList,IW(w)->trashregion);
1305 if (doclear)
1307 ClearRectRegion(IW(w)->trashregion,&rect);
1308 AndRectRegion(WLAYER(w)->DamageList,&rect);
1311 IW(w)->specialflags |= SPFLAG_LAYERREFRESH;
1312 #else
1313 #ifdef BEGINUPDATEGADGETREFRESH
1314 IW(w)->specialflags |= SPFLAG_LAYERREFRESH;
1315 #endif
1316 #endif
1318 #ifndef BEGINUPDATEGADGETREFRESH
1319 Gad_EndUpdate(WLAYER(w), FALSE, IntuitionBase);
1320 #else
1321 #ifdef DAMAGECACHE
1322 UnlockLayer(WLAYER(w));
1323 #endif
1324 #endif
1328 if (IS_DOCAREREFRESH(w))
1330 if (w->UserPort && (w->IDCMPFlags & IDCMP_REFRESHWINDOW))
1332 struct IntuiMessage *IM;
1333 BOOL found = FALSE;
1335 /* Can use Forbid() for this */
1336 Forbid();
1338 IM = (struct IntuiMessage *)w->UserPort->mp_MsgList.lh_Head;
1340 ForeachNode(&w->UserPort->mp_MsgList, IM)
1342 /* Does the window already have such a message? */
1343 if (IDCMP_REFRESHWINDOW == IM->Class && IM->IAddress == w)
1345 DEBUG_WINDOWNEEDSREFRESH(dprintf("WindowNeedsRefresh: refresh pending\n"));
1346 D(bug("Window %s already has a refresh message pending!!\n",
1347 w->Title ? w->Title : (STRPTR)"<NONAME>"));
1348 found = TRUE;
1349 break;
1353 Permit();
1355 if (!found)
1357 struct InputEvent *new_ie;
1358 struct IIHData *iihdata = (struct IIHData *)GetPrivIBase(IntuitionBase)->InputHandler->is_Data;
1360 D(bug("Sending a refresh message to window %s %d %d %d %d!!\n",
1361 w->Title ? w->Title : (STRPTR)"<NONAME>",
1362 w->LeftEdge,
1363 w->TopEdge,
1364 w->Width,
1365 w->Height));
1367 DEBUG_WINDOWNEEDSREFRESH(dprintf("WindowNeedsRefresh: sending idcmp message\n"));
1369 if ((new_ie = AllocInputEvent(iihdata)))
1371 new_ie->ie_Class = IECLASS_EVENT;
1372 new_ie->ie_Code = IECODE_REFRESH;
1373 new_ie->ie_EventAddress = w;
1374 CurrentTime(&new_ie->ie_TimeStamp.tv_secs, &new_ie->ie_TimeStamp.tv_micro);
1377 fire_intuimessage(w,
1378 IDCMP_REFRESHWINDOW,
1381 IntuitionBase);
1382 } /* if (!found) */
1384 } /* if (w->UserPort && (w->IDCMPFlags & IDCMP_REFRESHWINDOW)) */
1385 else
1387 struct IIHData *iihdata = (struct IIHData *)GetPrivIBase(IntuitionBase)->InputHandler->is_Data;
1389 if (FindTask(NULL) == iihdata->InputDeviceTask)
1391 struct InputEvent *new_ie;
1393 D(bug("Sending a refresh message to window %s %d %d %d %d!!\n",
1394 w->Title ? w->Title : (STRPTR)"<NONAME>",
1395 w->LeftEdge,
1396 w->TopEdge,
1397 w->Width,
1398 w->Height));
1399 DEBUG_WINDOWNEEDSREFRESH(dprintf("WindowNeedsRefresh: sending inputevent\n"));
1401 if ((new_ie = AllocInputEvent(iihdata)))
1403 new_ie->ie_Class = IECLASS_EVENT;
1404 new_ie->ie_Code = IECODE_REFRESH;
1405 new_ie->ie_EventAddress = w;
1406 CurrentTime(&new_ie->ie_TimeStamp.tv_secs, &new_ie->ie_TimeStamp.tv_micro);
1409 ih_fire_intuimessage(w,
1410 IDCMP_REFRESHWINDOW,
1413 IntuitionBase);
1417 } /* if (!IS_NOCAREREFRESH(w)) */
1421 /****************************************************************************************/
1423 struct Screen *FindHighestScreen(struct IntuitionBase *IntuitionBase)
1425 struct Screen *scr, *highest = IntuitionBase->FirstScreen;
1427 for (scr = highest; scr; scr = scr->NextScreen) {
1428 /* We only check screens that are on this monitor */
1429 if (GetPrivScreen(scr)->IMonitorNode
1430 != GetPrivIBase(IntuitionBase)->ActiveMonitor)
1431 continue;
1433 /* Check if top of screen is highest so far */
1434 if (scr->TopEdge < highest->TopEdge)
1435 highest = scr;
1437 return highest;
1440 /****************************************************************************************/
1442 struct Screen *FindActiveScreen(struct IntuitionBase *IntuitionBase)
1444 struct Screen *scr;
1445 WORD MinX, MinY, MaxX, MaxY;
1446 ULONG compflags;
1448 for (scr = IntuitionBase->FirstScreen; scr; scr = scr->NextScreen) {
1449 /* We check only screens which are on this monitor */
1450 if (GetPrivScreen(scr)->IMonitorNode != GetPrivIBase(IntuitionBase)->ActiveMonitor)
1451 continue;
1453 compflags = GetPrivScreen(scr)->SpecialFlags >> 8;
1455 /* adjust screen bounds if compositing */
1456 if (compflags & COMPF_ABOVE)
1457 MinY = 0;
1458 else
1459 MinY = -(scr->TopEdge);
1461 if (compflags & COMPF_BELOW)
1462 MaxY = scr->Height;
1463 else
1464 MaxY = scr->MouseY + 1;
1466 if (compflags & COMPF_LEFT)
1467 MinX = 0;
1468 else
1469 MinX = -(scr->LeftEdge);
1471 if (compflags & COMPF_RIGHT)
1472 MaxX = scr->Width;
1473 else
1474 MaxX = scr->MouseX + 1;
1476 D(bug("[Intuition] Bounds %d,%d->%d,%d\n", MinX, MinY, MaxX, MaxY));
1477 /* If the mouse is inside screen's bounds, we found it */
1478 if ((scr->MouseX >= MinX) && (scr->MouseY >= MinY) &&
1479 ((scr->MouseX < MaxX) && scr->MouseY < MaxY))
1480 break;
1482 return scr;
1485 /****************************************************************************************/
1487 struct Window *FindActiveWindow(struct InputEvent *ie, struct Screen *scr, ULONG *stitlebarhit,
1488 struct IntuitionBase *IntuitionBase)
1490 /* The caller has checked that the input event is a IECLASS_RAWMOUSE, SELECTDOWN event */
1491 /* NOTE: may be called with NULL ie ptr! */
1492 struct LayersBase *LayersBase = GetPrivIBase(IntuitionBase)->LayersBase;
1493 struct Layer *l;
1494 struct Window *new_w;
1495 ULONG lock;
1497 lock = LockIBase(0UL);
1499 new_w = IntuitionBase->ActiveWindow;
1501 UnlockIBase(lock);
1503 D(bug("FindActiveWindow: scr %p win %p\n",scr,new_w));
1505 if (stitlebarhit) *stitlebarhit = FALSE;
1507 if (scr)
1509 D(bug("FindActiveWindow: Click at (%d,%d)\n",scr->MouseX,scr->MouseY));
1511 /* What layer ? */
1512 LockLayerInfo(&scr->LayerInfo);
1514 l = WhichLayer(&scr->LayerInfo, scr->MouseX, scr->MouseY);
1516 UnlockLayerInfo(&scr->LayerInfo);
1518 if (NULL == l)
1520 new_w = NULL;
1521 D(bug("FindActiveWindow: Click not inside layer\n"));
1523 else if (l == scr->BarLayer)
1525 D(bug("FindActiveWindow: Click on screen bar layer -> active window stays the same\n"));
1526 if (stitlebarhit) *stitlebarhit = TRUE;
1528 else
1530 new_w = (struct Window *)l->Window;
1531 if (!new_w)
1533 D(bug("FindActiveWindow: Selected layer is not a window\n"));
1536 D(bug("FindActiveWindow: Found layer %p\n", l));
1540 D(bug("FindActiveWindow: New window %p\n", new_w));
1541 return new_w;
1544 /****************************************************************************************/
1546 struct Window *FindDesktopWindow(struct Screen *screen,struct IntuitionBase *IntuitionBase)
1548 struct Window *win;
1550 for (win = screen->FirstWindow; win; win = win->NextWindow)
1552 if (win->Flags & WFLG_BACKDROP &&
1553 win->Width == screen->Width &&
1554 win->Height >= screen->Height - (screen->BarHeight + 2))
1556 return win;
1560 return NULL;
1564 /****************************************************************************************/
1566 struct InputEvent *AllocInputEvent(struct IIHData *iihdata)
1568 struct GeneratedInputEvent *gie;
1569 struct InputEvent *ie;
1571 /* There might be an inputevent from someone else that our handler discarded.
1572 * We may as well use it. This can only happen inside our main loop.
1574 ie = iihdata->FreeInputEvents;
1575 if (ie)
1577 iihdata->FreeInputEvents = ie->ie_NextEvent;
1578 DEBUG_INPUTEVENT(dprintf("AllocInputEvent: reuse 0x%lx event\n", ie));
1580 else
1582 gie = AllocPooled(iihdata->InputEventMemPool, sizeof(struct GeneratedInputEvent));
1583 if (gie)
1585 /* Allocated events are put in the list of events that have not yet been
1586 * propagated.
1588 AddTail((struct List *)&iihdata->NewAllocatedInputEventList, (struct Node *)gie);
1589 ie = &gie->ie;
1591 DEBUG_INPUTEVENT(dprintf("AllocInputEvent: allocated 0x%lx (0x%lx)\n", ie, gie));
1594 if (ie)
1596 *iihdata->EndInputEventChain = ie;
1597 iihdata->EndInputEventChain = &ie->ie_NextEvent;
1600 return ie;
1603 /****************************************************************************************/
1605 void FreeGeneratedInputEvents(struct IIHData *iihdata)
1607 struct Node *node, *succ;
1609 /* Free the list of allocated events that have already been propagated. */
1610 ForeachNodeSafe(&iihdata->AllocatedInputEventList, node, succ)
1612 DEBUG_INPUTEVENT(dprintf("FreeGeneratedInputEvent: free 0x%lx\n", node));
1613 FreePooled(iihdata->InputEventMemPool, node, sizeof(struct GeneratedInputEvent));
1616 /* The list is not in a valid state at this point, and NewList() should
1617 * be called, but since we won't use it until the list of not-yet-propagated
1618 * events is copied in it, we won't bother.
1620 //NEWLIST(&iihdata->AllocatedInputEventList);
1623 /****************************************************************************************/
1625 BOOL FireMenuMessage(WORD code, struct Window *win,
1626 struct InputEvent *ie, struct IntuitionBase *IntuitionBase)
1628 struct MenuMessage *msg;
1629 BOOL result = FALSE;
1631 if ((msg = AllocMenuMessage(IntuitionBase)))
1633 msg->code = code;
1634 msg->win = win;
1635 if (ie) msg->ie = *ie;
1636 SendMenuMessage(msg, IntuitionBase);
1638 result = TRUE;
1641 return result;
1644 /****************************************************************************************/
1646 LONG Gad_BeginUpdate(struct Layer *layer, struct IntuitionBase *IntuitionBase)
1648 struct LayersBase *LayersBase = GetPrivIBase(IntuitionBase)->LayersBase;
1650 /* Must lock GadgetLock to avoid deadlocks with ObtainGirPort
1651 from other tasks, because ObtainGirPort first obtains
1652 GadgetLock and then layer lock through LockLayer!!!! */
1653 LOCKGADGET(IntuitionBase)
1654 return BeginUpdate(layer);
1657 /****************************************************************************************/
1659 void Gad_EndUpdate(struct Layer *layer, UWORD flag, struct IntuitionBase *IntuitionBase)
1661 struct LayersBase *LayersBase = GetPrivIBase(IntuitionBase)->LayersBase;
1663 EndUpdate(layer, flag);
1664 UNLOCKGADGET(IntuitionBase)
1667 /****************************************************************************************/