Tabs to spaces, more consistent formatting.
[AROS.git] / workbench / libs / muimaster / classes / window.c
blobdfd33e002136b745fe5afbf5007c234951664c37
1 /*
2 Copyright 1999, David Le Corfec.
3 Copyright 2002-2012, The AROS Development Team.
4 All rights reserved.
6 $Id$
7 */
8 #include <exec/types.h>
9 #include <exec/memory.h>
11 #include <string.h>
13 #include <intuition/imageclass.h>
14 #include <intuition/icclass.h>
15 #include <intuition/gadgetclass.h>
16 #ifdef __AROS__
17 #include <intuition/extensions.h>
18 #endif
19 #include <clib/alib_protos.h>
20 #include <graphics/gfxmacros.h>
21 #include <proto/exec.h>
22 #include <proto/intuition.h>
23 #include <proto/utility.h>
24 #include <proto/graphics.h>
25 #include <proto/commodities.h>
26 #include <proto/layers.h>
27 #include <proto/gadtools.h>
28 #include <proto/muimaster.h>
30 #define MUI_OBSOLETE /* for the obsolete menu stuff */
32 #include "mui.h"
33 #include "support.h"
34 #include "classes/window.h"
35 #include "classes/area.h"
36 #include "imspec.h"
37 #include "datatypescache.h"
38 #include "prefs.h"
39 #include "dragndrop.h"
41 #include "muimaster_intern.h"
43 //#define MYDEBUG 1
44 #include "debug.h"
46 extern struct Library *MUIMasterBase;
48 static const int __version = 1;
49 static const int __revision = 1;
51 #define IM(x) ((struct Image*)(x))
52 #define G(x) ((struct Gadget*)(x))
53 #define GADGETID(x) (((struct Gadget*)(x))->GadgetID)
55 /* this is for the cycle list */
56 struct ObjNode
58 struct MinNode node;
59 Object *obj;
62 /* For the gadget ids */
63 struct IDNode
65 struct MinNode node;
66 UWORD id;
69 struct MUI_ImageSpec_intern;
71 struct MUI_WindowData
73 struct MUI_RenderInfo wd_RenderInfo;
74 struct MUI_MinMax wd_MinMax;
75 struct IBox wd_AltDim; /* zoomed dimensions */
76 BOOL wd_ZoomGadget; /* enable/disable zoomgadget (altdim stuff) */
77 APTR wd_MemoryPool; /* for nodes and stuff to deallocate at
78 * OM_DISPOSE */
79 struct MinList wd_CycleChain; /* objects activated with tab */
80 struct MinList wd_EHList; /* event handlers */
81 struct MinList wd_CCList; /* control chars */
82 struct MinList wd_IDList; /* gadget ids */
83 ULONG wd_Events; /* events received */
84 ULONG wd_CrtFlags; /* window creation flags, see below */
85 Object *wd_ActiveObject; /* the active object */
86 Object *wd_OldActive; /* active object before window was closed */
87 APTR wd_DefaultObject;
88 ULONG wd_ID;
89 STRPTR wd_Title;
90 STRPTR wd_ScreenTitle;
91 LONG wd_Height; /* Current dimensions */
92 LONG wd_Width;
93 LONG wd_X;
94 LONG wd_Y;
95 LONG wd_ReqHeight; /* given by programmer */
96 LONG wd_ReqWidth;
97 APTR wd_RootObject; /* unique child */
98 ULONG wd_Flags; /* various status flags */
99 struct MUI_ImageSpec_intern *wd_Background;
100 ULONG wd_DisabledKeys;
101 BOOL wd_NoMenus; /* MUIA_Window_NoMenus */
103 Object *wd_DragObject; /* the object which is being dragged */
104 struct Window *wd_DropWindow; /* the destination window, for faster
105 * access */
106 Object *wd_DropObject; /* the destination object */
107 struct DragNDrop *wd_dnd;
108 struct MUI_DragImage *wd_DragImage;
110 Object *wd_Menustrip; /* The menustrip object which is actually
111 * used (either apps or windows or NULL) */
112 Object *wd_ChildMenustrip; /* If window has an own Menustrip */
113 struct Menu *wd_Menu; /* the intuition menustrip */
115 Object *wd_VertProp;
116 Object *wd_UpButton;
117 Object *wd_DownButton;
119 Object *wd_HorizProp;
120 Object *wd_LeftButton;
121 Object *wd_RightButton;
122 Object *wd_RefWindow;
124 Object *wd_MUIGadget;
126 Object *wd_HelpObject;
127 APTR wd_HelpBubble;
128 WORD wd_HelpTicker;
130 struct Screen *wd_UserScreen;
131 STRPTR wd_UserPublicScreen;
132 LONG wd_XStore; /* store MUIV_Window_LeftEdge_Centered Tags
133 * etc. because wd_X is overwritten by a
134 * value in CalcDimension. Popup windows work
135 * OK on AmiGG when main window is moved */
136 LONG wd_YStore;
138 WORD wd_SleepCount; /* MUIA_Window_Sleep nests */
141 #ifndef WFLG_SIZEGADGET
143 #define WFLG_CLOSEGADGET (1<<0) /* has close gadget */
144 #define WFLG_SIZEGADGET (1<<1) /* has size gadget */
145 #define WFLG_BACKDROP (1<<2) /* is backdrop window */
146 #define WFLG_BORDERLESS (1<<3) /* has no borders */
147 #define WFLG_DEPTHGADGET (1<<4) /* has depth gadget */
148 #define WFLG_DRAGBAR (1<<5) /* is draggable */
149 #define WFLG_SIZEBRIGHT (1<<6) /* size gadget is in right border */
151 #endif
153 /* wd_Flags */
154 #define MUIWF_OPENED (1<<0) /* window currently opened */
155 #define MUIWF_HIDDEN (1<<1) /* window currently iconified */
156 #define MUIWF_ACTIVE (1<<2) /* window currently active */
157 #define MUIWF_RESIZING (1<<4) /* window currently resizing,
158 * for simple refresh */
159 #define MUIWF_DONTACTIVATE (1<<7) /* do not activate the window when
160 * opening */
161 #define MUIWF_USERIGHTSCROLLER (1<<8) /* should have right scroller */
162 #define MUIWF_USEBOTTOMSCROLLER (1<<9) /* should have bottom scroller */
163 #define MUIWF_ERASEAREA (1<<10) /* Erase area after a window resize */
164 #define MUIWF_ISAPPWINDOW (1<<11) /* Is an AppWindow */
165 #define MUIWF_ISSUBWINDOW (1<<12) /* Don't get automatically disposed
166 * with app */
167 #define MUIWF_BUBBLEMODE (1<<13) /* Quick bubble mode. Bubbles appear
168 * quick when moving */
169 #define MUIWF_OPENONUNHIDE (1<<14) /* Open the window when unhiding */
170 #define MUIWF_SCREENLOCKED (1<<15) /* A pub screen was locked in
171 * SetupRenderInfo. Unlock it in
172 * CleanupRenderInfo! */
173 #define MUIWF_OBJECTGOACTIVESENT (1<<16) /* A MUIM_GoActive msg was sent to
174 * window's active object */
175 #define MUIWF_TOOLBOX (1<<17) /* Window should be opened as
176 * ToolBox */
178 #define BUBBLEHELP_TICKER_FIRST 10
179 #define BUBBLEHELP_TICKER_LATER 3
181 struct __dummyXFC3__
183 struct MUI_NotifyData mnd;
184 struct MUI_WindowData mwd;
187 #define muiWindowData(obj) (&(((struct __dummyXFC3__ *)(obj))->mwd))
189 static ULONG DoHalfshineGun(ULONG a, ULONG b)
191 ULONG val = ((((a) >> 24) + 3 * ((b) >> 24)) / 4);
192 val = val + (val << 8) + (val << 16) + (val << 24);
193 return val;
196 static ULONG DoHalfshadowGun(ULONG a, ULONG b)
198 ULONG val = ((((a) >> 24) + 5 * ((b) >> 24)) / 6);
199 val = val + (val << 8) + (val << 16) + (val << 24);
200 return val;
203 static Object *CreateSysimage(struct DrawInfo *dri, ULONG which)
205 return NewObject(NULL, "sysiclass",
206 SYSIA_DrawInfo, (IPTR) dri, SYSIA_Which, which, TAG_DONE);
209 static void EnqueueByPriAndAddress(struct List *list, struct Node *node)
211 struct Node *scannode;
213 /* Sort by priority and by node address, so that a
214 "remove - modify - enqueue" sequence will re-add
215 the node at the same place in the list it was
216 initially */
217 ForeachNode(list, scannode)
219 if (((struct Node *)node)->ln_Pri > scannode->ln_Pri)
220 break;
221 if (((struct Node *)node)->ln_Pri == scannode->ln_Pri)
223 if ((IPTR) node > (IPTR) scannode)
224 break;
228 Insert(list, (struct Node *)node, scannode->ln_Pred);
231 static BOOL InitCustomFrames(Object *obj, struct MUI_RenderInfo *mri)
233 int i;
235 for (i = 0; i < 16; i++)
237 mri->mri_FrameImage[i] = NULL;
240 mri->mri_FrameImage[0] =
241 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
242 customframe_config_1, mri->mri_Screen);
243 mri->mri_FrameImage[1] =
244 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
245 customframe_config_2, mri->mri_Screen);
246 mri->mri_FrameImage[2] =
247 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
248 customframe_config_3, mri->mri_Screen);
249 mri->mri_FrameImage[3] =
250 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
251 customframe_config_4, mri->mri_Screen);
252 mri->mri_FrameImage[4] =
253 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
254 customframe_config_5, mri->mri_Screen);
255 mri->mri_FrameImage[5] =
256 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
257 customframe_config_6, mri->mri_Screen);
258 mri->mri_FrameImage[6] =
259 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
260 customframe_config_7, mri->mri_Screen);
261 mri->mri_FrameImage[7] =
262 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
263 customframe_config_8, mri->mri_Screen);
264 mri->mri_FrameImage[8] =
265 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
266 customframe_config_9, mri->mri_Screen);
267 mri->mri_FrameImage[9] =
268 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
269 customframe_config_10, mri->mri_Screen);
270 mri->mri_FrameImage[10] =
271 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
272 customframe_config_11, mri->mri_Screen);
273 mri->mri_FrameImage[11] =
274 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
275 customframe_config_12, mri->mri_Screen);
276 mri->mri_FrameImage[12] =
277 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
278 customframe_config_13, mri->mri_Screen);
279 mri->mri_FrameImage[13] =
280 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
281 customframe_config_14, mri->mri_Screen);
282 mri->mri_FrameImage[14] =
283 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
284 customframe_config_15, mri->mri_Screen);
285 mri->mri_FrameImage[15] =
286 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
287 customframe_config_16, mri->mri_Screen);
289 return TRUE;
292 static void DisposeCustomFrames(struct MUI_RenderInfo *mri)
294 int i;
296 for (i = 0; i < 16; i++)
298 dispose_custom_frame(mri->mri_FrameImage[i]);
300 mri->mri_FrameImage[i] = NULL;
304 static BOOL SetupRenderInfo(Object *obj, struct MUI_WindowData *data,
305 struct MUI_RenderInfo *mri)
307 ULONG rgbtable[3 * 3];
308 Object *temp_obj;
309 IPTR val;
310 int i;
312 /* TODO: Move this whole screen locking/opening stuff into the
313 * application class by creating methods for this purpose */
315 /* If no user screen has been specified try to open the application
316 * specific screen */
317 if (!data->wd_UserScreen)
319 ULONG screenmodeid = muiGlobalInfo(obj)->mgi_Prefs->screenmodeid;
321 if (screenmodeid != ~0)
323 if (!muiGlobalInfo(obj)->mgi_CustomScreen)
325 muiGlobalInfo(obj)->mgi_CustomScreen = OpenScreenTags
326 (NULL,
327 SA_DisplayID, screenmodeid,
328 SA_SharePens, TRUE,
329 SA_FullPalette, TRUE, SA_LikeWorkbench, TRUE, TAG_DONE);
330 /* It's fine if this fails as there is a fallback case below */
333 data->wd_UserScreen = muiGlobalInfo(obj)->mgi_CustomScreen;
336 if (data->wd_UserScreen)
338 mri->mri_Screen = data->wd_UserScreen;
340 else
342 if (data->wd_UserPublicScreen)
344 mri->mri_Screen = LockPubScreen(data->wd_UserPublicScreen);
346 else if (muiGlobalInfo(obj)->mgi_Prefs->publicscreen_name
347 && muiGlobalInfo(obj)->mgi_Prefs->publicscreen_name[0])
349 mri->mri_Screen =
350 LockPubScreen(muiGlobalInfo(obj)->mgi_Prefs->
351 publicscreen_name);
352 // FIXME: open the public screen if necessary
355 if (mri->mri_Screen == NULL)
357 mri->mri_Screen = LockPubScreen(NULL);
358 if (mri->mri_Screen == NULL)
360 return FALSE;
364 // FIXME: is this the right place for this action?
365 if (mri->mri_Screen
366 && muiGlobalInfo(obj)->mgi_Prefs->publicscreen_pop_to_front)
368 ScreenToFront(mri->mri_Screen);
371 data->wd_Flags |= MUIWF_SCREENLOCKED;
374 if (!(mri->mri_DrawInfo = GetScreenDrawInfo(mri->mri_Screen)))
376 if (data->wd_Flags & MUIWF_SCREENLOCKED)
378 UnlockPubScreen(NULL, mri->mri_Screen);
379 data->wd_Flags &= ~MUIWF_SCREENLOCKED;
381 return FALSE;
384 if (!InitCustomFrames(obj, mri))
386 if (data->wd_Flags & MUIWF_SCREENLOCKED)
388 UnlockPubScreen(NULL, mri->mri_Screen);
389 data->wd_Flags &= ~MUIWF_SCREENLOCKED;
391 return FALSE;
394 mri->mri_Colormap = mri->mri_Screen->ViewPort.ColorMap;
395 mri->mri_ScreenWidth = mri->mri_Screen->Width;
396 mri->mri_ScreenHeight = mri->mri_Screen->Height;
398 if (mri->mri_ScreenWidth / mri->mri_ScreenHeight < 2)
400 mri->mri_Flags |= MUIMRI_THINFRAMES;
403 if (GetBitMapAttr(mri->mri_Screen->RastPort.BitMap, BMA_DEPTH) >= 15)
405 mri->mri_Flags |= MUIMRI_TRUECOLOR;
408 mri->mri_PensStorage[MPEN_SHINE] =
409 mri->mri_DrawInfo->dri_Pens[SHINEPEN];
410 mri->mri_PensStorage[MPEN_BACKGROUND] =
411 mri->mri_DrawInfo->dri_Pens[BACKGROUNDPEN];
412 mri->mri_PensStorage[MPEN_SHADOW] =
413 mri->mri_DrawInfo->dri_Pens[SHADOWPEN];
414 mri->mri_PensStorage[MPEN_TEXT] = mri->mri_DrawInfo->dri_Pens[TEXTPEN];
415 mri->mri_PensStorage[MPEN_FILL] = mri->mri_DrawInfo->dri_Pens[FILLPEN];
417 GetRGB32(mri->mri_Colormap, mri->mri_DrawInfo->dri_Pens[SHINEPEN], 1,
418 rgbtable);
419 GetRGB32(mri->mri_Colormap, mri->mri_DrawInfo->dri_Pens[BACKGROUNDPEN],
420 1, rgbtable + 3);
421 GetRGB32(mri->mri_Colormap, mri->mri_DrawInfo->dri_Pens[SHADOWPEN], 1,
422 rgbtable + 6);
424 mri->mri_PensStorage[MPEN_HALFSHINE] = ObtainBestPenA
425 (mri->mri_Colormap,
426 DoHalfshineGun(rgbtable[0], rgbtable[3]),
427 DoHalfshineGun(rgbtable[1], rgbtable[4]),
428 DoHalfshineGun(rgbtable[2], rgbtable[5]), NULL);
430 mri->mri_PensStorage[MPEN_HALFSHADOW] = ObtainBestPenA
431 (mri->mri_Colormap,
432 DoHalfshadowGun(rgbtable[6], rgbtable[3]),
433 DoHalfshadowGun(rgbtable[7], rgbtable[4]),
434 DoHalfshadowGun(rgbtable[8], rgbtable[5]), NULL);
436 /* I'm really not sure that MUI does this for MPEN_MARK, but it seems
437 * mostly acceptable -dlc */
438 mri->mri_PensStorage[MPEN_MARK] = ObtainBestPenA
439 (mri->mri_Colormap, 0xf4f4f4f4, 0xb5b5b5b5, 0x8b8b8b8b, NULL);
441 mri->mri_Pens = mri->mri_PensStorage;
443 for (i = 0; i < -MUIV_Font_NegCount; i++)
445 mri->mri_Fonts[i] = NULL;
448 if (data->wd_Flags & MUIWF_USEBOTTOMSCROLLER)
450 mri->mri_LeftImage = CreateSysimage(mri->mri_DrawInfo, LEFTIMAGE);
451 mri->mri_RightImage = CreateSysimage(mri->mri_DrawInfo, RIGHTIMAGE);
453 else
455 mri->mri_LeftImage = mri->mri_RightImage = NULL;
458 if (data->wd_Flags & MUIWF_USERIGHTSCROLLER)
460 mri->mri_UpImage = CreateSysimage(mri->mri_DrawInfo, UPIMAGE);
461 mri->mri_DownImage = CreateSysimage(mri->mri_DrawInfo, DOWNIMAGE);
463 else
465 mri->mri_UpImage = mri->mri_DownImage = NULL;
468 if ((data->wd_Flags & MUIWF_USEBOTTOMSCROLLER) ||
469 (data->wd_Flags & MUIWF_USERIGHTSCROLLER))
470 mri->mri_SizeImage = CreateSysimage(mri->mri_DrawInfo, SIZEIMAGE);
471 else
472 mri->mri_SizeImage = NULL;
474 if (data->wd_CrtFlags & WFLG_BORDERLESS)
476 /* Infact borderless windows could also have borders (if they have
477 * a window title e.g. but since they look ugly anyway we ignore it
478 * for now */
479 mri->mri_BorderLeft = 0;
480 mri->mri_BorderRight = 0;
481 mri->mri_BorderTop = 0;
482 mri->mri_BorderBottom = 0;
484 else
486 mri->mri_BorderLeft = mri->mri_Screen->WBorLeft;
487 mri->mri_BorderTop =
488 mri->mri_Screen->WBorTop + mri->mri_Screen->Font->ta_YSize + 1;
489 temp_obj =
490 NewObject(NULL, "sysiclass", SYSIA_DrawInfo,
491 (IPTR) mri->mri_DrawInfo, SYSIA_Which, SIZEIMAGE, TAG_DONE);
492 if (temp_obj)
494 GetAttr(IA_Height, temp_obj, &val);
495 DisposeObject(temp_obj);
496 mri->mri_BorderBottom = val;
498 else
499 mri->mri_BorderBottom = mri->mri_Screen->WBorBottom;
502 return TRUE;
505 static void CleanupRenderInfo(Object *obj, struct MUI_WindowData *data,
506 struct MUI_RenderInfo *mri)
508 int i;
510 DisposeCustomFrames(mri);
512 if (mri->mri_LeftImage)
514 DisposeObject(mri->mri_LeftImage);
515 mri->mri_LeftImage = NULL;
517 if (mri->mri_RightImage)
519 DisposeObject(mri->mri_RightImage);
520 mri->mri_RightImage = NULL;
522 if (mri->mri_UpImage)
524 DisposeObject(mri->mri_UpImage);
525 mri->mri_UpImage = NULL;
527 if (mri->mri_DownImage)
529 DisposeObject(mri->mri_DownImage);
530 mri->mri_DownImage = NULL;
532 if (mri->mri_SizeImage)
534 DisposeObject(mri->mri_SizeImage);
535 mri->mri_SizeImage = NULL;
538 /* bug("CleanupRenderInfo\n"); */
539 for (i = 0; i < -MUIV_Font_NegCount; i++)
541 if (mri->mri_Fonts[i])
543 /* bug("CleanupRenderInfo: closing font %p (%s/%d)\n", */
544 /* mri->mri_Fonts[i], */
545 /* mri->mri_Fonts[i]->tf_Message.mn_Node.ln_Name, */
546 /* mri->mri_Fonts[i]->tf_YSize); */
547 CloseFont(mri->mri_Fonts[i]);
548 mri->mri_Fonts[i] = NULL;
551 ReleasePen(mri->mri_Colormap, mri->mri_PensStorage[MPEN_MARK]);
552 ReleasePen(mri->mri_Colormap, mri->mri_PensStorage[MPEN_HALFSHADOW]);
553 ReleasePen(mri->mri_Colormap, mri->mri_PensStorage[MPEN_HALFSHINE]);
554 FreeScreenDrawInfo(mri->mri_Screen, mri->mri_DrawInfo);
555 mri->mri_DrawInfo = NULL;
557 /* If a custom screen has been opened by zune, close it as soon as zero
558 * windows are opened. See above for comments about refactorization. */
559 if (muiGlobalInfo(obj)->mgi_CustomScreen)
561 BOOL screenclose = TRUE;
562 Object *_app = _app(obj);
563 if (_app != NULL)
565 struct List *store = NULL;
566 get(_app, MUIA_Application_WindowList, &store);
567 if (store != NULL)
569 if (!IsListEmpty(store))
570 screenclose = FALSE;
573 if (screenclose)
575 /* If the window's user screen really was the custom screen,
576 * clear the reference */
577 if (data->wd_UserScreen == muiGlobalInfo(obj)->mgi_CustomScreen)
578 data->wd_UserScreen = NULL;
580 CloseScreen(muiGlobalInfo(obj)->mgi_CustomScreen);
581 muiGlobalInfo(obj)->mgi_CustomScreen = NULL;
585 if (data->wd_Flags & MUIWF_SCREENLOCKED)
587 UnlockPubScreen(NULL, mri->mri_Screen);
588 data->wd_Flags &= ~MUIWF_SCREENLOCKED;
590 mri->mri_Screen = NULL;
593 static void ShowRenderInfo(struct MUI_RenderInfo *mri)
595 if (mri->mri_BufferBM)
597 mri->mri_RastPort = &mri->mri_BufferRP;
599 else
601 mri->mri_RastPort = mri->mri_Window->RPort;
605 static void HideRenderInfo(struct MUI_RenderInfo *mri)
607 mri->mri_RastPort = NULL;
610 static ULONG GetDefaultEvents(void)
612 return IDCMP_NEWSIZE | IDCMP_REFRESHWINDOW
613 | IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE | IDCMP_MENUPICK
614 | IDCMP_CLOSEWINDOW | IDCMP_RAWKEY | IDCMP_INTUITICKS
615 | IDCMP_ACTIVEWINDOW | IDCMP_INACTIVEWINDOW | IDCMP_GADGETUP;
618 static void ChangeEvents(struct MUI_WindowData *data, ULONG new_events)
620 struct MinNode *mn;
621 struct MUI_EventHandlerNode *ehn;
622 ULONG old_events = data->wd_Events;
624 for (mn = data->wd_EHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
626 ehn = (struct MUI_EventHandlerNode *)mn;
627 new_events |= ehn->ehn_Events;
630 /* sba: kill the IDCMP_VANILLAKEY flag. MUI doesn't do this but programs
631 ** which use this will behave different if they request for this flag
632 ** (also on MUI)
634 new_events &= ~IDCMP_VANILLAKEY;
636 data->wd_Events = new_events;
637 if ((old_events != new_events) && (data->wd_Flags & MUIWF_OPENED))
639 ModifyIDCMP(data->wd_RenderInfo.mri_Window, new_events);
643 static void CalcWindowPosition(Object *obj, struct MUI_WindowData *data);
644 static void CreateWindowScrollbars(Object *obj,
645 struct MUI_WindowData *data);
646 static void CalcAltDimensions(Object *obj, struct MUI_WindowData *data);
647 static void UndisplayWindow(Object *obj, struct MUI_WindowData *data);
648 static struct ObjNode *FindObjNode(struct MinList *list, Object *obj);
650 static BOOL DisplayWindow(Object *obj, struct MUI_WindowData *data)
652 struct Window *win;
653 ULONG flags = data->wd_CrtFlags;
654 struct IBox altdims;
655 ULONG backfill, buttons;
657 struct Menu *menu = NULL;
658 struct NewMenu *newmenu = NULL;
659 APTR visinfo = NULL;
661 Object *gadgets;
663 if (!(data->wd_Flags & MUIWF_DONTACTIVATE))
665 flags |= WFLG_ACTIVATE;
668 /* Toolboxes are handled differently on AmigaOS */
669 #ifdef __AROS__
670 if (data->wd_Flags & MUIWF_TOOLBOX)
671 flags |= WFLG_TOOLBOX;
672 #endif
674 if (data->wd_MinMax.MinHeight == data->wd_MinMax.MaxHeight
675 && data->wd_MinMax.MinWidth == data->wd_MinMax.MaxWidth)
676 flags &= ~WFLG_SIZEGADGET;
678 if (!(flags & WFLG_SIZEBRIGHT))
679 flags |= WFLG_SIZEBBOTTOM;
681 CalcWindowPosition(obj, data);
683 if ((visinfo = GetVisualInfoA(data->wd_RenderInfo.mri_Screen, NULL)))
685 if (data->wd_Menustrip)
687 get(data->wd_Menustrip, MUIA_Menuitem_NewMenu, &newmenu);
688 if (newmenu)
690 if ((menu = CreateMenusA(newmenu, NULL)))
692 struct TagItem tags[] = {
693 {GTMN_NewLookMenus, TRUE},
694 {TAG_DONE, (IPTR) NULL}
696 LayoutMenusA(menu, visinfo, tags);
700 FreeVisualInfo(visinfo);
703 CreateWindowScrollbars(obj, data);
704 CalcAltDimensions(obj, data);
705 altdims = data->wd_AltDim;
707 /* hack to account for border size, as we only know the innersize and
708 * must give the total size.
710 altdims.Width +=
711 data->wd_RenderInfo.mri_Screen->WBorLeft +
712 data->wd_RenderInfo.mri_Screen->WBorRight;
713 altdims.Height +=
714 data->wd_RenderInfo.mri_Screen->WBorTop +
715 data->wd_RenderInfo.mri_Screen->WBorBottom +
716 data->wd_RenderInfo.mri_DrawInfo->dri_Font->tf_YSize + 1;
718 if (muiGlobalInfo(obj)->mgi_Prefs->window_redraw ==
719 WINDOW_REDRAW_WITHOUT_CLEAR)
720 backfill = WA_BackFill;
721 else
722 backfill = TAG_IGNORE;
724 if (muiGlobalInfo(obj)->mgi_Prefs->window_refresh ==
725 WINDOW_REFRESH_SMART)
726 flags &= ~WFLG_SIMPLE_REFRESH;
727 set(_app(obj), MUIA_Application_SearchWinId, data->wd_ID);
728 struct windowpos *winp = 0;
729 get(_app(obj), MUIA_Application_GetWinPos, &winp);
730 if (winp)
732 if (data->wd_RenderInfo.mri_ScreenWidth >
733 (data->wd_X + data->wd_Width))
735 data->wd_X = winp->x1;
736 data->wd_Width = winp->w1;
738 if (data->wd_RenderInfo.mri_ScreenHeight >
739 (data->wd_Y + data->wd_Height))
741 data->wd_Y = winp->y1;
742 data->wd_Height = winp->h1;
746 gadgets =
747 (data->wd_VertProp !=
748 NULL) ? data->wd_VertProp : data->wd_HorizProp;
749 buttons = muiGlobalInfo(obj)->mgi_Prefs->window_buttons;
751 win = OpenWindowTags
752 (NULL,
753 WA_Left, (IPTR) data->wd_X,
754 WA_Top, (IPTR) data->wd_Y,
755 WA_Flags, (IPTR) flags,
756 data->wd_Title ?
757 WA_Title :
758 TAG_IGNORE, (IPTR) data->wd_Title,
759 data->wd_ScreenTitle ?
760 WA_ScreenTitle :
761 TAG_IGNORE, (IPTR) data->wd_ScreenTitle,
762 WA_CustomScreen, (IPTR) data->wd_RenderInfo.mri_Screen,
763 WA_InnerWidth, (IPTR) data->wd_Width,
764 WA_InnerHeight, (IPTR) data->wd_Height,
765 WA_AutoAdjust, (IPTR) TRUE, WA_NewLookMenus, (IPTR) TRUE,
766 /* AmigaOS v4 extension */
767 #ifdef WA_ToolBox
768 WA_ToolBox, (IPTR) ! !(data->wd_Flags & MUIWF_TOOLBOX),
769 #endif
770 /* MorphOS extensions */
771 #ifdef WA_ExtraGadget_MUI
772 WA_ExtraGadget_MUI,
773 (IPTR) ((buttons & MUIV_Window_Button_MUI) != 0) ? TRUE : FALSE,
774 WA_ExtraGadget_PopUp,
775 (IPTR) ((buttons & MUIV_Window_Button_Popup) != 0) ? TRUE : FALSE,
776 WA_ExtraGadget_Snapshot,
777 (IPTR) ((buttons & MUIV_Window_Button_Snapshot) !=
778 0) ? TRUE : FALSE, WA_ExtraGadget_Iconify,
779 (IPTR) ((buttons & MUIV_Window_Button_Iconify) != 0) ? TRUE : FALSE,
780 #endif
781 data->wd_NoMenus ?
782 WA_RMBTrap :
783 TAG_IGNORE, (IPTR) TRUE,
784 WA_Gadgets, (IPTR) gadgets,
785 data->wd_ZoomGadget ?
786 WA_Zoom :
787 TAG_IGNORE, (IPTR) & altdims,
788 backfill, (IPTR) LAYERS_NOBACKFILL, TAG_DONE);
790 if (win)
793 int hborders = win->BorderLeft + win->BorderRight;
794 int vborders = win->BorderTop + win->BorderBottom;
796 /* recalc window size (which will hopefully equal our requested
797 * size) */
798 data->wd_Width = win->GZZWidth;
799 data->wd_Height = win->GZZHeight;
801 /* set window limits according to window contents */
802 WindowLimits
803 (win, data->wd_MinMax.MinWidth + hborders,
804 data->wd_MinMax.MinHeight + vborders,
805 data->wd_MinMax.MaxWidth + hborders,
806 data->wd_MinMax.MaxHeight + vborders);
808 win->UserData = (BYTE *) data->wd_RenderInfo.mri_WindowObject;
809 win->UserPort = muiGlobalInfo(obj)->mgi_WindowsPort;
810 /* Same port for all windows */
811 ModifyIDCMP(win, data->wd_Events);
813 data->wd_RenderInfo.mri_Window = win;
814 data->wd_RenderInfo.mri_VertProp = data->wd_VertProp;
815 data->wd_RenderInfo.mri_HorizProp = data->wd_HorizProp;
816 SetDrMd(win->RPort, JAM1);
817 //text is draw wrong in toolbarclass if not set
819 if (menu)
821 data->wd_Menu = menu;
822 SetMenuStrip(win, menu);
825 if (flags & WFLG_ACTIVATE)
827 data->wd_Flags |= MUIWF_ACTIVE;
830 return TRUE;
833 if (menu)
834 FreeMenus(menu);
835 UndisplayWindow(obj, data);
837 return FALSE;
841 static void UndisplayWindow(Object *obj, struct MUI_WindowData *data)
843 struct Window *win = data->wd_RenderInfo.mri_Window;
844 BOOL prefssnap =
845 ((muiGlobalInfo(obj)->mgi_Prefs->window_position ==
846 WINDOW_POSITION_REMEMBER_ON_EXIT)
847 || (muiGlobalInfo(obj)->mgi_Prefs->window_position ==
848 WINDOW_POSITION_SAVE_ON_EXIT));
850 if (((data->wd_XStore >= 0) && (data->wd_YStore >= 0)) || prefssnap)
852 DoMethod(obj, MUIM_Window_Snapshot, 0);
855 data->wd_RenderInfo.mri_Window = NULL;
856 data->wd_RenderInfo.mri_VertProp = NULL;
857 data->wd_RenderInfo.mri_HorizProp = NULL;
859 data->wd_Flags &= ~MUIWF_ACTIVE;
861 if (win != NULL)
863 /* store position and size */
864 if (data->wd_XStore >= 0)
865 data->wd_X = win->LeftEdge;
866 else
867 data->wd_X = data->wd_XStore;
868 if (data->wd_YStore >= 0)
869 data->wd_Y = win->TopEdge;
870 else
871 data->wd_Y = data->wd_YStore;
872 data->wd_Width = win->GZZWidth;
873 data->wd_Height = win->GZZHeight;
875 ClearMenuStrip(win);
876 if (data->wd_Menu)
878 FreeMenus(data->wd_Menu);
879 data->wd_Menu = NULL;
882 if (win->UserPort)
884 struct IntuiMessage *msg, *succ;
886 /* remove all messages pending for this window */
887 Forbid();
888 for (msg =
889 (struct IntuiMessage *)win->UserPort->mp_MsgList.lh_Head;
890 (succ =
891 (struct IntuiMessage *)msg->ExecMessage.mn_Node.
892 ln_Succ); msg = succ)
894 if (msg->IDCMPWindow == win)
896 Remove((struct Node *)msg);
897 ReplyMsg((struct Message *)msg);
900 win->UserPort = NULL;
901 ModifyIDCMP(win, 0);
902 Permit();
905 /* D(bug("before CloseWindow\n")); */
906 CloseWindow(win);
907 /* D(bug("after CloseWindow\n")); */
910 #define DISPOSEGADGET(x) \
911 if (x)\
913 DoMethod(obj, MUIM_Window_FreeGadgetID,\
914 ((struct Gadget*)x)->GadgetID);\
915 DisposeObject(x);\
916 x = NULL;\
919 DISPOSEGADGET(data->wd_VertProp);
920 DISPOSEGADGET(data->wd_UpButton);
921 DISPOSEGADGET(data->wd_DownButton);
922 DISPOSEGADGET(data->wd_HorizProp);
923 DISPOSEGADGET(data->wd_LeftButton);
924 DISPOSEGADGET(data->wd_RightButton);
925 #undef DISPOSEGADGET
929 /* Initialize data->wd_X and data->wd_Y for DisplayWindow */
930 /* FIXME 20030817: needs some fixing, seems not fully implemented */
931 static void CalcWindowPosition(Object *obj, struct MUI_WindowData *data)
933 data->wd_XStore = data->wd_X;
934 data->wd_YStore = data->wd_Y;
935 if (NULL == data->wd_RefWindow)
937 /* The following calculations are not very correct, the size and
938 * dragbar are ignored also the current overscan view */
939 if (data->wd_X == MUIV_Window_LeftEdge_Centered)
941 data->wd_X =
942 (data->wd_RenderInfo.mri_Screen->ViewPort.DWidth -
943 data->wd_Width) / 2 -
944 data->wd_RenderInfo.mri_Screen->LeftEdge;
946 else if (data->wd_X == MUIV_Window_LeftEdge_Moused)
948 data->wd_X = data->wd_RenderInfo.mri_Screen->MouseX;
951 if (data->wd_Y == MUIV_Window_TopEdge_Centered)
953 data->wd_Y =
954 (data->wd_RenderInfo.mri_Screen->ViewPort.DHeight -
955 data->wd_Height) / 2 -
956 data->wd_RenderInfo.mri_Screen->TopEdge;
958 else if (data->wd_Y == MUIV_Window_TopEdge_Moused)
960 data->wd_Y = data->wd_RenderInfo.mri_Screen->MouseY;
962 else if (data->wd_Y <= MUIV_Window_TopEdge_Delta(0))
964 data->wd_Y = data->wd_RenderInfo.mri_Screen->BarHeight + 1
965 + MUIV_Window_TopEdge_Delta(0) - data->wd_Y;
968 else
970 ULONG w = 0, x = 0;
971 ULONG h = 0, y = 0;
973 get(data->wd_RefWindow, MUIA_Window_Width, &w);
974 get(data->wd_RefWindow, MUIA_Window_LeftEdge, &x);
976 if (data->wd_X == MUIV_Window_LeftEdge_Centered)
978 data->wd_X = x + (w - data->wd_Width) / 2;
980 else
982 data->wd_X += x;
985 get(data->wd_RefWindow, MUIA_Window_Height, &h);
986 get(data->wd_RefWindow, MUIA_Window_TopEdge, &y);
988 if (data->wd_Y == MUIV_Window_TopEdge_Centered)
990 /* D(bug("y=%ld, h=%ld, wdh=%ld\n", y, h, data->wd_Height)); */
991 data->wd_Y = y + (h - data->wd_Height) / 2;
993 else if (data->wd_Y <= MUIV_Window_TopEdge_Delta(0))
995 /* ??? surely incorrect implementation */
996 data->wd_Y = y + 1 + MUIV_Window_TopEdge_Delta(0) - data->wd_Y;
998 else
1000 data->wd_Y += y;
1005 /* Initialize data->wd_AltDim for DisplayWindow */
1006 static void CalcAltDimensions(Object *obj, struct MUI_WindowData *data)
1008 /* Calculate alternate (zoomed) dimensions.
1010 if (data->wd_AltDim.Top == MUIV_Window_AltTopEdge_NoChange)
1011 data->wd_AltDim.Top = ~0;
1012 else if (data->wd_AltDim.Top == MUIV_Window_AltTopEdge_Centered)
1013 data->wd_AltDim.Top =
1014 (data->wd_RenderInfo.mri_Screen->Height - data->wd_Height) / 2;
1015 else if (data->wd_AltDim.Top == MUIV_Window_AltTopEdge_Moused)
1016 /* ? */ data->wd_AltDim.Top = ~0;
1018 if (data->wd_AltDim.Left == MUIV_Window_AltLeftEdge_NoChange)
1019 data->wd_AltDim.Left = ~0;
1020 else if (data->wd_AltDim.Left == MUIV_Window_AltLeftEdge_Centered)
1021 data->wd_AltDim.Left =
1022 (data->wd_RenderInfo.mri_Screen->Width - data->wd_Width) / 2;
1023 else if (data->wd_AltDim.Left == MUIV_Window_AltLeftEdge_Moused)
1024 /* ? */ data->wd_AltDim.Left = ~0;
1026 if (_between
1027 (MUIV_Window_AltWidth_MinMax(100),
1028 data->wd_AltDim.Width, MUIV_Window_AltWidth_MinMax(0)))
1030 data->wd_AltDim.Width = data->wd_MinMax.MinWidth
1031 - data->wd_AltDim.Width
1032 * (data->wd_MinMax.MaxWidth - data->wd_MinMax.MinWidth);
1034 else if
1035 (_between
1036 (MUIV_Window_AltWidth_Screen(100),
1037 data->wd_AltDim.Width, MUIV_Window_AltWidth_Screen(0)))
1039 data->wd_AltDim.Width = data->wd_RenderInfo.mri_ScreenWidth
1040 * (-(data->wd_AltDim.Width + 200)) / 100;
1042 else if
1043 (_between
1044 (MUIV_Window_AltWidth_Visible(100),
1045 data->wd_AltDim.Width, MUIV_Window_AltWidth_Visible(0)))
1047 data->wd_AltDim.Width = data->wd_RenderInfo.mri_ScreenWidth
1048 * (-(data->wd_AltDim.Width + 100)) / 100;
1051 if (_between
1052 (MUIV_Window_AltHeight_MinMax(100),
1053 data->wd_AltDim.Height, MUIV_Window_AltHeight_MinMax(0)))
1055 data->wd_AltDim.Height = data->wd_MinMax.MinHeight
1056 - data->wd_AltDim.Height
1057 * (data->wd_MinMax.MaxHeight - data->wd_MinMax.MinHeight);
1059 else if
1060 (_between
1061 (MUIV_Window_AltHeight_Screen(100),
1062 data->wd_AltDim.Height, MUIV_Window_AltHeight_Screen(0)))
1064 data->wd_AltDim.Height = data->wd_RenderInfo.mri_ScreenHeight
1065 * (-(data->wd_AltDim.Height + 200)) / 100;
1067 else if
1068 (_between
1069 (MUIV_Window_AltHeight_Visible(100),
1070 data->wd_AltDim.Height, MUIV_Window_AltHeight_Visible(0)))
1072 data->wd_AltDim.Height = data->wd_RenderInfo.mri_ScreenHeight
1073 * (-(data->wd_AltDim.Height + 100)) / 100;
1076 data->wd_AltDim.Width = CLAMP
1077 (data->wd_AltDim.Width, data->wd_MinMax.MinWidth,
1078 data->wd_MinMax.MaxWidth);
1079 data->wd_AltDim.Height = CLAMP
1080 (data->wd_AltDim.Height, data->wd_MinMax.MinHeight,
1081 data->wd_MinMax.MaxHeight);
1085 /* Create horiz/vert window scrollbars for DisplayWindow */
1086 static void CreateWindowScrollbars(Object *obj,
1087 struct MUI_WindowData *data)
1089 struct MUI_RenderInfo *mri = &data->wd_RenderInfo;
1090 Object *firstgad = NULL;
1091 Object *prevgad = NULL;
1092 LONG id;
1094 /* Create the right border scrollers now if requested */
1095 if (data->wd_Flags & MUIWF_USERIGHTSCROLLER)
1097 int voffset;
1099 voffset = IM(mri->mri_DownImage)->Width / 4;
1101 id = DoMethod(obj, MUIM_Window_AllocGadgetID);
1102 firstgad = prevgad = data->wd_VertProp = NewObject
1103 (NULL, "propgclass",
1104 GA_RelRight, 1 - (IM(mri->mri_UpImage)->Width - voffset),
1105 GA_Top, mri->mri_BorderTop + 2,
1106 GA_Width, IM(mri->mri_UpImage)->Width - voffset * 2,
1107 GA_RelHeight, -(mri->mri_BorderTop + 2)
1108 - IM(mri->mri_UpImage)->Height
1109 - IM(mri->mri_DownImage)->Height
1110 - IM(mri->mri_SizeImage)->Height - 2,
1111 GA_RightBorder, TRUE,
1112 GA_ID, id,
1113 PGA_Borderless, TRUE,
1114 PGA_NewLook, TRUE,
1115 PGA_Freedom, FREEVERT,
1116 PGA_Top, 0,
1117 PGA_Total, 2,
1118 PGA_Visible, 1, ICA_TARGET, ICTARGET_IDCMP, TAG_DONE);
1120 id = DoMethod(obj, MUIM_Window_AllocGadgetID);
1121 prevgad = data->wd_UpButton = NewObject
1122 (NULL, "buttongclass",
1123 GA_Image, (IPTR) mri->mri_UpImage,
1124 GA_RelRight, 1 - IM(mri->mri_UpImage)->Width,
1125 GA_RelBottom, 1 - IM(mri->mri_UpImage)->Height
1126 - IM(mri->mri_DownImage)->Height
1127 - IM(mri->mri_SizeImage)->Height,
1128 GA_RightBorder, TRUE,
1129 GA_Previous, (IPTR) prevgad,
1130 GA_ID, id, ICA_TARGET, ICTARGET_IDCMP, TAG_DONE);
1132 id = DoMethod(obj, MUIM_Window_AllocGadgetID);
1133 prevgad = data->wd_DownButton = NewObject
1134 (NULL, "buttongclass",
1135 GA_Image, (IPTR) mri->mri_DownImage,
1136 GA_RelRight, 1 - IM(mri->mri_DownImage)->Width,
1137 GA_RelBottom, 1 - IM(mri->mri_DownImage)->Height
1138 - IM(mri->mri_SizeImage)->Height,
1139 GA_RightBorder, TRUE,
1140 GA_Previous, (IPTR) prevgad,
1141 GA_ID, id, ICA_TARGET, ICTARGET_IDCMP, TAG_DONE);
1144 /* Create the bottom border scrollers now if requested */
1145 if (data->wd_Flags & MUIWF_USEBOTTOMSCROLLER)
1147 int hoffset;
1149 hoffset = IM(mri->mri_RightImage)->Height / 4;
1151 id = DoMethod(obj, MUIM_Window_AllocGadgetID);
1152 prevgad = data->wd_HorizProp = NewObject
1153 (NULL, "propgclass",
1154 GA_RelBottom, 1 - (IM(mri->mri_LeftImage)->Height - hoffset),
1155 GA_Left, mri->mri_BorderLeft,
1156 GA_Height, IM(mri->mri_LeftImage)->Height
1157 - hoffset * 2,
1158 GA_RelWidth, -(mri->mri_BorderLeft)
1159 - IM(mri->mri_LeftImage)->Width
1160 - IM(mri->mri_RightImage)->Width
1161 - IM(mri->mri_SizeImage)->Width
1162 - 2,
1163 GA_BottomBorder, TRUE,
1164 GA_ID, id,
1165 prevgad ? GA_Previous : TAG_IGNORE, (IPTR) prevgad,
1166 PGA_Borderless, TRUE,
1167 PGA_NewLook, TRUE,
1168 PGA_Freedom, FREEHORIZ,
1169 PGA_Top, 0,
1170 PGA_Total, 2,
1171 PGA_Visible, 1, ICA_TARGET, ICTARGET_IDCMP, TAG_DONE);
1173 if (!firstgad)
1174 firstgad = prevgad;
1176 id = DoMethod(obj, MUIM_Window_AllocGadgetID);
1177 prevgad = data->wd_LeftButton = NewObject
1178 (NULL, "buttongclass",
1179 GA_Image, (IPTR) mri->mri_LeftImage,
1180 GA_RelRight, 1 - IM(mri->mri_LeftImage)->Width
1181 - IM(mri->mri_RightImage)->Width
1182 - IM(mri->mri_SizeImage)->Width,
1183 GA_RelBottom, 1 - IM(mri->mri_LeftImage)->Height,
1184 GA_BottomBorder, TRUE,
1185 GA_Previous, (IPTR) prevgad,
1186 GA_ID, id, ICA_TARGET, ICTARGET_IDCMP, TAG_DONE);
1188 id = DoMethod(obj, MUIM_Window_AllocGadgetID);
1189 prevgad = data->wd_RightButton = NewObject
1190 (NULL, "buttongclass",
1191 GA_Image, (IPTR) mri->mri_RightImage,
1192 GA_RelRight, 1 - IM(mri->mri_RightImage)->Width
1193 - IM(mri->mri_SizeImage)->Width,
1194 GA_RelBottom, 1 - IM(mri->mri_RightImage)->Height,
1195 GA_BottomBorder, TRUE,
1196 GA_Previous, (IPTR) prevgad,
1197 GA_ID, id, ICA_TARGET, ICTARGET_IDCMP, TAG_DONE);
1201 /* return FALSE only if no resize (dx=dy=0) occured */
1202 static BOOL WindowResize(struct MUI_WindowData *data)
1204 struct Window *win = data->wd_RenderInfo.mri_Window;
1205 int hborders = win->BorderLeft + win->BorderRight;
1206 int vborders = win->BorderTop + win->BorderBottom;
1207 WORD dx = data->wd_Width - win->Width + hborders;
1208 WORD dy = data->wd_Height - win->Height + vborders;
1210 /* Temporarily disable window limits to let SizeWindow below work
1211 regardless of the previous limits */
1212 WindowLimits(win, 1, 1, -1, -1);
1213 /* D(bug("_zune_window_resize : dx=%d, dy=%d\n", dx, dy)); */
1214 SizeWindow(win, dx, dy);
1216 /* Set new window limits */
1217 WindowLimits
1218 (win, data->wd_MinMax.MinWidth + hborders,
1219 data->wd_MinMax.MinHeight + vborders,
1220 data->wd_MinMax.MaxWidth + hborders,
1221 data->wd_MinMax.MaxHeight + vborders);
1223 return dx || dy;
1226 static void KillHelpBubble(struct MUI_WindowData *data, Object *obj,
1227 BOOL kill_bubblemode)
1229 if (data->wd_HelpObject)
1231 DoMethod(data->wd_HelpObject, MUIM_DeleteBubble,
1232 (IPTR) data->wd_HelpBubble);
1233 data->wd_HelpObject = NULL;
1234 data->wd_HelpBubble = NULL;
1237 if (kill_bubblemode)
1238 data->wd_Flags &= ~MUIWF_BUBBLEMODE;
1240 if (data->wd_Flags & MUIWF_BUBBLEMODE)
1242 data->wd_HelpTicker = BUBBLEHELP_TICKER_LATER;
1244 else
1246 data->wd_HelpTicker = BUBBLEHELP_TICKER_FIRST;
1251 /**************/
1253 typedef BOOL(*UNDERCHECK_FUNC) (Object *obj);
1255 static BOOL ShortHelpUnderPointerCheck(Object *obj)
1257 return muiAreaData(obj)->mad_ShortHelp ? TRUE : FALSE;
1260 static Object *ObjectUnderPointer(struct MUI_WindowData *data, Object *obj,
1261 LONG x, LONG y, UNDERCHECK_FUNC func)
1263 Object *cstate;
1264 Object *child;
1265 struct MinList *ChildList = NULL;
1267 if (!(muiAreaData(obj)->mad_Flags & MADF_CANDRAW))
1268 return NULL;
1270 if (!(x >= _left(obj) && x <= _right(obj)
1271 && y >= _top(obj) && y <= _bottom(obj)))
1273 return NULL;
1276 if ((get(obj, MUIA_Group_ChildList, &(ChildList)))
1277 && (ChildList != NULL))
1279 cstate = (Object *) ChildList->mlh_Head;
1280 while ((child = NextObject(&cstate)))
1282 Object *ret;
1284 if ((x >= _left(child) && x <= _right(child)
1286 y >= _top(child) && y <= _bottom(child))
1287 && (ret = ObjectUnderPointer(data, child, x, y, func)))
1289 return ret;
1294 if (!(*func) (obj))
1295 return NULL;
1297 return obj;
1300 static BOOL ContextMenuUnderPointer(struct MUI_WindowData *data,
1301 Object *obj, LONG x, LONG y)
1303 Object *cstate;
1304 Object *child;
1305 struct MinList *ChildList = NULL;
1307 if (!(x >= _left(obj) && x <= _right(obj)
1308 && y >= _top(obj) && y <= _bottom(obj)))
1310 return FALSE;
1313 if ((get(obj, MUIA_Group_ChildList, &(ChildList)))
1314 && (ChildList != NULL))
1317 cstate = (Object *) ChildList->mlh_Head;
1318 while ((child = NextObject(&cstate)))
1320 if ((x >= _left(child) && x <= _right(child)
1322 y >= _top(child) && y <= _bottom(child))
1323 && (ContextMenuUnderPointer(data, child, x, y)))
1324 return TRUE;
1328 if (!(muiAreaData(obj)->mad_Flags & MADF_CANDRAW))
1329 return FALSE;
1330 if (!(muiAreaData(obj)->mad_ContextMenu))
1331 return FALSE;
1333 return TRUE;
1336 /**************/
1338 static void ActivateObject(struct MUI_WindowData *data)
1340 //bug("Window::ActivateObject (dummy) %08lx\n", data->wd_ActiveObject);
1341 // if (FindObjNode(&data->wd_CycleChain, data->wd_ActiveObject))
1342 // DoMethod(data->wd_ActiveObject, MUIM_GoActive);
1343 // else
1344 // data->wd_ActiveObject = NULL;
1346 //activate better string gadgets.Fix from Georg S On ML List
1347 if (FindObjNode(&data->wd_CycleChain, data->wd_ActiveObject))
1349 if (!(data->wd_Flags & MUIWF_OBJECTGOACTIVESENT))
1351 data->wd_Flags |= MUIWF_OBJECTGOACTIVESENT;
1352 DoMethod(data->wd_ActiveObject, MUIM_GoActive);
1355 else
1356 data->wd_ActiveObject = NULL;
1359 /**************/
1361 static void HandleInputEvent(Object *win, struct MUI_WindowData *data,
1362 struct IntuiMessage *event);
1364 /* handle intuimessage while an object is being dragged
1365 * (reply imsg before returning)
1367 void HandleDragging(Object *oWin, struct MUI_WindowData *data,
1368 struct IntuiMessage *imsg)
1370 struct Window *iWin;
1371 int finish_drag = 0;
1373 iWin = imsg->IDCMPWindow;
1375 if (imsg->Class == IDCMP_MOUSEMOVE)
1377 struct Layer *layer;
1378 layer =
1379 WhichLayer(&iWin->WScreen->LayerInfo,
1380 iWin->LeftEdge + imsg->MouseX, iWin->TopEdge + imsg->MouseY);
1382 if (data->wd_DropObject)
1384 struct Window *wnd;
1385 WORD mousex =
1386 imsg->MouseX + iWin->LeftEdge -
1387 data->wd_DropWindow->LeftEdge;
1388 WORD mousey =
1389 imsg->MouseY + iWin->TopEdge - data->wd_DropWindow->TopEdge;
1391 wnd = _window(data->wd_DropObject);
1392 if (mousex < _left(data->wd_DropObject)
1393 || mousex > _right(data->wd_DropObject)
1394 || mousey < _top(data->wd_DropObject)
1395 || mousey > _bottom(data->wd_DropObject)
1396 || layer != wnd->WLayer)
1398 /* We have left the object */
1399 UndrawDragNDrop(data->wd_dnd);
1400 DoMethod(data->wd_DropObject, MUIM_DragFinish,
1401 (IPTR) data->wd_DragObject);
1402 data->wd_DropObject = NULL;
1404 } /* if (data->wd_DropObject) */
1406 if (!data->wd_DropObject)
1408 Object *dest_wnd = NULL;
1410 /* Find out if app has an openend window at this position */
1411 if (layer)
1413 Object *cstate;
1414 Object *child;
1415 struct MinList *ChildList = 0;
1417 get(_app(oWin), MUIA_Application_WindowList, &(ChildList));
1418 cstate = (Object *) ChildList->mlh_Head;
1419 while ((child = NextObject(&cstate)))
1421 struct Window *wnd = NULL;
1422 get(child, MUIA_Window_Window, &wnd);
1423 if (!wnd)
1424 continue;
1426 if (wnd->WLayer == layer)
1428 data->wd_DropWindow = wnd;
1429 dest_wnd = child;
1430 break;
1433 } /* if (layer) */
1435 if (dest_wnd)
1437 Object *root = NULL;
1438 get(dest_wnd, MUIA_Window_RootObject, &root);
1440 if (root)
1442 if ((data->wd_DropObject = (Object *) DoMethod
1443 (root, MUIM_DragQueryExtended,
1444 (IPTR) data->wd_DragObject,
1445 imsg->MouseX + iWin->LeftEdge -
1446 data->wd_DropWindow->LeftEdge,
1447 imsg->MouseY + iWin->TopEdge -
1448 data->wd_DropWindow->TopEdge)))
1450 UndrawDragNDrop(data->wd_dnd);
1451 DoMethod(data->wd_DropObject, MUIM_DragBegin,
1452 (IPTR) data->wd_DragObject);
1458 if (data->wd_DropObject)
1460 LONG update = 0;
1461 LONG i;
1462 for (i = 0; i < 2; i++)
1464 LONG res = DoMethod(data->wd_DropObject, MUIM_DragReport,
1465 (IPTR) data->wd_DragObject,
1466 imsg->MouseX + iWin->LeftEdge -
1467 data->wd_DropWindow->LeftEdge,
1468 imsg->MouseY + iWin->TopEdge -
1469 data->wd_DropWindow->TopEdge, update);
1470 switch (res)
1472 case MUIV_DragReport_Abort:
1473 UndrawDragNDrop(data->wd_dnd);
1474 DoMethod(data->wd_DropObject, MUIM_DragFinish,
1475 (IPTR) data->wd_DragObject);
1476 data->wd_DropObject = NULL;
1477 i = 1;
1478 break;
1480 case MUIV_DragReport_Continue:
1481 break;
1482 case MUIV_DragReport_Lock:
1483 break; /* NYI */
1484 case MUIV_DragReport_Refresh:
1485 UndrawDragNDrop(data->wd_dnd);
1486 update = 1;
1487 break;
1491 DrawDragNDrop(data->wd_dnd, imsg->MouseX + iWin->LeftEdge,
1492 imsg->MouseY + iWin->TopEdge);
1495 if (imsg->Class == IDCMP_MOUSEBUTTONS)
1497 if ((imsg->Code == MENUDOWN) || (imsg->Code == SELECTUP))
1499 if (imsg->Code == SELECTUP && data->wd_DropObject)
1501 UndrawDragNDrop(data->wd_dnd);
1502 DoMethod(data->wd_DropObject, MUIM_DragFinish,
1503 (IPTR) data->wd_DragObject);
1504 DoMethod(data->wd_DropObject, MUIM_DragDrop,
1505 (IPTR) data->wd_DragObject,
1506 imsg->MouseX + iWin->LeftEdge -
1507 data->wd_DropWindow->LeftEdge,
1508 imsg->MouseY + iWin->TopEdge -
1509 data->wd_DropWindow->TopEdge);
1510 data->wd_DropObject = NULL;
1512 else if (imsg->Code == SELECTUP)
1514 DoMethod(data->wd_DragObject, MUIM_UnknownDropDestination,
1515 imsg);
1517 finish_drag = 1;
1521 if (imsg->Class == IDCMP_CLOSEWINDOW)
1522 finish_drag = 1;
1524 if (finish_drag)
1526 UndrawDragNDrop(data->wd_dnd);
1527 if (data->wd_DropObject)
1529 DoMethod(data->wd_DropObject, MUIM_DragFinish,
1530 (IPTR) data->wd_DragObject);
1531 data->wd_DropObject = NULL;
1533 DeleteDragNDrop(data->wd_dnd);
1534 DoMethod(data->wd_DragObject, MUIM_DeleteDragImage,
1535 (IPTR) data->wd_DragImage);
1536 muiAreaData(data->wd_DragObject)->mad_Flags &= ~MADF_DRAGGING;
1537 data->wd_DragImage = NULL;
1538 data->wd_DragObject = NULL;
1539 data->wd_DropWindow = NULL;
1540 data->wd_dnd = NULL;
1542 /* stop listening to IDCMP_MOUSEMOVE */
1543 ChangeEvents(data, GetDefaultEvents());
1545 ReplyMsg((struct Message *)imsg);
1548 /* Reply to imsg if handled */
1549 BOOL HandleWindowEvent(Object *oWin, struct MUI_WindowData *data,
1550 struct IntuiMessage *imsg)
1552 struct Window *iWin;
1553 BOOL is_handled = TRUE;
1554 BOOL replied = FALSE;
1556 iWin = imsg->IDCMPWindow;
1557 switch (imsg->Class)
1559 case IDCMP_ACTIVEWINDOW:
1560 data->wd_Flags |= MUIWF_ACTIVE;
1561 if (data->wd_OldActive)
1562 set(oWin, MUIA_Window_ActiveObject, data->wd_OldActive);
1563 set(oWin, MUIA_Window_Activate, TRUE);
1564 is_handled = FALSE; /* forwardable to area event handlers */
1565 break;
1567 case IDCMP_INACTIVEWINDOW:
1568 KillHelpBubble(data, oWin, TRUE);
1569 if (data->wd_ActiveObject)
1571 data->wd_OldActive = data->wd_ActiveObject;
1572 set(oWin, MUIA_Window_ActiveObject,
1573 MUIV_Window_ActiveObject_None);
1575 data->wd_Flags &= ~MUIWF_ACTIVE;
1576 set(oWin, MUIA_Window_Activate, FALSE);
1577 is_handled = FALSE; /* forwardable to area event handlers */
1578 break;
1580 case IDCMP_NEWSIZE:
1581 ReplyMsg((struct Message *)imsg);
1582 replied = TRUE;
1585 int hborders = iWin->BorderLeft + iWin->BorderRight;
1586 int vborders = iWin->BorderTop + iWin->BorderBottom;
1588 /* set window limits according to window contents */
1589 WindowLimits
1590 (iWin,
1591 data->wd_MinMax.MinWidth + hborders,
1592 data->wd_MinMax.MinHeight + vborders,
1593 data->wd_MinMax.MaxWidth + hborders,
1594 data->wd_MinMax.MaxHeight + vborders);
1597 if ((iWin->GZZWidth != data->wd_Width)
1598 || (iWin->GZZHeight != data->wd_Height))
1600 data->wd_Width = iWin->GZZWidth;
1601 data->wd_Height = iWin->GZZHeight;
1602 DoHideMethod(data->wd_RootObject);
1604 if (1)
1605 // why only simple refresh? was: if (
1606 // data->wd_RenderInfo.mri_Window->Flags & WFLG_SIMPLE_REFRESH)
1608 data->wd_Flags |= MUIWF_RESIZING;
1610 else
1612 _width(data->wd_RootObject) = data->wd_Width;
1613 _height(data->wd_RootObject) = data->wd_Height;
1614 DoMethod(data->wd_RootObject, MUIM_Layout);
1615 DoShowMethod(data->wd_RootObject);
1617 LONG left, top, width, height;
1619 left = data->wd_RenderInfo.mri_Window->BorderLeft;
1620 top = data->wd_RenderInfo.mri_Window->BorderTop,
1621 width = data->wd_RenderInfo.mri_Window->Width
1622 - data->wd_RenderInfo.mri_Window->BorderRight -
1623 left;
1624 height =
1625 data->wd_RenderInfo.mri_Window->Height -
1626 data->wd_RenderInfo.mri_Window->BorderBottom - top;
1628 //D(bug("%d:zune_imspec_draw(%p) "
1629 // "l=%d t=%d w=%d h=%d xo=%d yo=%d\n",
1630 // __LINE__, data->wd_Background, left, top, width,
1631 // height, left, top));
1632 zune_imspec_draw(data->wd_Background,
1633 &data->wd_RenderInfo, left, top, width, height,
1634 left, top, 0);
1636 if (muiGlobalInfo(oWin)->mgi_Prefs->window_redraw ==
1637 WINDOW_REDRAW_WITHOUT_CLEAR)
1638 MUI_Redraw(data->wd_RootObject, MADF_DRAWOBJECT);
1639 else
1640 MUI_Redraw(data->wd_RootObject, MADF_DRAWALL);
1641 // but should only draw focus without using MUIM_GoActive !
1642 ActivateObject(data);
1645 break;
1647 case IDCMP_REFRESHWINDOW:
1648 ReplyMsg((struct Message *)imsg);
1649 replied = TRUE;
1650 if (data->wd_Flags & MUIWF_RESIZING)
1652 //LONG left,top,right,bottom;
1653 if (MUI_BeginRefresh(&data->wd_RenderInfo, 0))
1655 MUI_EndRefresh(&data->wd_RenderInfo, 0);
1657 RefreshWindowFrame(data->wd_RenderInfo.mri_Window);
1659 data->wd_Flags &= ~MUIWF_RESIZING;
1660 _width(data->wd_RootObject) = data->wd_Width;
1661 _height(data->wd_RootObject) = data->wd_Height;
1662 DoMethod(data->wd_RootObject, MUIM_Layout);
1663 DoShowMethod(data->wd_RootObject);
1665 if (muiGlobalInfo(oWin)->mgi_Prefs->window_redraw ==
1666 WINDOW_REDRAW_WITH_CLEAR)
1668 LONG left, top, width, height;
1670 left = data->wd_RenderInfo.mri_Window->BorderLeft;
1671 top = data->wd_RenderInfo.mri_Window->BorderTop;
1672 width =
1673 data->wd_RenderInfo.mri_Window->Width -
1674 data->wd_RenderInfo.mri_Window->BorderRight - left;
1675 height =
1676 data->wd_RenderInfo.mri_Window->Height -
1677 data->wd_RenderInfo.mri_Window->BorderBottom - top;
1679 if (data->wd_Flags & MUIWF_ERASEAREA)
1681 //D(bug("%d:zune_imspec_draw(%p) "
1682 // "l=%d t=%d w=%d h=%d xo=%d yo=%d\n",
1683 // __LINE__, data->wd_Background, left, top, width,
1684 // height, left, top));
1685 zune_imspec_draw(data->wd_Background,
1686 &data->wd_RenderInfo, left, top, width, height,
1687 left, top, 0);
1689 MUI_Redraw(data->wd_RootObject, MADF_DRAWALL);
1691 else
1692 MUI_Redraw(data->wd_RootObject, MADF_DRAWOBJECT);
1693 // but should only draw focus without using MUIM_GoActive !
1694 ActivateObject(data);
1696 else
1698 if (MUI_BeginRefresh(&data->wd_RenderInfo, 0))
1700 MUI_Redraw(data->wd_RootObject, MADF_DRAWALL);
1701 // but should only draw focus without using MUIM_GoActive !
1702 ActivateObject(data);
1703 MUI_EndRefresh(&data->wd_RenderInfo, 0);
1706 break;
1708 case IDCMP_CLOSEWINDOW:
1709 ReplyMsg((struct Message *)imsg);
1710 replied = TRUE;
1711 set(oWin, MUIA_Window_CloseRequest, TRUE);
1712 break;
1714 case IDCMP_MENUPICK:
1715 ReplyMsg((struct Message *)imsg);
1716 replied = TRUE;
1718 if (data->wd_Menu)
1720 if (MENUNUM(imsg->Code) != NOMENU
1721 && ITEMNUM(imsg->Code) != NOITEM)
1723 struct MenuItem *item =
1724 ItemAddress(data->wd_Menu, imsg->Code);
1725 if (item)
1727 Object *item_obj = (Object *) GTMENUITEM_USERDATA(item);
1728 if (item_obj)
1730 Object *app = NULL;
1731 IPTR udata = 0;
1733 if (item->Flags & CHECKIT)
1734 set(item_obj, MUIA_Menuitem_Checked,
1735 ! !(item->Flags & CHECKED));
1737 set(item_obj, MUIA_Menuitem_Trigger, (IPTR) item);
1739 get(oWin, MUIA_ApplicationObject, &app);
1740 get(item_obj, MUIA_UserData, &udata);
1742 set(app, MUIA_Application_MenuAction, udata);
1743 set(oWin, MUIA_Window_MenuAction, udata);
1744 DoMethod(app, MUIM_Application_ReturnID, udata);
1749 break;
1751 case IDCMP_IDCMPUPDATE:
1752 is_handled = FALSE; /* forwardable to area event handlers */
1753 if (data->wd_VertProp || data->wd_HorizProp)
1755 struct TagItem *tag;
1756 tag = FindTagItem(GA_ID, (struct TagItem *)imsg->IAddress);
1757 if (tag)
1759 /* If there's a propclass object connected to the prop
1760 gadget, the prop gadget's userdata will point to
1761 that propclass object. See classes/prop.c */
1763 if (data->wd_VertProp)
1765 if (tag->ti_Data == GADGETID(data->wd_VertProp))
1768 if (tag->ti_Data == GADGETID(data->wd_UpButton))
1770 Object *prop =
1771 (Object *) ((struct Gadget *)data->
1772 wd_VertProp)->UserData;
1773 is_handled = TRUE;
1774 if (prop)
1775 DoMethod(prop, MUIM_Prop_Decrease, 1);
1778 if (tag->ti_Data == GADGETID(data->wd_DownButton))
1780 Object *prop =
1781 (Object *) ((struct Gadget *)data->
1782 wd_VertProp)->UserData;
1783 is_handled = TRUE;
1784 if (prop)
1785 DoMethod(prop, MUIM_Prop_Increase, 1);
1790 if (data->wd_HorizProp)
1792 if (tag->ti_Data == GADGETID(data->wd_HorizProp))
1795 if (tag->ti_Data == GADGETID(data->wd_LeftButton))
1797 Object *prop =
1798 (Object *) ((struct Gadget *)data->
1799 wd_HorizProp)->UserData;
1800 is_handled = TRUE;
1801 if (prop)
1802 DoMethod(prop, MUIM_Prop_Decrease, 1);
1805 if (tag->ti_Data == GADGETID(data->wd_RightButton))
1807 Object *prop =
1808 (Object *) ((struct Gadget *)data->
1809 wd_HorizProp)->UserData;
1810 is_handled = TRUE;
1811 if (prop)
1812 DoMethod(prop, MUIM_Prop_Increase, 1);
1818 break;
1820 case IDCMP_INTUITICKS:
1821 if (data->wd_HelpTicker)
1823 data->wd_HelpTicker--;
1825 if (data->wd_HelpTicker == 0)
1827 Object *underobj =
1828 ObjectUnderPointer(data, data->wd_RootObject,
1829 imsg->MouseX, imsg->MouseY,
1830 ShortHelpUnderPointerCheck);
1832 if (underobj != data->wd_HelpObject)
1834 if (data->wd_HelpObject)
1836 DoMethod(data->wd_HelpObject, MUIM_DeleteBubble,
1837 (IPTR) data->wd_HelpBubble);
1839 data->wd_HelpObject = NULL;
1840 data->wd_HelpBubble = NULL;
1843 if (underobj)
1845 data->wd_HelpBubble =
1846 (APTR) DoMethod(underobj, MUIM_CreateBubble,
1847 imsg->MouseX, imsg->MouseY, 0, 0);
1848 if (data->wd_HelpBubble)
1850 data->wd_HelpObject = underobj;
1851 data->wd_Flags |= MUIWF_BUBBLEMODE;
1856 if (data->wd_Flags & MUIWF_BUBBLEMODE)
1858 data->wd_HelpTicker = BUBBLEHELP_TICKER_LATER;
1860 else
1862 data->wd_HelpTicker = BUBBLEHELP_TICKER_FIRST;
1867 is_handled = FALSE; /* forwardable to area event handlers */
1868 break;
1870 case IDCMP_MOUSEBUTTONS:
1871 DoMethod(oWin, MUIM_Window_Snapshot, 0);
1872 KillHelpBubble(data, oWin, TRUE);
1873 is_handled = FALSE;
1874 break;
1877 case IDCMP_MOUSEMOVE:
1878 KillHelpBubble(data, oWin, FALSE);
1879 is_handled = FALSE;
1880 break;
1882 default:
1883 is_handled = FALSE;
1884 break;
1887 if (is_handled && !replied)
1888 ReplyMsg((struct Message *)imsg);
1890 return is_handled;
1893 static ULONG InvokeEventHandler(struct MUI_EventHandlerNode *ehn,
1894 struct IntuiMessage *event, ULONG muikey)
1896 ULONG res;
1898 if (!(_flags(ehn->ehn_Object) & MADF_CANDRAW))
1899 return 0;
1900 if (!(_flags(ehn->ehn_Object) & MADF_SHOWME))
1901 return 0;
1903 if (event != NULL
1904 && event->Class == IDCMP_MOUSEBUTTONS
1905 && event->Code == SELECTDOWN
1906 && (_flags(ehn->ehn_Object) & MADF_INVIRTUALGROUP))
1909 Here we filter out SELECTDOWN messages if objects is in a virtual
1910 group but the click went out of the virtual group
1912 Object *obj = ehn->ehn_Object;
1913 Object *parent = obj;
1914 Object *wnd = _win(obj);
1916 while (get(parent, MUIA_Parent, &parent))
1918 if (!parent)
1919 break;
1920 if (wnd == parent)
1921 break;
1922 if (_flags(parent) & MADF_ISVIRTUALGROUP)
1924 if (event->MouseX < _mleft(parent)
1925 || event->MouseX > _mright(parent)
1926 || event->MouseY < _mtop(parent)
1927 || event->MouseY > _mbottom(parent))
1929 return 0;
1936 if (ehn->ehn_Flags & MUI_EHF_HANDLEINPUT)
1938 DoMethod(ehn->ehn_Object, MUIM_HandleInput, (IPTR) event, muikey);
1939 res = 0;
1941 else
1943 if (ehn->ehn_Class)
1944 res = CoerceMethod
1945 (ehn->ehn_Class, ehn->ehn_Object, MUIM_HandleEvent,
1946 (IPTR) event, muikey);
1947 else
1948 res =
1949 DoMethod(ehn->ehn_Object, MUIM_HandleEvent, (IPTR) event,
1950 muikey);
1952 return res;
1955 static void HandleRawkey(Object *win, struct MUI_WindowData *data,
1956 struct IntuiMessage *event)
1958 struct MinNode *mn;
1959 struct MUI_EventHandlerNode *ehn;
1960 struct IntuiMessage imsg_copy;
1961 struct InputEvent ie = { 0 };
1962 ULONG res;
1963 LONG muikey = MUIKEY_NONE;
1964 Object *active_object = NULL;
1965 IPTR disabled = 0;
1966 ULONG key;
1967 ULONG deadkey;
1969 KillHelpBubble(data, win, BUBBLEHELP_TICKER_FIRST);
1971 ie.ie_NextEvent = NULL;
1972 ie.ie_Class = IECLASS_RAWKEY;
1973 ie.ie_SubClass = 0;
1974 ie.ie_Code = event->Code;
1975 ie.ie_Qualifier = event->Qualifier;
1976 ie.ie_EventAddress = (APTR) * (IPTR *) event->IAddress;
1977 #ifdef __AMIGAOS4__
1978 ie.ie_TimeStamp.Seconds = event->Seconds;
1979 ie.ie_TimeStamp.Microseconds = event->Micros;
1980 #else
1981 ie.ie_TimeStamp.tv_secs = event->Seconds;
1982 ie.ie_TimeStamp.tv_micro = event->Micros;
1983 #endif
1985 set(win, MUIA_Window_InputEvent, (IPTR) & ie);
1987 /* get the vanilla key for control char */
1989 UWORD msg_code;
1991 /* Remove the up prefix as convert key does not convert upkey event */
1992 msg_code = event->Code;
1993 event->Code &= ~IECODE_UP_PREFIX;
1994 key = ConvertKey(event);
1995 event->Code = msg_code;
1998 imsg_copy = *event;
1999 deadkey = *(ULONG *) event->IAddress;
2000 imsg_copy.IAddress = &deadkey;
2001 ReplyMsg((struct Message *)event);
2002 event = &imsg_copy;
2004 //bug("rawkey: code=%lx, qual=%lx\n", event->Code, event->Qualifier);
2006 /* check if imsg translate to predefined keystroke */
2008 struct InputEvent ievent;
2009 BOOL matched = FALSE;
2011 ievent.ie_NextEvent = NULL;
2012 ievent.ie_Class = IECLASS_RAWKEY;
2013 ievent.ie_SubClass = 0;
2014 ievent.ie_Code = event->Code;
2015 ievent.ie_Qualifier = event->Qualifier;
2016 /* ie_EventAddress is not used by MatchIX. If needed, it should be
2017 * ensured that it is still a valid adress because of the shallow
2018 * IntuiMessage copy currently done in _zune_window_message before
2019 * message is replied.
2021 ievent.ie_EventAddress = NULL;
2022 //ievent.ie_EventAddress = (APTR *) *((ULONG *)(event->IAddress));
2024 for (muikey = MUIKEY_COUNT - 1; muikey >= MUIKEY_PRESS; muikey--)
2026 if (muiGlobalInfo(win)->mgi_Prefs->muikeys[muikey].ix_well != 0
2027 && MatchIX(&ievent,
2028 &muiGlobalInfo(win)->mgi_Prefs->muikeys[muikey].ix))
2030 matched = TRUE;
2031 break;
2035 if (matched)
2037 if (muikey == MUIKEY_PRESS && (event->Code & IECODE_UP_PREFIX))
2038 muikey = MUIKEY_RELEASE;
2040 else
2042 muikey = MUIKEY_NONE;
2044 } /* check if imsg translate to predefined keystroke */
2046 if ((muikey != MUIKEY_NONE) && !(data->wd_DisabledKeys & (1 << muikey)))
2048 D(bug("HandleRawkey: try MUIKEY %ld on window %0x08lx\n", muikey,
2049 win));
2050 switch (muikey)
2052 case MUIKEY_PRESS:
2053 break;
2054 case MUIKEY_TOGGLE:
2055 break;
2056 case MUIKEY_UP:
2057 break;
2058 case MUIKEY_DOWN:
2059 break;
2060 case MUIKEY_PAGEUP:
2061 break;
2062 case MUIKEY_PAGEDOWN:
2063 break;
2064 case MUIKEY_TOP:
2065 break;
2066 case MUIKEY_BOTTOM:
2067 break;
2068 case MUIKEY_LEFT:
2069 break;
2070 case MUIKEY_RIGHT:
2071 break;
2072 case MUIKEY_WORDLEFT:
2073 break;
2074 case MUIKEY_WORDRIGHT:
2075 break;
2076 case MUIKEY_LINESTART:
2077 break;
2078 case MUIKEY_LINEEND:
2079 break;
2080 case MUIKEY_GADGET_NEXT:
2081 set(win, MUIA_Window_ActiveObject,
2082 MUIV_Window_ActiveObject_Next);
2083 break;
2084 case MUIKEY_GADGET_PREV:
2085 set(win, MUIA_Window_ActiveObject,
2086 MUIV_Window_ActiveObject_Prev);
2087 break;
2088 case MUIKEY_GADGET_OFF:
2089 set(win, MUIA_Window_ActiveObject,
2090 MUIV_Window_ActiveObject_None);
2091 break;
2092 case MUIKEY_WINDOW_CLOSE:
2093 set(win, MUIA_Window_CloseRequest, TRUE);
2094 break;
2095 case MUIKEY_WINDOW_NEXT:
2096 break;
2097 case MUIKEY_WINDOW_PREV:
2098 break;
2099 case MUIKEY_HELP:
2100 break;
2101 case MUIKEY_POPUP:
2102 break;
2103 default:
2104 break;
2108 active_object = NULL;
2109 if ((data->wd_ActiveObject != NULL)
2110 && (DoMethod(data->wd_RootObject, MUIM_FindAreaObject,
2111 (IPTR) data->wd_ActiveObject) != (IPTR) NULL))
2113 active_object = data->wd_ActiveObject;
2114 get(active_object, MUIA_Disabled, &disabled);
2116 else
2117 data->wd_ActiveObject = NULL;
2119 /* try ActiveObject */
2120 if ((active_object != NULL) && !disabled)
2122 #if 0
2123 /* sba:
2124 ** Which method should be used for muikeys? MUIM_HandleInput or
2125 ** MUIM_HandleEvent. Also note that there is a flag MUI_EHF_ALWAYSKEYS
2126 ** which probably means that all keys events are requested??
2127 ** For now MUIM_HandleEvent is used as this is currently implemented
2128 ** in Area class ;) although I guess it should be MUIM_HandleInput as
2129 ** this was earlier
2132 if (muikey != MUIKEY_NONE)
2134 res =
2135 DoMethod(active_object, MUIM_HandleEvent, (IPTR) event,
2136 muikey);
2137 if (res & MUI_EventHandlerRC_Eat)
2138 return;
2140 #endif
2141 D(bug("HandleRawkey: try active object (%08lx) handlers\n",
2142 active_object));
2144 for (mn = data->wd_EHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
2146 ehn = (struct MUI_EventHandlerNode *)mn;
2148 if ((ehn->ehn_Object == active_object)
2149 && ((ehn->ehn_Events & IDCMP_RAWKEY)
2150 || (ehn->ehn_Flags & MUI_EHF_ALWAYSKEYS)))
2152 D(bug("HandleRawkey: (active) invoking on %p (ehn=%p) "
2153 "event=%p muikey=%p\n",
2154 ehn->ehn_Object, ehn, event, muikey));
2155 res = InvokeEventHandler(ehn, event, muikey);
2156 D(bug("HandleRawkey: (active) got res=%d\n", res));
2157 if (res & MUI_EventHandlerRC_Eat)
2158 return;
2160 /* Leave the loop if a different object has been activated */
2161 if (active_object != data->wd_ActiveObject)
2162 break;
2166 // event not eaten by active object, try its parents
2167 // this is to implement popup key in Popstring
2168 if (active_object == data->wd_ActiveObject)
2170 Object *current_obj = active_object;
2172 D(bug("HandleRawkey: try active object parents handlers\n"));
2173 while (current_obj != NULL)
2175 for (mn = data->wd_EHList.mlh_Head; mn->mln_Succ;
2176 mn = mn->mln_Succ)
2178 ehn = (struct MUI_EventHandlerNode *)mn;
2180 if ((ehn->ehn_Object == current_obj)
2181 && ((ehn->ehn_Events & IDCMP_RAWKEY)
2182 || (ehn->ehn_Flags & MUI_EHF_ALWAYSKEYS)))
2184 //D(bug("HandleRawkey: (active parents) invoking on "
2185 // "%p (ehn=%p) event=%p muikey=%p\n",
2186 // ehn->ehn_Object, ehn, event, muikey));
2187 res = InvokeEventHandler(ehn, event, muikey);
2188 //D(bug("HandleRawkey: (active parents) got res=%d\n",
2189 // res));
2190 if (res & MUI_EventHandlerRC_Eat)
2191 return;
2193 /* Leave the loop if a different object has been
2194 * activated */
2195 if (active_object != data->wd_ActiveObject)
2196 break;
2199 current_obj = (Object *) XGET(current_obj, MUIA_Parent);
2204 D(bug("HandleRawkey: try default object handlers\n"));
2206 /* try DefaultObject */
2207 if (data->wd_DefaultObject != NULL)
2208 get(data->wd_DefaultObject, MUIA_Disabled, &disabled);
2210 if ((data->wd_DefaultObject != NULL) && !disabled
2211 && (active_object != data->wd_DefaultObject))
2213 /* No, we only should do this if the object actually has requested
2214 * this via RequestIDCMP()! */
2215 // if (muikey != MUIKEY_NONE
2216 // && (_flags(data->wd_DefaultObject) & MADF_CANDRAW))
2217 // {
2218 // DoMethod(data->wd_DefaultObject, MUIM_HandleInput, event, muikey);
2219 // return;
2220 // }
2222 for (mn = data->wd_EHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
2224 ehn = (struct MUI_EventHandlerNode *)mn;
2226 if ((ehn->ehn_Object == data->wd_DefaultObject)
2227 && ((ehn->ehn_Events & IDCMP_RAWKEY)
2228 || (ehn->ehn_Flags & MUI_EHF_ALWAYSKEYS)))
2230 //D(bug("HandleRawkey: (default) invoking on %p (ehn=%p) "
2231 //"event=%p muikey=%p\n",
2232 //ehn->ehn_Object, ehn, event, muikey));
2233 res = InvokeEventHandler(ehn, event, muikey);
2234 //D(bug("HandleRawkey: (default) got res=%d\n", res));
2235 if (res & MUI_EventHandlerRC_Eat)
2236 return;
2242 D(bug("HandleRawkey: try other handlers\n"));
2244 // try other handlers
2245 for (mn = data->wd_EHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
2247 ehn = (struct MUI_EventHandlerNode *)mn;
2249 // skip Active and Default object as they have already been
2250 // handled
2251 if (ehn->ehn_Object == data->wd_ActiveObject
2252 || ehn->ehn_Object == data->wd_DefaultObject)
2253 continue;
2255 if (ehn->ehn_Events & IDCMP_RAWKEY)
2257 //D(bug("HandleRawkey: (others) invoking on %p (ehn=%p) "
2258 //"event=%p muikey=%p\n",
2259 //ehn->ehn_Object, ehn, event, muikey));
2260 res = InvokeEventHandler(ehn, event, MUIKEY_NONE);
2261 //D(bug("HandleRawkey: (others) got res=%d\n", res));
2262 if (res & MUI_EventHandlerRC_Eat)
2263 return;
2267 D(bug("HandleRawkey: try control chars handlers\n"));
2269 /* try Control Chars */
2270 //bug("ctrlchar, key='%c' code=0x%08lx\n", key, event->Code);
2271 if (key)
2273 for (mn = data->wd_CCList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
2275 ehn = (struct MUI_EventHandlerNode *)mn;
2277 if (ehn->ehn_Events == key)
2279 IPTR disabled = 0;
2280 LONG muikey2 = ehn->ehn_Flags;
2282 get(ehn->ehn_Object, MUIA_Disabled, &disabled);
2283 if (disabled)
2284 continue;
2286 //bug("control char\n");
2287 if (event->Code & IECODE_UP_PREFIX)
2289 /* simulate a release */
2290 if (muikey2 == MUIKEY_PRESS)
2291 muikey2 = MUIKEY_RELEASE;
2292 else
2293 return;
2296 if ((muikey2 != MUIKEY_NONE)
2297 && (_flags(ehn->ehn_Object) & MADF_CANDRAW)
2298 && (_flags(ehn->ehn_Object) & MADF_SHOWME))
2300 res = CoerceMethod
2301 (ehn->ehn_Class, ehn->ehn_Object, MUIM_HandleEvent,
2302 (IPTR) NULL, muikey2);
2303 if (res & MUI_EventHandlerRC_Eat)
2304 return;
2311 /* forward non-keystroke events to event handlers */
2312 static void HandleInputEvent(Object *win, struct MUI_WindowData *data,
2313 struct IntuiMessage *event)
2315 struct MinNode *mn;
2316 struct MUI_EventHandlerNode *ehn;
2317 struct IntuiMessage imsg_copy;
2318 ULONG res;
2319 ULONG mask = event->Class;
2321 if (mask != IDCMP_IDCMPUPDATE)
2323 imsg_copy = *event;
2324 imsg_copy.IAddress = NULL; /* be sure to trap access to that */
2325 ReplyMsg((struct Message *)event);
2326 event = &imsg_copy;
2329 if (mask == IDCMP_MOUSEMOVE)
2331 struct Window *iWin;
2332 iWin = event->IDCMPWindow;
2334 if (ContextMenuUnderPointer(data, data->wd_RootObject,
2335 event->MouseX, event->MouseY))
2337 iWin->Flags |= WFLG_RMBTRAP;
2339 else if (!data->wd_NoMenus)
2341 iWin->Flags &= ~WFLG_RMBTRAP;
2345 for (mn = data->wd_EHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
2347 ehn = (struct MUI_EventHandlerNode *)mn;
2349 if (ehn->ehn_Events & mask)
2351 IPTR disabled = 0;
2353 get(ehn->ehn_Object, MUIA_Disabled, &disabled);
2354 if (disabled)
2355 continue;
2357 res = InvokeEventHandler(ehn, event, MUIKEY_NONE);
2358 if (res & MUI_EventHandlerRC_Eat)
2359 return;
2364 if (mask == IDCMP_IDCMPUPDATE)
2365 ReplyMsg((struct Message *)event);
2369 /* process window message, this does a ReplyMsg() to the message */
2370 /* Called from application.c */
2371 void _zune_window_message(struct IntuiMessage *imsg)
2373 struct Window *iWin;
2374 Object *oWin;
2375 struct MUI_WindowData *data;
2376 BOOL handled;
2378 iWin = imsg->IDCMPWindow;
2379 oWin = (Object *) iWin->UserData;
2380 data = muiWindowData(oWin);
2382 if (data->wd_DragObject)
2384 HandleDragging(oWin, data, imsg);
2385 return;
2388 handled = HandleWindowEvent(oWin, data, imsg);
2389 if (!handled)
2391 if (IDCMP_RAWKEY == imsg->Class)
2392 HandleRawkey(oWin, data, imsg);
2393 else if (IDCMP_GADGETUP == imsg->Class)
2395 #ifdef __AROS__
2396 if (ETI_MUI == ((struct Gadget *)imsg->IAddress)->GadgetID)
2398 DoMethod(_app(oWin), MUIM_Application_OpenConfigWindow);
2400 #endif
2401 if (ETI_Iconify == ((struct Gadget *)imsg->IAddress)->GadgetID)
2403 set(_app(oWin), MUIA_Application_Iconified, TRUE);
2406 else
2408 HandleInputEvent(oWin, data, imsg);
2413 /**************************************************************************/
2414 /**************************************************************************/
2416 /* code for setting MUIA_Window_RootObject */
2417 static void ChangeRootObject(struct MUI_WindowData *data, Object *obj,
2418 Object *newRoot)
2420 Object *oldRoot;
2422 ASSERT_VALID_PTR(data);
2423 ASSERT_VALID_PTR(obj);
2425 oldRoot = data->wd_RootObject;
2426 if (!(data->wd_Flags & MUIWF_OPENED))
2428 if (oldRoot)
2430 if (data->wd_ActiveObject == oldRoot)
2431 set(obj, MUIA_Window_ActiveObject,
2432 MUIV_Window_ActiveObject_None);
2433 DoMethod(oldRoot, MUIM_DisconnectParent);
2436 data->wd_RootObject = newRoot;
2437 if (newRoot)
2439 /* if window is in App tree, inform child */
2440 if (muiNotifyData(obj)->mnd_GlobalInfo)
2441 DoMethod(newRoot, MUIM_ConnectParent, (IPTR) obj);
2446 // find the ObjNode containing a pointer to the given object
2447 // currently only used for cycle chain objects
2448 static struct ObjNode *FindObjNode(struct MinList *list, Object *obj)
2450 struct ObjNode *node;
2452 ASSERT_VALID_PTR(list);
2454 if (!obj)
2455 return NULL;
2457 ASSERT_VALID_PTR(obj);
2459 for (node = (struct ObjNode *)list->mlh_Head;
2460 node->node.mln_Succ; node = (struct ObjNode *)node->node.mln_Succ)
2462 if (node->obj == obj)
2464 return node;
2467 return NULL;
2470 static Object *GetFirstActiveObject(struct MUI_WindowData *data)
2472 ASSERT_VALID_PTR(data);
2474 if (!IsListEmpty((struct List *)&data->wd_CycleChain))
2475 return ((struct ObjNode *)data->wd_CycleChain.mlh_Head)->obj;
2476 else
2477 return NULL;
2480 static Object *GetLastActiveObject(struct MUI_WindowData *data)
2482 ASSERT_VALID_PTR(data);
2484 if (!IsListEmpty((struct List *)&data->wd_CycleChain))
2485 return ((struct ObjNode *)data->wd_CycleChain.mlh_TailPred)->obj;
2486 else
2487 return NULL;
2490 typedef struct ObjNode *objnode_iterator_t(struct ObjNode *curr_node);
2492 static objnode_iterator_t NextObjNodeIterator;
2493 static objnode_iterator_t PrevObjNodeIterator;
2495 static struct ObjNode *NextObjNodeIterator(struct ObjNode *curr_node)
2497 if (curr_node->node.mln_Succ->mln_Succ)
2498 return (struct ObjNode *)curr_node->node.mln_Succ;
2499 else
2500 return NULL;
2503 static struct ObjNode *PrevObjNodeIterator(struct ObjNode *curr_node)
2505 if (curr_node->node.mln_Pred->mln_Pred)
2506 return (struct ObjNode *)curr_node->node.mln_Pred;
2507 else
2508 return NULL;
2511 static Object *GetPrevNextActiveObject(struct ObjNode *old_activenode,
2512 objnode_iterator_t node_iterator)
2514 struct ObjNode *curr_node;
2515 struct ObjNode *node;
2516 Object *obj;
2518 ASSERT_VALID_PTR(old_activenode);
2520 curr_node = old_activenode;
2521 node = NULL;
2522 obj = NULL;
2524 while (curr_node)
2526 node = node_iterator(curr_node);
2528 if (node)
2529 obj = node->obj;
2531 /* let's see if this object meets cycle requirements
2532 * (enabled & visible) */
2533 if (obj)
2535 IPTR is_disabled = 0;
2537 get(obj, MUIA_Disabled, &is_disabled);
2539 if (!is_disabled && (_flags(obj) & MADF_SHOWME))
2541 return obj;
2545 curr_node = node;
2546 obj = NULL;
2547 node = NULL;
2549 return obj;
2553 /**************************************************************************
2554 Code for setting MUIA_Window_ActiveObject
2555 Basically, it will:
2556 - remove focus drawing for current active object
2557 - find (if needed) the new active object
2558 - set data->wd_ActiveObject to the new object
2559 - draw focus around the new active object
2560 **************************************************************************/
2561 static void SetActiveObject(struct MUI_WindowData *data, Object *obj,
2562 IPTR newval)
2564 struct ObjNode *old_activenode = NULL;
2566 ASSERT_VALID_PTR(data);
2567 ASSERT_VALID_PTR(obj);
2569 D(bug("MUIC_Window:SetActiveObject(data, obj, %08lx) Active=%p\n",
2570 newval, data->wd_ActiveObject));
2572 if ((data->wd_ActiveObject != NULL)
2573 && (DoMethod(data->wd_RootObject, MUIM_FindAreaObject,
2574 (IPTR) data->wd_ActiveObject) != (IPTR) NULL))
2576 if ((IPTR) data->wd_ActiveObject != newval)
2578 old_activenode =
2579 FindObjNode(&data->wd_CycleChain, data->wd_ActiveObject);
2580 //if (_flags(data->wd_ActiveObject) & MADF_CANDRAW)
2581 if (data->wd_Flags & MUIWF_OBJECTGOACTIVESENT)
2583 D(bug("Inactivate=%p\n", data->wd_ActiveObject));
2584 DoMethod(data->wd_ActiveObject, MUIM_GoInactive);
2589 data->wd_ActiveObject = NULL;
2590 data->wd_Flags &= ~MUIWF_OBJECTGOACTIVESENT;
2592 switch (newval)
2594 case MUIV_Window_ActiveObject_None:
2595 break;
2597 case MUIV_Window_ActiveObject_Next:
2598 if (old_activenode != NULL)
2599 data->wd_ActiveObject = GetPrevNextActiveObject(old_activenode,
2600 NextObjNodeIterator);
2601 if (NULL == data->wd_ActiveObject)
2602 data->wd_ActiveObject = GetFirstActiveObject(data);
2603 break;
2605 case MUIV_Window_ActiveObject_Prev:
2606 if (old_activenode)
2607 data->wd_ActiveObject = GetPrevNextActiveObject(old_activenode,
2608 PrevObjNodeIterator);
2609 if (NULL == data->wd_ActiveObject)
2610 data->wd_ActiveObject = GetLastActiveObject(data);
2611 break;
2613 default:
2614 data->wd_ActiveObject = (Object *) newval;
2615 break;
2619 if (data->wd_ActiveObject != NULL
2620 && DoMethod(data->wd_RootObject, MUIM_FindAreaObject,
2621 (IPTR) data->wd_ActiveObject)
2622 && (_flags(data->wd_ActiveObject) & MADF_CANDRAW))
2624 D(bug("Activate=%p\n", data->wd_ActiveObject));
2625 DoMethod(data->wd_ActiveObject, MUIM_GoActive);
2626 data->wd_Flags |= MUIWF_OBJECTGOACTIVESENT;
2632 * calculate real dimensions from programmer requirements.
2633 * may be overridden by user settings if MUIA_Window_ID is set.
2635 /* MUIV_Window_Height_Screen and MUIV_Window_Height_Visible
2636 * are not handled yet, as their Width couterparts.
2638 static void WindowSelectDimensions(struct MUI_WindowData *data)
2640 if (!data->wd_Width)
2642 if (data->wd_ReqWidth > 0)
2643 data->wd_Width = data->wd_ReqWidth;
2644 else if (data->wd_ReqWidth == MUIV_Window_Width_Default)
2645 data->wd_Width = data->wd_MinMax.DefWidth;
2646 else if (_between(MUIV_Window_Width_MinMax(100),
2647 data->wd_ReqWidth, MUIV_Window_Width_MinMax(0)))
2649 data->wd_Width = data->wd_MinMax.MinWidth
2650 - data->wd_ReqWidth
2651 * (data->wd_MinMax.MaxWidth - data->wd_MinMax.MinWidth);
2653 else if (_between(MUIV_Window_Width_Screen(100),
2654 data->wd_ReqWidth, MUIV_Window_Width_Screen(0)))
2656 data->wd_Width = data->wd_RenderInfo.mri_ScreenWidth
2657 * (-(data->wd_ReqWidth + 200)) / 100;
2659 else if (_between(MUIV_Window_Width_Visible(100),
2660 data->wd_ReqWidth, MUIV_Window_Width_Visible(0)))
2662 data->wd_Width = data->wd_RenderInfo.mri_ScreenWidth
2663 * (-(data->wd_ReqWidth + 100)) / 100;
2666 if (data->wd_ReqHeight > 0)
2667 data->wd_Height = data->wd_ReqHeight;
2668 else if (data->wd_ReqHeight == MUIV_Window_Height_Default)
2669 data->wd_Height = data->wd_MinMax.DefHeight;
2670 else if (_between(MUIV_Window_Height_MinMax(100),
2671 data->wd_ReqHeight, MUIV_Window_Height_MinMax(0)))
2673 data->wd_Height = data->wd_MinMax.MinHeight
2674 - data->wd_ReqHeight
2675 * (data->wd_MinMax.MaxHeight - data->wd_MinMax.MinHeight);
2677 else if (_between(MUIV_Window_Height_Screen(100),
2678 data->wd_ReqHeight, MUIV_Window_Height_Screen(0)))
2680 struct Screen *scr;
2681 int height;
2683 scr = data->wd_RenderInfo.mri_Screen;
2685 height =
2686 scr->Height - data->wd_RenderInfo.mri_BorderTop -
2687 data->wd_RenderInfo.mri_BorderBottom;
2689 /* This is new to Zune: If TopEdge Delta is requested
2690 * the screenheight doesn't cover the barlayer */
2691 if (data->wd_Y <= MUIV_Window_TopEdge_Delta(0))
2692 height -= scr->BarHeight + 1;
2694 data->wd_Height = height * (-(data->wd_ReqHeight + 200)) / 100;
2696 else if (_between(MUIV_Window_Height_Visible(100),
2697 data->wd_ReqHeight, MUIV_Window_Height_Visible(0)))
2699 data->wd_Height = data->wd_RenderInfo.mri_ScreenHeight
2700 * (-(data->wd_ReqHeight + 100)) / 100;
2703 /* scaled */
2704 if (data->wd_ReqWidth == MUIV_Window_Width_Scaled)
2705 data->wd_Width = data->wd_Height * data->wd_MinMax.MinWidth
2706 / data->wd_MinMax.MinHeight;
2707 else if (data->wd_ReqHeight == MUIV_Window_Width_Scaled)
2708 data->wd_Height = data->wd_Width * data->wd_MinMax.MinHeight
2709 / data->wd_MinMax.MinWidth;
2711 data->wd_Width = CLAMP(data->wd_Width, data->wd_MinMax.MinWidth,
2712 data->wd_MinMax.MaxWidth);
2713 data->wd_Height = CLAMP(data->wd_Height, data->wd_MinMax.MinHeight,
2714 data->wd_MinMax.MaxHeight);
2718 /**************************************************************************
2719 OM_NEW
2720 **************************************************************************/
2721 IPTR Window__OM_NEW(struct IClass *cl, Object *obj, struct opSet *msg)
2723 struct MUI_WindowData *data;
2724 struct TagItem *tags;
2725 struct TagItem *tag;
2727 obj = (Object *) DoSuperMethodA(cl, obj, (Msg) msg);
2728 if (!obj)
2729 return FALSE;
2731 /* Initial local instance data */
2732 data = INST_DATA(cl, obj);
2734 data->wd_MemoryPool = CreatePool(0, 4096, 2048);
2735 if (NULL == data->wd_MemoryPool)
2737 CoerceMethod(cl, obj, OM_DISPOSE);
2738 return (IPTR) NULL;
2741 data->wd_RenderInfo.mri_WindowObject = obj;
2743 NewList((struct List *)&(data->wd_EHList));
2744 NewList((struct List *)&(data->wd_CCList));
2745 NewList((struct List *)&(data->wd_CycleChain));
2746 NewList((struct List *)&(data->wd_IDList));
2748 data->wd_CrtFlags = WFLG_SIZEGADGET | WFLG_DRAGBAR | WFLG_DEPTHGADGET
2749 | WFLG_CLOSEGADGET | WFLG_SIMPLE_REFRESH
2750 | WFLG_REPORTMOUSE | WFLG_NEWLOOKMENUS;
2751 data->wd_ZoomGadget = TRUE;
2752 data->wd_Events = GetDefaultEvents();
2753 data->wd_ActiveObject = NULL;
2754 data->wd_ID = 0;
2755 data->wd_ReqHeight = MUIV_Window_Height_Default;
2756 data->wd_ReqWidth = MUIV_Window_Width_Default;
2757 data->wd_RootObject = NULL;
2758 data->wd_DefaultObject = NULL;
2760 /* alternate dimensions */
2761 /* no change in coordinates */
2762 data->wd_AltDim.Top = MUIV_Window_AltTopEdge_NoChange;
2763 data->wd_AltDim.Left = MUIV_Window_AltLeftEdge_NoChange;
2764 /* default to min size */
2765 data->wd_AltDim.Width = MUIV_Window_AltWidth_MinMax(0);
2766 data->wd_AltDim.Height = MUIV_Window_AltHeight_MinMax(0);
2767 data->wd_X = MUIV_Window_LeftEdge_Centered;
2768 data->wd_Y = MUIV_Window_TopEdge_Centered;
2769 data->wd_DisabledKeys = 0L;
2770 data->wd_HelpTicker = BUBBLEHELP_TICKER_FIRST;
2772 /* parse initial taglist */
2774 for (tags = msg->ops_AttrList; (tag = NextTagItem(&tags));)
2776 switch (tag->ti_Tag)
2778 case MUIA_Window_EraseArea:
2779 _handle_bool_tag(data->wd_Flags, tag->ti_Data, MUIWF_ERASEAREA);
2780 break;
2782 case MUIA_Window_ToolBox:
2783 _handle_bool_tag(data->wd_Flags, tag->ti_Data, MUIWF_TOOLBOX);
2784 break;
2786 case MUIA_Window_CloseGadget:
2787 _handle_bool_tag(data->wd_CrtFlags, tag->ti_Data,
2788 WFLG_CLOSEGADGET);
2789 break;
2791 case MUIA_Window_SizeGadget:
2792 _handle_bool_tag(data->wd_CrtFlags, tag->ti_Data,
2793 WFLG_SIZEGADGET);
2794 break;
2796 case MUIA_Window_ZoomGadget:
2797 data->wd_ZoomGadget = tag->ti_Data;
2798 break;
2800 case MUIA_Window_Backdrop:
2801 _handle_bool_tag(data->wd_CrtFlags, tag->ti_Data,
2802 WFLG_BACKDROP);
2803 break;
2805 case MUIA_Window_Borderless:
2806 _handle_bool_tag(data->wd_CrtFlags, tag->ti_Data,
2807 WFLG_BORDERLESS);
2808 break;
2810 case MUIA_Window_DepthGadget:
2811 _handle_bool_tag(data->wd_CrtFlags, tag->ti_Data,
2812 WFLG_DEPTHGADGET);
2813 break;
2815 case MUIA_Window_DragBar:
2816 _handle_bool_tag(data->wd_CrtFlags, tag->ti_Data, WFLG_DRAGBAR);
2817 break;
2819 case MUIA_Window_SizeRight:
2820 _handle_bool_tag(data->wd_CrtFlags, tag->ti_Data,
2821 WFLG_SIZEBRIGHT);
2822 break;
2824 case MUIA_Window_Height:
2825 data->wd_ReqHeight = (LONG) tag->ti_Data;
2826 break;
2828 case MUIA_Window_Width:
2829 data->wd_ReqWidth = (LONG) tag->ti_Data;
2830 break;
2832 case MUIA_Window_ID:
2833 set(obj, MUIA_Window_ID, tag->ti_Data);
2834 break;
2836 case MUIA_Window_IsSubWindow:
2837 _handle_bool_tag(data->wd_Flags, tag->ti_Data,
2838 MUIWF_ISSUBWINDOW);
2839 break;
2841 case MUIA_Window_Title:
2842 set(obj, MUIA_Window_Title, tag->ti_Data);
2843 break;
2845 case MUIA_Window_ScreenTitle:
2846 set(obj, MUIA_Window_ScreenTitle, tag->ti_Data);
2847 break;
2849 case MUIA_Window_Activate:
2850 _handle_bool_tag(data->wd_Flags, !tag->ti_Data,
2851 MUIWF_DONTACTIVATE);
2852 break;
2854 case MUIA_Window_DefaultObject:
2855 set(obj, MUIA_Window_DefaultObject, tag->ti_Data);
2856 break;
2858 case MUIA_Window_Menustrip:
2859 data->wd_ChildMenustrip = (Object *) tag->ti_Data;
2860 break;
2862 case MUIA_Window_NoMenus:
2863 data->wd_NoMenus = (BOOL) tag->ti_Data;
2864 break;
2866 case MUIA_Window_RootObject:
2867 if (!tag->ti_Data)
2869 CoerceMethod(cl, obj, OM_DISPOSE);
2870 return 0;
2872 set(obj, MUIA_Window_RootObject, tag->ti_Data);
2873 break;
2875 case MUIA_Window_AltHeight:
2876 data->wd_AltDim.Height = (WORD) tag->ti_Data;
2877 break;
2879 case MUIA_Window_AltWidth:
2880 data->wd_AltDim.Width = (WORD) tag->ti_Data;
2881 break;
2883 case MUIA_Window_AltLeftEdge:
2884 data->wd_AltDim.Left = (WORD) tag->ti_Data;
2885 break;
2887 case MUIA_Window_AltTopEdge:
2888 data->wd_AltDim.Top = (WORD) tag->ti_Data;
2889 break;
2891 case MUIA_Window_AppWindow:
2892 _handle_bool_tag(data->wd_Flags, tag->ti_Data,
2893 MUIWF_ISAPPWINDOW);
2894 break;
2896 case MUIA_Window_LeftEdge:
2897 data->wd_X = tag->ti_Data;
2898 break;
2900 case MUIA_Window_TopEdge:
2901 data->wd_Y = tag->ti_Data;
2902 break;
2904 case MUIA_Window_UseBottomBorderScroller:
2905 _handle_bool_tag(data->wd_Flags, tag->ti_Data,
2906 MUIWF_USEBOTTOMSCROLLER);
2907 break;
2909 case MUIA_Window_UseRightBorderScroller:
2910 _handle_bool_tag(data->wd_Flags, tag->ti_Data,
2911 MUIWF_USERIGHTSCROLLER);
2912 break;
2914 case MUIA_Window_DisableKeys:
2915 data->wd_DisabledKeys = tag->ti_Data;
2916 break;
2918 case MUIA_Window_RefWindow:
2919 data->wd_RefWindow = (Object *) tag->ti_Data;
2920 break;
2922 case MUIA_Window_Screen:
2923 data->wd_UserScreen = (struct Screen *)tag->ti_Data;
2924 break;
2926 case MUIA_Window_PublicScreen:
2927 data->wd_UserPublicScreen = (STRPTR) tag->ti_Data;
2928 break;
2932 /* D(bug("muimaster.library/window.c: Window Object created at " */
2933 /* "0x%lx back=%lx\n", */
2934 /* obj,data->wd_Background)); */
2936 return (IPTR) obj;
2939 /**************************************************************************
2940 OM_DISPOSE
2941 **************************************************************************/
2942 IPTR Window__OM_DISPOSE(struct IClass *cl, Object *obj, Msg msg)
2944 struct MUI_WindowData *data = INST_DATA(cl, obj);
2946 /* D(bug("Window_Dispose(%p)\n", obj)); */
2948 #if 0
2949 /* We no longer clear muiGlobalInfo() during disconnections, so
2950 this can cause problems (remove object which is already removed).
2951 Furthermore AFAIK it is not legal to dispose a window object
2952 which is still ocnnected to the application object, anyway. */
2954 if (muiGlobalInfo(obj) && _app(obj))
2956 /* D(bug(" Window_Dispose(%p) : calling app->OM_REMMEMBER\n", obj)); */
2957 DoMethod(_app(obj), OM_REMMEMBER, (IPTR) obj);
2959 #endif
2961 if (data->wd_RootObject)
2962 MUI_DisposeObject(data->wd_RootObject);
2964 if (data->wd_ChildMenustrip)
2965 MUI_DisposeObject(data->wd_ChildMenustrip);
2967 if (data->wd_Title)
2968 FreeVec(data->wd_Title);
2970 if (data->wd_ScreenTitle)
2971 FreeVec(data->wd_ScreenTitle);
2973 DeletePool(data->wd_MemoryPool);
2975 /* D(bug(" Window_Dispose(%p) : calling supermethod\n", obj)); */
2976 return DoSuperMethodA(cl, obj, msg);
2979 static ULONG WindowOpen(struct IClass *cl, Object *obj);
2980 static ULONG WindowClose(struct IClass *cl, Object *obj);
2982 /**************************************************************************
2983 OM_SET
2984 **************************************************************************/
2985 IPTR Window__OM_SET(struct IClass *cl, Object *obj, struct opSet *msg)
2987 struct MUI_WindowData *data = INST_DATA(cl, obj);
2988 struct TagItem *tags = msg->ops_AttrList;
2989 struct TagItem *tag;
2991 while ((tag = NextTagItem(&tags)) != NULL)
2993 switch (tag->ti_Tag)
2995 case MUIA_Window_Activate:
2996 if (data->wd_RenderInfo.mri_Window)
2998 if (tag->ti_Data && !(data->wd_Flags & MUIWF_ACTIVE))
3000 ActivateWindow(data->wd_RenderInfo.mri_Window);
3001 _handle_bool_tag(data->wd_Flags, tag->ti_Data,
3002 MUIWF_ACTIVE);
3005 else
3006 _handle_bool_tag(data->wd_Flags, !tag->ti_Data,
3007 MUIWF_DONTACTIVATE);
3008 break;
3010 case MUIA_Window_ActiveObject:
3011 /* D(bug("MUIA_Window_ActiveObject %ld (%p)\n", */
3012 /* tag->ti_Data, tag->ti_Data)); */
3013 SetActiveObject(data, obj, tag->ti_Data);
3014 break;
3016 case MUIA_Window_DefaultObject:
3017 data->wd_DefaultObject = (APTR) tag->ti_Data;
3018 break;
3020 case MUIA_Window_ID:
3021 data->wd_ID = tag->ti_Data;
3022 break;
3024 case MUIA_Window_IsSubWindow:
3025 _handle_bool_tag(data->wd_Flags, tag->ti_Data,
3026 MUIWF_ISSUBWINDOW);
3027 break;
3029 case MUIA_Window_Open:
3030 if (tag->ti_Data)
3032 if (data->wd_Flags & MUIWF_HIDDEN)
3033 data->wd_Flags |= MUIWF_OPENONUNHIDE;
3034 else if (!(data->wd_Flags & MUIWF_OPENED))
3035 WindowOpen(cl, obj);
3036 else
3038 DoMethod(obj, MUIM_Window_ToFront);
3039 set(obj, MUIA_Window_Activate, TRUE);
3042 else if (data->wd_Flags & MUIWF_HIDDEN)
3043 data->wd_Flags &= ~MUIWF_OPENONUNHIDE;
3044 else if (data->wd_Flags & MUIWF_OPENED)
3045 WindowClose(cl, obj);
3046 break;
3048 case MUIA_ShowMe: /* PRIVATE *abuse* of the Area's ShowMe attr */
3049 if (tag->ti_Data)
3051 /* Deiconify */
3053 if (data->wd_Flags & MUIWF_HIDDEN)
3055 data->wd_Flags &= ~MUIWF_HIDDEN;
3057 if (data->wd_Flags & MUIWF_OPENONUNHIDE)
3059 data->wd_Flags &= ~MUIWF_OPENONUNHIDE;
3060 set(obj, MUIA_Window_Open, TRUE);
3064 else
3066 /* Iconify */
3068 if (data->wd_Flags & MUIWF_OPENED)
3070 data->wd_Flags |= MUIWF_OPENONUNHIDE;
3072 set(obj, MUIA_Window_Open, FALSE);
3075 data->wd_Flags |= MUIWF_HIDDEN;
3077 break;
3079 case MUIA_Window_RootObject:
3080 ChangeRootObject(data, obj, (Object *) tag->ti_Data);
3081 break;
3083 case MUIA_Window_Title:
3084 if (data->wd_Title)
3085 FreeVec(data->wd_Title);
3086 data->wd_Title = StrDup((STRPTR) tag->ti_Data);
3087 if (data->wd_RenderInfo.mri_Window)
3088 SetWindowTitles(data->wd_RenderInfo.mri_Window,
3089 data->wd_Title, (CONST_STRPTR) ~ 0);
3090 break;
3092 case MUIA_Window_ScreenTitle:
3093 if (data->wd_ScreenTitle)
3094 FreeVec(data->wd_ScreenTitle);
3095 data->wd_ScreenTitle = StrDup((STRPTR) tag->ti_Data);
3096 if (data->wd_RenderInfo.mri_Window)
3097 SetWindowTitles(data->wd_RenderInfo.mri_Window,
3098 (CONST_STRPTR) ~ 0, data->wd_ScreenTitle);
3099 break;
3101 case MUIA_Window_NoMenus:
3102 data->wd_NoMenus = (BOOL) tag->ti_Data;
3103 if (data->wd_RenderInfo.mri_Window)
3105 if (data->wd_NoMenus)
3106 data->wd_RenderInfo.mri_Window->Flags |= WFLG_RMBTRAP;
3107 else
3108 data->wd_RenderInfo.mri_Window->Flags &= ~WFLG_RMBTRAP;
3110 break;
3112 case MUIA_Window_UseBottomBorderScroller:
3113 _handle_bool_tag(data->wd_Flags, tag->ti_Data,
3114 MUIWF_USEBOTTOMSCROLLER);
3115 break;
3117 case MUIA_Window_UseRightBorderScroller:
3118 _handle_bool_tag(data->wd_Flags, tag->ti_Data,
3119 MUIWF_USERIGHTSCROLLER);
3120 break;
3122 case MUIA_Window_DisableKeys:
3123 data->wd_DisabledKeys = tag->ti_Data;
3124 break;
3126 case MUIA_Window_RefWindow:
3127 data->wd_RefWindow = (Object *) tag->ti_Data;
3128 break;
3130 case MUIA_Window_LeftEdge:
3131 data->wd_X = tag->ti_Data;
3132 break;
3134 case MUIA_Window_TopEdge:
3135 data->wd_Y = tag->ti_Data;
3136 break;
3138 case MUIA_Window_Width:
3139 data->wd_ReqWidth = (LONG) tag->ti_Data;
3140 data->wd_Width = 0; /* otherwise windowselectdimensions()
3141 * ignores ReqWidth */
3142 break;
3144 case MUIA_Window_Height:
3145 data->wd_ReqHeight = (LONG) tag->ti_Data;
3146 data->wd_Height = 0;
3147 break;
3149 case MUIA_Window_Screen:
3150 data->wd_UserScreen = (struct Screen *)tag->ti_Data;
3151 break;
3153 case MUIA_Window_PublicScreen:
3154 data->wd_UserPublicScreen = (STRPTR) tag->ti_Data;
3155 break;
3157 case MUIA_Window_Sleep:
3158 if (tag->ti_Data)
3160 data->wd_SleepCount++;
3161 if (data->wd_RenderInfo.mri_Window
3162 && (data->wd_SleepCount == 1))
3164 SetWindowPointer
3165 (data->wd_RenderInfo.mri_Window,
3166 WA_BusyPointer, TRUE,
3167 WA_PointerDelay, TRUE, TAG_DONE);
3168 // FIXME: how to disable event handling?
3171 else
3173 data->wd_SleepCount--;
3174 if (data->wd_RenderInfo.mri_Window
3175 && (data->wd_SleepCount == 0))
3177 SetWindowPointerA(data->wd_RenderInfo.mri_Window, NULL);
3180 break;
3185 return DoSuperMethodA(cl, obj, (Msg) msg);
3188 /**************************************************************************
3189 OM_GET
3190 **************************************************************************/
3191 IPTR Window__OM_GET(struct IClass *cl, Object *obj, struct opGet *msg)
3193 #define STORE *(msg->opg_Storage)
3195 struct MUI_WindowData *data = INST_DATA(cl, obj);
3197 STORE = (IPTR) 0;
3199 switch (msg->opg_AttrID)
3201 case MUIA_Window_Activate:
3202 STORE =
3203 (data->wd_Flags & (MUIWF_ACTIVE | MUIWF_OPENED)) ==
3204 (MUIWF_ACTIVE | MUIWF_OPENED);
3205 return TRUE;
3207 case MUIA_Window_Window:
3208 STORE = (IPTR) data->wd_RenderInfo.mri_Window;
3209 return TRUE;
3211 case MUIA_Window_Screen:
3212 STORE = (IPTR) data->wd_RenderInfo.mri_Screen;
3213 return TRUE;
3215 case MUIA_Window_PublicScreen:
3216 STORE = (IPTR) data->wd_UserPublicScreen;
3217 return TRUE;
3219 case MUIA_Window_ActiveObject:
3220 if ((data->wd_ActiveObject != NULL)
3221 && (DoMethod(data->wd_RootObject, MUIM_FindAreaObject,
3222 (IPTR) data->wd_ActiveObject) != (IPTR) NULL))
3223 STORE = (IPTR) data->wd_ActiveObject;
3224 else
3225 STORE = (IPTR) NULL;
3226 return TRUE;
3228 case MUIA_Window_CloseRequest:
3229 STORE = FALSE;
3230 return TRUE;
3232 case MUIA_Window_DefaultObject:
3233 STORE = (IPTR) data->wd_DefaultObject;
3234 return TRUE;
3236 case MUIA_Window_DisableKeys:
3237 STORE = data->wd_DisabledKeys;
3238 return TRUE;
3240 case MUIA_Window_Height:
3241 STORE = (IPTR) data->wd_Height;
3242 return TRUE;
3244 case MUIA_Window_ID:
3245 STORE = data->wd_ID;
3246 return TRUE;
3248 case MUIA_Window_IsSubWindow:
3249 STORE = (data->wd_Flags & MUIWF_ISSUBWINDOW) == MUIWF_ISSUBWINDOW;
3250 return TRUE;
3252 case MUIA_Window_LeftEdge:
3253 if (data->wd_RenderInfo.mri_Window)
3254 STORE = (IPTR) data->wd_RenderInfo.mri_Window->LeftEdge;
3255 else
3256 STORE = 0;
3257 return TRUE;
3259 case MUIA_Window_Open:
3260 STORE = (data->wd_Flags & MUIWF_OPENED) == MUIWF_OPENED;
3261 return TRUE;
3263 case MUIA_Window_RootObject:
3264 STORE = (IPTR) data->wd_RootObject;
3265 return TRUE;
3267 case MUIA_Window_ScreenTitle:
3268 STORE = (IPTR) data->wd_ScreenTitle;
3269 return TRUE;
3271 case MUIA_Window_Title:
3272 STORE = (IPTR) data->wd_Title;
3273 return TRUE;
3275 case MUIA_Window_TopEdge:
3276 if (data->wd_RenderInfo.mri_Window)
3277 STORE = (IPTR) data->wd_RenderInfo.mri_Window->TopEdge;
3278 else
3279 STORE = (IPTR) 0;
3280 return (TRUE);
3282 case MUIA_Window_Width:
3283 STORE = (IPTR) data->wd_Width;
3284 return TRUE;
3286 case MUIA_Window_Menustrip:
3287 STORE = (IPTR) data->wd_ChildMenustrip;
3288 return TRUE;
3290 case MUIA_Window_Sleep:
3291 STORE = data->wd_SleepCount ? TRUE : FALSE;
3292 return TRUE;
3294 case MUIA_Version:
3295 STORE = __version;
3296 return TRUE;
3298 case MUIA_Revision:
3299 STORE = __revision;
3300 return TRUE;
3303 return DoSuperMethodA(cl, obj, (Msg) msg);
3304 #undef STORE
3308 * MUIM_FindUData : tests if the MUIA_UserData of the object
3309 * contains the given <udata> and returns the object pointer in this case.
3311 IPTR Window__MUIM_FindUData(struct IClass *cl, Object *obj,
3312 struct MUIP_FindUData *msg)
3314 struct MUI_WindowData *data = INST_DATA(cl, obj);
3316 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
3317 return (IPTR) obj;
3319 if (data->wd_RootObject)
3320 return DoMethodA(data->wd_RootObject, (Msg) msg);
3322 return 0;
3327 * MUIM_GetUData : This method tests if the MUIA_UserData of the object
3328 * contains the given <udata> and gets <attr> to <storage> for itself
3329 * in this case.
3331 IPTR Window__MUIM_GetUData(struct IClass *cl, Object *obj,
3332 struct MUIP_GetUData *msg)
3334 struct MUI_WindowData *data = INST_DATA(cl, obj);
3336 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
3338 get(obj, msg->attr, msg->storage);
3339 return TRUE;
3342 if (data->wd_RootObject)
3343 return DoMethodA(data->wd_RootObject, (Msg) msg);
3345 return FALSE;
3350 * MUIM_SetUData : This method tests if the MUIA_UserData of the object
3351 * contains the given <udata> and sets <attr> to <val> for itself in this case.
3353 IPTR Window__MUIM_SetUData(struct IClass *cl, Object *obj,
3354 struct MUIP_SetUData *msg)
3356 struct MUI_WindowData *data = INST_DATA(cl, obj);
3358 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
3359 set(obj, msg->attr, msg->val);
3361 if (data->wd_RootObject)
3362 DoMethodA(data->wd_RootObject, (Msg) msg);
3364 return TRUE;
3369 * MUIM_SetUDataOnce : This method tests if the MUIA_UserData of the object
3370 * contains the given <udata> and sets <attr> to <val> for itself in this case.
3372 IPTR Window__MUIM_SetUDataOnce(struct IClass *cl, Object *obj,
3373 struct MUIP_SetUDataOnce *msg)
3375 struct MUI_WindowData *data = INST_DATA(cl, obj);
3377 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
3379 set(obj, msg->attr, msg->val);
3380 return TRUE;
3383 if (data->wd_RootObject)
3384 return DoMethodA(data->wd_RootObject, (Msg) msg);
3386 return FALSE;
3389 /**************************************************************************
3390 Called by Application (parent) object whenever this object is added.
3391 init GlobalInfo
3392 **************************************************************************/
3393 IPTR Window__MUIM_ConnectParent(struct IClass *cl, Object *obj,
3394 struct MUIP_ConnectParent *msg)
3396 struct MUI_WindowData *data = INST_DATA(cl, obj);
3398 if (!DoSuperMethodA(cl, obj, (Msg) msg))
3399 return 0;
3401 if (data->wd_RootObject)
3402 DoMethod(data->wd_RootObject, MUIM_ConnectParent, (IPTR) obj);
3404 if (data->wd_ChildMenustrip)
3405 DoMethod(data->wd_ChildMenustrip, MUIM_ConnectParent, (IPTR) obj);
3407 return TRUE;
3411 /**************************************************************************
3412 called by parent object
3413 **************************************************************************/
3414 IPTR Window__MUIM_DisconnectParent(struct IClass *cl, Object *obj,
3415 struct MUIP_DisconnectParent *msg)
3417 struct MUI_WindowData *data = INST_DATA(cl, obj);
3419 /* D(bug("Window_DisconnectParent(%p) : muiGlobalInfo=%p\n", */
3420 /* muiGlobalInfo(obj))); */
3421 if (muiGlobalInfo(obj))
3423 /* Close the window before disconnecting all the childs */
3424 if ((data->wd_Flags & MUIWF_OPENED))
3426 /* D(bug(" Window_DisconnectParent(%p) : closing window\n", */
3427 /* muiGlobalInfo(obj))); */
3428 set(obj, MUIA_Window_Open, FALSE);
3430 if (data->wd_ChildMenustrip)
3431 DoMethod(data->wd_ChildMenustrip, MUIM_DisconnectParent,
3432 (IPTR) obj);
3434 if (data->wd_RootObject)
3435 DoMethodA(data->wd_RootObject, (Msg) msg);
3437 /* D(bug(" Window_DisconnectParent(%p) : calling supermethod\n", */
3438 /* muiGlobalInfo(obj))); */
3439 return DoSuperMethodA(cl, obj, (Msg) msg);
3441 else
3443 return 0;
3447 static void SetRootObjInnerSpacing(Object *obj,
3448 struct MUI_WindowData *data)
3450 UWORD wd_innerLeft, wd_innerRight, wd_innerTop, wd_innerBottom;
3452 if (data->wd_CrtFlags & WFLG_BORDERLESS)
3454 wd_innerLeft = 0;
3455 wd_innerRight = 0;
3456 wd_innerTop = 0;
3457 wd_innerBottom = 0;
3459 else
3461 wd_innerLeft = muiGlobalInfo(obj)->mgi_Prefs->window_inner_left;
3462 wd_innerRight = muiGlobalInfo(obj)->mgi_Prefs->window_inner_right;
3463 wd_innerTop = muiGlobalInfo(obj)->mgi_Prefs->window_inner_top;
3464 wd_innerBottom = muiGlobalInfo(obj)->mgi_Prefs->window_inner_bottom;
3467 if (!(muiAreaData(data->wd_RootObject)->mad_Flags & MADF_INNERLEFT))
3469 muiAreaData(data->wd_RootObject)->mad_InnerLeft = wd_innerLeft;
3472 if (!(muiAreaData(data->wd_RootObject)->mad_Flags & MADF_INNERTOP))
3474 muiAreaData(data->wd_RootObject)->mad_InnerTop = wd_innerTop;
3477 if (!(muiAreaData(data->wd_RootObject)->mad_Flags & MADF_INNERRIGHT))
3479 muiAreaData(data->wd_RootObject)->mad_InnerRight = wd_innerRight;
3482 if (!(muiAreaData(data->wd_RootObject)->mad_Flags & MADF_INNERBOTTOM))
3484 muiAreaData(data->wd_RootObject)->mad_InnerBottom = wd_innerBottom;
3489 * Called before window is opened or resized. It determines its bounds,
3490 * so you can call WindowSelectDimensions() to find the final dims.
3492 static void WindowMinMax(Object *obj, struct MUI_WindowData *data)
3494 SetRootObjInnerSpacing(obj, data);
3495 /* inquire about sizes */
3496 DoMethod(data->wd_RootObject, MUIM_AskMinMax, (IPTR) & data->wd_MinMax);
3497 /* D(bug("*** root minmax = %ld,%ld => %ld,%ld\n", */
3498 /* data->wd_MinMax.MinWidth, */
3499 /* data->wd_MinMax.MinHeight, */
3500 /* data->wd_MinMax.MaxWidth, data->wd_MinMax.MaxHeight)); */
3501 __area_finish_minmax(data->wd_RootObject, &data->wd_MinMax);
3502 /* D(bug("*** root minmax2 = %ld,%ld => %ld,%ld\n", */
3503 /* data->wd_MinMax.MinWidth, */
3504 /* data->wd_MinMax.MinHeight, */
3505 /* data->wd_MinMax.MaxWidth, data->wd_MinMax.MaxHeight)); */
3509 static void InstallBackbuffer(struct IClass *cl, Object *obj)
3511 struct MUI_WindowData *data = INST_DATA(cl, obj);
3512 #if 0
3513 struct Window *win = data->wd_RenderInfo.mri_Window;
3515 data->wd_RenderInfo.mri_BufferBM =
3516 AllocBitMap(win->Width, win->Height, win->RPort->BitMap->Depth,
3517 0, win->RPort->BitMap);
3518 #endif
3519 if (data->wd_RenderInfo.mri_BufferBM)
3521 /* D(bug("install_backbuffer : allocated bitmap %dx%dx%d " */
3522 /* "with friend %p\n", */
3523 /* win->Width, win->Height, win->RPort->BitMap->Depth, */
3524 /* win->RPort->BitMap)); */
3525 InitRastPort(&data->wd_RenderInfo.mri_BufferRP);
3526 data->wd_RenderInfo.mri_BufferRP.BitMap =
3527 data->wd_RenderInfo.mri_BufferBM;
3531 static void DeinstallBackbuffer(struct IClass *cl, Object *obj)
3533 struct MUI_WindowData *data = INST_DATA(cl, obj);
3535 if (data->wd_RenderInfo.mri_BufferBM)
3537 DeinitRastPort(&data->wd_RenderInfo.mri_BufferRP);
3538 FreeBitMap(data->wd_RenderInfo.mri_BufferBM);
3539 data->wd_RenderInfo.mri_BufferBM = NULL;
3544 * Called after window is opened or resized.
3545 * An expose event is already queued, it will trigger
3546 * MUIM_Draw for us when going back to main loop.
3548 static void WindowShow(struct IClass *cl, Object *obj)
3550 struct MUI_WindowData *data = INST_DATA(cl, obj);
3551 struct Window *win = data->wd_RenderInfo.mri_Window;
3552 /* D(bug("window_show %s %d\n", __FILE__, __LINE__)); */
3554 _left(data->wd_RootObject) = win->BorderLeft;
3555 _top(data->wd_RootObject) = win->BorderTop;
3556 _width(data->wd_RootObject) = data->wd_Width;
3557 _height(data->wd_RootObject) = data->wd_Height;
3559 DoMethod(data->wd_RootObject, MUIM_Layout);
3561 ShowRenderInfo(&data->wd_RenderInfo);
3562 /* D(bug("zune_imspec_show %s %d\n", __FILE__, __LINE__)); */
3563 zune_imspec_show(data->wd_Background, obj);
3564 DoShowMethod(data->wd_RootObject);
3567 static ULONG WindowOpen(struct IClass *cl, Object *obj)
3569 struct MUI_WindowData *data = INST_DATA(cl, obj);
3571 if (!data->wd_RootObject)
3572 return FALSE;
3574 if (!DoMethod(obj, MUIM_Window_Setup))
3575 return FALSE;
3577 /* I got display info, so calculate your display dependant data */
3578 if (!DoSetupMethod(data->wd_RootObject, &data->wd_RenderInfo))
3580 DoMethod(obj, MUIM_Window_Cleanup);
3581 return FALSE;
3584 /* inquire about sizes */
3585 WindowMinMax(obj, data);
3586 WindowSelectDimensions(data);
3588 /* Decide which menustrip should be used */
3589 if (!data->wd_ChildMenustrip)
3590 get(_app(obj), MUIA_Application_Menustrip, &data->wd_Menustrip);
3591 else
3592 data->wd_Menustrip = data->wd_ChildMenustrip;
3594 /* open window here ... */
3595 if (!DisplayWindow(obj, data))
3597 /* free display dependant data */
3598 data->wd_Menustrip = NULL;
3599 DoMethod(data->wd_RootObject, MUIM_Cleanup);
3600 DoMethod(obj, MUIM_Window_Cleanup);
3601 return FALSE;
3604 InstallBackbuffer(cl, obj);
3606 data->wd_Flags |= MUIWF_OPENED;
3608 WindowShow(cl, obj);
3611 LONG left, top, width, height;
3613 left = data->wd_RenderInfo.mri_Window->BorderLeft;
3614 top = data->wd_RenderInfo.mri_Window->BorderTop,
3615 width = data->wd_RenderInfo.mri_Window->Width
3616 - data->wd_RenderInfo.mri_Window->BorderRight - left;
3617 height = data->wd_RenderInfo.mri_Window->Height
3618 - data->wd_RenderInfo.mri_Window->BorderBottom - top;
3620 /* D(bug("zune_imspec_draw %s %d\n", __FILE__, __LINE__)); */
3621 // D(bug("%d:zune_imspec_draw(%p) l=%d t=%d w=%d h=%d xo=%d yo=%d\n",
3622 // __LINE__, data->wd_Background, left, top, width,
3623 // height, left, top));
3625 zune_imspec_draw(data->wd_Background, &data->wd_RenderInfo,
3626 left, top, width, height, left, top, 0);
3629 MUI_Redraw(data->wd_RootObject, MADF_DRAWOBJECT);
3631 D(bug("MUIC_Window:windowOpen() ActiveObject=%p\n",
3632 data->wd_ActiveObject));
3633 if (data->wd_OldActive != NULL)
3635 set(obj, MUIA_Window_ActiveObject, data->wd_OldActive);
3638 return TRUE;
3641 /**************************************************************************/
3642 /**************************************************************************/
3644 static ULONG WindowClose(struct IClass *cl, Object *obj)
3646 struct MUI_WindowData *data = INST_DATA(cl, obj);
3648 if (data->wd_ActiveObject != NULL)
3650 data->wd_OldActive = data->wd_ActiveObject;
3651 set(obj, MUIA_Window_ActiveObject, MUIV_Window_ActiveObject_None);
3654 KillHelpBubble(data, obj, BUBBLEHELP_TICKER_FIRST);
3656 /* remove from window */
3657 DoHideMethod(data->wd_RootObject);
3658 zune_imspec_hide(data->wd_Background);
3660 DeinstallBackbuffer(cl, obj);
3662 HideRenderInfo(&data->wd_RenderInfo);
3664 /* close here ... */
3665 UndisplayWindow(obj, data);
3667 data->wd_Flags &= ~MUIWF_OPENED;
3668 data->wd_Menustrip = NULL;
3670 /* free display dependant data */
3671 DoMethod(data->wd_RootObject, MUIM_Cleanup);
3672 DoMethod(obj, MUIM_Window_Cleanup);
3673 return TRUE;
3676 /* calculate a new layout
3677 * see MUIA_ShowMe
3678 * see Group_ExitChange
3679 * see Group_Columns
3680 * see Group_Rows
3682 IPTR Window__MUIM_RecalcDisplay(struct IClass *cl, Object *obj,
3683 struct MUIP_Window_RecalcDisplay *msg)
3685 struct MUI_WindowData *data = INST_DATA(cl, obj);
3686 LONG left, top, width, height;
3687 BOOL resized, reshow = FALSE;
3688 Object *current_obj;
3690 if (!(data->wd_Flags & MUIWF_OPENED))
3691 return 0;
3693 current_obj = msg->originator;
3695 // typically originator is a group which has been added/removed a child
3696 // calculate minmax of current obj
3697 // if new minmax can accomodate current obj size, stop
3698 // else try with its parent
3699 // the resulting object will get a new layout
3700 // it currently produces some redundant AskMinMax but allows
3701 // to not always relayout the whole window
3703 D(bug("RecalcDisplay on %p\n", current_obj));
3704 while (current_obj != NULL)
3706 DoMethod(current_obj, MUIM_AskMinMax,
3707 (IPTR) & muiAreaData(current_obj)->mad_MinMax);
3708 __area_finish_minmax(current_obj,
3709 &muiAreaData(current_obj)->mad_MinMax);
3711 D(bug("size w = %d, h = %d\n", _width(current_obj),
3712 _height(current_obj)));
3713 D(bug("new w = %d-%d, h = %d-%d\n", _minwidth(current_obj),
3714 _maxwidth(current_obj), _minheight(current_obj),
3715 _maxheight(current_obj)));
3717 if (!_between(_minwidth(current_obj), _width(current_obj),
3718 _maxwidth(current_obj))
3719 || !_between(_minheight(current_obj), _height(current_obj),
3720 _maxheight(current_obj)))
3722 current_obj = _parent(current_obj);
3723 D(bug("RecalcDisplay, try parent %p\n", current_obj));
3725 else
3727 D(bug("found it\n"));
3728 break;
3732 if (!current_obj)
3733 current_obj = data->wd_RootObject;
3735 WindowMinMax(obj, data);
3737 /* Important: current_obj could be hidden, like in an inactive page! */
3738 if (_flags(current_obj) & MADF_CANDRAW)
3740 reshow = TRUE;
3743 if (reshow)
3744 DoHideMethod(current_obj);
3746 /* resize window ? */
3747 WindowSelectDimensions(data);
3748 resized = WindowResize(data);
3750 if (!resized)
3752 /* FIXME: Should we short circuit the following
3753 * if the window size didn't change?
3758 struct Window *win = data->wd_RenderInfo.mri_Window;
3759 _left(data->wd_RootObject) = win->BorderLeft;
3760 _top(data->wd_RootObject) = win->BorderTop;
3761 _width(data->wd_RootObject) = data->wd_Width;
3762 _height(data->wd_RootObject) = data->wd_Height;
3764 DoMethod(current_obj, MUIM_Layout);
3766 if (reshow)
3767 DoShowMethod(current_obj);
3769 if (muiGlobalInfo(obj)->mgi_Prefs->window_redraw ==
3770 WINDOW_REDRAW_WITHOUT_CLEAR)
3772 if (reshow)
3773 MUI_Redraw(current_obj, MADF_DRAWOBJECT);
3775 else
3777 left = data->wd_RenderInfo.mri_Window->BorderLeft;
3778 top = data->wd_RenderInfo.mri_Window->BorderTop;
3779 width = data->wd_RenderInfo.mri_Window->Width
3780 - data->wd_RenderInfo.mri_Window->BorderRight - left;
3781 height = data->wd_RenderInfo.mri_Window->Height
3782 - data->wd_RenderInfo.mri_Window->BorderBottom - top;
3784 zune_imspec_draw(data->wd_Background, &data->wd_RenderInfo,
3785 left, top, width, height, left, top, 0);
3786 MUI_Redraw(data->wd_RootObject, MADF_DRAWALL);
3789 ActivateObject(data);
3791 return TRUE;
3795 /**************************************************************************
3796 MUIM_AddEventHandler
3797 **************************************************************************/
3798 IPTR Window__MUIM_AddEventHandler(struct IClass *cl, Object *obj,
3799 struct MUIP_Window_AddEventHandler *msg)
3801 struct MUI_WindowData *data = INST_DATA(cl, obj);
3803 //D(bug("muimaster.library/window.c: Add Eventhandler %p\n", msg->ehnode));
3805 msg->ehnode->ehn_Priority = msg->ehnode->ehn_Priority;
3806 EnqueueByPriAndAddress((struct List *)&data->wd_EHList,
3807 (struct Node *)msg->ehnode);
3808 ChangeEvents(data, GetDefaultEvents());
3809 return TRUE;
3812 /**************************************************************************
3813 MUIM_RemEventHandler
3814 **************************************************************************/
3815 IPTR Window__MUIM_RemEventHandler(struct IClass *cl, Object *obj,
3816 struct MUIP_Window_RemEventHandler *msg)
3818 struct MUI_WindowData *data = INST_DATA(cl, obj);
3820 //D(bug("muimaster.library/window.c: Rem Eventhandler %p\n", msg->ehnode));
3822 Remove((struct Node *)msg->ehnode);
3823 ChangeEvents(data, GetDefaultEvents());
3824 return TRUE;
3827 /**************************************************************************
3828 Note that this is MUIM_Window_Setup, not MUIM_Setup
3829 **************************************************************************/
3830 IPTR Window__MUIM_Setup(struct IClass *cl, Object *obj, Msg msg)
3832 struct MUI_WindowData *data = INST_DATA(cl, obj);
3834 if (!SetupRenderInfo(obj, data, &data->wd_RenderInfo))
3835 return FALSE;
3837 data->wd_Background =
3838 zune_imspec_setup(MUII_WindowBack, &data->wd_RenderInfo);
3840 if (muiGlobalInfo(obj)->mgi_Prefs->window_redraw ==
3841 WINDOW_REDRAW_WITH_CLEAR)
3842 data->wd_Flags |= MUIWF_ERASEAREA;
3844 return TRUE;
3847 /**************************************************************************
3848 MUIM_Cleanup
3849 **************************************************************************/
3850 IPTR Window__MUIM_Cleanup(struct IClass *cl, Object *obj, Msg msg)
3852 struct MUI_WindowData *data = INST_DATA(cl, obj);
3854 zune_imspec_cleanup(data->wd_Background);
3856 if (data->wd_dnd)
3858 DeleteDragNDrop(data->wd_dnd);
3859 data->wd_dnd = NULL;
3862 CleanupRenderInfo(obj, data, &data->wd_RenderInfo);
3863 return TRUE;
3867 /**************************************************************************
3868 This adds the the control char handler and also do the MUIA_CycleChain
3869 stuff. Orginal MUI does this in an other way.
3870 **************************************************************************/
3871 IPTR Window__MUIM_AddControlCharHandler(struct IClass *cl, Object *obj,
3872 struct MUIP_Window_AddControlCharHandler *msg)
3874 struct MUI_WindowData *data = INST_DATA(cl, obj);
3875 struct ObjNode *node;
3877 if (msg->ccnode->ehn_Events)
3879 msg->ccnode->ehn_Priority = msg->ccnode->ehn_Priority;
3880 Enqueue((struct List *)&data->wd_CCList,
3881 (struct Node *)msg->ccnode);
3883 /* Due to the lack of a better idea ... */
3884 if (muiAreaData(msg->ccnode->ehn_Object)->mad_Flags & MADF_CYCLECHAIN)
3886 node = AllocPooled(data->wd_MemoryPool, sizeof(struct ObjNode));
3887 if (node)
3889 node->obj = msg->ccnode->ehn_Object;
3890 AddTail((struct List *)&data->wd_CycleChain,
3891 (struct Node *)node);
3894 return TRUE;
3897 /**************************************************************************
3898 MUIM_RemControlCharHandler
3899 **************************************************************************/
3900 IPTR Window__MUIM_RemControlCharHandler(struct IClass *cl, Object *obj,
3901 struct MUIP_Window_RemControlCharHandler *msg)
3903 struct MUI_WindowData *data = INST_DATA(cl, obj);
3904 struct ObjNode *node =
3905 FindObjNode(&data->wd_CycleChain, msg->ccnode->ehn_Object);
3907 if (msg->ccnode->ehn_Events)
3908 Remove((struct Node *)msg->ccnode);
3910 if (node)
3912 /* Remove from the chain list */
3913 Remove((struct Node *)node);
3914 FreePooled(data->wd_MemoryPool, node, sizeof(struct ObjNode));
3917 return TRUE;
3920 /**************************************************************************
3921 MUIM_DragObject
3922 **************************************************************************/
3923 IPTR Window__MUIM_DragObject(struct IClass *cl, Object *obj,
3924 struct MUIP_Window_DragObject *msg)
3926 struct MUI_WindowData *data = INST_DATA(cl, obj);
3927 if (msg->obj)
3929 struct DragNDrop *dnd;
3930 struct MUI_DragImage *di;
3931 struct BitMapNode *bmn;
3933 if (!(dnd = CreateDragNDropA(NULL)))
3934 return 0;
3936 if (!(di =
3937 (struct MUI_DragImage *)DoMethod(msg->obj,
3938 MUIM_CreateDragImage, -msg->touchx, -msg->touchy,
3939 msg->flags)))
3941 DeleteDragNDrop(dnd);
3942 return 0;
3944 if (!di->bm)
3946 DoMethod(msg->obj, MUIM_DeleteDragImage, (IPTR) di);
3947 DeleteDragNDrop(dnd);
3948 return 0;
3951 if (!(bmn = CreateBitMapNodeA(TAGLIST(
3952 GUI_BitMap, (IPTR)di->bm,
3953 GUI_LeftOffset, di->touchx,
3954 GUI_TopOffset, di->touchy,
3955 GUI_Width, di->width,
3956 GUI_Height, di->height,
3957 GUI_SourceAlpha, !!(di->flags & MUIF_DRAGIMAGE_SOURCEALPHA)))))
3959 DoMethod(msg->obj, MUIM_DeleteDragImage, (IPTR) di);
3960 DeleteDragNDrop(dnd);
3961 return 0;
3964 AttachBitMapNode(dnd, bmn);
3966 if (!PrepareDragNDrop(dnd, data->wd_RenderInfo.mri_Screen))
3968 DoMethod(msg->obj, MUIM_DeleteDragImage, (IPTR) di);
3969 DeleteDragNDrop(dnd);
3970 return 0;
3973 muiAreaData(msg->obj)->mad_Flags |= MADF_DRAGGING;
3975 data->wd_DragObject = msg->obj;
3976 data->wd_dnd = dnd;
3977 data->wd_DragImage = di;
3978 return 1;
3980 return 0;
3983 /**************************************************************************
3984 MUIM_AllocGadgetID
3985 **************************************************************************/
3986 IPTR Window__MUIM_AllocGadgetID(struct IClass *cl, Object *obj,
3987 struct MUIP_Window_AllocGadgetID *msg)
3989 struct MUI_WindowData *data = INST_DATA(cl, obj);
3990 struct IDNode *newnode;
3992 newnode = AllocPooled(data->wd_MemoryPool, sizeof(struct IDNode));
3993 if (newnode)
3995 int id;
3996 struct MinNode *mn;
3998 if (IsListEmpty((struct List *)&data->wd_IDList))
4000 newnode->id = 1;
4001 AddHead((struct List *)&data->wd_IDList,
4002 (struct Node *)&newnode->node);
4003 return (IPTR) 1;
4006 id = 1;
4008 for (mn = data->wd_IDList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
4010 struct IDNode *idn = (struct IDNode *)mn;
4011 if (id < idn->id)
4012 break;
4013 id++;
4015 newnode->id = id;
4016 Insert((struct List *)&data->wd_IDList,
4017 (struct Node *)&newnode->node, (struct Node *)mn);
4018 return (IPTR) id;
4021 return 0;
4024 /**************************************************************************
4025 MUIM_FreeGadgetID
4026 **************************************************************************/
4027 IPTR Window__MUIM_FreeGadgetID(struct IClass *cl, Object *obj,
4028 struct MUIP_Window_FreeGadgetID *msg)
4030 struct MUI_WindowData *data = INST_DATA(cl, obj);
4031 struct MinNode *mn;
4033 for (mn = data->wd_IDList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
4035 struct IDNode *idn = (struct IDNode *)mn;
4036 if (msg->gadgetid == idn->id)
4038 Remove((struct Node *)idn);
4039 FreePooled(data->wd_MemoryPool, idn, sizeof(struct IDNode));
4040 return 0;
4044 return 0;
4048 /**************************************************************************
4049 MUIM_Window_GetMenuCheck
4050 **************************************************************************/
4051 IPTR Window__MUIM_GetMenuCheck(struct IClass *cl, Object *obj,
4052 struct MUIP_Window_GetMenuCheck *msg)
4054 IPTR stat = 0;
4055 struct MUI_WindowData *data = INST_DATA(cl, obj);
4056 Object *item;
4057 Object *strip = data->wd_ChildMenustrip;
4058 if (!strip)
4059 strip = data->wd_Menustrip;
4060 if (!strip)
4061 return 0;
4062 if (!(item = (Object *) DoMethod(strip, MUIM_FindUData, msg->MenuID)))
4063 return 0;
4064 get(item, MUIA_Menuitem_Checked, &stat);
4065 return stat;
4068 /**************************************************************************
4069 MUIM_Window_SetMenuCheck
4070 **************************************************************************/
4071 IPTR Window__MUIM_SetMenuCheck(struct IClass *cl, Object *obj,
4072 struct MUIP_Window_SetMenuCheck *msg)
4074 struct MUI_WindowData *data = INST_DATA(cl, obj);
4075 Object *item;
4076 Object *strip = data->wd_ChildMenustrip;
4077 if (!strip)
4078 strip = data->wd_Menustrip;
4079 if (!strip)
4080 return 0;
4081 if (!(item = (Object *) DoMethod(strip, MUIM_FindUData, msg->MenuID)))
4082 return 0;
4083 set(item, MUIA_Menuitem_Checked, msg->stat);
4084 return 0;
4087 /**************************************************************************
4088 MUIM_Window_GetMenuState
4089 **************************************************************************/
4090 IPTR Window__MUIM_GetMenuState(struct IClass *cl, Object *obj,
4091 struct MUIP_Window_GetMenuState *msg)
4093 IPTR stat = 0;
4094 struct MUI_WindowData *data = INST_DATA(cl, obj);
4095 Object *item;
4096 Object *strip = data->wd_ChildMenustrip;
4097 if (!strip)
4098 strip = data->wd_Menustrip;
4099 if (!strip)
4100 return 0;
4101 if (!(item = (Object *) DoMethod(strip, MUIM_FindUData, msg->MenuID)))
4102 return 0;
4103 get(item, MUIA_Menuitem_Enabled, &stat);
4104 return stat;
4107 /**************************************************************************
4108 MUIM_Window_SetMenuState
4109 **************************************************************************/
4110 IPTR Window__MUIM_SetMenuState(struct IClass *cl, Object *obj,
4111 struct MUIP_Window_SetMenuState *msg)
4113 struct MUI_WindowData *data = INST_DATA(cl, obj);
4114 Object *item;
4115 Object *strip = data->wd_ChildMenustrip;
4116 if (!strip)
4117 strip = data->wd_Menustrip;
4118 if (!strip)
4119 return 0;
4120 if (!(item = (Object *) DoMethod(strip, MUIM_FindUData, msg->MenuID)))
4121 return 0;
4122 set(item, MUIA_Menuitem_Enabled, msg->stat);
4123 return 0;
4126 /**************************************************************************
4127 MUIM_Window_DrawBackground
4128 **************************************************************************/
4129 IPTR Window__MUIM_DrawBackground(struct IClass *cl, Object *obj,
4130 struct MUIP_Window_DrawBackground *msg)
4132 struct MUI_WindowData *data = INST_DATA(cl, obj);
4133 if (!(data->wd_RenderInfo.mri_Window)) /* not between show/hide */
4134 return FALSE;
4136 // D(bug("%d:zune_imspec_draw(%p) l=%d t=%d w=%d h=%d xo=%d yo=%d\n",
4137 // __LINE__, data->wd_Background, msg->left, msg->top, msg->width,
4138 // msg->height, msg->xoffset, msg->yoffset));
4139 zune_imspec_draw(data->wd_Background, &data->wd_RenderInfo,
4140 msg->left, msg->top, msg->width, msg->height,
4141 msg->xoffset, msg->yoffset, 0);
4142 return 0;
4145 /**************************************************************************
4146 MUIM_Window_ToFront
4147 **************************************************************************/
4148 IPTR Window__MUIM_ToFront(struct IClass *cl, Object *obj, Msg msg)
4150 struct MUI_WindowData *data = INST_DATA(cl, obj);
4151 if (!(data->wd_RenderInfo.mri_Window)) /* not between show/hide */
4152 return 0;
4154 WindowToFront(data->wd_RenderInfo.mri_Window);
4155 return 1;
4158 /**************************************************************************
4159 MUIM_Window_ToBack
4160 **************************************************************************/
4161 IPTR Window__MUIM_ToBack(struct IClass *cl, Object *obj, Msg msg)
4163 struct MUI_WindowData *data = INST_DATA(cl, obj);
4164 if (!(data->wd_RenderInfo.mri_Window)) /* not between show/hide */
4165 return 0;
4167 WindowToBack(data->wd_RenderInfo.mri_Window);
4168 return 1;
4171 /**************************************************************************
4172 MUIM_Window_ScreenToBack
4173 **************************************************************************/
4174 IPTR Window__MUIM_ScreenToBack(struct IClass *cl, Object *obj, Msg msg)
4176 struct MUI_WindowData *data = INST_DATA(cl, obj);
4177 if (!(data->wd_RenderInfo.mri_Window)) /* not between show/hide */
4178 return 0;
4180 ScreenToBack(data->wd_RenderInfo.mri_Screen);
4181 return 1;
4184 /**************************************************************************
4185 MUIM_Window_ScreenToFront
4186 **************************************************************************/
4187 IPTR Window__MUIM_ScreenToFront(struct IClass *cl, Object *obj, Msg msg)
4189 struct MUI_WindowData *data = INST_DATA(cl, obj);
4190 if (!(data->wd_RenderInfo.mri_Window)) /* not between show/hide */
4191 return 0;
4193 ScreenToFront(data->wd_RenderInfo.mri_Screen);
4194 return 1;
4197 /**************************************************************************
4198 MUIM_Window_ActionIconify
4199 **************************************************************************/
4200 IPTR Window__MUIM_ActionIconify(struct IClass *cl, Object *obj, Msg msg)
4202 set(_app(obj), MUIA_Application_Iconified, TRUE);
4204 return TRUE;
4208 /* Loads ENV: prefs, add a Window_ID chunk in the MUIW chunk, if no MUIW chunk
4209 * then create it at the same level as MUIC chunk, save prefs.
4210 * Do the same for ENVARC:
4211 * MUIW chunk layout:
4212 * 'MUIW'
4213 * 00 00 00 30 (chunk length for a single window, 0x30L big endian)
4214 * 'this window ID'
4215 * 00 00 00 28
4216 * xx xx yy yy (X, Y)
4217 * ww ww hh hh (Width, Height)
4218 * ax ax ay ay (AltX, AltY)
4219 * aw aw ah ah (AltWidth, AltHeight)
4220 * 00 00 00 00 (???)
4221 * 00 00 00 00
4222 * 00 00 00 00
4223 * 00 00 00 00
4224 * 00 01 00 00
4225 * 00 00 00 00
4227 static void RememberWindowPosition(Object *winobj, ULONG id)
4229 if (!id)
4230 return;
4233 /* Loads ENV: prefs, remove our Window_ID chunk from the MUIW chunk,
4234 * save prefs.
4235 * Do the same for ENVARC:
4236 * This function shouldn't really be in window.c, but rather in a file dealing
4237 * with prefs file stuff.
4239 static void ForgetWindowPosition(Object *winobj, ULONG id)
4241 if (!id)
4242 return;
4245 /**************************************************************************
4246 MUIM_Window_Snapshot
4247 **************************************************************************/
4248 IPTR Window__MUIM_Snapshot(struct IClass *cl, Object *obj,
4249 struct MUIP_Window_Snapshot *msg)
4251 struct MUI_WindowData *data = INST_DATA(cl, obj);
4252 struct windowpos winp;
4253 struct Window *w;
4254 winp.id = data->wd_ID;
4255 w = data->wd_RenderInfo.mri_Window;
4256 if (w)
4258 winp.x1 = w->LeftEdge;
4259 winp.y1 = w->TopEdge;
4260 winp.w1 = w->GZZWidth;
4261 winp.h1 = w->GZZHeight;
4262 winp.x2 = 0;
4263 winp.x2 = 0;
4264 winp.w2 = 0;
4265 winp.h2 = 0; //to do save alt dims
4267 set(_app(obj), MUIA_Application_SetWinPos, &winp);
4270 if (msg->flags)
4271 RememberWindowPosition(obj, data->wd_ID);
4272 else
4273 ForgetWindowPosition(obj, data->wd_ID);
4274 return 1;
4277 /**************************************************************************
4278 MUIM_Window_UpdateMenu
4279 **************************************************************************/
4280 IPTR Window__MUIM_UpdateMenu(struct IClass *cl, Object *obj, Msg msg)
4282 struct MUI_WindowData *data = INST_DATA(cl, obj);
4284 struct Menu *menu = NULL;
4285 struct NewMenu *newmenu = NULL;
4286 APTR visinfo = NULL;
4287 struct Window *win = NULL;
4289 if (data->wd_Menustrip) // only open windows can have a menustrip
4291 if ((visinfo =
4292 GetVisualInfoA(data->wd_RenderInfo.mri_Screen, NULL)))
4294 win = data->wd_RenderInfo.mri_Window;
4295 ClearMenuStrip(win);
4296 if (data->wd_Menu)
4298 FreeMenus(data->wd_Menu);
4299 data->wd_Menu = NULL;
4302 get(data->wd_Menustrip, MUIA_Menuitem_NewMenu, &newmenu);
4303 if (newmenu)
4305 if ((menu = CreateMenusA(newmenu, NULL)))
4307 struct TagItem tags[] = {
4308 {GTMN_NewLookMenus, TRUE},
4309 {TAG_DONE, 0}
4311 LayoutMenusA(menu, visinfo, tags);
4312 data->wd_Menu = menu;
4313 SetMenuStrip(win, menu);
4316 FreeVisualInfo(visinfo);
4320 return 1;
4323 /**************************************************************************
4324 MUIM_Export : to export an objects "contents" to a dataspace object.
4325 **************************************************************************/
4326 static IPTR Window__MUIM_Export(struct IClass *cl, Object *obj,
4327 struct MUIP_Export *msg)
4329 struct MUI_WindowData *data = INST_DATA(cl, obj);
4330 DoMethodA(data->wd_RootObject, (Msg) msg);
4331 return 0;
4335 /**************************************************************************
4336 MUIM_Import : to import an objects "contents" from a dataspace object.
4337 **************************************************************************/
4338 static IPTR Window__MUIM_Import(struct IClass *cl, Object *obj,
4339 struct MUIP_Import *msg)
4341 struct MUI_WindowData *data = INST_DATA(cl, obj);
4342 DoMethodA(data->wd_RootObject, (Msg) msg);
4343 return 0;
4346 BOOPSI_DISPATCHER(IPTR, Window_Dispatcher, cl, obj, msg)
4348 switch (msg->MethodID)
4350 case OM_NEW:
4351 return Window__OM_NEW(cl, obj, (struct opSet *)msg);
4352 case OM_DISPOSE:
4353 return Window__OM_DISPOSE(cl, obj, msg);
4354 case OM_SET:
4355 return Window__OM_SET(cl, obj, (struct opSet *)msg);
4356 case OM_GET:
4357 return Window__OM_GET(cl, obj, (struct opGet *)msg);
4358 case MUIM_FindUData:
4359 return Window__MUIM_FindUData(cl, obj,
4360 (struct MUIP_FindUData *)msg);
4361 case MUIM_GetUData:
4362 return Window__MUIM_GetUData(cl, obj, (struct MUIP_GetUData *)msg);
4363 case MUIM_SetUData:
4364 return Window__MUIM_SetUData(cl, obj, (struct MUIP_SetUData *)msg);
4365 case MUIM_SetUDataOnce:
4366 return Window__MUIM_SetUDataOnce(cl, obj,
4367 (struct MUIP_SetUDataOnce *)msg);
4368 case MUIM_Window_AddEventHandler:
4369 return Window__MUIM_AddEventHandler(cl, obj, (APTR) msg);
4370 case MUIM_Window_RemEventHandler:
4371 return Window__MUIM_RemEventHandler(cl, obj, (APTR) msg);
4372 case MUIM_ConnectParent:
4373 return Window__MUIM_ConnectParent(cl, obj, (APTR) msg);
4374 case MUIM_DisconnectParent:
4375 return Window__MUIM_DisconnectParent(cl, obj, (APTR) msg);
4376 case MUIM_Window_RecalcDisplay:
4377 return Window__MUIM_RecalcDisplay(cl, obj, (APTR) msg);
4378 case MUIM_Window_Setup:
4379 return Window__MUIM_Setup(cl, obj, (APTR) msg);
4380 case MUIM_Window_Cleanup:
4381 return Window__MUIM_Cleanup(cl, obj, (APTR) msg);
4382 case MUIM_Window_AddControlCharHandler:
4383 return Window__MUIM_AddControlCharHandler(cl, obj, (APTR) msg);
4384 case MUIM_Window_RemControlCharHandler:
4385 return Window__MUIM_RemControlCharHandler(cl, obj, (APTR) msg);
4386 case MUIM_Window_DragObject:
4387 return Window__MUIM_DragObject(cl, obj, (APTR) msg);
4388 case MUIM_Window_AllocGadgetID:
4389 return Window__MUIM_AllocGadgetID(cl, obj, (APTR) msg);
4390 case MUIM_Window_FreeGadgetID:
4391 return Window__MUIM_FreeGadgetID(cl, obj, (APTR) msg);
4392 case MUIM_Window_GetMenuCheck:
4393 return Window__MUIM_GetMenuCheck(cl, obj, (APTR) msg);
4394 case MUIM_Window_SetMenuCheck:
4395 return Window__MUIM_SetMenuCheck(cl, obj, (APTR) msg);
4396 case MUIM_Window_GetMenuState:
4397 return Window__MUIM_GetMenuState(cl, obj, (APTR) msg);
4398 case MUIM_Window_SetMenuState:
4399 return Window__MUIM_SetMenuState(cl, obj, (APTR) msg);
4400 case MUIM_Window_DrawBackground:
4401 return Window__MUIM_DrawBackground(cl, obj, (APTR) msg);
4402 case MUIM_Window_ToFront:
4403 return Window__MUIM_ToFront(cl, obj, (APTR) msg);
4404 case MUIM_Window_ToBack:
4405 return Window__MUIM_ToBack(cl, obj, (APTR) msg);
4406 case MUIM_Window_ScreenToFront:
4407 return Window__MUIM_ScreenToFront(cl, obj, (APTR) msg);
4408 case MUIM_Window_ScreenToBack:
4409 return Window__MUIM_ScreenToBack(cl, obj, (APTR) msg);
4410 case MUIM_Window_ActionIconify:
4411 return Window__MUIM_ActionIconify(cl, obj, (APTR) msg);
4412 case MUIM_Window_Snapshot:
4413 return Window__MUIM_Snapshot(cl, obj, (APTR) msg);
4414 case MUIM_Window_UpdateMenu:
4415 return Window__MUIM_UpdateMenu(cl, obj, (APTR) msg);
4416 case MUIM_Export:
4417 return Window__MUIM_Export(cl, obj, (APTR) msg);
4418 case MUIM_Import:
4419 return Window__MUIM_Import(cl, obj, (APTR) msg);
4422 return DoSuperMethodA(cl, obj, msg);
4424 BOOPSI_DISPATCHER_END
4427 * Class descriptor.
4429 const struct __MUIBuiltinClass _MUI_Window_desc =
4431 MUIC_Window,
4432 MUIC_Notify,
4433 sizeof(struct MUI_WindowData),
4434 (void *) Window_Dispatcher