Zune: react to pushing of iconify gadget.
[AROS.git] / workbench / libs / muimaster / classes / window.c
blob4b00e34e7bdf525373331f4aac651480f0bac315
1 /*
2 Copyright 1999, David Le Corfec.
3 Copyright 2002-2012, 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 #ifdef __AROS__
17 #include <intuition/extensions.h>
18 #endif
19 #include <clib/alib_protos.h>
20 #include <graphics/gfxmacros.h>
21 #include <proto/exec.h>
22 #include <proto/intuition.h>
23 #include <proto/utility.h>
24 #include <proto/graphics.h>
25 #include <proto/commodities.h>
26 #include <proto/layers.h>
27 #include <proto/gadtools.h>
28 #include <proto/muimaster.h>
30 #define MUI_OBSOLETE /* for the obsolete menu stuff */
32 #include "mui.h"
33 #include "support.h"
34 #include "classes/window.h"
35 #include "classes/area.h"
36 #include "imspec.h"
37 #include "datatypescache.h"
38 #include "prefs.h"
39 #include "dragndrop.h"
41 #include "muimaster_intern.h"
43 //#define MYDEBUG 1
44 #include "debug.h"
46 extern struct Library *MUIMasterBase;
48 static const int __version = 1;
49 static const int __revision = 1;
51 #define IM(x) ((struct Image*)(x))
52 #define G(x) ((struct Gadget*)(x))
53 #define GADGETID(x) (((struct Gadget*)(x))->GadgetID)
55 /* this is for the cycle list */
56 struct ObjNode
58 struct MinNode node;
59 Object *obj;
62 /* For the gadget ids */
63 struct IDNode
65 struct MinNode node;
66 UWORD id;
69 struct MUI_ImageSpec_intern;
71 struct MUI_WindowData
73 struct MUI_RenderInfo wd_RenderInfo;
74 struct MUI_MinMax wd_MinMax;
75 struct IBox wd_AltDim; /* zoomed dimensions */
76 BOOL wd_ZoomGadget; /* enable/disable zoomgadget (altdim stuff) */
77 APTR wd_MemoryPool; /* for nodes and stuff to deallocate at OM_DISPOSE */
78 struct MinList wd_CycleChain; /* objects activated with tab */
79 struct MinList wd_EHList; /* event handlers */
80 struct MinList wd_CCList; /* control chars */
81 struct MinList wd_IDList; /* gadget ids */
82 ULONG wd_Events; /* events received */
83 ULONG wd_CrtFlags; /* window creation flags, see below */
84 Object *wd_ActiveObject; /* the active object */
85 Object *wd_OldActive; /* active object before window was closed */
86 APTR wd_DefaultObject;
87 ULONG wd_ID;
88 STRPTR wd_Title;
89 STRPTR wd_ScreenTitle;
90 LONG wd_Height; /* Current dimensions */
91 LONG wd_Width;
92 LONG wd_X;
93 LONG wd_Y;
94 LONG wd_ReqHeight; /* given by programmer */
95 LONG wd_ReqWidth;
96 APTR wd_RootObject; /* unique child */
97 ULONG wd_Flags; /* various status flags */
98 struct MUI_ImageSpec_intern *wd_Background;
99 ULONG wd_DisabledKeys;
100 BOOL wd_NoMenus; /* MUIA_Window_NoMenus */
102 Object *wd_DragObject; /* the object which is being dragged */
103 struct Window *wd_DropWindow; /* the destination window, for faster access */
104 Object *wd_DropObject; /* the destination object */
105 struct DragNDrop *wd_dnd;
106 struct MUI_DragImage *wd_DragImage;
108 Object *wd_Menustrip; /* The menustrip object which is actually is used (either apps or windows or NULL) */
109 Object * wd_ChildMenustrip; /* If window has an own Menustrip */
110 struct Menu *wd_Menu; /* the intuition menustrip */
112 Object *wd_VertProp;
113 Object *wd_UpButton;
114 Object *wd_DownButton;
116 Object *wd_HorizProp;
117 Object *wd_LeftButton;
118 Object *wd_RightButton;
119 Object *wd_RefWindow;
121 Object *wd_MUIGadget;
123 Object *wd_HelpObject;
124 APTR wd_HelpBubble;
125 WORD wd_HelpTicker;
127 struct Screen *wd_UserScreen;
128 STRPTR wd_UserPublicScreen;
129 LONG wd_XStore; /*store MUIV_Window_LeftEdge_Centered Tags etc
130 because wd_X is overwritten by a value in CalcDimension
131 Popup windows work ok on AmiGG when main window is move
133 LONG wd_YStore;
135 WORD wd_SleepCount; /* MUIA_Window_Sleep nests */
138 #ifndef WFLG_SIZEGADGET
140 #define WFLG_CLOSEGADGET (1<<0) /* has close gadget */
141 #define WFLG_SIZEGADGET (1<<1) /* has size gadget */
142 #define WFLG_BACKDROP (1<<2) /* is backdrop window */
143 #define WFLG_BORDERLESS (1<<3) /* has no borders */
144 #define WFLG_DEPTHGADGET (1<<4) /* has depth gadget */
145 #define WFLG_DRAGBAR (1<<5) /* is draggable */
146 #define WFLG_SIZEBRIGHT (1<<6) /* size gadget is in right border */
148 #endif
150 /* wd_Flags */
151 #define MUIWF_OPENED (1<<0) /* window currently opened */
152 #define MUIWF_HIDDEN (1<<1) /* window currently iconified */
153 #define MUIWF_ACTIVE (1<<2) /* window currently active */
154 #define MUIWF_RESIZING (1<<4) /* window currently resizing, for simple refresh */
155 #define MUIWF_DONTACTIVATE (1<<7) /* do not activate the window when opening */
156 #define MUIWF_USERIGHTSCROLLER (1<<8) /* window should have a right scroller */
157 #define MUIWF_USEBOTTOMSCROLLER (1<<9) /* window should have a bottom scroller */
158 #define MUIWF_ERASEAREA (1<<10) /* Erase area after a window resize */
159 #define MUIWF_ISAPPWINDOW (1<<11) /* Is an app window (user can drop icons on it) */
160 #define MUIWF_ISSUBWINDOW (1<<12) /* Dont get automatically disposed with app */
161 #define MUIWF_BUBBLEMODE (1<<13) /* Quick bubble mode. Bubbles appear quick when moving */
162 #define MUIWF_OPENONUNHIDE (1<<14) /* Open the window when unhiding */
163 #define MUIWF_SCREENLOCKED (1<<15) /* A pub screen was locked in SetupRenderInfo. Unlock it in CleanupRenderInfo! */
164 #define MUIWF_OBJECTGOACTIVESENT (1<<16) /* A MUIM_GoActive msg was sent to window's active object */
165 #define MUIWF_TOOLBOX (1<<17) /* Window should be opened as ToolBox */
167 #define BUBBLEHELP_TICKER_FIRST 10
168 #define BUBBLEHELP_TICKER_LATER 3
170 struct __dummyXFC3__
172 struct MUI_NotifyData mnd;
173 struct MUI_WindowData mwd;
176 #define muiWindowData(obj) (&(((struct __dummyXFC3__ *)(obj))->mwd))
178 static ULONG DoHalfshineGun(ULONG a, ULONG b)
180 ULONG val = ((((a)>>24) + 3 * ((b)>>24)) / 4);
181 val = val + (val<<8) + (val<<16) + (val<<24);
182 return val;
185 static ULONG DoHalfshadowGun(ULONG a, ULONG b)
187 ULONG val = ((((a)>>24) + 5 * ((b)>>24)) / 6);
188 val = val + (val<<8) + (val<<16) + (val<<24);
189 return val;
192 static Object *CreateSysimage(struct DrawInfo *dri, ULONG which)
194 return NewObject(NULL, "sysiclass",
195 SYSIA_DrawInfo, (IPTR)dri,
196 SYSIA_Which, which,
197 TAG_DONE);
200 static void EnqueueByPriAndAddress(struct List *list, struct Node *node)
202 struct Node *scannode;
204 /* Sort by priority and by node address, so that a
205 "remove - modify - enqueue" sequence will re-add
206 the node at the same place in the list it was
207 initially */
209 ForeachNode(list, scannode)
211 if (((struct Node *)node)->ln_Pri > scannode->ln_Pri)
212 break;
213 if (((struct Node *)node)->ln_Pri == scannode->ln_Pri)
215 if ((IPTR)node > (IPTR)scannode)
216 break;
220 Insert(list, (struct Node *)node, scannode->ln_Pred);
223 static BOOL InitCustomFrames(Object *obj, struct MUI_RenderInfo *mri)
225 int i;
227 for (i = 0; i < 16; i++)
229 mri->mri_FrameImage[i] = NULL;
232 mri->mri_FrameImage[0] = load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->customframe_config_1, mri->mri_Screen);
233 mri->mri_FrameImage[1] = load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->customframe_config_2, mri->mri_Screen);
234 mri->mri_FrameImage[2] = load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->customframe_config_3, mri->mri_Screen);
235 mri->mri_FrameImage[3] = load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->customframe_config_4, mri->mri_Screen);
236 mri->mri_FrameImage[4] = load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->customframe_config_5, mri->mri_Screen);
237 mri->mri_FrameImage[5] = load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->customframe_config_6, mri->mri_Screen);
238 mri->mri_FrameImage[6] = load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->customframe_config_7, mri->mri_Screen);
239 mri->mri_FrameImage[7] = load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->customframe_config_8, mri->mri_Screen);
240 mri->mri_FrameImage[8] = load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->customframe_config_9, mri->mri_Screen);
241 mri->mri_FrameImage[9] = load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->customframe_config_10, mri->mri_Screen);
242 mri->mri_FrameImage[10] = load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->customframe_config_11, mri->mri_Screen);
243 mri->mri_FrameImage[11] = load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->customframe_config_12, mri->mri_Screen);
244 mri->mri_FrameImage[12] = load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->customframe_config_13, mri->mri_Screen);
245 mri->mri_FrameImage[13] = load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->customframe_config_14, mri->mri_Screen);
246 mri->mri_FrameImage[14] = load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->customframe_config_15, mri->mri_Screen);
247 mri->mri_FrameImage[15] = load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->customframe_config_16, mri->mri_Screen);
249 return TRUE;
252 static void DisposeCustomFrames(struct MUI_RenderInfo *mri)
254 int i;
256 for (i = 0; i < 16; i++)
258 dispose_custom_frame(mri->mri_FrameImage[i]);
260 mri->mri_FrameImage[i] = NULL;
264 static BOOL SetupRenderInfo(Object *obj, struct MUI_WindowData *data, struct MUI_RenderInfo *mri)
266 ULONG rgbtable[3 * 3];
267 Object *temp_obj;
268 IPTR val;
269 int i;
271 /* TODO: Move this whole screen locking/opening stuff into the application class
272 * by creating methods for this purpose */
274 /* If no user screen has been specified try to open the application specifc screen */
275 if (!data->wd_UserScreen)
277 ULONG screenmodeid = muiGlobalInfo(obj)->mgi_Prefs->screenmodeid;
279 if (screenmodeid != ~0)
281 if (!muiGlobalInfo(obj)->mgi_CustomScreen)
283 muiGlobalInfo(obj)->mgi_CustomScreen = OpenScreenTags
285 NULL,
286 SA_DisplayID, screenmodeid,
287 SA_SharePens, TRUE,
288 SA_FullPalette, TRUE,
289 SA_LikeWorkbench,TRUE,
290 TAG_DONE
292 /* It's fine if this fails as there is a back fall case below */
295 data->wd_UserScreen = muiGlobalInfo(obj)->mgi_CustomScreen;
298 if (data->wd_UserScreen)
300 mri->mri_Screen = data->wd_UserScreen;
302 else
304 if (data->wd_UserPublicScreen)
306 mri->mri_Screen = LockPubScreen(data->wd_UserPublicScreen);
308 else if (muiGlobalInfo(obj)->mgi_Prefs->publicscreen_name && muiGlobalInfo(obj)->mgi_Prefs->publicscreen_name[0])
310 mri->mri_Screen = LockPubScreen(muiGlobalInfo(obj)->mgi_Prefs->publicscreen_name);
311 // FIXME: open the public screen if necessary
314 if (mri->mri_Screen == NULL)
316 mri->mri_Screen = LockPubScreen(NULL);
317 if (mri->mri_Screen == NULL)
319 return FALSE;
323 // FIXME: is this the right place for this action?
324 if (mri->mri_Screen && muiGlobalInfo(obj)->mgi_Prefs->publicscreen_pop_to_front)
326 ScreenToFront(mri->mri_Screen);
329 data->wd_Flags |= MUIWF_SCREENLOCKED;
332 if (!(mri->mri_DrawInfo = GetScreenDrawInfo(mri->mri_Screen)))
334 if (data->wd_Flags & MUIWF_SCREENLOCKED)
336 UnlockPubScreen(NULL,mri->mri_Screen);
337 data->wd_Flags &= ~MUIWF_SCREENLOCKED;
339 return FALSE;
342 if (!InitCustomFrames(obj, mri))
344 if (data->wd_Flags & MUIWF_SCREENLOCKED)
346 UnlockPubScreen(NULL,mri->mri_Screen);
347 data->wd_Flags &= ~MUIWF_SCREENLOCKED;
349 return FALSE;
352 mri->mri_Colormap = mri->mri_Screen->ViewPort.ColorMap;
353 mri->mri_ScreenWidth = mri->mri_Screen->Width;
354 mri->mri_ScreenHeight = mri->mri_Screen->Height;
356 if (mri->mri_ScreenWidth / mri->mri_ScreenHeight < 2)
358 mri->mri_Flags |= MUIMRI_THINFRAMES;
361 if (GetBitMapAttr(mri->mri_Screen->RastPort.BitMap, BMA_DEPTH) >= 15)
363 mri->mri_Flags |= MUIMRI_TRUECOLOR;
366 mri->mri_PensStorage[MPEN_SHINE] = mri->mri_DrawInfo->dri_Pens[SHINEPEN];
367 mri->mri_PensStorage[MPEN_BACKGROUND] = mri->mri_DrawInfo->dri_Pens[BACKGROUNDPEN];
368 mri->mri_PensStorage[MPEN_SHADOW] = mri->mri_DrawInfo->dri_Pens[SHADOWPEN];
369 mri->mri_PensStorage[MPEN_TEXT] = mri->mri_DrawInfo->dri_Pens[TEXTPEN];
370 mri->mri_PensStorage[MPEN_FILL] = mri->mri_DrawInfo->dri_Pens[FILLPEN];
372 GetRGB32(mri->mri_Colormap, mri->mri_DrawInfo->dri_Pens[SHINEPEN], 1, rgbtable);
373 GetRGB32(mri->mri_Colormap, mri->mri_DrawInfo->dri_Pens[BACKGROUNDPEN], 1, rgbtable+3);
374 GetRGB32(mri->mri_Colormap, mri->mri_DrawInfo->dri_Pens[SHADOWPEN], 1, rgbtable+6);
376 mri->mri_PensStorage[MPEN_HALFSHINE] = ObtainBestPenA
378 mri->mri_Colormap,
379 DoHalfshineGun(rgbtable[0], rgbtable[3]),
380 DoHalfshineGun(rgbtable[1], rgbtable[4]),
381 DoHalfshineGun(rgbtable[2], rgbtable[5]), NULL
384 mri->mri_PensStorage[MPEN_HALFSHADOW] = ObtainBestPenA
386 mri->mri_Colormap,
387 DoHalfshadowGun(rgbtable[6], rgbtable[3]),
388 DoHalfshadowGun(rgbtable[7], rgbtable[4]),
389 DoHalfshadowGun(rgbtable[8], rgbtable[5]), NULL
392 /* I'm really not sure that MUI does this for MPEN_MARK, but it seems mostly acceptable -dlc */
393 mri->mri_PensStorage[MPEN_MARK] = ObtainBestPenA
395 mri->mri_Colormap, 0xf4f4f4f4, 0xb5b5b5b5, 0x8b8b8b8b, NULL
398 mri->mri_Pens = mri->mri_PensStorage;
400 for (i = 0; i < -MUIV_Font_NegCount; i++)
402 mri->mri_Fonts[i] = NULL;
405 if (data->wd_Flags & MUIWF_USEBOTTOMSCROLLER)
407 mri->mri_LeftImage = CreateSysimage(mri->mri_DrawInfo, LEFTIMAGE);
408 mri->mri_RightImage = CreateSysimage(mri->mri_DrawInfo, RIGHTIMAGE);
410 else
412 mri->mri_LeftImage = mri->mri_RightImage = NULL;
415 if (data->wd_Flags & MUIWF_USERIGHTSCROLLER)
417 mri->mri_UpImage = CreateSysimage(mri->mri_DrawInfo, UPIMAGE);
418 mri->mri_DownImage = CreateSysimage(mri->mri_DrawInfo, DOWNIMAGE);
420 else
422 mri->mri_UpImage = mri->mri_DownImage = NULL;
425 if ((data->wd_Flags & MUIWF_USEBOTTOMSCROLLER) ||
426 (data->wd_Flags & MUIWF_USERIGHTSCROLLER))
427 mri->mri_SizeImage = CreateSysimage(mri->mri_DrawInfo, SIZEIMAGE);
428 else
429 mri->mri_SizeImage = NULL;
431 if (data->wd_CrtFlags & WFLG_BORDERLESS)
433 /* Infact borderless windows could also have borders (if they have a window title e.g. but
434 since they look ugly anywhy we ignore it for now */
435 mri->mri_BorderLeft = 0;
436 mri->mri_BorderRight = 0;
437 mri->mri_BorderTop = 0;
438 mri->mri_BorderBottom = 0;
440 else
442 mri->mri_BorderLeft = mri->mri_Screen->WBorLeft;
443 mri->mri_BorderTop = mri->mri_Screen->WBorTop + mri->mri_Screen->Font->ta_YSize+ 1;
444 temp_obj = NewObject
446 NULL, "sysiclass",
447 SYSIA_DrawInfo, (IPTR)mri->mri_DrawInfo,
448 SYSIA_Which, SIZEIMAGE,
449 TAG_DONE
451 if (temp_obj)
453 GetAttr(IA_Height,temp_obj,&val);
454 DisposeObject(temp_obj);
455 mri->mri_BorderBottom = val;
457 else
458 mri->mri_BorderBottom = mri->mri_Screen->WBorBottom;
461 return TRUE;
464 static void CleanupRenderInfo(Object *obj, struct MUI_WindowData *data, struct MUI_RenderInfo *mri)
466 int i;
468 DisposeCustomFrames(mri);
470 if (mri->mri_LeftImage) {DisposeObject(mri->mri_LeftImage);mri->mri_LeftImage=NULL;};
471 if (mri->mri_RightImage){DisposeObject(mri->mri_RightImage);mri->mri_RightImage=NULL;};
472 if (mri->mri_UpImage) {DisposeObject(mri->mri_UpImage);mri->mri_UpImage=NULL;};
473 if (mri->mri_DownImage) {DisposeObject(mri->mri_DownImage);mri->mri_DownImage=NULL;};
474 if (mri->mri_SizeImage) {DisposeObject(mri->mri_SizeImage);mri->mri_SizeImage=NULL;};
476 /* bug("CleanupRenderInfo\n"); */
477 for (i = 0; i < -MUIV_Font_NegCount; i++)
479 if (mri->mri_Fonts[i])
481 /* bug("CleanupRenderInfo: closing font %p (%s/%d)\n", */
482 /* mri->mri_Fonts[i], mri->mri_Fonts[i]->tf_Message.mn_Node.ln_Name, */
483 /* mri->mri_Fonts[i]->tf_YSize); */
484 CloseFont(mri->mri_Fonts[i]);
485 mri->mri_Fonts[i] = NULL;
488 ReleasePen(mri->mri_Colormap, mri->mri_PensStorage[MPEN_MARK]);
489 ReleasePen(mri->mri_Colormap, mri->mri_PensStorage[MPEN_HALFSHADOW]);
490 ReleasePen(mri->mri_Colormap, mri->mri_PensStorage[MPEN_HALFSHINE]);
491 FreeScreenDrawInfo(mri->mri_Screen, mri->mri_DrawInfo);
492 mri->mri_DrawInfo = NULL;
494 /* If a custom screen has been opened by zune, close it as soon as
495 * zero windows are opened. See above for comments about refactorization. */
496 if (muiGlobalInfo(obj)->mgi_CustomScreen)
498 BOOL screenclose = TRUE;
499 Object *_app = _app(obj);
500 if (_app != NULL)
502 struct List *store = NULL;
503 get(_app, MUIA_Application_WindowList, &store);
504 if (store != NULL)
506 if (!IsListEmpty(store)) screenclose = FALSE;
509 if (screenclose)
511 /* If the window's user screen really was the custom screen, clear the reference */
512 if (data->wd_UserScreen == muiGlobalInfo(obj)->mgi_CustomScreen)
513 data->wd_UserScreen = NULL;
515 CloseScreen(muiGlobalInfo(obj)->mgi_CustomScreen);
516 muiGlobalInfo(obj)->mgi_CustomScreen = NULL;
521 if (data->wd_Flags & MUIWF_SCREENLOCKED)
523 UnlockPubScreen(NULL, mri->mri_Screen);
524 data->wd_Flags &= ~MUIWF_SCREENLOCKED;
526 mri->mri_Screen = NULL;
529 static void ShowRenderInfo(struct MUI_RenderInfo *mri)
531 if (mri->mri_BufferBM)
533 mri->mri_RastPort = &mri->mri_BufferRP;
535 else
537 mri->mri_RastPort = mri->mri_Window->RPort;
541 static void HideRenderInfo(struct MUI_RenderInfo *mri)
543 mri->mri_RastPort = NULL;
546 static ULONG GetDefaultEvents (void)
548 return IDCMP_NEWSIZE | IDCMP_REFRESHWINDOW
549 | IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE | IDCMP_MENUPICK
550 | IDCMP_CLOSEWINDOW | IDCMP_RAWKEY | IDCMP_INTUITICKS
551 | IDCMP_ACTIVEWINDOW | IDCMP_INACTIVEWINDOW | IDCMP_GADGETUP;
554 static void ChangeEvents (struct MUI_WindowData *data, ULONG new_events)
556 struct MinNode *mn;
557 struct MUI_EventHandlerNode *ehn;
558 ULONG old_events = data->wd_Events;
560 for (mn = data->wd_EHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
562 ehn = (struct MUI_EventHandlerNode *)mn;
563 new_events |= ehn->ehn_Events;
566 /* sba: kill the IDCMP_VANILLAKEY flag. MUI doesn't do this but programs
567 ** which use this will behave different if they request for this flag
568 ** (also on MUI)
570 new_events &= ~IDCMP_VANILLAKEY;
572 data->wd_Events = new_events;
573 if ((old_events != new_events) && (data->wd_Flags & MUIWF_OPENED))
575 ModifyIDCMP(data->wd_RenderInfo.mri_Window, new_events);
579 static void CalcWindowPosition(Object *obj, struct MUI_WindowData *data);
580 static void CreateWindowScrollbars(Object *obj, struct MUI_WindowData *data);
581 static void CalcAltDimensions(Object *obj, struct MUI_WindowData *data);
582 static void UndisplayWindow(Object *obj, struct MUI_WindowData *data);
583 static struct ObjNode *FindObjNode(struct MinList *list, Object *obj);
585 static BOOL DisplayWindow(Object *obj, struct MUI_WindowData *data)
587 struct Window *win;
588 ULONG flags = data->wd_CrtFlags;
589 struct IBox altdims;
590 ULONG backfill, buttons;
592 struct Menu *menu = NULL;
593 struct NewMenu *newmenu = NULL;
594 APTR visinfo = NULL;
596 Object *gadgets;
598 if (!(data->wd_Flags & MUIWF_DONTACTIVATE))
600 flags |= WFLG_ACTIVATE;
603 /* Toolboxes are handled differently on AmigaOS */
604 #ifdef __AROS__
605 if (data->wd_Flags & MUIWF_TOOLBOX)
606 flags |= WFLG_TOOLBOX;
607 #endif
611 data->wd_MinMax.MinHeight == data->wd_MinMax.MaxHeight
612 && data->wd_MinMax.MinWidth == data->wd_MinMax.MaxWidth
614 flags &= ~WFLG_SIZEGADGET;
616 if (!(flags & WFLG_SIZEBRIGHT))
617 flags |= WFLG_SIZEBBOTTOM;
619 CalcWindowPosition(obj, data);
621 if ((visinfo = GetVisualInfoA(data->wd_RenderInfo.mri_Screen,NULL)))
623 if (data->wd_Menustrip)
625 get(data->wd_Menustrip,MUIA_Menuitem_NewMenu,&newmenu);
626 if (newmenu)
628 if ((menu = CreateMenusA(newmenu,NULL)))
630 struct TagItem tags[] =
632 { GTMN_NewLookMenus, TRUE },
633 { TAG_DONE, (IPTR)NULL }
635 LayoutMenusA(menu, visinfo, tags);
639 FreeVisualInfo(visinfo);
642 CreateWindowScrollbars(obj, data);
643 CalcAltDimensions(obj, data);
644 altdims = data->wd_AltDim;
645 /* hack to account for border size, as we only know the innersize and must give
646 * the total size.
648 altdims.Width += data->wd_RenderInfo.mri_Screen->WBorLeft + data->wd_RenderInfo.mri_Screen->WBorRight;
649 altdims.Height += data->wd_RenderInfo.mri_Screen->WBorTop + data->wd_RenderInfo.mri_Screen->WBorBottom +
650 data->wd_RenderInfo.mri_DrawInfo->dri_Font->tf_YSize + 1;
652 if (muiGlobalInfo(obj)->mgi_Prefs->window_redraw == WINDOW_REDRAW_WITHOUT_CLEAR)
653 backfill = WA_BackFill;
654 else
655 backfill = TAG_IGNORE;
657 if (muiGlobalInfo(obj)->mgi_Prefs->window_refresh == WINDOW_REFRESH_SMART)
658 flags &= ~WFLG_SIMPLE_REFRESH;
659 set(_app(obj),MUIA_Application_SearchWinId,data->wd_ID);
660 struct windowpos *winp=0;
661 get(_app(obj),MUIA_Application_GetWinPos,&winp);
662 if (winp)
664 if (data->wd_RenderInfo.mri_ScreenWidth > (data->wd_X + data->wd_Width))
666 data->wd_X=winp->x1;
667 data->wd_Width=winp->w1;
669 if (data->wd_RenderInfo.mri_ScreenHeight > (data->wd_Y + data->wd_Height))
671 data->wd_Y=winp->y1;
672 data->wd_Height=winp->h1;
676 gadgets = (data->wd_VertProp != NULL) ? data->wd_VertProp : data->wd_HorizProp;
677 buttons = muiGlobalInfo(obj)->mgi_Prefs->window_buttons;
679 win = OpenWindowTags
681 NULL,
683 WA_Left, (IPTR) data->wd_X,
684 WA_Top, (IPTR) data->wd_Y,
685 WA_Flags, (IPTR) flags,
686 data->wd_Title ?
687 WA_Title :
688 TAG_IGNORE, (IPTR) data->wd_Title,
689 data->wd_ScreenTitle ?
690 WA_ScreenTitle :
691 TAG_IGNORE, (IPTR) data->wd_ScreenTitle,
692 WA_CustomScreen, (IPTR) data->wd_RenderInfo.mri_Screen,
693 WA_InnerWidth, (IPTR) data->wd_Width,
694 WA_InnerHeight, (IPTR) data->wd_Height,
695 WA_AutoAdjust, (IPTR) TRUE,
696 WA_NewLookMenus, (IPTR) TRUE,
697 /* AmigaOS v4 extension */
698 #ifdef WA_ToolBox
699 WA_ToolBox, (IPTR) !!(data->wd_Flags & MUIWF_TOOLBOX),
700 #endif
701 /* MorphOS extensions */
702 #ifdef WA_ExtraGadget_MUI
703 WA_ExtraGadget_MUI, (IPTR) ((buttons & MUIV_Window_Button_MUI) != 0) ? TRUE : FALSE,
704 WA_ExtraGadget_PopUp, (IPTR) ((buttons & MUIV_Window_Button_Popup) != 0) ? TRUE : FALSE,
705 WA_ExtraGadget_Snapshot,(IPTR) ((buttons & MUIV_Window_Button_Snapshot) != 0) ? TRUE : FALSE,
706 WA_ExtraGadget_Iconify, (IPTR) ((buttons & MUIV_Window_Button_Iconify) != 0) ? TRUE : FALSE,
707 #endif
708 data->wd_NoMenus ?
709 WA_RMBTrap :
710 TAG_IGNORE, (IPTR) TRUE,
711 WA_Gadgets, (IPTR) gadgets,
712 data->wd_ZoomGadget ?
713 WA_Zoom :
714 TAG_IGNORE, (IPTR) &altdims,
715 backfill, (IPTR) LAYERS_NOBACKFILL,
716 TAG_DONE
719 if (win)
722 int hborders = win->BorderLeft + win->BorderRight;
723 int vborders = win->BorderTop + win->BorderBottom;
725 /* recalc window size (which will hopefully equal our requested size) */
726 data->wd_Width = win->GZZWidth;
727 data->wd_Height = win->GZZHeight;
729 /* set window limits according to window contents */
730 WindowLimits
732 win, data->wd_MinMax.MinWidth + hborders,
733 data->wd_MinMax.MinHeight + vborders,
734 data->wd_MinMax.MaxWidth + hborders,
735 data->wd_MinMax.MaxHeight + vborders
738 win->UserData = (BYTE*)data->wd_RenderInfo.mri_WindowObject;
739 win->UserPort = muiGlobalInfo(obj)->mgi_WindowsPort; /* Same port for all windows */
740 ModifyIDCMP(win, data->wd_Events);
742 data->wd_RenderInfo.mri_Window = win;
743 data->wd_RenderInfo.mri_VertProp = data->wd_VertProp;
744 data->wd_RenderInfo.mri_HorizProp = data->wd_HorizProp;
745 SetDrMd(win->RPort,JAM1); //text is draw wrong in toolbarclass if not set
747 if (menu)
749 data->wd_Menu = menu;
750 SetMenuStrip(win,menu);
753 if (flags & WFLG_ACTIVATE)
755 data->wd_Flags |= MUIWF_ACTIVE;
758 return TRUE;
761 if (menu) FreeMenus(menu);
762 UndisplayWindow(obj, data);
764 return FALSE;
768 static void UndisplayWindow(Object *obj, struct MUI_WindowData *data)
770 struct Window *win = data->wd_RenderInfo.mri_Window;
771 if ((data->wd_XStore >= 0) && (data->wd_YStore >= 0))
773 DoMethod(obj,MUIM_Window_Snapshot,0);
776 data->wd_RenderInfo.mri_Window = NULL;
777 data->wd_RenderInfo.mri_VertProp = NULL;
778 data->wd_RenderInfo.mri_HorizProp = NULL;
780 data->wd_Flags &= ~MUIWF_ACTIVE;
782 if (win != NULL)
784 /* store position and size */
785 if (data->wd_XStore >=0)
786 data->wd_X = win->LeftEdge;
787 else
788 data->wd_X = data->wd_XStore;
789 if (data->wd_YStore >=0)
790 data->wd_Y = win->TopEdge;
791 else
792 data->wd_Y = data->wd_YStore;
793 data->wd_Width = win->GZZWidth;
794 data->wd_Height = win->GZZHeight;
796 ClearMenuStrip(win);
797 if (data->wd_Menu)
799 FreeMenus(data->wd_Menu);
800 data->wd_Menu = NULL;
803 if (win->UserPort)
805 struct IntuiMessage *msg, *succ;
807 /* remove all messages pending for this window */
808 Forbid();
811 msg = (struct IntuiMessage *)win->UserPort->mp_MsgList.lh_Head;
812 (succ = (struct IntuiMessage *)msg->ExecMessage.mn_Node.ln_Succ);
813 msg = succ
816 if (msg->IDCMPWindow == win)
818 Remove((struct Node *)msg);
819 ReplyMsg((struct Message *)msg);
822 win->UserPort = NULL;
823 ModifyIDCMP(win, 0);
824 Permit();
827 /* D(bug("before CloseWindow\n")); */
828 CloseWindow(win);
829 /* D(bug("after CloseWindow\n")); */
832 #define DISPOSEGADGET(x) \
833 if (x)\
835 DoMethod(obj, MUIM_Window_FreeGadgetID, ((struct Gadget*)x)->GadgetID);\
836 DisposeObject(x);\
837 x = NULL;\
840 DISPOSEGADGET(data->wd_VertProp);
841 DISPOSEGADGET(data->wd_UpButton);
842 DISPOSEGADGET(data->wd_DownButton);
843 DISPOSEGADGET(data->wd_HorizProp);
844 DISPOSEGADGET(data->wd_LeftButton);
845 DISPOSEGADGET(data->wd_RightButton);
846 #undef DISPOSEGADGET
850 /* Initialize data->wd_X and data->wd_Y for DisplayWindow */
851 /* FIXME 20030817: needs some fixing, seems not fully implemented */
852 static void CalcWindowPosition(Object *obj, struct MUI_WindowData *data)
854 data->wd_XStore = data->wd_X;
855 data->wd_YStore = data->wd_Y;
856 if (NULL == data->wd_RefWindow)
858 /* The following calculations are not very correct, the size and dragbar
859 ** are ignored also the current overscan view */
860 if (data->wd_X == MUIV_Window_LeftEdge_Centered)
862 data->wd_X = (data->wd_RenderInfo.mri_Screen->ViewPort.DWidth - data->wd_Width)/2
863 - data->wd_RenderInfo.mri_Screen->LeftEdge;
865 else if (data->wd_X == MUIV_Window_LeftEdge_Moused)
867 data->wd_X = data->wd_RenderInfo.mri_Screen->MouseX;
870 if (data->wd_Y == MUIV_Window_TopEdge_Centered)
872 data->wd_Y = (data->wd_RenderInfo.mri_Screen->ViewPort.DHeight - data->wd_Height)/2
873 - data->wd_RenderInfo.mri_Screen->TopEdge;
875 else if (data->wd_Y == MUIV_Window_TopEdge_Moused)
877 data->wd_Y = data->wd_RenderInfo.mri_Screen->MouseY;
879 else if (data->wd_Y <= MUIV_Window_TopEdge_Delta(0))
881 data->wd_Y = data->wd_RenderInfo.mri_Screen->BarHeight + 1
882 + MUIV_Window_TopEdge_Delta(0) - data->wd_Y;
885 else
887 ULONG w = 0, x = 0;
888 ULONG h = 0, y = 0;
890 get(data->wd_RefWindow, MUIA_Window_Width, &w);
891 get(data->wd_RefWindow, MUIA_Window_LeftEdge, &x);
893 if (data->wd_X == MUIV_Window_LeftEdge_Centered)
895 data->wd_X = x + (w - data->wd_Width)/2;
897 else
899 data->wd_X += x;
902 get(data->wd_RefWindow, MUIA_Window_Height, &h);
903 get(data->wd_RefWindow, MUIA_Window_TopEdge, &y);
905 if (data->wd_Y == MUIV_Window_TopEdge_Centered)
907 /* D(bug("y=%ld, h=%ld, wdh=%ld\n", y, h, data->wd_Height)); */
908 data->wd_Y = y + (h - data->wd_Height)/2;
910 else if (data->wd_Y <= MUIV_Window_TopEdge_Delta(0))
912 /* ??? surely incorrect implementation */
913 data->wd_Y = y + 1 + MUIV_Window_TopEdge_Delta(0) - data->wd_Y;
915 else
917 data->wd_Y += y;
922 /* Initialize data->wd_AltDim for DisplayWindow */
923 static void CalcAltDimensions(Object *obj, struct MUI_WindowData *data)
925 /* Calculate alternate (zoomed) dimensions.
927 if (data->wd_AltDim.Top == MUIV_Window_AltTopEdge_NoChange)
928 data->wd_AltDim.Top = ~0;
929 else if (data->wd_AltDim.Top == MUIV_Window_AltTopEdge_Centered)
930 data->wd_AltDim.Top = (data->wd_RenderInfo.mri_Screen->Height - data->wd_Height)/2;
931 else if (data->wd_AltDim.Top == MUIV_Window_AltTopEdge_Moused)
932 /* ? */ data->wd_AltDim.Top = ~0;
934 if (data->wd_AltDim.Left == MUIV_Window_AltLeftEdge_NoChange)
935 data->wd_AltDim.Left = ~0;
936 else if (data->wd_AltDim.Left == MUIV_Window_AltLeftEdge_Centered)
937 data->wd_AltDim.Left = (data->wd_RenderInfo.mri_Screen->Width - data->wd_Width)/2;
938 else if (data->wd_AltDim.Left == MUIV_Window_AltLeftEdge_Moused)
939 /* ? */ data->wd_AltDim.Left = ~0;
943 _between
945 MUIV_Window_AltWidth_MinMax(100),
946 data->wd_AltDim.Width,
947 MUIV_Window_AltWidth_MinMax(0)
951 data->wd_AltDim.Width = data->wd_MinMax.MinWidth
952 - data->wd_AltDim.Width
953 * (data->wd_MinMax.MaxWidth - data->wd_MinMax.MinWidth);
955 else if
957 _between
959 MUIV_Window_AltWidth_Screen(100),
960 data->wd_AltDim.Width,
961 MUIV_Window_AltWidth_Screen(0)
965 data->wd_AltDim.Width = data->wd_RenderInfo.mri_ScreenWidth
966 * (- (data->wd_AltDim.Width + 200)) / 100;
968 else if
970 _between
972 MUIV_Window_AltWidth_Visible(100),
973 data->wd_AltDim.Width,
974 MUIV_Window_AltWidth_Visible(0)
978 data->wd_AltDim.Width = data->wd_RenderInfo.mri_ScreenWidth
979 * (- (data->wd_AltDim.Width + 100)) / 100;
984 _between
986 MUIV_Window_AltHeight_MinMax(100),
987 data->wd_AltDim.Height,
988 MUIV_Window_AltHeight_MinMax(0)
992 data->wd_AltDim.Height = data->wd_MinMax.MinHeight
993 - data->wd_AltDim.Height
994 * (data->wd_MinMax.MaxHeight - data->wd_MinMax.MinHeight);
996 else if
998 _between
1000 MUIV_Window_AltHeight_Screen(100),
1001 data->wd_AltDim.Height,
1002 MUIV_Window_AltHeight_Screen(0)
1006 data->wd_AltDim.Height = data->wd_RenderInfo.mri_ScreenHeight
1007 * (- (data->wd_AltDim.Height + 200)) / 100;
1009 else if
1011 _between
1013 MUIV_Window_AltHeight_Visible(100),
1014 data->wd_AltDim.Height,
1015 MUIV_Window_AltHeight_Visible(0)
1019 data->wd_AltDim.Height = data->wd_RenderInfo.mri_ScreenHeight
1020 * (- (data->wd_AltDim.Height + 100)) / 100;
1023 data->wd_AltDim.Width = CLAMP
1025 data->wd_AltDim.Width, data->wd_MinMax.MinWidth,
1026 data->wd_MinMax.MaxWidth
1028 data->wd_AltDim.Height = CLAMP
1030 data->wd_AltDim.Height, data->wd_MinMax.MinHeight,
1031 data->wd_MinMax.MaxHeight
1036 /* Create horiz/vert window scrollbars for DisplayWindow */
1037 static void CreateWindowScrollbars(Object *obj, struct MUI_WindowData *data)
1039 struct MUI_RenderInfo *mri = &data->wd_RenderInfo;
1040 Object *firstgad = NULL;
1041 Object *prevgad = NULL;
1042 LONG id;
1044 /* Create the right border scrollers now if requested */
1045 if (data->wd_Flags & MUIWF_USERIGHTSCROLLER)
1047 int voffset;
1049 voffset = IM(mri->mri_DownImage)->Width / 4;
1051 id = DoMethod(obj, MUIM_Window_AllocGadgetID);
1052 firstgad = prevgad = data->wd_VertProp = NewObject
1054 NULL, "propgclass",
1056 GA_RelRight, 1 - (IM(mri->mri_UpImage)->Width - voffset),
1057 GA_Top, mri->mri_BorderTop + 2,
1058 GA_Width, IM(mri->mri_UpImage)->Width - voffset * 2,
1059 GA_RelHeight, - (mri->mri_BorderTop + 2)
1060 - IM(mri->mri_UpImage)->Height
1061 - IM(mri->mri_DownImage)->Height
1062 - IM(mri->mri_SizeImage)->Height - 2,
1063 GA_RightBorder, TRUE,
1064 GA_ID, id,
1065 PGA_Borderless, TRUE,
1066 PGA_NewLook, TRUE,
1067 PGA_Freedom, FREEVERT,
1068 PGA_Top, 0,
1069 PGA_Total, 2,
1070 PGA_Visible, 1,
1071 ICA_TARGET, ICTARGET_IDCMP,
1072 TAG_DONE
1075 id = DoMethod(obj, MUIM_Window_AllocGadgetID);
1076 prevgad = data->wd_UpButton = NewObject
1078 NULL, "buttongclass",
1080 GA_Image, (IPTR)mri->mri_UpImage,
1081 GA_RelRight, 1 - IM(mri->mri_UpImage)->Width,
1082 GA_RelBottom, 1 - IM(mri->mri_UpImage)->Height
1083 - IM(mri->mri_DownImage)->Height
1084 - IM(mri->mri_SizeImage)->Height,
1085 GA_RightBorder, TRUE,
1086 GA_Previous, (IPTR)prevgad,
1087 GA_ID, id,
1088 ICA_TARGET, ICTARGET_IDCMP,
1089 TAG_DONE
1092 id = DoMethod(obj, MUIM_Window_AllocGadgetID);
1093 prevgad = data->wd_DownButton = NewObject
1095 NULL, "buttongclass",
1097 GA_Image, (IPTR)mri->mri_DownImage,
1098 GA_RelRight, 1 - IM(mri->mri_DownImage)->Width,
1099 GA_RelBottom, 1 - IM(mri->mri_DownImage)->Height
1100 - IM(mri->mri_SizeImage)->Height,
1101 GA_RightBorder, TRUE,
1102 GA_Previous, (IPTR)prevgad,
1103 GA_ID, id,
1104 ICA_TARGET, ICTARGET_IDCMP,
1105 TAG_DONE
1107 } // if (data->wd_Flags & MUIWF_USERIGHTSCROLLER)
1109 /* Create the bottom border scrollers now if requested */
1110 if (data->wd_Flags & MUIWF_USEBOTTOMSCROLLER)
1112 int hoffset;
1114 hoffset = IM(mri->mri_RightImage)->Height / 4;
1116 id = DoMethod(obj, MUIM_Window_AllocGadgetID);
1117 prevgad = data->wd_HorizProp = NewObject
1119 NULL, "propgclass",
1121 GA_RelBottom, 1 - (IM(mri->mri_LeftImage)->Height - hoffset),
1122 GA_Left, mri->mri_BorderLeft,
1123 GA_Height, IM(mri->mri_LeftImage)->Height
1124 - hoffset * 2,
1125 GA_RelWidth, - (mri->mri_BorderLeft)
1126 - IM(mri->mri_LeftImage)->Width
1127 - IM(mri->mri_RightImage)->Width
1128 - IM(mri->mri_SizeImage)->Width
1129 - 2,
1130 GA_BottomBorder, TRUE,
1131 GA_ID, id,
1132 prevgad ? GA_Previous : TAG_IGNORE, (IPTR)prevgad,
1133 PGA_Borderless, TRUE,
1134 PGA_NewLook, TRUE,
1135 PGA_Freedom, FREEHORIZ,
1136 PGA_Top, 0,
1137 PGA_Total, 2,
1138 PGA_Visible, 1,
1139 ICA_TARGET, ICTARGET_IDCMP,
1140 TAG_DONE
1143 if (!firstgad) firstgad = prevgad;
1145 id = DoMethod(obj, MUIM_Window_AllocGadgetID);
1146 prevgad = data->wd_LeftButton = NewObject
1148 NULL, "buttongclass",
1150 GA_Image, (IPTR)mri->mri_LeftImage,
1151 GA_RelRight, 1 - IM(mri->mri_LeftImage)->Width
1152 - IM(mri->mri_RightImage)->Width
1153 - IM(mri->mri_SizeImage)->Width,
1154 GA_RelBottom, 1 - IM(mri->mri_LeftImage)->Height,
1155 GA_BottomBorder, TRUE,
1156 GA_Previous, (IPTR)prevgad,
1157 GA_ID, id,
1158 ICA_TARGET, ICTARGET_IDCMP,
1159 TAG_DONE
1162 id = DoMethod(obj, MUIM_Window_AllocGadgetID);
1163 prevgad = data->wd_RightButton = NewObject
1165 NULL, "buttongclass",
1167 GA_Image, (IPTR)mri->mri_RightImage,
1168 GA_RelRight, 1 - IM(mri->mri_RightImage)->Width
1169 - IM(mri->mri_SizeImage)->Width,
1170 GA_RelBottom, 1 - IM(mri->mri_RightImage)->Height,
1171 GA_BottomBorder, TRUE,
1172 GA_Previous, (IPTR)prevgad,
1173 GA_ID, id,
1174 ICA_TARGET, ICTARGET_IDCMP,
1175 TAG_DONE);
1176 } // if (data->wd_Flags & MUIWF_USEBOTTOMSCROLLER)
1179 /* return FALSE only if no resize (dx=dy=0) occured */
1180 static BOOL WindowResize (struct MUI_WindowData *data)
1182 struct Window *win = data->wd_RenderInfo.mri_Window;
1183 int hborders = win->BorderLeft + win->BorderRight;
1184 int vborders = win->BorderTop + win->BorderBottom;
1185 WORD dx = data->wd_Width - win->Width + hborders;
1186 WORD dy = data->wd_Height - win->Height + vborders;
1188 /* Temporarily disable window limits to let SizeWindow below work
1189 regardless of the previous limits */
1190 WindowLimits(win, 1, 1, -1, -1);
1191 /* D(bug("_zune_window_resize : dx=%d, dy=%d\n", dx, dy)); */
1192 SizeWindow(win, dx, dy);
1194 /* Set new window limits */
1195 WindowLimits
1197 win, data->wd_MinMax.MinWidth + hborders,
1198 data->wd_MinMax.MinHeight + vborders,
1199 data->wd_MinMax.MaxWidth + hborders,
1200 data->wd_MinMax.MaxHeight + vborders
1203 return dx || dy;
1206 static void KillHelpBubble(struct MUI_WindowData *data, Object *obj, BOOL kill_bubblemode)
1208 if (data->wd_HelpObject)
1210 DoMethod(data->wd_HelpObject, MUIM_DeleteBubble, (IPTR)data->wd_HelpBubble);
1211 data->wd_HelpObject = NULL;
1212 data->wd_HelpBubble = NULL;
1215 if (kill_bubblemode) data->wd_Flags &= ~MUIWF_BUBBLEMODE;
1217 if (data->wd_Flags & MUIWF_BUBBLEMODE)
1219 data->wd_HelpTicker = BUBBLEHELP_TICKER_LATER;
1221 else
1223 data->wd_HelpTicker = BUBBLEHELP_TICKER_FIRST;
1228 /**************/
1230 typedef BOOL (*UNDERCHECK_FUNC)(Object *obj);
1232 static BOOL ShortHelpUnderPointerCheck(Object *obj)
1234 return muiAreaData(obj)->mad_ShortHelp ? TRUE : FALSE;
1237 static Object *ObjectUnderPointer(struct MUI_WindowData *data, Object *obj,
1238 LONG x, LONG y, UNDERCHECK_FUNC func)
1240 Object *cstate;
1241 Object *child;
1242 struct MinList *ChildList = NULL;
1244 if (!(muiAreaData(obj)->mad_Flags & MADF_CANDRAW))
1245 return NULL;
1247 if (!(x >= _left(obj) && x <= _right(obj)
1248 && y >= _top(obj) && y <= _bottom(obj)))
1250 return NULL;
1253 if ((get(obj, MUIA_Group_ChildList, &(ChildList))) && (ChildList != NULL))
1255 cstate = (Object *)ChildList->mlh_Head;
1256 while ((child = NextObject(&cstate)))
1258 Object *ret;
1260 if ((x >= _left(child) && x <= _right(child)
1262 y >= _top(child) && y <= _bottom(child))
1264 (ret = ObjectUnderPointer(data, child, x, y, func)))
1266 return ret;
1271 if (!(*func)(obj)) return NULL;
1273 return obj;
1276 static BOOL ContextMenuUnderPointer(struct MUI_WindowData *data, Object *obj, LONG x, LONG y)
1278 Object *cstate;
1279 Object *child;
1280 struct MinList *ChildList = NULL;
1282 if (!(x >= _left(obj) && x <= _right(obj)
1283 && y >= _top(obj) && y <= _bottom(obj)))
1285 return FALSE;
1288 if ((get(obj, MUIA_Group_ChildList, &(ChildList))) && (ChildList != NULL))
1291 cstate = (Object *)ChildList->mlh_Head;
1292 while ((child = NextObject(&cstate)))
1294 if ((x >= _left(child) && x <= _right(child)
1296 y >= _top(child) && y <= _bottom(child))
1298 (ContextMenuUnderPointer(data,child,x,y)))
1299 return TRUE;
1303 if (!(muiAreaData(obj)->mad_Flags & MADF_CANDRAW))
1304 return FALSE;
1305 if (!(muiAreaData(obj)->mad_ContextMenu))
1306 return FALSE;
1308 return TRUE;
1311 /**************/
1313 static void ActivateObject (struct MUI_WindowData *data)
1315 //bug("Window::ActivateObject (dummy) %08lx\n", data->wd_ActiveObject);
1316 // if (FindObjNode(&data->wd_CycleChain, data->wd_ActiveObject))
1317 // DoMethod(data->wd_ActiveObject, MUIM_GoActive);
1318 // else
1319 // data->wd_ActiveObject = NULL;
1321 //activate better string gadgets.Fix from Georg S On ML List
1322 if (FindObjNode(&data->wd_CycleChain, data->wd_ActiveObject))
1324 if (!(data->wd_Flags & MUIWF_OBJECTGOACTIVESENT))
1326 data->wd_Flags |= MUIWF_OBJECTGOACTIVESENT;
1327 DoMethod(data->wd_ActiveObject, MUIM_GoActive);
1330 else
1331 data->wd_ActiveObject = NULL;
1334 /**************/
1336 static void HandleInputEvent(Object *win, struct MUI_WindowData *data,
1337 struct IntuiMessage *event);
1339 /* handle intuimessage while an object is being dragged
1340 * (reply imsg before returning)
1342 void HandleDragging (Object *oWin, struct MUI_WindowData *data,
1343 struct IntuiMessage *imsg)
1345 struct Window *iWin;
1346 int finish_drag = 0;
1348 iWin = imsg->IDCMPWindow;
1350 if (imsg->Class == IDCMP_MOUSEMOVE)
1352 struct Layer *layer;
1353 layer = WhichLayer(&iWin->WScreen->LayerInfo, iWin->LeftEdge + imsg->MouseX, iWin->TopEdge + imsg->MouseY);
1355 if (data->wd_DropObject)
1357 struct Window *wnd;
1358 WORD mousex = imsg->MouseX + iWin->LeftEdge - data->wd_DropWindow->LeftEdge;
1359 WORD mousey = imsg->MouseY + iWin->TopEdge - data->wd_DropWindow->TopEdge;
1361 wnd = _window(data->wd_DropObject);
1364 mousex < _left(data->wd_DropObject)
1365 || mousex > _right(data->wd_DropObject)
1366 || mousey < _top(data->wd_DropObject)
1367 || mousey > _bottom(data->wd_DropObject)
1368 || layer != wnd->WLayer
1371 /* We have left the object */
1372 UndrawDragNDrop(data->wd_dnd);
1373 DoMethod(data->wd_DropObject, MUIM_DragFinish,(IPTR)data->wd_DragObject);
1374 data->wd_DropObject = NULL;
1376 } /* if (data->wd_DropObject) */
1378 if (!data->wd_DropObject)
1380 Object *dest_wnd = NULL;
1382 /* Find out if app has an openend window at this position */
1383 if (layer)
1385 Object *cstate;
1386 Object *child;
1387 struct MinList *ChildList = 0;
1389 get(_app(oWin), MUIA_Application_WindowList, &(ChildList));
1390 cstate = (Object *)ChildList->mlh_Head;
1391 while ((child = NextObject(&cstate)))
1393 struct Window *wnd = NULL;
1394 get(child, MUIA_Window_Window,&wnd);
1395 if (!wnd) continue;
1397 if (wnd->WLayer == layer)
1399 data->wd_DropWindow = wnd;
1400 dest_wnd = child;
1401 break;
1404 } /* if (layer) */
1406 if (dest_wnd)
1408 Object *root = NULL;
1409 get(dest_wnd, MUIA_Window_RootObject, &root);
1411 if (root)
1416 data->wd_DropObject = (Object*) DoMethod
1418 root, MUIM_DragQueryExtended,
1419 (IPTR) data->wd_DragObject,
1420 imsg->MouseX + iWin->LeftEdge - data->wd_DropWindow->LeftEdge,
1421 imsg->MouseY + iWin->TopEdge - data->wd_DropWindow->TopEdge
1426 UndrawDragNDrop(data->wd_dnd);
1427 DoMethod(data->wd_DropObject, MUIM_DragBegin,(IPTR)data->wd_DragObject);
1430 } /* if (dest_wnd) */
1431 } /* if (!data->wd_DropObject) */
1433 if (data->wd_DropObject)
1435 LONG update = 0;
1436 LONG i;
1437 for (i=0;i<2;i++)
1439 LONG res = DoMethod
1441 data->wd_DropObject, MUIM_DragReport,
1442 (IPTR) data->wd_DragObject,
1443 imsg->MouseX + iWin->LeftEdge - data->wd_DropWindow->LeftEdge,
1444 imsg->MouseY + iWin->TopEdge - data->wd_DropWindow->TopEdge,update
1446 switch (res)
1448 case MUIV_DragReport_Abort:
1449 UndrawDragNDrop(data->wd_dnd);
1450 DoMethod(data->wd_DropObject, MUIM_DragFinish,(IPTR)data->wd_DragObject);
1451 data->wd_DropObject = NULL;
1452 i = 1;
1453 break;
1455 case MUIV_DragReport_Continue: break;
1456 case MUIV_DragReport_Lock: break; /* NYI */
1457 case MUIV_DragReport_Refresh:
1458 UndrawDragNDrop(data->wd_dnd);
1459 update = 1;
1460 break;
1463 } /* if (data->wd_DropObject) */
1464 DrawDragNDrop(data->wd_dnd, imsg->MouseX + iWin->LeftEdge , imsg->MouseY + iWin->TopEdge);
1465 } /* if (imsg->Class == IDCMP_MOUSEMOVE) */
1467 if (imsg->Class == IDCMP_MOUSEBUTTONS)
1469 if ((imsg->Code == MENUDOWN) || (imsg->Code == SELECTUP))
1471 if (imsg->Code == SELECTUP && data->wd_DropObject)
1473 UndrawDragNDrop(data->wd_dnd);
1474 DoMethod(data->wd_DropObject, MUIM_DragFinish, (IPTR)data->wd_DragObject);
1475 DoMethod
1477 data->wd_DropObject, MUIM_DragDrop, (IPTR)data->wd_DragObject,
1478 imsg->MouseX + iWin->LeftEdge - data->wd_DropWindow->LeftEdge,
1479 imsg->MouseY + iWin->TopEdge - data->wd_DropWindow->TopEdge
1481 data->wd_DropObject = NULL;
1483 else if (imsg->Code == SELECTUP)
1485 DoMethod(data->wd_DragObject, MUIM_UnknownDropDestination, imsg);
1487 finish_drag = 1;
1491 if (imsg->Class == IDCMP_CLOSEWINDOW)
1492 finish_drag = 1;
1494 if (finish_drag)
1496 UndrawDragNDrop(data->wd_dnd);
1497 if (data->wd_DropObject)
1499 DoMethod(data->wd_DropObject, MUIM_DragFinish, (IPTR)data->wd_DragObject);
1500 data->wd_DropObject = NULL;
1502 DeleteDragNDrop(data->wd_dnd);
1503 DoMethod(data->wd_DragObject, MUIM_DeleteDragImage, (IPTR)data->wd_DragImage);
1504 muiAreaData(data->wd_DragObject)->mad_Flags &= ~MADF_DRAGGING;
1505 data->wd_DragImage = NULL;
1506 data->wd_DragObject = NULL;
1507 data->wd_DropWindow = NULL;
1508 data->wd_dnd = NULL;
1509 /* stop listening to IDCMP_MOUSEMOVE */
1510 ChangeEvents(data, GetDefaultEvents());
1512 ReplyMsg((struct Message*)imsg);
1515 /* Reply to imsg if handled */
1516 BOOL HandleWindowEvent (Object *oWin, struct MUI_WindowData *data,
1517 struct IntuiMessage *imsg)
1519 struct Window *iWin;
1520 BOOL is_handled = TRUE;
1521 BOOL replied = FALSE;
1523 iWin = imsg->IDCMPWindow;
1524 switch (imsg->Class)
1526 case IDCMP_ACTIVEWINDOW:
1527 data->wd_Flags |= MUIWF_ACTIVE;
1528 if (data->wd_OldActive)
1529 set(oWin, MUIA_Window_ActiveObject, data->wd_OldActive);
1530 set(oWin, MUIA_Window_Activate, TRUE);
1531 is_handled = FALSE; /* forwardable to area event handlers */
1532 break;
1534 case IDCMP_INACTIVEWINDOW:
1535 KillHelpBubble(data, oWin, TRUE);
1536 if (data->wd_ActiveObject)
1538 data->wd_OldActive = data->wd_ActiveObject;
1539 set(oWin, MUIA_Window_ActiveObject, MUIV_Window_ActiveObject_None);
1541 data->wd_Flags &= ~MUIWF_ACTIVE;
1542 set(oWin, MUIA_Window_Activate, FALSE);
1543 is_handled = FALSE; /* forwardable to area event handlers */
1544 break;
1546 case IDCMP_NEWSIZE:
1547 ReplyMsg((struct Message*)imsg);
1548 replied = TRUE;
1551 int hborders = iWin->BorderLeft + iWin->BorderRight;
1552 int vborders = iWin->BorderTop + iWin->BorderBottom;
1554 /* set window limits according to window contents */
1555 WindowLimits
1557 iWin,
1558 data->wd_MinMax.MinWidth + hborders,
1559 data->wd_MinMax.MinHeight + vborders,
1560 data->wd_MinMax.MaxWidth + hborders,
1561 data->wd_MinMax.MaxHeight + vborders
1565 if ((iWin->GZZWidth != data->wd_Width) || (iWin->GZZHeight != data->wd_Height))
1567 data->wd_Width = iWin->GZZWidth;
1568 data->wd_Height = iWin->GZZHeight;
1569 DoHideMethod(data->wd_RootObject);
1571 if (1) // why only simple refresh? was: if (data->wd_RenderInfo.mri_Window->Flags & WFLG_SIMPLE_REFRESH)
1573 data->wd_Flags |= MUIWF_RESIZING;
1575 else
1577 _width(data->wd_RootObject) = data->wd_Width;
1578 _height(data->wd_RootObject) = data->wd_Height;
1579 DoMethod(data->wd_RootObject, MUIM_Layout);
1580 DoShowMethod(data->wd_RootObject);
1582 LONG left,top,width,height;
1584 left = data->wd_RenderInfo.mri_Window->BorderLeft;
1585 top = data->wd_RenderInfo.mri_Window->BorderTop,
1586 width = data->wd_RenderInfo.mri_Window->Width
1587 - data->wd_RenderInfo.mri_Window->BorderRight - left;
1588 height = data->wd_RenderInfo.mri_Window->Height
1589 - data->wd_RenderInfo.mri_Window->BorderBottom - top;
1591 // D(bug("%d:zune_imspec_draw(%p) l=%d t=%d w=%d h=%d xo=%d yo=%d\n",
1592 // __LINE__, data->wd_Background, left, top, width,
1593 // height, left, top));
1594 zune_imspec_draw(data->wd_Background, &data->wd_RenderInfo,
1595 left, top, width, height, left, top, 0);
1597 if (muiGlobalInfo(oWin)->mgi_Prefs->window_redraw == WINDOW_REDRAW_WITHOUT_CLEAR)
1598 MUI_Redraw(data->wd_RootObject, MADF_DRAWOBJECT);
1599 else
1600 MUI_Redraw(data->wd_RootObject, MADF_DRAWALL);
1601 // but should only draw focus without using MUIM_GoActive !
1602 ActivateObject(data);
1605 break;
1607 case IDCMP_REFRESHWINDOW:
1608 ReplyMsg((struct Message*)imsg);
1609 replied = TRUE;
1610 if (data->wd_Flags & MUIWF_RESIZING)
1612 //LONG left,top,right,bottom;
1613 if (MUI_BeginRefresh(&data->wd_RenderInfo, 0))
1615 MUI_EndRefresh(&data->wd_RenderInfo, 0);
1617 RefreshWindowFrame(data->wd_RenderInfo.mri_Window);
1619 data->wd_Flags &= ~MUIWF_RESIZING;
1620 _width(data->wd_RootObject) = data->wd_Width;
1621 _height(data->wd_RootObject) = data->wd_Height;
1622 DoMethod(data->wd_RootObject, MUIM_Layout);
1623 DoShowMethod(data->wd_RootObject);
1625 if (muiGlobalInfo(oWin)->mgi_Prefs->window_redraw == WINDOW_REDRAW_WITH_CLEAR)
1627 LONG left,top,width,height;
1629 left = data->wd_RenderInfo.mri_Window->BorderLeft;
1630 top = data->wd_RenderInfo.mri_Window->BorderTop;
1631 width = data->wd_RenderInfo.mri_Window->Width - data->wd_RenderInfo.mri_Window->BorderRight - left;
1632 height = data->wd_RenderInfo.mri_Window->Height - data->wd_RenderInfo.mri_Window->BorderBottom - top;
1634 if(data->wd_Flags & MUIWF_ERASEAREA)
1636 // D(bug("%d:zune_imspec_draw(%p) l=%d t=%d w=%d h=%d xo=%d yo=%d\n",
1637 // __LINE__, data->wd_Background, left, top, width,
1638 // height, left, top));
1639 zune_imspec_draw(data->wd_Background, &data->wd_RenderInfo,
1640 left, top, width, height, left, top, 0);
1642 MUI_Redraw(data->wd_RootObject, MADF_DRAWALL);
1644 else
1645 MUI_Redraw(data->wd_RootObject, MADF_DRAWOBJECT);
1646 // but should only draw focus without using MUIM_GoActive !
1647 ActivateObject(data);
1649 else
1651 if (MUI_BeginRefresh(&data->wd_RenderInfo, 0))
1653 MUI_Redraw(data->wd_RootObject, MADF_DRAWALL);
1654 // but should only draw focus without using MUIM_GoActive !
1655 ActivateObject(data);
1656 MUI_EndRefresh(&data->wd_RenderInfo, 0);
1659 break;
1661 case IDCMP_CLOSEWINDOW:
1662 ReplyMsg((struct Message*)imsg);
1663 replied = TRUE;
1664 set(oWin, MUIA_Window_CloseRequest, TRUE);
1665 break;
1667 case IDCMP_MENUPICK:
1668 ReplyMsg((struct Message*)imsg);
1669 replied = TRUE;
1671 if (data->wd_Menu)
1673 if (MENUNUM(imsg->Code) != NOMENU && ITEMNUM(imsg->Code) != NOITEM)
1675 struct MenuItem *item = ItemAddress(data->wd_Menu,imsg->Code);
1676 if (item)
1678 Object *item_obj = (Object*)GTMENUITEM_USERDATA(item);
1679 if (item_obj)
1681 Object *app = NULL;
1682 IPTR udata = 0;
1684 if (item->Flags & CHECKIT)
1685 set(item_obj, MUIA_Menuitem_Checked, !!(item->Flags & CHECKED));
1687 set(item_obj, MUIA_Menuitem_Trigger, (IPTR)item);
1689 get(oWin, MUIA_ApplicationObject, &app);
1690 get(item_obj, MUIA_UserData, &udata);
1692 set(app, MUIA_Application_MenuAction, udata);
1693 set(oWin, MUIA_Window_MenuAction, udata);
1694 DoMethod(app, MUIM_Application_ReturnID, udata);
1699 break;
1701 case IDCMP_IDCMPUPDATE:
1702 is_handled = FALSE; /* forwardable to area event handlers */
1703 if (data->wd_VertProp || data->wd_HorizProp)
1705 struct TagItem *tag;
1706 tag = FindTagItem(GA_ID,(struct TagItem*)imsg->IAddress);
1707 if (tag)
1709 /* If there's a propclass object connected to the prop
1710 gadget, the prop gadget's userdata will point to
1711 that propclass object. See classes/prop.c */
1713 if (data->wd_VertProp)
1715 if (tag->ti_Data == GADGETID(data->wd_VertProp))
1718 if (tag->ti_Data == GADGETID(data->wd_UpButton))
1720 Object *prop = (Object *)((struct Gadget *)data->wd_VertProp)->UserData;
1721 is_handled = TRUE;
1722 if (prop) DoMethod(prop, MUIM_Prop_Decrease, 1);
1725 if (tag->ti_Data == GADGETID(data->wd_DownButton))
1727 Object *prop = (Object *)((struct Gadget *)data->wd_VertProp)->UserData;
1728 is_handled = TRUE;
1729 if (prop) DoMethod(prop, MUIM_Prop_Increase, 1);
1734 if (data->wd_HorizProp)
1736 if (tag->ti_Data == GADGETID(data->wd_HorizProp))
1739 if (tag->ti_Data == GADGETID(data->wd_LeftButton))
1741 Object *prop = (Object *)((struct Gadget *)data->wd_HorizProp)->UserData;
1742 is_handled = TRUE;
1743 if (prop) DoMethod(prop, MUIM_Prop_Decrease, 1);
1746 if (tag->ti_Data == GADGETID(data->wd_RightButton))
1748 Object *prop = (Object *)((struct Gadget *)data->wd_HorizProp)->UserData;
1749 is_handled = TRUE;
1750 if (prop) DoMethod(prop, MUIM_Prop_Increase, 1);
1756 break;
1758 case IDCMP_INTUITICKS:
1759 if (data->wd_HelpTicker)
1761 data->wd_HelpTicker--;
1763 if (data->wd_HelpTicker == 0)
1765 Object *underobj = ObjectUnderPointer(data, data->wd_RootObject, imsg->MouseX, imsg->MouseY,
1766 ShortHelpUnderPointerCheck);
1768 if (underobj != data->wd_HelpObject)
1770 if (data->wd_HelpObject)
1772 DoMethod(data->wd_HelpObject, MUIM_DeleteBubble, (IPTR)data->wd_HelpBubble);
1774 data->wd_HelpObject = NULL;
1775 data->wd_HelpBubble = NULL;
1778 if (underobj)
1780 data->wd_HelpBubble = (APTR)DoMethod(underobj, MUIM_CreateBubble,
1781 imsg->MouseX, imsg->MouseY,
1782 0, 0);
1783 if (data->wd_HelpBubble)
1785 data->wd_HelpObject = underobj;
1786 data->wd_Flags |= MUIWF_BUBBLEMODE;
1791 if (data->wd_Flags & MUIWF_BUBBLEMODE)
1793 data->wd_HelpTicker = BUBBLEHELP_TICKER_LATER;
1795 else
1797 data->wd_HelpTicker = BUBBLEHELP_TICKER_FIRST;
1800 } /* if (data->wd_HelpTicker == 0) */
1802 } /* if (data->wd_HelpTicker) */
1804 is_handled = FALSE; /* forwardable to area event handlers */
1805 break;
1807 case IDCMP_MOUSEBUTTONS:
1808 DoMethod(oWin,MUIM_Window_Snapshot,0);
1809 KillHelpBubble(data, oWin, TRUE);
1810 is_handled = FALSE;
1811 break;
1814 case IDCMP_MOUSEMOVE:
1815 KillHelpBubble(data, oWin, FALSE);
1816 is_handled = FALSE;
1817 break;
1819 default:
1820 is_handled = FALSE;
1821 break;
1822 } /* switch (imsg->Class) */
1824 if (is_handled && !replied)
1825 ReplyMsg((struct Message*)imsg);
1827 return is_handled;
1830 static ULONG InvokeEventHandler (struct MUI_EventHandlerNode *ehn,
1831 struct IntuiMessage *event, ULONG muikey)
1833 ULONG res;
1835 if (!(_flags(ehn->ehn_Object) & MADF_CANDRAW)) return 0;
1836 if (!(_flags(ehn->ehn_Object) & MADF_SHOWME)) return 0;
1840 event != NULL
1841 && event->Class == IDCMP_MOUSEBUTTONS
1842 && event->Code == SELECTDOWN
1843 && (_flags(ehn->ehn_Object) & MADF_INVIRTUALGROUP)
1847 Here we filter out SELECTDOWN messages if objects is in a virtual
1848 group but the click went out of the virtual group
1850 Object *obj = ehn->ehn_Object;
1851 Object *parent = obj;
1852 Object *wnd = _win(obj);
1854 while (get(parent,MUIA_Parent,&parent))
1856 if (!parent) break;
1857 if (wnd == parent) break;
1858 if (_flags(parent) & MADF_ISVIRTUALGROUP)
1862 event->MouseX < _mleft(parent)
1863 || event->MouseX > _mright(parent)
1864 || event->MouseY < _mtop(parent)
1865 || event->MouseY > _mbottom(parent)
1868 return 0;
1875 if (ehn->ehn_Flags & MUI_EHF_HANDLEINPUT)
1877 DoMethod(ehn->ehn_Object, MUIM_HandleInput, (IPTR)event, muikey);
1878 res = 0;
1880 else
1882 if (ehn->ehn_Class)
1883 res = CoerceMethod
1885 ehn->ehn_Class, ehn->ehn_Object, MUIM_HandleEvent,
1886 (IPTR)event, muikey
1888 else
1889 res = DoMethod(ehn->ehn_Object, MUIM_HandleEvent, (IPTR)event, muikey);
1891 return res;
1894 static void HandleRawkey(Object *win, struct MUI_WindowData *data,
1895 struct IntuiMessage *event)
1897 struct MinNode *mn;
1898 struct MUI_EventHandlerNode *ehn;
1899 struct IntuiMessage imsg_copy;
1900 struct InputEvent ie = {0};
1901 ULONG res;
1902 LONG muikey = MUIKEY_NONE;
1903 Object *active_object = NULL;
1904 IPTR disabled = 0;
1905 ULONG key;
1906 ULONG deadkey;
1908 KillHelpBubble(data, win, BUBBLEHELP_TICKER_FIRST);
1910 ie.ie_NextEvent = NULL;
1911 ie.ie_Class = IECLASS_RAWKEY;
1912 ie.ie_SubClass = 0;
1913 ie.ie_Code = event->Code;
1914 ie.ie_Qualifier = event->Qualifier;
1915 ie.ie_EventAddress = (APTR)*(IPTR *)event->IAddress;
1916 #ifdef __AMIGAOS4__
1917 ie.ie_TimeStamp.Seconds = event->Seconds;
1918 ie.ie_TimeStamp.Microseconds = event->Micros;
1919 #else
1920 ie.ie_TimeStamp.tv_secs = event->Seconds;
1921 ie.ie_TimeStamp.tv_micro = event->Micros;
1922 #endif
1924 set(win, MUIA_Window_InputEvent, (IPTR)&ie);
1926 /* get the vanilla key for control char */
1928 UWORD msg_code;
1929 /* Remove the up prefix as convert key does not convert a upkey event */
1930 msg_code = event->Code;
1931 event->Code &= ~IECODE_UP_PREFIX;
1932 key = ConvertKey(event);
1933 event->Code = msg_code;
1936 imsg_copy = *event;
1937 deadkey = *(ULONG *)event->IAddress;
1938 imsg_copy.IAddress = &deadkey;
1939 ReplyMsg((struct Message*)event);
1940 event = &imsg_copy;
1942 //bug("rawkey: code=%lx, qual=%lx\n", event->Code, event->Qualifier);
1944 /* check if imsg translate to predefined keystroke */
1946 struct InputEvent ievent;
1947 BOOL matched = FALSE;
1949 ievent.ie_NextEvent = NULL;
1950 ievent.ie_Class = IECLASS_RAWKEY;
1951 ievent.ie_SubClass = 0;
1952 ievent.ie_Code = event->Code;
1953 ievent.ie_Qualifier = event->Qualifier;
1954 /* ie_EventAddress is not used by MatchIX. If needed, it should be
1955 * ensured that it is still a valid adress because of the shallow
1956 * IntuiMessage copy currently done in _zune_window_message before
1957 * message is replied.
1959 ievent.ie_EventAddress = NULL;
1960 //ievent.ie_EventAddress = (APTR *) *((ULONG *)(event->IAddress));
1962 for (muikey = MUIKEY_COUNT - 1; muikey >= MUIKEY_PRESS; muikey--)
1964 if (muiGlobalInfo(win)->mgi_Prefs->muikeys[muikey].ix_well != 0
1965 && MatchIX(&ievent, &muiGlobalInfo(win)->mgi_Prefs->muikeys[muikey].ix))
1967 matched = TRUE;
1968 break;
1972 if (matched)
1974 if (muikey == MUIKEY_PRESS && (event->Code & IECODE_UP_PREFIX))
1975 muikey = MUIKEY_RELEASE;
1977 else
1979 muikey = MUIKEY_NONE;
1981 } /* check if imsg translate to predefined keystroke */
1983 if ((muikey != MUIKEY_NONE)
1984 && !(data->wd_DisabledKeys & (1<<muikey)))
1986 D(bug("HandleRawkey: try MUIKEY %ld on window %0x08lx\n", muikey, win));
1987 switch (muikey)
1989 case MUIKEY_PRESS: break;
1990 case MUIKEY_TOGGLE: break;
1991 case MUIKEY_UP: break;
1992 case MUIKEY_DOWN: break;
1993 case MUIKEY_PAGEUP: break;
1994 case MUIKEY_PAGEDOWN: break;
1995 case MUIKEY_TOP: break;
1996 case MUIKEY_BOTTOM: break;
1997 case MUIKEY_LEFT: break;
1998 case MUIKEY_RIGHT: break;
1999 case MUIKEY_WORDLEFT: break;
2000 case MUIKEY_WORDRIGHT: break;
2001 case MUIKEY_LINESTART: break;
2002 case MUIKEY_LINEEND: break;
2003 case MUIKEY_GADGET_NEXT:
2004 set(win, MUIA_Window_ActiveObject, MUIV_Window_ActiveObject_Next);
2005 break;
2006 case MUIKEY_GADGET_PREV:
2007 set(win, MUIA_Window_ActiveObject, MUIV_Window_ActiveObject_Prev);
2008 break;
2009 case MUIKEY_GADGET_OFF:
2010 set(win, MUIA_Window_ActiveObject, MUIV_Window_ActiveObject_None);
2011 break;
2012 case MUIKEY_WINDOW_CLOSE:
2013 set(win, MUIA_Window_CloseRequest, TRUE);
2014 break;
2015 case MUIKEY_WINDOW_NEXT: break;
2016 case MUIKEY_WINDOW_PREV: break;
2017 case MUIKEY_HELP: break;
2018 case MUIKEY_POPUP: break;
2019 default: break;
2023 active_object = NULL;
2024 if ((data->wd_ActiveObject != NULL)
2025 && (DoMethod(data->wd_RootObject, MUIM_FindAreaObject,
2026 (IPTR)data->wd_ActiveObject) != (IPTR)NULL))
2028 active_object = data->wd_ActiveObject;
2029 get(active_object, MUIA_Disabled, &disabled);
2031 else
2032 data->wd_ActiveObject = NULL;
2034 /* try ActiveObject */
2035 if ((active_object != NULL) && !disabled)
2037 #if 0
2038 /* sba:
2039 ** Which method should be used for muikeys? MUIM_HandleInput or
2040 ** MUIM_HandleEvent. Also note that there is a flag MUI_EHF_ALWAYSKEYS
2041 ** which probably means that all keys events are requested??
2042 ** For now MUIM_HandleEvent is used as this is currently implemented
2043 ** in Area class ;) although I guess it should be MUIM_HandleInput as this
2044 ** was earlier
2047 if (muikey != MUIKEY_NONE)
2049 res = DoMethod(active_object, MUIM_HandleEvent, (IPTR)event, muikey);
2050 if (res & MUI_EventHandlerRC_Eat) return;
2052 #endif
2053 D(bug("HandleRawkey: try active object (%08lx) handlers\n", active_object));
2055 for (mn = data->wd_EHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
2057 ehn = (struct MUI_EventHandlerNode *)mn;
2059 if ((ehn->ehn_Object == active_object)
2060 && ((ehn->ehn_Events & IDCMP_RAWKEY)
2061 || (ehn->ehn_Flags & MUI_EHF_ALWAYSKEYS)))
2063 D(bug("HandleRawkey: (active) invoking on %p (ehn=%p) event=%p muikey=%p\n",
2064 ehn->ehn_Object, ehn, event, muikey));
2065 res = InvokeEventHandler(ehn, event, muikey);
2066 D(bug("HandleRawkey: (active) got res=%d\n", res));
2067 if (res & MUI_EventHandlerRC_Eat)
2068 return;
2070 /* Leave the loop if a different object has been activated */
2071 if (active_object != data->wd_ActiveObject)
2072 break;
2074 } /* for (mn = data->wd_EHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ) */
2076 // event not eaten by active object, try its parents
2077 // this is to implement popup key in Popstring
2078 if (active_object == data->wd_ActiveObject)
2080 Object *current_obj = active_object;
2082 D(bug("HandleRawkey: try active object parents handlers\n"));
2083 while (current_obj != NULL)
2085 for (mn = data->wd_EHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
2087 ehn = (struct MUI_EventHandlerNode *)mn;
2089 if ((ehn->ehn_Object == current_obj)
2090 && ((ehn->ehn_Events & IDCMP_RAWKEY)
2091 || (ehn->ehn_Flags & MUI_EHF_ALWAYSKEYS)))
2093 //D(bug("HandleRawkey: (active parents) invoking on %p (ehn=%p) "
2094 //"event=%p muikey=%p\n",
2095 //ehn->ehn_Object, ehn, event, muikey));
2096 res = InvokeEventHandler(ehn, event, muikey);
2097 //D(bug("HandleRawkey: (active parents) got res=%d\n", res));
2098 if (res & MUI_EventHandlerRC_Eat)
2099 return;
2101 /* Leave the loop if a different object has been activated */
2102 if (active_object != data->wd_ActiveObject)
2103 break;
2106 current_obj = (Object *)XGET(current_obj, MUIA_Parent);
2107 } // while (current_obj != NULL)
2109 } /* if (active_object && !disabled) */
2111 D(bug("HandleRawkey: try default object handlers\n"));
2113 /* try DefaultObject */
2114 if (data->wd_DefaultObject != NULL)
2115 get(data->wd_DefaultObject, MUIA_Disabled, &disabled);
2117 if ((data->wd_DefaultObject != NULL) && !disabled
2118 && (active_object != data->wd_DefaultObject))
2120 /* No, we only should do this if the object actually has requested this via RequestIDCMP()! */
2121 // if (muikey != MUIKEY_NONE && (_flags(data->wd_DefaultObject) & MADF_CANDRAW))
2122 // {
2123 // DoMethod(data->wd_DefaultObject, MUIM_HandleInput, event, muikey);
2124 // return;
2125 // }
2127 for (mn = data->wd_EHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
2129 ehn = (struct MUI_EventHandlerNode *)mn;
2131 if ((ehn->ehn_Object == data->wd_DefaultObject)
2132 && ((ehn->ehn_Events & IDCMP_RAWKEY)
2133 || (ehn->ehn_Flags & MUI_EHF_ALWAYSKEYS)))
2135 //D(bug("HandleRawkey: (default) invoking on %p (ehn=%p) event=%p muikey=%p\n",
2136 //ehn->ehn_Object, ehn, event, muikey));
2137 res = InvokeEventHandler(ehn, event, muikey);
2138 //D(bug("HandleRawkey: (default) got res=%d\n", res));
2139 if (res & MUI_EventHandlerRC_Eat)
2140 return;
2144 } /* if ... default object */
2146 D(bug("HandleRawkey: try other handlers\n"));
2148 // try other handlers
2149 for (mn = data->wd_EHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
2151 ehn = (struct MUI_EventHandlerNode *)mn;
2153 // skip Active and Default object as they have already been
2154 // handled
2155 if (ehn->ehn_Object == data->wd_ActiveObject || ehn->ehn_Object == data->wd_DefaultObject)
2156 continue;
2158 if (ehn->ehn_Events & IDCMP_RAWKEY)
2160 //D(bug("HandleRawkey: (others) invoking on %p (ehn=%p) event=%p muikey=%p\n",
2161 //ehn->ehn_Object, ehn, event, muikey));
2162 res = InvokeEventHandler(ehn, event, MUIKEY_NONE);
2163 //D(bug("HandleRawkey: (others) got res=%d\n", res));
2164 if (res & MUI_EventHandlerRC_Eat)
2165 return;
2167 } /* for (mn = data->wd_EHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ) */
2169 D(bug("HandleRawkey: try control chars handlers\n"));
2171 /* try Control Chars */
2172 //bug("ctrlchar, key='%c' code=0x%08lx\n", key, event->Code);
2173 if (key)
2175 for (mn = data->wd_CCList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
2177 ehn = (struct MUI_EventHandlerNode *)mn;
2179 if (ehn->ehn_Events == key)
2181 IPTR disabled = 0;
2182 LONG muikey2 = ehn->ehn_Flags;
2184 get(ehn->ehn_Object, MUIA_Disabled, &disabled);
2185 if (disabled)
2186 continue;
2188 //bug("control char\n");
2189 if (event->Code & IECODE_UP_PREFIX)
2191 /* simulate a release */
2192 if (muikey2 == MUIKEY_PRESS)
2193 muikey2 = MUIKEY_RELEASE;
2194 else
2195 return;
2198 if ((muikey2 != MUIKEY_NONE)
2199 && (_flags(ehn->ehn_Object) & MADF_CANDRAW)
2200 && (_flags(ehn->ehn_Object) & MADF_SHOWME))
2202 res = CoerceMethod
2204 ehn->ehn_Class, ehn->ehn_Object, MUIM_HandleEvent,
2205 (IPTR)NULL, muikey2
2207 if (res & MUI_EventHandlerRC_Eat)
2208 return;
2212 } /* try control chars */
2215 /* forward non-keystroke events to event handlers */
2216 static void HandleInputEvent(Object *win, struct MUI_WindowData *data,
2217 struct IntuiMessage *event)
2219 struct MinNode *mn;
2220 struct MUI_EventHandlerNode *ehn;
2221 struct IntuiMessage imsg_copy;
2222 ULONG res;
2223 ULONG mask = event->Class;
2225 if (mask != IDCMP_IDCMPUPDATE)
2227 imsg_copy = *event;
2228 imsg_copy.IAddress = NULL; /* be sure to trap access to that */
2229 ReplyMsg((struct Message*)event);
2230 event = &imsg_copy;
2233 if (mask == IDCMP_MOUSEMOVE)
2235 struct Window *iWin;
2236 iWin = event->IDCMPWindow;
2238 if (ContextMenuUnderPointer (data, data->wd_RootObject,
2239 event->MouseX, event->MouseY))
2241 iWin->Flags |= WFLG_RMBTRAP;
2243 else if (!data->wd_NoMenus)
2245 iWin->Flags &= ~WFLG_RMBTRAP;
2249 for (mn = data->wd_EHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
2251 ehn = (struct MUI_EventHandlerNode *)mn;
2253 if (ehn->ehn_Events & mask)
2255 IPTR disabled = 0;
2257 get(ehn->ehn_Object, MUIA_Disabled, &disabled);
2258 if (disabled)
2259 continue;
2261 res = InvokeEventHandler(ehn, event, MUIKEY_NONE);
2262 if (res & MUI_EventHandlerRC_Eat)
2263 return;
2268 if (mask == IDCMP_IDCMPUPDATE)
2269 ReplyMsg((struct Message*)event);
2273 /* process window message, this does a ReplyMsg() to the message */
2274 /* Called from application.c */
2275 void _zune_window_message(struct IntuiMessage *imsg)
2277 struct Window *iWin;
2278 Object *oWin;
2279 struct MUI_WindowData *data;
2280 BOOL handled;
2282 iWin = imsg->IDCMPWindow;
2283 oWin = (Object *)iWin->UserData;
2284 data = muiWindowData(oWin);
2286 if (data->wd_DragObject)
2288 HandleDragging(oWin, data, imsg);
2289 return;
2292 handled = HandleWindowEvent(oWin, data, imsg);
2293 if (!handled)
2295 if (IDCMP_RAWKEY == imsg->Class)
2296 HandleRawkey(oWin, data, imsg);
2297 else if (IDCMP_GADGETUP == imsg->Class)
2299 #ifdef __AROS__
2300 if (ETI_MUI == ((struct Gadget *) imsg->IAddress)->GadgetID)
2302 DoMethod(_app(oWin), MUIM_Application_OpenConfigWindow);
2304 #endif
2305 if (ETI_Iconify == ((struct Gadget *)imsg->IAddress)->GadgetID)
2307 set(_app(oWin), MUIA_Application_Iconified, TRUE);
2310 else
2312 HandleInputEvent(oWin, data, imsg);
2317 /******************************************************************************/
2318 /******************************************************************************/
2320 /* code for setting MUIA_Window_RootObject */
2321 static void ChangeRootObject (struct MUI_WindowData *data, Object *obj,
2322 Object *newRoot)
2324 Object *oldRoot;
2326 ASSERT_VALID_PTR(data);
2327 ASSERT_VALID_PTR(obj);
2329 oldRoot = data->wd_RootObject;
2330 if (!(data->wd_Flags & MUIWF_OPENED))
2332 if (oldRoot)
2334 if (data->wd_ActiveObject == oldRoot)
2335 set(obj, MUIA_Window_ActiveObject, MUIV_Window_ActiveObject_None);
2336 DoMethod(oldRoot, MUIM_DisconnectParent);
2339 data->wd_RootObject = newRoot;
2340 if (newRoot)
2342 /* if window is in App tree, inform child */
2343 if (muiNotifyData(obj)->mnd_GlobalInfo)
2344 DoMethod(newRoot, MUIM_ConnectParent, (IPTR)obj);
2349 // find the ObjNode containing a pointer to the given object
2350 // currently only used for cycle chain objects
2351 static struct ObjNode *FindObjNode(struct MinList *list, Object *obj)
2353 struct ObjNode *node;
2355 ASSERT_VALID_PTR(list);
2357 if (!obj)
2358 return NULL;
2360 ASSERT_VALID_PTR(obj);
2362 for (node = (struct ObjNode*)list->mlh_Head;
2363 node->node.mln_Succ;
2364 node = (struct ObjNode*)node->node.mln_Succ)
2366 if (node->obj == obj)
2368 return node;
2371 return NULL;
2374 static Object *GetFirstActiveObject (struct MUI_WindowData *data)
2376 ASSERT_VALID_PTR(data);
2378 if (!IsListEmpty((struct List*)&data->wd_CycleChain))
2379 return ((struct ObjNode*)data->wd_CycleChain.mlh_Head)->obj;
2380 else
2381 return NULL;
2384 static Object *GetLastActiveObject (struct MUI_WindowData *data)
2386 ASSERT_VALID_PTR(data);
2388 if (!IsListEmpty((struct List*)&data->wd_CycleChain))
2389 return ((struct ObjNode*)data->wd_CycleChain.mlh_TailPred)->obj;
2390 else
2391 return NULL;
2394 typedef struct ObjNode *objnode_iterator_t(struct ObjNode *curr_node);
2396 static objnode_iterator_t NextObjNodeIterator;
2397 static objnode_iterator_t PrevObjNodeIterator;
2399 static struct ObjNode *NextObjNodeIterator (struct ObjNode *curr_node)
2401 if (curr_node->node.mln_Succ->mln_Succ)
2402 return (struct ObjNode*)curr_node->node.mln_Succ;
2403 else
2404 return NULL;
2407 static struct ObjNode *PrevObjNodeIterator (struct ObjNode *curr_node)
2409 if (curr_node->node.mln_Pred->mln_Pred)
2410 return (struct ObjNode*)curr_node->node.mln_Pred;
2411 else
2412 return NULL;
2415 static Object *GetPrevNextActiveObject (struct ObjNode *old_activenode, objnode_iterator_t node_iterator)
2417 struct ObjNode *curr_node;
2418 struct ObjNode *node;
2419 Object *obj;
2421 ASSERT_VALID_PTR(old_activenode);
2423 curr_node = old_activenode;
2424 node = NULL;
2425 obj = NULL;
2427 while (curr_node)
2429 node = node_iterator(curr_node);
2431 if (node)
2432 obj = node->obj;
2434 /* let's see if this obj meets cycle requirements (enabled & visible) */
2435 if (obj)
2437 IPTR is_disabled = 0;
2439 get(obj, MUIA_Disabled, &is_disabled);
2441 if (!is_disabled && (_flags(obj) & MADF_SHOWME))
2443 return obj;
2447 curr_node = node;
2448 obj = NULL;
2449 node = NULL;
2451 return obj;
2455 /**************************************************************************
2456 Code for setting MUIA_Window_ActiveObject
2457 Basically, it will:
2458 - remove focus drawing for current active object
2459 - find (if needed) the new active object
2460 - set data->wd_ActiveObject to the new object
2461 - draw focus around the new active object
2462 **************************************************************************/
2463 static void SetActiveObject (struct MUI_WindowData *data, Object *obj, IPTR newval)
2465 struct ObjNode *old_activenode = NULL;
2467 ASSERT_VALID_PTR(data);
2468 ASSERT_VALID_PTR(obj);
2470 D(bug("MUIC_Window:SetActiveObject(data, obj, %08lx) Active=%p\n",
2471 newval, data->wd_ActiveObject));
2473 if ((data->wd_ActiveObject != NULL)
2474 && (DoMethod(data->wd_RootObject, MUIM_FindAreaObject,
2475 (IPTR)data->wd_ActiveObject) != (IPTR)NULL))
2477 if ((IPTR)data->wd_ActiveObject != newval)
2479 old_activenode = FindObjNode(&data->wd_CycleChain, data->wd_ActiveObject);
2480 //if (_flags(data->wd_ActiveObject) & MADF_CANDRAW)
2481 if (data->wd_Flags & MUIWF_OBJECTGOACTIVESENT)
2483 D(bug("Inactivate=%p\n", data->wd_ActiveObject));
2484 DoMethod(data->wd_ActiveObject, MUIM_GoInactive);
2489 data->wd_ActiveObject = NULL;
2490 data->wd_Flags &= ~MUIWF_OBJECTGOACTIVESENT;
2492 switch (newval)
2494 case MUIV_Window_ActiveObject_None:
2495 break;
2497 case MUIV_Window_ActiveObject_Next:
2498 if (old_activenode != NULL)
2499 data->wd_ActiveObject = GetPrevNextActiveObject(old_activenode,
2500 NextObjNodeIterator);
2501 if (NULL == data->wd_ActiveObject)
2502 data->wd_ActiveObject = GetFirstActiveObject(data);
2503 break;
2505 case MUIV_Window_ActiveObject_Prev:
2506 if (old_activenode)
2507 data->wd_ActiveObject = GetPrevNextActiveObject(old_activenode,
2508 PrevObjNodeIterator);
2509 if (NULL == data->wd_ActiveObject)
2510 data->wd_ActiveObject = GetLastActiveObject(data);
2511 break;
2513 default:
2514 data->wd_ActiveObject = (Object*)newval;
2515 break;
2519 if (data->wd_ActiveObject != NULL
2520 && DoMethod(data->wd_RootObject, MUIM_FindAreaObject,
2521 (IPTR) data->wd_ActiveObject)
2522 && (_flags(data->wd_ActiveObject) & MADF_CANDRAW))
2524 D(bug("Activate=%p\n", data->wd_ActiveObject));
2525 DoMethod(data->wd_ActiveObject, MUIM_GoActive);
2526 data->wd_Flags |= MUIWF_OBJECTGOACTIVESENT;
2532 * calculate real dimensions from programmer requirements.
2533 * may be overridden by user settings if MUIA_Window_ID is set.
2535 /* MUIV_Window_Height_Screen and MUIV_Window_Height_Visible
2536 * are not handled yet, as their Width couterparts.
2538 static void WindowSelectDimensions (struct MUI_WindowData *data)
2540 if (!data->wd_Width)
2542 if (data->wd_ReqWidth > 0)
2543 data->wd_Width = data->wd_ReqWidth;
2544 else if (data->wd_ReqWidth == MUIV_Window_Width_Default)
2545 data->wd_Width = data->wd_MinMax.DefWidth;
2546 else if (_between(MUIV_Window_Width_MinMax(100),
2547 data->wd_ReqWidth,
2548 MUIV_Window_Width_MinMax(0)))
2550 data->wd_Width = data->wd_MinMax.MinWidth
2551 - data->wd_ReqWidth
2552 * (data->wd_MinMax.MaxWidth - data->wd_MinMax.MinWidth);
2554 else if (_between(MUIV_Window_Width_Screen(100),
2555 data->wd_ReqWidth,
2556 MUIV_Window_Width_Screen(0)))
2558 data->wd_Width = data->wd_RenderInfo.mri_ScreenWidth
2559 * (- (data->wd_ReqWidth + 200)) / 100;
2561 else if (_between(MUIV_Window_Width_Visible(100),
2562 data->wd_ReqWidth,
2563 MUIV_Window_Width_Visible(0)))
2565 data->wd_Width = data->wd_RenderInfo.mri_ScreenWidth
2566 * (- (data->wd_ReqWidth + 100)) / 100;
2569 if (data->wd_ReqHeight > 0)
2570 data->wd_Height = data->wd_ReqHeight;
2571 else if (data->wd_ReqHeight == MUIV_Window_Height_Default)
2572 data->wd_Height = data->wd_MinMax.DefHeight;
2573 else if (_between(MUIV_Window_Height_MinMax(100),
2574 data->wd_ReqHeight,
2575 MUIV_Window_Height_MinMax(0)))
2577 data->wd_Height = data->wd_MinMax.MinHeight
2578 - data->wd_ReqHeight
2579 * (data->wd_MinMax.MaxHeight - data->wd_MinMax.MinHeight);
2581 else if (_between(MUIV_Window_Height_Screen(100),
2582 data->wd_ReqHeight,
2583 MUIV_Window_Height_Screen(0)))
2585 struct Screen *scr;
2586 int height;
2588 scr = data->wd_RenderInfo.mri_Screen;
2590 height = scr->Height - data->wd_RenderInfo.mri_BorderTop - data->wd_RenderInfo.mri_BorderBottom;
2592 /* This is new to Zune: If TopEdge Delta is requested
2593 * the screenheight doesn't cover the barlayer */
2594 if (data->wd_Y <= MUIV_Window_TopEdge_Delta(0))
2595 height -= scr->BarHeight + 1;
2597 data->wd_Height = height * (- (data->wd_ReqHeight + 200)) / 100;
2599 else if (_between(MUIV_Window_Height_Visible(100),
2600 data->wd_ReqHeight,
2601 MUIV_Window_Height_Visible(0)))
2603 data->wd_Height = data->wd_RenderInfo.mri_ScreenHeight
2604 * (- (data->wd_ReqHeight + 100)) / 100;
2607 /* scaled */
2608 if (data->wd_ReqWidth == MUIV_Window_Width_Scaled)
2609 data->wd_Width = data->wd_Height * data->wd_MinMax.MinWidth
2610 / data->wd_MinMax.MinHeight;
2611 else if (data->wd_ReqHeight == MUIV_Window_Width_Scaled)
2612 data->wd_Height = data->wd_Width * data->wd_MinMax.MinHeight
2613 / data->wd_MinMax.MinWidth;
2615 data->wd_Width = CLAMP(data->wd_Width, data->wd_MinMax.MinWidth,
2616 data->wd_MinMax.MaxWidth);
2617 data->wd_Height = CLAMP(data->wd_Height, data->wd_MinMax.MinHeight,
2618 data->wd_MinMax.MaxHeight);
2622 /**************************************************************************
2623 OM_NEW
2624 **************************************************************************/
2625 IPTR Window__OM_NEW(struct IClass *cl, Object *obj, struct opSet *msg)
2627 struct MUI_WindowData *data;
2628 struct TagItem *tags;
2629 struct TagItem *tag;
2631 obj = (Object *)DoSuperMethodA(cl, obj, (Msg)msg);
2632 if (!obj)
2633 return FALSE;
2635 /* Initial local instance data */
2636 data = INST_DATA(cl, obj);
2638 data->wd_MemoryPool = CreatePool(0, 4096, 2048);
2639 if (NULL == data->wd_MemoryPool)
2641 CoerceMethod(cl, obj, OM_DISPOSE);
2642 return (IPTR)NULL;
2645 data->wd_RenderInfo.mri_WindowObject = obj;
2647 NewList((struct List*)&(data->wd_EHList));
2648 NewList((struct List*)&(data->wd_CCList));
2649 NewList((struct List*)&(data->wd_CycleChain));
2650 NewList((struct List*)&(data->wd_IDList));
2652 data->wd_CrtFlags = WFLG_SIZEGADGET | WFLG_DRAGBAR | WFLG_DEPTHGADGET
2653 | WFLG_CLOSEGADGET | WFLG_SIMPLE_REFRESH
2654 | WFLG_REPORTMOUSE | WFLG_NEWLOOKMENUS;
2655 data->wd_ZoomGadget = TRUE;
2656 data->wd_Events = GetDefaultEvents();
2657 data->wd_ActiveObject = NULL;
2658 data->wd_ID = 0;
2659 data->wd_ReqHeight = MUIV_Window_Height_Default;
2660 data->wd_ReqWidth = MUIV_Window_Width_Default;
2661 data->wd_RootObject = NULL;
2662 data->wd_DefaultObject = NULL;
2664 /* alternate dimensions */
2665 /* no change in coordinates */
2667 // otigreat 02/10/2011 Commented out as this forbids
2668 // MUI-windows to behave like other windows when zoomed
2669 data->wd_AltDim.Top = MUIV_Window_AltTopEdge_NoChange;
2670 data->wd_AltDim.Left = MUIV_Window_AltLeftEdge_NoChange;
2672 /* default to min size */
2673 data->wd_AltDim.Width = MUIV_Window_AltWidth_MinMax(0);
2674 data->wd_AltDim.Height = MUIV_Window_AltHeight_MinMax(0);
2675 data->wd_X = MUIV_Window_LeftEdge_Centered;
2676 data->wd_Y = MUIV_Window_TopEdge_Centered;
2677 data->wd_DisabledKeys = 0L;
2678 data->wd_HelpTicker = BUBBLEHELP_TICKER_FIRST;
2680 /* parse initial taglist */
2682 for (tags = msg->ops_AttrList; (tag = NextTagItem(&tags)); )
2684 switch (tag->ti_Tag)
2686 case MUIA_Window_EraseArea:
2687 _handle_bool_tag(data->wd_Flags, tag->ti_Data, MUIWF_ERASEAREA);
2688 break;
2690 case MUIA_Window_ToolBox:
2691 _handle_bool_tag(data->wd_Flags, tag->ti_Data, MUIWF_TOOLBOX);
2692 break;
2694 case MUIA_Window_CloseGadget:
2695 _handle_bool_tag(data->wd_CrtFlags, tag->ti_Data, WFLG_CLOSEGADGET);
2696 break;
2698 case MUIA_Window_SizeGadget:
2699 _handle_bool_tag(data->wd_CrtFlags, tag->ti_Data, WFLG_SIZEGADGET);
2700 break;
2702 case MUIA_Window_ZoomGadget:
2703 data->wd_ZoomGadget = tag->ti_Data;
2704 break;
2706 case MUIA_Window_Backdrop:
2707 _handle_bool_tag(data->wd_CrtFlags, tag->ti_Data, WFLG_BACKDROP);
2708 break;
2710 case MUIA_Window_Borderless:
2711 _handle_bool_tag(data->wd_CrtFlags, tag->ti_Data, WFLG_BORDERLESS);
2712 break;
2714 case MUIA_Window_DepthGadget:
2715 _handle_bool_tag(data->wd_CrtFlags, tag->ti_Data, WFLG_DEPTHGADGET);
2716 break;
2718 case MUIA_Window_DragBar:
2719 _handle_bool_tag(data->wd_CrtFlags, tag->ti_Data, WFLG_DRAGBAR);
2720 break;
2722 case MUIA_Window_SizeRight:
2723 _handle_bool_tag(data->wd_CrtFlags, tag->ti_Data, WFLG_SIZEBRIGHT);
2724 break;
2726 case MUIA_Window_Height:
2727 data->wd_ReqHeight = (LONG)tag->ti_Data;
2728 break;
2730 case MUIA_Window_Width:
2731 data->wd_ReqWidth = (LONG)tag->ti_Data;
2732 break;
2734 case MUIA_Window_ID:
2735 set(obj, MUIA_Window_ID, tag->ti_Data);
2736 break;
2738 case MUIA_Window_IsSubWindow:
2739 _handle_bool_tag(data->wd_Flags, tag->ti_Data, MUIWF_ISSUBWINDOW);
2740 break;
2742 case MUIA_Window_Title:
2743 set(obj, MUIA_Window_Title, tag->ti_Data);
2744 break;
2746 case MUIA_Window_ScreenTitle:
2747 set(obj, MUIA_Window_ScreenTitle, tag->ti_Data);
2748 break;
2750 case MUIA_Window_Activate:
2751 _handle_bool_tag(data->wd_Flags, !tag->ti_Data, MUIWF_DONTACTIVATE);
2752 break;
2754 case MUIA_Window_DefaultObject:
2755 set(obj, MUIA_Window_DefaultObject, tag->ti_Data);
2756 break;
2758 case MUIA_Window_Menustrip:
2759 data->wd_ChildMenustrip = (Object*)tag->ti_Data;
2760 break;
2762 case MUIA_Window_NoMenus:
2763 data->wd_NoMenus = (BOOL) tag->ti_Data;
2764 break;
2766 case MUIA_Window_RootObject:
2767 if (!tag->ti_Data)
2769 CoerceMethod(cl, obj, OM_DISPOSE);
2770 return 0;
2772 set(obj, MUIA_Window_RootObject, tag->ti_Data);
2773 break;
2775 case MUIA_Window_AltHeight:
2776 data->wd_AltDim.Height = (WORD)tag->ti_Data;
2777 break;
2779 case MUIA_Window_AltWidth:
2780 data->wd_AltDim.Width = (WORD)tag->ti_Data;
2781 break;
2783 case MUIA_Window_AltLeftEdge:
2784 data->wd_AltDim.Left = (WORD)tag->ti_Data;
2785 break;
2787 case MUIA_Window_AltTopEdge:
2788 data->wd_AltDim.Top = (WORD)tag->ti_Data;
2789 break;
2791 case MUIA_Window_AppWindow:
2792 _handle_bool_tag(data->wd_Flags, tag->ti_Data, MUIWF_ISAPPWINDOW);
2793 break;
2795 case MUIA_Window_LeftEdge:
2796 data->wd_X = tag->ti_Data;
2797 break;
2799 case MUIA_Window_TopEdge:
2800 data->wd_Y = tag->ti_Data;
2801 break;
2803 case MUIA_Window_UseBottomBorderScroller:
2804 _handle_bool_tag(data->wd_Flags, tag->ti_Data, MUIWF_USEBOTTOMSCROLLER);
2805 break;
2807 case MUIA_Window_UseRightBorderScroller:
2808 _handle_bool_tag(data->wd_Flags, tag->ti_Data, MUIWF_USERIGHTSCROLLER);
2809 break;
2811 case MUIA_Window_DisableKeys:
2812 data->wd_DisabledKeys = tag->ti_Data;
2813 break;
2815 case MUIA_Window_RefWindow:
2816 data->wd_RefWindow = (Object *)tag->ti_Data;
2817 break;
2819 case MUIA_Window_Screen:
2820 data->wd_UserScreen = (struct Screen *)tag->ti_Data;
2821 break;
2823 case MUIA_Window_PublicScreen:
2824 data->wd_UserPublicScreen = (STRPTR)tag->ti_Data;
2825 break;
2829 /* D(bug("muimaster.library/window.c: Window Object created at 0x%lx back=%lx\n", */
2830 /* obj,data->wd_Background)); */
2832 return (IPTR)obj;
2835 /**************************************************************************
2836 OM_DISPOSE
2837 **************************************************************************/
2838 IPTR Window__OM_DISPOSE(struct IClass *cl, Object *obj, Msg msg)
2840 struct MUI_WindowData *data = INST_DATA(cl, obj);
2842 /* D(bug("Window_Dispose(%p)\n", obj)); */
2844 #if 0 /* We no longer clear muiGlobalInfo() during disconnections, so
2845 this can cause problems (remove object which is already removed).
2846 Furthermore AFAIK it is not legal to dispose a window object
2847 which is still ocnnected to the application object, anyway. */
2849 if (muiGlobalInfo(obj) && _app(obj))
2851 /* D(bug(" Window_Dispose(%p) : calling app->OM_REMMEMBER\n", obj)); */
2852 DoMethod(_app(obj), OM_REMMEMBER, (IPTR)obj);
2854 #endif
2856 if (data->wd_RootObject)
2857 MUI_DisposeObject(data->wd_RootObject);
2859 if (data->wd_ChildMenustrip)
2860 MUI_DisposeObject(data->wd_ChildMenustrip);
2862 if (data->wd_Title)
2863 FreeVec(data->wd_Title);
2865 if (data->wd_ScreenTitle)
2866 FreeVec(data->wd_ScreenTitle);
2868 DeletePool(data->wd_MemoryPool);
2870 /* D(bug(" Window_Dispose(%p) : calling supermethod\n", obj)); */
2871 return DoSuperMethodA(cl, obj, msg);
2874 static ULONG WindowOpen(struct IClass *cl, Object *obj);
2875 static ULONG WindowClose(struct IClass *cl, Object *obj);
2877 /**************************************************************************
2878 OM_SET
2879 **************************************************************************/
2880 IPTR Window__OM_SET(struct IClass *cl, Object *obj, struct opSet *msg)
2882 struct MUI_WindowData *data = INST_DATA(cl, obj);
2883 struct TagItem *tags = msg->ops_AttrList;
2884 struct TagItem *tag;
2886 while ((tag = NextTagItem(&tags)) != NULL)
2888 switch (tag->ti_Tag)
2890 case MUIA_Window_Activate:
2891 if (data->wd_RenderInfo.mri_Window)
2893 if (tag->ti_Data && !(data->wd_Flags & MUIWF_ACTIVE))
2895 ActivateWindow(data->wd_RenderInfo.mri_Window);
2896 _handle_bool_tag(data->wd_Flags, tag->ti_Data, MUIWF_ACTIVE);
2899 else
2900 _handle_bool_tag(data->wd_Flags, !tag->ti_Data, MUIWF_DONTACTIVATE);
2901 break;
2903 case MUIA_Window_ActiveObject:
2904 /* D(bug("MUIA_Window_ActiveObject %ld (%p)\n", tag->ti_Data, tag->ti_Data)); */
2905 SetActiveObject(data, obj, tag->ti_Data);
2906 break;
2908 case MUIA_Window_DefaultObject:
2909 data->wd_DefaultObject = (APTR)tag->ti_Data;
2910 break;
2912 case MUIA_Window_ID:
2913 data->wd_ID = tag->ti_Data;
2914 break;
2916 case MUIA_Window_IsSubWindow:
2917 _handle_bool_tag(data->wd_Flags, tag->ti_Data, MUIWF_ISSUBWINDOW);
2918 break;
2920 case MUIA_Window_Open:
2921 if (tag->ti_Data)
2923 if (data->wd_Flags & MUIWF_HIDDEN)
2924 data->wd_Flags |= MUIWF_OPENONUNHIDE;
2925 else
2926 if (!(data->wd_Flags & MUIWF_OPENED))
2927 WindowOpen(cl, obj);
2928 else
2930 DoMethod(obj, MUIM_Window_ToFront);
2931 set(obj, MUIA_Window_Activate, TRUE);
2934 else
2935 if (data->wd_Flags & MUIWF_HIDDEN)
2936 data->wd_Flags &= ~MUIWF_OPENONUNHIDE;
2937 else
2938 if (data->wd_Flags & MUIWF_OPENED)
2939 WindowClose(cl, obj);
2940 break;
2942 case MUIA_ShowMe: /* PRIVATE *abuse* of the Area's ShowMe attr */
2943 if (tag->ti_Data)
2945 /* Deiconify */
2947 if (data->wd_Flags & MUIWF_HIDDEN)
2949 data->wd_Flags &= ~MUIWF_HIDDEN;
2951 if (data->wd_Flags & MUIWF_OPENONUNHIDE)
2953 data->wd_Flags &= ~MUIWF_OPENONUNHIDE;
2954 set(obj, MUIA_Window_Open, TRUE);
2958 else
2960 /* Iconify */
2962 if (data->wd_Flags & MUIWF_OPENED)
2964 data->wd_Flags |= MUIWF_OPENONUNHIDE;
2966 set(obj, MUIA_Window_Open, FALSE);
2969 data->wd_Flags |= MUIWF_HIDDEN;
2971 break;
2973 case MUIA_Window_RootObject:
2974 ChangeRootObject(data, obj, (Object *)tag->ti_Data);
2975 break;
2977 case MUIA_Window_Title:
2978 if (data->wd_Title)
2979 FreeVec(data->wd_Title);
2980 data->wd_Title = StrDup((STRPTR)tag->ti_Data);
2981 if (data->wd_RenderInfo.mri_Window)
2982 SetWindowTitles(data->wd_RenderInfo.mri_Window,data->wd_Title, (CONST_STRPTR)~0);
2983 break;
2985 case MUIA_Window_ScreenTitle:
2986 if (data->wd_ScreenTitle)
2987 FreeVec(data->wd_ScreenTitle);
2988 data->wd_ScreenTitle = StrDup((STRPTR)tag->ti_Data);
2989 if (data->wd_RenderInfo.mri_Window)
2990 SetWindowTitles(data->wd_RenderInfo.mri_Window,
2991 (CONST_STRPTR)~0, data->wd_ScreenTitle);
2992 break;
2994 case MUIA_Window_NoMenus:
2995 data->wd_NoMenus = (BOOL) tag->ti_Data;
2996 if (data->wd_RenderInfo.mri_Window)
2998 if (data->wd_NoMenus)
2999 data->wd_RenderInfo.mri_Window->Flags |= WFLG_RMBTRAP;
3000 else
3001 data->wd_RenderInfo.mri_Window->Flags &= ~WFLG_RMBTRAP;
3003 break;
3005 case MUIA_Window_UseBottomBorderScroller:
3006 _handle_bool_tag(data->wd_Flags, tag->ti_Data, MUIWF_USEBOTTOMSCROLLER);
3007 break;
3009 case MUIA_Window_UseRightBorderScroller:
3010 _handle_bool_tag(data->wd_Flags, tag->ti_Data, MUIWF_USERIGHTSCROLLER);
3011 break;
3013 case MUIA_Window_DisableKeys:
3014 data->wd_DisabledKeys = tag->ti_Data;
3015 break;
3017 case MUIA_Window_RefWindow:
3018 data->wd_RefWindow = (Object *)tag->ti_Data;
3019 break;
3021 case MUIA_Window_LeftEdge:
3022 data->wd_X = tag->ti_Data;
3023 break;
3025 case MUIA_Window_TopEdge:
3026 data->wd_Y = tag->ti_Data;
3027 break;
3029 case MUIA_Window_Width:
3030 data->wd_ReqWidth = (LONG)tag->ti_Data;
3031 data->wd_Width = 0; /* otherwise windowselectdimensions() ignores ReqWidth */
3032 break;
3034 case MUIA_Window_Height:
3035 data->wd_ReqHeight = (LONG)tag->ti_Data;
3036 data->wd_Height = 0;
3037 break;
3039 case MUIA_Window_Screen:
3040 data->wd_UserScreen = (struct Screen *)tag->ti_Data;
3041 break;
3043 case MUIA_Window_PublicScreen:
3044 data->wd_UserPublicScreen = (STRPTR)tag->ti_Data;
3045 break;
3047 case MUIA_Window_Sleep:
3048 if (tag->ti_Data)
3050 data->wd_SleepCount++;
3051 if (data->wd_RenderInfo.mri_Window && (data->wd_SleepCount == 1))
3053 SetWindowPointer
3055 data->wd_RenderInfo.mri_Window,
3056 WA_BusyPointer, TRUE,
3057 WA_PointerDelay, TRUE,
3058 TAG_DONE
3060 // FIXME: how to disable event handling?
3063 else
3065 data->wd_SleepCount--;
3066 if (data->wd_RenderInfo.mri_Window && (data->wd_SleepCount == 0))
3068 SetWindowPointerA(data->wd_RenderInfo.mri_Window, NULL);
3071 break;
3076 return DoSuperMethodA(cl, obj, (Msg)msg);
3079 /**************************************************************************
3080 OM_GET
3081 **************************************************************************/
3082 IPTR Window__OM_GET(struct IClass *cl, Object *obj, struct opGet *msg)
3084 #define STORE *(msg->opg_Storage)
3086 struct MUI_WindowData *data = INST_DATA(cl, obj);
3088 STORE = (IPTR)0;
3090 switch(msg->opg_AttrID)
3092 case MUIA_Window_Activate:
3093 STORE = (data->wd_Flags & (MUIWF_ACTIVE | MUIWF_OPENED)) == (MUIWF_ACTIVE | MUIWF_OPENED);
3094 return TRUE ;
3096 case MUIA_Window_Window:
3097 STORE = (IPTR)data->wd_RenderInfo.mri_Window;
3098 return TRUE;
3100 case MUIA_Window_Screen:
3101 STORE = (IPTR)data->wd_RenderInfo.mri_Screen;
3102 return TRUE;
3104 case MUIA_Window_PublicScreen:
3105 STORE = (IPTR)data->wd_UserPublicScreen;
3106 return TRUE;
3108 case MUIA_Window_ActiveObject:
3109 if ((data->wd_ActiveObject != NULL)
3110 && (DoMethod(data->wd_RootObject, MUIM_FindAreaObject,
3111 (IPTR)data->wd_ActiveObject) != (IPTR)NULL))
3112 STORE = (IPTR)data->wd_ActiveObject;
3113 else
3114 STORE = (IPTR)NULL;
3115 return TRUE;
3117 case MUIA_Window_CloseRequest:
3118 STORE = FALSE;
3119 return TRUE;
3121 case MUIA_Window_DefaultObject:
3122 STORE = (IPTR)data->wd_DefaultObject;
3123 return TRUE;
3125 case MUIA_Window_DisableKeys:
3126 STORE = data->wd_DisabledKeys;
3127 return TRUE;
3129 case MUIA_Window_Height:
3130 STORE = (IPTR)data->wd_Height;
3131 return TRUE;
3133 case MUIA_Window_ID:
3134 STORE = data->wd_ID;
3135 return TRUE;
3137 case MUIA_Window_IsSubWindow:
3138 STORE = (data->wd_Flags & MUIWF_ISSUBWINDOW) == MUIWF_ISSUBWINDOW;
3139 return TRUE;
3141 case MUIA_Window_LeftEdge:
3142 if (data->wd_RenderInfo.mri_Window)
3143 STORE = (IPTR)data->wd_RenderInfo.mri_Window->LeftEdge;
3144 else
3145 STORE = 0;
3146 return TRUE;
3148 case MUIA_Window_Open:
3149 STORE = (data->wd_Flags & MUIWF_OPENED) == MUIWF_OPENED;
3150 return TRUE;
3152 case MUIA_Window_RootObject:
3153 STORE = (IPTR)data->wd_RootObject;
3154 return TRUE;
3156 case MUIA_Window_ScreenTitle:
3157 STORE = (IPTR)data->wd_ScreenTitle;
3158 return TRUE;
3160 case MUIA_Window_Title:
3161 STORE = (IPTR)data->wd_Title;
3162 return TRUE;
3164 case MUIA_Window_TopEdge:
3165 if (data->wd_RenderInfo.mri_Window)
3166 STORE = (IPTR)data->wd_RenderInfo.mri_Window->TopEdge;
3167 else
3168 STORE = (IPTR)0;
3169 return(TRUE);
3171 case MUIA_Window_Width:
3172 STORE = (IPTR)data->wd_Width;
3173 return TRUE;
3175 case MUIA_Window_Menustrip:
3176 STORE = (IPTR)data->wd_ChildMenustrip;
3177 return TRUE;
3179 case MUIA_Window_Sleep:
3180 STORE = data->wd_SleepCount ? TRUE : FALSE;
3181 return TRUE;
3183 case MUIA_Version:
3184 STORE = __version;
3185 return TRUE;
3187 case MUIA_Revision:
3188 STORE = __revision;
3189 return TRUE;
3192 return DoSuperMethodA(cl, obj, (Msg) msg);
3193 #undef STORE
3197 * MUIM_FindUData : tests if the MUIA_UserData of the object
3198 * contains the given <udata> and returns the object pointer in this case.
3200 IPTR Window__MUIM_FindUData(struct IClass *cl, Object *obj, struct MUIP_FindUData *msg)
3202 struct MUI_WindowData *data = INST_DATA(cl, obj);
3204 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
3205 return (IPTR)obj;
3207 if (data->wd_RootObject)
3208 return DoMethodA(data->wd_RootObject, (Msg)msg);
3210 return 0;
3215 * MUIM_GetUData : This method tests if the MUIA_UserData of the object
3216 * contains the given <udata> and gets <attr> to <storage> for itself
3217 * in this case.
3219 IPTR Window__MUIM_GetUData(struct IClass *cl, Object *obj, struct MUIP_GetUData *msg)
3221 struct MUI_WindowData *data = INST_DATA(cl, obj);
3223 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
3225 get(obj, msg->attr, msg->storage);
3226 return TRUE;
3229 if (data->wd_RootObject)
3230 return DoMethodA(data->wd_RootObject, (Msg)msg);
3232 return FALSE;
3237 * MUIM_SetUData : This method tests if the MUIA_UserData of the object
3238 * contains the given <udata> and sets <attr> to <val> for itself in this case.
3240 IPTR Window__MUIM_SetUData(struct IClass *cl, Object *obj, struct MUIP_SetUData *msg)
3242 struct MUI_WindowData *data = INST_DATA(cl, obj);
3244 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
3245 set(obj, msg->attr, msg->val);
3247 if (data->wd_RootObject)
3248 DoMethodA(data->wd_RootObject, (Msg)msg);
3250 return TRUE;
3255 * MUIM_SetUDataOnce : This method tests if the MUIA_UserData of the object
3256 * contains the given <udata> and sets <attr> to <val> for itself in this case.
3258 IPTR Window__MUIM_SetUDataOnce(struct IClass *cl, Object *obj, struct MUIP_SetUDataOnce *msg)
3260 struct MUI_WindowData *data = INST_DATA(cl, obj);
3262 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
3264 set(obj, msg->attr, msg->val);
3265 return TRUE;
3268 if (data->wd_RootObject)
3269 return DoMethodA(data->wd_RootObject, (Msg)msg);
3271 return FALSE;
3274 /**************************************************************************
3275 Called by Application (parent) object whenever this object is added.
3276 init GlobalInfo
3277 **************************************************************************/
3278 IPTR Window__MUIM_ConnectParent(struct IClass *cl, Object *obj,
3279 struct MUIP_ConnectParent *msg)
3281 struct MUI_WindowData *data = INST_DATA(cl, obj);
3283 if (!DoSuperMethodA(cl,obj,(Msg)msg))
3284 return 0;
3286 if (data->wd_RootObject)
3287 DoMethod(data->wd_RootObject, MUIM_ConnectParent, (IPTR)obj);
3289 if (data->wd_ChildMenustrip)
3290 DoMethod(data->wd_ChildMenustrip, MUIM_ConnectParent, (IPTR)obj);
3292 return TRUE;
3296 /**************************************************************************
3297 called by parent object
3298 **************************************************************************/
3299 IPTR Window__MUIM_DisconnectParent(struct IClass *cl, Object *obj, struct MUIP_DisconnectParent *msg)
3301 struct MUI_WindowData *data = INST_DATA(cl, obj);
3303 /* D(bug("Window_DisconnectParent(%p) : muiGlobalInfo=%p\n", muiGlobalInfo(obj))); */
3304 if (muiGlobalInfo(obj))
3306 /* Close the window before disconnecting all the childs */
3307 if ((data->wd_Flags & MUIWF_OPENED))
3309 /* D(bug(" Window_DisconnectParent(%p) : closing window\n", muiGlobalInfo(obj))); */
3310 set(obj, MUIA_Window_Open, FALSE);
3312 if (data->wd_ChildMenustrip)
3313 DoMethod(data->wd_ChildMenustrip, MUIM_DisconnectParent, (IPTR)obj);
3315 if (data->wd_RootObject)
3316 DoMethodA(data->wd_RootObject, (Msg)msg);
3318 /* D(bug(" Window_DisconnectParent(%p) : calling supermethod\n", muiGlobalInfo(obj))); */
3319 return DoSuperMethodA(cl,obj,(Msg)msg);
3321 else
3323 return 0;
3327 static void SetRootObjInnerSpacing(Object *obj, struct MUI_WindowData *data)
3329 UWORD wd_innerLeft, wd_innerRight, wd_innerTop, wd_innerBottom;
3331 if (data->wd_CrtFlags & WFLG_BORDERLESS)
3333 wd_innerLeft = 0;
3334 wd_innerRight = 0;
3335 wd_innerTop = 0;
3336 wd_innerBottom = 0;
3338 else
3340 wd_innerLeft = muiGlobalInfo(obj)->mgi_Prefs->window_inner_left;
3341 wd_innerRight = muiGlobalInfo(obj)->mgi_Prefs->window_inner_right;
3342 wd_innerTop = muiGlobalInfo(obj)->mgi_Prefs->window_inner_top;
3343 wd_innerBottom = muiGlobalInfo(obj)->mgi_Prefs->window_inner_bottom;
3346 if (!(muiAreaData(data->wd_RootObject)->mad_Flags & MADF_INNERLEFT))
3348 muiAreaData(data->wd_RootObject)->mad_InnerLeft = wd_innerLeft;
3351 if (!(muiAreaData(data->wd_RootObject)->mad_Flags & MADF_INNERTOP))
3353 muiAreaData(data->wd_RootObject)->mad_InnerTop = wd_innerTop;
3356 if (!(muiAreaData(data->wd_RootObject)->mad_Flags & MADF_INNERRIGHT))
3358 muiAreaData(data->wd_RootObject)->mad_InnerRight = wd_innerRight;
3361 if (!(muiAreaData(data->wd_RootObject)->mad_Flags & MADF_INNERBOTTOM))
3363 muiAreaData(data->wd_RootObject)->mad_InnerBottom = wd_innerBottom;
3368 * Called before window is opened or resized. It determines its bounds,
3369 * so you can call WindowSelectDimensions() to find the final dims.
3371 static void WindowMinMax(Object *obj, struct MUI_WindowData *data)
3373 SetRootObjInnerSpacing(obj, data);
3374 /* inquire about sizes */
3375 DoMethod(data->wd_RootObject, MUIM_AskMinMax, (IPTR)&data->wd_MinMax);
3376 /* D(bug("*** root minmax = %ld,%ld => %ld,%ld\n", data->wd_MinMax.MinWidth, */
3377 /* data->wd_MinMax.MinHeight, */
3378 /* data->wd_MinMax.MaxWidth, data->wd_MinMax.MaxHeight)); */
3379 __area_finish_minmax(data->wd_RootObject, &data->wd_MinMax);
3380 /* D(bug("*** root minmax2 = %ld,%ld => %ld,%ld\n", data->wd_MinMax.MinWidth, */
3381 /* data->wd_MinMax.MinHeight, */
3382 /* data->wd_MinMax.MaxWidth, data->wd_MinMax.MaxHeight)); */
3386 static void InstallBackbuffer (struct IClass *cl, Object *obj)
3388 struct MUI_WindowData *data = INST_DATA(cl, obj);
3389 #if 0
3390 struct Window *win = data->wd_RenderInfo.mri_Window;
3392 data->wd_RenderInfo.mri_BufferBM =
3393 AllocBitMap(win->Width, win->Height, win->RPort->BitMap->Depth,
3394 0, win->RPort->BitMap);
3395 #endif
3396 if (data->wd_RenderInfo.mri_BufferBM)
3398 /* D(bug("install_backbuffer : allocated bitmap %dx%dx%d with friend %p\n", */
3399 /* win->Width, win->Height, win->RPort->BitMap->Depth, win->RPort->BitMap)); */
3400 InitRastPort(&data->wd_RenderInfo.mri_BufferRP);
3401 data->wd_RenderInfo.mri_BufferRP.BitMap = data->wd_RenderInfo.mri_BufferBM;
3405 static void DeinstallBackbuffer (struct IClass *cl, Object *obj)
3407 struct MUI_WindowData *data = INST_DATA(cl, obj);
3409 if (data->wd_RenderInfo.mri_BufferBM)
3411 DeinitRastPort(&data->wd_RenderInfo.mri_BufferRP);
3412 FreeBitMap(data->wd_RenderInfo.mri_BufferBM);
3413 data->wd_RenderInfo.mri_BufferBM = NULL;
3418 * Called after window is opened or resized.
3419 * An expose event is already queued, it will trigger
3420 * MUIM_Draw for us when going back to main loop.
3422 static void WindowShow (struct IClass *cl, Object *obj)
3424 struct MUI_WindowData *data = INST_DATA(cl, obj);
3425 struct Window *win = data->wd_RenderInfo.mri_Window;
3426 /* D(bug("window_show %s %d\n", __FILE__, __LINE__)); */
3428 _left(data->wd_RootObject) = win->BorderLeft;
3429 _top(data->wd_RootObject) = win->BorderTop;
3430 _width(data->wd_RootObject) = data->wd_Width;
3431 _height(data->wd_RootObject) = data->wd_Height;
3433 DoMethod(data->wd_RootObject, MUIM_Layout);
3435 ShowRenderInfo(&data->wd_RenderInfo);
3436 /* D(bug("zune_imspec_show %s %d\n", __FILE__, __LINE__)); */
3437 zune_imspec_show(data->wd_Background, obj);
3438 DoShowMethod(data->wd_RootObject);
3441 static ULONG WindowOpen(struct IClass *cl, Object *obj)
3443 struct MUI_WindowData *data = INST_DATA(cl, obj);
3445 if (!data->wd_RootObject)
3446 return FALSE;
3448 if (!DoMethod(obj, MUIM_Window_Setup))
3449 return FALSE;
3451 /* I got display info, so calculate your display dependant data */
3452 if (!DoSetupMethod(data->wd_RootObject, &data->wd_RenderInfo))
3454 DoMethod(obj, MUIM_Window_Cleanup);
3455 return FALSE;
3458 /* inquire about sizes */
3459 WindowMinMax(obj,data);
3460 WindowSelectDimensions(data);
3462 /* Decide which menustrip should be used */
3463 if (!data->wd_ChildMenustrip)
3464 get(_app(obj), MUIA_Application_Menustrip, &data->wd_Menustrip);
3465 else
3466 data->wd_Menustrip = data->wd_ChildMenustrip;
3468 /* open window here ... */
3469 if (!DisplayWindow(obj,data))
3471 /* free display dependant data */
3472 data->wd_Menustrip = NULL;
3473 DoMethod(data->wd_RootObject, MUIM_Cleanup);
3474 DoMethod(obj, MUIM_Window_Cleanup);
3475 return FALSE;
3478 InstallBackbuffer(cl, obj);
3480 data->wd_Flags |= MUIWF_OPENED;
3482 WindowShow(cl, obj);
3485 LONG left,top,width,height;
3487 left = data->wd_RenderInfo.mri_Window->BorderLeft;
3488 top = data->wd_RenderInfo.mri_Window->BorderTop,
3489 width = data->wd_RenderInfo.mri_Window->Width
3490 - data->wd_RenderInfo.mri_Window->BorderRight - left;
3491 height = data->wd_RenderInfo.mri_Window->Height
3492 - data->wd_RenderInfo.mri_Window->BorderBottom - top;
3494 /* D(bug("zune_imspec_draw %s %d\n", __FILE__, __LINE__)); */
3495 // D(bug("%d:zune_imspec_draw(%p) l=%d t=%d w=%d h=%d xo=%d yo=%d\n",
3496 // __LINE__, data->wd_Background, left, top, width,
3497 // height, left, top));
3499 zune_imspec_draw(data->wd_Background, &data->wd_RenderInfo,
3500 left, top, width, height, left, top, 0);
3503 MUI_Redraw(data->wd_RootObject, MADF_DRAWOBJECT);
3505 D(bug("MUIC_Window:windowOpen() ActiveObject=%p\n", data->wd_ActiveObject));
3506 if (data->wd_OldActive != NULL)
3508 set(obj, MUIA_Window_ActiveObject, data->wd_OldActive);
3511 return TRUE;
3514 /******************************************************************************/
3515 /******************************************************************************/
3517 static ULONG WindowClose(struct IClass *cl, Object *obj)
3519 struct MUI_WindowData *data = INST_DATA(cl, obj);
3521 if (data->wd_ActiveObject != NULL)
3523 data->wd_OldActive = data->wd_ActiveObject;
3524 set(obj, MUIA_Window_ActiveObject, MUIV_Window_ActiveObject_None);
3527 KillHelpBubble(data, obj, BUBBLEHELP_TICKER_FIRST);
3529 /* remove from window */
3530 DoHideMethod(data->wd_RootObject);
3531 zune_imspec_hide(data->wd_Background);
3533 DeinstallBackbuffer(cl, obj);
3535 HideRenderInfo(&data->wd_RenderInfo);
3537 /* close here ... */
3538 UndisplayWindow(obj,data);
3540 data->wd_Flags &= ~MUIWF_OPENED;
3541 data->wd_Menustrip = NULL;
3543 /* free display dependant data */
3544 DoMethod(data->wd_RootObject, MUIM_Cleanup);
3545 DoMethod(obj, MUIM_Window_Cleanup);
3546 return TRUE;
3549 /* calculate a new layout
3550 * see MUIA_ShowMe
3551 * see Group_ExitChange
3552 * see Group_Columns
3553 * see Group_Rows
3555 IPTR Window__MUIM_RecalcDisplay(struct IClass *cl, Object *obj, struct MUIP_Window_RecalcDisplay *msg)
3557 struct MUI_WindowData *data = INST_DATA(cl, obj);
3558 LONG left,top,width,height;
3559 BOOL resized;
3560 Object *current_obj;
3562 if (!(data->wd_Flags & MUIWF_OPENED))
3563 return 0;
3565 current_obj = msg->originator;
3567 // typically originator is a group which has been added/removed a child
3568 // calculate minmax of current obj
3569 // if new minmax can accomodate current obj size, stop
3570 // else try with its parent
3571 // the resulting object will get a new layout
3572 // it currently produces some redundant AskMinMax but allows
3573 // to not always relayout the whole window
3575 D(bug("RecalcDisplay on %p\n", current_obj));
3576 while (current_obj != NULL)
3578 DoMethod(current_obj, MUIM_AskMinMax, (IPTR)&muiAreaData(current_obj)->mad_MinMax);
3579 __area_finish_minmax(current_obj, &muiAreaData(current_obj)->mad_MinMax);
3581 D(bug("size w = %d, h = %d\n", _width(current_obj), _height(current_obj)));
3582 D(bug("new w = %d-%d, h = %d-%d\n", _minwidth(current_obj), _maxwidth(current_obj),
3583 _minheight(current_obj), _maxheight(current_obj)));
3585 if (!_between(_minwidth(current_obj), _width(current_obj), _maxwidth(current_obj))
3586 || !_between(_minheight(current_obj), _height(current_obj), _maxheight(current_obj)))
3588 current_obj = _parent(current_obj);
3589 D(bug("RecalcDisplay, try parent %p\n", current_obj));
3591 else
3593 D(bug("found it\n"));
3594 break;
3598 if (!current_obj)
3599 current_obj = data->wd_RootObject;
3601 WindowMinMax(obj, data);
3602 DoHideMethod(current_obj);
3603 /* resize window ? */
3604 WindowSelectDimensions(data);
3605 resized = WindowResize(data);
3607 if (!resized) {
3608 /* FIXME: Should we short circuit the following
3609 * if the window size didn't change?
3614 struct Window *win = data->wd_RenderInfo.mri_Window;
3615 _left(data->wd_RootObject) = win->BorderLeft;
3616 _top(data->wd_RootObject) = win->BorderTop;
3617 _width(data->wd_RootObject) = data->wd_Width;
3618 _height(data->wd_RootObject) = data->wd_Height;
3620 DoMethod(current_obj, MUIM_Layout);
3621 DoShowMethod(current_obj);
3623 if (muiGlobalInfo(obj)->mgi_Prefs->window_redraw == WINDOW_REDRAW_WITHOUT_CLEAR)
3624 MUI_Redraw(current_obj, MADF_DRAWOBJECT);
3625 else
3627 left = data->wd_RenderInfo.mri_Window->BorderLeft;
3628 top = data->wd_RenderInfo.mri_Window->BorderTop;
3629 width = data->wd_RenderInfo.mri_Window->Width
3630 - data->wd_RenderInfo.mri_Window->BorderRight - left;
3631 height = data->wd_RenderInfo.mri_Window->Height
3632 - data->wd_RenderInfo.mri_Window->BorderBottom - top;
3634 zune_imspec_draw(data->wd_Background, &data->wd_RenderInfo,
3635 left, top, width, height, left, top, 0);
3636 MUI_Redraw(data->wd_RootObject, MADF_DRAWALL);
3639 ActivateObject(data);
3641 return TRUE;
3645 /**************************************************************************
3646 MUIM_AddEventHandler
3647 **************************************************************************/
3648 IPTR Window__MUIM_AddEventHandler(struct IClass *cl, Object *obj,
3649 struct MUIP_Window_AddEventHandler *msg)
3651 struct MUI_WindowData *data = INST_DATA(cl, obj);
3653 //D(bug("muimaster.library/window.c: Add Eventhandler %p\n", msg->ehnode));
3655 msg->ehnode->ehn_Priority = msg->ehnode->ehn_Priority;
3656 EnqueueByPriAndAddress((struct List *)&data->wd_EHList, (struct Node *)msg->ehnode);
3657 ChangeEvents(data, GetDefaultEvents());
3658 return TRUE;
3661 /**************************************************************************
3662 MUIM_RemEventHandler
3663 **************************************************************************/
3664 IPTR Window__MUIM_RemEventHandler(struct IClass *cl, Object *obj,
3665 struct MUIP_Window_RemEventHandler *msg)
3667 struct MUI_WindowData *data = INST_DATA(cl, obj);
3669 //D(bug("muimaster.library/window.c: Rem Eventhandler %p\n", msg->ehnode));
3671 Remove((struct Node *)msg->ehnode);
3672 ChangeEvents(data, GetDefaultEvents());
3673 return TRUE;
3676 /**************************************************************************
3677 Note that this is MUIM_Window_Setup, not MUIM_Setup
3678 **************************************************************************/
3679 IPTR Window__MUIM_Setup(struct IClass *cl, Object *obj, Msg msg)
3681 struct MUI_WindowData *data = INST_DATA(cl, obj);
3683 if (!SetupRenderInfo(obj, data, &data->wd_RenderInfo))
3684 return FALSE;
3686 data->wd_Background = zune_imspec_setup(MUII_WindowBack, &data->wd_RenderInfo);
3688 if (muiGlobalInfo(obj)->mgi_Prefs->window_redraw == WINDOW_REDRAW_WITH_CLEAR)
3689 data->wd_Flags |= MUIWF_ERASEAREA;
3691 return TRUE;
3694 /**************************************************************************
3695 MUIM_Cleanup
3696 **************************************************************************/
3697 IPTR Window__MUIM_Cleanup(struct IClass *cl, Object *obj, Msg msg)
3699 struct MUI_WindowData *data = INST_DATA(cl, obj);
3701 zune_imspec_cleanup(data->wd_Background);
3703 if (data->wd_dnd)
3705 DeleteDragNDrop(data->wd_dnd);
3706 data->wd_dnd = NULL;
3709 CleanupRenderInfo(obj, data, &data->wd_RenderInfo);
3710 return TRUE;
3714 /**************************************************************************
3715 This adds the the control char handler and also do the MUIA_CycleChain
3716 stuff. Orginal MUI does this in an other way.
3717 **************************************************************************/
3718 IPTR Window__MUIM_AddControlCharHandler(struct IClass *cl, Object *obj,
3719 struct MUIP_Window_AddControlCharHandler *msg)
3721 struct MUI_WindowData *data = INST_DATA(cl, obj);
3722 struct ObjNode *node;
3724 if (msg->ccnode->ehn_Events)
3726 msg->ccnode->ehn_Priority = msg->ccnode->ehn_Priority;
3727 Enqueue((struct List *)&data->wd_CCList, (struct Node *)msg->ccnode);
3729 /* Due to the lack of a better idea ... */
3730 if (muiAreaData(msg->ccnode->ehn_Object)->mad_Flags & MADF_CYCLECHAIN)
3732 node = AllocPooled(data->wd_MemoryPool, sizeof(struct ObjNode));
3733 if (node)
3735 node->obj = msg->ccnode->ehn_Object;
3736 AddTail((struct List *)&data->wd_CycleChain,(struct Node*)node);
3739 return TRUE;
3742 /**************************************************************************
3743 MUIM_RemControlCharHandler
3744 **************************************************************************/
3745 IPTR Window__MUIM_RemControlCharHandler(struct IClass *cl, Object *obj,
3746 struct MUIP_Window_RemControlCharHandler *msg)
3748 struct MUI_WindowData *data = INST_DATA(cl, obj);
3749 struct ObjNode *node = FindObjNode(&data->wd_CycleChain,msg->ccnode->ehn_Object);
3751 if (msg->ccnode->ehn_Events)
3752 Remove((struct Node *)msg->ccnode);
3754 if (node)
3756 /* Remove from the chain list */
3757 Remove((struct Node *)node);
3758 FreePooled(data->wd_MemoryPool, node, sizeof(struct ObjNode));
3761 return TRUE;
3764 /**************************************************************************
3765 MUIM_DragObject
3766 **************************************************************************/
3767 IPTR Window__MUIM_DragObject(struct IClass *cl, Object *obj, struct MUIP_Window_DragObject *msg)
3769 struct MUI_WindowData *data = INST_DATA(cl, obj);
3770 if (msg->obj)
3772 struct DragNDrop *dnd;
3773 struct MUI_DragImage *di;
3774 struct BitMapNode *bmn;
3776 if (!(dnd = CreateDragNDropA(NULL)))
3777 return 0;
3779 if (!(di = (struct MUI_DragImage*)DoMethod(msg->obj,MUIM_CreateDragImage,-msg->touchx,-msg->touchy,msg->flags)))
3781 DeleteDragNDrop(dnd);
3782 return 0;
3784 if (!di->bm)
3786 DoMethod(msg->obj,MUIM_DeleteDragImage, (IPTR)di);
3787 DeleteDragNDrop(dnd);
3788 return 0;
3791 if (!(bmn = CreateBitMapNodeA(TAGLIST(
3792 GUI_BitMap, (IPTR)di->bm,
3793 GUI_LeftOffset, di->touchx,
3794 GUI_TopOffset, di->touchy,
3795 GUI_Width, di->width,
3796 GUI_Height, di->height,
3797 GUI_SourceAlpha, !!(di->flags & MUIF_DRAGIMAGE_SOURCEALPHA)))))
3799 DoMethod(msg->obj, MUIM_DeleteDragImage, (IPTR)di);
3800 DeleteDragNDrop(dnd);
3801 return 0;
3804 AttachBitMapNode(dnd,bmn);
3806 if (!PrepareDragNDrop(dnd, data->wd_RenderInfo.mri_Screen))
3808 DoMethod(msg->obj,MUIM_DeleteDragImage, (IPTR)di);
3809 DeleteDragNDrop(dnd);
3810 return 0;
3813 muiAreaData(msg->obj)->mad_Flags |= MADF_DRAGGING;
3815 data->wd_DragObject = msg->obj;
3816 data->wd_dnd = dnd;
3817 data->wd_DragImage = di;
3818 return 1;
3820 return 0;
3823 /**************************************************************************
3824 MUIM_AllocGadgetID
3825 **************************************************************************/
3826 IPTR Window__MUIM_AllocGadgetID(struct IClass *cl, Object *obj, struct MUIP_Window_AllocGadgetID *msg)
3828 struct MUI_WindowData *data = INST_DATA(cl, obj);
3829 struct IDNode *newnode;
3831 newnode = AllocPooled(data->wd_MemoryPool, sizeof(struct IDNode));
3832 if (newnode)
3834 int id;
3835 struct MinNode *mn;
3837 if (IsListEmpty((struct List*)&data->wd_IDList))
3839 newnode->id = 1;
3840 AddHead((struct List*)&data->wd_IDList, (struct Node*)&newnode->node);
3841 return (IPTR)1;
3844 id = 1;
3846 for (mn = data->wd_IDList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
3848 struct IDNode *idn = (struct IDNode *)mn;
3849 if (id < idn->id)
3850 break;
3851 id++;
3853 newnode->id = id;
3854 Insert((struct List*)&data->wd_IDList, (struct Node*)&newnode->node, (struct Node*)mn);
3855 return (IPTR)id;
3858 return 0;
3861 /**************************************************************************
3862 MUIM_FreeGadgetID
3863 **************************************************************************/
3864 IPTR Window__MUIM_FreeGadgetID(struct IClass *cl, Object *obj, struct MUIP_Window_FreeGadgetID *msg)
3866 struct MUI_WindowData *data = INST_DATA(cl, obj);
3867 struct MinNode *mn;
3869 for (mn = data->wd_IDList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
3871 struct IDNode *idn = (struct IDNode *)mn;
3872 if (msg->gadgetid == idn->id)
3874 Remove((struct Node*)idn);
3875 FreePooled(data->wd_MemoryPool, idn, sizeof(struct IDNode));
3876 return 0;
3880 return 0;
3884 /**************************************************************************
3885 MUIM_Window_GetMenuCheck
3886 **************************************************************************/
3887 IPTR Window__MUIM_GetMenuCheck(struct IClass *cl, Object *obj, struct MUIP_Window_GetMenuCheck *msg)
3889 IPTR stat = 0;
3890 struct MUI_WindowData *data = INST_DATA(cl, obj);
3891 Object *item;
3892 Object *strip = data->wd_ChildMenustrip;
3893 if (!strip)
3894 strip = data->wd_Menustrip;
3895 if (!strip)
3896 return 0;
3897 if (!(item = (Object*)DoMethod(strip, MUIM_FindUData, msg->MenuID)))
3898 return 0;
3899 get(item,MUIA_Menuitem_Checked, &stat);
3900 return stat;
3903 /**************************************************************************
3904 MUIM_Window_SetMenuCheck
3905 **************************************************************************/
3906 IPTR Window__MUIM_SetMenuCheck(struct IClass *cl, Object *obj, struct MUIP_Window_SetMenuCheck *msg)
3908 struct MUI_WindowData *data = INST_DATA(cl, obj);
3909 Object *item;
3910 Object *strip = data->wd_ChildMenustrip;
3911 if (!strip)
3912 strip = data->wd_Menustrip;
3913 if (!strip)
3914 return 0;
3915 if (!(item = (Object*)DoMethod(strip, MUIM_FindUData, msg->MenuID)))
3916 return 0;
3917 set(item,MUIA_Menuitem_Checked,msg->stat);
3918 return 0;
3921 /**************************************************************************
3922 MUIM_Window_GetMenuState
3923 **************************************************************************/
3924 IPTR Window__MUIM_GetMenuState(struct IClass *cl, Object *obj, struct MUIP_Window_GetMenuState *msg)
3926 IPTR stat = 0;
3927 struct MUI_WindowData *data = INST_DATA(cl, obj);
3928 Object *item;
3929 Object *strip = data->wd_ChildMenustrip;
3930 if (!strip) strip = data->wd_Menustrip;
3931 if (!strip)
3932 return 0;
3933 if (!(item = (Object*)DoMethod(strip, MUIM_FindUData, msg->MenuID)))
3934 return 0;
3935 get(item,MUIA_Menuitem_Enabled, &stat);
3936 return stat;
3939 /**************************************************************************
3940 MUIM_Window_SetMenuState
3941 **************************************************************************/
3942 IPTR Window__MUIM_SetMenuState(struct IClass *cl, Object *obj, struct MUIP_Window_SetMenuState *msg)
3944 struct MUI_WindowData *data = INST_DATA(cl, obj);
3945 Object *item;
3946 Object *strip = data->wd_ChildMenustrip;
3947 if (!strip)
3948 strip = data->wd_Menustrip;
3949 if (!strip)
3950 return 0;
3951 if (!(item = (Object*)DoMethod(strip, MUIM_FindUData, msg->MenuID)))
3952 return 0;
3953 set(item,MUIA_Menuitem_Enabled,msg->stat);
3954 return 0;
3957 /**************************************************************************
3958 MUIM_Window_DrawBackground
3959 **************************************************************************/
3960 IPTR Window__MUIM_DrawBackground(struct IClass *cl, Object *obj, struct MUIP_Window_DrawBackground *msg)
3962 struct MUI_WindowData *data = INST_DATA(cl, obj);
3963 if (!(data->wd_RenderInfo.mri_Window)) /* not between show/hide */
3964 return FALSE;
3966 // D(bug("%d:zune_imspec_draw(%p) l=%d t=%d w=%d h=%d xo=%d yo=%d\n",
3967 // __LINE__, data->wd_Background, msg->left, msg->top, msg->width,
3968 // msg->height, msg->xoffset, msg->yoffset));
3969 zune_imspec_draw(data->wd_Background, &data->wd_RenderInfo,
3970 msg->left, msg->top, msg->width, msg->height,
3971 msg->xoffset, msg->yoffset, 0);
3972 return 0;
3975 /**************************************************************************
3976 MUIM_Window_ToFront
3977 **************************************************************************/
3978 IPTR Window__MUIM_ToFront(struct IClass *cl, Object *obj, Msg msg)
3980 struct MUI_WindowData *data = INST_DATA(cl, obj);
3981 if (!(data->wd_RenderInfo.mri_Window)) /* not between show/hide */
3982 return 0;
3984 WindowToFront(data->wd_RenderInfo.mri_Window);
3985 return 1;
3988 /**************************************************************************
3989 MUIM_Window_ToBack
3990 **************************************************************************/
3991 IPTR Window__MUIM_ToBack(struct IClass *cl, Object *obj, Msg msg)
3993 struct MUI_WindowData *data = INST_DATA(cl, obj);
3994 if (!(data->wd_RenderInfo.mri_Window)) /* not between show/hide */
3995 return 0;
3997 WindowToBack(data->wd_RenderInfo.mri_Window);
3998 return 1;
4001 /**************************************************************************
4002 MUIM_Window_ScreenToBack
4003 **************************************************************************/
4004 IPTR Window__MUIM_ScreenToBack(struct IClass *cl, Object *obj, Msg msg)
4006 struct MUI_WindowData *data = INST_DATA(cl, obj);
4007 if (!(data->wd_RenderInfo.mri_Window)) /* not between show/hide */
4008 return 0;
4010 ScreenToBack(data->wd_RenderInfo.mri_Screen);
4011 return 1;
4014 /**************************************************************************
4015 MUIM_Window_ScreenToFront
4016 **************************************************************************/
4017 IPTR Window__MUIM_ScreenToFront(struct IClass *cl, Object *obj, Msg msg)
4019 struct MUI_WindowData *data = INST_DATA(cl, obj);
4020 if (!(data->wd_RenderInfo.mri_Window)) /* not between show/hide */
4021 return 0;
4023 ScreenToFront(data->wd_RenderInfo.mri_Screen);
4024 return 1;
4027 /**************************************************************************
4028 MUIM_Window_ActionIconify
4029 **************************************************************************/
4030 IPTR Window__MUIM_ActionIconify(struct IClass *cl, Object *obj, Msg msg)
4032 set(_app(obj), MUIA_Application_Iconified, TRUE);
4034 return TRUE;
4038 /* Loads ENV: prefs, add a Window_ID chunk in the MUIW chunk, if no MUIW chunk
4039 * then create it at the same level as MUIC chunk, save prefs.
4040 * Do the same for ENVARC:
4041 * MUIW chunk layout:
4042 * 'MUIW'
4043 * 00 00 00 30 (chunk length for a single window, 0x30L big endian)
4044 * 'this window ID'
4045 * 00 00 00 28
4046 * xx xx yy yy (X, Y)
4047 * ww ww hh hh (Width, Height)
4048 * ax ax ay ay (AltX, AltY)
4049 * aw aw ah ah (AltWidth, AltHeight)
4050 * 00 00 00 00 (???)
4051 * 00 00 00 00
4052 * 00 00 00 00
4053 * 00 00 00 00
4054 * 00 01 00 00
4055 * 00 00 00 00
4057 static void RememberWindowPosition(Object *winobj, ULONG id)
4059 if (!id)
4060 return;
4063 /* Loads ENV: prefs, remove our Window_ID chunk from the MUIW chunk, save prefs.
4064 * Do the same for ENVARC:
4065 * This function shouldnt really be in window.c, but rather in a file dealing
4066 * with prefs file stuff.
4068 static void ForgetWindowPosition(Object *winobj, ULONG id)
4070 if (!id)
4071 return;
4074 /**************************************************************************
4075 MUIM_Window_Snapshot
4076 **************************************************************************/
4077 IPTR Window__MUIM_Snapshot(struct IClass *cl, Object *obj, struct MUIP_Window_Snapshot *msg)
4079 struct MUI_WindowData *data = INST_DATA(cl, obj);
4080 struct windowpos winp;
4081 struct Window *w;
4082 winp.id = data->wd_ID;
4083 w = data->wd_RenderInfo.mri_Window;
4084 if (w)
4086 winp.x1 = w->LeftEdge;
4087 winp.y1 = w->TopEdge;
4088 winp.w1 = w->GZZWidth;
4089 winp.h1 = w->GZZHeight;
4090 winp.x2 = 0;
4091 winp.x2 = 0;
4092 winp.w2 = 0;
4093 winp.h2 = 0; //to do save alt dims
4095 set(_app(obj),MUIA_Application_SetWinPos,&winp);
4098 if (msg->flags)
4099 RememberWindowPosition(obj, data->wd_ID);
4100 else
4101 ForgetWindowPosition(obj, data->wd_ID);
4102 return 1;
4105 /**************************************************************************
4106 MUIM_Window_UpdateMenu
4107 **************************************************************************/
4108 IPTR Window__MUIM_UpdateMenu(struct IClass *cl, Object *obj, Msg msg)
4110 struct MUI_WindowData *data = INST_DATA(cl, obj);
4112 struct Menu *menu = NULL;
4113 struct NewMenu *newmenu = NULL;
4114 APTR visinfo = NULL;
4115 struct Window *win =NULL;
4117 if (data->wd_Menustrip) // only open windows can have a menustrip
4119 if ((visinfo = GetVisualInfoA(data->wd_RenderInfo.mri_Screen, NULL)))
4121 win = data->wd_RenderInfo.mri_Window;
4122 ClearMenuStrip(win);
4123 if (data->wd_Menu)
4125 FreeMenus(data->wd_Menu);
4126 data->wd_Menu = NULL;
4129 get(data->wd_Menustrip, MUIA_Menuitem_NewMenu, &newmenu);
4130 if (newmenu)
4132 if ((menu = CreateMenusA(newmenu, NULL)))
4134 struct TagItem tags[] =
4136 { GTMN_NewLookMenus, TRUE },
4137 { TAG_DONE, 0 }
4139 LayoutMenusA(menu, visinfo, tags);
4140 data->wd_Menu = menu;
4141 SetMenuStrip(win, menu);
4144 FreeVisualInfo(visinfo);
4148 return 1;
4151 /**************************************************************************
4152 MUIM_Export : to export an objects "contents" to a dataspace object.
4153 **************************************************************************/
4154 static IPTR Window__MUIM_Export(struct IClass *cl, Object *obj, struct MUIP_Export *msg)
4156 struct MUI_WindowData *data = INST_DATA(cl, obj);
4157 DoMethodA(data->wd_RootObject, (Msg)msg);
4158 return 0;
4162 /**************************************************************************
4163 MUIM_Import : to import an objects "contents" from a dataspace object.
4164 **************************************************************************/
4165 static IPTR Window__MUIM_Import(struct IClass *cl, Object *obj, struct MUIP_Import *msg)
4167 struct MUI_WindowData *data = INST_DATA(cl, obj);
4168 DoMethodA(data->wd_RootObject, (Msg)msg);
4169 return 0;
4172 BOOPSI_DISPATCHER(IPTR, Window_Dispatcher, cl, obj, msg)
4174 switch (msg->MethodID)
4176 case OM_NEW: return Window__OM_NEW(cl, obj, (struct opSet *) msg);
4177 case OM_DISPOSE: return Window__OM_DISPOSE(cl, obj, msg);
4178 case OM_SET: return Window__OM_SET(cl, obj, (struct opSet *)msg);
4179 case OM_GET: return Window__OM_GET(cl, obj, (struct opGet *)msg);
4180 case MUIM_FindUData: return Window__MUIM_FindUData(cl, obj, (struct MUIP_FindUData *)msg);
4181 case MUIM_GetUData: return Window__MUIM_GetUData(cl, obj, (struct MUIP_GetUData *)msg);
4182 case MUIM_SetUData: return Window__MUIM_SetUData(cl, obj, (struct MUIP_SetUData *)msg);
4183 case MUIM_SetUDataOnce: return Window__MUIM_SetUDataOnce(cl, obj, (struct MUIP_SetUDataOnce *)msg);
4184 case MUIM_Window_AddEventHandler: return Window__MUIM_AddEventHandler(cl, obj, (APTR)msg);
4185 case MUIM_Window_RemEventHandler: return Window__MUIM_RemEventHandler(cl, obj, (APTR)msg);
4186 case MUIM_ConnectParent: return Window__MUIM_ConnectParent(cl, obj, (APTR)msg);
4187 case MUIM_DisconnectParent: return Window__MUIM_DisconnectParent(cl, obj, (APTR)msg);
4188 case MUIM_Window_RecalcDisplay: return Window__MUIM_RecalcDisplay(cl, obj, (APTR)msg);
4189 case MUIM_Window_Setup: return Window__MUIM_Setup(cl, obj, (APTR)msg);
4190 case MUIM_Window_Cleanup: return Window__MUIM_Cleanup(cl, obj, (APTR)msg);
4191 case MUIM_Window_AddControlCharHandler: return Window__MUIM_AddControlCharHandler(cl, obj, (APTR)msg);
4192 case MUIM_Window_RemControlCharHandler: return Window__MUIM_RemControlCharHandler(cl, obj, (APTR)msg);
4193 case MUIM_Window_DragObject: return Window__MUIM_DragObject(cl, obj, (APTR)msg);
4194 case MUIM_Window_AllocGadgetID: return Window__MUIM_AllocGadgetID(cl, obj, (APTR)msg);
4195 case MUIM_Window_FreeGadgetID: return Window__MUIM_FreeGadgetID(cl, obj, (APTR)msg);
4196 case MUIM_Window_GetMenuCheck: return Window__MUIM_GetMenuCheck(cl, obj, (APTR)msg);
4197 case MUIM_Window_SetMenuCheck: return Window__MUIM_SetMenuCheck(cl, obj, (APTR)msg);
4198 case MUIM_Window_GetMenuState: return Window__MUIM_GetMenuState(cl, obj, (APTR)msg);
4199 case MUIM_Window_SetMenuState: return Window__MUIM_SetMenuState(cl, obj, (APTR)msg);
4200 case MUIM_Window_DrawBackground: return Window__MUIM_DrawBackground(cl, obj, (APTR)msg);
4201 case MUIM_Window_ToFront: return Window__MUIM_ToFront(cl, obj, (APTR)msg);
4202 case MUIM_Window_ToBack: return Window__MUIM_ToBack(cl, obj, (APTR)msg);
4203 case MUIM_Window_ScreenToFront: return Window__MUIM_ScreenToFront(cl, obj, (APTR)msg);
4204 case MUIM_Window_ScreenToBack: return Window__MUIM_ScreenToBack(cl, obj, (APTR)msg);
4205 case MUIM_Window_ActionIconify: return Window__MUIM_ActionIconify(cl, obj, (APTR)msg);
4206 case MUIM_Window_Snapshot: return Window__MUIM_Snapshot(cl, obj, (APTR)msg);
4207 case MUIM_Window_UpdateMenu: return Window__MUIM_UpdateMenu(cl, obj, (APTR)msg);
4208 case MUIM_Export: return Window__MUIM_Export(cl, obj, (APTR)msg);
4209 case MUIM_Import: return Window__MUIM_Import(cl, obj, (APTR)msg);
4212 return DoSuperMethodA(cl, obj, msg);
4214 BOOPSI_DISPATCHER_END
4218 * Class descriptor.
4220 const struct __MUIBuiltinClass _MUI_Window_desc = {
4221 MUIC_Window,
4222 MUIC_Notify,
4223 sizeof(struct MUI_WindowData),
4224 (void*)Window_Dispatcher