comparison src/events.c @ 213:78f53ef88e17 r20-4b5

Import from CVS: tag r20-4b5
author cvs
date Mon, 13 Aug 2007 10:06:47 +0200
parents 41ff10fd062f
children 1f0dabaa0855
comparison
equal deleted inserted replaced
212:d8688acf4c5b 213:78f53ef88e17
184 case magic_eval_event: 184 case magic_eval_event:
185 print_event_1 ("#<magic-event ", obj, printcharfun); 185 print_event_1 ("#<magic-event ", obj, printcharfun);
186 break; 186 break;
187 case pointer_motion_event: 187 case pointer_motion_event:
188 { 188 {
189 char buf[100]; 189 char buf[64];
190 sprintf (buf, "#<motion-event %d, %d", 190 sprintf (buf, "#<motion-event %d, %d",
191 XEVENT (obj)->event.motion.x, XEVENT (obj)->event.motion.y); 191 XEVENT (obj)->event.motion.x, XEVENT (obj)->event.motion.y);
192 write_c_string (buf, printcharfun); 192 write_c_string (buf, printcharfun);
193 break; 193 break;
194 } 194 }
296 #ifdef HAVE_TTY 296 #ifdef HAVE_TTY
297 if (CONSOLE_TTY_P (con)) 297 if (CONSOLE_TTY_P (con))
298 return (e1->event.magic.underlying_tty_event == 298 return (e1->event.magic.underlying_tty_event ==
299 e2->event.magic.underlying_tty_event); 299 e2->event.magic.underlying_tty_event);
300 #endif 300 #endif
301 #ifdef HAVE_W32GUI 301 #ifdef HAVE_MS_WINDOWS
302 if (CONSOLE_W32_P (con)) 302 if (CONSOLE_MSWINDOWS_P (con))
303 return (!memcmp(&e1->event.magic.underlying_w32_event, 303 return (!memcmp(&e1->event.magic.underlying_mswindows_event,
304 &e2->event.magic.underlying_w32_event, 304 &e2->event.magic.underlying_mswindows_event,
305 sizeof(union magic_data))); 305 sizeof(union magic_data)));
306 #endif 306 #endif
307 return 1; /* not reached */ 307 return 1; /* not reached */
308 } 308 }
309 309
369 #endif 369 #endif
370 #ifdef HAVE_TTY 370 #ifdef HAVE_TTY
371 if (CONSOLE_TTY_P (con)) 371 if (CONSOLE_TTY_P (con))
372 return HASH2 (hash, e->event.magic.underlying_tty_event); 372 return HASH2 (hash, e->event.magic.underlying_tty_event);
373 #endif 373 #endif
374 #ifdef HAVE_W32GUI 374 #ifdef HAVE_MS_WINDOWS
375 if (CONSOLE_W32_P (con)) 375 if (CONSOLE_MSWINDOWS_P (con))
376 return HASH6 (hash, e->event.magic.underlying_w32_event.message, 376 return HASH6 (hash, e->event.magic.underlying_mswindows_event.message,
377 e->event.magic.underlying_w32_event.data[0], 377 e->event.magic.underlying_mswindows_event.data[0],
378 e->event.magic.underlying_w32_event.data[1], 378 e->event.magic.underlying_mswindows_event.data[1],
379 e->event.magic.underlying_w32_event.data[2], 379 e->event.magic.underlying_mswindows_event.data[2],
380 e->event.magic.underlying_w32_event.data[3], 380 e->event.magic.underlying_mswindows_event.data[3],
381 ); 381 );
382 #endif 382 #endif
383 } 383 }
384 384
385 case empty_event: 385 case empty_event:
386 case dead_event: 386 case dead_event:
393 return 0; /* unreached */ 393 return 0; /* unreached */
394 } 394 }
395 395
396 396
397 DEFUN ("make-event", Fmake_event, 0, 2, 0, /* 397 DEFUN ("make-event", Fmake_event, 0, 2, 0, /*
398 Create a new event of type TYPE, with properties stored in PLIST. 398 Create a new event of type TYPE, with properties described by PLIST.
399
399 TYPE is a symbol, either `empty', `key-press', `button-press', 400 TYPE is a symbol, either `empty', `key-press', `button-press',
401 `button-release', `motion' or `dnd-drop'. If TYPE is nil, it
402 defaults to `empty'.
403
404 PLIST is a property list, the properties being compatible to those
405 returned by `event-properties'. The following properties are
406 allowed:
407
408 channel -- The event channel, a frame or a console. For
409 button-press, button-release and motion events, this
410 must be a frame. For key-press events, it must be a
411 console. If channel is unspecified, it will be set to
412 the selected frame or selected console, as appropriate.
413 key -- The event key, a symbol or character. Allowed only for
414 keypress events.
415 button -- The event button, integer 1, 2 or 3. Allowed only for
416 button-press and button-release events.
417 modifiers -- The event modifiers, a list of modifier symbols. Allowed
418 for key-press, button-press, button-release and motion
419 events.
420 x -- The event X coordinate, an integer. This is relative
421 to the left of CHANNEL's root window. Allowed for
422 motion, button-press and button-release events.
423 y -- The event Y coordinate, an integer. This is relative
424 to the top of CHANNEL's root window. Allowed for
425 motion, button-press and button-release events.
426 dnd-data -- The event DND data, a list of (INTEGER DATA). Allowed
427 for dnd-drop events, if support for DND has been
428 compiled into XEmacs.
429 timestamp -- The event timestamp, a non-negative integer. Allowed for
430 all types of events.
431
432 For event type `empty', PLIST must be nil.
400 `button-release', or `motion'. If TYPE is left out, it defaults to 433 `button-release', or `motion'. If TYPE is left out, it defaults to
401 `empty'. 434 `empty'.
402 PLIST is a list of properties, as returned by `event-properties'. Not 435 PLIST is a list of properties, as returned by `event-properties'. Not
403 all properties are allowed for all kinds of events, and some are 436 all properties are allowed for all kinds of events, and some are
404 required. 437 required.
405 438
406 WARNING, the event object returned may be a reused one; see the function 439 WARNING: the event object returned may be a reused one; see the function
407 `deallocate-event'. 440 `deallocate-event'.
408 */ 441 */
409 (type, plist)) 442 (type, plist))
410 { 443 {
411 Lisp_Object event, prop, val; 444 Lisp_Object tail, keyword, value;
445 Lisp_Object event = Qnil;
446 Lisp_Object dnd_data = Qnil;
412 struct Lisp_Event *e; 447 struct Lisp_Event *e;
448 EMACS_INT coord_x = 0, coord_y = 0;
449 struct gcpro gcpro1, gcpro2;
450
451 GCPRO2 (event, dnd_data);
413 452
414 if (NILP (type)) 453 if (NILP (type))
415 type = Qempty; 454 type = Qempty;
416 455
417 if (!NILP (Vevent_resource)) 456 if (!NILP (Vevent_resource))
424 event = allocate_event (); 463 event = allocate_event ();
425 } 464 }
426 e = XEVENT (event); 465 e = XEVENT (event);
427 zero_event (e); 466 zero_event (e);
428 467
429 if (EQ (type, Qkey_press)) 468 if (EQ (type, Qempty))
469 {
470 /* For empty event, we return immediately, without processing
471 PLIST. In fact, processing PLIST would be wrong, because the
472 sanitizing process would fill in the properties
473 (e.g. CHANNEL), which we don't want in empty events. */
474 e->event_type = empty_event;
475 if (!NILP (plist))
476 error ("Cannot set properties of empty event");
477 UNGCPRO;
478 return event;
479 }
480 else if (EQ (type, Qkey_press))
430 e->event_type = key_press_event; 481 e->event_type = key_press_event;
431 else if (EQ (type, Qbutton_press)) 482 else if (EQ (type, Qbutton_press))
432 e->event_type = button_press_event; 483 e->event_type = button_press_event;
433 else if (EQ (type, Qbutton_release)) 484 else if (EQ (type, Qbutton_release))
434 e->event_type = button_release_event; 485 e->event_type = button_release_event;
435 else if (EQ (type, Qmotion)) 486 else if (EQ (type, Qmotion))
436 e->event_type = pointer_motion_event; 487 e->event_type = pointer_motion_event;
437 else if (EQ (type, Qempty)) 488 #ifdef HAVE_OFFIX_DND
438 e->event_type = empty_event; 489 else if (EQ (type, Qdnd_drop))
490 {
491 e->event_type = dnd_drop_event;
492 e->event.dnd_drop.data = Qnil;
493 }
494 #endif
439 else 495 else
440 /* not allowed: Qmisc_user, Qprocess, Qtimeout, Qmagic, Qmagic_eval */ 496 {
441 /* dnd_drop is also not allowed */ 497 /* Not allowed: Qmisc_user, Qprocess, Qtimeout, Qmagic, Qeval,
442 signal_simple_error ("Invalid event type", type); 498 Qmagic_eval. */
499 /* #### Should we allow misc-user events? */
500 signal_simple_error ("Invalid event type", type);
501 }
502
503 plist = Fcopy_sequence (plist);
504 Fcanonicalize_plist (plist, Qnil);
443 505
444 /* Process the plist. */ 506 /* Process the plist. */
445 while (!NILP (plist)) 507 EXTERNAL_PROPERTY_LIST_LOOP (tail, keyword, value, plist)
446 { 508 {
447 prop = Fcar (plist); 509 if (EQ (keyword, Qchannel))
448 plist = Fcdr (plist);
449 val = Fcar (plist);
450 plist = Fcdr (plist);
451 if (EQ (prop, Qchannel))
452 { 510 {
453 if (!FRAMEP (val) && !NILP (val)) 511 if (e->event_type == key_press_event)
454 signal_simple_error ("Invalid event channel", val); 512 {
455 EVENT_CHANNEL (e) = val; 513 if (!CONSOLEP (value))
514 wrong_type_argument (Qconsolep, value);
515 }
516 else
517 {
518 if (!FRAMEP (value))
519 wrong_type_argument (Qframep, value);
520 }
521 EVENT_CHANNEL (e) = value;
456 } 522 }
457 else if (EQ (prop, Qkey)) 523 else if (EQ (keyword, Qkey))
458 { 524 {
459 if (e->event_type != key_press_event) 525 if (e->event_type != key_press_event)
460 wrong_type_argument (Qkey_press_event_p, event); 526 signal_simple_error ("Invalid event type for `key' property",
461 if (!SYMBOLP (val) && !CHARP (val)) 527 type);
462 signal_simple_error ("Invalid event key", val); 528 if (!SYMBOLP (value) && !CHARP (value))
463 e->event.key.keysym = val; 529 signal_simple_error ("Invalid event key", value);
530 e->event.key.keysym = value;
464 } 531 }
465 else if (EQ (prop, Qbutton)) 532 else if (EQ (keyword, Qbutton))
466 { 533 {
467 CHECK_NATNUM (val); 534 CHECK_NATNUM (value);
468 check_int_range (XINT(val), 1, 3); 535 check_int_range (XINT(value), 1, 3);
469 if (e->event_type != button_press_event 536 if (e->event_type != button_press_event
470 && e->event_type != button_release_event) 537 && e->event_type != button_release_event)
471 signal_simple_error ("Invalid event type for `button' property", 538 signal_simple_error ("Invalid event type for `button' property",
472 type); 539 type);
473 e->event.button.button = XINT (val); 540 e->event.button.button = XINT (value);
474 } 541 }
475 else if (EQ (prop, Qmodifiers)) 542 else if (EQ (keyword, Qmodifiers))
476 { 543 {
477 Lisp_Object tail, sym; 544 Lisp_Object modtail, sym;
478 int modifiers = 0; 545 int modifiers = 0;
479 546
480 if (e->event_type != key_press_event 547 if (e->event_type != key_press_event
481 && e->event_type != button_press_event 548 && e->event_type != button_press_event
482 && e->event_type != button_release_event 549 && e->event_type != button_release_event
483 && e->event_type != pointer_motion_event) 550 && e->event_type != pointer_motion_event)
551 /* Currently unreached. */
484 signal_simple_error ("Invalid event type for modifiers", type); 552 signal_simple_error ("Invalid event type for modifiers", type);
485 553
486 for (tail = val; !NILP (tail); tail = Fcdr (tail)) 554 EXTERNAL_LIST_LOOP (modtail, value)
487 { 555 {
488 sym = Fcar (tail); 556 sym = XCAR (modtail);
489 if (EQ (sym, Qcontrol)) modifiers |= MOD_CONTROL; 557 if (EQ (sym, Qcontrol)) modifiers |= MOD_CONTROL;
490 else if (EQ (sym, Qmeta)) modifiers |= MOD_META; 558 else if (EQ (sym, Qmeta)) modifiers |= MOD_META;
491 else if (EQ (sym, Qsuper)) modifiers |= MOD_SUPER; 559 else if (EQ (sym, Qsuper)) modifiers |= MOD_SUPER;
492 else if (EQ (sym, Qhyper)) modifiers |= MOD_HYPER; 560 else if (EQ (sym, Qhyper)) modifiers |= MOD_HYPER;
493 else if (EQ (sym, Qalt)) modifiers |= MOD_ALT; 561 else if (EQ (sym, Qalt)) modifiers |= MOD_ALT;
494 else if (EQ (sym, Qsymbol)) modifiers |= MOD_ALT; 562 else if (EQ (sym, Qsymbol)) modifiers |= MOD_ALT;
495 else if (EQ (sym, Qshift)) modifiers |= MOD_SHIFT; 563 else if (EQ (sym, Qshift)) modifiers |= MOD_SHIFT;
496 else 564 else
497 signal_simple_error ("Invalid key modifier", Fcar (tail)); 565 signal_simple_error ("Invalid key modifier", XCAR (modtail));
498 } 566 }
499 if (e->event_type == key_press_event) 567 if (e->event_type == key_press_event)
500 e->event.key.modifiers = modifiers; 568 e->event.key.modifiers = modifiers;
501 else if (e->event_type == button_press_event 569 else if (e->event_type == button_press_event
502 || e->event_type == button_release_event) 570 || e->event_type == button_release_event)
503 e->event.button.modifiers = modifiers; 571 e->event.button.modifiers = modifiers;
504 else /* pointer_motion_event */ 572 else /* pointer_motion_event */
505 e->event.motion.modifiers = modifiers; 573 e->event.motion.modifiers = modifiers;
506 } 574 }
507 else if (EQ (prop, Qx)) 575 else if (EQ (keyword, Qx))
508 { 576 {
509 CHECK_NATNUM (val); 577 /* Allow negative values, so we can specify toolbar
510 if (e->event_type == pointer_motion_event) 578 positions. */
511 e->event.motion.x = XINT (val); 579 CHECK_INT (value);
512 else if (e->event_type == button_press_event 580 if (e->event_type != pointer_motion_event
513 || e->event_type == button_release_event) 581 && e->event_type != button_press_event
514 e->event.button.x = XINT (val); 582 && e->event_type != button_release_event)
583 {
584 signal_simple_error ("Cannot assign `x' property to event",
585 type);
586 }
587 coord_x = XINT (value);
515 } 588 }
516 else if (EQ (prop, Qy)) 589 else if (EQ (keyword, Qy))
517 { 590 {
518 CHECK_NATNUM (val); 591 /* Allow negative values; see above. */
519 if (e->event_type == pointer_motion_event) 592 CHECK_INT (value);
520 e->event.motion.y = XINT (val); 593 if (e->event_type != pointer_motion_event
521 else if (e->event_type == button_press_event 594 && e->event_type != button_press_event
522 || e->event_type == button_release_event) 595 && e->event_type != button_release_event)
523 e->event.button.y = XINT (val); 596 {
597 signal_simple_error ("Cannot assign `y' property to event",
598 type);
599 }
600 coord_y = XINT (value);
524 } 601 }
525 else if (EQ (prop, Qtimestamp)) 602 else if (EQ (keyword, Qtimestamp))
526 { 603 {
527 CHECK_NATNUM (val); 604 CHECK_NATNUM (value);
528 e->timestamp = XINT (val); 605 e->timestamp = XINT (value);
529 } 606 }
607 #ifdef HAVE_OFFIX_DND
608 else if (EQ (keyword, Qdnd_data))
609 {
610 Lisp_Object dnd_tail;
611 /* Value is a list of (INT DATA). Data is a list. */
612 CHECK_CONS (value);
613 /* Oliver, change this to accept symbols, when the time is
614 ripe! */
615 CHECK_NATNUM (XCAR (value));
616 CHECK_CONS (XCDR (value));
617 if (!NILP (XCDR (XCDR (value))))
618 wrong_type_argument (Qlistp, XCDR (value));
619 /* Check the list validity. */
620 EXTERNAL_LIST_LOOP (dnd_tail, XCAR (XCDR (value)))
621 ;
622 /* And now, copy it all. */
623 e->event.dnd_drop.data = Fcopy_tree (value, Qnil);
624 }
625 #endif /* HAVE_OFFIX_DND */
530 else 626 else
531 signal_simple_error ("Invalid property", prop); 627 signal_simple_error ("Invalid property", keyword);
532 } /* while */ 628 } /* while */
533 629
534 /* Now, let's validate what we got. */ 630 /* Insert the channel, if missing. */
631 if (NILP (EVENT_CHANNEL (e)))
632 {
633 if (e->event_type == key_press_event)
634 EVENT_CHANNEL (e) = Vselected_console;
635 else
636 EVENT_CHANNEL (e) = Fselected_frame (Qnil);
637 }
638
639 /* Fevent_properties, Fevent_x_pixel, etc. work with pixels relative
640 to the frame, so we must adjust accordingly. */
641 if (e->event_type == pointer_motion_event
642 || e->event_type == button_press_event
643 || e->event_type == button_release_event
644 #ifdef HAVE_OFFIX_DND
645 || e->event_type == dnd_drop_event
646 #endif
647 )
648 {
649 struct frame *f = XFRAME (EVENT_CHANNEL (e));
650
651 coord_x += FRAME_REAL_LEFT_TOOLBAR_WIDTH (f);
652 coord_y += FRAME_REAL_TOP_TOOLBAR_HEIGHT (f);
653
654 if (e->event_type == pointer_motion_event)
655 {
656 e->event.motion.x = coord_x;
657 e->event.motion.y = coord_y;
658 }
659 else if (e->event_type == button_press_event
660 || e->event_type == button_release_event
661 #ifdef HAVE_OFFIX_DND
662 || e->event_type == dnd_drop_event
663 #endif
664 )
665 {
666 e->event.button.x = coord_x;
667 e->event.button.y = coord_y;
668 }
669 }
670
671 /* Finally, do some more validation. */
535 switch (e->event_type) 672 switch (e->event_type)
536 { 673 {
537 case key_press_event: 674 case key_press_event:
538 if (!(SYMBOLP (e->event.key.keysym) || CHARP (e->event.key.keysym))) 675 if (!(SYMBOLP (e->event.key.keysym) || CHARP (e->event.key.keysym)))
539 error ("Undefined key for keypress event"); 676 error ("Undefined key for keypress event");
540 break; 677 break;
541 case button_press_event: 678 case button_press_event:
542 case button_release_event: 679 case button_release_event:
680 #ifdef HAVE_OFFIX_DND
681 case dnd_drop_event:
682 #endif
543 if (!e->event.button.button) 683 if (!e->event.button.button)
544 error ("Undefined button for button-press or button-release event"); 684 error ("Undefined button for %s event",
545 if (NILP (EVENT_CHANNEL (e))) 685 e->event_type == button_press_event
546 error ("Undefined channel for button-press or button-release event"); 686 ? "buton-press" :
547 break; 687 #ifdef HAVE_OFFIX_DND
688 e->event_type == button_release_event
689 ? "button-release" : "dnd-drop"
690 #else
691 "button-release"
692 #endif
693 );
694 #ifdef HAVE_OFFIX_DND
695 if ((e->event_type == dnd_drop_event) &&
696 NILP (e->event.dnd_drop.data))
697 error ("Unspecified data for dnd-drop event");
698 break;
699 #endif
548 default: 700 default:
549 break; 701 break;
550 } 702 }
703
704 UNGCPRO;
551 return event; 705 return event;
552 } 706 }
553 707
554 DEFUN ("deallocate-event", Fdeallocate_event, 1, 1, 0, /* 708 DEFUN ("deallocate-event", Fdeallocate_event, 1, 1, 0, /*
555 Allow the given event structure to be reused. 709 Allow the given event structure to be reused.