Repeater.c revision 7a84e134
1/*
2 * $Xorg: Repeater.c,v 1.4 2001/02/09 02:03:45 xorgcvs Exp $
3 *
4Copyright 1990, 1994, 1998  The Open Group
5
6Permission to use, copy, modify, distribute, and sell this software and its
7documentation for any purpose is hereby granted without fee, provided that
8the above copyright notice appear in all copies and that both that
9copyright notice and this permission notice appear in supporting
10documentation.
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
18OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22Except as contained in this notice, the name of The Open Group shall not be
23used in advertising or otherwise to promote the sale, use or other dealings
24in this Software without prior written authorization from The Open Group.
25 *
26 * Author:  Jim Fulton, MIT X Consortium
27 *
28 * This widget is used for press-and-hold style buttons.
29 */
30/* $XFree86: xc/lib/Xaw/Repeater.c,v 1.6 2001/01/17 19:42:29 dawes Exp $ */
31
32#ifdef HAVE_CONFIG_H
33#include <config.h>
34#endif
35#include <X11/IntrinsicP.h>
36#include <X11/StringDefs.h>
37#include <X11/Xaw/RepeaterP.h>
38#include <X11/Xaw/XawInit.h>
39
40#define DO_CALLBACK(rw) \
41XtCallCallbackList((Widget)rw, rw->command.callbacks, NULL)
42
43#define ADD_TIMEOUT(rw, delay)					\
44XtAppAddTimeOut(XtWidgetToApplicationContext((Widget)rw),	\
45		delay, tic, (XtPointer)rw)
46
47#define CLEAR_TIMEOUT(rw) \
48if ((rw)->repeater.timer) {			\
49    XtRemoveTimeOut((rw)->repeater.timer);	\
50    (rw)->repeater.timer = 0;			\
51}
52
53/*
54 * Class Methods
55 */
56static void XawRepeaterInitialize(Widget, Widget, ArgList, Cardinal*);
57static void XawRepeaterDestroy(Widget);
58static Boolean XawRepeaterSetValues(Widget, Widget, Widget,
59				    ArgList, Cardinal*);
60
61/*
62 * Prototypes
63 */
64static void tic(XtPointer, XtIntervalId*);
65
66/*
67 * Actions
68 */
69static void ActionStart(Widget, XEvent*, String*, Cardinal*);
70static void ActionStop(Widget, XEvent*, String*, Cardinal*);
71
72/*
73 * Initialization
74 */
75static char defaultTranslations[] =
76"<Enter>:"	"highlight()\n"
77"<Leave>:"	"unhighlight()\n"
78"<Btn1Down>:"	"set() start()\n"
79"<Btn1Up>:"	"stop() unset()\n"
80;
81
82static XtActionsRec actions[] = {
83  {"start",	ActionStart},
84  {"stop",	ActionStop},
85};
86
87#define offset(field)	XtOffsetOf(RepeaterRec, repeater.field)
88static XtResource resources[] = {
89  {
90    XtNdecay,
91    XtCDecay,
92    XtRInt,
93    sizeof(int),
94    offset(decay),
95    XtRImmediate,
96    (XtPointer)REP_DEF_DECAY
97  },
98  {
99    XtNinitialDelay,
100    XtCDelay,
101    XtRInt,
102    sizeof(int),
103    offset(initial_delay),
104    XtRImmediate,
105    (XtPointer)REP_DEF_INITIAL_DELAY
106  },
107  {
108    XtNminimumDelay,
109    XtCMinimumDelay,
110    XtRInt,
111    sizeof(int),
112    offset(minimum_delay),
113    XtRImmediate,
114    (XtPointer)REP_DEF_MINIMUM_DELAY
115  },
116  {
117    XtNrepeatDelay,
118    XtCDelay,
119    XtRInt,
120    sizeof(int),
121    offset(repeat_delay),
122    XtRImmediate,
123    (XtPointer)REP_DEF_REPEAT_DELAY
124  },
125  {
126    XtNflash,
127    XtCBoolean,
128    XtRBoolean,
129    sizeof(Boolean),
130    offset(flash),
131    XtRImmediate,
132    (XtPointer)False
133  },
134  {
135    XtNstartCallback,
136    XtCStartCallback,
137    XtRCallback,
138    sizeof(XtPointer),
139    offset(start_callbacks),
140    XtRImmediate,
141    NULL
142  },
143  {
144    XtNstopCallback,
145    XtCStopCallback,
146    XtRCallback,
147    sizeof(XtPointer),
148    offset(stop_callbacks),
149    XtRImmediate,
150    NULL
151  },
152};
153#undef offset
154
155#define Superclass	(&commandClassRec)
156RepeaterClassRec repeaterClassRec = {
157  /* core */
158  {
159    (WidgetClass)Superclass,		/* superclass */
160    "Repeater",				/* class_name */
161    sizeof(RepeaterRec),		/* widget_size */
162    XawInitializeWidgetSet,		/* class_initialize */
163    NULL,				/* class_part_initialize */
164    False,				/* class_inited */
165    XawRepeaterInitialize,		/* initialize */
166    NULL,				/* initialize_hook */
167    XtInheritRealize,			/* realize */
168    actions,				/* actions */
169    XtNumber(actions),			/* num_actions */
170    resources,				/* resources */
171    XtNumber(resources),		/* num_resources */
172    NULLQUARK,				/* xrm_class */
173    True,				/* compress_motion */
174    True,				/* compress_exposure */
175    True,				/* compress_enterleave */
176    False,				/* visible_interest */
177    XawRepeaterDestroy,			/* destroy */
178    XtInheritResize,			/* resize */
179    XtInheritExpose,			/* expose */
180    XawRepeaterSetValues,		/* set_values */
181    NULL,				/* set_values_hook */
182    XtInheritSetValuesAlmost,		/* set_values_almost */
183    NULL,				/* get_values_hook */
184    NULL,				/* accept_focus */
185    XtVersion,				/* version */
186    NULL,				/* callback_private */
187    defaultTranslations,		/* tm_table */
188    XtInheritQueryGeometry,		/* query_geometry */
189    XtInheritDisplayAccelerator,	/* display_accelerator */
190    NULL,				/* extension */
191  },
192  /* simple */
193  {
194    XtInheritChangeSensitive,		/* change_sensitive */
195  },
196  /* label */
197  {
198    NULL,				/* extension */
199  },
200  /* command */
201  {
202    NULL,				/* extension */
203  },
204  /* repeater */
205  {
206    NULL,				/* extension */
207  },
208};
209
210WidgetClass repeaterWidgetClass = (WidgetClass) &repeaterClassRec;
211
212
213/*
214 * Implementation
215 */
216/*ARGSUSED*/
217static void
218tic(XtPointer client_data, XtIntervalId *id)
219{
220    RepeaterWidget rw = (RepeaterWidget)client_data;
221
222    rw->repeater.timer = 0;		/* timer is removed */
223    if (rw->repeater.flash) {
224	Widget w = (Widget)rw;
225
226	XClearWindow(XtDisplay(w), XtWindow(w));
227	XtCallActionProc(w, "reset", NULL, NULL, 0);
228	XClearWindow(XtDisplay(w), XtWindow(w));
229	XtCallActionProc(w, "set", NULL, NULL, 0);
230    }
231    DO_CALLBACK(rw);
232
233    rw->repeater.timer = ADD_TIMEOUT(rw, rw->repeater.next_delay);
234
235    if (rw->repeater.decay) {
236	rw->repeater.next_delay -= rw->repeater.decay;
237	if (rw->repeater.next_delay < rw->repeater.minimum_delay)
238	    rw->repeater.next_delay = rw->repeater.minimum_delay;
239    }
240}
241
242/*ARGSUSED*/
243static void
244XawRepeaterInitialize(Widget greq, Widget gnew,
245		      ArgList args, Cardinal *num_args)
246{
247    RepeaterWidget cnew = (RepeaterWidget)gnew;
248
249    if (cnew->repeater.minimum_delay < 0)
250	cnew->repeater.minimum_delay = 0;
251    cnew->repeater.timer = 0;
252}
253
254static void
255XawRepeaterDestroy(Widget gw)
256{
257    CLEAR_TIMEOUT((RepeaterWidget)gw);
258}
259
260/*ARGSUSED*/
261static Boolean
262XawRepeaterSetValues(Widget gcur, Widget greq, Widget gnew,
263		     ArgList args, Cardinal *num_args)
264{
265    RepeaterWidget cur = (RepeaterWidget)gcur;
266    RepeaterWidget cnew = (RepeaterWidget)gnew;
267
268    if (cur->repeater.minimum_delay != cnew->repeater.minimum_delay) {
269	if (cnew->repeater.next_delay < cnew->repeater.minimum_delay)
270	    cnew->repeater.next_delay = cnew->repeater.minimum_delay;
271    }
272
273    return (False);
274}
275
276/*ARGSUSED*/
277static void
278ActionStart(Widget gw, XEvent *event, String *params, Cardinal *num_params)
279{
280    RepeaterWidget rw = (RepeaterWidget)gw;
281
282    CLEAR_TIMEOUT(rw);
283    if (rw->repeater.start_callbacks)
284	XtCallCallbackList(gw, rw->repeater.start_callbacks, NULL);
285
286    DO_CALLBACK(rw);
287    rw->repeater.timer = ADD_TIMEOUT(rw, rw->repeater.initial_delay);
288    rw->repeater.next_delay = rw->repeater.repeat_delay;
289}
290
291/*ARGSUSED*/
292static void
293ActionStop(Widget gw, XEvent *event, String *params, Cardinal *num_params)
294{
295    RepeaterWidget rw = (RepeaterWidget)gw;
296
297    CLEAR_TIMEOUT((RepeaterWidget)gw);
298    if (rw->repeater.stop_callbacks)
299	XtCallCallbackList(gw, rw->repeater.stop_callbacks, NULL);
300}
301