Fixed binary search: no more infinite loops when vendor is unknown.
[tangerine.git] / workbench / libs / muimaster / classes / window.c
blobe7230599b7c76b026b37f16164425d01221f1f35
1 /*
2 Copyright 1999, David Le Corfec.
3 Copyright 2002-2006, The AROS Development Team.
4 All rights reserved.
6 $Id$
7 */
8 #include <exec/types.h>
9 #include <exec/memory.h>
11 #include <string.h>
13 #include <intuition/imageclass.h>
14 #include <intuition/icclass.h>
15 #include <intuition/gadgetclass.h>
16 #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;
136 #ifndef WFLG_SIZEGADGET
138 #define WFLG_CLOSEGADGET (1<<0) /* has close gadget */
139 #define WFLG_SIZEGADGET (1<<1) /* has size gadget */
140 #define WFLG_BACKDROP (1<<2) /* is backdrop window */
141 #define WFLG_BORDERLESS (1<<3) /* has no borders */
142 #define WFLG_DEPTHGADGET (1<<4) /* has depth gadget */
143 #define WFLG_DRAGBAR (1<<5) /* is draggable */
144 #define WFLG_SIZEBRIGHT (1<<6) /* size gadget is in right border */
146 #endif
148 /* wd_Flags */
149 #define MUIWF_OPENED (1<<0) /* window currently opened */
150 #define MUIWF_HIDDEN (1<<1) /* window currently iconified */
151 #define MUIWF_ACTIVE (1<<2) /* window currently active */
152 #define MUIWF_RESIZING (1<<4) /* window currently resizing, for simple refresh */
153 #define MUIWF_DONTACTIVATE (1<<7) /* do not activate the window when opening */
154 #define MUIWF_USERIGHTSCROLLER (1<<8) /* window should have a right scroller */
155 #define MUIWF_USEBOTTOMSCROLLER (1<<9) /* window should have a bottom scroller */
156 #define MUIWF_ERASEAREA (1<<10) /* Erase area after a window resize */
157 #define MUIWF_ISAPPWINDOW (1<<11) /* Is an app window (user can drop icons on it) */
158 #define MUIWF_ISSUBWINDOW (1<<12) /* Dont get automatically disposed with app */
159 #define MUIWF_BUBBLEMODE (1<<13) /* Quick bubble mode. Bubbles appear quick when moving */
160 #define MUIWF_OPENONUNHIDE (1<<14) /* Open the window when unhiding */
161 #define MUIWF_SCREENLOCKED (1<<15) /* A pub screen was locked in SetupRenderInfo. Unlock it in CleanupRenderInfo! */
162 #define MUIWF_OBJECTGOACTIVESENT (1<<16) /* A MUIM_GoActive msg was sent to window's active object */
163 #define MUIWF_TOOLBOX (1<<17) /* Window should be opened as ToolBox */
165 #define BUBBLEHELP_TICKER_FIRST 10
166 #define BUBBLEHELP_TICKER_LATER 3
168 struct __dummyXFC3__
170 struct MUI_NotifyData mnd;
171 struct MUI_WindowData mwd;
174 #define muiWindowData(obj) (&(((struct __dummyXFC3__ *)(obj))->mwd))
176 static ULONG DoHalfshineGun(ULONG a, ULONG b)
178 ULONG val = ((((a)>>24) + 3 * ((b)>>24)) / 4);
179 val = val + (val<<8) + (val<<16) + (val<<24);
180 return val;
183 static ULONG DoHalfshadowGun(ULONG a, ULONG b)
185 ULONG val = ((((a)>>24) + 5 * ((b)>>24)) / 6);
186 val = val + (val<<8) + (val<<16) + (val<<24);
187 return val;
190 static Object *CreateSysimage(struct DrawInfo *dri, ULONG which)
192 return NewObject(NULL, "sysiclass",
193 SYSIA_DrawInfo, (IPTR)dri,
194 SYSIA_Which, which,
195 TAG_DONE);
198 static void EnqueueByPriAndAddress(struct List *list, struct Node *node)
200 struct Node *scannode;
202 /* Sort by priority and by node address, so that a
203 "remove - modify - enqueue" sequence will re-add
204 the node at the same place in the list it was
205 initially */
207 ForeachNode(list, scannode)
209 if (((struct Node *)node)->ln_Pri > scannode->ln_Pri) break;
210 if (((struct Node *)node)->ln_Pri == scannode->ln_Pri)
212 if ((IPTR)node > (IPTR)scannode) break;
216 Insert(list, (struct Node *)node, scannode->ln_Pred);
219 static BOOL InitCustomFrames(Object *obj, struct MUI_RenderInfo *mri)
221 int i;
223 for (i = 0; i < 16; i++)
225 mri->mri_FrameImage[i] = NULL;
228 mri->mri_FrameImage[0] = load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->customframe_config_1, mri->mri_Screen);
229 mri->mri_FrameImage[1] = load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->customframe_config_2, mri->mri_Screen);
230 mri->mri_FrameImage[2] = load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->customframe_config_3, mri->mri_Screen);
231 mri->mri_FrameImage[3] = load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->customframe_config_4, mri->mri_Screen);
232 mri->mri_FrameImage[4] = load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->customframe_config_5, mri->mri_Screen);
233 mri->mri_FrameImage[5] = load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->customframe_config_6, mri->mri_Screen);
234 mri->mri_FrameImage[6] = load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->customframe_config_7, mri->mri_Screen);
235 mri->mri_FrameImage[7] = load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->customframe_config_8, mri->mri_Screen);
236 mri->mri_FrameImage[8] = load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->customframe_config_9, mri->mri_Screen);
237 mri->mri_FrameImage[9] = load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->customframe_config_10, mri->mri_Screen);
238 mri->mri_FrameImage[10] = load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->customframe_config_11, mri->mri_Screen);
239 mri->mri_FrameImage[11] = load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->customframe_config_12, mri->mri_Screen);
240 mri->mri_FrameImage[12] = load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->customframe_config_13, mri->mri_Screen);
241 mri->mri_FrameImage[13] = load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->customframe_config_14, mri->mri_Screen);
242 mri->mri_FrameImage[14] = load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->customframe_config_15, mri->mri_Screen);
243 mri->mri_FrameImage[15] = load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->customframe_config_16, mri->mri_Screen);
245 return TRUE;
248 static void DisposeCustomFrames(struct MUI_RenderInfo *mri)
250 int i;
252 for (i = 0; i < 16; i++)
254 dispose_custom_frame(mri->mri_FrameImage[i]);
256 mri->mri_FrameImage[i] = NULL;
260 static BOOL SetupRenderInfo(Object *obj, struct MUI_WindowData *data, struct MUI_RenderInfo *mri)
262 ULONG rgbtable[3 * 3];
263 Object *temp_obj;
264 IPTR val;
265 int i;
267 /* TODO: Move this whole screen locking/opening stuff into the application class
268 * by creating methods for this purpose */
270 /* If no user screen has been specified try to open the application specifc screen */
271 if (!data->wd_UserScreen)
273 ULONG screenmodeid = muiGlobalInfo(obj)->mgi_Prefs->screenmodeid;
275 if (screenmodeid != ~0)
277 if (!muiGlobalInfo(obj)->mgi_CustomScreen)
279 muiGlobalInfo(obj)->mgi_CustomScreen = OpenScreenTags(NULL,
280 SA_DisplayID, screenmodeid,
281 SA_SharePens, TRUE,
282 SA_FullPalette, TRUE,
283 SA_LikeWorkbench,TRUE,
284 TAG_DONE);
285 /* It's fine if this fails as there is a back fall case below */
288 data->wd_UserScreen = muiGlobalInfo(obj)->mgi_CustomScreen;
292 if (data->wd_UserScreen)
294 mri->mri_Screen = data->wd_UserScreen;
296 else
298 if (!(mri->mri_Screen = LockPubScreen(data->wd_UserPublicScreen)))
300 if (!(mri->mri_Screen = LockPubScreen(NULL)))
302 return FALSE;
306 data->wd_Flags |= MUIWF_SCREENLOCKED;
309 if (!(mri->mri_DrawInfo = GetScreenDrawInfo(mri->mri_Screen)))
311 if (data->wd_Flags & MUIWF_SCREENLOCKED)
313 UnlockPubScreen(NULL,mri->mri_Screen);
314 data->wd_Flags &= ~MUIWF_SCREENLOCKED;
316 return FALSE;
319 if (!InitCustomFrames(obj, mri))
321 if (data->wd_Flags & MUIWF_SCREENLOCKED)
323 UnlockPubScreen(NULL,mri->mri_Screen);
324 data->wd_Flags &= ~MUIWF_SCREENLOCKED;
326 return FALSE;
329 mri->mri_Colormap = mri->mri_Screen->ViewPort.ColorMap;
330 mri->mri_ScreenWidth = mri->mri_Screen->Width;
331 mri->mri_ScreenHeight = mri->mri_Screen->Height;
333 if (mri->mri_ScreenWidth / mri->mri_ScreenHeight < 2)
335 mri->mri_Flags |= MUIMRI_THINFRAMES;
338 if (GetBitMapAttr(mri->mri_Screen->RastPort.BitMap, BMA_DEPTH) >= 15)
340 mri->mri_Flags |= MUIMRI_TRUECOLOR;
343 mri->mri_PensStorage[MPEN_SHINE] = mri->mri_DrawInfo->dri_Pens[SHINEPEN];
344 mri->mri_PensStorage[MPEN_BACKGROUND] = mri->mri_DrawInfo->dri_Pens[BACKGROUNDPEN];
345 mri->mri_PensStorage[MPEN_SHADOW] = mri->mri_DrawInfo->dri_Pens[SHADOWPEN];
346 mri->mri_PensStorage[MPEN_TEXT] = mri->mri_DrawInfo->dri_Pens[TEXTPEN];
347 mri->mri_PensStorage[MPEN_FILL] = mri->mri_DrawInfo->dri_Pens[FILLPEN];
349 GetRGB32(mri->mri_Colormap, mri->mri_DrawInfo->dri_Pens[SHINEPEN], 1, rgbtable);
350 GetRGB32(mri->mri_Colormap, mri->mri_DrawInfo->dri_Pens[BACKGROUNDPEN], 1, rgbtable+3);
351 GetRGB32(mri->mri_Colormap, mri->mri_DrawInfo->dri_Pens[SHADOWPEN], 1, rgbtable+6);
353 mri->mri_PensStorage[MPEN_HALFSHINE] = ObtainBestPenA
355 mri->mri_Colormap,
356 DoHalfshineGun(rgbtable[0], rgbtable[3]),
357 DoHalfshineGun(rgbtable[1], rgbtable[4]),
358 DoHalfshineGun(rgbtable[2], rgbtable[5]), NULL
361 mri->mri_PensStorage[MPEN_HALFSHADOW] = ObtainBestPenA
363 mri->mri_Colormap,
364 DoHalfshadowGun(rgbtable[6], rgbtable[3]),
365 DoHalfshadowGun(rgbtable[7], rgbtable[4]),
366 DoHalfshadowGun(rgbtable[8], rgbtable[5]), NULL
369 /* I'm really not sure that MUI does this for MPEN_MARK, but it seems mostly acceptable -dlc */
370 mri->mri_PensStorage[MPEN_MARK] = ObtainBestPenA
372 mri->mri_Colormap, 0xf4f4f4f4, 0xb5b5b5b5, 0x8b8b8b8b, NULL
375 mri->mri_Pens = mri->mri_PensStorage;
377 for (i = 0; i < -MUIV_Font_NegCount; i++)
379 mri->mri_Fonts[i] = NULL;
382 if (data->wd_Flags & MUIWF_USEBOTTOMSCROLLER)
384 mri->mri_LeftImage = CreateSysimage(mri->mri_DrawInfo, LEFTIMAGE);
385 mri->mri_RightImage = CreateSysimage(mri->mri_DrawInfo, RIGHTIMAGE);
387 else
389 mri->mri_LeftImage = mri->mri_RightImage = NULL;
392 if (data->wd_Flags & MUIWF_USERIGHTSCROLLER)
394 mri->mri_UpImage = CreateSysimage(mri->mri_DrawInfo, UPIMAGE);
395 mri->mri_DownImage = CreateSysimage(mri->mri_DrawInfo, DOWNIMAGE);
397 else
399 mri->mri_UpImage = mri->mri_DownImage = NULL;
402 if ((data->wd_Flags & MUIWF_USEBOTTOMSCROLLER) ||
403 (data->wd_Flags & MUIWF_USERIGHTSCROLLER))
404 mri->mri_SizeImage = CreateSysimage(mri->mri_DrawInfo, SIZEIMAGE);
405 else
406 mri->mri_SizeImage = NULL;
408 if (data->wd_CrtFlags & WFLG_BORDERLESS)
410 /* Infact borderless windows could also have borders (if they have a window title e.g. but
411 since they look ugly anywhy we ignore it for now */
412 mri->mri_BorderLeft = 0;
413 mri->mri_BorderRight = 0;
414 mri->mri_BorderTop = 0;
415 mri->mri_BorderBottom = 0;
417 else
419 mri->mri_BorderLeft = mri->mri_Screen->WBorLeft;
420 mri->mri_BorderTop = mri->mri_Screen->WBorTop + mri->mri_Screen->Font->ta_YSize+ 1;
421 temp_obj = NewObject
423 NULL, "sysiclass",
424 SYSIA_DrawInfo, (IPTR)mri->mri_DrawInfo,
425 SYSIA_Which, SIZEIMAGE,
426 TAG_DONE
428 if (temp_obj)
430 GetAttr(IA_Height,temp_obj,&val);
431 DisposeObject(temp_obj);
432 mri->mri_BorderBottom = val;
434 else
435 mri->mri_BorderBottom = mri->mri_Screen->WBorBottom;
438 return TRUE;
441 static void CleanupRenderInfo(Object *obj, struct MUI_WindowData *data, struct MUI_RenderInfo *mri)
443 int i;
445 DisposeCustomFrames(mri);
447 if (mri->mri_LeftImage) {DisposeObject(mri->mri_LeftImage);mri->mri_LeftImage=NULL;};
448 if (mri->mri_RightImage){DisposeObject(mri->mri_RightImage);mri->mri_RightImage=NULL;};
449 if (mri->mri_UpImage) {DisposeObject(mri->mri_UpImage);mri->mri_UpImage=NULL;};
450 if (mri->mri_DownImage) {DisposeObject(mri->mri_DownImage);mri->mri_DownImage=NULL;};
451 if (mri->mri_SizeImage) {DisposeObject(mri->mri_SizeImage);mri->mri_SizeImage=NULL;};
453 /* bug("CleanupRenderInfo\n"); */
454 for (i = 0; i < -MUIV_Font_NegCount; i++)
456 if (mri->mri_Fonts[i])
458 /* bug("CleanupRenderInfo: closing font %p (%s/%d)\n", */
459 /* mri->mri_Fonts[i], mri->mri_Fonts[i]->tf_Message.mn_Node.ln_Name, */
460 /* mri->mri_Fonts[i]->tf_YSize); */
461 CloseFont(mri->mri_Fonts[i]);
462 mri->mri_Fonts[i] = NULL;
465 ReleasePen(mri->mri_Colormap, mri->mri_PensStorage[MPEN_MARK]);
466 ReleasePen(mri->mri_Colormap, mri->mri_PensStorage[MPEN_HALFSHADOW]);
467 ReleasePen(mri->mri_Colormap, mri->mri_PensStorage[MPEN_HALFSHINE]);
468 FreeScreenDrawInfo(mri->mri_Screen, mri->mri_DrawInfo);
469 mri->mri_DrawInfo = NULL;
471 /* If a custom screen has been opened by zune, close it as soon as
472 * zero windows are opened. See above for comments about refactorization. */
473 if (muiGlobalInfo(obj)->mgi_CustomScreen)
475 BOOL screenclose = TRUE;
476 Object *_app = _app(obj);
477 if (_app != NULL)
479 struct List *store = NULL;
480 get(_app, MUIA_Application_WindowList, &store);
481 if (store != NULL)
483 if (!IsListEmpty(store)) screenclose = FALSE;
486 if (screenclose)
488 /* If the window's user screen really was the custom screen, clear the reference */
489 if (data->wd_UserScreen == muiGlobalInfo(obj)->mgi_CustomScreen)
490 data->wd_UserScreen = NULL;
492 CloseScreen(muiGlobalInfo(obj)->mgi_CustomScreen);
493 muiGlobalInfo(obj)->mgi_CustomScreen = NULL;
498 if (data->wd_Flags & MUIWF_SCREENLOCKED)
500 UnlockPubScreen(NULL, mri->mri_Screen);
501 data->wd_Flags &= ~MUIWF_SCREENLOCKED;
503 mri->mri_Screen = NULL;
506 static void ShowRenderInfo(struct MUI_RenderInfo *mri)
508 if (mri->mri_BufferBM)
510 mri->mri_RastPort = &mri->mri_BufferRP;
512 else
514 mri->mri_RastPort = mri->mri_Window->RPort;
518 static void HideRenderInfo(struct MUI_RenderInfo *mri)
520 mri->mri_RastPort = NULL;
523 static ULONG GetDefaultEvents (void)
525 return IDCMP_NEWSIZE | IDCMP_REFRESHWINDOW
526 | IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE | IDCMP_MENUPICK
527 | IDCMP_CLOSEWINDOW | IDCMP_RAWKEY | IDCMP_INTUITICKS
528 | IDCMP_ACTIVEWINDOW | IDCMP_INACTIVEWINDOW | IDCMP_GADGETUP;
531 static void ChangeEvents (struct MUI_WindowData *data, ULONG new_events)
533 struct MinNode *mn;
534 struct MUI_EventHandlerNode *ehn;
535 ULONG old_events = data->wd_Events;
537 for (mn = data->wd_EHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
539 ehn = (struct MUI_EventHandlerNode *)mn;
540 new_events |= ehn->ehn_Events;
543 /* sba: kill the IDCMP_VANILLAKEY flag. MUI doesn't do this but programs
544 ** which use this will behave different if they request for this flag
545 ** (also on MUI)
547 new_events &= ~IDCMP_VANILLAKEY;
549 data->wd_Events = new_events;
550 if ((old_events != new_events) && (data->wd_Flags & MUIWF_OPENED))
552 ModifyIDCMP(data->wd_RenderInfo.mri_Window, new_events);
556 static void CalcWindowPosition(Object *obj, struct MUI_WindowData *data);
557 static void CreateWindowScrollbars(Object *obj, struct MUI_WindowData *data);
558 static void CalcAltDimensions(Object *obj, struct MUI_WindowData *data);
559 static void UndisplayWindow(Object *obj, struct MUI_WindowData *data);
560 static struct ObjNode *FindObjNode(struct MinList *list, Object *obj);
562 static BOOL DisplayWindow(Object *obj, struct MUI_WindowData *data)
564 struct Window *win;
565 ULONG flags = data->wd_CrtFlags;
566 struct IBox altdims;
567 ULONG backfill, buttons;
569 struct Menu *menu = NULL;
570 struct NewMenu *newmenu = NULL;
571 APTR visinfo = NULL;
573 Object *gadgets;
575 if (!(data->wd_Flags & MUIWF_DONTACTIVATE))
577 flags |= WFLG_ACTIVATE;
580 /* Toolboxes are handled differently on AmigaOS */
581 #ifdef __AROS__
582 if (data->wd_Flags & MUIWF_TOOLBOX)
583 flags |= WFLG_TOOLBOX;
584 #endif
588 data->wd_MinMax.MinHeight == data->wd_MinMax.MaxHeight
589 && data->wd_MinMax.MinWidth == data->wd_MinMax.MaxWidth
591 flags &= ~WFLG_SIZEGADGET;
593 if (!(flags & WFLG_SIZEBRIGHT))
594 flags |= WFLG_SIZEBBOTTOM;
596 CalcWindowPosition(obj, data);
598 if ((visinfo = GetVisualInfoA(data->wd_RenderInfo.mri_Screen,NULL)))
600 if (data->wd_Menustrip)
602 get(data->wd_Menustrip,MUIA_Menuitem_NewMenu,&newmenu);
603 if (newmenu)
605 if ((menu = CreateMenusA(newmenu,NULL)))
607 struct TagItem tags[] =
609 { GTMN_NewLookMenus, TRUE },
610 { TAG_DONE, (IPTR)NULL }
612 LayoutMenusA(menu, visinfo, tags);
616 FreeVisualInfo(visinfo);
619 CreateWindowScrollbars(obj, data);
620 CalcAltDimensions(obj, data);
621 altdims = data->wd_AltDim;
622 /* hack to account for border size, as we only know the innersize and must give
623 * the total size.
625 altdims.Width += data->wd_RenderInfo.mri_Screen->WBorLeft + data->wd_RenderInfo.mri_Screen->WBorRight;
626 altdims.Height += data->wd_RenderInfo.mri_Screen->WBorTop + data->wd_RenderInfo.mri_Screen->WBorBottom +
627 data->wd_RenderInfo.mri_DrawInfo->dri_Font->tf_YSize + 1;
629 if (muiGlobalInfo(obj)->mgi_Prefs->window_redraw == WINDOW_REDRAW_WITHOUT_CLEAR)
630 backfill = WA_BackFill;
631 else
632 backfill = TAG_IGNORE;
634 if (muiGlobalInfo(obj)->mgi_Prefs->window_refresh == WINDOW_REFRESH_SMART)
635 flags &= ~WFLG_SIMPLE_REFRESH;
636 set(_app(obj),MUIA_Application_SearchWinId,data->wd_ID);
637 struct windowpos *winp=0;
638 get(_app(obj),MUIA_Application_GetWinPos,&winp);
639 if (winp)
641 if (data->wd_RenderInfo.mri_ScreenWidth > (data->wd_X + data->wd_Width))
643 data->wd_X=winp->x1;
644 data->wd_Width=winp->w1;
646 if (data->wd_RenderInfo.mri_ScreenHeight > (data->wd_Y + data->wd_Height))
648 data->wd_Y=winp->y1;
649 data->wd_Height=winp->h1;
654 gadgets = (data->wd_VertProp != NULL) ? data->wd_VertProp : data->wd_HorizProp;
655 buttons = muiGlobalInfo(obj)->mgi_Prefs->window_buttons;
657 win = OpenWindowTags
659 NULL,
661 WA_Left, (IPTR) data->wd_X,
662 WA_Top, (IPTR) data->wd_Y,
663 WA_Flags, (IPTR) flags,
664 data->wd_Title ?
665 WA_Title :
666 TAG_IGNORE, (IPTR) data->wd_Title,
667 data->wd_ScreenTitle ?
668 WA_ScreenTitle :
669 TAG_IGNORE, (IPTR) data->wd_ScreenTitle,
670 WA_CustomScreen, (IPTR) data->wd_RenderInfo.mri_Screen,
671 WA_InnerWidth, (IPTR) data->wd_Width,
672 WA_InnerHeight, (IPTR) data->wd_Height,
673 WA_AutoAdjust, (IPTR) TRUE,
674 WA_NewLookMenus, (IPTR) TRUE,
675 #ifdef __AMIGAOS4__
676 WA_ToolBox, (IPTR) !!(data->wd_Flags & MUIWF_TOOLBOX),
677 #endif
678 #ifdef __AROS__
679 WA_ExtraGadget_MUI, (IPTR) ((buttons & MUIV_Window_Button_MUI) != 0) ? TRUE : FALSE,
680 WA_ExtraGadget_PopUp, (IPTR) ((buttons & MUIV_Window_Button_Popup) != 0) ? TRUE : FALSE,
681 WA_ExtraGadget_Snapshot,(IPTR) ((buttons & MUIV_Window_Button_Snapshot) != 0) ? TRUE : FALSE,
682 WA_ExtraGadget_Iconify, (IPTR) ((buttons & MUIV_Window_Button_Iconify) != 0) ? TRUE : FALSE,
683 #endif
684 data->wd_NoMenus ?
685 WA_RMBTrap :
686 TAG_IGNORE, (IPTR) TRUE,
687 WA_Gadgets, (IPTR) gadgets,
688 data->wd_ZoomGadget ?
689 WA_Zoom :
690 TAG_IGNORE, (IPTR) &altdims,
691 backfill, (IPTR) LAYERS_NOBACKFILL,
692 TAG_DONE
695 if (win)
698 int hborders = win->BorderLeft + win->BorderRight;
699 int vborders = win->BorderTop + win->BorderBottom;
701 /* recalc window size (which will hopefully equal our requested size) */
702 data->wd_Width = win->GZZWidth;
703 data->wd_Height = win->GZZHeight;
705 /* set window limits according to window contents */
706 WindowLimits
708 win, data->wd_MinMax.MinWidth + hborders,
709 data->wd_MinMax.MinHeight + vborders,
710 data->wd_MinMax.MaxWidth + hborders,
711 data->wd_MinMax.MaxHeight + vborders
714 win->UserData = (BYTE*)data->wd_RenderInfo.mri_WindowObject;
715 win->UserPort = muiGlobalInfo(obj)->mgi_WindowsPort; /* Same port for all windows */
716 ModifyIDCMP(win, data->wd_Events);
718 data->wd_RenderInfo.mri_Window = win;
719 data->wd_RenderInfo.mri_VertProp = data->wd_VertProp;
720 data->wd_RenderInfo.mri_HorizProp = data->wd_HorizProp;
721 SetDrMd(win->RPort,JAM1); //text is draw wrong in toolbarclass if not set
723 if (menu)
725 data->wd_Menu = menu;
726 SetMenuStrip(win,menu);
729 if (flags & WFLG_ACTIVATE)
731 data->wd_Flags |= MUIWF_ACTIVE;
734 return TRUE;
737 if (menu) FreeMenus(menu);
738 UndisplayWindow(obj, data);
740 return FALSE;
744 static void UndisplayWindow(Object *obj, struct MUI_WindowData *data)
746 struct Window *win = data->wd_RenderInfo.mri_Window;
747 if ((data->wd_XStore >= 0) && (data->wd_YStore >= 0))
749 DoMethod(obj,MUIM_Window_Snapshot,0);
752 data->wd_RenderInfo.mri_Window = NULL;
753 data->wd_RenderInfo.mri_VertProp = NULL;
754 data->wd_RenderInfo.mri_HorizProp = NULL;
756 data->wd_Flags &= ~MUIWF_ACTIVE;
758 if (win != NULL)
760 /* store position and size */
761 if (data->wd_XStore >=0)
762 data->wd_X = win->LeftEdge;
763 else
764 data->wd_X = data->wd_XStore;
765 if (data->wd_YStore >=0)
766 data->wd_Y = win->TopEdge;
767 else
768 data->wd_Y = data->wd_YStore;
769 data->wd_Width = win->GZZWidth;
770 data->wd_Height = win->GZZHeight;
772 ClearMenuStrip(win);
773 if (data->wd_Menu)
775 FreeMenus(data->wd_Menu);
776 data->wd_Menu = NULL;
779 if (win->UserPort)
781 struct IntuiMessage *msg, *succ;
783 /* remove all messages pending for this window */
784 Forbid();
787 msg = (struct IntuiMessage *)win->UserPort->mp_MsgList.lh_Head;
788 (succ = (struct IntuiMessage *)msg->ExecMessage.mn_Node.ln_Succ);
789 msg = succ
792 if (msg->IDCMPWindow == win)
794 Remove((struct Node *)msg);
795 ReplyMsg((struct Message *)msg);
798 win->UserPort = NULL;
799 ModifyIDCMP(win, 0);
800 Permit();
803 /* D(bug("before CloseWindow\n")); */
804 CloseWindow(win);
805 /* D(bug("after CloseWindow\n")); */
808 #define DISPOSEGADGET(x) \
809 if (x)\
811 DoMethod(obj, MUIM_Window_FreeGadgetID, ((struct Gadget*)x)->GadgetID);\
812 DisposeObject(x);\
813 x = NULL;\
816 DISPOSEGADGET(data->wd_VertProp);
817 DISPOSEGADGET(data->wd_UpButton);
818 DISPOSEGADGET(data->wd_DownButton);
819 DISPOSEGADGET(data->wd_HorizProp);
820 DISPOSEGADGET(data->wd_LeftButton);
821 DISPOSEGADGET(data->wd_RightButton);
822 #undef DISPOSEGADGET
826 /* Initialize data->wd_X and data->wd_Y for DisplayWindow */
827 /* FIXME 20030817: needs some fixing, seems not fully implemented */
828 static void CalcWindowPosition(Object *obj, struct MUI_WindowData *data)
830 data->wd_XStore = data->wd_X;
831 data->wd_YStore = data->wd_Y;
832 if (NULL == data->wd_RefWindow)
834 /* The following calculations are not very correct, the size and dragbar
835 ** are ignored also the current overscan view */
836 if (data->wd_X == MUIV_Window_LeftEdge_Centered)
838 data->wd_X = (data->wd_RenderInfo.mri_Screen->Width - data->wd_Width)/2;
840 else if (data->wd_X == MUIV_Window_LeftEdge_Moused)
842 data->wd_X = data->wd_RenderInfo.mri_Screen->MouseX;
845 if (data->wd_Y == MUIV_Window_TopEdge_Centered)
847 data->wd_Y = (data->wd_RenderInfo.mri_Screen->Height - data->wd_Height)/2;
849 else if (data->wd_Y == MUIV_Window_TopEdge_Moused)
851 data->wd_Y = data->wd_RenderInfo.mri_Screen->MouseY;
853 else if (data->wd_Y <= MUIV_Window_TopEdge_Delta(0))
855 data->wd_Y = data->wd_RenderInfo.mri_Screen->BarHeight + 1
856 + MUIV_Window_TopEdge_Delta(0) - data->wd_Y;
859 else
861 ULONG w = 0, x = 0;
862 ULONG h = 0, y = 0;
864 get(data->wd_RefWindow, MUIA_Window_Width, &w);
865 get(data->wd_RefWindow, MUIA_Window_LeftEdge, &x);
867 if (data->wd_X == MUIV_Window_LeftEdge_Centered)
869 data->wd_X = x + (w - data->wd_Width)/2;
871 else
873 data->wd_X += x;
876 get(data->wd_RefWindow, MUIA_Window_Height, &h);
877 get(data->wd_RefWindow, MUIA_Window_TopEdge, &y);
879 if (data->wd_Y == MUIV_Window_TopEdge_Centered)
881 /* D(bug("y=%ld, h=%ld, wdh=%ld\n", y, h, data->wd_Height)); */
882 data->wd_Y = y + (h - data->wd_Height)/2;
884 else if (data->wd_Y <= MUIV_Window_TopEdge_Delta(0))
886 /* ??? surely incorrect implementation */
887 data->wd_Y = y + 1 + MUIV_Window_TopEdge_Delta(0) - data->wd_Y;
889 else
891 data->wd_Y += y;
896 /* Initialize data->wd_AltDim for DisplayWindow */
897 static void CalcAltDimensions(Object *obj, struct MUI_WindowData *data)
899 /* Calculate alternate (zoomed) dimensions.
901 if (data->wd_AltDim.Top == MUIV_Window_AltTopEdge_NoChange)
902 data->wd_AltDim.Top = ~0;
903 else if (data->wd_AltDim.Top == MUIV_Window_AltTopEdge_Centered)
904 data->wd_AltDim.Top = (data->wd_RenderInfo.mri_Screen->Height - data->wd_Height)/2;
905 else if (data->wd_AltDim.Top == MUIV_Window_AltTopEdge_Moused)
906 /* ? */ data->wd_AltDim.Top = ~0;
908 if (data->wd_AltDim.Left == MUIV_Window_AltLeftEdge_NoChange)
909 data->wd_AltDim.Left = ~0;
910 else if (data->wd_AltDim.Left == MUIV_Window_AltLeftEdge_Centered)
911 data->wd_AltDim.Left = (data->wd_RenderInfo.mri_Screen->Width - data->wd_Width)/2;
912 else if (data->wd_AltDim.Left == MUIV_Window_AltLeftEdge_Moused)
913 /* ? */ data->wd_AltDim.Left = ~0;
917 _between
919 MUIV_Window_AltWidth_MinMax(100),
920 data->wd_AltDim.Width,
921 MUIV_Window_AltWidth_MinMax(0)
925 data->wd_AltDim.Width = data->wd_MinMax.MinWidth
926 - data->wd_AltDim.Width
927 * (data->wd_MinMax.MaxWidth - data->wd_MinMax.MinWidth);
929 else if
931 _between
933 MUIV_Window_AltWidth_Screen(100),
934 data->wd_AltDim.Width,
935 MUIV_Window_AltWidth_Screen(0)
939 data->wd_AltDim.Width = data->wd_RenderInfo.mri_ScreenWidth
940 * (- (data->wd_AltDim.Width + 200)) / 100;
942 else if
944 _between
946 MUIV_Window_AltWidth_Visible(100),
947 data->wd_AltDim.Width,
948 MUIV_Window_AltWidth_Visible(0)
952 data->wd_AltDim.Width = data->wd_RenderInfo.mri_ScreenWidth
953 * (- (data->wd_AltDim.Width + 100)) / 100;
958 _between
960 MUIV_Window_AltHeight_MinMax(100),
961 data->wd_AltDim.Height,
962 MUIV_Window_AltHeight_MinMax(0)
966 data->wd_AltDim.Height = data->wd_MinMax.MinHeight
967 - data->wd_AltDim.Height
968 * (data->wd_MinMax.MaxHeight - data->wd_MinMax.MinHeight);
970 else if
972 _between
974 MUIV_Window_AltHeight_Screen(100),
975 data->wd_AltDim.Height,
976 MUIV_Window_AltHeight_Screen(0)
980 data->wd_AltDim.Height = data->wd_RenderInfo.mri_ScreenHeight
981 * (- (data->wd_AltDim.Height + 200)) / 100;
983 else if
985 _between
987 MUIV_Window_AltHeight_Visible(100),
988 data->wd_AltDim.Height,
989 MUIV_Window_AltHeight_Visible(0)
993 data->wd_AltDim.Height = data->wd_RenderInfo.mri_ScreenHeight
994 * (- (data->wd_AltDim.Height + 100)) / 100;
997 data->wd_AltDim.Width = CLAMP
999 data->wd_AltDim.Width, data->wd_MinMax.MinWidth,
1000 data->wd_MinMax.MaxWidth
1002 data->wd_AltDim.Height = CLAMP
1004 data->wd_AltDim.Height, data->wd_MinMax.MinHeight,
1005 data->wd_MinMax.MaxHeight
1010 /* Create horiz/vert window scrollbars for DisplayWindow */
1011 static void CreateWindowScrollbars(Object *obj, struct MUI_WindowData *data)
1013 struct MUI_RenderInfo *mri = &data->wd_RenderInfo;
1014 Object *firstgad = NULL;
1015 Object *prevgad = NULL;
1016 LONG id;
1018 /* Create the right border scrollers now if requested */
1019 if (data->wd_Flags & MUIWF_USERIGHTSCROLLER)
1021 int voffset;
1023 voffset = IM(mri->mri_DownImage)->Width / 4;
1025 id = DoMethod(obj, MUIM_Window_AllocGadgetID);
1026 firstgad = prevgad = data->wd_VertProp = NewObject
1028 NULL, "propgclass",
1030 GA_RelRight, 1 - (IM(mri->mri_UpImage)->Width - voffset),
1031 GA_Top, mri->mri_BorderTop + 2,
1032 GA_Width, IM(mri->mri_UpImage)->Width - voffset * 2,
1033 GA_RelHeight, - (mri->mri_BorderTop + 2)
1034 - IM(mri->mri_UpImage)->Height
1035 - IM(mri->mri_DownImage)->Height
1036 - IM(mri->mri_SizeImage)->Height - 2,
1037 GA_RightBorder, TRUE,
1038 GA_ID, id,
1039 PGA_Borderless, TRUE,
1040 PGA_NewLook, TRUE,
1041 PGA_Freedom, FREEVERT,
1042 PGA_Top, 0,
1043 PGA_Total, 2,
1044 PGA_Visible, 1,
1045 ICA_TARGET, ICTARGET_IDCMP,
1046 TAG_DONE
1049 id = DoMethod(obj, MUIM_Window_AllocGadgetID);
1050 prevgad = data->wd_UpButton = NewObject
1052 NULL, "buttongclass",
1054 GA_Image, (IPTR)mri->mri_UpImage,
1055 GA_RelRight, 1 - IM(mri->mri_UpImage)->Width,
1056 GA_RelBottom, 1 - IM(mri->mri_UpImage)->Height
1057 - IM(mri->mri_DownImage)->Height
1058 - IM(mri->mri_SizeImage)->Height,
1059 GA_RightBorder, TRUE,
1060 GA_Previous, (IPTR)prevgad,
1061 GA_ID, id,
1062 ICA_TARGET, ICTARGET_IDCMP,
1063 TAG_DONE
1066 id = DoMethod(obj, MUIM_Window_AllocGadgetID);
1067 prevgad = data->wd_DownButton = NewObject
1069 NULL, "buttongclass",
1071 GA_Image, (IPTR)mri->mri_DownImage,
1072 GA_RelRight, 1 - IM(mri->mri_DownImage)->Width,
1073 GA_RelBottom, 1 - IM(mri->mri_DownImage)->Height
1074 - IM(mri->mri_SizeImage)->Height,
1075 GA_RightBorder, TRUE,
1076 GA_Previous, (IPTR)prevgad,
1077 GA_ID, id,
1078 ICA_TARGET, ICTARGET_IDCMP,
1079 TAG_DONE
1081 } // if (data->wd_Flags & MUIWF_USERIGHTSCROLLER)
1083 /* Create the bottom border scrollers now if requested */
1084 if (data->wd_Flags & MUIWF_USEBOTTOMSCROLLER)
1086 int hoffset;
1088 hoffset = IM(mri->mri_RightImage)->Height / 4;
1090 id = DoMethod(obj, MUIM_Window_AllocGadgetID);
1091 prevgad = data->wd_HorizProp = NewObject
1093 NULL, "propgclass",
1095 GA_RelBottom, 1 - (IM(mri->mri_LeftImage)->Height - hoffset),
1096 GA_Left, mri->mri_BorderLeft,
1097 GA_Height, IM(mri->mri_LeftImage)->Height
1098 - hoffset * 2,
1099 GA_RelWidth, - (mri->mri_BorderLeft)
1100 - IM(mri->mri_LeftImage)->Width
1101 - IM(mri->mri_RightImage)->Width
1102 - IM(mri->mri_SizeImage)->Width
1103 - 2,
1104 GA_BottomBorder, TRUE,
1105 GA_ID, id,
1106 prevgad ? GA_Previous : TAG_IGNORE, (IPTR)prevgad,
1107 PGA_Borderless, TRUE,
1108 PGA_NewLook, TRUE,
1109 PGA_Freedom, FREEHORIZ,
1110 PGA_Top, 0,
1111 PGA_Total, 2,
1112 PGA_Visible, 1,
1113 ICA_TARGET, ICTARGET_IDCMP,
1114 TAG_DONE
1117 if (!firstgad) firstgad = prevgad;
1119 id = DoMethod(obj, MUIM_Window_AllocGadgetID);
1120 prevgad = data->wd_LeftButton = NewObject
1122 NULL, "buttongclass",
1124 GA_Image, (IPTR)mri->mri_LeftImage,
1125 GA_RelRight, 1 - IM(mri->mri_LeftImage)->Width
1126 - IM(mri->mri_RightImage)->Width
1127 - IM(mri->mri_SizeImage)->Width,
1128 GA_RelBottom, 1 - IM(mri->mri_LeftImage)->Height,
1129 GA_BottomBorder, TRUE,
1130 GA_Previous, (IPTR)prevgad,
1131 GA_ID, id,
1132 ICA_TARGET, ICTARGET_IDCMP,
1133 TAG_DONE
1136 id = DoMethod(obj, MUIM_Window_AllocGadgetID);
1137 prevgad = data->wd_RightButton = NewObject
1139 NULL, "buttongclass",
1141 GA_Image, (IPTR)mri->mri_RightImage,
1142 GA_RelRight, 1 - IM(mri->mri_RightImage)->Width
1143 - IM(mri->mri_SizeImage)->Width,
1144 GA_RelBottom, 1 - IM(mri->mri_RightImage)->Height,
1145 GA_BottomBorder, TRUE,
1146 GA_Previous, (IPTR)prevgad,
1147 GA_ID, id,
1148 ICA_TARGET, ICTARGET_IDCMP,
1149 TAG_DONE);
1150 } // if (data->wd_Flags & MUIWF_USEBOTTOMSCROLLER)
1153 /* return FALSE only if no resize (dx=dy=0) occured */
1154 static BOOL WindowResize (struct MUI_WindowData *data)
1156 struct Window *win = data->wd_RenderInfo.mri_Window;
1157 int hborders = win->BorderLeft + win->BorderRight;
1158 int vborders = win->BorderTop + win->BorderBottom;
1159 WORD dx = data->wd_Width - win->Width + hborders;
1160 WORD dy = data->wd_Height - win->Height + vborders;
1162 /* Temporarily disable window limits to let SizeWindow below work
1163 regardless of the previous limits */
1164 WindowLimits
1166 win, 1,
1171 /* D(bug("_zune_window_resize : dx=%d, dy=%d\n", dx, dy)); */
1172 SizeWindow(win, dx, dy);
1174 /* Set new window limits */
1175 WindowLimits
1177 win, data->wd_MinMax.MinWidth + hborders,
1178 data->wd_MinMax.MinHeight + vborders,
1179 data->wd_MinMax.MaxWidth + hborders,
1180 data->wd_MinMax.MaxHeight + vborders
1183 return (dx || dy);
1186 static void KillHelpBubble(struct MUI_WindowData *data, Object *obj, BOOL kill_bubblemode)
1188 if (data->wd_HelpObject)
1190 DoMethod(data->wd_HelpObject, MUIM_DeleteBubble, (IPTR)data->wd_HelpBubble);
1191 data->wd_HelpObject = NULL;
1192 data->wd_HelpBubble = NULL;
1195 if (kill_bubblemode) data->wd_Flags &= ~MUIWF_BUBBLEMODE;
1197 if (data->wd_Flags & MUIWF_BUBBLEMODE)
1199 data->wd_HelpTicker = BUBBLEHELP_TICKER_LATER;
1201 else
1203 data->wd_HelpTicker = BUBBLEHELP_TICKER_FIRST;
1208 /**************/
1210 typedef BOOL (*UNDERCHECK_FUNC)(Object *obj);
1212 static BOOL ShortHelpUnderPointerCheck(Object *obj)
1214 return muiAreaData(obj)->mad_ShortHelp ? TRUE : FALSE;
1217 static Object *ObjectUnderPointer(struct MUI_WindowData *data, Object *obj,
1218 LONG x, LONG y, UNDERCHECK_FUNC func)
1220 Object *cstate;
1221 Object *child;
1222 struct MinList *ChildList = NULL;
1224 if (!(muiAreaData(obj)->mad_Flags & MADF_CANDRAW))
1225 return NULL;
1227 if (!(x >= _left(obj) && x <= _right(obj)
1228 && y >= _top(obj) && y <= _bottom(obj)))
1230 return NULL;
1233 if ((get(obj, MUIA_Group_ChildList, &(ChildList))) && (ChildList != NULL))
1235 cstate = (Object *)ChildList->mlh_Head;
1236 while ((child = NextObject(&cstate)))
1238 Object *ret;
1240 if ((x >= _left(child) && x <= _right(child)
1242 y >= _top(child) && y <= _bottom(child))
1244 (ret = ObjectUnderPointer(data, child, x, y, func)))
1246 return ret;
1251 if (!(*func)(obj)) return NULL;
1253 return obj;
1256 static BOOL ContextMenuUnderPointer(struct MUI_WindowData *data, Object *obj, LONG x, LONG y)
1258 Object *cstate;
1259 Object *child;
1260 struct MinList *ChildList = NULL;
1262 if (!(x >= _left(obj) && x <= _right(obj)
1263 && y >= _top(obj) && y <= _bottom(obj)))
1265 return FALSE;
1268 if ((get(obj, MUIA_Group_ChildList, &(ChildList))) && (ChildList != NULL))
1271 cstate = (Object *)ChildList->mlh_Head;
1272 while ((child = NextObject(&cstate)))
1274 if ((x >= _left(child) && x <= _right(child)
1276 y >= _top(child) && y <= _bottom(child))
1278 (ContextMenuUnderPointer(data,child,x,y)))
1279 return TRUE;
1283 if (!(muiAreaData(obj)->mad_Flags & MADF_CANDRAW))
1284 return FALSE;
1285 if (!(muiAreaData(obj)->mad_ContextMenu))
1286 return FALSE;
1288 return TRUE;
1291 /**************/
1293 static void ActivateObject (struct MUI_WindowData *data)
1295 //bug("Window::ActivateObject (dummy) %08lx\n", data->wd_ActiveObject);
1296 // if (FindObjNode(&data->wd_CycleChain, data->wd_ActiveObject))
1297 // DoMethod(data->wd_ActiveObject, MUIM_GoActive);
1298 // else
1299 // data->wd_ActiveObject = NULL;
1300 //activate better string gadgets.Fix from Georg S On ML List
1301 if (FindObjNode(&data->wd_CycleChain, data->wd_ActiveObject))
1303 if (!(data->wd_Flags & MUIWF_OBJECTGOACTIVESENT))
1305 data->wd_Flags |= MUIWF_OBJECTGOACTIVESENT;
1306 DoMethod(data->wd_ActiveObject, MUIM_GoActive);
1309 else
1310 data->wd_ActiveObject = NULL;
1314 /**************/
1316 static void HandleInputEvent(Object *win, struct MUI_WindowData *data,
1317 struct IntuiMessage *event);
1319 /* handle intuimessage while an object is being dragged
1320 * (reply imsg before returning)
1322 void HandleDragging (Object *oWin, struct MUI_WindowData *data,
1323 struct IntuiMessage *imsg)
1325 struct Window *iWin;
1326 int finish_drag = 0;
1328 iWin = imsg->IDCMPWindow;
1330 if (imsg->Class == IDCMP_MOUSEMOVE)
1332 struct Layer *layer;
1333 layer = WhichLayer(&iWin->WScreen->LayerInfo, iWin->LeftEdge + imsg->MouseX, iWin->TopEdge + imsg->MouseY);
1335 if (data->wd_DropObject)
1337 struct Window *wnd;
1338 WORD mousex = imsg->MouseX + iWin->LeftEdge - data->wd_DropWindow->LeftEdge;
1339 WORD mousey = imsg->MouseY + iWin->TopEdge - data->wd_DropWindow->TopEdge;
1341 wnd = _window(data->wd_DropObject);
1344 mousex < _left(data->wd_DropObject)
1345 || mousex > _right(data->wd_DropObject)
1346 || mousey < _top(data->wd_DropObject)
1347 || mousey > _bottom(data->wd_DropObject)
1348 || layer != wnd->WLayer
1351 /* We have left the object */
1352 UndrawDragNDrop(data->wd_dnd);
1353 DoMethod(data->wd_DropObject, MUIM_DragFinish,(IPTR)data->wd_DragObject);
1354 data->wd_DropObject = NULL;
1356 } /* if (data->wd_DropObject) */
1358 if (!data->wd_DropObject)
1360 Object *dest_wnd = NULL;
1362 /* Find out if app has an openend window at this position */
1363 if (layer)
1365 Object *cstate;
1366 Object *child;
1367 struct MinList *ChildList;
1369 get(_app(oWin), MUIA_Application_WindowList, &(ChildList));
1370 cstate = (Object *)ChildList->mlh_Head;
1371 while ((child = NextObject(&cstate)))
1373 struct Window *wnd;
1374 get(child, MUIA_Window_Window,&wnd);
1375 if (!wnd) continue;
1377 if (wnd->WLayer == layer)
1379 data->wd_DropWindow = wnd;
1380 dest_wnd = child;
1381 break;
1384 } /* if (layer) */
1386 if (dest_wnd)
1388 Object *root;
1389 get(dest_wnd, MUIA_Window_RootObject, &root);
1391 if (root)
1396 data->wd_DropObject = (Object*) DoMethod
1398 root, MUIM_DragQueryExtended,
1399 (IPTR) data->wd_DragObject,
1400 imsg->MouseX + iWin->LeftEdge - data->wd_DropWindow->LeftEdge,
1401 imsg->MouseY + iWin->TopEdge - data->wd_DropWindow->TopEdge
1406 UndrawDragNDrop(data->wd_dnd);
1407 DoMethod(data->wd_DropObject, MUIM_DragBegin,(IPTR)data->wd_DragObject);
1410 } /* if (dest_wnd) */
1411 } /* if (!data->wd_DropObject) */
1413 if (data->wd_DropObject)
1415 LONG update = 0;
1416 LONG i;
1417 for (i=0;i<2;i++)
1419 LONG res = DoMethod
1421 data->wd_DropObject, MUIM_DragReport,
1422 (IPTR) data->wd_DragObject,
1423 imsg->MouseX + iWin->LeftEdge - data->wd_DropWindow->LeftEdge,
1424 imsg->MouseY + iWin->TopEdge - data->wd_DropWindow->TopEdge,update
1426 switch (res)
1428 case MUIV_DragReport_Abort:
1429 UndrawDragNDrop(data->wd_dnd);
1430 DoMethod(data->wd_DropObject, MUIM_DragFinish,(IPTR)data->wd_DragObject);
1431 data->wd_DropObject = NULL;
1432 i = 1;
1433 break;
1435 case MUIV_DragReport_Continue: break;
1436 case MUIV_DragReport_Lock: break; /* NYI */
1437 case MUIV_DragReport_Refresh:
1438 UndrawDragNDrop(data->wd_dnd);
1439 update = 1;
1440 break;
1443 } /* if (data->wd_DropObject) */
1444 DrawDragNDrop(data->wd_dnd, imsg->MouseX + iWin->LeftEdge , imsg->MouseY + iWin->TopEdge);
1445 } /* if (imsg->Class == IDCMP_MOUSEMOVE) */
1447 if (imsg->Class == IDCMP_MOUSEBUTTONS)
1449 if ((imsg->Code == MENUDOWN) || (imsg->Code == SELECTUP))
1451 if (imsg->Code == SELECTUP && data->wd_DropObject)
1453 UndrawDragNDrop(data->wd_dnd);
1454 DoMethod(data->wd_DropObject, MUIM_DragFinish, (IPTR)data->wd_DragObject);
1455 DoMethod
1457 data->wd_DropObject, MUIM_DragDrop, (IPTR)data->wd_DragObject,
1458 imsg->MouseX + iWin->LeftEdge - data->wd_DropWindow->LeftEdge,
1459 imsg->MouseY + iWin->TopEdge - data->wd_DropWindow->TopEdge
1461 data->wd_DropObject = NULL;
1463 else if (imsg->Code == SELECTUP)
1465 DoMethod(data->wd_DragObject, MUIM_UnknownDropDestination, imsg);
1467 finish_drag = 1;
1471 if (imsg->Class == IDCMP_CLOSEWINDOW)
1472 finish_drag = 1;
1474 if (finish_drag)
1476 UndrawDragNDrop(data->wd_dnd);
1477 if (data->wd_DropObject)
1479 DoMethod(data->wd_DropObject, MUIM_DragFinish,(IPTR)data->wd_DragObject);
1480 data->wd_DropObject = NULL;
1482 DeleteDragNDrop(data->wd_dnd);
1483 DoMethod(data->wd_DragObject,MUIM_DeleteDragImage, (IPTR)data->wd_DragImage);
1484 muiAreaData(data->wd_DragObject)->mad_Flags &= ~MADF_DRAGGING;
1485 data->wd_DragImage = NULL;
1486 data->wd_DragObject = NULL;
1487 data->wd_DropWindow = NULL;
1488 data->wd_dnd = NULL;
1489 /* stop listening to IDCMP_MOUSEMOVE */
1490 ChangeEvents(data, GetDefaultEvents());
1492 ReplyMsg((struct Message*)imsg);
1495 /* Reply to imsg if handled */
1496 BOOL HandleWindowEvent (Object *oWin, struct MUI_WindowData *data,
1497 struct IntuiMessage *imsg)
1499 struct Window *iWin;
1500 BOOL is_handled = TRUE;
1501 BOOL replied = FALSE;
1503 iWin = imsg->IDCMPWindow;
1504 switch (imsg->Class)
1506 case IDCMP_ACTIVEWINDOW:
1507 data->wd_Flags |= MUIWF_ACTIVE;
1508 if (data->wd_OldActive)
1509 set(oWin, MUIA_Window_ActiveObject, data->wd_OldActive);
1510 set(oWin, MUIA_Window_Activate, TRUE);
1511 is_handled = FALSE; /* forwardable to area event handlers */
1512 break;
1514 case IDCMP_INACTIVEWINDOW:
1515 KillHelpBubble(data, oWin, TRUE);
1516 if (data->wd_ActiveObject)
1518 data->wd_OldActive = data->wd_ActiveObject;
1519 set(oWin, MUIA_Window_ActiveObject, MUIV_Window_ActiveObject_None);
1521 data->wd_Flags &= ~MUIWF_ACTIVE;
1522 set(oWin, MUIA_Window_Activate, FALSE);
1523 is_handled = FALSE; /* forwardable to area event handlers */
1524 break;
1526 case IDCMP_NEWSIZE:
1527 ReplyMsg((struct Message*)imsg);
1528 replied = TRUE;
1531 int hborders = iWin->BorderLeft + iWin->BorderRight;
1532 int vborders = iWin->BorderTop + iWin->BorderBottom;
1534 /* set window limits according to window contents */
1535 WindowLimits (
1536 iWin,
1537 data->wd_MinMax.MinWidth + hborders,
1538 data->wd_MinMax.MinHeight + vborders,
1539 data->wd_MinMax.MaxWidth + hborders,
1540 data->wd_MinMax.MaxHeight + vborders
1544 if ((iWin->GZZWidth != data->wd_Width) || (iWin->GZZHeight != data->wd_Height))
1546 data->wd_Width = iWin->GZZWidth;
1547 data->wd_Height = iWin->GZZHeight;
1548 DoHideMethod(data->wd_RootObject);
1550 if (1) // why only simple refresh? was: if (data->wd_RenderInfo.mri_Window->Flags & WFLG_SIMPLE_REFRESH)
1552 data->wd_Flags |= MUIWF_RESIZING;
1554 else
1556 _width(data->wd_RootObject) = data->wd_Width;
1557 _height(data->wd_RootObject) = data->wd_Height;
1558 DoMethod(data->wd_RootObject, MUIM_Layout);
1559 DoShowMethod(data->wd_RootObject);
1561 LONG left,top,width,height;
1563 left = data->wd_RenderInfo.mri_Window->BorderLeft;
1564 top = data->wd_RenderInfo.mri_Window->BorderTop,
1565 width = data->wd_RenderInfo.mri_Window->Width
1566 - data->wd_RenderInfo.mri_Window->BorderRight - left;
1567 height = data->wd_RenderInfo.mri_Window->Height
1568 - data->wd_RenderInfo.mri_Window->BorderBottom - top;
1570 // D(bug("%d:zune_imspec_draw(%p) l=%d t=%d w=%d h=%d xo=%d yo=%d\n",
1571 // __LINE__, data->wd_Background, left, top, width,
1572 // height, left, top));
1573 zune_imspec_draw(data->wd_Background, &data->wd_RenderInfo,
1574 left, top, width, height, left, top, 0);
1576 if (muiGlobalInfo(oWin)->mgi_Prefs->window_redraw == WINDOW_REDRAW_WITHOUT_CLEAR)
1577 MUI_Redraw(data->wd_RootObject, MADF_DRAWOBJECT);
1578 else
1579 MUI_Redraw(data->wd_RootObject, MADF_DRAWALL);
1580 // but should only draw focus without using MUIM_GoActive !
1581 ActivateObject(data);
1584 break;
1586 case IDCMP_REFRESHWINDOW:
1587 ReplyMsg((struct Message*)imsg);
1588 replied = TRUE;
1589 if (data->wd_Flags & MUIWF_RESIZING)
1591 //LONG left,top,right,bottom;
1592 if (MUI_BeginRefresh(&data->wd_RenderInfo, 0))
1594 MUI_EndRefresh(&data->wd_RenderInfo, 0);
1596 RefreshWindowFrame(data->wd_RenderInfo.mri_Window);
1598 data->wd_Flags &= ~MUIWF_RESIZING;
1599 _width(data->wd_RootObject) = data->wd_Width;
1600 _height(data->wd_RootObject) = data->wd_Height;
1601 DoMethod(data->wd_RootObject, MUIM_Layout);
1602 DoShowMethod(data->wd_RootObject);
1604 if (muiGlobalInfo(oWin)->mgi_Prefs->window_redraw == WINDOW_REDRAW_WITH_CLEAR)
1606 LONG left,top,width,height;
1608 left = data->wd_RenderInfo.mri_Window->BorderLeft;
1609 top = data->wd_RenderInfo.mri_Window->BorderTop,
1610 width = data->wd_RenderInfo.mri_Window->Width - data->wd_RenderInfo.mri_Window->BorderRight - left;
1611 height = data->wd_RenderInfo.mri_Window->Height - data->wd_RenderInfo.mri_Window->BorderBottom - top;
1613 if(data->wd_Flags & MUIWF_ERASEAREA)
1615 // D(bug("%d:zune_imspec_draw(%p) l=%d t=%d w=%d h=%d xo=%d yo=%d\n",
1616 // __LINE__, data->wd_Background, left, top, width,
1617 // height, left, top));
1618 zune_imspec_draw(data->wd_Background, &data->wd_RenderInfo,
1619 left, top, width, height, left, top, 0);
1621 MUI_Redraw(data->wd_RootObject, MADF_DRAWALL);
1623 else
1624 MUI_Redraw(data->wd_RootObject, MADF_DRAWOBJECT);
1625 // but should only draw focus without using MUIM_GoActive !
1626 ActivateObject(data);
1628 else
1630 if (MUI_BeginRefresh(&data->wd_RenderInfo, 0))
1632 MUI_Redraw(data->wd_RootObject, MADF_DRAWALL);
1633 // but should only draw focus without using MUIM_GoActive !
1634 ActivateObject(data);
1635 MUI_EndRefresh(&data->wd_RenderInfo, 0);
1638 break;
1640 case IDCMP_CLOSEWINDOW:
1641 ReplyMsg((struct Message*)imsg);
1642 replied = TRUE;
1643 set(oWin, MUIA_Window_CloseRequest, TRUE);
1644 break;
1646 case IDCMP_MENUPICK:
1647 ReplyMsg((struct Message*)imsg);
1648 replied = TRUE;
1650 if (data->wd_Menu)
1652 if (MENUNUM(imsg->Code) != NOMENU && ITEMNUM(imsg->Code) != NOITEM)
1654 struct MenuItem *item = ItemAddress(data->wd_Menu,imsg->Code);
1655 if (item)
1657 Object *item_obj = (Object*)GTMENUITEM_USERDATA(item);
1658 if (item_obj)
1660 Object *app;
1661 IPTR udata;
1663 if (item->Flags & CHECKIT)
1664 set(item_obj, MUIA_Menuitem_Checked, !!(item->Flags & CHECKED));
1666 set(item_obj, MUIA_Menuitem_Trigger, (IPTR)item);
1668 get(oWin, MUIA_ApplicationObject, &app);
1669 get(item_obj, MUIA_UserData, &udata);
1671 set(app, MUIA_Application_MenuAction, udata);
1672 set(oWin, MUIA_Window_MenuAction, udata);
1673 DoMethod(app, MUIM_Application_ReturnID, udata);
1678 break;
1680 case IDCMP_IDCMPUPDATE:
1681 is_handled = FALSE; /* forwardable to area event handlers */
1682 if (data->wd_VertProp || data->wd_HorizProp)
1684 struct TagItem *tag;
1685 tag = FindTagItem(GA_ID,(struct TagItem*)imsg->IAddress);
1686 if (tag)
1688 /* If there's a propclass object connected to the prop
1689 gadget, the prop gadget's userdata will point to
1690 that propclass object. See classes/prop.c */
1692 if (data->wd_VertProp)
1694 if (tag->ti_Data == GADGETID(data->wd_VertProp))
1697 if (tag->ti_Data == GADGETID(data->wd_UpButton))
1699 Object *prop = (Object *)((struct Gadget *)data->wd_VertProp)->UserData;
1700 is_handled = TRUE;
1701 if (prop) DoMethod(prop, MUIM_Prop_Decrease, 1);
1704 if (tag->ti_Data == GADGETID(data->wd_DownButton))
1706 Object *prop = (Object *)((struct Gadget *)data->wd_VertProp)->UserData;
1707 is_handled = TRUE;
1708 if (prop) DoMethod(prop, MUIM_Prop_Increase, 1);
1713 if (data->wd_HorizProp)
1715 if (tag->ti_Data == GADGETID(data->wd_HorizProp))
1718 if (tag->ti_Data == GADGETID(data->wd_LeftButton))
1720 Object *prop = (Object *)((struct Gadget *)data->wd_HorizProp)->UserData;
1721 is_handled = TRUE;
1722 if (prop) DoMethod(prop, MUIM_Prop_Decrease, 1);
1725 if (tag->ti_Data == GADGETID(data->wd_RightButton))
1727 Object *prop = (Object *)((struct Gadget *)data->wd_HorizProp)->UserData;
1728 is_handled = TRUE;
1729 if (prop) DoMethod(prop, MUIM_Prop_Increase, 1);
1735 break;
1737 case IDCMP_INTUITICKS:
1738 if (data->wd_HelpTicker)
1740 data->wd_HelpTicker--;
1742 if (data->wd_HelpTicker == 0)
1744 Object *underobj = ObjectUnderPointer(data, data->wd_RootObject, imsg->MouseX, imsg->MouseY,
1745 ShortHelpUnderPointerCheck);
1747 if (underobj != data->wd_HelpObject)
1749 if (data->wd_HelpObject)
1751 DoMethod(data->wd_HelpObject, MUIM_DeleteBubble, (IPTR)data->wd_HelpBubble);
1753 data->wd_HelpObject = NULL;
1754 data->wd_HelpBubble = NULL;
1757 if (underobj)
1759 data->wd_HelpBubble = (APTR)DoMethod(underobj, MUIM_CreateBubble,
1760 imsg->MouseX, imsg->MouseY,
1761 0, 0);
1762 if (data->wd_HelpBubble)
1764 data->wd_HelpObject = underobj;
1765 data->wd_Flags |= MUIWF_BUBBLEMODE;
1770 if (data->wd_Flags & MUIWF_BUBBLEMODE)
1772 data->wd_HelpTicker = BUBBLEHELP_TICKER_LATER;
1774 else
1776 data->wd_HelpTicker = BUBBLEHELP_TICKER_FIRST;
1779 } /* if (data->wd_HelpTicker == 0) */
1781 } /* if (data->wd_HelpTicker) */
1783 is_handled = FALSE; /* forwardable to area event handlers */
1784 break;
1786 case IDCMP_MOUSEBUTTONS:
1787 DoMethod(oWin,MUIM_Window_Snapshot,0);
1788 KillHelpBubble(data, oWin, TRUE);
1789 is_handled = FALSE;
1790 break;
1793 case IDCMP_MOUSEMOVE:
1794 KillHelpBubble(data, oWin, FALSE);
1795 is_handled = FALSE;
1796 break;
1798 default:
1799 is_handled = FALSE;
1800 break;
1801 } /* switch (imsg->Class) */
1803 if (is_handled && !replied)
1804 ReplyMsg((struct Message*)imsg);
1806 return is_handled;
1809 static ULONG InvokeEventHandler (struct MUI_EventHandlerNode *ehn,
1810 struct IntuiMessage *event, ULONG muikey)
1812 ULONG res;
1814 if (!(_flags(ehn->ehn_Object) & MADF_CANDRAW)) return 0;
1815 if (!(_flags(ehn->ehn_Object) & MADF_SHOWME)) return 0;
1819 event != NULL
1820 && event->Class == IDCMP_MOUSEBUTTONS
1821 && event->Code == SELECTDOWN
1822 && (_flags(ehn->ehn_Object) & MADF_INVIRTUALGROUP)
1826 Here we filter out SELECTDOWN messages if objects is in a virtual
1827 group but the click went out of the virtual group
1829 Object *obj = ehn->ehn_Object;
1830 Object *parent = obj;
1831 Object *wnd = _win(obj);
1833 while (get(parent,MUIA_Parent,&parent))
1835 if (!parent) break;
1836 if (wnd == parent) break;
1837 if (_flags(parent) & MADF_ISVIRTUALGROUP)
1841 event->MouseX < _mleft(parent)
1842 || event->MouseX > _mright(parent)
1843 || event->MouseY < _mtop(parent)
1844 || event->MouseY > _mbottom(parent)
1847 return 0;
1854 if (ehn->ehn_Flags & MUI_EHF_HANDLEINPUT)
1856 DoMethod(ehn->ehn_Object, MUIM_HandleInput, (IPTR)event, muikey);
1857 res = 0;
1859 else
1861 if (ehn->ehn_Class)
1862 res = CoerceMethod
1864 ehn->ehn_Class, ehn->ehn_Object, MUIM_HandleEvent,
1865 (IPTR)event, muikey
1867 else
1868 res = DoMethod(ehn->ehn_Object, MUIM_HandleEvent, (IPTR)event, muikey);
1870 return res;
1873 static void HandleRawkey(Object *win, struct MUI_WindowData *data,
1874 struct IntuiMessage *event)
1876 struct MinNode *mn;
1877 struct MUI_EventHandlerNode *ehn;
1878 struct IntuiMessage imsg_copy;
1879 struct InputEvent ie = {0};
1880 ULONG res;
1881 LONG muikey = MUIKEY_NONE;
1882 Object *active_object = NULL;
1883 IPTR disabled;
1884 ULONG key;
1885 ULONG deadkey;
1887 KillHelpBubble(data, win, BUBBLEHELP_TICKER_FIRST);
1889 ie.ie_NextEvent = NULL;
1890 ie.ie_Class = IECLASS_RAWKEY;
1891 ie.ie_SubClass = 0;
1892 ie.ie_Code = event->Code;
1893 ie.ie_Qualifier = event->Qualifier;
1894 ie.ie_EventAddress = (APTR)*(ULONG *)event->IAddress;
1895 #ifdef __AMIGAOS4__
1896 ie.ie_TimeStamp.Seconds = event->Seconds;
1897 ie.ie_TimeStamp.Microseconds = event->Micros;
1898 #else
1899 ie.ie_TimeStamp.tv_secs = event->Seconds;
1900 ie.ie_TimeStamp.tv_micro = event->Micros;
1901 #endif
1903 set(win, MUIA_Window_InputEvent, (IPTR)&ie);
1905 /* get the vanilla key for control char */
1907 UWORD msg_code;
1908 /* Remove the up prefix as convert key does not convert a upkey event */
1909 msg_code = event->Code;
1910 event->Code &= ~IECODE_UP_PREFIX;
1911 key = ConvertKey(event);
1912 event->Code = msg_code;
1915 imsg_copy = *event;
1916 deadkey = *(ULONG *)event->IAddress;
1917 imsg_copy.IAddress = &deadkey;
1918 ReplyMsg((struct Message*)event);
1919 event = &imsg_copy;
1921 //bug("rawkey: code=%lx, qual=%lx\n", event->Code, event->Qualifier);
1923 /* check if imsg translate to predefined keystroke */
1925 struct InputEvent ievent;
1926 BOOL matched = FALSE;
1928 ievent.ie_NextEvent = NULL;
1929 ievent.ie_Class = IECLASS_RAWKEY;
1930 ievent.ie_SubClass = 0;
1931 ievent.ie_Code = event->Code;
1932 ievent.ie_Qualifier = event->Qualifier;
1933 /* ie_EventAddress is not used by MatchIX. If needed, it should be
1934 * ensured that it is still a valid adress because of the shallow
1935 * IntuiMessage copy currently done in _zune_window_message before
1936 * message is replied.
1938 ievent.ie_EventAddress = NULL;
1939 //ievent.ie_EventAddress = (APTR *) *((ULONG *)(event->IAddress));
1941 for (muikey = MUIKEY_COUNT - 1; muikey >= MUIKEY_PRESS; muikey--)
1943 if (muiGlobalInfo(win)->mgi_Prefs->muikeys[muikey].ix_well != 0
1944 && MatchIX(&ievent, &muiGlobalInfo(win)->mgi_Prefs->muikeys[muikey].ix))
1946 matched = TRUE;
1947 break;
1951 if (matched)
1953 if (muikey == MUIKEY_PRESS && (event->Code & IECODE_UP_PREFIX))
1954 muikey = MUIKEY_RELEASE;
1956 else
1958 muikey = MUIKEY_NONE;
1960 } /* check if imsg translate to predefined keystroke */
1962 if ((muikey != MUIKEY_NONE)
1963 && !(data->wd_DisabledKeys & (1<<muikey)))
1965 D(bug("HandleRawkey: try MUIKEY %ld on window %0x08lx\n", muikey, win));
1966 switch (muikey)
1968 case MUIKEY_PRESS: break;
1969 case MUIKEY_TOGGLE: break;
1970 case MUIKEY_UP: break;
1971 case MUIKEY_DOWN: break;
1972 case MUIKEY_PAGEUP: break;
1973 case MUIKEY_PAGEDOWN: break;
1974 case MUIKEY_TOP: break;
1975 case MUIKEY_BOTTOM: break;
1976 case MUIKEY_LEFT: break;
1977 case MUIKEY_RIGHT: break;
1978 case MUIKEY_WORDLEFT: break;
1979 case MUIKEY_WORDRIGHT: break;
1980 case MUIKEY_LINESTART: break;
1981 case MUIKEY_LINEEND: break;
1982 case MUIKEY_GADGET_NEXT:
1983 set(win, MUIA_Window_ActiveObject, MUIV_Window_ActiveObject_Next);
1984 break;
1985 case MUIKEY_GADGET_PREV:
1986 set(win, MUIA_Window_ActiveObject, MUIV_Window_ActiveObject_Prev);
1987 break;
1988 case MUIKEY_GADGET_OFF:
1989 set(win, MUIA_Window_ActiveObject, MUIV_Window_ActiveObject_None);
1990 break;
1991 case MUIKEY_WINDOW_CLOSE:
1992 set(win, MUIA_Window_CloseRequest, TRUE);
1993 break;
1994 case MUIKEY_WINDOW_NEXT: break;
1995 case MUIKEY_WINDOW_PREV: break;
1996 case MUIKEY_HELP: break;
1997 case MUIKEY_POPUP: break;
1998 default: break;
2002 active_object = NULL;
2003 if ((data->wd_ActiveObject != NULL)
2004 && (DoMethod(data->wd_RootObject, MUIM_FindAreaObject,
2005 (IPTR)data->wd_ActiveObject) != (IPTR)NULL))
2007 active_object = data->wd_ActiveObject;
2008 get(active_object, MUIA_Disabled, &disabled);
2010 else
2011 data->wd_ActiveObject = NULL;
2013 /* try ActiveObject */
2014 if ((active_object != NULL) && !disabled)
2016 #if 0
2017 /* sba:
2018 ** Which method should be used for muikeys? MUIM_HandleInput or
2019 ** MUIM_HandleEvent. Also note that there is a flag MUI_EHF_ALWAYSKEYS
2020 ** which probably means that all keys events are requested??
2021 ** For now MUIM_HandleEvent is used as this is currently implemented
2022 ** in Area class ;) although I guess it should be MUIM_HandleInput as this
2023 ** was earlier
2026 if (muikey != MUIKEY_NONE)
2028 res = DoMethod(active_object, MUIM_HandleEvent, (IPTR)event, muikey);
2029 if (res & MUI_EventHandlerRC_Eat) return;
2031 #endif
2032 D(bug("HandleRawkey: try active object (%08lx) handlers\n", active_object));
2034 for (mn = data->wd_EHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
2036 ehn = (struct MUI_EventHandlerNode *)mn;
2038 if ((ehn->ehn_Object == active_object)
2039 && ((ehn->ehn_Events & IDCMP_RAWKEY)
2040 || (ehn->ehn_Flags & MUI_EHF_ALWAYSKEYS)))
2042 D(bug("HandleRawkey: (active) invoking on %p (ehn=%p) event=%p muikey=%p\n",
2043 ehn->ehn_Object, ehn, event, muikey));
2044 res = InvokeEventHandler(ehn, event, muikey);
2045 D(bug("HandleRawkey: (active) got res=%d\n", res));
2046 if (res & MUI_EventHandlerRC_Eat)
2047 return;
2049 /* Leave the loop if a different object has been activated */
2050 if (active_object != data->wd_ActiveObject)
2051 break;
2053 } /* for (mn = data->wd_EHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ) */
2055 // event not eaten by active object, try its parents
2056 // this is to implement popup key in Popstring
2057 if (active_object == data->wd_ActiveObject)
2059 Object *current_obj = active_object;
2061 D(bug("HandleRawkey: try active object parents handlers\n"));
2062 while (current_obj != NULL)
2064 for (mn = data->wd_EHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
2066 ehn = (struct MUI_EventHandlerNode *)mn;
2068 if ((ehn->ehn_Object == current_obj)
2069 && ((ehn->ehn_Events & IDCMP_RAWKEY)
2070 || (ehn->ehn_Flags & MUI_EHF_ALWAYSKEYS)))
2072 //D(bug("HandleRawkey: (active parents) invoking on %p (ehn=%p) "
2073 //"event=%p muikey=%p\n",
2074 //ehn->ehn_Object, ehn, event, muikey));
2075 res = InvokeEventHandler(ehn, event, muikey);
2076 //D(bug("HandleRawkey: (active parents) got res=%d\n", res));
2077 if (res & MUI_EventHandlerRC_Eat)
2078 return;
2080 /* Leave the loop if a different object has been activated */
2081 if (active_object != data->wd_ActiveObject)
2082 break;
2085 current_obj = (Object *)XGET(current_obj, MUIA_Parent);
2086 } // while (current_obj != NULL)
2090 } /* if (active_object && !disabled) */
2092 D(bug("HandleRawkey: try default object handlers\n"));
2094 /* try DefaultObject */
2095 if (data->wd_DefaultObject != NULL)
2096 get(data->wd_DefaultObject, MUIA_Disabled, &disabled);
2098 if ((data->wd_DefaultObject != NULL) && !disabled
2099 && (active_object != data->wd_DefaultObject))
2101 /* No, we only should do this if the object actually has requested this via RequestIDCMP()! */
2102 // if (muikey != MUIKEY_NONE && (_flags(data->wd_DefaultObject) & MADF_CANDRAW))
2103 // {
2104 // DoMethod(data->wd_DefaultObject, MUIM_HandleInput, event, muikey);
2105 // return;
2106 // }
2108 for (mn = data->wd_EHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
2110 ehn = (struct MUI_EventHandlerNode *)mn;
2112 if ((ehn->ehn_Object == data->wd_DefaultObject)
2113 && ((ehn->ehn_Events & IDCMP_RAWKEY)
2114 || (ehn->ehn_Flags & MUI_EHF_ALWAYSKEYS)))
2116 //D(bug("HandleRawkey: (default) invoking on %p (ehn=%p) event=%p muikey=%p\n",
2117 //ehn->ehn_Object, ehn, event, muikey));
2118 res = InvokeEventHandler(ehn, event, muikey);
2119 //D(bug("HandleRawkey: (default) got res=%d\n", res));
2120 if (res & MUI_EventHandlerRC_Eat)
2121 return;
2125 } /* if ... default object */
2127 D(bug("HandleRawkey: try other handlers\n"));
2129 // try other handlers
2130 for (mn = data->wd_EHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
2132 ehn = (struct MUI_EventHandlerNode *)mn;
2134 // skip Active and Default object as they have already been
2135 // handled
2136 if (ehn->ehn_Object == data->wd_ActiveObject
2137 || ehn->ehn_Object == data->wd_DefaultObject)
2138 continue;
2140 if (ehn->ehn_Events & IDCMP_RAWKEY)
2142 //D(bug("HandleRawkey: (others) invoking on %p (ehn=%p) event=%p muikey=%p\n",
2143 //ehn->ehn_Object, ehn, event, muikey));
2144 res = InvokeEventHandler(ehn, event, MUIKEY_NONE);
2145 //D(bug("HandleRawkey: (others) got res=%d\n", res));
2146 if (res & MUI_EventHandlerRC_Eat)
2147 return;
2149 } /* for (mn = data->wd_EHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ) */
2151 D(bug("HandleRawkey: try control chars handlers\n"));
2153 /* try Control Chars */
2154 //bug("ctrlchar, key='%c' code=0x%08lx\n", key, event->Code);
2155 if (key)
2157 for (mn = data->wd_CCList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
2159 ehn = (struct MUI_EventHandlerNode *)mn;
2161 if (ehn->ehn_Events == key)
2163 IPTR disabled;
2164 LONG muikey2 = ehn->ehn_Flags;
2166 get(ehn->ehn_Object, MUIA_Disabled, &disabled);
2167 if (disabled)
2168 continue;
2170 //bug("control char\n");
2171 if (event->Code & IECODE_UP_PREFIX)
2173 /* simulate a release */
2174 if (muikey2 == MUIKEY_PRESS)
2175 muikey2 = MUIKEY_RELEASE;
2176 else
2177 return;
2180 if ((muikey2 != MUIKEY_NONE)
2181 && (_flags(ehn->ehn_Object) & MADF_CANDRAW)
2182 && (_flags(ehn->ehn_Object) & MADF_SHOWME))
2184 res = CoerceMethod
2186 ehn->ehn_Class, ehn->ehn_Object, MUIM_HandleEvent,
2187 (IPTR)NULL, muikey2
2189 if (res & MUI_EventHandlerRC_Eat)
2190 return;
2194 } /* try control chars */
2197 /* forward non-keystroke events to event handlers */
2198 static void HandleInputEvent(Object *win, struct MUI_WindowData *data,
2199 struct IntuiMessage *event)
2201 struct MinNode *mn;
2202 struct MUI_EventHandlerNode *ehn;
2203 struct IntuiMessage imsg_copy;
2204 ULONG res;
2205 ULONG mask = event->Class;
2207 if (mask != IDCMP_IDCMPUPDATE)
2209 imsg_copy = *event;
2210 imsg_copy.IAddress = NULL; /* be sure to trap access to that */
2211 ReplyMsg((struct Message*)event);
2212 event = &imsg_copy;
2215 if (mask == IDCMP_MOUSEMOVE)
2217 struct Window *iWin;
2218 iWin = event->IDCMPWindow;
2220 if (ContextMenuUnderPointer (data, data->wd_RootObject,
2221 event->MouseX, event->MouseY))
2223 iWin->Flags |= WFLG_RMBTRAP;
2225 else if (!data->wd_NoMenus)
2227 iWin->Flags &= ~WFLG_RMBTRAP;
2231 for (mn = data->wd_EHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
2233 ehn = (struct MUI_EventHandlerNode *)mn;
2235 if (ehn->ehn_Events & mask)
2237 IPTR disabled;
2239 get(ehn->ehn_Object, MUIA_Disabled, &disabled);
2240 if (disabled)
2241 continue;
2243 res = InvokeEventHandler(ehn, event, MUIKEY_NONE);
2244 if (res & MUI_EventHandlerRC_Eat)
2245 return;
2250 if (mask == IDCMP_IDCMPUPDATE)
2251 ReplyMsg((struct Message*)event);
2255 /* process window message, this does a ReplyMsg() to the message */
2256 /* Called from application.c */
2257 void _zune_window_message(struct IntuiMessage *imsg)
2259 struct Window *iWin;
2260 Object *oWin;
2261 struct MUI_WindowData *data;
2262 BOOL handled;
2264 iWin = imsg->IDCMPWindow;
2265 oWin = (Object *)iWin->UserData;
2266 data = muiWindowData(oWin);
2268 if (data->wd_DragObject)
2270 HandleDragging(oWin, data, imsg);
2271 return;
2274 handled = HandleWindowEvent(oWin, data, imsg);
2275 if (!handled)
2277 if (IDCMP_RAWKEY == imsg->Class)
2278 HandleRawkey(oWin, data, imsg);
2279 else if (IDCMP_GADGETUP == imsg->Class)
2281 #ifdef __AROS__
2282 if (ETI_MUI == ((struct Gadget *) imsg->IAddress)->GadgetID)
2284 DoMethod(_app(oWin), MUIM_Application_OpenConfigWindow);
2286 #endif
2288 else
2290 HandleInputEvent(oWin, data, imsg);
2296 /******************************************************************************/
2297 /******************************************************************************/
2299 /* code for setting MUIA_Window_RootObject */
2300 static void ChangeRootObject (struct MUI_WindowData *data, Object *obj,
2301 Object *newRoot)
2303 Object *oldRoot;
2305 ASSERT_VALID_PTR(data);
2306 ASSERT_VALID_PTR(obj);
2308 oldRoot = data->wd_RootObject;
2309 if (!(data->wd_Flags & MUIWF_OPENED))
2311 if (oldRoot)
2313 if (data->wd_ActiveObject == oldRoot)
2314 set(obj, MUIA_Window_ActiveObject, MUIV_Window_ActiveObject_None);
2315 DoMethod(oldRoot, MUIM_DisconnectParent);
2318 data->wd_RootObject = newRoot;
2319 if (newRoot)
2321 /* if window is in App tree, inform child */
2322 if (muiNotifyData(obj)->mnd_GlobalInfo)
2323 DoMethod(newRoot, MUIM_ConnectParent, (IPTR)obj);
2328 // find the ObjNode containing a pointer to the given object
2329 // currently only used for cycle chain objects
2330 static struct ObjNode *FindObjNode(struct MinList *list, Object *obj)
2332 struct ObjNode *node;
2334 ASSERT_VALID_PTR(list);
2336 if (!obj)
2337 return NULL;
2339 ASSERT_VALID_PTR(obj);
2341 for (node = (struct ObjNode*)list->mlh_Head;
2342 node->node.mln_Succ;
2343 node = (struct ObjNode*)node->node.mln_Succ)
2345 if (node->obj == obj)
2347 return node;
2350 return NULL;
2353 static Object *GetFirstActiveObject (struct MUI_WindowData *data)
2355 ASSERT_VALID_PTR(data);
2357 if (!IsListEmpty((struct List*)&data->wd_CycleChain))
2358 return ((struct ObjNode*)data->wd_CycleChain.mlh_Head)->obj;
2359 else
2360 return NULL;
2363 static Object *GetLastActiveObject (struct MUI_WindowData *data)
2365 ASSERT_VALID_PTR(data);
2367 if (!IsListEmpty((struct List*)&data->wd_CycleChain))
2368 return ((struct ObjNode*)data->wd_CycleChain.mlh_TailPred)->obj;
2369 else
2370 return NULL;
2373 typedef struct ObjNode *objnode_iterator_t(struct ObjNode *curr_node);
2375 static objnode_iterator_t NextObjNodeIterator;
2376 static objnode_iterator_t PrevObjNodeIterator;
2378 static struct ObjNode *NextObjNodeIterator (struct ObjNode *curr_node)
2380 if (curr_node->node.mln_Succ->mln_Succ)
2381 return (struct ObjNode*)curr_node->node.mln_Succ;
2382 else
2383 return NULL;
2386 static struct ObjNode *PrevObjNodeIterator (struct ObjNode *curr_node)
2388 if (curr_node->node.mln_Pred->mln_Pred)
2389 return (struct ObjNode*)curr_node->node.mln_Pred;
2390 else
2391 return NULL;
2394 static Object *GetPrevNextActiveObject (struct ObjNode *old_activenode, objnode_iterator_t node_iterator)
2396 struct ObjNode *curr_node;
2397 struct ObjNode *node;
2398 Object *obj;
2400 ASSERT_VALID_PTR(old_activenode);
2402 curr_node = old_activenode;
2403 node = NULL;
2404 obj = NULL;
2406 while (curr_node)
2408 node = node_iterator(curr_node);
2410 if (node)
2411 obj = node->obj;
2413 /* let's see if this obj meets cycle requirements (enabled & visible) */
2414 if (obj)
2416 IPTR is_disabled;
2418 get(obj, MUIA_Disabled, &is_disabled);
2420 if (!is_disabled && (_flags(obj) & MADF_SHOWME))
2422 return obj;
2426 curr_node = node;
2427 obj = NULL;
2428 node = NULL;
2430 return obj;
2434 /**************************************************************************
2435 Code for setting MUIA_Window_ActiveObject
2436 Basically, it will:
2437 - remove focus drawing for current active object
2438 - find (if needed) the new active object
2439 - set data->wd_ActiveObject to the new object
2440 - draw focus around the new active object
2441 **************************************************************************/
2442 static void SetActiveObject (struct MUI_WindowData *data, Object *obj, IPTR newval)
2444 struct ObjNode *old_activenode = NULL;
2446 ASSERT_VALID_PTR(data);
2447 ASSERT_VALID_PTR(obj);
2449 D(bug("MUIC_Window:SetActiveObject(data, obj, %08lx) Active=%p\n",
2450 newval, data->wd_ActiveObject));
2452 if ((data->wd_ActiveObject != NULL)
2453 && (DoMethod(data->wd_RootObject, MUIM_FindAreaObject,
2454 (IPTR)data->wd_ActiveObject) != (IPTR)NULL))
2456 if ((IPTR)data->wd_ActiveObject == newval)
2457 return;
2458 old_activenode = FindObjNode(&data->wd_CycleChain, data->wd_ActiveObject);
2459 //if (_flags(data->wd_ActiveObject) & MADF_CANDRAW)
2460 if (data->wd_Flags & MUIWF_OBJECTGOACTIVESENT)
2462 DoMethod(data->wd_ActiveObject, MUIM_GoInactive);
2466 data->wd_ActiveObject = NULL;
2467 data->wd_Flags &= ~MUIWF_OBJECTGOACTIVESENT;
2469 switch (newval)
2471 case MUIV_Window_ActiveObject_None:
2472 break;
2474 case MUIV_Window_ActiveObject_Next:
2475 if (old_activenode != NULL)
2476 data->wd_ActiveObject = GetPrevNextActiveObject(old_activenode,
2477 NextObjNodeIterator);
2478 if (NULL == data->wd_ActiveObject)
2479 data->wd_ActiveObject = GetFirstActiveObject(data);
2480 break;
2482 case MUIV_Window_ActiveObject_Prev:
2483 if (old_activenode)
2484 data->wd_ActiveObject = GetPrevNextActiveObject(old_activenode,
2485 PrevObjNodeIterator);
2486 if (NULL == data->wd_ActiveObject)
2487 data->wd_ActiveObject = GetLastActiveObject(data);
2488 break;
2490 default:
2491 data->wd_ActiveObject = (Object*)newval;
2492 break;
2495 if (data->wd_ActiveObject != NULL
2496 && DoMethod(data->wd_RootObject, MUIM_FindAreaObject,
2497 (IPTR)data->wd_ActiveObject)
2498 && (_flags(data->wd_ActiveObject) & MADF_CANDRAW))
2500 DoMethod(data->wd_ActiveObject, MUIM_GoActive);
2501 data->wd_Flags |= MUIWF_OBJECTGOACTIVESENT;
2507 * calculate real dimensions from programmer requirements.
2508 * may be overridden by user settings if MUIA_Window_ID is set.
2510 /* MUIV_Window_Height_Screen and MUIV_Window_Height_Visible
2511 * are not handled yet, as their Width couterparts.
2513 static void WindowSelectDimensions (struct MUI_WindowData *data)
2515 if (!data->wd_Width)
2517 if (data->wd_ReqWidth > 0) data->wd_Width = data->wd_ReqWidth;
2518 else if (data->wd_ReqWidth == MUIV_Window_Width_Default)
2519 data->wd_Width = data->wd_MinMax.DefWidth;
2520 else if (_between(MUIV_Window_Width_MinMax(100),
2521 data->wd_ReqWidth,
2522 MUIV_Window_Width_MinMax(0)))
2524 data->wd_Width = data->wd_MinMax.MinWidth
2525 - data->wd_ReqWidth
2526 * (data->wd_MinMax.MaxWidth - data->wd_MinMax.MinWidth);
2528 else if (_between(MUIV_Window_Width_Screen(100),
2529 data->wd_ReqWidth,
2530 MUIV_Window_Width_Screen(0)))
2532 data->wd_Width = data->wd_RenderInfo.mri_ScreenWidth
2533 * (- (data->wd_ReqWidth + 200)) / 100;
2535 else if (_between(MUIV_Window_Width_Visible(100),
2536 data->wd_ReqWidth,
2537 MUIV_Window_Width_Visible(0)))
2539 data->wd_Width = data->wd_RenderInfo.mri_ScreenWidth
2540 * (- (data->wd_ReqWidth + 100)) / 100;
2543 if (data->wd_ReqHeight > 0) data->wd_Height = data->wd_ReqHeight;
2544 else if (data->wd_ReqHeight == MUIV_Window_Height_Default)
2545 data->wd_Height = data->wd_MinMax.DefHeight;
2546 else if (_between(MUIV_Window_Height_MinMax(100),
2547 data->wd_ReqHeight,
2548 MUIV_Window_Height_MinMax(0)))
2550 data->wd_Height = data->wd_MinMax.MinHeight
2551 - data->wd_ReqHeight
2552 * (data->wd_MinMax.MaxHeight - data->wd_MinMax.MinHeight);
2554 else if (_between(MUIV_Window_Height_Screen(100),
2555 data->wd_ReqHeight,
2556 MUIV_Window_Height_Screen(0)))
2558 struct Screen *scr;
2559 int height;
2561 scr = data->wd_RenderInfo.mri_Screen;
2563 height = scr->Height - data->wd_RenderInfo.mri_BorderTop - data->wd_RenderInfo.mri_BorderBottom;
2565 /* This is new to Zune: If TopEdge Delta is requested
2566 * the screenheight doesn't cover the barlayer */
2567 if (data->wd_Y <= MUIV_Window_TopEdge_Delta(0))
2568 height -= scr->BarHeight + 1;
2570 data->wd_Height = height * (- (data->wd_ReqHeight + 200)) / 100;
2572 else if (_between(MUIV_Window_Height_Visible(100),
2573 data->wd_ReqHeight,
2574 MUIV_Window_Height_Visible(0)))
2576 data->wd_Height = data->wd_RenderInfo.mri_ScreenHeight
2577 * (- (data->wd_ReqHeight + 100)) / 100;
2580 /* scaled */
2581 if (data->wd_ReqWidth == MUIV_Window_Width_Scaled)
2582 data->wd_Width = data->wd_Height * data->wd_MinMax.MinWidth
2583 / data->wd_MinMax.MinHeight;
2584 else if (data->wd_ReqHeight == MUIV_Window_Width_Scaled)
2585 data->wd_Height = data->wd_Width * data->wd_MinMax.MinHeight
2586 / data->wd_MinMax.MinWidth;
2588 data->wd_Width = CLAMP(data->wd_Width, data->wd_MinMax.MinWidth,
2589 data->wd_MinMax.MaxWidth);
2590 data->wd_Height = CLAMP(data->wd_Height, data->wd_MinMax.MinHeight,
2591 data->wd_MinMax.MaxHeight);
2595 /**************************************************************************
2596 OM_NEW
2597 **************************************************************************/
2598 IPTR Window__OM_NEW(struct IClass *cl, Object *obj, struct opSet *msg)
2600 struct MUI_WindowData *data;
2601 const struct TagItem *tags;
2602 struct TagItem *tag;
2604 obj = (Object *)DoSuperMethodA(cl, obj, (Msg)msg);
2605 if (!obj)
2606 return FALSE;
2608 /* Initial local instance data */
2609 data = INST_DATA(cl, obj);
2611 data->wd_MemoryPool = CreatePool(0, 4096, 2048);
2612 if (NULL == data->wd_MemoryPool)
2614 CoerceMethod(cl, obj, OM_DISPOSE);
2615 return (IPTR)NULL;
2618 data->wd_RenderInfo.mri_WindowObject = obj;
2620 NewList((struct List*)&(data->wd_EHList));
2621 NewList((struct List*)&(data->wd_CCList));
2622 NewList((struct List*)&(data->wd_CycleChain));
2623 NewList((struct List*)&(data->wd_IDList));
2625 data->wd_CrtFlags = WFLG_SIZEGADGET | WFLG_DRAGBAR | WFLG_DEPTHGADGET
2626 | WFLG_CLOSEGADGET | WFLG_SIMPLE_REFRESH
2627 | WFLG_REPORTMOUSE | WFLG_NEWLOOKMENUS;
2628 data->wd_ZoomGadget = TRUE;
2629 data->wd_Events = GetDefaultEvents();
2630 data->wd_ActiveObject = NULL;
2631 data->wd_ID = 0;
2632 data->wd_ReqHeight = MUIV_Window_Height_Default;
2633 data->wd_ReqWidth = MUIV_Window_Width_Default;
2634 data->wd_RootObject = NULL;
2635 data->wd_DefaultObject = NULL;
2637 /* alternate dimensions */
2638 /* no change in coordinates */
2639 data->wd_AltDim.Top = MUIV_Window_AltTopEdge_NoChange;
2640 data->wd_AltDim.Left = MUIV_Window_AltLeftEdge_NoChange;
2641 /* default to min size */
2642 data->wd_AltDim.Width = MUIV_Window_AltWidth_MinMax(0);
2643 data->wd_AltDim.Height = MUIV_Window_AltHeight_MinMax(0);
2644 data->wd_X = MUIV_Window_LeftEdge_Centered;
2645 data->wd_Y = MUIV_Window_TopEdge_Centered;
2646 data->wd_DisabledKeys = 0L;
2647 data->wd_HelpTicker = BUBBLEHELP_TICKER_FIRST;
2649 /* parse initial taglist */
2651 for (tags = msg->ops_AttrList; (tag = NextTagItem(&tags)); )
2653 switch (tag->ti_Tag)
2655 case MUIA_Window_EraseArea:
2656 _handle_bool_tag(data->wd_Flags, tag->ti_Data, MUIWF_ERASEAREA);
2657 break;
2659 case MUIA_Window_ToolBox:
2660 _handle_bool_tag(data->wd_Flags, tag->ti_Data, MUIWF_TOOLBOX);
2661 break;
2663 case MUIA_Window_CloseGadget:
2664 _handle_bool_tag(data->wd_CrtFlags, tag->ti_Data, WFLG_CLOSEGADGET);
2665 break;
2667 case MUIA_Window_SizeGadget:
2668 _handle_bool_tag(data->wd_CrtFlags, tag->ti_Data, WFLG_SIZEGADGET);
2669 break;
2671 case MUIA_Window_ZoomGadget:
2672 data->wd_ZoomGadget = tag->ti_Data;
2673 break;
2675 case MUIA_Window_Backdrop:
2676 _handle_bool_tag(data->wd_CrtFlags, tag->ti_Data, WFLG_BACKDROP);
2677 break;
2679 case MUIA_Window_Borderless:
2680 _handle_bool_tag(data->wd_CrtFlags, tag->ti_Data, WFLG_BORDERLESS);
2681 break;
2683 case MUIA_Window_DepthGadget:
2684 _handle_bool_tag(data->wd_CrtFlags, tag->ti_Data, WFLG_DEPTHGADGET);
2685 break;
2687 case MUIA_Window_DragBar:
2688 _handle_bool_tag(data->wd_CrtFlags, tag->ti_Data, WFLG_DRAGBAR);
2689 break;
2691 case MUIA_Window_SizeRight:
2692 _handle_bool_tag(data->wd_CrtFlags, tag->ti_Data, WFLG_SIZEBRIGHT);
2693 break;
2695 case MUIA_Window_Height:
2696 data->wd_ReqHeight = (LONG)tag->ti_Data;
2697 break;
2699 case MUIA_Window_Width:
2700 data->wd_ReqWidth = (LONG)tag->ti_Data;
2701 break;
2703 case MUIA_Window_ID:
2704 set(obj, MUIA_Window_ID, tag->ti_Data);
2705 break;
2707 case MUIA_Window_IsSubWindow:
2708 _handle_bool_tag(data->wd_Flags, tag->ti_Data, MUIWF_ISSUBWINDOW);
2709 break;
2711 case MUIA_Window_Title:
2712 set(obj, MUIA_Window_Title, tag->ti_Data);
2713 break;
2715 case MUIA_Window_ScreenTitle:
2716 set(obj, MUIA_Window_ScreenTitle, tag->ti_Data);
2717 break;
2719 case MUIA_Window_Activate:
2720 _handle_bool_tag(data->wd_Flags, !tag->ti_Data, MUIWF_DONTACTIVATE);
2721 break;
2723 case MUIA_Window_DefaultObject:
2724 set(obj, MUIA_Window_DefaultObject, tag->ti_Data);
2725 break;
2727 case MUIA_Window_Menustrip:
2728 data->wd_ChildMenustrip = (Object*)tag->ti_Data;
2729 break;
2731 case MUIA_Window_NoMenus:
2732 data->wd_NoMenus = (BOOL) tag->ti_Data;
2733 break;
2735 case MUIA_Window_RootObject:
2736 if (!tag->ti_Data)
2738 CoerceMethod(cl, obj, OM_DISPOSE);
2739 return 0;
2741 set(obj, MUIA_Window_RootObject, tag->ti_Data);
2742 break;
2744 case MUIA_Window_AltHeight:
2745 data->wd_AltDim.Height = (WORD)tag->ti_Data;
2746 break;
2748 case MUIA_Window_AltWidth:
2749 data->wd_AltDim.Width = (WORD)tag->ti_Data;
2750 break;
2752 case MUIA_Window_AltLeftEdge:
2753 data->wd_AltDim.Left = (WORD)tag->ti_Data;
2754 break;
2756 case MUIA_Window_AltTopEdge:
2757 data->wd_AltDim.Top = (WORD)tag->ti_Data;
2758 break;
2760 case MUIA_Window_AppWindow:
2761 _handle_bool_tag(data->wd_Flags, tag->ti_Data, MUIWF_ISAPPWINDOW);
2762 break;
2764 case MUIA_Window_LeftEdge:
2765 data->wd_X = tag->ti_Data;
2766 break;
2768 case MUIA_Window_TopEdge:
2769 data->wd_Y = tag->ti_Data;
2770 break;
2772 case MUIA_Window_UseBottomBorderScroller:
2773 _handle_bool_tag(data->wd_Flags, tag->ti_Data, MUIWF_USEBOTTOMSCROLLER);
2774 break;
2776 case MUIA_Window_UseRightBorderScroller:
2777 _handle_bool_tag(data->wd_Flags, tag->ti_Data, MUIWF_USERIGHTSCROLLER);
2778 break;
2780 case MUIA_Window_DisableKeys:
2781 data->wd_DisabledKeys = tag->ti_Data;
2782 break;
2784 case MUIA_Window_RefWindow:
2785 data->wd_RefWindow = (Object *)tag->ti_Data;
2786 break;
2788 case MUIA_Window_Screen:
2789 data->wd_UserScreen = (struct Screen *)tag->ti_Data;
2790 break;
2792 case MUIA_Window_PublicScreen:
2793 data->wd_UserPublicScreen = (STRPTR)tag->ti_Data;
2794 break;
2798 /* D(bug("muimaster.library/window.c: Window Object created at 0x%lx back=%lx\n", */
2799 /* obj,data->wd_Background)); */
2801 return (IPTR)obj;
2804 /**************************************************************************
2805 OM_DISPOSE
2806 **************************************************************************/
2807 IPTR Window__OM_DISPOSE(struct IClass *cl, Object *obj, Msg msg)
2809 struct MUI_WindowData *data = INST_DATA(cl, obj);
2811 /* D(bug("Window_Dispose(%p)\n", obj)); */
2813 #if 0 /* We no longer clear muiGlobalInfo() during disconnections, so
2814 this can cause problems (remove object which is already removed).
2815 Furthermore AFAIK it is not legal to dispose a window object
2816 which is still ocnnected to the application object, anyway. */
2818 if (muiGlobalInfo(obj) && _app(obj))
2820 /* D(bug(" Window_Dispose(%p) : calling app->OM_REMMEMBER\n", obj)); */
2821 DoMethod(_app(obj), OM_REMMEMBER, (IPTR)obj);
2823 #endif
2825 if (data->wd_RootObject)
2826 MUI_DisposeObject(data->wd_RootObject);
2828 if (data->wd_ChildMenustrip)
2829 MUI_DisposeObject(data->wd_ChildMenustrip);
2831 if (data->wd_Title) FreeVec(data->wd_Title);
2832 if (data->wd_ScreenTitle)FreeVec(data->wd_ScreenTitle);
2834 DeletePool(data->wd_MemoryPool);
2836 /* D(bug(" Window_Dispose(%p) : calling supermethod\n", obj)); */
2837 return DoSuperMethodA(cl, obj, msg);
2840 static ULONG WindowOpen(struct IClass *cl, Object *obj);
2841 static ULONG WindowClose(struct IClass *cl, Object *obj);
2843 /**************************************************************************
2844 OM_SET
2845 **************************************************************************/
2846 IPTR Window__OM_SET(struct IClass *cl, Object *obj, struct opSet *msg)
2848 struct MUI_WindowData *data = INST_DATA(cl, obj);
2849 const struct TagItem *tags = msg->ops_AttrList;
2850 const struct TagItem *tag;
2852 while ((tag = NextTagItem(&tags)) != NULL)
2854 switch (tag->ti_Tag)
2856 case MUIA_Window_Activate:
2857 if (data->wd_RenderInfo.mri_Window)
2859 if (tag->ti_Data && !(data->wd_Flags & MUIWF_ACTIVE))
2861 ActivateWindow(data->wd_RenderInfo.mri_Window);
2862 _handle_bool_tag(data->wd_Flags, tag->ti_Data, MUIWF_ACTIVE);
2865 else
2866 _handle_bool_tag(data->wd_Flags, !tag->ti_Data, MUIWF_DONTACTIVATE);
2867 break;
2869 case MUIA_Window_ActiveObject:
2870 /* D(bug("MUIA_Window_ActiveObject %ld (%p)\n", tag->ti_Data, tag->ti_Data)); */
2871 SetActiveObject(data, obj, tag->ti_Data);
2872 break;
2874 case MUIA_Window_DefaultObject:
2875 data->wd_DefaultObject = (APTR)tag->ti_Data;
2876 break;
2878 case MUIA_Window_ID:
2879 data->wd_ID = tag->ti_Data;
2880 break;
2882 case MUIA_Window_IsSubWindow:
2883 _handle_bool_tag(data->wd_Flags, tag->ti_Data, MUIWF_ISSUBWINDOW);
2884 break;
2886 case MUIA_Window_Open:
2887 if (tag->ti_Data)
2889 if (data->wd_Flags & MUIWF_HIDDEN)
2890 data->wd_Flags |= MUIWF_OPENONUNHIDE;
2891 else
2892 if (!(data->wd_Flags & MUIWF_OPENED))
2893 WindowOpen(cl, obj);
2894 else
2896 DoMethod(obj, MUIM_Window_ToFront);
2897 set(obj, MUIA_Window_Activate, TRUE);
2900 else
2901 if (data->wd_Flags & MUIWF_HIDDEN)
2902 data->wd_Flags &= ~MUIWF_OPENONUNHIDE;
2903 else
2904 if (data->wd_Flags & MUIWF_OPENED)
2905 WindowClose(cl, obj);
2906 break;
2908 case MUIA_ShowMe: /* PRIVATE *abuse* of the Area's ShowMe attr */
2909 if (tag->ti_Data)
2911 /* Deiconify */
2913 if (data->wd_Flags & MUIWF_HIDDEN)
2915 data->wd_Flags &= ~MUIWF_HIDDEN;
2917 if (data->wd_Flags & MUIWF_OPENONUNHIDE)
2919 data->wd_Flags &= ~MUIWF_OPENONUNHIDE;
2920 set(obj, MUIA_Window_Open, TRUE);
2924 else
2926 /* Iconify */
2928 if (data->wd_Flags & MUIWF_OPENED)
2930 data->wd_Flags |= MUIWF_OPENONUNHIDE;
2932 set(obj, MUIA_Window_Open, FALSE);
2935 data->wd_Flags |= MUIWF_HIDDEN;
2937 break;
2939 case MUIA_Window_RootObject:
2940 ChangeRootObject(data, obj, (Object *)tag->ti_Data);
2941 break;
2943 case MUIA_Window_Title:
2944 if (data->wd_Title) FreeVec(data->wd_Title);
2945 data->wd_Title = StrDup((STRPTR)tag->ti_Data);
2946 if (data->wd_RenderInfo.mri_Window)
2947 SetWindowTitles(data->wd_RenderInfo.mri_Window,data->wd_Title, (CONST_STRPTR)~0);
2948 break;
2950 case MUIA_Window_ScreenTitle:
2951 if (data->wd_ScreenTitle) FreeVec(data->wd_ScreenTitle);
2952 data->wd_ScreenTitle = StrDup((STRPTR)tag->ti_Data);
2953 if (data->wd_RenderInfo.mri_Window)
2954 SetWindowTitles(data->wd_RenderInfo.mri_Window,
2955 (CONST_STRPTR)~0, data->wd_ScreenTitle);
2956 break;
2958 case MUIA_Window_NoMenus:
2959 data->wd_NoMenus = (BOOL) tag->ti_Data;
2960 if (data->wd_RenderInfo.mri_Window)
2962 if (data->wd_NoMenus)
2963 data->wd_RenderInfo.mri_Window->Flags |= WFLG_RMBTRAP;
2964 else
2965 data->wd_RenderInfo.mri_Window->Flags &= ~WFLG_RMBTRAP;
2968 break;
2970 case MUIA_Window_UseBottomBorderScroller:
2971 _handle_bool_tag(data->wd_Flags, tag->ti_Data, MUIWF_USEBOTTOMSCROLLER);
2972 break;
2974 case MUIA_Window_UseRightBorderScroller:
2975 _handle_bool_tag(data->wd_Flags, tag->ti_Data, MUIWF_USERIGHTSCROLLER);
2976 break;
2978 case MUIA_Window_DisableKeys:
2979 data->wd_DisabledKeys = tag->ti_Data;
2980 break;
2982 case MUIA_Window_RefWindow:
2983 data->wd_RefWindow = (Object *)tag->ti_Data;
2984 break;
2986 #warning "TODO: obsolete hacked atribute - remove"
2987 #if defined(MUIA_Window_WandererBackdrop)
2988 case MUIA_Window_WandererBackdrop:
2989 _handle_bool_tag(data->wd_CrtFlags, tag->ti_Data, WFLG_BACKDROP);
2990 _handle_bool_tag(data->wd_CrtFlags, !tag->ti_Data, WFLG_DRAGBAR);
2991 _handle_bool_tag(data->wd_CrtFlags, !tag->ti_Data, WFLG_SIZEGADGET);
2992 _handle_bool_tag(data->wd_CrtFlags, !tag->ti_Data, WFLG_CLOSEGADGET);
2993 _handle_bool_tag(data->wd_CrtFlags, !tag->ti_Data, WFLG_DEPTHGADGET);
2994 _handle_bool_tag(data->wd_CrtFlags, tag->ti_Data, WFLG_BORDERLESS);
2995 if (tag->ti_Data)
2997 data->wd_ReqWidth = (LONG)MUIV_Window_Width_Screen(100);
2998 /* won't take the barlayer into account */
2999 data->wd_ReqHeight = (LONG)MUIV_Window_Height_Screen(100);
3000 data->wd_Width = 0;
3001 data->wd_Height = 0;
3002 data->wd_X = (LONG)0;
3003 /* place the window below the bar layer */
3004 data->wd_Y = (LONG)MUIV_Window_TopEdge_Delta(0);
3006 break;
3007 #endif
3009 case MUIA_Window_LeftEdge:
3010 data->wd_X = tag->ti_Data;
3011 break;
3013 case MUIA_Window_TopEdge:
3014 data->wd_Y = tag->ti_Data;
3015 break;
3017 case MUIA_Window_Width:
3018 data->wd_ReqWidth = (LONG)tag->ti_Data;
3019 data->wd_Width = 0; /* otherwise windowselectdimensions() ignores ReqWidth */
3020 break;
3022 case MUIA_Window_Height:
3023 data->wd_ReqHeight = (LONG)tag->ti_Data;
3024 data->wd_Height = 0;
3025 break;
3027 case MUIA_Window_Screen:
3028 data->wd_UserScreen = (struct Screen *)tag->ti_Data;
3029 break;
3031 case MUIA_Window_PublicScreen:
3032 data->wd_UserPublicScreen = (STRPTR)tag->ti_Data;
3033 break;
3039 return DoSuperMethodA(cl, obj, (Msg)msg);
3042 /**************************************************************************
3043 OM_GET
3044 **************************************************************************/
3045 IPTR Window__OM_GET(struct IClass *cl, Object *obj, struct opGet *msg)
3047 #define STORE *(msg->opg_Storage)
3049 struct MUI_WindowData *data = INST_DATA(cl, obj);
3051 STORE = (IPTR)0;
3053 switch(msg->opg_AttrID)
3055 case MUIA_Window_Activate:
3056 STORE = (data->wd_Flags & (MUIWF_ACTIVE | MUIWF_OPENED)) == (MUIWF_ACTIVE | MUIWF_OPENED);
3057 return TRUE ;
3059 case MUIA_Window_Window:
3060 STORE = (IPTR)data->wd_RenderInfo.mri_Window;
3061 return TRUE;
3063 case MUIA_Window_Screen:
3064 STORE = (IPTR)data->wd_RenderInfo.mri_Screen;
3065 return TRUE;
3067 case MUIA_Window_PublicScreen:
3068 STORE = (IPTR)data->wd_UserPublicScreen;
3069 return TRUE;
3071 case MUIA_Window_ActiveObject:
3072 if ((data->wd_ActiveObject != NULL)
3073 && (DoMethod(data->wd_RootObject, MUIM_FindAreaObject,
3074 (IPTR)data->wd_ActiveObject) != (IPTR)NULL))
3075 STORE = (IPTR)data->wd_ActiveObject;
3076 else
3077 STORE = (IPTR)NULL;
3078 return TRUE;
3080 case MUIA_Window_CloseRequest:
3081 STORE = FALSE;
3082 return TRUE;
3084 case MUIA_Window_DefaultObject:
3085 STORE = (IPTR)data->wd_DefaultObject;
3086 return TRUE;
3088 case MUIA_Window_DisableKeys:
3089 STORE = data->wd_DisabledKeys;
3090 return TRUE;
3092 case MUIA_Window_Height:
3093 STORE = (IPTR)data->wd_Height;
3094 return TRUE;
3096 case MUIA_Window_ID:
3097 STORE = data->wd_ID;
3098 return TRUE;
3100 case MUIA_Window_IsSubWindow:
3101 STORE = (data->wd_Flags & MUIWF_ISSUBWINDOW) == MUIWF_ISSUBWINDOW;
3102 return TRUE;
3104 case MUIA_Window_LeftEdge:
3105 if (data->wd_RenderInfo.mri_Window)
3106 STORE = (IPTR)data->wd_RenderInfo.mri_Window->LeftEdge;
3107 else
3108 STORE = (IPTR)0;
3109 return TRUE;
3111 case MUIA_Window_Open:
3112 STORE = (data->wd_Flags & MUIWF_OPENED) == MUIWF_OPENED;
3113 return TRUE;
3115 case MUIA_Window_RootObject:
3116 STORE = (IPTR)data->wd_RootObject;
3117 return TRUE;
3119 case MUIA_Window_ScreenTitle:
3120 STORE = (IPTR)data->wd_ScreenTitle;
3121 return TRUE;
3123 case MUIA_Window_Title:
3124 STORE = (IPTR)data->wd_Title;
3125 return TRUE;
3127 case MUIA_Window_TopEdge:
3128 if (data->wd_RenderInfo.mri_Window)
3129 STORE = (IPTR)data->wd_RenderInfo.mri_Window->TopEdge;
3130 else
3131 STORE = (IPTR)0;
3132 return(TRUE);
3134 case MUIA_Window_Width:
3135 STORE = (IPTR)data->wd_Width;
3136 return TRUE;
3138 case MUIA_Window_Menustrip:
3139 STORE = (IPTR)data->wd_ChildMenustrip;
3140 return TRUE;
3142 case MUIA_Version:
3143 STORE = __version;
3144 return TRUE;
3146 case MUIA_Revision:
3147 STORE = __revision;
3148 return TRUE;
3151 return DoSuperMethodA(cl, obj, (Msg) msg);
3152 #undef STORE
3156 * MUIM_FindUData : tests if the MUIA_UserData of the object
3157 * contains the given <udata> and returns the object pointer in this case.
3159 IPTR Window__MUIM_FindUData(struct IClass *cl, Object *obj, struct MUIP_FindUData *msg)
3161 struct MUI_WindowData *data = INST_DATA(cl, obj);
3163 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
3164 return (IPTR)obj;
3166 if (data->wd_RootObject)
3167 return DoMethodA(data->wd_RootObject, (Msg)msg);
3169 return 0;
3174 * MUIM_GetUData : This method tests if the MUIA_UserData of the object
3175 * contains the given <udata> and gets <attr> to <storage> for itself
3176 * in this case.
3178 IPTR Window__MUIM_GetUData(struct IClass *cl, Object *obj, struct MUIP_GetUData *msg)
3180 struct MUI_WindowData *data = INST_DATA(cl, obj);
3182 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
3184 get(obj, msg->attr, msg->storage);
3185 return TRUE;
3188 if (data->wd_RootObject)
3189 return DoMethodA(data->wd_RootObject, (Msg)msg);
3191 return FALSE;
3196 * MUIM_SetUData : This method tests if the MUIA_UserData of the object
3197 * contains the given <udata> and sets <attr> to <val> for itself in this case.
3199 IPTR Window__MUIM_SetUData(struct IClass *cl, Object *obj, struct MUIP_SetUData *msg)
3201 struct MUI_WindowData *data = INST_DATA(cl, obj);
3203 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
3204 set(obj, msg->attr, msg->val);
3206 if (data->wd_RootObject)
3207 DoMethodA(data->wd_RootObject, (Msg)msg);
3209 return TRUE;
3214 * MUIM_SetUDataOnce : This method tests if the MUIA_UserData of the object
3215 * contains the given <udata> and sets <attr> to <val> for itself in this case.
3217 IPTR Window__MUIM_SetUDataOnce(struct IClass *cl, Object *obj, struct MUIP_SetUDataOnce *msg)
3219 struct MUI_WindowData *data = INST_DATA(cl, obj);
3221 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
3223 set(obj, msg->attr, msg->val);
3224 return TRUE;
3227 if (data->wd_RootObject)
3228 return DoMethodA(data->wd_RootObject, (Msg)msg);
3230 return FALSE;
3233 /**************************************************************************
3234 Called by Application (parent) object whenever this object is added.
3235 init GlobalInfo
3236 **************************************************************************/
3237 IPTR Window__MUIM_ConnectParent(struct IClass *cl, Object *obj,
3238 struct MUIP_ConnectParent *msg)
3240 struct MUI_WindowData *data = INST_DATA(cl, obj);
3242 if (!DoSuperMethodA(cl,obj,(Msg)msg)) return 0;
3244 if (data->wd_RootObject)
3245 DoMethod(data->wd_RootObject, MUIM_ConnectParent, (IPTR)obj);
3247 if (data->wd_ChildMenustrip)
3248 DoMethod(data->wd_ChildMenustrip, MUIM_ConnectParent, (IPTR)obj);
3250 return TRUE;
3254 /**************************************************************************
3255 called by parent object
3256 **************************************************************************/
3257 IPTR Window__MUIM_DisconnectParent(struct IClass *cl, Object *obj, struct MUIP_DisconnectParent *msg)
3259 struct MUI_WindowData *data = INST_DATA(cl, obj);
3261 /* D(bug("Window_DisconnectParent(%p) : muiGlobalInfo=%p\n", muiGlobalInfo(obj))); */
3262 if (muiGlobalInfo(obj))
3264 /* Close the window before disconnecting all the childs */
3265 if ((data->wd_Flags & MUIWF_OPENED))
3267 /* D(bug(" Window_DisconnectParent(%p) : closing window\n", muiGlobalInfo(obj))); */
3268 set(obj, MUIA_Window_Open, FALSE);
3270 if (data->wd_ChildMenustrip)
3271 DoMethod(data->wd_ChildMenustrip, MUIM_DisconnectParent, (IPTR)obj);
3273 if (data->wd_RootObject)
3274 DoMethodA(data->wd_RootObject, (Msg)msg);
3276 /* D(bug(" Window_DisconnectParent(%p) : calling supermethod\n", muiGlobalInfo(obj))); */
3277 return DoSuperMethodA(cl,obj,(Msg)msg);
3279 else
3281 return 0;
3285 static void SetRootObjInnerSpacing(Object *obj, struct MUI_WindowData *data)
3287 UWORD wd_innerLeft, wd_innerRight, wd_innerTop, wd_innerBottom;
3289 if (data->wd_CrtFlags & WFLG_BORDERLESS)
3291 wd_innerLeft = 0;
3292 wd_innerRight = 0;
3293 wd_innerTop = 0;
3294 wd_innerBottom = 0;
3296 else
3298 wd_innerLeft = muiGlobalInfo(obj)->mgi_Prefs->window_inner_left;
3299 wd_innerRight = muiGlobalInfo(obj)->mgi_Prefs->window_inner_right;
3300 wd_innerTop = muiGlobalInfo(obj)->mgi_Prefs->window_inner_top;
3301 wd_innerBottom = muiGlobalInfo(obj)->mgi_Prefs->window_inner_bottom;
3304 if (!(muiAreaData(data->wd_RootObject)->mad_Flags & MADF_INNERLEFT))
3306 muiAreaData(data->wd_RootObject)->mad_InnerLeft = wd_innerLeft;
3309 if (!(muiAreaData(data->wd_RootObject)->mad_Flags & MADF_INNERTOP))
3311 muiAreaData(data->wd_RootObject)->mad_InnerTop = wd_innerTop;
3314 if (!(muiAreaData(data->wd_RootObject)->mad_Flags & MADF_INNERRIGHT))
3316 muiAreaData(data->wd_RootObject)->mad_InnerRight = wd_innerRight;
3319 if (!(muiAreaData(data->wd_RootObject)->mad_Flags & MADF_INNERBOTTOM))
3321 muiAreaData(data->wd_RootObject)->mad_InnerBottom = wd_innerBottom;
3326 * Called before window is opened or resized. It determines its bounds,
3327 * so you can call WindowSelectDimensions() to find the final dims.
3329 static void WindowMinMax(Object *obj, struct MUI_WindowData *data)
3331 SetRootObjInnerSpacing(obj, data);
3332 /* inquire about sizes */
3333 DoMethod(data->wd_RootObject, MUIM_AskMinMax, (IPTR)&data->wd_MinMax);
3334 /* D(bug("*** root minmax = %ld,%ld => %ld,%ld\n", data->wd_MinMax.MinWidth, */
3335 /* data->wd_MinMax.MinHeight, */
3336 /* data->wd_MinMax.MaxWidth, data->wd_MinMax.MaxHeight)); */
3337 __area_finish_minmax(data->wd_RootObject, &data->wd_MinMax);
3338 /* D(bug("*** root minmax2 = %ld,%ld => %ld,%ld\n", data->wd_MinMax.MinWidth, */
3339 /* data->wd_MinMax.MinHeight, */
3340 /* data->wd_MinMax.MaxWidth, data->wd_MinMax.MaxHeight)); */
3344 static void InstallBackbuffer (struct IClass *cl, Object *obj)
3346 struct MUI_WindowData *data = INST_DATA(cl, obj);
3347 #if 0
3348 struct Window *win = data->wd_RenderInfo.mri_Window;
3350 data->wd_RenderInfo.mri_BufferBM =
3351 AllocBitMap(win->Width, win->Height, win->RPort->BitMap->Depth,
3352 0, win->RPort->BitMap);
3353 #endif
3354 if (data->wd_RenderInfo.mri_BufferBM)
3356 /* D(bug("install_backbuffer : allocated bitmap %dx%dx%d with friend %p\n", */
3357 /* win->Width, win->Height, win->RPort->BitMap->Depth, win->RPort->BitMap)); */
3358 InitRastPort(&data->wd_RenderInfo.mri_BufferRP);
3359 data->wd_RenderInfo.mri_BufferRP.BitMap = data->wd_RenderInfo.mri_BufferBM;
3363 static void DeinstallBackbuffer (struct IClass *cl, Object *obj)
3365 struct MUI_WindowData *data = INST_DATA(cl, obj);
3367 if (data->wd_RenderInfo.mri_BufferBM)
3369 DeinitRastPort(&data->wd_RenderInfo.mri_BufferRP);
3370 FreeBitMap(data->wd_RenderInfo.mri_BufferBM);
3371 data->wd_RenderInfo.mri_BufferBM = NULL;
3376 * Called after window is opened or resized.
3377 * An expose event is already queued, it will trigger
3378 * MUIM_Draw for us when going back to main loop.
3380 static void WindowShow (struct IClass *cl, Object *obj)
3382 struct MUI_WindowData *data = INST_DATA(cl, obj);
3383 struct Window *win = data->wd_RenderInfo.mri_Window;
3384 /* D(bug("window_show %s %d\n", __FILE__, __LINE__)); */
3386 _left(data->wd_RootObject) = win->BorderLeft;
3387 _top(data->wd_RootObject) = win->BorderTop;
3388 _width(data->wd_RootObject) = data->wd_Width;
3389 _height(data->wd_RootObject) = data->wd_Height;
3391 DoMethod(data->wd_RootObject, MUIM_Layout);
3393 ShowRenderInfo(&data->wd_RenderInfo);
3394 /* D(bug("zune_imspec_show %s %d\n", __FILE__, __LINE__)); */
3395 zune_imspec_show(data->wd_Background, obj);
3396 DoShowMethod(data->wd_RootObject);
3399 static ULONG WindowOpen(struct IClass *cl, Object *obj)
3401 struct MUI_WindowData *data = INST_DATA(cl, obj);
3403 if (!data->wd_RootObject)
3404 return FALSE;
3406 if (!DoMethod(obj, MUIM_Window_Setup))
3407 return FALSE;
3409 /* I got display info, so calculate your display dependant data */
3410 if (!DoSetupMethod(data->wd_RootObject, &data->wd_RenderInfo))
3412 DoMethod(obj, MUIM_Window_Cleanup);
3413 return FALSE;
3416 /* inquire about sizes */
3417 WindowMinMax(obj,data);
3418 WindowSelectDimensions(data);
3420 /* Decide which menustrip should be used */
3421 if (!data->wd_ChildMenustrip)
3422 get(_app(obj), MUIA_Application_Menustrip, &data->wd_Menustrip);
3423 else
3424 data->wd_Menustrip = data->wd_ChildMenustrip;
3426 /* open window here ... */
3427 if (!DisplayWindow(obj,data))
3429 /* free display dependant data */
3430 data->wd_Menustrip = NULL;
3431 DoMethod(data->wd_RootObject, MUIM_Cleanup);
3432 DoMethod(obj, MUIM_Window_Cleanup);
3433 return FALSE;
3436 InstallBackbuffer(cl, obj);
3438 data->wd_Flags |= MUIWF_OPENED;
3440 WindowShow(cl, obj);
3443 LONG left,top,width,height;
3445 left = data->wd_RenderInfo.mri_Window->BorderLeft;
3446 top = data->wd_RenderInfo.mri_Window->BorderTop,
3447 width = data->wd_RenderInfo.mri_Window->Width
3448 - data->wd_RenderInfo.mri_Window->BorderRight - left;
3449 height = data->wd_RenderInfo.mri_Window->Height
3450 - data->wd_RenderInfo.mri_Window->BorderBottom - top;
3452 /* D(bug("zune_imspec_draw %s %d\n", __FILE__, __LINE__)); */
3453 // D(bug("%d:zune_imspec_draw(%p) l=%d t=%d w=%d h=%d xo=%d yo=%d\n",
3454 // __LINE__, data->wd_Background, left, top, width,
3455 // height, left, top));
3457 zune_imspec_draw(data->wd_Background, &data->wd_RenderInfo,
3458 left, top, width, height, left, top, 0);
3461 MUI_Redraw(data->wd_RootObject, MADF_DRAWOBJECT);
3463 D(bug("MUIC_Window:windowOpen() ActiveObject=%p\n", data->wd_ActiveObject));
3464 if (data->wd_OldActive != NULL)
3466 set(obj, MUIA_Window_ActiveObject, data->wd_OldActive);
3469 return TRUE;
3472 /******************************************************************************/
3473 /******************************************************************************/
3475 static ULONG WindowClose(struct IClass *cl, Object *obj)
3477 struct MUI_WindowData *data = INST_DATA(cl, obj);
3479 if (data->wd_ActiveObject != NULL)
3481 data->wd_OldActive = data->wd_ActiveObject;
3482 set(obj, MUIA_Window_ActiveObject, MUIV_Window_ActiveObject_None);
3485 KillHelpBubble(data, obj, BUBBLEHELP_TICKER_FIRST);
3487 /* remove from window */
3488 DoHideMethod(data->wd_RootObject);
3489 zune_imspec_hide(data->wd_Background);
3491 DeinstallBackbuffer(cl, obj);
3493 HideRenderInfo(&data->wd_RenderInfo);
3495 /* close here ... */
3496 UndisplayWindow(obj,data);
3498 data->wd_Flags &= ~MUIWF_OPENED;
3499 data->wd_Menustrip = NULL;
3501 /* free display dependant data */
3502 DoMethod(data->wd_RootObject, MUIM_Cleanup);
3503 DoMethod(obj, MUIM_Window_Cleanup);
3504 return TRUE;
3507 /* calculate a new layout
3508 * see MUIA_ShowMe
3509 * see Group_ExitChange
3510 * see Group_Columns
3511 * see Group_Rows
3513 IPTR Window__MUIM_RecalcDisplay(struct IClass *cl, Object *obj, struct MUIP_Window_RecalcDisplay *msg)
3515 struct MUI_WindowData *data = INST_DATA(cl, obj);
3516 LONG left,top,width,height;
3517 BOOL resized;
3518 Object *current_obj;
3520 if (!(data->wd_Flags & MUIWF_OPENED))
3521 return 0;
3523 current_obj = msg->originator;
3525 // typically originator is a group which has been added/removed a child
3526 // calculate minmax of current obj
3527 // if new minmax can accomodate current obj size, stop
3528 // else try with its parent
3529 // the resulting object will get a new layout
3530 // it currently produces some redundant AskMinMax but allows
3531 // to not always relayout the whole window
3533 D(bug("RecalcDisplay on %p\n", current_obj));
3534 while (current_obj != NULL)
3536 DoMethod(current_obj, MUIM_AskMinMax, (IPTR)&muiAreaData(current_obj)->mad_MinMax);
3537 __area_finish_minmax(current_obj, &muiAreaData(current_obj)->mad_MinMax);
3539 D(bug("size w = %d, h = %d\n", _width(current_obj), _height(current_obj)));
3540 D(bug("new w = %d-%d, h = %d-%d\n", _minwidth(current_obj), _maxwidth(current_obj),
3541 _minheight(current_obj), _maxheight(current_obj)));
3543 if (!_between(_minwidth(current_obj), _width(current_obj), _maxwidth(current_obj))
3544 || !_between(_minheight(current_obj), _height(current_obj), _maxheight(current_obj)))
3546 current_obj = _parent(current_obj);
3547 D(bug("RecalcDisplay, try parent %p\n", current_obj));
3549 else
3551 D(bug("found it\n"));
3552 break;
3556 if (!current_obj)
3557 current_obj = data->wd_RootObject;
3559 WindowMinMax(obj, data);
3560 DoHideMethod(current_obj);
3561 /* resize window ? */
3562 WindowSelectDimensions(data);
3563 resized = WindowResize(data);
3566 struct Window *win = data->wd_RenderInfo.mri_Window;
3567 _left(data->wd_RootObject) = win->BorderLeft;
3568 _top(data->wd_RootObject) = win->BorderTop;
3569 _width(data->wd_RootObject) = data->wd_Width;
3570 _height(data->wd_RootObject) = data->wd_Height;
3572 DoMethod(current_obj, MUIM_Layout);
3573 DoShowMethod(current_obj);
3575 if (muiGlobalInfo(obj)->mgi_Prefs->window_redraw == WINDOW_REDRAW_WITHOUT_CLEAR)
3576 MUI_Redraw(current_obj, MADF_DRAWOBJECT);
3577 else
3579 left = data->wd_RenderInfo.mri_Window->BorderLeft;
3580 top = data->wd_RenderInfo.mri_Window->BorderTop;
3581 width = data->wd_RenderInfo.mri_Window->Width
3582 - data->wd_RenderInfo.mri_Window->BorderRight - left;
3583 height = data->wd_RenderInfo.mri_Window->Height
3584 - data->wd_RenderInfo.mri_Window->BorderBottom - top;
3586 zune_imspec_draw(data->wd_Background, &data->wd_RenderInfo,
3587 left, top, width, height, left, top, 0);
3588 MUI_Redraw(data->wd_RootObject, MADF_DRAWALL);
3591 ActivateObject(data);
3593 return TRUE;
3597 /**************************************************************************
3598 MUIM_AddEventHandler
3599 **************************************************************************/
3600 IPTR Window__MUIM_AddEventHandler(struct IClass *cl, Object *obj,
3601 struct MUIP_Window_AddEventHandler *msg)
3603 struct MUI_WindowData *data = INST_DATA(cl, obj);
3605 //D(bug("muimaster.library/window.c: Add Eventhandler %p\n", msg->ehnode));
3607 #ifdef __AROS__
3608 #if !(AROS_FLAVOUR & AROS_FLAVOUR_BINCOMPAT)
3609 msg->ehnode->ehn_Node.ln_Pri = msg->ehnode->ehn_Priority;
3610 #else
3611 msg->ehnode->ehn_Priority = msg->ehnode->ehn_Priority;
3612 #endif
3613 #endif
3614 EnqueueByPriAndAddress((struct List *)&data->wd_EHList, (struct Node *)msg->ehnode);
3615 ChangeEvents(data, GetDefaultEvents());
3616 return TRUE;
3619 /**************************************************************************
3620 MUIM_RemEventHandler
3621 **************************************************************************/
3622 IPTR Window__MUIM_RemEventHandler(struct IClass *cl, Object *obj,
3623 struct MUIP_Window_RemEventHandler *msg)
3625 struct MUI_WindowData *data = INST_DATA(cl, obj);
3627 //D(bug("muimaster.library/window.c: Rem Eventhandler %p\n", msg->ehnode));
3629 Remove((struct Node *)msg->ehnode);
3630 ChangeEvents(data, GetDefaultEvents());
3631 return TRUE;
3634 /**************************************************************************
3635 Note that this is MUIM_Window_Setup, not MUIM_Setup
3636 **************************************************************************/
3637 IPTR Window__MUIM_Setup(struct IClass *cl, Object *obj, Msg msg)
3639 struct MUI_WindowData *data = INST_DATA(cl, obj);
3641 if (!SetupRenderInfo(obj, data, &data->wd_RenderInfo))
3642 return FALSE;
3644 data->wd_Background = zune_imspec_setup(MUII_WindowBack, &data->wd_RenderInfo);
3646 if (muiGlobalInfo(obj)->mgi_Prefs->window_redraw == WINDOW_REDRAW_WITH_CLEAR)
3647 data->wd_Flags |= MUIWF_ERASEAREA;
3649 return TRUE;
3652 /**************************************************************************
3653 MUIM_Cleanup
3654 **************************************************************************/
3655 IPTR Window__MUIM_Cleanup(struct IClass *cl, Object *obj, Msg msg)
3657 struct MUI_WindowData *data = INST_DATA(cl, obj);
3659 zune_imspec_cleanup(data->wd_Background);
3661 if (data->wd_dnd)
3663 DeleteDragNDrop(data->wd_dnd);
3664 data->wd_dnd = NULL;
3667 CleanupRenderInfo(obj, data, &data->wd_RenderInfo);
3668 return TRUE;
3672 /**************************************************************************
3673 This adds the the control char handler and also do the MUIA_CycleChain
3674 stuff. Orginal MUI does this in an other way.
3675 **************************************************************************/
3676 IPTR Window__MUIM_AddControlCharHandler(struct IClass *cl, Object *obj,
3677 struct MUIP_Window_AddControlCharHandler *msg)
3679 struct MUI_WindowData *data = INST_DATA(cl, obj);
3680 struct ObjNode *node;
3682 if (msg->ccnode->ehn_Events)
3684 #ifdef __AROS__
3685 #if !(AROS_FLAVOUR & AROS_FLAVOUR_BINCOMPAT)
3686 msg->ccnode->ehn_Node.ln_Pri = msg->ccnode->ehn_Priority;
3687 #else
3688 msg->ccnode->ehn_Priority = msg->ccnode->ehn_Priority;
3689 #endif
3690 #endif
3691 Enqueue((struct List *)&data->wd_CCList, (struct Node *)msg->ccnode);
3693 /* Due to the lack of a better idea ... */
3694 if (muiAreaData(msg->ccnode->ehn_Object)->mad_Flags & MADF_CYCLECHAIN)
3696 node = AllocPooled(data->wd_MemoryPool, sizeof(struct ObjNode));
3697 if (node)
3699 node->obj = msg->ccnode->ehn_Object;
3700 AddTail((struct List *)&data->wd_CycleChain,(struct Node*)node);
3703 return TRUE;
3706 /**************************************************************************
3707 MUIM_RemControlCharHandler
3708 **************************************************************************/
3709 IPTR Window__MUIM_RemControlCharHandler(struct IClass *cl, Object *obj,
3710 struct MUIP_Window_RemControlCharHandler *msg)
3712 struct MUI_WindowData *data = INST_DATA(cl, obj);
3713 struct ObjNode *node = FindObjNode(&data->wd_CycleChain,msg->ccnode->ehn_Object);
3715 if (msg->ccnode->ehn_Events) Remove((struct Node *)msg->ccnode);
3717 if (node)
3719 /* Remove from the chain list */
3720 Remove((struct Node *)node);
3721 FreePooled(data->wd_MemoryPool, node, sizeof(struct ObjNode));
3724 return TRUE;
3727 /**************************************************************************
3728 MUIM_DragObject
3729 **************************************************************************/
3730 IPTR Window__MUIM_DragObject(struct IClass *cl, Object *obj, struct MUIP_Window_DragObject *msg)
3732 struct MUI_WindowData *data = INST_DATA(cl, obj);
3733 if (msg->obj)
3735 struct DragNDrop *dnd;
3736 struct MUI_DragImage *di;
3737 struct BitMapNode *bmn;
3739 if (!(dnd = CreateDragNDropA(NULL))) return 0;
3740 if (!(di = (struct MUI_DragImage*)DoMethod(msg->obj,MUIM_CreateDragImage,-msg->touchx,-msg->touchy,msg->flags)))
3742 DeleteDragNDrop(dnd);
3743 return 0;
3745 if (!di->bm)
3747 DoMethod(msg->obj,MUIM_DeleteDragImage, (IPTR)di);
3748 DeleteDragNDrop(dnd);
3749 return 0;
3752 if (!(bmn = CreateBitMapNodeA(TAGLIST(
3753 GUI_BitMap, (IPTR)di->bm,
3754 GUI_LeftOffset, di->touchx,
3755 GUI_TopOffset, di->touchy,
3756 GUI_Width, di->width,
3757 GUI_Height, di->height))))
3759 DoMethod(msg->obj, MUIM_DeleteDragImage, (IPTR)di);
3760 DeleteDragNDrop(dnd);
3761 return 0;
3764 AttachBitMapNode(dnd,bmn);
3766 if (!PrepareDragNDrop(dnd, data->wd_RenderInfo.mri_Screen))
3768 DoMethod(msg->obj,MUIM_DeleteDragImage, (IPTR)di);
3769 DeleteDragNDrop(dnd);
3770 return 0;
3773 muiAreaData(msg->obj)->mad_Flags |= MADF_DRAGGING;
3775 data->wd_DragObject = msg->obj;
3776 data->wd_dnd = dnd;
3777 data->wd_DragImage = di;
3778 return 1;
3780 return 0;
3783 /**************************************************************************
3784 MUIM_AllocGadgetID
3785 **************************************************************************/
3786 IPTR Window__MUIM_AllocGadgetID(struct IClass *cl, Object *obj, struct MUIP_Window_AllocGadgetID *msg)
3788 struct MUI_WindowData *data = INST_DATA(cl, obj);
3789 struct IDNode *newnode;
3791 newnode = AllocPooled(data->wd_MemoryPool, sizeof(struct IDNode));
3792 if (newnode)
3794 int id;
3795 struct MinNode *mn;
3797 if (IsListEmpty((struct List*)&data->wd_IDList))
3799 newnode->id = 1;
3800 AddHead((struct List*)&data->wd_IDList, (struct Node*)&newnode->node);
3801 return (IPTR)1;
3804 id = 1;
3806 for (mn = data->wd_IDList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
3808 struct IDNode *idn = (struct IDNode *)mn;
3809 if (id < idn->id)
3810 break;
3811 id++;
3813 newnode->id = id;
3814 Insert((struct List*)&data->wd_IDList, (struct Node*)&newnode->node, (struct Node*)mn);
3815 return (IPTR)id;
3818 return 0;
3821 /**************************************************************************
3822 MUIM_FreeGadgetID
3823 **************************************************************************/
3824 IPTR Window__MUIM_FreeGadgetID(struct IClass *cl, Object *obj, struct MUIP_Window_FreeGadgetID *msg)
3826 struct MUI_WindowData *data = INST_DATA(cl, obj);
3827 struct MinNode *mn;
3829 for (mn = data->wd_IDList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
3831 struct IDNode *idn = (struct IDNode *)mn;
3832 if (msg->gadgetid == idn->id)
3834 Remove((struct Node*)idn);
3835 FreePooled(data->wd_MemoryPool, idn, sizeof(struct IDNode));
3836 return 0;
3840 return 0;
3844 /**************************************************************************
3845 MUIM_Window_GetMenuCheck
3846 **************************************************************************/
3847 IPTR Window__MUIM_GetMenuCheck(struct IClass *cl, Object *obj, struct MUIP_Window_GetMenuCheck *msg)
3849 IPTR stat;
3850 struct MUI_WindowData *data = INST_DATA(cl, obj);
3851 Object *item;
3852 Object *strip = data->wd_ChildMenustrip;
3853 if (!strip) strip = data->wd_Menustrip;
3854 if (!strip) return 0;
3855 if (!(item = (Object*)DoMethod(strip, MUIM_FindUData, msg->MenuID))) return 0;
3856 get(item,MUIA_Menuitem_Checked, &stat);
3857 return stat;
3860 /**************************************************************************
3861 MUIM_Window_SetMenuCheck
3862 **************************************************************************/
3863 IPTR Window__MUIM_SetMenuCheck(struct IClass *cl, Object *obj, struct MUIP_Window_SetMenuCheck *msg)
3865 struct MUI_WindowData *data = INST_DATA(cl, obj);
3866 Object *item;
3867 Object *strip = data->wd_ChildMenustrip;
3868 if (!strip) strip = data->wd_Menustrip;
3869 if (!strip) return 0;
3870 if (!(item = (Object*)DoMethod(strip, MUIM_FindUData, msg->MenuID))) return 0;
3871 set(item,MUIA_Menuitem_Checked,msg->stat);
3872 return 0;
3875 /**************************************************************************
3876 MUIM_Window_GetMenuState
3877 **************************************************************************/
3878 IPTR Window__MUIM_GetMenuState(struct IClass *cl, Object *obj, struct MUIP_Window_GetMenuState *msg)
3880 IPTR stat;
3881 struct MUI_WindowData *data = INST_DATA(cl, obj);
3882 Object *item;
3883 Object *strip = data->wd_ChildMenustrip;
3884 if (!strip) strip = data->wd_Menustrip;
3885 if (!strip) return 0;
3886 if (!(item = (Object*)DoMethod(strip, MUIM_FindUData, msg->MenuID))) return 0;
3887 get(item,MUIA_Menuitem_Enabled, &stat);
3888 return stat;
3891 /**************************************************************************
3892 MUIM_Window_SetMenuState
3893 **************************************************************************/
3894 IPTR Window__MUIM_SetMenuState(struct IClass *cl, Object *obj, struct MUIP_Window_SetMenuState *msg)
3896 struct MUI_WindowData *data = INST_DATA(cl, obj);
3897 Object *item;
3898 Object *strip = data->wd_ChildMenustrip;
3899 if (!strip) strip = data->wd_Menustrip;
3900 if (!strip) return 0;
3901 if (!(item = (Object*)DoMethod(strip, MUIM_FindUData, msg->MenuID))) return 0;
3902 set(item,MUIA_Menuitem_Enabled,msg->stat);
3903 return 0;
3906 /**************************************************************************
3907 MUIM_Window_DrawBackground
3908 **************************************************************************/
3909 IPTR Window__MUIM_DrawBackground(struct IClass *cl, Object *obj, struct MUIP_Window_DrawBackground *msg)
3911 struct MUI_WindowData *data = INST_DATA(cl, obj);
3912 if (!(data->wd_RenderInfo.mri_Window)) /* not between show/hide */
3913 return FALSE;
3915 // D(bug("%d:zune_imspec_draw(%p) l=%d t=%d w=%d h=%d xo=%d yo=%d\n",
3916 // __LINE__, data->wd_Background, msg->left, msg->top, msg->width,
3917 // msg->height, msg->xoffset, msg->yoffset));
3918 zune_imspec_draw(data->wd_Background, &data->wd_RenderInfo,
3919 msg->left, msg->top, msg->width, msg->height,
3920 msg->xoffset, msg->yoffset, 0);
3921 return 0;
3924 /**************************************************************************
3925 MUIM_Window_ToFront
3926 **************************************************************************/
3927 IPTR Window__MUIM_ToFront(struct IClass *cl, Object *obj, Msg msg)
3929 struct MUI_WindowData *data = INST_DATA(cl, obj);
3930 if (!(data->wd_RenderInfo.mri_Window)) /* not between show/hide */
3931 return 0;
3933 WindowToFront(data->wd_RenderInfo.mri_Window);
3934 return 1;
3937 /**************************************************************************
3938 MUIM_Window_ToBack
3939 **************************************************************************/
3940 IPTR Window__MUIM_ToBack(struct IClass *cl, Object *obj, Msg msg)
3942 struct MUI_WindowData *data = INST_DATA(cl, obj);
3943 if (!(data->wd_RenderInfo.mri_Window)) /* not between show/hide */
3944 return 0;
3946 WindowToBack(data->wd_RenderInfo.mri_Window);
3947 return 1;
3950 /**************************************************************************
3951 MUIM_Window_ScreenToBack
3952 **************************************************************************/
3953 IPTR Window__MUIM_ScreenToBack(struct IClass *cl, Object *obj, Msg msg)
3955 struct MUI_WindowData *data = INST_DATA(cl, obj);
3956 if (!(data->wd_RenderInfo.mri_Window)) /* not between show/hide */
3957 return 0;
3959 ScreenToBack(data->wd_RenderInfo.mri_Screen);
3960 return 1;
3963 /**************************************************************************
3964 MUIM_Window_ScreenToFront
3965 **************************************************************************/
3966 IPTR Window__MUIM_ScreenToFront(struct IClass *cl, Object *obj, Msg msg)
3968 struct MUI_WindowData *data = INST_DATA(cl, obj);
3969 if (!(data->wd_RenderInfo.mri_Window)) /* not between show/hide */
3970 return 0;
3972 ScreenToFront(data->wd_RenderInfo.mri_Screen);
3973 return 1;
3976 /**************************************************************************
3977 MUIM_Window_ActionIconify
3978 **************************************************************************/
3979 IPTR Window__MUIM_ActionIconify(struct IClass *cl, Object *obj, Msg msg)
3981 set(_app(obj), MUIA_Application_Iconified, TRUE);
3983 return TRUE;
3987 /* Loads ENV: prefs, add a Window_ID chunk in the MUIW chunk, if no MUIW chunk
3988 * then create it at the same level as MUIC chunk, save prefs.
3989 * Do the same for ENVARC:
3990 * MUIW chunk layout:
3991 * 'MUIW'
3992 * 00 00 00 30 (chunk length for a single window, 0x30L big endian)
3993 * 'this window ID'
3994 * 00 00 00 28
3995 * xx xx yy yy (X, Y)
3996 * ww ww hh hh (Width, Height)
3997 * ax ax ay ay (AltX, AltY)
3998 * aw aw ah ah (AltWidth, AltHeight)
3999 * 00 00 00 00 (???)
4000 * 00 00 00 00
4001 * 00 00 00 00
4002 * 00 00 00 00
4003 * 00 01 00 00
4004 * 00 00 00 00
4006 static void RememberWindowPosition(Object *winobj, ULONG id)
4008 if (!id)
4009 return;
4012 /* Loads ENV: prefs, remove our Window_ID chunk from the MUIW chunk, save prefs.
4013 * Do the same for ENVARC:
4014 * This function shouldnt really be in window.c, but rather in a file dealing
4015 * with prefs file stuff.
4017 static void ForgetWindowPosition(Object *winobj, ULONG id)
4019 if (!id)
4020 return;
4023 /**************************************************************************
4024 MUIM_Window_Snapshot
4025 **************************************************************************/
4026 IPTR Window__MUIM_Snapshot(struct IClass *cl, Object *obj, struct MUIP_Window_Snapshot *msg)
4028 struct MUI_WindowData *data = INST_DATA(cl, obj);
4029 struct windowpos winp;
4030 struct Window *w;
4031 winp.id = data->wd_ID;
4032 w=data->wd_RenderInfo.mri_Window;
4033 if (w)
4035 winp.x1 = w->LeftEdge; winp.y1 = w->TopEdge;
4036 winp.w1 = w->GZZWidth; winp.h1 = w->GZZHeight;
4037 winp.x2 =0; winp.x2=0; winp.w2=0; winp.h2=0; //to do save alt dims
4039 set(_app(obj),MUIA_Application_SetWinPos,&winp);
4042 if (msg->flags)
4043 RememberWindowPosition(obj, data->wd_ID);
4044 else
4045 ForgetWindowPosition(obj, data->wd_ID);
4046 return 1;
4049 /**************************************************************************
4050 MUIM_Window_UpdateMenu
4051 **************************************************************************/
4052 IPTR Window__MUIM_UpdateMenu(struct IClass *cl, Object *obj, Msg msg)
4054 struct MUI_WindowData *data = INST_DATA(cl, obj);
4056 struct Menu *menu = NULL;
4057 struct NewMenu *newmenu = NULL;
4058 APTR visinfo = NULL;
4059 struct Window *win =NULL;
4061 if (data->wd_Menustrip) // only open windows can have a menustrip
4063 if ((visinfo = GetVisualInfoA(data->wd_RenderInfo.mri_Screen, NULL)))
4065 win = data->wd_RenderInfo.mri_Window;
4066 ClearMenuStrip(win);
4067 if (data->wd_Menu)
4069 FreeMenus(data->wd_Menu);
4070 data->wd_Menu = NULL;
4073 get(data->wd_Menustrip, MUIA_Menuitem_NewMenu, &newmenu);
4074 if (newmenu)
4076 if ((menu = CreateMenusA(newmenu, NULL)))
4078 struct TagItem tags[] =
4080 { GTMN_NewLookMenus, TRUE },
4081 { TAG_DONE, (IPTR)NULL }
4083 LayoutMenusA(menu, visinfo, tags);
4084 data->wd_Menu = menu;
4085 SetMenuStrip(win, menu);
4088 FreeVisualInfo(visinfo);
4092 return 1;
4095 /**************************************************************************
4096 MUIM_Export : to export an objects "contents" to a dataspace object.
4097 **************************************************************************/
4098 static IPTR Window__MUIM_Export(struct IClass *cl, Object *obj, struct MUIP_Export *msg)
4100 struct MUI_WindowData *data = INST_DATA(cl, obj);
4101 DoMethodA(data->wd_RootObject, (Msg)msg);
4102 return 0;
4106 /**************************************************************************
4107 MUIM_Import : to import an objects "contents" from a dataspace object.
4108 **************************************************************************/
4109 static IPTR Window__MUIM_Import(struct IClass *cl, Object *obj, struct MUIP_Import *msg)
4111 struct MUI_WindowData *data = INST_DATA(cl, obj);
4112 DoMethodA(data->wd_RootObject, (Msg)msg);
4113 return 0;
4116 BOOPSI_DISPATCHER(IPTR, Window_Dispatcher, cl, obj, msg)
4118 switch (msg->MethodID)
4120 case OM_NEW: return Window__OM_NEW(cl, obj, (struct opSet *) msg);
4121 case OM_DISPOSE: return Window__OM_DISPOSE(cl, obj, msg);
4122 case OM_SET: return Window__OM_SET(cl, obj, (struct opSet *)msg);
4123 case OM_GET: return Window__OM_GET(cl, obj, (struct opGet *)msg);
4124 case MUIM_FindUData: return Window__MUIM_FindUData(cl, obj, (struct MUIP_FindUData *)msg);
4125 case MUIM_GetUData: return Window__MUIM_GetUData(cl, obj, (struct MUIP_GetUData *)msg);
4126 case MUIM_SetUData: return Window__MUIM_SetUData(cl, obj, (struct MUIP_SetUData *)msg);
4127 case MUIM_SetUDataOnce: return Window__MUIM_SetUDataOnce(cl, obj, (struct MUIP_SetUDataOnce *)msg);
4128 case MUIM_Window_AddEventHandler: return Window__MUIM_AddEventHandler(cl, obj, (APTR)msg);
4129 case MUIM_Window_RemEventHandler: return Window__MUIM_RemEventHandler(cl, obj, (APTR)msg);
4130 case MUIM_ConnectParent: return Window__MUIM_ConnectParent(cl, obj, (APTR)msg);
4131 case MUIM_DisconnectParent: return Window__MUIM_DisconnectParent(cl, obj, (APTR)msg);
4132 case MUIM_Window_RecalcDisplay: return Window__MUIM_RecalcDisplay(cl, obj, (APTR)msg);
4133 case MUIM_Window_Setup: return Window__MUIM_Setup(cl, obj, (APTR)msg);
4134 case MUIM_Window_Cleanup: return Window__MUIM_Cleanup(cl, obj, (APTR)msg);
4135 case MUIM_Window_AddControlCharHandler: return Window__MUIM_AddControlCharHandler(cl, obj, (APTR)msg);
4136 case MUIM_Window_RemControlCharHandler: return Window__MUIM_RemControlCharHandler(cl, obj, (APTR)msg);
4137 case MUIM_Window_DragObject: return Window__MUIM_DragObject(cl, obj, (APTR)msg);
4138 case MUIM_Window_AllocGadgetID: return Window__MUIM_AllocGadgetID(cl, obj, (APTR)msg);
4139 case MUIM_Window_FreeGadgetID: return Window__MUIM_FreeGadgetID(cl, obj, (APTR)msg);
4140 case MUIM_Window_GetMenuCheck: return Window__MUIM_GetMenuCheck(cl, obj, (APTR)msg);
4141 case MUIM_Window_SetMenuCheck: return Window__MUIM_SetMenuCheck(cl, obj, (APTR)msg);
4142 case MUIM_Window_GetMenuState: return Window__MUIM_GetMenuState(cl, obj, (APTR)msg);
4143 case MUIM_Window_SetMenuState: return Window__MUIM_SetMenuState(cl, obj, (APTR)msg);
4144 case MUIM_Window_DrawBackground: return Window__MUIM_DrawBackground(cl, obj, (APTR)msg);
4145 case MUIM_Window_ToFront: return Window__MUIM_ToFront(cl, obj, (APTR)msg);
4146 case MUIM_Window_ToBack: return Window__MUIM_ToBack(cl, obj, (APTR)msg);
4147 case MUIM_Window_ScreenToFront: return Window__MUIM_ScreenToFront(cl, obj, (APTR)msg);
4148 case MUIM_Window_ScreenToBack: return Window__MUIM_ScreenToBack(cl, obj, (APTR)msg);
4149 case MUIM_Window_ActionIconify: return Window__MUIM_ActionIconify(cl, obj, (APTR)msg);
4150 case MUIM_Window_Snapshot: return Window__MUIM_Snapshot(cl, obj, (APTR)msg);
4151 case MUIM_Window_UpdateMenu: return Window__MUIM_UpdateMenu(cl, obj, (APTR)msg);
4152 case MUIM_Export: return Window__MUIM_Export(cl, obj, (APTR)msg);
4153 case MUIM_Import: return Window__MUIM_Import(cl, obj, (APTR)msg);
4156 return DoSuperMethodA(cl, obj, msg);
4158 BOOPSI_DISPATCHER_END
4162 * Class descriptor.
4164 const struct __MUIBuiltinClass _MUI_Window_desc = {
4165 MUIC_Window,
4166 MUIC_Notify,
4167 sizeof(struct MUI_WindowData),
4168 (void*)Window_Dispatcher