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