Check for SYS/GL during library init. Reason is that
[AROS.git] / workbench / libs / muimaster / classes / window.c
blob7e95a8caf22375d3358a7136b8e377c3700e5172
1 /*
2 Copyright © 1999, David Le Corfec.
3 Copyright © 2002-2015, 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>
29 #include <proto/workbench.h>
31 #define MUI_OBSOLETE /* for the obsolete menu stuff */
33 #include "mui.h"
34 #include "support.h"
35 #include "classes/window.h"
36 #include "classes/area.h"
37 #include "imspec.h"
38 #include "datatypescache.h"
39 #include "prefs.h"
40 #include "dragndrop.h"
42 #include "muimaster_intern.h"
44 //#define MYDEBUG 1
45 #include "debug.h"
47 extern struct Library *MUIMasterBase;
49 static const int __version = 1;
50 static const int __revision = 1;
52 #define IM(x) ((struct Image*)(x))
53 #define G(x) ((struct Gadget*)(x))
54 #define GADGETID(x) (((struct Gadget*)(x))->GadgetID)
56 /* this is for the cycle list */
57 struct ObjNode
59 struct MinNode node;
60 Object *obj;
63 /* For the gadget ids */
64 struct IDNode
66 struct MinNode node;
67 UWORD id;
70 struct MUI_ImageSpec_intern;
72 struct MUI_WindowData
74 struct MUI_RenderInfo wd_RenderInfo;
75 struct MUI_MinMax wd_MinMax;
76 struct IBox wd_AltDim; /* zoomed dimensions */
77 BOOL wd_ZoomGadget; /* enable/disable zoomgadget (altdim stuff) */
78 APTR wd_MemoryPool; /* for nodes and stuff to deallocate at
79 * OM_DISPOSE */
80 struct MinList wd_CycleChain; /* objects activated with tab */
81 struct MinList wd_EHList; /* event handlers */
82 struct MinList wd_CCList; /* control chars */
83 struct MinList wd_IDList; /* gadget ids */
84 ULONG wd_Events; /* events received */
85 ULONG wd_CrtFlags; /* window creation flags, see below */
86 Object *wd_ActiveObject; /* the active object */
87 Object *wd_OldActive; /* active object before window was closed */
88 APTR wd_DefaultObject;
89 ULONG wd_ID;
90 STRPTR wd_Title;
91 STRPTR wd_ScreenTitle;
92 LONG wd_Height; /* Current dimensions */
93 LONG wd_Width;
94 LONG wd_X;
95 LONG wd_Y;
96 LONG wd_ReqHeight; /* given by programmer */
97 LONG wd_ReqWidth;
98 APTR wd_RootObject; /* unique child */
99 ULONG wd_Flags; /* various status flags */
100 struct MUI_ImageSpec_intern *wd_Background;
101 ULONG wd_DisabledKeys;
102 BOOL wd_NoMenus; /* MUIA_Window_NoMenus */
104 Object *wd_DragObject; /* the object which is being dragged */
105 struct Window *wd_DropWindow; /* the destination window, for faster
106 * access */
107 Object *wd_DropObject; /* the destination object */
108 struct DragNDrop *wd_dnd;
109 struct MUI_DragImage *wd_DragImage;
110 struct AppWindow *wd_AppWindow;
112 Object *wd_Menustrip; /* The menustrip object which is actually
113 * used (either app's or window's or NULL) */
114 Object *wd_ChildMenustrip; /* If window has its own Menustrip */
115 struct Menu *wd_Menu; /* the intuition menustrip */
117 Object *wd_VertProp;
118 Object *wd_UpButton;
119 Object *wd_DownButton;
121 Object *wd_HorizProp;
122 Object *wd_LeftButton;
123 Object *wd_RightButton;
124 Object *wd_RefWindow;
126 Object *wd_MUIGadget;
128 Object *wd_HelpObject;
129 APTR wd_HelpBubble;
130 WORD wd_HelpTicker;
132 struct Screen *wd_UserScreen;
133 STRPTR wd_UserPublicScreen;
134 LONG wd_XStore; /* store MUIV_Window_LeftEdge_Centered Tags
135 * etc. because wd_X is overwritten by a
136 * value in CalcDimension. Popup windows work
137 * OK on AmiGG when main window is moved */
138 LONG wd_YStore;
140 WORD wd_SleepCount; /* MUIA_Window_Sleep nests */
141 struct IClass *wd_Class;
144 #ifndef WFLG_SIZEGADGET
146 #define WFLG_CLOSEGADGET (1<<0) /* has close gadget */
147 #define WFLG_SIZEGADGET (1<<1) /* has size gadget */
148 #define WFLG_BACKDROP (1<<2) /* is backdrop window */
149 #define WFLG_BORDERLESS (1<<3) /* has no borders */
150 #define WFLG_DEPTHGADGET (1<<4) /* has depth gadget */
151 #define WFLG_DRAGBAR (1<<5) /* is draggable */
152 #define WFLG_SIZEBRIGHT (1<<6) /* size gadget is in right border */
154 #endif
156 /* wd_Flags */
157 #define MUIWF_OPENED (1<<0) /* window currently opened */
158 #define MUIWF_HIDDEN (1<<1) /* window currently iconified */
159 #define MUIWF_ACTIVE (1<<2) /* window currently active */
160 #define MUIWF_RESIZING (1<<4) /* window currently resizing */
161 #define MUIWF_DONTACTIVATE (1<<7) /* do not activate the window when
162 * opening */
163 #define MUIWF_USERIGHTSCROLLER (1<<8) /* should have right scroller */
164 #define MUIWF_USEBOTTOMSCROLLER (1<<9) /* should have bottom scroller */
165 #define MUIWF_ERASEAREA (1<<10) /* Erase area after a window resize */
166 #define MUIWF_ISAPPWINDOW (1<<11) /* Is an AppWindow */
167 #define MUIWF_ISSUBWINDOW (1<<12) /* Don't get automatically disposed
168 * with app */
169 #define MUIWF_BUBBLEMODE (1<<13) /* Quick bubble mode. Bubbles appear
170 * quick when moving */
171 #define MUIWF_OPENONUNHIDE (1<<14) /* Open the window when unhiding */
172 #define MUIWF_SCREENLOCKED (1<<15) /* A pub screen was locked in
173 * SetupRenderInfo. Unlock it in
174 * CleanupRenderInfo! */
175 #define MUIWF_OBJECTGOACTIVESENT (1<<16) /* A MUIM_GoActive msg was sent to
176 * window's active object */
177 #define MUIWF_TOOLBOX (1<<17) /* Window should be opened as
178 * ToolBox */
180 #define BUBBLEHELP_TICKER_FIRST 10
181 #define BUBBLEHELP_TICKER_LATER 3
183 struct __dummyXFC3__
185 struct MUI_NotifyData mnd;
186 struct MUI_WindowData mwd;
189 #define muiWindowData(obj) (&(((struct __dummyXFC3__ *)(obj))->mwd))
191 static void ActivateObject(struct MUI_WindowData *data);
192 static void HandleInputEvent(Object *win, struct MUI_WindowData *data,
193 struct IntuiMessage *event);
195 static ULONG DoHalfshineGun(ULONG a, ULONG b)
197 ULONG val = ((((a) >> 24) + 3 * ((b) >> 24)) / 4);
198 val = val + (val << 8) + (val << 16) + (val << 24);
199 return val;
202 static ULONG DoHalfshadowGun(ULONG a, ULONG b)
204 ULONG val = ((((a) >> 24) + 5 * ((b) >> 24)) / 6);
205 val = val + (val << 8) + (val << 16) + (val << 24);
206 return val;
209 static Object *CreateSysimage(struct DrawInfo *dri, ULONG which)
211 return NewObject(NULL, "sysiclass",
212 SYSIA_DrawInfo, (IPTR) dri, SYSIA_Which, which, TAG_DONE);
215 static void EnqueueByPriAndAddress(struct List *list, struct Node *node)
217 struct Node *scannode;
219 /* Sort by priority and by node address, so that a
220 "remove - modify - enqueue" sequence will re-add
221 the node at the same place in the list it was
222 initially */
223 ForeachNode(list, scannode)
225 if (((struct Node *)node)->ln_Pri > scannode->ln_Pri)
226 break;
227 if (((struct Node *)node)->ln_Pri == scannode->ln_Pri)
229 if ((IPTR) node > (IPTR) scannode)
230 break;
234 Insert(list, (struct Node *)node, scannode->ln_Pred);
237 static BOOL InitCustomFrames(Object *obj, struct MUI_RenderInfo *mri)
239 int i;
241 for (i = 0; i < 16; i++)
243 mri->mri_FrameImage[i] = NULL;
246 mri->mri_FrameImage[0] =
247 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
248 customframe_config_1, mri->mri_Screen);
249 mri->mri_FrameImage[1] =
250 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
251 customframe_config_2, mri->mri_Screen);
252 mri->mri_FrameImage[2] =
253 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
254 customframe_config_3, mri->mri_Screen);
255 mri->mri_FrameImage[3] =
256 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
257 customframe_config_4, mri->mri_Screen);
258 mri->mri_FrameImage[4] =
259 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
260 customframe_config_5, mri->mri_Screen);
261 mri->mri_FrameImage[5] =
262 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
263 customframe_config_6, mri->mri_Screen);
264 mri->mri_FrameImage[6] =
265 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
266 customframe_config_7, mri->mri_Screen);
267 mri->mri_FrameImage[7] =
268 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
269 customframe_config_8, mri->mri_Screen);
270 mri->mri_FrameImage[8] =
271 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
272 customframe_config_9, mri->mri_Screen);
273 mri->mri_FrameImage[9] =
274 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
275 customframe_config_10, mri->mri_Screen);
276 mri->mri_FrameImage[10] =
277 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
278 customframe_config_11, mri->mri_Screen);
279 mri->mri_FrameImage[11] =
280 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
281 customframe_config_12, mri->mri_Screen);
282 mri->mri_FrameImage[12] =
283 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
284 customframe_config_13, mri->mri_Screen);
285 mri->mri_FrameImage[13] =
286 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
287 customframe_config_14, mri->mri_Screen);
288 mri->mri_FrameImage[14] =
289 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
290 customframe_config_15, mri->mri_Screen);
291 mri->mri_FrameImage[15] =
292 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
293 customframe_config_16, mri->mri_Screen);
295 return TRUE;
298 static void DisposeCustomFrames(struct MUI_RenderInfo *mri)
300 int i;
302 for (i = 0; i < 16; i++)
304 dispose_custom_frame(mri->mri_FrameImage[i]);
306 mri->mri_FrameImage[i] = NULL;
310 static BOOL SetupRenderInfo(Object *obj, struct MUI_WindowData *data,
311 struct MUI_RenderInfo *mri)
313 ULONG rgbtable[3 * 3];
314 Object *temp_obj;
315 IPTR val;
316 int i;
318 /* TODO: Move this whole screen locking/opening stuff into the
319 * application class by creating methods for this purpose */
321 /* If no user screen has been specified try to open the application
322 * specific screen */
323 if (!data->wd_UserScreen)
325 ULONG screenmodeid = muiGlobalInfo(obj)->mgi_Prefs->screenmodeid;
327 if (screenmodeid != ~0)
329 if (!muiGlobalInfo(obj)->mgi_CustomScreen)
331 muiGlobalInfo(obj)->mgi_CustomScreen = OpenScreenTags
332 (NULL,
333 SA_DisplayID, screenmodeid,
334 SA_SharePens, TRUE,
335 SA_FullPalette, TRUE, SA_LikeWorkbench, TRUE, TAG_DONE);
336 /* It's fine if this fails as there is a fallback case below */
339 data->wd_UserScreen = muiGlobalInfo(obj)->mgi_CustomScreen;
342 if (data->wd_UserScreen)
344 mri->mri_Screen = data->wd_UserScreen;
346 else
348 if (data->wd_UserPublicScreen)
350 mri->mri_Screen = LockPubScreen(data->wd_UserPublicScreen);
352 else if (muiGlobalInfo(obj)->mgi_Prefs->publicscreen_name
353 && muiGlobalInfo(obj)->mgi_Prefs->publicscreen_name[0])
355 mri->mri_Screen =
356 LockPubScreen(muiGlobalInfo(obj)->mgi_Prefs->
357 publicscreen_name);
358 // FIXME: open the public screen if necessary
361 if (mri->mri_Screen == NULL)
363 mri->mri_Screen = LockPubScreen(NULL);
364 if (mri->mri_Screen == NULL)
366 return FALSE;
370 // FIXME: is this the right place for this action?
371 if (mri->mri_Screen
372 && muiGlobalInfo(obj)->mgi_Prefs->publicscreen_pop_to_front)
374 ScreenToFront(mri->mri_Screen);
377 data->wd_Flags |= MUIWF_SCREENLOCKED;
380 if (!(mri->mri_DrawInfo = GetScreenDrawInfo(mri->mri_Screen)))
382 if (data->wd_Flags & MUIWF_SCREENLOCKED)
384 UnlockPubScreen(NULL, mri->mri_Screen);
385 data->wd_Flags &= ~MUIWF_SCREENLOCKED;
387 return FALSE;
390 if (!InitCustomFrames(obj, mri))
392 if (data->wd_Flags & MUIWF_SCREENLOCKED)
394 UnlockPubScreen(NULL, mri->mri_Screen);
395 data->wd_Flags &= ~MUIWF_SCREENLOCKED;
397 return FALSE;
400 mri->mri_Colormap = mri->mri_Screen->ViewPort.ColorMap;
401 mri->mri_ScreenWidth = mri->mri_Screen->Width;
402 mri->mri_ScreenHeight = mri->mri_Screen->Height;
404 if (mri->mri_ScreenWidth / mri->mri_ScreenHeight < 2)
406 mri->mri_Flags |= MUIMRI_THINFRAMES;
409 if (GetBitMapAttr(mri->mri_Screen->RastPort.BitMap, BMA_DEPTH) >= 15)
411 mri->mri_Flags |= MUIMRI_TRUECOLOR;
414 mri->mri_PensStorage[MPEN_SHINE] =
415 mri->mri_DrawInfo->dri_Pens[SHINEPEN];
416 mri->mri_PensStorage[MPEN_BACKGROUND] =
417 mri->mri_DrawInfo->dri_Pens[BACKGROUNDPEN];
418 mri->mri_PensStorage[MPEN_SHADOW] =
419 mri->mri_DrawInfo->dri_Pens[SHADOWPEN];
420 mri->mri_PensStorage[MPEN_TEXT] = mri->mri_DrawInfo->dri_Pens[TEXTPEN];
421 mri->mri_PensStorage[MPEN_FILL] = mri->mri_DrawInfo->dri_Pens[FILLPEN];
423 GetRGB32(mri->mri_Colormap, mri->mri_DrawInfo->dri_Pens[SHINEPEN], 1,
424 rgbtable);
425 GetRGB32(mri->mri_Colormap, mri->mri_DrawInfo->dri_Pens[BACKGROUNDPEN],
426 1, rgbtable + 3);
427 GetRGB32(mri->mri_Colormap, mri->mri_DrawInfo->dri_Pens[SHADOWPEN], 1,
428 rgbtable + 6);
430 mri->mri_PensStorage[MPEN_HALFSHINE] = ObtainBestPenA
431 (mri->mri_Colormap,
432 DoHalfshineGun(rgbtable[0], rgbtable[3]),
433 DoHalfshineGun(rgbtable[1], rgbtable[4]),
434 DoHalfshineGun(rgbtable[2], rgbtable[5]), NULL);
436 mri->mri_PensStorage[MPEN_HALFSHADOW] = ObtainBestPenA
437 (mri->mri_Colormap,
438 DoHalfshadowGun(rgbtable[6], rgbtable[3]),
439 DoHalfshadowGun(rgbtable[7], rgbtable[4]),
440 DoHalfshadowGun(rgbtable[8], rgbtable[5]), NULL);
442 /* I'm really not sure that MUI does this for MPEN_MARK, but it seems
443 * mostly acceptable -dlc */
444 mri->mri_PensStorage[MPEN_MARK] = ObtainBestPenA
445 (mri->mri_Colormap, 0xf4f4f4f4, 0xb5b5b5b5, 0x8b8b8b8b, NULL);
447 mri->mri_Pens = mri->mri_PensStorage;
449 for (i = 0; i < -MUIV_Font_NegCount; i++)
451 mri->mri_Fonts[i] = NULL;
454 if (data->wd_Flags & MUIWF_USEBOTTOMSCROLLER)
456 mri->mri_LeftImage = CreateSysimage(mri->mri_DrawInfo, LEFTIMAGE);
457 mri->mri_RightImage = CreateSysimage(mri->mri_DrawInfo, RIGHTIMAGE);
459 else
461 mri->mri_LeftImage = mri->mri_RightImage = NULL;
464 if (data->wd_Flags & MUIWF_USERIGHTSCROLLER)
466 mri->mri_UpImage = CreateSysimage(mri->mri_DrawInfo, UPIMAGE);
467 mri->mri_DownImage = CreateSysimage(mri->mri_DrawInfo, DOWNIMAGE);
469 else
471 mri->mri_UpImage = mri->mri_DownImage = NULL;
474 if ((data->wd_Flags & MUIWF_USEBOTTOMSCROLLER) ||
475 (data->wd_Flags & MUIWF_USERIGHTSCROLLER))
476 mri->mri_SizeImage = CreateSysimage(mri->mri_DrawInfo, SIZEIMAGE);
477 else
478 mri->mri_SizeImage = NULL;
480 if (data->wd_CrtFlags & WFLG_BORDERLESS)
482 /* In fact borderless windows could also have borders (if they have
483 * a window title e.g. but since they look ugly anyway we ignore it
484 * for now */
485 mri->mri_BorderLeft = 0;
486 mri->mri_BorderRight = 0;
487 mri->mri_BorderTop = 0;
488 mri->mri_BorderBottom = 0;
490 else
492 mri->mri_BorderLeft = mri->mri_Screen->WBorLeft;
493 mri->mri_BorderTop =
494 mri->mri_Screen->WBorTop + mri->mri_Screen->Font->ta_YSize + 1;
495 temp_obj =
496 NewObject(NULL, "sysiclass", SYSIA_DrawInfo,
497 (IPTR) mri->mri_DrawInfo, SYSIA_Which, SIZEIMAGE, TAG_DONE);
498 if (temp_obj)
500 GetAttr(IA_Height, temp_obj, &val);
501 DisposeObject(temp_obj);
502 mri->mri_BorderBottom = val;
504 else
505 mri->mri_BorderBottom = mri->mri_Screen->WBorBottom;
508 return TRUE;
511 static void CleanupRenderInfo(Object *obj, struct MUI_WindowData *data,
512 struct MUI_RenderInfo *mri)
514 int i;
516 DisposeCustomFrames(mri);
518 if (mri->mri_LeftImage)
520 DisposeObject(mri->mri_LeftImage);
521 mri->mri_LeftImage = NULL;
523 if (mri->mri_RightImage)
525 DisposeObject(mri->mri_RightImage);
526 mri->mri_RightImage = NULL;
528 if (mri->mri_UpImage)
530 DisposeObject(mri->mri_UpImage);
531 mri->mri_UpImage = NULL;
533 if (mri->mri_DownImage)
535 DisposeObject(mri->mri_DownImage);
536 mri->mri_DownImage = NULL;
538 if (mri->mri_SizeImage)
540 DisposeObject(mri->mri_SizeImage);
541 mri->mri_SizeImage = NULL;
544 /* bug("CleanupRenderInfo\n"); */
545 for (i = 0; i < -MUIV_Font_NegCount; i++)
547 if (mri->mri_Fonts[i])
549 /* bug("CleanupRenderInfo: closing font %p (%s/%d)\n", */
550 /* mri->mri_Fonts[i], */
551 /* mri->mri_Fonts[i]->tf_Message.mn_Node.ln_Name, */
552 /* mri->mri_Fonts[i]->tf_YSize); */
553 CloseFont(mri->mri_Fonts[i]);
554 mri->mri_Fonts[i] = NULL;
557 ReleasePen(mri->mri_Colormap, mri->mri_PensStorage[MPEN_MARK]);
558 ReleasePen(mri->mri_Colormap, mri->mri_PensStorage[MPEN_HALFSHADOW]);
559 ReleasePen(mri->mri_Colormap, mri->mri_PensStorage[MPEN_HALFSHINE]);
560 FreeScreenDrawInfo(mri->mri_Screen, mri->mri_DrawInfo);
561 mri->mri_DrawInfo = NULL;
563 /* If a custom screen has been opened by zune, close it as soon as zero
564 * windows are opened. See above for comments about refactorization. */
565 if (muiGlobalInfo(obj)->mgi_CustomScreen)
567 BOOL screenclose = TRUE;
568 Object *_app = _app(obj);
569 if (_app != NULL)
571 struct List *store = NULL;
572 get(_app, MUIA_Application_WindowList, &store);
573 if (store != NULL)
575 if (!IsListEmpty(store))
576 screenclose = FALSE;
579 if (screenclose)
581 /* If the window's user screen really was the custom screen,
582 * clear the reference */
583 if (data->wd_UserScreen == muiGlobalInfo(obj)->mgi_CustomScreen)
584 data->wd_UserScreen = NULL;
586 CloseScreen(muiGlobalInfo(obj)->mgi_CustomScreen);
587 muiGlobalInfo(obj)->mgi_CustomScreen = NULL;
591 if (data->wd_Flags & MUIWF_SCREENLOCKED)
593 UnlockPubScreen(NULL, mri->mri_Screen);
594 data->wd_Flags &= ~MUIWF_SCREENLOCKED;
596 mri->mri_Screen = NULL;
599 static void ShowRenderInfo(struct MUI_RenderInfo *mri)
601 if (mri->mri_BufferBM)
603 mri->mri_RastPort = &mri->mri_BufferRP;
605 else
607 mri->mri_RastPort = mri->mri_Window->RPort;
611 static void HideRenderInfo(struct MUI_RenderInfo *mri)
613 mri->mri_RastPort = NULL;
616 static ULONG GetDefaultEvents(void)
618 return IDCMP_NEWSIZE | IDCMP_CHANGEWINDOW | IDCMP_REFRESHWINDOW
619 | IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE | IDCMP_MENUPICK
620 | IDCMP_CLOSEWINDOW | IDCMP_RAWKEY | IDCMP_INTUITICKS
621 | IDCMP_ACTIVEWINDOW | IDCMP_INACTIVEWINDOW | IDCMP_GADGETUP;
624 static void ChangeEvents(struct MUI_WindowData *data, ULONG new_events)
626 struct MinNode *mn;
627 struct MUI_EventHandlerNode *ehn;
628 ULONG old_events = data->wd_Events;
630 for (mn = data->wd_EHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
632 ehn = (struct MUI_EventHandlerNode *)mn;
633 new_events |= ehn->ehn_Events;
636 /* sba: kill the IDCMP_VANILLAKEY flag. MUI doesn't do this but programs
637 ** which use this will behave different if they request for this flag
638 ** (also on MUI)
640 new_events &= ~IDCMP_VANILLAKEY;
642 data->wd_Events = new_events;
643 if ((old_events != new_events) && (data->wd_Flags & MUIWF_OPENED))
645 ModifyIDCMP(data->wd_RenderInfo.mri_Window, new_events);
649 static void CalcWindowPosition(Object *obj, struct MUI_WindowData *data);
650 static void CreateWindowScrollbars(Object *obj,
651 struct MUI_WindowData *data);
652 static void CalcAltDimensions(Object *obj, struct MUI_WindowData *data);
653 static void UndisplayWindow(Object *obj, struct MUI_WindowData *data);
654 static struct ObjNode *FindObjNode(struct MinList *list, Object *obj);
656 static BOOL DisplayWindow(Object *obj, struct MUI_WindowData *data)
658 struct Window *win;
659 ULONG flags = data->wd_CrtFlags;
660 struct IBox altdims;
661 ULONG backfill, buttons;
663 struct Menu *menu = NULL;
664 struct NewMenu *newmenu = NULL;
665 APTR visinfo = NULL;
667 Object *gadgets;
669 if (!(data->wd_Flags & MUIWF_DONTACTIVATE))
671 flags |= WFLG_ACTIVATE;
674 /* Toolboxes are handled differently on AmigaOS */
675 #ifdef __AROS__
676 if (data->wd_Flags & MUIWF_TOOLBOX)
677 flags |= WFLG_TOOLBOX;
678 #endif
680 if (data->wd_MinMax.MinHeight == data->wd_MinMax.MaxHeight
681 && data->wd_MinMax.MinWidth == data->wd_MinMax.MaxWidth)
682 flags &= ~WFLG_SIZEGADGET;
684 if (!(flags & WFLG_SIZEBRIGHT))
685 flags |= WFLG_SIZEBBOTTOM;
687 CalcWindowPosition(obj, data);
689 if ((visinfo = GetVisualInfoA(data->wd_RenderInfo.mri_Screen, NULL)))
691 if (data->wd_Menustrip)
693 get(data->wd_Menustrip, MUIA_Menuitem_NewMenu, &newmenu);
694 if (newmenu)
696 if ((menu = CreateMenusA(newmenu, NULL)))
698 struct TagItem tags[] = {
699 {GTMN_NewLookMenus, TRUE},
700 {TAG_DONE, (IPTR) NULL}
702 LayoutMenusA(menu, visinfo, tags);
706 FreeVisualInfo(visinfo);
709 CreateWindowScrollbars(obj, data);
710 CalcAltDimensions(obj, data);
711 altdims = data->wd_AltDim;
713 /* hack to account for border size, as we only know the innersize and
714 * must give the total size.
716 altdims.Width +=
717 data->wd_RenderInfo.mri_Screen->WBorLeft +
718 data->wd_RenderInfo.mri_Screen->WBorRight;
719 altdims.Height +=
720 data->wd_RenderInfo.mri_Screen->WBorTop +
721 data->wd_RenderInfo.mri_Screen->WBorBottom +
722 data->wd_RenderInfo.mri_DrawInfo->dri_Font->tf_YSize + 1;
724 if (muiGlobalInfo(obj)->mgi_Prefs->window_redraw ==
725 WINDOW_REDRAW_WITHOUT_CLEAR)
726 backfill = WA_BackFill;
727 else
728 backfill = TAG_IGNORE;
730 if (muiGlobalInfo(obj)->mgi_Prefs->window_refresh ==
731 WINDOW_REFRESH_SMART)
732 flags &= ~WFLG_SIMPLE_REFRESH;
733 set(_app(obj), MUIA_Application_SearchWinId, data->wd_ID);
734 struct windowpos *winp = 0;
735 get(_app(obj), MUIA_Application_GetWinPos, &winp);
736 if (winp)
738 if (data->wd_RenderInfo.mri_ScreenWidth >
739 (data->wd_X + data->wd_Width))
741 data->wd_X = winp->x1;
742 data->wd_Width = winp->w1;
744 if (data->wd_RenderInfo.mri_ScreenHeight >
745 (data->wd_Y + data->wd_Height))
747 data->wd_Y = winp->y1;
748 data->wd_Height = winp->h1;
752 gadgets =
753 (data->wd_VertProp !=
754 NULL) ? data->wd_VertProp : data->wd_HorizProp;
755 buttons = muiGlobalInfo(obj)->mgi_Prefs->window_buttons;
757 win = OpenWindowTags
758 (NULL,
759 WA_Left, (IPTR) data->wd_X,
760 WA_Top, (IPTR) data->wd_Y,
761 WA_Flags, (IPTR) flags,
762 data->wd_Title ?
763 WA_Title :
764 TAG_IGNORE, (IPTR) data->wd_Title,
765 data->wd_ScreenTitle ?
766 WA_ScreenTitle :
767 TAG_IGNORE, (IPTR) data->wd_ScreenTitle,
768 WA_CustomScreen, (IPTR) data->wd_RenderInfo.mri_Screen,
769 WA_InnerWidth, (IPTR) data->wd_Width,
770 WA_InnerHeight, (IPTR) data->wd_Height,
771 WA_AutoAdjust, (IPTR) TRUE, WA_NewLookMenus, (IPTR) TRUE,
772 /* AmigaOS v4 extension */
773 #ifdef WA_ToolBox
774 WA_ToolBox, (IPTR) ! !(data->wd_Flags & MUIWF_TOOLBOX),
775 #endif
776 /* MorphOS extensions */
777 #ifdef WA_ExtraGadget_MUI
778 WA_ExtraGadget_MUI,
779 (IPTR) ((buttons & MUIV_Window_Button_MUI) != 0) ? TRUE : FALSE,
780 WA_ExtraGadget_PopUp,
781 (IPTR) ((buttons & MUIV_Window_Button_Popup) != 0) ? TRUE : FALSE,
782 WA_ExtraGadget_Snapshot,
783 (IPTR) ((buttons & MUIV_Window_Button_Snapshot) !=
784 0) ? TRUE : FALSE, WA_ExtraGadget_Iconify,
785 (IPTR) ((buttons & MUIV_Window_Button_Iconify) != 0) ? TRUE : FALSE,
786 #endif
787 data->wd_NoMenus ?
788 WA_RMBTrap :
789 TAG_IGNORE, (IPTR) TRUE,
790 WA_Gadgets, (IPTR) gadgets,
791 data->wd_ZoomGadget ?
792 WA_Zoom :
793 TAG_IGNORE, (IPTR) & altdims,
794 backfill, (IPTR) LAYERS_NOBACKFILL, TAG_DONE);
796 if (win)
799 int hborders = win->BorderLeft + win->BorderRight;
800 int vborders = win->BorderTop + win->BorderBottom;
802 /* recalc window size (which will hopefully equal our requested
803 * size) */
804 data->wd_Width = win->GZZWidth;
805 data->wd_Height = win->GZZHeight;
807 /* set window limits according to window contents */
808 WindowLimits
809 (win, data->wd_MinMax.MinWidth + hborders,
810 data->wd_MinMax.MinHeight + vborders,
811 data->wd_MinMax.MaxWidth + hborders,
812 data->wd_MinMax.MaxHeight + vborders);
814 win->UserData = (BYTE *) data->wd_RenderInfo.mri_WindowObject;
815 win->UserPort = muiGlobalInfo(obj)->mgi_WindowsPort;
816 /* Same port for all windows */
817 ModifyIDCMP(win, data->wd_Events);
819 data->wd_RenderInfo.mri_Window = win;
820 data->wd_RenderInfo.mri_VertProp = data->wd_VertProp;
821 data->wd_RenderInfo.mri_HorizProp = data->wd_HorizProp;
822 SetDrMd(win->RPort, JAM1);
823 //text is drawn wrong in toolbarclass if not set
825 if (menu)
827 data->wd_Menu = menu;
828 SetMenuStrip(win, menu);
831 if (flags & WFLG_ACTIVATE)
833 data->wd_Flags |= MUIWF_ACTIVE;
836 if (data->wd_Flags & MUIWF_ISAPPWINDOW)
838 data->wd_AppWindow = AddAppWindowA(0, (IPTR) obj, win,
839 muiGlobalInfo(obj)->mgi_AppPort, NULL);
842 return TRUE;
845 if (menu)
846 FreeMenus(menu);
847 UndisplayWindow(obj, data);
849 return FALSE;
853 static void UndisplayWindow(Object *obj, struct MUI_WindowData *data)
855 struct Window *win = data->wd_RenderInfo.mri_Window;
856 BOOL prefssnap =
857 ((muiGlobalInfo(obj)->mgi_Prefs->window_position ==
858 WINDOW_POSITION_REMEMBER_ON_EXIT)
859 || (muiGlobalInfo(obj)->mgi_Prefs->window_position ==
860 WINDOW_POSITION_SAVE_ON_EXIT));
862 if (((data->wd_XStore >= 0) && (data->wd_YStore >= 0)) || prefssnap)
864 DoMethod(obj, MUIM_Window_Snapshot, 1);
867 data->wd_RenderInfo.mri_Window = NULL;
868 data->wd_RenderInfo.mri_VertProp = NULL;
869 data->wd_RenderInfo.mri_HorizProp = NULL;
871 data->wd_Flags &= ~MUIWF_ACTIVE;
873 if (win != NULL)
875 /* store position and size */
876 if (data->wd_XStore >= 0)
877 data->wd_X = win->LeftEdge;
878 else
879 data->wd_X = data->wd_XStore;
880 if (data->wd_YStore >= 0)
881 data->wd_Y = win->TopEdge;
882 else
883 data->wd_Y = data->wd_YStore;
884 data->wd_Width = win->GZZWidth;
885 data->wd_Height = win->GZZHeight;
887 ClearMenuStrip(win);
888 if (data->wd_Menu)
890 FreeMenus(data->wd_Menu);
891 data->wd_Menu = NULL;
894 if (win->UserPort)
896 struct IntuiMessage *msg, *succ;
898 /* remove all messages pending for this window */
899 Forbid();
900 for (msg =
901 (struct IntuiMessage *)win->UserPort->mp_MsgList.lh_Head;
902 (succ =
903 (struct IntuiMessage *)msg->ExecMessage.mn_Node.
904 ln_Succ); msg = succ)
906 if (msg->IDCMPWindow == win)
908 Remove((struct Node *)msg);
909 ReplyMsg((struct Message *)msg);
912 win->UserPort = NULL;
913 ModifyIDCMP(win, 0);
914 Permit();
917 /* D(bug("before CloseWindow\n")); */
918 CloseWindow(win);
919 /* D(bug("after CloseWindow\n")); */
922 #define DISPOSEGADGET(x) \
923 if (x)\
925 DoMethod(obj, MUIM_Window_FreeGadgetID,\
926 ((struct Gadget*)x)->GadgetID);\
927 DisposeObject(x);\
928 x = NULL;\
931 DISPOSEGADGET(data->wd_VertProp);
932 DISPOSEGADGET(data->wd_UpButton);
933 DISPOSEGADGET(data->wd_DownButton);
934 DISPOSEGADGET(data->wd_HorizProp);
935 DISPOSEGADGET(data->wd_LeftButton);
936 DISPOSEGADGET(data->wd_RightButton);
937 #undef DISPOSEGADGET
941 static VOID RefreshWindow(Object *oWin, struct MUI_WindowData *data)
943 if (data->wd_Flags & MUIWF_RESIZING)
945 //LONG left,top,right,bottom;
946 if (MUI_BeginRefresh(&data->wd_RenderInfo, 0))
948 MUI_EndRefresh(&data->wd_RenderInfo, 0);
950 RefreshWindowFrame(data->wd_RenderInfo.mri_Window);
952 data->wd_Flags &= ~MUIWF_RESIZING;
953 _width(data->wd_RootObject) = data->wd_Width;
954 _height(data->wd_RootObject) = data->wd_Height;
955 DoMethod(data->wd_RootObject, MUIM_Layout);
956 DoShowMethod(data->wd_RootObject);
958 if (muiGlobalInfo(oWin)->mgi_Prefs->window_redraw ==
959 WINDOW_REDRAW_WITH_CLEAR)
961 LONG left, top, width, height;
963 left = data->wd_RenderInfo.mri_Window->BorderLeft;
964 top = data->wd_RenderInfo.mri_Window->BorderTop;
965 width =
966 data->wd_RenderInfo.mri_Window->Width -
967 data->wd_RenderInfo.mri_Window->BorderRight - left;
968 height =
969 data->wd_RenderInfo.mri_Window->Height -
970 data->wd_RenderInfo.mri_Window->BorderBottom - top;
972 if (data->wd_Flags & MUIWF_ERASEAREA)
974 //D(bug("%d:zune_imspec_draw(%p) "
975 // "l=%d t=%d w=%d h=%d xo=%d yo=%d\n",
976 // __LINE__, data->wd_Background, left, top, width,
977 // height, left, top));
978 zune_imspec_draw(data->wd_Background,
979 &data->wd_RenderInfo, left, top, width, height,
980 left, top, 0);
982 MUI_Redraw(data->wd_RootObject, MADF_DRAWALL);
984 else
985 MUI_Redraw(data->wd_RootObject, MADF_DRAWOBJECT);
986 // but should only draw focus without using MUIM_GoActive !
987 ActivateObject(data);
989 else
991 if (MUI_BeginRefresh(&data->wd_RenderInfo, 0))
993 MUI_Redraw(data->wd_RootObject, MADF_DRAWALL);
994 // but should only draw focus without using MUIM_GoActive !
995 ActivateObject(data);
996 MUI_EndRefresh(&data->wd_RenderInfo, 0);
1002 /* Initialize data->wd_X and data->wd_Y for DisplayWindow */
1003 /* FIXME 20030817: needs some fixing, seems not fully implemented */
1004 static void CalcWindowPosition(Object *obj, struct MUI_WindowData *data)
1006 data->wd_XStore = data->wd_X;
1007 data->wd_YStore = data->wd_Y;
1008 if (NULL == data->wd_RefWindow)
1010 /* The following calculations are not very correct, the size and
1011 * dragbar are ignored also the current overscan view */
1012 if (data->wd_X == MUIV_Window_LeftEdge_Centered)
1014 data->wd_X =
1015 (data->wd_RenderInfo.mri_Screen->ViewPort.DWidth -
1016 data->wd_Width) / 2 -
1017 data->wd_RenderInfo.mri_Screen->LeftEdge;
1019 else if (data->wd_X == MUIV_Window_LeftEdge_Moused)
1021 data->wd_X = data->wd_RenderInfo.mri_Screen->MouseX;
1024 if (data->wd_Y == MUIV_Window_TopEdge_Centered)
1026 data->wd_Y =
1027 (data->wd_RenderInfo.mri_Screen->ViewPort.DHeight -
1028 data->wd_Height) / 2 -
1029 data->wd_RenderInfo.mri_Screen->TopEdge;
1031 else if (data->wd_Y == MUIV_Window_TopEdge_Moused)
1033 data->wd_Y = data->wd_RenderInfo.mri_Screen->MouseY;
1035 else if (data->wd_Y <= MUIV_Window_TopEdge_Delta(0))
1037 data->wd_Y = data->wd_RenderInfo.mri_Screen->BarHeight + 1
1038 + MUIV_Window_TopEdge_Delta(0) - data->wd_Y;
1041 else
1043 ULONG w = 0, x = 0;
1044 ULONG h = 0, y = 0;
1046 get(data->wd_RefWindow, MUIA_Window_Width, &w);
1047 get(data->wd_RefWindow, MUIA_Window_LeftEdge, &x);
1049 if (data->wd_X == MUIV_Window_LeftEdge_Centered)
1051 data->wd_X = x + (w - data->wd_Width) / 2;
1053 else
1055 data->wd_X += x;
1058 get(data->wd_RefWindow, MUIA_Window_Height, &h);
1059 get(data->wd_RefWindow, MUIA_Window_TopEdge, &y);
1061 if (data->wd_Y == MUIV_Window_TopEdge_Centered)
1063 /* D(bug("y=%ld, h=%ld, wdh=%ld\n", y, h, data->wd_Height)); */
1064 data->wd_Y = y + (h - data->wd_Height) / 2;
1066 else if (data->wd_Y <= MUIV_Window_TopEdge_Delta(0))
1068 /* ??? surely incorrect implementation */
1069 data->wd_Y = y + 1 + MUIV_Window_TopEdge_Delta(0) - data->wd_Y;
1071 else
1073 data->wd_Y += y;
1078 /* Initialize data->wd_AltDim for DisplayWindow */
1079 static void CalcAltDimensions(Object *obj, struct MUI_WindowData *data)
1081 /* Calculate alternate (zoomed) dimensions.
1083 if (data->wd_AltDim.Top == MUIV_Window_AltTopEdge_NoChange)
1084 data->wd_AltDim.Top = ~0;
1085 else if (data->wd_AltDim.Top == MUIV_Window_AltTopEdge_Centered)
1086 data->wd_AltDim.Top =
1087 (data->wd_RenderInfo.mri_Screen->Height - data->wd_Height) / 2;
1088 else if (data->wd_AltDim.Top == MUIV_Window_AltTopEdge_Moused)
1089 /* ? */ data->wd_AltDim.Top = ~0;
1091 if (data->wd_AltDim.Left == MUIV_Window_AltLeftEdge_NoChange)
1092 data->wd_AltDim.Left = ~0;
1093 else if (data->wd_AltDim.Left == MUIV_Window_AltLeftEdge_Centered)
1094 data->wd_AltDim.Left =
1095 (data->wd_RenderInfo.mri_Screen->Width - data->wd_Width) / 2;
1096 else if (data->wd_AltDim.Left == MUIV_Window_AltLeftEdge_Moused)
1097 /* ? */ data->wd_AltDim.Left = ~0;
1099 if (_between
1100 (MUIV_Window_AltWidth_MinMax(100),
1101 data->wd_AltDim.Width, MUIV_Window_AltWidth_MinMax(0)))
1103 data->wd_AltDim.Width = data->wd_MinMax.MinWidth
1104 - data->wd_AltDim.Width
1105 * (data->wd_MinMax.MaxWidth - data->wd_MinMax.MinWidth);
1107 else if
1108 (_between
1109 (MUIV_Window_AltWidth_Screen(100),
1110 data->wd_AltDim.Width, MUIV_Window_AltWidth_Screen(0)))
1112 data->wd_AltDim.Width = data->wd_RenderInfo.mri_ScreenWidth
1113 * (-(data->wd_AltDim.Width + 200)) / 100;
1115 else if
1116 (_between
1117 (MUIV_Window_AltWidth_Visible(100),
1118 data->wd_AltDim.Width, MUIV_Window_AltWidth_Visible(0)))
1120 data->wd_AltDim.Width = data->wd_RenderInfo.mri_ScreenWidth
1121 * (-(data->wd_AltDim.Width + 100)) / 100;
1124 if (_between
1125 (MUIV_Window_AltHeight_MinMax(100),
1126 data->wd_AltDim.Height, MUIV_Window_AltHeight_MinMax(0)))
1128 data->wd_AltDim.Height = data->wd_MinMax.MinHeight
1129 - data->wd_AltDim.Height
1130 * (data->wd_MinMax.MaxHeight - data->wd_MinMax.MinHeight);
1132 else if
1133 (_between
1134 (MUIV_Window_AltHeight_Screen(100),
1135 data->wd_AltDim.Height, MUIV_Window_AltHeight_Screen(0)))
1137 data->wd_AltDim.Height = data->wd_RenderInfo.mri_ScreenHeight
1138 * (-(data->wd_AltDim.Height + 200)) / 100;
1140 else if
1141 (_between
1142 (MUIV_Window_AltHeight_Visible(100),
1143 data->wd_AltDim.Height, MUIV_Window_AltHeight_Visible(0)))
1145 data->wd_AltDim.Height = data->wd_RenderInfo.mri_ScreenHeight
1146 * (-(data->wd_AltDim.Height + 100)) / 100;
1149 data->wd_AltDim.Width = CLAMP
1150 (data->wd_AltDim.Width, data->wd_MinMax.MinWidth,
1151 data->wd_MinMax.MaxWidth);
1152 data->wd_AltDim.Height = CLAMP
1153 (data->wd_AltDim.Height, data->wd_MinMax.MinHeight,
1154 data->wd_MinMax.MaxHeight);
1158 /* Create horiz/vert window scrollbars for DisplayWindow */
1159 static void CreateWindowScrollbars(Object *obj,
1160 struct MUI_WindowData *data)
1162 struct MUI_RenderInfo *mri = &data->wd_RenderInfo;
1163 Object *firstgad = NULL;
1164 Object *prevgad = NULL;
1165 LONG id;
1167 /* Create the right border scrollers now if requested */
1168 if (data->wd_Flags & MUIWF_USERIGHTSCROLLER)
1170 int voffset;
1172 voffset = IM(mri->mri_DownImage)->Width / 4;
1174 id = DoMethod(obj, MUIM_Window_AllocGadgetID);
1175 firstgad = prevgad = data->wd_VertProp = NewObject
1176 (NULL, "propgclass",
1177 GA_RelRight, 1 - (IM(mri->mri_UpImage)->Width - voffset),
1178 GA_Top, mri->mri_BorderTop + 2,
1179 GA_Width, IM(mri->mri_UpImage)->Width - voffset * 2,
1180 GA_RelHeight, -(mri->mri_BorderTop + 2)
1181 - IM(mri->mri_UpImage)->Height
1182 - IM(mri->mri_DownImage)->Height
1183 - IM(mri->mri_SizeImage)->Height - 2,
1184 GA_RightBorder, TRUE,
1185 GA_ID, id,
1186 PGA_Borderless, TRUE,
1187 PGA_NewLook, TRUE,
1188 PGA_Freedom, FREEVERT,
1189 PGA_Top, 0,
1190 PGA_Total, 2,
1191 PGA_Visible, 1, ICA_TARGET, ICTARGET_IDCMP, TAG_DONE);
1193 id = DoMethod(obj, MUIM_Window_AllocGadgetID);
1194 prevgad = data->wd_UpButton = NewObject
1195 (NULL, "buttongclass",
1196 GA_Image, (IPTR) mri->mri_UpImage,
1197 GA_RelRight, 1 - IM(mri->mri_UpImage)->Width,
1198 GA_RelBottom, 1 - IM(mri->mri_UpImage)->Height
1199 - IM(mri->mri_DownImage)->Height
1200 - IM(mri->mri_SizeImage)->Height,
1201 GA_RightBorder, TRUE,
1202 GA_Previous, (IPTR) prevgad,
1203 GA_ID, id, ICA_TARGET, ICTARGET_IDCMP, TAG_DONE);
1205 id = DoMethod(obj, MUIM_Window_AllocGadgetID);
1206 prevgad = data->wd_DownButton = NewObject
1207 (NULL, "buttongclass",
1208 GA_Image, (IPTR) mri->mri_DownImage,
1209 GA_RelRight, 1 - IM(mri->mri_DownImage)->Width,
1210 GA_RelBottom, 1 - IM(mri->mri_DownImage)->Height
1211 - IM(mri->mri_SizeImage)->Height,
1212 GA_RightBorder, TRUE,
1213 GA_Previous, (IPTR) prevgad,
1214 GA_ID, id, ICA_TARGET, ICTARGET_IDCMP, TAG_DONE);
1217 /* Create the bottom border scrollers now if requested */
1218 if (data->wd_Flags & MUIWF_USEBOTTOMSCROLLER)
1220 int hoffset;
1222 hoffset = IM(mri->mri_RightImage)->Height / 4;
1224 id = DoMethod(obj, MUIM_Window_AllocGadgetID);
1225 prevgad = data->wd_HorizProp = NewObject
1226 (NULL, "propgclass",
1227 GA_RelBottom, 1 - (IM(mri->mri_LeftImage)->Height - hoffset),
1228 GA_Left, mri->mri_BorderLeft,
1229 GA_Height, IM(mri->mri_LeftImage)->Height
1230 - hoffset * 2,
1231 GA_RelWidth, -(mri->mri_BorderLeft)
1232 - IM(mri->mri_LeftImage)->Width
1233 - IM(mri->mri_RightImage)->Width
1234 - IM(mri->mri_SizeImage)->Width
1235 - 2,
1236 GA_BottomBorder, TRUE,
1237 GA_ID, id,
1238 prevgad ? GA_Previous : TAG_IGNORE, (IPTR) prevgad,
1239 PGA_Borderless, TRUE,
1240 PGA_NewLook, TRUE,
1241 PGA_Freedom, FREEHORIZ,
1242 PGA_Top, 0,
1243 PGA_Total, 2,
1244 PGA_Visible, 1, ICA_TARGET, ICTARGET_IDCMP, TAG_DONE);
1246 if (!firstgad)
1247 firstgad = prevgad;
1249 id = DoMethod(obj, MUIM_Window_AllocGadgetID);
1250 prevgad = data->wd_LeftButton = NewObject
1251 (NULL, "buttongclass",
1252 GA_Image, (IPTR) mri->mri_LeftImage,
1253 GA_RelRight, 1 - IM(mri->mri_LeftImage)->Width
1254 - IM(mri->mri_RightImage)->Width
1255 - IM(mri->mri_SizeImage)->Width,
1256 GA_RelBottom, 1 - IM(mri->mri_LeftImage)->Height,
1257 GA_BottomBorder, TRUE,
1258 GA_Previous, (IPTR) prevgad,
1259 GA_ID, id, ICA_TARGET, ICTARGET_IDCMP, TAG_DONE);
1261 id = DoMethod(obj, MUIM_Window_AllocGadgetID);
1262 prevgad = data->wd_RightButton = NewObject
1263 (NULL, "buttongclass",
1264 GA_Image, (IPTR) mri->mri_RightImage,
1265 GA_RelRight, 1 - IM(mri->mri_RightImage)->Width
1266 - IM(mri->mri_SizeImage)->Width,
1267 GA_RelBottom, 1 - IM(mri->mri_RightImage)->Height,
1268 GA_BottomBorder, TRUE,
1269 GA_Previous, (IPTR) prevgad,
1270 GA_ID, id, ICA_TARGET, ICTARGET_IDCMP, TAG_DONE);
1274 /* return FALSE only if no resize (dx=dy=0) occured */
1275 static BOOL WindowResize(struct MUI_WindowData *data)
1277 struct Window *win = data->wd_RenderInfo.mri_Window;
1278 int hborders = win->BorderLeft + win->BorderRight;
1279 int vborders = win->BorderTop + win->BorderBottom;
1280 WORD dx = data->wd_Width - win->Width + hborders;
1281 WORD dy = data->wd_Height - win->Height + vborders;
1283 /* Temporarily disable window limits to let SizeWindow below work
1284 regardless of the previous limits */
1285 WindowLimits(win, 1, 1, -1, -1);
1286 /* D(bug("_zune_window_resize : dx=%d, dy=%d\n", dx, dy)); */
1287 SizeWindow(win, dx, dy);
1289 /* Set new window limits */
1290 WindowLimits
1291 (win, data->wd_MinMax.MinWidth + hborders,
1292 data->wd_MinMax.MinHeight + vborders,
1293 data->wd_MinMax.MaxWidth + hborders,
1294 data->wd_MinMax.MaxHeight + vborders);
1296 return dx || dy;
1299 static void KillHelpBubble(struct MUI_WindowData *data, Object *obj,
1300 BOOL kill_bubblemode)
1302 if (data->wd_HelpObject)
1304 DoMethod(data->wd_HelpObject, MUIM_DeleteBubble,
1305 (IPTR) data->wd_HelpBubble);
1306 data->wd_HelpObject = NULL;
1307 data->wd_HelpBubble = NULL;
1310 if (kill_bubblemode)
1311 data->wd_Flags &= ~MUIWF_BUBBLEMODE;
1313 if (data->wd_Flags & MUIWF_BUBBLEMODE)
1315 data->wd_HelpTicker = BUBBLEHELP_TICKER_LATER;
1317 else
1319 data->wd_HelpTicker = BUBBLEHELP_TICKER_FIRST;
1324 /**************/
1326 typedef BOOL(*UNDERCHECK_FUNC) (Object *obj);
1328 static BOOL ShortHelpUnderPointerCheck(Object *obj)
1330 return muiAreaData(obj)->mad_ShortHelp ? TRUE : FALSE;
1333 static Object *ObjectUnderPointer(struct MUI_WindowData *data, Object *obj,
1334 LONG x, LONG y, UNDERCHECK_FUNC func)
1336 Object *cstate;
1337 Object *child;
1338 struct MinList *ChildList = NULL;
1340 if (!(muiAreaData(obj)->mad_Flags & MADF_CANDRAW))
1341 return NULL;
1343 if (!(x >= _left(obj) && x <= _right(obj)
1344 && y >= _top(obj) && y <= _bottom(obj)))
1346 return NULL;
1349 if ((get(obj, MUIA_Group_ChildList, &(ChildList)))
1350 && (ChildList != NULL))
1352 cstate = (Object *) ChildList->mlh_Head;
1353 while ((child = NextObject(&cstate)))
1355 Object *ret;
1357 if ((x >= _left(child) && x <= _right(child)
1359 y >= _top(child) && y <= _bottom(child))
1360 && (ret = ObjectUnderPointer(data, child, x, y, func)))
1362 return ret;
1367 if (!(*func) (obj))
1368 return NULL;
1370 return obj;
1373 static BOOL ContextMenuUnderPointer(struct MUI_WindowData *data,
1374 Object *obj, LONG x, LONG y)
1376 Object *cstate;
1377 Object *child;
1378 struct MinList *ChildList = NULL;
1380 if (!(x >= _left(obj) && x <= _right(obj)
1381 && y >= _top(obj) && y <= _bottom(obj)))
1383 return FALSE;
1386 if ((get(obj, MUIA_Group_ChildList, &(ChildList)))
1387 && (ChildList != NULL))
1390 cstate = (Object *) ChildList->mlh_Head;
1391 while ((child = NextObject(&cstate)))
1393 if ((x >= _left(child) && x <= _right(child)
1395 y >= _top(child) && y <= _bottom(child))
1396 && (ContextMenuUnderPointer(data, child, x, y)))
1397 return TRUE;
1401 if (!(muiAreaData(obj)->mad_Flags & MADF_CANDRAW))
1402 return FALSE;
1403 if (!(muiAreaData(obj)->mad_ContextMenu))
1404 return FALSE;
1406 return TRUE;
1409 /**************/
1411 static void ActivateObject(struct MUI_WindowData *data)
1413 //bug("Window::ActivateObject (dummy) %08lx\n", data->wd_ActiveObject);
1414 // if (FindObjNode(&data->wd_CycleChain, data->wd_ActiveObject))
1415 // DoMethod(data->wd_ActiveObject, MUIM_GoActive);
1416 // else
1417 // data->wd_ActiveObject = NULL;
1419 //activate better string gadgets.Fix from Georg S On ML List
1420 if (FindObjNode(&data->wd_CycleChain, data->wd_ActiveObject))
1422 if (!(data->wd_Flags & MUIWF_OBJECTGOACTIVESENT))
1424 data->wd_Flags |= MUIWF_OBJECTGOACTIVESENT;
1425 DoMethod(data->wd_ActiveObject, MUIM_GoActive);
1428 else
1429 data->wd_ActiveObject = NULL;
1432 /**************/
1434 /* handle intuimessage while an object is being dragged
1435 * (reply imsg before returning)
1436 * Returns TRUE if finished dragging.
1438 static BOOL HandleDragging(Object *oWin, struct MUI_WindowData *data,
1439 struct IntuiMessage *imsg)
1441 struct Window *iWin;
1442 BOOL finish_drag = FALSE;
1444 iWin = imsg->IDCMPWindow;
1446 if (imsg->Class == IDCMP_MOUSEMOVE)
1448 struct Layer *layer;
1450 LockLayerInfo(&iWin->WScreen->LayerInfo);
1451 layer = WhichLayer(&iWin->WScreen->LayerInfo,
1452 iWin->LeftEdge + imsg->MouseX, iWin->TopEdge + imsg->MouseY);
1453 UnlockLayerInfo(&iWin->WScreen->LayerInfo);
1455 if (data->wd_DropObject)
1457 struct Window *wnd;
1458 WORD mousex =
1459 imsg->MouseX + iWin->LeftEdge -
1460 data->wd_DropWindow->LeftEdge;
1461 WORD mousey =
1462 imsg->MouseY + iWin->TopEdge - data->wd_DropWindow->TopEdge;
1464 wnd = _window(data->wd_DropObject);
1465 if (mousex < _left(data->wd_DropObject)
1466 || mousex > _right(data->wd_DropObject)
1467 || mousey < _top(data->wd_DropObject)
1468 || mousey > _bottom(data->wd_DropObject)
1469 || layer != wnd->WLayer)
1471 /* We have left the object */
1472 UndrawDragNDrop(data->wd_dnd);
1473 DoMethod(data->wd_DropObject, MUIM_DragFinish,
1474 (IPTR) data->wd_DragObject);
1475 data->wd_DropObject = NULL;
1477 } /* if (data->wd_DropObject) */
1479 if (!data->wd_DropObject)
1481 Object *dest_wnd = NULL;
1483 /* Find out if app has an open window at this position */
1484 if (layer)
1486 Object *cstate;
1487 Object *child;
1488 struct MinList *ChildList = 0;
1490 get(_app(oWin), MUIA_Application_WindowList, &(ChildList));
1491 cstate = (Object *) ChildList->mlh_Head;
1492 while ((child = NextObject(&cstate)))
1494 struct Window *wnd = NULL;
1495 get(child, MUIA_Window_Window, &wnd);
1496 if (!wnd)
1497 continue;
1499 if (wnd->WLayer == layer)
1501 data->wd_DropWindow = wnd;
1502 dest_wnd = child;
1503 break;
1506 } /* if (layer) */
1508 if (dest_wnd)
1510 Object *root = NULL;
1511 get(dest_wnd, MUIA_Window_RootObject, &root);
1513 if (root)
1515 if ((data->wd_DropObject = (Object *) DoMethod
1516 (root, MUIM_DragQueryExtended,
1517 (IPTR) data->wd_DragObject,
1518 imsg->MouseX + iWin->LeftEdge -
1519 data->wd_DropWindow->LeftEdge,
1520 imsg->MouseY + iWin->TopEdge -
1521 data->wd_DropWindow->TopEdge)))
1523 UndrawDragNDrop(data->wd_dnd);
1524 DoMethod(data->wd_DropObject, MUIM_DragBegin,
1525 (IPTR) data->wd_DragObject);
1531 if (data->wd_DropObject)
1533 LONG update = 0;
1534 LONG i;
1535 for (i = 0; i < 2; i++)
1537 LONG res = DoMethod(data->wd_DropObject, MUIM_DragReport,
1538 (IPTR) data->wd_DragObject,
1539 imsg->MouseX + iWin->LeftEdge -
1540 data->wd_DropWindow->LeftEdge,
1541 imsg->MouseY + iWin->TopEdge -
1542 data->wd_DropWindow->TopEdge, update);
1543 switch (res)
1545 case MUIV_DragReport_Abort:
1546 UndrawDragNDrop(data->wd_dnd);
1547 DoMethod(data->wd_DropObject, MUIM_DragFinish,
1548 (IPTR) data->wd_DragObject);
1549 data->wd_DropObject = NULL;
1550 i = 1;
1551 break;
1553 case MUIV_DragReport_Continue:
1554 break;
1555 case MUIV_DragReport_Lock:
1556 break; /* NYI */
1557 case MUIV_DragReport_Refresh:
1558 UndrawDragNDrop(data->wd_dnd);
1559 update = 1;
1560 break;
1564 DrawDragNDrop(data->wd_dnd, imsg->MouseX + iWin->LeftEdge,
1565 imsg->MouseY + iWin->TopEdge);
1568 if (imsg->Class == IDCMP_MOUSEBUTTONS)
1570 if ((imsg->Code == MENUDOWN) || (imsg->Code == SELECTUP))
1572 UndrawDragNDrop(data->wd_dnd);
1573 if (imsg->Code == SELECTUP && data->wd_DropObject)
1575 DoMethod(data->wd_DropObject, MUIM_DragDrop,
1576 (IPTR) data->wd_DragObject,
1577 imsg->MouseX + iWin->LeftEdge -
1578 data->wd_DropWindow->LeftEdge,
1579 imsg->MouseY + iWin->TopEdge -
1580 data->wd_DropWindow->TopEdge);
1581 DoMethod(data->wd_DropObject, MUIM_DragFinish,
1582 (IPTR) data->wd_DragObject);
1583 data->wd_DropObject = NULL;
1585 else if (imsg->Code == SELECTUP)
1587 DoMethod(data->wd_DragObject, MUIM_UnknownDropDestination,
1588 imsg);
1590 finish_drag = TRUE;
1594 if (imsg->Class == IDCMP_CLOSEWINDOW)
1595 finish_drag = TRUE;
1597 if (finish_drag)
1599 if (data->wd_DropObject)
1601 UndrawDragNDrop(data->wd_dnd);
1602 DoMethod(data->wd_DropObject, MUIM_DragFinish,
1603 (IPTR) data->wd_DragObject);
1604 data->wd_DropObject = NULL;
1606 DeleteDragNDrop(data->wd_dnd);
1607 DoMethod(data->wd_DragObject, MUIM_DeleteDragImage,
1608 (IPTR) data->wd_DragImage);
1609 muiAreaData(data->wd_DragObject)->mad_Flags &= ~MADF_DRAGGING;
1610 data->wd_DragImage = NULL;
1611 data->wd_DragObject = NULL;
1612 data->wd_DropWindow = NULL;
1613 data->wd_dnd = NULL;
1615 /* stop listening to IDCMP_MOUSEMOVE */
1616 ChangeEvents(data, GetDefaultEvents());
1618 if (!finish_drag)
1619 ReplyMsg((struct Message *)imsg);
1621 return finish_drag;
1624 /* Reply to imsg if handled */
1625 BOOL HandleWindowEvent(Object *oWin, struct MUI_WindowData *data,
1626 struct IntuiMessage *imsg)
1628 struct Window *iWin;
1629 BOOL is_handled = TRUE;
1630 BOOL replied = FALSE;
1632 iWin = imsg->IDCMPWindow;
1633 switch (imsg->Class)
1635 case IDCMP_ACTIVEWINDOW:
1636 data->wd_Flags |= MUIWF_ACTIVE;
1637 if (data->wd_OldActive)
1638 set(oWin, MUIA_Window_ActiveObject, data->wd_OldActive);
1639 set(oWin, MUIA_Window_Activate, TRUE);
1640 is_handled = FALSE; /* forwardable to area event handlers */
1641 break;
1643 case IDCMP_INACTIVEWINDOW:
1644 KillHelpBubble(data, oWin, TRUE);
1645 if (data->wd_ActiveObject)
1647 data->wd_OldActive = data->wd_ActiveObject;
1648 set(oWin, MUIA_Window_ActiveObject,
1649 MUIV_Window_ActiveObject_None);
1651 data->wd_Flags &= ~MUIWF_ACTIVE;
1652 set(oWin, MUIA_Window_Activate, FALSE);
1653 is_handled = FALSE; /* forwardable to area event handlers */
1654 break;
1656 case IDCMP_NEWSIZE:
1657 case IDCMP_CHANGEWINDOW:
1659 int hborders = iWin->BorderLeft + iWin->BorderRight;
1660 int vborders = iWin->BorderTop + iWin->BorderBottom;
1662 /* set window limits according to window contents */
1663 WindowLimits
1664 (iWin,
1665 data->wd_MinMax.MinWidth + hborders,
1666 data->wd_MinMax.MinHeight + vborders,
1667 data->wd_MinMax.MaxWidth + hborders,
1668 data->wd_MinMax.MaxHeight + vborders);
1671 if ((iWin->GZZWidth != data->wd_Width)
1672 || (iWin->GZZHeight != data->wd_Height))
1674 data->wd_Width = iWin->GZZWidth;
1675 data->wd_Height = iWin->GZZHeight;
1676 DoHideMethod(data->wd_RootObject);
1678 data->wd_Flags |= MUIWF_RESIZING;
1679 RefreshWindow(oWin, data);
1681 /* Use wd_Class below instead of OCLASS(oWin), because otherwise if oWin is an
1682 instance of a subclass of window class, then superset will go to window class's
1683 OM_SET where MUIA_window_Width|Height for some reason are always set to 0. This has
1684 the side effect that after the first window resize all future window moves(!) too
1685 are interpreted as "window size was changed" (if check above returns TRUE even if
1686 window size did not change) */
1687 superset(data->wd_Class, oWin, MUIA_Window_Width, data->wd_Width);
1688 superset(data->wd_Class, oWin, MUIA_Window_Height, data->wd_Height);
1691 if (iWin->LeftEdge != data->wd_X)
1693 data->wd_X = iWin->LeftEdge;
1694 superset(data->wd_Class, oWin, MUIA_Window_LeftEdge, data->wd_X);
1696 if (iWin->TopEdge != data->wd_Y)
1698 data->wd_Y = iWin->TopEdge;
1699 superset(data->wd_Class, oWin, MUIA_Window_TopEdge, data->wd_Y);
1702 is_handled = FALSE; /* forwardable to area event handlers */
1703 break;
1705 case IDCMP_REFRESHWINDOW:
1706 ReplyMsg((struct Message *)imsg);
1707 replied = TRUE;
1708 RefreshWindow(oWin, data);
1709 break;
1711 case IDCMP_CLOSEWINDOW:
1712 ReplyMsg((struct Message *)imsg);
1713 replied = TRUE;
1714 set(oWin, MUIA_Window_CloseRequest, TRUE);
1715 break;
1717 case IDCMP_MENUPICK:
1718 ReplyMsg((struct Message *)imsg);
1719 replied = TRUE;
1721 if (data->wd_Menu)
1723 if (MENUNUM(imsg->Code) != NOMENU
1724 && ITEMNUM(imsg->Code) != NOITEM)
1726 struct MenuItem *item =
1727 ItemAddress(data->wd_Menu, imsg->Code);
1728 if (item)
1730 Object *item_obj = (Object *) GTMENUITEM_USERDATA(item);
1731 if (item_obj)
1733 Object *app = NULL;
1734 IPTR udata = 0;
1736 if (item->Flags & CHECKIT)
1737 set(item_obj, MUIA_Menuitem_Checked,
1738 ! !(item->Flags & CHECKED));
1740 set(item_obj, MUIA_Menuitem_Trigger, (IPTR) item);
1742 get(oWin, MUIA_ApplicationObject, &app);
1743 get(item_obj, MUIA_UserData, &udata);
1745 set(app, MUIA_Application_MenuAction, udata);
1746 set(oWin, MUIA_Window_MenuAction, udata);
1747 DoMethod(app, MUIM_Application_ReturnID, udata);
1752 break;
1754 case IDCMP_IDCMPUPDATE:
1755 is_handled = FALSE; /* forwardable to area event handlers */
1756 if (data->wd_VertProp || data->wd_HorizProp)
1758 struct TagItem *tag;
1759 tag = FindTagItem(GA_ID, (struct TagItem *)imsg->IAddress);
1760 if (tag)
1762 /* If there's a propclass object connected to the prop
1763 gadget, the prop gadget's userdata will point to
1764 that propclass object. See classes/prop.c */
1766 if (data->wd_VertProp)
1768 if (tag->ti_Data == GADGETID(data->wd_VertProp))
1771 if (tag->ti_Data == GADGETID(data->wd_UpButton))
1773 Object *prop =
1774 (Object *) ((struct Gadget *)data->
1775 wd_VertProp)->UserData;
1776 is_handled = TRUE;
1777 if (prop)
1778 DoMethod(prop, MUIM_Prop_Decrease, 1);
1781 if (tag->ti_Data == GADGETID(data->wd_DownButton))
1783 Object *prop =
1784 (Object *) ((struct Gadget *)data->
1785 wd_VertProp)->UserData;
1786 is_handled = TRUE;
1787 if (prop)
1788 DoMethod(prop, MUIM_Prop_Increase, 1);
1793 if (data->wd_HorizProp)
1795 if (tag->ti_Data == GADGETID(data->wd_HorizProp))
1798 if (tag->ti_Data == GADGETID(data->wd_LeftButton))
1800 Object *prop =
1801 (Object *) ((struct Gadget *)data->
1802 wd_HorizProp)->UserData;
1803 is_handled = TRUE;
1804 if (prop)
1805 DoMethod(prop, MUIM_Prop_Decrease, 1);
1808 if (tag->ti_Data == GADGETID(data->wd_RightButton))
1810 Object *prop =
1811 (Object *) ((struct Gadget *)data->
1812 wd_HorizProp)->UserData;
1813 is_handled = TRUE;
1814 if (prop)
1815 DoMethod(prop, MUIM_Prop_Increase, 1);
1821 break;
1823 case IDCMP_INTUITICKS:
1824 if (data->wd_HelpTicker)
1826 data->wd_HelpTicker--;
1828 if (data->wd_HelpTicker == 0)
1830 Object *underobj =
1831 ObjectUnderPointer(data, data->wd_RootObject,
1832 imsg->MouseX, imsg->MouseY,
1833 ShortHelpUnderPointerCheck);
1835 if (underobj != data->wd_HelpObject)
1837 if (data->wd_HelpObject)
1839 DoMethod(data->wd_HelpObject, MUIM_DeleteBubble,
1840 (IPTR) data->wd_HelpBubble);
1842 data->wd_HelpObject = NULL;
1843 data->wd_HelpBubble = NULL;
1846 if (underobj)
1848 data->wd_HelpBubble =
1849 (APTR) DoMethod(underobj, MUIM_CreateBubble,
1850 imsg->MouseX, imsg->MouseY, 0, 0);
1851 if (data->wd_HelpBubble)
1853 data->wd_HelpObject = underobj;
1854 data->wd_Flags |= MUIWF_BUBBLEMODE;
1859 if (data->wd_Flags & MUIWF_BUBBLEMODE)
1861 data->wd_HelpTicker = BUBBLEHELP_TICKER_LATER;
1863 else
1865 data->wd_HelpTicker = BUBBLEHELP_TICKER_FIRST;
1870 is_handled = FALSE; /* forwardable to area event handlers */
1871 break;
1873 case IDCMP_MOUSEBUTTONS:
1874 DoMethod(oWin, MUIM_Window_Snapshot, 0);
1875 KillHelpBubble(data, oWin, TRUE);
1876 is_handled = FALSE;
1877 break;
1880 case IDCMP_MOUSEMOVE:
1881 KillHelpBubble(data, oWin, FALSE);
1882 is_handled = FALSE;
1883 break;
1885 default:
1886 is_handled = FALSE;
1887 break;
1890 if (is_handled && !replied)
1891 ReplyMsg((struct Message *)imsg);
1893 return is_handled;
1896 static ULONG InvokeEventHandler(struct MUI_EventHandlerNode *ehn,
1897 struct IntuiMessage *event, ULONG muikey)
1899 ULONG res;
1901 if (!(_flags(ehn->ehn_Object) & MADF_CANDRAW))
1902 return 0;
1903 if (!(_flags(ehn->ehn_Object) & MADF_SHOWME))
1904 return 0;
1906 if (event != NULL
1907 && event->Class == IDCMP_MOUSEBUTTONS
1908 && event->Code == SELECTDOWN
1909 && (_flags(ehn->ehn_Object) & MADF_INVIRTUALGROUP))
1912 Here we filter out SELECTDOWN messages if objects is in a virtual
1913 group but the click went out of the virtual group
1915 Object *obj = ehn->ehn_Object;
1916 Object *parent = obj;
1917 Object *wnd = _win(obj);
1919 while (get(parent, MUIA_Parent, &parent))
1921 if (!parent)
1922 break;
1923 if (wnd == parent)
1924 break;
1925 if (_flags(parent) & MADF_ISVIRTUALGROUP)
1927 if (event->MouseX < _mleft(parent)
1928 || event->MouseX > _mright(parent)
1929 || event->MouseY < _mtop(parent)
1930 || event->MouseY > _mbottom(parent))
1932 return 0;
1939 if (ehn->ehn_Flags & MUI_EHF_HANDLEINPUT)
1941 DoMethod(ehn->ehn_Object, MUIM_HandleInput, (IPTR) event, muikey);
1942 res = 0;
1944 else
1946 if (ehn->ehn_Class)
1947 res = CoerceMethod
1948 (ehn->ehn_Class, ehn->ehn_Object, MUIM_HandleEvent,
1949 (IPTR) event, muikey);
1950 else
1951 res =
1952 DoMethod(ehn->ehn_Object, MUIM_HandleEvent, (IPTR) event,
1953 muikey);
1956 return res;
1959 static void HandleRawkey(Object *win, struct MUI_WindowData *data,
1960 struct IntuiMessage *event)
1962 struct MinNode *mn;
1963 struct MUI_EventHandlerNode *ehn;
1964 struct IntuiMessage imsg_copy;
1965 struct InputEvent ie = { 0 };
1966 ULONG res;
1967 LONG muikey = MUIKEY_NONE;
1968 Object *active_object = NULL;
1969 IPTR disabled = 0;
1970 ULONG key;
1971 ULONG deadkey;
1973 KillHelpBubble(data, win, BUBBLEHELP_TICKER_FIRST);
1975 ie.ie_NextEvent = NULL;
1976 ie.ie_Class = IECLASS_RAWKEY;
1977 ie.ie_SubClass = 0;
1978 ie.ie_Code = event->Code;
1979 ie.ie_Qualifier = event->Qualifier;
1980 ie.ie_EventAddress = (APTR) * (IPTR *) event->IAddress;
1981 #ifdef __AMIGAOS4__
1982 ie.ie_TimeStamp.Seconds = event->Seconds;
1983 ie.ie_TimeStamp.Microseconds = event->Micros;
1984 #else
1985 ie.ie_TimeStamp.tv_secs = event->Seconds;
1986 ie.ie_TimeStamp.tv_micro = event->Micros;
1987 #endif
1989 set(win, MUIA_Window_InputEvent, (IPTR) & ie);
1991 /* get the vanilla key for control char */
1993 UWORD msg_code;
1995 /* Remove the up prefix as convert key does not convert upkey event */
1996 msg_code = event->Code;
1997 event->Code &= ~IECODE_UP_PREFIX;
1998 key = ConvertKey(event);
1999 event->Code = msg_code;
2002 imsg_copy = *event;
2003 deadkey = *(ULONG *) event->IAddress;
2004 imsg_copy.IAddress = &deadkey;
2005 ReplyMsg((struct Message *)event);
2006 event = &imsg_copy;
2008 //bug("rawkey: code=%lx, qual=%lx\n", event->Code, event->Qualifier);
2010 /* check if imsg translates to predefined keystroke */
2012 struct InputEvent ievent;
2013 BOOL matched = FALSE;
2015 ievent.ie_NextEvent = NULL;
2016 ievent.ie_Class = IECLASS_RAWKEY;
2017 ievent.ie_SubClass = 0;
2018 ievent.ie_Code = event->Code;
2019 ievent.ie_Qualifier = event->Qualifier;
2020 /* ie_EventAddress is not used by MatchIX. If needed, it should be
2021 * ensured that it is still a valid address because of the shallow
2022 * IntuiMessage copy currently done in _zune_window_message before
2023 * message is replied.
2025 ievent.ie_EventAddress = NULL;
2026 //ievent.ie_EventAddress = (APTR *) *((ULONG *)(event->IAddress));
2028 for (muikey = MUIKEY_COUNT - 1; muikey >= MUIKEY_PRESS; muikey--)
2030 if (muiGlobalInfo(win)->mgi_Prefs->muikeys[muikey].ix_well != 0
2031 && MatchIX(&ievent,
2032 &muiGlobalInfo(win)->mgi_Prefs->muikeys[muikey].ix))
2034 matched = TRUE;
2035 break;
2039 if (matched)
2041 if (muikey == MUIKEY_PRESS && (event->Code & IECODE_UP_PREFIX))
2042 muikey = MUIKEY_RELEASE;
2044 else
2046 muikey = MUIKEY_NONE;
2048 } /* check if imsg translate to predefined keystroke */
2050 if ((muikey != MUIKEY_NONE) && !(data->wd_DisabledKeys & (1 << muikey)))
2052 D(bug("HandleRawkey: try MUIKEY %ld on window %0x08lx\n", muikey,
2053 win));
2054 switch (muikey)
2056 case MUIKEY_PRESS:
2057 break;
2058 case MUIKEY_TOGGLE:
2059 break;
2060 case MUIKEY_UP:
2061 break;
2062 case MUIKEY_DOWN:
2063 break;
2064 case MUIKEY_PAGEUP:
2065 break;
2066 case MUIKEY_PAGEDOWN:
2067 break;
2068 case MUIKEY_TOP:
2069 break;
2070 case MUIKEY_BOTTOM:
2071 break;
2072 case MUIKEY_LEFT:
2073 break;
2074 case MUIKEY_RIGHT:
2075 break;
2076 case MUIKEY_WORDLEFT:
2077 break;
2078 case MUIKEY_WORDRIGHT:
2079 break;
2080 case MUIKEY_LINESTART:
2081 break;
2082 case MUIKEY_LINEEND:
2083 break;
2084 case MUIKEY_GADGET_NEXT:
2085 set(win, MUIA_Window_ActiveObject,
2086 MUIV_Window_ActiveObject_Next);
2087 break;
2088 case MUIKEY_GADGET_PREV:
2089 set(win, MUIA_Window_ActiveObject,
2090 MUIV_Window_ActiveObject_Prev);
2091 break;
2092 case MUIKEY_GADGET_OFF:
2093 set(win, MUIA_Window_ActiveObject,
2094 MUIV_Window_ActiveObject_None);
2095 break;
2096 case MUIKEY_WINDOW_CLOSE:
2097 set(win, MUIA_Window_CloseRequest, TRUE);
2098 break;
2099 case MUIKEY_WINDOW_NEXT:
2100 break;
2101 case MUIKEY_WINDOW_PREV:
2102 break;
2103 case MUIKEY_HELP:
2104 break;
2105 case MUIKEY_POPUP:
2106 break;
2107 default:
2108 break;
2112 active_object = NULL;
2113 if ((data->wd_ActiveObject != NULL)
2114 && (DoMethod(data->wd_RootObject, MUIM_FindAreaObject,
2115 (IPTR) data->wd_ActiveObject) != (IPTR) NULL))
2117 active_object = data->wd_ActiveObject;
2118 get(active_object, MUIA_Disabled, &disabled);
2120 else
2121 data->wd_ActiveObject = NULL;
2123 /* try ActiveObject */
2124 if ((active_object != NULL) && !disabled)
2126 #if 0
2127 /* sba:
2128 ** Which method should be used for muikeys? MUIM_HandleInput or
2129 ** MUIM_HandleEvent. Also note that there is a flag MUI_EHF_ALWAYSKEYS
2130 ** which probably means that all keys events are requested??
2131 ** For now MUIM_HandleEvent is used as this is currently implemented
2132 ** in Area class ;) although I guess it should be MUIM_HandleInput as
2133 ** this was earlier
2136 if (muikey != MUIKEY_NONE)
2138 res =
2139 DoMethod(active_object, MUIM_HandleEvent, (IPTR) event,
2140 muikey);
2141 if (res & MUI_EventHandlerRC_Eat)
2142 return;
2144 #endif
2145 D(bug("HandleRawkey: try active object (%08lx) handlers\n",
2146 active_object));
2148 for (mn = data->wd_EHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
2150 ehn = (struct MUI_EventHandlerNode *)mn;
2152 if ((ehn->ehn_Object == active_object)
2153 && ((ehn->ehn_Events & IDCMP_RAWKEY)
2154 || (ehn->ehn_Flags & MUI_EHF_ALWAYSKEYS)))
2156 D(bug("HandleRawkey: (active) invoking on %p (ehn=%p) "
2157 "event=%p muikey=%p\n",
2158 ehn->ehn_Object, ehn, event, muikey));
2159 res = InvokeEventHandler(ehn, event, muikey);
2160 D(bug("HandleRawkey: (active) got res=%d\n", res));
2161 if (res & MUI_EventHandlerRC_Eat)
2162 return;
2164 /* Leave the loop if a different object has been activated */
2165 if (active_object != data->wd_ActiveObject)
2166 break;
2170 // event not eaten by active object, try its parents
2171 // this is to implement popup key in Popstring
2172 if (active_object == data->wd_ActiveObject)
2174 Object *current_obj = active_object;
2176 D(bug("HandleRawkey: try active object parents handlers\n"));
2177 while (current_obj != NULL)
2179 for (mn = data->wd_EHList.mlh_Head; mn->mln_Succ;
2180 mn = mn->mln_Succ)
2182 ehn = (struct MUI_EventHandlerNode *)mn;
2184 if ((ehn->ehn_Object == current_obj)
2185 && ((ehn->ehn_Events & IDCMP_RAWKEY)
2186 || (ehn->ehn_Flags & MUI_EHF_ALWAYSKEYS)))
2188 //D(bug("HandleRawkey: (active parents) invoking on "
2189 // "%p (ehn=%p) event=%p muikey=%p\n",
2190 // ehn->ehn_Object, ehn, event, muikey));
2191 res = InvokeEventHandler(ehn, event, muikey);
2192 //D(bug("HandleRawkey: (active parents) got res=%d\n",
2193 // res));
2194 if (res & MUI_EventHandlerRC_Eat)
2195 return;
2197 /* Leave the loop if a different object has been
2198 * activated */
2199 if (active_object != data->wd_ActiveObject)
2200 break;
2203 current_obj = (Object *) XGET(current_obj, MUIA_Parent);
2208 D(bug("HandleRawkey: try default object handlers\n"));
2210 /* try DefaultObject */
2211 if (data->wd_DefaultObject != NULL)
2212 get(data->wd_DefaultObject, MUIA_Disabled, &disabled);
2214 if ((data->wd_DefaultObject != NULL) && !disabled
2215 && (active_object != data->wd_DefaultObject))
2217 /* No, we only should do this if the object actually has requested
2218 * this via RequestIDCMP()! */
2219 // if (muikey != MUIKEY_NONE
2220 // && (_flags(data->wd_DefaultObject) & MADF_CANDRAW))
2221 // {
2222 // DoMethod(data->wd_DefaultObject, MUIM_HandleInput, event, muikey);
2223 // return;
2224 // }
2226 for (mn = data->wd_EHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
2228 ehn = (struct MUI_EventHandlerNode *)mn;
2230 if ((ehn->ehn_Object == data->wd_DefaultObject)
2231 && ((ehn->ehn_Events & IDCMP_RAWKEY)
2232 || (ehn->ehn_Flags & MUI_EHF_ALWAYSKEYS)))
2234 //D(bug("HandleRawkey: (default) invoking on %p (ehn=%p) "
2235 //"event=%p muikey=%p\n",
2236 //ehn->ehn_Object, ehn, event, muikey));
2237 res = InvokeEventHandler(ehn, event, muikey);
2238 //D(bug("HandleRawkey: (default) got res=%d\n", res));
2239 if (res & MUI_EventHandlerRC_Eat)
2240 return;
2246 D(bug("HandleRawkey: try other handlers\n"));
2248 // try other handlers
2249 for (mn = data->wd_EHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
2251 ehn = (struct MUI_EventHandlerNode *)mn;
2253 // skip Active and Default object as they have already been
2254 // handled
2255 if (ehn->ehn_Object == data->wd_ActiveObject
2256 || ehn->ehn_Object == data->wd_DefaultObject)
2257 continue;
2259 if (ehn->ehn_Events & IDCMP_RAWKEY)
2261 //D(bug("HandleRawkey: (others) invoking on %p (ehn=%p) "
2262 //"event=%p muikey=%p\n",
2263 //ehn->ehn_Object, ehn, event, muikey));
2264 res = InvokeEventHandler(ehn, event, MUIKEY_NONE);
2265 //D(bug("HandleRawkey: (others) got res=%d\n", res));
2266 if (res & MUI_EventHandlerRC_Eat)
2267 return;
2271 D(bug("HandleRawkey: try control chars handlers\n"));
2273 /* try Control Chars */
2274 //bug("ctrlchar, key='%c' code=0x%08lx\n", key, event->Code);
2275 if (key)
2277 for (mn = data->wd_CCList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
2279 ehn = (struct MUI_EventHandlerNode *)mn;
2281 if (ehn->ehn_Events == key)
2283 IPTR disabled = 0;
2284 LONG muikey2 = ehn->ehn_Flags;
2286 get(ehn->ehn_Object, MUIA_Disabled, &disabled);
2287 if (disabled)
2288 continue;
2290 //bug("control char\n");
2291 if (event->Code & IECODE_UP_PREFIX)
2293 /* simulate a release */
2294 if (muikey2 == MUIKEY_PRESS)
2295 muikey2 = MUIKEY_RELEASE;
2296 else
2297 return;
2300 if ((muikey2 != MUIKEY_NONE)
2301 && (_flags(ehn->ehn_Object) & MADF_CANDRAW)
2302 && (_flags(ehn->ehn_Object) & MADF_SHOWME))
2304 res = CoerceMethod
2305 (ehn->ehn_Class, ehn->ehn_Object, MUIM_HandleEvent,
2306 (IPTR) NULL, muikey2);
2307 if (res & MUI_EventHandlerRC_Eat)
2308 return;
2315 /* forward non-keystroke events to event handlers */
2316 static void HandleInputEvent(Object *win, struct MUI_WindowData *data,
2317 struct IntuiMessage *event)
2319 struct MinNode *mn;
2320 struct MUI_EventHandlerNode *ehn;
2321 struct IntuiMessage imsg_copy;
2322 ULONG res;
2323 ULONG mask = event->Class;
2325 if (mask != IDCMP_IDCMPUPDATE)
2327 imsg_copy = *event;
2328 imsg_copy.IAddress = NULL; /* be sure to trap access to that */
2329 ReplyMsg((struct Message *)event);
2330 event = &imsg_copy;
2333 if (mask == IDCMP_MOUSEMOVE)
2335 struct Window *iWin;
2336 iWin = event->IDCMPWindow;
2338 if (ContextMenuUnderPointer(data, data->wd_RootObject,
2339 event->MouseX, event->MouseY))
2341 iWin->Flags |= WFLG_RMBTRAP;
2343 else if (!data->wd_NoMenus)
2345 iWin->Flags &= ~WFLG_RMBTRAP;
2349 for (mn = data->wd_EHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
2351 ehn = (struct MUI_EventHandlerNode *)mn;
2353 if (ehn->ehn_Events & mask)
2355 IPTR disabled = 0;
2357 get(ehn->ehn_Object, MUIA_Disabled, &disabled);
2358 if (disabled)
2359 continue;
2361 res = InvokeEventHandler(ehn, event, MUIKEY_NONE);
2362 if (res & MUI_EventHandlerRC_Eat)
2363 return;
2368 if (mask == IDCMP_IDCMPUPDATE)
2369 ReplyMsg((struct Message *)event);
2373 /* process window message; this does a ReplyMsg() to the message */
2374 /* Called from application.c */
2375 void _zune_window_message(struct IntuiMessage *imsg)
2377 struct Window *iWin;
2378 Object *oWin;
2379 struct MUI_WindowData *data;
2380 BOOL handled;
2382 iWin = imsg->IDCMPWindow;
2383 oWin = (Object *) iWin->UserData;
2384 data = muiWindowData(oWin);
2386 if (data->wd_DragObject)
2388 if (!HandleDragging(oWin, data, imsg))
2389 return;
2392 handled = HandleWindowEvent(oWin, data, imsg);
2393 if (!handled)
2395 if (IDCMP_RAWKEY == imsg->Class)
2396 HandleRawkey(oWin, data, imsg);
2397 else if (IDCMP_GADGETUP == imsg->Class)
2399 #ifdef __AROS__
2400 if (ETI_MUI == ((struct Gadget *)imsg->IAddress)->GadgetID)
2402 DoMethod(_app(oWin), MUIM_Application_OpenConfigWindow);
2404 #endif
2405 if (ETI_Iconify == ((struct Gadget *)imsg->IAddress)->GadgetID)
2407 set(_app(oWin), MUIA_Application_Iconified, TRUE);
2410 else
2412 HandleInputEvent(oWin, data, imsg);
2417 /**************************************************************************/
2418 /**************************************************************************/
2420 /* code for setting MUIA_Window_RootObject */
2421 static void ChangeRootObject(struct MUI_WindowData *data, Object *obj,
2422 Object *newRoot)
2424 Object *oldRoot;
2426 ASSERT_VALID_PTR(data);
2427 ASSERT_VALID_PTR(obj);
2429 oldRoot = data->wd_RootObject;
2430 if (!(data->wd_Flags & MUIWF_OPENED))
2432 if (oldRoot)
2434 if (data->wd_ActiveObject == oldRoot)
2435 set(obj, MUIA_Window_ActiveObject,
2436 MUIV_Window_ActiveObject_None);
2437 DoMethod(oldRoot, MUIM_DisconnectParent);
2440 data->wd_RootObject = newRoot;
2441 if (newRoot)
2443 /* if window is in App tree, inform child */
2444 if (muiNotifyData(obj)->mnd_GlobalInfo)
2445 DoMethod(newRoot, MUIM_ConnectParent, (IPTR) obj);
2450 // find the ObjNode containing a pointer to the given object
2451 // currently only used for cycle chain objects
2452 static struct ObjNode *FindObjNode(struct MinList *list, Object *obj)
2454 struct ObjNode *node;
2456 ASSERT_VALID_PTR(list);
2458 if (!obj)
2459 return NULL;
2461 ASSERT_VALID_PTR(obj);
2463 for (node = (struct ObjNode *)list->mlh_Head;
2464 node->node.mln_Succ; node = (struct ObjNode *)node->node.mln_Succ)
2466 if (node->obj == obj)
2468 return node;
2471 return NULL;
2474 static Object *GetFirstActiveObject(struct MUI_WindowData *data)
2476 ASSERT_VALID_PTR(data);
2478 if (!IsListEmpty(&data->wd_CycleChain))
2479 return ((struct ObjNode *)data->wd_CycleChain.mlh_Head)->obj;
2480 else
2481 return NULL;
2484 static Object *GetLastActiveObject(struct MUI_WindowData *data)
2486 ASSERT_VALID_PTR(data);
2488 if (!IsListEmpty(&data->wd_CycleChain))
2489 return ((struct ObjNode *)data->wd_CycleChain.mlh_TailPred)->obj;
2490 else
2491 return NULL;
2494 typedef struct ObjNode *objnode_iterator_t(struct ObjNode *curr_node);
2496 static objnode_iterator_t NextObjNodeIterator;
2497 static objnode_iterator_t PrevObjNodeIterator;
2499 static struct ObjNode *NextObjNodeIterator(struct ObjNode *curr_node)
2501 if (curr_node->node.mln_Succ->mln_Succ)
2502 return (struct ObjNode *)curr_node->node.mln_Succ;
2503 else
2504 return NULL;
2507 static struct ObjNode *PrevObjNodeIterator(struct ObjNode *curr_node)
2509 if (curr_node->node.mln_Pred->mln_Pred)
2510 return (struct ObjNode *)curr_node->node.mln_Pred;
2511 else
2512 return NULL;
2515 static Object *GetPrevNextActiveObject(struct ObjNode *old_activenode,
2516 objnode_iterator_t node_iterator)
2518 struct ObjNode *curr_node;
2519 struct ObjNode *node;
2520 Object *obj;
2522 ASSERT_VALID_PTR(old_activenode);
2524 curr_node = old_activenode;
2525 node = NULL;
2526 obj = NULL;
2528 while (curr_node)
2530 node = node_iterator(curr_node);
2532 if (node)
2533 obj = node->obj;
2535 /* let's see if this object meets cycle requirements
2536 * (enabled & visible) */
2537 if (obj)
2539 IPTR is_disabled = 0;
2541 get(obj, MUIA_Disabled, &is_disabled);
2543 if (!is_disabled && (_flags(obj) & MADF_SHOWME))
2545 return obj;
2549 curr_node = node;
2550 obj = NULL;
2551 node = NULL;
2553 return obj;
2557 /**************************************************************************
2558 Code for setting MUIA_Window_ActiveObject
2559 Basically, it will:
2560 - remove focus drawing for current active object
2561 - find (if needed) the new active object
2562 - set data->wd_ActiveObject to the new object
2563 - draw focus around the new active object
2564 **************************************************************************/
2565 static void SetActiveObject(struct MUI_WindowData *data, Object *obj,
2566 IPTR newval)
2568 struct ObjNode *old_activenode = NULL;
2570 ASSERT_VALID_PTR(data);
2571 ASSERT_VALID_PTR(obj);
2573 D(bug("MUIC_Window:SetActiveObject(data, obj, %08lx) Active=%p\n",
2574 newval, data->wd_ActiveObject));
2576 if ((data->wd_ActiveObject != NULL)
2577 && (DoMethod(data->wd_RootObject, MUIM_FindAreaObject,
2578 (IPTR) data->wd_ActiveObject) != (IPTR) NULL))
2580 if ((IPTR) data->wd_ActiveObject != newval)
2582 old_activenode =
2583 FindObjNode(&data->wd_CycleChain, data->wd_ActiveObject);
2584 if ((data->wd_Flags & MUIWF_OBJECTGOACTIVESENT)
2585 && (_flags(data->wd_ActiveObject) & MADF_SETUP))
2587 D(bug("Deactivate=%p\n", data->wd_ActiveObject));
2588 DoMethod(data->wd_ActiveObject, MUIM_GoInactive);
2593 data->wd_ActiveObject = NULL;
2594 data->wd_Flags &= ~MUIWF_OBJECTGOACTIVESENT;
2596 switch (newval)
2598 case MUIV_Window_ActiveObject_None:
2599 break;
2601 case MUIV_Window_ActiveObject_Next:
2602 if (old_activenode != NULL)
2603 data->wd_ActiveObject = GetPrevNextActiveObject(old_activenode,
2604 NextObjNodeIterator);
2605 if (NULL == data->wd_ActiveObject)
2606 data->wd_ActiveObject = GetFirstActiveObject(data);
2607 break;
2609 case MUIV_Window_ActiveObject_Prev:
2610 if (old_activenode)
2611 data->wd_ActiveObject = GetPrevNextActiveObject(old_activenode,
2612 PrevObjNodeIterator);
2613 if (NULL == data->wd_ActiveObject)
2614 data->wd_ActiveObject = GetLastActiveObject(data);
2615 break;
2617 default:
2618 data->wd_ActiveObject = (Object *) newval;
2619 break;
2623 if (data->wd_ActiveObject != NULL
2624 && DoMethod(data->wd_RootObject, MUIM_FindAreaObject,
2625 (IPTR) data->wd_ActiveObject)
2626 && (_flags(data->wd_ActiveObject) & MADF_CANDRAW))
2628 D(bug("Activate=%p\n", data->wd_ActiveObject));
2629 DoMethod(data->wd_ActiveObject, MUIM_GoActive);
2630 data->wd_Flags |= MUIWF_OBJECTGOACTIVESENT;
2635 static BOOL InBox(struct IBox *box, WORD x, WORD y)
2637 return x >= box->Left && x < box->Left + box->Width
2638 && y >= box->Top && y < box->Top + box->Height;
2643 * Pass on an AppMessage to all objects that it landed on.
2645 static void ForwardAppMessage(struct MUI_WindowData *data, Object *child,
2646 struct AppMessage *appmsg)
2648 WORD x = appmsg->am_MouseX, y = appmsg->am_MouseY;
2649 Object *cstate;
2650 struct List *children = NULL;
2652 ASSERT_VALID_PTR(data);
2653 ASSERT_VALID_PTR(child);
2655 set(child, MUIA_AppMessage, appmsg);
2657 children = (struct List *)XGET(child, MUIA_Group_ChildList);
2659 if (children != NULL)
2661 cstate = (Object *) children->lh_Head;
2662 while ((child = NextObject(&cstate)))
2664 if (InBox(&muiAreaData(child)->mad_Box, x, y))
2666 ForwardAppMessage(data, child, appmsg);
2674 * calculate real dimensions from programmer requirements.
2675 * may be overridden by user settings if MUIA_Window_ID is set.
2677 /* MUIV_Window_Height_Screen and MUIV_Window_Height_Visible
2678 * are not handled yet, as their Width couterparts.
2680 static void WindowSelectDimensions(struct MUI_WindowData *data)
2682 if (!data->wd_Width)
2684 if (data->wd_ReqWidth > 0)
2685 data->wd_Width = data->wd_ReqWidth;
2686 else if (data->wd_ReqWidth == MUIV_Window_Width_Default)
2687 data->wd_Width = data->wd_MinMax.DefWidth;
2688 else if (_between(MUIV_Window_Width_MinMax(100),
2689 data->wd_ReqWidth, MUIV_Window_Width_MinMax(0)))
2691 data->wd_Width = data->wd_MinMax.MinWidth
2692 - data->wd_ReqWidth
2693 * (data->wd_MinMax.MaxWidth - data->wd_MinMax.MinWidth);
2695 else if (_between(MUIV_Window_Width_Screen(100),
2696 data->wd_ReqWidth, MUIV_Window_Width_Screen(0)))
2698 data->wd_Width = data->wd_RenderInfo.mri_ScreenWidth
2699 * (-(data->wd_ReqWidth + 200)) / 100;
2701 else if (_between(MUIV_Window_Width_Visible(100),
2702 data->wd_ReqWidth, MUIV_Window_Width_Visible(0)))
2704 data->wd_Width = data->wd_RenderInfo.mri_ScreenWidth
2705 * (-(data->wd_ReqWidth + 100)) / 100;
2708 if (data->wd_ReqHeight > 0)
2709 data->wd_Height = data->wd_ReqHeight;
2710 else if (data->wd_ReqHeight == MUIV_Window_Height_Default)
2711 data->wd_Height = data->wd_MinMax.DefHeight;
2712 else if (_between(MUIV_Window_Height_MinMax(100),
2713 data->wd_ReqHeight, MUIV_Window_Height_MinMax(0)))
2715 data->wd_Height = data->wd_MinMax.MinHeight
2716 - data->wd_ReqHeight
2717 * (data->wd_MinMax.MaxHeight - data->wd_MinMax.MinHeight);
2719 else if (_between(MUIV_Window_Height_Screen(100),
2720 data->wd_ReqHeight, MUIV_Window_Height_Screen(0)))
2722 struct Screen *scr;
2723 int height;
2725 scr = data->wd_RenderInfo.mri_Screen;
2727 height =
2728 scr->Height - data->wd_RenderInfo.mri_BorderTop -
2729 data->wd_RenderInfo.mri_BorderBottom;
2731 /* This is new to Zune: If TopEdge Delta is requested
2732 * the screenheight doesn't cover the barlayer */
2733 if (data->wd_Y <= MUIV_Window_TopEdge_Delta(0))
2734 height -= scr->BarHeight + 1;
2736 data->wd_Height = height * (-(data->wd_ReqHeight + 200)) / 100;
2738 else if (_between(MUIV_Window_Height_Visible(100),
2739 data->wd_ReqHeight, MUIV_Window_Height_Visible(0)))
2741 data->wd_Height = data->wd_RenderInfo.mri_ScreenHeight
2742 * (-(data->wd_ReqHeight + 100)) / 100;
2745 /* scaled */
2746 if (data->wd_ReqWidth == MUIV_Window_Width_Scaled)
2747 data->wd_Width = data->wd_Height * data->wd_MinMax.MinWidth
2748 / data->wd_MinMax.MinHeight;
2749 else if (data->wd_ReqHeight == MUIV_Window_Width_Scaled)
2750 data->wd_Height = data->wd_Width * data->wd_MinMax.MinHeight
2751 / data->wd_MinMax.MinWidth;
2753 data->wd_Width = CLAMP(data->wd_Width, data->wd_MinMax.MinWidth,
2754 data->wd_MinMax.MaxWidth);
2755 data->wd_Height = CLAMP(data->wd_Height, data->wd_MinMax.MinHeight,
2756 data->wd_MinMax.MaxHeight);
2760 /**************************************************************************
2761 OM_NEW
2762 **************************************************************************/
2763 IPTR Window__OM_NEW(struct IClass *cl, Object *obj, struct opSet *msg)
2765 struct MUI_WindowData *data;
2766 struct TagItem *tags;
2767 struct TagItem *tag;
2769 obj = (Object *) DoSuperMethodA(cl, obj, (Msg) msg);
2770 if (!obj)
2771 return FALSE;
2773 /* Initial local instance data */
2774 data = INST_DATA(cl, obj);
2776 data->wd_Class = cl;
2777 data->wd_MemoryPool = CreatePool(0, 4096, 2048);
2778 if (NULL == data->wd_MemoryPool)
2780 CoerceMethod(cl, obj, OM_DISPOSE);
2781 return (IPTR) NULL;
2784 data->wd_RenderInfo.mri_WindowObject = obj;
2786 NewList((struct List *)&(data->wd_EHList));
2787 NewList((struct List *)&(data->wd_CCList));
2788 NewList((struct List *)&(data->wd_CycleChain));
2789 NewList((struct List *)&(data->wd_IDList));
2791 data->wd_CrtFlags = WFLG_SIZEGADGET | WFLG_DRAGBAR | WFLG_DEPTHGADGET
2792 | WFLG_CLOSEGADGET | WFLG_SIMPLE_REFRESH
2793 | WFLG_REPORTMOUSE | WFLG_NEWLOOKMENUS;
2794 data->wd_ZoomGadget = TRUE;
2795 data->wd_Events = GetDefaultEvents();
2796 data->wd_ActiveObject = NULL;
2797 data->wd_ID = 0;
2798 data->wd_ReqHeight = MUIV_Window_Height_Default;
2799 data->wd_ReqWidth = MUIV_Window_Width_Default;
2800 data->wd_RootObject = NULL;
2801 data->wd_DefaultObject = NULL;
2803 /* alternate dimensions */
2804 /* no change in coordinates */
2805 data->wd_AltDim.Top = MUIV_Window_AltTopEdge_NoChange;
2806 data->wd_AltDim.Left = MUIV_Window_AltLeftEdge_NoChange;
2807 /* default to min size */
2808 data->wd_AltDim.Width = MUIV_Window_AltWidth_MinMax(0);
2809 data->wd_AltDim.Height = MUIV_Window_AltHeight_MinMax(0);
2810 data->wd_X = MUIV_Window_LeftEdge_Centered;
2811 data->wd_Y = MUIV_Window_TopEdge_Centered;
2812 data->wd_DisabledKeys = 0L;
2813 data->wd_HelpTicker = BUBBLEHELP_TICKER_FIRST;
2815 /* parse initial taglist */
2817 for (tags = msg->ops_AttrList; (tag = NextTagItem(&tags));)
2819 switch (tag->ti_Tag)
2821 case MUIA_Window_EraseArea:
2822 _handle_bool_tag(data->wd_Flags, tag->ti_Data, MUIWF_ERASEAREA);
2823 break;
2825 case MUIA_Window_ToolBox:
2826 _handle_bool_tag(data->wd_Flags, tag->ti_Data, MUIWF_TOOLBOX);
2827 break;
2829 case MUIA_Window_CloseGadget:
2830 _handle_bool_tag(data->wd_CrtFlags, tag->ti_Data,
2831 WFLG_CLOSEGADGET);
2832 break;
2834 case MUIA_Window_SizeGadget:
2835 _handle_bool_tag(data->wd_CrtFlags, tag->ti_Data,
2836 WFLG_SIZEGADGET);
2837 break;
2839 case MUIA_Window_ZoomGadget:
2840 data->wd_ZoomGadget = tag->ti_Data;
2841 break;
2843 case MUIA_Window_Backdrop:
2844 _handle_bool_tag(data->wd_CrtFlags, tag->ti_Data,
2845 WFLG_BACKDROP);
2846 break;
2848 case MUIA_Window_Borderless:
2849 _handle_bool_tag(data->wd_CrtFlags, tag->ti_Data,
2850 WFLG_BORDERLESS);
2851 break;
2853 case MUIA_Window_DepthGadget:
2854 _handle_bool_tag(data->wd_CrtFlags, tag->ti_Data,
2855 WFLG_DEPTHGADGET);
2856 break;
2858 case MUIA_Window_DragBar:
2859 _handle_bool_tag(data->wd_CrtFlags, tag->ti_Data, WFLG_DRAGBAR);
2860 break;
2862 case MUIA_Window_SizeRight:
2863 _handle_bool_tag(data->wd_CrtFlags, tag->ti_Data,
2864 WFLG_SIZEBRIGHT);
2865 break;
2867 case MUIA_Window_Height:
2868 data->wd_ReqHeight = (LONG) tag->ti_Data;
2869 break;
2871 case MUIA_Window_Width:
2872 data->wd_ReqWidth = (LONG) tag->ti_Data;
2873 break;
2875 case MUIA_Window_ID:
2876 set(obj, MUIA_Window_ID, tag->ti_Data);
2877 break;
2879 case MUIA_Window_IsSubWindow:
2880 _handle_bool_tag(data->wd_Flags, tag->ti_Data,
2881 MUIWF_ISSUBWINDOW);
2882 break;
2884 case MUIA_Window_Title:
2885 set(obj, MUIA_Window_Title, tag->ti_Data);
2886 break;
2888 case MUIA_Window_ScreenTitle:
2889 set(obj, MUIA_Window_ScreenTitle, tag->ti_Data);
2890 break;
2892 case MUIA_Window_Activate:
2893 _handle_bool_tag(data->wd_Flags, !tag->ti_Data,
2894 MUIWF_DONTACTIVATE);
2895 break;
2897 case MUIA_Window_DefaultObject:
2898 set(obj, MUIA_Window_DefaultObject, tag->ti_Data);
2899 break;
2901 case MUIA_Window_Menustrip:
2902 data->wd_ChildMenustrip = (Object *) tag->ti_Data;
2903 break;
2905 case MUIA_Window_NoMenus:
2906 data->wd_NoMenus = (BOOL) tag->ti_Data;
2907 break;
2909 case MUIA_Window_RootObject:
2910 if (!tag->ti_Data)
2912 CoerceMethod(cl, obj, OM_DISPOSE);
2913 return 0;
2915 set(obj, MUIA_Window_RootObject, tag->ti_Data);
2916 break;
2918 case MUIA_Window_AltHeight:
2919 data->wd_AltDim.Height = (WORD) tag->ti_Data;
2920 break;
2922 case MUIA_Window_AltWidth:
2923 data->wd_AltDim.Width = (WORD) tag->ti_Data;
2924 break;
2926 case MUIA_Window_AltLeftEdge:
2927 data->wd_AltDim.Left = (WORD) tag->ti_Data;
2928 break;
2930 case MUIA_Window_AltTopEdge:
2931 data->wd_AltDim.Top = (WORD) tag->ti_Data;
2932 break;
2934 case MUIA_Window_AppWindow:
2935 _handle_bool_tag(data->wd_Flags, tag->ti_Data,
2936 MUIWF_ISAPPWINDOW);
2937 break;
2939 case MUIA_Window_LeftEdge:
2940 data->wd_X = tag->ti_Data;
2941 break;
2943 case MUIA_Window_TopEdge:
2944 data->wd_Y = tag->ti_Data;
2945 break;
2947 case MUIA_Window_UseBottomBorderScroller:
2948 _handle_bool_tag(data->wd_Flags, tag->ti_Data,
2949 MUIWF_USEBOTTOMSCROLLER);
2950 break;
2952 case MUIA_Window_UseRightBorderScroller:
2953 _handle_bool_tag(data->wd_Flags, tag->ti_Data,
2954 MUIWF_USERIGHTSCROLLER);
2955 break;
2957 case MUIA_Window_DisableKeys:
2958 data->wd_DisabledKeys = tag->ti_Data;
2959 break;
2961 case MUIA_Window_RefWindow:
2962 data->wd_RefWindow = (Object *) tag->ti_Data;
2963 break;
2965 case MUIA_Window_Screen:
2966 data->wd_UserScreen = (struct Screen *)tag->ti_Data;
2967 break;
2969 case MUIA_Window_PublicScreen:
2970 data->wd_UserPublicScreen = (STRPTR) tag->ti_Data;
2971 break;
2975 /* D(bug("muimaster.library/window.c: Window Object created at " */
2976 /* "0x%lx back=%lx\n", */
2977 /* obj,data->wd_Background)); */
2979 return (IPTR) obj;
2982 /**************************************************************************
2983 OM_DISPOSE
2984 **************************************************************************/
2985 IPTR Window__OM_DISPOSE(struct IClass *cl, Object *obj, Msg msg)
2987 struct MUI_WindowData *data = INST_DATA(cl, obj);
2989 /* D(bug("Window_Dispose(%p)\n", obj)); */
2991 #if 0
2992 /* We no longer clear muiGlobalInfo() during disconnections, so
2993 this can cause problems (remove object which is already removed).
2994 Furthermore AFAIK it is not legal to dispose a window object
2995 which is still ocnnected to the application object, anyway. */
2997 if (muiGlobalInfo(obj) && _app(obj))
2999 /* D(bug(" Window_Dispose(%p) : calling app->OM_REMMEMBER\n", obj)); */
3000 DoMethod(_app(obj), OM_REMMEMBER, (IPTR) obj);
3002 #endif
3004 if (data->wd_RootObject)
3005 MUI_DisposeObject(data->wd_RootObject);
3007 if (data->wd_ChildMenustrip)
3008 MUI_DisposeObject(data->wd_ChildMenustrip);
3010 if (data->wd_Title)
3011 FreeVec(data->wd_Title);
3013 if (data->wd_ScreenTitle)
3014 FreeVec(data->wd_ScreenTitle);
3016 DeletePool(data->wd_MemoryPool);
3018 /* D(bug(" Window_Dispose(%p) : calling supermethod\n", obj)); */
3019 return DoSuperMethodA(cl, obj, msg);
3022 static ULONG WindowOpen(struct IClass *cl, Object *obj);
3023 static ULONG WindowClose(struct IClass *cl, Object *obj);
3025 /**************************************************************************
3026 OM_SET
3027 **************************************************************************/
3028 IPTR Window__OM_SET(struct IClass *cl, Object *obj, struct opSet *msg)
3030 struct MUI_WindowData *data = INST_DATA(cl, obj);
3031 struct TagItem *tags = msg->ops_AttrList;
3032 struct TagItem *tag;
3034 while ((tag = NextTagItem(&tags)) != NULL)
3036 switch (tag->ti_Tag)
3038 case MUIA_AppMessage:
3039 ForwardAppMessage(data, data->wd_RootObject,
3040 (struct AppMessage *)tag->ti_Data);
3041 break;
3043 case MUIA_Window_Activate:
3044 if (data->wd_RenderInfo.mri_Window)
3046 if (tag->ti_Data && !(data->wd_Flags & MUIWF_ACTIVE))
3048 ActivateWindow(data->wd_RenderInfo.mri_Window);
3049 _handle_bool_tag(data->wd_Flags, tag->ti_Data,
3050 MUIWF_ACTIVE);
3053 else
3054 _handle_bool_tag(data->wd_Flags, !tag->ti_Data,
3055 MUIWF_DONTACTIVATE);
3056 break;
3058 case MUIA_Window_ActiveObject:
3059 /* D(bug("MUIA_Window_ActiveObject %ld (%p)\n", */
3060 /* tag->ti_Data, tag->ti_Data)); */
3061 SetActiveObject(data, obj, tag->ti_Data);
3062 break;
3064 case MUIA_Window_DefaultObject:
3065 data->wd_DefaultObject = (APTR) tag->ti_Data;
3066 break;
3068 case MUIA_Window_ID:
3069 data->wd_ID = tag->ti_Data;
3070 break;
3072 case MUIA_Window_IsSubWindow:
3073 _handle_bool_tag(data->wd_Flags, tag->ti_Data,
3074 MUIWF_ISSUBWINDOW);
3075 break;
3077 case MUIA_Window_Open:
3078 if (tag->ti_Data)
3080 if (data->wd_Flags & MUIWF_HIDDEN)
3081 data->wd_Flags |= MUIWF_OPENONUNHIDE;
3082 else if (!(data->wd_Flags & MUIWF_OPENED))
3083 WindowOpen(cl, obj);
3084 else
3086 DoMethod(obj, MUIM_Window_ToFront);
3087 set(obj, MUIA_Window_Activate, TRUE);
3090 else if (data->wd_Flags & MUIWF_HIDDEN)
3091 data->wd_Flags &= ~MUIWF_OPENONUNHIDE;
3092 else if (data->wd_Flags & MUIWF_OPENED)
3093 WindowClose(cl, obj);
3094 break;
3096 case MUIA_ShowMe: /* PRIVATE *abuse* of the Area's ShowMe attr */
3097 if (tag->ti_Data)
3099 /* Deiconify */
3101 if (data->wd_Flags & MUIWF_HIDDEN)
3103 data->wd_Flags &= ~MUIWF_HIDDEN;
3105 if (data->wd_Flags & MUIWF_OPENONUNHIDE)
3107 data->wd_Flags &= ~MUIWF_OPENONUNHIDE;
3108 set(obj, MUIA_Window_Open, TRUE);
3112 else
3114 /* Iconify */
3116 if (data->wd_Flags & MUIWF_OPENED)
3118 data->wd_Flags |= MUIWF_OPENONUNHIDE;
3120 set(obj, MUIA_Window_Open, FALSE);
3123 data->wd_Flags |= MUIWF_HIDDEN;
3125 break;
3127 case MUIA_Window_RootObject:
3128 ChangeRootObject(data, obj, (Object *) tag->ti_Data);
3129 break;
3131 case MUIA_Window_Title:
3132 if (data->wd_Title)
3133 FreeVec(data->wd_Title);
3134 data->wd_Title = StrDup((STRPTR) tag->ti_Data);
3135 if (data->wd_RenderInfo.mri_Window)
3136 SetWindowTitles(data->wd_RenderInfo.mri_Window,
3137 data->wd_Title, (CONST_STRPTR) ~ 0);
3138 break;
3140 case MUIA_Window_ScreenTitle:
3141 if (data->wd_ScreenTitle)
3142 FreeVec(data->wd_ScreenTitle);
3143 data->wd_ScreenTitle = StrDup((STRPTR) tag->ti_Data);
3144 if (data->wd_RenderInfo.mri_Window)
3145 SetWindowTitles(data->wd_RenderInfo.mri_Window,
3146 (CONST_STRPTR) ~ 0, data->wd_ScreenTitle);
3147 break;
3149 case MUIA_Window_NoMenus:
3150 data->wd_NoMenus = (BOOL) tag->ti_Data;
3151 if (data->wd_RenderInfo.mri_Window)
3153 if (data->wd_NoMenus)
3154 data->wd_RenderInfo.mri_Window->Flags |= WFLG_RMBTRAP;
3155 else
3156 data->wd_RenderInfo.mri_Window->Flags &= ~WFLG_RMBTRAP;
3158 break;
3160 case MUIA_Window_UseBottomBorderScroller:
3161 _handle_bool_tag(data->wd_Flags, tag->ti_Data,
3162 MUIWF_USEBOTTOMSCROLLER);
3163 break;
3165 case MUIA_Window_UseRightBorderScroller:
3166 _handle_bool_tag(data->wd_Flags, tag->ti_Data,
3167 MUIWF_USERIGHTSCROLLER);
3168 break;
3170 case MUIA_Window_DisableKeys:
3171 data->wd_DisabledKeys = tag->ti_Data;
3172 break;
3174 case MUIA_Window_RefWindow:
3175 data->wd_RefWindow = (Object *) tag->ti_Data;
3176 break;
3178 case MUIA_Window_LeftEdge:
3179 data->wd_X = tag->ti_Data;
3180 break;
3182 case MUIA_Window_TopEdge:
3183 data->wd_Y = tag->ti_Data;
3184 break;
3186 case MUIA_Window_Width:
3187 data->wd_ReqWidth = (LONG) tag->ti_Data;
3188 data->wd_Width = 0; /* otherwise windowselectdimensions()
3189 * ignores ReqWidth */
3190 break;
3192 case MUIA_Window_Height:
3193 data->wd_ReqHeight = (LONG) tag->ti_Data;
3194 data->wd_Height = 0;
3195 break;
3197 case MUIA_Window_Screen:
3198 data->wd_UserScreen = (struct Screen *)tag->ti_Data;
3199 break;
3201 case MUIA_Window_PublicScreen:
3202 data->wd_UserPublicScreen = (STRPTR) tag->ti_Data;
3203 break;
3205 case MUIA_Window_Sleep:
3206 if (tag->ti_Data)
3208 data->wd_SleepCount++;
3209 if (data->wd_RenderInfo.mri_Window
3210 && (data->wd_SleepCount == 1))
3212 SetWindowPointer
3213 (data->wd_RenderInfo.mri_Window,
3214 WA_BusyPointer, TRUE,
3215 WA_PointerDelay, TRUE, TAG_DONE);
3216 // FIXME: how to disable event handling?
3219 else
3221 data->wd_SleepCount--;
3222 if (data->wd_RenderInfo.mri_Window
3223 && (data->wd_SleepCount == 0))
3225 SetWindowPointerA(data->wd_RenderInfo.mri_Window, NULL);
3228 break;
3233 return DoSuperMethodA(cl, obj, (Msg) msg);
3236 /**************************************************************************
3237 OM_GET
3238 **************************************************************************/
3239 IPTR Window__OM_GET(struct IClass *cl, Object *obj, struct opGet *msg)
3241 #define STORE *(msg->opg_Storage)
3243 struct MUI_WindowData *data = INST_DATA(cl, obj);
3245 STORE = (IPTR) 0;
3247 switch (msg->opg_AttrID)
3249 case MUIA_Window_Activate:
3250 STORE =
3251 (data->wd_Flags & (MUIWF_ACTIVE | MUIWF_OPENED)) ==
3252 (MUIWF_ACTIVE | MUIWF_OPENED);
3253 return TRUE;
3255 case MUIA_Window_Window:
3256 STORE = (IPTR) data->wd_RenderInfo.mri_Window;
3257 return TRUE;
3259 case MUIA_Window_Screen:
3260 STORE = (IPTR) data->wd_RenderInfo.mri_Screen;
3261 return TRUE;
3263 case MUIA_Window_PublicScreen:
3264 STORE = (IPTR) data->wd_UserPublicScreen;
3265 return TRUE;
3267 case MUIA_Window_ActiveObject:
3268 if ((data->wd_ActiveObject != NULL)
3269 && (DoMethod(data->wd_RootObject, MUIM_FindAreaObject,
3270 (IPTR) data->wd_ActiveObject) != (IPTR) NULL))
3271 STORE = (IPTR) data->wd_ActiveObject;
3272 else
3273 STORE = (IPTR) NULL;
3274 return TRUE;
3276 case MUIA_Window_CloseRequest:
3277 STORE = FALSE;
3278 return TRUE;
3280 case MUIA_Window_DefaultObject:
3281 STORE = (IPTR) data->wd_DefaultObject;
3282 return TRUE;
3284 case MUIA_Window_DisableKeys:
3285 STORE = data->wd_DisabledKeys;
3286 return TRUE;
3288 case MUIA_Window_Height:
3289 STORE = (IPTR) data->wd_Height;
3290 return TRUE;
3292 case MUIA_Window_ID:
3293 STORE = data->wd_ID;
3294 return TRUE;
3296 case MUIA_Window_IsSubWindow:
3297 STORE = (data->wd_Flags & MUIWF_ISSUBWINDOW) == MUIWF_ISSUBWINDOW;
3298 return TRUE;
3300 case MUIA_Window_LeftEdge:
3301 if (data->wd_RenderInfo.mri_Window)
3302 STORE = (IPTR) data->wd_RenderInfo.mri_Window->LeftEdge;
3303 else
3304 STORE = 0;
3305 return TRUE;
3307 case MUIA_Window_Open:
3308 STORE = (data->wd_Flags & MUIWF_OPENED) == MUIWF_OPENED;
3309 return TRUE;
3311 case MUIA_Window_RootObject:
3312 STORE = (IPTR) data->wd_RootObject;
3313 return TRUE;
3315 case MUIA_Window_ScreenTitle:
3316 STORE = (IPTR) data->wd_ScreenTitle;
3317 return TRUE;
3319 case MUIA_Window_Title:
3320 STORE = (IPTR) data->wd_Title;
3321 return TRUE;
3323 case MUIA_Window_TopEdge:
3324 if (data->wd_RenderInfo.mri_Window)
3325 STORE = (IPTR) data->wd_RenderInfo.mri_Window->TopEdge;
3326 else
3327 STORE = (IPTR) 0;
3328 return (TRUE);
3330 case MUIA_Window_Width:
3331 STORE = (IPTR) data->wd_Width;
3332 return TRUE;
3334 case MUIA_Window_Menustrip:
3335 STORE = (IPTR) data->wd_ChildMenustrip;
3336 return TRUE;
3338 case MUIA_Window_Sleep:
3339 STORE = data->wd_SleepCount ? TRUE : FALSE;
3340 return TRUE;
3342 case MUIA_Version:
3343 STORE = __version;
3344 return TRUE;
3346 case MUIA_Revision:
3347 STORE = __revision;
3348 return TRUE;
3351 return DoSuperMethodA(cl, obj, (Msg) msg);
3352 #undef STORE
3356 * MUIM_FindUData : tests if the MUIA_UserData of the object
3357 * contains the given <udata> and returns the object pointer in this case.
3359 IPTR Window__MUIM_FindUData(struct IClass *cl, Object *obj,
3360 struct MUIP_FindUData *msg)
3362 struct MUI_WindowData *data = INST_DATA(cl, obj);
3364 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
3365 return (IPTR) obj;
3367 if (data->wd_RootObject)
3368 return DoMethodA(data->wd_RootObject, (Msg) msg);
3370 return 0;
3375 * MUIM_GetUData : This method tests if the MUIA_UserData of the object
3376 * contains the given <udata> and gets <attr> to <storage> for itself
3377 * in this case.
3379 IPTR Window__MUIM_GetUData(struct IClass *cl, Object *obj,
3380 struct MUIP_GetUData *msg)
3382 struct MUI_WindowData *data = INST_DATA(cl, obj);
3384 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
3386 get(obj, msg->attr, msg->storage);
3387 return TRUE;
3390 if (data->wd_RootObject)
3391 return DoMethodA(data->wd_RootObject, (Msg) msg);
3393 return FALSE;
3398 * MUIM_SetUData : This method tests if the MUIA_UserData of the object
3399 * contains the given <udata> and sets <attr> to <val> for itself in this case.
3401 IPTR Window__MUIM_SetUData(struct IClass *cl, Object *obj,
3402 struct MUIP_SetUData *msg)
3404 struct MUI_WindowData *data = INST_DATA(cl, obj);
3406 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
3407 set(obj, msg->attr, msg->val);
3409 if (data->wd_RootObject)
3410 DoMethodA(data->wd_RootObject, (Msg) msg);
3412 return TRUE;
3417 * MUIM_SetUDataOnce : This method tests if the MUIA_UserData of the object
3418 * contains the given <udata> and sets <attr> to <val> for itself in this case.
3420 IPTR Window__MUIM_SetUDataOnce(struct IClass *cl, Object *obj,
3421 struct MUIP_SetUDataOnce *msg)
3423 struct MUI_WindowData *data = INST_DATA(cl, obj);
3425 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
3427 set(obj, msg->attr, msg->val);
3428 return TRUE;
3431 if (data->wd_RootObject)
3432 return DoMethodA(data->wd_RootObject, (Msg) msg);
3434 return FALSE;
3437 /**************************************************************************
3438 Called by Application (parent) object whenever this object is added.
3439 init GlobalInfo
3440 **************************************************************************/
3441 IPTR Window__MUIM_ConnectParent(struct IClass *cl, Object *obj,
3442 struct MUIP_ConnectParent *msg)
3444 struct MUI_WindowData *data = INST_DATA(cl, obj);
3446 if (!DoSuperMethodA(cl, obj, (Msg) msg))
3447 return 0;
3449 if (data->wd_RootObject)
3450 DoMethod(data->wd_RootObject, MUIM_ConnectParent, (IPTR) obj);
3452 if (data->wd_ChildMenustrip)
3453 DoMethod(data->wd_ChildMenustrip, MUIM_ConnectParent, (IPTR) obj);
3455 return TRUE;
3459 /**************************************************************************
3460 called by parent object
3461 **************************************************************************/
3462 IPTR Window__MUIM_DisconnectParent(struct IClass *cl, Object *obj,
3463 struct MUIP_DisconnectParent *msg)
3465 struct MUI_WindowData *data = INST_DATA(cl, obj);
3467 /* D(bug("Window_DisconnectParent(%p) : muiGlobalInfo=%p\n", */
3468 /* muiGlobalInfo(obj))); */
3469 if (muiGlobalInfo(obj))
3471 /* Close the window before disconnecting all the childs */
3472 if ((data->wd_Flags & MUIWF_OPENED))
3474 /* D(bug(" Window_DisconnectParent(%p) : closing window\n", */
3475 /* muiGlobalInfo(obj))); */
3476 set(obj, MUIA_Window_Open, FALSE);
3478 if (data->wd_ChildMenustrip)
3479 DoMethod(data->wd_ChildMenustrip, MUIM_DisconnectParent,
3480 (IPTR) obj);
3482 if (data->wd_RootObject)
3483 DoMethodA(data->wd_RootObject, (Msg) msg);
3485 /* D(bug(" Window_DisconnectParent(%p) : calling supermethod\n", */
3486 /* muiGlobalInfo(obj))); */
3487 return DoSuperMethodA(cl, obj, (Msg) msg);
3489 else
3491 return 0;
3495 static void SetRootObjInnerSpacing(Object *obj,
3496 struct MUI_WindowData *data)
3498 UWORD wd_innerLeft, wd_innerRight, wd_innerTop, wd_innerBottom;
3500 if (data->wd_CrtFlags & WFLG_BORDERLESS)
3502 wd_innerLeft = 0;
3503 wd_innerRight = 0;
3504 wd_innerTop = 0;
3505 wd_innerBottom = 0;
3507 else
3509 wd_innerLeft = muiGlobalInfo(obj)->mgi_Prefs->window_inner_left;
3510 wd_innerRight = muiGlobalInfo(obj)->mgi_Prefs->window_inner_right;
3511 wd_innerTop = muiGlobalInfo(obj)->mgi_Prefs->window_inner_top;
3512 wd_innerBottom = muiGlobalInfo(obj)->mgi_Prefs->window_inner_bottom;
3515 if (!(muiAreaData(data->wd_RootObject)->mad_Flags & MADF_INNERLEFT))
3517 muiAreaData(data->wd_RootObject)->mad_InnerLeft = wd_innerLeft;
3520 if (!(muiAreaData(data->wd_RootObject)->mad_Flags & MADF_INNERTOP))
3522 muiAreaData(data->wd_RootObject)->mad_InnerTop = wd_innerTop;
3525 if (!(muiAreaData(data->wd_RootObject)->mad_Flags & MADF_INNERRIGHT))
3527 muiAreaData(data->wd_RootObject)->mad_InnerRight = wd_innerRight;
3530 if (!(muiAreaData(data->wd_RootObject)->mad_Flags & MADF_INNERBOTTOM))
3532 muiAreaData(data->wd_RootObject)->mad_InnerBottom = wd_innerBottom;
3537 * Called before window is opened or resized. It determines its bounds,
3538 * so you can call WindowSelectDimensions() to find the final dims.
3540 static void WindowMinMax(Object *obj, struct MUI_WindowData *data)
3542 SetRootObjInnerSpacing(obj, data);
3543 /* inquire about sizes */
3544 DoMethod(data->wd_RootObject, MUIM_AskMinMax, (IPTR) & data->wd_MinMax);
3545 /* D(bug("*** root minmax = %ld,%ld => %ld,%ld\n", */
3546 /* data->wd_MinMax.MinWidth, */
3547 /* data->wd_MinMax.MinHeight, */
3548 /* data->wd_MinMax.MaxWidth, data->wd_MinMax.MaxHeight)); */
3549 __area_finish_minmax(data->wd_RootObject, &data->wd_MinMax);
3550 /* D(bug("*** root minmax2 = %ld,%ld => %ld,%ld\n", */
3551 /* data->wd_MinMax.MinWidth, */
3552 /* data->wd_MinMax.MinHeight, */
3553 /* data->wd_MinMax.MaxWidth, data->wd_MinMax.MaxHeight)); */
3557 static void InstallBackbuffer(struct IClass *cl, Object *obj)
3559 struct MUI_WindowData *data = INST_DATA(cl, obj);
3560 #if 0
3561 struct Window *win = data->wd_RenderInfo.mri_Window;
3563 data->wd_RenderInfo.mri_BufferBM =
3564 AllocBitMap(win->Width, win->Height, win->RPort->BitMap->Depth,
3565 0, win->RPort->BitMap);
3566 #endif
3567 if (data->wd_RenderInfo.mri_BufferBM)
3569 /* D(bug("install_backbuffer : allocated bitmap %dx%dx%d " */
3570 /* "with friend %p\n", */
3571 /* win->Width, win->Height, win->RPort->BitMap->Depth, */
3572 /* win->RPort->BitMap)); */
3573 InitRastPort(&data->wd_RenderInfo.mri_BufferRP);
3574 data->wd_RenderInfo.mri_BufferRP.BitMap =
3575 data->wd_RenderInfo.mri_BufferBM;
3579 static void DeinstallBackbuffer(struct IClass *cl, Object *obj)
3581 struct MUI_WindowData *data = INST_DATA(cl, obj);
3583 if (data->wd_RenderInfo.mri_BufferBM)
3585 DeinitRastPort(&data->wd_RenderInfo.mri_BufferRP);
3586 FreeBitMap(data->wd_RenderInfo.mri_BufferBM);
3587 data->wd_RenderInfo.mri_BufferBM = NULL;
3592 * Called after window is opened or resized.
3593 * An expose event is already queued, it will trigger
3594 * MUIM_Draw for us when going back to main loop.
3596 static void WindowShow(struct IClass *cl, Object *obj)
3598 struct MUI_WindowData *data = INST_DATA(cl, obj);
3599 struct Window *win = data->wd_RenderInfo.mri_Window;
3600 /* D(bug("WindowShow %s %d\n", __FILE__, __LINE__)); */
3602 _left(data->wd_RootObject) = win->BorderLeft;
3603 _top(data->wd_RootObject) = win->BorderTop;
3604 _width(data->wd_RootObject) = data->wd_Width;
3605 _height(data->wd_RootObject) = data->wd_Height;
3607 DoMethod(data->wd_RootObject, MUIM_Layout);
3609 ShowRenderInfo(&data->wd_RenderInfo);
3610 /* D(bug("zune_imspec_show %s %d\n", __FILE__, __LINE__)); */
3611 zune_imspec_show(data->wd_Background, obj);
3612 DoShowMethod(data->wd_RootObject);
3615 static ULONG WindowOpen(struct IClass *cl, Object *obj)
3617 struct MUI_WindowData *data = INST_DATA(cl, obj);
3619 if (!data->wd_RootObject)
3620 return FALSE;
3622 if (!DoMethod(obj, MUIM_Window_Setup))
3623 return FALSE;
3625 /* I got display info, so calculate your display dependant data */
3626 if (!DoSetupMethod(data->wd_RootObject, &data->wd_RenderInfo))
3628 DoMethod(obj, MUIM_Window_Cleanup);
3629 return FALSE;
3632 /* inquire about sizes */
3633 WindowMinMax(obj, data);
3634 WindowSelectDimensions(data);
3636 /* Decide which menustrip should be used */
3637 if (!data->wd_ChildMenustrip)
3638 get(_app(obj), MUIA_Application_Menustrip, &data->wd_Menustrip);
3639 else
3640 data->wd_Menustrip = data->wd_ChildMenustrip;
3642 /* open window here ... */
3643 if (!DisplayWindow(obj, data))
3645 /* free display dependant data */
3646 data->wd_Menustrip = NULL;
3647 DoMethod(data->wd_RootObject, MUIM_Cleanup);
3648 DoMethod(obj, MUIM_Window_Cleanup);
3649 return FALSE;
3652 InstallBackbuffer(cl, obj);
3654 data->wd_Flags |= MUIWF_OPENED;
3656 WindowShow(cl, obj);
3659 LONG left, top, width, height;
3661 left = data->wd_RenderInfo.mri_Window->BorderLeft;
3662 top = data->wd_RenderInfo.mri_Window->BorderTop,
3663 width = data->wd_RenderInfo.mri_Window->Width
3664 - data->wd_RenderInfo.mri_Window->BorderRight - left;
3665 height = data->wd_RenderInfo.mri_Window->Height
3666 - data->wd_RenderInfo.mri_Window->BorderBottom - top;
3668 /* D(bug("zune_imspec_draw %s %d\n", __FILE__, __LINE__)); */
3669 // D(bug("%d:zune_imspec_draw(%p) l=%d t=%d w=%d h=%d xo=%d yo=%d\n",
3670 // __LINE__, data->wd_Background, left, top, width,
3671 // height, left, top));
3673 zune_imspec_draw(data->wd_Background, &data->wd_RenderInfo,
3674 left, top, width, height, left, top, 0);
3677 MUI_Redraw(data->wd_RootObject, MADF_DRAWOBJECT);
3679 D(bug("MUIC_Window:windowOpen() ActiveObject=%p\n",
3680 data->wd_ActiveObject));
3681 if (data->wd_OldActive != NULL)
3683 set(obj, MUIA_Window_ActiveObject, data->wd_OldActive);
3686 return TRUE;
3689 /**************************************************************************/
3690 /**************************************************************************/
3692 static ULONG WindowClose(struct IClass *cl, Object *obj)
3694 struct MUI_WindowData *data = INST_DATA(cl, obj);
3696 if (data->wd_ActiveObject != NULL)
3698 data->wd_OldActive = data->wd_ActiveObject;
3699 set(obj, MUIA_Window_ActiveObject, MUIV_Window_ActiveObject_None);
3702 KillHelpBubble(data, obj, BUBBLEHELP_TICKER_FIRST);
3704 /* remove from window */
3705 DoHideMethod(data->wd_RootObject);
3706 zune_imspec_hide(data->wd_Background);
3708 DeinstallBackbuffer(cl, obj);
3710 HideRenderInfo(&data->wd_RenderInfo);
3712 /* close here ... */
3713 UndisplayWindow(obj, data);
3715 data->wd_Flags &= ~MUIWF_OPENED;
3716 data->wd_Menustrip = NULL;
3718 /* free display dependant data */
3719 DoMethod(data->wd_RootObject, MUIM_Cleanup);
3720 DoMethod(obj, MUIM_Window_Cleanup);
3721 return TRUE;
3724 /* calculate a new layout
3725 * see MUIA_ShowMe
3726 * see Group_ExitChange
3727 * see Group_Columns
3728 * see Group_Rows
3730 IPTR Window__MUIM_RecalcDisplay(struct IClass *cl, Object *obj,
3731 struct MUIP_Window_RecalcDisplay *msg)
3733 struct MUI_WindowData *data = INST_DATA(cl, obj);
3734 LONG left, top, width, height;
3735 BOOL resized, reshow = FALSE;
3736 Object *current_obj;
3738 if (!(data->wd_Flags & MUIWF_OPENED))
3739 return 0;
3741 current_obj = msg->originator;
3743 // typically originator is a group which has been added/removed a child
3744 // calculate minmax of current obj
3745 // if new minmax can accomodate current obj size, stop
3746 // else try with its parent
3747 // the resulting object will get a new layout
3748 // it currently produces some redundant AskMinMax but allows
3749 // to not always relayout the whole window
3751 D(bug("RecalcDisplay on %p\n", current_obj));
3752 while (current_obj != NULL)
3754 DoMethod(current_obj, MUIM_AskMinMax,
3755 (IPTR) & muiAreaData(current_obj)->mad_MinMax);
3756 __area_finish_minmax(current_obj,
3757 &muiAreaData(current_obj)->mad_MinMax);
3759 D(bug("size w = %d, h = %d\n", _width(current_obj),
3760 _height(current_obj)));
3761 D(bug("new w = %d-%d, h = %d-%d\n", _minwidth(current_obj),
3762 _maxwidth(current_obj), _minheight(current_obj),
3763 _maxheight(current_obj)));
3765 if (!_between(_minwidth(current_obj), _width(current_obj),
3766 _maxwidth(current_obj))
3767 || !_between(_minheight(current_obj), _height(current_obj),
3768 _maxheight(current_obj)))
3770 current_obj = _parent(current_obj);
3771 D(bug("RecalcDisplay, try parent %p\n", current_obj));
3773 else
3775 D(bug("found it\n"));
3776 break;
3780 if (!current_obj)
3781 current_obj = data->wd_RootObject;
3783 WindowMinMax(obj, data);
3785 /* Important: current_obj could be hidden, like in an inactive page! */
3786 if (_flags(current_obj) & MADF_CANDRAW)
3788 reshow = TRUE;
3791 if (reshow)
3792 DoHideMethod(current_obj);
3794 /* resize window ? */
3795 WindowSelectDimensions(data);
3796 resized = WindowResize(data);
3798 if (!resized)
3800 /* FIXME: Should we short circuit the following
3801 * if the window size didn't change?
3806 struct Window *win = data->wd_RenderInfo.mri_Window;
3807 _left(data->wd_RootObject) = win->BorderLeft;
3808 _top(data->wd_RootObject) = win->BorderTop;
3809 _width(data->wd_RootObject) = data->wd_Width;
3810 _height(data->wd_RootObject) = data->wd_Height;
3812 DoMethod(current_obj, MUIM_Layout);
3814 if (reshow)
3815 DoShowMethod(current_obj);
3817 if (muiGlobalInfo(obj)->mgi_Prefs->window_redraw ==
3818 WINDOW_REDRAW_WITHOUT_CLEAR)
3820 if (reshow)
3821 MUI_Redraw(current_obj, MADF_DRAWOBJECT);
3823 else
3825 left = data->wd_RenderInfo.mri_Window->BorderLeft;
3826 top = data->wd_RenderInfo.mri_Window->BorderTop;
3827 width = data->wd_RenderInfo.mri_Window->Width
3828 - data->wd_RenderInfo.mri_Window->BorderRight - left;
3829 height = data->wd_RenderInfo.mri_Window->Height
3830 - data->wd_RenderInfo.mri_Window->BorderBottom - top;
3832 zune_imspec_draw(data->wd_Background, &data->wd_RenderInfo,
3833 left, top, width, height, left, top, 0);
3834 MUI_Redraw(data->wd_RootObject, MADF_DRAWALL);
3837 ActivateObject(data);
3839 return TRUE;
3843 /**************************************************************************
3844 MUIM_AddEventHandler
3845 **************************************************************************/
3846 IPTR Window__MUIM_AddEventHandler(struct IClass *cl, Object *obj,
3847 struct MUIP_Window_AddEventHandler *msg)
3849 struct MUI_WindowData *data = INST_DATA(cl, obj);
3851 //D(bug("muimaster.library/window.c: Add Eventhandler %p\n", msg->ehnode));
3853 msg->ehnode->ehn_Priority = msg->ehnode->ehn_Priority;
3854 EnqueueByPriAndAddress((struct List *)&data->wd_EHList,
3855 (struct Node *)msg->ehnode);
3856 ChangeEvents(data, GetDefaultEvents());
3857 return TRUE;
3860 /**************************************************************************
3861 MUIM_RemEventHandler
3862 **************************************************************************/
3863 IPTR Window__MUIM_RemEventHandler(struct IClass *cl, Object *obj,
3864 struct MUIP_Window_RemEventHandler *msg)
3866 struct MUI_WindowData *data = INST_DATA(cl, obj);
3868 //D(bug("muimaster.library/window.c: Rem Eventhandler %p\n", msg->ehnode));
3870 Remove((struct Node *)msg->ehnode);
3871 ChangeEvents(data, GetDefaultEvents());
3872 return TRUE;
3875 /**************************************************************************
3876 Note that this is MUIM_Window_Setup, not MUIM_Setup
3877 **************************************************************************/
3878 IPTR Window__MUIM_Setup(struct IClass *cl, Object *obj, Msg msg)
3880 struct MUI_WindowData *data = INST_DATA(cl, obj);
3882 if (!SetupRenderInfo(obj, data, &data->wd_RenderInfo))
3883 return FALSE;
3885 data->wd_Background =
3886 zune_imspec_setup(MUII_WindowBack, &data->wd_RenderInfo);
3888 if (muiGlobalInfo(obj)->mgi_Prefs->window_redraw ==
3889 WINDOW_REDRAW_WITH_CLEAR)
3890 data->wd_Flags |= MUIWF_ERASEAREA;
3892 return TRUE;
3895 /**************************************************************************
3896 MUIM_Cleanup
3897 **************************************************************************/
3898 IPTR Window__MUIM_Cleanup(struct IClass *cl, Object *obj, Msg msg)
3900 struct MUI_WindowData *data = INST_DATA(cl, obj);
3902 zune_imspec_cleanup(data->wd_Background);
3904 if (data->wd_dnd)
3906 DeleteDragNDrop(data->wd_dnd);
3907 data->wd_dnd = NULL;
3910 CleanupRenderInfo(obj, data, &data->wd_RenderInfo);
3911 return TRUE;
3915 /**************************************************************************
3916 This adds the the control char handler and also do the MUIA_CycleChain
3917 stuff. Orginal MUI does this in an other way.
3918 **************************************************************************/
3919 IPTR Window__MUIM_AddControlCharHandler(struct IClass *cl, Object *obj,
3920 struct MUIP_Window_AddControlCharHandler *msg)
3922 struct MUI_WindowData *data = INST_DATA(cl, obj);
3923 struct ObjNode *node;
3925 if (msg->ccnode->ehn_Events)
3927 msg->ccnode->ehn_Priority = msg->ccnode->ehn_Priority;
3928 Enqueue((struct List *)&data->wd_CCList,
3929 (struct Node *)msg->ccnode);
3931 /* Due to the lack of a better idea ... */
3932 if (muiAreaData(msg->ccnode->ehn_Object)->mad_Flags & MADF_CYCLECHAIN)
3934 node = AllocPooled(data->wd_MemoryPool, sizeof(struct ObjNode));
3935 if (node)
3937 node->obj = msg->ccnode->ehn_Object;
3938 AddTail((struct List *)&data->wd_CycleChain,
3939 (struct Node *)node);
3942 return TRUE;
3945 /**************************************************************************
3946 MUIM_RemControlCharHandler
3947 **************************************************************************/
3948 IPTR Window__MUIM_RemControlCharHandler(struct IClass *cl, Object *obj,
3949 struct MUIP_Window_RemControlCharHandler *msg)
3951 struct MUI_WindowData *data = INST_DATA(cl, obj);
3952 struct ObjNode *node =
3953 FindObjNode(&data->wd_CycleChain, msg->ccnode->ehn_Object);
3955 if (msg->ccnode->ehn_Events)
3956 Remove((struct Node *)msg->ccnode);
3958 if (node)
3960 /* Remove from the chain list */
3961 Remove((struct Node *)node);
3962 FreePooled(data->wd_MemoryPool, node, sizeof(struct ObjNode));
3965 return TRUE;
3968 /**************************************************************************
3969 MUIM_DragObject
3970 **************************************************************************/
3971 IPTR Window__MUIM_DragObject(struct IClass *cl, Object *obj,
3972 struct MUIP_Window_DragObject *msg)
3974 struct MUI_WindowData *data = INST_DATA(cl, obj);
3975 if (msg->obj)
3977 struct DragNDrop *dnd;
3978 struct MUI_DragImage *di;
3979 struct BitMapNode *bmn;
3981 if (!(dnd = CreateDragNDropA(NULL)))
3982 return 0;
3984 if (!(di =
3985 (struct MUI_DragImage *)DoMethod(msg->obj,
3986 MUIM_CreateDragImage, -msg->touchx, -msg->touchy,
3987 msg->flags)))
3989 DeleteDragNDrop(dnd);
3990 return 0;
3992 if (!di->bm)
3994 DoMethod(msg->obj, MUIM_DeleteDragImage, (IPTR) di);
3995 DeleteDragNDrop(dnd);
3996 return 0;
3999 if (!(bmn = CreateBitMapNodeA(TAGLIST(
4000 GUI_BitMap, (IPTR)di->bm,
4001 GUI_LeftOffset, di->touchx,
4002 GUI_TopOffset, di->touchy,
4003 GUI_Width, di->width,
4004 GUI_Height, di->height,
4005 GUI_SourceAlpha, !!(di->flags & MUIF_DRAGIMAGE_SOURCEALPHA)))))
4007 DoMethod(msg->obj, MUIM_DeleteDragImage, (IPTR) di);
4008 DeleteDragNDrop(dnd);
4009 return 0;
4012 AttachBitMapNode(dnd, bmn);
4014 if (!PrepareDragNDrop(dnd, data->wd_RenderInfo.mri_Screen))
4016 DoMethod(msg->obj, MUIM_DeleteDragImage, (IPTR) di);
4017 DeleteDragNDrop(dnd);
4018 return 0;
4021 muiAreaData(msg->obj)->mad_Flags |= MADF_DRAGGING;
4023 data->wd_DragObject = msg->obj;
4024 data->wd_dnd = dnd;
4025 data->wd_DragImage = di;
4026 return 1;
4028 return 0;
4031 /**************************************************************************
4032 MUIM_AllocGadgetID
4033 **************************************************************************/
4034 IPTR Window__MUIM_AllocGadgetID(struct IClass *cl, Object *obj,
4035 struct MUIP_Window_AllocGadgetID *msg)
4037 struct MUI_WindowData *data = INST_DATA(cl, obj);
4038 struct IDNode *newnode;
4040 newnode = AllocPooled(data->wd_MemoryPool, sizeof(struct IDNode));
4041 if (newnode)
4043 int id;
4044 struct MinNode *mn;
4046 if (IsListEmpty(&data->wd_IDList))
4048 newnode->id = 1;
4049 AddHead((struct List *)&data->wd_IDList,
4050 (struct Node *)&newnode->node);
4051 return (IPTR) 1;
4054 id = 1;
4056 for (mn = data->wd_IDList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
4058 struct IDNode *idn = (struct IDNode *)mn;
4059 if (id < idn->id)
4060 break;
4061 id++;
4063 newnode->id = id;
4064 Insert((struct List *)&data->wd_IDList,
4065 (struct Node *)&newnode->node, (struct Node *)mn);
4066 return (IPTR) id;
4069 return 0;
4072 /**************************************************************************
4073 MUIM_FreeGadgetID
4074 **************************************************************************/
4075 IPTR Window__MUIM_FreeGadgetID(struct IClass *cl, Object *obj,
4076 struct MUIP_Window_FreeGadgetID *msg)
4078 struct MUI_WindowData *data = INST_DATA(cl, obj);
4079 struct MinNode *mn;
4081 for (mn = data->wd_IDList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
4083 struct IDNode *idn = (struct IDNode *)mn;
4084 if (msg->gadgetid == idn->id)
4086 Remove((struct Node *)idn);
4087 FreePooled(data->wd_MemoryPool, idn, sizeof(struct IDNode));
4088 return 0;
4092 return 0;
4096 /**************************************************************************
4097 MUIM_Window_GetMenuCheck
4098 **************************************************************************/
4099 IPTR Window__MUIM_GetMenuCheck(struct IClass *cl, Object *obj,
4100 struct MUIP_Window_GetMenuCheck *msg)
4102 IPTR stat = 0;
4103 struct MUI_WindowData *data = INST_DATA(cl, obj);
4104 Object *item;
4105 Object *strip = data->wd_ChildMenustrip;
4106 if (!strip)
4107 strip = data->wd_Menustrip;
4108 if (!strip)
4109 return 0;
4110 if (!(item = (Object *) DoMethod(strip, MUIM_FindUData, msg->MenuID)))
4111 return 0;
4112 get(item, MUIA_Menuitem_Checked, &stat);
4113 return stat;
4116 /**************************************************************************
4117 MUIM_Window_SetMenuCheck
4118 **************************************************************************/
4119 IPTR Window__MUIM_SetMenuCheck(struct IClass *cl, Object *obj,
4120 struct MUIP_Window_SetMenuCheck *msg)
4122 struct MUI_WindowData *data = INST_DATA(cl, obj);
4123 Object *item;
4124 Object *strip = data->wd_ChildMenustrip;
4125 if (!strip)
4126 strip = data->wd_Menustrip;
4127 if (!strip)
4128 return 0;
4129 if (!(item = (Object *) DoMethod(strip, MUIM_FindUData, msg->MenuID)))
4130 return 0;
4131 set(item, MUIA_Menuitem_Checked, msg->stat);
4132 return 0;
4135 /**************************************************************************
4136 MUIM_Window_GetMenuState
4137 **************************************************************************/
4138 IPTR Window__MUIM_GetMenuState(struct IClass *cl, Object *obj,
4139 struct MUIP_Window_GetMenuState *msg)
4141 IPTR stat = 0;
4142 struct MUI_WindowData *data = INST_DATA(cl, obj);
4143 Object *item;
4144 Object *strip = data->wd_ChildMenustrip;
4145 if (!strip)
4146 strip = data->wd_Menustrip;
4147 if (!strip)
4148 return 0;
4149 if (!(item = (Object *) DoMethod(strip, MUIM_FindUData, msg->MenuID)))
4150 return 0;
4151 get(item, MUIA_Menuitem_Enabled, &stat);
4152 return stat;
4155 /**************************************************************************
4156 MUIM_Window_SetMenuState
4157 **************************************************************************/
4158 IPTR Window__MUIM_SetMenuState(struct IClass *cl, Object *obj,
4159 struct MUIP_Window_SetMenuState *msg)
4161 struct MUI_WindowData *data = INST_DATA(cl, obj);
4162 Object *item;
4163 Object *strip = data->wd_ChildMenustrip;
4164 if (!strip)
4165 strip = data->wd_Menustrip;
4166 if (!strip)
4167 return 0;
4168 if (!(item = (Object *) DoMethod(strip, MUIM_FindUData, msg->MenuID)))
4169 return 0;
4170 set(item, MUIA_Menuitem_Enabled, msg->stat);
4171 return 0;
4174 /**************************************************************************
4175 MUIM_Window_DrawBackground
4176 **************************************************************************/
4177 IPTR Window__MUIM_DrawBackground(struct IClass *cl, Object *obj,
4178 struct MUIP_Window_DrawBackground *msg)
4180 struct MUI_WindowData *data = INST_DATA(cl, obj);
4181 if (!(data->wd_RenderInfo.mri_Window)) /* not between show/hide */
4182 return FALSE;
4184 // D(bug("%d:zune_imspec_draw(%p) l=%d t=%d w=%d h=%d xo=%d yo=%d\n",
4185 // __LINE__, data->wd_Background, msg->left, msg->top, msg->width,
4186 // msg->height, msg->xoffset, msg->yoffset));
4187 zune_imspec_draw(data->wd_Background, &data->wd_RenderInfo,
4188 msg->left, msg->top, msg->width, msg->height,
4189 msg->xoffset, msg->yoffset, 0);
4190 return 0;
4193 /**************************************************************************
4194 MUIM_Window_ToFront
4195 **************************************************************************/
4196 IPTR Window__MUIM_ToFront(struct IClass *cl, Object *obj, Msg msg)
4198 struct MUI_WindowData *data = INST_DATA(cl, obj);
4199 if (!(data->wd_RenderInfo.mri_Window)) /* not between show/hide */
4200 return 0;
4202 WindowToFront(data->wd_RenderInfo.mri_Window);
4203 return 1;
4206 /**************************************************************************
4207 MUIM_Window_ToBack
4208 **************************************************************************/
4209 IPTR Window__MUIM_ToBack(struct IClass *cl, Object *obj, Msg msg)
4211 struct MUI_WindowData *data = INST_DATA(cl, obj);
4212 if (!(data->wd_RenderInfo.mri_Window)) /* not between show/hide */
4213 return 0;
4215 WindowToBack(data->wd_RenderInfo.mri_Window);
4216 return 1;
4219 /**************************************************************************
4220 MUIM_Window_ScreenToBack
4221 **************************************************************************/
4222 IPTR Window__MUIM_ScreenToBack(struct IClass *cl, Object *obj, Msg msg)
4224 struct MUI_WindowData *data = INST_DATA(cl, obj);
4225 if (!(data->wd_RenderInfo.mri_Window)) /* not between show/hide */
4226 return 0;
4228 ScreenToBack(data->wd_RenderInfo.mri_Screen);
4229 return 1;
4232 /**************************************************************************
4233 MUIM_Window_ScreenToFront
4234 **************************************************************************/
4235 IPTR Window__MUIM_ScreenToFront(struct IClass *cl, Object *obj, Msg msg)
4237 struct MUI_WindowData *data = INST_DATA(cl, obj);
4238 if (!(data->wd_RenderInfo.mri_Window)) /* not between show/hide */
4239 return 0;
4241 ScreenToFront(data->wd_RenderInfo.mri_Screen);
4242 return 1;
4245 /**************************************************************************
4246 MUIM_Window_ActionIconify
4247 **************************************************************************/
4248 IPTR Window__MUIM_ActionIconify(struct IClass *cl, Object *obj, Msg msg)
4250 set(_app(obj), MUIA_Application_Iconified, TRUE);
4252 return TRUE;
4256 /* Loads ENV: prefs, add a Window_ID chunk in the MUIW chunk, if no MUIW chunk
4257 * then create it at the same level as MUIC chunk, save prefs.
4258 * Do the same for ENVARC:
4259 * MUIW chunk layout:
4260 * 'MUIW'
4261 * 00 00 00 30 (chunk length for a single window, 0x30L big endian)
4262 * 'this window ID'
4263 * 00 00 00 28
4264 * xx xx yy yy (X, Y)
4265 * ww ww hh hh (Width, Height)
4266 * ax ax ay ay (AltX, AltY)
4267 * aw aw ah ah (AltWidth, AltHeight)
4268 * 00 00 00 00 (???)
4269 * 00 00 00 00
4270 * 00 00 00 00
4271 * 00 00 00 00
4272 * 00 01 00 00
4273 * 00 00 00 00
4275 static void RememberWindowPosition(Object *winobj, ULONG id)
4277 if (!id)
4278 return;
4281 /* Loads ENV: prefs, remove our Window_ID chunk from the MUIW chunk,
4282 * save prefs.
4283 * Do the same for ENVARC:
4284 * This function shouldn't really be in window.c, but rather in a file dealing
4285 * with prefs file stuff.
4287 static void ForgetWindowPosition(Object *winobj, ULONG id)
4289 if (!id)
4290 return;
4293 /**************************************************************************
4294 MUIM_Window_Snapshot
4295 **************************************************************************/
4296 IPTR Window__MUIM_Snapshot(struct IClass *cl, Object *obj,
4297 struct MUIP_Window_Snapshot *msg)
4299 struct MUI_WindowData *data = INST_DATA(cl, obj);
4300 struct windowpos winp;
4301 struct Window *w;
4303 winp.id = data->wd_ID;
4304 w = data->wd_RenderInfo.mri_Window;
4305 if (w)
4307 winp.x1 = w->LeftEdge;
4308 winp.y1 = w->TopEdge;
4309 winp.w1 = w->GZZWidth;
4310 winp.h1 = w->GZZHeight;
4311 winp.x2 = 0;
4312 winp.x2 = 0;
4313 winp.w2 = 0;
4314 winp.h2 = 0; //to do save alt dims
4316 set(_app(obj), MUIA_Application_SetWinPos, &winp);
4319 if (msg->flags)
4320 RememberWindowPosition(obj, data->wd_ID);
4321 else
4322 ForgetWindowPosition(obj, data->wd_ID);
4323 return 1;
4326 /**************************************************************************
4327 MUIM_Window_UpdateMenu
4328 **************************************************************************/
4329 IPTR Window__MUIM_UpdateMenu(struct IClass *cl, Object *obj, Msg msg)
4331 struct MUI_WindowData *data = INST_DATA(cl, obj);
4333 struct Menu *menu = NULL;
4334 struct NewMenu *newmenu = NULL;
4335 APTR visinfo = NULL;
4336 struct Window *win = NULL;
4338 if (data->wd_Menustrip) // only open windows can have a menustrip
4340 if ((visinfo =
4341 GetVisualInfoA(data->wd_RenderInfo.mri_Screen, NULL)))
4343 win = data->wd_RenderInfo.mri_Window;
4344 ClearMenuStrip(win);
4345 if (data->wd_Menu)
4347 FreeMenus(data->wd_Menu);
4348 data->wd_Menu = NULL;
4351 get(data->wd_Menustrip, MUIA_Menuitem_NewMenu, &newmenu);
4352 if (newmenu)
4354 if ((menu = CreateMenusA(newmenu, NULL)))
4356 struct TagItem tags[] = {
4357 {GTMN_NewLookMenus, TRUE},
4358 {TAG_DONE, 0}
4360 LayoutMenusA(menu, visinfo, tags);
4361 data->wd_Menu = menu;
4362 SetMenuStrip(win, menu);
4365 FreeVisualInfo(visinfo);
4369 return 1;
4372 /**************************************************************************
4373 MUIM_Window_Refresh
4374 **************************************************************************/
4375 IPTR Window__MUIM_Refresh(struct IClass *cl, Object *obj, Msg msg)
4377 struct MUI_WindowData *data = INST_DATA(cl, obj);
4379 RefreshWindow(obj, data);
4381 return 1;
4384 /**************************************************************************
4385 MUIM_Export : to export an object's "contents" to a dataspace object.
4386 **************************************************************************/
4387 static IPTR Window__MUIM_Export(struct IClass *cl, Object *obj,
4388 struct MUIP_Export *msg)
4390 struct MUI_WindowData *data = INST_DATA(cl, obj);
4391 DoMethodA(data->wd_RootObject, (Msg) msg);
4392 return 0;
4396 /**************************************************************************
4397 MUIM_Import : to import an object's "contents" from a dataspace object.
4398 **************************************************************************/
4399 static IPTR Window__MUIM_Import(struct IClass *cl, Object *obj,
4400 struct MUIP_Import *msg)
4402 struct MUI_WindowData *data = INST_DATA(cl, obj);
4403 DoMethodA(data->wd_RootObject, (Msg) msg);
4404 return 0;
4407 BOOPSI_DISPATCHER(IPTR, Window_Dispatcher, cl, obj, msg)
4409 switch (msg->MethodID)
4411 case OM_NEW:
4412 return Window__OM_NEW(cl, obj, (struct opSet *)msg);
4413 case OM_DISPOSE:
4414 return Window__OM_DISPOSE(cl, obj, msg);
4415 case OM_SET:
4416 return Window__OM_SET(cl, obj, (struct opSet *)msg);
4417 case OM_GET:
4418 return Window__OM_GET(cl, obj, (struct opGet *)msg);
4419 case MUIM_FindUData:
4420 return Window__MUIM_FindUData(cl, obj,
4421 (struct MUIP_FindUData *)msg);
4422 case MUIM_GetUData:
4423 return Window__MUIM_GetUData(cl, obj, (struct MUIP_GetUData *)msg);
4424 case MUIM_SetUData:
4425 return Window__MUIM_SetUData(cl, obj, (struct MUIP_SetUData *)msg);
4426 case MUIM_SetUDataOnce:
4427 return Window__MUIM_SetUDataOnce(cl, obj,
4428 (struct MUIP_SetUDataOnce *)msg);
4429 case MUIM_Window_AddEventHandler:
4430 return Window__MUIM_AddEventHandler(cl, obj, (APTR) msg);
4431 case MUIM_Window_RemEventHandler:
4432 return Window__MUIM_RemEventHandler(cl, obj, (APTR) msg);
4433 case MUIM_ConnectParent:
4434 return Window__MUIM_ConnectParent(cl, obj, (APTR) msg);
4435 case MUIM_DisconnectParent:
4436 return Window__MUIM_DisconnectParent(cl, obj, (APTR) msg);
4437 case MUIM_Window_RecalcDisplay:
4438 return Window__MUIM_RecalcDisplay(cl, obj, (APTR) msg);
4439 case MUIM_Window_Setup:
4440 return Window__MUIM_Setup(cl, obj, (APTR) msg);
4441 case MUIM_Window_Cleanup:
4442 return Window__MUIM_Cleanup(cl, obj, (APTR) msg);
4443 case MUIM_Window_AddControlCharHandler:
4444 return Window__MUIM_AddControlCharHandler(cl, obj, (APTR) msg);
4445 case MUIM_Window_RemControlCharHandler:
4446 return Window__MUIM_RemControlCharHandler(cl, obj, (APTR) msg);
4447 case MUIM_Window_DragObject:
4448 return Window__MUIM_DragObject(cl, obj, (APTR) msg);
4449 case MUIM_Window_AllocGadgetID:
4450 return Window__MUIM_AllocGadgetID(cl, obj, (APTR) msg);
4451 case MUIM_Window_FreeGadgetID:
4452 return Window__MUIM_FreeGadgetID(cl, obj, (APTR) msg);
4453 case MUIM_Window_GetMenuCheck:
4454 return Window__MUIM_GetMenuCheck(cl, obj, (APTR) msg);
4455 case MUIM_Window_SetMenuCheck:
4456 return Window__MUIM_SetMenuCheck(cl, obj, (APTR) msg);
4457 case MUIM_Window_GetMenuState:
4458 return Window__MUIM_GetMenuState(cl, obj, (APTR) msg);
4459 case MUIM_Window_SetMenuState:
4460 return Window__MUIM_SetMenuState(cl, obj, (APTR) msg);
4461 case MUIM_Window_DrawBackground:
4462 return Window__MUIM_DrawBackground(cl, obj, (APTR) msg);
4463 case MUIM_Window_ToFront:
4464 return Window__MUIM_ToFront(cl, obj, (APTR) msg);
4465 case MUIM_Window_ToBack:
4466 return Window__MUIM_ToBack(cl, obj, (APTR) msg);
4467 case MUIM_Window_ScreenToFront:
4468 return Window__MUIM_ScreenToFront(cl, obj, (APTR) msg);
4469 case MUIM_Window_ScreenToBack:
4470 return Window__MUIM_ScreenToBack(cl, obj, (APTR) msg);
4471 case MUIM_Window_ActionIconify:
4472 return Window__MUIM_ActionIconify(cl, obj, (APTR) msg);
4473 case MUIM_Window_Snapshot:
4474 return Window__MUIM_Snapshot(cl, obj, (APTR) msg);
4475 case MUIM_Window_UpdateMenu:
4476 return Window__MUIM_UpdateMenu(cl, obj, (APTR) msg);
4477 case MUIM_Window_Refresh:
4478 return Window__MUIM_Refresh(cl, obj, (APTR) msg);
4479 case MUIM_Export:
4480 return Window__MUIM_Export(cl, obj, (APTR) msg);
4481 case MUIM_Import:
4482 return Window__MUIM_Import(cl, obj, (APTR) msg);
4485 return DoSuperMethodA(cl, obj, msg);
4487 BOOPSI_DISPATCHER_END
4490 * Class descriptor.
4492 const struct __MUIBuiltinClass _MUI_Window_desc =
4494 MUIC_Window,
4495 MUIC_Notify,
4496 sizeof(struct MUI_WindowData),
4497 (void *) Window_Dispatcher