use dmb/dsb from asm/cpu.h file.
[AROS.git] / workbench / libs / muimaster / classes / window.c
blob7b1e9e048ded4f190b82926830b0db19c4b63548
1 /*
2 Copyright © 1999, David Le Corfec.
3 Copyright © 2002-2017, The AROS Development Team.
4 All rights reserved.
6 $Id$
7 */
8 #include <exec/types.h>
9 #include <exec/memory.h>
11 #include <string.h>
13 #include <intuition/imageclass.h>
14 #include <intuition/icclass.h>
15 #include <intuition/gadgetclass.h>
16 #ifdef __AROS__
17 #include <intuition/extensions.h>
18 #endif
19 #include <clib/alib_protos.h>
20 #include <graphics/gfxmacros.h>
21 #include <proto/exec.h>
22 #include <proto/intuition.h>
23 #include <proto/utility.h>
24 #include <proto/graphics.h>
25 #include <proto/commodities.h>
26 #include <proto/layers.h>
27 #include <proto/gadtools.h>
28 #include <proto/muimaster.h>
29 #include <proto/workbench.h>
31 #define MUI_OBSOLETE /* for the obsolete menu stuff */
33 #include "mui.h"
34 #include "support.h"
35 #include "classes/window.h"
36 #include "classes/area.h"
37 #include "imspec.h"
38 #include "datatypescache.h"
39 #include "prefs.h"
40 #include "dragndrop.h"
42 #include "muimaster_intern.h"
44 //#define MYDEBUG 1
45 #include "debug.h"
47 extern struct Library *MUIMasterBase;
49 static const int __version = 1;
50 static const int __revision = 1;
52 #define IM(x) ((struct Image*)(x))
53 #define G(x) ((struct Gadget*)(x))
54 #define GADGETID(x) (((struct Gadget*)(x))->GadgetID)
56 /* this is for the cycle list */
57 struct ObjNode
59 struct MinNode node;
60 Object *obj;
63 /* For the gadget ids */
64 struct IDNode
66 struct MinNode node;
67 UWORD id;
70 struct MUI_ImageSpec_intern;
72 struct MUI_WindowData
74 struct MUI_RenderInfo wd_RenderInfo;
75 struct MUI_MinMax wd_MinMax;
76 struct IBox wd_AltDim; /* zoomed dimensions */
77 BOOL wd_ZoomGadget; /* enable/disable zoomgadget (altdim stuff) */
78 APTR wd_MemoryPool; /* for nodes and stuff to deallocate at
79 * OM_DISPOSE */
80 struct MinList wd_CycleChain; /* objects activated with tab */
81 struct MinList wd_EHList; /* event handlers */
82 struct MinList wd_CCList; /* control chars */
83 struct MinList wd_IDList; /* gadget ids */
84 ULONG wd_Events; /* events received */
85 ULONG wd_CrtFlags; /* window creation flags, see below */
86 Object *wd_ActiveObject; /* the active object */
87 Object *wd_OldActive; /* active object before window was closed */
88 APTR wd_DefaultObject;
89 ULONG wd_ID;
90 STRPTR wd_Title;
91 STRPTR wd_ScreenTitle;
92 LONG wd_Height; /* Current dimensions */
93 LONG wd_Width;
94 LONG wd_X;
95 LONG wd_Y;
96 LONG wd_ReqHeight; /* given by programmer */
97 LONG wd_ReqWidth;
98 LONG wd_ReqX;
99 LONG wd_ReqY;
100 APTR wd_RootObject; /* unique child */
101 ULONG wd_Flags; /* various status flags */
102 struct MUI_ImageSpec_intern *wd_Background;
103 ULONG wd_DisabledKeys;
104 BOOL wd_NoMenus; /* MUIA_Window_NoMenus */
106 Object *wd_DragObject; /* the object which is being dragged */
107 struct Window *wd_DropWindow; /* the destination window, for faster
108 * access */
109 Object *wd_DropObject; /* the destination object */
110 struct DragNDrop *wd_dnd;
111 struct MUI_DragImage *wd_DragImage;
112 struct AppWindow *wd_AppWindow;
114 Object *wd_Menustrip; /* The menustrip object which is actually
115 * used (either app's or window's or NULL) */
116 Object *wd_ChildMenustrip; /* If window has its own Menustrip */
117 struct Menu *wd_Menu; /* the intuition menustrip */
119 Object *wd_VertProp;
120 Object *wd_UpButton;
121 Object *wd_DownButton;
123 Object *wd_HorizProp;
124 Object *wd_LeftButton;
125 Object *wd_RightButton;
126 Object *wd_RefWindow;
128 Object *wd_MUIGadget;
130 Object *wd_HelpObject;
131 APTR wd_HelpBubble;
132 WORD wd_HelpTicker;
134 struct Screen *wd_UserScreen;
135 STRPTR wd_UserPublicScreen;
137 WORD wd_SleepCount; /* MUIA_Window_Sleep nests */
138 LONG wd_SleepMaxHeight; /* Remember Min/Max values for wakeup */
139 LONG wd_SleepMaxWidth;
140 LONG wd_SleepMinHeight;
141 LONG wd_SleepMinWidth;
143 struct IClass *wd_Class;
146 #ifndef WFLG_SIZEGADGET
148 #define WFLG_CLOSEGADGET (1<<0) /* has close gadget */
149 #define WFLG_SIZEGADGET (1<<1) /* has size gadget */
150 #define WFLG_BACKDROP (1<<2) /* is backdrop window */
151 #define WFLG_BORDERLESS (1<<3) /* has no borders */
152 #define WFLG_DEPTHGADGET (1<<4) /* has depth gadget */
153 #define WFLG_DRAGBAR (1<<5) /* is draggable */
154 #define WFLG_SIZEBRIGHT (1<<6) /* size gadget is in right border */
156 #endif
158 /* wd_Flags */
159 #define MUIWF_OPENED (1<<0) /* window currently opened */
160 #define MUIWF_HIDDEN (1<<1) /* window currently iconified */
161 #define MUIWF_ACTIVE (1<<2) /* window currently active */
162 #define MUIWF_RESIZING (1<<4) /* window currently resizing */
163 #define MUIWF_DONTACTIVATE (1<<7) /* do not activate the window when
164 * opening */
165 #define MUIWF_USERIGHTSCROLLER (1<<8) /* should have right scroller */
166 #define MUIWF_USEBOTTOMSCROLLER (1<<9) /* should have bottom scroller */
167 #define MUIWF_ERASEAREA (1<<10) /* Erase area after a window resize */
168 #define MUIWF_ISAPPWINDOW (1<<11) /* Is an AppWindow */
169 #define MUIWF_ISSUBWINDOW (1<<12) /* Don't get automatically disposed
170 * with app */
171 #define MUIWF_BUBBLEMODE (1<<13) /* Quick bubble mode. Bubbles appear
172 * quick when moving */
173 #define MUIWF_OPENONUNHIDE (1<<14) /* Open the window when unhiding */
174 #define MUIWF_SCREENLOCKED (1<<15) /* A pub screen was locked in
175 * SetupRenderInfo. Unlock it in
176 * CleanupRenderInfo! */
177 #define MUIWF_OBJECTGOACTIVESENT (1<<16) /* A MUIM_GoActive msg was sent to
178 * window's active object */
179 #define MUIWF_TOOLBOX (1<<17) /* Window should be opened as
180 * ToolBox */
182 #define BUBBLEHELP_TICKER_FIRST 10
183 #define BUBBLEHELP_TICKER_LATER 3
185 struct __dummyXFC3__
187 struct MUI_NotifyData mnd;
188 struct MUI_WindowData mwd;
191 #define muiWindowData(obj) (&(((struct __dummyXFC3__ *)(obj))->mwd))
193 /****** List.mui/MUIA_Window_DragBar *****************************************
195 * NAME
196 * MUIA_Window_DragBar -- (V4) [I..], BOOL
198 * FUNCTION
199 * Allow the window to be dragged. Defaults to TRUE.
201 * SEE ALSO
202 * MUIA_Window_DepthGadget, MUIA_Window_SizeGadget
204 ******************************************************************************
208 /****** List.mui/MUIA_Window_ScreenTitle *************************************
210 * NAME
211 * MUIA_Window_ScreenTitle -- (V5) [ISG], STRPTR
213 * FUNCTION
214 * The title shown in the drag bar of the window's screen when the
215 * screen is active. If set to NULL, the screen's default title is shown.
216 * The set string is not copied.
218 * SEE ALSO
219 * MUIA_Window_Title
221 ******************************************************************************
225 /****** List.mui/MUIA_Window_Title *******************************************
227 * NAME
228 * MUIA_Window_Title -- (V4) [ISG], STRPTR
230 * FUNCTION
231 * The window title, as shown in the drag bar. If set to NULL, no title
232 * is shown. The set string is not copied.
234 * SEE ALSO
235 * MUIA_Window_ScreenTitle
237 ******************************************************************************
241 static void ActivateObject(struct MUI_WindowData *data);
242 static void HandleInputEvent(Object *win, struct MUI_WindowData *data,
243 struct IntuiMessage *event);
245 static ULONG DoHalfshineGun(ULONG a, ULONG b)
247 ULONG val = ((((a) >> 24) + 3 * ((b) >> 24)) / 4);
248 val = val + (val << 8) + (val << 16) + (val << 24);
249 return val;
252 static ULONG DoHalfshadowGun(ULONG a, ULONG b)
254 ULONG val = ((((a) >> 24) + 5 * ((b) >> 24)) / 6);
255 val = val + (val << 8) + (val << 16) + (val << 24);
256 return val;
259 static Object *CreateSysimage(struct DrawInfo *dri, ULONG which)
261 return NewObject(NULL, "sysiclass",
262 SYSIA_DrawInfo, (IPTR) dri, SYSIA_Which, which, TAG_DONE);
265 static void EnqueueByPriAndAddress(struct List *list, struct Node *node)
267 struct Node *scannode;
269 /* Sort by priority and by node address, so that a
270 "remove - modify - enqueue" sequence will re-add
271 the node at the same place in the list it was
272 initially */
273 ForeachNode(list, scannode)
275 if (((struct Node *)node)->ln_Pri > scannode->ln_Pri)
276 break;
277 if (((struct Node *)node)->ln_Pri == scannode->ln_Pri)
279 if ((IPTR) node > (IPTR) scannode)
280 break;
284 Insert(list, (struct Node *)node, scannode->ln_Pred);
287 static BOOL InitCustomFrames(Object *obj, struct MUI_RenderInfo *mri)
289 int i;
291 for (i = 0; i < 16; i++)
293 mri->mri_FrameImage[i] = NULL;
296 mri->mri_FrameImage[0] =
297 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
298 customframe_config_1, mri->mri_Screen);
299 mri->mri_FrameImage[1] =
300 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
301 customframe_config_2, mri->mri_Screen);
302 mri->mri_FrameImage[2] =
303 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
304 customframe_config_3, mri->mri_Screen);
305 mri->mri_FrameImage[3] =
306 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
307 customframe_config_4, mri->mri_Screen);
308 mri->mri_FrameImage[4] =
309 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
310 customframe_config_5, mri->mri_Screen);
311 mri->mri_FrameImage[5] =
312 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
313 customframe_config_6, mri->mri_Screen);
314 mri->mri_FrameImage[6] =
315 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
316 customframe_config_7, mri->mri_Screen);
317 mri->mri_FrameImage[7] =
318 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
319 customframe_config_8, mri->mri_Screen);
320 mri->mri_FrameImage[8] =
321 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
322 customframe_config_9, mri->mri_Screen);
323 mri->mri_FrameImage[9] =
324 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
325 customframe_config_10, mri->mri_Screen);
326 mri->mri_FrameImage[10] =
327 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
328 customframe_config_11, mri->mri_Screen);
329 mri->mri_FrameImage[11] =
330 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
331 customframe_config_12, mri->mri_Screen);
332 mri->mri_FrameImage[12] =
333 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
334 customframe_config_13, mri->mri_Screen);
335 mri->mri_FrameImage[13] =
336 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
337 customframe_config_14, mri->mri_Screen);
338 mri->mri_FrameImage[14] =
339 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
340 customframe_config_15, mri->mri_Screen);
341 mri->mri_FrameImage[15] =
342 load_custom_frame(muiGlobalInfo(obj)->mgi_Prefs->
343 customframe_config_16, mri->mri_Screen);
345 return TRUE;
348 static void DisposeCustomFrames(struct MUI_RenderInfo *mri)
350 int i;
352 for (i = 0; i < 16; i++)
354 dispose_custom_frame(mri->mri_FrameImage[i]);
356 mri->mri_FrameImage[i] = NULL;
360 static BOOL SetupRenderInfo(Object *obj, struct MUI_WindowData *data,
361 struct MUI_RenderInfo *mri)
363 ULONG rgbtable[3 * 3];
364 Object *temp_obj;
365 IPTR val;
366 int i;
368 /* TODO: Move this whole screen locking/opening stuff into the
369 * application class by creating methods for this purpose */
371 /* If no user screen has been specified try to open the application
372 * specific screen */
373 if (!data->wd_UserScreen)
375 ULONG screenmodeid = muiGlobalInfo(obj)->mgi_Prefs->screenmodeid;
377 if (screenmodeid != ~0)
379 if (!muiGlobalInfo(obj)->mgi_CustomScreen)
381 muiGlobalInfo(obj)->mgi_CustomScreen = OpenScreenTags
382 (NULL,
383 SA_DisplayID, screenmodeid,
384 SA_SharePens, TRUE,
385 SA_FullPalette, TRUE, SA_LikeWorkbench, TRUE, TAG_DONE);
386 /* It's fine if this fails as there is a fallback case below */
389 data->wd_UserScreen = muiGlobalInfo(obj)->mgi_CustomScreen;
392 if (data->wd_UserScreen)
394 mri->mri_Screen = data->wd_UserScreen;
396 else
398 if (data->wd_UserPublicScreen)
400 mri->mri_Screen = LockPubScreen(data->wd_UserPublicScreen);
402 else if (muiGlobalInfo(obj)->mgi_Prefs->publicscreen_name
403 && muiGlobalInfo(obj)->mgi_Prefs->publicscreen_name[0])
405 mri->mri_Screen =
406 LockPubScreen(muiGlobalInfo(obj)->mgi_Prefs->
407 publicscreen_name);
408 // FIXME: open the public screen if necessary
411 if (mri->mri_Screen == NULL)
413 mri->mri_Screen = LockPubScreen(NULL);
414 if (mri->mri_Screen == NULL)
416 return FALSE;
420 // FIXME: is this the right place for this action?
421 if (mri->mri_Screen
422 && muiGlobalInfo(obj)->mgi_Prefs->publicscreen_pop_to_front)
424 ScreenToFront(mri->mri_Screen);
427 data->wd_Flags |= MUIWF_SCREENLOCKED;
430 if (!(mri->mri_DrawInfo = GetScreenDrawInfo(mri->mri_Screen)))
432 if (data->wd_Flags & MUIWF_SCREENLOCKED)
434 UnlockPubScreen(NULL, mri->mri_Screen);
435 data->wd_Flags &= ~MUIWF_SCREENLOCKED;
437 return FALSE;
440 if (!InitCustomFrames(obj, mri))
442 if (data->wd_Flags & MUIWF_SCREENLOCKED)
444 UnlockPubScreen(NULL, mri->mri_Screen);
445 data->wd_Flags &= ~MUIWF_SCREENLOCKED;
447 return FALSE;
450 mri->mri_Colormap = mri->mri_Screen->ViewPort.ColorMap;
451 mri->mri_ScreenWidth = mri->mri_Screen->Width;
452 mri->mri_ScreenHeight = mri->mri_Screen->Height;
454 if (mri->mri_ScreenWidth / mri->mri_ScreenHeight < 2)
456 mri->mri_Flags |= MUIMRI_THINFRAMES;
459 if (GetBitMapAttr(mri->mri_Screen->RastPort.BitMap, BMA_DEPTH) >= 15)
461 mri->mri_Flags |= MUIMRI_TRUECOLOR;
464 mri->mri_PensStorage[MPEN_SHINE] =
465 mri->mri_DrawInfo->dri_Pens[SHINEPEN];
466 mri->mri_PensStorage[MPEN_BACKGROUND] =
467 mri->mri_DrawInfo->dri_Pens[BACKGROUNDPEN];
468 mri->mri_PensStorage[MPEN_SHADOW] =
469 mri->mri_DrawInfo->dri_Pens[SHADOWPEN];
470 mri->mri_PensStorage[MPEN_TEXT] = mri->mri_DrawInfo->dri_Pens[TEXTPEN];
471 mri->mri_PensStorage[MPEN_FILL] = mri->mri_DrawInfo->dri_Pens[FILLPEN];
473 GetRGB32(mri->mri_Colormap, mri->mri_DrawInfo->dri_Pens[SHINEPEN], 1,
474 rgbtable);
475 GetRGB32(mri->mri_Colormap, mri->mri_DrawInfo->dri_Pens[BACKGROUNDPEN],
476 1, rgbtable + 3);
477 GetRGB32(mri->mri_Colormap, mri->mri_DrawInfo->dri_Pens[SHADOWPEN], 1,
478 rgbtable + 6);
480 mri->mri_PensStorage[MPEN_HALFSHINE] = ObtainBestPenA
481 (mri->mri_Colormap,
482 DoHalfshineGun(rgbtable[0], rgbtable[3]),
483 DoHalfshineGun(rgbtable[1], rgbtable[4]),
484 DoHalfshineGun(rgbtable[2], rgbtable[5]), NULL);
486 mri->mri_PensStorage[MPEN_HALFSHADOW] = ObtainBestPenA
487 (mri->mri_Colormap,
488 DoHalfshadowGun(rgbtable[6], rgbtable[3]),
489 DoHalfshadowGun(rgbtable[7], rgbtable[4]),
490 DoHalfshadowGun(rgbtable[8], rgbtable[5]), NULL);
492 /* I'm really not sure that MUI does this for MPEN_MARK, but it seems
493 * mostly acceptable -dlc */
494 mri->mri_PensStorage[MPEN_MARK] = ObtainBestPenA
495 (mri->mri_Colormap, 0xf4f4f4f4, 0xb5b5b5b5, 0x8b8b8b8b, NULL);
497 mri->mri_Pens = mri->mri_PensStorage;
499 for (i = 0; i < -MUIV_Font_NegCount; i++)
501 mri->mri_Fonts[i] = NULL;
504 if (data->wd_Flags & MUIWF_USEBOTTOMSCROLLER)
506 mri->mri_LeftImage = CreateSysimage(mri->mri_DrawInfo, LEFTIMAGE);
507 mri->mri_RightImage = CreateSysimage(mri->mri_DrawInfo, RIGHTIMAGE);
509 else
511 mri->mri_LeftImage = mri->mri_RightImage = NULL;
514 if (data->wd_Flags & MUIWF_USERIGHTSCROLLER)
516 mri->mri_UpImage = CreateSysimage(mri->mri_DrawInfo, UPIMAGE);
517 mri->mri_DownImage = CreateSysimage(mri->mri_DrawInfo, DOWNIMAGE);
519 else
521 mri->mri_UpImage = mri->mri_DownImage = NULL;
524 if ((data->wd_Flags & MUIWF_USEBOTTOMSCROLLER) ||
525 (data->wd_Flags & MUIWF_USERIGHTSCROLLER))
526 mri->mri_SizeImage = CreateSysimage(mri->mri_DrawInfo, SIZEIMAGE);
527 else
528 mri->mri_SizeImage = NULL;
530 if (data->wd_CrtFlags & WFLG_BORDERLESS)
532 /* In fact borderless windows could also have borders (e.g. if they
533 * have a window title) but since they look ugly anyway we ignore it
534 * for now */
535 mri->mri_BorderLeft = 0;
536 mri->mri_BorderRight = 0;
537 mri->mri_BorderTop = 0;
538 mri->mri_BorderBottom = 0;
540 else
542 mri->mri_BorderLeft = mri->mri_Screen->WBorLeft;
543 mri->mri_BorderRight = mri->mri_Screen->WBorRight;
544 mri->mri_BorderTop =
545 mri->mri_Screen->WBorTop + mri->mri_Screen->Font->ta_YSize + 1;
546 temp_obj =
547 NewObject(NULL, "sysiclass", SYSIA_DrawInfo,
548 (IPTR) mri->mri_DrawInfo, SYSIA_Which, SIZEIMAGE, TAG_DONE);
549 if (temp_obj)
551 GetAttr(IA_Height, temp_obj, &val);
552 DisposeObject(temp_obj);
553 mri->mri_BorderBottom = val;
555 else
556 mri->mri_BorderBottom = mri->mri_Screen->WBorBottom;
559 return TRUE;
562 static void CleanupRenderInfo(Object *obj, struct MUI_WindowData *data,
563 struct MUI_RenderInfo *mri)
565 int i;
567 DisposeCustomFrames(mri);
569 if (mri->mri_LeftImage)
571 DisposeObject(mri->mri_LeftImage);
572 mri->mri_LeftImage = NULL;
574 if (mri->mri_RightImage)
576 DisposeObject(mri->mri_RightImage);
577 mri->mri_RightImage = NULL;
579 if (mri->mri_UpImage)
581 DisposeObject(mri->mri_UpImage);
582 mri->mri_UpImage = NULL;
584 if (mri->mri_DownImage)
586 DisposeObject(mri->mri_DownImage);
587 mri->mri_DownImage = NULL;
589 if (mri->mri_SizeImage)
591 DisposeObject(mri->mri_SizeImage);
592 mri->mri_SizeImage = NULL;
595 /* bug("CleanupRenderInfo\n"); */
596 for (i = 0; i < -MUIV_Font_NegCount; i++)
598 if (mri->mri_Fonts[i])
600 /* bug("CleanupRenderInfo: closing font %p (%s/%d)\n", */
601 /* mri->mri_Fonts[i], */
602 /* mri->mri_Fonts[i]->tf_Message.mn_Node.ln_Name, */
603 /* mri->mri_Fonts[i]->tf_YSize); */
604 CloseFont(mri->mri_Fonts[i]);
605 mri->mri_Fonts[i] = NULL;
608 ReleasePen(mri->mri_Colormap, mri->mri_PensStorage[MPEN_MARK]);
609 ReleasePen(mri->mri_Colormap, mri->mri_PensStorage[MPEN_HALFSHADOW]);
610 ReleasePen(mri->mri_Colormap, mri->mri_PensStorage[MPEN_HALFSHINE]);
611 FreeScreenDrawInfo(mri->mri_Screen, mri->mri_DrawInfo);
612 mri->mri_DrawInfo = NULL;
614 /* If a custom screen has been opened by zune, close it as soon as zero
615 * windows are opened. See above for comments about refactorization. */
616 if (muiGlobalInfo(obj)->mgi_CustomScreen)
618 BOOL screenclose = TRUE;
619 Object *_app = _app(obj);
620 if (_app != NULL)
622 struct List *store = NULL;
623 get(_app, MUIA_Application_WindowList, &store);
624 if (store != NULL)
626 if (!IsListEmpty(store))
627 screenclose = FALSE;
630 if (screenclose)
632 /* If the window's user screen really was the custom screen,
633 * clear the reference */
634 if (data->wd_UserScreen == muiGlobalInfo(obj)->mgi_CustomScreen)
635 data->wd_UserScreen = NULL;
637 CloseScreen(muiGlobalInfo(obj)->mgi_CustomScreen);
638 muiGlobalInfo(obj)->mgi_CustomScreen = NULL;
642 if (data->wd_Flags & MUIWF_SCREENLOCKED)
644 UnlockPubScreen(NULL, mri->mri_Screen);
645 data->wd_Flags &= ~MUIWF_SCREENLOCKED;
647 mri->mri_Screen = NULL;
650 static void ShowRenderInfo(struct MUI_RenderInfo *mri)
652 if (mri->mri_BufferBM)
654 mri->mri_RastPort = &mri->mri_BufferRP;
656 else
658 mri->mri_RastPort = mri->mri_Window->RPort;
662 static void HideRenderInfo(struct MUI_RenderInfo *mri)
664 mri->mri_RastPort = NULL;
667 static ULONG GetDefaultEvents(void)
669 return IDCMP_NEWSIZE | IDCMP_CHANGEWINDOW | IDCMP_REFRESHWINDOW
670 | IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE | IDCMP_MENUPICK
671 | IDCMP_CLOSEWINDOW | IDCMP_RAWKEY | IDCMP_INTUITICKS
672 | IDCMP_ACTIVEWINDOW | IDCMP_INACTIVEWINDOW | IDCMP_GADGETUP;
675 static void ChangeEvents(struct MUI_WindowData *data, ULONG new_events)
677 struct MinNode *mn;
678 struct MUI_EventHandlerNode *ehn;
679 ULONG old_events = data->wd_Events;
681 for (mn = data->wd_EHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
683 ehn = (struct MUI_EventHandlerNode *)mn;
684 new_events |= ehn->ehn_Events;
687 /* sba: kill the IDCMP_VANILLAKEY flag. MUI doesn't do this but programs
688 ** which use this will behave different if they request for this flag
689 ** (also on MUI)
691 new_events &= ~IDCMP_VANILLAKEY;
693 data->wd_Events = new_events;
694 if ((old_events != new_events) && (data->wd_Flags & MUIWF_OPENED))
696 ModifyIDCMP(data->wd_RenderInfo.mri_Window, new_events);
700 static void CalcWindowPosition(Object *obj, struct MUI_WindowData *data);
701 static void CreateWindowScrollbars(Object *obj,
702 struct MUI_WindowData *data);
703 static void CalcAltDimensions(Object *obj, struct MUI_WindowData *data,
704 struct IBox *altdims);
705 static void UndisplayWindow(Object *obj, struct MUI_WindowData *data);
706 static struct ObjNode *FindObjNode(struct MinList *list, Object *obj);
708 static BOOL DisplayWindow(Object *obj, struct MUI_WindowData *data)
710 struct Window *win;
711 ULONG flags = data->wd_CrtFlags;
712 struct IBox altdims;
713 ULONG backfill, buttons;
715 struct Menu *menu = NULL;
716 struct NewMenu *newmenu = NULL;
717 APTR visinfo = NULL;
719 Object *gadgets;
721 if (!(data->wd_Flags & MUIWF_DONTACTIVATE))
723 flags |= WFLG_ACTIVATE;
726 /* Toolboxes are handled differently on AmigaOS */
727 #ifdef __AROS__
728 if (data->wd_Flags & MUIWF_TOOLBOX)
729 flags |= WFLG_TOOLBOX;
730 #endif
732 if (data->wd_MinMax.MinHeight == data->wd_MinMax.MaxHeight
733 && data->wd_MinMax.MinWidth == data->wd_MinMax.MaxWidth)
734 flags &= ~WFLG_SIZEGADGET;
736 if (!(flags & WFLG_SIZEBRIGHT))
737 flags |= WFLG_SIZEBBOTTOM;
739 CalcWindowPosition(obj, data);
741 if ((visinfo = GetVisualInfoA(data->wd_RenderInfo.mri_Screen, NULL)))
743 if (data->wd_Menustrip)
745 get(data->wd_Menustrip, MUIA_Menuitem_NewMenu, &newmenu);
746 if (newmenu)
748 if ((menu = CreateMenusA(newmenu, NULL)))
750 struct TagItem tags[] = {
751 {GTMN_NewLookMenus, TRUE},
752 {TAG_DONE, (IPTR) NULL}
754 LayoutMenusA(menu, visinfo, tags);
758 FreeVisualInfo(visinfo);
761 CreateWindowScrollbars(obj, data);
762 altdims = data->wd_AltDim;
763 CalcAltDimensions(obj, data, &altdims);
765 /* hack to account for border size, as we only know the innersize and
766 * must give the total size.
768 altdims.Width +=
769 data->wd_RenderInfo.mri_Screen->WBorLeft +
770 data->wd_RenderInfo.mri_Screen->WBorRight;
771 altdims.Height +=
772 data->wd_RenderInfo.mri_Screen->WBorTop +
773 data->wd_RenderInfo.mri_Screen->WBorBottom +
774 data->wd_RenderInfo.mri_DrawInfo->dri_Font->tf_YSize + 1;
776 if (muiGlobalInfo(obj)->mgi_Prefs->window_redraw ==
777 WINDOW_REDRAW_WITHOUT_CLEAR)
778 backfill = WA_BackFill;
779 else
780 backfill = TAG_IGNORE;
782 if (muiGlobalInfo(obj)->mgi_Prefs->window_refresh ==
783 WINDOW_REFRESH_SMART)
784 flags &= ~WFLG_SIMPLE_REFRESH;
785 set(_app(obj), MUIA_Application_SearchWinId, data->wd_ID);
786 struct windowpos *winp = 0;
787 get(_app(obj), MUIA_Application_GetWinPos, &winp);
788 if (winp)
790 if (data->wd_RenderInfo.mri_ScreenWidth >
791 (data->wd_X + data->wd_Width))
793 data->wd_X = winp->x1;
794 data->wd_Width = winp->w1;
796 if (data->wd_RenderInfo.mri_ScreenHeight >
797 (data->wd_Y + data->wd_Height))
799 data->wd_Y = winp->y1;
800 data->wd_Height = winp->h1;
804 gadgets =
805 (data->wd_VertProp !=
806 NULL) ? data->wd_VertProp : data->wd_HorizProp;
807 buttons = muiGlobalInfo(obj)->mgi_Prefs->window_buttons;
809 win = OpenWindowTags
810 (NULL,
811 WA_Left, (IPTR) data->wd_X,
812 WA_Top, (IPTR) data->wd_Y,
813 WA_Flags, (IPTR) flags,
814 data->wd_Title ?
815 WA_Title :
816 TAG_IGNORE, (IPTR) data->wd_Title,
817 data->wd_ScreenTitle ?
818 WA_ScreenTitle :
819 TAG_IGNORE, (IPTR) data->wd_ScreenTitle,
820 WA_CustomScreen, (IPTR) data->wd_RenderInfo.mri_Screen,
821 WA_InnerWidth, (IPTR) data->wd_Width,
822 WA_InnerHeight, (IPTR) data->wd_Height,
823 WA_AutoAdjust, (IPTR) TRUE, WA_NewLookMenus, (IPTR) TRUE,
824 /* AmigaOS v4 extension */
825 #ifdef WA_ToolBox
826 WA_ToolBox, (IPTR) ! !(data->wd_Flags & MUIWF_TOOLBOX),
827 #endif
828 /* MorphOS extensions */
829 #ifdef WA_ExtraGadget_MUI
830 WA_ExtraGadget_MUI,
831 (IPTR) ((buttons & MUIV_Window_Button_MUI) != 0) ? TRUE : FALSE,
832 WA_ExtraGadget_PopUp,
833 (IPTR) ((buttons & MUIV_Window_Button_Popup) != 0) ? TRUE : FALSE,
834 WA_ExtraGadget_Snapshot,
835 (IPTR) ((buttons & MUIV_Window_Button_Snapshot) !=
836 0) ? TRUE : FALSE, WA_ExtraGadget_Iconify,
837 (IPTR) ((buttons & MUIV_Window_Button_Iconify) != 0) ? TRUE : FALSE,
838 #endif
839 data->wd_NoMenus ?
840 WA_RMBTrap :
841 TAG_IGNORE, (IPTR) TRUE,
842 WA_Gadgets, (IPTR) gadgets,
843 data->wd_ZoomGadget ?
844 WA_Zoom :
845 TAG_IGNORE, (IPTR) & altdims,
846 backfill, (IPTR) LAYERS_NOBACKFILL, TAG_DONE);
848 if (win)
851 int hborders = win->BorderLeft + win->BorderRight;
852 int vborders = win->BorderTop + win->BorderBottom;
854 /* recalc window size (which will hopefully equal our requested
855 * size) */
856 data->wd_Width = win->GZZWidth;
857 data->wd_Height = win->GZZHeight;
859 /* set window limits according to window contents */
860 WindowLimits
861 (win, data->wd_MinMax.MinWidth + hborders,
862 data->wd_MinMax.MinHeight + vborders,
863 data->wd_MinMax.MaxWidth + hborders,
864 data->wd_MinMax.MaxHeight + vborders);
866 win->UserData = (BYTE *) data->wd_RenderInfo.mri_WindowObject;
867 win->UserPort = muiGlobalInfo(obj)->mgi_WindowsPort;
868 /* Same port for all windows */
869 ModifyIDCMP(win, data->wd_Events);
871 data->wd_RenderInfo.mri_Window = win;
872 data->wd_RenderInfo.mri_VertProp = data->wd_VertProp;
873 data->wd_RenderInfo.mri_HorizProp = data->wd_HorizProp;
874 SetDrMd(win->RPort, JAM1);
875 //text is drawn wrong in toolbarclass if not set
877 if (menu)
879 data->wd_Menu = menu;
880 SetMenuStrip(win, menu);
883 if (flags & WFLG_ACTIVATE)
885 data->wd_Flags |= MUIWF_ACTIVE;
888 if (data->wd_Flags & MUIWF_ISAPPWINDOW)
890 data->wd_AppWindow = AddAppWindowA(0, (IPTR) obj, win,
891 muiGlobalInfo(obj)->mgi_AppPort, NULL);
894 return TRUE;
897 if (menu)
898 FreeMenus(menu);
899 UndisplayWindow(obj, data);
901 return FALSE;
905 static void UndisplayWindow(Object *obj, struct MUI_WindowData *data)
907 struct Window *win = data->wd_RenderInfo.mri_Window;
908 BOOL prefssnap =
909 data->wd_ID != 0 &&
910 ((muiGlobalInfo(obj)->mgi_Prefs->window_position ==
911 WINDOW_POSITION_REMEMBER_ON_EXIT)
912 || (muiGlobalInfo(obj)->mgi_Prefs->window_position ==
913 WINDOW_POSITION_SAVE_ON_EXIT));
915 if (prefssnap)
917 DoMethod(obj, MUIM_Window_Snapshot, 1);
920 data->wd_RenderInfo.mri_Window = NULL;
921 data->wd_RenderInfo.mri_VertProp = NULL;
922 data->wd_RenderInfo.mri_HorizProp = NULL;
924 data->wd_Flags &= ~MUIWF_ACTIVE;
926 if (win != NULL)
928 ClearMenuStrip(win);
929 if (data->wd_Menu)
931 FreeMenus(data->wd_Menu);
932 data->wd_Menu = NULL;
935 if (win->UserPort)
937 struct IntuiMessage *msg, *succ;
939 /* remove all messages pending for this window */
940 Forbid();
941 for (msg =
942 (struct IntuiMessage *)win->UserPort->mp_MsgList.lh_Head;
943 (succ =
944 (struct IntuiMessage *)msg->ExecMessage.mn_Node.
945 ln_Succ); msg = succ)
947 if (msg->IDCMPWindow == win)
949 Remove((struct Node *)msg);
950 ReplyMsg((struct Message *)msg);
953 win->UserPort = NULL;
954 ModifyIDCMP(win, 0);
955 Permit();
958 /* D(bug("before CloseWindow\n")); */
959 CloseWindow(win);
960 /* D(bug("after CloseWindow\n")); */
963 #define DISPOSEGADGET(x) \
964 if (x)\
966 DoMethod(obj, MUIM_Window_FreeGadgetID,\
967 ((struct Gadget*)x)->GadgetID);\
968 DisposeObject(x);\
969 x = NULL;\
972 DISPOSEGADGET(data->wd_VertProp);
973 DISPOSEGADGET(data->wd_UpButton);
974 DISPOSEGADGET(data->wd_DownButton);
975 DISPOSEGADGET(data->wd_HorizProp);
976 DISPOSEGADGET(data->wd_LeftButton);
977 DISPOSEGADGET(data->wd_RightButton);
978 #undef DISPOSEGADGET
982 static VOID RefreshWindow(Object *oWin, struct MUI_WindowData *data)
984 if (data->wd_Flags & MUIWF_RESIZING)
986 //LONG left,top,right,bottom;
987 if (MUI_BeginRefresh(&data->wd_RenderInfo, 0))
989 MUI_EndRefresh(&data->wd_RenderInfo, 0);
991 RefreshWindowFrame(data->wd_RenderInfo.mri_Window);
993 data->wd_Flags &= ~MUIWF_RESIZING;
994 _width(data->wd_RootObject) = data->wd_Width;
995 _height(data->wd_RootObject) = data->wd_Height;
996 DoMethod(data->wd_RootObject, MUIM_Layout);
997 DoShowMethod(data->wd_RootObject);
999 if (muiGlobalInfo(oWin)->mgi_Prefs->window_redraw ==
1000 WINDOW_REDRAW_WITH_CLEAR)
1002 LONG left, top, width, height;
1004 left = data->wd_RenderInfo.mri_Window->BorderLeft;
1005 top = data->wd_RenderInfo.mri_Window->BorderTop;
1006 width =
1007 data->wd_RenderInfo.mri_Window->Width -
1008 data->wd_RenderInfo.mri_Window->BorderRight - left;
1009 height =
1010 data->wd_RenderInfo.mri_Window->Height -
1011 data->wd_RenderInfo.mri_Window->BorderBottom - top;
1013 if (data->wd_Flags & MUIWF_ERASEAREA)
1015 //D(bug("%d:zune_imspec_draw(%p) "
1016 // "l=%d t=%d w=%d h=%d xo=%d yo=%d\n",
1017 // __LINE__, data->wd_Background, left, top, width,
1018 // height, left, top));
1019 zune_imspec_draw(data->wd_Background,
1020 &data->wd_RenderInfo, left, top, width, height,
1021 left, top, 0);
1023 MUI_Redraw(data->wd_RootObject, MADF_DRAWALL);
1025 else
1026 MUI_Redraw(data->wd_RootObject, MADF_DRAWOBJECT);
1027 // but should only draw focus without using MUIM_GoActive !
1028 ActivateObject(data);
1030 else
1032 if (MUI_BeginRefresh(&data->wd_RenderInfo, 0))
1034 MUI_Redraw(data->wd_RootObject, MADF_DRAWALL);
1035 // but should only draw focus without using MUIM_GoActive !
1036 ActivateObject(data);
1037 MUI_EndRefresh(&data->wd_RenderInfo, 0);
1043 /* Initialize data->wd_X and data->wd_Y for DisplayWindow */
1044 static void CalcWindowPosition(Object *obj, struct MUI_WindowData *data)
1046 struct MUI_RenderInfo *mri = &data->wd_RenderInfo;
1047 struct Screen *scr = mri->mri_Screen;
1048 WORD width = mri->mri_BorderLeft + data->wd_Width + mri->mri_BorderRight,
1049 height = mri->mri_BorderTop + data->wd_Height + mri->mri_BorderBottom;
1050 ULONG refw = 0, refx = 0, refh = 0, refy = 0;
1052 data->wd_X = data->wd_ReqX;
1053 data->wd_Y = data->wd_ReqY;
1055 /* Get dimensions of reference window */
1056 if (data->wd_RefWindow != NULL)
1058 get(data->wd_RefWindow, MUIA_Window_LeftEdge, &refx);
1059 get(data->wd_RefWindow, MUIA_Window_Width, &refw);
1060 get(data->wd_RefWindow, MUIA_Window_TopEdge, &refy);
1061 get(data->wd_RefWindow, MUIA_Window_Height, &refh);
1064 /* Adjust X */
1065 if (data->wd_X == MUIV_Window_LeftEdge_Centered)
1067 if (data->wd_RefWindow != NULL)
1068 /* FIXME: only correct if border thickness is the same for both
1069 windows */
1070 data->wd_X = refx + (refw - width) / 2;
1071 else
1072 data->wd_X = (scr->ViewPort.DWidth - width) / 2;
1074 else if (data->wd_X == MUIV_Window_LeftEdge_Moused)
1075 data->wd_X = scr->MouseX - width / 2;
1076 else if (data->wd_RefWindow != NULL)
1077 data->wd_X += refx;
1079 /* Adjust Y */
1080 if (data->wd_Y == MUIV_Window_TopEdge_Centered)
1082 if (data->wd_RefWindow != NULL)
1083 data->wd_Y = refy + (refh - data->wd_Height) / 2;
1084 else
1085 data->wd_Y = (scr->ViewPort.DHeight - height) / 2;
1087 else if (data->wd_Y == MUIV_Window_TopEdge_Moused)
1088 data->wd_Y = scr->MouseY - height / 2;
1089 else if (data->wd_Y <= MUIV_Window_TopEdge_Delta(0)
1090 && data->wd_Y > MUIV_Window_TopEdge_Delta(7))
1092 data->wd_Y = MUIV_Window_TopEdge_Delta(0) - data->wd_Y;
1093 if (data->wd_RefWindow != NULL)
1094 data->wd_Y += refy + mri->mri_BorderTop;
1095 else
1096 data->wd_Y += scr->BarHeight + 1;
1098 else if (data->wd_RefWindow != NULL)
1099 data->wd_Y += refy;
1102 /* Initialize alternative dimensions for DisplayWindow */
1103 static void CalcAltDimensions(Object *obj, struct MUI_WindowData *data,
1104 struct IBox *altdims)
1106 /* Calculate alternate (zoomed) dimensions.
1108 if (altdims->Top == MUIV_Window_AltTopEdge_NoChange)
1109 altdims->Top = ~0;
1110 else if (altdims->Top == MUIV_Window_AltTopEdge_Centered)
1111 altdims->Top =
1112 (data->wd_RenderInfo.mri_Screen->Height - data->wd_Height) / 2;
1113 else if (altdims->Top == MUIV_Window_AltTopEdge_Moused)
1114 /* ? */ altdims->Top = ~0;
1116 if (altdims->Left == MUIV_Window_AltLeftEdge_NoChange)
1117 altdims->Left = ~0;
1118 else if (altdims->Left == MUIV_Window_AltLeftEdge_Centered)
1119 altdims->Left =
1120 (data->wd_RenderInfo.mri_Screen->Width - data->wd_Width) / 2;
1121 else if (altdims->Left == MUIV_Window_AltLeftEdge_Moused)
1122 /* ? */ altdims->Left = ~0;
1124 if (_between
1125 (MUIV_Window_AltWidth_MinMax(100),
1126 altdims->Width, MUIV_Window_AltWidth_MinMax(0)))
1128 altdims->Width = data->wd_MinMax.MinWidth
1129 - altdims->Width
1130 * (data->wd_MinMax.MaxWidth - data->wd_MinMax.MinWidth);
1132 else if
1133 (_between
1134 (MUIV_Window_AltWidth_Screen(100),
1135 altdims->Width, MUIV_Window_AltWidth_Screen(0)))
1137 altdims->Width = data->wd_RenderInfo.mri_ScreenWidth
1138 * (-(altdims->Width + 200)) / 100;
1140 else if
1141 (_between
1142 (MUIV_Window_AltWidth_Visible(100),
1143 altdims->Width, MUIV_Window_AltWidth_Visible(0)))
1145 altdims->Width = data->wd_RenderInfo.mri_ScreenWidth
1146 * (-(altdims->Width + 100)) / 100;
1149 if (_between
1150 (MUIV_Window_AltHeight_MinMax(100),
1151 altdims->Height, MUIV_Window_AltHeight_MinMax(0)))
1153 altdims->Height = data->wd_MinMax.MinHeight
1154 - altdims->Height
1155 * (data->wd_MinMax.MaxHeight - data->wd_MinMax.MinHeight);
1157 else if
1158 (_between
1159 (MUIV_Window_AltHeight_Screen(100),
1160 altdims->Height, MUIV_Window_AltHeight_Screen(0)))
1162 altdims->Height = data->wd_RenderInfo.mri_ScreenHeight
1163 * (-(altdims->Height + 200)) / 100;
1165 else if
1166 (_between
1167 (MUIV_Window_AltHeight_Visible(100),
1168 altdims->Height, MUIV_Window_AltHeight_Visible(0)))
1170 altdims->Height = data->wd_RenderInfo.mri_ScreenHeight
1171 * (-(altdims->Height + 100)) / 100;
1174 altdims->Width = CLAMP
1175 (altdims->Width, data->wd_MinMax.MinWidth,
1176 data->wd_MinMax.MaxWidth);
1177 altdims->Height = CLAMP
1178 (altdims->Height, data->wd_MinMax.MinHeight,
1179 data->wd_MinMax.MaxHeight);
1183 /* Create horiz/vert window scrollbars for DisplayWindow */
1184 static void CreateWindowScrollbars(Object *obj,
1185 struct MUI_WindowData *data)
1187 struct MUI_RenderInfo *mri = &data->wd_RenderInfo;
1188 Object *firstgad = NULL;
1189 Object *prevgad = NULL;
1190 LONG id;
1192 /* Create the right border scrollers now if requested */
1193 if (data->wd_Flags & MUIWF_USERIGHTSCROLLER)
1195 int voffset;
1197 voffset = IM(mri->mri_DownImage)->Width / 4;
1199 id = DoMethod(obj, MUIM_Window_AllocGadgetID);
1200 firstgad = prevgad = data->wd_VertProp = NewObject
1201 (NULL, "propgclass",
1202 GA_RelRight, 1 - (IM(mri->mri_UpImage)->Width - voffset),
1203 GA_Top, mri->mri_BorderTop + 2,
1204 GA_Width, IM(mri->mri_UpImage)->Width - voffset * 2,
1205 GA_RelHeight, -(mri->mri_BorderTop + 2)
1206 - IM(mri->mri_UpImage)->Height
1207 - IM(mri->mri_DownImage)->Height
1208 - IM(mri->mri_SizeImage)->Height - 2,
1209 GA_RightBorder, TRUE,
1210 GA_ID, id,
1211 PGA_Borderless, TRUE,
1212 PGA_NewLook, TRUE,
1213 PGA_Freedom, FREEVERT,
1214 PGA_Top, 0,
1215 PGA_Total, 2,
1216 PGA_Visible, 1, ICA_TARGET, ICTARGET_IDCMP, TAG_DONE);
1218 id = DoMethod(obj, MUIM_Window_AllocGadgetID);
1219 prevgad = data->wd_UpButton = NewObject
1220 (NULL, "buttongclass",
1221 GA_Image, (IPTR) mri->mri_UpImage,
1222 GA_RelRight, 1 - IM(mri->mri_UpImage)->Width,
1223 GA_RelBottom, 1 - IM(mri->mri_UpImage)->Height
1224 - IM(mri->mri_DownImage)->Height
1225 - IM(mri->mri_SizeImage)->Height,
1226 GA_RightBorder, TRUE,
1227 GA_Previous, (IPTR) prevgad,
1228 GA_ID, id, ICA_TARGET, ICTARGET_IDCMP, TAG_DONE);
1230 id = DoMethod(obj, MUIM_Window_AllocGadgetID);
1231 prevgad = data->wd_DownButton = NewObject
1232 (NULL, "buttongclass",
1233 GA_Image, (IPTR) mri->mri_DownImage,
1234 GA_RelRight, 1 - IM(mri->mri_DownImage)->Width,
1235 GA_RelBottom, 1 - IM(mri->mri_DownImage)->Height
1236 - IM(mri->mri_SizeImage)->Height,
1237 GA_RightBorder, TRUE,
1238 GA_Previous, (IPTR) prevgad,
1239 GA_ID, id, ICA_TARGET, ICTARGET_IDCMP, TAG_DONE);
1242 /* Create the bottom border scrollers now if requested */
1243 if (data->wd_Flags & MUIWF_USEBOTTOMSCROLLER)
1245 int hoffset;
1247 hoffset = IM(mri->mri_RightImage)->Height / 4;
1249 id = DoMethod(obj, MUIM_Window_AllocGadgetID);
1250 prevgad = data->wd_HorizProp = NewObject
1251 (NULL, "propgclass",
1252 GA_RelBottom, 1 - (IM(mri->mri_LeftImage)->Height - hoffset),
1253 GA_Left, mri->mri_BorderLeft,
1254 GA_Height, IM(mri->mri_LeftImage)->Height
1255 - hoffset * 2,
1256 GA_RelWidth, -(mri->mri_BorderLeft)
1257 - IM(mri->mri_LeftImage)->Width
1258 - IM(mri->mri_RightImage)->Width
1259 - IM(mri->mri_SizeImage)->Width
1260 - 2,
1261 GA_BottomBorder, TRUE,
1262 GA_ID, id,
1263 prevgad ? GA_Previous : TAG_IGNORE, (IPTR) prevgad,
1264 PGA_Borderless, TRUE,
1265 PGA_NewLook, TRUE,
1266 PGA_Freedom, FREEHORIZ,
1267 PGA_Top, 0,
1268 PGA_Total, 2,
1269 PGA_Visible, 1, ICA_TARGET, ICTARGET_IDCMP, TAG_DONE);
1271 if (!firstgad)
1272 firstgad = prevgad;
1274 id = DoMethod(obj, MUIM_Window_AllocGadgetID);
1275 prevgad = data->wd_LeftButton = NewObject
1276 (NULL, "buttongclass",
1277 GA_Image, (IPTR) mri->mri_LeftImage,
1278 GA_RelRight, 1 - IM(mri->mri_LeftImage)->Width
1279 - IM(mri->mri_RightImage)->Width
1280 - IM(mri->mri_SizeImage)->Width,
1281 GA_RelBottom, 1 - IM(mri->mri_LeftImage)->Height,
1282 GA_BottomBorder, TRUE,
1283 GA_Previous, (IPTR) prevgad,
1284 GA_ID, id, ICA_TARGET, ICTARGET_IDCMP, TAG_DONE);
1286 id = DoMethod(obj, MUIM_Window_AllocGadgetID);
1287 prevgad = data->wd_RightButton = NewObject
1288 (NULL, "buttongclass",
1289 GA_Image, (IPTR) mri->mri_RightImage,
1290 GA_RelRight, 1 - IM(mri->mri_RightImage)->Width
1291 - IM(mri->mri_SizeImage)->Width,
1292 GA_RelBottom, 1 - IM(mri->mri_RightImage)->Height,
1293 GA_BottomBorder, TRUE,
1294 GA_Previous, (IPTR) prevgad,
1295 GA_ID, id, ICA_TARGET, ICTARGET_IDCMP, TAG_DONE);
1299 /* return FALSE only if no resize (dx=dy=0) occured */
1300 static BOOL WindowResize(struct MUI_WindowData *data)
1302 struct Window *win = data->wd_RenderInfo.mri_Window;
1303 int hborders = win->BorderLeft + win->BorderRight;
1304 int vborders = win->BorderTop + win->BorderBottom;
1305 WORD dx = data->wd_Width - win->Width + hborders;
1306 WORD dy = data->wd_Height - win->Height + vborders;
1308 /* Temporarily disable window limits to let SizeWindow below work
1309 regardless of the previous limits */
1310 WindowLimits(win, 1, 1, -1, -1);
1311 /* D(bug("_zune_window_resize : dx=%d, dy=%d\n", dx, dy)); */
1312 SizeWindow(win, dx, dy);
1314 /* Set new window limits */
1315 WindowLimits
1316 (win, data->wd_MinMax.MinWidth + hborders,
1317 data->wd_MinMax.MinHeight + vborders,
1318 data->wd_MinMax.MaxWidth + hborders,
1319 data->wd_MinMax.MaxHeight + vborders);
1321 return dx || dy;
1324 static void KillHelpBubble(struct MUI_WindowData *data, Object *obj,
1325 BOOL kill_bubblemode)
1327 if (data->wd_HelpObject)
1329 DoMethod(data->wd_HelpObject, MUIM_DeleteBubble,
1330 (IPTR) data->wd_HelpBubble);
1331 data->wd_HelpObject = NULL;
1332 data->wd_HelpBubble = NULL;
1335 if (kill_bubblemode)
1336 data->wd_Flags &= ~MUIWF_BUBBLEMODE;
1338 if (data->wd_Flags & MUIWF_BUBBLEMODE)
1340 data->wd_HelpTicker = BUBBLEHELP_TICKER_LATER;
1342 else
1344 data->wd_HelpTicker = BUBBLEHELP_TICKER_FIRST;
1349 /**************/
1351 typedef BOOL(*UNDERCHECK_FUNC) (Object *obj);
1353 static BOOL ShortHelpUnderPointerCheck(Object *obj)
1355 return muiAreaData(obj)->mad_ShortHelp ? TRUE : FALSE;
1358 static Object *ObjectUnderPointer(struct MUI_WindowData *data, Object *obj,
1359 LONG x, LONG y, UNDERCHECK_FUNC func)
1361 Object *cstate;
1362 Object *child;
1363 struct MinList *ChildList = NULL;
1365 if (!(muiAreaData(obj)->mad_Flags & MADF_CANDRAW))
1366 return NULL;
1368 if (!(x >= _left(obj) && x <= _right(obj)
1369 && y >= _top(obj) && y <= _bottom(obj)))
1371 return NULL;
1374 if ((get(obj, MUIA_Group_ChildList, &(ChildList)))
1375 && (ChildList != NULL))
1377 cstate = (Object *) ChildList->mlh_Head;
1378 while ((child = NextObject(&cstate)))
1380 Object *ret;
1382 if ((x >= _left(child) && x <= _right(child)
1384 y >= _top(child) && y <= _bottom(child))
1385 && (ret = ObjectUnderPointer(data, child, x, y, func)))
1387 return ret;
1392 if (!(*func) (obj))
1393 return NULL;
1395 return obj;
1398 static BOOL ContextMenuUnderPointer(struct MUI_WindowData *data,
1399 Object *obj, LONG x, LONG y)
1401 Object *cstate;
1402 Object *child;
1403 struct MinList *ChildList = NULL;
1405 if (!(x >= _left(obj) && x <= _right(obj)
1406 && y >= _top(obj) && y <= _bottom(obj)))
1408 return FALSE;
1411 if ((get(obj, MUIA_Group_ChildList, &(ChildList)))
1412 && (ChildList != NULL))
1415 cstate = (Object *) ChildList->mlh_Head;
1416 while ((child = NextObject(&cstate)))
1418 if ((x >= _left(child) && x <= _right(child)
1420 y >= _top(child) && y <= _bottom(child))
1421 && (ContextMenuUnderPointer(data, child, x, y)))
1422 return TRUE;
1426 if (!(muiAreaData(obj)->mad_Flags & MADF_CANDRAW))
1427 return FALSE;
1428 if (!(muiAreaData(obj)->mad_ContextMenu))
1429 return FALSE;
1431 return TRUE;
1434 /**************/
1436 static void ActivateObject(struct MUI_WindowData *data)
1438 //bug("Window::ActivateObject (dummy) %08lx\n", data->wd_ActiveObject);
1439 // if (FindObjNode(&data->wd_CycleChain, data->wd_ActiveObject))
1440 // DoMethod(data->wd_ActiveObject, MUIM_GoActive);
1441 // else
1442 // data->wd_ActiveObject = NULL;
1444 //activate better string gadgets.Fix from Georg S On ML List
1445 if (FindObjNode(&data->wd_CycleChain, data->wd_ActiveObject))
1447 if (!(data->wd_Flags & MUIWF_OBJECTGOACTIVESENT))
1449 data->wd_Flags |= MUIWF_OBJECTGOACTIVESENT;
1450 DoMethod(data->wd_ActiveObject, MUIM_GoActive);
1453 else
1454 data->wd_ActiveObject = NULL;
1457 /**************/
1459 /* handle intuimessage while an object is being dragged
1460 * (reply imsg before returning)
1461 * Returns TRUE if finished dragging.
1463 static BOOL HandleDragging(Object *oWin, struct MUI_WindowData *data,
1464 struct IntuiMessage *imsg)
1466 struct Window *iWin;
1467 BOOL finish_drag = FALSE;
1469 iWin = imsg->IDCMPWindow;
1471 if (imsg->Class == IDCMP_MOUSEMOVE)
1473 struct Layer *layer;
1475 LockLayerInfo(&iWin->WScreen->LayerInfo);
1476 layer = WhichLayer(&iWin->WScreen->LayerInfo,
1477 iWin->LeftEdge + imsg->MouseX, iWin->TopEdge + imsg->MouseY);
1478 UnlockLayerInfo(&iWin->WScreen->LayerInfo);
1480 if (data->wd_DropObject)
1482 struct Window *wnd;
1483 WORD mousex =
1484 imsg->MouseX + iWin->LeftEdge -
1485 data->wd_DropWindow->LeftEdge;
1486 WORD mousey =
1487 imsg->MouseY + iWin->TopEdge - data->wd_DropWindow->TopEdge;
1489 wnd = _window(data->wd_DropObject);
1490 if (mousex < _left(data->wd_DropObject)
1491 || mousex > _right(data->wd_DropObject)
1492 || mousey < _top(data->wd_DropObject)
1493 || mousey > _bottom(data->wd_DropObject)
1494 || layer != wnd->WLayer)
1496 /* We have left the object */
1497 UndrawDragNDrop(data->wd_dnd);
1498 DoMethod(data->wd_DropObject, MUIM_DragFinish,
1499 (IPTR) data->wd_DragObject);
1500 data->wd_DropObject = NULL;
1502 } /* if (data->wd_DropObject) */
1504 if (!data->wd_DropObject)
1506 Object *dest_wnd = NULL;
1508 /* Find out if app has an open window at this position */
1509 if (layer)
1511 Object *cstate;
1512 Object *child;
1513 struct MinList *ChildList = 0;
1515 get(_app(oWin), MUIA_Application_WindowList, &(ChildList));
1516 cstate = (Object *) ChildList->mlh_Head;
1517 while ((child = NextObject(&cstate)))
1519 struct Window *wnd = NULL;
1520 get(child, MUIA_Window_Window, &wnd);
1521 if (!wnd)
1522 continue;
1524 if (wnd->WLayer == layer)
1526 data->wd_DropWindow = wnd;
1527 dest_wnd = child;
1528 break;
1531 } /* if (layer) */
1533 if (dest_wnd)
1535 Object *root = NULL;
1536 get(dest_wnd, MUIA_Window_RootObject, &root);
1538 if (root)
1540 if ((data->wd_DropObject = (Object *) DoMethod
1541 (root, MUIM_DragQueryExtended,
1542 (IPTR) data->wd_DragObject,
1543 imsg->MouseX + iWin->LeftEdge -
1544 data->wd_DropWindow->LeftEdge,
1545 imsg->MouseY + iWin->TopEdge -
1546 data->wd_DropWindow->TopEdge)))
1548 UndrawDragNDrop(data->wd_dnd);
1549 DoMethod(data->wd_DropObject, MUIM_DragBegin,
1550 (IPTR) data->wd_DragObject);
1556 if (data->wd_DropObject)
1558 LONG update = 0;
1559 LONG i;
1560 for (i = 0; i < 2; i++)
1562 LONG res = DoMethod(data->wd_DropObject, MUIM_DragReport,
1563 (IPTR) data->wd_DragObject,
1564 imsg->MouseX + iWin->LeftEdge -
1565 data->wd_DropWindow->LeftEdge,
1566 imsg->MouseY + iWin->TopEdge -
1567 data->wd_DropWindow->TopEdge, update);
1568 switch (res)
1570 case MUIV_DragReport_Abort:
1571 UndrawDragNDrop(data->wd_dnd);
1572 DoMethod(data->wd_DropObject, MUIM_DragFinish,
1573 (IPTR) data->wd_DragObject);
1574 data->wd_DropObject = NULL;
1575 i = 1;
1576 break;
1578 case MUIV_DragReport_Continue:
1579 break;
1580 case MUIV_DragReport_Lock:
1581 break; /* NYI */
1582 case MUIV_DragReport_Refresh:
1583 UndrawDragNDrop(data->wd_dnd);
1584 update = 1;
1585 break;
1589 DrawDragNDrop(data->wd_dnd, imsg->MouseX + iWin->LeftEdge,
1590 imsg->MouseY + iWin->TopEdge);
1593 if (imsg->Class == IDCMP_MOUSEBUTTONS)
1595 if ((imsg->Code == MENUDOWN) || (imsg->Code == SELECTUP))
1597 UndrawDragNDrop(data->wd_dnd);
1598 if (imsg->Code == SELECTUP && data->wd_DropObject)
1600 DoMethod(data->wd_DropObject, MUIM_DragDrop,
1601 (IPTR) data->wd_DragObject,
1602 imsg->MouseX + iWin->LeftEdge -
1603 data->wd_DropWindow->LeftEdge,
1604 imsg->MouseY + iWin->TopEdge -
1605 data->wd_DropWindow->TopEdge);
1606 DoMethod(data->wd_DropObject, MUIM_DragFinish,
1607 (IPTR) data->wd_DragObject);
1608 data->wd_DropObject = NULL;
1610 else if (imsg->Code == SELECTUP)
1612 DoMethod(data->wd_DragObject, MUIM_UnknownDropDestination,
1613 imsg);
1615 finish_drag = TRUE;
1619 if (imsg->Class == IDCMP_CLOSEWINDOW)
1620 finish_drag = TRUE;
1622 if (finish_drag)
1624 if (data->wd_DropObject)
1626 UndrawDragNDrop(data->wd_dnd);
1627 DoMethod(data->wd_DropObject, MUIM_DragFinish,
1628 (IPTR) data->wd_DragObject);
1629 data->wd_DropObject = NULL;
1631 DeleteDragNDrop(data->wd_dnd);
1632 DoMethod(data->wd_DragObject, MUIM_DeleteDragImage,
1633 (IPTR) data->wd_DragImage);
1634 muiAreaData(data->wd_DragObject)->mad_Flags &= ~MADF_DRAGGING;
1635 data->wd_DragImage = NULL;
1636 data->wd_DragObject = NULL;
1637 data->wd_DropWindow = NULL;
1638 data->wd_dnd = NULL;
1640 /* stop listening to IDCMP_MOUSEMOVE */
1641 ChangeEvents(data, GetDefaultEvents());
1643 if (!finish_drag)
1644 ReplyMsg((struct Message *)imsg);
1646 return finish_drag;
1649 /* Reply to imsg if handled */
1650 BOOL HandleWindowEvent(Object *oWin, struct MUI_WindowData *data,
1651 struct IntuiMessage *imsg)
1653 struct Window *iWin;
1654 BOOL is_handled = TRUE;
1655 BOOL replied = FALSE;
1657 iWin = imsg->IDCMPWindow;
1658 switch (imsg->Class)
1660 case IDCMP_ACTIVEWINDOW:
1661 data->wd_Flags |= MUIWF_ACTIVE;
1662 if (data->wd_OldActive)
1663 set(oWin, MUIA_Window_ActiveObject, data->wd_OldActive);
1664 set(oWin, MUIA_Window_Activate, TRUE);
1665 is_handled = FALSE; /* forwardable to area event handlers */
1666 break;
1668 case IDCMP_INACTIVEWINDOW:
1669 KillHelpBubble(data, oWin, TRUE);
1670 if (data->wd_ActiveObject)
1672 data->wd_OldActive = data->wd_ActiveObject;
1673 set(oWin, MUIA_Window_ActiveObject,
1674 MUIV_Window_ActiveObject_None);
1676 data->wd_Flags &= ~MUIWF_ACTIVE;
1677 set(oWin, MUIA_Window_Activate, FALSE);
1678 is_handled = FALSE; /* forwardable to area event handlers */
1679 break;
1681 case IDCMP_NEWSIZE:
1682 case IDCMP_CHANGEWINDOW:
1684 int hborders = iWin->BorderLeft + iWin->BorderRight;
1685 int vborders = iWin->BorderTop + iWin->BorderBottom;
1687 /* set window limits according to window contents */
1688 WindowLimits
1689 (iWin,
1690 data->wd_MinMax.MinWidth + hborders,
1691 data->wd_MinMax.MinHeight + vborders,
1692 data->wd_MinMax.MaxWidth + hborders,
1693 data->wd_MinMax.MaxHeight + vborders);
1696 if ((iWin->GZZWidth != data->wd_Width)
1697 || (iWin->GZZHeight != data->wd_Height))
1699 data->wd_Width = iWin->GZZWidth;
1700 data->wd_Height = iWin->GZZHeight;
1701 DoHideMethod(data->wd_RootObject);
1703 data->wd_Flags |= MUIWF_RESIZING;
1704 RefreshWindow(oWin, data);
1706 /* Use wd_Class below instead of OCLASS(oWin), because otherwise if oWin is an
1707 instance of a subclass of window class, then superset will go to window class's
1708 OM_SET where MUIA_Window_Width|Height for some reason are always set to 0. This has
1709 the side effect that after the first window resize all future window moves(!) too
1710 are interpreted as "window size was changed" (if check above returns TRUE even if
1711 window size did not change) */
1712 superset(data->wd_Class, oWin, MUIA_Window_Width, data->wd_Width);
1713 superset(data->wd_Class, oWin, MUIA_Window_Height, data->wd_Height);
1716 if (iWin->LeftEdge != data->wd_X)
1718 data->wd_X = iWin->LeftEdge;
1719 superset(data->wd_Class, oWin, MUIA_Window_LeftEdge, data->wd_X);
1721 if (iWin->TopEdge != data->wd_Y)
1723 data->wd_Y = iWin->TopEdge;
1724 superset(data->wd_Class, oWin, MUIA_Window_TopEdge, data->wd_Y);
1727 is_handled = FALSE; /* forwardable to area event handlers */
1728 break;
1730 case IDCMP_REFRESHWINDOW:
1731 ReplyMsg((struct Message *)imsg);
1732 replied = TRUE;
1733 RefreshWindow(oWin, data);
1734 break;
1736 case IDCMP_CLOSEWINDOW:
1737 ReplyMsg((struct Message *)imsg);
1738 replied = TRUE;
1739 set(oWin, MUIA_Window_CloseRequest, TRUE);
1740 break;
1742 case IDCMP_MENUPICK:
1743 ReplyMsg((struct Message *)imsg);
1744 replied = TRUE;
1746 if (data->wd_Menu)
1748 if (MENUNUM(imsg->Code) != NOMENU
1749 && ITEMNUM(imsg->Code) != NOITEM)
1751 struct MenuItem *item =
1752 ItemAddress(data->wd_Menu, imsg->Code);
1753 if (item)
1755 Object *item_obj = (Object *) GTMENUITEM_USERDATA(item);
1756 if (item_obj)
1758 Object *app = NULL;
1759 IPTR udata = 0;
1761 if (item->Flags & CHECKIT)
1762 set(item_obj, MUIA_Menuitem_Checked,
1763 ! !(item->Flags & CHECKED));
1765 set(item_obj, MUIA_Menuitem_Trigger, (IPTR) item);
1767 get(oWin, MUIA_ApplicationObject, &app);
1768 get(item_obj, MUIA_UserData, &udata);
1770 set(app, MUIA_Application_MenuAction, udata);
1771 set(oWin, MUIA_Window_MenuAction, udata);
1772 DoMethod(app, MUIM_Application_ReturnID, udata);
1777 break;
1779 case IDCMP_IDCMPUPDATE:
1780 is_handled = FALSE; /* forwardable to area event handlers */
1781 if (data->wd_VertProp || data->wd_HorizProp)
1783 struct TagItem *tag;
1784 tag = FindTagItem(GA_ID, (struct TagItem *)imsg->IAddress);
1785 if (tag)
1787 /* If there's a propclass object connected to the prop
1788 gadget, the prop gadget's userdata will point to
1789 that propclass object. See classes/prop.c */
1791 if (data->wd_VertProp)
1793 if (tag->ti_Data == GADGETID(data->wd_VertProp))
1796 if (tag->ti_Data == GADGETID(data->wd_UpButton))
1798 Object *prop =
1799 (Object *) ((struct Gadget *)data->
1800 wd_VertProp)->UserData;
1801 is_handled = TRUE;
1802 if (prop)
1803 DoMethod(prop, MUIM_Prop_Decrease, 1);
1806 if (tag->ti_Data == GADGETID(data->wd_DownButton))
1808 Object *prop =
1809 (Object *) ((struct Gadget *)data->
1810 wd_VertProp)->UserData;
1811 is_handled = TRUE;
1812 if (prop)
1813 DoMethod(prop, MUIM_Prop_Increase, 1);
1818 if (data->wd_HorizProp)
1820 if (tag->ti_Data == GADGETID(data->wd_HorizProp))
1823 if (tag->ti_Data == GADGETID(data->wd_LeftButton))
1825 Object *prop =
1826 (Object *) ((struct Gadget *)data->
1827 wd_HorizProp)->UserData;
1828 is_handled = TRUE;
1829 if (prop)
1830 DoMethod(prop, MUIM_Prop_Decrease, 1);
1833 if (tag->ti_Data == GADGETID(data->wd_RightButton))
1835 Object *prop =
1836 (Object *) ((struct Gadget *)data->
1837 wd_HorizProp)->UserData;
1838 is_handled = TRUE;
1839 if (prop)
1840 DoMethod(prop, MUIM_Prop_Increase, 1);
1846 break;
1848 case IDCMP_INTUITICKS:
1849 if (data->wd_HelpTicker)
1851 data->wd_HelpTicker--;
1853 if (data->wd_HelpTicker == 0)
1855 Object *underobj =
1856 ObjectUnderPointer(data, data->wd_RootObject,
1857 imsg->MouseX, imsg->MouseY,
1858 ShortHelpUnderPointerCheck);
1860 if (underobj != data->wd_HelpObject)
1862 if (data->wd_HelpObject)
1864 DoMethod(data->wd_HelpObject, MUIM_DeleteBubble,
1865 (IPTR) data->wd_HelpBubble);
1867 data->wd_HelpObject = NULL;
1868 data->wd_HelpBubble = NULL;
1871 if (underobj)
1873 data->wd_HelpBubble =
1874 (APTR) DoMethod(underobj, MUIM_CreateBubble,
1875 imsg->MouseX, imsg->MouseY, 0, 0);
1876 if (data->wd_HelpBubble)
1878 data->wd_HelpObject = underobj;
1879 data->wd_Flags |= MUIWF_BUBBLEMODE;
1884 if (data->wd_Flags & MUIWF_BUBBLEMODE)
1886 data->wd_HelpTicker = BUBBLEHELP_TICKER_LATER;
1888 else
1890 data->wd_HelpTicker = BUBBLEHELP_TICKER_FIRST;
1895 is_handled = FALSE; /* forwardable to area event handlers */
1896 break;
1898 case IDCMP_MOUSEBUTTONS:
1899 DoMethod(oWin, MUIM_Window_Snapshot, 0);
1900 KillHelpBubble(data, oWin, TRUE);
1901 is_handled = FALSE;
1902 break;
1905 case IDCMP_MOUSEMOVE:
1906 KillHelpBubble(data, oWin, FALSE);
1907 is_handled = FALSE;
1908 break;
1910 default:
1911 is_handled = FALSE;
1912 break;
1915 if (is_handled && !replied)
1916 ReplyMsg((struct Message *)imsg);
1918 return is_handled;
1921 static ULONG InvokeEventHandler(struct MUI_EventHandlerNode *ehn,
1922 struct IntuiMessage *event, ULONG muikey)
1924 ULONG res;
1926 if (!(_flags(ehn->ehn_Object) & MADF_CANDRAW))
1927 return 0;
1928 if (!(_flags(ehn->ehn_Object) & MADF_SHOWME))
1929 return 0;
1931 if (event != NULL
1932 && event->Class == IDCMP_MOUSEBUTTONS
1933 && event->Code == SELECTDOWN
1934 && (_flags(ehn->ehn_Object) & MADF_INVIRTUALGROUP))
1937 Here we filter out SELECTDOWN messages if objects is in a virtual
1938 group but the click went out of the virtual group
1940 Object *obj = ehn->ehn_Object;
1941 Object *parent = obj;
1942 Object *wnd = _win(obj);
1944 while (get(parent, MUIA_Parent, &parent))
1946 if (!parent)
1947 break;
1948 if (wnd == parent)
1949 break;
1950 if (_flags(parent) & MADF_ISVIRTUALGROUP)
1952 if (event->MouseX < _mleft(parent)
1953 || event->MouseX > _mright(parent)
1954 || event->MouseY < _mtop(parent)
1955 || event->MouseY > _mbottom(parent))
1957 return 0;
1964 if (ehn->ehn_Flags & MUI_EHF_HANDLEINPUT)
1966 DoMethod(ehn->ehn_Object, MUIM_HandleInput, (IPTR) event, muikey);
1967 res = 0;
1969 else
1971 if (ehn->ehn_Class)
1972 res = CoerceMethod
1973 (ehn->ehn_Class, ehn->ehn_Object, MUIM_HandleEvent,
1974 (IPTR) event, muikey);
1975 else
1976 res =
1977 DoMethod(ehn->ehn_Object, MUIM_HandleEvent, (IPTR) event,
1978 muikey);
1981 return res;
1984 static void HandleRawkey(Object *win, struct MUI_WindowData *data,
1985 struct IntuiMessage *event)
1987 struct MinNode *mn;
1988 struct MUI_EventHandlerNode *ehn;
1989 struct IntuiMessage imsg_copy;
1990 struct InputEvent ie = { 0 };
1991 ULONG res;
1992 LONG muikey = MUIKEY_NONE;
1993 Object *active_object = NULL;
1994 IPTR disabled = 0;
1995 ULONG key;
1996 ULONG deadkey;
1998 KillHelpBubble(data, win, BUBBLEHELP_TICKER_FIRST);
2000 ie.ie_NextEvent = NULL;
2001 ie.ie_Class = IECLASS_RAWKEY;
2002 ie.ie_SubClass = 0;
2003 ie.ie_Code = event->Code;
2004 ie.ie_Qualifier = event->Qualifier;
2005 ie.ie_EventAddress = (APTR) * (IPTR *) event->IAddress;
2006 #ifdef __AMIGAOS4__
2007 ie.ie_TimeStamp.Seconds = event->Seconds;
2008 ie.ie_TimeStamp.Microseconds = event->Micros;
2009 #else
2010 ie.ie_TimeStamp.tv_secs = event->Seconds;
2011 ie.ie_TimeStamp.tv_micro = event->Micros;
2012 #endif
2014 set(win, MUIA_Window_InputEvent, (IPTR) & ie);
2016 /* get the vanilla key for control char */
2018 UWORD msg_code;
2020 /* Remove the up prefix as convert key does not convert upkey event */
2021 msg_code = event->Code;
2022 event->Code &= ~IECODE_UP_PREFIX;
2023 key = ConvertKey(event);
2024 event->Code = msg_code;
2027 imsg_copy = *event;
2028 deadkey = *(ULONG *) event->IAddress;
2029 imsg_copy.IAddress = &deadkey;
2030 ReplyMsg((struct Message *)event);
2031 event = &imsg_copy;
2033 //bug("rawkey: code=%lx, qual=%lx\n", event->Code, event->Qualifier);
2035 /* check if imsg translates to predefined keystroke */
2037 struct InputEvent ievent;
2038 BOOL matched = FALSE;
2040 ievent.ie_NextEvent = NULL;
2041 ievent.ie_Class = IECLASS_RAWKEY;
2042 ievent.ie_SubClass = 0;
2043 ievent.ie_Code = event->Code;
2044 ievent.ie_Qualifier = event->Qualifier;
2045 /* ie_EventAddress is not used by MatchIX. If needed, it should be
2046 * ensured that it is still a valid address because of the shallow
2047 * IntuiMessage copy currently done in _zune_window_message before
2048 * message is replied.
2050 ievent.ie_EventAddress = NULL;
2051 //ievent.ie_EventAddress = (APTR *) *((ULONG *)(event->IAddress));
2053 for (muikey = MUIKEY_COUNT - 1; muikey >= MUIKEY_PRESS; muikey--)
2055 if (muiGlobalInfo(win)->mgi_Prefs->muikeys[muikey].ix_well != 0
2056 && MatchIX(&ievent,
2057 &muiGlobalInfo(win)->mgi_Prefs->muikeys[muikey].ix))
2059 matched = TRUE;
2060 break;
2064 if (matched)
2066 if (muikey == MUIKEY_PRESS && (event->Code & IECODE_UP_PREFIX))
2067 muikey = MUIKEY_RELEASE;
2069 else
2071 muikey = MUIKEY_NONE;
2073 } /* check if imsg translate to predefined keystroke */
2075 if ((muikey != MUIKEY_NONE) && !(data->wd_DisabledKeys & (1 << muikey)))
2077 D(bug("HandleRawkey: try MUIKEY %ld on window %0x08lx\n", muikey,
2078 win));
2079 switch (muikey)
2081 case MUIKEY_PRESS:
2082 break;
2083 case MUIKEY_TOGGLE:
2084 break;
2085 case MUIKEY_UP:
2086 break;
2087 case MUIKEY_DOWN:
2088 break;
2089 case MUIKEY_PAGEUP:
2090 break;
2091 case MUIKEY_PAGEDOWN:
2092 break;
2093 case MUIKEY_TOP:
2094 break;
2095 case MUIKEY_BOTTOM:
2096 break;
2097 case MUIKEY_LEFT:
2098 break;
2099 case MUIKEY_RIGHT:
2100 break;
2101 case MUIKEY_WORDLEFT:
2102 break;
2103 case MUIKEY_WORDRIGHT:
2104 break;
2105 case MUIKEY_LINESTART:
2106 break;
2107 case MUIKEY_LINEEND:
2108 break;
2109 case MUIKEY_GADGET_NEXT:
2110 set(win, MUIA_Window_ActiveObject,
2111 MUIV_Window_ActiveObject_Next);
2112 break;
2113 case MUIKEY_GADGET_PREV:
2114 set(win, MUIA_Window_ActiveObject,
2115 MUIV_Window_ActiveObject_Prev);
2116 break;
2117 case MUIKEY_GADGET_OFF:
2118 set(win, MUIA_Window_ActiveObject,
2119 MUIV_Window_ActiveObject_None);
2120 break;
2121 case MUIKEY_WINDOW_CLOSE:
2122 set(win, MUIA_Window_CloseRequest, TRUE);
2123 break;
2124 case MUIKEY_WINDOW_NEXT:
2125 break;
2126 case MUIKEY_WINDOW_PREV:
2127 break;
2128 case MUIKEY_HELP:
2129 break;
2130 case MUIKEY_POPUP:
2131 break;
2132 default:
2133 break;
2137 active_object = NULL;
2138 if ((data->wd_ActiveObject != NULL)
2139 && (DoMethod(data->wd_RootObject, MUIM_FindAreaObject,
2140 (IPTR) data->wd_ActiveObject) != (IPTR) NULL))
2142 active_object = data->wd_ActiveObject;
2143 get(active_object, MUIA_Disabled, &disabled);
2145 else
2146 data->wd_ActiveObject = NULL;
2148 /* try ActiveObject */
2149 if ((active_object != NULL) && !disabled)
2151 #if 0
2152 /* sba:
2153 ** Which method should be used for muikeys? MUIM_HandleInput or
2154 ** MUIM_HandleEvent. Also note that there is a flag MUI_EHF_ALWAYSKEYS
2155 ** which probably means that all keys events are requested??
2156 ** For now MUIM_HandleEvent is used as this is currently implemented
2157 ** in Area class ;) although I guess it should be MUIM_HandleInput as
2158 ** this was earlier
2161 if (muikey != MUIKEY_NONE)
2163 res =
2164 DoMethod(active_object, MUIM_HandleEvent, (IPTR) event,
2165 muikey);
2166 if (res & MUI_EventHandlerRC_Eat)
2167 return;
2169 #endif
2170 D(bug("HandleRawkey: try active object (%08lx) handlers\n",
2171 active_object));
2173 for (mn = data->wd_EHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
2175 ehn = (struct MUI_EventHandlerNode *)mn;
2177 if ((ehn->ehn_Object == active_object)
2178 && ((ehn->ehn_Events & IDCMP_RAWKEY)
2179 || (ehn->ehn_Flags & MUI_EHF_ALWAYSKEYS)))
2181 D(bug("HandleRawkey: (active) invoking on %p (ehn=%p) "
2182 "event=%p muikey=%p\n",
2183 ehn->ehn_Object, ehn, event, muikey));
2184 res = InvokeEventHandler(ehn, event, muikey);
2185 D(bug("HandleRawkey: (active) got res=%d\n", res));
2186 if (res & MUI_EventHandlerRC_Eat)
2187 return;
2189 /* Leave the loop if a different object has been activated */
2190 if (active_object != data->wd_ActiveObject)
2191 break;
2195 // event not eaten by active object, try its parents
2196 // this is to implement popup key in Popstring
2197 if (active_object == data->wd_ActiveObject)
2199 Object *current_obj = active_object;
2201 D(bug("HandleRawkey: try active object parents handlers\n"));
2202 while (current_obj != NULL)
2204 for (mn = data->wd_EHList.mlh_Head; mn->mln_Succ;
2205 mn = mn->mln_Succ)
2207 ehn = (struct MUI_EventHandlerNode *)mn;
2209 if ((ehn->ehn_Object == current_obj)
2210 && ((ehn->ehn_Events & IDCMP_RAWKEY)
2211 || (ehn->ehn_Flags & MUI_EHF_ALWAYSKEYS)))
2213 //D(bug("HandleRawkey: (active parents) invoking on "
2214 // "%p (ehn=%p) event=%p muikey=%p\n",
2215 // ehn->ehn_Object, ehn, event, muikey));
2216 res = InvokeEventHandler(ehn, event, muikey);
2217 //D(bug("HandleRawkey: (active parents) got res=%d\n",
2218 // res));
2219 if (res & MUI_EventHandlerRC_Eat)
2220 return;
2222 /* Leave the loop if a different object has been
2223 * activated */
2224 if (active_object != data->wd_ActiveObject)
2225 break;
2228 current_obj = (Object *) XGET(current_obj, MUIA_Parent);
2233 D(bug("HandleRawkey: try default object handlers\n"));
2235 /* try DefaultObject */
2236 if (data->wd_DefaultObject != NULL)
2237 get(data->wd_DefaultObject, MUIA_Disabled, &disabled);
2239 if ((data->wd_DefaultObject != NULL) && !disabled
2240 && (active_object != data->wd_DefaultObject))
2242 /* No, we only should do this if the object actually has requested
2243 * this via RequestIDCMP()! */
2244 // if (muikey != MUIKEY_NONE
2245 // && (_flags(data->wd_DefaultObject) & MADF_CANDRAW))
2246 // {
2247 // DoMethod(data->wd_DefaultObject, MUIM_HandleInput, event, muikey);
2248 // return;
2249 // }
2251 for (mn = data->wd_EHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
2253 ehn = (struct MUI_EventHandlerNode *)mn;
2255 if ((ehn->ehn_Object == data->wd_DefaultObject)
2256 && ((ehn->ehn_Events & IDCMP_RAWKEY)
2257 || (ehn->ehn_Flags & MUI_EHF_ALWAYSKEYS)))
2259 //D(bug("HandleRawkey: (default) invoking on %p (ehn=%p) "
2260 //"event=%p muikey=%p\n",
2261 //ehn->ehn_Object, ehn, event, muikey));
2262 res = InvokeEventHandler(ehn, event, muikey);
2263 //D(bug("HandleRawkey: (default) got res=%d\n", res));
2264 if (res & MUI_EventHandlerRC_Eat)
2265 return;
2271 D(bug("HandleRawkey: try other handlers\n"));
2273 // try other handlers
2274 for (mn = data->wd_EHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
2276 ehn = (struct MUI_EventHandlerNode *)mn;
2278 // skip Active and Default object as they have already been
2279 // handled
2280 if (ehn->ehn_Object == data->wd_ActiveObject
2281 || ehn->ehn_Object == data->wd_DefaultObject)
2282 continue;
2284 if (ehn->ehn_Events & IDCMP_RAWKEY)
2286 //D(bug("HandleRawkey: (others) invoking on %p (ehn=%p) "
2287 //"event=%p muikey=%p\n",
2288 //ehn->ehn_Object, ehn, event, muikey));
2289 res = InvokeEventHandler(ehn, event, MUIKEY_NONE);
2290 //D(bug("HandleRawkey: (others) got res=%d\n", res));
2291 if (res & MUI_EventHandlerRC_Eat)
2292 return;
2296 D(bug("HandleRawkey: try control chars handlers\n"));
2298 /* try Control Chars */
2299 //bug("ctrlchar, key='%c' code=0x%08lx\n", key, event->Code);
2300 if (key)
2302 for (mn = data->wd_CCList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
2304 ehn = (struct MUI_EventHandlerNode *)mn;
2306 if (ehn->ehn_Events == key)
2308 IPTR disabled = 0;
2309 LONG muikey2 = ehn->ehn_Flags;
2311 get(ehn->ehn_Object, MUIA_Disabled, &disabled);
2312 if (disabled)
2313 continue;
2315 //bug("control char\n");
2316 if (event->Code & IECODE_UP_PREFIX)
2318 /* simulate a release */
2319 if (muikey2 == MUIKEY_PRESS)
2320 muikey2 = MUIKEY_RELEASE;
2321 else
2322 return;
2325 if ((muikey2 != MUIKEY_NONE)
2326 && (_flags(ehn->ehn_Object) & MADF_CANDRAW)
2327 && (_flags(ehn->ehn_Object) & MADF_SHOWME))
2329 res = CoerceMethod
2330 (ehn->ehn_Class, ehn->ehn_Object, MUIM_HandleEvent,
2331 (IPTR) NULL, muikey2);
2332 if (res & MUI_EventHandlerRC_Eat)
2333 return;
2340 /* forward non-keystroke events to event handlers */
2341 static void HandleInputEvent(Object *win, struct MUI_WindowData *data,
2342 struct IntuiMessage *event)
2344 struct MinNode *mn;
2345 struct MUI_EventHandlerNode *ehn;
2346 struct IntuiMessage imsg_copy;
2347 ULONG res;
2348 ULONG mask = event->Class;
2350 if (mask != IDCMP_IDCMPUPDATE)
2352 imsg_copy = *event;
2353 imsg_copy.IAddress = NULL; /* be sure to trap access to that */
2354 ReplyMsg((struct Message *)event);
2355 event = &imsg_copy;
2358 if (mask == IDCMP_MOUSEMOVE)
2360 struct Window *iWin;
2361 iWin = event->IDCMPWindow;
2363 if (ContextMenuUnderPointer(data, data->wd_RootObject,
2364 event->MouseX, event->MouseY))
2366 iWin->Flags |= WFLG_RMBTRAP;
2368 else if (!data->wd_NoMenus)
2370 iWin->Flags &= ~WFLG_RMBTRAP;
2374 for (mn = data->wd_EHList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
2376 ehn = (struct MUI_EventHandlerNode *)mn;
2378 if (ehn->ehn_Events & mask)
2380 IPTR disabled = 0;
2382 get(ehn->ehn_Object, MUIA_Disabled, &disabled);
2383 if (disabled)
2384 continue;
2386 res = InvokeEventHandler(ehn, event, MUIKEY_NONE);
2387 if (res & MUI_EventHandlerRC_Eat)
2388 return;
2393 if (mask == IDCMP_IDCMPUPDATE)
2394 ReplyMsg((struct Message *)event);
2398 /* process window message; this does a ReplyMsg() to the message */
2399 /* Called from application.c */
2400 void _zune_window_message(struct IntuiMessage *imsg)
2402 struct Window *iWin;
2403 Object *oWin;
2404 struct MUI_WindowData *data;
2405 BOOL handled;
2407 iWin = imsg->IDCMPWindow;
2408 oWin = (Object *) iWin->UserData;
2409 data = muiWindowData(oWin);
2411 if (data->wd_SleepCount > 0)
2413 BOOL refresh=FALSE;
2414 /* Window is sleeping, so we just ignore (and reply) all messages.
2415 * MUI 3.8/AmigaOS3 also receives all messages (IDCMP Flags
2416 * are not modified during sleeping). MUI refreshes the window
2417 * contents, so it seems to handle IDCMP_REFRESHWINDOW messages.
2418 * If any other messages are handled by MUI is unsure/not tested.
2420 if (imsg->Class == IDCMP_REFRESHWINDOW)
2422 refresh=TRUE;
2424 ReplyMsg((struct Message *)imsg);
2425 if (refresh)
2427 RefreshWindow(oWin, data);
2429 return;
2432 if (data->wd_DragObject)
2434 if (!HandleDragging(oWin, data, imsg))
2435 return;
2438 handled = HandleWindowEvent(oWin, data, imsg);
2439 if (!handled)
2441 if (IDCMP_RAWKEY == imsg->Class)
2442 HandleRawkey(oWin, data, imsg);
2443 else if (IDCMP_GADGETUP == imsg->Class)
2445 #ifdef __AROS__
2446 if (ETI_MUI == ((struct Gadget *)imsg->IAddress)->GadgetID)
2448 DoMethod(_app(oWin), MUIM_Application_OpenConfigWindow);
2450 #endif
2451 if (ETI_Iconify == ((struct Gadget *)imsg->IAddress)->GadgetID)
2453 set(_app(oWin), MUIA_Application_Iconified, TRUE);
2456 else
2458 HandleInputEvent(oWin, data, imsg);
2463 /**************************************************************************/
2464 /**************************************************************************/
2466 /* code for setting MUIA_Window_RootObject */
2467 static void ChangeRootObject(struct MUI_WindowData *data, Object *obj,
2468 Object *newRoot)
2470 Object *oldRoot;
2472 ASSERT_VALID_PTR(data);
2473 ASSERT_VALID_PTR(obj);
2475 oldRoot = data->wd_RootObject;
2476 if (!(data->wd_Flags & MUIWF_OPENED))
2478 if (oldRoot)
2480 if (data->wd_ActiveObject == oldRoot)
2481 set(obj, MUIA_Window_ActiveObject,
2482 MUIV_Window_ActiveObject_None);
2483 DoMethod(oldRoot, MUIM_DisconnectParent);
2486 data->wd_RootObject = newRoot;
2487 if (newRoot)
2489 /* if window is in App tree, inform child */
2490 if (muiNotifyData(obj)->mnd_GlobalInfo)
2491 DoMethod(newRoot, MUIM_ConnectParent, (IPTR) obj);
2496 // find the ObjNode containing a pointer to the given object
2497 // currently only used for cycle chain objects
2498 static struct ObjNode *FindObjNode(struct MinList *list, Object *obj)
2500 struct ObjNode *node;
2502 ASSERT_VALID_PTR(list);
2504 if (!obj)
2505 return NULL;
2507 ASSERT_VALID_PTR(obj);
2509 for (node = (struct ObjNode *)list->mlh_Head;
2510 node->node.mln_Succ; node = (struct ObjNode *)node->node.mln_Succ)
2512 if (node->obj == obj)
2514 return node;
2517 return NULL;
2520 static Object *GetFirstActiveObject(struct MUI_WindowData *data)
2522 ASSERT_VALID_PTR(data);
2524 if (!IsListEmpty(&data->wd_CycleChain))
2525 return ((struct ObjNode *)data->wd_CycleChain.mlh_Head)->obj;
2526 else
2527 return NULL;
2530 static Object *GetLastActiveObject(struct MUI_WindowData *data)
2532 ASSERT_VALID_PTR(data);
2534 if (!IsListEmpty(&data->wd_CycleChain))
2535 return ((struct ObjNode *)data->wd_CycleChain.mlh_TailPred)->obj;
2536 else
2537 return NULL;
2540 typedef struct ObjNode *objnode_iterator_t(struct ObjNode *curr_node);
2542 static objnode_iterator_t NextObjNodeIterator;
2543 static objnode_iterator_t PrevObjNodeIterator;
2545 static struct ObjNode *NextObjNodeIterator(struct ObjNode *curr_node)
2547 if (curr_node->node.mln_Succ->mln_Succ)
2548 return (struct ObjNode *)curr_node->node.mln_Succ;
2549 else
2550 return NULL;
2553 static struct ObjNode *PrevObjNodeIterator(struct ObjNode *curr_node)
2555 if (curr_node->node.mln_Pred->mln_Pred)
2556 return (struct ObjNode *)curr_node->node.mln_Pred;
2557 else
2558 return NULL;
2561 static Object *GetPrevNextActiveObject(struct ObjNode *old_activenode,
2562 objnode_iterator_t node_iterator)
2564 struct ObjNode *curr_node;
2565 struct ObjNode *node;
2566 Object *obj;
2568 ASSERT_VALID_PTR(old_activenode);
2570 curr_node = old_activenode;
2571 node = NULL;
2572 obj = NULL;
2574 while (curr_node)
2576 node = node_iterator(curr_node);
2578 if (node)
2579 obj = node->obj;
2581 /* let's see if this object meets cycle requirements
2582 * (enabled & visible) */
2583 if (obj)
2585 IPTR is_disabled = 0;
2587 get(obj, MUIA_Disabled, &is_disabled);
2589 if (!is_disabled && (_flags(obj) & MADF_SHOWME))
2591 return obj;
2595 curr_node = node;
2596 obj = NULL;
2597 node = NULL;
2599 return obj;
2603 /**************************************************************************
2604 Code for setting MUIA_Window_ActiveObject
2605 Basically, it will:
2606 - remove focus drawing for current active object
2607 - find (if needed) the new active object
2608 - set data->wd_ActiveObject to the new object
2609 - draw focus around the new active object
2610 **************************************************************************/
2611 static void SetActiveObject(struct MUI_WindowData *data, Object *obj,
2612 IPTR newval)
2614 struct ObjNode *old_activenode = NULL;
2616 ASSERT_VALID_PTR(data);
2617 ASSERT_VALID_PTR(obj);
2619 D(bug("MUIC_Window:SetActiveObject(data, obj, %08lx) Active=%p\n",
2620 newval, data->wd_ActiveObject));
2622 /* If the window is closed, we just store the object for later activation
2623 * when the window is (re)opened */
2624 if (!(data->wd_Flags & MUIWF_OPENED))
2626 data->wd_OldActive = (Object *)newval;
2627 return;
2630 if ((data->wd_ActiveObject != NULL)
2631 && (DoMethod(data->wd_RootObject, MUIM_FindAreaObject,
2632 (IPTR) data->wd_ActiveObject) != (IPTR) NULL))
2634 if ((IPTR) data->wd_ActiveObject != newval)
2636 old_activenode =
2637 FindObjNode(&data->wd_CycleChain, data->wd_ActiveObject);
2638 if ((data->wd_Flags & MUIWF_OBJECTGOACTIVESENT)
2639 && (_flags(data->wd_ActiveObject) & MADF_SETUP))
2641 D(bug("Deactivate=%p\n", data->wd_ActiveObject));
2642 DoMethod(data->wd_ActiveObject, MUIM_GoInactive);
2647 data->wd_ActiveObject = NULL;
2648 data->wd_Flags &= ~MUIWF_OBJECTGOACTIVESENT;
2650 switch (newval)
2652 case MUIV_Window_ActiveObject_None:
2653 break;
2655 case MUIV_Window_ActiveObject_Next:
2656 if (old_activenode != NULL)
2657 data->wd_ActiveObject = GetPrevNextActiveObject(old_activenode,
2658 NextObjNodeIterator);
2659 if (NULL == data->wd_ActiveObject)
2660 data->wd_ActiveObject = GetFirstActiveObject(data);
2661 break;
2663 case MUIV_Window_ActiveObject_Prev:
2664 if (old_activenode)
2665 data->wd_ActiveObject = GetPrevNextActiveObject(old_activenode,
2666 PrevObjNodeIterator);
2667 if (NULL == data->wd_ActiveObject)
2668 data->wd_ActiveObject = GetLastActiveObject(data);
2669 break;
2671 default:
2672 data->wd_ActiveObject = (Object *) newval;
2673 break;
2677 if (data->wd_ActiveObject != NULL
2678 && DoMethod(data->wd_RootObject, MUIM_FindAreaObject,
2679 (IPTR) data->wd_ActiveObject)
2680 && (_flags(data->wd_ActiveObject) & MADF_CANDRAW))
2682 D(bug("Activate=%p\n", data->wd_ActiveObject));
2683 DoMethod(data->wd_ActiveObject, MUIM_GoActive);
2684 data->wd_Flags |= MUIWF_OBJECTGOACTIVESENT;
2689 static BOOL InBox(struct IBox *box, WORD x, WORD y)
2691 return x >= box->Left && x < box->Left + box->Width
2692 && y >= box->Top && y < box->Top + box->Height;
2697 * Pass on an AppMessage to all objects that it landed on.
2699 static void ForwardAppMessage(struct MUI_WindowData *data, Object *child,
2700 struct AppMessage *appmsg)
2702 WORD x = appmsg->am_MouseX, y = appmsg->am_MouseY;
2703 Object *cstate;
2704 struct List *children = NULL;
2706 ASSERT_VALID_PTR(data);
2707 ASSERT_VALID_PTR(child);
2709 set(child, MUIA_AppMessage, appmsg);
2711 children = (struct List *)XGET(child, MUIA_Group_ChildList);
2713 if (children != NULL)
2715 cstate = (Object *) children->lh_Head;
2716 while ((child = NextObject(&cstate)))
2718 if (InBox(&muiAreaData(child)->mad_Box, x, y))
2720 ForwardAppMessage(data, child, appmsg);
2728 * calculate real dimensions from programmer requirements.
2729 * may be overridden by user settings if MUIA_Window_ID is set.
2731 /* MUIV_Window_Height_Screen and MUIV_Window_Height_Visible
2732 * are not handled yet, as their Width couterparts.
2734 static void WindowSelectDimensions(struct MUI_WindowData *data)
2736 if (!data->wd_Width)
2738 if (data->wd_ReqWidth > 0)
2739 data->wd_Width = data->wd_ReqWidth;
2740 else if (data->wd_ReqWidth == MUIV_Window_Width_Default)
2741 data->wd_Width = data->wd_MinMax.DefWidth;
2742 else if (_between(MUIV_Window_Width_MinMax(100),
2743 data->wd_ReqWidth, MUIV_Window_Width_MinMax(0)))
2745 data->wd_Width = data->wd_MinMax.MinWidth
2746 - data->wd_ReqWidth
2747 * (data->wd_MinMax.MaxWidth - data->wd_MinMax.MinWidth);
2749 else if (_between(MUIV_Window_Width_Screen(100),
2750 data->wd_ReqWidth, MUIV_Window_Width_Screen(0)))
2752 data->wd_Width = data->wd_RenderInfo.mri_ScreenWidth
2753 * (-(data->wd_ReqWidth + 200)) / 100;
2755 else if (_between(MUIV_Window_Width_Visible(100),
2756 data->wd_ReqWidth, MUIV_Window_Width_Visible(0)))
2758 data->wd_Width = data->wd_RenderInfo.mri_ScreenWidth
2759 * (-(data->wd_ReqWidth + 100)) / 100;
2762 if (data->wd_ReqHeight > 0)
2763 data->wd_Height = data->wd_ReqHeight;
2764 else if (data->wd_ReqHeight == MUIV_Window_Height_Default)
2765 data->wd_Height = data->wd_MinMax.DefHeight;
2766 else if (_between(MUIV_Window_Height_MinMax(100),
2767 data->wd_ReqHeight, MUIV_Window_Height_MinMax(0)))
2769 data->wd_Height = data->wd_MinMax.MinHeight
2770 - data->wd_ReqHeight
2771 * (data->wd_MinMax.MaxHeight - data->wd_MinMax.MinHeight);
2773 else if (_between(MUIV_Window_Height_Screen(100),
2774 data->wd_ReqHeight, MUIV_Window_Height_Screen(0)))
2776 struct Screen *scr;
2777 int height;
2779 scr = data->wd_RenderInfo.mri_Screen;
2781 height =
2782 scr->Height - data->wd_RenderInfo.mri_BorderTop -
2783 data->wd_RenderInfo.mri_BorderBottom;
2785 data->wd_Height = height * (-(data->wd_ReqHeight + 200)) / 100;
2787 else if (_between(MUIV_Window_Height_Visible(100),
2788 data->wd_ReqHeight, MUIV_Window_Height_Visible(0)))
2790 data->wd_Height = data->wd_RenderInfo.mri_ScreenHeight
2791 * (-(data->wd_ReqHeight + 100)) / 100;
2794 /* scaled */
2795 if (data->wd_ReqWidth == MUIV_Window_Width_Scaled)
2796 data->wd_Width = data->wd_Height * data->wd_MinMax.MinWidth
2797 / data->wd_MinMax.MinHeight;
2798 else if (data->wd_ReqHeight == MUIV_Window_Width_Scaled)
2799 data->wd_Height = data->wd_Width * data->wd_MinMax.MinHeight
2800 / data->wd_MinMax.MinWidth;
2802 data->wd_Width = CLAMP(data->wd_Width, data->wd_MinMax.MinWidth,
2803 data->wd_MinMax.MaxWidth);
2804 data->wd_Height = CLAMP(data->wd_Height, data->wd_MinMax.MinHeight,
2805 data->wd_MinMax.MaxHeight);
2809 /**************************************************************************
2810 OM_NEW
2811 **************************************************************************/
2812 IPTR Window__OM_NEW(struct IClass *cl, Object *obj, struct opSet *msg)
2814 struct MUI_WindowData *data;
2815 struct TagItem *tags;
2816 struct TagItem *tag;
2818 obj = (Object *) DoSuperMethodA(cl, obj, (Msg) msg);
2819 if (!obj)
2820 return FALSE;
2822 /* Initial local instance data */
2823 data = INST_DATA(cl, obj);
2825 data->wd_Class = cl;
2826 data->wd_MemoryPool = CreatePool(0, 4096, 2048);
2827 if (NULL == data->wd_MemoryPool)
2829 CoerceMethod(cl, obj, OM_DISPOSE);
2830 return (IPTR) NULL;
2833 data->wd_RenderInfo.mri_WindowObject = obj;
2835 NewList((struct List *)&(data->wd_EHList));
2836 NewList((struct List *)&(data->wd_CCList));
2837 NewList((struct List *)&(data->wd_CycleChain));
2838 NewList((struct List *)&(data->wd_IDList));
2840 data->wd_CrtFlags = WFLG_SIZEGADGET | WFLG_DRAGBAR | WFLG_DEPTHGADGET
2841 | WFLG_CLOSEGADGET | WFLG_SIMPLE_REFRESH
2842 | WFLG_REPORTMOUSE | WFLG_NEWLOOKMENUS;
2843 data->wd_ZoomGadget = TRUE;
2844 data->wd_Events = GetDefaultEvents();
2845 data->wd_ActiveObject = NULL;
2846 data->wd_ID = 0;
2847 data->wd_ReqHeight = MUIV_Window_Height_Default;
2848 data->wd_ReqWidth = MUIV_Window_Width_Default;
2849 data->wd_RootObject = NULL;
2850 data->wd_DefaultObject = NULL;
2852 data->wd_AltDim.Top = MUIV_Window_AltTopEdge_NoChange;
2853 data->wd_AltDim.Left = MUIV_Window_AltLeftEdge_NoChange;
2854 data->wd_AltDim.Width = MUIV_Window_AltWidth_MinMax(0);
2855 data->wd_AltDim.Height = MUIV_Window_AltHeight_MinMax(0);
2856 data->wd_ReqX = MUIV_Window_LeftEdge_Centered;
2857 data->wd_ReqY = MUIV_Window_TopEdge_Centered;
2858 data->wd_DisabledKeys = 0L;
2859 data->wd_HelpTicker = BUBBLEHELP_TICKER_FIRST;
2861 /* parse initial taglist */
2863 for (tags = msg->ops_AttrList; (tag = NextTagItem(&tags));)
2865 switch (tag->ti_Tag)
2867 case MUIA_Window_EraseArea:
2868 _handle_bool_tag(data->wd_Flags, tag->ti_Data, MUIWF_ERASEAREA);
2869 break;
2871 case MUIA_Window_ToolBox:
2872 _handle_bool_tag(data->wd_Flags, tag->ti_Data, MUIWF_TOOLBOX);
2873 break;
2875 case MUIA_Window_CloseGadget:
2876 _handle_bool_tag(data->wd_CrtFlags, tag->ti_Data,
2877 WFLG_CLOSEGADGET);
2878 break;
2880 case MUIA_Window_SizeGadget:
2881 _handle_bool_tag(data->wd_CrtFlags, tag->ti_Data,
2882 WFLG_SIZEGADGET);
2883 break;
2885 case MUIA_Window_ZoomGadget:
2886 data->wd_ZoomGadget = tag->ti_Data;
2887 break;
2889 case MUIA_Window_Backdrop:
2890 _handle_bool_tag(data->wd_CrtFlags, tag->ti_Data,
2891 WFLG_BACKDROP);
2892 break;
2894 case MUIA_Window_Borderless:
2895 _handle_bool_tag(data->wd_CrtFlags, tag->ti_Data,
2896 WFLG_BORDERLESS);
2897 break;
2899 case MUIA_Window_DepthGadget:
2900 _handle_bool_tag(data->wd_CrtFlags, tag->ti_Data,
2901 WFLG_DEPTHGADGET);
2902 break;
2904 case MUIA_Window_DragBar:
2905 _handle_bool_tag(data->wd_CrtFlags, tag->ti_Data, WFLG_DRAGBAR);
2906 break;
2908 case MUIA_Window_SizeRight:
2909 _handle_bool_tag(data->wd_CrtFlags, tag->ti_Data,
2910 WFLG_SIZEBRIGHT);
2911 break;
2913 case MUIA_Window_Height:
2914 data->wd_ReqHeight = (LONG) tag->ti_Data;
2915 break;
2917 case MUIA_Window_Width:
2918 data->wd_ReqWidth = (LONG) tag->ti_Data;
2919 break;
2921 case MUIA_Window_ID:
2922 set(obj, MUIA_Window_ID, tag->ti_Data);
2923 break;
2925 case MUIA_Window_IsSubWindow:
2926 _handle_bool_tag(data->wd_Flags, tag->ti_Data,
2927 MUIWF_ISSUBWINDOW);
2928 break;
2930 case MUIA_Window_Title:
2931 set(obj, MUIA_Window_Title, tag->ti_Data);
2932 break;
2934 case MUIA_Window_ScreenTitle:
2935 set(obj, MUIA_Window_ScreenTitle, tag->ti_Data);
2936 break;
2938 case MUIA_Window_Activate:
2939 _handle_bool_tag(data->wd_Flags, !tag->ti_Data,
2940 MUIWF_DONTACTIVATE);
2941 break;
2943 case MUIA_Window_DefaultObject:
2944 set(obj, MUIA_Window_DefaultObject, tag->ti_Data);
2945 break;
2947 case MUIA_Window_Menustrip:
2948 data->wd_ChildMenustrip = (Object *) tag->ti_Data;
2949 break;
2951 case MUIA_Window_NoMenus:
2952 data->wd_NoMenus = (BOOL) tag->ti_Data;
2953 break;
2955 case MUIA_Window_RootObject:
2956 if (!tag->ti_Data)
2958 CoerceMethod(cl, obj, OM_DISPOSE);
2959 return 0;
2961 set(obj, MUIA_Window_RootObject, tag->ti_Data);
2962 break;
2964 case MUIA_Window_AltHeight:
2965 data->wd_AltDim.Height = (WORD) tag->ti_Data;
2966 break;
2968 case MUIA_Window_AltWidth:
2969 data->wd_AltDim.Width = (WORD) tag->ti_Data;
2970 break;
2972 case MUIA_Window_AltLeftEdge:
2973 data->wd_AltDim.Left = (WORD) tag->ti_Data;
2974 break;
2976 case MUIA_Window_AltTopEdge:
2977 data->wd_AltDim.Top = (WORD) tag->ti_Data;
2978 break;
2980 case MUIA_Window_AppWindow:
2981 _handle_bool_tag(data->wd_Flags, tag->ti_Data,
2982 MUIWF_ISAPPWINDOW);
2983 break;
2985 case MUIA_Window_LeftEdge:
2986 data->wd_ReqX = tag->ti_Data;
2987 break;
2989 case MUIA_Window_TopEdge:
2990 data->wd_ReqY = tag->ti_Data;
2991 break;
2993 case MUIA_Window_UseBottomBorderScroller:
2994 _handle_bool_tag(data->wd_Flags, tag->ti_Data,
2995 MUIWF_USEBOTTOMSCROLLER);
2996 break;
2998 case MUIA_Window_UseRightBorderScroller:
2999 _handle_bool_tag(data->wd_Flags, tag->ti_Data,
3000 MUIWF_USERIGHTSCROLLER);
3001 break;
3003 case MUIA_Window_DisableKeys:
3004 data->wd_DisabledKeys = tag->ti_Data;
3005 break;
3007 case MUIA_Window_RefWindow:
3008 data->wd_RefWindow = (Object *) tag->ti_Data;
3009 break;
3011 case MUIA_Window_Screen:
3012 data->wd_UserScreen = (struct Screen *)tag->ti_Data;
3013 break;
3015 case MUIA_Window_PublicScreen:
3016 data->wd_UserPublicScreen = (STRPTR) tag->ti_Data;
3017 break;
3021 /* D(bug("muimaster.library/window.c: Window Object created at " */
3022 /* "0x%lx back=%lx\n", */
3023 /* obj,data->wd_Background)); */
3025 return (IPTR) obj;
3028 /**************************************************************************
3029 OM_DISPOSE
3030 **************************************************************************/
3031 IPTR Window__OM_DISPOSE(struct IClass *cl, Object *obj, Msg msg)
3033 struct MUI_WindowData *data = INST_DATA(cl, obj);
3035 /* D(bug("Window_Dispose(%p)\n", obj)); */
3037 #if 0
3038 /* We no longer clear muiGlobalInfo() during disconnections, so
3039 this can cause problems (remove object which is already removed).
3040 Furthermore AFAIK it is not legal to dispose a window object
3041 which is still ocnnected to the application object, anyway. */
3043 if (muiGlobalInfo(obj) && _app(obj))
3045 /* D(bug(" Window_Dispose(%p) : calling app->OM_REMMEMBER\n", obj)); */
3046 DoMethod(_app(obj), OM_REMMEMBER, (IPTR) obj);
3048 #endif
3050 if (data->wd_RootObject)
3051 MUI_DisposeObject(data->wd_RootObject);
3053 if (data->wd_ChildMenustrip)
3054 MUI_DisposeObject(data->wd_ChildMenustrip);
3056 DeletePool(data->wd_MemoryPool);
3058 /* D(bug(" Window_Dispose(%p) : calling supermethod\n", obj)); */
3059 return DoSuperMethodA(cl, obj, msg);
3062 static ULONG WindowOpen(struct IClass *cl, Object *obj);
3063 static ULONG WindowClose(struct IClass *cl, Object *obj);
3065 /**************************************************************************
3066 OM_SET
3067 **************************************************************************/
3068 IPTR Window__OM_SET(struct IClass *cl, Object *obj, struct opSet *msg)
3070 struct MUI_WindowData *data = INST_DATA(cl, obj);
3071 struct TagItem *tags = msg->ops_AttrList;
3072 struct TagItem *tag;
3074 while ((tag = NextTagItem(&tags)) != NULL)
3076 switch (tag->ti_Tag)
3078 case MUIA_AppMessage:
3079 ForwardAppMessage(data, data->wd_RootObject,
3080 (struct AppMessage *)tag->ti_Data);
3081 break;
3083 case MUIA_Window_Activate:
3084 if (data->wd_RenderInfo.mri_Window)
3086 if (tag->ti_Data && !(data->wd_Flags & MUIWF_ACTIVE))
3088 ActivateWindow(data->wd_RenderInfo.mri_Window);
3089 _handle_bool_tag(data->wd_Flags, tag->ti_Data,
3090 MUIWF_ACTIVE);
3093 else
3094 _handle_bool_tag(data->wd_Flags, !tag->ti_Data,
3095 MUIWF_DONTACTIVATE);
3096 break;
3098 case MUIA_Window_ActiveObject:
3099 /* D(bug("MUIA_Window_ActiveObject %ld (%p)\n", */
3100 /* tag->ti_Data, tag->ti_Data)); */
3101 SetActiveObject(data, obj, tag->ti_Data);
3102 break;
3104 case MUIA_Window_DefaultObject:
3105 data->wd_DefaultObject = (APTR) tag->ti_Data;
3106 break;
3108 case MUIA_Window_ID:
3109 data->wd_ID = tag->ti_Data;
3110 break;
3112 case MUIA_Window_IsSubWindow:
3113 _handle_bool_tag(data->wd_Flags, tag->ti_Data,
3114 MUIWF_ISSUBWINDOW);
3115 break;
3117 case MUIA_Window_Open:
3118 if (tag->ti_Data)
3120 if (data->wd_Flags & MUIWF_HIDDEN)
3121 data->wd_Flags |= MUIWF_OPENONUNHIDE;
3122 else if (!(data->wd_Flags & MUIWF_OPENED))
3123 WindowOpen(cl, obj);
3124 else
3126 DoMethod(obj, MUIM_Window_ToFront);
3127 set(obj, MUIA_Window_Activate, TRUE);
3130 else if (data->wd_Flags & MUIWF_HIDDEN)
3131 data->wd_Flags &= ~MUIWF_OPENONUNHIDE;
3132 else if (data->wd_Flags & MUIWF_OPENED)
3133 WindowClose(cl, obj);
3134 break;
3136 case MUIA_ShowMe: /* PRIVATE *abuse* of the Area's ShowMe attr */
3137 if (tag->ti_Data)
3139 /* Deiconify */
3141 if (data->wd_Flags & MUIWF_HIDDEN)
3143 data->wd_Flags &= ~MUIWF_HIDDEN;
3145 if (data->wd_Flags & MUIWF_OPENONUNHIDE)
3147 data->wd_Flags &= ~MUIWF_OPENONUNHIDE;
3148 set(obj, MUIA_Window_Open, TRUE);
3152 else
3154 /* Iconify */
3156 if (data->wd_Flags & MUIWF_OPENED)
3158 data->wd_Flags |= MUIWF_OPENONUNHIDE;
3160 set(obj, MUIA_Window_Open, FALSE);
3163 data->wd_Flags |= MUIWF_HIDDEN;
3165 break;
3167 case MUIA_Window_RootObject:
3168 ChangeRootObject(data, obj, (Object *) tag->ti_Data);
3169 break;
3171 case MUIA_Window_Title:
3172 data->wd_Title = (STRPTR) tag->ti_Data;
3173 if (data->wd_RenderInfo.mri_Window)
3174 SetWindowTitles(data->wd_RenderInfo.mri_Window,
3175 data->wd_Title, (CONST_STRPTR) ~ 0);
3176 break;
3178 case MUIA_Window_ScreenTitle:
3179 data->wd_ScreenTitle = (STRPTR) tag->ti_Data;
3180 if (data->wd_RenderInfo.mri_Window)
3181 SetWindowTitles(data->wd_RenderInfo.mri_Window,
3182 (CONST_STRPTR) ~ 0, data->wd_ScreenTitle);
3183 break;
3185 case MUIA_Window_NoMenus:
3186 data->wd_NoMenus = (BOOL) tag->ti_Data;
3187 if (data->wd_RenderInfo.mri_Window)
3189 if (data->wd_NoMenus)
3190 data->wd_RenderInfo.mri_Window->Flags |= WFLG_RMBTRAP;
3191 else
3192 data->wd_RenderInfo.mri_Window->Flags &= ~WFLG_RMBTRAP;
3194 break;
3196 case MUIA_Window_UseBottomBorderScroller:
3197 _handle_bool_tag(data->wd_Flags, tag->ti_Data,
3198 MUIWF_USEBOTTOMSCROLLER);
3199 break;
3201 case MUIA_Window_UseRightBorderScroller:
3202 _handle_bool_tag(data->wd_Flags, tag->ti_Data,
3203 MUIWF_USERIGHTSCROLLER);
3204 break;
3206 case MUIA_Window_DisableKeys:
3207 data->wd_DisabledKeys = tag->ti_Data;
3208 break;
3210 case MUIA_Window_RefWindow:
3211 data->wd_RefWindow = (Object *) tag->ti_Data;
3212 break;
3214 case MUIA_Window_LeftEdge:
3215 data->wd_ReqX = tag->ti_Data;
3216 break;
3218 case MUIA_Window_TopEdge:
3219 data->wd_ReqY = tag->ti_Data;
3220 break;
3222 case MUIA_Window_Width:
3223 data->wd_ReqWidth = (LONG) tag->ti_Data;
3224 data->wd_Width = 0; /* otherwise windowselectdimensions()
3225 * ignores ReqWidth */
3226 break;
3228 case MUIA_Window_Height:
3229 data->wd_ReqHeight = (LONG) tag->ti_Data;
3230 data->wd_Height = 0;
3231 break;
3233 case MUIA_Window_Screen:
3234 data->wd_UserScreen = (struct Screen *)tag->ti_Data;
3235 break;
3237 case MUIA_Window_PublicScreen:
3238 data->wd_UserPublicScreen = (STRPTR) tag->ti_Data;
3239 break;
3241 case MUIA_Window_Sleep:
3242 if (tag->ti_Data)
3244 data->wd_SleepCount++;
3245 if (data->wd_RenderInfo.mri_Window
3246 && (data->wd_SleepCount == 1))
3248 SetWindowPointer
3249 (data->wd_RenderInfo.mri_Window,
3250 WA_BusyPointer, TRUE,
3251 WA_PointerDelay, TRUE, TAG_DONE);
3253 /* event handling is disabled in _zune_window_message() */
3255 data->wd_SleepMaxHeight=data->wd_RenderInfo.mri_Window->MaxHeight;
3256 data->wd_SleepMinHeight=data->wd_RenderInfo.mri_Window->MinHeight;
3257 data->wd_SleepMaxWidth=data->wd_RenderInfo.mri_Window->MaxWidth;
3258 data->wd_SleepMinWidth=data->wd_RenderInfo.mri_Window->MaxWidth;
3259 /* According to MUI autodocs, sleeping windows can't be resized.
3260 * MUI 3.8/AmigaOS also changes min/max values with WindowLimits */
3261 WindowLimits(data->wd_RenderInfo.mri_Window,
3262 data->wd_RenderInfo.mri_Window->Width,
3263 data->wd_RenderInfo.mri_Window->Height,
3264 data->wd_RenderInfo.mri_Window->Width,
3265 data->wd_RenderInfo.mri_Window->Height);
3268 else
3270 data->wd_SleepCount--;
3271 if (data->wd_RenderInfo.mri_Window
3272 && (data->wd_SleepCount == 0))
3274 SetWindowPointerA(data->wd_RenderInfo.mri_Window, NULL);
3276 /* Only restore settings, if they have been saved
3277 * during (MUIA_Window_Sleep, TRUE) call */
3278 if (data->wd_SleepMaxHeight > 0)
3280 WindowLimits(data->wd_RenderInfo.mri_Window,
3281 data->wd_SleepMinWidth,
3282 data->wd_SleepMinHeight,
3283 data->wd_SleepMaxWidth,
3284 data->wd_SleepMaxHeight);
3285 data->wd_SleepMinHeight=0;
3286 data->wd_SleepMaxHeight=0;
3287 data->wd_SleepMinWidth=0;
3288 data->wd_SleepMaxWidth=0;
3292 break;
3297 return DoSuperMethodA(cl, obj, (Msg) msg);
3300 /**************************************************************************
3301 OM_GET
3302 **************************************************************************/
3303 IPTR Window__OM_GET(struct IClass *cl, Object *obj, struct opGet *msg)
3305 #define STORE *(msg->opg_Storage)
3307 struct MUI_WindowData *data = INST_DATA(cl, obj);
3309 STORE = (IPTR) 0;
3311 switch (msg->opg_AttrID)
3313 case MUIA_Window_Activate:
3314 STORE =
3315 (data->wd_Flags & (MUIWF_ACTIVE | MUIWF_OPENED)) ==
3316 (MUIWF_ACTIVE | MUIWF_OPENED);
3317 return TRUE;
3319 case MUIA_Window_Window:
3320 STORE = (IPTR) data->wd_RenderInfo.mri_Window;
3321 return TRUE;
3323 case MUIA_Window_Screen:
3324 STORE = (IPTR) data->wd_RenderInfo.mri_Screen;
3325 return TRUE;
3327 case MUIA_Window_PublicScreen:
3328 STORE = (IPTR) data->wd_UserPublicScreen;
3329 return TRUE;
3331 case MUIA_Window_ActiveObject:
3332 if ((data->wd_ActiveObject != NULL)
3333 && (DoMethod(data->wd_RootObject, MUIM_FindAreaObject,
3334 (IPTR) data->wd_ActiveObject) != (IPTR) NULL))
3335 STORE = (IPTR) data->wd_ActiveObject;
3336 else
3337 STORE = (IPTR) NULL;
3338 return TRUE;
3340 case MUIA_Window_CloseRequest:
3341 STORE = FALSE;
3342 return TRUE;
3344 case MUIA_Window_DefaultObject:
3345 STORE = (IPTR) data->wd_DefaultObject;
3346 return TRUE;
3348 case MUIA_Window_DisableKeys:
3349 STORE = data->wd_DisabledKeys;
3350 return TRUE;
3352 case MUIA_Window_Height:
3353 if (data->wd_RenderInfo.mri_Window != NULL)
3354 STORE = (IPTR) data->wd_RenderInfo.mri_Window->GZZHeight;
3355 else
3356 STORE = 0;
3357 return TRUE;
3359 case MUIA_Window_ID:
3360 STORE = data->wd_ID;
3361 return TRUE;
3363 case MUIA_Window_IsSubWindow:
3364 STORE = (data->wd_Flags & MUIWF_ISSUBWINDOW) == MUIWF_ISSUBWINDOW;
3365 return TRUE;
3367 case MUIA_Window_LeftEdge:
3368 if (data->wd_RenderInfo.mri_Window)
3369 STORE = (IPTR) data->wd_RenderInfo.mri_Window->LeftEdge;
3370 else
3371 STORE = 0;
3372 return TRUE;
3374 case MUIA_Window_Open:
3375 STORE = (data->wd_Flags & MUIWF_OPENED) == MUIWF_OPENED;
3376 return TRUE;
3378 case MUIA_Window_RootObject:
3379 STORE = (IPTR) data->wd_RootObject;
3380 return TRUE;
3382 case MUIA_Window_ScreenTitle:
3383 STORE = (IPTR) data->wd_ScreenTitle;
3384 return TRUE;
3386 case MUIA_Window_Title:
3387 STORE = (IPTR) data->wd_Title;
3388 return TRUE;
3390 case MUIA_Window_TopEdge:
3391 if (data->wd_RenderInfo.mri_Window)
3392 STORE = (IPTR) data->wd_RenderInfo.mri_Window->TopEdge;
3393 else
3394 STORE = (IPTR) 0;
3395 return (TRUE);
3397 case MUIA_Window_Width:
3398 if (data->wd_RenderInfo.mri_Window != NULL)
3399 STORE = (IPTR) data->wd_RenderInfo.mri_Window->GZZWidth;
3400 else
3401 STORE = 0;
3402 return TRUE;
3404 case MUIA_Window_Menustrip:
3405 STORE = (IPTR) data->wd_ChildMenustrip;
3406 return TRUE;
3408 case MUIA_Window_Sleep:
3409 STORE = data->wd_SleepCount ? TRUE : FALSE;
3410 return TRUE;
3412 case MUIA_Version:
3413 STORE = __version;
3414 return TRUE;
3416 case MUIA_Revision:
3417 STORE = __revision;
3418 return TRUE;
3420 case MUIA_Window_AltLeftEdge:
3421 STORE = (IPTR) data->wd_AltDim.Left;
3422 return TRUE;
3424 case MUIA_Window_AltTopEdge:
3425 STORE = (IPTR) data->wd_AltDim.Top;
3426 return TRUE;
3428 case MUIA_Window_AltWidth:
3429 STORE = (IPTR) data->wd_AltDim.Width;
3430 return TRUE;
3432 case MUIA_Window_AltHeight:
3433 STORE = (IPTR) data->wd_AltDim.Height;
3434 return TRUE;
3437 return DoSuperMethodA(cl, obj, (Msg) msg);
3438 #undef STORE
3442 * MUIM_FindUData : tests if the MUIA_UserData of the object
3443 * contains the given <udata> and returns the object pointer in this case.
3445 IPTR Window__MUIM_FindUData(struct IClass *cl, Object *obj,
3446 struct MUIP_FindUData *msg)
3448 struct MUI_WindowData *data = INST_DATA(cl, obj);
3450 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
3451 return (IPTR) obj;
3453 if (data->wd_RootObject)
3454 return DoMethodA(data->wd_RootObject, (Msg) msg);
3456 return 0;
3461 * MUIM_GetUData : This method tests if the MUIA_UserData of the object
3462 * contains the given <udata> and gets <attr> to <storage> for itself
3463 * in this case.
3465 IPTR Window__MUIM_GetUData(struct IClass *cl, Object *obj,
3466 struct MUIP_GetUData *msg)
3468 struct MUI_WindowData *data = INST_DATA(cl, obj);
3470 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
3472 get(obj, msg->attr, msg->storage);
3473 return TRUE;
3476 if (data->wd_RootObject)
3477 return DoMethodA(data->wd_RootObject, (Msg) msg);
3479 return FALSE;
3484 * MUIM_SetUData : This method tests if the MUIA_UserData of the object
3485 * contains the given <udata> and sets <attr> to <val> for itself in this case.
3487 IPTR Window__MUIM_SetUData(struct IClass *cl, Object *obj,
3488 struct MUIP_SetUData *msg)
3490 struct MUI_WindowData *data = INST_DATA(cl, obj);
3492 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
3493 set(obj, msg->attr, msg->val);
3495 if (data->wd_RootObject)
3496 DoMethodA(data->wd_RootObject, (Msg) msg);
3498 return TRUE;
3503 * MUIM_SetUDataOnce : This method tests if the MUIA_UserData of the object
3504 * contains the given <udata> and sets <attr> to <val> for itself in this case.
3506 IPTR Window__MUIM_SetUDataOnce(struct IClass *cl, Object *obj,
3507 struct MUIP_SetUDataOnce *msg)
3509 struct MUI_WindowData *data = INST_DATA(cl, obj);
3511 if (muiNotifyData(obj)->mnd_UserData == msg->udata)
3513 set(obj, msg->attr, msg->val);
3514 return TRUE;
3517 if (data->wd_RootObject)
3518 return DoMethodA(data->wd_RootObject, (Msg) msg);
3520 return FALSE;
3523 /**************************************************************************
3524 Called by Application (parent) object whenever this object is added.
3525 init GlobalInfo
3526 **************************************************************************/
3527 IPTR Window__MUIM_ConnectParent(struct IClass *cl, Object *obj,
3528 struct MUIP_ConnectParent *msg)
3530 struct MUI_WindowData *data = INST_DATA(cl, obj);
3532 if (!DoSuperMethodA(cl, obj, (Msg) msg))
3533 return 0;
3535 if (data->wd_RootObject)
3536 DoMethod(data->wd_RootObject, MUIM_ConnectParent, (IPTR) obj);
3538 if (data->wd_ChildMenustrip)
3539 DoMethod(data->wd_ChildMenustrip, MUIM_ConnectParent, (IPTR) obj);
3541 return TRUE;
3545 /**************************************************************************
3546 called by parent object
3547 **************************************************************************/
3548 IPTR Window__MUIM_DisconnectParent(struct IClass *cl, Object *obj,
3549 struct MUIP_DisconnectParent *msg)
3551 struct MUI_WindowData *data = INST_DATA(cl, obj);
3553 /* D(bug("Window_DisconnectParent(%p) : muiGlobalInfo=%p\n", */
3554 /* muiGlobalInfo(obj))); */
3555 if (muiGlobalInfo(obj))
3557 /* Close the window before disconnecting all the childs */
3558 if ((data->wd_Flags & MUIWF_OPENED))
3560 /* D(bug(" Window_DisconnectParent(%p) : closing window\n", */
3561 /* muiGlobalInfo(obj))); */
3562 set(obj, MUIA_Window_Open, FALSE);
3564 if (data->wd_ChildMenustrip)
3565 DoMethod(data->wd_ChildMenustrip, MUIM_DisconnectParent,
3566 (IPTR) obj);
3568 if (data->wd_RootObject)
3569 DoMethodA(data->wd_RootObject, (Msg) msg);
3571 /* D(bug(" Window_DisconnectParent(%p) : calling supermethod\n", */
3572 /* muiGlobalInfo(obj))); */
3573 return DoSuperMethodA(cl, obj, (Msg) msg);
3575 else
3577 return 0;
3581 static void SetRootObjInnerSpacing(Object *obj,
3582 struct MUI_WindowData *data)
3584 UWORD wd_innerLeft, wd_innerRight, wd_innerTop, wd_innerBottom;
3586 if (data->wd_CrtFlags & WFLG_BORDERLESS)
3588 wd_innerLeft = 0;
3589 wd_innerRight = 0;
3590 wd_innerTop = 0;
3591 wd_innerBottom = 0;
3593 else
3595 wd_innerLeft = muiGlobalInfo(obj)->mgi_Prefs->window_inner_left;
3596 wd_innerRight = muiGlobalInfo(obj)->mgi_Prefs->window_inner_right;
3597 wd_innerTop = muiGlobalInfo(obj)->mgi_Prefs->window_inner_top;
3598 wd_innerBottom = muiGlobalInfo(obj)->mgi_Prefs->window_inner_bottom;
3601 if (!(muiAreaData(data->wd_RootObject)->mad_Flags & MADF_INNERLEFT))
3603 muiAreaData(data->wd_RootObject)->mad_InnerLeft = wd_innerLeft;
3606 if (!(muiAreaData(data->wd_RootObject)->mad_Flags & MADF_INNERTOP))
3608 muiAreaData(data->wd_RootObject)->mad_InnerTop = wd_innerTop;
3611 if (!(muiAreaData(data->wd_RootObject)->mad_Flags & MADF_INNERRIGHT))
3613 muiAreaData(data->wd_RootObject)->mad_InnerRight = wd_innerRight;
3616 if (!(muiAreaData(data->wd_RootObject)->mad_Flags & MADF_INNERBOTTOM))
3618 muiAreaData(data->wd_RootObject)->mad_InnerBottom = wd_innerBottom;
3623 * Called before window is opened or resized. It determines its bounds,
3624 * so you can call WindowSelectDimensions() to find the final dims.
3626 static void WindowMinMax(Object *obj, struct MUI_WindowData *data)
3628 SetRootObjInnerSpacing(obj, data);
3629 /* inquire about sizes */
3630 DoMethod(data->wd_RootObject, MUIM_AskMinMax, (IPTR) & data->wd_MinMax);
3631 /* D(bug("*** root minmax = %ld,%ld => %ld,%ld\n", */
3632 /* data->wd_MinMax.MinWidth, */
3633 /* data->wd_MinMax.MinHeight, */
3634 /* data->wd_MinMax.MaxWidth, data->wd_MinMax.MaxHeight)); */
3635 __area_finish_minmax(data->wd_RootObject, &data->wd_MinMax);
3636 /* D(bug("*** root minmax2 = %ld,%ld => %ld,%ld\n", */
3637 /* data->wd_MinMax.MinWidth, */
3638 /* data->wd_MinMax.MinHeight, */
3639 /* data->wd_MinMax.MaxWidth, data->wd_MinMax.MaxHeight)); */
3643 static void InstallBackbuffer(struct IClass *cl, Object *obj)
3645 struct MUI_WindowData *data = INST_DATA(cl, obj);
3646 #if 0
3647 struct Window *win = data->wd_RenderInfo.mri_Window;
3649 data->wd_RenderInfo.mri_BufferBM =
3650 AllocBitMap(win->Width, win->Height, win->RPort->BitMap->Depth,
3651 0, win->RPort->BitMap);
3652 #endif
3653 if (data->wd_RenderInfo.mri_BufferBM)
3655 /* D(bug("install_backbuffer : allocated bitmap %dx%dx%d " */
3656 /* "with friend %p\n", */
3657 /* win->Width, win->Height, win->RPort->BitMap->Depth, */
3658 /* win->RPort->BitMap)); */
3659 InitRastPort(&data->wd_RenderInfo.mri_BufferRP);
3660 data->wd_RenderInfo.mri_BufferRP.BitMap =
3661 data->wd_RenderInfo.mri_BufferBM;
3665 static void DeinstallBackbuffer(struct IClass *cl, Object *obj)
3667 struct MUI_WindowData *data = INST_DATA(cl, obj);
3669 if (data->wd_RenderInfo.mri_BufferBM)
3671 DeinitRastPort(&data->wd_RenderInfo.mri_BufferRP);
3672 FreeBitMap(data->wd_RenderInfo.mri_BufferBM);
3673 data->wd_RenderInfo.mri_BufferBM = NULL;
3678 * Called after window is opened or resized.
3679 * An expose event is already queued, it will trigger
3680 * MUIM_Draw for us when going back to main loop.
3682 static void WindowShow(struct IClass *cl, Object *obj)
3684 struct MUI_WindowData *data = INST_DATA(cl, obj);
3685 struct Window *win = data->wd_RenderInfo.mri_Window;
3686 /* D(bug("WindowShow %s %d\n", __FILE__, __LINE__)); */
3688 _left(data->wd_RootObject) = win->BorderLeft;
3689 _top(data->wd_RootObject) = win->BorderTop;
3690 _width(data->wd_RootObject) = data->wd_Width;
3691 _height(data->wd_RootObject) = data->wd_Height;
3693 DoMethod(data->wd_RootObject, MUIM_Layout);
3695 ShowRenderInfo(&data->wd_RenderInfo);
3696 /* D(bug("zune_imspec_show %s %d\n", __FILE__, __LINE__)); */
3697 zune_imspec_show(data->wd_Background, obj);
3698 DoShowMethod(data->wd_RootObject);
3701 static ULONG WindowOpen(struct IClass *cl, Object *obj)
3703 struct MUI_WindowData *data = INST_DATA(cl, obj);
3705 if (!data->wd_RootObject)
3706 return FALSE;
3708 if (!DoMethod(obj, MUIM_Window_Setup))
3709 return FALSE;
3711 /* I got display info, so calculate your display dependant data */
3712 if (!DoSetupMethod(data->wd_RootObject, &data->wd_RenderInfo))
3714 DoMethod(obj, MUIM_Window_Cleanup);
3715 return FALSE;
3718 /* inquire about sizes */
3719 WindowMinMax(obj, data);
3720 WindowSelectDimensions(data);
3722 /* Decide which menustrip should be used */
3723 if (!data->wd_ChildMenustrip)
3724 get(_app(obj), MUIA_Application_Menustrip, &data->wd_Menustrip);
3725 else
3726 data->wd_Menustrip = data->wd_ChildMenustrip;
3728 /* open window here ... */
3729 if (!DisplayWindow(obj, data))
3731 /* free display dependant data */
3732 data->wd_Menustrip = NULL;
3733 DoMethod(data->wd_RootObject, MUIM_Cleanup);
3734 DoMethod(obj, MUIM_Window_Cleanup);
3735 return FALSE;
3738 InstallBackbuffer(cl, obj);
3740 data->wd_Flags |= MUIWF_OPENED;
3742 WindowShow(cl, obj);
3745 LONG left, top, width, height;
3747 left = data->wd_RenderInfo.mri_Window->BorderLeft;
3748 top = data->wd_RenderInfo.mri_Window->BorderTop,
3749 width = data->wd_RenderInfo.mri_Window->Width
3750 - data->wd_RenderInfo.mri_Window->BorderRight - left;
3751 height = data->wd_RenderInfo.mri_Window->Height
3752 - data->wd_RenderInfo.mri_Window->BorderBottom - top;
3754 /* D(bug("zune_imspec_draw %s %d\n", __FILE__, __LINE__)); */
3755 // D(bug("%d:zune_imspec_draw(%p) l=%d t=%d w=%d h=%d xo=%d yo=%d\n",
3756 // __LINE__, data->wd_Background, left, top, width,
3757 // height, left, top));
3759 zune_imspec_draw(data->wd_Background, &data->wd_RenderInfo,
3760 left, top, width, height, left, top, 0);
3763 MUI_Redraw(data->wd_RootObject, MADF_DRAWOBJECT);
3765 D(bug("MUIC_Window:windowOpen() ActiveObject=%p\n",
3766 data->wd_ActiveObject));
3767 if (data->wd_OldActive != NULL)
3769 set(obj, MUIA_Window_ActiveObject, data->wd_OldActive);
3772 return TRUE;
3775 /**************************************************************************/
3776 /**************************************************************************/
3778 static ULONG WindowClose(struct IClass *cl, Object *obj)
3780 struct MUI_WindowData *data = INST_DATA(cl, obj);
3782 if (data->wd_ActiveObject != NULL)
3784 data->wd_OldActive = data->wd_ActiveObject;
3785 set(obj, MUIA_Window_ActiveObject, MUIV_Window_ActiveObject_None);
3788 KillHelpBubble(data, obj, BUBBLEHELP_TICKER_FIRST);
3790 /* remove from window */
3791 DoHideMethod(data->wd_RootObject);
3792 zune_imspec_hide(data->wd_Background);
3794 DeinstallBackbuffer(cl, obj);
3796 HideRenderInfo(&data->wd_RenderInfo);
3798 /* close here ... */
3799 UndisplayWindow(obj, data);
3801 data->wd_Flags &= ~MUIWF_OPENED;
3802 data->wd_Menustrip = NULL;
3804 /* free display dependant data */
3805 DoMethod(data->wd_RootObject, MUIM_Cleanup);
3806 DoMethod(obj, MUIM_Window_Cleanup);
3807 return TRUE;
3810 /* calculate a new layout
3811 * see MUIA_ShowMe
3812 * see Group_ExitChange
3813 * see Group_Columns
3814 * see Group_Rows
3816 IPTR Window__MUIM_RecalcDisplay(struct IClass *cl, Object *obj,
3817 struct MUIP_Window_RecalcDisplay *msg)
3819 struct MUI_WindowData *data = INST_DATA(cl, obj);
3820 LONG left, top, width, height;
3821 BOOL resized, reshow = FALSE;
3822 Object *current_obj;
3824 if (!(data->wd_Flags & MUIWF_OPENED))
3825 return 0;
3827 current_obj = msg->originator;
3829 // typically originator is a group which has been added/removed a child
3830 // calculate minmax of current obj
3831 // if new minmax can accomodate current obj size, stop
3832 // else try with its parent
3833 // the resulting object will get a new layout
3834 // it currently produces some redundant AskMinMax but allows
3835 // to not always relayout the whole window
3837 D(bug("RecalcDisplay on %p\n", current_obj));
3838 while (current_obj != NULL)
3840 DoMethod(current_obj, MUIM_AskMinMax,
3841 (IPTR) & muiAreaData(current_obj)->mad_MinMax);
3842 __area_finish_minmax(current_obj,
3843 &muiAreaData(current_obj)->mad_MinMax);
3845 D(bug("size w = %d, h = %d\n", _width(current_obj),
3846 _height(current_obj)));
3847 D(bug("new w = %d-%d, h = %d-%d\n", _minwidth(current_obj),
3848 _maxwidth(current_obj), _minheight(current_obj),
3849 _maxheight(current_obj)));
3851 if (!_between(_minwidth(current_obj), _width(current_obj),
3852 _maxwidth(current_obj))
3853 || !_between(_minheight(current_obj), _height(current_obj),
3854 _maxheight(current_obj)))
3856 current_obj = _parent(current_obj);
3857 D(bug("RecalcDisplay, try parent %p\n", current_obj));
3859 else
3861 D(bug("found it\n"));
3862 break;
3866 if (!current_obj)
3867 current_obj = data->wd_RootObject;
3869 WindowMinMax(obj, data);
3871 /* Important: current_obj could be hidden, like in an inactive page! */
3872 if (_flags(current_obj) & MADF_CANDRAW)
3874 reshow = TRUE;
3877 if (reshow)
3878 DoHideMethod(current_obj);
3880 /* resize window ? */
3881 WindowSelectDimensions(data);
3882 resized = WindowResize(data);
3884 if (!resized)
3886 /* FIXME: Should we short circuit the following
3887 * if the window size didn't change?
3892 struct Window *win = data->wd_RenderInfo.mri_Window;
3893 _left(data->wd_RootObject) = win->BorderLeft;
3894 _top(data->wd_RootObject) = win->BorderTop;
3895 _width(data->wd_RootObject) = data->wd_Width;
3896 _height(data->wd_RootObject) = data->wd_Height;
3898 DoMethod(current_obj, MUIM_Layout);
3900 if (reshow)
3901 DoShowMethod(current_obj);
3903 if (muiGlobalInfo(obj)->mgi_Prefs->window_redraw ==
3904 WINDOW_REDRAW_WITHOUT_CLEAR)
3906 if (reshow)
3907 MUI_Redraw(current_obj, MADF_DRAWOBJECT);
3909 else
3911 left = data->wd_RenderInfo.mri_Window->BorderLeft;
3912 top = data->wd_RenderInfo.mri_Window->BorderTop;
3913 width = data->wd_RenderInfo.mri_Window->Width
3914 - data->wd_RenderInfo.mri_Window->BorderRight - left;
3915 height = data->wd_RenderInfo.mri_Window->Height
3916 - data->wd_RenderInfo.mri_Window->BorderBottom - top;
3918 zune_imspec_draw(data->wd_Background, &data->wd_RenderInfo,
3919 left, top, width, height, left, top, 0);
3920 MUI_Redraw(data->wd_RootObject, MADF_DRAWALL);
3923 ActivateObject(data);
3925 return TRUE;
3929 /**************************************************************************
3930 MUIM_AddEventHandler
3931 **************************************************************************/
3932 IPTR Window__MUIM_AddEventHandler(struct IClass *cl, Object *obj,
3933 struct MUIP_Window_AddEventHandler *msg)
3935 struct MUI_WindowData *data = INST_DATA(cl, obj);
3937 //D(bug("muimaster.library/window.c: Add Eventhandler %p\n", msg->ehnode));
3939 msg->ehnode->ehn_Priority = msg->ehnode->ehn_Priority;
3940 EnqueueByPriAndAddress((struct List *)&data->wd_EHList,
3941 (struct Node *)msg->ehnode);
3942 ChangeEvents(data, GetDefaultEvents());
3943 return TRUE;
3946 /**************************************************************************
3947 MUIM_RemEventHandler
3948 **************************************************************************/
3949 IPTR Window__MUIM_RemEventHandler(struct IClass *cl, Object *obj,
3950 struct MUIP_Window_RemEventHandler *msg)
3952 struct MUI_WindowData *data = INST_DATA(cl, obj);
3954 //D(bug("muimaster.library/window.c: Rem Eventhandler %p\n", msg->ehnode));
3956 Remove((struct Node *)msg->ehnode);
3957 ChangeEvents(data, GetDefaultEvents());
3958 return TRUE;
3961 /**************************************************************************
3962 Note that this is MUIM_Window_Setup, not MUIM_Setup
3963 **************************************************************************/
3964 IPTR Window__MUIM_Setup(struct IClass *cl, Object *obj, Msg msg)
3966 struct MUI_WindowData *data = INST_DATA(cl, obj);
3968 if (!SetupRenderInfo(obj, data, &data->wd_RenderInfo))
3969 return FALSE;
3971 data->wd_Background =
3972 zune_imspec_setup(MUII_WindowBack, &data->wd_RenderInfo);
3974 if (muiGlobalInfo(obj)->mgi_Prefs->window_redraw ==
3975 WINDOW_REDRAW_WITH_CLEAR)
3976 data->wd_Flags |= MUIWF_ERASEAREA;
3978 return TRUE;
3981 /**************************************************************************
3982 MUIM_Cleanup
3983 **************************************************************************/
3984 IPTR Window__MUIM_Cleanup(struct IClass *cl, Object *obj, Msg msg)
3986 struct MUI_WindowData *data = INST_DATA(cl, obj);
3988 zune_imspec_cleanup(data->wd_Background);
3990 if (data->wd_dnd)
3992 DeleteDragNDrop(data->wd_dnd);
3993 data->wd_dnd = NULL;
3996 CleanupRenderInfo(obj, data, &data->wd_RenderInfo);
3997 return TRUE;
4001 /**************************************************************************
4002 This adds the the control char handler and also does the MUIA_CycleChain
4003 stuff. Orginal MUI does this another way.
4004 **************************************************************************/
4005 IPTR Window__MUIM_AddControlCharHandler(struct IClass *cl, Object *obj,
4006 struct MUIP_Window_AddControlCharHandler *msg)
4008 struct MUI_WindowData *data = INST_DATA(cl, obj);
4009 struct ObjNode *node;
4011 if (msg->ccnode->ehn_Events)
4013 msg->ccnode->ehn_Priority = msg->ccnode->ehn_Priority;
4014 Enqueue((struct List *)&data->wd_CCList,
4015 (struct Node *)msg->ccnode);
4017 /* Due to the lack of a better idea ... */
4018 if (muiAreaData(msg->ccnode->ehn_Object)->mad_Flags & MADF_CYCLECHAIN)
4020 node = AllocPooled(data->wd_MemoryPool, sizeof(struct ObjNode));
4021 if (node)
4023 node->obj = msg->ccnode->ehn_Object;
4024 AddTail((struct List *)&data->wd_CycleChain,
4025 (struct Node *)node);
4028 return TRUE;
4031 /**************************************************************************
4032 MUIM_RemControlCharHandler
4033 **************************************************************************/
4034 IPTR Window__MUIM_RemControlCharHandler(struct IClass *cl, Object *obj,
4035 struct MUIP_Window_RemControlCharHandler *msg)
4037 struct MUI_WindowData *data = INST_DATA(cl, obj);
4038 struct ObjNode *node =
4039 FindObjNode(&data->wd_CycleChain, msg->ccnode->ehn_Object);
4041 if (msg->ccnode->ehn_Events)
4042 Remove((struct Node *)msg->ccnode);
4044 if (node)
4046 /* Remove from the chain list */
4047 Remove((struct Node *)node);
4048 FreePooled(data->wd_MemoryPool, node, sizeof(struct ObjNode));
4051 return TRUE;
4054 /**************************************************************************
4055 MUIM_DragObject
4056 **************************************************************************/
4057 IPTR Window__MUIM_DragObject(struct IClass *cl, Object *obj,
4058 struct MUIP_Window_DragObject *msg)
4060 struct MUI_WindowData *data = INST_DATA(cl, obj);
4061 if (msg->obj)
4063 struct DragNDrop *dnd;
4064 struct MUI_DragImage *di;
4065 struct BitMapNode *bmn;
4067 if (!(dnd = CreateDragNDropA(NULL)))
4068 return 0;
4070 if (!(di =
4071 (struct MUI_DragImage *)DoMethod(msg->obj,
4072 MUIM_CreateDragImage, -msg->touchx, -msg->touchy,
4073 msg->flags)))
4075 DeleteDragNDrop(dnd);
4076 return 0;
4078 if (!di->bm)
4080 DoMethod(msg->obj, MUIM_DeleteDragImage, (IPTR) di);
4081 DeleteDragNDrop(dnd);
4082 return 0;
4085 if (!(bmn = CreateBitMapNodeA(TAGLIST(
4086 GUI_BitMap, (IPTR)di->bm,
4087 GUI_LeftOffset, di->touchx,
4088 GUI_TopOffset, di->touchy,
4089 GUI_Width, di->width,
4090 GUI_Height, di->height,
4091 GUI_SourceAlpha, !!(di->flags & MUIF_DRAGIMAGE_SOURCEALPHA)))))
4093 DoMethod(msg->obj, MUIM_DeleteDragImage, (IPTR) di);
4094 DeleteDragNDrop(dnd);
4095 return 0;
4098 AttachBitMapNode(dnd, bmn);
4100 if (!PrepareDragNDrop(dnd, data->wd_RenderInfo.mri_Screen))
4102 DoMethod(msg->obj, MUIM_DeleteDragImage, (IPTR) di);
4103 DeleteDragNDrop(dnd);
4104 return 0;
4107 muiAreaData(msg->obj)->mad_Flags |= MADF_DRAGGING;
4109 data->wd_DragObject = msg->obj;
4110 data->wd_dnd = dnd;
4111 data->wd_DragImage = di;
4112 return 1;
4114 return 0;
4117 /**************************************************************************
4118 MUIM_AllocGadgetID
4119 **************************************************************************/
4120 IPTR Window__MUIM_AllocGadgetID(struct IClass *cl, Object *obj,
4121 struct MUIP_Window_AllocGadgetID *msg)
4123 struct MUI_WindowData *data = INST_DATA(cl, obj);
4124 struct IDNode *newnode;
4126 newnode = AllocPooled(data->wd_MemoryPool, sizeof(struct IDNode));
4127 if (newnode)
4129 int id;
4130 struct MinNode *mn;
4132 if (IsListEmpty(&data->wd_IDList))
4134 newnode->id = 1;
4135 AddHead((struct List *)&data->wd_IDList,
4136 (struct Node *)&newnode->node);
4137 return (IPTR) 1;
4140 id = 1;
4142 for (mn = data->wd_IDList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
4144 struct IDNode *idn = (struct IDNode *)mn;
4145 if (id < idn->id)
4146 break;
4147 id++;
4149 newnode->id = id;
4150 Insert((struct List *)&data->wd_IDList,
4151 (struct Node *)&newnode->node, (struct Node *)mn);
4152 return (IPTR) id;
4155 return 0;
4158 /**************************************************************************
4159 MUIM_FreeGadgetID
4160 **************************************************************************/
4161 IPTR Window__MUIM_FreeGadgetID(struct IClass *cl, Object *obj,
4162 struct MUIP_Window_FreeGadgetID *msg)
4164 struct MUI_WindowData *data = INST_DATA(cl, obj);
4165 struct MinNode *mn;
4167 for (mn = data->wd_IDList.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
4169 struct IDNode *idn = (struct IDNode *)mn;
4170 if (msg->gadgetid == idn->id)
4172 Remove((struct Node *)idn);
4173 FreePooled(data->wd_MemoryPool, idn, sizeof(struct IDNode));
4174 return 0;
4178 return 0;
4182 /**************************************************************************
4183 MUIM_Window_GetMenuCheck
4184 **************************************************************************/
4185 IPTR Window__MUIM_GetMenuCheck(struct IClass *cl, Object *obj,
4186 struct MUIP_Window_GetMenuCheck *msg)
4188 IPTR stat = 0;
4189 struct MUI_WindowData *data = INST_DATA(cl, obj);
4190 Object *item;
4191 Object *strip = data->wd_ChildMenustrip;
4192 if (!strip)
4193 strip = data->wd_Menustrip;
4194 if (!strip)
4195 return 0;
4196 if (!(item = (Object *) DoMethod(strip, MUIM_FindUData, msg->MenuID)))
4197 return 0;
4198 get(item, MUIA_Menuitem_Checked, &stat);
4199 return stat;
4202 /**************************************************************************
4203 MUIM_Window_SetMenuCheck
4204 **************************************************************************/
4205 IPTR Window__MUIM_SetMenuCheck(struct IClass *cl, Object *obj,
4206 struct MUIP_Window_SetMenuCheck *msg)
4208 struct MUI_WindowData *data = INST_DATA(cl, obj);
4209 Object *item;
4210 Object *strip = data->wd_ChildMenustrip;
4211 if (!strip)
4212 strip = data->wd_Menustrip;
4213 if (!strip)
4214 return 0;
4215 if (!(item = (Object *) DoMethod(strip, MUIM_FindUData, msg->MenuID)))
4216 return 0;
4217 set(item, MUIA_Menuitem_Checked, msg->stat);
4218 return 0;
4221 /**************************************************************************
4222 MUIM_Window_GetMenuState
4223 **************************************************************************/
4224 IPTR Window__MUIM_GetMenuState(struct IClass *cl, Object *obj,
4225 struct MUIP_Window_GetMenuState *msg)
4227 IPTR stat = 0;
4228 struct MUI_WindowData *data = INST_DATA(cl, obj);
4229 Object *item;
4230 Object *strip = data->wd_ChildMenustrip;
4231 if (!strip)
4232 strip = data->wd_Menustrip;
4233 if (!strip)
4234 return 0;
4235 if (!(item = (Object *) DoMethod(strip, MUIM_FindUData, msg->MenuID)))
4236 return 0;
4237 get(item, MUIA_Menuitem_Enabled, &stat);
4238 return stat;
4241 /**************************************************************************
4242 MUIM_Window_SetMenuState
4243 **************************************************************************/
4244 IPTR Window__MUIM_SetMenuState(struct IClass *cl, Object *obj,
4245 struct MUIP_Window_SetMenuState *msg)
4247 struct MUI_WindowData *data = INST_DATA(cl, obj);
4248 Object *item;
4249 Object *strip = data->wd_ChildMenustrip;
4250 if (!strip)
4251 strip = data->wd_Menustrip;
4252 if (!strip)
4253 return 0;
4254 if (!(item = (Object *) DoMethod(strip, MUIM_FindUData, msg->MenuID)))
4255 return 0;
4256 set(item, MUIA_Menuitem_Enabled, msg->stat);
4257 return 0;
4260 /**************************************************************************
4261 MUIM_Window_DrawBackground
4262 **************************************************************************/
4263 IPTR Window__MUIM_DrawBackground(struct IClass *cl, Object *obj,
4264 struct MUIP_Window_DrawBackground *msg)
4266 struct MUI_WindowData *data = INST_DATA(cl, obj);
4267 if (!(data->wd_RenderInfo.mri_Window)) /* not between show/hide */
4268 return FALSE;
4270 // D(bug("%d:zune_imspec_draw(%p) l=%d t=%d w=%d h=%d xo=%d yo=%d\n",
4271 // __LINE__, data->wd_Background, msg->left, msg->top, msg->width,
4272 // msg->height, msg->xoffset, msg->yoffset));
4273 zune_imspec_draw(data->wd_Background, &data->wd_RenderInfo,
4274 msg->left, msg->top, msg->width, msg->height,
4275 msg->xoffset, msg->yoffset, 0);
4276 return 0;
4279 /**************************************************************************
4280 MUIM_Window_ToFront
4281 **************************************************************************/
4282 IPTR Window__MUIM_ToFront(struct IClass *cl, Object *obj, Msg msg)
4284 struct MUI_WindowData *data = INST_DATA(cl, obj);
4285 if (!(data->wd_RenderInfo.mri_Window)) /* not between show/hide */
4286 return 0;
4288 WindowToFront(data->wd_RenderInfo.mri_Window);
4289 return 1;
4292 /**************************************************************************
4293 MUIM_Window_ToBack
4294 **************************************************************************/
4295 IPTR Window__MUIM_ToBack(struct IClass *cl, Object *obj, Msg msg)
4297 struct MUI_WindowData *data = INST_DATA(cl, obj);
4298 if (!(data->wd_RenderInfo.mri_Window)) /* not between show/hide */
4299 return 0;
4301 WindowToBack(data->wd_RenderInfo.mri_Window);
4302 return 1;
4305 /**************************************************************************
4306 MUIM_Window_ScreenToBack
4307 **************************************************************************/
4308 IPTR Window__MUIM_ScreenToBack(struct IClass *cl, Object *obj, Msg msg)
4310 struct MUI_WindowData *data = INST_DATA(cl, obj);
4311 if (!(data->wd_RenderInfo.mri_Window)) /* not between show/hide */
4312 return 0;
4314 ScreenToBack(data->wd_RenderInfo.mri_Screen);
4315 return 1;
4318 /**************************************************************************
4319 MUIM_Window_ScreenToFront
4320 **************************************************************************/
4321 IPTR Window__MUIM_ScreenToFront(struct IClass *cl, Object *obj, Msg msg)
4323 struct MUI_WindowData *data = INST_DATA(cl, obj);
4324 if (!(data->wd_RenderInfo.mri_Window)) /* not between show/hide */
4325 return 0;
4327 ScreenToFront(data->wd_RenderInfo.mri_Screen);
4328 return 1;
4331 /**************************************************************************
4332 MUIM_Window_ActionIconify
4333 **************************************************************************/
4334 IPTR Window__MUIM_ActionIconify(struct IClass *cl, Object *obj, Msg msg)
4336 set(_app(obj), MUIA_Application_Iconified, TRUE);
4338 return TRUE;
4342 /* Loads ENV: prefs, add a Window_ID chunk in the MUIW chunk, if no MUIW chunk
4343 * then create it at the same level as MUIC chunk, save prefs.
4344 * Do the same for ENVARC:
4345 * MUIW chunk layout:
4346 * 'MUIW'
4347 * 00 00 00 30 (chunk length for a single window, 0x30L big endian)
4348 * 'this window ID'
4349 * 00 00 00 28
4350 * xx xx yy yy (X, Y)
4351 * ww ww hh hh (Width, Height)
4352 * ax ax ay ay (AltX, AltY)
4353 * aw aw ah ah (AltWidth, AltHeight)
4354 * 00 00 00 00 (???)
4355 * 00 00 00 00
4356 * 00 00 00 00
4357 * 00 00 00 00
4358 * 00 01 00 00
4359 * 00 00 00 00
4361 static void RememberWindowPosition(Object *winobj, ULONG id)
4363 if (!id)
4364 return;
4367 /* Loads ENV: prefs, remove our Window_ID chunk from the MUIW chunk,
4368 * save prefs.
4369 * Do the same for ENVARC:
4370 * This function shouldn't really be in window.c, but rather in a file dealing
4371 * with prefs file stuff.
4373 static void ForgetWindowPosition(Object *winobj, ULONG id)
4375 if (!id)
4376 return;
4379 /**************************************************************************
4380 MUIM_Window_Snapshot
4381 **************************************************************************/
4382 IPTR Window__MUIM_Snapshot(struct IClass *cl, Object *obj,
4383 struct MUIP_Window_Snapshot *msg)
4385 struct MUI_WindowData *data = INST_DATA(cl, obj);
4386 struct windowpos winp;
4387 struct Window *w;
4389 winp.id = data->wd_ID;
4390 w = data->wd_RenderInfo.mri_Window;
4391 if (w)
4393 winp.x1 = w->LeftEdge;
4394 winp.y1 = w->TopEdge;
4395 winp.w1 = w->GZZWidth;
4396 winp.h1 = w->GZZHeight;
4397 winp.x2 = 0;
4398 winp.x2 = 0;
4399 winp.w2 = 0;
4400 winp.h2 = 0; //to do save alt dims
4402 set(_app(obj), MUIA_Application_SetWinPos, &winp);
4405 if (msg->flags)
4406 RememberWindowPosition(obj, data->wd_ID);
4407 else
4408 ForgetWindowPosition(obj, data->wd_ID);
4409 return 1;
4412 /**************************************************************************
4413 MUIM_Window_UpdateMenu
4414 **************************************************************************/
4415 IPTR Window__MUIM_UpdateMenu(struct IClass *cl, Object *obj, Msg msg)
4417 struct MUI_WindowData *data = INST_DATA(cl, obj);
4419 struct Menu *menu = NULL;
4420 struct NewMenu *newmenu = NULL;
4421 APTR visinfo = NULL;
4422 struct Window *win = NULL;
4424 if (data->wd_Menustrip) // only open windows can have a menustrip
4426 if ((visinfo =
4427 GetVisualInfoA(data->wd_RenderInfo.mri_Screen, NULL)))
4429 win = data->wd_RenderInfo.mri_Window;
4430 ClearMenuStrip(win);
4431 if (data->wd_Menu)
4433 FreeMenus(data->wd_Menu);
4434 data->wd_Menu = NULL;
4437 get(data->wd_Menustrip, MUIA_Menuitem_NewMenu, &newmenu);
4438 if (newmenu)
4440 if ((menu = CreateMenusA(newmenu, NULL)))
4442 struct TagItem tags[] = {
4443 {GTMN_NewLookMenus, TRUE},
4444 {TAG_DONE, 0}
4446 LayoutMenusA(menu, visinfo, tags);
4447 data->wd_Menu = menu;
4448 SetMenuStrip(win, menu);
4451 FreeVisualInfo(visinfo);
4455 return 1;
4458 /**************************************************************************
4459 MUIM_Window_Refresh
4460 **************************************************************************/
4461 IPTR Window__MUIM_Refresh(struct IClass *cl, Object *obj, Msg msg)
4463 struct MUI_WindowData *data = INST_DATA(cl, obj);
4465 RefreshWindow(obj, data);
4467 return 1;
4470 /**************************************************************************
4471 MUIM_Export : to export an object's "contents" to a dataspace object.
4472 **************************************************************************/
4473 static IPTR Window__MUIM_Export(struct IClass *cl, Object *obj,
4474 struct MUIP_Export *msg)
4476 struct MUI_WindowData *data = INST_DATA(cl, obj);
4477 DoMethodA(data->wd_RootObject, (Msg) msg);
4478 return 0;
4482 /**************************************************************************
4483 MUIM_Import : to import an object's "contents" from a dataspace object.
4484 **************************************************************************/
4485 static IPTR Window__MUIM_Import(struct IClass *cl, Object *obj,
4486 struct MUIP_Import *msg)
4488 struct MUI_WindowData *data = INST_DATA(cl, obj);
4489 DoMethodA(data->wd_RootObject, (Msg) msg);
4490 return 0;
4493 BOOPSI_DISPATCHER(IPTR, Window_Dispatcher, cl, obj, msg)
4495 switch (msg->MethodID)
4497 case OM_NEW:
4498 return Window__OM_NEW(cl, obj, (struct opSet *)msg);
4499 case OM_DISPOSE:
4500 return Window__OM_DISPOSE(cl, obj, msg);
4501 case OM_SET:
4502 return Window__OM_SET(cl, obj, (struct opSet *)msg);
4503 case OM_GET:
4504 return Window__OM_GET(cl, obj, (struct opGet *)msg);
4505 case MUIM_FindUData:
4506 return Window__MUIM_FindUData(cl, obj,
4507 (struct MUIP_FindUData *)msg);
4508 case MUIM_GetUData:
4509 return Window__MUIM_GetUData(cl, obj, (struct MUIP_GetUData *)msg);
4510 case MUIM_SetUData:
4511 return Window__MUIM_SetUData(cl, obj, (struct MUIP_SetUData *)msg);
4512 case MUIM_SetUDataOnce:
4513 return Window__MUIM_SetUDataOnce(cl, obj,
4514 (struct MUIP_SetUDataOnce *)msg);
4515 case MUIM_Window_AddEventHandler:
4516 return Window__MUIM_AddEventHandler(cl, obj, (APTR) msg);
4517 case MUIM_Window_RemEventHandler:
4518 return Window__MUIM_RemEventHandler(cl, obj, (APTR) msg);
4519 case MUIM_ConnectParent:
4520 return Window__MUIM_ConnectParent(cl, obj, (APTR) msg);
4521 case MUIM_DisconnectParent:
4522 return Window__MUIM_DisconnectParent(cl, obj, (APTR) msg);
4523 case MUIM_Window_RecalcDisplay:
4524 return Window__MUIM_RecalcDisplay(cl, obj, (APTR) msg);
4525 case MUIM_Window_Setup:
4526 return Window__MUIM_Setup(cl, obj, (APTR) msg);
4527 case MUIM_Window_Cleanup:
4528 return Window__MUIM_Cleanup(cl, obj, (APTR) msg);
4529 case MUIM_Window_AddControlCharHandler:
4530 return Window__MUIM_AddControlCharHandler(cl, obj, (APTR) msg);
4531 case MUIM_Window_RemControlCharHandler:
4532 return Window__MUIM_RemControlCharHandler(cl, obj, (APTR) msg);
4533 case MUIM_Window_DragObject:
4534 return Window__MUIM_DragObject(cl, obj, (APTR) msg);
4535 case MUIM_Window_AllocGadgetID:
4536 return Window__MUIM_AllocGadgetID(cl, obj, (APTR) msg);
4537 case MUIM_Window_FreeGadgetID:
4538 return Window__MUIM_FreeGadgetID(cl, obj, (APTR) msg);
4539 case MUIM_Window_GetMenuCheck:
4540 return Window__MUIM_GetMenuCheck(cl, obj, (APTR) msg);
4541 case MUIM_Window_SetMenuCheck:
4542 return Window__MUIM_SetMenuCheck(cl, obj, (APTR) msg);
4543 case MUIM_Window_GetMenuState:
4544 return Window__MUIM_GetMenuState(cl, obj, (APTR) msg);
4545 case MUIM_Window_SetMenuState:
4546 return Window__MUIM_SetMenuState(cl, obj, (APTR) msg);
4547 case MUIM_Window_DrawBackground:
4548 return Window__MUIM_DrawBackground(cl, obj, (APTR) msg);
4549 case MUIM_Window_ToFront:
4550 return Window__MUIM_ToFront(cl, obj, (APTR) msg);
4551 case MUIM_Window_ToBack:
4552 return Window__MUIM_ToBack(cl, obj, (APTR) msg);
4553 case MUIM_Window_ScreenToFront:
4554 return Window__MUIM_ScreenToFront(cl, obj, (APTR) msg);
4555 case MUIM_Window_ScreenToBack:
4556 return Window__MUIM_ScreenToBack(cl, obj, (APTR) msg);
4557 case MUIM_Window_ActionIconify:
4558 return Window__MUIM_ActionIconify(cl, obj, (APTR) msg);
4559 case MUIM_Window_Snapshot:
4560 return Window__MUIM_Snapshot(cl, obj, (APTR) msg);
4561 case MUIM_Window_UpdateMenu:
4562 return Window__MUIM_UpdateMenu(cl, obj, (APTR) msg);
4563 case MUIM_Window_Refresh:
4564 return Window__MUIM_Refresh(cl, obj, (APTR) msg);
4565 case MUIM_Export:
4566 return Window__MUIM_Export(cl, obj, (APTR) msg);
4567 case MUIM_Import:
4568 return Window__MUIM_Import(cl, obj, (APTR) msg);
4571 return DoSuperMethodA(cl, obj, msg);
4573 BOOPSI_DISPATCHER_END
4576 * Class descriptor.
4578 const struct __MUIBuiltinClass _MUI_Window_desc =
4580 MUIC_Window,
4581 MUIC_Notify,
4582 sizeof(struct MUI_WindowData),
4583 (void *) Window_Dispatcher