- Redraw the window upon IDCMP_CHANGEWINDOW events too. That's all we get
[AROS.git] / workbench / libs / muimaster / classes / window.c
blob4d9c839691dce4f1fb356128ca5d0f50f4eddc33
1 /*
2 Copyright 1999, David Le Corfec.
3 Copyright 2002-2014, 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 apps or windows or NULL) */
114 Object *wd_ChildMenustrip; /* If window has an 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 */
143 #ifndef WFLG_SIZEGADGET
145 #define WFLG_CLOSEGADGET (1<<0) /* has close gadget */
146 #define WFLG_SIZEGADGET (1<<1) /* has size gadget */
147 #define WFLG_BACKDROP (1<<2) /* is backdrop window */
148 #define WFLG_BORDERLESS (1<<3) /* has no borders */
149 #define WFLG_DEPTHGADGET (1<<4) /* has depth gadget */
150 #define WFLG_DRAGBAR (1<<5) /* is draggable */
151 #define WFLG_SIZEBRIGHT (1<<6) /* size gadget is in right border */
153 #endif
155 /* wd_Flags */
156 #define MUIWF_OPENED (1<<0) /* window currently opened */
157 #define MUIWF_HIDDEN (1<<1) /* window currently iconified */
158 #define MUIWF_ACTIVE (1<<2) /* window currently active */
159 #define MUIWF_RESIZING (1<<4) /* window currently resizing */
160 #define MUIWF_DONTACTIVATE (1<<7) /* do not activate the window when
161 * opening */
162 #define MUIWF_USERIGHTSCROLLER (1<<8) /* should have right scroller */
163 #define MUIWF_USEBOTTOMSCROLLER (1<<9) /* should have bottom scroller */
164 #define MUIWF_ERASEAREA (1<<10) /* Erase area after a window resize */
165 #define MUIWF_ISAPPWINDOW (1<<11) /* Is an AppWindow */
166 #define MUIWF_ISSUBWINDOW (1<<12) /* Don't get automatically disposed
167 * with app */
168 #define MUIWF_BUBBLEMODE (1<<13) /* Quick bubble mode. Bubbles appear
169 * quick when moving */
170 #define MUIWF_OPENONUNHIDE (1<<14) /* Open the window when unhiding */
171 #define MUIWF_SCREENLOCKED (1<<15) /* A pub screen was locked in
172 * SetupRenderInfo. Unlock it in
173 * CleanupRenderInfo! */
174 #define MUIWF_OBJECTGOACTIVESENT (1<<16) /* A MUIM_GoActive msg was sent to
175 * window's active object */
176 #define MUIWF_TOOLBOX (1<<17) /* Window should be opened as
177 * ToolBox */
179 #define BUBBLEHELP_TICKER_FIRST 10
180 #define BUBBLEHELP_TICKER_LATER 3
182 struct __dummyXFC3__
184 struct MUI_NotifyData mnd;
185 struct MUI_WindowData mwd;
188 #define muiWindowData(obj) (&(((struct __dummyXFC3__ *)(obj))->mwd))
190 static void ActivateObject(struct MUI_WindowData *data);
191 static void HandleInputEvent(Object *win, struct MUI_WindowData *data,
192 struct IntuiMessage *event);
194 static ULONG DoHalfshineGun(ULONG a, ULONG b)
196 ULONG val = ((((a) >> 24) + 3 * ((b) >> 24)) / 4);
197 val = val + (val << 8) + (val << 16) + (val << 24);
198 return val;
201 static ULONG DoHalfshadowGun(ULONG a, ULONG b)
203 ULONG val = ((((a) >> 24) + 5 * ((b) >> 24)) / 6);
204 val = val + (val << 8) + (val << 16) + (val << 24);
205 return val;
208 static Object *CreateSysimage(struct DrawInfo *dri, ULONG which)
210 return NewObject(NULL, "sysiclass",
211 SYSIA_DrawInfo, (IPTR) dri, SYSIA_Which, which, TAG_DONE);
214 static void EnqueueByPriAndAddress(struct List *list, struct Node *node)
216 struct Node *scannode;
218 /* Sort by priority and by node address, so that a
219 "remove - modify - enqueue" sequence will re-add
220 the node at the same place in the list it was
221 initially */
222 ForeachNode(list, scannode)
224 if (((struct Node *)node)->ln_Pri > scannode->ln_Pri)
225 break;
226 if (((struct Node *)node)->ln_Pri == scannode->ln_Pri)
228 if ((IPTR) node > (IPTR) scannode)
229 break;
233 Insert(list, (struct Node *)node, scannode->ln_Pred);
236 static BOOL InitCustomFrames(Object *obj, struct MUI_RenderInfo *mri)
238 int i;
240 for (i = 0; i < 16; i++)
242 mri->mri_FrameImage[i] = NULL;
245 mri->mri_FrameImage[0] =
246 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
247 customframe_config_1, mri->mri_Screen);
248 mri->mri_FrameImage[1] =
249 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
250 customframe_config_2, mri->mri_Screen);
251 mri->mri_FrameImage[2] =
252 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
253 customframe_config_3, mri->mri_Screen);
254 mri->mri_FrameImage[3] =
255 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
256 customframe_config_4, mri->mri_Screen);
257 mri->mri_FrameImage[4] =
258 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
259 customframe_config_5, mri->mri_Screen);
260 mri->mri_FrameImage[5] =
261 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
262 customframe_config_6, mri->mri_Screen);
263 mri->mri_FrameImage[6] =
264 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
265 customframe_config_7, mri->mri_Screen);
266 mri->mri_FrameImage[7] =
267 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
268 customframe_config_8, mri->mri_Screen);
269 mri->mri_FrameImage[8] =
270 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
271 customframe_config_9, mri->mri_Screen);
272 mri->mri_FrameImage[9] =
273 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
274 customframe_config_10, mri->mri_Screen);
275 mri->mri_FrameImage[10] =
276 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
277 customframe_config_11, mri->mri_Screen);
278 mri->mri_FrameImage[11] =
279 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
280 customframe_config_12, mri->mri_Screen);
281 mri->mri_FrameImage[12] =
282 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
283 customframe_config_13, mri->mri_Screen);
284 mri->mri_FrameImage[13] =
285 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
286 customframe_config_14, mri->mri_Screen);
287 mri->mri_FrameImage[14] =
288 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
289 customframe_config_15, mri->mri_Screen);
290 mri->mri_FrameImage[15] =
291 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
292 customframe_config_16, mri->mri_Screen);
294 return TRUE;
297 static void DisposeCustomFrames(struct MUI_RenderInfo *mri)
299 int i;
301 for (i = 0; i < 16; i++)
303 dispose_custom_frame(mri->mri_FrameImage[i]);
305 mri->mri_FrameImage[i] = NULL;
309 static BOOL SetupRenderInfo(Object *obj, struct MUI_WindowData *data,
310 struct MUI_RenderInfo *mri)
312 ULONG rgbtable[3 * 3];
313 Object *temp_obj;
314 IPTR val;
315 int i;
317 /* TODO: Move this whole screen locking/opening stuff into the
318 * application class by creating methods for this purpose */
320 /* If no user screen has been specified try to open the application
321 * specific screen */
322 if (!data->wd_UserScreen)
324 ULONG screenmodeid = muiGlobalInfo(obj)->mgi_Prefs->screenmodeid;
326 if (screenmodeid != ~0)
328 if (!muiGlobalInfo(obj)->mgi_CustomScreen)
330 muiGlobalInfo(obj)->mgi_CustomScreen = OpenScreenTags
331 (NULL,
332 SA_DisplayID, screenmodeid,
333 SA_SharePens, TRUE,
334 SA_FullPalette, TRUE, SA_LikeWorkbench, TRUE, TAG_DONE);
335 /* It's fine if this fails as there is a fallback case below */
338 data->wd_UserScreen = muiGlobalInfo(obj)->mgi_CustomScreen;
341 if (data->wd_UserScreen)
343 mri->mri_Screen = data->wd_UserScreen;
345 else
347 if (data->wd_UserPublicScreen)
349 mri->mri_Screen = LockPubScreen(data->wd_UserPublicScreen);
351 else if (muiGlobalInfo(obj)->mgi_Prefs->publicscreen_name
352 && muiGlobalInfo(obj)->mgi_Prefs->publicscreen_name[0])
354 mri->mri_Screen =
355 LockPubScreen(muiGlobalInfo(obj)->mgi_Prefs->
356 publicscreen_name);
357 // FIXME: open the public screen if necessary
360 if (mri->mri_Screen == NULL)
362 mri->mri_Screen = LockPubScreen(NULL);
363 if (mri->mri_Screen == NULL)
365 return FALSE;
369 // FIXME: is this the right place for this action?
370 if (mri->mri_Screen
371 && muiGlobalInfo(obj)->mgi_Prefs->publicscreen_pop_to_front)
373 ScreenToFront(mri->mri_Screen);
376 data->wd_Flags |= MUIWF_SCREENLOCKED;
379 if (!(mri->mri_DrawInfo = GetScreenDrawInfo(mri->mri_Screen)))
381 if (data->wd_Flags & MUIWF_SCREENLOCKED)
383 UnlockPubScreen(NULL, mri->mri_Screen);
384 data->wd_Flags &= ~MUIWF_SCREENLOCKED;
386 return FALSE;
389 if (!InitCustomFrames(obj, mri))
391 if (data->wd_Flags & MUIWF_SCREENLOCKED)
393 UnlockPubScreen(NULL, mri->mri_Screen);
394 data->wd_Flags &= ~MUIWF_SCREENLOCKED;
396 return FALSE;
399 mri->mri_Colormap = mri->mri_Screen->ViewPort.ColorMap;
400 mri->mri_ScreenWidth = mri->mri_Screen->Width;
401 mri->mri_ScreenHeight = mri->mri_Screen->Height;
403 if (mri->mri_ScreenWidth / mri->mri_ScreenHeight < 2)
405 mri->mri_Flags |= MUIMRI_THINFRAMES;
408 if (GetBitMapAttr(mri->mri_Screen->RastPort.BitMap, BMA_DEPTH) >= 15)
410 mri->mri_Flags |= MUIMRI_TRUECOLOR;
413 mri->mri_PensStorage[MPEN_SHINE] =
414 mri->mri_DrawInfo->dri_Pens[SHINEPEN];
415 mri->mri_PensStorage[MPEN_BACKGROUND] =
416 mri->mri_DrawInfo->dri_Pens[BACKGROUNDPEN];
417 mri->mri_PensStorage[MPEN_SHADOW] =
418 mri->mri_DrawInfo->dri_Pens[SHADOWPEN];
419 mri->mri_PensStorage[MPEN_TEXT] = mri->mri_DrawInfo->dri_Pens[TEXTPEN];
420 mri->mri_PensStorage[MPEN_FILL] = mri->mri_DrawInfo->dri_Pens[FILLPEN];
422 GetRGB32(mri->mri_Colormap, mri->mri_DrawInfo->dri_Pens[SHINEPEN], 1,
423 rgbtable);
424 GetRGB32(mri->mri_Colormap, mri->mri_DrawInfo->dri_Pens[BACKGROUNDPEN],
425 1, rgbtable + 3);
426 GetRGB32(mri->mri_Colormap, mri->mri_DrawInfo->dri_Pens[SHADOWPEN], 1,
427 rgbtable + 6);
429 mri->mri_PensStorage[MPEN_HALFSHINE] = ObtainBestPenA
430 (mri->mri_Colormap,
431 DoHalfshineGun(rgbtable[0], rgbtable[3]),
432 DoHalfshineGun(rgbtable[1], rgbtable[4]),
433 DoHalfshineGun(rgbtable[2], rgbtable[5]), NULL);
435 mri->mri_PensStorage[MPEN_HALFSHADOW] = ObtainBestPenA
436 (mri->mri_Colormap,
437 DoHalfshadowGun(rgbtable[6], rgbtable[3]),
438 DoHalfshadowGun(rgbtable[7], rgbtable[4]),
439 DoHalfshadowGun(rgbtable[8], rgbtable[5]), NULL);
441 /* I'm really not sure that MUI does this for MPEN_MARK, but it seems
442 * mostly acceptable -dlc */
443 mri->mri_PensStorage[MPEN_MARK] = ObtainBestPenA
444 (mri->mri_Colormap, 0xf4f4f4f4, 0xb5b5b5b5, 0x8b8b8b8b, NULL);
446 mri->mri_Pens = mri->mri_PensStorage;
448 for (i = 0; i < -MUIV_Font_NegCount; i++)
450 mri->mri_Fonts[i] = NULL;
453 if (data->wd_Flags & MUIWF_USEBOTTOMSCROLLER)
455 mri->mri_LeftImage = CreateSysimage(mri->mri_DrawInfo, LEFTIMAGE);
456 mri->mri_RightImage = CreateSysimage(mri->mri_DrawInfo, RIGHTIMAGE);
458 else
460 mri->mri_LeftImage = mri->mri_RightImage = NULL;
463 if (data->wd_Flags & MUIWF_USERIGHTSCROLLER)
465 mri->mri_UpImage = CreateSysimage(mri->mri_DrawInfo, UPIMAGE);
466 mri->mri_DownImage = CreateSysimage(mri->mri_DrawInfo, DOWNIMAGE);
468 else
470 mri->mri_UpImage = mri->mri_DownImage = NULL;
473 if ((data->wd_Flags & MUIWF_USEBOTTOMSCROLLER) ||
474 (data->wd_Flags & MUIWF_USERIGHTSCROLLER))
475 mri->mri_SizeImage = CreateSysimage(mri->mri_DrawInfo, SIZEIMAGE);
476 else
477 mri->mri_SizeImage = NULL;
479 if (data->wd_CrtFlags & WFLG_BORDERLESS)
481 /* In fact borderless windows could also have borders (if they have
482 * a window title e.g. but since they look ugly anyway we ignore it
483 * for now */
484 mri->mri_BorderLeft = 0;
485 mri->mri_BorderRight = 0;
486 mri->mri_BorderTop = 0;
487 mri->mri_BorderBottom = 0;
489 else
491 mri->mri_BorderLeft = mri->mri_Screen->WBorLeft;
492 mri->mri_BorderTop =
493 mri->mri_Screen->WBorTop + mri->mri_Screen->Font->ta_YSize + 1;
494 temp_obj =
495 NewObject(NULL, "sysiclass", SYSIA_DrawInfo,
496 (IPTR) mri->mri_DrawInfo, SYSIA_Which, SIZEIMAGE, TAG_DONE);
497 if (temp_obj)
499 GetAttr(IA_Height, temp_obj, &val);
500 DisposeObject(temp_obj);
501 mri->mri_BorderBottom = val;
503 else
504 mri->mri_BorderBottom = mri->mri_Screen->WBorBottom;
507 return TRUE;
510 static void CleanupRenderInfo(Object *obj, struct MUI_WindowData *data,
511 struct MUI_RenderInfo *mri)
513 int i;
515 DisposeCustomFrames(mri);
517 if (mri->mri_LeftImage)
519 DisposeObject(mri->mri_LeftImage);
520 mri->mri_LeftImage = NULL;
522 if (mri->mri_RightImage)
524 DisposeObject(mri->mri_RightImage);
525 mri->mri_RightImage = NULL;
527 if (mri->mri_UpImage)
529 DisposeObject(mri->mri_UpImage);
530 mri->mri_UpImage = NULL;
532 if (mri->mri_DownImage)
534 DisposeObject(mri->mri_DownImage);
535 mri->mri_DownImage = NULL;
537 if (mri->mri_SizeImage)
539 DisposeObject(mri->mri_SizeImage);
540 mri->mri_SizeImage = NULL;
543 /* bug("CleanupRenderInfo\n"); */
544 for (i = 0; i < -MUIV_Font_NegCount; i++)
546 if (mri->mri_Fonts[i])
548 /* bug("CleanupRenderInfo: closing font %p (%s/%d)\n", */
549 /* mri->mri_Fonts[i], */
550 /* mri->mri_Fonts[i]->tf_Message.mn_Node.ln_Name, */
551 /* mri->mri_Fonts[i]->tf_YSize); */
552 CloseFont(mri->mri_Fonts[i]);
553 mri->mri_Fonts[i] = NULL;
556 ReleasePen(mri->mri_Colormap, mri->mri_PensStorage[MPEN_MARK]);
557 ReleasePen(mri->mri_Colormap, mri->mri_PensStorage[MPEN_HALFSHADOW]);
558 ReleasePen(mri->mri_Colormap, mri->mri_PensStorage[MPEN_HALFSHINE]);
559 FreeScreenDrawInfo(mri->mri_Screen, mri->mri_DrawInfo);
560 mri->mri_DrawInfo = NULL;
562 /* If a custom screen has been opened by zune, close it as soon as zero
563 * windows are opened. See above for comments about refactorization. */
564 if (muiGlobalInfo(obj)->mgi_CustomScreen)
566 BOOL screenclose = TRUE;
567 Object *_app = _app(obj);
568 if (_app != NULL)
570 struct List *store = NULL;
571 get(_app, MUIA_Application_WindowList, &store);
572 if (store != NULL)
574 if (!IsListEmpty(store))
575 screenclose = FALSE;
578 if (screenclose)
580 /* If the window's user screen really was the custom screen,
581 * clear the reference */
582 if (data->wd_UserScreen == muiGlobalInfo(obj)->mgi_CustomScreen)
583 data->wd_UserScreen = NULL;
585 CloseScreen(muiGlobalInfo(obj)->mgi_CustomScreen);
586 muiGlobalInfo(obj)->mgi_CustomScreen = NULL;
590 if (data->wd_Flags & MUIWF_SCREENLOCKED)
592 UnlockPubScreen(NULL, mri->mri_Screen);
593 data->wd_Flags &= ~MUIWF_SCREENLOCKED;
595 mri->mri_Screen = NULL;
598 static void ShowRenderInfo(struct MUI_RenderInfo *mri)
600 if (mri->mri_BufferBM)
602 mri->mri_RastPort = &mri->mri_BufferRP;
604 else
606 mri->mri_RastPort = mri->mri_Window->RPort;
610 static void HideRenderInfo(struct MUI_RenderInfo *mri)
612 mri->mri_RastPort = NULL;
615 static ULONG GetDefaultEvents(void)
617 return IDCMP_NEWSIZE | IDCMP_CHANGEWINDOW | IDCMP_REFRESHWINDOW
618 | IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE | IDCMP_MENUPICK
619 | IDCMP_CLOSEWINDOW | IDCMP_RAWKEY | IDCMP_INTUITICKS
620 | IDCMP_ACTIVEWINDOW | IDCMP_INACTIVEWINDOW | IDCMP_GADGETUP;
623 static void ChangeEvents(struct MUI_WindowData *data, ULONG new_events)
625 struct MinNode *mn;
626 struct MUI_EventHandlerNode *ehn;
627 ULONG old_events = data->wd_Events;
629 for (mn = data->wd_EHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
631 ehn = (struct MUI_EventHandlerNode *)mn;
632 new_events |= ehn->ehn_Events;
635 /* sba: kill the IDCMP_VANILLAKEY flag. MUI doesn't do this but programs
636 ** which use this will behave different if they request for this flag
637 ** (also on MUI)
639 new_events &= ~IDCMP_VANILLAKEY;
641 data->wd_Events = new_events;
642 if ((old_events != new_events) && (data->wd_Flags & MUIWF_OPENED))
644 ModifyIDCMP(data->wd_RenderInfo.mri_Window, new_events);
648 static void CalcWindowPosition(Object *obj, struct MUI_WindowData *data);
649 static void CreateWindowScrollbars(Object *obj,
650 struct MUI_WindowData *data);
651 static void CalcAltDimensions(Object *obj, struct MUI_WindowData *data);
652 static void UndisplayWindow(Object *obj, struct MUI_WindowData *data);
653 static struct ObjNode *FindObjNode(struct MinList *list, Object *obj);
655 static BOOL DisplayWindow(Object *obj, struct MUI_WindowData *data)
657 struct Window *win;
658 ULONG flags = data->wd_CrtFlags;
659 struct IBox altdims;
660 ULONG backfill, buttons;
662 struct Menu *menu = NULL;
663 struct NewMenu *newmenu = NULL;
664 APTR visinfo = NULL;
666 Object *gadgets;
668 if (!(data->wd_Flags & MUIWF_DONTACTIVATE))
670 flags |= WFLG_ACTIVATE;
673 /* Toolboxes are handled differently on AmigaOS */
674 #ifdef __AROS__
675 if (data->wd_Flags & MUIWF_TOOLBOX)
676 flags |= WFLG_TOOLBOX;
677 #endif
679 if (data->wd_MinMax.MinHeight == data->wd_MinMax.MaxHeight
680 && data->wd_MinMax.MinWidth == data->wd_MinMax.MaxWidth)
681 flags &= ~WFLG_SIZEGADGET;
683 if (!(flags & WFLG_SIZEBRIGHT))
684 flags |= WFLG_SIZEBBOTTOM;
686 CalcWindowPosition(obj, data);
688 if ((visinfo = GetVisualInfoA(data->wd_RenderInfo.mri_Screen, NULL)))
690 if (data->wd_Menustrip)
692 get(data->wd_Menustrip, MUIA_Menuitem_NewMenu, &newmenu);
693 if (newmenu)
695 if ((menu = CreateMenusA(newmenu, NULL)))
697 struct TagItem tags[] = {
698 {GTMN_NewLookMenus, TRUE},
699 {TAG_DONE, (IPTR) NULL}
701 LayoutMenusA(menu, visinfo, tags);
705 FreeVisualInfo(visinfo);
708 CreateWindowScrollbars(obj, data);
709 CalcAltDimensions(obj, data);
710 altdims = data->wd_AltDim;
712 /* hack to account for border size, as we only know the innersize and
713 * must give the total size.
715 altdims.Width +=
716 data->wd_RenderInfo.mri_Screen->WBorLeft +
717 data->wd_RenderInfo.mri_Screen->WBorRight;
718 altdims.Height +=
719 data->wd_RenderInfo.mri_Screen->WBorTop +
720 data->wd_RenderInfo.mri_Screen->WBorBottom +
721 data->wd_RenderInfo.mri_DrawInfo->dri_Font->tf_YSize + 1;
723 if (muiGlobalInfo(obj)->mgi_Prefs->window_redraw ==
724 WINDOW_REDRAW_WITHOUT_CLEAR)
725 backfill = WA_BackFill;
726 else
727 backfill = TAG_IGNORE;
729 if (muiGlobalInfo(obj)->mgi_Prefs->window_refresh ==
730 WINDOW_REFRESH_SMART)
731 flags &= ~WFLG_SIMPLE_REFRESH;
732 set(_app(obj), MUIA_Application_SearchWinId, data->wd_ID);
733 struct windowpos *winp = 0;
734 get(_app(obj), MUIA_Application_GetWinPos, &winp);
735 if (winp)
737 if (data->wd_RenderInfo.mri_ScreenWidth >
738 (data->wd_X + data->wd_Width))
740 data->wd_X = winp->x1;
741 data->wd_Width = winp->w1;
743 if (data->wd_RenderInfo.mri_ScreenHeight >
744 (data->wd_Y + data->wd_Height))
746 data->wd_Y = winp->y1;
747 data->wd_Height = winp->h1;
751 gadgets =
752 (data->wd_VertProp !=
753 NULL) ? data->wd_VertProp : data->wd_HorizProp;
754 buttons = muiGlobalInfo(obj)->mgi_Prefs->window_buttons;
756 win = OpenWindowTags
757 (NULL,
758 WA_Left, (IPTR) data->wd_X,
759 WA_Top, (IPTR) data->wd_Y,
760 WA_Flags, (IPTR) flags,
761 data->wd_Title ?
762 WA_Title :
763 TAG_IGNORE, (IPTR) data->wd_Title,
764 data->wd_ScreenTitle ?
765 WA_ScreenTitle :
766 TAG_IGNORE, (IPTR) data->wd_ScreenTitle,
767 WA_CustomScreen, (IPTR) data->wd_RenderInfo.mri_Screen,
768 WA_InnerWidth, (IPTR) data->wd_Width,
769 WA_InnerHeight, (IPTR) data->wd_Height,
770 WA_AutoAdjust, (IPTR) TRUE, WA_NewLookMenus, (IPTR) TRUE,
771 /* AmigaOS v4 extension */
772 #ifdef WA_ToolBox
773 WA_ToolBox, (IPTR) ! !(data->wd_Flags & MUIWF_TOOLBOX),
774 #endif
775 /* MorphOS extensions */
776 #ifdef WA_ExtraGadget_MUI
777 WA_ExtraGadget_MUI,
778 (IPTR) ((buttons & MUIV_Window_Button_MUI) != 0) ? TRUE : FALSE,
779 WA_ExtraGadget_PopUp,
780 (IPTR) ((buttons & MUIV_Window_Button_Popup) != 0) ? TRUE : FALSE,
781 WA_ExtraGadget_Snapshot,
782 (IPTR) ((buttons & MUIV_Window_Button_Snapshot) !=
783 0) ? TRUE : FALSE, WA_ExtraGadget_Iconify,
784 (IPTR) ((buttons & MUIV_Window_Button_Iconify) != 0) ? TRUE : FALSE,
785 #endif
786 data->wd_NoMenus ?
787 WA_RMBTrap :
788 TAG_IGNORE, (IPTR) TRUE,
789 WA_Gadgets, (IPTR) gadgets,
790 data->wd_ZoomGadget ?
791 WA_Zoom :
792 TAG_IGNORE, (IPTR) & altdims,
793 backfill, (IPTR) LAYERS_NOBACKFILL, TAG_DONE);
795 if (win)
798 int hborders = win->BorderLeft + win->BorderRight;
799 int vborders = win->BorderTop + win->BorderBottom;
801 /* recalc window size (which will hopefully equal our requested
802 * size) */
803 data->wd_Width = win->GZZWidth;
804 data->wd_Height = win->GZZHeight;
806 /* set window limits according to window contents */
807 WindowLimits
808 (win, data->wd_MinMax.MinWidth + hborders,
809 data->wd_MinMax.MinHeight + vborders,
810 data->wd_MinMax.MaxWidth + hborders,
811 data->wd_MinMax.MaxHeight + vborders);
813 win->UserData = (BYTE *) data->wd_RenderInfo.mri_WindowObject;
814 win->UserPort = muiGlobalInfo(obj)->mgi_WindowsPort;
815 /* Same port for all windows */
816 ModifyIDCMP(win, data->wd_Events);
818 data->wd_RenderInfo.mri_Window = win;
819 data->wd_RenderInfo.mri_VertProp = data->wd_VertProp;
820 data->wd_RenderInfo.mri_HorizProp = data->wd_HorizProp;
821 SetDrMd(win->RPort, JAM1);
822 //text is drawn wrong in toolbarclass if not set
824 if (menu)
826 data->wd_Menu = menu;
827 SetMenuStrip(win, menu);
830 if (flags & WFLG_ACTIVATE)
832 data->wd_Flags |= MUIWF_ACTIVE;
835 if (data->wd_Flags & MUIWF_ISAPPWINDOW)
837 data->wd_AppWindow = AddAppWindowA(0, (IPTR) obj, win,
838 muiGlobalInfo(obj)->mgi_AppPort, NULL);
841 return TRUE;
844 if (menu)
845 FreeMenus(menu);
846 UndisplayWindow(obj, data);
848 return FALSE;
852 static void UndisplayWindow(Object *obj, struct MUI_WindowData *data)
854 struct Window *win = data->wd_RenderInfo.mri_Window;
855 BOOL prefssnap =
856 ((muiGlobalInfo(obj)->mgi_Prefs->window_position ==
857 WINDOW_POSITION_REMEMBER_ON_EXIT)
858 || (muiGlobalInfo(obj)->mgi_Prefs->window_position ==
859 WINDOW_POSITION_SAVE_ON_EXIT));
861 if (((data->wd_XStore >= 0) && (data->wd_YStore >= 0)) || prefssnap)
863 DoMethod(obj, MUIM_Window_Snapshot, 1);
866 data->wd_RenderInfo.mri_Window = NULL;
867 data->wd_RenderInfo.mri_VertProp = NULL;
868 data->wd_RenderInfo.mri_HorizProp = NULL;
870 data->wd_Flags &= ~MUIWF_ACTIVE;
872 if (win != NULL)
874 /* store position and size */
875 if (data->wd_XStore >= 0)
876 data->wd_X = win->LeftEdge;
877 else
878 data->wd_X = data->wd_XStore;
879 if (data->wd_YStore >= 0)
880 data->wd_Y = win->TopEdge;
881 else
882 data->wd_Y = data->wd_YStore;
883 data->wd_Width = win->GZZWidth;
884 data->wd_Height = win->GZZHeight;
886 ClearMenuStrip(win);
887 if (data->wd_Menu)
889 FreeMenus(data->wd_Menu);
890 data->wd_Menu = NULL;
893 if (win->UserPort)
895 struct IntuiMessage *msg, *succ;
897 /* remove all messages pending for this window */
898 Forbid();
899 for (msg =
900 (struct IntuiMessage *)win->UserPort->mp_MsgList.lh_Head;
901 (succ =
902 (struct IntuiMessage *)msg->ExecMessage.mn_Node.
903 ln_Succ); msg = succ)
905 if (msg->IDCMPWindow == win)
907 Remove((struct Node *)msg);
908 ReplyMsg((struct Message *)msg);
911 win->UserPort = NULL;
912 ModifyIDCMP(win, 0);
913 Permit();
916 /* D(bug("before CloseWindow\n")); */
917 CloseWindow(win);
918 /* D(bug("after CloseWindow\n")); */
921 #define DISPOSEGADGET(x) \
922 if (x)\
924 DoMethod(obj, MUIM_Window_FreeGadgetID,\
925 ((struct Gadget*)x)->GadgetID);\
926 DisposeObject(x);\
927 x = NULL;\
930 DISPOSEGADGET(data->wd_VertProp);
931 DISPOSEGADGET(data->wd_UpButton);
932 DISPOSEGADGET(data->wd_DownButton);
933 DISPOSEGADGET(data->wd_HorizProp);
934 DISPOSEGADGET(data->wd_LeftButton);
935 DISPOSEGADGET(data->wd_RightButton);
936 #undef DISPOSEGADGET
940 static VOID RefreshWindow(Object *oWin, struct MUI_WindowData *data)
942 if (data->wd_Flags & MUIWF_RESIZING)
944 //LONG left,top,right,bottom;
945 if (MUI_BeginRefresh(&data->wd_RenderInfo, 0))
947 MUI_EndRefresh(&data->wd_RenderInfo, 0);
949 RefreshWindowFrame(data->wd_RenderInfo.mri_Window);
951 data->wd_Flags &= ~MUIWF_RESIZING;
952 _width(data->wd_RootObject) = data->wd_Width;
953 _height(data->wd_RootObject) = data->wd_Height;
954 DoMethod(data->wd_RootObject, MUIM_Layout);
955 DoShowMethod(data->wd_RootObject);
957 if (muiGlobalInfo(oWin)->mgi_Prefs->window_redraw ==
958 WINDOW_REDRAW_WITH_CLEAR)
960 LONG left, top, width, height;
962 left = data->wd_RenderInfo.mri_Window->BorderLeft;
963 top = data->wd_RenderInfo.mri_Window->BorderTop;
964 width =
965 data->wd_RenderInfo.mri_Window->Width -
966 data->wd_RenderInfo.mri_Window->BorderRight - left;
967 height =
968 data->wd_RenderInfo.mri_Window->Height -
969 data->wd_RenderInfo.mri_Window->BorderBottom - top;
971 if (data->wd_Flags & MUIWF_ERASEAREA)
973 //D(bug("%d:zune_imspec_draw(%p) "
974 // "l=%d t=%d w=%d h=%d xo=%d yo=%d\n",
975 // __LINE__, data->wd_Background, left, top, width,
976 // height, left, top));
977 zune_imspec_draw(data->wd_Background,
978 &data->wd_RenderInfo, left, top, width, height,
979 left, top, 0);
981 MUI_Redraw(data->wd_RootObject, MADF_DRAWALL);
983 else
984 MUI_Redraw(data->wd_RootObject, MADF_DRAWOBJECT);
985 // but should only draw focus without using MUIM_GoActive !
986 ActivateObject(data);
988 else
990 if (MUI_BeginRefresh(&data->wd_RenderInfo, 0))
992 MUI_Redraw(data->wd_RootObject, MADF_DRAWALL);
993 // but should only draw focus without using MUIM_GoActive !
994 ActivateObject(data);
995 MUI_EndRefresh(&data->wd_RenderInfo, 0);
1001 /* Initialize data->wd_X and data->wd_Y for DisplayWindow */
1002 /* FIXME 20030817: needs some fixing, seems not fully implemented */
1003 static void CalcWindowPosition(Object *obj, struct MUI_WindowData *data)
1005 data->wd_XStore = data->wd_X;
1006 data->wd_YStore = data->wd_Y;
1007 if (NULL == data->wd_RefWindow)
1009 /* The following calculations are not very correct, the size and
1010 * dragbar are ignored also the current overscan view */
1011 if (data->wd_X == MUIV_Window_LeftEdge_Centered)
1013 data->wd_X =
1014 (data->wd_RenderInfo.mri_Screen->ViewPort.DWidth -
1015 data->wd_Width) / 2 -
1016 data->wd_RenderInfo.mri_Screen->LeftEdge;
1018 else if (data->wd_X == MUIV_Window_LeftEdge_Moused)
1020 data->wd_X = data->wd_RenderInfo.mri_Screen->MouseX;
1023 if (data->wd_Y == MUIV_Window_TopEdge_Centered)
1025 data->wd_Y =
1026 (data->wd_RenderInfo.mri_Screen->ViewPort.DHeight -
1027 data->wd_Height) / 2 -
1028 data->wd_RenderInfo.mri_Screen->TopEdge;
1030 else if (data->wd_Y == MUIV_Window_TopEdge_Moused)
1032 data->wd_Y = data->wd_RenderInfo.mri_Screen->MouseY;
1034 else if (data->wd_Y <= MUIV_Window_TopEdge_Delta(0))
1036 data->wd_Y = data->wd_RenderInfo.mri_Screen->BarHeight + 1
1037 + MUIV_Window_TopEdge_Delta(0) - data->wd_Y;
1040 else
1042 ULONG w = 0, x = 0;
1043 ULONG h = 0, y = 0;
1045 get(data->wd_RefWindow, MUIA_Window_Width, &w);
1046 get(data->wd_RefWindow, MUIA_Window_LeftEdge, &x);
1048 if (data->wd_X == MUIV_Window_LeftEdge_Centered)
1050 data->wd_X = x + (w - data->wd_Width) / 2;
1052 else
1054 data->wd_X += x;
1057 get(data->wd_RefWindow, MUIA_Window_Height, &h);
1058 get(data->wd_RefWindow, MUIA_Window_TopEdge, &y);
1060 if (data->wd_Y == MUIV_Window_TopEdge_Centered)
1062 /* D(bug("y=%ld, h=%ld, wdh=%ld\n", y, h, data->wd_Height)); */
1063 data->wd_Y = y + (h - data->wd_Height) / 2;
1065 else if (data->wd_Y <= MUIV_Window_TopEdge_Delta(0))
1067 /* ??? surely incorrect implementation */
1068 data->wd_Y = y + 1 + MUIV_Window_TopEdge_Delta(0) - data->wd_Y;
1070 else
1072 data->wd_Y += y;
1077 /* Initialize data->wd_AltDim for DisplayWindow */
1078 static void CalcAltDimensions(Object *obj, struct MUI_WindowData *data)
1080 /* Calculate alternate (zoomed) dimensions.
1082 if (data->wd_AltDim.Top == MUIV_Window_AltTopEdge_NoChange)
1083 data->wd_AltDim.Top = ~0;
1084 else if (data->wd_AltDim.Top == MUIV_Window_AltTopEdge_Centered)
1085 data->wd_AltDim.Top =
1086 (data->wd_RenderInfo.mri_Screen->Height - data->wd_Height) / 2;
1087 else if (data->wd_AltDim.Top == MUIV_Window_AltTopEdge_Moused)
1088 /* ? */ data->wd_AltDim.Top = ~0;
1090 if (data->wd_AltDim.Left == MUIV_Window_AltLeftEdge_NoChange)
1091 data->wd_AltDim.Left = ~0;
1092 else if (data->wd_AltDim.Left == MUIV_Window_AltLeftEdge_Centered)
1093 data->wd_AltDim.Left =
1094 (data->wd_RenderInfo.mri_Screen->Width - data->wd_Width) / 2;
1095 else if (data->wd_AltDim.Left == MUIV_Window_AltLeftEdge_Moused)
1096 /* ? */ data->wd_AltDim.Left = ~0;
1098 if (_between
1099 (MUIV_Window_AltWidth_MinMax(100),
1100 data->wd_AltDim.Width, MUIV_Window_AltWidth_MinMax(0)))
1102 data->wd_AltDim.Width = data->wd_MinMax.MinWidth
1103 - data->wd_AltDim.Width
1104 * (data->wd_MinMax.MaxWidth - data->wd_MinMax.MinWidth);
1106 else if
1107 (_between
1108 (MUIV_Window_AltWidth_Screen(100),
1109 data->wd_AltDim.Width, MUIV_Window_AltWidth_Screen(0)))
1111 data->wd_AltDim.Width = data->wd_RenderInfo.mri_ScreenWidth
1112 * (-(data->wd_AltDim.Width + 200)) / 100;
1114 else if
1115 (_between
1116 (MUIV_Window_AltWidth_Visible(100),
1117 data->wd_AltDim.Width, MUIV_Window_AltWidth_Visible(0)))
1119 data->wd_AltDim.Width = data->wd_RenderInfo.mri_ScreenWidth
1120 * (-(data->wd_AltDim.Width + 100)) / 100;
1123 if (_between
1124 (MUIV_Window_AltHeight_MinMax(100),
1125 data->wd_AltDim.Height, MUIV_Window_AltHeight_MinMax(0)))
1127 data->wd_AltDim.Height = data->wd_MinMax.MinHeight
1128 - data->wd_AltDim.Height
1129 * (data->wd_MinMax.MaxHeight - data->wd_MinMax.MinHeight);
1131 else if
1132 (_between
1133 (MUIV_Window_AltHeight_Screen(100),
1134 data->wd_AltDim.Height, MUIV_Window_AltHeight_Screen(0)))
1136 data->wd_AltDim.Height = data->wd_RenderInfo.mri_ScreenHeight
1137 * (-(data->wd_AltDim.Height + 200)) / 100;
1139 else if
1140 (_between
1141 (MUIV_Window_AltHeight_Visible(100),
1142 data->wd_AltDim.Height, MUIV_Window_AltHeight_Visible(0)))
1144 data->wd_AltDim.Height = data->wd_RenderInfo.mri_ScreenHeight
1145 * (-(data->wd_AltDim.Height + 100)) / 100;
1148 data->wd_AltDim.Width = CLAMP
1149 (data->wd_AltDim.Width, data->wd_MinMax.MinWidth,
1150 data->wd_MinMax.MaxWidth);
1151 data->wd_AltDim.Height = CLAMP
1152 (data->wd_AltDim.Height, data->wd_MinMax.MinHeight,
1153 data->wd_MinMax.MaxHeight);
1157 /* Create horiz/vert window scrollbars for DisplayWindow */
1158 static void CreateWindowScrollbars(Object *obj,
1159 struct MUI_WindowData *data)
1161 struct MUI_RenderInfo *mri = &data->wd_RenderInfo;
1162 Object *firstgad = NULL;
1163 Object *prevgad = NULL;
1164 LONG id;
1166 /* Create the right border scrollers now if requested */
1167 if (data->wd_Flags & MUIWF_USERIGHTSCROLLER)
1169 int voffset;
1171 voffset = IM(mri->mri_DownImage)->Width / 4;
1173 id = DoMethod(obj, MUIM_Window_AllocGadgetID);
1174 firstgad = prevgad = data->wd_VertProp = NewObject
1175 (NULL, "propgclass",
1176 GA_RelRight, 1 - (IM(mri->mri_UpImage)->Width - voffset),
1177 GA_Top, mri->mri_BorderTop + 2,
1178 GA_Width, IM(mri->mri_UpImage)->Width - voffset * 2,
1179 GA_RelHeight, -(mri->mri_BorderTop + 2)
1180 - IM(mri->mri_UpImage)->Height
1181 - IM(mri->mri_DownImage)->Height
1182 - IM(mri->mri_SizeImage)->Height - 2,
1183 GA_RightBorder, TRUE,
1184 GA_ID, id,
1185 PGA_Borderless, TRUE,
1186 PGA_NewLook, TRUE,
1187 PGA_Freedom, FREEVERT,
1188 PGA_Top, 0,
1189 PGA_Total, 2,
1190 PGA_Visible, 1, ICA_TARGET, ICTARGET_IDCMP, TAG_DONE);
1192 id = DoMethod(obj, MUIM_Window_AllocGadgetID);
1193 prevgad = data->wd_UpButton = NewObject
1194 (NULL, "buttongclass",
1195 GA_Image, (IPTR) mri->mri_UpImage,
1196 GA_RelRight, 1 - IM(mri->mri_UpImage)->Width,
1197 GA_RelBottom, 1 - IM(mri->mri_UpImage)->Height
1198 - IM(mri->mri_DownImage)->Height
1199 - IM(mri->mri_SizeImage)->Height,
1200 GA_RightBorder, TRUE,
1201 GA_Previous, (IPTR) prevgad,
1202 GA_ID, id, ICA_TARGET, ICTARGET_IDCMP, TAG_DONE);
1204 id = DoMethod(obj, MUIM_Window_AllocGadgetID);
1205 prevgad = data->wd_DownButton = NewObject
1206 (NULL, "buttongclass",
1207 GA_Image, (IPTR) mri->mri_DownImage,
1208 GA_RelRight, 1 - IM(mri->mri_DownImage)->Width,
1209 GA_RelBottom, 1 - IM(mri->mri_DownImage)->Height
1210 - IM(mri->mri_SizeImage)->Height,
1211 GA_RightBorder, TRUE,
1212 GA_Previous, (IPTR) prevgad,
1213 GA_ID, id, ICA_TARGET, ICTARGET_IDCMP, TAG_DONE);
1216 /* Create the bottom border scrollers now if requested */
1217 if (data->wd_Flags & MUIWF_USEBOTTOMSCROLLER)
1219 int hoffset;
1221 hoffset = IM(mri->mri_RightImage)->Height / 4;
1223 id = DoMethod(obj, MUIM_Window_AllocGadgetID);
1224 prevgad = data->wd_HorizProp = NewObject
1225 (NULL, "propgclass",
1226 GA_RelBottom, 1 - (IM(mri->mri_LeftImage)->Height - hoffset),
1227 GA_Left, mri->mri_BorderLeft,
1228 GA_Height, IM(mri->mri_LeftImage)->Height
1229 - hoffset * 2,
1230 GA_RelWidth, -(mri->mri_BorderLeft)
1231 - IM(mri->mri_LeftImage)->Width
1232 - IM(mri->mri_RightImage)->Width
1233 - IM(mri->mri_SizeImage)->Width
1234 - 2,
1235 GA_BottomBorder, TRUE,
1236 GA_ID, id,
1237 prevgad ? GA_Previous : TAG_IGNORE, (IPTR) prevgad,
1238 PGA_Borderless, TRUE,
1239 PGA_NewLook, TRUE,
1240 PGA_Freedom, FREEHORIZ,
1241 PGA_Top, 0,
1242 PGA_Total, 2,
1243 PGA_Visible, 1, ICA_TARGET, ICTARGET_IDCMP, TAG_DONE);
1245 if (!firstgad)
1246 firstgad = prevgad;
1248 id = DoMethod(obj, MUIM_Window_AllocGadgetID);
1249 prevgad = data->wd_LeftButton = NewObject
1250 (NULL, "buttongclass",
1251 GA_Image, (IPTR) mri->mri_LeftImage,
1252 GA_RelRight, 1 - IM(mri->mri_LeftImage)->Width
1253 - IM(mri->mri_RightImage)->Width
1254 - IM(mri->mri_SizeImage)->Width,
1255 GA_RelBottom, 1 - IM(mri->mri_LeftImage)->Height,
1256 GA_BottomBorder, TRUE,
1257 GA_Previous, (IPTR) prevgad,
1258 GA_ID, id, ICA_TARGET, ICTARGET_IDCMP, TAG_DONE);
1260 id = DoMethod(obj, MUIM_Window_AllocGadgetID);
1261 prevgad = data->wd_RightButton = NewObject
1262 (NULL, "buttongclass",
1263 GA_Image, (IPTR) mri->mri_RightImage,
1264 GA_RelRight, 1 - IM(mri->mri_RightImage)->Width
1265 - IM(mri->mri_SizeImage)->Width,
1266 GA_RelBottom, 1 - IM(mri->mri_RightImage)->Height,
1267 GA_BottomBorder, TRUE,
1268 GA_Previous, (IPTR) prevgad,
1269 GA_ID, id, ICA_TARGET, ICTARGET_IDCMP, TAG_DONE);
1273 /* return FALSE only if no resize (dx=dy=0) occured */
1274 static BOOL WindowResize(struct MUI_WindowData *data)
1276 struct Window *win = data->wd_RenderInfo.mri_Window;
1277 int hborders = win->BorderLeft + win->BorderRight;
1278 int vborders = win->BorderTop + win->BorderBottom;
1279 WORD dx = data->wd_Width - win->Width + hborders;
1280 WORD dy = data->wd_Height - win->Height + vborders;
1282 /* Temporarily disable window limits to let SizeWindow below work
1283 regardless of the previous limits */
1284 WindowLimits(win, 1, 1, -1, -1);
1285 /* D(bug("_zune_window_resize : dx=%d, dy=%d\n", dx, dy)); */
1286 SizeWindow(win, dx, dy);
1288 /* Set new window limits */
1289 WindowLimits
1290 (win, data->wd_MinMax.MinWidth + hborders,
1291 data->wd_MinMax.MinHeight + vborders,
1292 data->wd_MinMax.MaxWidth + hborders,
1293 data->wd_MinMax.MaxHeight + vborders);
1295 return dx || dy;
1298 static void KillHelpBubble(struct MUI_WindowData *data, Object *obj,
1299 BOOL kill_bubblemode)
1301 if (data->wd_HelpObject)
1303 DoMethod(data->wd_HelpObject, MUIM_DeleteBubble,
1304 (IPTR) data->wd_HelpBubble);
1305 data->wd_HelpObject = NULL;
1306 data->wd_HelpBubble = NULL;
1309 if (kill_bubblemode)
1310 data->wd_Flags &= ~MUIWF_BUBBLEMODE;
1312 if (data->wd_Flags & MUIWF_BUBBLEMODE)
1314 data->wd_HelpTicker = BUBBLEHELP_TICKER_LATER;
1316 else
1318 data->wd_HelpTicker = BUBBLEHELP_TICKER_FIRST;
1323 /**************/
1325 typedef BOOL(*UNDERCHECK_FUNC) (Object *obj);
1327 static BOOL ShortHelpUnderPointerCheck(Object *obj)
1329 return muiAreaData(obj)->mad_ShortHelp ? TRUE : FALSE;
1332 static Object *ObjectUnderPointer(struct MUI_WindowData *data, Object *obj,
1333 LONG x, LONG y, UNDERCHECK_FUNC func)
1335 Object *cstate;
1336 Object *child;
1337 struct MinList *ChildList = NULL;
1339 if (!(muiAreaData(obj)->mad_Flags & MADF_CANDRAW))
1340 return NULL;
1342 if (!(x >= _left(obj) && x <= _right(obj)
1343 && y >= _top(obj) && y <= _bottom(obj)))
1345 return NULL;
1348 if ((get(obj, MUIA_Group_ChildList, &(ChildList)))
1349 && (ChildList != NULL))
1351 cstate = (Object *) ChildList->mlh_Head;
1352 while ((child = NextObject(&cstate)))
1354 Object *ret;
1356 if ((x >= _left(child) && x <= _right(child)
1358 y >= _top(child) && y <= _bottom(child))
1359 && (ret = ObjectUnderPointer(data, child, x, y, func)))
1361 return ret;
1366 if (!(*func) (obj))
1367 return NULL;
1369 return obj;
1372 static BOOL ContextMenuUnderPointer(struct MUI_WindowData *data,
1373 Object *obj, LONG x, LONG y)
1375 Object *cstate;
1376 Object *child;
1377 struct MinList *ChildList = NULL;
1379 if (!(x >= _left(obj) && x <= _right(obj)
1380 && y >= _top(obj) && y <= _bottom(obj)))
1382 return FALSE;
1385 if ((get(obj, MUIA_Group_ChildList, &(ChildList)))
1386 && (ChildList != NULL))
1389 cstate = (Object *) ChildList->mlh_Head;
1390 while ((child = NextObject(&cstate)))
1392 if ((x >= _left(child) && x <= _right(child)
1394 y >= _top(child) && y <= _bottom(child))
1395 && (ContextMenuUnderPointer(data, child, x, y)))
1396 return TRUE;
1400 if (!(muiAreaData(obj)->mad_Flags & MADF_CANDRAW))
1401 return FALSE;
1402 if (!(muiAreaData(obj)->mad_ContextMenu))
1403 return FALSE;
1405 return TRUE;
1408 /**************/
1410 static void ActivateObject(struct MUI_WindowData *data)
1412 //bug("Window::ActivateObject (dummy) %08lx\n", data->wd_ActiveObject);
1413 // if (FindObjNode(&data->wd_CycleChain, data->wd_ActiveObject))
1414 // DoMethod(data->wd_ActiveObject, MUIM_GoActive);
1415 // else
1416 // data->wd_ActiveObject = NULL;
1418 //activate better string gadgets.Fix from Georg S On ML List
1419 if (FindObjNode(&data->wd_CycleChain, data->wd_ActiveObject))
1421 if (!(data->wd_Flags & MUIWF_OBJECTGOACTIVESENT))
1423 data->wd_Flags |= MUIWF_OBJECTGOACTIVESENT;
1424 DoMethod(data->wd_ActiveObject, MUIM_GoActive);
1427 else
1428 data->wd_ActiveObject = NULL;
1431 /**************/
1433 /* handle intuimessage while an object is being dragged
1434 * (reply imsg before returning)
1435 * Returns TRUE if finished dragging.
1437 static BOOL HandleDragging(Object *oWin, struct MUI_WindowData *data,
1438 struct IntuiMessage *imsg)
1440 struct Window *iWin;
1441 BOOL finish_drag = FALSE;
1443 iWin = imsg->IDCMPWindow;
1445 if (imsg->Class == IDCMP_MOUSEMOVE)
1447 struct Layer *layer;
1449 LockLayerInfo(&iWin->WScreen->LayerInfo);
1450 layer = WhichLayer(&iWin->WScreen->LayerInfo, iWin->LeftEdge + imsg->MouseX,
1451 iWin->TopEdge + imsg->MouseY);
1452 UnlockLayerInfo(&iWin->WScreen->LayerInfo);
1454 if (data->wd_DropObject)
1456 struct Window *wnd;
1457 WORD mousex =
1458 imsg->MouseX + iWin->LeftEdge -
1459 data->wd_DropWindow->LeftEdge;
1460 WORD mousey =
1461 imsg->MouseY + iWin->TopEdge - data->wd_DropWindow->TopEdge;
1463 wnd = _window(data->wd_DropObject);
1464 if (mousex < _left(data->wd_DropObject)
1465 || mousex > _right(data->wd_DropObject)
1466 || mousey < _top(data->wd_DropObject)
1467 || mousey > _bottom(data->wd_DropObject)
1468 || layer != wnd->WLayer)
1470 /* We have left the object */
1471 UndrawDragNDrop(data->wd_dnd);
1472 DoMethod(data->wd_DropObject, MUIM_DragFinish,
1473 (IPTR) data->wd_DragObject);
1474 data->wd_DropObject = NULL;
1476 } /* if (data->wd_DropObject) */
1478 if (!data->wd_DropObject)
1480 Object *dest_wnd = NULL;
1482 /* Find out if app has an open window at this position */
1483 if (layer)
1485 Object *cstate;
1486 Object *child;
1487 struct MinList *ChildList = 0;
1489 get(_app(oWin), MUIA_Application_WindowList, &(ChildList));
1490 cstate = (Object *) ChildList->mlh_Head;
1491 while ((child = NextObject(&cstate)))
1493 struct Window *wnd = NULL;
1494 get(child, MUIA_Window_Window, &wnd);
1495 if (!wnd)
1496 continue;
1498 if (wnd->WLayer == layer)
1500 data->wd_DropWindow = wnd;
1501 dest_wnd = child;
1502 break;
1505 } /* if (layer) */
1507 if (dest_wnd)
1509 Object *root = NULL;
1510 get(dest_wnd, MUIA_Window_RootObject, &root);
1512 if (root)
1514 if ((data->wd_DropObject = (Object *) DoMethod
1515 (root, MUIM_DragQueryExtended,
1516 (IPTR) data->wd_DragObject,
1517 imsg->MouseX + iWin->LeftEdge -
1518 data->wd_DropWindow->LeftEdge,
1519 imsg->MouseY + iWin->TopEdge -
1520 data->wd_DropWindow->TopEdge)))
1522 UndrawDragNDrop(data->wd_dnd);
1523 DoMethod(data->wd_DropObject, MUIM_DragBegin,
1524 (IPTR) data->wd_DragObject);
1530 if (data->wd_DropObject)
1532 LONG update = 0;
1533 LONG i;
1534 for (i = 0; i < 2; i++)
1536 LONG res = DoMethod(data->wd_DropObject, MUIM_DragReport,
1537 (IPTR) data->wd_DragObject,
1538 imsg->MouseX + iWin->LeftEdge -
1539 data->wd_DropWindow->LeftEdge,
1540 imsg->MouseY + iWin->TopEdge -
1541 data->wd_DropWindow->TopEdge, update);
1542 switch (res)
1544 case MUIV_DragReport_Abort:
1545 UndrawDragNDrop(data->wd_dnd);
1546 DoMethod(data->wd_DropObject, MUIM_DragFinish,
1547 (IPTR) data->wd_DragObject);
1548 data->wd_DropObject = NULL;
1549 i = 1;
1550 break;
1552 case MUIV_DragReport_Continue:
1553 break;
1554 case MUIV_DragReport_Lock:
1555 break; /* NYI */
1556 case MUIV_DragReport_Refresh:
1557 UndrawDragNDrop(data->wd_dnd);
1558 update = 1;
1559 break;
1563 DrawDragNDrop(data->wd_dnd, imsg->MouseX + iWin->LeftEdge,
1564 imsg->MouseY + iWin->TopEdge);
1567 if (imsg->Class == IDCMP_MOUSEBUTTONS)
1569 if ((imsg->Code == MENUDOWN) || (imsg->Code == SELECTUP))
1571 UndrawDragNDrop(data->wd_dnd);
1572 if (imsg->Code == SELECTUP && data->wd_DropObject)
1574 DoMethod(data->wd_DropObject, MUIM_DragDrop,
1575 (IPTR) data->wd_DragObject,
1576 imsg->MouseX + iWin->LeftEdge -
1577 data->wd_DropWindow->LeftEdge,
1578 imsg->MouseY + iWin->TopEdge -
1579 data->wd_DropWindow->TopEdge);
1580 DoMethod(data->wd_DropObject, MUIM_DragFinish,
1581 (IPTR) data->wd_DragObject);
1582 data->wd_DropObject = NULL;
1584 else if (imsg->Code == SELECTUP)
1586 DoMethod(data->wd_DragObject, MUIM_UnknownDropDestination,
1587 imsg);
1589 finish_drag = TRUE;
1593 if (imsg->Class == IDCMP_CLOSEWINDOW)
1594 finish_drag = TRUE;
1596 if (finish_drag)
1598 if (data->wd_DropObject)
1600 UndrawDragNDrop(data->wd_dnd);
1601 DoMethod(data->wd_DropObject, MUIM_DragFinish,
1602 (IPTR) data->wd_DragObject);
1603 data->wd_DropObject = NULL;
1605 DeleteDragNDrop(data->wd_dnd);
1606 DoMethod(data->wd_DragObject, MUIM_DeleteDragImage,
1607 (IPTR) data->wd_DragImage);
1608 muiAreaData(data->wd_DragObject)->mad_Flags &= ~MADF_DRAGGING;
1609 data->wd_DragImage = NULL;
1610 data->wd_DragObject = NULL;
1611 data->wd_DropWindow = NULL;
1612 data->wd_dnd = NULL;
1614 /* stop listening to IDCMP_MOUSEMOVE */
1615 ChangeEvents(data, GetDefaultEvents());
1617 if (!finish_drag)
1618 ReplyMsg((struct Message *)imsg);
1620 return finish_drag;
1623 /* Reply to imsg if handled */
1624 BOOL HandleWindowEvent(Object *oWin, struct MUI_WindowData *data,
1625 struct IntuiMessage *imsg)
1627 struct Window *iWin;
1628 BOOL is_handled = TRUE;
1629 BOOL replied = FALSE;
1631 iWin = imsg->IDCMPWindow;
1632 switch (imsg->Class)
1634 case IDCMP_ACTIVEWINDOW:
1635 data->wd_Flags |= MUIWF_ACTIVE;
1636 if (data->wd_OldActive)
1637 set(oWin, MUIA_Window_ActiveObject, data->wd_OldActive);
1638 set(oWin, MUIA_Window_Activate, TRUE);
1639 is_handled = FALSE; /* forwardable to area event handlers */
1640 break;
1642 case IDCMP_INACTIVEWINDOW:
1643 KillHelpBubble(data, oWin, TRUE);
1644 if (data->wd_ActiveObject)
1646 data->wd_OldActive = data->wd_ActiveObject;
1647 set(oWin, MUIA_Window_ActiveObject,
1648 MUIV_Window_ActiveObject_None);
1650 data->wd_Flags &= ~MUIWF_ACTIVE;
1651 set(oWin, MUIA_Window_Activate, FALSE);
1652 is_handled = FALSE; /* forwardable to area event handlers */
1653 break;
1655 case IDCMP_NEWSIZE:
1656 case IDCMP_CHANGEWINDOW:
1657 ReplyMsg((struct Message *)imsg);
1658 replied = TRUE;
1661 int hborders = iWin->BorderLeft + iWin->BorderRight;
1662 int vborders = iWin->BorderTop + iWin->BorderBottom;
1664 /* set window limits according to window contents */
1665 WindowLimits
1666 (iWin,
1667 data->wd_MinMax.MinWidth + hborders,
1668 data->wd_MinMax.MinHeight + vborders,
1669 data->wd_MinMax.MaxWidth + hborders,
1670 data->wd_MinMax.MaxHeight + vborders);
1673 if ((iWin->GZZWidth != data->wd_Width)
1674 || (iWin->GZZHeight != data->wd_Height))
1676 data->wd_Width = iWin->GZZWidth;
1677 data->wd_Height = iWin->GZZHeight;
1678 DoHideMethod(data->wd_RootObject);
1680 data->wd_Flags |= MUIWF_RESIZING;
1681 RefreshWindow(oWin, data);
1683 break;
1685 case IDCMP_REFRESHWINDOW:
1686 ReplyMsg((struct Message *)imsg);
1687 replied = TRUE;
1688 RefreshWindow(oWin, data);
1689 break;
1691 case IDCMP_CLOSEWINDOW:
1692 ReplyMsg((struct Message *)imsg);
1693 replied = TRUE;
1694 set(oWin, MUIA_Window_CloseRequest, TRUE);
1695 break;
1697 case IDCMP_MENUPICK:
1698 ReplyMsg((struct Message *)imsg);
1699 replied = TRUE;
1701 if (data->wd_Menu)
1703 if (MENUNUM(imsg->Code) != NOMENU
1704 && ITEMNUM(imsg->Code) != NOITEM)
1706 struct MenuItem *item =
1707 ItemAddress(data->wd_Menu, imsg->Code);
1708 if (item)
1710 Object *item_obj = (Object *) GTMENUITEM_USERDATA(item);
1711 if (item_obj)
1713 Object *app = NULL;
1714 IPTR udata = 0;
1716 if (item->Flags & CHECKIT)
1717 set(item_obj, MUIA_Menuitem_Checked,
1718 ! !(item->Flags & CHECKED));
1720 set(item_obj, MUIA_Menuitem_Trigger, (IPTR) item);
1722 get(oWin, MUIA_ApplicationObject, &app);
1723 get(item_obj, MUIA_UserData, &udata);
1725 set(app, MUIA_Application_MenuAction, udata);
1726 set(oWin, MUIA_Window_MenuAction, udata);
1727 DoMethod(app, MUIM_Application_ReturnID, udata);
1732 break;
1734 case IDCMP_IDCMPUPDATE:
1735 is_handled = FALSE; /* forwardable to area event handlers */
1736 if (data->wd_VertProp || data->wd_HorizProp)
1738 struct TagItem *tag;
1739 tag = FindTagItem(GA_ID, (struct TagItem *)imsg->IAddress);
1740 if (tag)
1742 /* If there's a propclass object connected to the prop
1743 gadget, the prop gadget's userdata will point to
1744 that propclass object. See classes/prop.c */
1746 if (data->wd_VertProp)
1748 if (tag->ti_Data == GADGETID(data->wd_VertProp))
1751 if (tag->ti_Data == GADGETID(data->wd_UpButton))
1753 Object *prop =
1754 (Object *) ((struct Gadget *)data->
1755 wd_VertProp)->UserData;
1756 is_handled = TRUE;
1757 if (prop)
1758 DoMethod(prop, MUIM_Prop_Decrease, 1);
1761 if (tag->ti_Data == GADGETID(data->wd_DownButton))
1763 Object *prop =
1764 (Object *) ((struct Gadget *)data->
1765 wd_VertProp)->UserData;
1766 is_handled = TRUE;
1767 if (prop)
1768 DoMethod(prop, MUIM_Prop_Increase, 1);
1773 if (data->wd_HorizProp)
1775 if (tag->ti_Data == GADGETID(data->wd_HorizProp))
1778 if (tag->ti_Data == GADGETID(data->wd_LeftButton))
1780 Object *prop =
1781 (Object *) ((struct Gadget *)data->
1782 wd_HorizProp)->UserData;
1783 is_handled = TRUE;
1784 if (prop)
1785 DoMethod(prop, MUIM_Prop_Decrease, 1);
1788 if (tag->ti_Data == GADGETID(data->wd_RightButton))
1790 Object *prop =
1791 (Object *) ((struct Gadget *)data->
1792 wd_HorizProp)->UserData;
1793 is_handled = TRUE;
1794 if (prop)
1795 DoMethod(prop, MUIM_Prop_Increase, 1);
1801 break;
1803 case IDCMP_INTUITICKS:
1804 if (data->wd_HelpTicker)
1806 data->wd_HelpTicker--;
1808 if (data->wd_HelpTicker == 0)
1810 Object *underobj =
1811 ObjectUnderPointer(data, data->wd_RootObject,
1812 imsg->MouseX, imsg->MouseY,
1813 ShortHelpUnderPointerCheck);
1815 if (underobj != data->wd_HelpObject)
1817 if (data->wd_HelpObject)
1819 DoMethod(data->wd_HelpObject, MUIM_DeleteBubble,
1820 (IPTR) data->wd_HelpBubble);
1822 data->wd_HelpObject = NULL;
1823 data->wd_HelpBubble = NULL;
1826 if (underobj)
1828 data->wd_HelpBubble =
1829 (APTR) DoMethod(underobj, MUIM_CreateBubble,
1830 imsg->MouseX, imsg->MouseY, 0, 0);
1831 if (data->wd_HelpBubble)
1833 data->wd_HelpObject = underobj;
1834 data->wd_Flags |= MUIWF_BUBBLEMODE;
1839 if (data->wd_Flags & MUIWF_BUBBLEMODE)
1841 data->wd_HelpTicker = BUBBLEHELP_TICKER_LATER;
1843 else
1845 data->wd_HelpTicker = BUBBLEHELP_TICKER_FIRST;
1850 is_handled = FALSE; /* forwardable to area event handlers */
1851 break;
1853 case IDCMP_MOUSEBUTTONS:
1854 DoMethod(oWin, MUIM_Window_Snapshot, 0);
1855 KillHelpBubble(data, oWin, TRUE);
1856 is_handled = FALSE;
1857 break;
1860 case IDCMP_MOUSEMOVE:
1861 KillHelpBubble(data, oWin, FALSE);
1862 is_handled = FALSE;
1863 break;
1865 default:
1866 is_handled = FALSE;
1867 break;
1870 if (is_handled && !replied)
1871 ReplyMsg((struct Message *)imsg);
1873 return is_handled;
1876 static ULONG InvokeEventHandler(struct MUI_EventHandlerNode *ehn,
1877 struct IntuiMessage *event, ULONG muikey)
1879 ULONG res;
1881 if (!(_flags(ehn->ehn_Object) & MADF_CANDRAW))
1882 return 0;
1883 if (!(_flags(ehn->ehn_Object) & MADF_SHOWME))
1884 return 0;
1886 if (event != NULL
1887 && event->Class == IDCMP_MOUSEBUTTONS
1888 && event->Code == SELECTDOWN
1889 && (_flags(ehn->ehn_Object) & MADF_INVIRTUALGROUP))
1892 Here we filter out SELECTDOWN messages if objects is in a virtual
1893 group but the click went out of the virtual group
1895 Object *obj = ehn->ehn_Object;
1896 Object *parent = obj;
1897 Object *wnd = _win(obj);
1899 while (get(parent, MUIA_Parent, &parent))
1901 if (!parent)
1902 break;
1903 if (wnd == parent)
1904 break;
1905 if (_flags(parent) & MADF_ISVIRTUALGROUP)
1907 if (event->MouseX < _mleft(parent)
1908 || event->MouseX > _mright(parent)
1909 || event->MouseY < _mtop(parent)
1910 || event->MouseY > _mbottom(parent))
1912 return 0;
1919 if (ehn->ehn_Flags & MUI_EHF_HANDLEINPUT)
1921 DoMethod(ehn->ehn_Object, MUIM_HandleInput, (IPTR) event, muikey);
1922 res = 0;
1924 else
1926 if (ehn->ehn_Class)
1927 res = CoerceMethod
1928 (ehn->ehn_Class, ehn->ehn_Object, MUIM_HandleEvent,
1929 (IPTR) event, muikey);
1930 else
1931 res =
1932 DoMethod(ehn->ehn_Object, MUIM_HandleEvent, (IPTR) event,
1933 muikey);
1936 return res;
1939 static void HandleRawkey(Object *win, struct MUI_WindowData *data,
1940 struct IntuiMessage *event)
1942 struct MinNode *mn;
1943 struct MUI_EventHandlerNode *ehn;
1944 struct IntuiMessage imsg_copy;
1945 struct InputEvent ie = { 0 };
1946 ULONG res;
1947 LONG muikey = MUIKEY_NONE;
1948 Object *active_object = NULL;
1949 IPTR disabled = 0;
1950 ULONG key;
1951 ULONG deadkey;
1953 KillHelpBubble(data, win, BUBBLEHELP_TICKER_FIRST);
1955 ie.ie_NextEvent = NULL;
1956 ie.ie_Class = IECLASS_RAWKEY;
1957 ie.ie_SubClass = 0;
1958 ie.ie_Code = event->Code;
1959 ie.ie_Qualifier = event->Qualifier;
1960 ie.ie_EventAddress = (APTR) * (IPTR *) event->IAddress;
1961 #ifdef __AMIGAOS4__
1962 ie.ie_TimeStamp.Seconds = event->Seconds;
1963 ie.ie_TimeStamp.Microseconds = event->Micros;
1964 #else
1965 ie.ie_TimeStamp.tv_secs = event->Seconds;
1966 ie.ie_TimeStamp.tv_micro = event->Micros;
1967 #endif
1969 set(win, MUIA_Window_InputEvent, (IPTR) & ie);
1971 /* get the vanilla key for control char */
1973 UWORD msg_code;
1975 /* Remove the up prefix as convert key does not convert upkey event */
1976 msg_code = event->Code;
1977 event->Code &= ~IECODE_UP_PREFIX;
1978 key = ConvertKey(event);
1979 event->Code = msg_code;
1982 imsg_copy = *event;
1983 deadkey = *(ULONG *) event->IAddress;
1984 imsg_copy.IAddress = &deadkey;
1985 ReplyMsg((struct Message *)event);
1986 event = &imsg_copy;
1988 //bug("rawkey: code=%lx, qual=%lx\n", event->Code, event->Qualifier);
1990 /* check if imsg translates to predefined keystroke */
1992 struct InputEvent ievent;
1993 BOOL matched = FALSE;
1995 ievent.ie_NextEvent = NULL;
1996 ievent.ie_Class = IECLASS_RAWKEY;
1997 ievent.ie_SubClass = 0;
1998 ievent.ie_Code = event->Code;
1999 ievent.ie_Qualifier = event->Qualifier;
2000 /* ie_EventAddress is not used by MatchIX. If needed, it should be
2001 * ensured that it is still a valid address because of the shallow
2002 * IntuiMessage copy currently done in _zune_window_message before
2003 * message is replied.
2005 ievent.ie_EventAddress = NULL;
2006 //ievent.ie_EventAddress = (APTR *) *((ULONG *)(event->IAddress));
2008 for (muikey = MUIKEY_COUNT - 1; muikey >= MUIKEY_PRESS; muikey--)
2010 if (muiGlobalInfo(win)->mgi_Prefs->muikeys[muikey].ix_well != 0
2011 && MatchIX(&ievent,
2012 &muiGlobalInfo(win)->mgi_Prefs->muikeys[muikey].ix))
2014 matched = TRUE;
2015 break;
2019 if (matched)
2021 if (muikey == MUIKEY_PRESS && (event->Code & IECODE_UP_PREFIX))
2022 muikey = MUIKEY_RELEASE;
2024 else
2026 muikey = MUIKEY_NONE;
2028 } /* check if imsg translate to predefined keystroke */
2030 if ((muikey != MUIKEY_NONE) && !(data->wd_DisabledKeys & (1 << muikey)))
2032 D(bug("HandleRawkey: try MUIKEY %ld on window %0x08lx\n", muikey,
2033 win));
2034 switch (muikey)
2036 case MUIKEY_PRESS:
2037 break;
2038 case MUIKEY_TOGGLE:
2039 break;
2040 case MUIKEY_UP:
2041 break;
2042 case MUIKEY_DOWN:
2043 break;
2044 case MUIKEY_PAGEUP:
2045 break;
2046 case MUIKEY_PAGEDOWN:
2047 break;
2048 case MUIKEY_TOP:
2049 break;
2050 case MUIKEY_BOTTOM:
2051 break;
2052 case MUIKEY_LEFT:
2053 break;
2054 case MUIKEY_RIGHT:
2055 break;
2056 case MUIKEY_WORDLEFT:
2057 break;
2058 case MUIKEY_WORDRIGHT:
2059 break;
2060 case MUIKEY_LINESTART:
2061 break;
2062 case MUIKEY_LINEEND:
2063 break;
2064 case MUIKEY_GADGET_NEXT:
2065 set(win, MUIA_Window_ActiveObject,
2066 MUIV_Window_ActiveObject_Next);
2067 break;
2068 case MUIKEY_GADGET_PREV:
2069 set(win, MUIA_Window_ActiveObject,
2070 MUIV_Window_ActiveObject_Prev);
2071 break;
2072 case MUIKEY_GADGET_OFF:
2073 set(win, MUIA_Window_ActiveObject,
2074 MUIV_Window_ActiveObject_None);
2075 break;
2076 case MUIKEY_WINDOW_CLOSE:
2077 set(win, MUIA_Window_CloseRequest, TRUE);
2078 break;
2079 case MUIKEY_WINDOW_NEXT:
2080 break;
2081 case MUIKEY_WINDOW_PREV:
2082 break;
2083 case MUIKEY_HELP:
2084 break;
2085 case MUIKEY_POPUP:
2086 break;
2087 default:
2088 break;
2092 active_object = NULL;
2093 if ((data->wd_ActiveObject != NULL)
2094 && (DoMethod(data->wd_RootObject, MUIM_FindAreaObject,
2095 (IPTR) data->wd_ActiveObject) != (IPTR) NULL))
2097 active_object = data->wd_ActiveObject;
2098 get(active_object, MUIA_Disabled, &disabled);
2100 else
2101 data->wd_ActiveObject = NULL;
2103 /* try ActiveObject */
2104 if ((active_object != NULL) && !disabled)
2106 #if 0
2107 /* sba:
2108 ** Which method should be used for muikeys? MUIM_HandleInput or
2109 ** MUIM_HandleEvent. Also note that there is a flag MUI_EHF_ALWAYSKEYS
2110 ** which probably means that all keys events are requested??
2111 ** For now MUIM_HandleEvent is used as this is currently implemented
2112 ** in Area class ;) although I guess it should be MUIM_HandleInput as
2113 ** this was earlier
2116 if (muikey != MUIKEY_NONE)
2118 res =
2119 DoMethod(active_object, MUIM_HandleEvent, (IPTR) event,
2120 muikey);
2121 if (res & MUI_EventHandlerRC_Eat)
2122 return;
2124 #endif
2125 D(bug("HandleRawkey: try active object (%08lx) handlers\n",
2126 active_object));
2128 for (mn = data->wd_EHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
2130 ehn = (struct MUI_EventHandlerNode *)mn;
2132 if ((ehn->ehn_Object == active_object)
2133 && ((ehn->ehn_Events & IDCMP_RAWKEY)
2134 || (ehn->ehn_Flags & MUI_EHF_ALWAYSKEYS)))
2136 D(bug("HandleRawkey: (active) invoking on %p (ehn=%p) "
2137 "event=%p muikey=%p\n",
2138 ehn->ehn_Object, ehn, event, muikey));
2139 res = InvokeEventHandler(ehn, event, muikey);
2140 D(bug("HandleRawkey: (active) got res=%d\n", res));
2141 if (res & MUI_EventHandlerRC_Eat)
2142 return;
2144 /* Leave the loop if a different object has been activated */
2145 if (active_object != data->wd_ActiveObject)
2146 break;
2150 // event not eaten by active object, try its parents
2151 // this is to implement popup key in Popstring
2152 if (active_object == data->wd_ActiveObject)
2154 Object *current_obj = active_object;
2156 D(bug("HandleRawkey: try active object parents handlers\n"));
2157 while (current_obj != NULL)
2159 for (mn = data->wd_EHList.mlh_Head; mn->mln_Succ;
2160 mn = mn->mln_Succ)
2162 ehn = (struct MUI_EventHandlerNode *)mn;
2164 if ((ehn->ehn_Object == current_obj)
2165 && ((ehn->ehn_Events & IDCMP_RAWKEY)
2166 || (ehn->ehn_Flags & MUI_EHF_ALWAYSKEYS)))
2168 //D(bug("HandleRawkey: (active parents) invoking on "
2169 // "%p (ehn=%p) event=%p muikey=%p\n",
2170 // ehn->ehn_Object, ehn, event, muikey));
2171 res = InvokeEventHandler(ehn, event, muikey);
2172 //D(bug("HandleRawkey: (active parents) got res=%d\n",
2173 // res));
2174 if (res & MUI_EventHandlerRC_Eat)
2175 return;
2177 /* Leave the loop if a different object has been
2178 * activated */
2179 if (active_object != data->wd_ActiveObject)
2180 break;
2183 current_obj = (Object *) XGET(current_obj, MUIA_Parent);
2188 D(bug("HandleRawkey: try default object handlers\n"));
2190 /* try DefaultObject */
2191 if (data->wd_DefaultObject != NULL)
2192 get(data->wd_DefaultObject, MUIA_Disabled, &disabled);
2194 if ((data->wd_DefaultObject != NULL) && !disabled
2195 && (active_object != data->wd_DefaultObject))
2197 /* No, we only should do this if the object actually has requested
2198 * this via RequestIDCMP()! */
2199 // if (muikey != MUIKEY_NONE
2200 // && (_flags(data->wd_DefaultObject) & MADF_CANDRAW))
2201 // {
2202 // DoMethod(data->wd_DefaultObject, MUIM_HandleInput, event, muikey);
2203 // return;
2204 // }
2206 for (mn = data->wd_EHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
2208 ehn = (struct MUI_EventHandlerNode *)mn;
2210 if ((ehn->ehn_Object == data->wd_DefaultObject)
2211 && ((ehn->ehn_Events & IDCMP_RAWKEY)
2212 || (ehn->ehn_Flags & MUI_EHF_ALWAYSKEYS)))
2214 //D(bug("HandleRawkey: (default) invoking on %p (ehn=%p) "
2215 //"event=%p muikey=%p\n",
2216 //ehn->ehn_Object, ehn, event, muikey));
2217 res = InvokeEventHandler(ehn, event, muikey);
2218 //D(bug("HandleRawkey: (default) got res=%d\n", res));
2219 if (res & MUI_EventHandlerRC_Eat)
2220 return;
2226 D(bug("HandleRawkey: try other handlers\n"));
2228 // try other handlers
2229 for (mn = data->wd_EHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
2231 ehn = (struct MUI_EventHandlerNode *)mn;
2233 // skip Active and Default object as they have already been
2234 // handled
2235 if (ehn->ehn_Object == data->wd_ActiveObject
2236 || ehn->ehn_Object == data->wd_DefaultObject)
2237 continue;
2239 if (ehn->ehn_Events & IDCMP_RAWKEY)
2241 //D(bug("HandleRawkey: (others) invoking on %p (ehn=%p) "
2242 //"event=%p muikey=%p\n",
2243 //ehn->ehn_Object, ehn, event, muikey));
2244 res = InvokeEventHandler(ehn, event, MUIKEY_NONE);
2245 //D(bug("HandleRawkey: (others) got res=%d\n", res));
2246 if (res & MUI_EventHandlerRC_Eat)
2247 return;
2251 D(bug("HandleRawkey: try control chars handlers\n"));
2253 /* try Control Chars */
2254 //bug("ctrlchar, key='%c' code=0x%08lx\n", key, event->Code);
2255 if (key)
2257 for (mn = data->wd_CCList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
2259 ehn = (struct MUI_EventHandlerNode *)mn;
2261 if (ehn->ehn_Events == key)
2263 IPTR disabled = 0;
2264 LONG muikey2 = ehn->ehn_Flags;
2266 get(ehn->ehn_Object, MUIA_Disabled, &disabled);
2267 if (disabled)
2268 continue;
2270 //bug("control char\n");
2271 if (event->Code & IECODE_UP_PREFIX)
2273 /* simulate a release */
2274 if (muikey2 == MUIKEY_PRESS)
2275 muikey2 = MUIKEY_RELEASE;
2276 else
2277 return;
2280 if ((muikey2 != MUIKEY_NONE)
2281 && (_flags(ehn->ehn_Object) & MADF_CANDRAW)
2282 && (_flags(ehn->ehn_Object) & MADF_SHOWME))
2284 res = CoerceMethod
2285 (ehn->ehn_Class, ehn->ehn_Object, MUIM_HandleEvent,
2286 (IPTR) NULL, muikey2);
2287 if (res & MUI_EventHandlerRC_Eat)
2288 return;
2295 /* forward non-keystroke events to event handlers */
2296 static void HandleInputEvent(Object *win, struct MUI_WindowData *data,
2297 struct IntuiMessage *event)
2299 struct MinNode *mn;
2300 struct MUI_EventHandlerNode *ehn;
2301 struct IntuiMessage imsg_copy;
2302 ULONG res;
2303 ULONG mask = event->Class;
2305 if (mask != IDCMP_IDCMPUPDATE)
2307 imsg_copy = *event;
2308 imsg_copy.IAddress = NULL; /* be sure to trap access to that */
2309 ReplyMsg((struct Message *)event);
2310 event = &imsg_copy;
2313 if (mask == IDCMP_MOUSEMOVE)
2315 struct Window *iWin;
2316 iWin = event->IDCMPWindow;
2318 if (ContextMenuUnderPointer(data, data->wd_RootObject,
2319 event->MouseX, event->MouseY))
2321 iWin->Flags |= WFLG_RMBTRAP;
2323 else if (!data->wd_NoMenus)
2325 iWin->Flags &= ~WFLG_RMBTRAP;
2329 for (mn = data->wd_EHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
2331 ehn = (struct MUI_EventHandlerNode *)mn;
2333 if (ehn->ehn_Events & mask)
2335 IPTR disabled = 0;
2337 get(ehn->ehn_Object, MUIA_Disabled, &disabled);
2338 if (disabled)
2339 continue;
2341 res = InvokeEventHandler(ehn, event, MUIKEY_NONE);
2342 if (res & MUI_EventHandlerRC_Eat)
2343 return;
2348 if (mask == IDCMP_IDCMPUPDATE)
2349 ReplyMsg((struct Message *)event);
2353 /* process window message; this does a ReplyMsg() to the message */
2354 /* Called from application.c */
2355 void _zune_window_message(struct IntuiMessage *imsg)
2357 struct Window *iWin;
2358 Object *oWin;
2359 struct MUI_WindowData *data;
2360 BOOL handled;
2362 iWin = imsg->IDCMPWindow;
2363 oWin = (Object *) iWin->UserData;
2364 data = muiWindowData(oWin);
2366 if (data->wd_DragObject)
2368 if (!HandleDragging(oWin, data, imsg))
2369 return;
2372 handled = HandleWindowEvent(oWin, data, imsg);
2373 if (!handled)
2375 if (IDCMP_RAWKEY == imsg->Class)
2376 HandleRawkey(oWin, data, imsg);
2377 else if (IDCMP_GADGETUP == imsg->Class)
2379 #ifdef __AROS__
2380 if (ETI_MUI == ((struct Gadget *)imsg->IAddress)->GadgetID)
2382 DoMethod(_app(oWin), MUIM_Application_OpenConfigWindow);
2384 #endif
2385 if (ETI_Iconify == ((struct Gadget *)imsg->IAddress)->GadgetID)
2387 set(_app(oWin), MUIA_Application_Iconified, TRUE);
2390 else
2392 HandleInputEvent(oWin, data, imsg);
2397 /**************************************************************************/
2398 /**************************************************************************/
2400 /* code for setting MUIA_Window_RootObject */
2401 static void ChangeRootObject(struct MUI_WindowData *data, Object *obj,
2402 Object *newRoot)
2404 Object *oldRoot;
2406 ASSERT_VALID_PTR(data);
2407 ASSERT_VALID_PTR(obj);
2409 oldRoot = data->wd_RootObject;
2410 if (!(data->wd_Flags & MUIWF_OPENED))
2412 if (oldRoot)
2414 if (data->wd_ActiveObject == oldRoot)
2415 set(obj, MUIA_Window_ActiveObject,
2416 MUIV_Window_ActiveObject_None);
2417 DoMethod(oldRoot, MUIM_DisconnectParent);
2420 data->wd_RootObject = newRoot;
2421 if (newRoot)
2423 /* if window is in App tree, inform child */
2424 if (muiNotifyData(obj)->mnd_GlobalInfo)
2425 DoMethod(newRoot, MUIM_ConnectParent, (IPTR) obj);
2430 // find the ObjNode containing a pointer to the given object
2431 // currently only used for cycle chain objects
2432 static struct ObjNode *FindObjNode(struct MinList *list, Object *obj)
2434 struct ObjNode *node;
2436 ASSERT_VALID_PTR(list);
2438 if (!obj)
2439 return NULL;
2441 ASSERT_VALID_PTR(obj);
2443 for (node = (struct ObjNode *)list->mlh_Head;
2444 node->node.mln_Succ; node = (struct ObjNode *)node->node.mln_Succ)
2446 if (node->obj == obj)
2448 return node;
2451 return NULL;
2454 static Object *GetFirstActiveObject(struct MUI_WindowData *data)
2456 ASSERT_VALID_PTR(data);
2458 if (!IsListEmpty((struct List *)&data->wd_CycleChain))
2459 return ((struct ObjNode *)data->wd_CycleChain.mlh_Head)->obj;
2460 else
2461 return NULL;
2464 static Object *GetLastActiveObject(struct MUI_WindowData *data)
2466 ASSERT_VALID_PTR(data);
2468 if (!IsListEmpty((struct List *)&data->wd_CycleChain))
2469 return ((struct ObjNode *)data->wd_CycleChain.mlh_TailPred)->obj;
2470 else
2471 return NULL;
2474 typedef struct ObjNode *objnode_iterator_t(struct ObjNode *curr_node);
2476 static objnode_iterator_t NextObjNodeIterator;
2477 static objnode_iterator_t PrevObjNodeIterator;
2479 static struct ObjNode *NextObjNodeIterator(struct ObjNode *curr_node)
2481 if (curr_node->node.mln_Succ->mln_Succ)
2482 return (struct ObjNode *)curr_node->node.mln_Succ;
2483 else
2484 return NULL;
2487 static struct ObjNode *PrevObjNodeIterator(struct ObjNode *curr_node)
2489 if (curr_node->node.mln_Pred->mln_Pred)
2490 return (struct ObjNode *)curr_node->node.mln_Pred;
2491 else
2492 return NULL;
2495 static Object *GetPrevNextActiveObject(struct ObjNode *old_activenode,
2496 objnode_iterator_t node_iterator)
2498 struct ObjNode *curr_node;
2499 struct ObjNode *node;
2500 Object *obj;
2502 ASSERT_VALID_PTR(old_activenode);
2504 curr_node = old_activenode;
2505 node = NULL;
2506 obj = NULL;
2508 while (curr_node)
2510 node = node_iterator(curr_node);
2512 if (node)
2513 obj = node->obj;
2515 /* let's see if this object meets cycle requirements
2516 * (enabled & visible) */
2517 if (obj)
2519 IPTR is_disabled = 0;
2521 get(obj, MUIA_Disabled, &is_disabled);
2523 if (!is_disabled && (_flags(obj) & MADF_SHOWME))
2525 return obj;
2529 curr_node = node;
2530 obj = NULL;
2531 node = NULL;
2533 return obj;
2537 /**************************************************************************
2538 Code for setting MUIA_Window_ActiveObject
2539 Basically, it will:
2540 - remove focus drawing for current active object
2541 - find (if needed) the new active object
2542 - set data->wd_ActiveObject to the new object
2543 - draw focus around the new active object
2544 **************************************************************************/
2545 static void SetActiveObject(struct MUI_WindowData *data, Object *obj,
2546 IPTR newval)
2548 struct ObjNode *old_activenode = NULL;
2550 ASSERT_VALID_PTR(data);
2551 ASSERT_VALID_PTR(obj);
2553 D(bug("MUIC_Window:SetActiveObject(data, obj, %08lx) Active=%p\n",
2554 newval, data->wd_ActiveObject));
2556 if ((data->wd_ActiveObject != NULL)
2557 && (DoMethod(data->wd_RootObject, MUIM_FindAreaObject,
2558 (IPTR) data->wd_ActiveObject) != (IPTR) NULL))
2560 if ((IPTR) data->wd_ActiveObject != newval)
2562 old_activenode =
2563 FindObjNode(&data->wd_CycleChain, data->wd_ActiveObject);
2564 if ((data->wd_Flags & MUIWF_OBJECTGOACTIVESENT)
2565 && (_flags(data->wd_ActiveObject) & MADF_SETUP))
2567 D(bug("Deactivate=%p\n", data->wd_ActiveObject));
2568 DoMethod(data->wd_ActiveObject, MUIM_GoInactive);
2573 data->wd_ActiveObject = NULL;
2574 data->wd_Flags &= ~MUIWF_OBJECTGOACTIVESENT;
2576 switch (newval)
2578 case MUIV_Window_ActiveObject_None:
2579 break;
2581 case MUIV_Window_ActiveObject_Next:
2582 if (old_activenode != NULL)
2583 data->wd_ActiveObject = GetPrevNextActiveObject(old_activenode,
2584 NextObjNodeIterator);
2585 if (NULL == data->wd_ActiveObject)
2586 data->wd_ActiveObject = GetFirstActiveObject(data);
2587 break;
2589 case MUIV_Window_ActiveObject_Prev:
2590 if (old_activenode)
2591 data->wd_ActiveObject = GetPrevNextActiveObject(old_activenode,
2592 PrevObjNodeIterator);
2593 if (NULL == data->wd_ActiveObject)
2594 data->wd_ActiveObject = GetLastActiveObject(data);
2595 break;
2597 default:
2598 data->wd_ActiveObject = (Object *) newval;
2599 break;
2603 if (data->wd_ActiveObject != NULL
2604 && DoMethod(data->wd_RootObject, MUIM_FindAreaObject,
2605 (IPTR) data->wd_ActiveObject)
2606 && (_flags(data->wd_ActiveObject) & MADF_CANDRAW))
2608 D(bug("Activate=%p\n", data->wd_ActiveObject));
2609 DoMethod(data->wd_ActiveObject, MUIM_GoActive);
2610 data->wd_Flags |= MUIWF_OBJECTGOACTIVESENT;
2615 static BOOL InBox(struct IBox *box, WORD x, WORD y)
2617 return x >= box->Left && x < box->Left + box->Width
2618 && y >= box->Top && y < box->Top + box->Height;
2623 * Pass on an AppMessage to all objects that it landed on.
2625 static void ForwardAppMessage(struct MUI_WindowData *data, Object *child,
2626 struct AppMessage *appmsg)
2628 WORD x = appmsg->am_MouseX, y = appmsg->am_MouseY;
2629 Object *cstate;
2630 struct List *children = NULL;
2632 ASSERT_VALID_PTR(data);
2633 ASSERT_VALID_PTR(child);
2635 set(child, MUIA_AppMessage, appmsg);
2637 children = (struct List *)XGET(child, MUIA_Group_ChildList);
2639 if (children != NULL)
2641 cstate = (Object *) children->lh_Head;
2642 while ((child = NextObject(&cstate)))
2644 if (InBox(&muiAreaData(child)->mad_Box, x, y))
2646 ForwardAppMessage(data, child, appmsg);
2654 * calculate real dimensions from programmer requirements.
2655 * may be overridden by user settings if MUIA_Window_ID is set.
2657 /* MUIV_Window_Height_Screen and MUIV_Window_Height_Visible
2658 * are not handled yet, as their Width couterparts.
2660 static void WindowSelectDimensions(struct MUI_WindowData *data)
2662 if (!data->wd_Width)
2664 if (data->wd_ReqWidth > 0)
2665 data->wd_Width = data->wd_ReqWidth;
2666 else if (data->wd_ReqWidth == MUIV_Window_Width_Default)
2667 data->wd_Width = data->wd_MinMax.DefWidth;
2668 else if (_between(MUIV_Window_Width_MinMax(100),
2669 data->wd_ReqWidth, MUIV_Window_Width_MinMax(0)))
2671 data->wd_Width = data->wd_MinMax.MinWidth
2672 - data->wd_ReqWidth
2673 * (data->wd_MinMax.MaxWidth - data->wd_MinMax.MinWidth);
2675 else if (_between(MUIV_Window_Width_Screen(100),
2676 data->wd_ReqWidth, MUIV_Window_Width_Screen(0)))
2678 data->wd_Width = data->wd_RenderInfo.mri_ScreenWidth
2679 * (-(data->wd_ReqWidth + 200)) / 100;
2681 else if (_between(MUIV_Window_Width_Visible(100),
2682 data->wd_ReqWidth, MUIV_Window_Width_Visible(0)))
2684 data->wd_Width = data->wd_RenderInfo.mri_ScreenWidth
2685 * (-(data->wd_ReqWidth + 100)) / 100;
2688 if (data->wd_ReqHeight > 0)
2689 data->wd_Height = data->wd_ReqHeight;
2690 else if (data->wd_ReqHeight == MUIV_Window_Height_Default)
2691 data->wd_Height = data->wd_MinMax.DefHeight;
2692 else if (_between(MUIV_Window_Height_MinMax(100),
2693 data->wd_ReqHeight, MUIV_Window_Height_MinMax(0)))
2695 data->wd_Height = data->wd_MinMax.MinHeight
2696 - data->wd_ReqHeight
2697 * (data->wd_MinMax.MaxHeight - data->wd_MinMax.MinHeight);
2699 else if (_between(MUIV_Window_Height_Screen(100),
2700 data->wd_ReqHeight, MUIV_Window_Height_Screen(0)))
2702 struct Screen *scr;
2703 int height;
2705 scr = data->wd_RenderInfo.mri_Screen;
2707 height =
2708 scr->Height - data->wd_RenderInfo.mri_BorderTop -
2709 data->wd_RenderInfo.mri_BorderBottom;
2711 /* This is new to Zune: If TopEdge Delta is requested
2712 * the screenheight doesn't cover the barlayer */
2713 if (data->wd_Y <= MUIV_Window_TopEdge_Delta(0))
2714 height -= scr->BarHeight + 1;
2716 data->wd_Height = height * (-(data->wd_ReqHeight + 200)) / 100;
2718 else if (_between(MUIV_Window_Height_Visible(100),
2719 data->wd_ReqHeight, MUIV_Window_Height_Visible(0)))
2721 data->wd_Height = data->wd_RenderInfo.mri_ScreenHeight
2722 * (-(data->wd_ReqHeight + 100)) / 100;
2725 /* scaled */
2726 if (data->wd_ReqWidth == MUIV_Window_Width_Scaled)
2727 data->wd_Width = data->wd_Height * data->wd_MinMax.MinWidth
2728 / data->wd_MinMax.MinHeight;
2729 else if (data->wd_ReqHeight == MUIV_Window_Width_Scaled)
2730 data->wd_Height = data->wd_Width * data->wd_MinMax.MinHeight
2731 / data->wd_MinMax.MinWidth;
2733 data->wd_Width = CLAMP(data->wd_Width, data->wd_MinMax.MinWidth,
2734 data->wd_MinMax.MaxWidth);
2735 data->wd_Height = CLAMP(data->wd_Height, data->wd_MinMax.MinHeight,
2736 data->wd_MinMax.MaxHeight);
2740 /**************************************************************************
2741 OM_NEW
2742 **************************************************************************/
2743 IPTR Window__OM_NEW(struct IClass *cl, Object *obj, struct opSet *msg)
2745 struct MUI_WindowData *data;
2746 struct TagItem *tags;
2747 struct TagItem *tag;
2749 obj = (Object *) DoSuperMethodA(cl, obj, (Msg) msg);
2750 if (!obj)
2751 return FALSE;
2753 /* Initial local instance data */
2754 data = INST_DATA(cl, obj);
2756 data->wd_MemoryPool = CreatePool(0, 4096, 2048);
2757 if (NULL == data->wd_MemoryPool)
2759 CoerceMethod(cl, obj, OM_DISPOSE);
2760 return (IPTR) NULL;
2763 data->wd_RenderInfo.mri_WindowObject = obj;
2765 NewList((struct List *)&(data->wd_EHList));
2766 NewList((struct List *)&(data->wd_CCList));
2767 NewList((struct List *)&(data->wd_CycleChain));
2768 NewList((struct List *)&(data->wd_IDList));
2770 data->wd_CrtFlags = WFLG_SIZEGADGET | WFLG_DRAGBAR | WFLG_DEPTHGADGET
2771 | WFLG_CLOSEGADGET | WFLG_SIMPLE_REFRESH
2772 | WFLG_REPORTMOUSE | WFLG_NEWLOOKMENUS;
2773 data->wd_ZoomGadget = TRUE;
2774 data->wd_Events = GetDefaultEvents();
2775 data->wd_ActiveObject = NULL;
2776 data->wd_ID = 0;
2777 data->wd_ReqHeight = MUIV_Window_Height_Default;
2778 data->wd_ReqWidth = MUIV_Window_Width_Default;
2779 data->wd_RootObject = NULL;
2780 data->wd_DefaultObject = NULL;
2782 /* alternate dimensions */
2783 /* no change in coordinates */
2784 data->wd_AltDim.Top = MUIV_Window_AltTopEdge_NoChange;
2785 data->wd_AltDim.Left = MUIV_Window_AltLeftEdge_NoChange;
2786 /* default to min size */
2787 data->wd_AltDim.Width = MUIV_Window_AltWidth_MinMax(0);
2788 data->wd_AltDim.Height = MUIV_Window_AltHeight_MinMax(0);
2789 data->wd_X = MUIV_Window_LeftEdge_Centered;
2790 data->wd_Y = MUIV_Window_TopEdge_Centered;
2791 data->wd_DisabledKeys = 0L;
2792 data->wd_HelpTicker = BUBBLEHELP_TICKER_FIRST;
2794 /* parse initial taglist */
2796 for (tags = msg->ops_AttrList; (tag = NextTagItem(&tags));)
2798 switch (tag->ti_Tag)
2800 case MUIA_Window_EraseArea:
2801 _handle_bool_tag(data->wd_Flags, tag->ti_Data, MUIWF_ERASEAREA);
2802 break;
2804 case MUIA_Window_ToolBox:
2805 _handle_bool_tag(data->wd_Flags, tag->ti_Data, MUIWF_TOOLBOX);
2806 break;
2808 case MUIA_Window_CloseGadget:
2809 _handle_bool_tag(data->wd_CrtFlags, tag->ti_Data,
2810 WFLG_CLOSEGADGET);
2811 break;
2813 case MUIA_Window_SizeGadget:
2814 _handle_bool_tag(data->wd_CrtFlags, tag->ti_Data,
2815 WFLG_SIZEGADGET);
2816 break;
2818 case MUIA_Window_ZoomGadget:
2819 data->wd_ZoomGadget = tag->ti_Data;
2820 break;
2822 case MUIA_Window_Backdrop:
2823 _handle_bool_tag(data->wd_CrtFlags, tag->ti_Data,
2824 WFLG_BACKDROP);
2825 break;
2827 case MUIA_Window_Borderless:
2828 _handle_bool_tag(data->wd_CrtFlags, tag->ti_Data,
2829 WFLG_BORDERLESS);
2830 break;
2832 case MUIA_Window_DepthGadget:
2833 _handle_bool_tag(data->wd_CrtFlags, tag->ti_Data,
2834 WFLG_DEPTHGADGET);
2835 break;
2837 case MUIA_Window_DragBar:
2838 _handle_bool_tag(data->wd_CrtFlags, tag->ti_Data, WFLG_DRAGBAR);
2839 break;
2841 case MUIA_Window_SizeRight:
2842 _handle_bool_tag(data->wd_CrtFlags, tag->ti_Data,
2843 WFLG_SIZEBRIGHT);
2844 break;
2846 case MUIA_Window_Height:
2847 data->wd_ReqHeight = (LONG) tag->ti_Data;
2848 break;
2850 case MUIA_Window_Width:
2851 data->wd_ReqWidth = (LONG) tag->ti_Data;
2852 break;
2854 case MUIA_Window_ID:
2855 set(obj, MUIA_Window_ID, tag->ti_Data);
2856 break;
2858 case MUIA_Window_IsSubWindow:
2859 _handle_bool_tag(data->wd_Flags, tag->ti_Data,
2860 MUIWF_ISSUBWINDOW);
2861 break;
2863 case MUIA_Window_Title:
2864 set(obj, MUIA_Window_Title, tag->ti_Data);
2865 break;
2867 case MUIA_Window_ScreenTitle:
2868 set(obj, MUIA_Window_ScreenTitle, tag->ti_Data);
2869 break;
2871 case MUIA_Window_Activate:
2872 _handle_bool_tag(data->wd_Flags, !tag->ti_Data,
2873 MUIWF_DONTACTIVATE);
2874 break;
2876 case MUIA_Window_DefaultObject:
2877 set(obj, MUIA_Window_DefaultObject, tag->ti_Data);
2878 break;
2880 case MUIA_Window_Menustrip:
2881 data->wd_ChildMenustrip = (Object *) tag->ti_Data;
2882 break;
2884 case MUIA_Window_NoMenus:
2885 data->wd_NoMenus = (BOOL) tag->ti_Data;
2886 break;
2888 case MUIA_Window_RootObject:
2889 if (!tag->ti_Data)
2891 CoerceMethod(cl, obj, OM_DISPOSE);
2892 return 0;
2894 set(obj, MUIA_Window_RootObject, tag->ti_Data);
2895 break;
2897 case MUIA_Window_AltHeight:
2898 data->wd_AltDim.Height = (WORD) tag->ti_Data;
2899 break;
2901 case MUIA_Window_AltWidth:
2902 data->wd_AltDim.Width = (WORD) tag->ti_Data;
2903 break;
2905 case MUIA_Window_AltLeftEdge:
2906 data->wd_AltDim.Left = (WORD) tag->ti_Data;
2907 break;
2909 case MUIA_Window_AltTopEdge:
2910 data->wd_AltDim.Top = (WORD) tag->ti_Data;
2911 break;
2913 case MUIA_Window_AppWindow:
2914 _handle_bool_tag(data->wd_Flags, tag->ti_Data,
2915 MUIWF_ISAPPWINDOW);
2916 break;
2918 case MUIA_Window_LeftEdge:
2919 data->wd_X = tag->ti_Data;
2920 break;
2922 case MUIA_Window_TopEdge:
2923 data->wd_Y = tag->ti_Data;
2924 break;
2926 case MUIA_Window_UseBottomBorderScroller:
2927 _handle_bool_tag(data->wd_Flags, tag->ti_Data,
2928 MUIWF_USEBOTTOMSCROLLER);
2929 break;
2931 case MUIA_Window_UseRightBorderScroller:
2932 _handle_bool_tag(data->wd_Flags, tag->ti_Data,
2933 MUIWF_USERIGHTSCROLLER);
2934 break;
2936 case MUIA_Window_DisableKeys:
2937 data->wd_DisabledKeys = tag->ti_Data;
2938 break;
2940 case MUIA_Window_RefWindow:
2941 data->wd_RefWindow = (Object *) tag->ti_Data;
2942 break;
2944 case MUIA_Window_Screen:
2945 data->wd_UserScreen = (struct Screen *)tag->ti_Data;
2946 break;
2948 case MUIA_Window_PublicScreen:
2949 data->wd_UserPublicScreen = (STRPTR) tag->ti_Data;
2950 break;
2954 /* D(bug("muimaster.library/window.c: Window Object created at " */
2955 /* "0x%lx back=%lx\n", */
2956 /* obj,data->wd_Background)); */
2958 return (IPTR) obj;
2961 /**************************************************************************
2962 OM_DISPOSE
2963 **************************************************************************/
2964 IPTR Window__OM_DISPOSE(struct IClass *cl, Object *obj, Msg msg)
2966 struct MUI_WindowData *data = INST_DATA(cl, obj);
2968 /* D(bug("Window_Dispose(%p)\n", obj)); */
2970 #if 0
2971 /* We no longer clear muiGlobalInfo() during disconnections, so
2972 this can cause problems (remove object which is already removed).
2973 Furthermore AFAIK it is not legal to dispose a window object
2974 which is still ocnnected to the application object, anyway. */
2976 if (muiGlobalInfo(obj) && _app(obj))
2978 /* D(bug(" Window_Dispose(%p) : calling app->OM_REMMEMBER\n", obj)); */
2979 DoMethod(_app(obj), OM_REMMEMBER, (IPTR) obj);
2981 #endif
2983 if (data->wd_RootObject)
2984 MUI_DisposeObject(data->wd_RootObject);
2986 if (data->wd_ChildMenustrip)
2987 MUI_DisposeObject(data->wd_ChildMenustrip);
2989 if (data->wd_Title)
2990 FreeVec(data->wd_Title);
2992 if (data->wd_ScreenTitle)
2993 FreeVec(data->wd_ScreenTitle);
2995 DeletePool(data->wd_MemoryPool);
2997 /* D(bug(" Window_Dispose(%p) : calling supermethod\n", obj)); */
2998 return DoSuperMethodA(cl, obj, msg);
3001 static ULONG WindowOpen(struct IClass *cl, Object *obj);
3002 static ULONG WindowClose(struct IClass *cl, Object *obj);
3004 /**************************************************************************
3005 OM_SET
3006 **************************************************************************/
3007 IPTR Window__OM_SET(struct IClass *cl, Object *obj, struct opSet *msg)
3009 struct MUI_WindowData *data = INST_DATA(cl, obj);
3010 struct TagItem *tags = msg->ops_AttrList;
3011 struct TagItem *tag;
3013 while ((tag = NextTagItem(&tags)) != NULL)
3015 switch (tag->ti_Tag)
3017 case MUIA_AppMessage:
3018 ForwardAppMessage(data, data->wd_RootObject,
3019 (struct AppMessage *)tag->ti_Data);
3020 break;
3022 case MUIA_Window_Activate:
3023 if (data->wd_RenderInfo.mri_Window)
3025 if (tag->ti_Data && !(data->wd_Flags & MUIWF_ACTIVE))
3027 ActivateWindow(data->wd_RenderInfo.mri_Window);
3028 _handle_bool_tag(data->wd_Flags, tag->ti_Data,
3029 MUIWF_ACTIVE);
3032 else
3033 _handle_bool_tag(data->wd_Flags, !tag->ti_Data,
3034 MUIWF_DONTACTIVATE);
3035 break;
3037 case MUIA_Window_ActiveObject:
3038 /* D(bug("MUIA_Window_ActiveObject %ld (%p)\n", */
3039 /* tag->ti_Data, tag->ti_Data)); */
3040 SetActiveObject(data, obj, tag->ti_Data);
3041 break;
3043 case MUIA_Window_DefaultObject:
3044 data->wd_DefaultObject = (APTR) tag->ti_Data;
3045 break;
3047 case MUIA_Window_ID:
3048 data->wd_ID = tag->ti_Data;
3049 break;
3051 case MUIA_Window_IsSubWindow:
3052 _handle_bool_tag(data->wd_Flags, tag->ti_Data,
3053 MUIWF_ISSUBWINDOW);
3054 break;
3056 case MUIA_Window_Open:
3057 if (tag->ti_Data)
3059 if (data->wd_Flags & MUIWF_HIDDEN)
3060 data->wd_Flags |= MUIWF_OPENONUNHIDE;
3061 else if (!(data->wd_Flags & MUIWF_OPENED))
3062 WindowOpen(cl, obj);
3063 else
3065 DoMethod(obj, MUIM_Window_ToFront);
3066 set(obj, MUIA_Window_Activate, TRUE);
3069 else if (data->wd_Flags & MUIWF_HIDDEN)
3070 data->wd_Flags &= ~MUIWF_OPENONUNHIDE;
3071 else if (data->wd_Flags & MUIWF_OPENED)
3072 WindowClose(cl, obj);
3073 break;
3075 case MUIA_ShowMe: /* PRIVATE *abuse* of the Area's ShowMe attr */
3076 if (tag->ti_Data)
3078 /* Deiconify */
3080 if (data->wd_Flags & MUIWF_HIDDEN)
3082 data->wd_Flags &= ~MUIWF_HIDDEN;
3084 if (data->wd_Flags & MUIWF_OPENONUNHIDE)
3086 data->wd_Flags &= ~MUIWF_OPENONUNHIDE;
3087 set(obj, MUIA_Window_Open, TRUE);
3091 else
3093 /* Iconify */
3095 if (data->wd_Flags & MUIWF_OPENED)
3097 data->wd_Flags |= MUIWF_OPENONUNHIDE;
3099 set(obj, MUIA_Window_Open, FALSE);
3102 data->wd_Flags |= MUIWF_HIDDEN;
3104 break;
3106 case MUIA_Window_RootObject:
3107 ChangeRootObject(data, obj, (Object *) tag->ti_Data);
3108 break;
3110 case MUIA_Window_Title:
3111 if (data->wd_Title)
3112 FreeVec(data->wd_Title);
3113 data->wd_Title = StrDup((STRPTR) tag->ti_Data);
3114 if (data->wd_RenderInfo.mri_Window)
3115 SetWindowTitles(data->wd_RenderInfo.mri_Window,
3116 data->wd_Title, (CONST_STRPTR) ~ 0);
3117 break;
3119 case MUIA_Window_ScreenTitle:
3120 if (data->wd_ScreenTitle)
3121 FreeVec(data->wd_ScreenTitle);
3122 data->wd_ScreenTitle = StrDup((STRPTR) tag->ti_Data);
3123 if (data->wd_RenderInfo.mri_Window)
3124 SetWindowTitles(data->wd_RenderInfo.mri_Window,
3125 (CONST_STRPTR) ~ 0, data->wd_ScreenTitle);
3126 break;
3128 case MUIA_Window_NoMenus:
3129 data->wd_NoMenus = (BOOL) tag->ti_Data;
3130 if (data->wd_RenderInfo.mri_Window)
3132 if (data->wd_NoMenus)
3133 data->wd_RenderInfo.mri_Window->Flags |= WFLG_RMBTRAP;
3134 else
3135 data->wd_RenderInfo.mri_Window->Flags &= ~WFLG_RMBTRAP;
3137 break;
3139 case MUIA_Window_UseBottomBorderScroller:
3140 _handle_bool_tag(data->wd_Flags, tag->ti_Data,
3141 MUIWF_USEBOTTOMSCROLLER);
3142 break;
3144 case MUIA_Window_UseRightBorderScroller:
3145 _handle_bool_tag(data->wd_Flags, tag->ti_Data,
3146 MUIWF_USERIGHTSCROLLER);
3147 break;
3149 case MUIA_Window_DisableKeys:
3150 data->wd_DisabledKeys = tag->ti_Data;
3151 break;
3153 case MUIA_Window_RefWindow:
3154 data->wd_RefWindow = (Object *) tag->ti_Data;
3155 break;
3157 case MUIA_Window_LeftEdge:
3158 data->wd_X = tag->ti_Data;
3159 break;
3161 case MUIA_Window_TopEdge:
3162 data->wd_Y = tag->ti_Data;
3163 break;
3165 case MUIA_Window_Width:
3166 data->wd_ReqWidth = (LONG) tag->ti_Data;
3167 data->wd_Width = 0; /* otherwise windowselectdimensions()
3168 * ignores ReqWidth */
3169 break;
3171 case MUIA_Window_Height:
3172 data->wd_ReqHeight = (LONG) tag->ti_Data;
3173 data->wd_Height = 0;
3174 break;
3176 case MUIA_Window_Screen:
3177 data->wd_UserScreen = (struct Screen *)tag->ti_Data;
3178 break;
3180 case MUIA_Window_PublicScreen:
3181 data->wd_UserPublicScreen = (STRPTR) tag->ti_Data;
3182 break;
3184 case MUIA_Window_Sleep:
3185 if (tag->ti_Data)
3187 data->wd_SleepCount++;
3188 if (data->wd_RenderInfo.mri_Window
3189 && (data->wd_SleepCount == 1))
3191 SetWindowPointer
3192 (data->wd_RenderInfo.mri_Window,
3193 WA_BusyPointer, TRUE,
3194 WA_PointerDelay, TRUE, TAG_DONE);
3195 // FIXME: how to disable event handling?
3198 else
3200 data->wd_SleepCount--;
3201 if (data->wd_RenderInfo.mri_Window
3202 && (data->wd_SleepCount == 0))
3204 SetWindowPointerA(data->wd_RenderInfo.mri_Window, NULL);
3207 break;
3212 return DoSuperMethodA(cl, obj, (Msg) msg);
3215 /**************************************************************************
3216 OM_GET
3217 **************************************************************************/
3218 IPTR Window__OM_GET(struct IClass *cl, Object *obj, struct opGet *msg)
3220 #define STORE *(msg->opg_Storage)
3222 struct MUI_WindowData *data = INST_DATA(cl, obj);
3224 STORE = (IPTR) 0;
3226 switch (msg->opg_AttrID)
3228 case MUIA_Window_Activate:
3229 STORE =
3230 (data->wd_Flags & (MUIWF_ACTIVE | MUIWF_OPENED)) ==
3231 (MUIWF_ACTIVE | MUIWF_OPENED);
3232 return TRUE;
3234 case MUIA_Window_Window:
3235 STORE = (IPTR) data->wd_RenderInfo.mri_Window;
3236 return TRUE;
3238 case MUIA_Window_Screen:
3239 STORE = (IPTR) data->wd_RenderInfo.mri_Screen;
3240 return TRUE;
3242 case MUIA_Window_PublicScreen:
3243 STORE = (IPTR) data->wd_UserPublicScreen;
3244 return TRUE;
3246 case MUIA_Window_ActiveObject:
3247 if ((data->wd_ActiveObject != NULL)
3248 && (DoMethod(data->wd_RootObject, MUIM_FindAreaObject,
3249 (IPTR) data->wd_ActiveObject) != (IPTR) NULL))
3250 STORE = (IPTR) data->wd_ActiveObject;
3251 else
3252 STORE = (IPTR) NULL;
3253 return TRUE;
3255 case MUIA_Window_CloseRequest:
3256 STORE = FALSE;
3257 return TRUE;
3259 case MUIA_Window_DefaultObject:
3260 STORE = (IPTR) data->wd_DefaultObject;
3261 return TRUE;
3263 case MUIA_Window_DisableKeys:
3264 STORE = data->wd_DisabledKeys;
3265 return TRUE;
3267 case MUIA_Window_Height:
3268 STORE = (IPTR) data->wd_Height;
3269 return TRUE;
3271 case MUIA_Window_ID:
3272 STORE = data->wd_ID;
3273 return TRUE;
3275 case MUIA_Window_IsSubWindow:
3276 STORE = (data->wd_Flags & MUIWF_ISSUBWINDOW) == MUIWF_ISSUBWINDOW;
3277 return TRUE;
3279 case MUIA_Window_LeftEdge:
3280 if (data->wd_RenderInfo.mri_Window)
3281 STORE = (IPTR) data->wd_RenderInfo.mri_Window->LeftEdge;
3282 else
3283 STORE = 0;
3284 return TRUE;
3286 case MUIA_Window_Open:
3287 STORE = (data->wd_Flags & MUIWF_OPENED) == MUIWF_OPENED;
3288 return TRUE;
3290 case MUIA_Window_RootObject:
3291 STORE = (IPTR) data->wd_RootObject;
3292 return TRUE;
3294 case MUIA_Window_ScreenTitle:
3295 STORE = (IPTR) data->wd_ScreenTitle;
3296 return TRUE;
3298 case MUIA_Window_Title:
3299 STORE = (IPTR) data->wd_Title;
3300 return TRUE;
3302 case MUIA_Window_TopEdge:
3303 if (data->wd_RenderInfo.mri_Window)
3304 STORE = (IPTR) data->wd_RenderInfo.mri_Window->TopEdge;
3305 else
3306 STORE = (IPTR) 0;
3307 return (TRUE);
3309 case MUIA_Window_Width:
3310 STORE = (IPTR) data->wd_Width;
3311 return TRUE;
3313 case MUIA_Window_Menustrip:
3314 STORE = (IPTR) data->wd_ChildMenustrip;
3315 return TRUE;
3317 case MUIA_Window_Sleep:
3318 STORE = data->wd_SleepCount ? TRUE : FALSE;
3319 return TRUE;
3321 case MUIA_Version:
3322 STORE = __version;
3323 return TRUE;
3325 case MUIA_Revision:
3326 STORE = __revision;
3327 return TRUE;
3330 return DoSuperMethodA(cl, obj, (Msg) msg);
3331 #undef STORE
3335 * MUIM_FindUData : tests if the MUIA_UserData of the object
3336 * contains the given <udata> and returns the object pointer in this case.
3338 IPTR Window__MUIM_FindUData(struct IClass *cl, Object *obj,
3339 struct MUIP_FindUData *msg)
3341 struct MUI_WindowData *data = INST_DATA(cl, obj);
3343 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
3344 return (IPTR) obj;
3346 if (data->wd_RootObject)
3347 return DoMethodA(data->wd_RootObject, (Msg) msg);
3349 return 0;
3354 * MUIM_GetUData : This method tests if the MUIA_UserData of the object
3355 * contains the given <udata> and gets <attr> to <storage> for itself
3356 * in this case.
3358 IPTR Window__MUIM_GetUData(struct IClass *cl, Object *obj,
3359 struct MUIP_GetUData *msg)
3361 struct MUI_WindowData *data = INST_DATA(cl, obj);
3363 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
3365 get(obj, msg->attr, msg->storage);
3366 return TRUE;
3369 if (data->wd_RootObject)
3370 return DoMethodA(data->wd_RootObject, (Msg) msg);
3372 return FALSE;
3377 * MUIM_SetUData : This method tests if the MUIA_UserData of the object
3378 * contains the given <udata> and sets <attr> to <val> for itself in this case.
3380 IPTR Window__MUIM_SetUData(struct IClass *cl, Object *obj,
3381 struct MUIP_SetUData *msg)
3383 struct MUI_WindowData *data = INST_DATA(cl, obj);
3385 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
3386 set(obj, msg->attr, msg->val);
3388 if (data->wd_RootObject)
3389 DoMethodA(data->wd_RootObject, (Msg) msg);
3391 return TRUE;
3396 * MUIM_SetUDataOnce : This method tests if the MUIA_UserData of the object
3397 * contains the given <udata> and sets <attr> to <val> for itself in this case.
3399 IPTR Window__MUIM_SetUDataOnce(struct IClass *cl, Object *obj,
3400 struct MUIP_SetUDataOnce *msg)
3402 struct MUI_WindowData *data = INST_DATA(cl, obj);
3404 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
3406 set(obj, msg->attr, msg->val);
3407 return TRUE;
3410 if (data->wd_RootObject)
3411 return DoMethodA(data->wd_RootObject, (Msg) msg);
3413 return FALSE;
3416 /**************************************************************************
3417 Called by Application (parent) object whenever this object is added.
3418 init GlobalInfo
3419 **************************************************************************/
3420 IPTR Window__MUIM_ConnectParent(struct IClass *cl, Object *obj,
3421 struct MUIP_ConnectParent *msg)
3423 struct MUI_WindowData *data = INST_DATA(cl, obj);
3425 if (!DoSuperMethodA(cl, obj, (Msg) msg))
3426 return 0;
3428 if (data->wd_RootObject)
3429 DoMethod(data->wd_RootObject, MUIM_ConnectParent, (IPTR) obj);
3431 if (data->wd_ChildMenustrip)
3432 DoMethod(data->wd_ChildMenustrip, MUIM_ConnectParent, (IPTR) obj);
3434 return TRUE;
3438 /**************************************************************************
3439 called by parent object
3440 **************************************************************************/
3441 IPTR Window__MUIM_DisconnectParent(struct IClass *cl, Object *obj,
3442 struct MUIP_DisconnectParent *msg)
3444 struct MUI_WindowData *data = INST_DATA(cl, obj);
3446 /* D(bug("Window_DisconnectParent(%p) : muiGlobalInfo=%p\n", */
3447 /* muiGlobalInfo(obj))); */
3448 if (muiGlobalInfo(obj))
3450 /* Close the window before disconnecting all the childs */
3451 if ((data->wd_Flags & MUIWF_OPENED))
3453 /* D(bug(" Window_DisconnectParent(%p) : closing window\n", */
3454 /* muiGlobalInfo(obj))); */
3455 set(obj, MUIA_Window_Open, FALSE);
3457 if (data->wd_ChildMenustrip)
3458 DoMethod(data->wd_ChildMenustrip, MUIM_DisconnectParent,
3459 (IPTR) obj);
3461 if (data->wd_RootObject)
3462 DoMethodA(data->wd_RootObject, (Msg) msg);
3464 /* D(bug(" Window_DisconnectParent(%p) : calling supermethod\n", */
3465 /* muiGlobalInfo(obj))); */
3466 return DoSuperMethodA(cl, obj, (Msg) msg);
3468 else
3470 return 0;
3474 static void SetRootObjInnerSpacing(Object *obj,
3475 struct MUI_WindowData *data)
3477 UWORD wd_innerLeft, wd_innerRight, wd_innerTop, wd_innerBottom;
3479 if (data->wd_CrtFlags & WFLG_BORDERLESS)
3481 wd_innerLeft = 0;
3482 wd_innerRight = 0;
3483 wd_innerTop = 0;
3484 wd_innerBottom = 0;
3486 else
3488 wd_innerLeft = muiGlobalInfo(obj)->mgi_Prefs->window_inner_left;
3489 wd_innerRight = muiGlobalInfo(obj)->mgi_Prefs->window_inner_right;
3490 wd_innerTop = muiGlobalInfo(obj)->mgi_Prefs->window_inner_top;
3491 wd_innerBottom = muiGlobalInfo(obj)->mgi_Prefs->window_inner_bottom;
3494 if (!(muiAreaData(data->wd_RootObject)->mad_Flags & MADF_INNERLEFT))
3496 muiAreaData(data->wd_RootObject)->mad_InnerLeft = wd_innerLeft;
3499 if (!(muiAreaData(data->wd_RootObject)->mad_Flags & MADF_INNERTOP))
3501 muiAreaData(data->wd_RootObject)->mad_InnerTop = wd_innerTop;
3504 if (!(muiAreaData(data->wd_RootObject)->mad_Flags & MADF_INNERRIGHT))
3506 muiAreaData(data->wd_RootObject)->mad_InnerRight = wd_innerRight;
3509 if (!(muiAreaData(data->wd_RootObject)->mad_Flags & MADF_INNERBOTTOM))
3511 muiAreaData(data->wd_RootObject)->mad_InnerBottom = wd_innerBottom;
3516 * Called before window is opened or resized. It determines its bounds,
3517 * so you can call WindowSelectDimensions() to find the final dims.
3519 static void WindowMinMax(Object *obj, struct MUI_WindowData *data)
3521 SetRootObjInnerSpacing(obj, data);
3522 /* inquire about sizes */
3523 DoMethod(data->wd_RootObject, MUIM_AskMinMax, (IPTR) & data->wd_MinMax);
3524 /* D(bug("*** root minmax = %ld,%ld => %ld,%ld\n", */
3525 /* data->wd_MinMax.MinWidth, */
3526 /* data->wd_MinMax.MinHeight, */
3527 /* data->wd_MinMax.MaxWidth, data->wd_MinMax.MaxHeight)); */
3528 __area_finish_minmax(data->wd_RootObject, &data->wd_MinMax);
3529 /* D(bug("*** root minmax2 = %ld,%ld => %ld,%ld\n", */
3530 /* data->wd_MinMax.MinWidth, */
3531 /* data->wd_MinMax.MinHeight, */
3532 /* data->wd_MinMax.MaxWidth, data->wd_MinMax.MaxHeight)); */
3536 static void InstallBackbuffer(struct IClass *cl, Object *obj)
3538 struct MUI_WindowData *data = INST_DATA(cl, obj);
3539 #if 0
3540 struct Window *win = data->wd_RenderInfo.mri_Window;
3542 data->wd_RenderInfo.mri_BufferBM =
3543 AllocBitMap(win->Width, win->Height, win->RPort->BitMap->Depth,
3544 0, win->RPort->BitMap);
3545 #endif
3546 if (data->wd_RenderInfo.mri_BufferBM)
3548 /* D(bug("install_backbuffer : allocated bitmap %dx%dx%d " */
3549 /* "with friend %p\n", */
3550 /* win->Width, win->Height, win->RPort->BitMap->Depth, */
3551 /* win->RPort->BitMap)); */
3552 InitRastPort(&data->wd_RenderInfo.mri_BufferRP);
3553 data->wd_RenderInfo.mri_BufferRP.BitMap =
3554 data->wd_RenderInfo.mri_BufferBM;
3558 static void DeinstallBackbuffer(struct IClass *cl, Object *obj)
3560 struct MUI_WindowData *data = INST_DATA(cl, obj);
3562 if (data->wd_RenderInfo.mri_BufferBM)
3564 DeinitRastPort(&data->wd_RenderInfo.mri_BufferRP);
3565 FreeBitMap(data->wd_RenderInfo.mri_BufferBM);
3566 data->wd_RenderInfo.mri_BufferBM = NULL;
3571 * Called after window is opened or resized.
3572 * An expose event is already queued, it will trigger
3573 * MUIM_Draw for us when going back to main loop.
3575 static void WindowShow(struct IClass *cl, Object *obj)
3577 struct MUI_WindowData *data = INST_DATA(cl, obj);
3578 struct Window *win = data->wd_RenderInfo.mri_Window;
3579 /* D(bug("WindowShow %s %d\n", __FILE__, __LINE__)); */
3581 _left(data->wd_RootObject) = win->BorderLeft;
3582 _top(data->wd_RootObject) = win->BorderTop;
3583 _width(data->wd_RootObject) = data->wd_Width;
3584 _height(data->wd_RootObject) = data->wd_Height;
3586 DoMethod(data->wd_RootObject, MUIM_Layout);
3588 ShowRenderInfo(&data->wd_RenderInfo);
3589 /* D(bug("zune_imspec_show %s %d\n", __FILE__, __LINE__)); */
3590 zune_imspec_show(data->wd_Background, obj);
3591 DoShowMethod(data->wd_RootObject);
3594 static ULONG WindowOpen(struct IClass *cl, Object *obj)
3596 struct MUI_WindowData *data = INST_DATA(cl, obj);
3598 if (!data->wd_RootObject)
3599 return FALSE;
3601 if (!DoMethod(obj, MUIM_Window_Setup))
3602 return FALSE;
3604 /* I got display info, so calculate your display dependant data */
3605 if (!DoSetupMethod(data->wd_RootObject, &data->wd_RenderInfo))
3607 DoMethod(obj, MUIM_Window_Cleanup);
3608 return FALSE;
3611 /* inquire about sizes */
3612 WindowMinMax(obj, data);
3613 WindowSelectDimensions(data);
3615 /* Decide which menustrip should be used */
3616 if (!data->wd_ChildMenustrip)
3617 get(_app(obj), MUIA_Application_Menustrip, &data->wd_Menustrip);
3618 else
3619 data->wd_Menustrip = data->wd_ChildMenustrip;
3621 /* open window here ... */
3622 if (!DisplayWindow(obj, data))
3624 /* free display dependant data */
3625 data->wd_Menustrip = NULL;
3626 DoMethod(data->wd_RootObject, MUIM_Cleanup);
3627 DoMethod(obj, MUIM_Window_Cleanup);
3628 return FALSE;
3631 InstallBackbuffer(cl, obj);
3633 data->wd_Flags |= MUIWF_OPENED;
3635 WindowShow(cl, obj);
3638 LONG left, top, width, height;
3640 left = data->wd_RenderInfo.mri_Window->BorderLeft;
3641 top = data->wd_RenderInfo.mri_Window->BorderTop,
3642 width = data->wd_RenderInfo.mri_Window->Width
3643 - data->wd_RenderInfo.mri_Window->BorderRight - left;
3644 height = data->wd_RenderInfo.mri_Window->Height
3645 - data->wd_RenderInfo.mri_Window->BorderBottom - top;
3647 /* D(bug("zune_imspec_draw %s %d\n", __FILE__, __LINE__)); */
3648 // D(bug("%d:zune_imspec_draw(%p) l=%d t=%d w=%d h=%d xo=%d yo=%d\n",
3649 // __LINE__, data->wd_Background, left, top, width,
3650 // height, left, top));
3652 zune_imspec_draw(data->wd_Background, &data->wd_RenderInfo,
3653 left, top, width, height, left, top, 0);
3656 MUI_Redraw(data->wd_RootObject, MADF_DRAWOBJECT);
3658 D(bug("MUIC_Window:windowOpen() ActiveObject=%p\n",
3659 data->wd_ActiveObject));
3660 if (data->wd_OldActive != NULL)
3662 set(obj, MUIA_Window_ActiveObject, data->wd_OldActive);
3665 return TRUE;
3668 /**************************************************************************/
3669 /**************************************************************************/
3671 static ULONG WindowClose(struct IClass *cl, Object *obj)
3673 struct MUI_WindowData *data = INST_DATA(cl, obj);
3675 if (data->wd_ActiveObject != NULL)
3677 data->wd_OldActive = data->wd_ActiveObject;
3678 set(obj, MUIA_Window_ActiveObject, MUIV_Window_ActiveObject_None);
3681 KillHelpBubble(data, obj, BUBBLEHELP_TICKER_FIRST);
3683 /* remove from window */
3684 DoHideMethod(data->wd_RootObject);
3685 zune_imspec_hide(data->wd_Background);
3687 DeinstallBackbuffer(cl, obj);
3689 HideRenderInfo(&data->wd_RenderInfo);
3691 /* close here ... */
3692 UndisplayWindow(obj, data);
3694 data->wd_Flags &= ~MUIWF_OPENED;
3695 data->wd_Menustrip = NULL;
3697 /* free display dependant data */
3698 DoMethod(data->wd_RootObject, MUIM_Cleanup);
3699 DoMethod(obj, MUIM_Window_Cleanup);
3700 return TRUE;
3703 /* calculate a new layout
3704 * see MUIA_ShowMe
3705 * see Group_ExitChange
3706 * see Group_Columns
3707 * see Group_Rows
3709 IPTR Window__MUIM_RecalcDisplay(struct IClass *cl, Object *obj,
3710 struct MUIP_Window_RecalcDisplay *msg)
3712 struct MUI_WindowData *data = INST_DATA(cl, obj);
3713 LONG left, top, width, height;
3714 BOOL resized, reshow = FALSE;
3715 Object *current_obj;
3717 if (!(data->wd_Flags & MUIWF_OPENED))
3718 return 0;
3720 current_obj = msg->originator;
3722 // typically originator is a group which has been added/removed a child
3723 // calculate minmax of current obj
3724 // if new minmax can accomodate current obj size, stop
3725 // else try with its parent
3726 // the resulting object will get a new layout
3727 // it currently produces some redundant AskMinMax but allows
3728 // to not always relayout the whole window
3730 D(bug("RecalcDisplay on %p\n", current_obj));
3731 while (current_obj != NULL)
3733 DoMethod(current_obj, MUIM_AskMinMax,
3734 (IPTR) & muiAreaData(current_obj)->mad_MinMax);
3735 __area_finish_minmax(current_obj,
3736 &muiAreaData(current_obj)->mad_MinMax);
3738 D(bug("size w = %d, h = %d\n", _width(current_obj),
3739 _height(current_obj)));
3740 D(bug("new w = %d-%d, h = %d-%d\n", _minwidth(current_obj),
3741 _maxwidth(current_obj), _minheight(current_obj),
3742 _maxheight(current_obj)));
3744 if (!_between(_minwidth(current_obj), _width(current_obj),
3745 _maxwidth(current_obj))
3746 || !_between(_minheight(current_obj), _height(current_obj),
3747 _maxheight(current_obj)))
3749 current_obj = _parent(current_obj);
3750 D(bug("RecalcDisplay, try parent %p\n", current_obj));
3752 else
3754 D(bug("found it\n"));
3755 break;
3759 if (!current_obj)
3760 current_obj = data->wd_RootObject;
3762 WindowMinMax(obj, data);
3764 /* Important: current_obj could be hidden, like in an inactive page! */
3765 if (_flags(current_obj) & MADF_CANDRAW)
3767 reshow = TRUE;
3770 if (reshow)
3771 DoHideMethod(current_obj);
3773 /* resize window ? */
3774 WindowSelectDimensions(data);
3775 resized = WindowResize(data);
3777 if (!resized)
3779 /* FIXME: Should we short circuit the following
3780 * if the window size didn't change?
3785 struct Window *win = data->wd_RenderInfo.mri_Window;
3786 _left(data->wd_RootObject) = win->BorderLeft;
3787 _top(data->wd_RootObject) = win->BorderTop;
3788 _width(data->wd_RootObject) = data->wd_Width;
3789 _height(data->wd_RootObject) = data->wd_Height;
3791 DoMethod(current_obj, MUIM_Layout);
3793 if (reshow)
3794 DoShowMethod(current_obj);
3796 if (muiGlobalInfo(obj)->mgi_Prefs->window_redraw ==
3797 WINDOW_REDRAW_WITHOUT_CLEAR)
3799 if (reshow)
3800 MUI_Redraw(current_obj, MADF_DRAWOBJECT);
3802 else
3804 left = data->wd_RenderInfo.mri_Window->BorderLeft;
3805 top = data->wd_RenderInfo.mri_Window->BorderTop;
3806 width = data->wd_RenderInfo.mri_Window->Width
3807 - data->wd_RenderInfo.mri_Window->BorderRight - left;
3808 height = data->wd_RenderInfo.mri_Window->Height
3809 - data->wd_RenderInfo.mri_Window->BorderBottom - top;
3811 zune_imspec_draw(data->wd_Background, &data->wd_RenderInfo,
3812 left, top, width, height, left, top, 0);
3813 MUI_Redraw(data->wd_RootObject, MADF_DRAWALL);
3816 ActivateObject(data);
3818 return TRUE;
3822 /**************************************************************************
3823 MUIM_AddEventHandler
3824 **************************************************************************/
3825 IPTR Window__MUIM_AddEventHandler(struct IClass *cl, Object *obj,
3826 struct MUIP_Window_AddEventHandler *msg)
3828 struct MUI_WindowData *data = INST_DATA(cl, obj);
3830 //D(bug("muimaster.library/window.c: Add Eventhandler %p\n", msg->ehnode));
3832 msg->ehnode->ehn_Priority = msg->ehnode->ehn_Priority;
3833 EnqueueByPriAndAddress((struct List *)&data->wd_EHList,
3834 (struct Node *)msg->ehnode);
3835 ChangeEvents(data, GetDefaultEvents());
3836 return TRUE;
3839 /**************************************************************************
3840 MUIM_RemEventHandler
3841 **************************************************************************/
3842 IPTR Window__MUIM_RemEventHandler(struct IClass *cl, Object *obj,
3843 struct MUIP_Window_RemEventHandler *msg)
3845 struct MUI_WindowData *data = INST_DATA(cl, obj);
3847 //D(bug("muimaster.library/window.c: Rem Eventhandler %p\n", msg->ehnode));
3849 Remove((struct Node *)msg->ehnode);
3850 ChangeEvents(data, GetDefaultEvents());
3851 return TRUE;
3854 /**************************************************************************
3855 Note that this is MUIM_Window_Setup, not MUIM_Setup
3856 **************************************************************************/
3857 IPTR Window__MUIM_Setup(struct IClass *cl, Object *obj, Msg msg)
3859 struct MUI_WindowData *data = INST_DATA(cl, obj);
3861 if (!SetupRenderInfo(obj, data, &data->wd_RenderInfo))
3862 return FALSE;
3864 data->wd_Background =
3865 zune_imspec_setup(MUII_WindowBack, &data->wd_RenderInfo);
3867 if (muiGlobalInfo(obj)->mgi_Prefs->window_redraw ==
3868 WINDOW_REDRAW_WITH_CLEAR)
3869 data->wd_Flags |= MUIWF_ERASEAREA;
3871 return TRUE;
3874 /**************************************************************************
3875 MUIM_Cleanup
3876 **************************************************************************/
3877 IPTR Window__MUIM_Cleanup(struct IClass *cl, Object *obj, Msg msg)
3879 struct MUI_WindowData *data = INST_DATA(cl, obj);
3881 zune_imspec_cleanup(data->wd_Background);
3883 if (data->wd_dnd)
3885 DeleteDragNDrop(data->wd_dnd);
3886 data->wd_dnd = NULL;
3889 CleanupRenderInfo(obj, data, &data->wd_RenderInfo);
3890 return TRUE;
3894 /**************************************************************************
3895 This adds the the control char handler and also do the MUIA_CycleChain
3896 stuff. Orginal MUI does this in an other way.
3897 **************************************************************************/
3898 IPTR Window__MUIM_AddControlCharHandler(struct IClass *cl, Object *obj,
3899 struct MUIP_Window_AddControlCharHandler *msg)
3901 struct MUI_WindowData *data = INST_DATA(cl, obj);
3902 struct ObjNode *node;
3904 if (msg->ccnode->ehn_Events)
3906 msg->ccnode->ehn_Priority = msg->ccnode->ehn_Priority;
3907 Enqueue((struct List *)&data->wd_CCList,
3908 (struct Node *)msg->ccnode);
3910 /* Due to the lack of a better idea ... */
3911 if (muiAreaData(msg->ccnode->ehn_Object)->mad_Flags & MADF_CYCLECHAIN)
3913 node = AllocPooled(data->wd_MemoryPool, sizeof(struct ObjNode));
3914 if (node)
3916 node->obj = msg->ccnode->ehn_Object;
3917 AddTail((struct List *)&data->wd_CycleChain,
3918 (struct Node *)node);
3921 return TRUE;
3924 /**************************************************************************
3925 MUIM_RemControlCharHandler
3926 **************************************************************************/
3927 IPTR Window__MUIM_RemControlCharHandler(struct IClass *cl, Object *obj,
3928 struct MUIP_Window_RemControlCharHandler *msg)
3930 struct MUI_WindowData *data = INST_DATA(cl, obj);
3931 struct ObjNode *node =
3932 FindObjNode(&data->wd_CycleChain, msg->ccnode->ehn_Object);
3934 if (msg->ccnode->ehn_Events)
3935 Remove((struct Node *)msg->ccnode);
3937 if (node)
3939 /* Remove from the chain list */
3940 Remove((struct Node *)node);
3941 FreePooled(data->wd_MemoryPool, node, sizeof(struct ObjNode));
3944 return TRUE;
3947 /**************************************************************************
3948 MUIM_DragObject
3949 **************************************************************************/
3950 IPTR Window__MUIM_DragObject(struct IClass *cl, Object *obj,
3951 struct MUIP_Window_DragObject *msg)
3953 struct MUI_WindowData *data = INST_DATA(cl, obj);
3954 if (msg->obj)
3956 struct DragNDrop *dnd;
3957 struct MUI_DragImage *di;
3958 struct BitMapNode *bmn;
3960 if (!(dnd = CreateDragNDropA(NULL)))
3961 return 0;
3963 if (!(di =
3964 (struct MUI_DragImage *)DoMethod(msg->obj,
3965 MUIM_CreateDragImage, -msg->touchx, -msg->touchy,
3966 msg->flags)))
3968 DeleteDragNDrop(dnd);
3969 return 0;
3971 if (!di->bm)
3973 DoMethod(msg->obj, MUIM_DeleteDragImage, (IPTR) di);
3974 DeleteDragNDrop(dnd);
3975 return 0;
3978 if (!(bmn = CreateBitMapNodeA(TAGLIST(
3979 GUI_BitMap, (IPTR)di->bm,
3980 GUI_LeftOffset, di->touchx,
3981 GUI_TopOffset, di->touchy,
3982 GUI_Width, di->width,
3983 GUI_Height, di->height,
3984 GUI_SourceAlpha, !!(di->flags & MUIF_DRAGIMAGE_SOURCEALPHA)))))
3986 DoMethod(msg->obj, MUIM_DeleteDragImage, (IPTR) di);
3987 DeleteDragNDrop(dnd);
3988 return 0;
3991 AttachBitMapNode(dnd, bmn);
3993 if (!PrepareDragNDrop(dnd, data->wd_RenderInfo.mri_Screen))
3995 DoMethod(msg->obj, MUIM_DeleteDragImage, (IPTR) di);
3996 DeleteDragNDrop(dnd);
3997 return 0;
4000 muiAreaData(msg->obj)->mad_Flags |= MADF_DRAGGING;
4002 data->wd_DragObject = msg->obj;
4003 data->wd_dnd = dnd;
4004 data->wd_DragImage = di;
4005 return 1;
4007 return 0;
4010 /**************************************************************************
4011 MUIM_AllocGadgetID
4012 **************************************************************************/
4013 IPTR Window__MUIM_AllocGadgetID(struct IClass *cl, Object *obj,
4014 struct MUIP_Window_AllocGadgetID *msg)
4016 struct MUI_WindowData *data = INST_DATA(cl, obj);
4017 struct IDNode *newnode;
4019 newnode = AllocPooled(data->wd_MemoryPool, sizeof(struct IDNode));
4020 if (newnode)
4022 int id;
4023 struct MinNode *mn;
4025 if (IsListEmpty((struct List *)&data->wd_IDList))
4027 newnode->id = 1;
4028 AddHead((struct List *)&data->wd_IDList,
4029 (struct Node *)&newnode->node);
4030 return (IPTR) 1;
4033 id = 1;
4035 for (mn = data->wd_IDList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
4037 struct IDNode *idn = (struct IDNode *)mn;
4038 if (id < idn->id)
4039 break;
4040 id++;
4042 newnode->id = id;
4043 Insert((struct List *)&data->wd_IDList,
4044 (struct Node *)&newnode->node, (struct Node *)mn);
4045 return (IPTR) id;
4048 return 0;
4051 /**************************************************************************
4052 MUIM_FreeGadgetID
4053 **************************************************************************/
4054 IPTR Window__MUIM_FreeGadgetID(struct IClass *cl, Object *obj,
4055 struct MUIP_Window_FreeGadgetID *msg)
4057 struct MUI_WindowData *data = INST_DATA(cl, obj);
4058 struct MinNode *mn;
4060 for (mn = data->wd_IDList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
4062 struct IDNode *idn = (struct IDNode *)mn;
4063 if (msg->gadgetid == idn->id)
4065 Remove((struct Node *)idn);
4066 FreePooled(data->wd_MemoryPool, idn, sizeof(struct IDNode));
4067 return 0;
4071 return 0;
4075 /**************************************************************************
4076 MUIM_Window_GetMenuCheck
4077 **************************************************************************/
4078 IPTR Window__MUIM_GetMenuCheck(struct IClass *cl, Object *obj,
4079 struct MUIP_Window_GetMenuCheck *msg)
4081 IPTR stat = 0;
4082 struct MUI_WindowData *data = INST_DATA(cl, obj);
4083 Object *item;
4084 Object *strip = data->wd_ChildMenustrip;
4085 if (!strip)
4086 strip = data->wd_Menustrip;
4087 if (!strip)
4088 return 0;
4089 if (!(item = (Object *) DoMethod(strip, MUIM_FindUData, msg->MenuID)))
4090 return 0;
4091 get(item, MUIA_Menuitem_Checked, &stat);
4092 return stat;
4095 /**************************************************************************
4096 MUIM_Window_SetMenuCheck
4097 **************************************************************************/
4098 IPTR Window__MUIM_SetMenuCheck(struct IClass *cl, Object *obj,
4099 struct MUIP_Window_SetMenuCheck *msg)
4101 struct MUI_WindowData *data = INST_DATA(cl, obj);
4102 Object *item;
4103 Object *strip = data->wd_ChildMenustrip;
4104 if (!strip)
4105 strip = data->wd_Menustrip;
4106 if (!strip)
4107 return 0;
4108 if (!(item = (Object *) DoMethod(strip, MUIM_FindUData, msg->MenuID)))
4109 return 0;
4110 set(item, MUIA_Menuitem_Checked, msg->stat);
4111 return 0;
4114 /**************************************************************************
4115 MUIM_Window_GetMenuState
4116 **************************************************************************/
4117 IPTR Window__MUIM_GetMenuState(struct IClass *cl, Object *obj,
4118 struct MUIP_Window_GetMenuState *msg)
4120 IPTR stat = 0;
4121 struct MUI_WindowData *data = INST_DATA(cl, obj);
4122 Object *item;
4123 Object *strip = data->wd_ChildMenustrip;
4124 if (!strip)
4125 strip = data->wd_Menustrip;
4126 if (!strip)
4127 return 0;
4128 if (!(item = (Object *) DoMethod(strip, MUIM_FindUData, msg->MenuID)))
4129 return 0;
4130 get(item, MUIA_Menuitem_Enabled, &stat);
4131 return stat;
4134 /**************************************************************************
4135 MUIM_Window_SetMenuState
4136 **************************************************************************/
4137 IPTR Window__MUIM_SetMenuState(struct IClass *cl, Object *obj,
4138 struct MUIP_Window_SetMenuState *msg)
4140 struct MUI_WindowData *data = INST_DATA(cl, obj);
4141 Object *item;
4142 Object *strip = data->wd_ChildMenustrip;
4143 if (!strip)
4144 strip = data->wd_Menustrip;
4145 if (!strip)
4146 return 0;
4147 if (!(item = (Object *) DoMethod(strip, MUIM_FindUData, msg->MenuID)))
4148 return 0;
4149 set(item, MUIA_Menuitem_Enabled, msg->stat);
4150 return 0;
4153 /**************************************************************************
4154 MUIM_Window_DrawBackground
4155 **************************************************************************/
4156 IPTR Window__MUIM_DrawBackground(struct IClass *cl, Object *obj,
4157 struct MUIP_Window_DrawBackground *msg)
4159 struct MUI_WindowData *data = INST_DATA(cl, obj);
4160 if (!(data->wd_RenderInfo.mri_Window)) /* not between show/hide */
4161 return FALSE;
4163 // D(bug("%d:zune_imspec_draw(%p) l=%d t=%d w=%d h=%d xo=%d yo=%d\n",
4164 // __LINE__, data->wd_Background, msg->left, msg->top, msg->width,
4165 // msg->height, msg->xoffset, msg->yoffset));
4166 zune_imspec_draw(data->wd_Background, &data->wd_RenderInfo,
4167 msg->left, msg->top, msg->width, msg->height,
4168 msg->xoffset, msg->yoffset, 0);
4169 return 0;
4172 /**************************************************************************
4173 MUIM_Window_ToFront
4174 **************************************************************************/
4175 IPTR Window__MUIM_ToFront(struct IClass *cl, Object *obj, Msg msg)
4177 struct MUI_WindowData *data = INST_DATA(cl, obj);
4178 if (!(data->wd_RenderInfo.mri_Window)) /* not between show/hide */
4179 return 0;
4181 WindowToFront(data->wd_RenderInfo.mri_Window);
4182 return 1;
4185 /**************************************************************************
4186 MUIM_Window_ToBack
4187 **************************************************************************/
4188 IPTR Window__MUIM_ToBack(struct IClass *cl, Object *obj, Msg msg)
4190 struct MUI_WindowData *data = INST_DATA(cl, obj);
4191 if (!(data->wd_RenderInfo.mri_Window)) /* not between show/hide */
4192 return 0;
4194 WindowToBack(data->wd_RenderInfo.mri_Window);
4195 return 1;
4198 /**************************************************************************
4199 MUIM_Window_ScreenToBack
4200 **************************************************************************/
4201 IPTR Window__MUIM_ScreenToBack(struct IClass *cl, Object *obj, Msg msg)
4203 struct MUI_WindowData *data = INST_DATA(cl, obj);
4204 if (!(data->wd_RenderInfo.mri_Window)) /* not between show/hide */
4205 return 0;
4207 ScreenToBack(data->wd_RenderInfo.mri_Screen);
4208 return 1;
4211 /**************************************************************************
4212 MUIM_Window_ScreenToFront
4213 **************************************************************************/
4214 IPTR Window__MUIM_ScreenToFront(struct IClass *cl, Object *obj, Msg msg)
4216 struct MUI_WindowData *data = INST_DATA(cl, obj);
4217 if (!(data->wd_RenderInfo.mri_Window)) /* not between show/hide */
4218 return 0;
4220 ScreenToFront(data->wd_RenderInfo.mri_Screen);
4221 return 1;
4224 /**************************************************************************
4225 MUIM_Window_ActionIconify
4226 **************************************************************************/
4227 IPTR Window__MUIM_ActionIconify(struct IClass *cl, Object *obj, Msg msg)
4229 set(_app(obj), MUIA_Application_Iconified, TRUE);
4231 return TRUE;
4235 /* Loads ENV: prefs, add a Window_ID chunk in the MUIW chunk, if no MUIW chunk
4236 * then create it at the same level as MUIC chunk, save prefs.
4237 * Do the same for ENVARC:
4238 * MUIW chunk layout:
4239 * 'MUIW'
4240 * 00 00 00 30 (chunk length for a single window, 0x30L big endian)
4241 * 'this window ID'
4242 * 00 00 00 28
4243 * xx xx yy yy (X, Y)
4244 * ww ww hh hh (Width, Height)
4245 * ax ax ay ay (AltX, AltY)
4246 * aw aw ah ah (AltWidth, AltHeight)
4247 * 00 00 00 00 (???)
4248 * 00 00 00 00
4249 * 00 00 00 00
4250 * 00 00 00 00
4251 * 00 01 00 00
4252 * 00 00 00 00
4254 static void RememberWindowPosition(Object *winobj, ULONG id)
4256 if (!id)
4257 return;
4260 /* Loads ENV: prefs, remove our Window_ID chunk from the MUIW chunk,
4261 * save prefs.
4262 * Do the same for ENVARC:
4263 * This function shouldn't really be in window.c, but rather in a file dealing
4264 * with prefs file stuff.
4266 static void ForgetWindowPosition(Object *winobj, ULONG id)
4268 if (!id)
4269 return;
4272 /**************************************************************************
4273 MUIM_Window_Snapshot
4274 **************************************************************************/
4275 IPTR Window__MUIM_Snapshot(struct IClass *cl, Object *obj,
4276 struct MUIP_Window_Snapshot *msg)
4278 struct MUI_WindowData *data = INST_DATA(cl, obj);
4279 struct windowpos winp;
4280 struct Window *w;
4282 winp.id = data->wd_ID;
4283 w = data->wd_RenderInfo.mri_Window;
4284 if (w)
4286 winp.x1 = w->LeftEdge;
4287 winp.y1 = w->TopEdge;
4288 winp.w1 = w->GZZWidth;
4289 winp.h1 = w->GZZHeight;
4290 winp.x2 = 0;
4291 winp.x2 = 0;
4292 winp.w2 = 0;
4293 winp.h2 = 0; //to do save alt dims
4295 set(_app(obj), MUIA_Application_SetWinPos, &winp);
4298 if (msg->flags)
4299 RememberWindowPosition(obj, data->wd_ID);
4300 else
4301 ForgetWindowPosition(obj, data->wd_ID);
4302 return 1;
4305 /**************************************************************************
4306 MUIM_Window_UpdateMenu
4307 **************************************************************************/
4308 IPTR Window__MUIM_UpdateMenu(struct IClass *cl, Object *obj, Msg msg)
4310 struct MUI_WindowData *data = INST_DATA(cl, obj);
4312 struct Menu *menu = NULL;
4313 struct NewMenu *newmenu = NULL;
4314 APTR visinfo = NULL;
4315 struct Window *win = NULL;
4317 if (data->wd_Menustrip) // only open windows can have a menustrip
4319 if ((visinfo =
4320 GetVisualInfoA(data->wd_RenderInfo.mri_Screen, NULL)))
4322 win = data->wd_RenderInfo.mri_Window;
4323 ClearMenuStrip(win);
4324 if (data->wd_Menu)
4326 FreeMenus(data->wd_Menu);
4327 data->wd_Menu = NULL;
4330 get(data->wd_Menustrip, MUIA_Menuitem_NewMenu, &newmenu);
4331 if (newmenu)
4333 if ((menu = CreateMenusA(newmenu, NULL)))
4335 struct TagItem tags[] = {
4336 {GTMN_NewLookMenus, TRUE},
4337 {TAG_DONE, 0}
4339 LayoutMenusA(menu, visinfo, tags);
4340 data->wd_Menu = menu;
4341 SetMenuStrip(win, menu);
4344 FreeVisualInfo(visinfo);
4348 return 1;
4351 /**************************************************************************
4352 MUIM_Export : to export an object's "contents" to a dataspace object.
4353 **************************************************************************/
4354 static IPTR Window__MUIM_Export(struct IClass *cl, Object *obj,
4355 struct MUIP_Export *msg)
4357 struct MUI_WindowData *data = INST_DATA(cl, obj);
4358 DoMethodA(data->wd_RootObject, (Msg) msg);
4359 return 0;
4363 /**************************************************************************
4364 MUIM_Import : to import an object's "contents" from a dataspace object.
4365 **************************************************************************/
4366 static IPTR Window__MUIM_Import(struct IClass *cl, Object *obj,
4367 struct MUIP_Import *msg)
4369 struct MUI_WindowData *data = INST_DATA(cl, obj);
4370 DoMethodA(data->wd_RootObject, (Msg) msg);
4371 return 0;
4374 BOOPSI_DISPATCHER(IPTR, Window_Dispatcher, cl, obj, msg)
4376 switch (msg->MethodID)
4378 case OM_NEW:
4379 return Window__OM_NEW(cl, obj, (struct opSet *)msg);
4380 case OM_DISPOSE:
4381 return Window__OM_DISPOSE(cl, obj, msg);
4382 case OM_SET:
4383 return Window__OM_SET(cl, obj, (struct opSet *)msg);
4384 case OM_GET:
4385 return Window__OM_GET(cl, obj, (struct opGet *)msg);
4386 case MUIM_FindUData:
4387 return Window__MUIM_FindUData(cl, obj,
4388 (struct MUIP_FindUData *)msg);
4389 case MUIM_GetUData:
4390 return Window__MUIM_GetUData(cl, obj, (struct MUIP_GetUData *)msg);
4391 case MUIM_SetUData:
4392 return Window__MUIM_SetUData(cl, obj, (struct MUIP_SetUData *)msg);
4393 case MUIM_SetUDataOnce:
4394 return Window__MUIM_SetUDataOnce(cl, obj,
4395 (struct MUIP_SetUDataOnce *)msg);
4396 case MUIM_Window_AddEventHandler:
4397 return Window__MUIM_AddEventHandler(cl, obj, (APTR) msg);
4398 case MUIM_Window_RemEventHandler:
4399 return Window__MUIM_RemEventHandler(cl, obj, (APTR) msg);
4400 case MUIM_ConnectParent:
4401 return Window__MUIM_ConnectParent(cl, obj, (APTR) msg);
4402 case MUIM_DisconnectParent:
4403 return Window__MUIM_DisconnectParent(cl, obj, (APTR) msg);
4404 case MUIM_Window_RecalcDisplay:
4405 return Window__MUIM_RecalcDisplay(cl, obj, (APTR) msg);
4406 case MUIM_Window_Setup:
4407 return Window__MUIM_Setup(cl, obj, (APTR) msg);
4408 case MUIM_Window_Cleanup:
4409 return Window__MUIM_Cleanup(cl, obj, (APTR) msg);
4410 case MUIM_Window_AddControlCharHandler:
4411 return Window__MUIM_AddControlCharHandler(cl, obj, (APTR) msg);
4412 case MUIM_Window_RemControlCharHandler:
4413 return Window__MUIM_RemControlCharHandler(cl, obj, (APTR) msg);
4414 case MUIM_Window_DragObject:
4415 return Window__MUIM_DragObject(cl, obj, (APTR) msg);
4416 case MUIM_Window_AllocGadgetID:
4417 return Window__MUIM_AllocGadgetID(cl, obj, (APTR) msg);
4418 case MUIM_Window_FreeGadgetID:
4419 return Window__MUIM_FreeGadgetID(cl, obj, (APTR) msg);
4420 case MUIM_Window_GetMenuCheck:
4421 return Window__MUIM_GetMenuCheck(cl, obj, (APTR) msg);
4422 case MUIM_Window_SetMenuCheck:
4423 return Window__MUIM_SetMenuCheck(cl, obj, (APTR) msg);
4424 case MUIM_Window_GetMenuState:
4425 return Window__MUIM_GetMenuState(cl, obj, (APTR) msg);
4426 case MUIM_Window_SetMenuState:
4427 return Window__MUIM_SetMenuState(cl, obj, (APTR) msg);
4428 case MUIM_Window_DrawBackground:
4429 return Window__MUIM_DrawBackground(cl, obj, (APTR) msg);
4430 case MUIM_Window_ToFront:
4431 return Window__MUIM_ToFront(cl, obj, (APTR) msg);
4432 case MUIM_Window_ToBack:
4433 return Window__MUIM_ToBack(cl, obj, (APTR) msg);
4434 case MUIM_Window_ScreenToFront:
4435 return Window__MUIM_ScreenToFront(cl, obj, (APTR) msg);
4436 case MUIM_Window_ScreenToBack:
4437 return Window__MUIM_ScreenToBack(cl, obj, (APTR) msg);
4438 case MUIM_Window_ActionIconify:
4439 return Window__MUIM_ActionIconify(cl, obj, (APTR) msg);
4440 case MUIM_Window_Snapshot:
4441 return Window__MUIM_Snapshot(cl, obj, (APTR) msg);
4442 case MUIM_Window_UpdateMenu:
4443 return Window__MUIM_UpdateMenu(cl, obj, (APTR) msg);
4444 case MUIM_Export:
4445 return Window__MUIM_Export(cl, obj, (APTR) msg);
4446 case MUIM_Import:
4447 return Window__MUIM_Import(cl, obj, (APTR) msg);
4450 return DoSuperMethodA(cl, obj, msg);
4452 BOOPSI_DISPATCHER_END
4455 * Class descriptor.
4457 const struct __MUIBuiltinClass _MUI_Window_desc =
4459 MUIC_Window,
4460 MUIC_Notify,
4461 sizeof(struct MUI_WindowData),
4462 (void *) Window_Dispatcher