2 Copyright © 1995-2005, The AROS Development Team. All rights reserved.
3 Copyright © 2001-2003, The MorphOS Development Team. All Rights Reserved.
6 Classes for window decor stuff, like dragbar, close etc.
9 /***********************************************************************************/
13 #include <proto/exec.h>
14 #include <proto/intuition.h>
15 #include <proto/graphics.h>
16 #include <proto/utility.h>
17 #include <proto/layers.h>
19 #include <intuition/classes.h>
20 #include <intuition/gadgetclass.h>
21 #include <intuition/cghooks.h>
22 #include <intuition/imageclass.h>
23 #include <intuition/extensions.h>
24 #include <aros/asmcall.h>
28 #include "intuition_intern.h"
29 #include "inputhandler.h"
30 #include "inputhandler_support.h"
31 #include "inputhandler_actions.h"
34 #include "intuition_customizesupport.h"
35 #include "renderwindowframe.h"
43 #include <aros/debug.h>
45 #define MOVEHACK (GetPrivIBase(IntuitionBase)->IControlPrefs.ic_Flags & ICF_PRIVILEDGEDREFRESH)
49 jDc: opaque resize code is NOT sutiable for other apps than MUI, I have no intentions in fixing it so that
50 it would work with all apps out there. Use mui or die :)
52 The idea behind the trick is that we use a func that checks if apps reply to idcmps in some period
53 of time. As long as they are replying fast we can do another layer resize, send idcmp to app.
54 If they do not then we wait for a while and after some time, if one or more apps don't reply
55 we do the resize again (the timeout is also useful when we have some dead app with windows
61 # define OPAQUESIZE (w->MoreFlags & WMFLG_IAMMUI)
69 /***********************************************************************************/
71 #define WSIG_MOVE SIGF_INTUITION
72 #define WSIG_DIE SIGF_ABORT
74 /***********************************************************************************/
76 void MoveTask(struct dragbar_data
*data
,struct Window
*w
,struct Screen
*screen
,struct IntuitionBase
*IntuitionBase
)
82 signals
= Wait(WSIG_DIE
|WSIG_MOVE
);
84 if (signals
& WSIG_DIE
)
89 WindowAction(w
,WAC_CHANGEWINDOWBOX
,0);
93 if (signals
& WSIG_MOVE
)
97 LockLayers(&screen
->LayerInfo
);
99 for (L
= screen
->LayerInfo
.top_layer
; L
; L
= L
->back
)
103 //window not closed yet!
104 if (data
->curleft
!= w
->LeftEdge
|| data
->curtop
!= w
->TopEdge
)
106 struct Requester
*req
;
110 /* move outer window first */
111 MoveSizeLayer(BLAYER(w
), data
->curleft
- w
->LeftEdge
, data
->curtop
- w
->TopEdge
, 0, 0);
114 MoveSizeLayer(WLAYER(w
), data
->curleft
- w
->LeftEdge
, data
->curtop
- w
->TopEdge
, 0, 0);
116 for (req
= w
->FirstRequest
; req
; req
= req
->OlderRequest
)
118 struct Layer
*layer
= req
->ReqLayer
;
123 int left
, top
, right
, bottom
;
125 left
= data
->curleft
+ req
->LeftEdge
;
126 top
= data
->curtop
+ req
->TopEdge
;
127 right
= left
+ req
->Width
- 1;
128 bottom
= top
+ req
->Height
- 1;
130 if (left
> data
->curleft
+ w
->Width
- 1)
131 left
= data
->curleft
+ w
->Width
- 1;
133 if (top
> data
->curtop
+ w
->Height
- 1)
134 top
= data
->curtop
+ w
->Height
- 1;
136 if (right
> data
->curleft
+ w
->Width
- 1)
137 right
= data
->curleft
+ w
->Width
- 1;
139 if (bottom
> data
->curtop
+ w
->Height
- 1)
140 bottom
= data
->curtop
+ w
->Height
- 1;
142 dx
= left
- layer
->bounds
.MinX
;
143 dy
= top
- layer
->bounds
.MinY
;
144 dw
= right
- left
- layer
->bounds
.MaxX
+ layer
->bounds
.MinX
;
145 dh
= bottom
- top
- layer
->bounds
.MaxY
+ layer
->bounds
.MinY
;
147 MoveSizeLayer(layer
, dx
, dy
, dw
, dh
);
151 w
->LeftEdge
= data
->curleft
;
152 w
->TopEdge
= data
->curtop
;
153 UpdateMouseCoords(w
);
160 RecordDamage(screen
,IntuitionBase
);
162 data
->drag_refreshed
= FALSE
;
164 UnlockLayers(&screen
->LayerInfo
);
169 /***********************************************************************************/
171 /* drawwindowframe is used when the user drags or resizes a window */
173 #define DWF_THICK_X 2
174 #define DWF_THICK_Y 2
176 /***********************************************************************************/
178 static void cliprectfill(struct Screen
*scr
, struct RastPort
*rp
,
179 WORD x1
, WORD y1
, WORD x2
, WORD y2
,
180 struct IntuitionBase
*IntuitionBase
)
182 WORD scrx2
= scr
->Width
- 1;
183 WORD scry2
= scr
->Height
- 1;
185 /* Check if inside at all */
187 if (!((x1
> scrx2
) || (x2
< 0) || (y1
> scry2
) || (y2
< 0)))
191 if (x2
> scrx2
) x2
= scrx2
;
192 if (y2
> scry2
) y2
= scry2
;
196 if ((x2
>= x1
) && (y2
>= y1
))
198 RectFill(rp
, x1
, y1
, x2
, y2
);
204 /***********************************************************************************/
206 static void drawwindowframe(struct Screen
*scr
, struct RastPort
*rp
,
207 WORD x1
, WORD y1
, WORD x2
, WORD y2
,
208 struct IntuitionBase
*IntuitionBase
)
210 /* this checks should not be necessary, but just to be sure */
228 if (((x2
- x1
) < (DWF_THICK_X
* 2)) ||
229 ((y2
- y1
) < (DWF_THICK_Y
* 2)))
231 cliprectfill(scr
, rp
, x1
, y1
, x2
, y2
, IntuitionBase
);
235 cliprectfill(scr
, rp
, x1
, y1
, x2
, y1
+ DWF_THICK_Y
- 1, IntuitionBase
);
236 cliprectfill(scr
, rp
, x2
- DWF_THICK_X
+ 1, y1
+ DWF_THICK_Y
, x2
, y2
, IntuitionBase
);
237 cliprectfill(scr
, rp
, x1
, y2
- DWF_THICK_Y
+ 1, x2
- DWF_THICK_X
, y2
, IntuitionBase
);
238 cliprectfill(scr
, rp
, x1
, y1
+ DWF_THICK_Y
, x1
+ DWF_THICK_X
- 1, y2
- DWF_THICK_Y
, IntuitionBase
);
242 /***********************************************************************************/
244 #define IntuitionBase ((struct IntuitionBase *)(cl)->cl_UserData)
246 /***********************************************************************************/
249 IPTR
DragBarClass__GM_RENDER(Class
*cl
, struct Gadget
*g
, struct gpRender
* msg
)
251 EnterFunc(bug("DragBar::Render()\n"));
252 /* We will let the AROS gadgetclass test if it is safe to render */
254 if ( DoSuperMethodA(cl
, (Object
*)g
, (Msg
)msg
) != 0)
256 struct DrawInfo
*dri
= msg
->gpr_GInfo
->gi_DrInfo
;
257 UWORD
*pens
= dri
->dri_Pens
;
258 struct RastPort
*rp
= msg
->gpr_RPort
;
259 struct IBox container
;
260 struct Window
*win
= msg
->gpr_GInfo
->gi_Window
;
261 struct TextExtent te
;
263 GetGadgetIBox(g
, msg
->gpr_GInfo
, &container
);
265 if (container
.Width
<= 1 || container
.Height
<= 1)
269 /* Clear the dragbar */
271 SetAPen(rp
, (win
->Flags
& WFLG_WINDOWACTIVE
) ?
272 pens
[FILLPEN
] : pens
[BACKGROUNDPEN
]);
276 D(bug("Filling from (%d, %d) to (%d, %d)\n",
279 container
.Left
+ container
.Width
- 1,
280 container
.Top
+ container
.Height
- 1));
285 container
.Left
+ container
.Width
- 1,
286 container
.Top
+ container
.Height
- 2);
288 /* Draw a thin dark line around the bar */
290 SetAPen(rp
, pens
[SHINEPEN
]);
291 RectFill(rp
,container
.Left
,
294 container
.Top
+ container
.Height
- 1 - ((container
.Left
== 0) ? 0 : 1));
295 RectFill(rp
,container
.Left
+ 1,
297 container
.Left
+ container
.Width
- 1,
300 SetAPen(rp
,pens
[SHADOWPEN
]);
301 RectFill(rp
,container
.Left
+ container
.Width
- 1,
303 container
.Left
+ container
.Width
- 1,
304 container
.Top
+ container
.Height
- 1);
305 RectFill(rp
,container
.Left
+ ((container
.Left
== 0) ? 1 : 0),
306 container
.Top
+ container
.Height
- 1,
307 container
.Left
+ container
.Width
- 2,
308 container
.Top
+ container
.Height
- 1);
310 /* Render the titlebar */
311 if (NULL
!= win
->Title
)
313 ULONG textlen
, titlelen
;
315 SetFont(rp
, dri
->dri_Font
);
317 titlelen
= strlen(win
->Title
);
324 , container
.Width
- 6
327 SetAPen(rp
, pens
[(win
->Flags
& WFLG_WINDOWACTIVE
) ? FILLTEXTPEN
: TEXTPEN
]);
328 Move(rp
, container
.Left
+ 3, container
.Top
+ dri
->dri_Font
->tf_Baseline
+ 2);
330 Text(rp
, win
->Title
, textlen
);
333 } /* if (allowed to render) */
339 /***********************************************************************************/
341 IPTR
DragBarClass__GM_GOACTIVE(Class
*cl
, struct Gadget
*g
, struct gpInput
*msg
)
343 struct InputEvent
*ie
= msg
->gpi_IEvent
;
344 IPTR retval
= GMR_NOREUSE
;
348 /* The gadget was activated via mouse input */
349 struct dragbar_data
*data
;
352 /* There is no point in rerendering ourseleves her, as this
353 is done by a call to RefreshWindowFrame() in the intuition inputhandler
356 w
= msg
->gpi_GInfo
->gi_Window
;
358 data
= INST_DATA(cl
, g
);
361 /* do NOT ObtainSemaphore here since this would lead to deadlocks!!! */
362 /* when the semaphore can not be obtained we simply ignore gadget activation */
364 /* in movehack the task that locks windowlock is the one that calls MoveWindow*/
365 if (!(AttemptSemaphore(&GetPrivIBase(IntuitionBase
)->WindowLock
)))
369 data
->drag_windowlock
= TRUE
;
372 data
->curleft
= w
->LeftEdge
;
373 data
->curtop
= w
->TopEdge
;
375 data
->startleft
= w
->LeftEdge
;
376 data
->starttop
= w
->TopEdge
;
378 data
->mousex
= w
->WScreen
->MouseX
- data
->curleft
;
379 data
->mousey
= w
->WScreen
->MouseY
- data
->curtop
;
381 data
->drag_refreshed
= TRUE
;
383 data
->rp
= CloneRastPort(&w
->WScreen
->RastPort
);
387 /* Lock all layers while the window is dragged.
388 * Get the gadget lock first to avoid deadlocks
389 * with ObtainGIRPort. */
391 D(bug("locking all layers\n"));
393 if (!(GetPrivIBase(IntuitionBase
)->IControlPrefs
.ic_Flags
& ICF_OPAQUEMOVE
))
396 if (AttemptSemaphore(&GetPrivIBase(IntuitionBase
)->GadgetLock
))
398 data
->drag_gadgetlock
= TRUE
;
406 LockLayers(&w
->WScreen
->LayerInfo
);
407 data
->drag_layerlock
= TRUE
;
414 NewCreateTask(TASKTAG_CODETYPE
, CODETYPE_PPC
, TASKTAG_PC
, (ULONG
)MoveTask
,
416 TASKTAG_PPC_ARG1
,(ULONG
)data
,
417 TASKTAG_PPC_ARG2
,(ULONG
)w
,
418 TASKTAG_PPC_ARG3
,(ULONG
)w
->WScreen
,
419 TASKTAG_PPC_ARG4
,(ULONG
)IntuitionBase
,
423 #warning Implemente MOVEHACK support for AROS (?)
428 SetDrMd(data
->rp
, COMPLEMENT
);
431 if (!(GetPrivIBase(IntuitionBase
)->IControlPrefs
.ic_Flags
& ICF_OPAQUEMOVE
))
432 drawwindowframe(w
->WScreen
436 , data
->curleft
+ w
->Width
- 1
437 , data
->curtop
+ w
->Height
- 1
441 data
->isrendered
= TRUE
;
444 data
->drag_canceled
= FALSE
;
449 currenttime
= ie
->ie_TimeStamp
.tv_secs
;
450 currenttime
= currenttime
* 50;
451 currenttime
+= ie
->ie_TimeStamp
.tv_micro
/ 20000;
453 data
->lasteventtime
= currenttime
;
456 /* size mouse bounds such that mouse pointer cannot move if window cannot move, if offscreenlayers is turned off */
457 if (!(GetPrivIBase(IntuitionBase
)->IControlPrefs
.ic_Flags
& ICF_OFFSCREENLAYERS
)) {
458 struct IIHData
*iihd
= (struct IIHData
*)GetPrivIBase(IntuitionBase
)->InputHandler
->is_Data
;
459 iihd
->MouseBoundsActiveFlag
= TRUE
;
460 iihd
->MouseBoundsLeft
= data
->mousex
;
461 iihd
->MouseBoundsRight
= w
->WScreen
->Width
- (w
->Width
- data
->mousex
);
462 iihd
->MouseBoundsTop
= data
->mousey
;
463 iihd
->MouseBoundsBottom
= w
->WScreen
->Height
- (w
->Height
- data
->mousey
);
470 if (data
->drag_layerlock
)
472 UnlockLayers(&w
->WScreen
->LayerInfo
);
473 data
->drag_layerlock
= FALSE
;
478 if (data
->drag_gadgetlock
)
480 ReleaseSemaphore(&GetPrivIBase(IntuitionBase
)->GadgetLock
);
481 data
->drag_gadgetlock
= FALSE
;
486 if (data
->drag_windowlock
)
488 ReleaseSemaphore(&GetPrivIBase(IntuitionBase
)->WindowLock
);
489 data
->drag_windowlock
= FALSE
;
498 /***********************************************************************************/
500 IPTR
DragBarClass__GM_MOVETEST(Class
*cl
, struct Gadget
*g
, struct gpInput
*msg
)
502 IPTR retval
= MOVETEST_MOVE
;
504 struct dragbar_data
*data
= INST_DATA(cl
, g
);
505 struct Window
*w
= msg
->gpi_GInfo
->gi_Window
;
506 struct InputEvent myie
;
510 CopyMem(msg
->gpi_IEvent
,&myie
,sizeof (struct InputEvent
));
511 myie
.ie_Code
= 0x68; //mouse_leftpress
513 /* Can we move to the new position, or is window at edge of display ? */
514 new_left
= msg
->gpi_Mouse
.X
- data
->mousex
;
515 new_top
= msg
->gpi_Mouse
.Y
- data
->mousey
;
517 if ((!((GetPrivIBase(IntuitionBase
)->IControlPrefs
.ic_Flags
& ICF_OFFSCREENLAYERS
) && (w
->WScreen
->LayerInfo
.Flags
& LIFLG_SUPPORTS_OFFSCREEN_LAYERS
))) ||
518 MatchHotkey(&myie
,IA_TOGGLEOFFSCREEN
,IntuitionBase
))
522 msg
->gpi_Mouse
.X
-= new_left
;
523 retval
= MOVETEST_ADJUSTPOS
;
528 msg
->gpi_Mouse
.Y
-= new_top
;
529 retval
= MOVETEST_ADJUSTPOS
;
532 if (new_left
+ w
->Width
> w
->WScreen
->Width
)
534 msg
->gpi_Mouse
.X
-= new_left
- (w
->WScreen
->Width
- w
->Width
);
535 retval
= MOVETEST_ADJUSTPOS
;
538 if (new_top
+ w
->Height
> w
->WScreen
->Height
)
540 msg
->gpi_Mouse
.Y
-= new_top
- (w
->WScreen
->Height
- w
->Height
);
541 retval
= MOVETEST_ADJUSTPOS
;
550 /***********************************************************************************/
552 IPTR
DragBarClass__GM_HANDLEINPUT(Class
*cl
, struct Gadget
*g
, struct gpInput
*msg
)
554 struct GadgetInfo
*gi
= msg
->gpi_GInfo
;
555 IPTR retval
= GMR_MEACTIVE
;
559 struct InputEvent
*ie
= msg
->gpi_IEvent
;
560 struct dragbar_data
*data
= INST_DATA(cl
, g
);
561 struct Window
*w
= msg
->gpi_GInfo
->gi_Window
;
563 switch (ie
->ie_Class
)
565 case IECLASS_RAWMOUSE
:
569 retval
= GMR_NOREUSE
;
570 data
->drag_canceled
= TRUE
;
574 retval
= GMR_NOREUSE
;
578 case IECODE_NOBUTTON
:
580 struct Screen
*scr
= w
->WScreen
;
581 struct InputEvent myie
;
585 /* Can we move to the new position, or is window at edge of display ? */
586 new_left
= scr
->MouseX
- data
->mousex
;
587 new_top
= scr
->MouseY
- data
->mousey
;
589 CopyMem(ie
,&myie
,sizeof (struct InputEvent
));
590 myie
.ie_Code
= SELECTDOWN
; //mouse_leftpress
593 if ((!((GetPrivIBase(IntuitionBase
)->IControlPrefs
.ic_Flags
& ICF_OFFSCREENLAYERS
) && (w
->WScreen
->LayerInfo
.Flags
& LIFLG_SUPPORTS_OFFSCREEN_LAYERS
))) ||
594 MatchHotkey(&myie
,IA_TOGGLEOFFSCREEN
,IntuitionBase
))
596 if (!((GetPrivIBase(IntuitionBase
)->IControlPrefs
.ic_Flags
& ICF_OFFSCREENLAYERS
) && (w
->WScreen
->LayerInfo
.Flags
& LIFLG_SUPPORTS_OFFSCREEN_LAYERS
)))
601 data
->mousex
+= new_left
;
607 data
->mousey
+= new_top
;
611 if (new_left
+ w
->Width
> scr
->Width
)
614 correct_left
= scr
->Width
- w
->Width
; /* align to screen border */
615 data
->mousex
+= new_left
- correct_left
;
616 new_left
= correct_left
;
619 if (new_top
+ w
->Height
> scr
->Height
)
622 correct_top
= scr
->Height
- w
->Height
; /* align to screen border */
623 data
->mousey
+= new_top
- correct_top
;
624 new_top
= correct_top
;
628 if (data
->curleft
!= new_left
|| data
->curtop
!= new_top
)
630 SetDrMd(data
->rp
, COMPLEMENT
);
632 if ((data
->isrendered
) && (!(GetPrivIBase(IntuitionBase
)->IControlPrefs
.ic_Flags
& ICF_OPAQUEMOVE
)))
634 /* Erase old frame */
635 drawwindowframe(w
->WScreen
639 , data
->curleft
+ w
->Width
- 1
640 , data
->curtop
+ w
->Height
- 1
645 data
->curleft
= new_left
;
646 data
->curtop
= new_top
;
648 if (GetPrivIBase(IntuitionBase
)->IControlPrefs
.ic_Flags
& ICF_OPAQUEMOVE
)
650 WORD newx
= new_left
- w
->LeftEdge
, newy
= new_top
- w
->TopEdge
;
656 currenttime
= ie
->ie_TimeStamp
.tv_secs
;
657 currenttime
= currenttime
* 50;
658 currenttime
+= ie
->ie_TimeStamp
.tv_micro
/ 20000;
660 if (currenttime
> data
->lasteventtime
+ 10) //10 delay should result in intuitick freq
662 ih_fire_intuimessage(w
,
667 data
->lasteventtime
= currenttime
;
673 Signal(data
->movetask
,WSIG_MOVE
);
676 CheckLayers(w
->WScreen
, IntuitionBase
);
680 struct Requester
*req
;
682 LockLayers(&w
->WScreen
->LayerInfo
);
689 MoveSizeLayer(BLAYER(w
), newx
, newy
, 0, 0);
692 MoveSizeLayer(WLAYER(w
), newx
, newy
, 0, 0);
694 for (req
= w
->FirstRequest
; req
; req
= req
->OlderRequest
)
696 struct Layer
*layer
= req
->ReqLayer
;
701 int left
, top
, right
, bottom
;
703 left
= data
->curleft
+ req
->LeftEdge
;
704 top
= data
->curtop
+ req
->TopEdge
;
705 right
= left
+ req
->Width
- 1;
706 bottom
= top
+ req
->Height
- 1;
708 if (left
> data
->curleft
+ w
->Width
- 1)
709 left
= data
->curleft
+ w
->Width
- 1;
711 if (top
> data
->curtop
+ w
->Height
- 1)
712 top
= data
->curtop
+ w
->Height
- 1;
714 if (right
> data
->curleft
+ w
->Width
- 1)
715 right
= data
->curleft
+ w
->Width
- 1;
717 if (bottom
> data
->curtop
+ w
->Height
- 1)
718 bottom
= data
->curtop
+ w
->Height
- 1;
720 dx
= left
- layer
->bounds
.MinX
;
721 dy
= top
- layer
->bounds
.MinY
;
722 dw
= right
- left
- layer
->bounds
.MaxX
+ layer
->bounds
.MinX
;
723 dh
= bottom
- top
- layer
->bounds
.MaxY
+ layer
->bounds
.MinY
;
725 MoveSizeLayer(layer
, dx
, dy
, dw
, dh
);
729 CheckLayers(w
->WScreen
, IntuitionBase
);
731 UnlockLayers(&w
->WScreen
->LayerInfo
);
738 if ((!(GetPrivIBase(IntuitionBase
)->IControlPrefs
.ic_Flags
& ICF_OPAQUEMOVE
)) && (!data
->drag_layerlock
))
740 LockLayers(&w
->WScreen
->LayerInfo
);
741 data
->drag_layerlock
= TRUE
;
744 /* Rerender the window frame */
745 drawwindowframe(w
->WScreen
749 , data
->curleft
+ w
->Width
- 1
750 , data
->curtop
+ w
->Height
- 1
752 data
->isrendered
= TRUE
;
757 retval
= GMR_MEACTIVE
;
763 retval
= GMR_NOREUSE
;
764 if (!(GetPrivIBase(IntuitionBase
)->IControlPrefs
.ic_Flags
& ICF_OPAQUEMOVE
)) data
->drag_canceled
= TRUE
;
767 } /* switch (ie->ie_Code) */
772 if ((!(GetPrivIBase(IntuitionBase
)->IControlPrefs
.ic_Flags
& ICF_OPAQUEMOVE
)) && (!data
->drag_layerlock
))
776 currenttime
= ie
->ie_TimeStamp
.tv_secs
;
777 currenttime
= currenttime
* 50;
778 currenttime
+= ie
->ie_TimeStamp
.tv_micro
/ 20000;
780 if (currenttime
> data
->lasteventtime
+ 10)
782 LockLayers(&w
->WScreen
->LayerInfo
);
783 data
->drag_layerlock
= TRUE
;
785 drawwindowframe(w
->WScreen
789 , data
->curleft
+ w
->Width
- 1
790 , data
->curtop
+ w
->Height
- 1
793 data
->lasteventtime
= currenttime
;
794 data
->isrendered
= TRUE
;
803 currenttime
= ie
->ie_TimeStamp
.tv_secs
;
804 currenttime
= currenttime
* 50;
805 currenttime
+= ie
->ie_TimeStamp
.tv_micro
/ 20000;
807 if ((!data
->drag_refreshed
) && currenttime
> data
->lasteventtime
+ 10) //10 delay should result in intuitick freq
809 ih_fire_intuimessage( w
,
814 data
->drag_refreshed
= TRUE
;
815 data
->lasteventtime
= currenttime
;
817 CheckLayers(w
->WScreen
,IntuitionBase
);
820 } /* switch (ie->ie_Class) */
827 /***********************************************************************************/
829 IPTR
DragBarClass__GM_GOINACTIVE(Class
*cl
, struct Gadget
*g
, struct gpGoInactive
*msg
)
831 struct dragbar_data
*data
;
834 data
= INST_DATA(cl
, g
);
836 w
= msg
->gpgi_GInfo
->gi_Window
;
838 /* Always clear last drawn frame */
840 if (data
->isrendered
&& data
->rp
&& (!(GetPrivIBase(IntuitionBase
)->IControlPrefs
.ic_Flags
& ICF_OPAQUEMOVE
)))
843 SetDrMd(data
->rp
, COMPLEMENT
);
845 /* Erase old frame */
846 drawwindowframe(w
->WScreen
850 , data
->curleft
+ w
->Width
- 1
851 , data
->curtop
+ w
->Height
- 1
857 data
->isrendered
= FALSE
;
859 if (!data
->drag_refreshed
) CheckLayers(w
->WScreen
, IntuitionBase
);
864 Signal(data
->movetask
,WSIG_DIE
);
869 if (!data
->drag_canceled
)// && !(GetPrivIBase(IntuitionBase)->IControlPrefs.ic_Flags & ICF_OPAQUEMOVE))
872 , data
->curleft
- w
->LeftEdge
/* dx */
873 , data
->curtop
- w
->TopEdge
/* dy */
878 if (data
->drag_canceled
&& (GetPrivIBase(IntuitionBase
)->IControlPrefs
.ic_Flags
& ICF_OPAQUEMOVE
))
881 , data
->startleft
- w
->LeftEdge
/* dx */
882 , data
->starttop
- w
->TopEdge
/* dy */
887 ih_fire_intuimessage(w
,
893 data
->drag_canceled
= TRUE
;
895 if (data
->drag_layerlock
)
897 UnlockLayers(&w
->WScreen
->LayerInfo
);
898 data
->drag_layerlock
= FALSE
;
902 if (data
->drag_gadgetlock
)
904 ReleaseSemaphore(&GetPrivIBase(IntuitionBase
)->GadgetLock
);
905 data
->drag_gadgetlock
= FALSE
;
910 if (data
->drag_windowlock
)
912 ReleaseSemaphore(&GetPrivIBase(IntuitionBase
)->WindowLock
);
913 data
->drag_windowlock
= FALSE
;
917 /* User throught with drag operation. Unlock layesr and free
923 FreeRastPort(data
->rp
);
927 /* shut off mouse bounds checking. */
928 struct IIHData
*iihd
= (struct IIHData
*)GetPrivIBase(IntuitionBase
)->InputHandler
->is_Data
;
929 iihd
->MouseBoundsActiveFlag
= FALSE
;
936 /***********************************************************************************/
938 IPTR
DragBarClass__NOP(Class
*cl
, Object
*o
, Msg msg
)
943 /***********************************************************************************/
945 IPTR
DragBarClass__GM_HITTEST(Class
*cl
, Object
*o
, Msg msg
)
950 /***********************************************************************************/
952 IPTR
DragBarClass__OM_NEW(Class
*cl
, Object
*o
, Msg msg
)
954 struct Gadget
*g
= (struct Gadget
*)DoSuperMethodA(cl
, o
, msg
);
957 g
->GadgetType
|= GTYP_SYSGADGET
| GTYP_WDRAGGING
;
963 /***********************************************************************************/
965 /*********************
966 ** The SizeButtonClass
967 *********************/
970 #define SIZETYPE_RIGHTBOTTOM 1
971 #define SIZETYPE_RIGHT 2
972 #define SIZETYPE_BOTTOM 3
973 #define SIZETYPE_LEFTBOTTOM 4
974 #define SIZETYPE_LEFT 5
975 #define SIZETYPE_LEFTTOP 6
976 #define SIZETYPE_TOP 7
977 #define SIZETYPE_RIGHTTOP 8
980 /***********************************************************************************/
982 void smartresize(struct Window
*w
,struct sizebutton_data
*data
,Class
*cl
)
984 struct IIHData
*iihdata
= (struct IIHData
*)GetPrivIBase(IntuitionBase
)->InputHandler
->is_Data
;
986 LockLayers(&w
->WScreen
->LayerInfo
);
990 struct Hook
*backfill
;
992 backfill
= BLAYER(w
)->BackFill
;
993 BLAYER(w
)->BackFill
= LAYERS_NOBACKFILL
;
995 /* move outer window first */
996 MoveSizeLayer(BLAYER(w
), data
->left
- w
->LeftEdge
, data
->top
- w
->TopEdge
, data
->width
- w
->Width
, data
->height
- w
->Height
);
998 BLAYER(w
)->BackFill
= backfill
;
1002 struct Hook
*backfill
;
1004 backfill
= WLAYER(w
)->BackFill
;
1005 WLAYER(w
)->BackFill
= LAYERS_NOBACKFILL
;
1006 MoveSizeLayer(WLAYER(w
), data
->left
- w
->LeftEdge
, data
->top
- w
->TopEdge
, data
->width
- w
->Width
, data
->height
- w
->Height
);
1007 WLAYER(w
)->BackFill
= backfill
;
1010 w
->TopEdge
= data
->top
;
1011 w
->LeftEdge
= data
->left
;
1012 w
->Width
= data
->width
;
1013 w
->Height
= data
->height
;
1015 IW(w
)->specialflags
|= SPFLAG_LAYERRESIZED
;
1017 if ((iihdata
->ActiveGadget
) && (w
== iihdata
->GadgetInfo
.gi_Window
))
1019 GetGadgetDomain(iihdata
->ActiveGadget
,
1020 iihdata
->GadgetInfo
.gi_Screen
,
1021 iihdata
->GadgetInfo
.gi_Window
,
1023 &iihdata
->GadgetInfo
.gi_Domain
);
1026 /* Relayout GFLG_REL??? gadgets */
1027 DoGMLayout(w
->FirstGadget
, w
, NULL
, -1, FALSE
, IntuitionBase
);
1029 ih_fire_intuimessage(w
,
1035 CheckLayers(w
->WScreen
, IntuitionBase
);
1037 UnlockLayers(&w
->WScreen
->LayerInfo
);
1040 /***********************************************************************************/
1042 IPTR
SizeButtonClass__GM_GOACTIVE(Class
*cl
, struct Gadget
*g
, struct gpInput
*msg
)
1044 struct InputEvent
*ie
= msg
->gpi_IEvent
;
1045 IPTR retval
= GMR_NOREUSE
;
1049 /* The gadget was activated via mouse input */
1050 struct sizebutton_data
*data
;
1053 /* There is no point in rerendering ourseleves her, as this
1054 is done by a call to RefreshWindowFrame() in the intuition inputhandler
1057 w
= msg
->gpi_GInfo
->gi_Window
;
1059 data
= INST_DATA(cl
, g
);
1061 #ifdef USEWINDOWLOCK
1062 /* do NOT ObtainSemaphore here since this would lead to deadlocks!!! */
1063 /* when the semaphore can not be obtained we simply ignore gadget activation */
1064 if (!(AttemptSemaphore(&GetPrivIBase(IntuitionBase
)->WindowLock
)))
1068 data
->drag_windowlock
= TRUE
;
1071 data
->height
= data
->Height
= w
->Height
;
1072 data
->width
= data
->Width
= w
->Width
;
1073 data
->left
= data
->LeftEdge
= w
->LeftEdge
;
1074 data
->top
= data
->TopEdge
= w
->TopEdge
;
1076 data
->mouseoffsetx
= w
->WScreen
->MouseX
;
1077 data
->mouseoffsety
= w
->WScreen
->MouseY
;
1079 data
->drag_refreshed
= TRUE
;
1080 data
->drag_ticks
= 2;
1083 data
->drag_type
= 0;
1085 if (w
->MouseX
< IW(w
)->sizeimage_width
)
1087 if (w
->MouseY
< IW(w
)->sizeimage_height
) data
->drag_type
= SIZETYPE_LEFTTOP
;
1088 if (w
->MouseY
> w
->Height
- IW(w
)->sizeimage_height
- 1) data
->drag_type
= SIZETYPE_LEFTBOTTOM
;
1089 if (!data
->drag_type
) data
->drag_type
= SIZETYPE_LEFT
;
1092 if ((!data
->drag_type
) && (w
->MouseX
>= IW(w
)->sizeimage_width
) && (w
->MouseX
<= w
->Width
- 1 - IW(w
)->sizeimage_width
))
1094 if (w
->MouseY
< w
->BorderTop
)
1096 data
->drag_type
= SIZETYPE_TOP
;
1098 data
->drag_type
= SIZETYPE_BOTTOM
;
1102 if ((!data
->drag_type
) && (w
->MouseX
> IW(w
)->sizeimage_width
))
1104 if (w
->MouseY
< IW(w
)->sizeimage_height
) data
->drag_type
= SIZETYPE_RIGHTTOP
;
1105 if (w
->MouseY
> w
->Height
- IW(w
)->sizeimage_height
- 1) data
->drag_type
= SIZETYPE_RIGHTBOTTOM
;
1106 if (!data
->drag_type
) data
->drag_type
= SIZETYPE_RIGHT
;
1109 if (!data
->drag_type
) goto fail
;
1112 data
->rp
= CloneRastPort(&w
->WScreen
->RastPort
);
1115 /* Lock all layers while the window is resized.
1116 * Get the gadget lock first to avoid deadlocks
1117 * with ObtainGIRPort. */
1121 #ifdef USEGADGETLOCK
1122 if (AttemptSemaphore(&GetPrivIBase(IntuitionBase
)->GadgetLock
))
1124 data
->drag_gadgetlock
= TRUE
;
1132 LockLayers(&w
->WScreen
->LayerInfo
);
1133 data
->drag_layerlock
= TRUE
;
1137 SetDrMd(data
->rp
, COMPLEMENT
);
1141 drawwindowframe(w
->WScreen
1145 , data
->left
+ data
->width
- 1
1146 , data
->top
+ data
->height
- 1
1150 data
->isrendered
= TRUE
;
1156 currenttime
= ie
->ie_TimeStamp
.tv_secs
;
1157 currenttime
= currenttime
* 50;
1158 currenttime
+= ie
->ie_TimeStamp
.tv_micro
/ 20000;
1159 data
->lasteventtime
= currenttime
;
1162 data
->drag_canceled
= FALSE
;
1164 return GMR_MEACTIVE
;
1168 if (data
->drag_layerlock
)
1170 UnlockLayers(&w
->WScreen
->LayerInfo
);
1171 data
->drag_layerlock
= FALSE
;
1175 #ifdef USEGADGETLOCK
1176 if (data
->drag_gadgetlock
)
1178 ReleaseSemaphore(&GetPrivIBase(IntuitionBase
)->GadgetLock
);
1179 data
->drag_gadgetlock
= FALSE
;
1183 #ifdef USEWINDOWLOCK
1184 if (data
->drag_windowlock
)
1186 ReleaseSemaphore(&GetPrivIBase(IntuitionBase
)->WindowLock
);
1187 data
->drag_windowlock
= FALSE
;
1196 /***********************************************************************************/
1198 IPTR
SizeButtonClass__GM_HANDLEINPUT(Class
*cl
, struct Gadget
*g
, struct gpInput
*msg
)
1200 struct GadgetInfo
*gi
= msg
->gpi_GInfo
;
1201 IPTR retval
= GMR_MEACTIVE
;
1205 struct InputEvent
*ie
= msg
->gpi_IEvent
;
1206 struct sizebutton_data
*data
= INST_DATA(cl
, g
);
1207 struct Window
*w
= msg
->gpi_GInfo
->gi_Window
;
1209 switch (ie
->ie_Class
)
1211 case IECLASS_RAWMOUSE
:
1212 switch (ie
->ie_Code
)
1215 retval
= GMR_NOREUSE
;
1219 case IECODE_NOBUTTON
:
1221 struct Screen
*scr
= w
->WScreen
;
1223 LONG new_height
= 0;
1225 /* Can we move to the new position, or is window at edge of display ? */
1227 switch(data
->drag_type
)
1229 case SIZETYPE_BOTTOM
:
1230 new_height
= data
->Height
+ scr
->MouseY
- data
->mouseoffsety
;
1231 new_width
= data
->Width
;
1235 new_height
= data
->Height
+ data
->mouseoffsety
- scr
->MouseY
;
1236 new_width
= data
->Width
;
1239 case SIZETYPE_RIGHTBOTTOM
:
1240 new_width
= data
->Width
+ scr
->MouseX
- data
->mouseoffsetx
;
1241 new_height
= data
->Height
+ scr
->MouseY
- data
->mouseoffsety
;
1244 case SIZETYPE_LEFTTOP
:
1245 new_width
= data
->Width
+ data
->mouseoffsetx
- scr
->MouseX
;
1246 new_height
= data
->Height
+ data
->mouseoffsety
- scr
->MouseY
;
1249 case SIZETYPE_RIGHTTOP
:
1250 new_width
= data
->Width
+ scr
->MouseX
- data
->mouseoffsetx
;
1251 new_height
= data
->Height
+ data
->mouseoffsety
- scr
->MouseY
;
1254 case SIZETYPE_LEFTBOTTOM
:
1255 new_width
= data
->Width
+ data
->mouseoffsetx
- scr
->MouseX
;
1256 new_height
= data
->Height
+ scr
->MouseY
- data
->mouseoffsety
;
1260 new_width
= data
->Width
+ data
->mouseoffsetx
- scr
->MouseX
;
1261 new_height
= data
->Height
;
1264 case SIZETYPE_RIGHT
:
1265 new_width
= data
->Width
+ scr
->MouseX
- data
->mouseoffsetx
;
1266 new_height
= data
->Height
;
1270 new_width
= data
->Width
+ scr
->MouseX
- data
->mouseoffsetx
;
1271 new_height
= data
->Height
+ scr
->MouseY
- data
->mouseoffsety
;
1276 if (w
->MinWidth
!= 0 && new_width
< (ULONG
)w
->MinWidth
)
1277 new_width
= w
->MinWidth
;
1279 if (w
->MaxWidth
!= 0 && new_width
> (ULONG
)w
->MaxWidth
)
1280 new_width
= w
->MaxWidth
;
1285 if (w
->MinHeight
!= 0 && new_height
< (ULONG
)w
->MinHeight
)
1286 new_height
= w
->MinHeight
;
1288 if (w
->MaxHeight
!= 0 && new_height
> (ULONG
)w
->MaxHeight
)
1289 new_height
= w
->MaxHeight
;
1293 if (!((GetPrivIBase(IntuitionBase
)->IControlPrefs
.ic_Flags
& ICF_OFFSCREENLAYERS
) && (w
->WScreen
->LayerInfo
.Flags
& LIFLG_SUPPORTS_OFFSCREEN_LAYERS
)))
1295 /* limit dimensions so window fits on the screen */
1296 switch (data
->drag_type
)
1298 case SIZETYPE_RIGHT
:
1299 case SIZETYPE_RIGHTTOP
:
1300 case SIZETYPE_RIGHTBOTTOM
:
1301 if (data
->left
+ new_width
> scr
->Width
)
1302 new_width
= scr
->Width
- data
->left
;
1306 case SIZETYPE_LEFTBOTTOM
:
1307 case SIZETYPE_LEFTTOP
:
1308 if (data
->LeftEdge
+ data
->Width
- new_width
< 0)
1309 new_width
+= (data
->LeftEdge
+ data
->Width
- new_width
);
1313 switch (data
->drag_type
)
1315 case SIZETYPE_LEFTBOTTOM
:
1316 case SIZETYPE_BOTTOM
:
1317 case SIZETYPE_RIGHTBOTTOM
:
1318 if (data
->top
+ new_height
> scr
->Height
)
1319 new_height
= scr
->Height
- data
->top
;
1323 case SIZETYPE_LEFTTOP
:
1324 case SIZETYPE_RIGHTTOP
:
1325 if (data
->TopEdge
+ data
->Height
- new_height
< 0)
1326 new_height
+= (data
->TopEdge
+ data
->Height
- new_height
);
1332 if (data
->height
!= new_height
|| data
->width
!= new_width
)
1334 SetDrMd(data
->rp
, COMPLEMENT
);
1336 if (data
->isrendered
&& !OPAQUESIZE
)
1338 /* Erase old frame */
1339 drawwindowframe(w
->WScreen
1343 , data
->left
+ data
->width
- 1
1344 , data
->top
+ data
->height
- 1
1351 switch(data
->drag_type
)
1354 data
->left
= data
->LeftEdge
+ data
->Width
- new_width
;
1357 case SIZETYPE_LEFTTOP
:
1358 data
->left
= data
->LeftEdge
+ data
->Width
- new_width
;
1359 data
->top
= data
->TopEdge
+ data
->Height
- new_height
;
1362 case SIZETYPE_LEFTBOTTOM
:
1363 data
->left
= data
->LeftEdge
+ data
->Width
- new_width
;
1366 case SIZETYPE_RIGHTTOP
:
1367 data
->top
= data
->TopEdge
+ data
->Height
- new_height
;
1371 data
->top
= data
->TopEdge
+ data
->Height
- new_height
;
1376 data
->width
= new_width
;
1377 data
->height
= new_height
;
1379 /* Rerender the window frame */
1382 if (!data
->drag_layerlock
&& !OPAQUESIZE
)
1384 LockLayers(&w
->WScreen
->LayerInfo
);
1385 data
->drag_layerlock
= TRUE
;
1389 data
->drag_refreshed
= FALSE
;
1390 data
->drag_ticks
= 2;
1393 drawwindowframe(w
->WScreen
1397 , data
->left
+ data
->width
- 1
1398 , data
->top
+ data
->height
- 1
1402 data
->isrendered
= TRUE
;
1406 retval
= GMR_MEACTIVE
;
1412 retval
= GMR_NOREUSE
;
1413 data
->drag_canceled
= TRUE
;
1418 } /* switch (ie->ie_Code) */
1423 if (!data
->drag_layerlock
&& !OPAQUESIZE
)
1426 currenttime
= ie
->ie_TimeStamp
.tv_secs
;
1427 currenttime
= currenttime
* 50;
1428 currenttime
+= ie
->ie_TimeStamp
.tv_micro
/ 20000;
1430 if (currenttime
> data
->lasteventtime
+ 10)
1432 LockLayers(&w
->WScreen
->LayerInfo
);
1433 data
->drag_layerlock
= TRUE
;
1435 drawwindowframe(w
->WScreen
1439 , data
->left
+ data
->width
- 1
1440 , data
->top
+ data
->height
- 1
1443 data
->lasteventtime
= currenttime
;
1444 data
->isrendered
= TRUE
;
1452 data
->drag_ticks
--;
1453 if (!data
->drag_refreshed
&& !data
->drag_ticks
&& WindowsReplied(w
->WScreen
,IntuitionBase
))
1455 smartresize(w
,data
,cl
);
1456 data
->drag_refreshed
= TRUE
;
1457 data
->drag_ticks
= 2;
1460 #endif /* USE_OPAQUESIZE */
1465 case IECLASS_NEWTIMER
:
1466 if (OPAQUESIZE
&& !data
->drag_refreshed
&& WindowsReplied(w
->WScreen
,IntuitionBase
))
1468 smartresize(w
,data
,cl
);
1469 data
->drag_refreshed
= TRUE
;
1470 data
->drag_ticks
= 2;
1473 #endif /* __MORPHOS__ */
1475 } /* switch (ie->ie_Class) */
1482 /***********************************************************************************/
1484 IPTR
SizeButtonClass__GM_GOINACTIVE(Class
*cl
, struct Gadget
*g
, struct gpGoInactive
*msg
)
1486 struct sizebutton_data
*data
;
1489 data
= INST_DATA(cl
, g
);
1490 w
= msg
->gpgi_GInfo
->gi_Window
;
1492 /* Allways clear last drawn frame */
1494 if (data
->isrendered
&& data
->rp
)
1497 SetDrMd(data
->rp
, COMPLEMENT
);
1499 /* Erase old frame */
1501 drawwindowframe(w
->WScreen
1505 , data
->left
+ data
->width
- 1
1506 , data
->top
+ data
->height
- 1
1515 data
->drag_canceled
= TRUE
;
1518 data
->isrendered
= FALSE
;
1520 if (data
->drag_layerlock
)
1522 UnlockLayers(&w
->WScreen
->LayerInfo
);
1523 data
->drag_layerlock
= FALSE
;
1526 #ifdef USEGADGETLOCK
1527 if (data
->drag_gadgetlock
)
1529 ReleaseSemaphore(&GetPrivIBase(IntuitionBase
)->GadgetLock
);
1530 data
->drag_gadgetlock
= FALSE
;
1534 #ifdef USEWINDOWLOCK
1535 if (data
->drag_windowlock
)
1537 ReleaseSemaphore(&GetPrivIBase(IntuitionBase
)->WindowLock
);
1538 data
->drag_windowlock
= FALSE
;
1542 //jDc: workarounds refresh pb on GZZ window resize
1543 ((struct IIHData
*)GetPrivIBase(IntuitionBase
)->InputHandler
->is_Data
)->ActiveSysGadget
->Flags
&= ~GFLG_SELECTED
;
1545 if (!data
->drag_canceled
|| OPAQUESIZE
)
1547 if (OPAQUESIZE
&& data
->drag_canceled
)
1549 DoMoveSizeWindow(w
,data
->LeftEdge
,data
->TopEdge
,data
->Width
,data
->Height
,TRUE
,IntuitionBase
);
1553 DoMoveSizeWindow(w
,data
->left
,data
->top
,data
->width
,data
->height
,TRUE
,IntuitionBase
);
1555 //ChangeWindowBox(w,data->left,data->top,data->width,data->height);
1557 data
->drag_canceled
= TRUE
;
1559 /* User throught with drag operation. Unlock layesr and free
1564 FreeRastPort(data
->rp
);
1571 /***********************************************************************************/
1573 IPTR
SizeButtonClass__OM_NEW(Class
*cl
, Object
*o
, Msg msg
)
1575 struct Gadget
*g
= DoSuperMethodA(cl
, o
, msg
);
1578 g
->GadgetType
|= GTYP_SYSGADGET
| GTYP_SIZING
;
1584 /***********************************************************************************/