1 /* The lwlib interface to Athena widgets.
2 Copyright (C) 1993 Chuck Thompson <cthomp@cs.uiuc.edu>
3 Copyright (C) 1994, 2001, 2002, 2003, 2004, 2005, 2006,
4 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
6 This file is part of the Lucid Widget Library.
8 The Lucid Widget Library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 1, or (at your option)
13 The Lucid Widget Library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs; see the file COPYING. If not, write to
20 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA. */
30 #include "../src/lisp.h"
32 #include "lwlib-Xaw.h"
34 #include <X11/StringDefs.h>
35 #include <X11/IntrinsicP.h>
36 #include <X11/CoreP.h>
37 #include <X11/Shell.h>
40 #include <X11/Xaw3d/Scrollbar.h>
41 #include <X11/Xaw3d/Paned.h>
42 #include <X11/Xaw3d/Dialog.h>
43 #include <X11/Xaw3d/Form.h>
44 #include <X11/Xaw3d/Command.h>
45 #include <X11/Xaw3d/Label.h>
46 #else /* !HAVE_XAW3D */
47 #include <X11/Xaw/Scrollbar.h>
48 #include <X11/Xaw/Paned.h>
49 #include <X11/Xaw/Dialog.h>
50 #include <X11/Xaw/Form.h>
51 #include <X11/Xaw/Command.h>
52 #include <X11/Xaw/Label.h>
53 #endif /* HAVE_XAW3D */
55 #include <X11/Xatom.h>
58 #include <X11/Xft/Xft.h>
60 struct widget_xft_data
65 XftColor xft_fg
, xft_bg
;
66 int p_width
, p_height
;
73 static void xaw_generic_callback (/*Widget, XtPointer, XtPointer*/);
77 lw_xaw_widget_p (widget
)
80 return (XtIsSubclass (widget
, scrollbarWidgetClass
) ||
81 XtIsSubclass (widget
, dialogWidgetClass
));
86 xaw_update_scrollbar (instance
, widget
, val
)
87 widget_instance
*instance
;
91 if (val
->scrollbar_data
)
93 scrollbar_values
*data
= val
->scrollbar_data
;
94 Dimension height
, width
;
95 Dimension pos_x
, pos_y
;
96 int widget_shown
, widget_topOfThumb
;
97 float new_shown
, new_topOfThumb
;
99 XtVaGetValues (widget
,
104 XtNtopOfThumb
, &widget_topOfThumb
,
105 XtNshown
, &widget_shown
,
109 * First size and position the scrollbar widget.
110 * We need to position it to second-guess the Paned widget's notion
111 * of what should happen when the WMShell gets resized.
113 if (height
!= data
->scrollbar_height
|| pos_y
!= data
->scrollbar_pos
)
115 XtConfigureWidget (widget
, pos_x
, data
->scrollbar_pos
,
116 width
, data
->scrollbar_height
, 0);
118 XtVaSetValues (widget
,
119 XtNlength
, data
->scrollbar_height
,
125 * Now the size the scrollbar's slider.
127 new_shown
= (float) data
->slider_size
/
128 (float) (data
->maximum
- data
->minimum
);
130 new_topOfThumb
= (float) (data
->slider_position
- data
->minimum
) /
131 (float) (data
->maximum
- data
->minimum
);
138 if (new_topOfThumb
> 1.0)
139 new_topOfThumb
= 1.0;
140 if (new_topOfThumb
< 0)
143 if (new_shown
!= widget_shown
|| new_topOfThumb
!= widget_topOfThumb
)
144 XawScrollbarSetThumb (widget
, new_topOfThumb
, new_shown
);
151 fill_xft_data (struct widget_xft_data
*data
, Widget widget
, XftFont
*font
)
155 int screen
= XScreenNumberOfScreen (XtScreen (widget
));
157 data
->widget
= widget
;
158 data
->xft_font
= font
;
159 XtVaGetValues (widget
,
164 colors
[0].pixel
= data
->xft_fg
.pixel
= fg
;
165 colors
[1].pixel
= data
->xft_bg
.pixel
= bg
;
166 XQueryColors (XtDisplay (widget
),
167 DefaultColormapOfScreen (XtScreen (widget
)),
170 data
->xft_fg
.color
.alpha
= 0xFFFF;
171 data
->xft_fg
.color
.red
= colors
[0].red
;
172 data
->xft_fg
.color
.green
= colors
[0].green
;
173 data
->xft_fg
.color
.blue
= colors
[0].blue
;
174 data
->xft_bg
.color
.alpha
= 0xFFFF;
175 data
->xft_bg
.color
.red
= colors
[1].red
;
176 data
->xft_bg
.color
.green
= colors
[1].green
;
177 data
->xft_bg
.color
.blue
= colors
[1].blue
;
181 data
->p_width
= data
->p_height
= 0;
185 openFont (Widget widget
, char *name
)
188 int screen
= XScreenNumberOfScreen (XtScreen (widget
));
189 int len
= strlen (fname
), i
= len
-1;
192 /* Try to convert Gtk-syntax (Sans 9) to Xft syntax Sans-9. */
193 while (i
> 0 && isdigit (fname
[i
]))
197 fname
= xstrdup (name
);
201 fn
= XftFontOpenName (XtDisplay (widget
), screen
, fname
);
202 if (fname
!= name
) free (fname
);
208 get_text_width_and_height (Widget widget
, char *text
,
215 while (bp
&& *bp
!= '\0')
218 char *cp
= strchr (bp
, '\n');
219 XftTextExtentsUtf8 (XtDisplay (widget
), xft_font
,
221 cp
? cp
- bp
: strlen (bp
),
223 bp
= cp
? cp
+ 1 : NULL
;
224 h
+= xft_font
->height
;
225 if (w
< gi
.width
) w
= gi
.width
;
233 draw_text (struct widget_xft_data
*data
, char *lbl
, int inverse
)
235 Screen
*sc
= XtScreen (data
->widget
);
236 int screen
= XScreenNumberOfScreen (sc
);
237 int y
= data
->xft_font
->ascent
;
238 int x
= inverse
? 0 : 2;
241 data
->xft_draw
= XftDrawCreate (XtDisplay (data
->widget
),
243 DefaultVisual (XtDisplay (data
->widget
),
245 DefaultColormapOfScreen (sc
));
246 XftDrawRect (data
->xft_draw
,
247 inverse
? &data
->xft_fg
: &data
->xft_bg
,
248 0, 0, data
->p_width
, data
->p_height
);
250 if (!inverse
) y
+= 2;
251 while (bp
&& *bp
!= '\0')
253 char *cp
= strchr (bp
, '\n');
254 XftDrawStringUtf8 (data
->xft_draw
,
255 inverse
? &data
->xft_bg
: &data
->xft_fg
,
256 data
->xft_font
, x
, y
, bp
, cp
? cp
- bp
: strlen (bp
));
257 bp
= cp
? cp
+ 1 : NULL
;
258 /* 1.2 gives reasonable line spacing. */
259 y
+= data
->xft_font
->height
* 1.2;
266 set_text (struct widget_xft_data
*data
, Widget toplevel
, char *lbl
, int margin
)
268 int screen
= XScreenNumberOfScreen (XtScreen (data
->widget
));
271 width
= get_text_width_and_height (data
->widget
, lbl
, data
->xft_font
,
273 data
->p_width
= width
+ margin
;
274 data
->p_height
= height
+ margin
;
276 data
->p
= XCreatePixmap (XtDisplay (data
->widget
),
280 DefaultDepthOfScreen (XtScreen (data
->widget
)));
281 draw_text (data
, lbl
, 0);
282 XtVaSetValues (data
->widget
, XtNbitmap
, data
->p
, NULL
);
285 static struct widget_xft_data
*
286 find_xft_data (Widget widget
)
288 widget_instance
*inst
= NULL
;
289 Widget parent
= XtParent (widget
);
290 struct widget_xft_data
*data
= NULL
;
292 while (parent
&& !inst
)
294 inst
= lw_get_widget_instance (parent
);
295 parent
= XtParent (parent
);
297 if (!inst
|| !inst
->xft_data
|| !inst
->xft_data
[0].xft_font
) return;
299 for (nr
= 0; data
== NULL
&& nr
< inst
->nr_xft_data
; ++nr
)
301 if (inst
->xft_data
[nr
].widget
== widget
)
302 data
= &inst
->xft_data
[nr
];
309 command_press (Widget widget
,
312 Cardinal
*num_params
)
314 struct widget_xft_data
*data
= find_xft_data (widget
);
318 /* Since this isn't used for rectangle buttons, use it to for armed. */
319 XtVaSetValues (widget
, XtNcornerRoundPercent
, 1, NULL
);
321 XtVaGetValues (widget
, XtNlabel
, &lbl
, NULL
);
322 draw_text (data
, lbl
, 1);
327 command_reset (Widget widget
,
330 Cardinal
*num_params
)
332 struct widget_xft_data
*data
= find_xft_data (widget
);
336 XtVaGetValues (widget
, XtNcornerRoundPercent
, &cr
, NULL
);
340 XtVaSetValues (widget
, XtNcornerRoundPercent
, 0, NULL
);
341 XtVaGetValues (widget
, XtNlabel
, &lbl
, NULL
);
342 draw_text (data
, lbl
, 0);
352 xaw_update_one_widget (widget_instance
*instance
, Widget widget
,
353 widget_value
*val
, Boolean deep_p
)
355 xaw_update_one_widget (instance
, widget
, val
, deep_p
)
356 widget_instance
*instance
;
363 if (XtIsSubclass (widget
, scrollbarWidgetClass
))
365 xaw_update_scrollbar (instance
, widget
, val
);
368 if (XtIsSubclass (widget
, dialogWidgetClass
))
372 if (instance
->xft_data
&& instance
->xft_data
[0].xft_font
)
374 set_text (&instance
->xft_data
[0], instance
->parent
,
375 val
->contents
->value
, 10);
378 XtVaSetValues (widget
, XtNlabel
, val
->contents
->value
, NULL
);
380 else if (XtIsSubclass (widget
, commandWidgetClass
))
386 XtVaGetValues (widget
, XtNborderWidth
, &bw
, NULL
);
388 /* Don't let buttons end up with 0 borderwidth, that's ugly...
389 Yeah, all this should really be done through app-defaults files
390 or fallback resources, but that's a whole different can of worms
391 that I don't feel like opening right now. Making Athena widgets
392 not look like shit is just entirely too much work.
395 XtSetArg (al
[0], XtNborderWidth
, 1);
396 XtSetValues (widget
, al
, 1);
399 XtSetSensitive (widget
, val
->enabled
);
400 XtSetArg (al
[ac
], XtNlabel
, val
->value
);ac
++;
401 /* Force centered button text. Se above. */
402 XtSetArg (al
[ac
], XtNjustify
, XtJustifyCenter
);ac
++;
404 if (instance
->xft_data
&& instance
->xft_data
[0].xft_font
)
408 for (nr
= 0; nr
< instance
->nr_xft_data
; ++nr
)
409 if (instance
->xft_data
[nr
].widget
== widget
)
411 if (nr
< instance
->nr_xft_data
)
413 set_text (&instance
->xft_data
[nr
], instance
->parent
,
416 /* Must set internalHeight to twice the highlight thickness,
417 or else it gets overwritten by our pixmap. Probably a bug. */
418 XtVaGetValues (widget
, XtNhighlightThickness
, &th
, NULL
);
419 XtSetArg (al
[ac
], XtNinternalHeight
, 2*th
);ac
++;
423 XtSetValues (widget
, al
, ac
);
424 XtRemoveAllCallbacks (widget
, XtNcallback
);
425 XtAddCallback (widget
, XtNcallback
, xaw_generic_callback
, instance
);
430 xaw_update_one_value (instance
, widget
, val
)
431 widget_instance
*instance
;
435 /* This function is not used by the scrollbars and those are the only
436 Athena widget implemented at the moment so do nothing. */
441 xaw_destroy_instance (instance
)
442 widget_instance
*instance
;
445 if (instance
->xft_data
)
448 for (i
= 0; i
< instance
->nr_xft_data
; ++i
)
450 if (instance
->xft_data
[i
].xft_draw
)
451 XftDrawDestroy (instance
->xft_data
[i
].xft_draw
);
452 if (instance
->xft_data
[i
].p
!= None
)
454 XtVaSetValues (instance
->xft_data
[i
].widget
, XtNbitmap
, None
,
456 XFreePixmap (XtDisplay (instance
->widget
),
457 instance
->xft_data
[i
].p
);
460 if (instance
->xft_data
[0].xft_font
)
461 XftFontClose (XtDisplay (instance
->widget
),
462 instance
->xft_data
[0].xft_font
);
463 free (instance
->xft_data
);
466 if (XtIsSubclass (instance
->widget
, dialogWidgetClass
))
467 /* Need to destroy the Shell too. */
468 XtDestroyWidget (XtParent (instance
->widget
));
470 XtDestroyWidget (instance
->widget
);
474 xaw_popup_menu (widget
, event
)
478 /* An Athena menubar has not been implemented. */
484 xaw_pop_instance (widget_instance
*instance
, Boolean up
)
486 xaw_pop_instance (instance
, up
)
487 widget_instance
*instance
;
491 Widget widget
= instance
->widget
;
495 if (XtIsSubclass (widget
, dialogWidgetClass
))
497 /* For dialogs, we need to call XtPopup on the parent instead
498 of calling XtManageChild on the widget.
499 Also we need to hack the shell's WM_PROTOCOLS to get it to
500 understand what the close box is supposed to do!!
502 Display
*dpy
= XtDisplay (widget
);
503 Widget shell
= XtParent (widget
);
506 props
[i
++] = XInternAtom (dpy
, "WM_DELETE_WINDOW", False
);
507 XChangeProperty (dpy
, XtWindow (shell
),
508 XInternAtom (dpy
, "WM_PROTOCOLS", False
),
509 XA_ATOM
, 32, PropModeAppend
,
510 (unsigned char *) props
, i
);
512 /* Center the widget in its parent. Why isn't this kind of crap
513 done automatically? I thought toolkits were supposed to make
517 unsigned int x
, y
, w
, h
;
518 Widget topmost
= instance
->parent
;
521 w
= shell
->core
.width
;
522 h
= shell
->core
.height
;
523 while (topmost
->core
.parent
&& XtIsRealized (topmost
->core
.parent
))
524 topmost
= topmost
->core
.parent
;
525 if (topmost
->core
.width
< w
) x
= topmost
->core
.x
;
526 else x
= topmost
->core
.x
+ ((topmost
->core
.width
- w
) / 2);
527 if (topmost
->core
.height
< h
) y
= topmost
->core
.y
;
528 else y
= topmost
->core
.y
+ ((topmost
->core
.height
- h
) / 2);
529 /* Using XtMoveWidget caused the widget to come
530 out in the wrong place with vtwm.
531 Question of virtual vs real coords, perhaps. */
532 XtSetArg (args
[0], XtNx
, x
);
533 XtSetArg (args
[1], XtNy
, y
);
534 XtSetValues (shell
, args
, 2);
537 /* Finally, pop it up. */
538 XtPopup (shell
, XtGrabNonexclusive
);
541 XtManageChild (widget
);
545 if (XtIsSubclass (widget
, dialogWidgetClass
))
546 XtUnmanageChild (XtParent (widget
));
548 XtUnmanageChild (widget
);
555 static char overrideTrans
[] =
556 "<Message>WM_PROTOCOLS: lwlib_delete_dialog()";
557 /* Dialogs pop down on any key press */
558 static char dialogOverride
[] =
559 "<KeyPress>Escape: lwlib_delete_dialog()";
560 static void wm_delete_window();
561 static XtActionsRec xaw_actions
[] = {
562 {"lwlib_delete_dialog", wm_delete_window
}
564 static Boolean actions_initted
= False
;
567 static XtActionsRec button_actions
[] =
569 { "my_reset", command_reset
},
570 { "my_press", command_press
},
573 "<Leave>: reset() my_reset()\n"
574 "<Btn1Down>: set() my_press()\n"
575 "<Btn1Up>: my_reset() notify() unset()\n";
579 make_dialog (name
, parent
, pop_up_p
, shell_title
, icon_name
, text_input_slot
,
580 radio_box
, list
, left_buttons
, right_buttons
, instance
)
586 Boolean text_input_slot
;
591 widget_instance
*instance
;
596 char button_name
[255];
600 XtTranslations override
;
602 XftFont
*xft_font
= 0;
603 XtTranslations button_override
;
606 if (! pop_up_p
) abort (); /* not implemented */
607 if (text_input_slot
) abort (); /* not implemented */
608 if (radio_box
) abort (); /* not implemented */
609 if (list
) abort (); /* not implemented */
611 if (! actions_initted
)
613 XtAppContext app
= XtWidgetToApplicationContext (parent
);
614 XtAppAddActions (app
, xaw_actions
,
615 sizeof (xaw_actions
) / sizeof (xaw_actions
[0]));
617 XtAppAddActions (app
, button_actions
,
618 sizeof (button_actions
) / sizeof (button_actions
[0]));
620 actions_initted
= True
;
623 override
= XtParseTranslationTable (overrideTrans
);
626 XtSetArg (av
[ac
], XtNtitle
, shell_title
); ac
++;
627 XtSetArg (av
[ac
], XtNallowShellResize
, True
); ac
++;
629 /* Don't allow any geometry request from the user. */
630 XtSetArg (av
[ac
], XtNgeometry
, 0); ac
++;
632 shell
= XtCreatePopupShell ("dialog", transientShellWidgetClass
,
634 XtOverrideTranslations (shell
, override
);
637 dialog
= XtCreateManagedWidget (name
, dialogWidgetClass
, shell
, av
, ac
);
638 override
= XtParseTranslationTable (dialogOverride
);
639 XtOverrideTranslations (dialog
, override
);
646 XtVaGetValues (dialog
,
647 XtNnumChildren
, &num
,
648 XtNchildren
, &ch
, NULL
);
649 for (i
= 0; i
< num
; ++i
)
651 if (!XtIsSubclass (ch
[i
], commandWidgetClass
)
652 && XtIsSubclass (ch
[i
], labelWidgetClass
))
658 instance
->xft_data
= 0;
659 instance
->nr_xft_data
= 0;
663 { { "faceName", "FaceName", XtRString
, sizeof(String
), 0, XtRString
,
664 (XtPointer
)"Sans-14" }};
666 XtVaGetSubresources (dialog
, &faceName
, "Dialog", "dialog",
668 if (strcmp ("none", faceName
) != 0)
669 xft_font
= openFont (dialog
, faceName
);
672 instance
->nr_xft_data
= left_buttons
+ right_buttons
+ 1;
673 instance
->xft_data
= calloc (instance
->nr_xft_data
,
674 sizeof(*instance
->xft_data
));
676 fill_xft_data (&instance
->xft_data
[0], w
, xft_font
);
680 button_override
= XtParseTranslationTable (buttonTrans
);
686 for (i
= 0; i
< left_buttons
; i
++)
689 XtSetArg (av
[ac
], XtNfromHoriz
, button
); ac
++;
690 XtSetArg (av
[ac
], XtNleft
, XtChainLeft
); ac
++;
691 XtSetArg (av
[ac
], XtNright
, XtChainLeft
); ac
++;
692 XtSetArg (av
[ac
], XtNtop
, XtChainBottom
); ac
++;
693 XtSetArg (av
[ac
], XtNbottom
, XtChainBottom
); ac
++;
694 XtSetArg (av
[ac
], XtNresizable
, True
); ac
++;
696 if (DefaultDepthOfScreen (XtScreen (dialog
)) >= 16)
698 /* Turn of dithered shadow if we can. Looks bad */
699 XtSetArg (av
[ac
], "beNiceToColormap", False
); ac
++;
702 sprintf (button_name
, "button%d", ++bc
);
703 button
= XtCreateManagedWidget (button_name
, commandWidgetClass
,
708 fill_xft_data (&instance
->xft_data
[bc
], button
, xft_font
);
709 XtOverrideTranslations (button
, button_override
);
714 for (i
= 0; i
< right_buttons
; i
++)
717 XtSetArg (av
[ac
], XtNfromHoriz
, button
); ac
++;
720 /* Separator to the other buttons. */
721 XtSetArg (av
[ac
], XtNhorizDistance
, 30); ac
++;
723 XtSetArg (av
[ac
], XtNleft
, XtChainRight
); ac
++;
724 XtSetArg (av
[ac
], XtNright
, XtChainRight
); ac
++;
725 XtSetArg (av
[ac
], XtNtop
, XtChainBottom
); ac
++;
726 XtSetArg (av
[ac
], XtNbottom
, XtChainBottom
); ac
++;
727 XtSetArg (av
[ac
], XtNresizable
, True
); ac
++;
729 if (DefaultDepthOfScreen (XtScreen (dialog
)) >= 16)
731 /* Turn of dithered shadow if we can. Looks bad */
732 XtSetArg (av
[ac
], "beNiceToColormap", False
); ac
++;
735 sprintf (button_name
, "button%d", ++bc
);
736 button
= XtCreateManagedWidget (button_name
, commandWidgetClass
,
741 fill_xft_data (&instance
->xft_data
[bc
], button
, xft_font
);
742 XtOverrideTranslations (button
, button_override
);
751 xaw_create_dialog (instance
)
752 widget_instance
* instance
;
754 char *name
= instance
->info
->type
;
755 Widget parent
= instance
->parent
;
757 Boolean pop_up_p
= instance
->pop_up_p
;
758 char *shell_name
= 0;
760 Boolean text_input_slot
= False
;
761 Boolean radio_box
= False
;
762 Boolean list
= False
;
764 int left_buttons
= 0;
765 int right_buttons
= 1;
769 icon_name
= "dbox-error";
770 shell_name
= "Error";
774 icon_name
= "dbox-info";
775 shell_name
= "Information";
780 icon_name
= "dbox-question";
781 shell_name
= "Prompt";
785 text_input_slot
= True
;
786 icon_name
= "dbox-question";
787 shell_name
= "Prompt";
791 icon_name
= "dbox-question";
792 shell_name
= "Question";
796 total_buttons
= name
[1] - '0';
798 if (name
[3] == 'T' || name
[3] == 't')
800 text_input_slot
= False
;
804 right_buttons
= name
[4] - '0';
806 left_buttons
= total_buttons
- right_buttons
;
808 widget
= make_dialog (name
, parent
, pop_up_p
,
809 shell_name
, icon_name
, text_input_slot
, radio_box
,
810 list
, left_buttons
, right_buttons
, instance
);
816 xaw_generic_callback (widget
, closure
, call_data
)
821 widget_instance
*instance
= (widget_instance
*) closure
;
822 Widget instance_widget
;
826 lw_internal_update_other_instances (widget
, closure
, call_data
);
830 if (widget
->core
.being_destroyed
)
833 instance_widget
= instance
->widget
;
834 if (!instance_widget
)
837 id
= instance
->info
->id
;
841 XtVaGetValues (widget
, XtNuserData
, &user_data
, NULL
);
843 /* Damn! Athena doesn't give us a way to hang our own data on the
844 buttons, so we have to go find it... I guess this assumes that
845 all instances of a button have the same call data. */
847 widget_value
*val
= instance
->info
->val
->contents
;
848 char *name
= XtName (widget
);
851 if (val
->name
&& !strcmp (val
->name
, name
))
856 user_data
= val
->call_data
;
860 if (instance
->info
->selection_cb
)
861 instance
->info
->selection_cb (widget
, id
, user_data
);
865 wm_delete_window (w
, closure
, call_data
)
874 Widget widget
, shell
;
876 if (XtIsSubclass (w
, dialogWidgetClass
))
877 shell
= XtParent (w
);
881 if (! XtIsSubclass (shell
, shellWidgetClass
))
883 XtVaGetValues (shell
, XtNnumChildren
, &nkids
, NULL
);
884 XtVaGetValues (shell
, XtNchildren
, &kids
, NULL
);
887 for (i
= 0; i
< nkids
; i
++)
890 if (XtIsSubclass (widget
, dialogWidgetClass
))
893 id
= lw_get_widget_id (widget
);
897 widget_info
*info
= lw_get_widget_info (id
);
898 if (! info
) abort ();
899 if (info
->selection_cb
)
900 info
->selection_cb (widget
, id
, (XtPointer
) -1);
903 lw_destroy_all_widgets (id
);
911 xaw_scrollbar_scroll (widget
, closure
, call_data
)
916 widget_instance
*instance
= (widget_instance
*) closure
;
918 scroll_event event_data
;
920 if (!instance
|| widget
->core
.being_destroyed
)
923 id
= instance
->info
->id
;
924 event_data
.slider_value
= 0;
927 if ((int) call_data
> 0)
928 event_data
.action
= SCROLLBAR_PAGE_DOWN
;
930 event_data
.action
= SCROLLBAR_PAGE_UP
;
932 if (instance
->info
->pre_activate_cb
)
933 instance
->info
->pre_activate_cb (widget
, id
, (XtPointer
) &event_data
);
939 xaw_scrollbar_jump (widget
, closure
, call_data
)
944 widget_instance
*instance
= (widget_instance
*) closure
;
946 scroll_event event_data
;
947 scrollbar_values
*val
=
948 (scrollbar_values
*) instance
->info
->val
->scrollbar_data
;
951 if (!instance
|| widget
->core
.being_destroyed
)
954 id
= instance
->info
->id
;
956 percent
= * (float *) call_data
;
957 event_data
.slider_value
=
958 (int) (percent
* (float) (val
->maximum
- val
->minimum
)) + val
->minimum
;
961 event_data
.action
= SCROLLBAR_DRAG
;
963 if (instance
->info
->pre_activate_cb
)
964 instance
->info
->pre_activate_cb (widget
, id
, (XtPointer
) &event_data
);
969 xaw_create_scrollbar (instance
)
970 widget_instance
*instance
;
978 XtVaGetValues (instance
->parent
, XtNwidth
, &width
, NULL
);
980 XtSetArg (av
[ac
], XtNshowGrip
, 0); ac
++;
981 XtSetArg (av
[ac
], XtNresizeToPreferred
, 1); ac
++;
982 XtSetArg (av
[ac
], XtNallowResize
, True
); ac
++;
983 XtSetArg (av
[ac
], XtNskipAdjust
, True
); ac
++;
984 XtSetArg (av
[ac
], XtNwidth
, width
); ac
++;
985 XtSetArg (av
[ac
], XtNmappedWhenManaged
, True
); ac
++;
988 XtCreateWidget (instance
->info
->name
, scrollbarWidgetClass
,
989 instance
->parent
, av
, ac
);
991 /* We have to force the border width to be 0 otherwise the
992 geometry manager likes to start looping for awhile... */
993 XtVaSetValues (scrollbar
, XtNborderWidth
, 0, NULL
);
995 XtRemoveAllCallbacks (scrollbar
, "jumpProc");
996 XtRemoveAllCallbacks (scrollbar
, "scrollProc");
998 XtAddCallback (scrollbar
, "jumpProc", xaw_scrollbar_jump
,
999 (XtPointer
) instance
);
1000 XtAddCallback (scrollbar
, "scrollProc", xaw_scrollbar_scroll
,
1001 (XtPointer
) instance
);
1010 xaw_create_main (instance
)
1011 widget_instance
*instance
;
1016 /* Create a vertical Paned to hold menubar */
1018 XtSetArg (al
[ac
], XtNborderWidth
, 0); ac
++;
1019 return XtCreateWidget (instance
->info
->name
, panedWidgetClass
,
1020 instance
->parent
, al
, ac
);
1023 widget_creation_entry
1024 xaw_creation_table
[] =
1026 {"scrollbar", xaw_create_scrollbar
},
1027 {"main", xaw_create_main
},
1031 /* arch-tag: fbbd3589-ae1c-41a0-9142-f628cfee6564
1032 (do not change this comment) */