lightweight X11 utility to dim the screen and/or keyboard backlight when idle
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

lots of cleanup, fix XSync bug in backlight_op

- use float instead of double, we don't need the extra precision
- eliminate dim() and brighten(), just call stepper() directly
- simplify XSyncAlarm setting and resetting
- primarily use XPeekEvent instead of XNextEvent so when we break
out of stepper(), the alarm event is still on the queue waiting to
be read and processed
- in backlight_op, don't discard events in the XSync call; this is
what was making it randomly not notice the idle timer resetting
until stepper was done and the idle alarm reset

+147 -218
+147 -218
xdimmer.c
··· 1 1 /* 2 2 * xdimmer 3 - * Copyright (c) 2013-2017 joshua stein <jcs@jcs.org> 3 + * Copyright (c) 2013-2019 joshua stein <jcs@jcs.org> 4 4 * 5 5 * Redistribution and use in source and binary forms, with or without 6 6 * modification, are permitted provided that the following conditions ··· 30 30 #include <getopt.h> 31 31 #include <limits.h> 32 32 #include <math.h> 33 + #include <poll.h> 33 34 #include <signal.h> 34 35 #include <stdio.h> 35 36 #include <stdlib.h> ··· 54 55 #define DEFAULT_DIM_TIMEOUT 120 55 56 #define DEFAULT_DIM_PERCENTAGE 10 56 57 57 - #define DIM_STEPS 20 58 - #define BRIGHTEN_STEPS 5 58 + #define DEFAULT_DIM_STEPS 20 59 + #define DEFAULT_BRIGHTEN_STEPS 5 59 60 60 61 enum { 61 62 OP_GET, ··· 68 69 int backlight; 69 70 int kbd_backlight; 70 71 } als_settings[] = { 71 - /* scene min lux screen kbd */ 72 + /* scene min lux screen kbd */ 72 73 { "pitch black", 0, 20, 80 }, 73 74 { "very dark", 11, 30, 70 }, 74 75 { "dark indoors", 51, 40, 60 }, ··· 81 82 }; 82 83 83 84 void xloop(void); 84 - void set_alarm(XSyncAlarm *, XSyncCounter, XSyncTestType, XSyncValue); 85 - void dim(void); 86 - void brighten(void); 85 + void set_alarm(XSyncAlarm *, XSyncTestType, unsigned long); 87 86 void bail(int); 88 - void stepper(double, double, int); 89 - double backlight_op(int, double); 90 - double kbd_backlight_op(int, double); 87 + void stepper(float, float, int, int); 88 + float backlight_op(int, float); 89 + float kbd_backlight_op(int, float); 91 90 int als_find_sensor(void); 92 91 void als_fetch(void); 93 92 void usage(void); 94 - int XNextEventOrTimeout(Display *, XEvent *, unsigned int); 93 + int XPeekEventOrTimeout(Display *, XEvent *, unsigned int); 95 94 96 95 extern char *__progname; 97 96 98 - static double als = -1; 99 - static double backlight = -1; 100 - static Atom backlight_a = 0; 101 - static int dimkbd = 0; 97 + /* options */ 98 + static int dim_kbd = 0; 102 99 static int dimmed = 0; 103 - static int dimscreen = 1; 104 - static int useals = 0; 105 - static int exiting = 0; 106 - static double kbd_backlight = -1; 100 + static int dim_screen = 1; 101 + static int use_als = 0; 102 + 103 + /* ALS reading */ 104 + static float als = -1; 107 105 108 - static int debug = 0; 109 - #define DPRINTF(x) { if (debug) { printf x; } }; 106 + /* backlight reading and target while dimming/undimming */ 107 + static float backlight = -1; 108 + static float kbd_backlight = -1; 110 109 111 110 static int dim_timeout = DEFAULT_DIM_TIMEOUT; 112 111 static int dim_pct = DEFAULT_DIM_PERCENTAGE; 113 - static int dim_steps = DIM_STEPS; 112 + static int dim_steps = DEFAULT_DIM_STEPS; 113 + 114 + static Atom backlight_a = 0; 115 + static XSyncCounter idler_counter = 0; 116 + static int exiting = 0; 117 + static int debug = 0; 118 + #define DPRINTF(x) { if (debug) { printf x; } }; 114 119 115 120 #ifdef __OpenBSD__ 116 121 static int wsconsdfd = 0; ··· 134 139 errx(1, "ambient light sensors not supported on this " 135 140 "platform"); 136 141 #endif 137 - useals = 1; 142 + use_als = 1; 138 143 break; 139 144 case 'd': 140 145 debug = 1; ··· 144 149 errx(1, "keyboard backlight not supported on this " 145 150 "platform"); 146 151 #endif 147 - dimkbd = 1; 152 + dim_kbd = 1; 148 153 break; 149 154 case 'n': 150 - dimscreen = 0; 155 + dim_screen = 0; 151 156 break; 152 157 case 'p': 153 158 dim_pct = strtonum(optarg, 1, 100, &errstr); ··· 171 176 argc -= optind; 172 177 argv += optind; 173 178 174 - if (!dimscreen && !dimkbd && !useals) 179 + if (!dim_screen && !dim_kbd && !use_als) 175 180 errx(1, "not dimming screen or keyboard, nothing to do"); 176 181 177 182 if (!(dpy = XOpenDisplay(NULL))) 178 183 errx(1, "can't open display %s", XDisplayName(NULL)); 179 184 180 - if (dimscreen || useals) { 185 + if (dim_screen || use_als) { 181 186 backlight_a = XInternAtom(dpy, RR_PROPERTY_BACKLIGHT, True); 182 187 if (backlight_a == None) { 183 188 #ifdef __OpenBSD__ ··· 190 195 } 191 196 192 197 #ifdef __OpenBSD__ 193 - if (dimkbd) 198 + if (dim_kbd) 194 199 if (!(wsconskfd = open("/dev/wskbd0", O_WRONLY)) || 195 200 kbd_backlight_op(OP_GET, 0) < 0) 196 201 errx(1, "no keyboard backlight control"); 197 202 198 - if (useals && !als_find_sensor()) 203 + if (use_als && !als_find_sensor()) 199 204 errx(1, "can't find ambient light sensor"); 200 205 #endif 201 206 202 - if (dimscreen) 207 + if (dim_screen) 203 208 DPRINTF(("dimming screen to %d%% in %d secs\n", dim_pct, 204 209 dim_timeout)); 205 - if (dimkbd) 210 + if (dim_kbd) 206 211 DPRINTF(("dimming keyboard backlight in %d secs\n", 207 212 dim_timeout)); 208 - if (useals) 213 + if (use_als) 209 214 DPRINTF(("automatically updating brightness from ALS\n")); 210 215 211 216 signal(SIGINT, bail); ··· 213 218 214 219 xloop(); 215 220 216 - return (0); 221 + return 0; 217 222 } 218 223 219 224 void ··· 222 227 XSyncSystemCounter *counters; 223 228 XSyncAlarm idle_alarm = None; 224 229 XSyncAlarm reset_alarm = None; 225 - XSyncValue val; 226 230 int sync_event, error; 227 - int sync_major, sync_minor, ncounters, idler = 0; 231 + int major, minor, ncounters; 228 232 int i; 229 233 230 234 if (XSyncQueryExtension(dpy, &sync_event, &error) != True) 231 235 errx(1, "no sync extension available"); 232 236 233 - XSyncInitialize(dpy, &sync_major, &sync_minor); 237 + XSyncInitialize(dpy, &major, &minor); 234 238 235 239 counters = XSyncListSystemCounters(dpy, &ncounters); 236 - for (i = 0; i < ncounters; i++) 240 + for (i = 0; i < ncounters; i++) { 237 241 if (!strcmp(counters[i].name, "IDLETIME")) { 238 - idler = counters[i].counter; 242 + idler_counter = counters[i].counter; 239 243 break; 240 244 } 245 + } 241 246 XSyncFreeSystemCounterList(counters); 242 247 243 - if (!idler) 248 + if (!idler_counter) 244 249 errx(1, "no idle counter"); 245 250 246 251 /* 247 - * fire an XSyncAlarmNotifyEvent when idletime counter reaches our 252 + * fire an XSyncAlarmNotifyEvent when IDLETIME counter reaches 248 253 * dim_timeout seconds 249 254 */ 250 - XSyncIntToValue(&val, dim_timeout * 1000); 251 - set_alarm(&idle_alarm, idler, XSyncPositiveComparison, val); 252 - 253 - if (dimscreen || useals) 254 - backlight = backlight_op(OP_GET, 0); 255 - if (dimkbd) 256 - kbd_backlight = kbd_backlight_op(OP_GET, 0); 255 + set_alarm(&idle_alarm, XSyncPositiveComparison, dim_timeout * 1000); 257 256 258 257 for (;;) { 259 258 XEvent e; 260 259 XSyncAlarmNotifyEvent *alarm_e; 261 - int overflow; 262 - XSyncValue add, plusone; 263 260 264 - if (exiting) { 265 - brighten(); 266 - exit(0); 267 - } 261 + if (exiting) 262 + break; 268 263 269 264 DPRINTF(("waiting for next event\n")); 270 265 271 266 /* if we're checking an als, only wait 1 second for x event */ 272 - XNextEventOrTimeout(dpy, &e, (useals ? 1000 : 0)); 273 - 274 - if (e.type == 0) { 275 - if (useals && !dimmed) 267 + if (XPeekEventOrTimeout(dpy, &e, (use_als ? 1000 : 0)) == 0) { 268 + if (use_als && !dimmed) 276 269 als_fetch(); 277 - 278 270 continue; 279 271 } 280 272 281 - if (!dimscreen && !dimkbd) 273 + XNextEvent(dpy, &e); 274 + 275 + if (!dim_screen && !dim_kbd) 282 276 continue; 283 277 284 - if (e.type != sync_event + XSyncAlarmNotify) { 278 + if (e.type != (sync_event + XSyncAlarmNotify)) { 285 279 DPRINTF(("got event of type %d\n", e.type)); 286 280 continue; 287 281 } ··· 289 283 alarm_e = (XSyncAlarmNotifyEvent *)&e; 290 284 291 285 if (alarm_e->alarm == idle_alarm) { 292 - DPRINTF(("idle counter reached %dms\n", 286 + DPRINTF(("idle counter reached %dms, dimming\n", 293 287 XSyncValueLow32(alarm_e->counter_value))); 294 288 295 - XSyncDestroyAlarm(dpy, idle_alarm); 296 - idle_alarm = None; 289 + /* fire reset_alarm when idle counter resets */ 290 + set_alarm(&reset_alarm, XSyncNegativeComparison, 291 + (dim_timeout * 1000) - 1); 297 292 298 - /* 299 - * fire reset_alarm when idletime counter resets, but 300 - * set it up before dimming so we can break from 301 - * dimming early if movement is detected 302 - */ 303 - if (reset_alarm != None) { 304 - XSyncDestroyAlarm(dpy, reset_alarm); 305 - reset_alarm = None; 306 - } 307 - XSyncIntToValue(&add, -1); 308 - XSyncValueAdd(&plusone, alarm_e->counter_value, add, 309 - &overflow); 310 - set_alarm(&reset_alarm, idler, XSyncNegativeComparison, 311 - plusone); 293 + if (dim_screen) 294 + backlight = backlight_op(OP_GET, 0); 295 + if (dim_kbd) 296 + kbd_backlight = kbd_backlight_op(OP_GET, 0); 312 297 313 - dim(); 298 + stepper(dim_pct, 0, dim_steps, 1); 299 + dimmed = 1; 314 300 315 - XSyncDestroyAlarm(dpy, reset_alarm); 316 - reset_alarm = None; 317 - set_alarm(&reset_alarm, idler, XSyncNegativeComparison, 318 - plusone); 301 + set_alarm(&reset_alarm, XSyncNegativeComparison, 302 + (dim_timeout * 1000) - 1); 319 303 } 320 304 else if (alarm_e->alarm == reset_alarm) { 321 - DPRINTF(("idle counter reset\n")); 305 + DPRINTF(("idle counter reset, brightening\n")); 322 306 323 - XSyncDestroyAlarm(dpy, reset_alarm); 324 - reset_alarm = None; 325 - 326 - if (useals) 307 + if (use_als) 327 308 als_fetch(); 328 309 329 - brighten(); 310 + set_alarm(&idle_alarm, XSyncPositiveComparison, 311 + dim_timeout * 1000); 330 312 331 - XSyncIntToValue(&val, dim_timeout * 1000); 332 - set_alarm(&idle_alarm, idler, XSyncPositiveComparison, 333 - val); 313 + stepper(backlight, kbd_backlight, DEFAULT_BRIGHTEN_STEPS, 314 + 0); 315 + dimmed = 0; 334 316 } 335 317 } 318 + 319 + DPRINTF(("restoring backlight to %f / %f before exiting\n", backlight, 320 + kbd_backlight)); 321 + stepper(backlight, kbd_backlight, 1, 0); 336 322 } 337 323 338 324 void 339 - set_alarm(XSyncAlarm *alarm, XSyncCounter counter, XSyncTestType test, 340 - XSyncValue value) 325 + set_alarm(XSyncAlarm *alarm, XSyncTestType test, unsigned long seconds) 341 326 { 342 327 XSyncAlarmAttributes attr; 343 - XSyncValue delta; 344 328 unsigned int flags; 345 329 346 - XSyncIntToValue (&delta, 0); 347 - 348 - attr.trigger.counter = counter; 330 + attr.trigger.counter = idler_counter; 349 331 attr.trigger.value_type = XSyncAbsolute; 350 332 attr.trigger.test_type = test; 351 - attr.trigger.wait_value = value; 352 - attr.delta = delta; 333 + XSyncIntToValue(&attr.trigger.wait_value, seconds); 334 + XSyncIntToValue(&attr.delta, 0); 353 335 354 - flags = XSyncCACounter | XSyncCAValueType | XSyncCATestType | 355 - XSyncCAValue | XSyncCADelta; 336 + flags = XSyncCACounter | XSyncCATestType | XSyncCAValue | XSyncCADelta; 356 337 357 338 if (*alarm) 358 - XSyncChangeAlarm(dpy, *alarm, flags, &attr); 359 - else 360 - *alarm = XSyncCreateAlarm(dpy, flags, &attr); 361 - } 339 + XSyncDestroyAlarm(dpy, *alarm); 362 340 363 - void 364 - dim(void) 365 - { 366 - if (dimscreen) 367 - backlight = backlight_op(OP_GET, 0); 368 - if (dimkbd) 369 - kbd_backlight = kbd_backlight_op(OP_GET, 0); 370 - 371 - if (((dimscreen || useals) && (backlight > dim_pct)) || 372 - (dimkbd && (kbd_backlight > 0))) { 373 - if (dimscreen) 374 - DPRINTF(("dimming screen to %d\n", dim_pct)); 375 - if (dimkbd) 376 - DPRINTF(("dimming keyboard\n")); 377 - 378 - stepper(dim_pct, 0, dim_steps); 379 - dimmed = 1; 380 - } 381 - else if (dimscreen) 382 - DPRINTF(("backlight already at %f, not dimming to %d\n", 383 - backlight, dim_pct)); 341 + *alarm = XSyncCreateAlarm(dpy, flags, &attr); 384 342 } 385 343 386 344 void 387 - brighten(void) 345 + stepper(float new_backlight, float new_kbd_backlight, int steps, int inter) 388 346 { 389 - if (dimmed) { 390 - if (dimscreen || useals) 391 - DPRINTF(("brightening screen back to %f\n", backlight)); 392 - if (dimkbd) 393 - DPRINTF(("brightening keyboard\n")); 394 - 395 - stepper(backlight, kbd_backlight, BRIGHTEN_STEPS); 396 - } 397 - else 398 - DPRINTF(("no previous backlight setting, not brightening\n")); 399 - 400 - dimmed = 0; 401 - } 402 - 403 - void 404 - stepper(double new_backlight, double new_kbd_backlight, int steps) 405 - { 406 - double tbacklight = 0; 407 - double tkbdbacklight = 0; 408 - double step_inc = 0, kbd_step_inc = 0; 347 + float tbacklight, tkbd_backlight; 348 + float step_inc = 0, kbd_step_inc = 0; 409 349 int j; 410 350 411 - if (dimscreen || useals) { 351 + if (dim_screen) { 412 352 tbacklight = backlight_op(OP_GET, 0); 413 - 414 - if ((int)new_backlight != (int)tbacklight) 353 + if (((int)new_backlight != (int)tbacklight)) 415 354 step_inc = (new_backlight - tbacklight) / steps; 416 355 } 417 - if (dimkbd) { 418 - tkbdbacklight = kbd_backlight_op(OP_GET, 0); 419 356 420 - if ((int)new_kbd_backlight != (int)tkbdbacklight) 421 - kbd_step_inc = (new_kbd_backlight - tkbdbacklight) / 357 + if (dim_kbd) { 358 + tkbd_backlight = kbd_backlight_op(OP_GET, 0); 359 + if ((int)new_kbd_backlight != (int)tkbd_backlight) 360 + kbd_step_inc = (new_kbd_backlight - tkbd_backlight) / 422 361 steps; 423 362 } 424 363 425 - if (!(step_inc || kbd_step_inc)) 364 + if (!step_inc && !kbd_step_inc) 426 365 return; 427 366 428 - if (dimscreen || useals) 367 + if (dim_screen || use_als) 429 368 DPRINTF(("stepping from %0.2f to %0.2f in increments of %f " 430 - "(%d step%s)\n", tbacklight, new_backlight, step_inc, 431 - steps, (steps == 1 ? "" : "s"))); 369 + "(%d step%s)\n", tbacklight, new_backlight, step_inc, steps, 370 + (steps == 1 ? "" : "s"))); 432 371 433 - if (dimkbd) 372 + if (dim_kbd) 434 373 DPRINTF(("stepping keyboard from %0.2f to %0.2f in increments " 435 - "of %f (%d step%s)\n", tkbdbacklight, new_kbd_backlight, 374 + "of %f (%d step%s)\n", tkbd_backlight, new_kbd_backlight, 436 375 kbd_step_inc, steps, (steps == 1 ? "" : "s"))); 437 376 438 - /* discard any stale events */ 377 + /* discard any stale alarm events */ 439 378 XSync(dpy, True); 440 379 441 380 for (j = 1; j <= steps; j++) { 442 381 XEvent e; 443 382 444 - if (dimscreen || useals) 445 - tbacklight += step_inc; 446 - if (dimkbd) 447 - tkbdbacklight += kbd_step_inc; 448 - 449 - if (j == steps) { 450 - if (dimscreen || useals) 383 + if (dim_screen || use_als) { 384 + if (j == steps) 451 385 tbacklight = new_backlight; 452 - if (dimkbd) 453 - tkbdbacklight = new_kbd_backlight; 454 - } 386 + else 387 + tbacklight += step_inc; 455 388 456 - if (dimscreen || useals) 457 389 backlight_op(OP_SET, tbacklight); 458 - if (dimkbd) 459 - kbd_backlight_op(OP_SET, tkbdbacklight); 390 + } 460 391 461 - /* only slow down steps if we're dimming */ 462 - if (j < steps && (((dimscreen || useals) && (step_inc < 0)) || 463 - (dimkbd && (kbd_step_inc < 0)))) 464 - usleep(steps > 50 ? 10000 : 25000); 392 + if (dim_kbd) { 393 + if (j == steps) 394 + tkbd_backlight = new_kbd_backlight; 395 + else 396 + tkbd_backlight += kbd_step_inc; 465 397 466 - if (XNextEventOrTimeout(dpy, &e, 1) && e.type != 0) { 467 - DPRINTF(("%s: %d event while stepping, breaking " 468 - "early\n", __func__, e.type)); 398 + kbd_backlight_op(OP_SET, tkbd_backlight); 399 + } 469 400 401 + if (inter && XPeekEventOrTimeout(dpy, &e, 1) != 0) { 402 + DPRINTF(("%s: X event of type %d while stepping, " 403 + "breaking early\n", __func__, e.type)); 470 404 return; 471 405 } 472 406 } 473 407 } 474 408 475 - double 476 - backlight_op(int op, double new_backlight) 409 + float 410 + backlight_op(int op, float new_backlight) 477 411 { 478 412 Atom actual_type; 479 413 int actual_format; ··· 482 416 unsigned char *prop; 483 417 XRRPropertyInfo *info; 484 418 long value, to; 485 - double min, max; 419 + float min, max; 486 420 int i; 487 421 488 - double cur_backlight = -1.0; 422 + float cur_backlight = -1.0; 489 423 490 424 if (backlight_a == None) { 491 425 #ifdef __OpenBSD__ ··· 500 434 err(1, "WSDISPLAYIO_GETPARAM failed"); 501 435 502 436 if (op == OP_SET) { 503 - param.curval = (double)(param.max - param.min) * 437 + param.curval = (float)(param.max - param.min) * 504 438 (new_backlight / 100.0); 505 439 506 440 if (param.curval > param.max) ··· 512 446 err(1, "WSDISPLAYIO_SETPARAM failed"); 513 447 } 514 448 515 - cur_backlight = ((double)param.curval / 516 - (double)(param.max - param.min)) * 100; 449 + cur_backlight = ((float)param.curval / 450 + (float)(param.max - param.min)) * 100; 517 451 #endif 518 452 } else { 519 453 if (op == OP_SET) ··· 527 461 528 462 for (i = 0; i < screen_res->noutput; i++) { 529 463 RROutput output = screen_res->outputs[i]; 530 - 531 - /* yay magic numbers */ 532 464 533 465 if (XRRGetOutputProperty(dpy, output, backlight_a, 534 466 0, 4, False, False, None, &actual_type, ··· 573 505 backlight_a, XA_INTEGER, 32, 574 506 PropModeReplace, 575 507 (unsigned char *)&to, 1); 576 - XSync(dpy, True); 508 + XSync(dpy, False); 577 509 } 578 510 else 579 511 /* just return the first screen's backlight */ ··· 589 521 return cur_backlight; 590 522 } 591 523 592 - double 593 - kbd_backlight_op(int op, double new_backlight) 524 + float 525 + kbd_backlight_op(int op, float new_backlight) 594 526 { 595 527 #ifdef __OpenBSD__ 596 528 struct wskbd_backlight param; ··· 601 533 if (op == OP_SET) { 602 534 DPRINTF(("%s: %f\n", __func__, new_backlight)); 603 535 604 - param.curval = (double)(param.max - param.min) * 605 - (new_backlight / 100.0); 536 + param.curval = (float)(param.max - param.min) * 537 + (new_backlight / 100.0); 606 538 607 539 if (param.curval > param.max) 608 540 param.curval = param.max; ··· 613 545 err(1, "WSKBDIO_SETBACKLIGHT failed"); 614 546 } 615 547 616 - return ((double)param.curval / (double)(param.max - param.min)) * 100; 548 + return ((float)param.curval / (float)(param.max - param.min)) * 100; 617 549 #else 618 550 return 0; 619 551 #endif ··· 674 606 struct sensordev sensordev; 675 607 struct sensor sensor; 676 608 size_t sdlen, slen; 677 - double lux, tbacklight = backlight, tkbd_backlight = kbd_backlight; 609 + float lux, tbacklight = backlight, tkbd_backlight = kbd_backlight; 678 610 int i; 679 611 680 612 sdlen = sizeof(sensordev); ··· 709 641 710 642 DPRINTF(("using lux profile %s\n", as.label)); 711 643 712 - if (dimkbd && ((int)round(kbd_backlight) != as.kbd_backlight)) { 644 + if (dim_kbd && ((int)round(kbd_backlight) != as.kbd_backlight)) { 713 645 DPRINTF(("als: adjusting keyboard backlight from %d%% " 714 646 "to %d%%\n", (int)round(kbd_backlight), 715 647 as.kbd_backlight)); 716 - 717 648 tkbd_backlight = as.kbd_backlight; 718 649 } 719 650 720 651 if ((int)round(backlight) != as.backlight) { 721 652 DPRINTF(("als: adjusting screen backlight from %d%% " 722 653 "to %d%%\n", (int)round(backlight), as.backlight)); 723 - 724 654 tbacklight = as.backlight; 725 655 } 726 656 727 657 if ((int)round(kbd_backlight) != tkbd_backlight || 728 658 (int)round(backlight) != tbacklight) 729 - stepper(tbacklight, tkbd_backlight, dim_steps); 659 + stepper(tbacklight, tkbd_backlight, dim_steps, 0); 730 660 731 661 /* become our new normal */ 732 662 backlight = tbacklight; ··· 751 681 void 752 682 bail(int sig) 753 683 { 684 + if (exiting) 685 + exit(0); 686 + 754 687 DPRINTF(("got signal %d, trying to exit\n", sig)); 755 688 756 689 /* XXX: doing X ops inside a signal handler causes an infinite loop in ··· 764 697 } 765 698 766 699 int 767 - XNextEventOrTimeout(Display *dpy, XEvent *e, unsigned int msecs) 700 + XPeekEventOrTimeout(Display *dpy, XEvent *e, unsigned int msecs) 768 701 { 769 - int fd; 770 - fd_set fdsr; 771 - struct timeval tv; 702 + struct pollfd pfd[1]; 772 703 773 - if (msecs == 0) { 774 - XNextEvent(dpy, e); 775 - return 1; 776 - } 704 + if (!XPending(dpy)) { 705 + memset(&pfd, 0, sizeof(pfd)); 706 + pfd[0].fd = ConnectionNumber(dpy); 707 + pfd[0].events = POLLIN; 777 708 778 - if (XPending(dpy) == 0) { 779 - fd = ConnectionNumber(dpy); 780 - FD_ZERO(&fdsr); 781 - FD_SET(fd, &fdsr); 782 - tv.tv_sec = msecs / 1000; 783 - tv.tv_usec = (msecs % 1000) * 1000; 784 - if (select(fd + 1, &fdsr, NULL, NULL, &tv) >= 0) { 785 - e->type = 0; 709 + if (poll(pfd, 1, msecs == 0 ? INFTIM : msecs) == 0) 786 710 return 0; 711 + 712 + if (pfd[0].revents) { 713 + DPRINTF(("%s: got X event\n", __func__)); 714 + XPeekEvent(dpy, e); 715 + return 1; 787 716 } 788 717 } 789 718 790 - XNextEvent(dpy, e); 719 + XPeekEvent(dpy, e); 791 720 return 1; 792 721 }