Small fix to the mouse wheel code
[wmaker-crm.git] / WINGs / wpopupbutton.c
blobd09661b7e802c6dbab1027f1db2c316f4ea8b9ef
5 #include "WINGsP.h"
8 typedef struct W_PopUpButton {
9 W_Class widgetClass;
10 WMView *view;
12 void *clientData;
13 WMAction *action;
15 char *caption;
17 WMBag *items;
19 short selectedItemIndex;
21 short highlightedItem;
23 WMView *menuView; /* override redirect popup menu */
25 WMHandlerID timer; /* for autoscroll */
27 /**/
28 int scrollStartY; /* for autoscroll */
30 struct {
31 unsigned int pullsDown:1;
33 unsigned int configured:1;
35 unsigned int insideMenu:1;
37 unsigned int enabled:1;
39 } flags;
40 } PopUpButton;
43 #define MENU_BLINK_DELAY 60000
44 #define MENU_BLINK_COUNT 2
46 #define SCROLL_DELAY 10
49 #define DEFAULT_WIDTH 60
50 #define DEFAULT_HEIGHT 20
51 #define DEFAULT_CAPTION ""
54 static void destroyPopUpButton(PopUpButton *bPtr);
55 static void paintPopUpButton(PopUpButton *bPtr);
57 static void handleEvents(XEvent *event, void *data);
58 static void handleActionEvents(XEvent *event, void *data);
60 static void resizeMenu(PopUpButton *bPtr);
63 WMPopUpButton*
64 WMCreatePopUpButton(WMWidget *parent)
66 PopUpButton *bPtr;
67 W_Screen *scr = W_VIEW(parent)->screen;
70 bPtr = wmalloc(sizeof(PopUpButton));
71 memset(bPtr, 0, sizeof(PopUpButton));
73 bPtr->widgetClass = WC_PopUpButton;
75 bPtr->view = W_CreateView(W_VIEW(parent));
76 if (!bPtr->view) {
77 wfree(bPtr);
78 return NULL;
80 bPtr->view->self = bPtr;
82 WMCreateEventHandler(bPtr->view, ExposureMask|StructureNotifyMask
83 |ClientMessageMask, handleEvents, bPtr);
86 W_ResizeView(bPtr->view, DEFAULT_WIDTH, DEFAULT_HEIGHT);
87 bPtr->caption = wstrdup(DEFAULT_CAPTION);
89 WMCreateEventHandler(bPtr->view, ButtonPressMask|ButtonReleaseMask,
90 handleActionEvents, bPtr);
92 bPtr->flags.enabled = 1;
94 bPtr->items = WMCreateBag(4);
96 bPtr->selectedItemIndex = -1;
98 bPtr->menuView = W_CreateTopView(scr);
99 bPtr->menuView->attribs.override_redirect = True;
100 bPtr->menuView->attribFlags |= CWOverrideRedirect;
102 W_ResizeView(bPtr->menuView, bPtr->view->size.width, 1);
104 WMCreateEventHandler(bPtr->menuView, ButtonPressMask|ButtonReleaseMask
105 |EnterWindowMask|LeaveWindowMask|ButtonMotionMask
106 |ExposureMask, handleActionEvents, bPtr);
108 return bPtr;
112 void
113 WMSetPopUpButtonAction(WMPopUpButton *bPtr, WMAction *action, void *clientData)
115 CHECK_CLASS(bPtr, WC_PopUpButton);
117 bPtr->action = action;
119 bPtr->clientData = clientData;
123 WMMenuItem*
124 WMAddPopUpButtonItem(WMPopUpButton *bPtr, char *title)
126 WMMenuItem *item;
128 CHECK_CLASS(bPtr, WC_PopUpButton);
130 item = WMCreateMenuItem();
131 WMSetMenuItemTitle(item, title);
133 WMPutInBag(bPtr->items, item);
135 if (bPtr->menuView && bPtr->menuView->flags.realized)
136 resizeMenu(bPtr);
138 return item;
142 WMMenuItem*
143 WMInsertPopUpButtonItem(WMPopUpButton *bPtr, int index, char *title)
145 WMMenuItem *item;
147 CHECK_CLASS(bPtr, WC_PopUpButton);
149 item = WMCreateMenuItem();
150 WMSetMenuItemTitle(item, title);
152 WMInsertInBag(bPtr->items, index, item);
154 /* if there is an selected item, update it's index to match the new
155 * position */
156 if (index < bPtr->selectedItemIndex)
157 bPtr->selectedItemIndex++;
159 if (bPtr->menuView && bPtr->menuView->flags.realized)
160 resizeMenu(bPtr);
162 return item;
166 void
167 WMRemovePopUpButtonItem(WMPopUpButton *bPtr, int index)
169 WMMenuItem *item;
171 CHECK_CLASS(bPtr, WC_PopUpButton);
173 wassertr(index >= 0 && index < WMGetBagItemCount(bPtr->items));
176 item = WMGetFromBag(bPtr->items, index);
177 WMDeleteFromBag(bPtr->items, index);
179 WMDestroyMenuItem(item);
181 if (bPtr->selectedItemIndex >= 0 && !bPtr->flags.pullsDown) {
182 if (index < bPtr->selectedItemIndex)
183 bPtr->selectedItemIndex--;
184 else if (index == bPtr->selectedItemIndex) {
185 /* reselect first item if the removed item is the
186 * selected one */
187 bPtr->selectedItemIndex = 0;
188 if (bPtr->view->flags.mapped)
189 paintPopUpButton(bPtr);
193 if (bPtr->menuView && bPtr->menuView->flags.realized)
194 resizeMenu(bPtr);
198 void
199 WMSetPopUpButtonEnabled(WMPopUpButton *bPtr, Bool flag)
201 bPtr->flags.enabled = flag;
202 if (bPtr->view->flags.mapped)
203 paintPopUpButton(bPtr);
207 Bool
208 WMGetPopUpButtonEnabled(WMPopUpButton *bPtr)
210 return bPtr->flags.enabled;
214 void
215 WMSetPopUpButtonSelectedItem(WMPopUpButton *bPtr, int index)
218 wassertr(index < WMGetBagItemCount(bPtr->items));
220 /* if (index >= WMGetBagCount(bPtr->items))
221 index = -1;*/
223 bPtr->selectedItemIndex = index;
225 if (bPtr->view->flags.mapped)
226 paintPopUpButton(bPtr);
230 WMGetPopUpButtonSelectedItem(WMPopUpButton *bPtr)
232 if (!bPtr->flags.pullsDown && bPtr->selectedItemIndex < 0)
233 return -1;
234 else
235 return bPtr->selectedItemIndex;
239 void
240 WMSetPopUpButtonText(WMPopUpButton *bPtr, char *text)
242 if (bPtr->caption)
243 wfree(bPtr->caption);
244 if (text)
245 bPtr->caption = wstrdup(text);
246 else
247 bPtr->caption = NULL;
248 if (bPtr->view->flags.realized) {
249 if (bPtr->flags.pullsDown || bPtr->selectedItemIndex < 0) {
250 paintPopUpButton(bPtr);
257 void
258 WMSetPopUpButtonItemEnabled(WMPopUpButton *bPtr, int index, Bool flag)
260 WMMenuItem *item;
262 item = WMGetFromBag(bPtr->items, index);
263 wassertr(item != NULL);
265 WMSetMenuItemEnabled(item, flag);
269 Bool
270 WMGetPopUpButtonItemEnabled(WMPopUpButton *bPtr, int index)
272 WMMenuItem *item;
274 item = WMGetFromBag(bPtr->items, index);
275 wassertrv(item != NULL, False);
277 return WMGetMenuItemEnabled(item);
281 void
282 WMSetPopUpButtonPullsDown(WMPopUpButton *bPtr, Bool flag)
284 bPtr->flags.pullsDown = flag;
285 if (flag) {
286 bPtr->selectedItemIndex = -1;
289 if (bPtr->view->flags.mapped)
290 paintPopUpButton(bPtr);
295 WMGetPopUpButtonNumberOfItems(WMPopUpButton *bPtr)
297 return WMGetBagItemCount(bPtr->items);
301 char*
302 WMGetPopUpButtonItem(WMPopUpButton *bPtr, int index)
304 WMMenuItem *item;
306 if (index >= WMGetBagItemCount(bPtr->items) || index < 0)
307 return NULL;
309 item = WMGetFromBag(bPtr->items, index);
310 if (item == NULL)
311 return NULL;
313 return WMGetMenuItemTitle(item);
317 WMMenuItem*
318 WMGetPopUpButtonMenuItem(WMPopUpButton *bPtr, int index)
320 WMMenuItem *item;
322 item = WMGetFromBag(bPtr->items, index);
324 return item;
329 static void
330 paintPopUpButton(PopUpButton *bPtr)
332 W_Screen *scr = bPtr->view->screen;
333 char *caption;
334 Pixmap pixmap;
337 if (bPtr->flags.pullsDown) {
338 caption = bPtr->caption;
339 } else {
340 if (bPtr->selectedItemIndex < 0) {
341 /* if no item selected, show the caption */
342 caption = bPtr->caption;
343 } else {
344 caption = WMGetPopUpButtonItem(bPtr, bPtr->selectedItemIndex);
348 pixmap = XCreatePixmap(scr->display, bPtr->view->window,
349 bPtr->view->size.width, bPtr->view->size.height,
350 scr->depth);
351 XFillRectangle(scr->display, pixmap, WMColorGC(scr->gray), 0, 0,
352 bPtr->view->size.width, bPtr->view->size.height);
354 W_DrawRelief(scr, pixmap, 0, 0, bPtr->view->size.width,
355 bPtr->view->size.height, WRRaised);
357 if (caption) {
358 W_PaintText(bPtr->view, pixmap, scr->normalFont, 6,
359 (bPtr->view->size.height-WMFontHeight(scr->normalFont))/2,
360 bPtr->view->size.width, WALeft,
361 bPtr->flags.enabled ? WMColorGC(scr->black) : WMColorGC(scr->darkGray),
362 False, caption, strlen(caption));
365 if (bPtr->flags.pullsDown) {
366 XCopyArea(scr->display, scr->pullDownIndicator->pixmap,
367 pixmap, scr->copyGC, 0, 0, scr->pullDownIndicator->width,
368 scr->pullDownIndicator->height,
369 bPtr->view->size.width-scr->pullDownIndicator->width-4,
370 (bPtr->view->size.height-scr->pullDownIndicator->height)/2);
371 } else {
372 int x, y;
374 x = bPtr->view->size.width - scr->popUpIndicator->width - 4;
375 y = (bPtr->view->size.height-scr->popUpIndicator->height)/2;
377 XSetClipOrigin(scr->display, scr->clipGC, x, y);
378 XSetClipMask(scr->display, scr->clipGC, scr->popUpIndicator->mask);
379 XCopyArea(scr->display, scr->popUpIndicator->pixmap, pixmap,
380 scr->clipGC, 0, 0, scr->popUpIndicator->width,
381 scr->popUpIndicator->height, x, y);
384 XCopyArea(scr->display, pixmap, bPtr->view->window, scr->copyGC, 0, 0,
385 bPtr->view->size.width, bPtr->view->size.height, 0, 0);
387 XFreePixmap(scr->display, pixmap);
392 static void
393 handleEvents(XEvent *event, void *data)
395 PopUpButton *bPtr = (PopUpButton*)data;
397 CHECK_CLASS(data, WC_PopUpButton);
400 switch (event->type) {
401 case Expose:
402 if (event->xexpose.count!=0)
403 break;
404 paintPopUpButton(bPtr);
405 break;
407 case DestroyNotify:
408 destroyPopUpButton(bPtr);
409 break;
415 static void
416 paintMenuEntry(PopUpButton *bPtr, int index, int highlight)
418 W_Screen *scr = bPtr->view->screen;
419 int yo;
420 int width, height, itemHeight, itemCount;
421 char *title;
423 itemCount = WMGetBagItemCount(bPtr->items);
424 if (index < 0 || index >= itemCount)
425 return;
427 itemHeight = bPtr->view->size.height;
428 width = bPtr->view->size.width;
429 height = itemHeight * itemCount;
430 yo = (itemHeight - WMFontHeight(scr->normalFont))/2;
432 if (!highlight) {
433 XClearArea(scr->display, bPtr->menuView->window, 0, index*itemHeight,
434 width, itemHeight, False);
435 return;
436 } else if (index < 0 && bPtr->flags.pullsDown) {
437 return;
440 XFillRectangle(scr->display, bPtr->menuView->window, WMColorGC(scr->white),
441 1, index*itemHeight+1, width-3, itemHeight-3);
443 title = WMGetPopUpButtonItem(bPtr, index);
445 W_DrawRelief(scr, bPtr->menuView->window, 0, index*itemHeight,
446 width, itemHeight, WRRaised);
448 W_PaintText(bPtr->menuView, bPtr->menuView->window, scr->normalFont, 6,
449 index*itemHeight + yo, width, WALeft, WMColorGC(scr->black),
450 False, title, strlen(title));
452 if (!bPtr->flags.pullsDown && index == bPtr->selectedItemIndex) {
453 XCopyArea(scr->display, scr->popUpIndicator->pixmap,
454 bPtr->menuView->window, scr->copyGC, 0, 0,
455 scr->popUpIndicator->width, scr->popUpIndicator->height,
456 width-scr->popUpIndicator->width-4,
457 index*itemHeight+(itemHeight-scr->popUpIndicator->height)/2);
462 Pixmap
463 makeMenuPixmap(PopUpButton *bPtr)
465 Pixmap pixmap;
466 W_Screen *scr = bPtr->view->screen;
467 WMMenuItem *item;
468 WMBagIterator iter;
469 int yo, i;
470 int width, height, itemHeight;
472 itemHeight = bPtr->view->size.height;
473 width = bPtr->view->size.width;
474 height = itemHeight * WMGetBagItemCount(bPtr->items);
475 yo = (itemHeight - WMFontHeight(scr->normalFont))/2;
477 pixmap = XCreatePixmap(scr->display, bPtr->view->window, width, height,
478 scr->depth);
480 XFillRectangle(scr->display, pixmap, WMColorGC(scr->gray), 0, 0,
481 width, height);
483 i = 0;
484 WM_ITERATE_BAG(bPtr->items, item, iter) {
485 GC gc;
486 char *text;
488 text = WMGetMenuItemTitle(item);
490 W_DrawRelief(scr, pixmap, 0, i*itemHeight, width, itemHeight,
491 WRRaised);
493 if (!WMGetMenuItemEnabled(item))
494 gc = WMColorGC(scr->darkGray);
495 else
496 gc = WMColorGC(scr->black);
498 W_PaintText(bPtr->menuView, pixmap, scr->normalFont, 6,
499 i*itemHeight + yo, width, WALeft, gc, False,
500 text, strlen(text));
502 if (!bPtr->flags.pullsDown && i == bPtr->selectedItemIndex) {
503 XCopyArea(scr->display, scr->popUpIndicator->pixmap, pixmap,
504 scr->copyGC, 0, 0, scr->popUpIndicator->width,
505 scr->popUpIndicator->height,
506 width-scr->popUpIndicator->width-4,
507 i*itemHeight+(itemHeight-scr->popUpIndicator->height)/2);
510 i++;
513 return pixmap;
517 static void
518 resizeMenu(PopUpButton *bPtr)
520 int height;
522 height = WMGetBagItemCount(bPtr->items) * bPtr->view->size.height;
523 if (height > 0)
524 W_ResizeView(bPtr->menuView, bPtr->view->size.width, height);
528 static void
529 popUpMenu(PopUpButton *bPtr)
531 W_Screen *scr = bPtr->view->screen;
532 Window dummyW;
533 int x, y;
535 if (!bPtr->menuView->flags.realized) {
536 W_RealizeView(bPtr->menuView);
537 resizeMenu(bPtr);
540 if (WMGetBagItemCount(bPtr->items) < 1)
541 return;
543 XTranslateCoordinates(scr->display, bPtr->view->window, scr->rootWin,
544 0, 0, &x, &y, &dummyW);
546 if (bPtr->flags.pullsDown) {
547 y += bPtr->view->size.height;
548 } else {
549 y -= bPtr->view->size.height*bPtr->selectedItemIndex;
551 W_MoveView(bPtr->menuView, x, y);
553 XSetWindowBackgroundPixmap(scr->display, bPtr->menuView->window,
554 makeMenuPixmap(bPtr));
555 XClearWindow(scr->display, bPtr->menuView->window);
557 W_MapView(bPtr->menuView);
559 bPtr->highlightedItem = 0;
560 if (!bPtr->flags.pullsDown && bPtr->selectedItemIndex < 0)
561 paintMenuEntry(bPtr, bPtr->selectedItemIndex, True);
565 static void
566 popDownMenu(PopUpButton *bPtr)
568 W_UnmapView(bPtr->menuView);
570 /* free the background pixmap used to draw the menu contents */
571 XSetWindowBackgroundPixmap(bPtr->view->screen->display,
572 bPtr->menuView->window, None);
576 static void
577 autoScroll(void *data)
579 PopUpButton *bPtr = (PopUpButton*)data;
580 int scrHeight = WMWidgetScreen(bPtr)->rootView->size.height;
581 int repeat = 0;
582 int dy = 0;
585 if (bPtr->scrollStartY >= scrHeight-1
586 && bPtr->menuView->pos.y+bPtr->menuView->size.height >= scrHeight-1) {
587 repeat = 1;
589 if (bPtr->menuView->pos.y+bPtr->menuView->size.height-5
590 <= scrHeight - 1) {
591 dy = scrHeight - 1
592 - (bPtr->menuView->pos.y+bPtr->menuView->size.height);
593 } else
594 dy = -5;
596 } else if (bPtr->scrollStartY <= 1 && bPtr->menuView->pos.y < 1) {
597 repeat = 1;
599 if (bPtr->menuView->pos.y+5 > 1)
600 dy = 1 - bPtr->menuView->pos.y;
601 else
602 dy = 5;
605 if (repeat) {
606 int oldItem;
608 W_MoveView(bPtr->menuView, bPtr->menuView->pos.x,
609 bPtr->menuView->pos.y + dy);
611 oldItem = bPtr->highlightedItem;
612 bPtr->highlightedItem = (bPtr->scrollStartY - bPtr->menuView->pos.y)
613 / bPtr->view->size.height;
615 if (oldItem!=bPtr->highlightedItem) {
616 WMMenuItem *item;
618 paintMenuEntry(bPtr, oldItem, False);
620 if (bPtr->highlightedItem >= 0 &&
621 bPtr->highlightedItem < WMGetBagItemCount(bPtr->items)) {
622 item = WMGetPopUpButtonMenuItem(bPtr, bPtr->highlightedItem);
623 paintMenuEntry(bPtr, bPtr->highlightedItem,
624 WMGetMenuItemEnabled(item));
625 } else {
626 bPtr->highlightedItem = -1;
630 bPtr->timer = WMAddTimerHandler(SCROLL_DELAY, autoScroll, bPtr);
631 } else {
632 bPtr->timer = NULL;
637 static void
638 wheelScrollUp(PopUpButton *bPtr)
640 int testIndex = bPtr->selectedItemIndex - 1;
642 while (testIndex>=0 && !WMGetPopUpButtonItemEnabled(bPtr, testIndex))
643 testIndex--;
644 if (testIndex != -1) {
645 WMSetPopUpButtonSelectedItem(bPtr, testIndex);
646 if (bPtr->action)
647 (*bPtr->action)(bPtr, bPtr->clientData);
652 static void
653 wheelScrollDown(PopUpButton *bPtr)
655 int itemCount = WMGetBagItemCount(bPtr->items);
656 int testIndex = bPtr->selectedItemIndex + 1;
658 while (testIndex<itemCount && !WMGetPopUpButtonItemEnabled(bPtr, testIndex))
659 testIndex++;
660 if (testIndex != itemCount) {
661 WMSetPopUpButtonSelectedItem(bPtr, testIndex);
662 if (bPtr->action)
663 (*bPtr->action)(bPtr, bPtr->clientData);
668 static void
669 handleActionEvents(XEvent *event, void *data)
671 PopUpButton *bPtr = (PopUpButton*)data;
672 int oldItem;
673 int scrHeight = WMWidgetScreen(bPtr)->rootView->size.height;
675 CHECK_CLASS(data, WC_PopUpButton);
677 if (WMGetBagItemCount(bPtr->items) < 1)
678 return;
680 switch (event->type) {
681 /* called for menuView */
682 case Expose:
683 paintMenuEntry(bPtr, bPtr->highlightedItem, True);
684 break;
686 case LeaveNotify:
687 bPtr->flags.insideMenu = 0;
688 if (bPtr->menuView->flags.mapped)
689 paintMenuEntry(bPtr, bPtr->highlightedItem, False);
690 bPtr->highlightedItem = -1;
691 break;
693 case EnterNotify:
694 bPtr->flags.insideMenu = 1;
695 break;
697 case MotionNotify:
698 if (bPtr->flags.insideMenu) {
699 oldItem = bPtr->highlightedItem;
700 bPtr->highlightedItem = event->xmotion.y / bPtr->view->size.height;
701 if (oldItem!=bPtr->highlightedItem) {
702 WMMenuItem *item;
704 paintMenuEntry(bPtr, oldItem, False);
705 if (bPtr->highlightedItem >= 0 &&
706 bPtr->highlightedItem < WMGetBagItemCount(bPtr->items)) {
707 item = WMGetPopUpButtonMenuItem(bPtr, bPtr->highlightedItem);
708 paintMenuEntry(bPtr, bPtr->highlightedItem,
709 WMGetMenuItemEnabled(item));
710 } else {
711 bPtr->highlightedItem = -1;
716 if (event->xmotion.y_root >= scrHeight-1
717 || event->xmotion.y_root <= 1) {
718 bPtr->scrollStartY = event->xmotion.y_root;
719 if (!bPtr->timer)
720 autoScroll(bPtr);
721 } else if (bPtr->timer) {
722 WMDeleteTimerHandler(bPtr->timer);
723 bPtr->timer = NULL;
726 break;
728 /* called for bPtr->view */
729 case ButtonPress:
730 if (!bPtr->flags.enabled)
731 break;
733 if (event->xbutton.button==WINGsConfiguration.mouseWheelUp) {
734 if (!bPtr->menuView->flags.mapped && !bPtr->flags.pullsDown) {
735 wheelScrollUp(bPtr);
737 break;
738 } else if (event->xbutton.button==WINGsConfiguration.mouseWheelDown) {
739 if (!bPtr->menuView->flags.mapped && !bPtr->flags.pullsDown) {
740 wheelScrollDown(bPtr);
742 break;
744 popUpMenu(bPtr);
745 if (!bPtr->flags.pullsDown) {
746 bPtr->highlightedItem = bPtr->selectedItemIndex;
747 bPtr->flags.insideMenu = 1;
748 } else {
749 bPtr->highlightedItem = -1;
750 bPtr->flags.insideMenu = 0;
752 XGrabPointer(bPtr->view->screen->display, bPtr->menuView->window,
753 False, ButtonReleaseMask|ButtonMotionMask|EnterWindowMask
754 |LeaveWindowMask, GrabModeAsync, GrabModeAsync,
755 None, None, CurrentTime);
756 break;
758 case ButtonRelease:
759 if (event->xbutton.button==WINGsConfiguration.mouseWheelUp ||
760 event->xbutton.button==WINGsConfiguration.mouseWheelDown) {
761 break;
763 XUngrabPointer(bPtr->view->screen->display, event->xbutton.time);
764 if (!bPtr->flags.pullsDown)
765 popDownMenu(bPtr);
767 if (bPtr->timer) {
768 WMDeleteTimerHandler(bPtr->timer);
769 bPtr->timer = NULL;
772 if (bPtr->flags.insideMenu && bPtr->highlightedItem>=0) {
773 WMMenuItem *item;
775 item = WMGetPopUpButtonMenuItem(bPtr, bPtr->highlightedItem);
777 if (WMGetMenuItemEnabled(item)) {
778 int i;
779 WMSetPopUpButtonSelectedItem(bPtr, bPtr->highlightedItem);
781 if (bPtr->flags.pullsDown) {
782 for (i=0; i<MENU_BLINK_COUNT; i++) {
783 paintMenuEntry(bPtr, bPtr->highlightedItem, False);
784 XSync(bPtr->view->screen->display, 0);
785 wusleep(MENU_BLINK_DELAY);
786 paintMenuEntry(bPtr, bPtr->highlightedItem, True);
787 XSync(bPtr->view->screen->display, 0);
788 wusleep(MENU_BLINK_DELAY);
791 paintMenuEntry(bPtr, bPtr->highlightedItem, False);
792 popDownMenu(bPtr);
793 if (bPtr->action)
794 (*bPtr->action)(bPtr, bPtr->clientData);
797 if (bPtr->menuView->flags.mapped)
798 popDownMenu(bPtr);
799 break;
805 static void
806 destroyPopUpButton(PopUpButton *bPtr)
808 WMMenuItem *item;
809 WMBagIterator i;
811 if (bPtr->timer) {
812 WMDeleteTimerHandler(bPtr->timer);
815 WM_ITERATE_BAG(bPtr->items, item, i) {
816 WMDestroyMenuItem(item);
818 WMFreeBag(bPtr->items);
820 if (bPtr->caption)
821 wfree(bPtr->caption);
823 /* have to destroy explicitly because the popup is a toplevel */
824 W_DestroyView(bPtr->menuView);
826 wfree(bPtr);