2 Copyright 1995-2005, The AROS Development Team. All rights reserved.
3 Copyright 2001-2003, The MorphOS Development Team. All Rights Reserved.
6 Support functions for InputHandler.
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>
30 #include "inputhandler.h"
32 #include "boopsigadgets.h"
33 #include "boolgadgets.h"
34 #include "propgadgets.h"
35 #include "strgadgets.h"
37 #include "intuition_intern.h" /* EWFLG_xxx */
38 #include "inputhandler_actions.h"
39 #include "inputhandler_support.h"
48 #include <aros/debug.h>
50 #define DEBUG_WINDOWNEEDSREFRESH(x) ;
51 #define DEBUG_DOGPINPUT(x) ;
52 #define DEBUG_HANDLECUSTOMRETVAL(x) ;
53 #define DEBUG_ACTIVATEGADGET(x) ;
54 #define DEBUG_FIREINTUIMSG(x) ;
58 /****************************************************************************************/
61 All screens and windows will be updated with the current position of
62 the mouse pointer. The windows will receive relative mouse coordinates.
65 /****************************************************************************************/
67 void notify_mousemove_screensandwindows(WORD x
,
69 struct IntuitionBase
* IntuitionBase
)
71 LONG lock
= LockIBase(0);
72 struct Screen
*scr
= IntuitionBase
->FirstScreen
;
76 struct Window
* win
= scr
->FirstWindow
;
78 scr
->MouseX
= x
;// - scr->LeftEdge;
79 scr
->MouseY
= y
;// - scr->TopEdge;
82 ** Visit all windows of this screen
87 UpdateMouseCoords(win
);
89 win
= win
-> NextWindow
;
92 scr
= scr
->NextScreen
;
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
);
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
;
135 imsg
->MouseX
= w
->MouseX
;
136 imsg
->MouseY
= w
->MouseY
;
139 CurrentTime(&imsg
->Seconds
, &imsg
->Micros
);
145 /****************************************************************************************/
147 BOOL
fire_intuimessage(struct Window
*w
,
151 struct IntuitionBase
*IntuitionBase
)
153 struct IntuiMessage
*imsg
;
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
;
164 imsg
->Qualifier
= iihd
->ActQualifier
;
165 if (Class
== IDCMP_RAWKEY
)
167 INT_INTUIMESSAGE(imsg
)->prevCodeQuals
= IAddress
;
168 imsg
->IAddress
= &INT_INTUIMESSAGE(imsg
)->prevCodeQuals
;
172 imsg
->IAddress
= IAddress
;
175 send_intuimessage(imsg
, w
, IntuitionBase
);
181 DEBUG_FIREINTUIMSG(dprintf("fire_intuimessage: can't alloc imsg\n"));
186 DEBUG_FIREINTUIMSG(dprintf("fire_intuimessage: no Userport or masked out idcmpflags\n"));
192 BOOL
fire_message(struct Window
*w
,ULONG Class
, UWORD Code
, APTR IAddress
, struct IntuitionBase
*IntuitionBase
)
194 struct ExtIntuiMessage
*imsg
;
197 if ((w
->IDCMPFlags
& Class
) && (w
->UserPort
))
199 if ((imsg
= (struct ExtIntuiMessage
*)alloc_intuimessage(w
, IntuitionBase
)))
201 struct IIHData
*iihdata
= (struct IIHData
*)GetPrivIBase(IntuitionBase
)->InputHandler
->is_Data
;
203 imsg
->eim_IntuiMessage
.Class
= Class
;
204 imsg
->eim_IntuiMessage
.Code
= Code
;
205 imsg
->eim_IntuiMessage
.Qualifier
= iihdata
->ActQualifier
;
206 if (Class
== IDCMP_RAWKEY
)
208 INT_INTUIMESSAGE(imsg
)->prevCodeQuals
= IAddress
;
209 imsg
->eim_IntuiMessage
.IAddress
= &INT_INTUIMESSAGE(imsg
)->prevCodeQuals
;
213 imsg
->eim_IntuiMessage
.IAddress
= IAddress
;
216 if (iihdata
->ActEventTablet
&& (w
->MoreFlags
& WMFLG_TABLETMESSAGES
))
218 if ((imsg
->eim_TabletData
= AllocPooled(GetPrivIBase(IntuitionBase
)->IDCMPPool
,sizeof (struct TabletData
))))
220 memclr(imsg
->eim_TabletData
,sizeof (struct TabletData
));
221 imsg
->eim_TabletData
->td_XFraction
= iihdata
->ActEventTablet
->ient_ScaledXFraction
;
222 imsg
->eim_TabletData
->td_YFraction
= iihdata
->ActEventTablet
->ient_ScaledYFraction
;
223 imsg
->eim_TabletData
->td_TabletX
= iihdata
->ActEventTablet
->ient_TabletX
;
224 imsg
->eim_TabletData
->td_TabletY
= iihdata
->ActEventTablet
->ient_TabletY
;
225 imsg
->eim_TabletData
->td_RangeX
= iihdata
->ActEventTablet
->ient_RangeX
;
226 imsg
->eim_TabletData
->td_RangeY
= iihdata
->ActEventTablet
->ient_RangeY
;
227 imsg
->eim_TabletData
->td_TagList
= CloneTagItems(iihdata
->ActEventTablet
->ient_TagList
);
231 send_intuimessage(imsg
, w
, IntuitionBase
);
237 DEBUG_FIREINTUIMSG(dprintf("fire_intuimessage: can't alloc imsg\n"));
242 DEBUG_FIREINTUIMSG(dprintf("fire_intuimessage: no Userport or masked out idcmpflags\n"));
248 /****************************************************************************************/
251 use ih_fire_intuimessage if A) the inputevent because of which
252 you call this function might have to be eaten or modified
253 by Intuition or B) an inputevent might have to be created
254 by Intuition because of a deferred action.
256 In any case this function may be called only from inside Intuition's
260 /****************************************************************************************/
262 BOOL
ih_fire_intuimessage(struct Window
* w
,
266 struct IntuitionBase
*IntuitionBase
)
268 struct IIHData
*iihd
= (struct IIHData
*)GetPrivIBase(IntuitionBase
)->InputHandler
->is_Data
;
269 struct InputEvent
*ie
/* = iihd->ActInputEvent*/;
273 DEBUG_FIREINTUIMSG(dprintf("ih_fire_intuimessage: win 0x%lx class 0x%lx code 0x%lx IAddress 0x%lx\n",
279 result
= fire_message(w
, Class
, Code
, IAddress
, IntuitionBase
);
281 DEBUG_FIREINTUIMSG(dprintf("ih_fire_intuimessage: fire_intuimessage result 0x%lx\n",
284 if (result
/*&& ie*/)
286 /* was sent as IDCMP to window so eat inputevent */
288 //ie->ie_Class = IECLASS_NULL;
293 else if (ie
/* && (ie->ie_Class != IECLASS_NULL) && !iihd->ActInputEventUsed*/)
296 /* ih_fire_intuimessage was called from inside Intuition's event handling loop */
298 //iihd->ActInputEventUsed = TRUE;
302 //ie->ie_Qualifier = iihd->ActQualifier;
303 ie
->ie_EventAddress
= IAddress
;
308 /* Note: on the Amiga if a boopsi Gadget which is GA_Immediate
309 and GA_RelVerify immediately in GM_GOACTIVE returns GMR_VERIFY,
310 then this sends IDCMP_GADGETDOWN + IDCMP_GADGETUP. AROS does
311 the same. But for changed inputevents (if window does not have this
312 IDCMP Flags set) there will be only one IECLASS_GADGETDOWN
315 ie
->ie_Class
= IECLASS_GADGETUP
;
318 case IDCMP_GADGETDOWN
:
319 ie
->ie_Class
= IECLASS_GADGETDOWN
;
322 case IDCMP_ACTIVEWINDOW
:
323 ie
->ie_Class
= IECLASS_ACTIVEWINDOW
;
326 case IDCMP_INACTIVEWINDOW
:
327 ie
->ie_Class
= IECLASS_INACTIVEWINDOW
;
330 case IDCMP_CLOSEWINDOW
:
331 ie
->ie_Class
= IECLASS_CLOSEWINDOW
;
335 ie
->ie_Class
= IECLASS_MENUHELP
;
339 ie
->ie_Class
= IECLASS_MENULIST
;
342 case IDCMP_MOUSEBUTTONS
:
343 case IDCMP_MOUSEMOVE
:
345 case IDCMP_VANILLAKEY
:
349 D(bug("ih_fireintuimessage: unexpected IDCMP (%x) for an inputevent-handling-fireintuimessage!\n", Class
));
357 /* ih_fire_intuimessage was called from inside Intuition's defered action handling routines */
359 if ((ie
= AllocInputEvent(iihd
)))
364 ie
->ie_Class
= IECLASS_SIZEWINDOW
;
367 case IDCMP_CHANGEWINDOW
:
368 ie
->ie_Class
= IECLASS_CHANGEWINDOW
;
371 case IDCMP_ACTIVEWINDOW
:
372 ie
->ie_Class
= IECLASS_ACTIVEWINDOW
;
375 case IDCMP_INACTIVEWINDOW
:
376 ie
->ie_Class
= IECLASS_INACTIVEWINDOW
;
379 case IDCMP_CLOSEWINDOW
:
380 ie
->ie_Class
= IECLASS_CLOSEWINDOW
;
384 ie
->ie_Class
= IECLASS_GADGETUP
;
387 case IDCMP_GADGETDOWN
:
388 ie
->ie_Class
= IECLASS_GADGETDOWN
;
391 case IDCMP_REFRESHWINDOW
:
392 ie
->ie_Class
= IECLASS_REFRESHWINDOW
;
396 ie
->ie_Class
= IECLASS_MENUHELP
;
400 ie
->ie_Class
= IECLASS_MENULIST
;
404 D(bug("ih_fireintuimessage: unexpected IDCMP (0x%X) for a deferred-action-fireintuimessage!\n", Class
));
407 } /* switch(Class) */
410 ie
->ie_Qualifier
= iihd
->ActQualifier
;
411 ie
->ie_EventAddress
= IAddress
;
412 CurrentTime(&ie
->ie_TimeStamp
.tv_secs
, &ie
->ie_TimeStamp
.tv_micro
);
414 D(bug("ih_fireintuimessage: generated InputEvent. Class = 0x%X Code = %d EventAddress = 0x%X\n",
417 ie
->ie_EventAddress
));
419 } /* if ((ie = AllocInputEvent(iihd))) */
422 DEBUG_FIREINTUIMSG(dprintf("ih_fire_intuimessage: result 0x%lx\n",
428 /*********************************************************************/
430 /* This function must never be called with the layer/layerinfo locked,
431 * otherwise a deadlock with ObtainGIRPort can happen.
433 IPTR
Locked_DoMethodA (struct Window
*w
, struct Gadget
*g
, Msg message
, struct IntuitionBase
*IntuitionBase
)
436 BOOL lock
= w
&& (g
->GadgetType
& GTYP_SYSGADGET
&&
437 ((g
->GadgetType
& GTYP_SYSTYPEMASK
) == GTYP_WDRAGGING
||
438 (g
->GadgetType
& GTYP_SYSTYPEMASK
) == GTYP_SIZING
));
442 LOCK_REFRESH(w
->WScreen
);
446 rc
= Custom_DoMethodA(g
, message
);
451 UNLOCK_REFRESH(w
->WScreen
);
457 /*********************************************************************/
459 #undef Custom_DoMethodA
460 IPTR
Custom_DoMethodA (struct IntuitionBase
*IntuitionBase
, struct Gadget
*g
, Msg message
)
462 if (g
->MutualExclude
)
464 return AROS_UFC4(IPTR
, ((struct Hook
*)g
->MutualExclude
)->h_Entry
,
465 AROS_UFCA(struct Hook
*, (struct Hook
*)g
->MutualExclude
, A0
),
466 AROS_UFCA(struct Gadget
*, g
, A2
),
467 AROS_UFCA(APTR
, message
, A1
),
468 AROS_UFCA(struct IntuitionBase
*, IntuitionBase
, A6
));
470 else /* Not needed since gadgetclass sets MutualExclude, but doesn't hurt. */
471 return DoMethodA((Object
*)g
, message
);
474 /****************************************************************************************/
476 void NotifyDepthArrangement(struct Window
*w
, struct IntuitionBase
*IntuitionBase
)
478 if(w
->MoreFlags
& WMFLG_NOTIFYDEPTH
)
480 ih_fire_intuimessage(w
,
489 /****************************************************************************************/
491 void PrepareGadgetInfo(struct GadgetInfo
*gi
, struct Screen
*scr
, struct Window
*win
,
492 struct Requester
*req
)
496 gi
->gi_Requester
= req
;
498 gi
->gi_Pens
.DetailPen
= scr
->DetailPen
;
499 gi
->gi_Pens
.BlockPen
= scr
->BlockPen
;
500 gi
->gi_DrInfo
= (APTR
)&(((struct IntScreen
*)gi
->gi_Screen
)->DInfo
);
503 /****************************************************************************************/
505 void SetGadgetInfoGadget(struct GadgetInfo
*gi
, struct Gadget
*gad
,
506 struct IntuitionBase
*IntuitionBase
)
508 struct IIHData
*iihd
= (struct IIHData
*)GetPrivIBase(IntuitionBase
)->InputHandler
->is_Data
;
510 SET_GI_RPORT(gi
, gi
->gi_Window
, gi
->gi_Requester
, gad
);
511 InitRastPort(&iihd
->GadgetInfoRastPort
);
513 iihd
->GadgetInfoRastPort
.Layer
= gi
->gi_RastPort
->Layer
;
514 iihd
->GadgetInfoRastPort
.BitMap
= gi
->gi_RastPort
->BitMap
;
516 SetFont(&iihd
->GadgetInfoRastPort
, gi
->gi_DrInfo
->dri_Font
);
518 gi
->gi_Layer
= gi
->gi_RastPort
->Layer
;
519 gi
->gi_RastPort
= &iihd
->GadgetInfoRastPort
;
521 GetGadgetDomain(gad
, gi
->gi_Screen
, gi
->gi_Window
, gi
->gi_Requester
, &gi
->gi_Domain
);
524 /****************************************************************************************/
526 void SetGPIMouseCoords(struct gpInput
*gpi
, struct Gadget
*gad
)
528 struct GadgetInfo
*gi
= gpi
->gpi_GInfo
;
532 if (IS_SCREEN_GADGET(gad
) || !gi
->gi_Window
)
534 mousex
= gi
->gi_Screen
->MouseX
;
535 mousey
= gi
->gi_Screen
->MouseY
;
540 mousex
= gi
->gi_Window
->MouseX
;
541 mousey
= gi
->gi_Window
->MouseY
;
544 gpi
->gpi_Mouse
.X
= mousex
- gi
->gi_Domain
.Left
- GetGadgetLeft(gad
, gi
->gi_Screen
, gi
->gi_Window
, gi
->gi_Requester
);
545 gpi
->gpi_Mouse
.Y
= mousey
- gi
->gi_Domain
.Top
- GetGadgetTop(gad
, gi
->gi_Screen
, gi
->gi_Window
, gi
->gi_Requester
);
549 /****************************************************************************************/
551 void HandleSysGadgetVerify(struct GadgetInfo
*gi
, struct Gadget
*gadget
,
552 struct IntuitionBase
*IntuitionBase
)
554 switch(gadget
->GadgetType
& GTYP_SYSTYPEMASK
)
558 if (((struct IntWindow
*)(gi
->gi_Window
))->specialflags
& SPFLAG_IAMDEAD
)
560 CrashedDispose(gi
->gi_Window
,IntuitionBase
);
565 ih_fire_intuimessage(gi
->gi_Window
,
576 if (!IsLayerHiddenBySibling(WLAYER(gi
->gi_Window
), FALSE
))
578 /* Send window to back */
579 WindowToBack(gi
->gi_Window
);
583 /* Send window to front */
584 WindowToFront(gi
->gi_Window
);
589 ZipWindow(gi
->gi_Window
);
593 if (gi
->gi_Screen
== IntuitionBase
->FirstScreen
)
595 ScreenToBack(gi
->gi_Screen
);
599 ScreenToFront(gi
->gi_Screen
);
603 } /* switch(gad->GadgetType & GTYP_SYSTYPEMASK) */
606 /****************************************************************************************/
608 struct Gadget
*HandleCustomGadgetRetVal(IPTR retval
, struct GadgetInfo
*gi
, struct Gadget
*gadget
,
609 ULONG termination
, BOOL
*reuse_event
,
610 struct IntuitionBase
*IntuitionBase
)
612 struct IIHData
*iihdata
= (struct IIHData
*)GetPrivIBase(IntuitionBase
)->InputHandler
->is_Data
;
614 DEBUG_HANDLECUSTOMRETVAL(dprintf("HandleCustomGadgetRetVal: retval %ld gi 0x%lx gadget 0x%lx termination %ld reuse %ld\n",
621 if (retval
!= GMR_MEACTIVE
)
623 struct gpGoInactive gpgi
;
625 DEBUG_HANDLECUSTOMRETVAL(dprintf("HandleCustomGadgetRetVal: !GMR_MEACTIVE\n"));
627 if (retval
& GMR_REUSE
)
629 DEBUG_HANDLECUSTOMRETVAL(dprintf("HandleCustomGadgetRetVal: GMR_REUSE\n"));
633 if (retval
& GMR_VERIFY
)
635 DEBUG_HANDLECUSTOMRETVAL(dprintf("HandleCustomGadgetRetVal: GMR_VERIFY\n"));
636 if (IS_SYS_GADGET(gadget
))
638 DEBUG_HANDLECUSTOMRETVAL(dprintf("HandleCustomGadgetRetVal: SysGad\n"));
639 HandleSysGadgetVerify(gi
, gadget
, IntuitionBase
);
643 /* Not a system gadget. Send IDCMP_GADGETUP, but not
644 if it is a screen gadget where gi->gi_Window would
647 DEBUG_HANDLECUSTOMRETVAL(dprintf("HandleCustomGadgetRetVal: no sysgad\n"));
648 if ((gadget
->Activation
& GACT_RELVERIFY
) &&
651 DEBUG_HANDLECUSTOMRETVAL(dprintf("HandleCustomGadgetRetVal: Send IDCMP_GADGETUP\n"));
652 ih_fire_intuimessage(gi
->gi_Window
,
654 termination
& 0x0000FFFF,
659 } /* switch(gad->GadgetType & GTYP_SYSTYPEMASK) */
661 } /* if (retval & GMR_VERIFY) */
663 DEBUG_HANDLECUSTOMRETVAL(dprintf("HandleCustomGadgetRetVal: Send GM_GOINACTIVE\n"));
665 gpgi
.MethodID
= GM_GOINACTIVE
;
666 gpgi
.gpgi_GInfo
= gi
;
669 Locked_DoMethodA(gi
->gi_Window
, gadget
, (Msg
)&gpgi
, IntuitionBase
);
671 if (SYSGADGET_ACTIVE
)
673 /* Switch back from Master Drag or Size Gadget to
674 real/original/app Size or Drag Gadget */
676 DEBUG_HANDLECUSTOMRETVAL(dprintf("HandleCustomGadgetRetVal: SYSGADGET_ACTIVE\n"));
677 gadget
= iihdata
->ActiveSysGadget
;
678 iihdata
->ActiveSysGadget
= NULL
;
680 if (IS_BOOPSI_GADGET(gadget
))
682 Locked_DoMethodA(gi
->gi_Window
, gadget
, (Msg
)&gpgi
, IntuitionBase
);
686 if ((gadget
->GadgetType
& GTYP_SYSTYPEMASK
) == GTYP_WDRAGGING2
)
688 ih_fire_intuimessage(gi
->gi_Window
,
699 if (retval
& GMR_VERIFY
&& gi
->gi_Requester
&& gadget
->Activation
& GACT_ENDGADGET
)
701 DEBUG_HANDLECUSTOMRETVAL(dprintf("HandleCustomGadgetRetVal: EndRequest\n"));
702 EndRequest(gi
->gi_Requester
, gi
->gi_Window
);
706 gadget
->Activation
&= ~GACT_ACTIVEGADGET
;
708 DEBUG_HANDLECUSTOMRETVAL(dprintf("HandleCustomGadgetRetVal: TabCycle 0x%lx retval 0x%lx\n",
709 (gadget
->Flags
& GFLG_TABCYCLE
),
712 if ((gadget
->Flags
& GFLG_TABCYCLE
) && (retval
& GMR_NEXTACTIVE
))
714 DEBUG_HANDLECUSTOMRETVAL(dprintf("HandleCustomGadgetRetVal: TabCycle+GMR_NEXTACTIVE\n"));
715 gadget
= FindCycleGadget(gi
->gi_Window
, gi
->gi_Requester
, gadget
, GMR_NEXTACTIVE
);
717 else if ((gadget
->Flags
& GFLG_TABCYCLE
) && (retval
& GMR_PREVACTIVE
))
719 DEBUG_HANDLECUSTOMRETVAL(dprintf("HandleCustomGadgetRetVal: TabCycle+GMR_PREVACTIVE\n"));
720 gadget
= FindCycleGadget(gi
->gi_Window
, gi
->gi_Requester
, gadget
, GMR_PREVACTIVE
);
725 DEBUG_HANDLECUSTOMRETVAL(dprintf("HandleCustomGadgetRetVal: No gadget\n"));
730 DEBUG_HANDLECUSTOMRETVAL(dprintf("HandleCustomGadgetRetVal: activate gadget 0x%lx\n",gadget
));
731 gadget
= DoActivateGadget(gi
->gi_Window
, gi
->gi_Requester
, gadget
, IntuitionBase
);
734 } /* if (retval != GMR_MEACTIVE) */
737 DEBUG_HANDLECUSTOMRETVAL(dprintf("HandleCustomGadgetRetVal: set GACT_ACTIVEGADGET\n"));
738 gadget
->Activation
|= GACT_ACTIVEGADGET
;
741 DEBUG_HANDLECUSTOMRETVAL(dprintf("HandleCustomGadgetRetVal: return 0x%x\n", gadget
));
745 /****************************************************************************************/
747 /* This function must never be called with the layer/layerinfo locked,
748 * otherwise a deadlock with ObtainGIRPort can happen.
750 struct Gadget
*DoGPInput(struct GadgetInfo
*gi
, struct Gadget
*gadget
,
751 struct InputEvent
*ie
, STACKULONG methodid
,
752 BOOL
*reuse_event
, struct IntuitionBase
*IntuitionBase
)
754 struct IIHData
*iihdata
= (struct IIHData
*)GetPrivIBase(IntuitionBase
)->InputHandler
->is_Data
;
758 ie
->ie_Qualifier
= iihdata
->ActQualifier
;
760 gpi
.MethodID
= methodid
;
763 gpi
.gpi_Termination
= &termination
;
764 gpi
.gpi_TabletData
= NULL
;
766 SetGPIMouseCoords(&gpi
, gadget
);
768 retval
= Locked_DoMethodA (gi
->gi_Window
, gadget
, (Msg
)&gpi
, IntuitionBase
);
770 DEBUG_DOGPINPUT(dprintf("DoGPInput: Locked_DoMethod gadget %p method 0x%lx retval %ld termination 0x%lx\n",
771 gadget
, methodid
, retval
, termination
));
773 return HandleCustomGadgetRetVal(retval
, gi
, gadget
, termination
,
774 reuse_event
, IntuitionBase
);
778 /****************************************************************************************/
780 struct Gadget
* FindGadget (struct Screen
*scr
, struct Window
* window
,
781 struct Requester
* req
, int x
, int y
,
782 struct GadgetInfo
* gi
,BOOL sysonly
,
783 struct IntuitionBase
*IntuitionBase
)
785 struct Gadget
*gadget
, *firstgadget
, *draggadget
= 0;
786 struct gpHitTest gpht
;
789 BOOL sys_only
= sysonly
;
791 gpht
.MethodID
= GM_HITTEST
;
792 gpht
.gpht_GInfo
= gi
;
794 while (req
|| window
|| scr
)
798 firstgadget
= req
->ReqGadget
;
802 firstgadget
= window
->FirstGadget
;
806 if (draggadget
) return draggadget
;
807 firstgadget
= scr
->FirstGadget
;
810 for (gadget
= firstgadget
; gadget
; gadget
= gadget
->NextGadget
)
812 if (!(gadget
->Flags
& GFLG_DISABLED
) &&
814 (gadget
->GadgetType
& GTYP_SYSGADGET
&&
815 ((gadget
->GadgetType
& GTYP_SYSTYPEMASK
) == GTYP_SIZING
||
816 (gadget
->GadgetType
& GTYP_SYSTYPEMASK
) == GTYP_WDRAGGING
||
817 (gadget
->GadgetType
& GTYP_SYSTYPEMASK
) == GTYP_WDEPTH
||
818 (gadget
->GadgetType
& GTYP_SYSTYPEMASK
) == GTYP_SDEPTH
||
819 (gadget
->GadgetType
& GTYP_SYSTYPEMASK
) == GTYP_WZOOM
||
820 (gadget
->GadgetType
& GTYP_SYSTYPEMASK
) == GTYP_CLOSE
))))
822 /* stegerg: domain depends on gadgettype and windowflags! */
823 GetGadgetDomain(gadget
, scr
, window
, req
, &gi
->gi_Domain
);
825 /* Get coords relative to window */
827 GetGadgetIBox(gadget
, gi
, &ibox
);
829 xrel
= x
- gi
->gi_Domain
.Left
;
830 yrel
= y
- gi
->gi_Domain
.Top
;
834 xrel -= req->LeftEdge + window->BorderLeft;
835 yrel -= req->TopEdge + window->BorderTop;
840 xrel
-= window
->LeftEdge
;
841 yrel
-= window
->TopEdge
;
844 if ((xrel
>= ibox
.Left
) &&
845 (yrel
>= ibox
.Top
) &&
846 (xrel
< ibox
.Left
+ ibox
.Width
) &&
847 (yrel
< ibox
.Top
+ ibox
.Height
))
849 if ((gadget
->GadgetType
& GTYP_SYSTYPEMASK
) == GTYP_WDRAGGING
)
851 if (!draggadget
) draggadget
= gadget
;
856 if ((gadget
->GadgetType
& GTYP_GTYPEMASK
) == GTYP_CUSTOMGADGET
)
859 gpht
.gpht_Mouse
.X
= xrel
- ibox
.Left
;
860 gpht
.gpht_Mouse
.Y
= yrel
- ibox
.Top
;
862 /* jDc: don't check for == GMR_GADGETHIT since some reaction classes*/
863 /* (BURN IN HELL!) return TRUE here (related to imageclass HITEST?)*/
864 if (Locked_DoMethodA (window
, gadget
, (Msg
)&gpht
, IntuitionBase
))
874 } /* if (!(gadget->Flags & GFLG_DISABLED)) */
876 } /* for (gadget = window->FirstGadget; gadget; gadget = gadget->NextGadget) */
888 draggadget
= findbordergadget(window
,draggadget
,IntuitionBase
);
901 /****************************************************************************************/
903 struct Gadget
* FindHelpGadget (struct Window
* window
,
904 int x
, int y
, struct IntuitionBase
*IntuitionBase
)
906 struct Gadget
*gadget
, *firstgadget
;
907 struct Requester
*req
= window
->FirstRequest
;
909 while (req
|| window
)
913 firstgadget
= req
->ReqGadget
;
917 firstgadget
= window
->FirstGadget
;
920 for (gadget
= firstgadget
; gadget
; gadget
= gadget
->NextGadget
)
922 if ((gadget
->Flags
& GFLG_EXTENDED
) &&
923 (((struct ExtGadget
*)gadget
)->MoreFlags
& GMORE_GADGETHELP
))
925 if (InsideGadget(window
->WScreen
, window
, req
, gadget
, x
, y
))
934 req
= req
->OlderRequest
;
944 /****************************************************************************************/
946 BOOL
InsideGadget(struct Screen
*scr
, struct Window
*win
, struct Requester
*req
,
947 struct Gadget
*gad
, WORD x
, WORD y
)
952 GetScrGadgetIBox(gad
, scr
, win
, req
, &box
);
954 if ((x
>= box
.Left
) &&
956 (x
< box
.Left
+ box
.Width
) &&
957 (y
< box
.Top
+ box
.Height
))
965 /****************************************************************************************/
967 struct Gadget
*DoActivateGadget(struct Window
*win
, struct Requester
*req
, struct Gadget
*gad
,
968 struct IntuitionBase
*IntuitionBase
)
970 struct IIHData
*iihd
= (struct IIHData
*)GetPrivIBase(IntuitionBase
)->InputHandler
->is_Data
;
971 struct GadgetInfo
*gi
= &iihd
->GadgetInfo
;
972 struct Gadget
*result
= NULL
;
974 DEBUG_ACTIVATEGADGET(dprintf("DoActivateGadget: Window 0x%lx Req 0x%lx Gadget 0x%lx\n",
979 DEBUG_ACTIVATEGADGET(dprintf("DoActivateGadget: Activation 0x%lx\n",
982 if (gad
->Activation
& GACT_IMMEDIATE
)
984 DEBUG_ACTIVATEGADGET(dprintf("DoActivateGadget: Send GADGETDOWN msg\n"));
985 ih_fire_intuimessage(win
,
992 PrepareGadgetInfo(gi
, win
->WScreen
, win
, req
);
993 SetGadgetInfoGadget(gi
, gad
, IntuitionBase
);
995 DEBUG_ACTIVATEGADGET(dprintf("DoActivateGadget: Type 0x%lx\n",
996 gad
->GadgetType
& GTYP_GTYPEMASK
));
998 switch(gad
->GadgetType
& GTYP_GTYPEMASK
)
1000 case GTYP_STRGADGET
:
1001 DEBUG_ACTIVATEGADGET(dprintf("DoActivateGadget: GTYP_STRGADGET\n"));
1002 gad
->Activation
|= GACT_ACTIVEGADGET
;
1003 UpdateStrGadget(gad
, win
, req
, IntuitionBase
);
1007 case GTYP_CUSTOMGADGET
:
1014 DEBUG_ACTIVATEGADGET(dprintf("DoActivateGadget: GTYP_CUSTOMGADGET\n"));
1016 gpi
.MethodID
= GM_GOACTIVE
;
1018 gpi
.gpi_IEvent
= NULL
;
1019 gpi
.gpi_Termination
= &termination
;
1020 gpi
.gpi_Mouse
.X
= win
->MouseX
- gi
->gi_Domain
.Left
- GetGadgetLeft(gad
, gi
->gi_Screen
, gi
->gi_Window
, NULL
);
1021 gpi
.gpi_Mouse
.Y
= win
->MouseY
- gi
->gi_Domain
.Top
- GetGadgetTop(gad
, gi
->gi_Screen
, gi
->gi_Window
, NULL
);
1022 gpi
.gpi_TabletData
= NULL
;
1024 retval
= Locked_DoMethodA (win
, gad
, (Msg
)&gpi
, IntuitionBase
);
1026 gad
= HandleCustomGadgetRetVal(retval
, gi
, gad
,termination
,
1027 &reuse_event
, IntuitionBase
);
1031 gad
->Activation
|= GACT_ACTIVEGADGET
;
1037 } /* switch(gad->GadgetType & GTYP_GTYPEMASK) */
1039 DEBUG_ACTIVATEGADGET(dprintf("DoActivateGadget: result 0x%lx\n",
1042 if (result
) iihd
->ActiveGadget
= result
;
1048 /****************************************************************************************/
1050 struct Gadget
*FindCycleGadget(struct Window
*win
, struct Requester
*req
,
1051 struct Gadget
*gad
, WORD direction
)
1053 struct Gadget
*g
= NULL
, *gg
, *prev
, *first
;
1055 D(bug("FindCycleGadget: win = %p req %p gad = %p direction = %d\n", win
, req
, gad
, direction
));
1058 first
= req
->ReqGadget
;
1060 first
= win
->FirstGadget
;
1064 case GMR_NEXTACTIVE
:
1065 g
= gad
->NextGadget
;
1072 if (!(gad
->Flags
& GFLG_TABCYCLE
) || (gad
->Flags
& GFLG_DISABLED
))
1074 /* should never happen */
1079 if (!(g
->Flags
& GFLG_DISABLED
) && (g
->Flags
& GFLG_TABCYCLE
)) break;
1086 case GMR_PREVACTIVE
:
1091 /* find a TABCYCLE gadget which is before gad in window's gadgetlist */
1099 if (!(gg
->Flags
& GFLG_DISABLED
) && (gg
->Flags
& GFLG_TABCYCLE
)) prev
= gg
;
1100 gg
= gg
->NextGadget
;
1105 /* There was no TABCYCLE gadget before gad in window's gadgetlist */
1107 gg
= gg
->NextGadget
;
1110 if (!(gad
->Flags
& GFLG_DISABLED
) && (gad
->Flags
& GFLG_TABCYCLE
)) g
= gad
;
1117 if (!(gg
->Flags
& GFLG_DISABLED
) && (gg
->Flags
& GFLG_TABCYCLE
)) prev
= gg
;
1118 gg
= gg
->NextGadget
;
1127 if (!(gad
->Flags
& GFLG_DISABLED
) && (gad
->Flags
& GFLG_TABCYCLE
)) g
= gad
;
1134 default: /* Unused, but well... */
1138 } /* switch(direction) */
1143 /****************************************************************************************/
1145 void FixWindowCoords(struct Window
*win
, LONG
*left
, LONG
*top
, LONG
*width
, LONG
*height
,struct IntuitionBase
*IntuitionBase
)
1147 struct Screen
*scr
= win
->WScreen
;
1149 if (*width
< 1) *width
= 1;
1150 if (*height
< 1) *height
= 1;
1152 if (*width
> scr
->Width
) *width
= scr
->Width
;
1153 if (*height
> scr
->Height
) *height
= scr
->Height
;
1155 if ((GetPrivIBase(IntuitionBase
)->IControlPrefs
.ic_Flags
& ICF_OFFSCREENLAYERS
) && (win
->WScreen
->LayerInfo
.Flags
& LIFLG_SUPPORTS_OFFSCREEN_LAYERS
))
1157 if (*left
> scr
->Width
- 1) *left
= scr
->Width
- 1;
1158 if (*top
> scr
->Height
- 1) *top
= scr
->Height
-1;
1163 if ((*left
+ *width
) > scr
->Width
)
1165 *left
= scr
->Width
- *width
;
1172 if ((*top
+ *height
) > scr
->Height
)
1174 *top
= scr
->Height
- *height
;
1183 /****************************************************************************************/
1185 void WindowNeedsRefresh(struct Window
* w
,
1186 struct IntuitionBase
* IntuitionBase
)
1188 /* Supposed to send a message to this window, saying that it needs a
1189 refresh. I will check whether there is no such a message queued in
1190 its messageport, though. It only needs one such message!
1193 /* Refresh the window's gadgetry ...
1194 ... stegerg: and in the actual implementation
1195 call RefershWindowFrame first, as the border gadgets dont
1196 cover the whole border area.*/
1199 jDc: in actual implementation sizeevent means that we need to send
1200 idcmp, etc and do not clear the flag for smart_refresh window that
1201 has no idcmp_refreshwindow, otherwise we clear the flag!
1204 DEBUG_WINDOWNEEDSREFRESH(dprintf("WindowNeedsRefresh: window 0x%lx gzz %d nocarerefresh %d\n",
1205 w
, IS_GZZWINDOW(w
), IS_NOCAREREFRESH(w
)));
1207 //trashregion means that we use delayed refreshing!
1211 (!IW(w
)->trashregion
) ||
1213 (!(w
->Flags
& WFLG_SIMPLE_REFRESH
)) ||
1215 IS_NOCAREREFRESH(w
))
1218 Gad_BeginUpdate(WLAYER(w
), IntuitionBase
);
1220 if (IS_NOCAREREFRESH(w
) || (!((!(w
->Flags
& WFLG_SIMPLE_REFRESH
)) && (!(IW(w
)->specialflags
& SPFLAG_LAYERRESIZED
)))))
1222 if (!IS_GZZWINDOW(w
))
1224 if (w
->Flags
& WFLG_BORDERLESS
)
1226 int_refreshglist(w
->FirstGadget
, w
, NULL
, -1, 0, 0, IntuitionBase
);
1230 int_refreshwindowframe(w
,0,0,IntuitionBase
);
1235 /* refresh all gadgets except border gadgets */
1236 int_refreshglist(w
->FirstGadget
, w
, NULL
, -1, 0, REFRESHGAD_BORDER
, IntuitionBase
);
1238 IW(w
)->specialflags
&= ~SPFLAG_LAYERRESIZED
;
1241 if (IS_NOCAREREFRESH(w
)) WLAYER(w
)->Flags
&= ~LAYERREFRESH
;
1243 Gad_EndUpdate(WLAYER(w
), IS_NOCAREREFRESH(w
) ? TRUE
: FALSE
, IntuitionBase
);
1247 struct Rectangle rect
;
1248 BOOL doclear
= (w
->Flags
& WFLG_BORDERLESS
) ? FALSE
: TRUE
;
1250 rect
.MinX
= w
->BorderLeft
;
1251 rect
.MinY
= w
->BorderTop
;
1252 rect
.MaxX
= w
->Width
- w
->BorderRight
- 1;
1253 rect
.MaxY
= w
->Height
- w
->BorderBottom
- 1;
1256 #ifndef BEGINUPDATEGADGETREFRESH
1257 Gad_BeginUpdate(WLAYER(w
), IntuitionBase
);
1260 LockLayer(0,WLAYER(w
));
1264 #ifndef BEGINUPDATEGADGETREFRESH
1265 if (!IS_GZZWINDOW(w
))
1267 if (w
->Flags
& WFLG_BORDERLESS
)
1269 int_refreshglist(w
->FirstGadget
, w
, NULL
, -1, 0, 0, IntuitionBase
);
1273 int_refreshwindowframe(w
,0,0,IntuitionBase
);
1278 /* refresh all gadgets except border and gadtools gadgets */
1279 int_refreshglist(w
->FirstGadget
, w
, NULL
, -1, 0, REFRESHGAD_BORDER
, IntuitionBase
);
1284 //add rects to trashregion here
1285 OrRegionRegion(WLAYER(w
)->DamageList
,IW(w
)->trashregion
);
1289 ClearRectRegion(IW(w
)->trashregion
,&rect
);
1290 AndRectRegion(WLAYER(w
)->DamageList
,&rect
);
1293 IW(w
)->specialflags
|= SPFLAG_LAYERREFRESH
;
1295 #ifdef BEGINUPDATEGADGETREFRESH
1296 IW(w
)->specialflags
|= SPFLAG_LAYERREFRESH
;
1300 #ifndef BEGINUPDATEGADGETREFRESH
1301 Gad_EndUpdate(WLAYER(w
), FALSE
, IntuitionBase
);
1304 UnlockLayer(WLAYER(w
));
1310 if (IS_DOCAREREFRESH(w
))
1312 if (w
->UserPort
&& (w
->IDCMPFlags
& IDCMP_REFRESHWINDOW
))
1314 struct IntuiMessage
*IM
;
1317 /* Can use Forbid() for this */
1320 IM
= (struct IntuiMessage
*)w
->UserPort
->mp_MsgList
.lh_Head
;
1322 ForeachNode(&w
->UserPort
->mp_MsgList
, IM
)
1324 /* Does the window already have such a message? */
1325 if (IDCMP_REFRESHWINDOW
== IM
->Class
&& IM
->IAddress
== w
)
1327 DEBUG_WINDOWNEEDSREFRESH(dprintf("WindowNeedsRefresh: refresh pending\n"));
1328 D(bug("Window %s already has a refresh message pending!!\n",
1329 w
->Title
? w
->Title
: (STRPTR
)"<NONAME>"));
1339 struct InputEvent
*new_ie
;
1340 struct IIHData
*iihdata
= (struct IIHData
*)GetPrivIBase(IntuitionBase
)->InputHandler
->is_Data
;
1342 D(bug("Sending a refresh message to window %s %d %d %d %d!!\n",
1343 w
->Title
? w
->Title
: (STRPTR
)"<NONAME>",
1349 DEBUG_WINDOWNEEDSREFRESH(dprintf("WindowNeedsRefresh: sending idcmp message\n"));
1351 if ((new_ie
= AllocInputEvent(iihdata
)))
1353 new_ie
->ie_Class
= IECLASS_EVENT
;
1354 new_ie
->ie_Code
= IECODE_REFRESH
;
1355 new_ie
->ie_EventAddress
= w
;
1356 CurrentTime(&new_ie
->ie_TimeStamp
.tv_secs
, &new_ie
->ie_TimeStamp
.tv_micro
);
1359 fire_intuimessage(w
,
1360 IDCMP_REFRESHWINDOW
,
1366 } /* if (w->UserPort && (w->IDCMPFlags & IDCMP_REFRESHWINDOW)) */
1369 struct IIHData
*iihdata
= (struct IIHData
*)GetPrivIBase(IntuitionBase
)->InputHandler
->is_Data
;
1371 if (FindTask(NULL
) == iihdata
->InputDeviceTask
)
1373 struct InputEvent
*new_ie
;
1375 DEBUG_WINDOWNEEDSREFRESH(dprintf("WindowNeedsRefresh: sending inputevent\n"));
1377 if ((new_ie
= AllocInputEvent(iihdata
)))
1379 new_ie
->ie_Class
= IECLASS_EVENT
;
1380 new_ie
->ie_Code
= IECODE_REFRESH
;
1381 new_ie
->ie_EventAddress
= w
;
1382 CurrentTime(&new_ie
->ie_TimeStamp
.tv_secs
, &new_ie
->ie_TimeStamp
.tv_micro
);
1385 ih_fire_intuimessage(w
,
1386 IDCMP_REFRESHWINDOW
,
1393 } /* if (!IS_NOCAREREFRESH(w)) */
1397 /****************************************************************************************/
1399 struct Window
*FindActiveWindow(struct InputEvent
*ie
,ULONG
*stitlebarhit
,
1400 struct IntuitionBase
*IntuitionBase
)
1402 /* The caller has checked that the input event is a IECLASS_RAWMOUSE, SELECTDOWN event */
1403 /* NOTE: may be called with NULL ie ptr! */
1406 struct Window
*new_w
;
1409 lock
= LockIBase(0UL);
1411 new_w
= IntuitionBase
->ActiveWindow
;
1412 scr
= IntuitionBase
->FirstScreen
;
1416 D(bug("FindActiveWindow: scr %p win %p\n",scr
,new_w
));
1418 if (stitlebarhit
) *stitlebarhit
= FALSE
;
1422 D(bug("FindActiveWindow: Click at (%d,%d)\n",scr
->MouseX
,scr
->MouseY
));
1425 LockLayerInfo(&scr
->LayerInfo
);
1427 l
= WhichLayer(&scr
->LayerInfo
, scr
->MouseX
, scr
->MouseY
);
1429 UnlockLayerInfo(&scr
->LayerInfo
);
1434 D(bug("FindActiveWindow: Click not inside layer\n"));
1436 else if (l
== scr
->BarLayer
)
1438 D(bug("FindActiveWindow: Click on screen bar layer -> active window stays the same\n"));
1439 if (stitlebarhit
) *stitlebarhit
= TRUE
;
1443 new_w
= (struct Window
*)l
->Window
;
1446 D(bug("FindActiveWindow: Selected layer is not a window\n"));
1449 D(bug("FindActiveWindow: Found layer %p\n", l
));
1453 D(bug("FindActiveWindow: New window %p\n", new_w
));
1457 /****************************************************************************************/
1459 struct Window
*FindDesktopWindow(struct Screen
*screen
,struct IntuitionBase
*IntuitionBase
)
1463 for (win
= screen
->FirstWindow
; win
; win
= win
->NextWindow
)
1465 if (win
->Flags
& WFLG_BACKDROP
&&
1466 win
->Width
== screen
->Width
&&
1467 win
->Height
>= screen
->Height
- (screen
->BarHeight
+ 2))
1477 /****************************************************************************************/
1479 struct InputEvent
*AllocInputEvent(struct IIHData
*iihdata
)
1481 struct IntuitionBase
*IntuitionBase
= iihdata
->IntuitionBase
;
1482 struct GeneratedInputEvent
*gie
;
1483 struct InputEvent
*ie
;
1485 /* There might be an inputevent from someone else that our handler discarded.
1486 * We may as well use it. This can only happen inside our main loop.
1488 ie
= iihdata
->FreeInputEvents
;
1491 iihdata
->FreeInputEvents
= ie
->ie_NextEvent
;
1492 DEBUG_INPUTEVENT(dprintf("AllocInputEvent: reuse 0x%lx event\n", ie
));
1496 gie
= AllocPooled(iihdata
->InputEventMemPool
, sizeof(struct GeneratedInputEvent
));
1499 /* Allocated events are put in the list of events that have not yet been
1502 AddTail((struct List
*)&iihdata
->NewAllocatedInputEventList
, (struct Node
*)gie
);
1505 DEBUG_INPUTEVENT(dprintf("AllocInputEvent: allocated 0x%lx (0x%lx)\n", ie
, gie
));
1510 *iihdata
->EndInputEventChain
= ie
;
1511 iihdata
->EndInputEventChain
= &ie
->ie_NextEvent
;
1517 /****************************************************************************************/
1519 void FreeGeneratedInputEvents(struct IIHData
*iihdata
)
1521 struct IntuitionBase
*IntuitionBase
= iihdata
->IntuitionBase
;
1522 struct Node
*node
, *succ
;
1524 /* Free the list of allocated events that have already been propagated. */
1525 ForeachNodeSafe(&iihdata
->AllocatedInputEventList
, node
, succ
)
1527 DEBUG_INPUTEVENT(dprintf("FreeGeneratedInputEvent: free 0x%lx\n", node
));
1528 FreePooled(iihdata
->InputEventMemPool
, node
, sizeof(struct GeneratedInputEvent
));
1531 /* The list is not in a valid state at this point, and NewList() should
1532 * be called, but since we won't use it until the list of not-yet-propagated
1533 * events is copied in it, we won't bother.
1535 //NEWLIST(&iihdata->AllocatedInputEventList);
1538 /****************************************************************************************/
1540 BOOL
FireMenuMessage(WORD code
, struct Window
*win
,
1541 struct InputEvent
*ie
, struct IntuitionBase
*IntuitionBase
)
1543 struct MenuMessage
*msg
;
1544 BOOL result
= FALSE
;
1546 if ((msg
= AllocMenuMessage(IntuitionBase
)))
1550 if (ie
) msg
->ie
= *ie
;
1551 SendMenuMessage(msg
, IntuitionBase
);
1559 /****************************************************************************************/
1561 LONG
Gad_BeginUpdate(struct Layer
*layer
, struct IntuitionBase
*IntuitionBase
)
1563 /* Must lock GadgetLock to avoid deadlocks with ObtainGirPort
1564 from other tasks, because ObtainGirPort first obtains
1565 GadgetLock and then layer lock through LockLayer!!!! */
1567 return BeginUpdate(layer
);
1570 /****************************************************************************************/
1572 void Gad_EndUpdate(struct Layer
*layer
, UWORD flag
, struct IntuitionBase
*IntuitionBase
)
1574 EndUpdate(layer
, flag
);
1578 /****************************************************************************************/