revert between 56095 -> 55830 in arch
[AROS.git] / rom / intuition / inputhandler_support.c
blob93c037fc49a500f9f4cdd4c7bd62ee60d674b36b
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 <aros/config.h>
13 #include <proto/exec.h>
14 #include <proto/execlock.h>
15 #include <proto/intuition.h>
16 #include <proto/alib.h>
17 #include <proto/layers.h>
18 #include <proto/graphics.h>
19 #include <proto/utility.h>
20 #include <proto/keymap.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/cghooks.h>
29 #include <intuition/sghooks.h>
30 #include <devices/inputevent.h>
31 #include <hidd/gfx.h>
32 #include <string.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_actions.h"
43 #include "inputhandler_support.h"
44 #include "menus.h"
46 #ifdef SKINS
47 # include "mosmisc.h"
48 #endif
50 #undef DEBUG
51 #define DEBUG 0
52 #include <aros/debug.h>
54 #define DEBUG_WINDOWNEEDSREFRESH(x) ;
55 #define DEBUG_DOGPINPUT(x) ;
56 #define DEBUG_HANDLECUSTOMRETVAL(x) ;
57 #define DEBUG_ACTIVATEGADGET(x) ;
58 #define DEBUG_FIREINTUIMSG(x) ;
59 #define DEBUG_CLICK(x)
61 #include <stddef.h>
63 /****************************************************************************************/
66 All screens and windows on active monitor will be updated with the current position of
67 the mouse pointer. Windows will receive relative mouse coordinates.
70 /****************************************************************************************/
72 void notify_mousemove_screensandwindows(struct IntuitionBase * IntuitionBase)
74 LONG lock = LockIBase(0);
75 struct Screen *scr;
77 for (scr = IntuitionBase->FirstScreen; scr; scr = scr->NextScreen)
79 struct Window *win;
81 /* Ignore screens which are not on our current monitor */
82 if (GetPrivScreen(scr)->IMonitorNode != GetPrivIBase(IntuitionBase)->ActiveMonitor)
83 continue;
85 scr->MouseX = IntuitionBase->MouseX - scr->LeftEdge;
86 scr->MouseY = IntuitionBase->MouseY - scr->TopEdge;
88 /* update windows belonging to this screen */
89 for (win = scr->FirstWindow; win; win = win->NextWindow)
91 UpdateMouseCoords(win);
95 UnlockIBase(lock);
98 /****************************************************************************************/
100 void send_intuimessage(struct IntuiMessage *imsg, struct Window *w,
101 struct IntuitionBase *IntuitionBase)
103 SendIntuiMessage(w, imsg);
106 /****************************************************************************************/
108 void free_intuimessage(struct IntuiMessage *imsg,
109 struct IntuitionBase *IntuitionBase)
111 FreeIntuiMessage(imsg);
114 /****************************************************************************************/
116 struct IntuiMessage *alloc_intuimessage(struct Window *w,
117 struct IntuitionBase *IntuitionBase)
119 struct IntuiMessage *imsg;
121 imsg = AllocIntuiMessage(w);
122 if (imsg)
124 if (w)
126 if (w->IDCMPFlags & IDCMP_DELTAMOVE)
128 struct IIHData *iihd = (struct IIHData *)GetPrivIBase(IntuitionBase)->InputHandler->is_Data;
130 imsg->MouseX = iihd->DeltaMouseX;
131 imsg->MouseY = iihd->DeltaMouseY;
133 else
135 imsg->MouseX = w->MouseX;
136 imsg->MouseY = w->MouseY;
139 CurrentTime(&imsg->Seconds, &imsg->Micros);
142 return imsg;
145 /****************************************************************************************/
147 BOOL fire_intuimessage(struct Window *w,
148 ULONG Class,
149 UWORD Code,
150 APTR IAddress,
151 struct IntuitionBase *IntuitionBase)
153 struct IntuiMessage *imsg;
154 BOOL result = FALSE;
156 if ((w->IDCMPFlags & Class) && (w->UserPort))
158 if ((imsg = alloc_intuimessage(w, IntuitionBase)))
160 struct IIHData *iihd = (struct IIHData *)GetPrivIBase(IntuitionBase)->InputHandler->is_Data;
162 imsg->Class = Class;
163 imsg->Code = Code;
164 imsg->Qualifier = iihd->ActQualifier;
165 if (Class == IDCMP_RAWKEY)
167 INT_INTUIMESSAGE(imsg)->prevCodeQuals = IAddress;
168 imsg->IAddress = &INT_INTUIMESSAGE(imsg)->prevCodeQuals;
170 else
172 imsg->IAddress = IAddress;
175 send_intuimessage(imsg, w, IntuitionBase);
177 result = TRUE;
179 else
181 DEBUG_FIREINTUIMSG(dprintf("fire_intuimessage: can't alloc imsg\n"));
184 else
186 DEBUG_FIREINTUIMSG(dprintf("fire_intuimessage: no Userport or masked out idcmpflags\n"));
189 return result;
192 BOOL fire_message(struct Window *w,ULONG Class, UWORD Code, APTR IAddress, struct IntuitionBase *IntuitionBase)
194 struct Library *UtilityBase = GetPrivIBase(IntuitionBase)->UtilityBase;
195 struct ExtIntuiMessage *imsg;
196 BOOL result = FALSE;
198 if ((w->IDCMPFlags & Class) && (w->UserPort))
200 if ((imsg = (struct ExtIntuiMessage *)alloc_intuimessage(w, IntuitionBase)))
202 struct IIHData *iihdata = (struct IIHData *)GetPrivIBase(IntuitionBase)->InputHandler->is_Data;
204 imsg->eim_IntuiMessage.Class = Class;
205 imsg->eim_IntuiMessage.Code = Code;
206 imsg->eim_IntuiMessage.Qualifier = iihdata->ActQualifier;
207 if (Class == IDCMP_RAWKEY)
209 INT_INTUIMESSAGE(imsg)->prevCodeQuals = IAddress;
210 imsg->eim_IntuiMessage.IAddress = &INT_INTUIMESSAGE(imsg)->prevCodeQuals;
212 else
214 imsg->eim_IntuiMessage.IAddress = IAddress;
217 if (iihdata->ActEventTablet && (w->MoreFlags & WMFLG_TABLETMESSAGES))
219 if ((imsg->eim_TabletData = AllocPooled(GetPrivIBase(IntuitionBase)->IDCMPPool,sizeof (struct TabletData))))
221 memclr(imsg->eim_TabletData,sizeof (struct TabletData));
222 imsg->eim_TabletData->td_XFraction = iihdata->ActEventTablet->ient_ScaledXFraction;
223 imsg->eim_TabletData->td_YFraction = iihdata->ActEventTablet->ient_ScaledYFraction;
224 imsg->eim_TabletData->td_TabletX = iihdata->ActEventTablet->ient_TabletX;
225 imsg->eim_TabletData->td_TabletY = iihdata->ActEventTablet->ient_TabletY;
226 imsg->eim_TabletData->td_RangeX = iihdata->ActEventTablet->ient_RangeX;
227 imsg->eim_TabletData->td_RangeY = iihdata->ActEventTablet->ient_RangeY;
228 imsg->eim_TabletData->td_TagList = CloneTagItems(iihdata->ActEventTablet->ient_TagList);
232 send_intuimessage((struct IntuiMessage *)imsg, w, IntuitionBase);
234 result = TRUE;
236 else
238 DEBUG_FIREINTUIMSG(dprintf("fire_intuimessage: can't alloc imsg\n"));
241 else
243 DEBUG_FIREINTUIMSG(dprintf("fire_intuimessage: no Userport or masked out idcmpflags\n"));
246 return result;
249 /****************************************************************************************/
252 use ih_fire_intuimessage if A) the inputevent because of which
253 you call this function might have to be eaten or modified
254 by Intuition or B) an inputevent might have to be created
255 by Intuition because of a deferred action.
257 In any case this function may be called only from inside Intuition's
258 InputHandler!!!!!!
261 /****************************************************************************************/
263 BOOL ih_fire_intuimessage(struct Window * w,
264 ULONG Class,
265 UWORD Code,
266 APTR IAddress,
267 struct IntuitionBase *IntuitionBase)
269 struct IIHData *iihd = (struct IIHData *)GetPrivIBase(IntuitionBase)->InputHandler->is_Data;
270 struct InputEvent *ie/* = iihd->ActInputEvent*/;
272 BOOL result;
274 DEBUG_FIREINTUIMSG(dprintf("ih_fire_intuimessage: win 0x%lx class 0x%lx code 0x%lx IAddress 0x%lx\n",
276 Class,
277 Code,
278 IAddress));
280 result = fire_message(w, Class, Code, IAddress, IntuitionBase);
282 DEBUG_FIREINTUIMSG(dprintf("ih_fire_intuimessage: fire_intuimessage result 0x%lx\n",
283 result));
285 if (result /*&& ie*/)
287 /* was sent as IDCMP to window so eat inputevent */
289 //ie->ie_Class = IECLASS_NULL;
293 #if 0
294 else if (ie/* && (ie->ie_Class != IECLASS_NULL) && !iihd->ActInputEventUsed*/)
297 /* ih_fire_intuimessage was called from inside Intuition's event handling loop */
299 //iihd->ActInputEventUsed = TRUE;
301 ie->ie_SubClass = 0;
302 ie->ie_Code = Code;
303 //ie->ie_Qualifier = iihd->ActQualifier;
304 ie->ie_EventAddress = IAddress;
306 switch(Class)
308 case IDCMP_GADGETUP:
309 /* Note: on the Amiga if a boopsi Gadget which is GA_Immediate
310 and GA_RelVerify immediately in GM_GOACTIVE returns GMR_VERIFY,
311 then this sends IDCMP_GADGETDOWN + IDCMP_GADGETUP. AROS does
312 the same. But for changed inputevents (if window does not have this
313 IDCMP Flags set) there will be only one IECLASS_GADGETDOWN
316 ie->ie_Class = IECLASS_GADGETUP;
317 break;
319 case IDCMP_GADGETDOWN:
320 ie->ie_Class = IECLASS_GADGETDOWN;
321 break;
323 case IDCMP_ACTIVEWINDOW:
324 ie->ie_Class = IECLASS_ACTIVEWINDOW;
325 break;
327 case IDCMP_INACTIVEWINDOW:
328 ie->ie_Class = IECLASS_INACTIVEWINDOW;
329 break;
331 case IDCMP_CLOSEWINDOW:
332 ie->ie_Class = IECLASS_CLOSEWINDOW;
333 break;
335 case IDCMP_MENUHELP:
336 ie->ie_Class = IECLASS_MENUHELP;
337 break;
339 case IDCMP_MENUPICK:
340 ie->ie_Class = IECLASS_MENULIST;
341 break;
343 case IDCMP_MOUSEBUTTONS:
344 case IDCMP_MOUSEMOVE:
345 case IDCMP_RAWKEY:
346 case IDCMP_VANILLAKEY:
347 break;
349 default:
350 D(bug("ih_fireintuimessage: unexpected IDCMP (%x) for an inputevent-handling-fireintuimessage!\n", Class));
351 break;
355 #endif
356 else //if (!ie)
358 /* ih_fire_intuimessage was called from inside Intuition's defered action handling routines */
360 if ((ie = AllocInputEvent(iihd)))
362 switch(Class)
364 case IDCMP_NEWSIZE:
365 ie->ie_Class = IECLASS_SIZEWINDOW;
366 break;
368 case IDCMP_CHANGEWINDOW:
369 ie->ie_Class = IECLASS_CHANGEWINDOW;
370 break;
372 case IDCMP_ACTIVEWINDOW:
373 ie->ie_Class = IECLASS_ACTIVEWINDOW;
374 break;
376 case IDCMP_INACTIVEWINDOW:
377 ie->ie_Class = IECLASS_INACTIVEWINDOW;
378 break;
380 case IDCMP_CLOSEWINDOW:
381 ie->ie_Class = IECLASS_CLOSEWINDOW;
382 break;
384 case IDCMP_GADGETUP:
385 ie->ie_Class = IECLASS_GADGETUP;
386 break;
388 case IDCMP_GADGETDOWN:
389 ie->ie_Class = IECLASS_GADGETDOWN;
390 break;
392 case IDCMP_REFRESHWINDOW:
393 ie->ie_Class = IECLASS_REFRESHWINDOW;
394 break;
396 case IDCMP_MENUHELP:
397 ie->ie_Class = IECLASS_MENUHELP;
398 break;
400 case IDCMP_MENUPICK:
401 ie->ie_Class = IECLASS_MENULIST;
402 break;
404 default:
405 D(bug("ih_fireintuimessage: unexpected IDCMP (0x%X) for a deferred-action-fireintuimessage!\n", Class));
406 break;
408 } /* switch(Class) */
410 ie->ie_Code = Code;
411 ie->ie_Qualifier = iihd->ActQualifier;
412 ie->ie_EventAddress = IAddress;
413 CurrentTime(&ie->ie_TimeStamp.tv_secs, &ie->ie_TimeStamp.tv_micro);
415 D(bug("ih_fireintuimessage: generated InputEvent. Class = 0x%X Code = %d EventAddress = 0x%X\n",
416 ie->ie_Class,
417 ie->ie_Code,
418 ie->ie_EventAddress));
420 } /* if ((ie = AllocInputEvent(iihd))) */
423 DEBUG_FIREINTUIMSG(dprintf("ih_fire_intuimessage: result 0x%lx\n",
424 result));
426 return result;
429 /*********************************************************************/
431 /* This function must never be called with the layer/layerinfo locked,
432 * otherwise a deadlock with ObtainGIRPort can happen.
434 IPTR Locked_DoMethodA (struct Window *w, struct Gadget *g, Msg message, struct IntuitionBase *IntuitionBase)
436 struct LayersBase *LayersBase = GetPrivIBase(IntuitionBase)->LayersBase;
437 IPTR rc;
438 BOOL lock = w && (g->GadgetType & GTYP_SYSGADGET &&
439 ((g->GadgetType & GTYP_SYSTYPEMASK) == GTYP_WDRAGGING ||
440 (g->GadgetType & GTYP_SYSTYPEMASK) == GTYP_SIZING));
442 if (lock)
444 LOCK_REFRESH(w->WScreen);
447 LOCKGADGET(IntuitionBase)
448 rc = Custom_DoMethodA(IntuitionBase, g, message);
449 UNLOCKGADGET(IntuitionBase)
451 if (lock)
453 UNLOCK_REFRESH(w->WScreen);
456 return rc;
459 /*********************************************************************/
461 IPTR Custom_DoMethodA (struct IntuitionBase *IntuitionBase, struct Gadget *g, Msg message)
463 if (g->MutualExclude)
465 return AROS_UFC4(IPTR, ((struct Hook *)g->MutualExclude)->h_Entry,
466 AROS_UFCA(struct Hook *, (struct Hook *)g->MutualExclude, A0),
467 AROS_UFCA(struct Gadget *, g, A2),
468 AROS_UFCA(APTR, message, A1),
469 AROS_UFCA(struct IntuitionBase *, IntuitionBase, A6));
471 else /* Not needed since gadgetclass sets MutualExclude, but doesn't hurt. */
472 return DoMethodA((Object *)g, message);
475 /****************************************************************************************/
477 void NotifyDepthArrangement(struct Window *w, struct IntuitionBase *IntuitionBase)
479 if(w->MoreFlags & WMFLG_NOTIFYDEPTH)
481 ih_fire_intuimessage(w,
482 IDCMP_CHANGEWINDOW,
483 CWCODE_DEPTH,
485 IntuitionBase);
490 /****************************************************************************************/
492 void PrepareGadgetInfo(struct GadgetInfo *gi, struct Screen *scr, struct Window *win,
493 struct Requester *req)
495 gi->gi_Screen = scr;
496 gi->gi_Window = win;
497 gi->gi_Requester = req;
498 gi->gi_RastPort = 0;
499 gi->gi_Pens.DetailPen = scr->DetailPen;
500 gi->gi_Pens.BlockPen = scr->BlockPen;
501 gi->gi_DrInfo = (APTR)&(((struct IntScreen *)gi->gi_Screen)->DInfo);
504 /****************************************************************************************/
506 void SetGadgetInfoGadget(struct GadgetInfo *gi, struct Gadget *gad,
507 struct IntuitionBase *IntuitionBase)
509 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
510 struct IIHData *iihd = (struct IIHData *)GetPrivIBase(IntuitionBase)->InputHandler->is_Data;
512 SET_GI_RPORT(gi, gi->gi_Window, gi->gi_Requester, gad);
513 InitRastPort(&iihd->GadgetInfoRastPort);
515 iihd->GadgetInfoRastPort.Layer = gi->gi_RastPort->Layer;
516 iihd->GadgetInfoRastPort.BitMap = gi->gi_RastPort->BitMap;
518 SetFont(&iihd->GadgetInfoRastPort, gi->gi_DrInfo->dri_Font);
520 gi->gi_Layer = gi->gi_RastPort->Layer;
521 gi->gi_RastPort = &iihd->GadgetInfoRastPort;
523 GetGadgetDomain(gad, gi->gi_Screen, gi->gi_Window, gi->gi_Requester, &gi->gi_Domain);
526 /****************************************************************************************/
528 void SetGPIMouseCoords(struct gpInput *gpi, struct Gadget *gad)
530 struct GadgetInfo *gi = gpi->gpi_GInfo;
532 WORD mousex, mousey;
534 if (IS_SCREEN_GADGET(gad) || !gi->gi_Window)
536 mousex = gi->gi_Screen->MouseX;
537 mousey = gi->gi_Screen->MouseY;
539 else
542 mousex = gi->gi_Window->MouseX;
543 mousey = gi->gi_Window->MouseY;
546 gpi->gpi_Mouse.X = mousex - gi->gi_Domain.Left - GetGadgetLeft(gad, gi->gi_Screen, gi->gi_Window, gi->gi_Requester);
547 gpi->gpi_Mouse.Y = mousey - gi->gi_Domain.Top - GetGadgetTop(gad, gi->gi_Screen, gi->gi_Window, gi->gi_Requester);
551 /****************************************************************************************/
553 void HandleSysGadgetVerify(struct GadgetInfo *gi, struct Gadget *gadget,
554 struct IntuitionBase *IntuitionBase)
556 struct LayersBase *LayersBase = GetPrivIBase(IntuitionBase)->LayersBase;
557 struct Screen *scr;
558 struct IIHData *iihd = (struct IIHData *)GetPrivIBase(IntuitionBase)->InputHandler->is_Data;
560 switch(gadget->GadgetType & GTYP_SYSTYPEMASK)
562 case GTYP_CLOSE:
563 #ifdef __MORPHOS__
564 if (((struct IntWindow *)(gi->gi_Window))->specialflags & SPFLAG_IAMDEAD)
566 CrashedDispose(gi->gi_Window,IntuitionBase);
568 else
570 #endif
571 ih_fire_intuimessage(gi->gi_Window,
572 IDCMP_CLOSEWINDOW,
574 gi->gi_Window,
575 IntuitionBase);
576 #ifdef __MORPHOS__
578 #endif
579 break;
581 case GTYP_WDEPTH:
582 if (!IsLayerHiddenBySibling(WLAYER(gi->gi_Window), FALSE)
583 || (iihd->ActQualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) != 0)
585 /* Send window to back */
586 WindowToBack(gi->gi_Window);
588 else
590 /* Send window to front */
591 WindowToFront(gi->gi_Window);
593 break;
595 case GTYP_WZOOM:
596 ZipWindow(gi->gi_Window);
597 break;
599 case GTYP_SDEPTH:
600 scr = FindFirstScreen(GetPrivIBase(IntuitionBase)->ActiveMonitor, IntuitionBase);
601 if (gi->gi_Screen == scr
602 || (iihd->ActQualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) != 0)
604 ScreenToBack(gi->gi_Screen);
606 else
608 ScreenToFront(gi->gi_Screen);
610 break;
612 } /* switch(gad->GadgetType & GTYP_SYSTYPEMASK) */
615 /****************************************************************************************/
617 struct Gadget *HandleCustomGadgetRetVal(IPTR retval, struct GadgetInfo *gi, struct Gadget *gadget,
618 ULONG termination, BOOL *reuse_event,
619 struct IntuitionBase *IntuitionBase)
621 struct IIHData *iihdata = (struct IIHData *)GetPrivIBase(IntuitionBase)->InputHandler->is_Data;
623 DEBUG_HANDLECUSTOMRETVAL(dprintf("HandleCustomGadgetRetVal: retval %ld gi 0x%lx gadget 0x%lx termination %ld reuse %ld\n",
624 retval,
626 gadget,
627 termination,
628 *reuse_event));
630 if (retval != GMR_MEACTIVE)
632 struct gpGoInactive gpgi;
634 DEBUG_HANDLECUSTOMRETVAL(dprintf("HandleCustomGadgetRetVal: !GMR_MEACTIVE\n"));
636 if (retval & GMR_REUSE)
638 DEBUG_HANDLECUSTOMRETVAL(dprintf("HandleCustomGadgetRetVal: GMR_REUSE\n"));
639 *reuse_event = TRUE;
642 if (retval & GMR_VERIFY)
644 DEBUG_HANDLECUSTOMRETVAL(dprintf("HandleCustomGadgetRetVal: GMR_VERIFY\n"));
645 if (IS_SYS_GADGET(gadget))
647 DEBUG_HANDLECUSTOMRETVAL(dprintf("HandleCustomGadgetRetVal: SysGad\n"));
648 HandleSysGadgetVerify(gi, gadget, IntuitionBase);
650 else
652 /* Not a system gadget. Send IDCMP_GADGETUP, but not
653 if it is a screen gadget where gi->gi_Window would
654 be NULL */
656 DEBUG_HANDLECUSTOMRETVAL(dprintf("HandleCustomGadgetRetVal: no sysgad\n"));
657 if ((gadget->Activation & GACT_RELVERIFY) &&
658 (gi->gi_Window))
660 DEBUG_HANDLECUSTOMRETVAL(dprintf("HandleCustomGadgetRetVal: Send IDCMP_GADGETUP\n"));
661 ih_fire_intuimessage(gi->gi_Window,
662 IDCMP_GADGETUP,
663 termination & 0x0000FFFF,
664 gadget,
665 IntuitionBase);
668 } /* switch(gad->GadgetType & GTYP_SYSTYPEMASK) */
670 } /* if (retval & GMR_VERIFY) */
672 DEBUG_HANDLECUSTOMRETVAL(dprintf("HandleCustomGadgetRetVal: Send GM_GOINACTIVE\n"));
674 gpgi.MethodID = GM_GOINACTIVE;
675 gpgi.gpgi_GInfo = gi;
676 gpgi.gpgi_Abort = 0;
678 Locked_DoMethodA(gi->gi_Window, gadget, (Msg)&gpgi, IntuitionBase);
680 if (SYSGADGET_ACTIVE)
682 /* Switch back from Master Drag or Size Gadget to
683 real/original/app Size or Drag Gadget */
685 DEBUG_HANDLECUSTOMRETVAL(dprintf("HandleCustomGadgetRetVal: SYSGADGET_ACTIVE\n"));
686 gadget = iihdata->ActiveSysGadget;
687 iihdata->ActiveSysGadget = NULL;
689 if (IS_BOOPSI_GADGET(gadget))
691 Locked_DoMethodA(gi->gi_Window, gadget, (Msg)&gpgi, IntuitionBase);
694 #ifdef __MORPHOS__
695 if ((gadget->GadgetType & GTYP_SYSTYPEMASK) == GTYP_WDRAGGING2)
697 ih_fire_intuimessage(gi->gi_Window,
698 IDCMP_GADGETUP,
700 gadget,
701 IntuitionBase);
703 #endif
705 retval = 0;
708 if (retval & GMR_VERIFY && gi->gi_Requester && gadget->Activation & GACT_ENDGADGET)
710 DEBUG_HANDLECUSTOMRETVAL(dprintf("HandleCustomGadgetRetVal: EndRequest\n"));
711 EndRequest(gi->gi_Requester, gi->gi_Window);
712 retval = 0;
715 gadget->Activation &= ~GACT_ACTIVEGADGET;
717 DEBUG_HANDLECUSTOMRETVAL(dprintf("HandleCustomGadgetRetVal: TabCycle 0x%lx retval 0x%lx\n",
718 (gadget->Flags & GFLG_TABCYCLE),
719 retval));
721 if ((gadget->Flags & GFLG_TABCYCLE) && (retval & GMR_NEXTACTIVE))
723 DEBUG_HANDLECUSTOMRETVAL(dprintf("HandleCustomGadgetRetVal: TabCycle+GMR_NEXTACTIVE\n"));
724 gadget = FindCycleGadget(gi->gi_Window, gi->gi_Requester, gadget, GMR_NEXTACTIVE);
726 else if ((gadget->Flags & GFLG_TABCYCLE) && (retval & GMR_PREVACTIVE))
728 DEBUG_HANDLECUSTOMRETVAL(dprintf("HandleCustomGadgetRetVal: TabCycle+GMR_PREVACTIVE\n"));
729 gadget = FindCycleGadget(gi->gi_Window, gi->gi_Requester, gadget, GMR_PREVACTIVE);
731 else
733 gadget = NULL;
734 DEBUG_HANDLECUSTOMRETVAL(dprintf("HandleCustomGadgetRetVal: No gadget\n"));
737 if (gadget)
739 DEBUG_HANDLECUSTOMRETVAL(dprintf("HandleCustomGadgetRetVal: activate gadget 0x%lx\n",gadget));
740 gadget = DoActivateGadget(gi->gi_Window, gi->gi_Requester, gadget, IntuitionBase);
743 } /* if (retval != GMR_MEACTIVE) */
744 else
746 DEBUG_HANDLECUSTOMRETVAL(dprintf("HandleCustomGadgetRetVal: set GACT_ACTIVEGADGET\n"));
747 gadget->Activation |= GACT_ACTIVEGADGET;
750 DEBUG_HANDLECUSTOMRETVAL(dprintf("HandleCustomGadgetRetVal: return 0x%x\n", gadget));
751 return gadget;
754 /****************************************************************************************/
756 /* This function must never be called with the layer/layerinfo locked,
757 * otherwise a deadlock with ObtainGIRPort can happen.
759 struct Gadget *DoGPInput(struct GadgetInfo *gi, struct Gadget *gadget,
760 struct InputEvent *ie, STACKULONG methodid,
761 BOOL *reuse_event, struct IntuitionBase *IntuitionBase)
763 struct IIHData *iihdata = (struct IIHData *)GetPrivIBase(IntuitionBase)->InputHandler->is_Data;
764 struct gpInput gpi;
765 IPTR retval;
766 ULONG termination;
767 ie->ie_Qualifier = iihdata->ActQualifier;
769 gpi.MethodID = methodid;
770 gpi.gpi_GInfo = gi;
771 gpi.gpi_IEvent = ie;
772 gpi.gpi_Termination = &termination;
773 gpi.gpi_TabletData = NULL;
775 SetGPIMouseCoords(&gpi, gadget);
777 retval = Locked_DoMethodA (gi->gi_Window, gadget, (Msg)&gpi, IntuitionBase);
779 DEBUG_DOGPINPUT(dprintf("DoGPInput: Locked_DoMethod gadget %p method 0x%lx retval %ld termination 0x%lx\n",
780 gadget, methodid, retval, termination));
782 return HandleCustomGadgetRetVal(retval, gi, gadget, termination,
783 reuse_event, IntuitionBase);
787 /****************************************************************************************/
789 struct Gadget * FindGadget (struct Screen *scr, struct Window * window,
790 struct Requester * req, int x, int y,
791 struct GadgetInfo * gi,BOOL sysonly,
792 struct IntuitionBase *IntuitionBase)
794 struct Gadget *gadget, *firstgadget, *draggadget = 0;
795 struct gpHitTest gpht;
796 struct IBox ibox;
797 WORD xrel, yrel;
798 BOOL sys_only = sysonly;
800 DEBUG_CLICK(bug("[Inputhandler] FindGadget(0x%p, 0x%p, 0x%p, %d, %d, %d)\n", scr, window, req, x, y, sysonly));
801 gpht.MethodID = GM_HITTEST;
802 gpht.gpht_GInfo = gi;
804 while (req || window || scr)
806 if (req)
808 firstgadget = req->ReqGadget;
810 else if (window)
812 firstgadget = window->FirstGadget;
814 else
816 if (draggadget) return draggadget;
817 firstgadget = scr->FirstGadget;
820 for (gadget = firstgadget; gadget; gadget = gadget->NextGadget)
822 if (!(gadget->Flags & GFLG_DISABLED) &&
823 (!sys_only ||
824 (gadget->GadgetType & GTYP_SYSGADGET &&
825 ((gadget->GadgetType & GTYP_SYSTYPEMASK) == GTYP_SIZING ||
826 (gadget->GadgetType & GTYP_SYSTYPEMASK) == GTYP_WDRAGGING ||
827 (gadget->GadgetType & GTYP_SYSTYPEMASK) == GTYP_WDEPTH ||
828 (gadget->GadgetType & GTYP_SYSTYPEMASK) == GTYP_SDEPTH ||
829 (gadget->GadgetType & GTYP_SYSTYPEMASK) == GTYP_WZOOM ||
830 (gadget->GadgetType & GTYP_SYSTYPEMASK) == GTYP_CLOSE))))
832 /* stegerg: domain depends on gadgettype and windowflags! */
833 GetGadgetDomain(gadget, scr, window, req, &gi->gi_Domain);
835 /* Get coords relative to window */
837 GetGadgetIBox(gadget, gi, &ibox);
839 xrel = x - gi->gi_Domain.Left;
840 yrel = y - gi->gi_Domain.Top;
842 /*if (req)
844 xrel -= req->LeftEdge + window->BorderLeft;
845 yrel -= req->TopEdge + window->BorderTop;
848 if (window)
850 xrel -= window->LeftEdge;
851 yrel -= window->TopEdge;
854 if ((xrel >= ibox.Left) &&
855 (yrel >= ibox.Top) &&
856 (xrel < ibox.Left + ibox.Width) &&
857 (yrel < ibox.Top + ibox.Height))
859 if ((gadget->GadgetType & GTYP_SYSTYPEMASK) == GTYP_WDRAGGING)
861 if (!draggadget) draggadget = gadget;
863 else
866 if ((gadget->GadgetType & GTYP_GTYPEMASK) == GTYP_CUSTOMGADGET)
869 gpht.gpht_Mouse.X = xrel - ibox.Left;
870 gpht.gpht_Mouse.Y = yrel - ibox.Top;
872 /* jDc: don't check for == GMR_GADGETHIT since some reaction classes*/
873 /* (BURN IN HELL!) return TRUE here (related to imageclass HITEST?)*/
874 if (Locked_DoMethodA (window, gadget, (Msg)&gpht, IntuitionBase))
875 return (gadget);
877 else
879 return (gadget);
884 } /* if (!(gadget->Flags & GFLG_DISABLED)) */
886 } /* for (gadget = window->FirstGadget; gadget; gadget = gadget->NextGadget) */
888 sys_only = sysonly;
890 if (req)
892 req = NULL;
893 sys_only = TRUE;
895 else if (window)
897 #ifdef SKINS
898 draggadget = findbordergadget(window,draggadget,IntuitionBase);
899 #endif
900 window = NULL;
902 else
903 scr = NULL;
906 return (draggadget);
908 } /* FindGadget */
911 /****************************************************************************************/
913 struct Gadget * FindHelpGadget (struct Window * window,
914 int x, int y, struct IntuitionBase *IntuitionBase)
916 struct Gadget *gadget, *firstgadget;
917 struct Requester *req = window->FirstRequest;
919 while (req || window)
921 if (req)
923 firstgadget = req->ReqGadget;
925 else
927 firstgadget = window->FirstGadget;
930 for (gadget = firstgadget; gadget; gadget = gadget->NextGadget)
932 if ((gadget->Flags & GFLG_EXTENDED) &&
933 (((struct ExtGadget *)gadget)->MoreFlags & GMORE_GADGETHELP))
935 if (InsideGadget(window->WScreen, window, req, gadget, x, y))
937 return (gadget);
943 if (req)
944 req = req->OlderRequest;
945 else
946 window = NULL;
949 return (NULL);
951 } /* FindHelpGadget */
954 /****************************************************************************************/
956 BOOL InsideGadget(struct Screen *scr, struct Window *win, struct Requester *req,
957 struct Gadget *gad, WORD x, WORD y)
959 struct IBox box;
960 BOOL rc = FALSE;
962 GetScrGadgetIBox(gad, scr, win, req, &box);
964 if ((x >= box.Left) &&
965 (y >= box.Top) &&
966 (x < box.Left + box.Width) &&
967 (y < box.Top + box.Height))
969 rc = TRUE;
972 return rc;
975 /****************************************************************************************/
977 struct Gadget *DoActivateGadget(struct Window *win, struct Requester *req, struct Gadget *gad,
978 struct IntuitionBase *IntuitionBase)
980 struct IIHData *iihd = (struct IIHData *)GetPrivIBase(IntuitionBase)->InputHandler->is_Data;
981 struct GadgetInfo *gi = &iihd->GadgetInfo;
982 struct Gadget *result = NULL;
984 DEBUG_ACTIVATEGADGET(dprintf("DoActivateGadget: Window 0x%lx Req 0x%lx Gadget 0x%lx\n",
985 win,
986 req,
987 gad));
989 DEBUG_ACTIVATEGADGET(dprintf("DoActivateGadget: Activation 0x%lx\n",
990 gad->Activation));
992 if (gad->Activation & GACT_IMMEDIATE)
994 DEBUG_ACTIVATEGADGET(dprintf("DoActivateGadget: Send GADGETDOWN msg\n"));
995 ih_fire_intuimessage(win,
996 IDCMP_GADGETDOWN,
998 gad,
999 IntuitionBase);
1002 PrepareGadgetInfo(gi, win->WScreen, win, req);
1003 SetGadgetInfoGadget(gi, gad, IntuitionBase);
1005 DEBUG_ACTIVATEGADGET(dprintf("DoActivateGadget: Type 0x%lx\n",
1006 gad->GadgetType & GTYP_GTYPEMASK));
1008 switch(gad->GadgetType & GTYP_GTYPEMASK)
1010 case GTYP_STRGADGET:
1012 struct StringInfo *si = (struct StringInfo *)gad->SpecialInfo;
1014 DEBUG_ACTIVATEGADGET(dprintf("DoActivateGadget: GTYP_STRGADGET\n"));
1016 gad->Flags |= GFLG_SELECTED;
1017 if (si && si->UndoBuffer)
1019 strcpy(si->UndoBuffer, si->Buffer);
1022 gad->Activation |= GACT_ACTIVEGADGET;
1023 UpdateStrGadget(gad, win, req, IntuitionBase);
1024 result = gad;
1025 break;
1028 case GTYP_CUSTOMGADGET:
1030 struct gpInput gpi;
1031 ULONG termination;
1032 IPTR retval;
1033 BOOL reuse_event;
1035 DEBUG_ACTIVATEGADGET(dprintf("DoActivateGadget: GTYP_CUSTOMGADGET\n"));
1037 gpi.MethodID = GM_GOACTIVE;
1038 gpi.gpi_GInfo = gi;
1039 gpi.gpi_IEvent = NULL;
1040 gpi.gpi_Termination = &termination;
1041 gpi.gpi_Mouse.X = win->MouseX - gi->gi_Domain.Left - GetGadgetLeft(gad, gi->gi_Screen, gi->gi_Window, NULL);
1042 gpi.gpi_Mouse.Y = win->MouseY - gi->gi_Domain.Top - GetGadgetTop(gad, gi->gi_Screen, gi->gi_Window, NULL);
1043 gpi.gpi_TabletData = NULL;
1045 retval = Locked_DoMethodA (win, gad, (Msg)&gpi, IntuitionBase);
1047 gad = HandleCustomGadgetRetVal(retval, gi, gad,termination,
1048 &reuse_event, IntuitionBase);
1050 if (gad)
1052 gad->Activation |= GACT_ACTIVEGADGET;
1053 result = gad;
1055 break;
1058 } /* switch(gad->GadgetType & GTYP_GTYPEMASK) */
1060 DEBUG_ACTIVATEGADGET(dprintf("DoActivateGadget: result 0x%lx\n",
1061 result));
1063 if (result) iihd->ActiveGadget = result;
1065 return result;
1069 /****************************************************************************************/
1071 struct Gadget *FindCycleGadget(struct Window *win, struct Requester *req,
1072 struct Gadget *gad, WORD direction)
1074 struct Gadget *g = NULL, *gg, *prev, *first;
1076 D(bug("FindCycleGadget: win = %p req %p gad = %p direction = %d\n", win, req, gad, direction));
1078 if (req)
1079 first = req->ReqGadget;
1080 else
1081 first = win->FirstGadget;
1083 switch(direction)
1085 case GMR_NEXTACTIVE:
1086 g = gad->NextGadget;
1087 if (!g) g = first;
1089 while(g)
1091 if (g == gad)
1093 if (!(gad->Flags & GFLG_TABCYCLE) || (gad->Flags & GFLG_DISABLED))
1095 /* should never happen */
1096 g = NULL;
1098 break;
1100 if (!(g->Flags & GFLG_DISABLED) && (g->Flags & GFLG_TABCYCLE)) break;
1102 g = g->NextGadget;
1103 if (!g) g = first;
1105 break;
1107 case GMR_PREVACTIVE:
1108 prev = 0;
1109 g = 0;
1110 gg = first;
1112 /* find a TABCYCLE gadget which is before gad in window's gadgetlist */
1113 while (gg)
1115 if (gg == gad)
1117 if (prev) g = prev;
1118 break;
1120 if (!(gg->Flags & GFLG_DISABLED) && (gg->Flags & GFLG_TABCYCLE)) prev = gg;
1121 gg = gg->NextGadget;
1124 if (gg && !g)
1126 /* There was no TABCYCLE gadget before gad in window's gadgetlist */
1128 gg = gg->NextGadget;
1129 if (!gg)
1131 if (!(gad->Flags & GFLG_DISABLED) && (gad->Flags & GFLG_TABCYCLE)) g = gad;
1132 break;
1134 prev = 0;
1136 while(gg)
1138 if (!(gg->Flags & GFLG_DISABLED) && (gg->Flags & GFLG_TABCYCLE)) prev = gg;
1139 gg = gg->NextGadget;
1142 if (prev)
1144 g = prev;
1146 else
1148 if (!(gad->Flags & GFLG_DISABLED) && (gad->Flags & GFLG_TABCYCLE)) g = gad;
1153 break;
1155 default: /* Unused, but well... */
1156 g = first;
1157 break;
1159 } /* switch(direction) */
1161 return g;
1164 /****************************************************************************************/
1166 void FixWindowCoords(struct Window *win, LONG *left, LONG *top, LONG *width, LONG *height,struct IntuitionBase *IntuitionBase)
1168 struct Screen *scr = win->WScreen;
1170 if (*width < 1) *width = 1;
1171 if (*height < 1) *height = 1;
1173 if (*width > scr->Width) *width = scr->Width;
1174 if (*height > scr->Height) *height = scr->Height;
1176 if ((GetPrivIBase(IntuitionBase)->IControlPrefs.ic_Flags & ICF_OFFSCREENLAYERS) && (win->WScreen->LayerInfo.Flags & LIFLG_SUPPORTS_OFFSCREEN_LAYERS))
1178 if (*left > scr->Width - 1) *left = scr->Width - 1;
1179 if (*top > scr->Height - 1) *top = scr->Height -1;
1181 else
1184 if ((*left + *width) > scr->Width)
1186 *left = scr->Width - *width;
1188 else if (*left < 0)
1190 *left = 0;
1193 if ((*top + *height) > scr->Height)
1195 *top = scr->Height - *height;
1197 else if (*top < 0)
1199 *top = 0;
1204 /****************************************************************************************/
1206 void WindowNeedsRefresh(struct Window * w,
1207 struct IntuitionBase * IntuitionBase )
1209 /* Supposed to send a message to this window, saying that it needs a
1210 refresh. I will check whether there is no such a message queued in
1211 its messageport, though. It only needs one such message!
1214 /* Refresh the window's gadgetry ...
1215 ... stegerg: and in the actual implementation
1216 call RefreshWindowFrame first, as the border gadgets don't
1217 cover the whole border area.*/
1220 jDc: in actual implementation sizeevent means that we need to send
1221 idcmp, etc and do not clear the flag for smart_refresh window that
1222 has no idcmp_refreshwindow, otherwise we clear the flag!
1225 DEBUG_WINDOWNEEDSREFRESH(dprintf("WindowNeedsRefresh: window 0x%lx gzz %d nocarerefresh %d\n",
1226 w, IS_GZZWINDOW(w), IS_NOCAREREFRESH(w)));
1228 //trashregion means that we use delayed refreshing!
1230 if (
1231 #ifdef DAMAGECACHE
1232 (!IW(w)->trashregion) ||
1233 #else
1234 (!(w->Flags & WFLG_SIMPLE_REFRESH)) ||
1235 #endif
1236 IS_NOCAREREFRESH(w))
1239 Gad_BeginUpdate(WLAYER(w), IntuitionBase);
1241 if (IS_NOCAREREFRESH(w) || (!((!(w->Flags & WFLG_SIMPLE_REFRESH)) && (!(IW(w)->specialflags & SPFLAG_LAYERRESIZED)))))
1243 if (!IS_GZZWINDOW(w))
1245 if (w->Flags & WFLG_BORDERLESS)
1247 int_refreshglist(w->FirstGadget, w, NULL, -1, 0, 0, IntuitionBase);
1249 else
1251 int_refreshwindowframe(w,0,0,IntuitionBase);
1254 else
1256 /* refresh all gadgets except border gadgets */
1257 int_refreshglist(w->FirstGadget, w, NULL, -1, 0, REFRESHGAD_BORDER, IntuitionBase);
1259 IW(w)->specialflags &= ~SPFLAG_LAYERRESIZED;
1262 if (IS_NOCAREREFRESH(w)) WLAYER(w)->Flags &= ~LAYERREFRESH;
1264 Gad_EndUpdate(WLAYER(w), IS_NOCAREREFRESH(w) ? TRUE : FALSE, IntuitionBase);
1266 } else {
1267 #ifdef DAMAGECACHE
1268 struct Rectangle rect;
1269 BOOL doclear = (w->Flags & WFLG_BORDERLESS) ? FALSE : TRUE;
1271 rect.MinX = w->BorderLeft;
1272 rect.MinY = w->BorderTop;
1273 rect.MaxX = w->Width - w->BorderRight - 1;
1274 rect.MaxY = w->Height - w->BorderBottom - 1;
1275 #endif
1277 #ifndef BEGINUPDATEGADGETREFRESH
1278 Gad_BeginUpdate(WLAYER(w), IntuitionBase);
1279 #else
1280 #ifdef DAMAGECACHE
1281 LockLayer(0,WLAYER(w));
1282 #endif
1283 #endif
1285 #ifndef BEGINUPDATEGADGETREFRESH
1286 if (!IS_GZZWINDOW(w))
1288 if (w->Flags & WFLG_BORDERLESS)
1290 int_refreshglist(w->FirstGadget, w, NULL, -1, 0, 0, IntuitionBase);
1292 else
1294 int_refreshwindowframe(w,0,0,IntuitionBase);
1297 else
1299 /* refresh all gadgets except border and gadtools gadgets */
1300 int_refreshglist(w->FirstGadget, w, NULL, -1, 0, REFRESHGAD_BORDER , IntuitionBase);
1302 #endif
1304 #ifdef DAMAGECACHE
1305 //add rects to trashregion here
1306 OrRegionRegion(WLAYER(w)->DamageList,IW(w)->trashregion);
1308 if (doclear)
1310 ClearRectRegion(IW(w)->trashregion,&rect);
1311 AndRectRegion(WLAYER(w)->DamageList,&rect);
1314 IW(w)->specialflags |= SPFLAG_LAYERREFRESH;
1315 #else
1316 #ifdef BEGINUPDATEGADGETREFRESH
1317 IW(w)->specialflags |= SPFLAG_LAYERREFRESH;
1318 #endif
1319 #endif
1321 #ifndef BEGINUPDATEGADGETREFRESH
1322 Gad_EndUpdate(WLAYER(w), FALSE, IntuitionBase);
1323 #else
1324 #ifdef DAMAGECACHE
1325 UnlockLayer(WLAYER(w));
1326 #endif
1327 #endif
1331 if (IS_DOCAREREFRESH(w))
1333 if (w->UserPort && (w->IDCMPFlags & IDCMP_REFRESHWINDOW))
1335 struct IntuiMessage *IM;
1336 BOOL found = FALSE;
1337 #if defined(__AROSEXEC_SMP__)
1338 struct ExecLockBase *ExecLockBase = GetPrivIBase(IntuitionBase)->ExecLockBase;
1339 #endif
1340 /* Can use Forbid() for this */
1341 Forbid();
1342 #if defined(__AROSEXEC_SMP__)
1343 if (ExecLockBase) ObtainLock(&w->UserPort->mp_SpinLock, SPINLOCK_MODE_READ, 0);
1344 #endif
1345 IM = (struct IntuiMessage *)w->UserPort->mp_MsgList.lh_Head;
1347 ForeachNode(&w->UserPort->mp_MsgList, IM)
1349 /* Does the window already have such a message? */
1350 if (IDCMP_REFRESHWINDOW == IM->Class && IM->IAddress == w)
1352 DEBUG_WINDOWNEEDSREFRESH(dprintf("WindowNeedsRefresh: refresh pending\n"));
1353 D(bug("Window %s already has a refresh message pending!!\n",
1354 w->Title ? w->Title : (STRPTR)"<NONAME>"));
1355 found = TRUE;
1356 break;
1359 #if defined(__AROSEXEC_SMP__)
1360 if (ExecLockBase) ReleaseLock(&w->UserPort->mp_SpinLock, 0);
1361 #endif
1362 Permit();
1364 if (!found)
1366 struct InputEvent *new_ie;
1367 struct IIHData *iihdata = (struct IIHData *)GetPrivIBase(IntuitionBase)->InputHandler->is_Data;
1369 D(bug("Sending a refresh message to window %s %d %d %d %d!!\n",
1370 w->Title ? w->Title : (STRPTR)"<NONAME>",
1371 w->LeftEdge,
1372 w->TopEdge,
1373 w->Width,
1374 w->Height));
1376 DEBUG_WINDOWNEEDSREFRESH(dprintf("WindowNeedsRefresh: sending idcmp message\n"));
1378 if ((new_ie = AllocInputEvent(iihdata)))
1380 new_ie->ie_Class = IECLASS_EVENT;
1381 new_ie->ie_Code = IECODE_REFRESH;
1382 new_ie->ie_EventAddress = w;
1383 CurrentTime(&new_ie->ie_TimeStamp.tv_secs, &new_ie->ie_TimeStamp.tv_micro);
1386 fire_intuimessage(w,
1387 IDCMP_REFRESHWINDOW,
1390 IntuitionBase);
1391 } /* if (!found) */
1393 } /* if (w->UserPort && (w->IDCMPFlags & IDCMP_REFRESHWINDOW)) */
1394 else
1396 struct IIHData *iihdata = (struct IIHData *)GetPrivIBase(IntuitionBase)->InputHandler->is_Data;
1398 if (FindTask(NULL) == iihdata->InputDeviceTask)
1400 struct InputEvent *new_ie;
1402 D(bug("Sending a refresh message to window %s %d %d %d %d!!\n",
1403 w->Title ? w->Title : (STRPTR)"<NONAME>",
1404 w->LeftEdge,
1405 w->TopEdge,
1406 w->Width,
1407 w->Height));
1408 DEBUG_WINDOWNEEDSREFRESH(dprintf("WindowNeedsRefresh: sending inputevent\n"));
1410 if ((new_ie = AllocInputEvent(iihdata)))
1412 new_ie->ie_Class = IECLASS_EVENT;
1413 new_ie->ie_Code = IECODE_REFRESH;
1414 new_ie->ie_EventAddress = w;
1415 CurrentTime(&new_ie->ie_TimeStamp.tv_secs, &new_ie->ie_TimeStamp.tv_micro);
1418 ih_fire_intuimessage(w,
1419 IDCMP_REFRESHWINDOW,
1422 IntuitionBase);
1426 } /* if (!IS_NOCAREREFRESH(w)) */
1430 /****************************************************************************************/
1432 struct Screen *FindHighestScreen(struct IntuitionBase *IntuitionBase)
1434 struct Screen *scr, *highest = IntuitionBase->FirstScreen;
1436 for (scr = highest; scr; scr = scr->NextScreen) {
1437 /* We only check screens that are on this monitor */
1438 if (GetPrivScreen(scr)->IMonitorNode
1439 != GetPrivIBase(IntuitionBase)->ActiveMonitor)
1440 continue;
1442 /* Check if top of screen is highest so far */
1443 if (scr->TopEdge < highest->TopEdge)
1444 highest = scr;
1446 return highest;
1449 /****************************************************************************************/
1451 struct Screen *FindActiveScreen(struct IntuitionBase *IntuitionBase)
1453 struct Screen *scr;
1454 WORD MinX, MinY, MaxX, MaxY;
1455 ULONG compflags;
1457 for (scr = IntuitionBase->FirstScreen; scr; scr = scr->NextScreen) {
1458 /* We check only screens which are on this monitor */
1459 if (GetPrivScreen(scr)->IMonitorNode != GetPrivIBase(IntuitionBase)->ActiveMonitor)
1460 continue;
1462 compflags = GetPrivScreen(scr)->SpecialFlags >> 8;
1464 /* adjust screen bounds if compositing */
1465 if (compflags & COMPF_ABOVE)
1466 MinY = 0;
1467 else
1468 MinY = -(scr->TopEdge);
1470 if (compflags & COMPF_BELOW)
1471 MaxY = scr->Height;
1472 else
1473 MaxY = scr->MouseY + 1;
1475 if (compflags & COMPF_LEFT)
1476 MinX = 0;
1477 else
1478 MinX = -(scr->LeftEdge);
1480 if (compflags & COMPF_RIGHT)
1481 MaxX = scr->Width;
1482 else
1483 MaxX = scr->MouseX + 1;
1485 D(bug("[Intuition] Bounds %d,%d->%d,%d\n", MinX, MinY, MaxX, MaxY));
1486 /* If the mouse is inside screen's bounds, we found it */
1487 if ((scr->MouseX >= MinX) && (scr->MouseY >= MinY) &&
1488 ((scr->MouseX < MaxX) && scr->MouseY < MaxY))
1489 break;
1491 return scr;
1494 /****************************************************************************************/
1496 struct Window *FindActiveWindow(struct InputEvent *ie, struct Screen *scr, ULONG *stitlebarhit,
1497 struct IntuitionBase *IntuitionBase)
1499 /* The caller has checked that the input event is a IECLASS_RAWMOUSE, SELECTDOWN event */
1500 /* NOTE: may be called with NULL ie ptr! */
1501 struct LayersBase *LayersBase = GetPrivIBase(IntuitionBase)->LayersBase;
1502 struct Layer *l;
1503 struct Window *new_w;
1504 ULONG lock;
1506 lock = LockIBase(0UL);
1508 new_w = IntuitionBase->ActiveWindow;
1510 UnlockIBase(lock);
1512 D(bug("FindActiveWindow: scr %p win %p\n",scr,new_w));
1514 if (stitlebarhit) *stitlebarhit = FALSE;
1516 if (scr)
1518 D(bug("FindActiveWindow: Click at (%d,%d)\n",scr->MouseX,scr->MouseY));
1520 /* What layer ? */
1521 LockLayerInfo(&scr->LayerInfo);
1523 l = WhichLayer(&scr->LayerInfo, scr->MouseX, scr->MouseY);
1525 UnlockLayerInfo(&scr->LayerInfo);
1527 if (NULL == l)
1529 new_w = NULL;
1530 D(bug("FindActiveWindow: Click not inside layer\n"));
1532 else if (l == scr->BarLayer)
1534 D(bug("FindActiveWindow: Click on screen bar layer -> active window stays the same\n"));
1535 if (stitlebarhit) *stitlebarhit = TRUE;
1537 else
1539 new_w = (struct Window *)l->Window;
1540 if (!new_w)
1542 D(bug("FindActiveWindow: Selected layer is not a window\n"));
1545 D(bug("FindActiveWindow: Found layer %p\n", l));
1549 D(bug("FindActiveWindow: New window %p\n", new_w));
1550 return new_w;
1553 /****************************************************************************************/
1555 struct Window *FindDesktopWindow(struct Screen *screen,struct IntuitionBase *IntuitionBase)
1557 struct Window *win;
1559 for (win = screen->FirstWindow; win; win = win->NextWindow)
1561 if (win->Flags & WFLG_BACKDROP &&
1562 win->Width == screen->Width &&
1563 win->Height >= screen->Height - (screen->BarHeight + 2))
1565 return win;
1569 return NULL;
1573 /****************************************************************************************/
1575 struct InputEvent *AllocInputEvent(struct IIHData *iihdata)
1577 struct GeneratedInputEvent *gie;
1578 struct InputEvent *ie;
1580 /* There might be an inputevent from someone else that our handler discarded.
1581 * We may as well use it. This can only happen inside our main loop.
1583 ie = iihdata->FreeInputEvents;
1584 if (ie)
1586 iihdata->FreeInputEvents = ie->ie_NextEvent;
1587 DEBUG_INPUTEVENT(dprintf("AllocInputEvent: reuse 0x%lx event\n", ie));
1589 else
1591 gie = AllocPooled(iihdata->InputEventMemPool, sizeof(struct GeneratedInputEvent));
1592 if (gie)
1594 /* Allocated events are put in the list of events that have not yet been
1595 * propagated.
1597 AddTail((struct List *)&iihdata->NewAllocatedInputEventList, (struct Node *)gie);
1598 ie = &gie->ie;
1600 DEBUG_INPUTEVENT(dprintf("AllocInputEvent: allocated 0x%lx (0x%lx)\n", ie, gie));
1603 if (ie)
1605 *iihdata->EndInputEventChain = ie;
1606 iihdata->EndInputEventChain = &ie->ie_NextEvent;
1609 return ie;
1612 /****************************************************************************************/
1614 void FreeGeneratedInputEvents(struct IIHData *iihdata)
1616 struct Node *node, *succ;
1618 /* Free the list of allocated events that have already been propagated. */
1619 ForeachNodeSafe(&iihdata->AllocatedInputEventList, node, succ)
1621 DEBUG_INPUTEVENT(dprintf("FreeGeneratedInputEvent: free 0x%lx\n", node));
1622 FreePooled(iihdata->InputEventMemPool, node, sizeof(struct GeneratedInputEvent));
1625 /* The list is not in a valid state at this point, and NewList() should
1626 * be called, but since we won't use it until the list of not-yet-propagated
1627 * events is copied in it, we won't bother.
1629 //NEWLIST(&iihdata->AllocatedInputEventList);
1632 /****************************************************************************************/
1634 BOOL FireMenuMessage(WORD code, struct Window *win,
1635 struct InputEvent *ie, struct IntuitionBase *IntuitionBase)
1637 struct MenuMessage *msg;
1638 BOOL result = FALSE;
1640 if ((msg = AllocMenuMessage(IntuitionBase)))
1642 msg->code = code;
1643 msg->win = win;
1644 if (ie) msg->ie = *ie;
1645 SendMenuMessage(msg, IntuitionBase);
1647 result = TRUE;
1650 return result;
1653 /****************************************************************************************/
1655 LONG Gad_BeginUpdate(struct Layer *layer, struct IntuitionBase *IntuitionBase)
1657 struct LayersBase *LayersBase = GetPrivIBase(IntuitionBase)->LayersBase;
1659 /* Must lock GadgetLock to avoid deadlocks with ObtainGirPort
1660 from other tasks, because ObtainGirPort first obtains
1661 GadgetLock and then layer lock through LockLayer!!!! */
1662 LOCKGADGET(IntuitionBase)
1663 return BeginUpdate(layer);
1666 /****************************************************************************************/
1668 void Gad_EndUpdate(struct Layer *layer, UWORD flag, struct IntuitionBase *IntuitionBase)
1670 struct LayersBase *LayersBase = GetPrivIBase(IntuitionBase)->LayersBase;
1672 EndUpdate(layer, flag);
1673 UNLOCKGADGET(IntuitionBase)
1676 /****************************************************************************************/