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