~ubuntu-branches/ubuntu/lucid/sawfish/lucid-updates

« back to all changes in this revision

Viewing changes to src/events.c

  • Committer: Bazaar Package Importer
  • Author(s): Christian Marillat
  • Date: 2005-02-23 16:16:46 UTC
  • mfrom: (1.2.1 upstream) (2.1.2 hoary)
  • Revision ID: james.westby@ubuntu.com-20050223161646-4id6qyw4h9lkvb0v
Tags: 1:1.3+cvs20050222-1
* New cvs release.
* Add an emacs initialisation script to load sawfish.el (Closes: #295290)
* Updated sawfish.el to 1.32

Show diffs side-by-side

added added

removed removed

Lines of Context:
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 $
3
3
 
4
4
   Copyright (C) 1999 John Harper <john@dcs.warwick.ac.uk>
5
5
 
21
21
 
22
22
#include "sawmill.h"
23
23
#include <limits.h>
 
24
#include <string.h>
24
25
#include <time.h>
25
26
#include <X11/extensions/shape.h>
26
27
#include <X11/Xresource.h>
56
57
/* We need a ButtonRelease on this fp. */
57
58
struct frame_part *clicked_frame_part;
58
59
 
 
60
/* Set to true when the pointer is actively grabbed */
 
61
static bool pointer_is_grabbed;
 
62
 
59
63
static XID event_handler_context;
60
64
 
61
65
static Atom xa_sawmill_timestamp;
376
380
button_press (XEvent *ev)
377
381
{
378
382
    struct frame_part *fp;
379
 
    Lisp_Window *w = 0;
380
383
 
381
384
    /* This works for both press and release events. The desired outcome
382
385
       is that press and motion events get the context map active when
388
391
    record_mouse_position (ev->xbutton.x_root, ev->xbutton.y_root,
389
392
                           ev->type, ev->xany.window);
390
393
 
391
 
    fp = find_frame_part_by_window (ev->xbutton.window);
392
 
    if (fp != 0)
 
394
    /* Only let through events we're expecting */
 
395
    if (pointer_is_grabbed
 
396
        || ev->xbutton.window != root_window
 
397
        || ev->xbutton.subwindow == None)
393
398
    {
394
 
        w = fp->win;
395
 
 
396
399
        if (ev->type == ButtonPress)
397
 
            handle_fp_click (fp, ev);
398
 
    }
399
 
 
400
 
    eval_input_event (current_context_map ());
401
 
 
402
 
    if (fp != 0 && !WINDOW_IS_GONE_P (w) && ev->type == ButtonRelease)
403
 
    {
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);
411
 
        rep_POPGC;
412
 
        rep_throw_value = old_throw;
 
400
        {
 
401
            fp = find_frame_part_by_window (ev->xbutton.window);
 
402
            if (fp != 0)
 
403
                handle_fp_click (fp, ev);
 
404
        }
 
405
 
 
406
        eval_input_event (current_context_map ());
 
407
 
 
408
        if (ev->type == ButtonRelease)
 
409
        {
 
410
            fp = find_frame_part_by_window (ev->xbutton.window);
 
411
            if (fp != 0 && !WINDOW_IS_GONE_P (fp->win))
 
412
            {
 
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);
 
420
                rep_POPGC;
 
421
                rep_throw_value = old_throw;
 
422
            }
 
423
        }
413
424
    }
414
425
 
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);
 
431
        ungrab_pointer ();
421
432
    }
422
433
 
423
434
    XAllowEvents (dpy, SyncPointer, last_event_time);
443
454
        record_mouse_position (x, y, ev->type, ev->xmotion.window);
444
455
    }
445
456
 
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)
 
461
    {
 
462
        if (pointer_in_motion)
 
463
            eval_input_event (current_context_map ());
 
464
    }
448
465
 
449
466
    XAllowEvents (dpy, SyncPointer, last_event_time);
450
467
 
462
479
    if (w != 0 && ev->xproperty.window == w->id)
463
480
    {
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;
467
484
 
468
485
        switch (ev->xproperty.atom)
486
503
                if (format == 8 && !WINDOW_IS_GONE_P (w))
487
504
                {
488
505
                    repv str = Qnil;
489
 
                    if (actual == xa_compound_text)
 
506
                    if (actual == xa_compound_text || actual == XA_STRING)
490
507
                    {
491
508
                        char **text_list;
492
509
                        XTextProperty tprop;
504
521
                            XFreeStringList(text_list);
505
522
                        }
506
523
                    }
507
 
                    else if (actual == XA_STRING)
508
 
                    {
509
 
                        str = rep_string_dup (prop);
510
 
                    }
511
524
                    if (str == Qnil)
512
525
                        str = rep_null_string ();
513
526
 
553
566
            XGetWMNormalHints (dpy, w->id, &w->hints, &supplied);
554
567
            break;
555
568
 
556
 
        case XA_WM_TRANSIENT_FOR:
557
 
            if (!XGetTransientForHint (dpy, w->id, &w->transient_for_hint))
558
 
                w->transient_for_hint = 0;
559
 
            break;
560
 
 
561
569
        default:
562
570
            if (ev->xproperty.atom == xa_wm_colormap_windows)
563
571
            {
580
588
        rep_PUSHGC (gc_w, w_);
581
589
        rep_PUSHGC (gc_changed_states, changed_states);
582
590
 
 
591
        prop = x_atom_symbol (ev->xproperty.atom);
 
592
        property_cache_invalidate (w_, prop);
 
593
 
583
594
        if (need_refresh && w->reparented
584
595
            && w->property_change != 0 && !WINDOW_IS_GONE_P (w))
585
596
        {
589
600
        if (changed)
590
601
        {
591
602
            Fcall_window_hook (Qproperty_notify_hook, rep_VAL(w),
592
 
                               rep_list_2 (x_atom_symbol (ev->xproperty.atom),
593
 
                                           ev->xproperty.state
 
603
                               rep_list_2 (prop, ev->xproperty.state
594
604
                                           == PropertyNewValue
595
605
                                           ? Qnew_value : Qdeleted), Qnil);
596
606
        }
660
670
    Lisp_Window *w = x_find_window_by_id (ev->xdestroywindow.window);
661
671
    if (w == 0 || ev->xdestroywindow.window != w->saved_id)
662
672
        return;
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..? */
 
677
    w->saved_id = 0;
665
678
}
666
679
 
667
680
void
720
733
            && ev->xreparent.parent != w->frame)
721
734
        {
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);
726
739
        }
739
752
        if (wa.override_redirect)
740
753
        {
741
754
            /* arrgh, the window changed its override redirect status.. */
742
 
            remove_window (w, Qnil, Qnil);
 
755
            remove_window (w, FALSE, FALSE);
743
756
        }
744
757
        else
745
758
        {
781
794
        }
782
795
        Fcall_window_hook (Qunmap_notify_hook, rep_VAL(w), Qnil, Qnil);
783
796
 
784
 
        focus_off_window (w);
785
797
        XDeleteProperty (dpy, w->id, xa_wm_state);
786
798
 
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);
790
802
    }
791
803
}
792
804
 
891
903
static Lisp_Window *last_focused;
892
904
 
893
905
static void
 
906
report_focus_change (Lisp_Window *w)
 
907
{
 
908
    if (w != 0
 
909
        && w->focus_change != 0
 
910
        && !WINDOW_IS_GONE_P (w))
 
911
    {
 
912
        DB (("  calling focus change %p on %s\n",
 
913
             w->focus_change, rep_STR(w->name)));
 
914
        w->focus_change (w);
 
915
    }
 
916
}
 
917
 
 
918
static void
894
919
focus_in (XEvent *ev)
895
920
{
896
921
    Lisp_Window *w = find_window_by_id (ev->xfocus.window);
898
923
        return;
899
924
    if (w != 0 && w->visible)
900
925
    {
 
926
        Lisp_Window *old = focus_window;
901
927
        focus_window = w;
902
 
        if (pending_focus_window == w)
903
 
            pending_focus_window = 0;
904
928
 
905
929
        if (last_focused != w)
906
930
        {
907
931
            last_focused = w;
 
932
            if (old != 0)
 
933
                report_focus_change (old);
908
934
            install_colormaps (w);
909
 
            if (w->focus_change != 0)
910
 
            {
911
 
                DB (("  calling focus change %p on %s\n",
912
 
                     w->focus_change, rep_STR(w->name)));
913
 
                w->focus_change (w);
914
 
            }
 
935
            report_focus_change (w);
915
936
            if (!WINDOW_IS_GONE_P (w))
916
937
            {
917
938
                Fcall_window_hook (Qfocus_in_hook, rep_VAL(w),
933
954
    if (w != 0 && ev->xfocus.detail != NotifyInferior)
934
955
    {
935
956
        if (focus_window == w)
 
957
        {
936
958
            focus_window = 0;
 
959
            report_focus_change (w);
 
960
        }
 
961
 
937
962
        if (last_focused == w)
938
963
        {
939
964
            last_focused = 0;
940
 
            if (w->focus_change != 0)
941
 
            {
942
 
                DB (("  calling focus change %p on %s\n",
943
 
                     w->focus_change, rep_STR(w->name)));
944
 
                w->focus_change (w);
945
 
            }
946
965
            if (!WINDOW_IS_GONE_P (w))
947
966
            {
948
967
                Fcall_window_hook (Qfocus_out_hook, rep_VAL(w),
1031
1050
                alist = Fcons (Fcons (Qstack, stack_data), alist);
1032
1051
            }
1033
1052
        }
1034
 
        if ((mask & CWX) && (mask & CWY))
 
1053
        if ((mask & CWX) || (mask & CWY))
1035
1054
        {
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)),
 
1060
                           alist);
1041
1061
        }
1042
1062
        if ((mask & CWWidth) || (mask & CWHeight))
1043
1063
        {
1072
1092
}
1073
1093
 
1074
1094
static void
 
1095
gravity_notify (XEvent *ev)
 
1096
{
 
1097
}
 
1098
 
 
1099
static void
1075
1100
configure_notify (XEvent *ev)
1076
1101
{
1077
1102
}
1194
1219
    return ev.xproperty.time;
1195
1220
}
1196
1221
 
 
1222
void
 
1223
mark_pointer_grabbed (void)
 
1224
{
 
1225
    pointer_is_grabbed = TRUE;
 
1226
}
 
1227
 
 
1228
void
 
1229
ungrab_pointer (void)
 
1230
{
 
1231
    pointer_is_grabbed = FALSE;
 
1232
    XUngrabPointer (dpy, last_event_time);
 
1233
}
 
1234
 
1197
1235
 
1198
1236
/* Window-local event handlers */
1199
1237
 
1215
1253
static inline void *
1216
1254
window_event_handler (Window w)
1217
1255
{
1218
 
    void *fun;
 
1256
    union {
 
1257
        void *v;
 
1258
        XPointer p;
 
1259
    } fun;
 
1260
 
1219
1261
    return XFindContext (dpy, w, event_handler_context,
1220
 
                         (XPointer *)&fun) ? 0 : fun;
 
1262
                         &fun.p) ? 0 : fun.v;
1221
1263
}
1222
1264
 
1223
1265
 
1282
1324
        if (xev.type == NoExpose || xev.type == GraphicsExpose)
1283
1325
            continue;
1284
1326
 
1285
 
        DB(("** Event: %s (win %lx)\n",
1286
 
            xev.type < LASTEvent ? event_names[xev.type] : "unknown",
1287
 
            (long)xev.xany.window));
 
1327
#ifdef DEBUG
 
1328
        do {
 
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"));
 
1333
        } while (0);
 
1334
#endif
1288
1335
 
1289
1336
        record_event_time (&xev);
1290
1337
        current_x_event = &xev;
1460
1507
}
1461
1508
 
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]
1466
1513
 
1467
1514
Return a recent X server timestamp, as an integer.
1468
1515
 
1473
1520
{
1474
1521
    Time time = ((from_server == Qnil)
1475
1522
                 ? last_event_time : get_server_timestamp ());
 
1523
    if (store != Qnil)
 
1524
        save_timestamp (time);
1476
1525
    return rep_make_long_uint (time);
1477
1526
}
1478
1527
 
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);
1625
1675
 
1626
1676
    rep_INTERN_SPECIAL(pointer_motion_threshold);
1627
 
    Fset (Qpointer_motion_threshold, rep_MAKE_INT (0));
1628
1677
 
1629
1678
    rep_INTERN(iconify_window);
1630
1679
    rep_INTERN(uniconify_window);