1
1
/* events.c -- Event handling
2
$Id: events.c,v 1.143 2001/11/13 03:50:51 jsh Exp $
2
$Id: events.c,v 1.158 2005/01/04 15:34:25 jsh Exp $
4
4
Copyright (C) 1999 John Harper <john@dcs.warwick.ac.uk>
56
57
/* We need a ButtonRelease on this fp. */
57
58
struct frame_part *clicked_frame_part;
60
/* Set to true when the pointer is actively grabbed */
61
static bool pointer_is_grabbed;
59
63
static XID event_handler_context;
61
65
static Atom xa_sawmill_timestamp;
388
391
record_mouse_position (ev->xbutton.x_root, ev->xbutton.y_root,
389
392
ev->type, ev->xany.window);
391
fp = find_frame_part_by_window (ev->xbutton.window);
394
/* Only let through events we're expecting */
395
if (pointer_is_grabbed
396
|| ev->xbutton.window != root_window
397
|| ev->xbutton.subwindow == None)
396
399
if (ev->type == ButtonPress)
397
handle_fp_click (fp, ev);
400
eval_input_event (current_context_map ());
402
if (fp != 0 && !WINDOW_IS_GONE_P (w) && ev->type == ButtonRelease)
404
/* In case the event binding threw a non-local-exit, fake
405
an unwind-protect thing */
406
repv old_throw = rep_throw_value;
407
rep_GC_root gc_old_throw;
408
rep_throw_value = rep_NULL;
409
rep_PUSHGC(gc_old_throw, old_throw);
410
handle_fp_click (fp, ev);
412
rep_throw_value = old_throw;
401
fp = find_frame_part_by_window (ev->xbutton.window);
403
handle_fp_click (fp, ev);
406
eval_input_event (current_context_map ());
408
if (ev->type == ButtonRelease)
410
fp = find_frame_part_by_window (ev->xbutton.window);
411
if (fp != 0 && !WINDOW_IS_GONE_P (fp->win))
413
/* In case the event binding threw a non-local-exit, fake
414
an unwind-protect thing */
415
repv old_throw = rep_throw_value;
416
rep_GC_root gc_old_throw;
417
rep_throw_value = rep_NULL;
418
rep_PUSHGC(gc_old_throw, old_throw);
419
handle_fp_click (fp, ev);
421
rep_throw_value = old_throw;
415
426
if (ev->type == ButtonRelease)
417
428
button_press_mouse_x = button_press_mouse_y = -1;
418
429
button_press_window = 0;
419
430
/* The pointer is _always_ ungrabbed after a button-release */
420
XUngrabPointer (dpy, last_event_time);
423
434
XAllowEvents (dpy, SyncPointer, last_event_time);
443
454
record_mouse_position (x, y, ev->type, ev->xmotion.window);
446
if (pointer_in_motion)
447
eval_input_event (current_context_map ());
457
/* Only let through events we're expecting */
458
if (pointer_is_grabbed
459
|| ev->xbutton.window != root_window
460
|| ev->xbutton.subwindow == None)
462
if (pointer_in_motion)
463
eval_input_event (current_context_map ());
449
466
XAllowEvents (dpy, SyncPointer, last_event_time);
462
479
if (w != 0 && ev->xproperty.window == w->id)
464
481
bool need_refresh = FALSE, changed = TRUE;
465
repv changed_states = Qnil;
482
repv changed_states = Qnil, prop;
466
483
rep_GC_root gc_w, gc_changed_states;
468
485
switch (ev->xproperty.atom)
553
566
XGetWMNormalHints (dpy, w->id, &w->hints, &supplied);
556
case XA_WM_TRANSIENT_FOR:
557
if (!XGetTransientForHint (dpy, w->id, &w->transient_for_hint))
558
w->transient_for_hint = 0;
562
570
if (ev->xproperty.atom == xa_wm_colormap_windows)
580
588
rep_PUSHGC (gc_w, w_);
581
589
rep_PUSHGC (gc_changed_states, changed_states);
591
prop = x_atom_symbol (ev->xproperty.atom);
592
property_cache_invalidate (w_, prop);
583
594
if (need_refresh && w->reparented
584
595
&& w->property_change != 0 && !WINDOW_IS_GONE_P (w))
591
602
Fcall_window_hook (Qproperty_notify_hook, rep_VAL(w),
592
rep_list_2 (x_atom_symbol (ev->xproperty.atom),
603
rep_list_2 (prop, ev->xproperty.state
594
604
== PropertyNewValue
595
605
? Qnew_value : Qdeleted), Qnil);
660
670
Lisp_Window *w = x_find_window_by_id (ev->xdestroywindow.window);
661
671
if (w == 0 || ev->xdestroywindow.window != w->saved_id)
663
remove_window (w, Qt, Qnil);
673
remove_window (w, TRUE, FALSE);
674
property_cache_invalidate_window (rep_VAL (w));
664
675
emit_pending_destroys ();
676
/* in case the id gets recycled but the window doesn't get gc'd..? */
720
733
&& ev->xreparent.parent != w->frame)
722
735
/* Not us doing the reparenting.. */
723
remove_window (w, Qnil, Qnil);
736
remove_window (w, FALSE, FALSE);
724
737
XReparentWindow (dpy, ev->xreparent.window, ev->xreparent.parent,
725
738
ev->xreparent.x, ev->xreparent.y);
739
752
if (wa.override_redirect)
741
754
/* arrgh, the window changed its override redirect status.. */
742
remove_window (w, Qnil, Qnil);
755
remove_window (w, FALSE, FALSE);
782
795
Fcall_window_hook (Qunmap_notify_hook, rep_VAL(w), Qnil, Qnil);
784
focus_off_window (w);
785
797
XDeleteProperty (dpy, w->id, xa_wm_state);
787
799
/* Changed the window-handling model, don't let windows exist
788
800
while they're withdrawn */
789
remove_window (w, Qnil, Qnil);
801
remove_window (w, FALSE, FALSE);
891
903
static Lisp_Window *last_focused;
906
report_focus_change (Lisp_Window *w)
909
&& w->focus_change != 0
910
&& !WINDOW_IS_GONE_P (w))
912
DB ((" calling focus change %p on %s\n",
913
w->focus_change, rep_STR(w->name)));
894
919
focus_in (XEvent *ev)
896
921
Lisp_Window *w = find_window_by_id (ev->xfocus.window);
899
924
if (w != 0 && w->visible)
926
Lisp_Window *old = focus_window;
901
927
focus_window = w;
902
if (pending_focus_window == w)
903
pending_focus_window = 0;
905
929
if (last_focused != w)
907
931
last_focused = w;
933
report_focus_change (old);
908
934
install_colormaps (w);
909
if (w->focus_change != 0)
911
DB ((" calling focus change %p on %s\n",
912
w->focus_change, rep_STR(w->name)));
935
report_focus_change (w);
915
936
if (!WINDOW_IS_GONE_P (w))
917
938
Fcall_window_hook (Qfocus_in_hook, rep_VAL(w),
933
954
if (w != 0 && ev->xfocus.detail != NotifyInferior)
935
956
if (focus_window == w)
936
958
focus_window = 0;
959
report_focus_change (w);
937
962
if (last_focused == w)
939
964
last_focused = 0;
940
if (w->focus_change != 0)
942
DB ((" calling focus change %p on %s\n",
943
w->focus_change, rep_STR(w->name)));
946
965
if (!WINDOW_IS_GONE_P (w))
948
967
Fcall_window_hook (Qfocus_out_hook, rep_VAL(w),
1031
1050
alist = Fcons (Fcons (Qstack, stack_data), alist);
1034
if ((mask & CWX) && (mask & CWY))
1053
if ((mask & CWX) || (mask & CWY))
1036
1055
int x = ev->xconfigurerequest.x;
1037
1056
int y = ev->xconfigurerequest.y;
1038
1057
alist = Fcons (Fcons (Qposition,
1039
Fcons (rep_MAKE_INT (x),
1040
rep_MAKE_INT (y))), alist);
1058
Fcons ((mask & CWX) ? rep_MAKE_INT (x) : Qnil,
1059
(mask & CWY) ? rep_MAKE_INT (y) : Qnil)),
1042
1062
if ((mask & CWWidth) || (mask & CWHeight))
1194
1219
return ev.xproperty.time;
1223
mark_pointer_grabbed (void)
1225
pointer_is_grabbed = TRUE;
1229
ungrab_pointer (void)
1231
pointer_is_grabbed = FALSE;
1232
XUngrabPointer (dpy, last_event_time);
1198
1236
/* Window-local event handlers */
1215
1253
static inline void *
1216
1254
window_event_handler (Window w)
1219
1261
return XFindContext (dpy, w, event_handler_context,
1220
(XPointer *)&fun) ? 0 : fun;
1262
&fun.p) ? 0 : fun.v;
1282
1324
if (xev.type == NoExpose || xev.type == GraphicsExpose)
1285
DB(("** Event: %s (win %lx)\n",
1286
xev.type < LASTEvent ? event_names[xev.type] : "unknown",
1287
(long)xev.xany.window));
1329
Lisp_Window *w = x_find_window_by_id (xev.xany.window);
1330
DB(("** Event: %s (win %lx: %s)\n",
1331
xev.type < LASTEvent ? event_names[xev.type] : "unknown",
1332
(long)xev.xany.window, w ? (char *) rep_STR (w->name) : "unknown"));
1289
1336
record_event_time (&xev);
1290
1337
current_x_event = &xev;
1462
1509
DEFUN("x-server-timestamp", Fx_server_timestamp, Sx_server_timestamp,
1463
(repv from_server), rep_Subr1) /*
1510
(repv from_server, repv store), rep_Subr2) /*
1464
1511
::doc:sawfish.wm.events#x-server-timestamp::
1465
x-server-timestamp [FROM-SERVER]
1512
x-server-timestamp [FROM-SERVER] [STORE]
1467
1514
Return a recent X server timestamp, as an integer.
1514
1563
event_handlers[FocusIn] = focus_in;
1515
1564
event_handlers[FocusOut] = focus_out;
1516
1565
event_handlers[ConfigureRequest] = configure_request;
1566
event_handlers[GravityNotify] = gravity_notify;
1517
1567
event_handlers[ConfigureNotify] = configure_notify;
1518
1568
event_handlers[ReparentNotify] = reparent_notify;
1519
1569
event_handlers[CreateNotify] = create_notify;
1624
1674
rep_INTERN_SPECIAL(window_state_change_hook);
1626
1676
rep_INTERN_SPECIAL(pointer_motion_threshold);
1627
Fset (Qpointer_motion_threshold, rep_MAKE_INT (0));
1629
1678
rep_INTERN(iconify_window);
1630
1679
rep_INTERN(uniconify_window);