Some fix for scrolling with lasso.
[tangerine.git] / workbench / libs / muimaster / classes / window.c
blob48b1910d25e5f11fb73ea2390b41a514fd06ec1f
1 /*
2 Copyright 1999, David Le Corfec.
3 Copyright 2002-2006, The AROS Development Team.
4 All rights reserved.
6 $Id$
7 */
8 #include <exec/types.h>
9 #include <exec/memory.h>
11 #include <string.h>
13 #include <intuition/imageclass.h>
14 #include <intuition/icclass.h>
15 #include <intuition/gadgetclass.h>
16 #include <clib/alib_protos.h>
17 #include <graphics/gfxmacros.h>
18 #include <proto/exec.h>
19 #include <proto/intuition.h>
20 #include <proto/utility.h>
21 #include <proto/graphics.h>
22 #include <proto/commodities.h>
23 #include <proto/layers.h>
24 #include <proto/gadtools.h>
25 #include <proto/muimaster.h>
27 #define MUI_OBSOLETE /* for the obsolete menu stuff */
29 #include "mui.h"
30 #include "support.h"
31 #include "classes/window.h"
32 #include "classes/area.h"
33 #include "imspec.h"
34 #include "prefs.h"
35 #include "dragndrop.h"
37 #include "muimaster_intern.h"
39 //#define MYDEBUG 1
40 #include "debug.h"
42 extern struct Library *MUIMasterBase;
44 static const int __version = 1;
45 static const int __revision = 1;
47 #define IM(x) ((struct Image*)(x))
48 #define G(x) ((struct Gadget*)(x))
49 #define GADGETID(x) (((struct Gadget*)(x))->GadgetID)
51 /* this is for the cycle list */
52 struct ObjNode
54 struct MinNode node;
55 Object *obj;
58 /* For the gadget ids */
59 struct IDNode
61 struct MinNode node;
62 UWORD id;
65 struct MUI_ImageSpec_intern;
67 struct MUI_WindowData
69 struct MUI_RenderInfo wd_RenderInfo;
70 struct MUI_MinMax wd_MinMax;
71 struct IBox wd_AltDim; /* zoomed dimensions */
72 BOOL wd_ZoomGadget; /* enable/disable zoomgadget (altdim stuff) */
73 APTR wd_MemoryPool; /* for nodes and stuff to deallocate at OM_DISPOSE */
74 struct MinList wd_CycleChain; /* objects activated with tab */
75 struct MinList wd_EHList; /* event handlers */
76 struct MinList wd_CCList; /* control chars */
77 struct MinList wd_IDList; /* gadget ids */
78 ULONG wd_Events; /* events received */
79 ULONG wd_CrtFlags; /* window creation flags, see below */
80 Object *wd_ActiveObject; /* the active object */
81 Object *wd_OldActive; /* active object before window was closed */
82 APTR wd_DefaultObject;
83 ULONG wd_ID;
84 STRPTR wd_Title;
85 STRPTR wd_ScreenTitle;
86 LONG wd_Height; /* Current dimensions */
87 LONG wd_Width;
88 LONG wd_X;
89 LONG wd_Y;
90 LONG wd_ReqHeight; /* given by programmer */
91 LONG wd_ReqWidth;
92 APTR wd_RootObject; /* unique child */
93 ULONG wd_Flags; /* various status flags */
94 struct MUI_ImageSpec_intern *wd_Background;
95 ULONG wd_DisabledKeys;
96 BOOL wd_NoMenus; /* MUIA_Window_NoMenus */
98 Object *wd_DragObject; /* the object which is being dragged */
99 struct Window *wd_DropWindow; /* the destination window, for faster access */
100 Object *wd_DropObject; /* the destination object */
101 struct DragNDrop *wd_dnd;
102 struct MUI_DragImage *wd_DragImage;
104 Object *wd_Menustrip; /* The menustrip object which is actually is used (either apps or windows or NULL) */
105 Object * wd_ChildMenustrip; /* If window has an own Menustrip */
106 struct Menu *wd_Menu; /* the intuition menustrip */
108 Object *wd_VertProp;
109 Object *wd_UpButton;
110 Object *wd_DownButton;
112 Object *wd_HorizProp;
113 Object *wd_LeftButton;
114 Object *wd_RightButton;
115 Object *wd_RefWindow;
117 Object *wd_HelpObject;
118 APTR wd_HelpBubble;
119 WORD wd_HelpTicker;
121 struct Screen *wd_UserScreen;
122 STRPTR wd_UserPublicScreen;
123 LONG wd_XStore; /*store MUIV_Window_LeftEdge_Centered Tags etc
124 because wd_X is overwritten by a value in CalcDimension
125 Popup windows work ok on AmiGG when main window is move
127 LONG wd_YStore;
130 #ifndef WFLG_SIZEGADGET
132 #define WFLG_CLOSEGADGET (1<<0) /* has close gadget */
133 #define WFLG_SIZEGADGET (1<<1) /* has size gadget */
134 #define WFLG_BACKDROP (1<<2) /* is backdrop window */
135 #define WFLG_BORDERLESS (1<<3) /* has no borders */
136 #define WFLG_DEPTHGADGET (1<<4) /* has depth gadget */
137 #define WFLG_DRAGBAR (1<<5) /* is draggable */
138 #define WFLG_SIZEBRIGHT (1<<6) /* size gadget is in right border */
140 #endif
142 /* wd_Flags */
143 #define MUIWF_OPENED (1<<0) /* window currently opened */
144 #define MUIWF_HIDDEN (1<<1) /* window currently iconified */
145 #define MUIWF_ACTIVE (1<<2) /* window currently active */
146 #define MUIWF_RESIZING (1<<4) /* window currently resizing, for simple refresh */
147 #define MUIWF_DONTACTIVATE (1<<7) /* do not activate the window when opening */
148 #define MUIWF_USERIGHTSCROLLER (1<<8) /* window should have a right scroller */
149 #define MUIWF_USEBOTTOMSCROLLER (1<<9) /* window should have a bottom scroller */
150 #define MUIWF_ERASEAREA (1<<10) /* Erase area after a window resize */
151 #define MUIWF_ISAPPWINDOW (1<<11) /* Is an app window (user can drop icons on it) */
152 #define MUIWF_ISSUBWINDOW (1<<12) /* Dont get automatically disposed with app */
153 #define MUIWF_BUBBLEMODE (1<<13) /* Quick bubble mode. Bubbles appear quick when moving */
154 #define MUIWF_OPENONUNHIDE (1<<14) /* Open the window when unhiding */
155 #define MUIWF_SCREENLOCKED (1<<15) /* A pub screen was locked in SetupRenderInfo. Unlock it in CleanupRenderInfo! */
156 #define MUIWF_OBJECTGOACTIVESENT (1<<16) /* A MUIM_GoActive msg was sent to window's active object */
158 #define BUBBLEHELP_TICKER_FIRST 10
159 #define BUBBLEHELP_TICKER_LATER 3
161 ULONG screenmode;
164 struct __dummyXFC3__
166 struct MUI_NotifyData mnd;
167 struct MUI_WindowData mwd;
170 #define muiWindowData(obj) (&(((struct __dummyXFC3__ *)(obj))->mwd))
172 static ULONG DoHalfshineGun(ULONG a, ULONG b)
174 ULONG val = ((((a)>>24) + 3 * ((b)>>24)) / 4);
175 val = val + (val<<8) + (val<<16) + (val<<24);
176 return val;
179 static ULONG DoHalfshadowGun(ULONG a, ULONG b)
181 ULONG val = ((((a)>>24) + 5 * ((b)>>24)) / 6);
182 val = val + (val<<8) + (val<<16) + (val<<24);
183 return val;
186 static Object *CreateSysimage(struct DrawInfo *dri, ULONG which)
188 return NewObject(NULL, "sysiclass",
189 SYSIA_DrawInfo, (IPTR)dri,
190 SYSIA_Which, which,
191 TAG_DONE);
194 static void EnqueueByPriAndAddress(struct List *list, struct Node *node)
196 struct Node *scannode;
198 /* Sort by priority and by node address, so that a
199 "remove - modify - enqueue" sequence will re-add
200 the node at the same place in the list it was
201 initially */
203 ForeachNode(list, scannode)
205 if (((struct Node *)node)->ln_Pri > scannode->ln_Pri) break;
206 if (((struct Node *)node)->ln_Pri == scannode->ln_Pri)
208 if ((IPTR)node > (IPTR)scannode) break;
212 Insert(list, (struct Node *)node, scannode->ln_Pred);
216 static BOOL SetupRenderInfo(Object *obj, struct MUI_WindowData *data, struct MUI_RenderInfo *mri)
218 ULONG rgbtable[3 * 3];
219 Object *temp_obj;
220 ULONG val;
221 int i;
222 screenmode=muiGlobalInfo(obj)->mgi_Prefs->screenmodeid;
224 if (screenmode != -1)
226 if (muiGlobalInfo(obj)->mgi_Prefs->screenaddress)
227 data->wd_UserScreen=muiGlobalInfo(obj)->mgi_Prefs->screenaddress;
228 else
229 data->wd_UserScreen = OpenScreenTags (
231 // SA_Width, 1280,
232 // SA_Height, 1024,
233 // SA_Depth, 24,
234 SA_DisplayID,screenmode,
235 SA_SharePens, TRUE,
236 SA_FullPalette, TRUE,
237 SA_LikeWorkbench,TRUE,
238 TAG_DONE
240 muiGlobalInfo(obj)->mgi_Prefs->screenaddress=data->wd_UserScreen; // so screen is open only once
244 if (data->wd_UserScreen)
246 mri->mri_Screen = data->wd_UserScreen;
248 else
250 if (!(mri->mri_Screen = LockPubScreen(data->wd_UserPublicScreen)))
252 if (!(mri->mri_Screen = LockPubScreen(NULL)))
254 return FALSE;
258 data->wd_Flags |= MUIWF_SCREENLOCKED;
261 if (!(mri->mri_DrawInfo = GetScreenDrawInfo(mri->mri_Screen)))
263 if (data->wd_Flags & MUIWF_SCREENLOCKED)
265 UnlockPubScreen(NULL,mri->mri_Screen);
266 data->wd_Flags &= ~MUIWF_SCREENLOCKED;
268 return FALSE;
271 mri->mri_Colormap = mri->mri_Screen->ViewPort.ColorMap;
272 mri->mri_ScreenWidth = mri->mri_Screen->Width;
273 mri->mri_ScreenHeight = mri->mri_Screen->Height;
275 if (mri->mri_ScreenWidth / mri->mri_ScreenHeight < 2)
277 mri->mri_Flags |= MUIMRI_THINFRAMES;
280 if (GetBitMapAttr(mri->mri_Screen->RastPort.BitMap, BMA_DEPTH) >= 15)
282 mri->mri_Flags |= MUIMRI_TRUECOLOR;
285 mri->mri_PensStorage[MPEN_SHINE] = mri->mri_DrawInfo->dri_Pens[SHINEPEN];
286 mri->mri_PensStorage[MPEN_BACKGROUND] = mri->mri_DrawInfo->dri_Pens[BACKGROUNDPEN];
287 mri->mri_PensStorage[MPEN_SHADOW] = mri->mri_DrawInfo->dri_Pens[SHADOWPEN];
288 mri->mri_PensStorage[MPEN_TEXT] = mri->mri_DrawInfo->dri_Pens[TEXTPEN];
289 mri->mri_PensStorage[MPEN_FILL] = mri->mri_DrawInfo->dri_Pens[FILLPEN];
291 GetRGB32(mri->mri_Colormap, mri->mri_DrawInfo->dri_Pens[SHINEPEN], 1, rgbtable);
292 GetRGB32(mri->mri_Colormap, mri->mri_DrawInfo->dri_Pens[BACKGROUNDPEN], 1, rgbtable+3);
293 GetRGB32(mri->mri_Colormap, mri->mri_DrawInfo->dri_Pens[SHADOWPEN], 1, rgbtable+6);
295 mri->mri_PensStorage[MPEN_HALFSHINE] = ObtainBestPenA
297 mri->mri_Colormap,
298 DoHalfshineGun(rgbtable[0], rgbtable[3]),
299 DoHalfshineGun(rgbtable[1], rgbtable[4]),
300 DoHalfshineGun(rgbtable[2], rgbtable[5]), NULL
303 mri->mri_PensStorage[MPEN_HALFSHADOW] = ObtainBestPenA
305 mri->mri_Colormap,
306 DoHalfshadowGun(rgbtable[6], rgbtable[3]),
307 DoHalfshadowGun(rgbtable[7], rgbtable[4]),
308 DoHalfshadowGun(rgbtable[8], rgbtable[5]), NULL
311 /* I'm really not sure that MUI does this for MPEN_MARK, but it seems mostly acceptable -dlc */
312 mri->mri_PensStorage[MPEN_MARK] = ObtainBestPenA
314 mri->mri_Colormap, 0xf4f4f4f4, 0xb5b5b5b5, 0x8b8b8b8b, NULL
317 mri->mri_Pens = mri->mri_PensStorage;
319 for (i = 0; i < -MUIV_Font_NegCount; i++)
321 mri->mri_Fonts[i] = NULL;
324 if (data->wd_Flags & MUIWF_USEBOTTOMSCROLLER)
326 mri->mri_LeftImage = CreateSysimage(mri->mri_DrawInfo, LEFTIMAGE);
327 mri->mri_RightImage = CreateSysimage(mri->mri_DrawInfo, RIGHTIMAGE);
329 else
331 mri->mri_LeftImage = mri->mri_RightImage = NULL;
334 if (data->wd_Flags & MUIWF_USERIGHTSCROLLER)
336 mri->mri_UpImage = CreateSysimage(mri->mri_DrawInfo, UPIMAGE);
337 mri->mri_DownImage = CreateSysimage(mri->mri_DrawInfo, DOWNIMAGE);
339 else
341 mri->mri_UpImage = mri->mri_DownImage = NULL;
344 if ((data->wd_Flags & MUIWF_USEBOTTOMSCROLLER) ||
345 (data->wd_Flags & MUIWF_USERIGHTSCROLLER))
346 mri->mri_SizeImage = CreateSysimage(mri->mri_DrawInfo, SIZEIMAGE);
347 else
348 mri->mri_SizeImage = NULL;
350 if (data->wd_CrtFlags & WFLG_BORDERLESS)
352 /* Infact borderless windows could also have borders (if they have a window title e.g. but
353 since they look ugly anywhy we ignore it for now */
354 mri->mri_BorderLeft = 0;
355 mri->mri_BorderRight = 0;
356 mri->mri_BorderTop = 0;
357 mri->mri_BorderBottom = 0;
359 else
361 mri->mri_BorderLeft = mri->mri_Screen->WBorLeft;
362 mri->mri_BorderTop = mri->mri_Screen->WBorTop + mri->mri_Screen->Font->ta_YSize+ 1;
363 temp_obj = NewObject
365 NULL, "sysiclass",
366 SYSIA_DrawInfo, (IPTR)mri->mri_DrawInfo,
367 SYSIA_Which, SIZEIMAGE,
368 TAG_DONE
370 if (temp_obj)
372 GetAttr(IA_Height,temp_obj,&val);
373 DisposeObject(temp_obj);
374 mri->mri_BorderBottom = val;
376 else
377 mri->mri_BorderBottom = mri->mri_Screen->WBorBottom;
380 return TRUE;
383 static void CleanupRenderInfo(struct MUI_WindowData *data, struct MUI_RenderInfo *mri)
385 int i;
387 if (mri->mri_LeftImage) {DisposeObject(mri->mri_LeftImage);mri->mri_LeftImage=NULL;};
388 if (mri->mri_RightImage){DisposeObject(mri->mri_RightImage);mri->mri_RightImage=NULL;};
389 if (mri->mri_UpImage) {DisposeObject(mri->mri_UpImage);mri->mri_UpImage=NULL;};
390 if (mri->mri_DownImage) {DisposeObject(mri->mri_DownImage);mri->mri_DownImage=NULL;};
391 if (mri->mri_SizeImage) {DisposeObject(mri->mri_SizeImage);mri->mri_SizeImage=NULL;};
393 /* bug("CleanupRenderInfo\n"); */
394 for (i = 0; i < -MUIV_Font_NegCount; i++)
396 if (mri->mri_Fonts[i])
398 /* bug("CleanupRenderInfo: closing font %p (%s/%d)\n", */
399 /* mri->mri_Fonts[i], mri->mri_Fonts[i]->tf_Message.mn_Node.ln_Name, */
400 /* mri->mri_Fonts[i]->tf_YSize); */
401 CloseFont(mri->mri_Fonts[i]);
402 mri->mri_Fonts[i] = NULL;
405 ReleasePen(mri->mri_Colormap, mri->mri_PensStorage[MPEN_MARK]);
406 ReleasePen(mri->mri_Colormap, mri->mri_PensStorage[MPEN_HALFSHADOW]);
407 ReleasePen(mri->mri_Colormap, mri->mri_PensStorage[MPEN_HALFSHINE]);
408 FreeScreenDrawInfo(mri->mri_Screen, mri->mri_DrawInfo);
409 mri->mri_DrawInfo = NULL;
411 if (data->wd_UserScreen)
413 CloseScreen(mri->mri_Screen);
417 if (data->wd_Flags & MUIWF_SCREENLOCKED)
419 UnlockPubScreen(NULL, mri->mri_Screen);
420 data->wd_Flags &= ~MUIWF_SCREENLOCKED;
422 mri->mri_Screen = NULL;
425 static void ShowRenderInfo(struct MUI_RenderInfo *mri)
427 if (mri->mri_BufferBM)
429 mri->mri_RastPort = &mri->mri_BufferRP;
431 else
433 mri->mri_RastPort = mri->mri_Window->RPort;
437 static void HideRenderInfo(struct MUI_RenderInfo *mri)
439 mri->mri_RastPort = NULL;
442 static ULONG GetDefaultEvents (void)
444 return IDCMP_NEWSIZE | IDCMP_REFRESHWINDOW
445 | IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE | IDCMP_MENUPICK
446 | IDCMP_CLOSEWINDOW | IDCMP_RAWKEY | IDCMP_INTUITICKS
447 | IDCMP_ACTIVEWINDOW | IDCMP_INACTIVEWINDOW;
450 static void ChangeEvents (struct MUI_WindowData *data, ULONG new_events)
452 struct MinNode *mn;
453 struct MUI_EventHandlerNode *ehn;
454 ULONG old_events = data->wd_Events;
456 for (mn = data->wd_EHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
458 ehn = (struct MUI_EventHandlerNode *)mn;
459 new_events |= ehn->ehn_Events;
462 /* sba: kill the IDCMP_VANILLAKEY flag. MUI doesn't do this but programs
463 ** which use this will behave different if they request for this flag
464 ** (also on MUI)
466 new_events &= ~IDCMP_VANILLAKEY;
468 data->wd_Events = new_events;
469 if ((old_events != new_events) && (data->wd_Flags & MUIWF_OPENED))
471 ModifyIDCMP(data->wd_RenderInfo.mri_Window, new_events);
475 static void CalcWindowPosition(Object *obj, struct MUI_WindowData *data);
476 static void CreateWindowScrollbars(Object *obj, struct MUI_WindowData *data);
477 static void CalcAltDimensions(Object *obj, struct MUI_WindowData *data);
478 static void UndisplayWindow(Object *obj, struct MUI_WindowData *data);
479 static struct ObjNode *FindObjNode(struct MinList *list, Object *obj);
481 static BOOL DisplayWindow(Object *obj, struct MUI_WindowData *data)
483 struct Window *win;
484 ULONG flags = data->wd_CrtFlags;
485 struct IBox altdims;
486 ULONG backfill;
488 struct Menu *menu = NULL;
489 struct NewMenu *newmenu = NULL;
490 APTR visinfo = NULL;
492 if (!(data->wd_Flags & MUIWF_DONTACTIVATE))
494 flags |= WFLG_ACTIVATE;
499 data->wd_MinMax.MinHeight == data->wd_MinMax.MaxHeight
500 && data->wd_MinMax.MinWidth == data->wd_MinMax.MaxWidth
502 flags &= ~WFLG_SIZEGADGET;
504 if (!(flags & WFLG_SIZEBRIGHT))
505 flags |= WFLG_SIZEBBOTTOM;
507 CalcWindowPosition(obj, data);
509 if ((visinfo = GetVisualInfoA(data->wd_RenderInfo.mri_Screen,NULL)))
511 if (data->wd_Menustrip)
513 get(data->wd_Menustrip,MUIA_Menuitem_NewMenu,&newmenu);
514 if (newmenu)
516 if ((menu = CreateMenusA(newmenu,NULL)))
518 struct TagItem tags[] =
520 { GTMN_NewLookMenus, TRUE },
521 { TAG_DONE, (IPTR)NULL }
523 LayoutMenusA(menu, visinfo, tags);
527 FreeVisualInfo(visinfo);
530 CreateWindowScrollbars(obj, data);
531 CalcAltDimensions(obj, data);
532 altdims = data->wd_AltDim;
533 /* hack to account for border size, as we only know the innersize and must give
534 * the total size.
536 altdims.Width += data->wd_RenderInfo.mri_Screen->WBorLeft + data->wd_RenderInfo.mri_Screen->WBorRight;
537 altdims.Height += data->wd_RenderInfo.mri_Screen->WBorTop + data->wd_RenderInfo.mri_Screen->WBorBottom +
538 data->wd_RenderInfo.mri_DrawInfo->dri_Font->tf_YSize + 1;
540 if (muiGlobalInfo(obj)->mgi_Prefs->window_redraw == WINDOW_REDRAW_WITHOUT_CLEAR)
541 backfill = WA_BackFill;
542 else
543 backfill = TAG_IGNORE;
545 if (muiGlobalInfo(obj)->mgi_Prefs->window_refresh == WINDOW_REFRESH_SMART)
546 flags &= ~WFLG_SIMPLE_REFRESH;
547 set(_app(obj),MUIA_Application_SearchWinId,data->wd_ID);
548 struct windowpos *winp=0;
549 get(_app(obj),MUIA_Application_GetWinPos,&winp);
550 if (winp)
552 if (data->wd_RenderInfo.mri_ScreenWidth > (data->wd_X + data->wd_Width))
554 data->wd_X=winp->x1;
555 data->wd_Width=winp->w1;
557 if (data->wd_RenderInfo.mri_ScreenHeight > (data->wd_Y + data->wd_Height))
559 data->wd_Y=winp->y1;
560 data->wd_Height=winp->h1;
565 win = OpenWindowTags
567 NULL,
569 WA_Left, (IPTR) data->wd_X,
570 WA_Top, (IPTR) data->wd_Y,
571 WA_Flags, (IPTR) flags,
572 data->wd_Title ?
573 WA_Title :
574 TAG_IGNORE, (IPTR) data->wd_Title,
575 data->wd_ScreenTitle ?
576 WA_ScreenTitle :
577 TAG_IGNORE, (IPTR) data->wd_ScreenTitle,
578 WA_CustomScreen, (IPTR) data->wd_RenderInfo.mri_Screen,
579 WA_InnerWidth, (IPTR) data->wd_Width,
580 WA_InnerHeight, (IPTR) data->wd_Height,
581 WA_AutoAdjust, (IPTR) TRUE,
582 WA_NewLookMenus, (IPTR) TRUE,
583 data->wd_NoMenus ?
584 WA_RMBTrap :
585 TAG_IGNORE, (IPTR) TRUE,
586 WA_Gadgets, (IPTR) (data->wd_VertProp ? data->wd_VertProp : data->wd_HorizProp),
587 data->wd_ZoomGadget ?
588 WA_Zoom :
589 TAG_IGNORE, (IPTR) &altdims,
590 backfill, (IPTR) LAYERS_NOBACKFILL,
591 TAG_DONE
594 if (win)
596 int hborders = win->BorderLeft + win->BorderRight;
597 int vborders = win->BorderTop + win->BorderBottom;
599 /* recalc window size (which will hopefully equal our requested size) */
600 data->wd_Width = win->GZZWidth;
601 data->wd_Height = win->GZZHeight;
603 /* set window limits according to window contents */
604 WindowLimits
606 win, data->wd_MinMax.MinWidth + hborders,
607 data->wd_MinMax.MinHeight + vborders,
608 data->wd_MinMax.MaxWidth + hborders,
609 data->wd_MinMax.MaxHeight + vborders
612 win->UserData = (char*)data->wd_RenderInfo.mri_WindowObject;
613 win->UserPort = muiGlobalInfo(obj)->mgi_WindowsPort; /* Same port for all windows */
614 ModifyIDCMP(win, data->wd_Events);
616 data->wd_RenderInfo.mri_Window = win;
617 data->wd_RenderInfo.mri_VertProp = data->wd_VertProp;
618 data->wd_RenderInfo.mri_HorizProp = data->wd_HorizProp;
619 SetDrMd(win->RPort,JAM1); //text is draw wrong in toolbarclass if not set
621 if (menu)
623 data->wd_Menu = menu;
624 SetMenuStrip(win,menu);
627 if (flags & WFLG_ACTIVATE)
629 data->wd_Flags |= MUIWF_ACTIVE;
632 return TRUE;
635 if (menu) FreeMenus(menu);
636 UndisplayWindow(obj, data);
638 return FALSE;
642 static void UndisplayWindow(Object *obj, struct MUI_WindowData *data)
644 struct Window *win = data->wd_RenderInfo.mri_Window;
645 if ((data->wd_XStore >= 0) && (data->wd_YStore >= 0))
647 DoMethod(obj,MUIM_Window_Snapshot,0);
650 data->wd_RenderInfo.mri_Window = NULL;
651 data->wd_RenderInfo.mri_VertProp = NULL;
652 data->wd_RenderInfo.mri_HorizProp = NULL;
654 data->wd_Flags &= ~MUIWF_ACTIVE;
656 if (win != NULL)
658 /* store position and size */
659 if (data->wd_XStore >=0)
660 data->wd_X = win->LeftEdge;
661 else
662 data->wd_X = data->wd_XStore;
663 if (data->wd_YStore >=0)
664 data->wd_Y = win->TopEdge;
665 else
666 data->wd_Y = data->wd_YStore;
667 data->wd_Width = win->GZZWidth;
668 data->wd_Height = win->GZZHeight;
670 ClearMenuStrip(win);
671 if (data->wd_Menu)
673 FreeMenus(data->wd_Menu);
674 data->wd_Menu = NULL;
677 if (win->UserPort)
679 struct IntuiMessage *msg, *succ;
681 /* remove all messages pending for this window */
682 Forbid();
685 msg = (struct IntuiMessage *)win->UserPort->mp_MsgList.lh_Head;
686 (succ = (struct IntuiMessage *)msg->ExecMessage.mn_Node.ln_Succ);
687 msg = succ
690 if (msg->IDCMPWindow == win)
692 Remove((struct Node *)msg);
693 ReplyMsg((struct Message *)msg);
696 win->UserPort = NULL;
697 ModifyIDCMP(win, 0);
698 Permit();
701 /* D(bug("before CloseWindow\n")); */
702 CloseWindow(win);
703 /* D(bug("after CloseWindow\n")); */
706 #define DISPOSEGADGET(x) \
707 if (x)\
709 DoMethod(obj, MUIM_Window_FreeGadgetID, ((struct Gadget*)x)->GadgetID);\
710 DisposeObject(x);\
711 x = NULL;\
714 DISPOSEGADGET(data->wd_VertProp);
715 DISPOSEGADGET(data->wd_UpButton);
716 DISPOSEGADGET(data->wd_DownButton);
717 DISPOSEGADGET(data->wd_HorizProp);
718 DISPOSEGADGET(data->wd_LeftButton);
719 DISPOSEGADGET(data->wd_RightButton);
720 #undef DISPOSEGADGET
724 /* Initialize data->wd_X and data->wd_Y for DisplayWindow */
725 /* FIXME 20030817: needs some fixing, seems not fully implemented */
726 static void CalcWindowPosition(Object *obj, struct MUI_WindowData *data)
728 data->wd_XStore = data->wd_X;
729 data->wd_YStore = data->wd_Y;
730 if (NULL == data->wd_RefWindow)
732 /* The following calculations are not very correct, the size and dragbar
733 ** are ignored also the current overscan view */
734 if (data->wd_X == MUIV_Window_LeftEdge_Centered)
736 data->wd_X = (data->wd_RenderInfo.mri_Screen->Width - data->wd_Width)/2;
738 else if (data->wd_X == MUIV_Window_LeftEdge_Moused)
740 data->wd_X = data->wd_RenderInfo.mri_Screen->MouseX;
743 if (data->wd_Y == MUIV_Window_TopEdge_Centered)
745 data->wd_Y = (data->wd_RenderInfo.mri_Screen->Height - data->wd_Height)/2;
747 else if (data->wd_Y == MUIV_Window_TopEdge_Moused)
749 data->wd_Y = data->wd_RenderInfo.mri_Screen->MouseY;
751 else if (data->wd_Y <= MUIV_Window_TopEdge_Delta(0))
753 data->wd_Y = data->wd_RenderInfo.mri_Screen->BarHeight + 1
754 + MUIV_Window_TopEdge_Delta(0) - data->wd_Y;
757 else
759 ULONG w = 0, x = 0;
760 ULONG h = 0, y = 0;
762 get(data->wd_RefWindow, MUIA_Window_Width, &w);
763 get(data->wd_RefWindow, MUIA_Window_LeftEdge, &x);
765 if (data->wd_X == MUIV_Window_LeftEdge_Centered)
767 data->wd_X = x + (w - data->wd_Width)/2;
769 else
771 data->wd_X += x;
774 get(data->wd_RefWindow, MUIA_Window_Height, &h);
775 get(data->wd_RefWindow, MUIA_Window_TopEdge, &y);
777 if (data->wd_Y == MUIV_Window_TopEdge_Centered)
779 /* D(bug("y=%ld, h=%ld, wdh=%ld\n", y, h, data->wd_Height)); */
780 data->wd_Y = y + (h - data->wd_Height)/2;
782 else if (data->wd_Y <= MUIV_Window_TopEdge_Delta(0))
784 /* ??? surely incorrect implementation */
785 data->wd_Y = y + 1 + MUIV_Window_TopEdge_Delta(0) - data->wd_Y;
787 else
789 data->wd_Y += y;
794 /* Initialize data->wd_AltDim for DisplayWindow */
795 static void CalcAltDimensions(Object *obj, struct MUI_WindowData *data)
797 /* Calculate alternate (zoomed) dimensions.
799 if (data->wd_AltDim.Top == MUIV_Window_AltTopEdge_NoChange)
800 data->wd_AltDim.Top = ~0;
801 else if (data->wd_AltDim.Top == MUIV_Window_AltTopEdge_Centered)
802 data->wd_AltDim.Top = (data->wd_RenderInfo.mri_Screen->Height - data->wd_Height)/2;
803 else if (data->wd_AltDim.Top == MUIV_Window_AltTopEdge_Moused)
804 /* ? */ data->wd_AltDim.Top = ~0;
806 if (data->wd_AltDim.Left == MUIV_Window_AltLeftEdge_NoChange)
807 data->wd_AltDim.Left = ~0;
808 else if (data->wd_AltDim.Left == MUIV_Window_AltLeftEdge_Centered)
809 data->wd_AltDim.Left = (data->wd_RenderInfo.mri_Screen->Width - data->wd_Width)/2;
810 else if (data->wd_AltDim.Left == MUIV_Window_AltLeftEdge_Moused)
811 /* ? */ data->wd_AltDim.Left = ~0;
815 _between
817 MUIV_Window_AltWidth_MinMax(100),
818 data->wd_AltDim.Width,
819 MUIV_Window_AltWidth_MinMax(0)
823 data->wd_AltDim.Width = data->wd_MinMax.MinWidth
824 - data->wd_AltDim.Width
825 * (data->wd_MinMax.MaxWidth - data->wd_MinMax.MinWidth);
827 else if
829 _between
831 MUIV_Window_AltWidth_Screen(100),
832 data->wd_AltDim.Width,
833 MUIV_Window_AltWidth_Screen(0)
837 data->wd_AltDim.Width = data->wd_RenderInfo.mri_ScreenWidth
838 * (- (data->wd_AltDim.Width + 200)) / 100;
840 else if
842 _between
844 MUIV_Window_AltWidth_Visible(100),
845 data->wd_AltDim.Width,
846 MUIV_Window_AltWidth_Visible(0)
850 data->wd_AltDim.Width = data->wd_RenderInfo.mri_ScreenWidth
851 * (- (data->wd_AltDim.Width + 100)) / 100;
856 _between
858 MUIV_Window_AltHeight_MinMax(100),
859 data->wd_AltDim.Height,
860 MUIV_Window_AltHeight_MinMax(0)
864 data->wd_AltDim.Height = data->wd_MinMax.MinHeight
865 - data->wd_AltDim.Height
866 * (data->wd_MinMax.MaxHeight - data->wd_MinMax.MinHeight);
868 else if
870 _between
872 MUIV_Window_AltHeight_Screen(100),
873 data->wd_AltDim.Height,
874 MUIV_Window_AltHeight_Screen(0)
878 data->wd_AltDim.Height = data->wd_RenderInfo.mri_ScreenHeight
879 * (- (data->wd_AltDim.Height + 200)) / 100;
881 else if
883 _between
885 MUIV_Window_AltHeight_Visible(100),
886 data->wd_AltDim.Height,
887 MUIV_Window_AltHeight_Visible(0)
891 data->wd_AltDim.Height = data->wd_RenderInfo.mri_ScreenHeight
892 * (- (data->wd_AltDim.Height + 100)) / 100;
895 data->wd_AltDim.Width = CLAMP
897 data->wd_AltDim.Width, data->wd_MinMax.MinWidth,
898 data->wd_MinMax.MaxWidth
900 data->wd_AltDim.Height = CLAMP
902 data->wd_AltDim.Height, data->wd_MinMax.MinHeight,
903 data->wd_MinMax.MaxHeight
908 /* Create horiz/vert window scrollbars for DisplayWindow */
909 static void CreateWindowScrollbars(Object *obj, struct MUI_WindowData *data)
911 struct MUI_RenderInfo *mri = &data->wd_RenderInfo;
912 Object *firstgad = NULL;
913 Object *prevgad = NULL;
914 LONG id;
916 /* Create the right border scrollers now if requested */
917 if (data->wd_Flags & MUIWF_USERIGHTSCROLLER)
919 int voffset;
921 voffset = IM(mri->mri_DownImage)->Width / 4;
923 id = DoMethod(obj, MUIM_Window_AllocGadgetID);
924 firstgad = prevgad = data->wd_VertProp = NewObject
926 NULL, "propgclass",
928 GA_RelRight, 1 - (IM(mri->mri_UpImage)->Width - voffset),
929 GA_Top, mri->mri_BorderTop + 2,
930 GA_Width, IM(mri->mri_UpImage)->Width - voffset * 2,
931 GA_RelHeight, - (mri->mri_BorderTop + 2)
932 - IM(mri->mri_UpImage)->Height
933 - IM(mri->mri_DownImage)->Height
934 - IM(mri->mri_SizeImage)->Height - 2,
935 GA_RightBorder, TRUE,
936 GA_ID, id,
937 PGA_Borderless, TRUE,
938 PGA_NewLook, TRUE,
939 PGA_Freedom, FREEVERT,
940 PGA_Top, 0,
941 PGA_Total, 2,
942 PGA_Visible, 1,
943 ICA_TARGET, ICTARGET_IDCMP,
944 TAG_DONE
947 id = DoMethod(obj, MUIM_Window_AllocGadgetID);
948 prevgad = data->wd_UpButton = NewObject
950 NULL, "buttongclass",
952 GA_Image, (IPTR)mri->mri_UpImage,
953 GA_RelRight, 1 - IM(mri->mri_UpImage)->Width,
954 GA_RelBottom, 1 - IM(mri->mri_UpImage)->Height
955 - IM(mri->mri_DownImage)->Height
956 - IM(mri->mri_SizeImage)->Height,
957 GA_RightBorder, TRUE,
958 GA_Previous, (IPTR)prevgad,
959 GA_ID, id,
960 ICA_TARGET, ICTARGET_IDCMP,
961 TAG_DONE
964 id = DoMethod(obj, MUIM_Window_AllocGadgetID);
965 prevgad = data->wd_DownButton = NewObject
967 NULL, "buttongclass",
969 GA_Image, (IPTR)mri->mri_DownImage,
970 GA_RelRight, 1 - IM(mri->mri_DownImage)->Width,
971 GA_RelBottom, 1 - IM(mri->mri_DownImage)->Height
972 - IM(mri->mri_SizeImage)->Height,
973 GA_RightBorder, TRUE,
974 GA_Previous, (IPTR)prevgad,
975 GA_ID, id,
976 ICA_TARGET, ICTARGET_IDCMP,
977 TAG_DONE
979 } // if (data->wd_Flags & MUIWF_USERIGHTSCROLLER)
981 /* Create the bottom border scrollers now if requested */
982 if (data->wd_Flags & MUIWF_USEBOTTOMSCROLLER)
984 int hoffset;
986 hoffset = IM(mri->mri_RightImage)->Height / 4;
988 id = DoMethod(obj, MUIM_Window_AllocGadgetID);
989 prevgad = data->wd_HorizProp = NewObject
991 NULL, "propgclass",
993 GA_RelBottom, 1 - (IM(mri->mri_LeftImage)->Height - hoffset),
994 GA_Left, mri->mri_BorderLeft,
995 GA_Height, IM(mri->mri_LeftImage)->Height
996 - hoffset * 2,
997 GA_RelWidth, - (mri->mri_BorderLeft)
998 - IM(mri->mri_LeftImage)->Width
999 - IM(mri->mri_RightImage)->Width
1000 - IM(mri->mri_SizeImage)->Width
1001 - 2,
1002 GA_BottomBorder, TRUE,
1003 GA_ID, id,
1004 prevgad ? GA_Previous : TAG_IGNORE, (IPTR)prevgad,
1005 PGA_Borderless, TRUE,
1006 PGA_NewLook, TRUE,
1007 PGA_Freedom, FREEHORIZ,
1008 PGA_Top, 0,
1009 PGA_Total, 2,
1010 PGA_Visible, 1,
1011 ICA_TARGET, ICTARGET_IDCMP,
1012 TAG_DONE
1015 if (!firstgad) firstgad = prevgad;
1017 id = DoMethod(obj, MUIM_Window_AllocGadgetID);
1018 prevgad = data->wd_LeftButton = NewObject
1020 NULL, "buttongclass",
1022 GA_Image, (IPTR)mri->mri_LeftImage,
1023 GA_RelRight, 1 - IM(mri->mri_LeftImage)->Width
1024 - IM(mri->mri_RightImage)->Width
1025 - IM(mri->mri_SizeImage)->Width,
1026 GA_RelBottom, 1 - IM(mri->mri_LeftImage)->Height,
1027 GA_BottomBorder, TRUE,
1028 GA_Previous, (IPTR)prevgad,
1029 GA_ID, id,
1030 ICA_TARGET, ICTARGET_IDCMP,
1031 TAG_DONE
1034 id = DoMethod(obj, MUIM_Window_AllocGadgetID);
1035 prevgad = data->wd_RightButton = NewObject
1037 NULL, "buttongclass",
1039 GA_Image, (IPTR)mri->mri_RightImage,
1040 GA_RelRight, 1 - IM(mri->mri_RightImage)->Width
1041 - IM(mri->mri_SizeImage)->Width,
1042 GA_RelBottom, 1 - IM(mri->mri_RightImage)->Height,
1043 GA_BottomBorder, TRUE,
1044 GA_Previous, (IPTR)prevgad,
1045 GA_ID, id,
1046 ICA_TARGET, ICTARGET_IDCMP,
1047 TAG_DONE);
1048 } // if (data->wd_Flags & MUIWF_USEBOTTOMSCROLLER)
1051 /* return FALSE only if no resize (dx=dy=0) occured */
1052 static BOOL WindowResize (struct MUI_WindowData *data)
1054 struct Window *win = data->wd_RenderInfo.mri_Window;
1055 int hborders = win->BorderLeft + win->BorderRight;
1056 int vborders = win->BorderTop + win->BorderBottom;
1057 WORD dx = data->wd_Width - win->Width + hborders;
1058 WORD dy = data->wd_Height - win->Height + vborders;
1060 /* D(bug("_zune_window_resize : dx=%d, dy=%d\n", dx, dy)); */
1061 SizeWindow(win, dx, dy);
1063 /* The following WindowLimits() call doesn't really work because SizeWindow() is async */
1064 WindowLimits
1066 win, data->wd_MinMax.MinWidth + hborders,
1067 data->wd_MinMax.MinHeight + vborders,
1068 data->wd_MinMax.MaxWidth + hborders,
1069 data->wd_MinMax.MaxHeight + vborders
1072 return (dx || dy);
1075 static void KillHelpBubble(struct MUI_WindowData *data, Object *obj, BOOL kill_bubblemode)
1077 if (data->wd_HelpObject)
1079 DoMethod(data->wd_HelpObject, MUIM_DeleteBubble, (IPTR)data->wd_HelpBubble);
1080 data->wd_HelpObject = NULL;
1081 data->wd_HelpBubble = NULL;
1084 if (kill_bubblemode) data->wd_Flags &= ~MUIWF_BUBBLEMODE;
1086 if (data->wd_Flags & MUIWF_BUBBLEMODE)
1088 data->wd_HelpTicker = BUBBLEHELP_TICKER_LATER;
1090 else
1092 data->wd_HelpTicker = BUBBLEHELP_TICKER_FIRST;
1097 /**************/
1099 typedef BOOL (*UNDERCHECK_FUNC)(Object *obj);
1101 static BOOL ShortHelpUnderPointerCheck(Object *obj)
1103 return muiAreaData(obj)->mad_ShortHelp ? TRUE : FALSE;
1106 static Object *ObjectUnderPointer(struct MUI_WindowData *data, Object *obj,
1107 LONG x, LONG y, UNDERCHECK_FUNC func)
1109 Object *cstate;
1110 Object *child;
1111 struct MinList *ChildList;
1113 if (!(muiAreaData(obj)->mad_Flags & MADF_CANDRAW))
1114 return NULL;
1116 if (!(x >= _left(obj) && x <= _right(obj)
1117 && y >= _top(obj) && y <= _bottom(obj)))
1119 return NULL;
1122 if (get(obj, MUIA_Group_ChildList, (IPTR *)&(ChildList)))
1124 cstate = (Object *)ChildList->mlh_Head;
1125 while ((child = NextObject(&cstate)))
1127 Object *ret;
1129 if ((x >= _left(child) && x <= _right(child)
1131 y >= _top(child) && y <= _bottom(child))
1133 (ret = ObjectUnderPointer(data, child, x, y, func)))
1135 return ret;
1140 if (!(*func)(obj)) return NULL;
1142 return obj;
1145 static BOOL ContextMenuUnderPointer(struct MUI_WindowData *data, Object *obj, LONG x, LONG y)
1147 Object *cstate;
1148 Object *child;
1149 struct MinList *ChildList = 0;
1151 if (!(x >= _left(obj) && x <= _right(obj)
1152 && y >= _top(obj) && y <= _bottom(obj)))
1154 return FALSE;
1157 if (get(obj, MUIA_Group_ChildList, (IPTR *)&(ChildList)) && (ChildList != 0))
1160 cstate = (Object *)ChildList->mlh_Head;
1161 while ((child = NextObject(&cstate)))
1163 if ((x >= _left(child) && x <= _right(child)
1165 y >= _top(child) && y <= _bottom(child))
1167 (ContextMenuUnderPointer(data,child,x,y)))
1168 return TRUE;
1172 if (!(muiAreaData(obj)->mad_Flags & MADF_CANDRAW))
1173 return FALSE;
1174 if (!(muiAreaData(obj)->mad_ContextMenu))
1175 return FALSE;
1177 return TRUE;
1180 /**************/
1182 static void ActivateObject (struct MUI_WindowData *data)
1184 //bug("Window::ActivateObject (dummy) %08lx\n", data->wd_ActiveObject);
1185 // if (FindObjNode(&data->wd_CycleChain, data->wd_ActiveObject))
1186 // DoMethod(data->wd_ActiveObject, MUIM_GoActive);
1187 // else
1188 // data->wd_ActiveObject = NULL;
1189 //activate better string gadgets.Fix from Georg S On ML List
1190 if (FindObjNode(&data->wd_CycleChain, data->wd_ActiveObject))
1192 if (!(data->wd_Flags & MUIWF_OBJECTGOACTIVESENT))
1194 data->wd_Flags |= MUIWF_OBJECTGOACTIVESENT;
1195 DoMethod(data->wd_ActiveObject, MUIM_GoActive);
1198 else
1199 data->wd_ActiveObject = NULL;
1203 /**************/
1205 static void HandleInputEvent(Object *win, struct MUI_WindowData *data,
1206 struct IntuiMessage *event);
1208 /* handle intuimessage while an object is being dragged
1209 * (reply imsg before returning)
1211 void HandleDragging (Object *oWin, struct MUI_WindowData *data,
1212 struct IntuiMessage *imsg)
1214 struct Window *iWin;
1215 int finish_drag = 0;
1217 iWin = imsg->IDCMPWindow;
1219 if (imsg->Class == IDCMP_MOUSEMOVE)
1221 struct Layer *layer;
1222 layer = WhichLayer(&iWin->WScreen->LayerInfo, iWin->LeftEdge + imsg->MouseX, iWin->TopEdge + imsg->MouseY);
1224 if (data->wd_DropObject)
1226 struct Window *wnd;
1227 WORD mousex = imsg->MouseX + iWin->LeftEdge - data->wd_DropWindow->LeftEdge;
1228 WORD mousey = imsg->MouseY + iWin->TopEdge - data->wd_DropWindow->TopEdge;
1230 wnd = _window(data->wd_DropObject);
1233 mousex < _left(data->wd_DropObject)
1234 || mousex > _right(data->wd_DropObject)
1235 || mousey < _top(data->wd_DropObject)
1236 || mousey > _bottom(data->wd_DropObject)
1237 || layer != wnd->WLayer
1240 /* We have left the object */
1241 UndrawDragNDrop(data->wd_dnd);
1242 DoMethod(data->wd_DropObject, MUIM_DragFinish,(IPTR)data->wd_DragObject);
1243 data->wd_DropObject = NULL;
1245 } /* if (data->wd_DropObject) */
1247 if (!data->wd_DropObject)
1249 Object *dest_wnd = NULL;
1251 /* Find out if app has an openend window at this position */
1252 if (layer)
1254 Object *cstate;
1255 Object *child;
1256 struct MinList *ChildList;
1258 get(_app(oWin), MUIA_Application_WindowList, (IPTR *)&(ChildList));
1259 cstate = (Object *)ChildList->mlh_Head;
1260 while ((child = NextObject(&cstate)))
1262 struct Window *wnd;
1263 get(child, MUIA_Window_Window,&wnd);
1264 if (!wnd) continue;
1266 if (wnd->WLayer == layer)
1268 data->wd_DropWindow = wnd;
1269 dest_wnd = child;
1270 break;
1273 } /* if (layer) */
1275 if (dest_wnd)
1277 Object *root;
1278 get(dest_wnd, MUIA_Window_RootObject, (IPTR *)&root);
1280 if (root)
1285 data->wd_DropObject = (Object*) DoMethod
1287 root, MUIM_DragQueryExtended,
1288 (IPTR) data->wd_DragObject,
1289 imsg->MouseX + iWin->LeftEdge - data->wd_DropWindow->LeftEdge,
1290 imsg->MouseY + iWin->TopEdge - data->wd_DropWindow->TopEdge
1295 UndrawDragNDrop(data->wd_dnd);
1296 DoMethod(data->wd_DropObject, MUIM_DragBegin,(IPTR)data->wd_DragObject);
1299 } /* if (dest_wnd) */
1300 } /* if (!data->wd_DropObject) */
1302 if (data->wd_DropObject)
1304 LONG update = 0;
1305 LONG i;
1306 for (i=0;i<2;i++)
1308 LONG res = DoMethod
1310 data->wd_DropObject, MUIM_DragReport,
1311 (IPTR) data->wd_DragObject,
1312 imsg->MouseX + iWin->LeftEdge - data->wd_DropWindow->LeftEdge,
1313 imsg->MouseY + iWin->TopEdge - data->wd_DropWindow->TopEdge,update
1315 switch (res)
1317 case MUIV_DragReport_Abort:
1318 UndrawDragNDrop(data->wd_dnd);
1319 DoMethod(data->wd_DropObject, MUIM_DragFinish,(IPTR)data->wd_DragObject);
1320 data->wd_DropObject = NULL;
1321 i = 1;
1322 break;
1324 case MUIV_DragReport_Continue: break;
1325 case MUIV_DragReport_Lock: break; /* NYI */
1326 case MUIV_DragReport_Refresh:
1327 UndrawDragNDrop(data->wd_dnd);
1328 update = 1;
1329 break;
1332 } /* if (data->wd_DropObject) */
1333 DrawDragNDrop(data->wd_dnd, imsg->MouseX + iWin->LeftEdge , imsg->MouseY + iWin->TopEdge);
1334 } /* if (imsg->Class == IDCMP_MOUSEMOVE) */
1336 if (imsg->Class == IDCMP_MOUSEBUTTONS)
1338 if ((imsg->Code == MENUDOWN) || (imsg->Code == SELECTUP))
1340 if (imsg->Code == SELECTUP && data->wd_DropObject)
1342 UndrawDragNDrop(data->wd_dnd);
1343 DoMethod(data->wd_DropObject, MUIM_DragFinish, (IPTR)data->wd_DragObject);
1344 DoMethod
1346 data->wd_DropObject, MUIM_DragDrop, (IPTR)data->wd_DragObject,
1347 imsg->MouseX + iWin->LeftEdge - data->wd_DropWindow->LeftEdge,
1348 imsg->MouseY + iWin->TopEdge - data->wd_DropWindow->TopEdge
1350 data->wd_DropObject = NULL;
1352 else if (imsg->Code == SELECTUP)
1354 DoMethod(data->wd_DragObject, MUIM_UnknownDropDestination, imsg);
1356 finish_drag = 1;
1360 if (imsg->Class == IDCMP_CLOSEWINDOW)
1361 finish_drag = 1;
1363 if (finish_drag)
1365 UndrawDragNDrop(data->wd_dnd);
1366 if (data->wd_DropObject)
1368 DoMethod(data->wd_DropObject, MUIM_DragFinish,(IPTR)data->wd_DragObject);
1369 data->wd_DropObject = NULL;
1371 DeleteDragNDrop(data->wd_dnd);
1372 DoMethod(data->wd_DragObject,MUIM_DeleteDragImage, (IPTR)data->wd_DragImage);
1373 muiAreaData(data->wd_DragObject)->mad_Flags &= ~MADF_DRAGGING;
1374 data->wd_DragImage = NULL;
1375 data->wd_DragObject = NULL;
1376 data->wd_DropWindow = NULL;
1377 data->wd_dnd = NULL;
1378 /* stop listening to IDCMP_MOUSEMOVE */
1379 ChangeEvents(data, GetDefaultEvents());
1381 ReplyMsg((struct Message*)imsg);
1384 /* Reply to imsg if handled */
1385 BOOL HandleWindowEvent (Object *oWin, struct MUI_WindowData *data,
1386 struct IntuiMessage *imsg)
1388 struct Window *iWin;
1389 BOOL is_handled = TRUE;
1390 BOOL replied = FALSE;
1392 iWin = imsg->IDCMPWindow;
1393 switch (imsg->Class)
1395 case IDCMP_ACTIVEWINDOW:
1396 data->wd_Flags |= MUIWF_ACTIVE;
1397 if (data->wd_OldActive)
1398 set(oWin, MUIA_Window_ActiveObject, data->wd_OldActive);
1399 set(oWin, MUIA_Window_Activate, TRUE);
1400 is_handled = FALSE; /* forwardable to area event handlers */
1401 break;
1403 case IDCMP_INACTIVEWINDOW:
1404 KillHelpBubble(data, oWin, TRUE);
1405 if (data->wd_ActiveObject)
1407 data->wd_OldActive = data->wd_ActiveObject;
1408 set(oWin, MUIA_Window_ActiveObject, MUIV_Window_ActiveObject_None);
1410 data->wd_Flags &= ~MUIWF_ACTIVE;
1411 set(oWin, MUIA_Window_Activate, FALSE);
1412 is_handled = FALSE; /* forwardable to area event handlers */
1413 break;
1415 case IDCMP_NEWSIZE:
1416 ReplyMsg((struct Message*)imsg);
1417 replied = TRUE;
1420 int hborders = iWin->BorderLeft + iWin->BorderRight;
1421 int vborders = iWin->BorderTop + iWin->BorderBottom;
1423 /* set window limits according to window contents */
1424 WindowLimits (
1425 iWin,
1426 data->wd_MinMax.MinWidth + hborders,
1427 data->wd_MinMax.MinHeight + vborders,
1428 data->wd_MinMax.MaxWidth + hborders,
1429 data->wd_MinMax.MaxHeight + vborders
1433 if ((iWin->GZZWidth != data->wd_Width) || (iWin->GZZHeight != data->wd_Height))
1435 data->wd_Width = iWin->GZZWidth;
1436 data->wd_Height = iWin->GZZHeight;
1437 DoHideMethod(data->wd_RootObject);
1439 if (1) // why only simple refresh? was: if (data->wd_RenderInfo.mri_Window->Flags & WFLG_SIMPLE_REFRESH)
1441 data->wd_Flags |= MUIWF_RESIZING;
1443 else
1445 _width(data->wd_RootObject) = data->wd_Width;
1446 _height(data->wd_RootObject) = data->wd_Height;
1447 DoMethod(data->wd_RootObject, MUIM_Layout);
1448 DoShowMethod(data->wd_RootObject);
1450 LONG left,top,width,height;
1452 left = data->wd_RenderInfo.mri_Window->BorderLeft;
1453 top = data->wd_RenderInfo.mri_Window->BorderTop,
1454 width = data->wd_RenderInfo.mri_Window->Width
1455 - data->wd_RenderInfo.mri_Window->BorderRight - left;
1456 height = data->wd_RenderInfo.mri_Window->Height
1457 - data->wd_RenderInfo.mri_Window->BorderBottom - top;
1459 // D(bug("%d:zune_imspec_draw(%p) l=%d t=%d w=%d h=%d xo=%d yo=%d\n",
1460 // __LINE__, data->wd_Background, left, top, width,
1461 // height, left, top));
1462 zune_imspec_draw(data->wd_Background, &data->wd_RenderInfo,
1463 left, top, width, height, left, top, 0);
1465 if (muiGlobalInfo(oWin)->mgi_Prefs->window_redraw == WINDOW_REDRAW_WITHOUT_CLEAR)
1466 MUI_Redraw(data->wd_RootObject, MADF_DRAWOBJECT);
1467 else
1468 MUI_Redraw(data->wd_RootObject, MADF_DRAWALL);
1469 // but should only draw focus without using MUIM_GoActive !
1470 ActivateObject(data);
1473 break;
1475 case IDCMP_REFRESHWINDOW:
1476 ReplyMsg((struct Message*)imsg);
1477 replied = TRUE;
1478 if (data->wd_Flags & MUIWF_RESIZING)
1480 //LONG left,top,right,bottom;
1481 if (MUI_BeginRefresh(&data->wd_RenderInfo, 0))
1483 MUI_EndRefresh(&data->wd_RenderInfo, 0);
1485 RefreshWindowFrame(data->wd_RenderInfo.mri_Window);
1487 data->wd_Flags &= ~MUIWF_RESIZING;
1488 _width(data->wd_RootObject) = data->wd_Width;
1489 _height(data->wd_RootObject) = data->wd_Height;
1490 DoMethod(data->wd_RootObject, MUIM_Layout);
1491 DoShowMethod(data->wd_RootObject);
1493 if (muiGlobalInfo(oWin)->mgi_Prefs->window_redraw == WINDOW_REDRAW_WITH_CLEAR)
1495 LONG left,top,width,height;
1497 left = data->wd_RenderInfo.mri_Window->BorderLeft;
1498 top = data->wd_RenderInfo.mri_Window->BorderTop,
1499 width = data->wd_RenderInfo.mri_Window->Width - data->wd_RenderInfo.mri_Window->BorderRight - left;
1500 height = data->wd_RenderInfo.mri_Window->Height - data->wd_RenderInfo.mri_Window->BorderBottom - top;
1502 if(data->wd_Flags & MUIWF_ERASEAREA)
1504 // D(bug("%d:zune_imspec_draw(%p) l=%d t=%d w=%d h=%d xo=%d yo=%d\n",
1505 // __LINE__, data->wd_Background, left, top, width,
1506 // height, left, top));
1507 zune_imspec_draw(data->wd_Background, &data->wd_RenderInfo,
1508 left, top, width, height, left, top, 0);
1510 MUI_Redraw(data->wd_RootObject, MADF_DRAWALL);
1512 else
1513 MUI_Redraw(data->wd_RootObject, MADF_DRAWOBJECT);
1514 // but should only draw focus without using MUIM_GoActive !
1515 ActivateObject(data);
1517 else
1519 if (MUI_BeginRefresh(&data->wd_RenderInfo, 0))
1521 MUI_Redraw(data->wd_RootObject, MADF_DRAWALL);
1522 // but should only draw focus without using MUIM_GoActive !
1523 ActivateObject(data);
1524 MUI_EndRefresh(&data->wd_RenderInfo, 0);
1527 break;
1529 case IDCMP_CLOSEWINDOW:
1530 ReplyMsg((struct Message*)imsg);
1531 replied = TRUE;
1532 set(oWin, MUIA_Window_CloseRequest, TRUE);
1533 break;
1535 case IDCMP_MENUPICK:
1536 ReplyMsg((struct Message*)imsg);
1537 replied = TRUE;
1539 if (data->wd_Menu)
1541 if (MENUNUM(imsg->Code) != NOMENU && ITEMNUM(imsg->Code) != NOITEM)
1543 struct MenuItem *item = ItemAddress(data->wd_Menu,imsg->Code);
1544 if (item)
1546 Object *item_obj = (Object*)GTMENUITEM_USERDATA(item);
1547 if (item_obj)
1549 Object *app;
1550 IPTR udata;
1552 if (item->Flags & CHECKIT)
1553 set(item_obj, MUIA_Menuitem_Checked, !!(item->Flags & CHECKED));
1555 set(item_obj, MUIA_Menuitem_Trigger, (IPTR)item);
1557 get(oWin, MUIA_ApplicationObject, &app);
1558 get(item_obj, MUIA_UserData, &udata);
1560 set(app, MUIA_Application_MenuAction, udata);
1561 set(oWin, MUIA_Window_MenuAction, udata);
1562 DoMethod(app, MUIM_Application_ReturnID, udata);
1567 break;
1569 case IDCMP_IDCMPUPDATE:
1570 is_handled = FALSE; /* forwardable to area event handlers */
1571 if (data->wd_VertProp || data->wd_HorizProp)
1573 struct TagItem *tag;
1574 tag = FindTagItem(GA_ID,(struct TagItem*)imsg->IAddress);
1575 if (tag)
1577 /* If there's a propclass object connected to the prop
1578 gadget, the prop gadget's userdata will point to
1579 that propclass object. See classes/prop.c */
1581 if (data->wd_VertProp)
1583 if (tag->ti_Data == GADGETID(data->wd_VertProp))
1586 if (tag->ti_Data == GADGETID(data->wd_UpButton))
1588 Object *prop = (Object *)((struct Gadget *)data->wd_VertProp)->UserData;
1589 is_handled = TRUE;
1590 if (prop) DoMethod(prop, MUIM_Prop_Decrease, 1);
1593 if (tag->ti_Data == GADGETID(data->wd_DownButton))
1595 Object *prop = (Object *)((struct Gadget *)data->wd_VertProp)->UserData;
1596 is_handled = TRUE;
1597 if (prop) DoMethod(prop, MUIM_Prop_Increase, 1);
1602 if (data->wd_HorizProp)
1604 if (tag->ti_Data == GADGETID(data->wd_HorizProp))
1607 if (tag->ti_Data == GADGETID(data->wd_LeftButton))
1609 Object *prop = (Object *)((struct Gadget *)data->wd_HorizProp)->UserData;
1610 is_handled = TRUE;
1611 if (prop) DoMethod(prop, MUIM_Prop_Decrease, 1);
1614 if (tag->ti_Data == GADGETID(data->wd_RightButton))
1616 Object *prop = (Object *)((struct Gadget *)data->wd_HorizProp)->UserData;
1617 is_handled = TRUE;
1618 if (prop) DoMethod(prop, MUIM_Prop_Increase, 1);
1624 break;
1626 case IDCMP_INTUITICKS:
1627 if (data->wd_HelpTicker)
1629 data->wd_HelpTicker--;
1631 if (data->wd_HelpTicker == 0)
1633 Object *underobj = ObjectUnderPointer(data, data->wd_RootObject, imsg->MouseX, imsg->MouseY,
1634 ShortHelpUnderPointerCheck);
1636 if (underobj != data->wd_HelpObject)
1638 if (data->wd_HelpObject)
1640 DoMethod(data->wd_HelpObject, MUIM_DeleteBubble, (IPTR)data->wd_HelpBubble);
1642 data->wd_HelpObject = NULL;
1643 data->wd_HelpBubble = NULL;
1646 if (underobj)
1648 data->wd_HelpBubble = (APTR)DoMethod(underobj, MUIM_CreateBubble,
1649 imsg->MouseX, imsg->MouseY,
1650 0, 0);
1651 if (data->wd_HelpBubble)
1653 data->wd_HelpObject = underobj;
1654 data->wd_Flags |= MUIWF_BUBBLEMODE;
1659 if (data->wd_Flags & MUIWF_BUBBLEMODE)
1661 data->wd_HelpTicker = BUBBLEHELP_TICKER_LATER;
1663 else
1665 data->wd_HelpTicker = BUBBLEHELP_TICKER_FIRST;
1668 } /* if (data->wd_HelpTicker == 0) */
1670 } /* if (data->wd_HelpTicker) */
1672 is_handled = FALSE; /* forwardable to area event handlers */
1673 break;
1675 case IDCMP_MOUSEBUTTONS:
1676 DoMethod(oWin,MUIM_Window_Snapshot,0);
1677 KillHelpBubble(data, oWin, TRUE);
1678 is_handled = FALSE;
1679 break;
1682 case IDCMP_MOUSEMOVE:
1683 KillHelpBubble(data, oWin, FALSE);
1684 is_handled = FALSE;
1685 break;
1687 default:
1688 is_handled = FALSE;
1689 break;
1690 } /* switch (imsg->Class) */
1692 if (is_handled && !replied)
1693 ReplyMsg((struct Message*)imsg);
1695 return is_handled;
1698 static ULONG InvokeEventHandler (struct MUI_EventHandlerNode *ehn,
1699 struct IntuiMessage *event, ULONG muikey)
1701 ULONG res;
1703 if (!(_flags(ehn->ehn_Object) & MADF_CANDRAW)) return 0;
1704 if (!(_flags(ehn->ehn_Object) & MADF_SHOWME)) return 0;
1708 event != NULL
1709 && event->Class == IDCMP_MOUSEBUTTONS
1710 && event->Code == SELECTDOWN
1711 && (_flags(ehn->ehn_Object) & MADF_INVIRTUALGROUP)
1715 Here we filter out SELECTDOWN messages if objects is in a virtual
1716 group but the click went out of the virtual group
1718 Object *obj = ehn->ehn_Object;
1719 Object *parent = obj;
1720 Object *wnd = _win(obj);
1722 while (get(parent,MUIA_Parent,(IPTR *)&parent))
1724 if (!parent) break;
1725 if (wnd == parent) break;
1726 if (_flags(parent) & MADF_ISVIRTUALGROUP)
1730 event->MouseX < _mleft(parent)
1731 || event->MouseX > _mright(parent)
1732 || event->MouseY < _mtop(parent)
1733 || event->MouseY > _mbottom(parent)
1736 return 0;
1743 if (ehn->ehn_Flags & MUI_EHF_HANDLEINPUT)
1745 DoMethod(ehn->ehn_Object, MUIM_HandleInput, (IPTR)event, muikey);
1746 res = 0;
1748 else
1750 if (ehn->ehn_Class)
1751 res = CoerceMethod
1753 ehn->ehn_Class, ehn->ehn_Object, MUIM_HandleEvent,
1754 (IPTR)event, muikey
1756 else
1757 res = DoMethod(ehn->ehn_Object, MUIM_HandleEvent, (IPTR)event, muikey);
1759 return res;
1762 static void HandleRawkey(Object *win, struct MUI_WindowData *data,
1763 struct IntuiMessage *event)
1765 struct MinNode *mn;
1766 struct MUI_EventHandlerNode *ehn;
1767 struct IntuiMessage imsg_copy;
1768 struct InputEvent ie = {0};
1769 ULONG res;
1770 LONG muikey = MUIKEY_NONE;
1771 Object *active_object = NULL;
1772 IPTR disabled;
1773 ULONG key;
1774 ULONG deadkey;
1776 KillHelpBubble(data, win, BUBBLEHELP_TICKER_FIRST);
1778 ie.ie_NextEvent = NULL;
1779 ie.ie_Class = IECLASS_RAWKEY;
1780 ie.ie_SubClass = 0;
1781 ie.ie_Code = event->Code;
1782 ie.ie_Qualifier = event->Qualifier;
1783 ie.ie_EventAddress = (APTR)*(ULONG *)event->IAddress;
1784 ie.ie_TimeStamp.tv_secs = event->Seconds;
1785 ie.ie_TimeStamp.tv_micro = event->Micros;
1787 set(win, MUIA_Window_InputEvent, (IPTR)&ie);
1789 /* get the vanilla key for control char */
1791 UWORD msg_code;
1792 /* Remove the up prefix as convert key does not convert a upkey event */
1793 msg_code = event->Code;
1794 event->Code &= ~IECODE_UP_PREFIX;
1795 key = ConvertKey(event);
1796 event->Code = msg_code;
1799 imsg_copy = *event;
1800 deadkey = *(ULONG *)event->IAddress;
1801 imsg_copy.IAddress = &deadkey;
1802 ReplyMsg((struct Message*)event);
1803 event = &imsg_copy;
1805 //bug("rawkey: code=%lx, qual=%lx\n", event->Code, event->Qualifier);
1807 /* check if imsg translate to predefined keystroke */
1809 struct InputEvent ievent;
1810 BOOL matched = FALSE;
1812 ievent.ie_NextEvent = NULL;
1813 ievent.ie_Class = IECLASS_RAWKEY;
1814 ievent.ie_SubClass = 0;
1815 ievent.ie_Code = event->Code;
1816 ievent.ie_Qualifier = event->Qualifier;
1817 /* ie_EventAddress is not used by MatchIX. If needed, it should be
1818 * ensured that it is still a valid adress because of the shallow
1819 * IntuiMessage copy currently done in _zune_window_message before
1820 * message is replied.
1822 ievent.ie_EventAddress = NULL;
1823 //ievent.ie_EventAddress = (APTR *) *((ULONG *)(event->IAddress));
1825 for (muikey = MUIKEY_COUNT - 1; muikey >= MUIKEY_PRESS; muikey--)
1827 if (muiGlobalInfo(win)->mgi_Prefs->muikeys[muikey].ix_well != 0
1828 && MatchIX(&ievent, &muiGlobalInfo(win)->mgi_Prefs->muikeys[muikey].ix))
1830 matched = TRUE;
1831 break;
1835 if (matched)
1837 if (muikey == MUIKEY_PRESS && (event->Code & IECODE_UP_PREFIX))
1838 muikey = MUIKEY_RELEASE;
1840 else
1842 muikey = MUIKEY_NONE;
1844 } /* check if imsg translate to predefined keystroke */
1846 if ((muikey != MUIKEY_NONE)
1847 && !(data->wd_DisabledKeys & (1<<muikey)))
1849 D(bug("HandleRawkey: try MUIKEY %ld on window %0x08lx\n", muikey, win));
1850 switch (muikey)
1852 case MUIKEY_PRESS: break;
1853 case MUIKEY_TOGGLE: break;
1854 case MUIKEY_UP: break;
1855 case MUIKEY_DOWN: break;
1856 case MUIKEY_PAGEUP: break;
1857 case MUIKEY_PAGEDOWN: break;
1858 case MUIKEY_TOP: break;
1859 case MUIKEY_BOTTOM: break;
1860 case MUIKEY_LEFT: break;
1861 case MUIKEY_RIGHT: break;
1862 case MUIKEY_WORDLEFT: break;
1863 case MUIKEY_WORDRIGHT: break;
1864 case MUIKEY_LINESTART: break;
1865 case MUIKEY_LINEEND: break;
1866 case MUIKEY_GADGET_NEXT:
1867 set(win, MUIA_Window_ActiveObject, MUIV_Window_ActiveObject_Next);
1868 break;
1869 case MUIKEY_GADGET_PREV:
1870 set(win, MUIA_Window_ActiveObject, MUIV_Window_ActiveObject_Prev);
1871 break;
1872 case MUIKEY_GADGET_OFF:
1873 set(win, MUIA_Window_ActiveObject, MUIV_Window_ActiveObject_None);
1874 break;
1875 case MUIKEY_WINDOW_CLOSE:
1876 set(win, MUIA_Window_CloseRequest, TRUE);
1877 break;
1878 case MUIKEY_WINDOW_NEXT: break;
1879 case MUIKEY_WINDOW_PREV: break;
1880 case MUIKEY_HELP: break;
1881 case MUIKEY_POPUP: break;
1882 default: break;
1886 active_object = NULL;
1887 if ((data->wd_ActiveObject != NULL)
1888 && (DoMethod(data->wd_RootObject, MUIM_FindAreaObject,
1889 (IPTR)data->wd_ActiveObject) != (IPTR)NULL))
1891 active_object = data->wd_ActiveObject;
1892 get(active_object, MUIA_Disabled, &disabled);
1894 else
1895 data->wd_ActiveObject = NULL;
1897 /* try ActiveObject */
1898 if ((active_object != NULL) && !disabled)
1900 #if 0
1901 /* sba:
1902 ** Which method should be used for muikeys? MUIM_HandleInput or
1903 ** MUIM_HandleEvent. Also note that there is a flag MUI_EHF_ALWAYSKEYS
1904 ** which probably means that all keys events are requested??
1905 ** For now MUIM_HandleEvent is used as this is currently implemented
1906 ** in Area class ;) although I guess it should be MUIM_HandleInput as this
1907 ** was earlier
1910 if (muikey != MUIKEY_NONE)
1912 res = DoMethod(active_object, MUIM_HandleEvent, (IPTR)event, muikey);
1913 if (res & MUI_EventHandlerRC_Eat) return;
1915 #endif
1916 D(bug("HandleRawkey: try active object (%08lx) handlers\n", active_object));
1918 for (mn = data->wd_EHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
1920 ehn = (struct MUI_EventHandlerNode *)mn;
1922 if ((ehn->ehn_Object == active_object)
1923 && ((ehn->ehn_Events & IDCMP_RAWKEY)
1924 || (ehn->ehn_Flags & MUI_EHF_ALWAYSKEYS)))
1926 D(bug("HandleRawkey: (active) invoking on %p (ehn=%p) event=%p muikey=%p\n",
1927 ehn->ehn_Object, ehn, event, muikey));
1928 res = InvokeEventHandler(ehn, event, muikey);
1929 D(bug("HandleRawkey: (active) got res=%d\n", res));
1930 if (res & MUI_EventHandlerRC_Eat)
1931 return;
1933 /* Leave the loop if a different object has been activated */
1934 if (active_object != data->wd_ActiveObject)
1935 break;
1937 } /* for (mn = data->wd_EHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ) */
1939 // event not eaten by active object, try its parents
1940 // this is to implement popup key in Popstring
1941 if (active_object == data->wd_ActiveObject)
1943 Object *current_obj = active_object;
1945 D(bug("HandleRawkey: try active object parents handlers\n"));
1946 while (current_obj != NULL)
1948 for (mn = data->wd_EHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
1950 ehn = (struct MUI_EventHandlerNode *)mn;
1952 if ((ehn->ehn_Object == current_obj)
1953 && ((ehn->ehn_Events & IDCMP_RAWKEY)
1954 || (ehn->ehn_Flags & MUI_EHF_ALWAYSKEYS)))
1956 //D(bug("HandleRawkey: (active parents) invoking on %p (ehn=%p) "
1957 //"event=%p muikey=%p\n",
1958 //ehn->ehn_Object, ehn, event, muikey));
1959 res = InvokeEventHandler(ehn, event, muikey);
1960 //D(bug("HandleRawkey: (active parents) got res=%d\n", res));
1961 if (res & MUI_EventHandlerRC_Eat)
1962 return;
1964 /* Leave the loop if a different object has been activated */
1965 if (active_object != data->wd_ActiveObject)
1966 break;
1969 current_obj = (Object *)XGET(current_obj, MUIA_Parent);
1970 } // while (current_obj != NULL)
1974 } /* if (active_object && !disabled) */
1976 D(bug("HandleRawkey: try default object handlers\n"));
1978 /* try DefaultObject */
1979 if (data->wd_DefaultObject != NULL)
1980 get(data->wd_DefaultObject, MUIA_Disabled, &disabled);
1982 if ((data->wd_DefaultObject != NULL) && !disabled
1983 && (active_object != data->wd_DefaultObject))
1985 /* No, we only should do this if the object actually has requested this via RequestIDCMP()! */
1986 // if (muikey != MUIKEY_NONE && (_flags(data->wd_DefaultObject) & MADF_CANDRAW))
1987 // {
1988 // DoMethod(data->wd_DefaultObject, MUIM_HandleInput, event, muikey);
1989 // return;
1990 // }
1992 for (mn = data->wd_EHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
1994 ehn = (struct MUI_EventHandlerNode *)mn;
1996 if ((ehn->ehn_Object == data->wd_DefaultObject)
1997 && ((ehn->ehn_Events & IDCMP_RAWKEY)
1998 || (ehn->ehn_Flags & MUI_EHF_ALWAYSKEYS)))
2000 //D(bug("HandleRawkey: (default) invoking on %p (ehn=%p) event=%p muikey=%p\n",
2001 //ehn->ehn_Object, ehn, event, muikey));
2002 res = InvokeEventHandler(ehn, event, muikey);
2003 //D(bug("HandleRawkey: (default) got res=%d\n", res));
2004 if (res & MUI_EventHandlerRC_Eat)
2005 return;
2009 } /* if ... default object */
2011 D(bug("HandleRawkey: try other handlers\n"));
2013 // try other handlers
2014 for (mn = data->wd_EHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
2016 ehn = (struct MUI_EventHandlerNode *)mn;
2018 // skip Active and Default object as they have already been
2019 // handled
2020 if (ehn->ehn_Object == data->wd_ActiveObject
2021 || ehn->ehn_Object == data->wd_DefaultObject)
2022 continue;
2024 if (ehn->ehn_Events & IDCMP_RAWKEY)
2026 //D(bug("HandleRawkey: (others) invoking on %p (ehn=%p) event=%p muikey=%p\n",
2027 //ehn->ehn_Object, ehn, event, muikey));
2028 res = InvokeEventHandler(ehn, event, MUIKEY_NONE);
2029 //D(bug("HandleRawkey: (others) got res=%d\n", res));
2030 if (res & MUI_EventHandlerRC_Eat)
2031 return;
2033 } /* for (mn = data->wd_EHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ) */
2035 D(bug("HandleRawkey: try control chars handlers\n"));
2037 /* try Control Chars */
2038 //bug("ctrlchar, key='%c' code=0x%08lx\n", key, event->Code);
2039 if (key)
2041 for (mn = data->wd_CCList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
2043 ehn = (struct MUI_EventHandlerNode *)mn;
2045 if (ehn->ehn_Events == key)
2047 IPTR disabled;
2048 LONG muikey2 = ehn->ehn_Flags;
2050 get(ehn->ehn_Object, MUIA_Disabled, &disabled);
2051 if (disabled)
2052 continue;
2054 //bug("control char\n");
2055 if (event->Code & IECODE_UP_PREFIX)
2057 /* simulate a release */
2058 if (muikey2 == MUIKEY_PRESS)
2059 muikey2 = MUIKEY_RELEASE;
2060 else
2061 return;
2064 if ((muikey2 != MUIKEY_NONE)
2065 && (_flags(ehn->ehn_Object) & MADF_CANDRAW)
2066 && (_flags(ehn->ehn_Object) & MADF_SHOWME))
2068 res = CoerceMethod
2070 ehn->ehn_Class, ehn->ehn_Object, MUIM_HandleEvent,
2071 (IPTR)NULL, muikey2
2073 if (res & MUI_EventHandlerRC_Eat)
2074 return;
2078 } /* try control chars */
2081 /* forward non-keystroke events to event handlers */
2082 static void HandleInputEvent(Object *win, struct MUI_WindowData *data,
2083 struct IntuiMessage *event)
2085 struct MinNode *mn;
2086 struct MUI_EventHandlerNode *ehn;
2087 struct IntuiMessage imsg_copy;
2088 ULONG res;
2089 ULONG mask = event->Class;
2091 if (mask != IDCMP_IDCMPUPDATE)
2093 imsg_copy = *event;
2094 imsg_copy.IAddress = NULL; /* be sure to trap access to that */
2095 ReplyMsg((struct Message*)event);
2096 event = &imsg_copy;
2099 if (mask == IDCMP_MOUSEMOVE)
2101 struct Window *iWin;
2102 iWin = event->IDCMPWindow;
2104 if (ContextMenuUnderPointer (data, data->wd_RootObject,
2105 event->MouseX, event->MouseY))
2107 iWin->Flags |= WFLG_RMBTRAP;
2109 else if (!data->wd_NoMenus)
2111 iWin->Flags &= ~WFLG_RMBTRAP;
2115 for (mn = data->wd_EHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
2117 ehn = (struct MUI_EventHandlerNode *)mn;
2119 if (ehn->ehn_Events & mask)
2121 IPTR disabled;
2123 get(ehn->ehn_Object, MUIA_Disabled, &disabled);
2124 if (disabled)
2125 continue;
2127 res = InvokeEventHandler(ehn, event, MUIKEY_NONE);
2128 if (res & MUI_EventHandlerRC_Eat)
2129 return;
2134 if (mask == IDCMP_IDCMPUPDATE)
2135 ReplyMsg((struct Message*)event);
2139 /* process window message, this does a ReplyMsg() to the message */
2140 /* Called from application.c */
2141 void _zune_window_message(struct IntuiMessage *imsg)
2143 struct Window *iWin;
2144 Object *oWin;
2145 struct MUI_WindowData *data;
2146 BOOL handled;
2148 iWin = imsg->IDCMPWindow;
2149 oWin = (Object *)iWin->UserData;
2150 data = muiWindowData(oWin);
2152 if (data->wd_DragObject)
2154 HandleDragging(oWin, data, imsg);
2155 return;
2158 handled = HandleWindowEvent(oWin, data, imsg);
2159 if (!handled)
2161 if (IDCMP_RAWKEY == imsg->Class)
2162 HandleRawkey(oWin, data, imsg);
2163 else
2164 HandleInputEvent(oWin, data, imsg);
2168 /******************************************************************************/
2169 /******************************************************************************/
2171 /* code for setting MUIA_Window_RootObject */
2172 static void ChangeRootObject (struct MUI_WindowData *data, Object *obj,
2173 Object *newRoot)
2175 Object *oldRoot;
2177 ASSERT_VALID_PTR(data);
2178 ASSERT_VALID_PTR(obj);
2180 oldRoot = data->wd_RootObject;
2181 if (!(data->wd_Flags & MUIWF_OPENED))
2183 if (oldRoot)
2185 if (data->wd_ActiveObject == oldRoot)
2186 set(obj, MUIA_Window_ActiveObject, MUIV_Window_ActiveObject_None);
2187 DoMethod(oldRoot, MUIM_DisconnectParent);
2190 data->wd_RootObject = newRoot;
2191 if (newRoot)
2193 /* if window is in App tree, inform child */
2194 if (muiNotifyData(obj)->mnd_GlobalInfo)
2195 DoMethod(newRoot, MUIM_ConnectParent, (IPTR)obj);
2200 // find the ObjNode containing a pointer to the given object
2201 // currently only used for cycle chain objects
2202 static struct ObjNode *FindObjNode(struct MinList *list, Object *obj)
2204 struct ObjNode *node;
2206 ASSERT_VALID_PTR(list);
2208 if (!obj)
2209 return NULL;
2211 ASSERT_VALID_PTR(obj);
2213 for (node = (struct ObjNode*)list->mlh_Head;
2214 node->node.mln_Succ;
2215 node = (struct ObjNode*)node->node.mln_Succ)
2217 if (node->obj == obj)
2219 return node;
2222 return NULL;
2225 static Object *GetFirstActiveObject (struct MUI_WindowData *data)
2227 ASSERT_VALID_PTR(data);
2229 if (!IsListEmpty((struct List*)&data->wd_CycleChain))
2230 return ((struct ObjNode*)data->wd_CycleChain.mlh_Head)->obj;
2231 else
2232 return NULL;
2235 static Object *GetLastActiveObject (struct MUI_WindowData *data)
2237 ASSERT_VALID_PTR(data);
2239 if (!IsListEmpty((struct List*)&data->wd_CycleChain))
2240 return ((struct ObjNode*)data->wd_CycleChain.mlh_TailPred)->obj;
2241 else
2242 return NULL;
2245 typedef struct ObjNode *objnode_iterator_t(struct ObjNode *curr_node);
2247 static objnode_iterator_t NextObjNodeIterator;
2248 static objnode_iterator_t PrevObjNodeIterator;
2250 static struct ObjNode *NextObjNodeIterator (struct ObjNode *curr_node)
2252 if (curr_node->node.mln_Succ->mln_Succ)
2253 return (struct ObjNode*)curr_node->node.mln_Succ;
2254 else
2255 return NULL;
2258 static struct ObjNode *PrevObjNodeIterator (struct ObjNode *curr_node)
2260 if (curr_node->node.mln_Pred->mln_Pred)
2261 return (struct ObjNode*)curr_node->node.mln_Pred;
2262 else
2263 return NULL;
2266 static Object *GetPrevNextActiveObject (struct ObjNode *old_activenode, objnode_iterator_t node_iterator)
2268 struct ObjNode *curr_node;
2269 struct ObjNode *node;
2270 Object *obj;
2272 ASSERT_VALID_PTR(old_activenode);
2274 curr_node = old_activenode;
2275 node = NULL;
2276 obj = NULL;
2278 while (curr_node)
2280 node = node_iterator(curr_node);
2282 if (node)
2283 obj = node->obj;
2285 /* let's see if this obj meets cycle requirements (enabled & visible) */
2286 if (obj)
2288 IPTR is_disabled;
2290 get(obj, MUIA_Disabled, &is_disabled);
2292 if (!is_disabled && (_flags(obj) & MADF_SHOWME))
2294 return obj;
2298 curr_node = node;
2299 obj = NULL;
2300 node = NULL;
2302 return obj;
2306 /**************************************************************************
2307 Code for setting MUIA_Window_ActiveObject
2308 Basically, it will:
2309 - remove focus drawing for current active object
2310 - find (if needed) the new active object
2311 - set data->wd_ActiveObject to the new object
2312 - draw focus around the new active object
2313 **************************************************************************/
2314 static void SetActiveObject (struct MUI_WindowData *data, Object *obj, IPTR newval)
2316 struct ObjNode *old_activenode = NULL;
2318 ASSERT_VALID_PTR(data);
2319 ASSERT_VALID_PTR(obj);
2321 D(bug("MUIC_Window:SetActiveObject(data, obj, %08lx) Active=%p\n",
2322 newval, data->wd_ActiveObject));
2324 if ((data->wd_ActiveObject != NULL)
2325 && (DoMethod(data->wd_RootObject, MUIM_FindAreaObject,
2326 (IPTR)data->wd_ActiveObject) != (IPTR)NULL))
2328 if ((IPTR)data->wd_ActiveObject == newval)
2329 return;
2330 old_activenode = FindObjNode(&data->wd_CycleChain, data->wd_ActiveObject);
2331 //if (_flags(data->wd_ActiveObject) & MADF_CANDRAW)
2332 if (data->wd_Flags & MUIWF_OBJECTGOACTIVESENT)
2334 DoMethod(data->wd_ActiveObject, MUIM_GoInactive);
2338 data->wd_ActiveObject = NULL;
2339 data->wd_Flags &= ~MUIWF_OBJECTGOACTIVESENT;
2341 switch (newval)
2343 case MUIV_Window_ActiveObject_None:
2344 break;
2346 case MUIV_Window_ActiveObject_Next:
2347 if (old_activenode != NULL)
2348 data->wd_ActiveObject = GetPrevNextActiveObject(old_activenode,
2349 NextObjNodeIterator);
2350 if (NULL == data->wd_ActiveObject)
2351 data->wd_ActiveObject = GetFirstActiveObject(data);
2352 break;
2354 case MUIV_Window_ActiveObject_Prev:
2355 if (old_activenode)
2356 data->wd_ActiveObject = GetPrevNextActiveObject(old_activenode,
2357 PrevObjNodeIterator);
2358 if (NULL == data->wd_ActiveObject)
2359 data->wd_ActiveObject = GetLastActiveObject(data);
2360 break;
2362 default:
2363 data->wd_ActiveObject = (Object*)newval;
2364 break;
2367 if (data->wd_ActiveObject != NULL
2368 && DoMethod(data->wd_RootObject, MUIM_FindAreaObject,
2369 (IPTR)data->wd_ActiveObject)
2370 && (_flags(data->wd_ActiveObject) & MADF_CANDRAW))
2372 DoMethod(data->wd_ActiveObject, MUIM_GoActive);
2373 data->wd_Flags |= MUIWF_OBJECTGOACTIVESENT;
2379 * calculate real dimensions from programmer requirements.
2380 * may be overridden by user settings if MUIA_Window_ID is set.
2382 /* MUIV_Window_Height_Screen and MUIV_Window_Height_Visible
2383 * are not handled yet, as their Width couterparts.
2385 static void WindowSelectDimensions (struct MUI_WindowData *data)
2387 if (!data->wd_Width)
2389 if (data->wd_ReqWidth > 0) data->wd_Width = data->wd_ReqWidth;
2390 else if (data->wd_ReqWidth == MUIV_Window_Width_Default)
2391 data->wd_Width = data->wd_MinMax.DefWidth;
2392 else if (_between(MUIV_Window_Width_MinMax(100),
2393 data->wd_ReqWidth,
2394 MUIV_Window_Width_MinMax(0)))
2396 data->wd_Width = data->wd_MinMax.MinWidth
2397 - data->wd_ReqWidth
2398 * (data->wd_MinMax.MaxWidth - data->wd_MinMax.MinWidth);
2400 else if (_between(MUIV_Window_Width_Screen(100),
2401 data->wd_ReqWidth,
2402 MUIV_Window_Width_Screen(0)))
2404 data->wd_Width = data->wd_RenderInfo.mri_ScreenWidth
2405 * (- (data->wd_ReqWidth + 200)) / 100;
2407 else if (_between(MUIV_Window_Width_Visible(100),
2408 data->wd_ReqWidth,
2409 MUIV_Window_Width_Visible(0)))
2411 data->wd_Width = data->wd_RenderInfo.mri_ScreenWidth
2412 * (- (data->wd_ReqWidth + 100)) / 100;
2415 if (data->wd_ReqHeight > 0) data->wd_Height = data->wd_ReqHeight;
2416 else if (data->wd_ReqHeight == MUIV_Window_Height_Default)
2417 data->wd_Height = data->wd_MinMax.DefHeight;
2418 else if (_between(MUIV_Window_Height_MinMax(100),
2419 data->wd_ReqHeight,
2420 MUIV_Window_Height_MinMax(0)))
2422 data->wd_Height = data->wd_MinMax.MinHeight
2423 - data->wd_ReqHeight
2424 * (data->wd_MinMax.MaxHeight - data->wd_MinMax.MinHeight);
2426 else if (_between(MUIV_Window_Height_Screen(100),
2427 data->wd_ReqHeight,
2428 MUIV_Window_Height_Screen(0)))
2430 struct Screen *scr;
2431 int height;
2433 scr = data->wd_RenderInfo.mri_Screen;
2435 height = scr->Height - data->wd_RenderInfo.mri_BorderTop - data->wd_RenderInfo.mri_BorderBottom;
2437 /* This is new to Zune: If TopEdge Delta is requested
2438 * the screenheight doesn't cover the barlayer */
2439 if (data->wd_Y <= MUIV_Window_TopEdge_Delta(0))
2440 height -= scr->BarHeight + 1;
2442 data->wd_Height = height * (- (data->wd_ReqHeight + 200)) / 100;
2444 else if (_between(MUIV_Window_Height_Visible(100),
2445 data->wd_ReqHeight,
2446 MUIV_Window_Height_Visible(0)))
2448 data->wd_Height = data->wd_RenderInfo.mri_ScreenHeight
2449 * (- (data->wd_ReqHeight + 100)) / 100;
2452 /* scaled */
2453 if (data->wd_ReqWidth == MUIV_Window_Width_Scaled)
2454 data->wd_Width = data->wd_Height * data->wd_MinMax.MinWidth
2455 / data->wd_MinMax.MinHeight;
2456 else if (data->wd_ReqHeight == MUIV_Window_Width_Scaled)
2457 data->wd_Height = data->wd_Width * data->wd_MinMax.MinHeight
2458 / data->wd_MinMax.MinWidth;
2460 data->wd_Width = CLAMP(data->wd_Width, data->wd_MinMax.MinWidth,
2461 data->wd_MinMax.MaxWidth);
2462 data->wd_Height = CLAMP(data->wd_Height, data->wd_MinMax.MinHeight,
2463 data->wd_MinMax.MaxHeight);
2467 /**************************************************************************
2468 OM_NEW
2469 **************************************************************************/
2470 IPTR Window__OM_NEW(struct IClass *cl, Object *obj, struct opSet *msg)
2472 struct MUI_WindowData *data;
2473 struct TagItem *tags,*tag;
2475 obj = (Object *)DoSuperMethodA(cl, obj, (Msg)msg);
2476 if (!obj)
2477 return FALSE;
2479 /* Initial local instance data */
2480 data = INST_DATA(cl, obj);
2482 data->wd_MemoryPool = CreatePool(0, 4096, 2048);
2483 if (NULL == data->wd_MemoryPool)
2485 CoerceMethod(cl, obj, OM_DISPOSE);
2486 return (IPTR)NULL;
2489 data->wd_RenderInfo.mri_WindowObject = obj;
2491 NewList((struct List*)&(data->wd_EHList));
2492 NewList((struct List*)&(data->wd_CCList));
2493 NewList((struct List*)&(data->wd_CycleChain));
2494 NewList((struct List*)&(data->wd_IDList));
2496 data->wd_CrtFlags = WFLG_SIZEGADGET | WFLG_DRAGBAR | WFLG_DEPTHGADGET
2497 | WFLG_CLOSEGADGET | WFLG_SIMPLE_REFRESH
2498 | WFLG_REPORTMOUSE | WFLG_NEWLOOKMENUS;
2499 data->wd_ZoomGadget = TRUE;
2500 data->wd_Events = GetDefaultEvents();
2501 data->wd_ActiveObject = NULL;
2502 data->wd_ID = 0;
2503 data->wd_ReqHeight = MUIV_Window_Height_Default;
2504 data->wd_ReqWidth = MUIV_Window_Width_Default;
2505 data->wd_RootObject = NULL;
2506 data->wd_DefaultObject = NULL;
2508 /* alternate dimensions */
2509 /* no change in coordinates */
2510 data->wd_AltDim.Top = MUIV_Window_AltTopEdge_NoChange;
2511 data->wd_AltDim.Left = MUIV_Window_AltLeftEdge_NoChange;
2512 /* default to min size */
2513 data->wd_AltDim.Width = MUIV_Window_AltWidth_MinMax(0);
2514 data->wd_AltDim.Height = MUIV_Window_AltHeight_MinMax(0);
2515 data->wd_X = MUIV_Window_LeftEdge_Centered;
2516 data->wd_Y = MUIV_Window_TopEdge_Centered;
2517 data->wd_DisabledKeys = 0L;
2518 data->wd_HelpTicker = BUBBLEHELP_TICKER_FIRST;
2520 /* parse initial taglist */
2522 for (tags = msg->ops_AttrList; (tag = NextTagItem((const struct TagItem **)&tags)); )
2524 switch (tag->ti_Tag)
2526 case MUIA_Window_EraseArea:
2527 _handle_bool_tag(data->wd_Flags, tag->ti_Data, MUIWF_ERASEAREA);
2528 break;
2530 case MUIA_Window_CloseGadget:
2531 _handle_bool_tag(data->wd_CrtFlags, tag->ti_Data, WFLG_CLOSEGADGET);
2532 break;
2534 case MUIA_Window_SizeGadget:
2535 _handle_bool_tag(data->wd_CrtFlags, tag->ti_Data, WFLG_SIZEGADGET);
2536 break;
2538 case MUIA_Window_ZoomGadget:
2539 data->wd_ZoomGadget = tag->ti_Data;
2540 break;
2542 case MUIA_Window_Backdrop:
2543 _handle_bool_tag(data->wd_CrtFlags, tag->ti_Data, WFLG_BACKDROP);
2544 break;
2546 case MUIA_Window_Borderless:
2547 _handle_bool_tag(data->wd_CrtFlags, tag->ti_Data, WFLG_BORDERLESS);
2548 break;
2550 case MUIA_Window_DepthGadget:
2551 _handle_bool_tag(data->wd_CrtFlags, tag->ti_Data, WFLG_DEPTHGADGET);
2552 break;
2554 case MUIA_Window_DragBar:
2555 _handle_bool_tag(data->wd_CrtFlags, tag->ti_Data, WFLG_DRAGBAR);
2556 break;
2558 case MUIA_Window_SizeRight:
2559 _handle_bool_tag(data->wd_CrtFlags, tag->ti_Data, WFLG_SIZEBRIGHT);
2560 break;
2562 case MUIA_Window_Height:
2563 data->wd_ReqHeight = (LONG)tag->ti_Data;
2564 break;
2566 case MUIA_Window_Width:
2567 data->wd_ReqWidth = (LONG)tag->ti_Data;
2568 break;
2570 case MUIA_Window_ID:
2571 set(obj, MUIA_Window_ID, tag->ti_Data);
2572 break;
2574 case MUIA_Window_IsSubWindow:
2575 _handle_bool_tag(data->wd_Flags, tag->ti_Data, MUIWF_ISSUBWINDOW);
2576 break;
2578 case MUIA_Window_Title:
2579 set(obj, MUIA_Window_Title, tag->ti_Data);
2580 break;
2582 case MUIA_Window_ScreenTitle:
2583 set(obj, MUIA_Window_ScreenTitle, tag->ti_Data);
2584 break;
2586 case MUIA_Window_Activate:
2587 _handle_bool_tag(data->wd_Flags, !tag->ti_Data, MUIWF_DONTACTIVATE);
2588 break;
2590 case MUIA_Window_DefaultObject:
2591 set(obj, MUIA_Window_DefaultObject, tag->ti_Data);
2592 break;
2594 case MUIA_Window_Menustrip:
2595 data->wd_ChildMenustrip = (Object*)tag->ti_Data;
2596 break;
2598 case MUIA_Window_NoMenus:
2599 data->wd_NoMenus = (BOOL) tag->ti_Data;
2600 break;
2602 case MUIA_Window_RootObject:
2603 if (!tag->ti_Data)
2605 CoerceMethod(cl, obj, OM_DISPOSE);
2606 return 0;
2608 set(obj, MUIA_Window_RootObject, tag->ti_Data);
2609 break;
2611 case MUIA_Window_AltHeight:
2612 data->wd_AltDim.Height = (WORD)tag->ti_Data;
2613 break;
2615 case MUIA_Window_AltWidth:
2616 data->wd_AltDim.Width = (WORD)tag->ti_Data;
2617 break;
2619 case MUIA_Window_AltLeftEdge:
2620 data->wd_AltDim.Left = (WORD)tag->ti_Data;
2621 break;
2623 case MUIA_Window_AltTopEdge:
2624 data->wd_AltDim.Top = (WORD)tag->ti_Data;
2625 break;
2627 case MUIA_Window_AppWindow:
2628 _handle_bool_tag(data->wd_Flags, tag->ti_Data, MUIWF_ISAPPWINDOW);
2629 break;
2631 case MUIA_Window_LeftEdge:
2632 data->wd_X = tag->ti_Data;
2633 break;
2635 case MUIA_Window_TopEdge:
2636 data->wd_Y = tag->ti_Data;
2637 break;
2639 case MUIA_Window_UseBottomBorderScroller:
2640 _handle_bool_tag(data->wd_Flags, tag->ti_Data, MUIWF_USEBOTTOMSCROLLER);
2641 break;
2643 case MUIA_Window_UseRightBorderScroller:
2644 _handle_bool_tag(data->wd_Flags, tag->ti_Data, MUIWF_USERIGHTSCROLLER);
2645 break;
2647 case MUIA_Window_DisableKeys:
2648 data->wd_DisabledKeys = tag->ti_Data;
2649 break;
2651 case MUIA_Window_RefWindow:
2652 data->wd_RefWindow = (Object *)tag->ti_Data;
2653 break;
2655 case MUIA_Window_Screen:
2656 data->wd_UserScreen = (struct Screen *)tag->ti_Data;
2657 break;
2659 case MUIA_Window_PublicScreen:
2660 data->wd_UserPublicScreen = (STRPTR)tag->ti_Data;
2661 break;
2665 /* D(bug("muimaster.library/window.c: Window Object created at 0x%lx back=%lx\n", */
2666 /* obj,data->wd_Background)); */
2668 return (IPTR)obj;
2671 /**************************************************************************
2672 OM_DISPOSE
2673 **************************************************************************/
2674 IPTR Window__OM_DISPOSE(struct IClass *cl, Object *obj, Msg msg)
2676 struct MUI_WindowData *data = INST_DATA(cl, obj);
2678 /* D(bug("Window_Dispose(%p)\n", obj)); */
2680 #if 0 /* We no longer clear muiGlobalInfo() during disconnections, so
2681 this can cause problems (remove object which is already removed).
2682 Furthermore AFAIK it is not legal to dispose a window object
2683 which is still ocnnected to the application object, anyway. */
2685 if (muiGlobalInfo(obj) && _app(obj))
2687 /* D(bug(" Window_Dispose(%p) : calling app->OM_REMMEMBER\n", obj)); */
2688 DoMethod(_app(obj), OM_REMMEMBER, (IPTR)obj);
2690 #endif
2692 if (data->wd_RootObject)
2693 MUI_DisposeObject(data->wd_RootObject);
2695 if (data->wd_ChildMenustrip)
2696 MUI_DisposeObject(data->wd_ChildMenustrip);
2698 if (data->wd_Title) FreeVec(data->wd_Title);
2699 if (data->wd_ScreenTitle)FreeVec(data->wd_ScreenTitle);
2701 DeletePool(data->wd_MemoryPool);
2703 /* D(bug(" Window_Dispose(%p) : calling supermethod\n", obj)); */
2704 return DoSuperMethodA(cl, obj, msg);
2707 static ULONG WindowOpen(struct IClass *cl, Object *obj);
2708 static ULONG WindowClose(struct IClass *cl, Object *obj);
2710 /**************************************************************************
2711 OM_SET
2712 **************************************************************************/
2713 IPTR Window__OM_SET(struct IClass *cl, Object *obj, struct opSet *msg)
2715 struct MUI_WindowData *data = INST_DATA(cl, obj);
2716 struct TagItem *tags = msg->ops_AttrList;
2717 struct TagItem *tag;
2719 while ((tag = NextTagItem((const struct TagItem **)&tags)) != NULL)
2721 switch (tag->ti_Tag)
2723 case MUIA_Window_Activate:
2724 if (data->wd_RenderInfo.mri_Window)
2726 if (tag->ti_Data && !(data->wd_Flags & MUIWF_ACTIVE))
2728 ActivateWindow(data->wd_RenderInfo.mri_Window);
2729 _handle_bool_tag(data->wd_Flags, tag->ti_Data, MUIWF_ACTIVE);
2732 else
2733 _handle_bool_tag(data->wd_Flags, !tag->ti_Data, MUIWF_DONTACTIVATE);
2734 break;
2736 case MUIA_Window_ActiveObject:
2737 /* D(bug("MUIA_Window_ActiveObject %ld (%p)\n", tag->ti_Data, tag->ti_Data)); */
2738 SetActiveObject(data, obj, tag->ti_Data);
2739 break;
2741 case MUIA_Window_DefaultObject:
2742 data->wd_DefaultObject = (APTR)tag->ti_Data;
2743 break;
2745 case MUIA_Window_ID:
2746 data->wd_ID = tag->ti_Data;
2747 break;
2749 case MUIA_Window_IsSubWindow:
2750 _handle_bool_tag(data->wd_Flags, tag->ti_Data, MUIWF_ISSUBWINDOW);
2751 break;
2753 case MUIA_Window_Open:
2754 if (tag->ti_Data)
2756 if (data->wd_Flags & MUIWF_HIDDEN)
2757 data->wd_Flags |= MUIWF_OPENONUNHIDE;
2758 else
2759 if (!(data->wd_Flags & MUIWF_OPENED))
2760 WindowOpen(cl, obj);
2761 else
2763 DoMethod(obj, MUIM_Window_ToFront);
2764 set(obj, MUIA_Window_Activate, TRUE);
2767 else
2768 if (data->wd_Flags & MUIWF_HIDDEN)
2769 data->wd_Flags &= ~MUIWF_OPENONUNHIDE;
2770 else
2771 if (data->wd_Flags & MUIWF_OPENED)
2772 WindowClose(cl, obj);
2773 break;
2775 case MUIA_ShowMe: /* PRIVATE *abuse* of the Area's ShowMe attr */
2776 if (tag->ti_Data)
2778 /* Deiconify */
2780 if (data->wd_Flags & MUIWF_HIDDEN)
2782 data->wd_Flags &= ~MUIWF_HIDDEN;
2784 if (data->wd_Flags & MUIWF_OPENONUNHIDE)
2786 data->wd_Flags &= ~MUIWF_OPENONUNHIDE;
2787 set(obj, MUIA_Window_Open, TRUE);
2791 else
2793 /* Iconify */
2795 if (data->wd_Flags & MUIWF_OPENED)
2797 data->wd_Flags |= MUIWF_OPENONUNHIDE;
2799 set(obj, MUIA_Window_Open, FALSE);
2802 data->wd_Flags |= MUIWF_HIDDEN;
2804 break;
2806 case MUIA_Window_RootObject:
2807 ChangeRootObject(data, obj, (Object *)tag->ti_Data);
2808 break;
2810 case MUIA_Window_Title:
2811 if (data->wd_Title) FreeVec(data->wd_Title);
2812 data->wd_Title = StrDup((STRPTR)tag->ti_Data);
2813 if (data->wd_RenderInfo.mri_Window)
2814 SetWindowTitles(data->wd_RenderInfo.mri_Window,data->wd_Title, (CONST_STRPTR)~0);
2815 break;
2817 case MUIA_Window_ScreenTitle:
2818 if (data->wd_ScreenTitle) FreeVec(data->wd_ScreenTitle);
2819 data->wd_ScreenTitle = StrDup((STRPTR)tag->ti_Data);
2820 if (data->wd_RenderInfo.mri_Window)
2821 SetWindowTitles(data->wd_RenderInfo.mri_Window,
2822 (CONST_STRPTR)~0, data->wd_ScreenTitle);
2823 break;
2825 case MUIA_Window_NoMenus:
2826 data->wd_NoMenus = (BOOL) tag->ti_Data;
2827 if (data->wd_RenderInfo.mri_Window)
2829 if (data->wd_NoMenus)
2830 data->wd_RenderInfo.mri_Window->Flags |= WFLG_RMBTRAP;
2831 else
2832 data->wd_RenderInfo.mri_Window->Flags &= ~WFLG_RMBTRAP;
2835 break;
2837 case MUIA_Window_UseBottomBorderScroller:
2838 _handle_bool_tag(data->wd_Flags, tag->ti_Data, MUIWF_USEBOTTOMSCROLLER);
2839 break;
2841 case MUIA_Window_UseRightBorderScroller:
2842 _handle_bool_tag(data->wd_Flags, tag->ti_Data, MUIWF_USERIGHTSCROLLER);
2843 break;
2845 case MUIA_Window_DisableKeys:
2846 data->wd_DisabledKeys = tag->ti_Data;
2847 break;
2849 case MUIA_Window_RefWindow:
2850 data->wd_RefWindow = (Object *)tag->ti_Data;
2851 break;
2853 #warning "TODO: obsolete hacked atribute - remove"
2854 #if defined(MUIA_Window_WandererBackdrop)
2855 case MUIA_Window_WandererBackdrop:
2856 _handle_bool_tag(data->wd_CrtFlags, tag->ti_Data, WFLG_BACKDROP);
2857 _handle_bool_tag(data->wd_CrtFlags, !tag->ti_Data, WFLG_DRAGBAR);
2858 _handle_bool_tag(data->wd_CrtFlags, !tag->ti_Data, WFLG_SIZEGADGET);
2859 _handle_bool_tag(data->wd_CrtFlags, !tag->ti_Data, WFLG_CLOSEGADGET);
2860 _handle_bool_tag(data->wd_CrtFlags, !tag->ti_Data, WFLG_DEPTHGADGET);
2861 _handle_bool_tag(data->wd_CrtFlags, tag->ti_Data, WFLG_BORDERLESS);
2862 if (tag->ti_Data)
2864 data->wd_ReqWidth = (LONG)MUIV_Window_Width_Screen(100);
2865 /* won't take the barlayer into account */
2866 data->wd_ReqHeight = (LONG)MUIV_Window_Height_Screen(100);
2867 data->wd_Width = 0;
2868 data->wd_Height = 0;
2869 data->wd_X = (LONG)0;
2870 /* place the window below the bar layer */
2871 data->wd_Y = (LONG)MUIV_Window_TopEdge_Delta(0);
2873 break;
2874 #endif
2876 case MUIA_Window_LeftEdge:
2877 data->wd_X = tag->ti_Data;
2878 break;
2880 case MUIA_Window_TopEdge:
2881 data->wd_Y = tag->ti_Data;
2882 break;
2884 case MUIA_Window_Width:
2885 data->wd_ReqWidth = (LONG)tag->ti_Data;
2886 data->wd_Width = 0; /* otherwise windowselectdimensions() ignores ReqWidth */
2887 break;
2889 case MUIA_Window_Height:
2890 data->wd_ReqWidth = (LONG)tag->ti_Data;
2891 data->wd_Height = 0;
2892 break;
2894 case MUIA_Window_Screen:
2895 data->wd_UserScreen = (struct Screen *)tag->ti_Data;
2896 break;
2898 case MUIA_Window_PublicScreen:
2899 data->wd_UserPublicScreen = (STRPTR)tag->ti_Data;
2900 break;
2906 return DoSuperMethodA(cl, obj, (Msg)msg);
2909 /**************************************************************************
2910 OM_GET
2911 **************************************************************************/
2912 IPTR Window__OM_GET(struct IClass *cl, Object *obj, struct opGet *msg)
2914 #define STORE *(msg->opg_Storage)
2916 struct MUI_WindowData *data = INST_DATA(cl, obj);
2918 STORE = (IPTR)0;
2920 switch(msg->opg_AttrID)
2922 case MUIA_Window_Activate:
2923 STORE = (data->wd_Flags & (MUIWF_ACTIVE | MUIWF_OPENED)) == (MUIWF_ACTIVE | MUIWF_OPENED);
2924 return TRUE ;
2926 case MUIA_Window_Window:
2927 STORE = (IPTR)data->wd_RenderInfo.mri_Window;
2928 return TRUE;
2930 case MUIA_Window_Screen:
2931 STORE = (IPTR)data->wd_RenderInfo.mri_Screen;
2932 return TRUE;
2934 case MUIA_Window_PublicScreen:
2935 STORE = (IPTR)data->wd_UserPublicScreen;
2936 return TRUE;
2938 case MUIA_Window_ActiveObject:
2939 if ((data->wd_ActiveObject != NULL)
2940 && (DoMethod(data->wd_RootObject, MUIM_FindAreaObject,
2941 (IPTR)data->wd_ActiveObject) != (IPTR)NULL))
2942 STORE = (IPTR)data->wd_ActiveObject;
2943 else
2944 STORE = (IPTR)NULL;
2945 return TRUE;
2947 case MUIA_Window_CloseRequest:
2948 STORE = FALSE;
2949 return TRUE;
2951 case MUIA_Window_DefaultObject:
2952 STORE = (IPTR)data->wd_DefaultObject;
2953 return TRUE;
2955 case MUIA_Window_DisableKeys:
2956 STORE = data->wd_DisabledKeys;
2957 return TRUE;
2959 case MUIA_Window_Height:
2960 STORE = (IPTR)data->wd_Height;
2961 return TRUE;
2963 case MUIA_Window_ID:
2964 STORE = data->wd_ID;
2965 return TRUE;
2967 case MUIA_Window_IsSubWindow:
2968 STORE = (data->wd_Flags & MUIWF_ISSUBWINDOW) == MUIWF_ISSUBWINDOW;
2969 return TRUE;
2971 case MUIA_Window_LeftEdge:
2972 if (data->wd_RenderInfo.mri_Window)
2973 STORE = (IPTR)data->wd_RenderInfo.mri_Window->LeftEdge;
2974 else
2975 STORE = (IPTR)0;
2976 return TRUE;
2978 case MUIA_Window_Open:
2979 STORE = (data->wd_Flags & MUIWF_OPENED) == MUIWF_OPENED;
2980 return TRUE;
2982 case MUIA_Window_RootObject:
2983 STORE = (IPTR)data->wd_RootObject;
2984 return TRUE;
2986 case MUIA_Window_ScreenTitle:
2987 STORE = (IPTR)data->wd_ScreenTitle;
2988 return TRUE;
2990 case MUIA_Window_Title:
2991 STORE = (IPTR)data->wd_Title;
2992 return TRUE;
2994 case MUIA_Window_TopEdge:
2995 if (data->wd_RenderInfo.mri_Window)
2996 STORE = (IPTR)data->wd_RenderInfo.mri_Window->TopEdge;
2997 else
2998 STORE = (IPTR)0;
2999 return(TRUE);
3001 case MUIA_Window_Width:
3002 STORE = (IPTR)data->wd_Width;
3003 return TRUE;
3005 case MUIA_Version:
3006 STORE = __version;
3007 return TRUE;
3009 case MUIA_Revision:
3010 STORE = __revision;
3011 return TRUE;
3014 return DoSuperMethodA(cl, obj, (Msg) msg);
3015 #undef STORE
3019 * MUIM_FindUData : tests if the MUIA_UserData of the object
3020 * contains the given <udata> and returns the object pointer in this case.
3022 IPTR Window__MUIM_FindUData(struct IClass *cl, Object *obj, struct MUIP_FindUData *msg)
3024 struct MUI_WindowData *data = INST_DATA(cl, obj);
3026 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
3027 return (IPTR)obj;
3029 if (data->wd_RootObject)
3030 return DoMethodA(data->wd_RootObject, (Msg)msg);
3032 return 0;
3037 * MUIM_GetUData : This method tests if the MUIA_UserData of the object
3038 * contains the given <udata> and gets <attr> to <storage> for itself
3039 * in this case.
3041 IPTR Window__MUIM_GetUData(struct IClass *cl, Object *obj, struct MUIP_GetUData *msg)
3043 struct MUI_WindowData *data = INST_DATA(cl, obj);
3045 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
3047 get(obj, msg->attr, msg->storage);
3048 return TRUE;
3051 if (data->wd_RootObject)
3052 return DoMethodA(data->wd_RootObject, (Msg)msg);
3054 return FALSE;
3059 * MUIM_SetUData : This method tests if the MUIA_UserData of the object
3060 * contains the given <udata> and sets <attr> to <val> for itself in this case.
3062 IPTR Window__MUIM_SetUData(struct IClass *cl, Object *obj, struct MUIP_SetUData *msg)
3064 struct MUI_WindowData *data = INST_DATA(cl, obj);
3066 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
3067 set(obj, msg->attr, msg->val);
3069 if (data->wd_RootObject)
3070 DoMethodA(data->wd_RootObject, (Msg)msg);
3072 return TRUE;
3077 * MUIM_SetUDataOnce : This method tests if the MUIA_UserData of the object
3078 * contains the given <udata> and sets <attr> to <val> for itself in this case.
3080 IPTR Window__MUIM_SetUDataOnce(struct IClass *cl, Object *obj, struct MUIP_SetUDataOnce *msg)
3082 struct MUI_WindowData *data = INST_DATA(cl, obj);
3084 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
3086 set(obj, msg->attr, msg->val);
3087 return TRUE;
3090 if (data->wd_RootObject)
3091 return DoMethodA(data->wd_RootObject, (Msg)msg);
3093 return FALSE;
3096 /**************************************************************************
3097 Called by Application (parent) object whenever this object is added.
3098 init GlobalInfo
3099 **************************************************************************/
3100 IPTR Window__MUIM_ConnectParent(struct IClass *cl, Object *obj,
3101 struct MUIP_ConnectParent *msg)
3103 struct MUI_WindowData *data = INST_DATA(cl, obj);
3105 if (!DoSuperMethodA(cl,obj,(Msg)msg)) return 0;
3107 if (data->wd_RootObject)
3108 DoMethod(data->wd_RootObject, MUIM_ConnectParent, (IPTR)obj);
3110 if (data->wd_ChildMenustrip)
3111 DoMethod(data->wd_ChildMenustrip, MUIM_ConnectParent, (IPTR)obj);
3113 return TRUE;
3117 /**************************************************************************
3118 called by parent object
3119 **************************************************************************/
3120 IPTR Window__MUIM_DisconnectParent(struct IClass *cl, Object *obj, struct MUIP_DisconnectParent *msg)
3122 struct MUI_WindowData *data = INST_DATA(cl, obj);
3124 /* D(bug("Window_DisconnectParent(%p) : muiGlobalInfo=%p\n", muiGlobalInfo(obj))); */
3125 if (muiGlobalInfo(obj))
3127 /* Close the window before disconnecting all the childs */
3128 if ((data->wd_Flags & MUIWF_OPENED))
3130 /* D(bug(" Window_DisconnectParent(%p) : closing window\n", muiGlobalInfo(obj))); */
3131 set(obj, MUIA_Window_Open, FALSE);
3133 if (data->wd_ChildMenustrip)
3134 DoMethod(data->wd_ChildMenustrip, MUIM_DisconnectParent, (IPTR)obj);
3136 if (data->wd_RootObject)
3137 DoMethodA(data->wd_RootObject, (Msg)msg);
3139 /* D(bug(" Window_DisconnectParent(%p) : calling supermethod\n", muiGlobalInfo(obj))); */
3140 return DoSuperMethodA(cl,obj,(Msg)msg);
3142 else
3144 return 0;
3148 static void SetRootObjInnerSpacing(Object *obj, struct MUI_WindowData *data)
3150 UWORD wd_innerLeft, wd_innerRight, wd_innerTop, wd_innerBottom;
3152 if (data->wd_CrtFlags & WFLG_BORDERLESS)
3154 wd_innerLeft = 0;
3155 wd_innerRight = 0;
3156 wd_innerTop = 0;
3157 wd_innerBottom = 0;
3159 else
3161 wd_innerLeft = muiGlobalInfo(obj)->mgi_Prefs->window_inner_left;
3162 wd_innerRight = muiGlobalInfo(obj)->mgi_Prefs->window_inner_right;
3163 wd_innerTop = muiGlobalInfo(obj)->mgi_Prefs->window_inner_top;
3164 wd_innerBottom = muiGlobalInfo(obj)->mgi_Prefs->window_inner_bottom;
3167 if (!(muiAreaData(data->wd_RootObject)->mad_Flags & MADF_INNERLEFT))
3169 muiAreaData(data->wd_RootObject)->mad_InnerLeft = wd_innerLeft;
3172 if (!(muiAreaData(data->wd_RootObject)->mad_Flags & MADF_INNERTOP))
3174 muiAreaData(data->wd_RootObject)->mad_InnerTop = wd_innerTop;
3177 if (!(muiAreaData(data->wd_RootObject)->mad_Flags & MADF_INNERRIGHT))
3179 muiAreaData(data->wd_RootObject)->mad_InnerRight = wd_innerRight;
3182 if (!(muiAreaData(data->wd_RootObject)->mad_Flags & MADF_INNERBOTTOM))
3184 muiAreaData(data->wd_RootObject)->mad_InnerBottom = wd_innerBottom;
3189 * Called before window is opened or resized. It determines its bounds,
3190 * so you can call WindowSelectDimensions() to find the final dims.
3192 static void WindowMinMax(Object *obj, struct MUI_WindowData *data)
3194 SetRootObjInnerSpacing(obj, data);
3195 /* inquire about sizes */
3196 DoMethod(data->wd_RootObject, MUIM_AskMinMax, (IPTR)&data->wd_MinMax);
3197 /* D(bug("*** root minmax = %ld,%ld => %ld,%ld\n", data->wd_MinMax.MinWidth, */
3198 /* data->wd_MinMax.MinHeight, */
3199 /* data->wd_MinMax.MaxWidth, data->wd_MinMax.MaxHeight)); */
3200 __area_finish_minmax(data->wd_RootObject, &data->wd_MinMax);
3201 /* D(bug("*** root minmax2 = %ld,%ld => %ld,%ld\n", data->wd_MinMax.MinWidth, */
3202 /* data->wd_MinMax.MinHeight, */
3203 /* data->wd_MinMax.MaxWidth, data->wd_MinMax.MaxHeight)); */
3207 static void InstallBackbuffer (struct IClass *cl, Object *obj)
3209 struct MUI_WindowData *data = INST_DATA(cl, obj);
3210 #if 0
3211 struct Window *win = data->wd_RenderInfo.mri_Window;
3213 data->wd_RenderInfo.mri_BufferBM =
3214 AllocBitMap(win->Width, win->Height, win->RPort->BitMap->Depth,
3215 0, win->RPort->BitMap);
3216 #endif
3217 if (data->wd_RenderInfo.mri_BufferBM)
3219 /* D(bug("install_backbuffer : allocated bitmap %dx%dx%d with friend %p\n", */
3220 /* win->Width, win->Height, win->RPort->BitMap->Depth, win->RPort->BitMap)); */
3221 InitRastPort(&data->wd_RenderInfo.mri_BufferRP);
3222 data->wd_RenderInfo.mri_BufferRP.BitMap = data->wd_RenderInfo.mri_BufferBM;
3226 static void DeinstallBackbuffer (struct IClass *cl, Object *obj)
3228 struct MUI_WindowData *data = INST_DATA(cl, obj);
3230 if (data->wd_RenderInfo.mri_BufferBM)
3232 DeinitRastPort(&data->wd_RenderInfo.mri_BufferRP);
3233 FreeBitMap(data->wd_RenderInfo.mri_BufferBM);
3234 data->wd_RenderInfo.mri_BufferBM = NULL;
3239 * Called after window is opened or resized.
3240 * An expose event is already queued, it will trigger
3241 * MUIM_Draw for us when going back to main loop.
3243 static void WindowShow (struct IClass *cl, Object *obj)
3245 struct MUI_WindowData *data = INST_DATA(cl, obj);
3246 struct Window *win = data->wd_RenderInfo.mri_Window;
3247 /* D(bug("window_show %s %d\n", __FILE__, __LINE__)); */
3249 _left(data->wd_RootObject) = win->BorderLeft;
3250 _top(data->wd_RootObject) = win->BorderTop;
3251 _width(data->wd_RootObject) = data->wd_Width;
3252 _height(data->wd_RootObject) = data->wd_Height;
3254 DoMethod(data->wd_RootObject, MUIM_Layout);
3256 ShowRenderInfo(&data->wd_RenderInfo);
3257 /* D(bug("zune_imspec_show %s %d\n", __FILE__, __LINE__)); */
3258 zune_imspec_show(data->wd_Background, obj);
3259 DoShowMethod(data->wd_RootObject);
3262 static ULONG WindowOpen(struct IClass *cl, Object *obj)
3264 struct MUI_WindowData *data = INST_DATA(cl, obj);
3266 if (!data->wd_RootObject)
3267 return FALSE;
3269 if (!DoMethod(obj, MUIM_Window_Setup))
3270 return FALSE;
3272 /* I got display info, so calculate your display dependant data */
3273 if (!DoSetupMethod(data->wd_RootObject, &data->wd_RenderInfo))
3275 DoMethod(obj, MUIM_Window_Cleanup);
3276 return FALSE;
3279 /* inquire about sizes */
3280 WindowMinMax(obj,data);
3281 WindowSelectDimensions(data);
3283 /* Decide which menustrip should be used */
3284 if (!data->wd_ChildMenustrip)
3285 get(_app(obj), MUIA_Application_Menustrip, (IPTR *)&data->wd_Menustrip);
3286 else
3287 data->wd_Menustrip = data->wd_ChildMenustrip;
3289 /* open window here ... */
3290 if (!DisplayWindow(obj,data))
3292 /* free display dependant data */
3293 data->wd_Menustrip = NULL;
3294 DoMethod(data->wd_RootObject, MUIM_Cleanup);
3295 DoMethod(obj, MUIM_Window_Cleanup);
3296 return FALSE;
3299 InstallBackbuffer(cl, obj);
3301 data->wd_Flags |= MUIWF_OPENED;
3303 WindowShow(cl, obj);
3306 LONG left,top,width,height;
3308 left = data->wd_RenderInfo.mri_Window->BorderLeft;
3309 top = data->wd_RenderInfo.mri_Window->BorderTop,
3310 width = data->wd_RenderInfo.mri_Window->Width
3311 - data->wd_RenderInfo.mri_Window->BorderRight - left;
3312 height = data->wd_RenderInfo.mri_Window->Height
3313 - data->wd_RenderInfo.mri_Window->BorderBottom - top;
3315 /* D(bug("zune_imspec_draw %s %d\n", __FILE__, __LINE__)); */
3316 // D(bug("%d:zune_imspec_draw(%p) l=%d t=%d w=%d h=%d xo=%d yo=%d\n",
3317 // __LINE__, data->wd_Background, left, top, width,
3318 // height, left, top));
3320 zune_imspec_draw(data->wd_Background, &data->wd_RenderInfo,
3321 left, top, width, height, left, top, 0);
3324 MUI_Redraw(data->wd_RootObject, MADF_DRAWOBJECT);
3326 D(bug("MUIC_Window:windowOpen() ActiveObject=%p\n", data->wd_ActiveObject));
3327 if (data->wd_OldActive != NULL)
3329 set(obj, MUIA_Window_ActiveObject, data->wd_OldActive);
3332 return TRUE;
3335 /******************************************************************************/
3336 /******************************************************************************/
3338 static ULONG WindowClose(struct IClass *cl, Object *obj)
3340 struct MUI_WindowData *data = INST_DATA(cl, obj);
3342 if (data->wd_ActiveObject != NULL)
3344 data->wd_OldActive = data->wd_ActiveObject;
3345 set(obj, MUIA_Window_ActiveObject, MUIV_Window_ActiveObject_None);
3348 KillHelpBubble(data, obj, BUBBLEHELP_TICKER_FIRST);
3350 /* remove from window */
3351 DoHideMethod(data->wd_RootObject);
3352 zune_imspec_hide(data->wd_Background);
3354 DeinstallBackbuffer(cl, obj);
3356 HideRenderInfo(&data->wd_RenderInfo);
3358 /* close here ... */
3359 UndisplayWindow(obj,data);
3361 data->wd_Flags &= ~MUIWF_OPENED;
3362 data->wd_Menustrip = NULL;
3364 /* free display dependant data */
3365 DoMethod(data->wd_RootObject, MUIM_Cleanup);
3366 DoMethod(obj, MUIM_Window_Cleanup);
3367 return TRUE;
3370 /* calculate a new layout
3371 * see MUIA_ShowMe
3372 * see Group_ExitChange
3373 * see Group_Columns
3374 * see Group_Rows
3376 IPTR Window__MUIM_RecalcDisplay(struct IClass *cl, Object *obj, struct MUIP_Window_RecalcDisplay *msg)
3378 struct MUI_WindowData *data = INST_DATA(cl, obj);
3379 LONG left,top,width,height;
3380 BOOL resized;
3381 Object *current_obj;
3383 if (!(data->wd_Flags & MUIWF_OPENED))
3384 return 0;
3386 current_obj = msg->originator;
3388 // typically originator is a group which has been added/removed a child
3389 // calculate minmax of current obj
3390 // if new minmax can accomodate current obj size, stop
3391 // else try with its parent
3392 // the resulting object will get a new layout
3393 // it currently produces some redundant AskMinMax but allows
3394 // to not always relayout the whole window
3396 D(bug("RecalcDisplay on %p\n", current_obj));
3397 while (current_obj != NULL)
3399 DoMethod(current_obj, MUIM_AskMinMax, (IPTR)&muiAreaData(current_obj)->mad_MinMax);
3400 __area_finish_minmax(current_obj, &muiAreaData(current_obj)->mad_MinMax);
3402 D(bug("size w = %d, h = %d\n", _width(current_obj), _height(current_obj)));
3403 D(bug("new w = %d-%d, h = %d-%d\n", _minwidth(current_obj), _maxwidth(current_obj),
3404 _minheight(current_obj), _maxheight(current_obj)));
3406 if (!_between(_minwidth(current_obj), _width(current_obj), _maxwidth(current_obj))
3407 || !_between(_minheight(current_obj), _height(current_obj), _maxheight(current_obj)))
3409 current_obj = _parent(current_obj);
3410 D(bug("RecalcDisplay, try parent %p\n", current_obj));
3412 else
3414 D(bug("found it\n"));
3415 break;
3419 if (!current_obj)
3420 current_obj = data->wd_RootObject;
3422 WindowMinMax(obj, data);
3423 DoHideMethod(current_obj);
3424 /* resize window ? */
3425 WindowSelectDimensions(data);
3426 resized = WindowResize(data);
3429 struct Window *win = data->wd_RenderInfo.mri_Window;
3430 _left(data->wd_RootObject) = win->BorderLeft;
3431 _top(data->wd_RootObject) = win->BorderTop;
3432 _width(data->wd_RootObject) = data->wd_Width;
3433 _height(data->wd_RootObject) = data->wd_Height;
3435 DoMethod(current_obj, MUIM_Layout);
3436 DoShowMethod(current_obj);
3438 if (muiGlobalInfo(obj)->mgi_Prefs->window_redraw == WINDOW_REDRAW_WITHOUT_CLEAR)
3439 MUI_Redraw(current_obj, MADF_DRAWOBJECT);
3440 else
3442 left = data->wd_RenderInfo.mri_Window->BorderLeft;
3443 top = data->wd_RenderInfo.mri_Window->BorderTop;
3444 width = data->wd_RenderInfo.mri_Window->Width
3445 - data->wd_RenderInfo.mri_Window->BorderRight - left;
3446 height = data->wd_RenderInfo.mri_Window->Height
3447 - data->wd_RenderInfo.mri_Window->BorderBottom - top;
3449 zune_imspec_draw(data->wd_Background, &data->wd_RenderInfo,
3450 left, top, width, height, left, top, 0);
3451 MUI_Redraw(data->wd_RootObject, MADF_DRAWALL);
3454 ActivateObject(data);
3456 return TRUE;
3460 /**************************************************************************
3461 MUIM_AddEventHandler
3462 **************************************************************************/
3463 IPTR Window__MUIM_AddEventHandler(struct IClass *cl, Object *obj,
3464 struct MUIP_Window_AddEventHandler *msg)
3466 struct MUI_WindowData *data = INST_DATA(cl, obj);
3468 //D(bug("muimaster.library/window.c: Add Eventhandler %p\n", msg->ehnode));
3470 #ifdef __AROS__
3471 #if !(AROS_FLAVOUR & AROS_FLAVOUR_BINCOMPAT)
3472 msg->ehnode->ehn_Node.ln_Pri = msg->ehnode->ehn_Priority;
3473 #else
3474 msg->ehnode->ehn_Priority = msg->ehnode->ehn_Priority;
3475 #endif
3476 #endif
3477 EnqueueByPriAndAddress((struct List *)&data->wd_EHList, (struct Node *)msg->ehnode);
3478 ChangeEvents(data, GetDefaultEvents());
3479 return TRUE;
3482 /**************************************************************************
3483 MUIM_RemEventHandler
3484 **************************************************************************/
3485 IPTR Window__MUIM_RemEventHandler(struct IClass *cl, Object *obj,
3486 struct MUIP_Window_RemEventHandler *msg)
3488 struct MUI_WindowData *data = INST_DATA(cl, obj);
3490 //D(bug("muimaster.library/window.c: Rem Eventhandler %p\n", msg->ehnode));
3492 Remove((struct Node *)msg->ehnode);
3493 ChangeEvents(data, GetDefaultEvents());
3494 return TRUE;
3497 /**************************************************************************
3498 Note that this is MUIM_Window_Setup, not MUIM_Setup
3499 **************************************************************************/
3500 IPTR Window__MUIM_Setup(struct IClass *cl, Object *obj, Msg msg)
3502 struct MUI_WindowData *data = INST_DATA(cl, obj);
3504 if (!SetupRenderInfo(obj, data, &data->wd_RenderInfo))
3505 return FALSE;
3507 data->wd_Background = zune_imspec_setup(MUII_WindowBack, &data->wd_RenderInfo);
3509 if (muiGlobalInfo(obj)->mgi_Prefs->window_redraw == WINDOW_REDRAW_WITH_CLEAR)
3510 data->wd_Flags |= MUIWF_ERASEAREA;
3512 return TRUE;
3515 /**************************************************************************
3516 MUIM_Cleanup
3517 **************************************************************************/
3518 IPTR Window__MUIM_Cleanup(struct IClass *cl, Object *obj, Msg msg)
3520 struct MUI_WindowData *data = INST_DATA(cl, obj);
3522 zune_imspec_cleanup(data->wd_Background);
3524 if (data->wd_dnd)
3526 DeleteDragNDrop(data->wd_dnd);
3527 data->wd_dnd = NULL;
3530 CleanupRenderInfo(data, &data->wd_RenderInfo);
3531 return TRUE;
3535 /**************************************************************************
3536 This adds the the control char handler and also do the MUIA_CycleChain
3537 stuff. Orginal MUI does this in an other way.
3538 **************************************************************************/
3539 IPTR Window__MUIM_AddControlCharHandler(struct IClass *cl, Object *obj,
3540 struct MUIP_Window_AddControlCharHandler *msg)
3542 struct MUI_WindowData *data = INST_DATA(cl, obj);
3543 struct ObjNode *node;
3545 if (msg->ccnode->ehn_Events)
3547 #ifdef __AROS__
3548 #if !(AROS_FLAVOUR & AROS_FLAVOUR_BINCOMPAT)
3549 msg->ccnode->ehn_Node.ln_Pri = msg->ccnode->ehn_Priority;
3550 #else
3551 msg->ccnode->ehn_Priority = msg->ccnode->ehn_Priority;
3552 #endif
3553 #endif
3554 Enqueue((struct List *)&data->wd_CCList, (struct Node *)msg->ccnode);
3556 /* Due to the lack of a better idea ... */
3557 if (muiAreaData(msg->ccnode->ehn_Object)->mad_Flags & MADF_CYCLECHAIN)
3559 node = AllocPooled(data->wd_MemoryPool, sizeof(struct ObjNode));
3560 if (node)
3562 node->obj = msg->ccnode->ehn_Object;
3563 AddTail((struct List *)&data->wd_CycleChain,(struct Node*)node);
3566 return TRUE;
3569 /**************************************************************************
3570 MUIM_RemControlCharHandler
3571 **************************************************************************/
3572 IPTR Window__MUIM_RemControlCharHandler(struct IClass *cl, Object *obj,
3573 struct MUIP_Window_RemControlCharHandler *msg)
3575 struct MUI_WindowData *data = INST_DATA(cl, obj);
3576 struct ObjNode *node = FindObjNode(&data->wd_CycleChain,msg->ccnode->ehn_Object);
3578 if (msg->ccnode->ehn_Events) Remove((struct Node *)msg->ccnode);
3580 if (node)
3582 /* Remove from the chain list */
3583 Remove((struct Node *)node);
3584 FreePooled(data->wd_MemoryPool, node, sizeof(struct ObjNode));
3587 return TRUE;
3590 /**************************************************************************
3591 MUIM_DragObject
3592 **************************************************************************/
3593 IPTR Window__MUIM_DragObject(struct IClass *cl, Object *obj, struct MUIP_Window_DragObject *msg)
3595 struct MUI_WindowData *data = INST_DATA(cl, obj);
3596 if (msg->obj)
3598 struct DragNDrop *dnd;
3599 struct MUI_DragImage *di;
3600 struct BitMapNode *bmn;
3602 if (!(dnd = CreateDragNDropA(NULL))) return 0;
3603 if (!(di = (struct MUI_DragImage*)DoMethod(msg->obj,MUIM_CreateDragImage,-msg->touchx,-msg->touchy,msg->flags)))
3605 DeleteDragNDrop(dnd);
3606 return 0;
3608 if (!di->bm)
3610 DoMethod(msg->obj,MUIM_DeleteDragImage, (IPTR)di);
3611 DeleteDragNDrop(dnd);
3612 return 0;
3615 if (!(bmn = CreateBitMapNode(NULL, /* dummy */
3616 GUI_BitMap, di->bm,
3617 GUI_LeftOffset, di->touchx,
3618 GUI_TopOffset, di->touchy,
3619 GUI_Width, di->width,
3620 GUI_Height, di->height,
3621 TAG_DONE)))
3623 DoMethod(msg->obj, MUIM_DeleteDragImage, (IPTR)di);
3624 DeleteDragNDrop(dnd);
3625 return 0;
3628 AttachBitMapNode(dnd,bmn);
3630 if (!PrepareDragNDrop(dnd, data->wd_RenderInfo.mri_Screen))
3632 DoMethod(msg->obj,MUIM_DeleteDragImage, (IPTR)di);
3633 DeleteDragNDrop(dnd);
3634 return 0;
3637 muiAreaData(msg->obj)->mad_Flags |= MADF_DRAGGING;
3639 data->wd_DragObject = msg->obj;
3640 data->wd_dnd = dnd;
3641 data->wd_DragImage = di;
3642 return 1;
3644 return 0;
3647 /**************************************************************************
3648 MUIM_AllocGadgetID
3649 **************************************************************************/
3650 IPTR Window__MUIM_AllocGadgetID(struct IClass *cl, Object *obj, struct MUIP_Window_AllocGadgetID *msg)
3652 struct MUI_WindowData *data = INST_DATA(cl, obj);
3653 struct IDNode *newnode;
3655 newnode = AllocPooled(data->wd_MemoryPool, sizeof(struct IDNode));
3656 if (newnode)
3658 int id;
3659 struct MinNode *mn;
3661 if (IsListEmpty((struct List*)&data->wd_IDList))
3663 newnode->id = 1;
3664 AddHead((struct List*)&data->wd_IDList, (struct Node*)&newnode->node);
3665 return (IPTR)1;
3668 id = 1;
3670 for (mn = data->wd_IDList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
3672 struct IDNode *idn = (struct IDNode *)mn;
3673 if (id < idn->id)
3674 break;
3675 id++;
3677 newnode->id = id;
3678 Insert((struct List*)&data->wd_IDList, (struct Node*)&newnode->node, (struct Node*)mn);
3679 return (IPTR)id;
3682 return 0;
3685 /**************************************************************************
3686 MUIM_FreeGadgetID
3687 **************************************************************************/
3688 IPTR Window__MUIM_FreeGadgetID(struct IClass *cl, Object *obj, struct MUIP_Window_FreeGadgetID *msg)
3690 struct MUI_WindowData *data = INST_DATA(cl, obj);
3691 struct MinNode *mn;
3693 for (mn = data->wd_IDList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
3695 struct IDNode *idn = (struct IDNode *)mn;
3696 if (msg->gadgetid == idn->id)
3698 Remove((struct Node*)idn);
3699 FreePooled(data->wd_MemoryPool, idn, sizeof(struct IDNode));
3700 return 0;
3704 return 0;
3708 /**************************************************************************
3709 MUIM_Window_GetMenuCheck
3710 **************************************************************************/
3711 IPTR Window__MUIM_GetMenuCheck(struct IClass *cl, Object *obj, struct MUIP_Window_GetMenuCheck *msg)
3713 IPTR stat;
3714 struct MUI_WindowData *data = INST_DATA(cl, obj);
3715 Object *item;
3716 Object *strip = data->wd_ChildMenustrip;
3717 if (!strip) strip = data->wd_Menustrip;
3718 if (!strip) return 0;
3719 if (!(item = (Object*)DoMethod(strip, MUIM_FindUData, msg->MenuID))) return 0;
3720 get(item,MUIA_Menuitem_Checked, &stat);
3721 return stat;
3724 /**************************************************************************
3725 MUIM_Window_SetMenuCheck
3726 **************************************************************************/
3727 IPTR Window__MUIM_SetMenuCheck(struct IClass *cl, Object *obj, struct MUIP_Window_SetMenuCheck *msg)
3729 struct MUI_WindowData *data = INST_DATA(cl, obj);
3730 Object *item;
3731 Object *strip = data->wd_ChildMenustrip;
3732 if (!strip) strip = data->wd_Menustrip;
3733 if (!strip) return 0;
3734 if (!(item = (Object*)DoMethod(strip, MUIM_FindUData, msg->MenuID))) return 0;
3735 set(item,MUIA_Menuitem_Checked,msg->stat);
3736 return 0;
3739 /**************************************************************************
3740 MUIM_Window_GetMenuState
3741 **************************************************************************/
3742 IPTR Window__MUIM_GetMenuState(struct IClass *cl, Object *obj, struct MUIP_Window_GetMenuState *msg)
3744 IPTR stat;
3745 struct MUI_WindowData *data = INST_DATA(cl, obj);
3746 Object *item;
3747 Object *strip = data->wd_ChildMenustrip;
3748 if (!strip) strip = data->wd_Menustrip;
3749 if (!strip) return 0;
3750 if (!(item = (Object*)DoMethod(strip, MUIM_FindUData, msg->MenuID))) return 0;
3751 get(item,MUIA_Menuitem_Enabled, &stat);
3752 return stat;
3755 /**************************************************************************
3756 MUIM_Window_SetMenuState
3757 **************************************************************************/
3758 IPTR Window__MUIM_SetMenuState(struct IClass *cl, Object *obj, struct MUIP_Window_SetMenuState *msg)
3760 struct MUI_WindowData *data = INST_DATA(cl, obj);
3761 Object *item;
3762 Object *strip = data->wd_ChildMenustrip;
3763 if (!strip) strip = data->wd_Menustrip;
3764 if (!strip) return 0;
3765 if (!(item = (Object*)DoMethod(strip, MUIM_FindUData, msg->MenuID))) return 0;
3766 set(item,MUIA_Menuitem_Enabled,msg->stat);
3767 return 0;
3770 /**************************************************************************
3771 MUIM_Window_DrawBackground
3772 **************************************************************************/
3773 IPTR Window__MUIM_DrawBackground(struct IClass *cl, Object *obj, struct MUIP_Window_DrawBackground *msg)
3775 struct MUI_WindowData *data = INST_DATA(cl, obj);
3776 if (!(data->wd_RenderInfo.mri_Window)) /* not between show/hide */
3777 return FALSE;
3779 // D(bug("%d:zune_imspec_draw(%p) l=%d t=%d w=%d h=%d xo=%d yo=%d\n",
3780 // __LINE__, data->wd_Background, msg->left, msg->top, msg->width,
3781 // msg->height, msg->xoffset, msg->yoffset));
3782 zune_imspec_draw(data->wd_Background, &data->wd_RenderInfo,
3783 msg->left, msg->top, msg->width, msg->height,
3784 msg->xoffset, msg->yoffset, 0);
3785 return 0;
3788 /**************************************************************************
3789 MUIM_Window_ToFront
3790 **************************************************************************/
3791 IPTR Window__MUIM_ToFront(struct IClass *cl, Object *obj, Msg msg)
3793 struct MUI_WindowData *data = INST_DATA(cl, obj);
3794 if (!(data->wd_RenderInfo.mri_Window)) /* not between show/hide */
3795 return 0;
3797 WindowToFront(data->wd_RenderInfo.mri_Window);
3798 return 1;
3801 /**************************************************************************
3802 MUIM_Window_ToBack
3803 **************************************************************************/
3804 IPTR Window__MUIM_ToBack(struct IClass *cl, Object *obj, Msg msg)
3806 struct MUI_WindowData *data = INST_DATA(cl, obj);
3807 if (!(data->wd_RenderInfo.mri_Window)) /* not between show/hide */
3808 return 0;
3810 WindowToBack(data->wd_RenderInfo.mri_Window);
3811 return 1;
3814 /**************************************************************************
3815 MUIM_Window_ScreenToBack
3816 **************************************************************************/
3817 IPTR Window__MUIM_ScreenToBack(struct IClass *cl, Object *obj, Msg msg)
3819 struct MUI_WindowData *data = INST_DATA(cl, obj);
3820 if (!(data->wd_RenderInfo.mri_Window)) /* not between show/hide */
3821 return 0;
3823 ScreenToBack(data->wd_RenderInfo.mri_Screen);
3824 return 1;
3827 /**************************************************************************
3828 MUIM_Window_ScreenToFront
3829 **************************************************************************/
3830 IPTR Window__MUIM_ScreenToFront(struct IClass *cl, Object *obj, Msg msg)
3832 struct MUI_WindowData *data = INST_DATA(cl, obj);
3833 if (!(data->wd_RenderInfo.mri_Window)) /* not between show/hide */
3834 return 0;
3836 ScreenToFront(data->wd_RenderInfo.mri_Screen);
3837 return 1;
3840 /**************************************************************************
3841 MUIM_Window_ActionIconify
3842 **************************************************************************/
3843 IPTR Window__MUIM_ActionIconify(struct IClass *cl, Object *obj, Msg msg)
3845 set(_app(obj), MUIA_Application_Iconified, TRUE);
3847 return TRUE;
3851 /* Loads ENV: prefs, add a Window_ID chunk in the MUIW chunk, if no MUIW chunk
3852 * then create it at the same level as MUIC chunk, save prefs.
3853 * Do the same for ENVARC:
3854 * MUIW chunk layout:
3855 * 'MUIW'
3856 * 00 00 00 30 (chunk length for a single window, 0x30L big endian)
3857 * 'this window ID'
3858 * 00 00 00 28
3859 * xx xx yy yy (X, Y)
3860 * ww ww hh hh (Width, Height)
3861 * ax ax ay ay (AltX, AltY)
3862 * aw aw ah ah (AltWidth, AltHeight)
3863 * 00 00 00 00 (???)
3864 * 00 00 00 00
3865 * 00 00 00 00
3866 * 00 00 00 00
3867 * 00 01 00 00
3868 * 00 00 00 00
3870 static void RememberWindowPosition(Object *winobj, ULONG id)
3872 if (!id)
3873 return;
3876 /* Loads ENV: prefs, remove our Window_ID chunk from the MUIW chunk, save prefs.
3877 * Do the same for ENVARC:
3878 * This function shouldnt really be in window.c, but rather in a file dealing
3879 * with prefs file stuff.
3881 static void ForgetWindowPosition(Object *winobj, ULONG id)
3883 if (!id)
3884 return;
3887 /**************************************************************************
3888 MUIM_Window_Snapshot
3889 **************************************************************************/
3890 IPTR Window__MUIM_Snapshot(struct IClass *cl, Object *obj, struct MUIP_Window_Snapshot *msg)
3892 struct MUI_WindowData *data = INST_DATA(cl, obj);
3893 struct windowpos winp;
3894 struct Window *w;
3895 winp.id = data->wd_ID;
3896 w=data->wd_RenderInfo.mri_Window;
3897 if (w)
3899 winp.x1 = w->LeftEdge; winp.y1 = w->TopEdge;
3900 winp.w1 = w->GZZWidth; winp.h1 = w->GZZHeight;
3901 winp.x2 =0; winp.x2=0; winp.w2=0; winp.h2=0; //to do save alt dims
3903 set(_app(obj),MUIA_Application_SetWinPos,&winp);
3906 if (msg->flags)
3907 RememberWindowPosition(obj, data->wd_ID);
3908 else
3909 ForgetWindowPosition(obj, data->wd_ID);
3910 return 1;
3915 BOOPSI_DISPATCHER(IPTR, Window_Dispatcher, cl, obj, msg)
3917 switch (msg->MethodID)
3919 case OM_NEW: return Window__OM_NEW(cl, obj, (struct opSet *) msg);
3920 case OM_DISPOSE: return Window__OM_DISPOSE(cl, obj, msg);
3921 case OM_SET: return Window__OM_SET(cl, obj, (struct opSet *)msg);
3922 case OM_GET: return Window__OM_GET(cl, obj, (struct opGet *)msg);
3923 case MUIM_FindUData: return Window__MUIM_FindUData(cl, obj, (struct MUIP_FindUData *)msg);
3924 case MUIM_GetUData: return Window__MUIM_GetUData(cl, obj, (struct MUIP_GetUData *)msg);
3925 case MUIM_SetUData: return Window__MUIM_SetUData(cl, obj, (struct MUIP_SetUData *)msg);
3926 case MUIM_SetUDataOnce: return Window__MUIM_SetUDataOnce(cl, obj, (struct MUIP_SetUDataOnce *)msg);
3927 case MUIM_Window_AddEventHandler: return Window__MUIM_AddEventHandler(cl, obj, (APTR)msg);
3928 case MUIM_Window_RemEventHandler: return Window__MUIM_RemEventHandler(cl, obj, (APTR)msg);
3929 case MUIM_ConnectParent: return Window__MUIM_ConnectParent(cl, obj, (APTR)msg);
3930 case MUIM_DisconnectParent: return Window__MUIM_DisconnectParent(cl, obj, (APTR)msg);
3931 case MUIM_Window_RecalcDisplay: return Window__MUIM_RecalcDisplay(cl, obj, (APTR)msg);
3932 case MUIM_Window_Setup: return Window__MUIM_Setup(cl, obj, (APTR)msg);
3933 case MUIM_Window_Cleanup: return Window__MUIM_Cleanup(cl, obj, (APTR)msg);
3934 case MUIM_Window_AddControlCharHandler: return Window__MUIM_AddControlCharHandler(cl, obj, (APTR)msg);
3935 case MUIM_Window_RemControlCharHandler: return Window__MUIM_RemControlCharHandler(cl, obj, (APTR)msg);
3936 case MUIM_Window_DragObject: return Window__MUIM_DragObject(cl, obj, (APTR)msg);
3937 case MUIM_Window_AllocGadgetID: return Window__MUIM_AllocGadgetID(cl, obj, (APTR)msg);
3938 case MUIM_Window_FreeGadgetID: return Window__MUIM_FreeGadgetID(cl, obj, (APTR)msg);
3939 case MUIM_Window_GetMenuCheck: return Window__MUIM_GetMenuCheck(cl, obj, (APTR)msg);
3940 case MUIM_Window_SetMenuCheck: return Window__MUIM_SetMenuCheck(cl, obj, (APTR)msg);
3941 case MUIM_Window_GetMenuState: return Window__MUIM_GetMenuState(cl, obj, (APTR)msg);
3942 case MUIM_Window_SetMenuState: return Window__MUIM_SetMenuState(cl, obj, (APTR)msg);
3943 case MUIM_Window_DrawBackground: return Window__MUIM_DrawBackground(cl, obj, (APTR)msg);
3944 case MUIM_Window_ToFront: return Window__MUIM_ToFront(cl, obj, (APTR)msg);
3945 case MUIM_Window_ToBack: return Window__MUIM_ToBack(cl, obj, (APTR)msg);
3946 case MUIM_Window_ScreenToFront: return Window__MUIM_ScreenToFront(cl, obj, (APTR)msg);
3947 case MUIM_Window_ScreenToBack: return Window__MUIM_ScreenToBack(cl, obj, (APTR)msg);
3948 case MUIM_Window_ActionIconify: return Window__MUIM_ActionIconify(cl, obj, (APTR)msg);
3949 case MUIM_Window_Snapshot: return Window__MUIM_Snapshot(cl, obj, (APTR)msg);
3952 return DoSuperMethodA(cl, obj, msg);
3954 BOOPSI_DISPATCHER_END
3958 * Class descriptor.
3960 const struct __MUIBuiltinClass _MUI_Window_desc = {
3961 MUIC_Window,
3962 MUIC_Notify,
3963 sizeof(struct MUI_WindowData),
3964 (void*)Window_Dispatcher