1 /* vi:set ts=8 sts=4 sw=4:
3 * VIM - Vi IMproved by Bram Moolenaar
5 * Do ":help uganda" in Vim to read copying and usage conditions.
6 * Do ":help credits" in Vim to see a list of people who contributed.
7 * See README.txt for an overview of the Vim source code.
11 * (C) 2002,2005 by Marcin Dalecki <martin@dalecki.de>
13 * MARCIN DALECKI ASSUMES NO RESPONSIBILITY FOR THE USE OR INABILITY TO USE ANY
14 * OF THIS SOFTWARE . THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
15 * KIND, AND MARCIN DALECKI EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES,
16 * INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 * FITNESS FOR A PARTICULAR PURPOSE.
21 * Enhanced Motif PushButton widget with move over behavior.
30 #if defined(HAVE_XM_TRAITP_H) && defined(HAVE_XM_MANAGER_H) \
31 && defined(HAVE_XM_UNHIGHLIGHTT_H) && defined(HAVE_XM_XPMP_H)
32 # include <Xm/TraitP.h>
33 # include <Xm/Manager.h>
34 # include <Xm/UnhighlightT.h>
40 #include <Xm/ManagerP.h>
41 #include <Xm/Display.h>
42 #include <Xm/DisplayP.h>
44 #include <X11/Shell.h>
45 #include <X11/ShellP.h>
47 #include "gui_xmebwp.h"
49 /* Provide some missing wrappers, which are missed from the LessTif
50 * implementation. Also missing in Motif 1.2 and earlier.
52 * We neither use XmeGetPixmapData or _XmGetPixmapData, since with LessTif the
53 * pixmap will not appear in it's caches properly. We cache the interesting
54 * values in XmEnhancedButtonPart instead ourself.
56 #if defined(LESSTIF_VERSION) || (XmVersion <= 1002)
57 # ifndef Lab_IsMenupane
58 # define Lab_IsMenupane(w) (Lab_MenuType(w) == (int)XmMENU_POPUP || \
59 Lab_MenuType(w) == (int)XmMENU_PULLDOWN)
61 # define XmeClearBorder _XmClearBorder
62 # define XmeDrawShadows _XmDrawShadows
63 # define XmeDrawHighlight(a, b, c, d, e, f, g, h) \
64 _XmDrawHighlight(a, b, c, d, e, f, g, h, LineSolid)
68 * Motif internals we have to cheat around with.
71 /* Hopefully this will never change... */
72 #ifndef XmFOCUS_IGNORE
73 # define XmFOCUS_IGNORE 1<<1
76 extern Boolean
_XmGetInDragMode(Widget widget
);
77 extern void _XmPrimitiveEnter(Widget wid
,
79 String
* params
, Cardinal
* num_params
);
80 extern void _XmPrimitiveLeave(Widget wid
,
82 String
* params
, Cardinal
* num_params
);
83 extern void _XmSetFocusFlag(Widget w
, unsigned int mask
, Boolean value
);
84 extern void _XmCalcLabelDimensions(Widget wid
);
87 * Declaration of class methods.
89 static void Destroy(Widget w
);
90 static void Initialize(Widget rq
, Widget eb
, ArgList args
, Cardinal
*n
);
91 static Boolean
SetValues(Widget current
, Widget request
, Widget
new, ArgList args
, Cardinal
*n
);
92 static void Redisplay(Widget
, XEvent
*, Region
);
95 * Declaration of action methods.
97 static void Enter(Widget
, XEvent
*, String
*, Cardinal
*);
98 static void Leave(Widget
, XEvent
*, String
*, Cardinal
*);
99 static void BorderHighlight(Widget
);
100 static void BorderUnhighlight(Widget
);
103 * 4 x 4 stipple for desensitized widgets
105 #define stipple_width 4
106 #define stipple_height 4
107 static char stipple_bits
[] = { 0x0a, 0x05, 0x0a, 0x05 };
108 #define STIPPLE_BITMAP xmEnhancedButtonClassRec.enhancedbutton_class.stipple_bitmap
113 static XtActionsRec actionsList
[] =
119 static XtResource resources
[] =
122 XmNpixmapData
, XmCPixmap
, XmRString
, sizeof(String
),
123 XtOffsetOf(XmEnhancedButtonRec
, enhancedbutton
.pixmap_data
),
124 XmRImmediate
, (XtPointer
) NULL
126 XmNpixmapFile
, XmCPixmap
, XmRString
, sizeof(String
),
127 XtOffsetOf(XmEnhancedButtonRec
, enhancedbutton
.pixmap_file
),
128 XmRImmediate
, (XtPointer
) NULL
130 XmNspacing
, XmCSpacing
, XmRHorizontalDimension
, sizeof(Dimension
),
131 XtOffsetOf(XmEnhancedButtonRec
, enhancedbutton
.spacing
),
132 XmRImmediate
, (XtPointer
) 2
135 XmNlabelLocation
, XmCLocation
, XmRInt
, sizeof(int),
136 XtOffsetOf(XmEnhancedButtonRec
, enhancedbutton
.label_location
),
137 XtRImmediate
, (XtPointer
) XmRIGHT
141 /* This is needed to work around a bug in Lesstif 2, leaving the extension
142 * NULL somehow results in getting it set to an invalid pointer. */
143 XmPrimitiveClassExtRec xmEnhancedButtonPrimClassExtRec
=
145 /* next_extension */ NULL
,
146 /* record_type */ NULLQUARK
,
147 /* version */ XmPrimitiveClassExtVersion
,
148 /* record_size */ sizeof(XmPrimitiveClassExtRec
),
149 /* widget_baseline */ XmInheritBaselineProc
,
150 /* widget_display_rect */ XmInheritDisplayRectProc
,
151 /* widget_margins */ NULL
154 XmEnhancedButtonClassRec xmEnhancedButtonClassRec
=
157 /* core_class fields */
158 /* superclass */ (WidgetClass
) & xmPushButtonClassRec
,
159 /* class_name */ "XmEnhancedButton",
160 /* widget_size */ sizeof(XmEnhancedButtonRec
),
161 /* class_initialize */ NULL
,
162 /* class_part_initialize */ NULL
,
163 /* class_inited */ False
,
164 /* initialize */ Initialize
,
165 /* initialize_hook */ NULL
,
166 /* realize */ XtInheritRealize
,
167 /* actions */ actionsList
,
168 /* num_actions */ XtNumber(actionsList
),
169 /* resources */ resources
,
170 /* num_resources */ XtNumber(resources
),
171 /* xrm_class */ NULLQUARK
,
172 /* compress_motion */ True
,
173 /* compress_exposure */ XtExposeCompressMaximal
,
174 /* compress_enterleave */ True
,
175 /* visible_interest */ False
,
176 /* destroy */ Destroy
,
177 /* resize */ XtInheritResize
,
178 /* expose */ Redisplay
,
179 /* set_values */ SetValues
,
180 /* set_values_hook */ NULL
,
181 /* set_values_almost */ XtInheritSetValuesAlmost
,
182 /* get_values_hook */ NULL
,
183 /* accept_focus */ XtInheritAcceptFocus
,
184 /* version */ XtVersion
,
185 /* callback_private */ NULL
,
187 /* query_geometry */ NULL
,
188 /* display_accelerator */ XtInheritDisplayAccelerator
,
192 /* primitive_class fields */
194 /* border highlight */ BorderHighlight
,
195 /* border_unhighlight */ BorderUnhighlight
,
196 /* translations */ XtInheritTranslations
,
197 /* arm and activate */ XmInheritArmAndActivate
,
198 /* synthetic resources */ NULL
,
199 /* number of syn res */ 0,
200 /* extension */ (XtPointer
)&xmEnhancedButtonPrimClassExtRec
,
203 /* label_class fields */
205 /* setOverrideCallback */ XmInheritSetOverrideCallback
,
206 /* menuProcs */ XmInheritMenuProc
,
207 /* translations */ XtInheritTranslations
,
208 /* extension */ NULL
,
211 /* pushbutton_class record */
213 /* extension */ (XtPointer
) NULL
,
216 /* enhancedbutton_class fields */
218 /* stipple_bitmap */ None
223 WidgetClass xmEnhancedButtonWidgetClass
=
224 (WidgetClass
)&xmEnhancedButtonClassRec
;
228 * Create a slightly fainter pixmap to be shown on button entry.
230 static unsigned short
231 bump_color(unsigned short value
)
233 int tmp
= 2 * (((int) value
- 65535) / 3) + 65535;
240 alloc_color(Display
*display
,
249 if (!XParseColor(display
, colormap
, colorname
, xcolor
))
252 xcolor
->red
= bump_color(xcolor
->red
);
253 xcolor
->green
= bump_color(xcolor
->green
);
254 xcolor
->blue
= bump_color(xcolor
->blue
);
256 status
= XAllocColor(display
, colormap
, xcolor
);
257 return status
!= 0 ? 1 : 0;
261 static char * blank_xpm
[] =
263 /* width height ncolors cpp [x_hot y_hot] */
266 " s iconColor1 m black c #000000",
267 ". s none m none c none",
268 "X s topShadowColor m none c #DCDEE5",
269 "o s bottomShadowColor m black c #5D6069",
288 set_pixmap(XmEnhancedButtonWidget eb
)
290 /* Configure defines XPMATTRIBUTES_TYPE as XpmAttributes or as
291 * XpmAttributes_21, depending on what is in Xm/XpmP.h. */
292 XPMATTRIBUTES_TYPE attr
;
295 static XpmColorSymbol color
[8] = {
298 {"background", NULL
, 0},
299 {"foreground", NULL
, 0},
300 {"bottomShadowColor", NULL
, 0},
301 {"topShadowColor", NULL
, 0},
302 {"highlightColor", NULL
, 0},
303 {"armColor", NULL
, 0}
306 Display
*dpy
= XtDisplay(eb
);
309 unsigned int height
, width
, border
, depth
;
313 Pixmap arm_pix
= None
;
314 Pixmap ins_pix
= None
;
315 Pixmap high_pix
= None
;
316 char **data
= (char **) eb
->enhancedbutton
.pixmap_data
;
317 char *fname
= (char *) eb
->enhancedbutton
.pixmap_file
;
321 /* Make sure there is a default value for the pixmap.
326 gc
= XtGetGC((Widget
)eb
, (XtGCMask
)0, NULL
);
328 scr
= DefaultScreen(dpy
);
329 root
= RootWindow(dpy
, scr
);
331 eb
->label
.pixmap
= None
;
333 eb
->enhancedbutton
.pixmap_depth
= 0;
334 eb
->enhancedbutton
.pixmap_width
= 0;
335 eb
->enhancedbutton
.pixmap_height
= 0;
336 eb
->enhancedbutton
.normal_pixmap
= None
;
337 eb
->enhancedbutton
.armed_pixmap
= None
;
338 eb
->enhancedbutton
.highlight_pixmap
= None
;
339 eb
->enhancedbutton
.insensitive_pixmap
= None
;
341 /* We use dynamic colors, get them now. */
342 motif_get_toolbar_colors(
343 &eb
->core
.background_pixel
,
344 &eb
->primitive
.foreground
,
345 &eb
->primitive
.bottom_shadow_color
,
346 &eb
->primitive
.top_shadow_color
,
347 &eb
->primitive
.highlight_color
);
349 /* Setup color subsititution table. */
350 color
[0].pixel
= eb
->core
.background_pixel
;
351 color
[1].pixel
= eb
->core
.background_pixel
;
352 color
[2].pixel
= eb
->core
.background_pixel
;
353 color
[3].pixel
= eb
->primitive
.foreground
;
354 color
[4].pixel
= eb
->core
.background_pixel
;
355 color
[5].pixel
= eb
->primitive
.top_shadow_color
;
356 color
[6].pixel
= eb
->primitive
.highlight_color
;
357 color
[7].pixel
= eb
->pushbutton
.arm_color
;
359 /* Create the "sensitive" pixmap. */
360 attr
.valuemask
= XpmColorSymbols
| XpmCloseness
;
361 attr
.closeness
= 65535; /* accuracy isn't crucial */
362 attr
.colorsymbols
= color
;
363 attr
.numsymbols
= XtNumber(color
);
366 status
= XpmReadFileToPixmap(dpy
, root
, fname
, &pix
, &mask
, &attr
);
367 if (!fname
|| status
!= XpmSuccess
)
368 status
= XpmCreatePixmapFromData(dpy
, root
, data
, &pix
, &mask
, &attr
);
370 /* If something failed, we will fill in the default pixmap. */
371 if (status
!= XpmSuccess
)
372 status
= XpmCreatePixmapFromData(dpy
, root
, blank_xpm
, &pix
,
375 XpmFreeAttributes(&attr
);
377 XGetGeometry(dpy
, pix
, &root
, &x
, &y
, &width
, &height
, &border
, &depth
);
379 if (eb
->enhancedbutton
.label_location
== (int)XmTOP
380 || eb
->enhancedbutton
.label_location
== (int)XmBOTTOM
)
381 shift
= eb
->primitive
.shadow_thickness
/ 2;
383 shift
= eb
->primitive
.shadow_thickness
/ 2;
388 sen_pix
= XCreatePixmap(dpy
, root
, width
+ shift
, height
+ shift
, depth
);
390 XSetForeground(dpy
, gc
, eb
->core
.background_pixel
);
391 XFillRectangle(dpy
, sen_pix
, gc
, 0, 0, width
+ shift
, height
+ shift
);
392 XSetClipMask(dpy
, gc
, mask
);
393 XSetClipOrigin(dpy
, gc
, shift
, shift
);
394 XCopyArea(dpy
, pix
, sen_pix
, gc
, 0, 0, width
, height
, shift
, shift
);
396 /* Create the "highlight" pixmap. */
397 color
[4].pixel
= eb
->primitive
.bottom_shadow_color
;
398 attr
.valuemask
= XpmColorSymbols
| XpmCloseness
| XpmAllocColor
;
399 attr
.closeness
= 65535; /* accuracy isn't crucial */
400 attr
.colorsymbols
= color
;
401 attr
.numsymbols
= XtNumber(color
);
402 attr
.alloc_color
= alloc_color
;
404 status
= XpmCreatePixmapFromData(dpy
, root
, data
, &pix
, NULL
, &attr
);
405 XpmFreeAttributes(&attr
);
407 high_pix
= XCreatePixmap(dpy
, root
, width
+ shift
, height
+ shift
, depth
);
410 XSetForeground(dpy
, gc
, eb
->core
.background_pixel
);
412 XSetForeground(dpy
, gc
, eb
->primitive
.top_shadow_color
);
414 XSetClipMask(dpy
, gc
, None
);
415 XFillRectangle(dpy
, high_pix
, gc
, 0, 0, width
+ shift
, height
+ shift
);
416 XSetClipMask(dpy
, gc
, mask
);
417 XSetClipOrigin(dpy
, gc
, 0, 0);
418 XCopyArea(dpy
, pix
, high_pix
, gc
, 0, 0, width
, height
, 0, 0);
420 arm_pix
= XCreatePixmap(dpy
, pix
, width
+ shift
, height
+ shift
, depth
);
422 if (eb
->pushbutton
.fill_on_arm
)
423 XSetForeground(dpy
, gc
, eb
->pushbutton
.arm_color
);
425 XSetForeground(dpy
, gc
, eb
->core
.background_pixel
);
426 XSetClipOrigin(dpy
, gc
, shift
, shift
);
427 XSetClipMask(dpy
, gc
, None
);
428 XFillRectangle(dpy
, arm_pix
, gc
, 0, 0, width
+ shift
, height
+ shift
);
429 XSetClipMask(dpy
, gc
, mask
);
430 XSetClipOrigin(dpy
, gc
, 2 * shift
, 2 * shift
);
431 XCopyArea(dpy
, pix
, arm_pix
, gc
, 0, 0, width
, height
, 2 * shift
, 2 * shift
);
433 XFreePixmap(dpy
, pix
);
434 XFreePixmap(dpy
, mask
);
436 /* Create the "insensitive" pixmap. */
437 attr
.valuemask
= XpmColorSymbols
| XpmCloseness
| XpmColorKey
;
438 attr
.closeness
= 65535; /* accuracy isn't crucial */
439 attr
.colorsymbols
= color
;
440 attr
.numsymbols
= sizeof(color
) / sizeof(color
[0]);
441 attr
.color_key
= XPM_MONO
;
442 status
= XpmCreatePixmapFromData(dpy
, root
, data
, &pix
, &mask
, &attr
);
444 /* Need to create new Pixmaps with the mask applied. */
446 ins_pix
= XCreatePixmap(dpy
, root
, width
+ shift
, height
+ shift
, depth
);
448 XSetForeground(dpy
, gc
, eb
->core
.background_pixel
);
449 XSetClipOrigin(dpy
, gc
, 0, 0);
450 XSetClipMask(dpy
, gc
, None
);
451 XFillRectangle(dpy
, ins_pix
, gc
, 0, 0, width
+ shift
, height
+ shift
);
452 XSetClipMask(dpy
, gc
, mask
);
453 XSetForeground(dpy
, gc
, eb
->primitive
.top_shadow_color
);
454 XSetClipOrigin(dpy
, gc
, 2 * shift
, 2 * shift
);
455 XFillRectangle(dpy
, ins_pix
, gc
, 2 * shift
, 2 * shift
, width
, height
);
456 XSetForeground(dpy
, gc
, eb
->primitive
.bottom_shadow_color
);
457 XSetClipOrigin(dpy
, gc
, shift
, shift
);
458 XFillRectangle(dpy
, ins_pix
, gc
, 0, 0, width
+ shift
, height
+ shift
);
459 XtReleaseGC((Widget
) eb
, gc
);
461 XpmFreeAttributes(&attr
);
463 eb
->enhancedbutton
.pixmap_depth
= depth
;
464 eb
->enhancedbutton
.pixmap_width
= width
;
465 eb
->enhancedbutton
.pixmap_height
= height
;
466 eb
->enhancedbutton
.normal_pixmap
= sen_pix
;
467 eb
->enhancedbutton
.highlight_pixmap
= high_pix
;
468 eb
->enhancedbutton
.insensitive_pixmap
= ins_pix
;
469 eb
->enhancedbutton
.armed_pixmap
= arm_pix
;
471 eb
->enhancedbutton
.doing_setvalues
= True
;
472 eb
->enhancedbutton
.doing_setvalues
= False
;
474 XFreePixmap(dpy
, pix
);
475 XFreePixmap(dpy
, mask
);
478 #define BUTTON_MASK ( \
479 Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask \
483 draw_shadows(XmEnhancedButtonWidget eb
)
489 if (!eb
->primitive
.shadow_thickness
)
492 if ((eb
->core
.width
<= 2 * eb
->primitive
.highlight_thickness
)
493 || (eb
->core
.height
<= 2 * eb
->primitive
.highlight_thickness
))
496 #if !defined(LESSTIF_VERSION) && (XmVersion > 1002)
500 dpy
= (XmDisplay
) XmGetXmDisplay(XtDisplay(eb
));
501 etched_in
= dpy
->display
.enable_etched_in_menu
;
506 if (!etched_in
^ eb
->pushbutton
.armed
)
508 top_gc
= eb
->primitive
.top_shadow_GC
;
509 bottom_gc
= eb
->primitive
.bottom_shadow_GC
;
513 top_gc
= eb
->primitive
.bottom_shadow_GC
;
514 bottom_gc
= eb
->primitive
.top_shadow_GC
;
517 XmeDrawShadows(XtDisplay(eb
), XtWindow(eb
),
520 eb
->primitive
.highlight_thickness
,
521 eb
->primitive
.highlight_thickness
,
522 eb
->core
.width
- 2 * eb
->primitive
.highlight_thickness
,
523 eb
->core
.height
- 2 * eb
->primitive
.highlight_thickness
,
524 eb
->primitive
.shadow_thickness
,
525 (unsigned)(etched_in
? XmSHADOW_IN
: XmSHADOW_OUT
));
529 draw_highlight(XmEnhancedButtonWidget eb
)
531 eb
->primitive
.highlighted
= True
;
532 eb
->primitive
.highlight_drawn
= True
;
534 if (!XtWidth(eb
) || !XtHeight(eb
) || !eb
->primitive
.highlight_thickness
)
537 XmeDrawHighlight(XtDisplay(eb
), XtWindow(eb
),
538 eb
->primitive
.highlight_GC
, 0, 0,
539 XtWidth(eb
), XtHeight(eb
),
540 eb
->primitive
.highlight_thickness
);
544 draw_unhighlight(XmEnhancedButtonWidget eb
)
546 GC manager_background_GC
;
548 eb
->primitive
.highlighted
= False
;
549 eb
->primitive
.highlight_drawn
= False
;
551 if (!XtWidth(eb
) || !XtHeight(eb
) || !eb
->primitive
.highlight_thickness
)
554 if (XmIsManager(eb
->core
.parent
))
557 XmSpecifyUnhighlightTrait UnhighlightT
;
559 if (((UnhighlightT
= (XmSpecifyUnhighlightTrait
) XmeTraitGet((XtPointer
)
560 XtClass(eb
->core
.parent
), XmQTspecifyUnhighlight
))
561 != NULL
) && (UnhighlightT
->getUnhighlightGC
!= NULL
))
563 /* if unhighlight trait in parent use specified GC... */
564 manager_background_GC
=
565 UnhighlightT
->getUnhighlightGC(eb
->core
.parent
, (Widget
) eb
);
569 /* ...otherwise, use parent's background GC */
570 manager_background_GC
= ((XmManagerWidget
)
571 (eb
->core
.parent
))->manager
.background_GC
;
574 manager_background_GC
= ((XmManagerWidget
)
575 (eb
->core
.parent
))->manager
.background_GC
;
577 XmeDrawHighlight(XtDisplay(eb
), XtWindow(eb
),
578 manager_background_GC
,
579 0, 0, XtWidth(eb
), XtHeight(eb
),
580 eb
->primitive
.highlight_thickness
);
581 if (!eb
->pushbutton
.armed
&& eb
->primitive
.shadow_thickness
)
582 XmeClearBorder(XtDisplay(eb
), XtWindow(eb
),
583 eb
->primitive
.highlight_thickness
,
584 eb
->primitive
.highlight_thickness
,
585 eb
->core
.width
- 2 * eb
->primitive
.highlight_thickness
,
586 eb
->core
.height
- 2 * eb
->primitive
.highlight_thickness
,
587 eb
->primitive
.shadow_thickness
);
590 XmeClearBorder(XtDisplay(eb
), XtWindow(eb
), 0, 0, XtWidth(eb
),
591 XtHeight(eb
), eb
->primitive
.highlight_thickness
);
596 draw_pixmap(XmEnhancedButtonWidget eb
, XEvent
*event
, Region region
)
599 GC gc
= eb
->label
.normal_GC
;
608 if (!XtIsSensitive((Widget
) eb
))
609 pix
= eb
->enhancedbutton
.insensitive_pixmap
;
612 if (eb
->primitive
.highlighted
&& !eb
->pushbutton
.armed
)
613 pix
= eb
->enhancedbutton
.highlight_pixmap
;
614 else if (eb
->pushbutton
.armed
)
615 pix
= eb
->enhancedbutton
.armed_pixmap
;
617 pix
= eb
->enhancedbutton
.normal_pixmap
;
620 if (pix
== None
|| !eb
->enhancedbutton
.pixmap_data
)
623 depth
= eb
->enhancedbutton
.pixmap_depth
;
624 w
= eb
->enhancedbutton
.pixmap_width
;
625 h
= eb
->enhancedbutton
.pixmap_height
;
627 gc
= eb
->label
.normal_GC
;
628 x
= eb
->primitive
.highlight_thickness
629 + eb
->primitive
.shadow_thickness
630 + eb
->label
.margin_width
;
631 y
= eb
->primitive
.highlight_thickness
632 + eb
->primitive
.shadow_thickness
633 + eb
->label
.margin_height
;
634 width
= eb
->core
.width
- 2 * x
;
637 height
= eb
->core
.height
- 2 * y
;
640 if (depth
== eb
->core
.depth
)
641 XCopyArea(XtDisplay(eb
), pix
, XtWindow(eb
), gc
, 0, 0,
642 width
, height
, x
, y
);
644 XCopyPlane(XtDisplay(eb
), pix
, XtWindow(eb
), gc
, 0, 0,
645 width
, height
, x
, y
, (unsigned long)1);
649 * Draw the label contained in the pushbutton.
652 draw_label(XmEnhancedButtonWidget eb
, XEvent
*event
, Region region
)
655 Boolean replaceGC
= False
;
656 Boolean deadjusted
= False
;
657 #if !defined(LESSTIF_VERSION) && (XmVersion > 1002)
658 XmDisplay dpy
= (XmDisplay
)XmGetXmDisplay(XtDisplay(eb
));
659 Boolean etched_in
= dpy
->display
.enable_etched_in_menu
;
661 Boolean etched_in
= False
;
664 if (eb
->pushbutton
.armed
665 && ((!Lab_IsMenupane(eb
) && eb
->pushbutton
.fill_on_arm
)
666 || (Lab_IsMenupane(eb
) && etched_in
)))
668 if (eb
->label
.label_type
== (int)XmSTRING
669 && eb
->pushbutton
.arm_color
== eb
->primitive
.foreground
)
671 tmp_gc
= eb
->label
.normal_GC
;
672 eb
->label
.normal_GC
= eb
->pushbutton
.background_gc
;
678 * If the button contains a labeled pixmap, we will take it instead of our
682 if (eb
->label
.label_type
== (int)XmPIXMAP
)
684 if (eb
->pushbutton
.armed
)
686 if (eb
->pushbutton
.arm_pixmap
!= XmUNSPECIFIED_PIXMAP
)
687 eb
->label
.pixmap
= eb
->pushbutton
.arm_pixmap
;
689 eb
->label
.pixmap
= eb
->pushbutton
.unarm_pixmap
;
692 /* pushbutton is not armed */
693 eb
->label
.pixmap
= eb
->pushbutton
.unarm_pixmap
;
697 * Temporarily remove the Xm3D_ENHANCE_PIXEL hack ("adjustment") from the
698 * margin values, so we don't confuse Label.
700 if (eb
->pushbutton
.default_button_shadow_thickness
> 0)
703 Lab_MarginLeft(eb
) -= Xm3D_ENHANCE_PIXEL
;
704 Lab_MarginRight(eb
) -= Xm3D_ENHANCE_PIXEL
;
705 Lab_MarginTop(eb
) -= Xm3D_ENHANCE_PIXEL
;
706 Lab_MarginBottom(eb
) -= Xm3D_ENHANCE_PIXEL
;
713 expose
= xmLabelClassRec
.core_class
.expose
;
715 (*expose
)((Widget
) eb
, event
, region
);
720 Lab_MarginLeft(eb
) += Xm3D_ENHANCE_PIXEL
;
721 Lab_MarginRight(eb
) += Xm3D_ENHANCE_PIXEL
;
722 Lab_MarginTop(eb
) += Xm3D_ENHANCE_PIXEL
;
723 Lab_MarginBottom(eb
) += Xm3D_ENHANCE_PIXEL
;
727 eb
->label
.normal_GC
= tmp_gc
;
732 Enter(Widget wid
, XEvent
*event
, String
*params
, Cardinal
*num_params
)
734 XmEnhancedButtonWidget eb
= (XmEnhancedButtonWidget
) wid
;
735 XmPushButtonCallbackStruct call_value
;
737 if (Lab_IsMenupane(eb
))
739 if ((((ShellWidget
) XtParent(XtParent(eb
)))->shell
.popped_up
)
740 && _XmGetInDragMode((Widget
) eb
))
742 #if !defined(LESSTIF_VERSION) && (XmVersion > 1002)
743 XmDisplay dpy
= (XmDisplay
) XmGetXmDisplay(XtDisplay(wid
));
744 Boolean etched_in
= dpy
->display
.enable_etched_in_menu
;
746 Boolean etched_in
= False
;
749 if (eb
->pushbutton
.armed
)
752 /* ...so KHelp event is delivered correctly. */
753 _XmSetFocusFlag(XtParent(XtParent(eb
)), XmFOCUS_IGNORE
, TRUE
);
754 XtSetKeyboardFocus(XtParent(XtParent(eb
)), (Widget
) eb
);
755 _XmSetFocusFlag(XtParent(XtParent(eb
)), XmFOCUS_IGNORE
, FALSE
);
757 eb
->pushbutton
.armed
= TRUE
;
759 ((XmManagerWidget
) XtParent(wid
))->manager
.active_child
= wid
;
761 /* etched in menu button */
762 if (etched_in
&& !XmIsTearOffButton(eb
))
764 XFillRectangle(XtDisplay(eb
), XtWindow(eb
),
765 eb
->pushbutton
.fill_gc
,
766 0, 0, eb
->core
.width
, eb
->core
.height
);
767 draw_label(eb
, event
, NULL
);
768 draw_pixmap(eb
, event
, NULL
);
771 if ((eb
->core
.width
> 2 * eb
->primitive
.highlight_thickness
)
772 && (eb
->core
.height
>
773 2 * eb
->primitive
.highlight_thickness
))
775 XmeDrawShadows(XtDisplay(eb
), XtWindow(eb
),
776 eb
->primitive
.top_shadow_GC
,
777 eb
->primitive
.bottom_shadow_GC
,
778 eb
->primitive
.highlight_thickness
,
779 eb
->primitive
.highlight_thickness
,
780 eb
->core
.width
- 2 * eb
->primitive
.highlight_thickness
,
781 eb
->core
.height
- 2 * eb
->primitive
.highlight_thickness
,
782 eb
->primitive
.shadow_thickness
,
783 (unsigned)(etched_in
? XmSHADOW_IN
: XmSHADOW_OUT
));
786 if (eb
->pushbutton
.arm_callback
)
788 XFlush(XtDisplay(eb
));
790 call_value
.reason
= (int)XmCR_ARM
;
791 call_value
.event
= event
;
792 XtCallCallbackList((Widget
) eb
,
793 eb
->pushbutton
.arm_callback
,
802 _XmPrimitiveEnter((Widget
) eb
, event
, NULL
, NULL
);
803 if (eb
->pushbutton
.armed
== TRUE
)
806 expose
= XtClass(eb
)->core_class
.expose
;
808 (*expose
) (wid
, event
, (Region
) NULL
);
813 draw_pixmap(eb
, event
, NULL
);
819 Leave(Widget wid
, XEvent
*event
, String
*params
, Cardinal
*num_params
)
821 XmEnhancedButtonWidget eb
= (XmEnhancedButtonWidget
)wid
;
822 XmPushButtonCallbackStruct call_value
;
824 if (Lab_IsMenupane(eb
))
826 #if !defined(LESSTIF_VERSION) && (XmVersion > 1002)
827 XmDisplay dpy
= (XmDisplay
) XmGetXmDisplay(XtDisplay(wid
));
828 Boolean etched_in
= dpy
->display
.enable_etched_in_menu
;
830 Boolean etched_in
= False
;
833 if (_XmGetInDragMode((Widget
)eb
)
834 && eb
->pushbutton
.armed
835 && ( /* !ActiveTearOff || */
836 event
->xcrossing
.mode
== NotifyNormal
))
838 eb
->pushbutton
.armed
= FALSE
;
840 ((XmManagerWidget
) XtParent(wid
))->manager
.active_child
= NULL
;
842 if (etched_in
&& !XmIsTearOffButton(eb
))
844 XFillRectangle(XtDisplay(eb
), XtWindow(eb
),
845 eb
->pushbutton
.background_gc
,
846 0, 0, eb
->core
.width
, eb
->core
.height
);
847 draw_label(eb
, event
, NULL
);
848 draw_pixmap(eb
, event
, NULL
);
852 (XtDisplay(eb
), XtWindow(eb
),
853 eb
->primitive
.highlight_thickness
,
854 eb
->primitive
.highlight_thickness
,
856 2 * eb
->primitive
.highlight_thickness
,
858 2 * eb
->primitive
.highlight_thickness
,
859 eb
->primitive
.shadow_thickness
);
861 if (eb
->pushbutton
.disarm_callback
)
863 XFlush(XtDisplay(eb
));
865 call_value
.reason
= (int)XmCR_DISARM
;
866 call_value
.event
= event
;
867 XtCallCallbackList((Widget
) eb
,
868 eb
->pushbutton
.disarm_callback
,
875 _XmPrimitiveLeave((Widget
) eb
, event
, NULL
, NULL
);
877 if (eb
->pushbutton
.armed
== TRUE
)
880 eb
->pushbutton
.armed
= FALSE
;
882 expose
= XtClass(eb
)->core_class
.expose
;
884 (*expose
) (wid
, event
, (Region
)NULL
);
885 draw_unhighlight(eb
);
886 draw_pixmap(eb
, event
, NULL
);
887 eb
->pushbutton
.armed
= TRUE
;
891 draw_unhighlight(eb
);
892 draw_pixmap(eb
, event
, NULL
);
897 #define IsNull(p) ((p) == XmUNSPECIFIED_PIXMAP)
900 set_size(XmEnhancedButtonWidget newtb
)
905 _XmCalcLabelDimensions((Widget
) newtb
);
907 /* Find out how big the pixmap is */
908 if (newtb
->enhancedbutton
.pixmap_data
909 && !IsNull(newtb
->label
.pixmap
)
910 && !IsNull(newtb
->enhancedbutton
.normal_pixmap
))
912 w
= newtb
->enhancedbutton
.pixmap_width
;
913 h
= newtb
->enhancedbutton
.pixmap_height
;
917 * Plase note that we manipulate the width only in case of push buttons not
918 * used in the context of a menu pane.
920 if (Lab_IsMenupane(newtb
))
922 newtb
->label
.margin_left
= w
+ 2 * (newtb
->primitive
.shadow_thickness
923 + newtb
->primitive
.highlight_thickness
)
924 + newtb
->label
.margin_width
;
928 newtb
->label
.margin_left
= w
;
929 newtb
->core
.width
= w
+ 2 * (newtb
->primitive
.shadow_thickness
930 + newtb
->primitive
.highlight_thickness
931 + newtb
->label
.margin_width
)
932 + newtb
->label
.TextRect
.width
;
934 if (newtb
->label
.TextRect
.width
> 0)
936 newtb
->label
.margin_left
+= newtb
->label
.margin_width
937 + newtb
->primitive
.shadow_thickness
;
938 newtb
->core
.width
+= newtb
->label
.margin_width
939 + newtb
->primitive
.shadow_thickness
;
942 if (newtb
->label
.TextRect
.height
< h
)
944 newtb
->core
.height
= h
+ 2 * (newtb
->primitive
.shadow_thickness
945 + newtb
->primitive
.highlight_thickness
946 + newtb
->label
.margin_height
);
950 /* FIXME: We should calculate an drawing offset for the pixmap here to
955 printf("%d %d %d %d %d %d - %d %d\n", newtb
->enhancedbutton
.normal_pixmap
,
956 h
, newtb
->core
.height
,
957 newtb
->primitive
.shadow_thickness
,
958 newtb
->primitive
.highlight_thickness
,
959 newtb
->label
.margin_height
,
964 /* Invoke Label's Resize procedure. */
968 resize
= xmLabelClassRec
.core_class
.resize
;
971 (* resize
) ((Widget
) newtb
);
977 Initialize(Widget rq
, Widget ebw
, ArgList args
, Cardinal
*n
)
979 XmEnhancedButtonWidget request
= (XmEnhancedButtonWidget
)rq
;
980 XmEnhancedButtonWidget eb
= (XmEnhancedButtonWidget
)ebw
;
984 resize
= xmLabelClassRec
.core_class
.resize
;
987 /* Create a bitmap for stippling (Drawable resources are cheap). */
988 if (STIPPLE_BITMAP
== None
)
990 Display
*dpy
= XtDisplay((Widget
) request
);
991 Window rootW
= DefaultRootWindow(dpy
);
993 STIPPLE_BITMAP
= XCreateBitmapFromData(dpy
, rootW
, stipple_bits
,
994 stipple_width
, stipple_height
);
996 eb
->enhancedbutton
.doing_setvalues
= False
;
998 /* First see what type of extended label this is.
1000 if (eb
->enhancedbutton
.pixmap_data
)
1005 /* FIXME: this is not the perfect way to deal with menues, which do not
1006 * have any string set right now. */
1007 str
= XmStringCreateLocalized("");
1008 XtVaSetValues((Widget
) eb
, XmNlabelString
, str
, NULL
);
1011 eb
->label
.pixmap
= eb
->enhancedbutton
.normal_pixmap
;
1013 if (request
->core
.width
== 0)
1015 if (request
->core
.height
== 0)
1016 eb
->core
.height
= 0;
1019 (* resize
)((Widget
)eb
);
1023 free_pixmaps(XmEnhancedButtonWidget eb
)
1026 * Clear the old pixmaps.
1028 Pixmap norm_pix
= eb
->enhancedbutton
.normal_pixmap
;
1029 Pixmap arm_pix
= eb
->enhancedbutton
.armed_pixmap
;
1030 Pixmap insen_pix
= eb
->enhancedbutton
.insensitive_pixmap
;
1031 Pixmap high_pix
= eb
->enhancedbutton
.highlight_pixmap
;
1033 if (norm_pix
!= None
&& norm_pix
!= XmUNSPECIFIED_PIXMAP
)
1034 XFreePixmap(XtDisplay(eb
), norm_pix
);
1036 if (arm_pix
!= None
&& arm_pix
!= XmUNSPECIFIED_PIXMAP
)
1037 XFreePixmap(XtDisplay(eb
), arm_pix
);
1039 if (insen_pix
!= None
&& insen_pix
!= XmUNSPECIFIED_PIXMAP
)
1040 XFreePixmap(XtDisplay(eb
), insen_pix
);
1042 if (high_pix
!= None
&& high_pix
!= XmUNSPECIFIED_PIXMAP
)
1043 XFreePixmap(XtDisplay(eb
), high_pix
);
1049 if (!XmIsEnhancedButton(w
))
1052 free_pixmaps((XmEnhancedButtonWidget
)w
);
1057 SetValues(Widget current
, Widget request
, Widget
new, ArgList args
, Cardinal
*n
)
1059 XmEnhancedButtonWidget cur
= (XmEnhancedButtonWidget
) current
;
1060 XmEnhancedButtonWidget eb
= (XmEnhancedButtonWidget
) new;
1061 Boolean redraw
= False
;
1062 Boolean change
= True
;
1063 Display
*dpy
= XtDisplay(current
);
1065 #define NOT_EQUAL(field) (cur->field != eb->field)
1068 * Make sure that lost sensitivity is causing the border to vanish as well.
1070 if (NOT_EQUAL(core
.sensitive
) && !Lab_IsMenupane(current
))
1072 if (cur
->core
.sensitive
== True
)
1074 draw_unhighlight(eb
);
1080 unsigned int r_height
;
1081 unsigned int r_width
;
1082 unsigned int r_border
;
1083 unsigned int r_depth
;
1094 * Artificially let the highlight appear if the mouse is over us.
1096 /* Best way to get the root window of object: */
1097 XGetGeometry(dpy
, XtWindow(cur
), &root
, &r_x
, &r_y
, &r_width
,
1098 &r_height
, &r_border
, &r_depth
);
1099 XQueryPointer(XtDisplay(cur
), XtWindow(cur
), &root_q
, &child
,
1100 &root_x
, &root_y
, &win_x
, &win_y
, &mask
);
1104 if ((win_x
< 0) || (win_y
< 0))
1107 if ((win_x
> r_width
) || (win_y
> r_height
))
1118 * Check for changed ExtLabelString.
1120 if (NOT_EQUAL(primitive
.shadow_thickness
))
1123 /* Don't change the pixmaps */
1127 if (NOT_EQUAL(primitive
.foreground
))
1129 if (NOT_EQUAL(core
.background_pixel
))
1131 if (NOT_EQUAL(pushbutton
.fill_on_arm
))
1133 if (NOT_EQUAL(enhancedbutton
.spacing
))
1135 if (NOT_EQUAL(enhancedbutton
.label_location
))
1140 if (NOT_EQUAL(label
._label
))
1150 if (eb
->primitive
.highlighted
)
1151 eb
->label
.pixmap
= eb
->enhancedbutton
.highlight_pixmap
;
1153 eb
->label
.pixmap
= eb
->enhancedbutton
.normal_pixmap
;
1163 Redisplay(Widget w
, XEvent
*event
, Region region
)
1165 XmEnhancedButtonWidget eb
= (XmEnhancedButtonWidget
) w
;
1166 #if !defined(LESSTIF_VERSION) && (XmVersion > 1002)
1168 XtEnum default_button_emphasis
;
1175 if (!XtIsRealized((Widget
)eb
))
1178 #if !defined(LESSTIF_VERSION) && (XmVersion > 1002)
1179 dpy
= (XmDisplay
)XmGetXmDisplay(XtDisplay(eb
));
1180 default_button_emphasis
= dpy
->display
.default_button_emphasis
;
1184 * Compute the area allocated to the label of the pushbutton; fill in the
1185 * dimensions in the box.
1188 if ((eb
->pushbutton
.arm_color
== eb
->primitive
.top_shadow_color
)
1189 || (eb
->pushbutton
.arm_color
== eb
->primitive
.bottom_shadow_color
))
1192 if (eb
->pushbutton
.compatible
)
1193 adjust
= eb
->pushbutton
.show_as_default
;
1195 adjust
= eb
->pushbutton
.default_button_shadow_thickness
;
1199 adjust
= adjust
+ eb
->primitive
.shadow_thickness
;
1200 adjust
= (adjust
<< 1);
1201 dx
= eb
->primitive
.highlight_thickness
+ adjust
+ fill
;
1204 dx
= (eb
->primitive
.highlight_thickness
1205 + eb
->primitive
.shadow_thickness
+ fill
);
1210 box
.width
= eb
->core
.width
- adjust
;
1211 box
.height
= eb
->core
.height
- adjust
;
1214 * Redraw the background.
1216 if (!Lab_IsMenupane(eb
))
1220 /* Don't shade if the button contains a label with a pixmap, since
1221 * there is no variant of the label available with the needed
1224 if (eb
->pushbutton
.armed
&& eb
->pushbutton
.fill_on_arm
)
1226 if (eb
->label
.label_type
== (int)XmPIXMAP
)
1228 if (eb
->pushbutton
.arm_pixmap
!= XmUNSPECIFIED_PIXMAP
)
1229 gc
= eb
->pushbutton
.fill_gc
;
1231 gc
= eb
->pushbutton
.background_gc
;
1234 gc
= eb
->pushbutton
.fill_gc
;
1237 gc
= eb
->pushbutton
.background_gc
;
1238 /* really need to fill with background if not armed ? */
1240 XFillRectangle(XtDisplay(eb
), XtWindow(eb
), gc
,
1241 box
.x
, box
.y
, box
.width
, box
.height
);
1244 draw_label(eb
, event
, region
);
1246 if (Lab_IsMenupane(eb
))
1248 if (eb
->pushbutton
.armed
)
1249 (*(((XmPushButtonWidgetClass
)XtClass(eb
))
1250 ->primitive_class
.border_highlight
))(w
);
1251 draw_pixmap(eb
, event
, region
);
1257 #if !defined(LESSTIF_VERSION) && (XmVersion > 1002)
1259 * NOTE: PushButton has two types of shadows: primitive-shadow and
1260 * default-button-shadow. If pushbutton is in a menu only primitive
1261 * shadows are drawn.
1263 switch (default_button_emphasis
)
1265 case XmEXTERNAL_HIGHLIGHT
:
1266 adjust
= (eb
->primitive
.highlight_thickness
-
1267 (eb
->pushbutton
.default_button_shadow_thickness
?
1268 Xm3D_ENHANCE_PIXEL
: 0));
1271 case XmINTERNAL_HIGHLIGHT
:
1282 * Clear the area not occupied by label with parents background color.
1283 * Label will invoke BorderUnhighlight() on the highlight_thickness
1284 * area, which is redundant when XmEXTERNAL_HIGHLIGHT default button
1285 * shadow emphasis is used.
1289 int borderwidth
=box
.x
- adjust
;
1290 int rectwidth
= eb
->core
.width
- 2 * adjust
;
1291 int rectheight
= eb
->core
.height
- 2 * adjust
;
1293 if (XmIsManager(XtParent(eb
)))
1295 XmeDrawHighlight(XtDisplay(eb
), XtWindow(eb
),
1296 XmParentBackgroundGC(eb
),
1297 adjust
, adjust
, rectwidth
, rectheight
, borderwidth
);
1301 XmeClearBorder(XtDisplay(eb
), XtWindow(eb
),
1302 adjust
, adjust
, rectwidth
, rectheight
, borderwidth
);
1305 #if !defined(LESSTIF_VERSION) && (XmVersion > 1002)
1306 switch (default_button_emphasis
)
1308 case XmINTERNAL_HIGHLIGHT
:
1309 /* The call above erases the border highlighting. */
1310 if (eb
->primitive
.highlight_drawn
)
1311 (*(((XmPushButtonWidgetClass
) XtClass (eb
))
1312 ->primitive_class
.border_highlight
)) ((Widget
) eb
) ;
1321 if (eb
->pushbutton
.default_button_shadow_thickness
)
1323 if (eb
->pushbutton
.show_as_default
)
1326 * - get the topShadowColor and bottomShadowColor from the
1327 * parent; use those colors to construct top and bottom gc;
1328 * use these GCs to draw the shadows of the button.
1330 * - Should not be called if pushbutton is in a row column or
1333 * - Should be called only if a defaultbuttonshadow is to be
1338 int default_button_shadow_thickness
;
1339 int x
, y
, width
, height
, delta
;
1342 if (eb
->pushbutton
.compatible
1343 && (eb
->pushbutton
.show_as_default
== 0))
1346 if (!eb
->pushbutton
.compatible
1347 && (eb
->pushbutton
.default_button_shadow_thickness
1351 delta
= eb
->primitive
.highlight_thickness
;
1354 * May need more complex computation for getting the GCs.
1356 parent
= XtParent(eb
);
1357 if (XmIsManager(parent
))
1359 /* Use the parent's GC so monochrome works. */
1360 bottom_gc
= XmParentTopShadowGC(eb
);
1361 top_gc
= XmParentBottomShadowGC(eb
);
1365 /* Use your own pixel for drawing. */
1366 bottom_gc
= eb
->primitive
.top_shadow_GC
;
1367 top_gc
= eb
->primitive
.bottom_shadow_GC
;
1370 if ((bottom_gc
== None
) || (top_gc
== None
))
1374 if (eb
->pushbutton
.compatible
)
1375 default_button_shadow_thickness
=
1376 eb
->pushbutton
.show_as_default
;
1378 default_button_shadow_thickness
=
1379 eb
->pushbutton
.default_button_shadow_thickness
;
1381 #if !defined(LESSTIF_VERSION) && (XmVersion > 1002)
1383 * Compute location of bounding box to contain the
1384 * defaultButtonShadow.
1386 switch (default_button_emphasis
)
1388 case XmEXTERNAL_HIGHLIGHT
:
1389 delta
= eb
->primitive
.highlight_thickness
;
1392 case XmINTERNAL_HIGHLIGHT
:
1393 delta
= Xm3D_ENHANCE_PIXEL
;
1403 width
= eb
->core
.width
- 2 * delta
;
1404 height
= eb
->core
.height
- 2 * delta
;
1406 if ((width
> 0) && (height
> 0))
1407 XmeDrawShadows(XtDisplay(eb
), XtWindow(eb
),
1408 top_gc
, bottom_gc
, x
, y
, width
, height
,
1409 default_button_shadow_thickness
,
1410 (unsigned)XmSHADOW_OUT
);
1414 if (eb
->primitive
.highlight_drawn
)
1416 draw_pixmap(eb
, event
, region
);
1421 BorderHighlight(Widget w
)
1423 XmEnhancedButtonWidget eb
= (XmEnhancedButtonWidget
)w
;
1425 (*(xmPushButtonClassRec
.primitive_class
.border_highlight
))(w
);
1426 draw_pixmap(eb
, NULL
, NULL
);
1430 BorderUnhighlight(Widget w
)
1432 XmEnhancedButtonWidget eb
= (XmEnhancedButtonWidget
)w
;
1434 (*(xmPushButtonClassRec
.primitive_class
.border_unhighlight
))(w
);
1435 draw_pixmap(eb
, NULL
, NULL
);
1438 #endif /* FEAT_TOOLBAR */