Updated Sourceforge username and host.
[tangerine.git] / rom / intuition / windowclasses.c
blob9e3e85c2dd6e7edd72a417254bd6b2d3f530930e
1 /*
2 Copyright © 1995-2005, The AROS Development Team. All rights reserved.
3 Copyright © 2001-2003, The MorphOS Development Team. All Rights Reserved.
4 $Id$
6 Classes for window decor stuff, like dragbar, close etc.
7 */
9 /***********************************************************************************/
11 #include <string.h>
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>
26 #include "gadgets.h"
28 #include "intuition_intern.h"
29 #include "inputhandler.h"
30 #include "inputhandler_support.h"
31 #include "inputhandler_actions.h"
33 #ifdef SKINS
34 #include "intuition_customizesupport.h"
35 #include "renderwindowframe.h"
36 #include "mosmisc.h"
37 #endif
39 #undef SDEBUG
40 #undef DEBUG
41 #define SDEBUG 0
42 #define DEBUG 0
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
56 on screen.
60 #if USE_OPAQUESIZE
61 # define OPAQUESIZE (w->MoreFlags & WMFLG_IAMMUI)
62 #else
63 # define OPAQUESIZE 0
64 #endif
66 //#define DELAYEDDRAG
67 //#define DELAYEDSIZE
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)
78 ULONG signals;
80 for (;;)
82 signals = Wait(WSIG_DIE|WSIG_MOVE);
84 if (signals & WSIG_DIE)
86 Forbid();
87 data->movetask = 0;
88 Permit();
89 WindowAction(w,WAC_CHANGEWINDOWBOX,0);
90 return;
93 if (signals & WSIG_MOVE)
95 struct Layer *L;
97 LockLayers(&screen->LayerInfo);
99 for (L = screen->LayerInfo.top_layer; L; L = L->back)
101 if (L->Window == w)
103 //window not closed yet!
104 if (data->curleft != w->LeftEdge || data->curtop != w->TopEdge)
106 struct Requester *req;
108 if (BLAYER(w))
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;
120 if (layer)
122 int dx, dy, dw, dh;
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);
159 #ifdef DAMAGECACHE
160 RecordDamage(screen,IntuitionBase);
161 #endif
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)))
189 if (x1 < 0) x1 = 0;
190 if (y1 < 0) y1 = 0;
191 if (x2 > scrx2) x2 = scrx2;
192 if (y2 > scry2) y2 = scry2;
194 /* paranoia */
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 */
212 if (x2 < x1)
214 /* swap x2 and x1 */
215 x2 ^= x1;
216 x1 ^= x2;
217 x2 ^= x1;
220 if (y2 < y1)
222 /* swap y2 and y1 */
223 y2 ^= y1;
224 y1 ^= y2;
225 y2 ^= y1;
228 if (((x2 - x1) < (DWF_THICK_X * 2)) ||
229 ((y2 - y1) < (DWF_THICK_Y * 2)))
231 cliprectfill(scr, rp, x1, y1, x2, y2, IntuitionBase);
233 else
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 /***********************************************************************************/
248 #if 0
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)
266 return;
269 /* Clear the dragbar */
271 SetAPen(rp, (win->Flags & WFLG_WINDOWACTIVE) ?
272 pens[FILLPEN] : pens[BACKGROUNDPEN]);
274 SetDrMd(rp, JAM1);
276 D(bug("Filling from (%d, %d) to (%d, %d)\n",
277 container.Left,
278 container.Top,
279 container.Left + container.Width - 1,
280 container.Top + container.Height - 1));
282 RectFill(rp,
283 container.Left,
284 container.Top,
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,
292 container.Top,
293 container.Left,
294 container.Top + container.Height - 1 - ((container.Left == 0) ? 0 : 1));
295 RectFill(rp,container.Left + 1,
296 container.Top,
297 container.Left + container.Width - 1,
298 container.Top);
300 SetAPen(rp,pens[SHADOWPEN]);
301 RectFill(rp,container.Left + container.Width - 1,
302 container.Top + 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);
318 textlen = TextFit(rp
319 , win->Title
320 , titlelen
321 , &te
322 , NULL
324 , container.Width - 6
325 , container.Height);
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) */
335 return (IPTR)0;
337 #endif
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;
346 if (ie)
348 /* The gadget was activated via mouse input */
349 struct dragbar_data *data;
350 struct Window *w;
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);
360 #ifdef USEWINDOWLOCK
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)))
367 goto fail;
369 data->drag_windowlock = TRUE;
370 #endif
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);
384 if (data->rp)
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))
395 #ifdef USEGADGETLOCK
396 if (AttemptSemaphore(&GetPrivIBase(IntuitionBase)->GadgetLock))
398 data->drag_gadgetlock = TRUE;
400 else
402 goto fail;
404 #endif
405 #ifndef DELAYEDDRAG
406 LockLayers(&w->WScreen->LayerInfo);
407 data->drag_layerlock = TRUE;
408 #endif
409 } else {
410 if (MOVEHACK)
412 #ifdef __MORPHOS__
413 data->movetask =
414 NewCreateTask(TASKTAG_CODETYPE, CODETYPE_PPC, TASKTAG_PC, (ULONG)MoveTask,
415 TASKTAG_PRI, 0,
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,
420 TAG_DONE);
421 #else
422 // FIXME!
423 #warning Implemente MOVEHACK support for AROS (?)
424 #endif
428 SetDrMd(data->rp, COMPLEMENT);
430 #ifndef DELAYEDDRAG
431 if (!(GetPrivIBase(IntuitionBase)->IControlPrefs.ic_Flags & ICF_OPAQUEMOVE))
432 drawwindowframe(w->WScreen
433 , data->rp
434 , data->curleft
435 , data->curtop
436 , data->curleft + w->Width - 1
437 , data->curtop + w->Height - 1
438 , IntuitionBase
441 data->isrendered = TRUE;
442 #endif
444 data->drag_canceled = FALSE;
447 UQUAD currenttime;
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);
466 return GMR_MEACTIVE;
469 fail:
470 if (data->drag_layerlock)
472 UnlockLayers(&w->WScreen->LayerInfo);
473 data->drag_layerlock = FALSE;
477 #ifdef USEGADGETLOCK
478 if (data->drag_gadgetlock)
480 ReleaseSemaphore(&GetPrivIBase(IntuitionBase)->GadgetLock);
481 data->drag_gadgetlock = FALSE;
483 #endif
485 #ifdef USEWINDOWLOCK
486 if (data->drag_windowlock)
488 ReleaseSemaphore(&GetPrivIBase(IntuitionBase)->WindowLock);
489 data->drag_windowlock = FALSE;
491 #endif
494 return retval;
498 /***********************************************************************************/
500 IPTR DragBarClass__GM_MOVETEST(Class *cl, struct Gadget *g, struct gpInput *msg)
502 IPTR retval = MOVETEST_MOVE;
503 #ifdef SKINS
504 struct dragbar_data *data = INST_DATA(cl, g);
505 struct Window *w = msg->gpi_GInfo->gi_Window;
506 struct InputEvent myie;
507 LONG new_left;
508 LONG new_top;
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))
520 if (new_left < 0)
522 msg->gpi_Mouse.X -= new_left;
523 retval = MOVETEST_ADJUSTPOS;
526 if (new_top < 0)
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;
544 #endif
546 return retval;
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;
557 if (gi)
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:
566 switch (ie->ie_Code)
568 case MENUDOWN:
569 retval = GMR_NOREUSE;
570 data->drag_canceled = TRUE;
571 break;
573 case SELECTUP:
574 retval = GMR_NOREUSE;
575 break;
578 case IECODE_NOBUTTON:
580 struct Screen *scr = w->WScreen;
581 struct InputEvent myie;
582 LONG new_left;
583 LONG new_top;
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
592 #ifdef SKINS
593 if ((!((GetPrivIBase(IntuitionBase)->IControlPrefs.ic_Flags & ICF_OFFSCREENLAYERS) && (w->WScreen->LayerInfo.Flags & LIFLG_SUPPORTS_OFFSCREEN_LAYERS))) ||
594 MatchHotkey(&myie,IA_TOGGLEOFFSCREEN,IntuitionBase))
595 #else
596 if (!((GetPrivIBase(IntuitionBase)->IControlPrefs.ic_Flags & ICF_OFFSCREENLAYERS) && (w->WScreen->LayerInfo.Flags & LIFLG_SUPPORTS_OFFSCREEN_LAYERS)))
597 #endif
599 if (new_left < 0)
601 data->mousex += new_left;
602 new_left = 0;
605 if (new_top < 0)
607 data->mousey += new_top;
608 new_top = 0;
611 if (new_left + w->Width > scr->Width)
613 LONG correct_left;
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)
621 LONG correct_top;
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
636 , data->rp
637 , data->curleft
638 , data->curtop
639 , data->curleft + w->Width - 1
640 , data->curtop + w->Height - 1
641 , IntuitionBase
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;
652 if (newx || newy)
654 UQUAD currenttime;
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,
663 IDCMP_CHANGEWINDOW,
664 CWCODE_MOVESIZE,
666 IntuitionBase);
667 data->lasteventtime = currenttime;
670 if (data->movetask)
672 Forbid();
673 Signal(data->movetask,WSIG_MOVE);
674 Permit();
676 CheckLayers(w->WScreen, IntuitionBase);
678 else
680 struct Requester *req;
682 LockLayers(&w->WScreen->LayerInfo);
684 w->LeftEdge += newx;
685 w->TopEdge += newy;
687 if (BLAYER(w))
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;
698 if (layer)
700 int dx, dy, dw, dh;
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);
735 else
737 #ifdef DELAYEDDRAG
738 if ((!(GetPrivIBase(IntuitionBase)->IControlPrefs.ic_Flags & ICF_OPAQUEMOVE)) && (!data->drag_layerlock))
740 LockLayers(&w->WScreen->LayerInfo);
741 data->drag_layerlock = TRUE;
743 #endif
744 /* Rerender the window frame */
745 drawwindowframe(w->WScreen
746 , data->rp
747 , data->curleft
748 , data->curtop
749 , data->curleft + w->Width - 1
750 , data->curtop + w->Height - 1
751 , IntuitionBase);
752 data->isrendered = TRUE;
757 retval = GMR_MEACTIVE;
759 break;
762 default:
763 retval = GMR_NOREUSE;
764 if (!(GetPrivIBase(IntuitionBase)->IControlPrefs.ic_Flags & ICF_OPAQUEMOVE)) data->drag_canceled = TRUE;
765 break;
767 } /* switch (ie->ie_Code) */
768 break;
770 case IECLASS_TIMER:
771 #ifdef DELAYEDDRAG
772 if ((!(GetPrivIBase(IntuitionBase)->IControlPrefs.ic_Flags & ICF_OPAQUEMOVE)) && (!data->drag_layerlock))
774 UQUAD currenttime;
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
786 , data->rp
787 , data->curleft
788 , data->curtop
789 , data->curleft + w->Width - 1
790 , data->curtop + w->Height - 1
791 , IntuitionBase
793 data->lasteventtime = currenttime;
794 data->isrendered = TRUE;
797 #endif
799 if (data->movetask)
801 UQUAD currenttime;
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,
810 IDCMP_CHANGEWINDOW,
811 CWCODE_MOVESIZE,
813 IntuitionBase);
814 data->drag_refreshed = TRUE;
815 data->lasteventtime = currenttime;
817 CheckLayers(w->WScreen,IntuitionBase);
819 break;
820 } /* switch (ie->ie_Class) */
822 } /* if (gi) */
824 return retval;
827 /***********************************************************************************/
829 IPTR DragBarClass__GM_GOINACTIVE(Class *cl, struct Gadget *g, struct gpGoInactive *msg)
831 struct dragbar_data *data;
832 struct Window *w;
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
847 , data->rp
848 , data->curleft
849 , data->curtop
850 , data->curleft + w->Width - 1
851 , data->curtop + w->Height - 1
852 , IntuitionBase
857 data->isrendered = FALSE;
859 if (!data->drag_refreshed) CheckLayers(w->WScreen, IntuitionBase);
861 Forbid();
862 if (data->movetask)
864 Signal(data->movetask,WSIG_DIE);
865 data->movetask = 0;
867 Permit();
869 if (!data->drag_canceled)// && !(GetPrivIBase(IntuitionBase)->IControlPrefs.ic_Flags & ICF_OPAQUEMOVE))
871 MoveWindow(w
872 , data->curleft - w->LeftEdge /* dx */
873 , data->curtop - w->TopEdge /* dy */
878 if (data->drag_canceled && (GetPrivIBase(IntuitionBase)->IControlPrefs.ic_Flags & ICF_OPAQUEMOVE))
880 MoveWindow(w
881 , data->startleft - w->LeftEdge /* dx */
882 , data->starttop - w->TopEdge /* dy */
887 ih_fire_intuimessage(w,
888 IDCMP_CHANGEWINDOW,
889 CWCODE_MOVESIZE,
891 IntuitionBase);
893 data->drag_canceled = TRUE;
895 if (data->drag_layerlock)
897 UnlockLayers(&w->WScreen->LayerInfo);
898 data->drag_layerlock = FALSE;
901 #ifdef USEGADGETLOCK
902 if (data->drag_gadgetlock)
904 ReleaseSemaphore(&GetPrivIBase(IntuitionBase)->GadgetLock);
905 data->drag_gadgetlock = FALSE;
907 #endif
909 #ifdef USEWINDOWLOCK
910 if (data->drag_windowlock)
912 ReleaseSemaphore(&GetPrivIBase(IntuitionBase)->WindowLock);
913 data->drag_windowlock = FALSE;
915 #endif
917 /* User throught with drag operation. Unlock layesr and free
918 rastport clone
921 if (data->rp)
923 FreeRastPort(data->rp);
924 data->rp = NULL;
927 /* shut off mouse bounds checking. */
928 struct IIHData *iihd = (struct IIHData *)GetPrivIBase(IntuitionBase)->InputHandler->is_Data;
929 iihd->MouseBoundsActiveFlag = FALSE;
931 return TRUE;
936 /***********************************************************************************/
938 IPTR DragBarClass__NOP(Class *cl, Object *o, Msg msg)
940 return (IPTR)0;
943 /***********************************************************************************/
945 IPTR DragBarClass__GM_HITTEST(Class *cl, Object *o, Msg msg)
947 return (IPTR)1;
950 /***********************************************************************************/
952 IPTR DragBarClass__OM_NEW(Class *cl, Object *o, Msg msg)
954 struct Gadget *g = (struct Gadget *)DoSuperMethodA(cl, o, msg);
955 if (g)
957 g->GadgetType |= GTYP_SYSGADGET | GTYP_WDRAGGING;
960 return (IPTR)g;
963 /***********************************************************************************/
965 /*********************
966 ** The SizeButtonClass
967 *********************/
969 #ifdef SKINS
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
978 #endif
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);
988 if (BLAYER(w))
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,
1022 NULL,
1023 &iihdata->GadgetInfo.gi_Domain);
1026 /* Relayout GFLG_REL??? gadgets */
1027 DoGMLayout(w->FirstGadget, w, NULL, -1, FALSE, IntuitionBase);
1029 ih_fire_intuimessage(w,
1030 IDCMP_NEWSIZE,
1033 IntuitionBase);
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;
1047 if (ie)
1049 /* The gadget was activated via mouse input */
1050 struct sizebutton_data *data;
1051 struct Window *w;
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)))
1066 goto fail;
1068 data->drag_windowlock = TRUE;
1069 #endif
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;
1082 #ifdef SKINS
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;
1097 } else {
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;
1110 #endif
1112 data->rp = CloneRastPort(&w->WScreen->RastPort);
1113 if (data->rp)
1115 /* Lock all layers while the window is resized.
1116 * Get the gadget lock first to avoid deadlocks
1117 * with ObtainGIRPort. */
1119 if (!OPAQUESIZE)
1121 #ifdef USEGADGETLOCK
1122 if (AttemptSemaphore(&GetPrivIBase(IntuitionBase)->GadgetLock))
1124 data->drag_gadgetlock = TRUE;
1126 else
1128 goto fail;
1130 #endif
1131 #ifndef DELAYEDSIZE
1132 LockLayers(&w->WScreen->LayerInfo);
1133 data->drag_layerlock = TRUE;
1134 #endif
1137 SetDrMd(data->rp, COMPLEMENT);
1139 #ifndef DELAYEDSIZE
1140 if(!OPAQUESIZE)
1141 drawwindowframe(w->WScreen
1142 , data->rp
1143 , data->left
1144 , data->top
1145 , data->left + data->width - 1
1146 , data->top + data->height - 1
1147 , IntuitionBase
1150 data->isrendered = TRUE;
1151 #endif
1154 UQUAD currenttime;
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;
1167 fail:
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;
1181 #endif
1183 #ifdef USEWINDOWLOCK
1184 if (data->drag_windowlock)
1186 ReleaseSemaphore(&GetPrivIBase(IntuitionBase)->WindowLock);
1187 data->drag_windowlock = FALSE;
1189 #endif
1192 return retval;
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;
1203 if (gi)
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)
1214 case SELECTUP:
1215 retval = GMR_NOREUSE;
1216 break;
1219 case IECODE_NOBUTTON:
1221 struct Screen *scr = w->WScreen;
1222 LONG new_width = 0;
1223 LONG new_height = 0;
1225 /* Can we move to the new position, or is window at edge of display ? */
1226 #ifdef SKINS
1227 switch(data->drag_type)
1229 case SIZETYPE_BOTTOM:
1230 new_height = data->Height + scr->MouseY - data->mouseoffsety;
1231 new_width = data->Width;
1232 break;
1234 case SIZETYPE_TOP:
1235 new_height = data->Height + data->mouseoffsety - scr->MouseY;
1236 new_width = data->Width;
1237 break;
1239 case SIZETYPE_RIGHTBOTTOM:
1240 new_width = data->Width + scr->MouseX - data->mouseoffsetx;
1241 new_height = data->Height + scr->MouseY - data->mouseoffsety;
1242 break;
1244 case SIZETYPE_LEFTTOP:
1245 new_width = data->Width + data->mouseoffsetx - scr->MouseX;
1246 new_height = data->Height + data->mouseoffsety - scr->MouseY;
1247 break;
1249 case SIZETYPE_RIGHTTOP:
1250 new_width = data->Width + scr->MouseX - data->mouseoffsetx;
1251 new_height = data->Height + data->mouseoffsety - scr->MouseY;
1252 break;
1254 case SIZETYPE_LEFTBOTTOM:
1255 new_width = data->Width + data->mouseoffsetx - scr->MouseX;
1256 new_height = data->Height + scr->MouseY - data->mouseoffsety;
1257 break;
1259 case SIZETYPE_LEFT:
1260 new_width = data->Width + data->mouseoffsetx - scr->MouseX;
1261 new_height = data->Height;
1262 break;
1264 case SIZETYPE_RIGHT:
1265 new_width = data->Width + scr->MouseX - data->mouseoffsetx;
1266 new_height = data->Height;
1267 break;
1269 #else
1270 new_width = data->Width + scr->MouseX - data->mouseoffsetx;
1271 new_height = data->Height + scr->MouseY - data->mouseoffsety;
1272 #endif
1273 if (new_width < 0)
1274 new_width = 1;
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;
1282 if (new_height < 0)
1283 new_height = 1;
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;
1292 #ifdef SKINS
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;
1303 break;
1305 case SIZETYPE_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);
1310 break;
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;
1320 break;
1322 case SIZETYPE_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);
1327 break;
1330 #endif
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
1340 , data->rp
1341 , data->left
1342 , data->top
1343 , data->left + data->width - 1
1344 , data->top + data->height - 1
1345 , IntuitionBase
1350 #ifdef SKINS
1351 switch(data->drag_type)
1353 case SIZETYPE_LEFT:
1354 data->left = data->LeftEdge + data->Width - new_width;
1355 break;
1357 case SIZETYPE_LEFTTOP:
1358 data->left = data->LeftEdge + data->Width - new_width;
1359 data->top = data->TopEdge + data->Height - new_height;
1360 break;
1362 case SIZETYPE_LEFTBOTTOM:
1363 data->left = data->LeftEdge + data->Width - new_width;
1364 break;
1366 case SIZETYPE_RIGHTTOP:
1367 data->top = data->TopEdge + data->Height - new_height;
1368 break;
1370 case SIZETYPE_TOP:
1371 data->top = data->TopEdge + data->Height - new_height;
1372 break;
1374 #endif
1376 data->width = new_width;
1377 data->height = new_height;
1379 /* Rerender the window frame */
1381 #ifdef DELAYEDSIZE
1382 if (!data->drag_layerlock && !OPAQUESIZE)
1384 LockLayers(&w->WScreen->LayerInfo);
1385 data->drag_layerlock = TRUE;
1387 #endif
1389 data->drag_refreshed = FALSE;
1390 data->drag_ticks = 2;
1392 if (!OPAQUESIZE)
1393 drawwindowframe(w->WScreen
1394 , data->rp
1395 , data->left
1396 , data->top
1397 , data->left + data->width - 1
1398 , data->top + data->height - 1
1399 , IntuitionBase
1402 data->isrendered = TRUE;
1406 retval = GMR_MEACTIVE;
1408 break;
1411 default:
1412 retval = GMR_NOREUSE;
1413 data->drag_canceled = TRUE;
1414 break;
1418 } /* switch (ie->ie_Code) */
1419 break;
1421 case IECLASS_TIMER:
1422 #ifdef DELAYEDSIZE
1423 if (!data->drag_layerlock && !OPAQUESIZE)
1425 UQUAD currenttime;
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
1436 , data->rp
1437 , data->left
1438 , data->top
1439 , data->left + data->width - 1
1440 , data->top + data->height - 1
1441 , IntuitionBase
1443 data->lasteventtime = currenttime;
1444 data->isrendered = TRUE;
1447 #endif
1449 #if USE_OPAQUESIZE
1450 if (OPAQUESIZE)
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 */
1462 break;
1464 #ifdef __MORPHOS__
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;
1472 break;
1473 #endif /* __MORPHOS__ */
1475 } /* switch (ie->ie_Class) */
1477 } /* if (gi) */
1479 return retval;
1482 /***********************************************************************************/
1484 IPTR SizeButtonClass__GM_GOINACTIVE(Class *cl, struct Gadget *g, struct gpGoInactive *msg)
1486 struct sizebutton_data *data;
1487 struct Window *w;
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 */
1500 if (!OPAQUESIZE)
1501 drawwindowframe(w->WScreen
1502 , data->rp
1503 , data->left
1504 , data->top
1505 , data->left + data->width - 1
1506 , data->top + data->height - 1
1507 , IntuitionBase
1511 else
1513 if (!OPAQUESIZE)
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;
1532 #endif
1534 #ifdef USEWINDOWLOCK
1535 if (data->drag_windowlock)
1537 ReleaseSemaphore(&GetPrivIBase(IntuitionBase)->WindowLock);
1538 data->drag_windowlock = FALSE;
1540 #endif
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);
1551 else
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
1560 rastport clone
1562 if (data->rp)
1564 FreeRastPort(data->rp);
1565 data->rp = NULL;
1568 return TRUE;
1571 /***********************************************************************************/
1573 IPTR SizeButtonClass__OM_NEW(Class *cl, Object *o, Msg msg)
1575 struct Gadget *g = DoSuperMethodA(cl, o, msg);
1576 if (g)
1578 g->GadgetType |= GTYP_SYSGADGET | GTYP_SIZING;
1581 return (IPTR)g;
1584 /***********************************************************************************/