2 /* This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 /* ---------------------------- included header files ---------------------- */
23 #include "libs/fvwmlib.h"
24 #include "libs/Picture.h"
25 #include "libs/Graphics.h"
26 #include "libs/PictureGraphics.h"
27 #include "libs/Rectangles.h"
30 #include "execcontext.h"
34 #include "menustyle.h"
36 #include "decorations.h"
38 /* ---------------------------- local definitions -------------------------- */
40 /* ---------------------------- local macros ------------------------------- */
42 /* ---------------------------- imports ------------------------------------ */
44 /* ---------------------------- included code files ------------------------ */
46 /* ---------------------------- local types -------------------------------- */
48 /* ---------------------------- forward declarations ----------------------- */
50 /* ---------------------------- local variables ---------------------------- */
52 /* ---------------------------- exported variables (globals) --------------- */
54 /* ---------------------------- local functions ---------------------------- */
55 static void clear_menu_item_background(
56 MenuPaintItemParameters
*mpip
, int x
, int y
, int w
, int h
)
58 MenuStyle
*ms
= mpip
->ms
;
60 if (!ST_HAS_MENU_CSET(ms
) &&
61 ST_FACE(ms
).type
== GradientMenu
&&
62 (ST_FACE(ms
).gradient_type
== D_GRADIENT
||
63 ST_FACE(ms
).gradient_type
== B_GRADIENT
))
71 mpip
->cb_reset_bg(mpip
->cb_mr
, &e
);
75 XClearArea(dpy
, mpip
->w
, x
, y
, w
, h
, False
);
81 * Draws two horizontal lines to form a separator
84 static void draw_separator(
85 Window w
, GC TopGC
, GC BottomGC
, int x1
, int y
, int x2
)
87 XDrawLine(dpy
, w
, TopGC
, x1
, y
, x2
, y
);
88 XDrawLine(dpy
, w
, BottomGC
, x1
-1, y
+1, x2
+1, y
+1);
95 * Draws a tear off bar. Similar to a separator, but with a dashed line.
98 static void draw_tear_off_bar(
99 Window w
, GC TopGC
, GC BottomGC
, int x1
, int y
, int x2
)
105 xgcv
.line_style
= LineOnOffDash
;
106 xgcv
.dashes
= MENU_TEAR_OFF_BAR_DASH_WIDTH
;
107 XChangeGC(dpy
, TopGC
, GCLineStyle
| GCDashList
, &xgcv
);
108 XChangeGC(dpy
, BottomGC
, GCLineStyle
| GCDashList
, &xgcv
);
109 width
= (x2
- x1
+ 1);
110 offset
= (width
/ MENU_TEAR_OFF_BAR_DASH_WIDTH
) *
111 MENU_TEAR_OFF_BAR_DASH_WIDTH
;
112 offset
= (width
- offset
) / 2;
115 XDrawLine(dpy
, w
, TopGC
, x1
, y
, x2
, y
);
116 XDrawLine(dpy
, w
, BottomGC
, x1
, y
+ 1, x2
, y
+ 1);
117 xgcv
.line_style
= LineSolid
;
118 XChangeGC(dpy
, TopGC
, GCLineStyle
, &xgcv
);
119 XChangeGC(dpy
, BottomGC
, GCLineStyle
, &xgcv
);
124 static void draw_highlight_background(
125 struct MenuPaintItemParameters
*mpip
, int x
, int y
, int width
,
126 int height
, colorset_t
*cs
, GC gc
)
128 if (cs
!= NULL
&& cs
->pixmap
&& cs
->pixmap_type
!= PIXMAP_TILED
)
132 p
= CreateOffsetBackgroundPixmap(
133 dpy
, mpip
->w
, 0, 0, width
, height
, cs
, Pdepth
, gc
,
135 switch (cs
->pixmap_type
)
137 case PIXMAP_STRETCH_X
:
138 /* todo: optimize to only create one pixmap and gc per
140 case PIXMAP_STRETCH_Y
:
147 gcv
.fill_style
= FillTiled
;
148 gcm
= GCFillStyle
| GCTile
;
150 /* vertcal gradients has to be aligned properly */
151 if (cs
->pixmap_type
== PIXMAP_STRETCH_Y
)
154 gcm
|=GCTileStipYOrigin
;
156 else if (cs
->pixmap_type
== PIXMAP_STRETCH_X
)
159 gcm
|=GCTileStipXOrigin
;
161 bgc
= fvwmlib_XCreateGC(dpy
, mpip
->w
, gcm
, &gcv
);
162 XFillRectangle(dpy
, mpip
->w
, bgc
, x
, y
, width
, height
);
167 XCopyArea(dpy
, p
, mpip
->w
, gc
, 0, 0, width
, height
,
175 XFillRectangle(dpy
, mpip
->w
, gc
, x
, y
, width
, height
);
179 /* ---------------------------- interface functions ------------------------ */
181 /* Allocates a new, empty menu item */
182 struct MenuItem
*menuitem_create(void)
186 mi
= (MenuItem
*)safemalloc(sizeof(MenuItem
));
187 memset(mi
, 0, sizeof(MenuItem
));
192 /* Frees a menu item and all of its allocated resources. */
193 void menuitem_free(struct MenuItem
*mi
)
201 for (i
= 0; i
< MAX_MENU_ITEM_LABELS
; i
++)
203 if (MI_LABEL(mi
)[i
] != NULL
)
205 free(MI_LABEL(mi
)[i
]);
208 if (MI_ACTION(mi
) != NULL
)
214 PDestroyFvwmPicture(dpy
, MI_PICTURE(mi
));
216 for (i
= 0; i
< MAX_MENU_ITEM_MINI_ICONS
; i
++)
218 if (MI_MINI_ICON(mi
)[i
])
220 PDestroyFvwmPicture(dpy
, MI_MINI_ICON(mi
)[i
]);
228 /* Duplicate a menu item into newly allocated memory. The new item is
229 * completely independent of the old one. */
230 struct MenuItem
*menuitem_clone(struct MenuItem
*mi
)
235 /* copy everything */
236 new_mi
= (MenuItem
*)safemalloc(sizeof(MenuItem
));
237 memcpy(new_mi
, mi
, sizeof(MenuItem
));
238 /* special treatment for a few parts */
239 MI_NEXT_ITEM(new_mi
) = NULL
;
240 MI_PREV_ITEM(new_mi
) = NULL
;
241 MI_WAS_DESELECTED(new_mi
) = 0;
242 if (MI_ACTION(mi
) != NULL
)
244 MI_ACTION(new_mi
) = safestrdup(MI_ACTION(mi
));
246 for (i
= 0; i
< MAX_MENU_ITEM_LABELS
; i
++)
248 if (MI_LABEL(mi
)[i
] != NULL
)
250 MI_LABEL(new_mi
)[i
] = strdup(MI_LABEL(mi
)[i
]);
253 if (MI_PICTURE(mi
) != NULL
)
255 MI_PICTURE(new_mi
) = PCloneFvwmPicture(MI_PICTURE(mi
));
257 for (i
= 0; i
< MAX_MENU_ITEM_MINI_ICONS
; i
++)
259 if (MI_MINI_ICON(mi
)[i
] != NULL
)
261 MI_MINI_ICON(new_mi
)[i
] =
262 PCloneFvwmPicture(MI_MINI_ICON(mi
)[i
]);
269 /* Calculate the size of the various parts of the item. The sizes are returned
271 void menuitem_get_size(
272 struct MenuItem
*mi
, struct MenuItemPartSizesT
*mipst
,
273 FlocaleFont
*font
, Bool do_reverse_icon_order
)
279 memset(mipst
, 0, sizeof(MenuItemPartSizesT
));
282 mipst
->triangle_width
= MENU_TRIANGLE_WIDTH
;
284 else if (MI_IS_TITLE(mi
) && !MI_HAS_PICTURE(mi
))
286 Bool is_formatted
= False
;
288 /* titles stretch over the whole menu width, so count the
289 * maximum separately if the title is unformatted. */
290 for (j
= 1; j
< MAX_MENU_ITEM_LABELS
; j
++)
292 if (MI_LABEL(mi
)[j
] != NULL
)
299 MI_LABEL_OFFSET(mi
)[j
] = 0;
302 if (!is_formatted
&& MI_LABEL(mi
)[0] != NULL
)
304 MI_LABEL_STRLEN(mi
)[0] =
305 strlen(MI_LABEL(mi
)[0]);
306 w
= FlocaleTextWidth(
307 font
, MI_LABEL(mi
)[0], MI_LABEL_STRLEN(mi
)[0]);
308 MI_LABEL_OFFSET(mi
)[0] = w
;
309 MI_IS_TITLE_CENTERED(mi
) = True
;
310 if (mipst
->title_width
< w
)
312 mipst
->title_width
= w
;
317 /* regular item or formatted title */
318 for (i
= 0; i
< MAX_MENU_ITEM_LABELS
; i
++)
322 MI_LABEL_STRLEN(mi
)[i
] = strlen(MI_LABEL(mi
)[i
]);
323 w
= FlocaleTextWidth(
324 font
, MI_LABEL(mi
)[i
], MI_LABEL_STRLEN(mi
)[i
]);
325 MI_LABEL_OFFSET(mi
)[i
] = w
;
326 if (mipst
->label_width
[i
] < w
)
328 mipst
->label_width
[i
] = w
;
332 if (MI_PICTURE(mi
) && mipst
->picture_width
< MI_PICTURE(mi
)->width
)
334 mipst
->picture_width
= MI_PICTURE(mi
)->width
;
336 for (i
= 0; i
< MAX_MENU_ITEM_MINI_ICONS
; i
++)
338 if (MI_MINI_ICON(mi
)[i
])
342 /* Reverse mini icon order for left submenu style. */
343 k
= (do_reverse_icon_order
== True
) ?
344 MAX_MENU_ITEM_MINI_ICONS
- 1 - i
: i
;
345 mipst
->icon_width
[k
] = MI_MINI_ICON(mi
)[i
]->width
;
355 * menuitem_paint - draws a single entry in a popped up menu
357 * mr - the menu instance that holds the menu item
358 * mi - the menu item to redraw
359 * fw - the FvwmWindow structure to check against allowed functions
363 struct MenuItem
*mi
, struct MenuPaintItemParameters
*mpip
)
365 struct MenuStyle
*ms
= mpip
->ms
;
366 struct MenuDimensions
*dim
= mpip
->dim
;
368 static FlocaleWinString
*fws
= NULL
;
380 FvwmRenderAttributes fra
;
382 int relief_thickness
= ST_RELIEF_THICKNESS(ms
);
383 Bool is_item_selected
;
384 Bool item_cleared
= False
;
385 Bool xft_clear
= False
;
386 Bool empty_inter
= False
;
388 Region region
= None
;
398 is_item_selected
= (mi
== mpip
->selected_item
);
402 font
= ST_PTITLEFONT(ms
);
406 font
= ST_PSTDFONT(ms
);
409 y_offset
= MI_Y_OFFSET(mi
);
410 y_height
= MI_HEIGHT(mi
);
411 if (MI_IS_SELECTABLE(mi
))
413 text_y
= y_offset
+ MDIM_ITEM_TEXT_Y_OFFSET(*dim
);
417 text_y
= y_offset
+ font
->ascent
+
418 ST_TITLE_GAP_ABOVE(ms
);
420 /* center text vertically if the pixmap is taller */
423 text_y
+= MI_PICTURE(mi
)->height
;
425 for (i
= 0; i
< mpip
->used_mini_icons
; i
++)
428 if (MI_MINI_ICON(mi
)[i
])
430 if (MI_MINI_ICON(mi
)[i
]->height
> y
)
432 y
= MI_MINI_ICON(mi
)[i
]->height
;
442 off_cs
= ST_HAS_MENU_CSET(ms
) ? ST_CSET_MENU(ms
) : -1;
443 /* Note: it's ok to pass a NULL label to is_function_allowed. */
445 !IS_EWMH_DESKTOP_FW(mpip
->fw
) &&
446 !is_function_allowed(
447 MI_FUNC_TYPE(mi
), MI_LABEL(mi
)[0], mpip
->fw
,
448 RQORIG_PROGRAM_US
, False
))
450 gcs
= ST_MENU_STIPPLE_GCS(ms
);
452 off_cs
= ST_HAS_GREYED_CSET(ms
) ? ST_CSET_GREYED(ms
) : -1;
454 else if (is_item_selected
)
456 gcs
= ST_MENU_ACTIVE_GCS(ms
);
457 off_gcs
= ST_MENU_INACTIVE_GCS(ms
);
459 else if (MI_IS_TITLE(mi
))
461 gcs
= ST_MENU_TITLE_GCS(ms
);
462 off_gcs
= ST_MENU_INACTIVE_GCS(ms
);
466 gcs
= ST_MENU_INACTIVE_GCS(ms
);
467 off_gcs
= ST_MENU_INACTIVE_GCS(ms
);
469 if (is_item_selected
)
471 cs
= (ST_HAS_ACTIVE_CSET(ms
)) ? ST_CSET_ACTIVE(ms
) : -1;
473 else if (MI_IS_TITLE(mi
))
475 cs
= (ST_HAS_TITLE_CSET(ms
)) ? ST_CSET_TITLE(ms
) : off_cs
;
485 if (FftSupport
&& ST_PSTDFONT(ms
)->fftf
.fftfont
!= NULL
)
490 /* Hilight or clear the background. */
493 if (is_item_selected
&&
494 (ST_DO_HILIGHT_BACK(ms
) || ST_DO_HILIGHT_FORE(ms
)))
496 /* Hilight the background. */
497 if (MDIM_HILIGHT_WIDTH(*dim
) - 2 * relief_thickness
> 0)
499 lit_x_start
= MDIM_HILIGHT_X_OFFSET(*dim
) +
501 lit_x_end
= lit_x_start
+ MDIM_HILIGHT_WIDTH(*dim
) -
502 2 * relief_thickness
;
503 if (ST_DO_HILIGHT_BACK(ms
))
505 draw_highlight_background(
507 y_offset
+ relief_thickness
,
508 lit_x_end
- lit_x_start
,
509 y_height
- relief_thickness
,
510 (cs
>= 0 ? &Colorset
[cs
] : NULL
),
516 else if ((MI_WAS_DESELECTED(mi
) &&
517 (relief_thickness
> 0 ||
518 ST_DO_HILIGHT_BACK(ms
) || ST_DO_HILIGHT_FORE(ms
)) &&
519 (ST_FACE(ms
).type
!= GradientMenu
|| ST_HAS_MENU_CSET(ms
))))
523 /* we clear if xft_clear and !ST_HAS_MENU_CSET(ms) as the
524 * non colorset code is too complicate ... olicha */
527 if (MI_PREV_ITEM(mi
) &&
528 mpip
->selected_item
== MI_PREV_ITEM(mi
))
530 /* Don't paint over the hilight relief. */
531 d
= relief_thickness
;
533 /* Undo the hilighting. */
535 MDIM_HILIGHT_X_OFFSET(*dim
), MDIM_ITEM_X_OFFSET(*dim
));
537 MDIM_HILIGHT_X_OFFSET(*dim
) + MDIM_HILIGHT_WIDTH(*dim
),
538 MDIM_ITEM_X_OFFSET(*dim
) + MDIM_ITEM_WIDTH(*dim
));
539 clear_menu_item_background(
540 mpip
, x1
, y_offset
+ d
, x2
- x1
,
541 y_height
+ relief_thickness
- d
);
544 else if (MI_IS_TITLE(mi
))
546 lit_x_start
= MDIM_ITEM_X_OFFSET(*dim
);
547 lit_x_end
= lit_x_start
+ MDIM_ITEM_WIDTH(*dim
);
548 /* Hilight the background. */
550 MDIM_HILIGHT_WIDTH(*dim
) > 0 &&
551 ST_DO_HILIGHT_TITLE_BACK(ms
))
553 draw_highlight_background(
555 y_offset
+ relief_thickness
,
556 lit_x_end
- lit_x_start
,
557 y_height
- relief_thickness
,
558 (cs
>= 0 ? &Colorset
[cs
] : NULL
),
564 MI_WAS_DESELECTED(mi
) = False
;
565 memset(&fra
, 0, sizeof(fra
));
569 if (is_item_selected
&& relief_thickness
> 0)
574 rgc
= gcs
.hilight_gc
;
576 if (ST_IS_ITEM_RELIEF_REVERSED(ms
))
580 /* swap gcs for reversed relief */
584 if (MDIM_HILIGHT_WIDTH(*dim
) - 2 * relief_thickness
> 0)
586 /* The relief reaches down into the next item, hence
587 * the value for the second y coordinate:
588 * MI_HEIGHT(mi) + 1 */
590 dpy
, mpip
->w
, MDIM_HILIGHT_X_OFFSET(*dim
),
591 y_offset
, MDIM_HILIGHT_WIDTH(*dim
) - 1,
592 MI_HEIGHT(mi
) - 1 + relief_thickness
, rgc
, sgc
,
599 * Draw the item itself.
602 /* Calculate the separator offsets. */
603 if (ST_HAS_LONG_SEPARATORS(ms
))
605 sx1
= MDIM_ITEM_X_OFFSET(*dim
) + relief_thickness
;
606 sx2
= MDIM_ITEM_X_OFFSET(*dim
) + MDIM_ITEM_WIDTH(*dim
) - 1 -
611 sx1
= MDIM_ITEM_X_OFFSET(*dim
) + relief_thickness
+
612 MENU_SEPARATOR_SHORT_X_OFFSET
;
613 sx2
= MDIM_ITEM_X_OFFSET(*dim
) + MDIM_ITEM_WIDTH(*dim
) - 1 -
614 relief_thickness
- MENU_SEPARATOR_SHORT_X_OFFSET
;
616 if (MI_IS_SEPARATOR(mi
))
620 /* It's a separator. */
622 mpip
->w
, gcs
.shadow_gc
, gcs
.hilight_gc
, sx1
,
623 y_offset
+ y_height
- MENU_SEPARATOR_HEIGHT
,
625 /* Nothing else to do. */
629 else if (MI_IS_TEAR_OFF_BAR(mi
))
634 tx1
= MDIM_ITEM_X_OFFSET(*dim
) + relief_thickness
+
635 MENU_TEAR_OFF_BAR_X_OFFSET
;
636 tx2
= MDIM_ITEM_X_OFFSET(*dim
) + MDIM_ITEM_WIDTH(*dim
) - 1 -
638 MENU_TEAR_OFF_BAR_X_OFFSET
;
642 /* It's a tear off bar. */
644 mpip
->w
, gcs
.shadow_gc
, gcs
.hilight_gc
, tx1
,
645 y_offset
+ relief_thickness
+
646 MENU_TEAR_OFF_BAR_Y_OFFSET
, tx2
);
648 /* Nothing else to do. */
651 else if (MI_IS_TITLE(mi
))
653 /* Separate the title. */
654 if (ST_TITLE_UNDERLINES(ms
) > 0 && !mpip
->flags
.is_first_item
)
656 int add
= (MI_IS_SELECTABLE(MI_PREV_ITEM(mi
))) ?
657 relief_thickness
: 0;
659 text_y
+= MENU_SEPARATOR_HEIGHT
+ add
;
664 mpip
->w
, gcs
.shadow_gc
, gcs
.hilight_gc
,
668 /* Underline the title. */
669 switch (ST_TITLE_UNDERLINES(ms
))
674 if (MI_NEXT_ITEM(mi
) != NULL
)
676 y
= y_offset
+ y_height
- MENU_SEPARATOR_HEIGHT
;
678 mpip
->w
, gcs
.shadow_gc
, gcs
.hilight_gc
,
683 for (i
= ST_TITLE_UNDERLINES(ms
); i
-- > 0; )
685 y
= y_offset
+ y_height
- 1 -
686 i
* MENU_UNDERLINE_HEIGHT
;
688 dpy
, mpip
->w
, gcs
.shadow_gc
, sx1
, y
,
700 FlocaleAllocateWinString(&fws
);
704 fws
->flags
.has_colorset
= 0;
705 b
.y
= text_y
- font
->ascent
;
706 b
.height
= font
->height
+ 1; /* ? */
707 if (!item_cleared
&& mpip
->ev
)
710 if (!frect_get_seg_intersection(
711 mpip
->ev
->xexpose
.y
, mpip
->ev
->xexpose
.height
,
712 b
.y
, b
.height
, &u
, &v
))
714 /* empty intersection */
721 for (i
= MAX_MENU_ITEM_LABELS
; i
-- > 0; )
723 if (!empty_inter
&& MI_LABEL(mi
)[i
] && *(MI_LABEL(mi
)[i
]))
725 Bool draw_string
= True
;
729 if (MI_LABEL_OFFSET(mi
)[i
] >= lit_x_start
&&
730 MI_LABEL_OFFSET(mi
)[i
] < lit_x_end
)
732 /* label is in hilighted area */
733 fws
->gc
= gcs
.fore_gc
;
738 /* label is in unhilighted area */
739 fws
->gc
= off_gcs
.fore_gc
;
744 fws
->colorset
= &Colorset
[tmp_cs
];
745 fws
->flags
.has_colorset
= 1;
747 fws
->str
= MI_LABEL(mi
)[i
];
748 b
.x
= fws
->x
= MI_LABEL_OFFSET(mi
)[i
];
749 b
.width
= text_width
= FlocaleTextWidth(
750 font
, fws
->str
, strlen(fws
->str
));
752 if (!item_cleared
&& mpip
->ev
)
755 if (frect_get_seg_intersection(
757 mpip
->ev
->xexpose
.width
,
763 region
= XCreateRegion();
764 XUnionRectWithRegion(
766 fws
->flags
.has_clip_region
= True
;
767 fws
->clip_region
= region
;
769 XSetRegion(dpy
, fws
->gc
, region
);
773 /* empty intersection */
779 if (!item_cleared
&& xft_clear
)
781 clear_menu_item_background(
782 mpip
, b
.x
, b
.y
, b
.width
,
785 FlocaleDrawString(dpy
, font
, fws
, 0);
788 if (MI_HAS_HOTKEY(mi
) && !MI_IS_TITLE(mi
) &&
789 (!MI_IS_HOTKEY_AUTOMATIC(mi
) ||
790 ST_USE_AUTOMATIC_HOTKEYS(ms
)) &&
791 MI_HOTKEY_COLUMN(mi
) == i
)
793 FlocaleDrawUnderline(
794 dpy
, ST_PSTDFONT(ms
), fws
,
795 MI_HOTKEY_COFFSET(mi
));
801 XDestroyRegion(region
);
803 fws
->flags
.has_clip_region
= False
;
804 fws
->clip_region
= None
;
805 XSetClipMask(dpy
, fws
->gc
, None
);
810 * Draw the submenu triangle.
817 if (MDIM_TRIANGLE_X_OFFSET(*dim
) >= lit_x_start
&&
818 MDIM_TRIANGLE_X_OFFSET(*dim
) < lit_x_end
&&
821 /* triangle is in hilighted area */
822 if (ST_TRIANGLES_USE_FORE(ms
))
824 tmp_gc
= gcs
.fore_gc
;
828 tmp_gc
= gcs
.hilight_gc
;
833 /* triangle is in unhilighted area */
834 if (ST_TRIANGLES_USE_FORE(ms
))
836 tmp_gc
= off_gcs
.fore_gc
;
840 tmp_gc
= off_gcs
.hilight_gc
;
843 y
= y_offset
+ (y_height
- MENU_TRIANGLE_HEIGHT
+
844 relief_thickness
) / 2;
846 if (ST_TRIANGLES_USE_FORE(ms
))
849 dpy
, mpip
->w
, tmp_gc
, tmp_gc
, tmp_gc
,
850 MDIM_TRIANGLE_X_OFFSET(*dim
), y
,
851 MENU_TRIANGLE_WIDTH
, MENU_TRIANGLE_HEIGHT
, 0,
852 (mpip
->flags
.is_left_triangle
) ? 'l' : 'r',
853 ST_HAS_TRIANGLE_RELIEF(ms
),
854 !ST_HAS_TRIANGLE_RELIEF(ms
), is_item_selected
);
860 dpy
, mpip
->w
, gcs
.hilight_gc
, gcs
.shadow_gc
,
861 tmp_gc
, MDIM_TRIANGLE_X_OFFSET(*dim
), y
,
862 MENU_TRIANGLE_WIDTH
, MENU_TRIANGLE_HEIGHT
, 0,
863 (mpip
->flags
.is_left_triangle
) ? 'l' : 'r',
864 ST_HAS_TRIANGLE_RELIEF(ms
),
865 !ST_HAS_TRIANGLE_RELIEF(ms
), is_item_selected
);
870 * Draw the item picture.
877 Bool draw_picture
= True
;
879 x
= menudim_middle_x_offset(mpip
->dim
) -
880 MI_PICTURE(mi
)->width
/ 2;
881 y
= y_offset
+ ((MI_IS_SELECTABLE(mi
)) ? relief_thickness
: 0);
882 if (x
>= lit_x_start
&& x
< lit_x_end
)
884 tmp_gc
= gcs
.fore_gc
;
889 tmp_gc
= off_gcs
.fore_gc
;
892 fra
.mask
= FRAM_DEST_IS_A_WINDOW
;
895 fra
.mask
|= FRAM_HAVE_ICON_CSET
;
896 fra
.colorset
= &Colorset
[tmp_cs
];
900 b
.width
= MI_PICTURE(mi
)->width
;
901 b
.height
= MI_PICTURE(mi
)->height
;
902 if (!item_cleared
&& mpip
->ev
)
904 if (!frect_get_intersection(
905 mpip
->ev
->xexpose
.x
, mpip
->ev
->xexpose
.y
,
906 mpip
->ev
->xexpose
.width
,
907 mpip
->ev
->xexpose
.height
,
908 b
.x
, b
.y
, b
.width
, b
.height
, &b
))
910 draw_picture
= False
;
917 (MI_PICTURE(mi
)->alpha
!= None
||
919 Colorset
[tmp_cs
].icon_alpha_percent
< 100)))
921 clear_menu_item_background(
922 mpip
, b
.x
, b
.y
, b
.width
, b
.height
);
924 PGraphicsRenderPicture(
925 dpy
, mpip
->w
, MI_PICTURE(mi
), &fra
,
926 mpip
->w
, tmp_gc
, Scr
.MonoGC
, Scr
.AlphaGC
,
927 b
.x
- x
, b
.y
- y
, b
.width
, b
.height
,
928 b
.x
, b
.y
, b
.width
, b
.height
, False
);
933 * Draw the mini icons.
936 for (i
= 0; i
< mpip
->used_mini_icons
; i
++)
939 Bool draw_picture
= True
;
941 /* We need to reverse the mini icon order for left submenu
943 k
= (ST_USE_LEFT_SUBMENUS(ms
)) ?
944 mpip
->used_mini_icons
- 1 - i
: i
;
946 if (MI_MINI_ICON(mi
)[i
])
953 y
= y_offset
+ MI_HEIGHT(mi
) -
954 MI_MINI_ICON(mi
)[i
]->height
;
960 ((MI_IS_SELECTABLE(mi
)) ?
961 relief_thickness
: 0) -
962 MI_MINI_ICON(mi
)[i
]->height
) / 2;
964 if (MDIM_ICON_X_OFFSET(*dim
)[k
] >= lit_x_start
&&
965 MDIM_ICON_X_OFFSET(*dim
)[k
] < lit_x_end
)
967 /* icon is in hilighted area */
968 tmp_gc
= gcs
.fore_gc
;
973 /* icon is in unhilighted area */
974 tmp_gc
= off_gcs
.fore_gc
;
977 fra
.mask
= FRAM_DEST_IS_A_WINDOW
;
980 fra
.mask
|= FRAM_HAVE_ICON_CSET
;
981 fra
.colorset
= &Colorset
[tmp_cs
];
983 b
.x
= MDIM_ICON_X_OFFSET(*dim
)[k
];
985 b
.width
= MI_MINI_ICON(mi
)[i
]->width
;
986 b
.height
= MI_MINI_ICON(mi
)[i
]->height
;
987 if (!item_cleared
&& mpip
->ev
)
989 if (!frect_get_intersection(
992 mpip
->ev
->xexpose
.width
,
993 mpip
->ev
->xexpose
.height
,
994 b
.x
, b
.y
, b
.width
, b
.height
, &b
))
996 draw_picture
= False
;
1001 if (!item_cleared
&&
1002 (MI_MINI_ICON(mi
)[i
]->alpha
!= None
1004 Colorset
[tmp_cs
].icon_alpha_percent
<
1007 clear_menu_item_background(
1009 b
.x
, b
.y
, b
.width
, b
.height
);
1011 PGraphicsRenderPicture(
1012 dpy
, mpip
->w
, MI_MINI_ICON(mi
)[i
],
1013 &fra
, mpip
->w
, tmp_gc
, Scr
.MonoGC
,
1015 b
.x
- MDIM_ICON_X_OFFSET(*dim
)[k
],
1016 b
.y
- y
, b
.width
, b
.height
,
1017 b
.x
, b
.y
, b
.width
, b
.height
, False
);
1025 /* returns the center y coordinate of the menu item */
1026 int menuitem_middle_y_offset(struct MenuItem
*mi
, struct MenuStyle
*ms
)
1032 return ST_BORDER_WIDTH(ms
);
1034 r
= (MI_IS_SELECTABLE(mi
)) ? ST_RELIEF_THICKNESS(ms
) : 0;
1036 return MI_Y_OFFSET(mi
) + (MI_HEIGHT(mi
) + r
) / 2;